// looks for an edit at depth "depth" // returns false and null in bestScript if no edit is found at depth "depth" // returns false and not null in bestScript if found // returns true if timeout internal bool GetNFAEditScriptTimeout( int depth, long lastEditHash, Automaton <BDD> currentNfa2, List <NFAEdit> editList, int scriptCost, NFAEditScript bestScript) { // if timeout return true if (sw.ElapsedMilliseconds > timeout) { return(true); } //Stop if no more moves left if (depth == 0) { if (DFAUtilities.ApproximateMNEquivalent(tests, nfa1density, currentNfa2, al, solver) && currentNfa2.IsEquivalentWith(nfa1, solver)) { //check if totalCost < finalScript cost and replace if needed if (bestScript.script == null || scriptCost < bestScript.GetCost()) { bestScript.script = ObjectCopier.Clone <List <NFAEdit> >(editList); } } return(false); } NFAEdit edit = null; long thisEditHash = 0; #region Flip one state from fin to non fin foreach (var state in currentNfa2.States) { thisEditHash = state; if (CanAdd(thisEditHash, lastEditHash)) { //flip its final non final status var newFinalStates = new HashSet <int>(currentNfa2.GetFinalStates()); Automaton <BDD> nfa2new = null; if (currentNfa2.GetFinalStates().Contains(state)) { edit = new NFAEditState(state, false); editList.Insert(0, edit); newFinalStates.Remove(state); nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, newFinalStates, currentNfa2.GetMoves()); } else { edit = new NFAEditState(state, true); editList.Insert(0, edit); newFinalStates.Add(state); nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, newFinalStates, currentNfa2.GetMoves()); } if (GetNFAEditScriptTimeout(depth - 1, thisEditHash, nfa2new, editList, scriptCost + edit.GetCost(), bestScript)) { return(true); } editList.RemoveAt(0); } } #endregion #region Change transition from source state currentNfa2 = NFAUtilities.normalizeMoves(currentNfa2, solver); foreach (var sourceState in currentNfa2.States) { HashSet <int> unreachedStates = new HashSet <int>(currentNfa2.States); foreach (var moveFromSource in currentNfa2.GetMovesFrom(sourceState)) { // take all chars in alphabet foreach (var c in al) { long moveHash = currentNfa2.StateCount + IntegerUtil.TripleToInt(sourceState, moveFromSource.TargetState, alphabetMap[c]); thisEditHash = currentNfa2.StateCount + moveHash; if (CanAdd(thisEditHash, lastEditHash)) { BDD cCond = solver.False; BDD newCond = solver.False; //skip epsilon moves if (moveFromSource.Label != null) { // if c in move, remove it and recursion if (solver.Contains(moveFromSource.Label, c)) { cCond = solver.MkNot(solver.MkCharConstraint(false, c)); newCond = solver.MkAnd(moveFromSource.Label, cCond); } else // if c not in move, add it and recursion { cCond = solver.MkCharConstraint(false, c); newCond = solver.MkOr(moveFromSource.Label, cCond); } var newMoves = new List <Move <BDD> >(currentNfa2.GetMoves()); newMoves.Remove(moveFromSource); newMoves.Add(new Move <BDD>(sourceState, moveFromSource.TargetState, newCond)); var nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, currentNfa2.GetFinalStates(), newMoves); edit = new NFAEditMove(sourceState, moveFromSource.TargetState, c); editList.Insert(0, edit); if (GetNFAEditScriptTimeout(depth - 1, thisEditHash, nfa2new, editList, scriptCost + edit.GetCost(), bestScript)) { return(true); } editList.RemoveAt(0); } } } unreachedStates.Remove(moveFromSource.TargetState); } foreach (var targetState in unreachedStates) { //try adding a symbol not in transition foreach (var c in al) { long moveHash = IntegerUtil.TripleToInt(sourceState, targetState, alphabetMap[c]); thisEditHash = currentNfa2.StateCount + moveHash; var moveCond = solver.MkCharConstraint(false, c); var newMoves = new List <Move <BDD> >(currentNfa2.GetMoves()); newMoves.Add(new Move <BDD>(sourceState, targetState, moveCond)); var nfa2new = Automaton <BDD> .Create(currentNfa2.InitialState, currentNfa2.GetFinalStates(), newMoves); edit = new NFAEditMove(sourceState, targetState, c); editList.Insert(0, edit); //TODO put correct hash if (GetNFAEditScriptTimeout(depth - 1, thisEditHash, nfa2new, editList, scriptCost + edit.GetCost(), bestScript)) { return(true); } editList.RemoveAt(0); } } } #endregion return(false); }
// looks for an edit at depth "depth" // returns false and null in bestScript if no edit is found at depth "depth" // returns false and not null in bestScript if found // returns true if timeout internal static bool GetDFAEditScriptTimeout( Automaton <BDD> dfa1, Automaton <BDD> dfa2, HashSet <char> al, CharSetSolver solver, List <long> editScriptHash, List <DFAEdit> editList, int depth, long timeout, Stopwatch sw, Pair <IEnumerable <string>, IEnumerable <string> > tests, double dfa1density, int totalCost, DFAEditScript bestScript, Dictionary <int, int> stateNamesMapping) { // check timer if (sw.ElapsedMilliseconds > timeout) { return(true); } //Compute worst case distance, call finalScript with this value? int dist = (dfa1.StateCount + dfa2.StateCount) * (al.Count + 1); //Stop if no more moves left if (depth == 0) { if (DFAUtilities.ApproximateMNEquivalent(tests, dfa1density, dfa2, al, solver) && dfa2.IsEquivalentWith(dfa1, solver)) { //check if totalCost < finalScript cost and replace if needed if (bestScript.script == null || totalCost < bestScript.GetCost()) { bestScript.script = ObjectCopier.Clone <List <DFAEdit> >(editList); } } return(false); } DFAEdit edit = null; #region Flip one move target state foreach (var move in dfa2.GetMoves()) { //Creaty copy of the moves without current move var movesWithoutCurrMove = dfa2.GetMoves().ToList(); movesWithoutCurrMove.Remove(move); //Redirect every ch belonging to move condition foreach (var c in solver.GenerateAllCharacters(move.Label, false)) { long hash = IntegerUtil.PairToInt(move.SourceState, c - 97) + dfa2.StateCount; if (CanAdd(hash, editScriptHash)) { editScriptHash.Insert(0, hash); //Local copy of moves var newMoves = movesWithoutCurrMove.ToList(); var newMoveCondition = solver.MkCharConstraint(false, c); #region Remove ch from current move var andCond = solver.MkAnd(move.Label, solver.MkNot(newMoveCondition)); //add back move without ch iff satisfiable if (solver.IsSatisfiable(andCond)) { newMoves.Add(new Move <BDD>(move.SourceState, move.TargetState, andCond)); } #endregion #region Redirect c to a different state foreach (var state in dfa2.States) { if (state != move.TargetState) { var newMovesComplete = newMoves.ToList(); newMovesComplete.Add(new Move <BDD>(move.SourceState, state, newMoveCondition)); var dfa2new = Automaton <BDD> .Create(dfa2.InitialState, dfa2.GetFinalStates(), newMovesComplete); edit = new DFAEditMove(stateNamesMapping[move.SourceState], stateNamesMapping[state], c); editList.Insert(0, edit); if (GetDFAEditScriptTimeout(dfa1, dfa2new, al, solver, editScriptHash, editList, depth - 1, timeout, sw, tests, dfa1density, totalCost + edit.GetCost(), bestScript, stateNamesMapping)) { return(true); } editList.RemoveAt(0); } } #endregion editScriptHash.RemoveAt(0); } } } #endregion #region Flip one state from fin to non fin foreach (var state in dfa2.States) { if (CanAdd(state, editScriptHash)) { //flip its final non final status editScriptHash.Insert(0, state); var newFinalStates = new HashSet <int>(dfa2.GetFinalStates()); Automaton <BDD> dfa2new = null; if (dfa2.GetFinalStates().Contains(state)) { edit = new DFAEditState(stateNamesMapping[state], false); editList.Insert(0, edit); newFinalStates.Remove(state); dfa2new = Automaton <BDD> .Create(dfa2.InitialState, newFinalStates, dfa2.GetMoves()); } else { edit = new DFAEditState(stateNamesMapping[state], true); editList.Insert(0, edit); newFinalStates.Add(state); dfa2new = Automaton <BDD> .Create(dfa2.InitialState, newFinalStates, dfa2.GetMoves()); } if (GetDFAEditScriptTimeout(dfa1, dfa2new, al, solver, editScriptHash, editList, depth - 1, timeout, sw, tests, dfa1density, totalCost + edit.GetCost(), bestScript, stateNamesMapping)) { return(true); } editScriptHash.RemoveAt(0); editList.RemoveAt(0); } } #endregion return(false); }