/// <summary> /// Returns true iff the DFA is not complete or not a DFA (misses transitions) /// </summary> /// <param name="dfa"></param> /// <param name="al"></param> /// <param name="solver"></param> /// <returns></returns> public static bool ContainsSyntacticMistake(Automaton <BDD> dfa, HashSet <char> al, CharSetSolver solver, HashSet <int> missingEdges) { bool mistake = false; var dfaNorm = DFAUtilities.normalizeDFA(dfa).First; foreach (var state in dfaNorm.States) { HashSet <char> alCopy = new HashSet <char>(al); foreach (var move in dfaNorm.GetMovesFrom(state)) { foreach (var c in solver.GenerateAllCharacters(move.Label, false)) { if (!alCopy.Contains(c)) { int hash = (int)(Math.Pow(2, move.SourceState) + Math.Pow(3, c - 97)) + dfaNorm.StateCount; mistake = true; } alCopy.Remove(c); } } if (alCopy.Count > 0) { mistake = true; } } return(mistake); }
/// <summary> /// /// </summary> /// <returns></returns> public NFAEditScript GetNFAOptimalEdit(Automaton <BDD> nfa2) { NFAEditScript editScript = new NFAEditScript(); //Start timer sw.Start(); //Normalize NFAs var normNfaPair = DFAUtilities.normalizeDFA(nfa2); var normNfa2 = normNfaPair.First; var stateNamesMapping = normNfaPair.Second; NFAEditScript bestScript = new NFAEditScript(); bestScript.script = null; // increase depth up to maxMoves for (int depth = 1; true; depth++) { var editList = new List <NFAEdit>(); if (GetNFAEditScriptTimeout( depth, -1, normNfa2, editScript.script, editScript.GetCost(), bestScript)) { // if hits timeout break and return null break; } if (bestScript.script != null) { bestScript.script.Reverse(); sw.Stop(); var mappedEditList = new List <NFAEdit>(); //fix states name because of normalization foreach (var edit in bestScript.script) { NFAEdit mappedEdit = null; if (edit is NFAEditState) { var castEdit = edit as NFAEditState; mappedEdit = new NFAEditState(stateNamesMapping[castEdit.state], castEdit.makeFinal); } if (edit is NFAEditMove) { var castEdit = edit as NFAEditMove; mappedEdit = new NFAEditMove( stateNamesMapping[castEdit.sourceState], stateNamesMapping[castEdit.newTargetState], castEdit.ch); } mappedEditList.Add(mappedEdit); } return(bestScript); } } return(null); }
// returns an array where a[n] is the number of paths of length n private static double[] GetPathsUpToN(Automaton <BDD> dfa, HashSet <char> al, CharSetSolver solver, int n) { var normDfa1 = DFAUtilities.normalizeDFA(dfa).First; int length = 0; double[] totPaths = new double[n + 1]; var finalStates = normDfa1.GetFinalStates(); double[] pathNum = new double[normDfa1.StateCount]; pathNum[0] = 1; totPaths[0] = finalStates.Contains(0) ? 1 : 0; for (int i = 1; i < pathNum.Length; i++) { pathNum[i] = 0; } while (length < n) { double[] oldPathNum = pathNum.ToArray(); for (int i = 0; i < pathNum.Length; i++) { pathNum[i] = 0; } length++; foreach (var state in normDfa1.States) { if (oldPathNum[state] > 0) { foreach (var move in normDfa1.GetMovesFrom(state)) { int size = 0; //Check if epsilon transition if (move.Label == null) { size = 1; } else { foreach (var v in solver.GenerateAllCharacters(move.Label, false)) { size++; } } pathNum[move.TargetState] += oldPathNum[state] * size; } } } //totPaths[length] = totPaths[length - 1]; foreach (var state in finalStates) { totPaths[length] += pathNum[state]; } } return(totPaths); }
/// <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); }