예제 #1
0
        /// <summary>
        /// The sink state will be the state with the largest id.
        /// </summary>
        public ThreeAutomaton <S> MakeTotal()
        {
            var aut = this;

            int deadState = aut.maxState + 1;

            var newMoves = new List <Move <S> >();

            foreach (int state in aut.States)
            {
                var cond = algebra.MkNot(algebra.MkOr(aut.EnumerateConditions(state)));
                if (algebra.IsSatisfiable(cond))
                {
                    newMoves.Add(Move <S> .Create(state, deadState, cond));
                }
            }
            if (newMoves.Count == 0)
            {
                return(this);
            }

            newMoves.Add(Move <S> .Create(deadState, deadState, algebra.True));
            newMoves.AddRange(GetMoves());

            return(ThreeAutomaton <S> .Create(algebra, aut.initialState, aut.rejectingStateSet, aut.acceptingStateSet, newMoves));
        }
예제 #2
0
        /// <summary>
        /// Returns true iff this automaton and another automaton B are equivalent
        /// </summary>
        /// <param name="B">another autonmaton</param>
        public bool IsEquivalentWith(ThreeAutomaton <S> B, IBooleanAlgebra <S> solver)
        {
            Automaton <S> accA = Automaton <S> .Create(algebra, this.initialState, this.acceptingStateSet, this.GetMoves());

            Automaton <S> accB = Automaton <S> .Create(algebra, B.initialState, B.acceptingStateSet, B.GetMoves());

            if (!accA.IsEquivalentWith(accB))
            {
                return(false);
            }

            Automaton <S> rejA = Automaton <S> .Create(algebra, this.initialState, this.rejectingStateSet, this.GetMoves());

            Automaton <S> rejB = Automaton <S> .Create(algebra, B.initialState, B.rejectingStateSet, B.GetMoves());

            return(rejA.IsEquivalentWith(rejB));
        }
