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 }