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 } |
