// 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);
        }
예제 #2
0
        // 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);
        }