예제 #3
0
 private bool AreDistinguishable(ThreeAutomaton <S> fa, Equivalence E, Tuple <int, int> pq, IBooleanAlgebraPositive <S> solver)
 {
     foreach (Move <S> from_p in fa.GetMovesFrom(pq.Item1))
     {
         foreach (Move <S> from_q in fa.GetMovesFrom(pq.Item2))
         {
             if (from_p.TargetState != from_q.TargetState &&
                 !E.AreEquiv(from_p.TargetState, from_q.TargetState))
             {
                 if (solver.IsSatisfiable(solver.MkAnd(from_p.Label, from_q.Label)))
                 {
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
예제 #4
0
        /// <summary>
        /// Extension of standard minimization of FAs, use timeout.
        /// </summary>
        ThreeAutomaton <S> MinimizeClassical(IBooleanAlgebra <S> solver, int timeout)
        {
            var fa = this.MakeTotal();

            Equivalence E = new Equivalence();

            //initialize E, all nonfinal states are equivalent
            //and all final states are equivalent and all dontcare are equivalent
            List <int> stateList = new List <int>(fa.States);

            for (int i = 0; i < stateList.Count; i++)
            {
                //E.Add(stateList[i], stateList[i]);
                for (int j = 0; j < stateList.Count; j++)
                {
                    int  p        = stateList[i];
                    int  q        = stateList[j];
                    bool pIsFinal = fa.IsFinalState(p);
                    bool qIsFinal = fa.IsFinalState(q);
                    if (pIsFinal == qIsFinal)
                    {
                        if (pIsFinal)
                        {
                            E.Add(p, q);
                        }
                        else
                        {
                            bool pIsRej = fa.IsRejectingState(p);
                            bool qIsRej = fa.IsRejectingState(q);
                            if (pIsRej == qIsRej)
                            {
                                E.Add(p, q);
                            }
                        }
                    }
                }
            }

            //refine E
            bool       continueRefinement = true;
            List <int> statesList         = new List <int>(fa.States);

            while (continueRefinement)
            {
                continueRefinement = false;
                for (int i = 0; i < statesList.Count; i++)
                {
                    for (int j = 0; j < statesList.Count; j++)
                    {
                        Tuple <int, int> pq = new Tuple <int, int>(statesList[i], statesList[j]);
                        if (E.Contains(pq))
                        {
                            if (pq.Item1 != pq.Item2 && AreDistinguishable(fa, E, pq, solver))
                            {
                                E.Remove(pq);
                                continueRefinement = true;
                            }
                        }
                    }
                }
            }

            //create id's for equivalence classes
            Dictionary <int, int> equivIdMap = new Dictionary <int, int>();
            List <int>            mfaStates  = new List <int>();

            foreach (Tuple <int, int> pq in E)
            {
                int equivId;
                if (equivIdMap.TryGetValue(pq.Item1, out equivId))
                {
                    equivIdMap[pq.Item2] = equivId;
                }
                else if (equivIdMap.TryGetValue(pq.Item2, out equivId))
                {
                    equivIdMap[pq.Item1] = equivId;
                }
                else
                {
                    equivIdMap[pq.Item1] = pq.Item1;
                    equivIdMap[pq.Item2] = pq.Item1;
                    mfaStates.Add(pq.Item1);
                }
            }
            //remaining states map to themselves
            foreach (int state in fa.States)
            {
                if (!equivIdMap.ContainsKey(state))
                {
                    equivIdMap[state] = state;
                    mfaStates.Add(state);
                }
            }

            int mfaInitialState = equivIdMap[fa.InitialState];

            //group together transition conditions for transitions on equivalent states
            Dictionary <Tuple <int, int>, S> combinedConditionMap = new Dictionary <Tuple <int, int>, S>();

            foreach (int state in fa.States)
            {
                int fromStateId = equivIdMap[state];
                foreach (Move <S> trans in fa.GetMovesFrom(state))
                {
                    int toStateId = equivIdMap[trans.TargetState];
                    S   cond;
                    var p = new Tuple <int, int>(fromStateId, toStateId);
                    if (combinedConditionMap.TryGetValue(p, out cond))
                    {
                        combinedConditionMap[p] = solver.MkOr(cond, trans.Label);
                    }
                    else
                    {
                        combinedConditionMap[p] = trans.Label;
                    }
                }
            }

            //form the transitions of the mfa
            List <Move <S> > mfaTransitions = new List <Move <S> >();

            foreach (var kv in combinedConditionMap)
            {
                mfaTransitions.Add(Move <S> .Create(kv.Key.Item1, kv.Key.Item2, kv.Value));
            }


            //accepting states and rejecting
            HashSet <int> mfaAccStates = new HashSet <int>();
            HashSet <int> mfaRejStates = new HashSet <int>();

            foreach (int state in acceptingStateSet)
            {
                mfaAccStates.Add(equivIdMap[state]);
            }
            foreach (int state in rejectingStateSet)
            {
                mfaRejStates.Add(equivIdMap[state]);
            }

            return(ThreeAutomaton <S> .Create(algebra, mfaInitialState, mfaRejStates, mfaAccStates, mfaTransitions));
        }
예제 #5
0
 /// <summary>
 /// Make a complement of the automaton.
 /// Assumes that the automaton is deterministic, otherwise throws AutomataException.
 /// </summary>
 /// <param name="solver">solver for character constraints</param>
 /// <returns>Complement of this automaton</returns>
 public ThreeAutomaton <S> MkComplement()
 {
     return(ThreeAutomaton <S> .Create(algebra, initialState, acceptingStateSet, rejectingStateSet, this.GetMoves()));
 }
예제 #6
0
 /// <summary>
 /// Creates the automaton that accepts the union of L(this) and L(B).
 /// Uses additional epsilon transitions and does not need the solver for S.
 /// </summary>
 /// <param name="B">another automaton</param>
 public ThreeAutomaton <S> Union(ThreeAutomaton <S> B, IBooleanAlgebra <S> solver)
 {
     return(MkSum(this, B, solver));
 }
예제 #7
0
 /// <summary>
 /// Creates the automaton that accepts the intersection of L(this) and L(B).
 /// </summary>
 /// <param name="B">another automaton</param>
 /// <param name="solver">boolean algebra solver over S</param>
 public ThreeAutomaton <S> Intersect(ThreeAutomaton <S> B, IBooleanAlgebra <S> solver)
 {
     return(MkProduct(this, B, solver));
 }
예제 #8
0
 /// <summary>
 /// Make a sum (union) of a and b. Produces an automaton a+b such that L(a+b) = L(a) union L(b)
 /// </summary>
 public static ThreeAutomaton <S> MkSum(ThreeAutomaton <S> a, ThreeAutomaton <S> b, IBooleanAlgebra <S> solver)
 {
     return(MkProduct(a, b, solver, false));
 }
예제 #9
0
        public static ThreeAutomaton <S> MkProduct(ThreeAutomaton <S> aut1, ThreeAutomaton <S> aut2, IBooleanAlgebra <S> solver, bool inters)
        {
            var a = aut1.MakeTotal();
            var b = aut2.MakeTotal();

            var stateIdMap = new Dictionary <Tuple <int, int>, int>();
            var initPair   = new Tuple <int, int>(a.InitialState, b.InitialState);
            var frontier   = new Stack <Tuple <int, int> >();

            frontier.Push(initPair);
            stateIdMap[initPair] = 0;

            var delta = new Dictionary <int, List <Move <S> > >();

            delta[0] = new List <Move <S> >();
            var states = new List <int>();

            states.Add(0);

            var accStates = new List <int>();
            var rejStates = new List <int>();

            if (inters)
            {
                if (a.IsFinalState(a.InitialState) && b.IsFinalState(b.InitialState))
                {
                    accStates.Add(0);
                }
                else
                if (a.IsRejectingState(a.InitialState) || b.IsRejectingState(b.InitialState))
                {
                    rejStates.Add(0);
                }
            }
            else
            {
                if (a.IsRejectingState(a.InitialState) && b.IsRejectingState(b.InitialState))
                {
                    rejStates.Add(0);
                }
                else
                if (a.IsFinalState(a.InitialState) || b.IsFinalState(b.InitialState))
                {
                    accStates.Add(0);
                }
            }

            int n = 1;

            while (frontier.Count > 0)
            {
                var currPair       = frontier.Pop();
                int source         = stateIdMap[currPair];
                var outTransitions = delta[source];

                foreach (var t1 in a.GetMovesFrom(currPair.Item1))
                {
                    foreach (var t2 in b.GetMovesFrom(currPair.Item2))
                    {
                        var cond = solver.MkAnd(t1.Label, t2.Label);
                        if (!solver.IsSatisfiable(cond))
                        {
                            continue; //ignore the unsatisfiable move
                        }
                        Tuple <int, int> targetPair = new Tuple <int, int>(t1.TargetState, t2.TargetState);
                        int target;
                        if (!stateIdMap.TryGetValue(targetPair, out target))
                        {
                            //state has not yet been found
                            target = n;
                            n     += 1;
                            stateIdMap[targetPair] = target;
                            states.Add(target);
                            delta[target] = new List <Move <S> >();
                            frontier.Push(targetPair);

                            if (inters)
                            {
                                if (a.IsFinalState(t1.TargetState) && b.IsFinalState(t2.TargetState))
                                {
                                    accStates.Add(target);
                                }
                                else
                                if (a.IsRejectingState(t1.TargetState) || b.IsRejectingState(t2.TargetState))
                                {
                                    rejStates.Add(target);
                                }
                            }
                            else
                            {
                                if (a.IsRejectingState(t1.TargetState) && b.IsRejectingState(t2.TargetState))
                                {
                                    rejStates.Add(target);
                                }
                                else
                                if (a.IsFinalState(t1.TargetState) || b.IsFinalState(t2.TargetState))
                                {
                                    accStates.Add(target);
                                }
                            }
                        }
                        outTransitions.Add(Move <S> .Create(source, target, cond));
                    }
                }
            }

            var incomingTransitions = new Dictionary <int, List <Move <S> > >();

            foreach (int state in states)
            {
                incomingTransitions[state] = new List <Move <S> >();
            }
            foreach (int state in states)
            {
                foreach (Move <S> t in delta[state])
                {
                    incomingTransitions[t.TargetState].Add(t);
                }
            }


            return(ThreeAutomaton <S> .Create(aut1.algebra, 0, rejStates, accStates, EnumerateMoves(delta)));
        }
예제 #10
0
        /// <summary>
        /// Create a three symbolic automaton.
        /// </summary>
        /// <param name="initialState">initial state</param>
        /// <param name="acceptingStates">final states</param>
        /// <param name="moves">moves</param>
        /// <returns></returns>
        public static ThreeAutomaton <S> Create(IBooleanAlgebra <S> algebra, int initialState, IEnumerable <int> rejectingStates, IEnumerable <int> acceptingStates, IEnumerable <Move <S> > moves)
        {
            var delta    = new Dictionary <int, List <Move <S> > >();
            var deltaInv = new Dictionary <int, List <Move <S> > >();

            delta[initialState]    = new List <Move <S> >();
            deltaInv[initialState] = new List <Move <S> >();
            int maxState = initialState;

            foreach (Move <S> move in moves)
            {
                if (move.IsEpsilon)
                {
                    throw new AutomataException("Epsilon transitions not supported.");
                }
                if (!delta.ContainsKey(move.SourceState))
                {
                    delta[move.SourceState] = new List <Move <S> >();
                }
                if (!delta.ContainsKey(move.TargetState))
                {
                    delta[move.TargetState] = new List <Move <S> >();
                }
                if (!deltaInv.ContainsKey(move.SourceState))
                {
                    deltaInv[move.SourceState] = new List <Move <S> >();
                }
                if (!deltaInv.ContainsKey(move.TargetState))
                {
                    deltaInv[move.TargetState] = new List <Move <S> >();
                }
                delta[move.SourceState].Add(move);
                deltaInv[move.TargetState].Add(move);
                maxState = Math.Max(maxState, Math.Max(move.SourceState, move.TargetState));
            }
            HashSet <int> acceptingStateSet = new HashSet <int>(acceptingStates);

            acceptingStateSet.RemoveWhere(x => !delta.ContainsKey(x)); //remove irrelevant states
            HashSet <int> rejectingStateSet = new HashSet <int>(rejectingStates);

            rejectingStateSet.RemoveWhere(x => !delta.ContainsKey(x));
            HashSet <int> dontCareStateSet = new HashSet <int>();

            foreach (var state in delta.Keys)
            {
                if (!acceptingStateSet.Contains(state) && !rejectingStateSet.Contains(state))
                {
                    dontCareStateSet.Add(state);
                }
            }


            ThreeAutomaton <S> fsa = new ThreeAutomaton <S>();

            fsa.algebra           = algebra;
            fsa.initialState      = initialState;
            fsa.acceptingStateSet = acceptingStateSet;
            fsa.rejectingStateSet = rejectingStateSet;
            fsa.dontCareStateSet  = dontCareStateSet;

            fsa.maxState = maxState;
            fsa.delta    = delta;
            fsa.deltaInv = deltaInv;
            //TODO add determinism check
            return(fsa);
        }