Advertisement
honey_the_codewitch

minimize javascript

Nov 1st, 2024
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. static _minimize(a, progress) {
  2.     let prog = 0;
  3.     if (progress === null) {
  4.         progress = new faProgress();
  5.     }
  6.     progress.report(prog);
  7.     a = a.toDfa(progress);
  8.     const tr = a.transitions;
  9.     if (tr.length == 1) {
  10.         const t = tr[0];
  11.         if (t.to === a && t.min == 0 && t.max == 0x10ffff) {
  12.             return a;
  13.         }
  14.     }
  15.     a.totalize();
  16.     ++prog;
  17.     progress.report(prog);
  18.     const cl = a.fillClosure();
  19.     const states = new Array();
  20.     let mtag = 0;
  21.     for (const q of cl) {
  22.         q._minimizationTag = mtag;
  23.         states.push(q);
  24.         ++mtag;
  25.     }
  26.     let pp = [];
  27.     for (let ic = cl.length, i = 0; i < ic; ++i) {
  28.         const ffa = cl[i];
  29.         pp.push(0);
  30.         for (const t of ffa.transitions) {
  31.             pp.push(t.min);
  32.             if (t.max < 0x10ffff) {
  33.                 pp.push(t.max + 1);
  34.             }
  35.         }
  36.     }
  37.     const sigma = new Array();
  38.     for (let i = 0; i < pp.length; ++i) {
  39.         sigma.push(pp[i]);
  40.     }
  41.     sigma.sort();
  42.     // initialize the data structures
  43.     const reverse = new Array();
  44.     for (const s of states) {
  45.         const arr = new Array(sigma.length);
  46.         arr.fill(null, 0, arr.length - 1);
  47.         reverse.push(arr);
  48.     }
  49.     ++prog;
  50.     progress.report(prog);
  51.     const reverseNonempty = Array(); //[states.length,sigma.length];
  52.     for (let i = 0; i < states.length; ++i) {
  53.         const arr = new Array(sigma.length);
  54.         arr.fill(false, 0, arr.length - 1);
  55.         reverseNonempty.push(arr);
  56.     }
  57.     const partition = new Array(states.length);
  58.     partition.fill(null, 0, partition.length - 1);
  59.     ++prog;
  60.     progress.report(prog);
  61.     const block = new Array(states.length);
  62.     const active = new Array(); // [states.length,sigma.length];
  63.     for (let i = 0; i < states.length; ++i) {
  64.         const arr = new Array(sigma.length);
  65.         arr.fill(null, 0, arr.length - 1);
  66.         active.push(arr);
  67.     }
  68.     const active2 = new Array(); //[states.length,sigma.length];
  69.     for (let i = 0; i < states.length; ++i) {
  70.         const arr = new Array(sigma.length);
  71.         arr.fill(null, 0, arr.length - 1);
  72.         active2.push(arr);
  73.     }
  74.     const pending = new Array();
  75.     const pending2 = Array(); //[sigma.length,states.length];
  76.     for (let i = 0; i < sigma.length; ++i) {
  77.         const arr = new Array(states.length);
  78.         arr.fill(false, 0, arr.length - 1);
  79.         pending2.push(arr);
  80.     }
  81.     let split = new Array();
  82.     const split2 = new Array(states.length);
  83.     split2.fill(false, 0, split2.length - 1);
  84.     let refine = new Array();
  85.     const refine2 = new Array(states.length);
  86.     split2.fill(false, 0, refine2.length - 1);
  87.     const splitBlock = new Array(states.length);
  88.     splitBlock.fill(null, 0, splitBlock.length - 1);
  89.     ++prog;
  90.     progress.report(prog);
  91.     for (let q = 0; q < states.length; ++q) {
  92.         splitBlock[q] = new Array();
  93.         partition[q] = new Array();
  94.         for (let x = 0; x < sigma.length; ++x) {
  95.             reverse[q][x] = new Array();
  96.             active[q][x] = new _FList();
  97.         }
  98.     }
  99.     // Find the initial partition and reverse edges
  100.     for (const qq of states) {
  101.         const j = qq.isAccepting() ? 0 : 1;
  102.         partition[j].push(qq);
  103.         block[qq._minimizationTag] = j;
  104.         for (let x = 0; x < sigma.length; ++x) {
  105.             const y = sigma[x];
  106.             const p = qq._step(y);
  107.             const pn = p._minimizationTag;
  108.             if (reverse[pn] !== null && reverse[pn][x] !== null) {
  109.                 reverse[pn][x].push(qq);
  110.             }
  111.             reverseNonempty[pn][x] = true;
  112.         }
  113.         ++prog;
  114.         progress.report(prog);
  115.     }
  116.     // initialize the active sets
  117.     for (let j = 0; j <= 1; ++j) {
  118.         for (let x = 0; x < sigma.length; ++x) {
  119.             const part = partition[j];
  120.             for (const qq of part) {
  121.                 if (reverseNonempty[qq._minimizationTag][x] === true) {
  122.                     active2[qq._minimizationTag][x] = active[j][x].add(qq);
  123.                 }
  124.             }
  125.         }
  126.         ++prog;
  127.         progress.report(prog);
  128.     }
  129.     // initialize pending
  130.     for (let x = 0; x < sigma.length; ++x) {
  131.         const a0 = active[0][x].count;
  132.         const a1 = active[1][x].count;
  133.         const j = a0 <= a1 ? 0 : 1;
  134.         pending.push(new _FKeyPair(j, x));
  135.         pending2[x][j] = true;
  136.     }
  137.     // process pending until fixed point
  138.     let k = 2;
  139.     while (pending.length > 0) {
  140.         const ip = pending.shift();
  141.         const p = ip.key;
  142.         const x = ip.value;
  143.         pending2[x][p] = false;
  144.         for (let m = active[p][x].first; m !== null; m = m.next) {
  145.             for (const s of reverse[m.state._minimizationTag][x]) {
  146.                 if (!split2[s._minimizationTag]) {
  147.                     split2[s._minimizationTag] = true;
  148.                     split.push(s);
  149.                     const j = block[s._minimizationTag];
  150.                     splitBlock[j].push(s);
  151.                     if (refine2[j] !== true) {
  152.                         refine2[j] = true;
  153.                         refine.push(j);
  154.                     }
  155.                 }
  156.             }
  157.         }
  158.         ++prog;
  159.         progress.report(prog);
  160.         // refine blocks
  161.         for (const j of refine) {
  162.             if (splitBlock[j].length < partition[j].length) {
  163.                 let b1 = partition[j];
  164.                 let b2 = partition[k];
  165.                 const e = splitBlock[j];
  166.                 for (const s of e) {
  167.                     partition[j] = b1 = b1.splice(b1.indexOf(s), 1);
  168.                     b2.push(s);
  169.                     block[s._minimizationTag] = k;
  170.                     for (let c = 0; c < sigma.length; ++c) {
  171.                         const sn = active2[s._minimizationTag][c];
  172.                         if (sn !== null && sn.stateList === active[j][c]) {
  173.                             sn.remove();
  174.                             active2[s._minimizationTag][c] = active[k][c].add(s);
  175.                         }
  176.                     }
  177.                 }
  178.                 // update pending
  179.                 for (let c = 0; c < sigma.length; ++c) {
  180.                     const aj = active[j][c].count;
  181.                     const ak = active[k][c].count;
  182.                     if (!pending2[c][j] && 0 < aj && aj <= ak) {
  183.                         pending2[c][j] = true;
  184.                         pending.push(new _FKeyPair(j, c));
  185.                     }
  186.                     else {
  187.                         pending2[c][k] = true;
  188.                         pending.push(new _FKeyPair(k, c));
  189.                     }
  190.                 }
  191.                 ++k;
  192.             }
  193.             const sbj = splitBlock[j];
  194.             for (const s of sbj) {
  195.                 split2[s._minimizationTag] = false;
  196.             }
  197.             refine2[j] = false;
  198.             splitBlock[j].length = 0;
  199.             ++prog;
  200.             progress.report(prog);
  201.         }
  202.         split.length = 0;
  203.         refine.length = 0;
  204.     }
  205.     ++prog;
  206.     progress.report(prog);
  207.     // make a new state for each equiv class, set initial state
  208.     const newstates = new Array();
  209.     for (let n = 0; n < k; ++n) {
  210.         const s = new fa();
  211.         s.isDeterministic = true;
  212.         newstates.push(s);
  213.         const pn = partition[n];
  214.         for (const q of pn) {
  215.             if (q === a) {
  216.                 a = s;
  217.             }
  218.             s.id = q.id;
  219.             s.acceptSymbol = q.acceptSymbol;
  220.             s._minimizationTag = q._minimizationTag;
  221.             q._minimizationTag = n;
  222.         }
  223.         ++prog;
  224.         progress.report(prog);
  225.     }
  226.     // build transitions and set acceptance
  227.     for (const s of newstates) {
  228.         const st = states[s._minimizationTag];
  229.         s.acceptSymbol = st.acceptSymbol;
  230.         for (const t of st.transitions) {
  231.             s.transitions.push(new faTransition(newstates[t.to._minimizationTag], t.min, t.max));
  232.         }
  233.         ++prog;
  234.         progress.report(prog);
  235.     }
  236.     // remove dead transitions
  237.     for (const ffa of a.fillClosure()) {
  238.         const itrns = new Array(...ffa.transitions);
  239.         ffa.transitions = new Array();
  240.         for (const trns of itrns) {
  241.             if (!trns.to.isTrap()) {
  242.                 ffa.transitions.push(trns);
  243.             }
  244.         }
  245.     }
  246.     return a;
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement