Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- static _minimize(a, progress) {
- let prog = 0;
- if (progress === null) {
- progress = new faProgress();
- }
- progress.report(prog);
- a = a.toDfa(progress);
- const tr = a.transitions;
- if (tr.length == 1) {
- const t = tr[0];
- if (t.to === a && t.min == 0 && t.max == 0x10ffff) {
- return a;
- }
- }
- a.totalize();
- ++prog;
- progress.report(prog);
- const cl = a.fillClosure();
- const states = new Array();
- let mtag = 0;
- for (const q of cl) {
- q._minimizationTag = mtag;
- states.push(q);
- ++mtag;
- }
- let pp = [];
- for (let ic = cl.length, i = 0; i < ic; ++i) {
- const ffa = cl[i];
- pp.push(0);
- for (const t of ffa.transitions) {
- pp.push(t.min);
- if (t.max < 0x10ffff) {
- pp.push(t.max + 1);
- }
- }
- }
- const sigma = new Array();
- for (let i = 0; i < pp.length; ++i) {
- sigma.push(pp[i]);
- }
- sigma.sort();
- // initialize the data structures
- const reverse = new Array();
- for (const s of states) {
- const arr = new Array(sigma.length);
- arr.fill(null, 0, arr.length - 1);
- reverse.push(arr);
- }
- ++prog;
- progress.report(prog);
- const reverseNonempty = Array(); //[states.length,sigma.length];
- for (let i = 0; i < states.length; ++i) {
- const arr = new Array(sigma.length);
- arr.fill(false, 0, arr.length - 1);
- reverseNonempty.push(arr);
- }
- const partition = new Array(states.length);
- partition.fill(null, 0, partition.length - 1);
- ++prog;
- progress.report(prog);
- const block = new Array(states.length);
- const active = new Array(); // [states.length,sigma.length];
- for (let i = 0; i < states.length; ++i) {
- const arr = new Array(sigma.length);
- arr.fill(null, 0, arr.length - 1);
- active.push(arr);
- }
- const active2 = new Array(); //[states.length,sigma.length];
- for (let i = 0; i < states.length; ++i) {
- const arr = new Array(sigma.length);
- arr.fill(null, 0, arr.length - 1);
- active2.push(arr);
- }
- const pending = new Array();
- const pending2 = Array(); //[sigma.length,states.length];
- for (let i = 0; i < sigma.length; ++i) {
- const arr = new Array(states.length);
- arr.fill(false, 0, arr.length - 1);
- pending2.push(arr);
- }
- let split = new Array();
- const split2 = new Array(states.length);
- split2.fill(false, 0, split2.length - 1);
- let refine = new Array();
- const refine2 = new Array(states.length);
- split2.fill(false, 0, refine2.length - 1);
- const splitBlock = new Array(states.length);
- splitBlock.fill(null, 0, splitBlock.length - 1);
- ++prog;
- progress.report(prog);
- for (let q = 0; q < states.length; ++q) {
- splitBlock[q] = new Array();
- partition[q] = new Array();
- for (let x = 0; x < sigma.length; ++x) {
- reverse[q][x] = new Array();
- active[q][x] = new _FList();
- }
- }
- // Find the initial partition and reverse edges
- for (const qq of states) {
- const j = qq.isAccepting() ? 0 : 1;
- partition[j].push(qq);
- block[qq._minimizationTag] = j;
- for (let x = 0; x < sigma.length; ++x) {
- const y = sigma[x];
- const p = qq._step(y);
- const pn = p._minimizationTag;
- if (reverse[pn] !== null && reverse[pn][x] !== null) {
- reverse[pn][x].push(qq);
- }
- reverseNonempty[pn][x] = true;
- }
- ++prog;
- progress.report(prog);
- }
- // initialize the active sets
- for (let j = 0; j <= 1; ++j) {
- for (let x = 0; x < sigma.length; ++x) {
- const part = partition[j];
- for (const qq of part) {
- if (reverseNonempty[qq._minimizationTag][x] === true) {
- active2[qq._minimizationTag][x] = active[j][x].add(qq);
- }
- }
- }
- ++prog;
- progress.report(prog);
- }
- // initialize pending
- for (let x = 0; x < sigma.length; ++x) {
- const a0 = active[0][x].count;
- const a1 = active[1][x].count;
- const j = a0 <= a1 ? 0 : 1;
- pending.push(new _FKeyPair(j, x));
- pending2[x][j] = true;
- }
- // process pending until fixed point
- let k = 2;
- while (pending.length > 0) {
- const ip = pending.shift();
- const p = ip.key;
- const x = ip.value;
- pending2[x][p] = false;
- for (let m = active[p][x].first; m !== null; m = m.next) {
- for (const s of reverse[m.state._minimizationTag][x]) {
- if (!split2[s._minimizationTag]) {
- split2[s._minimizationTag] = true;
- split.push(s);
- const j = block[s._minimizationTag];
- splitBlock[j].push(s);
- if (refine2[j] !== true) {
- refine2[j] = true;
- refine.push(j);
- }
- }
- }
- }
- ++prog;
- progress.report(prog);
- // refine blocks
- for (const j of refine) {
- if (splitBlock[j].length < partition[j].length) {
- let b1 = partition[j];
- let b2 = partition[k];
- const e = splitBlock[j];
- for (const s of e) {
- partition[j] = b1 = b1.splice(b1.indexOf(s), 1);
- b2.push(s);
- block[s._minimizationTag] = k;
- for (let c = 0; c < sigma.length; ++c) {
- const 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 (let c = 0; c < sigma.length; ++c) {
- const aj = active[j][c].count;
- const ak = active[k][c].count;
- if (!pending2[c][j] && 0 < aj && aj <= ak) {
- pending2[c][j] = true;
- pending.push(new _FKeyPair(j, c));
- }
- else {
- pending2[c][k] = true;
- pending.push(new _FKeyPair(k, c));
- }
- }
- ++k;
- }
- const sbj = splitBlock[j];
- for (const s of sbj) {
- split2[s._minimizationTag] = false;
- }
- refine2[j] = false;
- splitBlock[j].length = 0;
- ++prog;
- progress.report(prog);
- }
- split.length = 0;
- refine.length = 0;
- }
- ++prog;
- progress.report(prog);
- // make a new state for each equiv class, set initial state
- const newstates = new Array();
- for (let n = 0; n < k; ++n) {
- const s = new fa();
- s.isDeterministic = true;
- newstates.push(s);
- const pn = partition[n];
- for (const q of pn) {
- if (q === a) {
- a = s;
- }
- s.id = q.id;
- s.acceptSymbol = q.acceptSymbol;
- s._minimizationTag = q._minimizationTag;
- q._minimizationTag = n;
- }
- ++prog;
- progress.report(prog);
- }
- // build transitions and set acceptance
- for (const s of newstates) {
- const st = states[s._minimizationTag];
- s.acceptSymbol = st.acceptSymbol;
- for (const t of st.transitions) {
- s.transitions.push(new faTransition(newstates[t.to._minimizationTag], t.min, t.max));
- }
- ++prog;
- progress.report(prog);
- }
- // remove dead transitions
- for (const ffa of a.fillClosure()) {
- const itrns = new Array(...ffa.transitions);
- ffa.transitions = new Array();
- for (const trns of itrns) {
- if (!trns.to.isTrap()) {
- ffa.transitions.push(trns);
- }
- }
- }
- return a;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement