Mercurial > pub > ImplabNet
comparison Implab/Automaton/DFATable.cs @ 182:76e8f2ba12b8 ref20160224
pretty print DFA, the minimization is still buggy
author | cin |
---|---|
date | Thu, 24 Mar 2016 18:52:10 +0300 |
parents | b2b6a6640aa3 |
children | 4f82e0f161c3 |
comparison
equal
deleted
inserted
replaced
181:b2b6a6640aa3 | 182:76e8f2ba12b8 |
---|---|
1 using Implab; | 1 using Implab; |
2 using System; | 2 using System; |
3 using System.Collections.Generic; | 3 using System.Collections.Generic; |
4 using System.Linq; | 4 using System.Linq; |
5 using System.Diagnostics; | 5 using System.Diagnostics; |
6 using System.IO; | |
7 using System.CodeDom.Compiler; | |
8 using System.CodeDom; | |
6 | 9 |
7 namespace Implab.Automaton { | 10 namespace Implab.Automaton { |
8 public class DFATable : IDFATableBuilder { | 11 public class DFATable : IDFATableBuilder { |
9 int m_stateCount; | 12 int m_stateCount; |
10 int m_symbolCount; | 13 int m_symbolCount; |
99 return m_transitions.GetEnumerator(); | 102 return m_transitions.GetEnumerator(); |
100 } | 103 } |
101 | 104 |
102 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { | 105 System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { |
103 return GetEnumerator(); | 106 return GetEnumerator(); |
107 } | |
108 | |
109 public void AddSymbol(int symbol) { | |
110 Safe.ArgumentAssert(symbol >= 0, "symbol"); | |
111 m_symbolCount = Math.Max(symbol + 1, m_symbolCount); | |
104 } | 112 } |
105 | 113 |
106 public int[,] CreateTransitionTable() { | 114 public int[,] CreateTransitionTable() { |
107 var table = new int[StateCount,AlphabetSize]; | 115 var table = new int[StateCount,AlphabetSize]; |
108 | 116 |
160 GroupFinalStates() | 168 GroupFinalStates() |
161 ); | 169 ); |
162 | 170 |
163 var state = new HashSet<int>( | 171 var state = new HashSet<int>( |
164 Enumerable | 172 Enumerable |
165 .Range(0, m_stateCount - 1) | 173 .Range(0, m_stateCount) |
166 .Where(i => !m_finalStates.Contains(i)) | 174 .Where(i => !m_finalStates.Contains(i)) |
167 ); | 175 ); |
168 | 176 |
169 optimalStates.Add(state); | 177 optimalStates.Add(state); |
170 queue.Add(state); | 178 queue.Add(state); |
180 var stateA = queue.First(); | 188 var stateA = queue.First(); |
181 queue.Remove(stateA); | 189 queue.Remove(stateA); |
182 | 190 |
183 for (int c = 0; c < m_symbolCount; c++) { | 191 for (int c = 0; c < m_symbolCount; c++) { |
184 var stateX = new HashSet<int>(); | 192 var stateX = new HashSet<int>(); |
185 foreach(var a in stateA.Where(rmap.ContainsKey)) | 193 //foreach(var a in stateA.Where(rmap.ContainsKey)) |
186 stateX.UnionWith(rmap[a][c]); // all states from wich the symbol 'c' leads to the state 'a' | 194 // stateX.UnionWith(rmap[a][c]); // all states from wich the symbol 'c' leads to the state 'a' |
187 | 195 |
188 foreach (var stateY in optimalStates.ToArray()) { | 196 stateX.UnionWith(m_transitions.Where(t => stateA.Contains(t.s2) && t.edge == c).Select(t => t.s1)); |
197 | |
198 var tmp = optimalStates.ToArray(); | |
199 foreach (var stateY in tmp) { | |
189 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) { | 200 if (stateX.Overlaps(stateY) && !stateY.IsSubsetOf(stateX)) { |
190 var stateR1 = new HashSet<int>(stateY); | 201 var stateR1 = new HashSet<int>(stateY); |
191 var stateR2 = new HashSet<int>(stateY); | 202 var stateR2 = new HashSet<int>(stateY); |
192 | 203 |
193 stateR1.IntersectWith(stateX); | 204 stateR1.IntersectWith(stateX); |
243 // optimalState -> alphaClass | 254 // optimalState -> alphaClass |
244 var classes = new Dictionary<int, HashSet<int>>(); | 255 var classes = new Dictionary<int, HashSet<int>>(); |
245 | 256 |
246 foreach (var term in A) { | 257 foreach (var term in A) { |
247 // ищем все переходы класса по символу term | 258 // ищем все переходы класса по символу term |
248 var res = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).ToArray(); | 259 var s2 = m_transitions.Where(t => stateMap[t.s1] == s && t.edge == term).Select(t => stateMap[t.s2]).DefaultIfEmpty(-1).First(); |
249 | 260 |
250 Debug.Assert(res.Length <= 1); | |
251 | |
252 var s2 = res.Length > 0 ? res[0] : -1; | |
253 | |
254 HashSet<int> a2; | 261 HashSet<int> a2; |
255 if (!classes.TryGetValue(s2, out a2)) { | 262 if (!classes.TryGetValue(s2, out a2)) { |
256 a2 = new HashSet<int>(); | 263 a2 = new HashSet<int>(); |
257 newQueue.Enqueue(a2); | 264 newQueue.Enqueue(a2); |
258 classes[s2] = a2; | 265 classes[s2] = a2; |
281 if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT) | 288 if (nextCls == AutomatonConst.UNCLASSIFIED_INPUT) |
282 nextCls++; | 289 nextCls++; |
283 | 290 |
284 // сохраняем DFAConst.UNCLASSIFIED_INPUT | 291 // сохраняем DFAConst.UNCLASSIFIED_INPUT |
285 var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls++; | 292 var cls = item.Contains(AutomatonConst.UNCLASSIFIED_INPUT) ? AutomatonConst.UNCLASSIFIED_INPUT : nextCls++; |
293 optimalDFA.AddSymbol(cls); | |
286 | 294 |
287 foreach (var a in item) | 295 foreach (var a in item) |
288 alphabetMap[a] = cls; | 296 alphabetMap[a] = cls; |
289 } | 297 } |
290 | 298 |
296 | 304 |
297 foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct()) | 305 foreach (var t in m_transitions.Select(t => new AutomatonTransition(stateMap[t.s1],stateMap[t.s2],alphabetMap[t.edge])).Distinct()) |
298 optimalDFA.Add(t); | 306 optimalDFA.Add(t); |
299 } | 307 } |
300 | 308 |
301 protected void PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) { | 309 protected string PrintDFA<TInput, TState>(IAlphabet<TInput> inputAlphabet, IAlphabet<TState> stateAlphabet) { |
302 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet"); | 310 Safe.ArgumentNotNull(inputAlphabet, "inputAlphabet"); |
303 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet"); | 311 Safe.ArgumentNotNull(stateAlphabet, "stateAlphabet"); |
304 | 312 |
305 foreach(var t in m_transitions) | 313 var data = new List<string>(); |
306 Console.WriteLine( | 314 |
307 "[{0}] -{{{1}}}-> [{2}]{3}", | 315 data.Add("digraph dfa {"); |
308 String.Join(",", stateAlphabet.GetSymbols(t.s1)), | 316 |
309 String.Join("", inputAlphabet.GetSymbols(t.edge)), | 317 foreach (var final in m_finalStates) |
310 String.Join(",", stateAlphabet.GetSymbols(t.s2)), | 318 data.Add(String.Format("{0} [shape=box];",String.Join("", stateAlphabet.GetSymbols(final)))); |
311 m_finalStates.Contains(t.s2) ? "$" : "" | 319 |
312 ); | 320 foreach (var t in m_transitions) |
313 } | 321 data.Add(String.Format( |
314 | 322 "{0} -> {2} [label={1}];", |
323 String.Join("", stateAlphabet.GetSymbols(t.s1)), | |
324 ToLiteral(ToLiteral(String.Join("", t.edge == AutomatonConst.UNCLASSIFIED_INPUT ? new [] { "@" } : inputAlphabet.GetSymbols(t.edge).Select(x => x.ToString())))), | |
325 String.Join("", stateAlphabet.GetSymbols(t.s2)) | |
326 )); | |
327 data.Add("}"); | |
328 return String.Join("\n", data); | |
329 } | |
330 | |
331 static string ToLiteral(string input) | |
332 { | |
333 using (var writer = new StringWriter()) | |
334 { | |
335 using (var provider = CodeDomProvider.CreateProvider("CSharp")) | |
336 { | |
337 provider.GenerateCodeFromExpression(new CodePrimitiveExpression(input), writer, null); | |
338 return writer.ToString(); | |
339 } | |
340 } | |
341 } | |
315 } | 342 } |
316 } | 343 } |