163
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3 using System.Linq;
|
|
4
|
|
5 namespace Implab.Automaton {
|
|
6 public class MapAlphabet<T> : IAlphabetBuilder<T> {
|
|
7 readonly Dictionary<T,int> m_map;
|
164
|
8 int m_nextCls = 1;
|
|
9
|
|
10 public MapAlphabet() {
|
|
11 m_map = new Dictionary<T, int>();
|
|
12 }
|
163
|
13
|
|
14 public MapAlphabet(IEqualityComparer<T> comparer) {
|
|
15 m_map = new Dictionary<T, int>(comparer);
|
|
16 }
|
|
17
|
|
18 #region IAlphabetBuilder implementation
|
|
19
|
|
20 public int DefineSymbol(T symbol) {
|
|
21 int cls;
|
|
22 if (m_map.TryGetValue(symbol, out cls))
|
|
23 return cls;
|
|
24
|
|
25 cls = m_nextCls++;
|
|
26
|
|
27 m_map.Add(symbol, cls);
|
|
28
|
|
29 return cls;
|
|
30 }
|
|
31
|
|
32 public int DefineClass(IEnumerable<T> symbols) {
|
|
33 Safe.ArgumentNotNull(symbols, "symbols");
|
|
34 symbols = symbols.Distinct();
|
|
35
|
|
36 foreach (var symbol in symbols) {
|
|
37 if (!m_map.Contains(symbol))
|
|
38 m_map.Add(symbol, m_nextCls);
|
|
39 else
|
|
40 throw new InvalidOperationException(String.Format("Symbol '{0}' already in use", symbol));
|
|
41 }
|
|
42 return m_nextCls++;
|
|
43 }
|
|
44
|
|
45 #endregion
|
|
46
|
|
47 #region IAlphabet implementation
|
|
48
|
|
49 public List<T>[] CreateReverseMap() {
|
|
50 var empty = new List<T>();
|
|
51 var rmap = new List<T>[m_nextCls];
|
|
52
|
|
53 for (int i = 0; i < rmap.Length; i++)
|
|
54 rmap[i] = empty;
|
|
55
|
|
56 foreach (var pair in m_map) {
|
|
57 var symbols = rmap[pair.Value];
|
|
58 if (symbols == null) {
|
|
59 symbols = new List<T>();
|
|
60 rmap[pair.Value] = symbols;
|
|
61 }
|
|
62
|
|
63 symbols.Add(pair.Key);
|
|
64 }
|
|
65
|
|
66 return rmap;
|
|
67 }
|
|
68
|
|
69 public int[] Reclassify(IAlphabetBuilder<T> newAlphabet, IEnumerable<IEnumerable<int>> classes) {
|
|
70 Safe.ArgumentNotNull(newAlphabet, "newAlphabet");
|
|
71 Safe.ArgumentNotNull(classes, "classes");
|
|
72
|
|
73 var rmap = CreateReverseMap();
|
|
74 var map = new int[rmap.Length];
|
|
75
|
|
76 foreach (var cls in classes) {
|
164
|
77 if (cls.Contains(DFAConst.UNCLASSIFIED_INPUT))
|
|
78 continue;
|
|
79
|
163
|
80 var symbols = new List<T>();
|
|
81 foreach (var id in cls) {
|
|
82 if (id < 0 || id >= rmap.Length)
|
|
83 throw new ArgumentOutOfRangeException(String.Format("Class {0} is not valid for the current alphabet", id));
|
|
84 if (rmap[id] != null)
|
|
85 symbols.AddRange(rmap[id]);
|
|
86 }
|
|
87
|
|
88 var newId = newAlphabet.DefineClass(symbols);
|
|
89
|
|
90 foreach (var id in cls)
|
|
91 map[id] = newId;
|
|
92 }
|
|
93 }
|
|
94
|
|
95 public int Translate(T symobl) {
|
|
96 int cls;
|
|
97 return m_map.TryGetValue(symobl, out cls) ? cls : DFAConst.UNCLASSIFIED_INPUT;
|
|
98 }
|
|
99
|
|
100 public int Count {
|
|
101 get {
|
|
102 return m_nextCls;
|
|
103 }
|
|
104 }
|
|
105
|
|
106 #endregion
|
|
107 }
|
|
108 }
|
|
109
|