Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- static void _Init<T>(IList<T> list, int count)
- {
- for (int i = 0; i < count; ++i)
- {
- list.Add(default(T));
- }
- }
- static FA _Minimize(FA a, IProgress<int> progress)
- {
- int prog = 0;
- progress?.Report(prog);
- a = a.ToDfa(progress);
- var tr = a._transitions;
- if (1 == tr.Count)
- {
- FATransition t = tr[0];
- if (t.To == a && t.Min == 0 && t.Max == 0x10ffff)
- {
- return a;
- }
- }
- a.Totalize();
- ++prog;
- progress?.Report(prog);
- // Make arrays for numbered states and effective alphabet.
- var cl = a.FillClosure();
- var states = new FA[cl.Count];
- int number = 0;
- foreach (var q in cl)
- {
- states[number] = q;
- q._MinimizationTag = number;
- ++number;
- }
- var pp = new List<int>();
- for (int ic = cl.Count, i = 0; i < ic; ++i)
- {
- var ffa = cl[i];
- pp.Add(0);
- foreach (var t in ffa._transitions)
- {
- pp.Add(t.Min);
- if (t.Max < 0x10ffff)
- {
- pp.Add((t.Max + 1));
- }
- }
- }
- var sigma = new int[pp.Count];
- pp.CopyTo(sigma, 0);
- Array.Sort(sigma);
- // Initialize data structures.
- var reverse = new List<List<Queue<FA>>>();
- foreach (var s in states)
- {
- var v = new List<Queue<FA>>();
- _Init(v, sigma.Length);
- reverse.Add(v);
- }
- prog = 2;
- if (progress != null) { progress.Report(prog); }
- var reverseNonempty = new bool[states.Length, sigma.Length];
- var partition = new List<LinkedList<FA>>();
- _Init(partition, states.Length);
- ++prog;
- if (progress != null) { progress.Report(prog); }
- var block = new int[states.Length];
- var active = new _FList[states.Length, sigma.Length];
- var active2 = new _FListNode[states.Length, sigma.Length];
- var pending = new Queue<KeyValuePair<int, int>>();
- var pending2 = new bool[sigma.Length, states.Length];
- var split = new List<FA>();
- var split2 = new bool[states.Length];
- var refine = new List<int>();
- var refine2 = new bool[states.Length];
- var splitblock = new List<List<FA>>();
- _Init(splitblock, states.Length);
- ++prog;
- progress?.Report(prog);
- for (int q = 0; q < states.Length; q++)
- {
- splitblock[q] = new List<FA>();
- partition[q] = new LinkedList<FA>();
- for (int x = 0; x < sigma.Length; x++)
- {
- reverse[q][x] = new Queue<FA>();
- active[q, x] = new _FList();
- }
- }
- // Find initial partition and reverse edges.
- foreach (var qq in states)
- {
- int j = qq.IsAccepting ? 0 : 1;
- partition[j]?.AddLast(qq);
- block[qq._MinimizationTag] = j;
- for (int x = 0; x < sigma.Length; x++)
- {
- var y = sigma[x];
- var p = qq._Step(y);
- System.Diagnostics.Debug.Assert(p != null);
- var pn = p._MinimizationTag;
- reverse[pn]?[x]?.Enqueue(qq);
- reverseNonempty[pn, x] = true;
- }
- ++prog;
- progress?.Report(prog);
- }
- // Initialize active sets.
- for (int j = 0; j <= 1; j++)
- {
- for (int x = 0; x < sigma.Length; x++)
- {
- var part = partition[j];
- System.Diagnostics.Debug.Assert(part != null);
- foreach (var qq in part)
- {
- System.Diagnostics.Debug.Assert(qq != null);
- if (reverseNonempty[qq._MinimizationTag, x])
- {
- active2[qq._MinimizationTag, x] = active[j, x].Add(qq);
- }
- }
- }
- ++prog;
- progress?.Report(prog);
- }
- // Initialize pending.
- for (int x = 0; x < sigma.Length; x++)
- {
- int a0 = active[0, x].Count;
- int a1 = active[1, x].Count;
- int j = a0 <= a1 ? 0 : 1;
- pending.Enqueue(new KeyValuePair<int, int>(j, x));
- pending2[x, j] = true;
- }
- // Process pending until fixed point.
- int k = 2;
- while (pending.Count > 0)
- {
- KeyValuePair<int, int> ip = pending.Dequeue();
- int p = ip.Key;
- int x = ip.Value;
- pending2[x, p] = false;
- // Find states that need to be split off their blocks.
- for (var m = active[p, x].First; m != null; m = m.Next)
- {
- System.Diagnostics.Debug.Assert(m.State != null);
- foreach (var s in reverse[m.State._MinimizationTag][x])
- {
- if (!split2[s._MinimizationTag])
- {
- split2[s._MinimizationTag] = true;
- split.Add(s);
- int j = block[s._MinimizationTag];
- splitblock[j]?.Add(s);
- if (!refine2[j])
- {
- refine2[j] = true;
- refine.Add(j);
- }
- }
- }
- }
- ++prog;
- if (progress != null) { progress.Report(prog); }
- // Refine blocks.
- foreach (int j in refine)
- {
- if (splitblock[j]?.Count < partition[j]?.Count)
- {
- LinkedList<FA> b1 = partition[j];
- System.Diagnostics.Debug.Assert(b1 != null);
- LinkedList<FA> b2 = partition[k];
- System.Diagnostics.Debug.Assert(b2 != null);
- var e = splitblock[j];
- System.Diagnostics.Debug.Assert(e != null);
- foreach (var s in e)
- {
- b1.Remove(s);
- b2.AddLast(s);
- block[s._MinimizationTag] = k;
- for (int c = 0; c < sigma.Length; c++)
- {
- _FListNode sn = active2[s._MinimizationTag, c];
- if (sn != null && sn.StateList == active[j, c])
- {
- sn.Remove();
- active2[s._MinimizationTag, c] = active[k, c].Add(s);
- }
- }
- }
- // Update pending.
- for (int c = 0; c < sigma.Length; c++)
- {
- int aj = active[j, c].Count;
- int ak = active[k, c].Count;
- if (!pending2[c, j] && 0 < aj && aj <= ak)
- {
- pending2[c, j] = true;
- pending.Enqueue(new KeyValuePair<int, int>(j, c));
- }
- else
- {
- pending2[c, k] = true;
- pending.Enqueue(new KeyValuePair<int, int>(k, c));
- }
- }
- k++;
- }
- var sbj = splitblock[j];
- System.Diagnostics.Debug.Assert(sbj != null);
- foreach (var s in sbj)
- {
- split2[s._MinimizationTag] = false;
- }
- refine2[j] = false;
- //splitblock[j].Clear();
- sbj.Clear();
- ++prog;
- if (progress != null) { progress.Report(prog); }
- }
- split.Clear();
- refine.Clear();
- }
- ++prog;
- if (progress != null) { progress.Report(prog); }
- // Make a new state for each equivalence class, set initial state.
- var newstates = new FA[k];
- for (int n = 0; n < newstates.Length; n++)
- {
- var s = new FA();
- s.IsDeterministic = true;
- newstates[n] = s;
- var pn = partition[n];
- System.Diagnostics.Debug.Assert(pn != null);
- foreach (var q in pn)
- {
- if (q == a)
- {
- a = s;
- }
- s.Id = q.Id;
- s.AcceptSymbol = q.AcceptSymbol;
- s._MinimizationTag = q._MinimizationTag; // Select representative.
- q._MinimizationTag = n;
- }
- ++prog;
- progress?.Report(prog);
- }
- // Build transitions and set acceptance.
- foreach (var s in newstates)
- {
- var st = states[s._MinimizationTag];
- s.AcceptSymbol = st.AcceptSymbol;
- foreach (var t in st._transitions)
- {
- s._transitions.Add(new FATransition(newstates[t.To._MinimizationTag], t.Min, t.Max));
- }
- ++prog;
- progress?.Report(prog);
- }
- // remove dead transitions
- foreach (var ffa in a.FillClosure())
- {
- var itrns = new List<FATransition>(ffa._transitions);
- foreach (var trns in itrns)
- {
- if (null == trns.To.FindFirst(AcceptingFilter))
- {
- ffa._transitions.Remove(trns);
- }
- }
- }
- return a;
- }
- FA _Step(int input)
- {
- for (int ic = _transitions.Count, i = 0; i < ic; ++i)
- {
- var t = _transitions[i];
- if (t.Min <= input && input <= t.Max)
- return t.To;
- }
- return null;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement