Mercurial > pub > ImplabNet
annotate Implab/Parsing/AlphabetBase.cs @ 157:948c015a9011 v2
sync
author | cin |
---|---|
date | Thu, 18 Feb 2016 11:03:47 +0300 |
parents | 97fbbf816844 |
children |
rev | line source |
---|---|
55 | 1 using Implab; |
2 using System; | |
3 using System.Collections.Generic; | |
4 using System.Diagnostics; | |
5 using System.Linq; | |
6 using System.Text; | |
7 using System.Threading.Tasks; | |
8 | |
9 namespace Implab.Parsing { | |
10 public abstract class AlphabetBase<T> : IAlphabet<T> { | |
11 public const int UNCLASSIFIED = 0; | |
12 | |
13 int m_nextId = 1; | |
156
97fbbf816844
Promises: SignalXXX methods merged into SignalHandler method.
cin
parents:
59
diff
changeset
|
14 readonly int[] m_map; |
55 | 15 |
16 public int Count { | |
17 get { return m_nextId; } | |
18 } | |
19 | |
59 | 20 protected AlphabetBase(int mapSize) { |
21 m_map = new int[mapSize]; | |
55 | 22 } |
23 | |
24 protected AlphabetBase(int[] map) { | |
25 Debug.Assert(map != null); | |
26 | |
27 m_map = map; | |
28 m_nextId = map.Max() + 1; | |
29 } | |
30 | |
31 public int DefineSymbol(T symbol) { | |
32 var index = GetSymbolIndex(symbol); | |
33 if (m_map[index] == UNCLASSIFIED) | |
34 m_map[index] = m_nextId++; | |
35 return m_map[index]; | |
36 } | |
37 | |
38 public int DefineClass(IEnumerable<T> symbols) { | |
39 Safe.ArgumentNotNull(symbols, "symbols"); | |
40 symbols = symbols.Distinct(); | |
41 | |
42 foreach (var symbol in symbols) { | |
43 var index = GetSymbolIndex(symbol); | |
44 if (m_map[index] == UNCLASSIFIED) | |
45 m_map[GetSymbolIndex(symbol)] = m_nextId; | |
46 else | |
47 throw new InvalidOperationException(String.Format("Symbol '{0}' already in use", symbol)); | |
48 } | |
49 return m_nextId++; | |
50 } | |
51 | |
52 public List<T>[] CreateReverseMap() { | |
53 return | |
54 Enumerable.Range(UNCLASSIFIED, Count) | |
55 .Select( | |
56 i => InputSymbols | |
57 .Where(x => i != UNCLASSIFIED && m_map[GetSymbolIndex(x)] == i) | |
58 .ToList() | |
59 ) | |
60 .ToArray(); | |
61 } | |
62 | |
63 public int[] Reclassify(IAlphabet<T> newAlphabet, IEnumerable<ICollection<int>> classes) { | |
64 Safe.ArgumentNotNull(newAlphabet, "newAlphabet"); | |
65 Safe.ArgumentNotNull(classes, "classes"); | |
66 var reverseMap = CreateReverseMap(); | |
67 | |
68 int[] translationMap = new int[Count]; | |
69 | |
70 foreach (var scl in classes) { | |
71 // skip if the supper class contains the unclassified element | |
72 if (scl.Contains(UNCLASSIFIED)) | |
73 continue; | |
74 var range = new List<T>(); | |
75 foreach (var cl in scl) { | |
76 if (cl < 0 || cl >= reverseMap.Length) | |
77 throw new ArgumentOutOfRangeException(String.Format("Class {0} is not valid for the current alphabet", cl)); | |
78 range.AddRange(reverseMap[cl]); | |
79 } | |
80 var newClass = newAlphabet.DefineClass(range); | |
81 foreach (var cl in scl) | |
82 translationMap[cl] = newClass; | |
83 } | |
84 | |
85 return translationMap; | |
86 } | |
87 | |
88 public int Translate(T symbol) { | |
89 return m_map[GetSymbolIndex(symbol)]; | |
90 } | |
91 | |
92 public abstract int GetSymbolIndex(T symbol); | |
93 | |
94 public abstract IEnumerable<T> InputSymbols { get; } | |
95 | |
96 public int[] GetTranslationMap() { | |
97 return m_map; | |
98 } | |
99 } | |
100 } |