/// <summary> /// Simple, original brics implementation of determinize() /// </summary> public static void DeterminizeSimple(Automaton a) { if (a.Deterministic || a.IsSingleton) { return; } HashSet <State> initialset = new ValueHashSet <State>(); initialset.Add(a.Initial); DeterminizeSimple(a, initialset); }
/// <summary> /// Reverses the language of the given (non-singleton) automaton while returning /// the set of new initial states. /// </summary> public static ISet <State> Reverse(Automaton a) { a.ExpandSingleton(); // reverse all edges Dictionary <State, HashSet <Transition> > m = new Dictionary <State, HashSet <Transition> >(); State[] states = a.NumberedStates; HashSet <State> accept = new HashSet <State>(); foreach (State s in states) { if (s.Accept) { accept.Add(s); } } foreach (State r in states) { m[r] = new ValueHashSet <Transition>(); r.accept = false; } foreach (State r in states) { foreach (Transition t in r.Transitions) { m[t.To].Add(new Transition(t.Min_Renamed, t.Max_Renamed, r)); } } foreach (State r in states) { HashSet <Transition> tr = m[r]; r.Transitions = tr.ToArray(/*new Transition[tr.Count]*/); } // make new initial+final states a.Initial.accept = true; a.Initial = new State(); foreach (State r in accept) { a.Initial.AddEpsilon(r); // ensures that all initial states are reachable } a.deterministic = false; a.ClearNumberedStates(); return(accept); }
/// <summary> /// Simple, original brics implementation of determinize() /// Determinizes the given automaton using the given set of initial states. /// </summary> public static void DeterminizeSimple(Automaton a, ISet <State> initialset) { int[] points = a.StartPoints; // subset construction IDictionary <ISet <State>, ISet <State> > sets = new Dictionary <ISet <State>, ISet <State> >(); LinkedList <ISet <State> > worklist = new LinkedList <ISet <State> >(); IDictionary <ISet <State>, State> newstate = new Dictionary <ISet <State>, State>(); sets[initialset] = initialset; worklist.AddLast(initialset); a.Initial = new State(); newstate[initialset] = a.Initial; while (worklist.Count > 0) { ISet <State> s = worklist.First.Value; worklist.RemoveFirst(); State r = newstate[s]; foreach (State q in s) { if (q.Accept) { r.Accept = true; break; } } for (int n = 0; n < points.Length; n++) { ISet <State> p = new ValueHashSet <State>(); foreach (State q in s) { foreach (Transition t in q.Transitions) { if (t.Min <= points[n] && points[n] <= t.Max) { p.Add(t.To); } } } if (!sets.ContainsKey(p)) { sets[p] = p; worklist.AddLast(p); newstate[p] = new State(); } State q_ = newstate[p]; int min = points[n]; int max; if (n + 1 < points.Length) { max = points[n + 1] - 1; } else { max = Character.MAX_CODE_POINT; } r.AddTransition(new Transition(min, max, q_)); } } a.Deterministic = true; a.ClearNumberedStates(); a.RemoveDeadTransitions(); }
/// <summary> /// Reverses the language of the given (non-singleton) automaton while returning /// the set of new initial states. /// </summary> public static ISet<State> Reverse(Automaton a) { a.ExpandSingleton(); // reverse all edges Dictionary<State, HashSet<Transition>> m = new Dictionary<State, HashSet<Transition>>(); State[] states = a.NumberedStates; HashSet<State> accept = new HashSet<State>(); foreach (State s in states) { if (s.Accept) { accept.Add(s); } } foreach (State r in states) { m[r] = new ValueHashSet<Transition>(); r.accept = false; } foreach (State r in states) { foreach (Transition t in r.Transitions) { m[t.To].Add(new Transition(t.Min_Renamed, t.Max_Renamed, r)); } } foreach (State r in states) { HashSet<Transition> tr = m[r]; r.Transitions = tr.ToArray(/*new Transition[tr.Count]*/); } // make new initial+final states a.Initial.accept = true; a.Initial = new State(); foreach (State r in accept) { a.Initial.AddEpsilon(r); // ensures that all initial states are reachable } a.deterministic = false; a.ClearNumberedStates(); return accept; }
/// <summary> /// Minimizes the given automaton using Hopcroft's algorithm. /// </summary> public static void MinimizeHopcroft(Automaton a) { a.Determinize(); if (a.Initial.numTransitions == 1) { Transition t = a.Initial.TransitionsArray[0]; if (t.To == a.Initial && t.Min_Renamed == Character.MIN_CODE_POINT && t.Max_Renamed == Character.MAX_CODE_POINT) { return; } } a.Totalize(); // initialize data structures int[] sigma = a.StartPoints; State[] states = a.NumberedStates; int sigmaLen = sigma.Length, statesLen = states.Length; List <State>[,] reverse = new List <State> [statesLen, sigmaLen]; HashSet <State>[] partition = new ValueHashSet <State> [statesLen]; List <State>[] splitblock = new List <State> [statesLen]; int[] block = new int[statesLen]; StateList[,] active = new StateList[statesLen, sigmaLen]; StateListNode[,] active2 = new StateListNode[statesLen, sigmaLen]; LinkedList <IntPair> pending = new LinkedList <IntPair>(); BitArray pending2 = new BitArray(sigmaLen * statesLen); BitArray split = new BitArray(statesLen), refine = new BitArray(statesLen), refine2 = new BitArray(statesLen); for (int q = 0; q < statesLen; q++) { splitblock[q] = new List <State>(); partition[q] = new ValueHashSet <State>(); for (int x = 0; x < sigmaLen; x++) { active[q, x] = new StateList(); } } // find initial partition and reverse edges for (int q = 0; q < statesLen; q++) { State qq = states[q]; int j = qq.accept ? 0 : 1; partition[j].Add(qq); block[q] = j; for (int x = 0; x < sigmaLen; x++) { //List<State>[] r = reverse[qq.Step(sigma[x]).number]; var r = qq.Step(sigma[x]).number; if (reverse[r, x] == null) { reverse[r, x] = new List <State>(); } reverse[r, x].Add(qq); } } // initialize active sets for (int j = 0; j <= 1; j++) { for (int x = 0; x < sigmaLen; x++) { foreach (State qq in partition[j]) { if (reverse[qq.number, x] != null) { active2[qq.number, x] = active[j, x].Add(qq); } } } } // initialize pending for (int x = 0; x < sigmaLen; x++) { int j = (active[0, x].Size <= active[1, x].Size) ? 0 : 1; pending.AddLast(new IntPair(j, x)); pending2.SafeSet(x * statesLen + j, true); } // process pending until fixed point int k = 2; while (pending.Count > 0) { IntPair ip = pending.First.Value; pending.RemoveFirst(); int p = ip.N1; int x = ip.N2; pending2.SafeSet(x * statesLen + p, false); // find states that need to be split off their blocks for (StateListNode m = active[p, x].First; m != null; m = m.Next) { List <State> r = reverse[m.q.number, x]; if (r != null) { foreach (State s in r) { int i = s.number; if (!split.SafeGet(i)) { split.SafeSet(i, true); int j = block[i]; splitblock[j].Add(s); if (!refine2.SafeGet(j)) { refine2.SafeSet(j, true); refine.SafeSet(j, true); } } } } } // refine blocks for (int j = Number.NextSetBit(refine, 0); j >= 0; j = Number.NextSetBit(refine, j + 1)) { List <State> sb = splitblock[j]; if (sb.Count < partition[j].Count) { HashSet <State> b1 = partition[j]; HashSet <State> b2 = partition[k]; foreach (State s in sb) { b1.Remove(s); b2.Add(s); block[s.number] = k; for (int c = 0; c < sigmaLen; c++) { StateListNode sn = active2[s.number, c]; if (sn != null && sn.Sl == active[j, c]) { sn.Remove(); active2[s.number, c] = active[k, c].Add(s); } } } // update pending for (int c = 0; c < sigmaLen; c++) { int aj = active[j, c].Size, ak = active[k, c].Size, ofs = c * statesLen; if (!pending2.SafeGet(ofs + j) && 0 < aj && aj <= ak) { pending2.SafeSet(ofs + j, true); pending.AddLast(new IntPair(j, c)); } else { pending2.SafeSet(ofs + k, true); pending.AddLast(new IntPair(k, c)); } } k++; } refine2.SafeSet(j, false); foreach (State s in sb) { split.SafeSet(s.number, false); } sb.Clear(); } refine.SetAll(false); } // make a new state for each equivalence class, set initial state State[] newstates = new State[k]; for (int n = 0; n < newstates.Length; n++) { State s = new State(); newstates[n] = s; foreach (State q in partition[n]) { if (q == a.Initial) { a.Initial = s; } s.accept = q.accept; s.number = q.number; // select representative q.number = n; } } // build transitions and set acceptance for (int n = 0; n < newstates.Length; n++) { State s = newstates[n]; s.accept = states[s.number].accept; foreach (Transition t in states[s.number].Transitions) { s.AddTransition(new Transition(t.Min_Renamed, t.Max_Renamed, newstates[t.To.number])); } } a.ClearNumberedStates(); a.RemoveDeadTransitions(); }
/// <summary> /// Simple, original brics implementation of determinize() /// Determinizes the given automaton using the given set of initial states. /// </summary> public static void DeterminizeSimple(Automaton a, ISet<State> initialset) { int[] points = a.StartPoints; // subset construction IDictionary<ISet<State>, ISet<State>> sets = new Dictionary<ISet<State>, ISet<State>>(); LinkedList<ISet<State>> worklist = new LinkedList<ISet<State>>(); IDictionary<ISet<State>, State> newstate = new Dictionary<ISet<State>, State>(); sets[initialset] = initialset; worklist.AddLast(initialset); a.Initial = new State(); newstate[initialset] = a.Initial; while (worklist.Count > 0) { ISet<State> s = worklist.First.Value; worklist.RemoveFirst(); State r = newstate[s]; foreach (State q in s) { if (q.Accept) { r.Accept = true; break; } } for (int n = 0; n < points.Length; n++) { ISet<State> p = new ValueHashSet<State>(); foreach (State q in s) { foreach (Transition t in q.Transitions) { if (t.Min <= points[n] && points[n] <= t.Max) { p.Add(t.To); } } } if (!sets.ContainsKey(p)) { sets[p] = p; worklist.AddLast(p); newstate[p] = new State(); } State q_ = newstate[p]; int min = points[n]; int max; if (n + 1 < points.Length) { max = points[n + 1] - 1; } else { max = Character.MAX_CODE_POINT; } r.AddTransition(new Transition(min, max, q_)); } } a.Deterministic = true; a.ClearNumberedStates(); a.RemoveDeadTransitions(); }
/// <summary> /// Simple, original brics implementation of determinize() /// </summary> public static void DeterminizeSimple(Automaton a) { if (a.Deterministic || a.IsSingleton) { return; } HashSet<State> initialset = new ValueHashSet<State>(); initialset.Add(a.Initial); DeterminizeSimple(a, initialset); }
/// <summary> /// Minimizes the given automaton using Hopcroft's algorithm. /// </summary> public static void MinimizeHopcroft(Automaton a) { a.Determinize(); if (a.Initial.numTransitions == 1) { Transition t = a.Initial.TransitionsArray[0]; if (t.To == a.Initial && t.Min_Renamed == Character.MIN_CODE_POINT && t.Max_Renamed == Character.MAX_CODE_POINT) { return; } } a.Totalize(); // initialize data structures int[] sigma = a.StartPoints; State[] states = a.NumberedStates; int sigmaLen = sigma.Length, statesLen = states.Length; List<State>[,] reverse = new List<State>[statesLen, sigmaLen]; HashSet<State>[] partition = new ValueHashSet<State>[statesLen]; List<State>[] splitblock = new List<State>[statesLen]; int[] block = new int[statesLen]; StateList[,] active = new StateList[statesLen, sigmaLen]; StateListNode[,] active2 = new StateListNode[statesLen, sigmaLen]; LinkedList<IntPair> pending = new LinkedList<IntPair>(); BitArray pending2 = new BitArray(sigmaLen * statesLen); BitArray split = new BitArray(statesLen), refine = new BitArray(statesLen), refine2 = new BitArray(statesLen); for (int q = 0; q < statesLen; q++) { splitblock[q] = new List<State>(); partition[q] = new ValueHashSet<State>(); for (int x = 0; x < sigmaLen; x++) { active[q, x] = new StateList(); } } // find initial partition and reverse edges for (int q = 0; q < statesLen; q++) { State qq = states[q]; int j = qq.accept ? 0 : 1; partition[j].Add(qq); block[q] = j; for (int x = 0; x < sigmaLen; x++) { //List<State>[] r = reverse[qq.Step(sigma[x]).number]; var r = qq.Step(sigma[x]).number; if (reverse[r, x] == null) { reverse[r, x] = new List<State>(); } reverse[r, x].Add(qq); } } // initialize active sets for (int j = 0; j <= 1; j++) { for (int x = 0; x < sigmaLen; x++) { foreach (State qq in partition[j]) { if (reverse[qq.number, x] != null) { active2[qq.number, x] = active[j, x].Add(qq); } } } } // initialize pending for (int x = 0; x < sigmaLen; x++) { int j = (active[0, x].Size <= active[1, x].Size) ? 0 : 1; pending.AddLast(new IntPair(j, x)); pending2.SafeSet(x * statesLen + j, true); } // process pending until fixed point int k = 2; while (pending.Count > 0) { IntPair ip = pending.First.Value; pending.RemoveFirst(); int p = ip.N1; int x = ip.N2; pending2.SafeSet(x * statesLen + p, false); // find states that need to be split off their blocks for (StateListNode m = active[p, x].First; m != null; m = m.Next) { List<State> r = reverse[m.q.number, x]; if (r != null) { foreach (State s in r) { int i = s.number; if (!split.SafeGet(i)) { split.SafeSet(i, true); int j = block[i]; splitblock[j].Add(s); if (!refine2.SafeGet(j)) { refine2.SafeSet(j, true); refine.SafeSet(j, true); } } } } } // refine blocks for (int j = Number.NextSetBit(refine, 0); j >= 0; j = Number.NextSetBit(refine, j + 1)) { List<State> sb = splitblock[j]; if (sb.Count < partition[j].Count) { HashSet<State> b1 = partition[j]; HashSet<State> b2 = partition[k]; foreach (State s in sb) { b1.Remove(s); b2.Add(s); block[s.number] = k; for (int c = 0; c < sigmaLen; c++) { StateListNode sn = active2[s.number, c]; if (sn != null && sn.Sl == active[j, c]) { sn.Remove(); active2[s.number, c] = active[k, c].Add(s); } } } // update pending for (int c = 0; c < sigmaLen; c++) { int aj = active[j, c].Size, ak = active[k, c].Size, ofs = c * statesLen; if (!pending2.SafeGet(ofs + j) && 0 < aj && aj <= ak) { pending2.SafeSet(ofs + j, true); pending.AddLast(new IntPair(j, c)); } else { pending2.SafeSet(ofs + k, true); pending.AddLast(new IntPair(k, c)); } } k++; } refine2.SafeSet(j, false); foreach (State s in sb) { split.SafeSet(s.number, false); } sb.Clear(); } refine.SetAll(false); } // make a new state for each equivalence class, set initial state State[] newstates = new State[k]; for (int n = 0; n < newstates.Length; n++) { State s = new State(); newstates[n] = s; foreach (State q in partition[n]) { if (q == a.Initial) { a.Initial = s; } s.accept = q.accept; s.number = q.number; // select representative q.number = n; } } // build transitions and set acceptance for (int n = 0; n < newstates.Length; n++) { State s = newstates[n]; s.accept = states[s.number].accept; foreach (Transition t in states[s.number].Transitions) { s.AddTransition(new Transition(t.Min_Renamed, t.Max_Renamed, newstates[t.To.number])); } } a.ClearNumberedStates(); a.RemoveDeadTransitions(); }