Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- private static _minimize(a: fa, progress: faProgress) : fa {
- // TODO: This doesn't work
- let prog: number = 0;
- if(progress===null) {
- progress = new faProgress();
- }
- progress.report(prog);
- a=a.toDfa(progress);
- const tr: faTransition[] = a.transitions;
- if(tr.length==1) {
- const t: faTransition = tr[0];
- if(t.to=== a && t.min==0&&t.max==0x10ffff) {
- return a;
- }
- }
- a.totalize();
- ++prog;progress.report(prog);
- const cl: fa[] = a.fillClosure();
- const states: fa[] = new Array<fa>();
- let mtag: number = 0;
- for(const q of cl) {
- q._minimizationTag = mtag;
- states.push(q);
- ++mtag;
- }
- let pp: number[] = [];
- for(let ic: number = cl.length,i=0;i<ic;++i) {
- const ffa: fa=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: number[] = new Array<number>();
- for(let i = 0;i<pp.length;++i) {
- sigma.push(pp[i]);
- }
- sigma.sort();
- // initialize the data structures
- const reverse : fa[][][] = new Array<Array<Array<fa>>>();
- for(const s of states) {
- const arr: fa[][] = new Array<Array<fa>>(sigma.length);
- arr.fill(null,0,arr.length-1);
- reverse.push(arr);
- }
- ++prog;progress.report(prog);
- const reverseNonempty: boolean[][] = Array<Array<boolean>>();//[states.length,sigma.length];
- for(let i: number = 0;i<states.length;++i) {
- const arr: boolean[] = new Array<boolean>(sigma.length);
- arr.fill(false,0,arr.length-1);
- reverseNonempty.push(arr);
- }
- const partition: fa[][] = new Array<Array<fa>>(states.length);
- partition.fill(null,0,partition.length-1);
- ++prog;progress.report(prog);
- const block: number[] = new Array<number>(states.length);
- const active: _FList[][] = new Array<Array<_FList>>(); // [states.length,sigma.length];
- for(let i: number = 0;i<states.length;++i) {
- const arr: _FList[] = new Array<_FList>(sigma.length);
- arr.fill(null,0,arr.length-1);
- active.push(arr);
- }
- const active2: _FListNode[][] = new Array<Array<_FListNode>>()//[states.length,sigma.length];
- for(let i: number = 0;i<states.length;++i) {
- const arr: _FListNode[] = new Array<_FListNode>(sigma.length);
- arr.fill(null,0,arr.length-1);
- active2.push(arr);
- }
- const pending: _FKeyPair[] = new Array<_FKeyPair>();
- const pending2: boolean[][] = Array<Array<boolean>>();//[sigma.length,states.length];
- for(let i: number = 0;i<sigma.length;++i) {
- const arr : boolean[] = new Array<boolean>(states.length);
- arr.fill(false,0,arr.length-1);
- pending2.push(arr);
- }
- let split: fa[] = new Array<fa>();
- const split2: boolean[] = new Array<boolean>(states.length);
- split2.fill(false,0,split2.length-1);
- let refine: number[] = new Array<number>();
- const refine2: boolean[] = new Array<boolean>(states.length);
- split2.fill(false,0,refine2.length-1);
- const splitBlock: fa[][] = new Array<Array<fa>>(states.length);
- splitBlock.fill(null,0,splitBlock.length-1);
- ++prog;progress.report(prog);
- for(let q: number = 0;q<states.length;++q) {
- splitBlock[q]= new Array<fa>();
- partition[q]=new Array<fa>();
- for(let x: number = 0;x<sigma.length;++x) {
- reverse[q][x]=new Array<fa>();
- active[q][x]=new _FList();
- }
- }
- // Find the initial partition and reverse edges
- for(const qq of states) {
- const j: number = qq.isAccepting()? 0: 1;
- partition[j].push(qq);
- block[qq._minimizationTag]=j;
- for(let x: number = 0;x<sigma.length;++x) {
- const y: number = sigma[x];
- const p: fa = qq._step(y);
- const pn: number = 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: number = 0;j<=1;++j) {
- for(let x: number = 0;x<sigma.length;++x) {
- const part: fa[] = 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: number = 0; x<sigma.length;++x) {
- const a0: number = active[0][x].count;
- const a1: number = active[1][x].count;
- const j: number = a0<=a1?0:1;
- pending.push(new _FKeyPair(j,x));
- pending2[x][j]=true;
- }
- // process pending until fixed point
- let k: number = 2;
- while(pending.length>0) {
- const ip: _FKeyPair = pending.shift();
- const p: number = ip.key;
- const x: number = ip.value;
- pending2[x][p]=false;
- for(let m: _FListNode = 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: number = 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: Array<fa> = partition[j];
- let b2: Array<fa> = partition[k];
- const e: Array<fa> = 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: number = 0;c<sigma.length;++c) {
- const sn: _FListNode = 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:number = 0;c<sigma.length;++c) {
- const aj: number = active[j][c].count;
- const ak: number = 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: Array<fa> = 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 : fa[] = new Array<fa>();
- for(let n: number = 0; n<k;++n) {
- const s: fa = new fa();
- s.isDeterministic = true;
- newstates.push(s);
- const pn: Array<fa> = 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: fa = 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: faTransition[] = new Array<faTransition>(...ffa.transitions)
- ffa.transitions = new Array<faTransition>();
- 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