/// <summary> /// Refine the partitions by splitting incompatible states /// </summary> internal void RefinePartitions() { int generation = 0; while (worklist.Count > 0) { List <DFSA.DState> predSet = null; // // We are going to split all blocks with respect to a // particular (Block, Symbol) pair. // Fetch the pair components. // // In order to avoid having to reset the predCount ints // all the time we keep a generation count to indicate to // which pass through the loop the counts apply. // PartitionBlock blk = worklist.Peek(); int sym = blk.Sym - 1; if (sym < 0) { worklist.Pop(); // Remove block from the worklist. continue; // Go around again to get new block. } generation++; predSet = new List <DFSA.DState>(); // // Form a set of all those states that have a // next-state in "blk" on symbol "sym". // Note that despite the nested loops the // complexity is only N == number of states. // foreach (DFSA.DState dSt in blk.members) { if (dSt.HasPredecessors()) { List <DFSA.DState> prds = dSt.GetPredecessors(sym); if (prds != null && prds.Count > 0) { foreach (DFSA.DState pSt in prds) { // The same predecessor state might appear on the // list for more than one state of the blk.members. // States should only appear once in the predSet "set" if (pSt.listOrd != generation) // This predecessor is not in the set already { PartitionBlock predBlk = (pSt.block as PartitionBlock); pSt.listOrd = generation; if (predBlk.Gen != generation) { predBlk.Gen = generation; predBlk.PredCount = 0; } predSet.Add(pSt); // Add the predecessor to the set predBlk.PredCount++; } } } } } blk.Sym--; // "Remove" (blk,sym) from the pair list. // // Now, if the predecessor set is not empty, // we split all blocks with respect to (blk,sym) // if (predSet.Count != 0) { List <PartitionBlock> splits = new List <PartitionBlock>(); foreach (DFSA.DState lSt in predSet) { PartitionBlock tBlk = null; PartitionBlock lBlk = (lSt.block as PartitionBlock); if (lBlk.PredCount != lBlk.MemberCount) // Need to split this block { tBlk = lBlk.twinBlk; if (tBlk == null) { tBlk = MkNewBlock(); splits.Add(tBlk); lBlk.twinBlk = tBlk; tBlk.twinBlk = lBlk; } lBlk.MoveMember(lSt, tBlk); lSt.block = tBlk; } } foreach (PartitionBlock tBlk in splits) { PartitionBlock lBlk = tBlk.twinBlk; PartitionBlock push = null; if (lBlk.Sym == 0) // lBlk is not currently on the list so push smaller block { if (lBlk.MemberCount < tBlk.MemberCount) { push = lBlk; } else { push = tBlk; } } else // lBlk is on the list with Sym > 0 { push = tBlk; if (lBlk.MemberCount < tBlk.MemberCount) { // tBlk has the larger cardinality, so give it the smaller Sym value tBlk.Sym = lBlk.Sym; lBlk.Sym = dfsa.MaxSym; } } worklist.Push(push); lBlk.twinBlk = null; tBlk.twinBlk = null; } } } // end of while loop... }