/// <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);
        }
Exemplo n.º 4
0
        /// <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);
        }