annotate Implab/Automaton/DFADefinition.cs @ 162:0526412bbb26 ref20160224

DFA refactoring
author cin
date Wed, 24 Feb 2016 08:39:53 +0300
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
162
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
1 using Implab;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
2 using System;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
3 using System.Collections.Generic;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
4 using System.Linq;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
5
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
6 namespace Implab.Automaton {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
7 public class DFADefinition<TInput, TState, TTag> : IDFADefinitionBuilder<TTag>, IDFADefinition<TInput, TState, TTag> {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
8 DFAStateDescriptior<TTag>[] m_dfaTable;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
9 readonly IAlphabet<TInput> m_inputAlphabet;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
10 readonly IAlphabet<TState> m_stateAlphabet;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
11
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
12 readonly Dictionary<int, TTag[]> m_finalStates = new Dictionary<int, TTag[]>();
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
13 readonly HashSet<AutomatonTransition> m_transitions = new HashSet<AutomatonTransition>();
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
14
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
15 public DFADefinition(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
16 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
17 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
18
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
19 m_inputAlphabet = inputAlphabet;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
20 m_stateAlphabet = stateAlphabet;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
21 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
22
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
23 public void DefineTransition(int s1, int s2, int symbol) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
24 Safe.ArgumentInRange(s1, 0, m_stateAlphabet.Count-1, "s1");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
25 Safe.ArgumentInRange(s2, 0, m_stateAlphabet.Count-1, "s2");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
26 Safe.ArgumentInRange(symbol, 0, m_inputAlphabet.Count-1, "symbol");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
27
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
28 m_transitions.Add(new AutomatonTransition(s1, s2, symbol));
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
29 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
30
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
31
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
32 #region IDFADefinition implementation
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
33
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
34 public DFAStateDescriptior<TTag>[] GetTransitionTable() {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
35 if (m_dfaTable == null) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
36 m_dfaTable = new DFAStateDescriptior<TTag>[m_stateAlphabet.Count];
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
37
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
38 foreach (var pair in m_finalStates) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
39 var idx = pair.Key;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
40
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
41 m_dfaTable[idx].final = true;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
42 m_dfaTable[idx].tag = m_dfaTable[idx].tag != null ?
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
43 m_dfaTable[idx].tag.Concat(pair.Value).Distinct().ToArray() :
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
44 pair.Value;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
45 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
46
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
47 foreach (var t in m_transitions) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
48 if (m_dfaTable[t.s1].transitions == null) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
49 m_dfaTable[t.s1].transitions = new int[m_inputAlphabet.Count];
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
50 for (int i = 0; i < m_dfaTable[t.s1].transitions.Length; i++)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
51 m_dfaTable[t.s1].transitions[i] = DFAConst.UNREACHABLE_STATE;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
52 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
53
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
54 m_dfaTable[t.s1].transitions[t.edge] = t.s2;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
55 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
56 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
57 return m_dfaTable;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
58 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
59
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
60 public IAlphabet<TInput> InputAlphabet {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
61 get {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
62 return m_inputAlphabet;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
63 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
64 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
65
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
66 public IAlphabet<TState> StateAlphabet {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
67 get {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
68 return m_stateAlphabet;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
69 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
70 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
71
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
72 #endregion
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
73
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
74 #region IDFADefinitionBuilder
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
75
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
76 public void DefineTransition(int s1, int s2, int symbol) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
77 Safe.ArgumentInRange(s1, 0, m_stateAlphabet.Count - 1, "s1");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
78 Safe.ArgumentInRange(s2, 0, m_stateAlphabet.Count - 1, "s2");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
79 Safe.ArgumentInRange(symbol, 0, m_inputAlphabet.Count - 1, "symbol");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
80
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
81 m_transitions.Add(new AutomatonTransition(s1, s2, symbol));
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
82 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
83
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
84 public void MarkFinalState(int state, params TTag[] tags) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
85 m_finalStates[state] = tags;
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
86 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
87
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
88
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
89 #endregion
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
90
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
91 protected void Optimize(IDFADefinitionBuilder<TTag> optimalDFA,IAlphabetBuilder<TInput> optimalInputAlphabet, IAlphabetBuilder<TState> optimalStateAlphabet) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
92 Safe.ArgumentNotNull(optimalDFA, "dfa");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
93 Safe.ArgumentNotNull(optimalInputAlphabet, "optimalInputAlphabet");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
94 Safe.ArgumentNotNull(optimalStateAlphabet, "optimalStateAlphabet");
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
95
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
96 var setComparer = new CustomEqualityComparer<HashSet<int>>(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
97 (x, y) => x.SetEquals(y),
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
98 s => s.Sum(x => x.GetHashCode())
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
99 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
100
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
101 var arrayComparer = new CustomEqualityComparer<TTag[]>(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
102 (x,y) => (new HashSet<int>(x)).SetEquals(new HashSet<int>(y)),
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
103 a => a.Sum(x => x.GetHashCode())
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
104 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
105
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
106 var optimalStates = new HashSet<HashSet<int>>(setComparer);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
107 var queue = new HashSet<HashSet<int>>(setComparer);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
108
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
109 // получаем конечные состояния, сгруппированные по маркерам
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
110 optimalStates.UnionWith(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
111 m_finalStates
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
112 .GroupBy(pair => pair.Value, arrayComparer)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
113 .Select(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
114 g => new HashSet<int>(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
115 g.Select( pair => pair.Key)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
116 )
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
117 )
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
118 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
119
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
120 var state = new HashSet<int>(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
121 Enumerable
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
122 .Range(0, m_stateAlphabet.Count - 1)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
123 .Where(i => !m_finalStates.ContainsKey(i))
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
124 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
125 optimalStates.Add(state);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
126 queue.Add(state);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
127
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
128 var rmap = m_transitions
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
129 .GroupBy(t => t.s2)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
130 .ToLookup(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
131 g => g.Key, // s2
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
132 g => g.ToLookup(t => t.edge, t => t.s1)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
133 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
134
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
135 while (queue.Count > 0) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
136 var stateA = queue.First();
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
137 queue.Remove(stateA);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
138
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
139 for (int c = 0; c < m_inputAlphabet.Count; c++) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
140 var stateX = new HashSet<int>();
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
141 foreach(var a in stateA)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
142 stateX.UnionWith(rmap[a][c]); // all states from wich 'c' leads to 'a'
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
143
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
144 foreach (var stateY in optimalStates.ToArray()) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
145 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
146 var stateR1 = new HashSet<int>(stateY);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
147 var stateR2 = new HashSet<int>(stateY);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
148
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
149 stateR1.IntersectWith(stateX);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
150 stateR2.ExceptWith(stateX);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
151
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
152 optimalStates.Remove(stateY);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
153 optimalStates.Add(stateR1);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
154 optimalStates.Add(stateR2);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
155
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
156 if (queue.Contains(stateY)) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
157 queue.Remove(stateY);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
158 queue.Add(stateR1);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
159 queue.Add(stateR2);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
160 } else {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
161 queue.Add(stateR1.Count <= stateR2.Count ? stateR1 : stateR2);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
162 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
163 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
164 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
165 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
166 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
167
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
168 // карта получения оптимального состояния по соотвествующему ему простому состоянию
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
169 var statesMap = m_stateAlphabet.Reclassify(optimalStateAlphabet, optimalStates);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
170
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
171 // получаем минимальный алфавит
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
172 // входные символы не различимы, если Move(s,a1) == Move(s,a2)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
173 var optimalAlphabet = m_transitions
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
174 .GroupBy(t => Tuple.Create(statesMap[t.s1], statesMap[t.s2]), t => t.edge);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
175
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
176 var alphabetMap = m_inputAlphabet.Reclassify(optimalInputAlphabet, optimalAlphabet);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
177
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
178 var optimalTags = m_finalStates
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
179 .GroupBy(pair => statesMap[pair.Key])
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
180 .ToDictionary(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
181 g => g.Key,
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
182 g => g.SelectMany(pair => pair.Value).ToArray()
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
183 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
184
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
185 // построение автомата
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
186 foreach (var pair in optimalTags)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
187 optimalDFA.MarkFinalState(pair.Key, pair.Value);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
188
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
189 foreach (var t in m_transitions.Select(t => new AutomatonTransition(statesMap[t.s1],statesMap[t.s2],alphabetMap[t.edge])).Distinct())
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
190 optimalDFA.DefineTransition(t.s1, t.s2, t.edge);
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
191 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
192
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
193 public void PrintDFA() {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
194
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
195 var inputMap = InputAlphabet.CreateReverseMap();
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
196 var stateMap = StateAlphabet.CreateReverseMap();
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
197
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
198 for (int i = 0; i < inputMap.Length; i++) {
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
199 Console.WriteLine("C{0}: {1}", i, String.Join(",", inputMap[i]));
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
200 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
201
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
202 foreach(var t in m_transitions)
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
203 Console.WriteLine(
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
204 "S{0} -{1}-> S{2}{3}",
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
205 stateMap[t.s1],
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
206 String.Join(",", inputMap[t.edge]),
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
207 stateMap[t.s2],
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
208 m_finalStates.ContainsKey(t.s2) ? "$" : ""
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
209 );
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
210
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
211 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
212 }
0526412bbb26 DFA refactoring
cin
parents:
diff changeset
213 }