public StateListNode(State state, StateList stateList) { State = state; StateList = stateList; if (stateList.Size++ == 0) { stateList.First = stateList.Last = this; } else { stateList.Last.Next = this; Prev = stateList.Last; stateList.Last = this; } }
internal static StateListNode[][] ReturnRectangularStateListNodeArray(int Size1, int Size2) { StateListNode[][] Array; if (Size1 > -1) { Array = new StateListNode[Size1][]; if (Size2 > -1) { for (int Array1 = 0; Array1 < Size1; Array1++) { Array[Array1] = new StateListNode[Size2]; } } } else Array = null; return Array; }
internal static StateListNode[][] ReturnRectangularStateListNodeArray(int Size1, int Size2) { StateListNode[][] Array; if (Size1 > -1) { Array = new StateListNode[Size1][]; if (Size2 > -1) { for (int Array1 = 0; Array1 < Size1; Array1++) { Array[Array1] = new StateListNode[Size2]; } } } else { Array = null; } return(Array); }
/// <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 == Character.MIN_CODE_POINT && t.max == Character.MAX_CODE_POINT) { return; } } a.Totalize(); // initialize data structures int[] sigma = a.GetStartPoints(); State[] states = a.GetNumberedStates(); int sigmaLen = sigma.Length, statesLen = states.Length; List <State>[,] reverse = new List <State> [statesLen, sigmaLen]; ISet <State>[] partition = new EquatableSet <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 <Int32Pair> pending = new LinkedList <Int32Pair>(); OpenBitSet pending2 = new OpenBitSet(sigmaLen * statesLen); OpenBitSet split = new OpenBitSet(statesLen), refine = new OpenBitSet(statesLen), refine2 = new OpenBitSet(statesLen); for (int q = 0; q < statesLen; q++) { splitblock[q] = new List <State>(); partition[q] = new EquatableSet <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].Count <= active[1, x].Count) ? 0 : 1; pending.AddLast(new Int32Pair(j, x)); pending2.Set(x * statesLen + j); } // process pending until fixed point int k = 2; while (pending.Count > 0) { Int32Pair ip = pending.First.Value; pending.Remove(ip); int p = ip.N1; int x = ip.N2; pending2.Clear(x * statesLen + p); // 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.Get(i)) { split.Set(i); int j = block[i]; splitblock[j].Add(s); if (!refine2.Get(j)) { refine2.Set(j); refine.Set(j); } } } } } // refine blocks for (int j = refine.NextSetBit(0); j >= 0; j = refine.NextSetBit(j + 1)) { List <State> sb = splitblock[j]; if (sb.Count < partition[j].Count) { ISet <State> b1 = partition[j]; ISet <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].Count, ak = active[k, c].Count, ofs = c * statesLen; if (!pending2.Get(ofs + j) && 0 < aj && aj <= ak) { pending2.Set(ofs + j); pending.AddLast(new Int32Pair(j, c)); } else { pending2.Set(ofs + k); pending.AddLast(new Int32Pair(k, c)); } } k++; } refine2.Clear(j); foreach (State s in sb) { split.Clear(s.number); } sb.Clear(); } refine.Clear(0, refine.Length - 1); } // 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].GetTransitions()) { s.AddTransition(new Transition(t.min, t.max, newstates[t.to.number])); } } a.ClearNumberedStates(); a.RemoveDeadTransitions(); }
internal static void MinimizeHopcroft(Automaton a) { a.Determinize(); IList <Transition> tr = a.Initial.Transitions; if (tr.Count == 1) { Transition t = tr[0]; if (t.To == a.Initial && t.Min == char.MinValue && t.Max == char.MaxValue) { return; } } a.Totalize(); // Make arrays for numbered states and effective alphabet. HashSet <State> ss = a.GetStates(); var states = new State[ss.Count]; int number = 0; foreach (State q in ss) { states[number] = q; q.Number = number++; } char[] sigma = a.GetStartPoints(); // Initialize data structures. var reverse = new List <List <LinkedList <State> > >(); foreach (State s in states) { var v = new List <LinkedList <State> >(); Initialize(ref v, sigma.Length); reverse.Add(v); } var reverseNonempty = new bool[states.Length, sigma.Length]; var partition = new List <LinkedList <State> >(); Initialize(ref partition, states.Length); var block = new int[states.Length]; var active = new StateList[states.Length, sigma.Length]; var active2 = new StateListNode[states.Length, sigma.Length]; var pending = new LinkedList <IntPair>(); var pending2 = new bool[sigma.Length, states.Length]; var split = new List <State>(); var split2 = new bool[states.Length]; var refine = new List <int>(); var refine2 = new bool[states.Length]; var splitblock = new List <List <State> >(); Initialize(ref splitblock, states.Length); for (int q = 0; q < states.Length; q++) { splitblock[q] = new List <State>(); partition[q] = new LinkedList <State>(); for (int x = 0; x < sigma.Length; x++) { reverse[q][x] = new LinkedList <State>(); active[q, x] = new StateList(); } } // Find initial partition and reverse edges. foreach (State qq in states) { int j = qq.Accept ? 0 : 1; partition[j].AddLast(qq); block[qq.Number] = j; for (int x = 0; x < sigma.Length; x++) { char y = sigma[x]; State p = qq.Step(y); reverse[p.Number][x].AddLast(qq); reverseNonempty[p.Number, x] = true; } } // Initialize active sets. for (int j = 0; j <= 1; j++) { for (int x = 0; x < sigma.Length; x++) { foreach (State qq in partition[j]) { if (reverseNonempty[qq.Number, x]) { active2[qq.Number, x] = active[j, x].Add(qq); } } } } // Initialize pending. for (int x = 0; x < sigma.Length; x++) { int a0 = active[0, x].Size; int a1 = active[1, x].Size; int j = a0 <= a1 ? 0 : 1; pending.AddLast(new IntPair(j, x)); pending2[x, j] = true; } // Process pending until fixed point. int k = 2; while (pending.Count > 0) { IntPair ip = pending.RemoveAndReturnFirst(); int p = ip.N1; int x = ip.N2; pending2[x, p] = false; // Find states that need to be split off their blocks. for (StateListNode m = active[p, x].First; m != null; m = m.Next) { foreach (State s in reverse[m.State.Number][x]) { if (!split2[s.Number]) { split2[s.Number] = true; split.Add(s); int j = block[s.Number]; splitblock[j].Add(s); if (!refine2[j]) { refine2[j] = true; refine.Add(j); } } } } // Refine blocks. foreach (int j in refine) { if (splitblock[j].Count < partition[j].Count) { LinkedList <State> b1 = partition[j]; LinkedList <State> b2 = partition[k]; foreach (State s in splitblock[j]) { b1.Remove(s); b2.AddLast(s); block[s.Number] = k; for (int c = 0; c < sigma.Length; c++) { StateListNode sn = active2[s.Number, c]; if (sn != null && sn.StateList == active[j, c]) { sn.Remove(); active2[s.Number, c] = active[k, c].Add(s); } } } // Update pending. for (int c = 0; c < sigma.Length; c++) { int aj = active[j, c].Size; int ak = active[k, c].Size; if (!pending2[c, j] && 0 < aj && aj <= ak) { pending2[c, j] = true; pending.AddLast(new IntPair(j, c)); } else { pending2[c, k] = true; pending.AddLast(new IntPair(k, c)); } } k++; } foreach (State s in splitblock[j]) { split2[s.Number] = false; } refine2[j] = false; splitblock[j].Clear(); } split.Clear(); refine.Clear(); } // Make a new state for each equivalence class, set initial state. var newstates = new State[k]; for (int n = 0; n < newstates.Length; n++) { var 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. foreach (State s in newstates) { s.Accept = states[s.Number].Accept; foreach (Transition t in states[s.Number].Transitions) { s.Transitions.Add(new Transition(t.Min, t.Max, newstates[t.To.Number])); } } a.RemoveDeadTransitions(); }
/// <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 HashSet<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 HashSet<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.Set(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.Set(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.Get(i)) { split.Set(i, true); int j = block[i]; splitblock[j].Add(s); if (!refine2.Get(j)) { refine2.Set(j, true); refine.Set(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.Get(ofs + j) && 0 < aj && aj <= ak) { pending2.Set(ofs + j, true); pending.AddLast(new IntPair(j, c)); } else { pending2.Set(ofs + k, true); pending.AddLast(new IntPair(k, c)); } } k++; } refine2.Set(j, false); foreach (State s in sb) { split.Set(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(); }