/// <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); }
/// <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; }
// 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 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); }