/// <summary> /// Computes the ratio of the symmetric difference to the size of dfa1 enumerating paths up to length n (uses the complement if density is high) /// </summary> /// <returns>size of ((dfa2-dfa1)+(dfa1-dfa2))/dfa1</returns> public static double GetDFADifferenceRatio(Automaton <BDD> dfa1, Automaton <BDD> dfa2, HashSet <char> al, CharSetSolver solver) { var solutionDensity = DFADensity.GetDFADensity(dfa1, al, solver); //Symmetric difference var dfadiff1 = dfa1.Minus(dfa2, solver); var dfadiff2 = dfa2.Minus(dfa1, solver); var dfatrue = Automaton <BDD> .Create(0, new int[] { 0 }, new Move <BDD>[] { new Move <BDD>(0, 0, solver.True) }); var dfadiff = dfatrue.Minus(dfatrue.Minus(dfadiff1, solver).Intersect(dfatrue.Minus(dfadiff2, solver), solver), solver).Determinize(solver).Minimize(solver); //Use smallest of |dfa1| and complement of |dfa1| for cardinality base return(GetDFARatio(dfa1.Determinize(solver).Minimize(solver), dfadiff, al, solver, solutionDensity > 0.5)); }
public static bool canCollapseStates(Automaton <BDD> nfa, int state1, int state2, CharSetSolver solver, Pair <IEnumerable <string>, IEnumerable <string> > tests, HashSet <char> al) { var density = DFADensity.GetDFADensity(nfa, al, solver); // collapses state2 to state1 List <Move <BDD> > newMoves = new List <Move <BDD> >(); foreach (var move in nfa.GetMoves()) { var newSource = move.SourceState; var newTarget = move.TargetState; if (newSource == state2) { newSource = state1; } if (newTarget == state2) { newTarget = state1; } newMoves.Add(new Move <BDD>(newSource, newTarget, move.Label)); } // replace state2 with state1 if initial state // no need to remove state2 from final state list, as it is unreachable int newInitialState = nfa.InitialState; if (nfa.InitialState == state2) { newInitialState = state1; } //makes new Nfa and returns collapse state edit if are equiv var newNfa = Automaton <BDD> .Create(newInitialState, nfa.GetFinalStates(), newMoves); if (DFAUtilities.ApproximateMNEquivalent(tests, density, newNfa, al, solver)) { return(nfa.IsEquivalentWith(newNfa, solver)); } return(false); }
/// <summary> /// create new instance of NFAEdit distance and assigns a number to each character /// </summary> /// <param name="nfa1"></param> /// <param name="nfa2"></param> /// <param name="al"></param> /// <param name="solver"></param> /// <param name="timeout"></param> public NFAEditDistanceProvider(Automaton <BDD> nfa1, HashSet <char> al, CharSetSolver solver, long timeout) { this.nfa1 = nfa1; this.al = al; this.solver = solver; this.timeout = timeout; this.alphabetMap = new Dictionary <char, int>(); int index = 0; foreach (var c in al) { this.alphabetMap[c] = index; index++; } this.sw = new Stopwatch(); this.tests = NFAUtilities.MyHillTestGeneration(al, nfa1.Determinize(solver), solver); var dfa1 = nfa1.RemoveEpsilons(solver.MkOr).Determinize(solver).Minimize(solver); this.nfa1density = DFADensity.GetDFADensity(dfa1, al, solver); }
/// <summary> /// Finds min edit distance script between DFAs if operation /// takes less than timeout ms /// </summary> /// <param name="dfa1"></param> /// <param name="dfa2"></param> /// <param name="al"></param> /// <param name="solver"></param> /// <param name="timeout"></param> /// <param name="sb"></param> /// <returns></returns> public static DFAEditScript GetDFAOptimalEdit( // copy Automaton <BDD> dfa1, Automaton <BDD> dfa2, HashSet <char> al, CharSetSolver solver, long timeout, StringBuilder sb) { //Contract.Assert(dfa1.IsDeterministic); //Contract.Assert(dfa2.IsDeterministic); DFAEditScript editScript = new DFAEditScript(); #region Add states to dfa2 to make it at least as dfa1 BDD fullAlphabetCondition = BDDOf(al, solver); //Normalize the DFA giving only names from 0 to |States|-1 var normDfaPair = DFAUtilities.normalizeDFA(dfa2); var dfa2augmented = normDfaPair.First; //solver.SaveAsDot(dfa2augmented, "aaaa"); var stateNamesMapping = normDfaPair.Second; //Add states to make dfa2 have the |dfa2.States|>= |dfa1.States| var newMoves = new List <Move <BDD> >(dfa2augmented.GetMoves()); for (int i = 1; i <= dfa1.StateCount - dfa2augmented.StateCount; i++) { int newStateName = dfa2augmented.MaxState + i; //Pick the next available name to be added stateNamesMapping[newStateName] = dfa2.MaxState + i; //save the operation in the script editScript.script.Insert(0, new DFAAddState(dfa2.MaxState + i)); newMoves.Add(new Move <BDD>(newStateName, newStateName, fullAlphabetCondition)); newStateName++; } //Create the new DFA with the added states dfa2augmented = Automaton <BDD> .Create(dfa2augmented.InitialState, dfa2augmented.GetFinalStates().ToList(), newMoves); #endregion int maxScore = (dfa1.StateCount + dfa2augmented.StateCount) * (al.Count + 1); int oldScirptSize = editScript.script.Count; //Start with the internal script equals to null, at the end bestScript.Script will contain the best script DFAEditScript bestScript = new DFAEditScript(); bestScript.script = null; Stopwatch sw = new Stopwatch(); sw.Start(); // Iteratively check if there exists an edit of a given depth for (int depth = 1; true; depth++) { var editList = new List <DFAEdit>(); if (GetDFAEditScriptTimeout( dfa1, dfa2augmented, al, solver, new List <long>(), editScript.script, depth, timeout, sw, DFAUtilities.MyHillTestGeneration(al, dfa1, solver), DFADensity.GetDFADensity(dfa1, al, solver), editScript.GetCost(), bestScript, stateNamesMapping)) { // if hits timeout break and return null break; } if (bestScript.script != null) { bestScript.script.Reverse(); sw.Stop(); return(bestScript); } } sw.Stop(); return(null); }