Exemple #1
0
        /// <summary>
        /// Counts the number of nodes (both terminals and nonterminals) in the BDD.
        /// </summary>
        public int CountNodes()
        {
            if (IsLeaf)
            {
                return(1);
            }

            HashSet <BDD>     visited = new HashSet <BDD>();
            SimpleStack <BDD> stack   = new SimpleStack <BDD>();

            stack.Push(this);
            visited.Add(this);
            while (stack.IsNonempty)
            {
                BDD a = stack.Pop();
                if (!a.IsLeaf)
                {
                    if (visited.Add(a.One))
                    {
                        stack.Push(a.One);
                    }
                    if (visited.Add(a.Zero))
                    {
                        stack.Push(a.Zero);
                    }
                }
            }
            return(visited.Count);
        }
Exemple #2
0
        /// <summary>
        /// Computes (number of nonterminals, number of terminals) in the underlying directed acyclic graph.
        /// </summary>
        public Tuple <int, int> GetSize()
        {
            int nrNodes  = 0;
            int nrLeaves = 0;
            HashSet <BDG <T, S> >     done  = new HashSet <BDG <T, S> >();
            SimpleStack <BDG <T, S> > stack = new SimpleStack <BDG <T, S> >();

            stack.Push(this);
            done.Add(this);
            while (stack.IsNonempty)
            {
                var bdg = stack.Pop();
                if (bdg.IsLeaf)
                {
                    nrLeaves += 1;
                }
                else
                {
                    if (done.Add(bdg.TrueCase))
                    {
                        stack.Push(bdg.TrueCase);
                    }
                    if (done.Add(bdg.FalseCase))
                    {
                        stack.Push(bdg.FalseCase);
                    }
                    nrNodes += 1;
                }
            }
            return(new Tuple <int, int>(nrNodes, nrLeaves));
        }
Exemple #3
0
        /// <summary>
        /// Based on MinimizeMoore method/technique.
        /// </summary>
        void Initialize()
        {
            var fa = aut;

            var currLayer = new SimpleStack <Tuple <int, int> >();
            var nextLayer = new SimpleStack <Tuple <int, int> >();

            //any pair of states (p,q) where one state is final and the other is not are distinguished by
            //the empty list represented by null, this set of distinguishing sequences is trivially suffix-closed
            foreach (var p in fa.GetStates())
            {
                if (!fa.IsFinalState(p))
                {
                    foreach (var q in fa.GetFinalStates())
                    {
                        var pair = MkPair(p, q);
                        if (!distinguisher.ContainsKey(pair))
                        {
                            //the empty sequence distinguishes the states
                            distinguisherConcrete[pair] = "";
                            //List<Pair> pairs;
                            //if (!distinguishingStringsMap.TryGetValue("", out pairs))
                            //{
                            //    pairs = new List<Tuple<int, int>>();
                            //    distinguishingStringsMap[""] = pairs;
                            //    distinguishingStringsSeq.Add("");
                            //}
                            //pairs.Add(pair);
                            distinguisher[pair] = null;
                            nextLayer.Push(pair);
                        }
                    }
                }
            }

            //if a target pair of states is distinguished by some sequence
            //then any pair entering those states is also distinguished by extending that sequence
            //work breadth-first to maintain shortest witnesses
            while (nextLayer.IsNonempty)
            {
                var tmp = currLayer;
                currLayer = nextLayer;
                nextLayer = new SimpleStack <Tuple <int, int> >();
                while (currLayer.IsNonempty)
                {
                    var targetpair = currLayer.Pop();
                    foreach (var m1 in fa.GetMovesTo(targetpair.Item1))
                    {
                        foreach (var m2 in fa.GetMovesTo(targetpair.Item2))
                        {
                            if (m1.SourceState != m2.SourceState)
                            {
                                var psi = solver.MkAnd(m1.Label, m2.Label);
                                if (solver.IsSatisfiable(psi))
                                {
                                    var sourcepair = MkPair(m1.SourceState, m2.SourceState);
                                    if (!distinguisher.ContainsKey(sourcepair))
                                    {
                                        //add a new distinguishing sequence for the source pair
                                        //it extends a sequence of the target pair
                                        //thus the sequences remain suffix-closed
                                        if (concretize != null)
                                        {
                                            #region when concretization function is given precompute concrete distinguishers
                                            char c;
                                            if (!selectedCharacterMap.TryGetValue(psi, out c))
                                            {
                                                c = concretize(psi);
                                                selectedCharacterMap[psi] = c;
                                            }
                                            var s = c + distinguisherConcrete[targetpair];
                                            distinguisherConcrete[sourcepair] = s;

                                            //List<Pair> pairs;
                                            //if (!distinguishingStringsMap.TryGetValue(s, out pairs))
                                            //{
                                            //    pairs = new List<Tuple<int, int>>();
                                            //    distinguishingStringsMap[s] = pairs;
                                            //    distinguishingStringsSeq.Add(s);
                                            //}
                                            //pairs.Add(sourcepair);
                                            #endregion
                                        }

                                        var list = new ConsList <T>(psi, distinguisher[targetpair]);
                                        distinguisher[sourcepair] = list;

                                        nextLayer.Push(sourcepair);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        public STb <FUNC, TERM, SORT> Compose()
        {
            var stack         = new SimpleStack <Tuple <int, int> >();
            int stateId       = 1;
            var stateIdMap    = new Dictionary <Tuple <int, int>, int>();
            var revStateIdMap = new Dictionary <int, Tuple <int, int> >();
            var q0A_x_q0B     = new Tuple <int, int>(A.InitialState, B.InitialState);

            stack.Push(q0A_x_q0B);
            stateIdMap[q0A_x_q0B] = 0;
            revStateIdMap[0]      = q0A_x_q0B;

            Func <int, int, int> ComposeStates = (x, y) =>
            {
                var xy = new Tuple <int, int>(x, y);
                int q;
                if (stateIdMap.TryGetValue(xy, out q))
                {
                    return(q);
                }
                else
                {
                    q                = stateId;
                    stateId         += 1;
                    stateIdMap[xy]   = q;
                    revStateIdMap[q] = xy;
                    stack.Push(xy);
                    return(q);
                }
            };
            var A2B = new STb <FUNC, TERM, SORT>(solver, A.Name + "2" + B.Name, A.InputSort, B.OutputSort, regSort, JoinRegs(A.InitialRegister, B.InitialRegister), 0);

            //create normal composed rules
            while (stack.IsNonempty)
            {
                var qA_x_qB = stack.Pop();
                var qA      = qA_x_qB.Item1;
                var qB      = qA_x_qB.Item2;
                var ruleA   = A.GetRuleFrom(qA);
                if (ruleA.IsNotUndef)
                {
                    var qAB_rule = Comp(solver.True, ruleA, qB, ComposeStates, false);
                    A2B.AssignRule(stateIdMap[qA_x_qB], qAB_rule);
                }
                else
                {
                    A2B.AssignRule(stateIdMap[qA_x_qB], UndefRule <TERM> .Default);
                }
            }
            foreach (var qAB in A2B.States)
            {
                var qA_x_qB = revStateIdMap[qAB];
                var qA      = qA_x_qB.Item1;
                var qB      = qA_x_qB.Item2;
                var ruleA   = A.GetFinalRuleFrom(qA);
                if (ruleA.IsNotUndef)
                {
                    var qAB_Frule = Comp(solver.True, ruleA, qB, (p, q) => qAB, true);
                    A2B.AssignFinalRule(qAB, qAB_Frule);
                }
            }

            A2B.EliminateDeadends();


            //Func<Rule<TERM>, Rule<TERM>> ReplaceWithEpsilon = (r) =>
            //    {

            //    };

            //var aut = A2B.ToST(true).automaton.RelpaceAllGuards(ReplaceWithEpsilon);


            return(A2B);
        }
Exemple #5
0
        //public List<Move<Rule<T>>> CoveredMoves
        //{
        //    get { return covered_moves; }
        //}

        public void Explore()
        {
            var seen_states = new HashSet <int>();

            seen_states.Add(stb.InitialState);

            var stack      = new SimpleStack <Tuple <int, T> >();
            var stack_next = new SimpleStack <Tuple <int, T> >();
            var seen_next  = new HashSet <Tuple <int, T> >();

            stack_next.Push(new Tuple <int, T>(stb.InitialState, stb.InitialRegister));



            while (stack_next.IsNonempty)
            {
                foreach (var p_r in seen_next)
                {
                    seen_states.Add(p_r.Item1);
                }

                var tmp = stack;
                stack      = stack_next;
                stack_next = tmp;
                seen_next.Clear();

                while (stack.IsNonempty)
                {
                    var q_r  = stack.Pop();
                    var q    = q_r.Item1;
                    var r_in = q_r.Item2;
                    foreach (var dir_move in moves[q])
                    {
                        var move    = dir_move.Item3;
                        var guard1  = Z.ApplySubstitution(move.Label.Guard, stb.RegVar, r_in);
                        var witness = Z.MainSolver.FindOneMember(Z.MkAnd(guard1, Z.MkEq(stb.InputVar, stb.InputVar)));
                        if (witness != null)
                        {
                            var r_out = Z.Simplify(Z.ApplySubstitution(move.Label.Update, stb.InputVar, witness.Value, stb.RegVar, r_in));
                            var p_r   = new Tuple <int, T>(move.TargetState, r_out);
                            if (!exploredSteps.ContainsKey(q))
                            {
                                exploredSteps[q] = new Dictionary <Tuple <T, T>, Tuple <int, T> >();
                            }
                            exploredSteps[q][new Tuple <T, T>(witness.Value, r_in)] = p_r;
                            if (!seen_states.Contains(move.TargetState))
                            {
                                if (seen_next.Add(p_r))
                                {
                                    stack_next.Push(p_r);
                                }
                            }
                        }
                        else //the move is inaccessible from this state (and register value) since guard1 is unsatisfiable
                        {
                            uncovered_moves.Add(dir_move);
                        }
                    }
                    foreach (var dir_fmove in final_moves[q])
                    {
                        var fmove  = dir_fmove.Item3;
                        var guard1 = Z.Simplify(Z.ApplySubstitution(fmove.Label.Guard, stb.RegVar, r_in));
                        if (guard1.Equals(stb.Solver.False))
                        {
                            uncovered_final_moves.Add(dir_fmove);
                        }
                    }
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Generate method code for a given BDD with given methid as method name
        /// </summary>
        private static void GenerateCodeForBDD(StringBuilder code, BDD pred, string methid)
        {
            Dictionary <BDD, int> idMap = new Dictionary <BDD, int>();
            int             nextLabelId = 0;
            Func <BDD, int> getId       = bdd =>
            {
                int bddid;
                if (!idMap.TryGetValue(bdd, out bddid))
                {
                    bddid      = nextLabelId++;
                    idMap[bdd] = bddid;
                }

                return(bddid);
            };

            HashSet <BDD>     done = new HashSet <BDD>();
            SimpleStack <BDD> todo = new SimpleStack <BDD>();

            todo.Push(pred);
            done.Add(pred);
            StringBuilder leaves = new StringBuilder();

            while (todo.IsNonempty)
            {
                var bdd = todo.Pop();
                if (bdd.IsLeaf)
                {
                    leaves.Append(String.Format("\r\n        P{0}_{1}: return {2};", methid, getId(bdd), bdd.IsEmpty ? "false" : "true"));
                }
                else
                {
                    BDD exit         = !bdd.Zero.IsLeaf && (bdd.Zero.Zero == bdd.One || bdd.Zero.One == bdd.One) ? bdd.One : bdd.Zero;
                    BDD continuation = bdd;
                    int zeros        = 0;
                    int ones         = 0;
                    while (true)
                    {
                        if (exit == continuation.Zero)
                        {
                            zeros       |= 1 << continuation.Ordinal;
                            continuation = continuation.One;
                        }
                        else if (exit == continuation.One)
                        {
                            ones        |= 1 << continuation.Ordinal;
                            continuation = continuation.Zero;
                        }
                        else
                        {
                            break;
                        }
                    }

                    var anyZero       = string.Format("(c & 0x{0:X}) != 0x{0:X}", zeros);
                    var anyOne        = string.Format("(c & 0x{0:X}) != 0", ones);
                    var exitCondition = zeros == 0 ? anyOne : ones == 0 ? anyZero : string.Format("({0}) || ({1})", anyOne, anyZero);
                    code.Append(string.Format(@"
        "));
                    if (bdd != pred)
                    {
                        code.Append(string.Format("P{0}_{1}: ", methid, getId(bdd)));
                    }

                    code.Append(string.Format("if ({2}) goto P{0}_{3}; else goto P{0}_{4};", methid, getId(bdd), exitCondition, getId(exit), getId(continuation)));
                    if (done.Add(exit))
                    {
                        todo.Push(exit);
                    }

                    if (done.Add(continuation))
                    {
                        todo.Push(continuation);
                    }
                }
            }

            code.Append(leaves.ToString());
        }
        /// <summary>
        /// Explores the PDA and converts it into an automaton,
        /// only stacks up to bounded depth are considered.
        /// </summary>
        /// <param name="stackDepth">upper bound on reached stack depth, nonpositive value means unbounded and may cause nontermination</param>
        public Automaton <T> Explore(int stackDepth = 0)
        {
            var moves       = new List <Move <T> >();
            var stateMap    = new Dictionary <Tuple <int, Sequence <S> >, int>();
            var configMap   = new Dictionary <int, Tuple <int, Sequence <S> > >();
            var finalStates = new HashSet <int>();

            int q0          = 0;
            var config0     = new Tuple <int, Sequence <S> >(this.automaton.InitialState, new Sequence <S>(this.initialStackSymbol));
            int nextStateId = 1;

            stateMap[config0] = q0;
            configMap[q0]     = config0;
            if (automaton.IsFinalState(this.automaton.InitialState))
            {
                finalStates.Add(q0);
            }

            var movemap = new Dictionary <Tuple <int, int>, T>();
            Action <int, int, T> AddMove = (source, target, pred) =>
            {
                var key = new Tuple <int, int>(source, target);
                T   psi;
                if (movemap.TryGetValue(key, out psi))
                {
                    movemap[key] = this.terminalAlgebra.MkOr(psi, pred);
                }
                else
                {
                    movemap[key] = pred;
                }
            };

            var frontier = new SimpleStack <int>();

            frontier.Push(q0);
            while (frontier.IsNonempty)
            {
                int q      = frontier.Pop();
                var config = configMap[q];
                foreach (var move in automaton.GetMovesFrom(config.Item1))
                {
                    if (stackDepth < 1 || (config.Item2.Length - 1 + move.Label.PushSymbols.Length) <= stackDepth)
                    {
                        var pop  = move.Label.PopSymbol;
                        var push = move.Label.PushSymbols;
                        if (config.Item2.First.Equals(pop))
                        {
                            var targetConfig = new Tuple <int, Sequence <S> >(move.TargetState, push.Append(config.Item2.Rest()));
                            int target;
                            if (!stateMap.TryGetValue(targetConfig, out target))
                            {
                                target = nextStateId++;
                                stateMap[targetConfig] = target;
                                configMap[target]      = targetConfig;
                                frontier.Push(target);
                                if (automaton.IsFinalState(move.TargetState))
                                {
                                    finalStates.Add(target);
                                }
                            }
                            Move <T> newmove;
                            if (move.Label.InputIsEpsilon)
                            {
                                newmove = Move <T> .Epsilon(q, target);

                                moves.Add(newmove);
                            }
                            else
                            {
                                //accumulate predicates for transitions
                                AddMove(q, target, move.Label.Input);
                            }
                        }
                    }
                }
            }

            foreach (var entry in movemap)
            {
                moves.Add(Move <T> .Create(entry.Key.Item1, entry.Key.Item2, entry.Value));
            }

            var res = Automaton <T> .Create(this.terminalAlgebra, q0, finalStates, moves, false, true);

            return(res);
        }
        PushdownAutomaton <S, T> Intersect1(IMinimalAutomaton <T> nfa)
        {
            //depth first product construction, PDA may have epsilon moves
            var stateIdMap  = new Dictionary <Pair, int>();
            int nextStateId = 1;
            var stack       = new SimpleStack <Pair>();
            var moves       = new List <Move <PushdownLabel <S, T> > >();
            var states      = new List <int>();
            var finalstates = new List <int>();

            #region  GetState: push the pair to stack if the state id was new and update final states as needed
            Func <Pair, int> GetState = (pair) =>
            {
                int id;
                if (!stateIdMap.TryGetValue(pair, out id))
                {
                    id               = nextStateId;
                    nextStateId     += 1;
                    stateIdMap[pair] = id;
                    stack.Push(pair);
                    states.Add(id);
                    if (this.automaton.IsFinalState(pair.Item1) && nfa.IsFinalState(pair.Item2))
                    {
                        finalstates.Add(id);
                    }
                }
                return(id);
            };
            #endregion

            var initPair  = new Pair(this.automaton.InitialState, nfa.InitialState);
            int initState = GetState(initPair);

            #region compute the product transitions with depth-first search
            while (stack.IsNonempty)
            {
                var sourcePair = stack.Pop();
                var source     = stateIdMap[sourcePair];
                var pda_state  = sourcePair.Item1;
                var aut_state  = sourcePair.Item2;
                foreach (var pda_move in this.automaton.GetMovesFrom(pda_state))
                {
                    if (pda_move.IsEpsilon || pda_move.Label.InputIsEpsilon)
                    {
                        var targetPair = new Pair(pda_move.TargetState, aut_state);
                        int target     = GetState(targetPair);
                        moves.Add(Move <PushdownLabel <S, T> > .Create(source, target, pda_move.Label));
                    }
                    else
                    {
                        //assuming here that the automaton does not have epsilons
                        foreach (var aut_move in nfa.GetMovesFrom(aut_state))
                        {
                            if (aut_move.IsEpsilon)
                            {
                                throw new AutomataException(AutomataExceptionKind.AutomatonIsNotEpsilonfree);
                            }

                            var cond = nfa.Algebra.MkAnd(aut_move.Label, pda_move.Label.Input);
                            //if the joint condition is not satisfiable then the
                            //joint move does effectively not exist
                            if (nfa.Algebra.IsSatisfiable(cond))
                            {
                                var targetPair = new Pair(pda_move.TargetState, aut_move.TargetState);
                                int target     = GetState(targetPair);
                                var label      = new PushdownLabel <S, T>(cond, pda_move.Label.PushAndPop);
                                var jointmove  = Move <PushdownLabel <S, T> > .Create(source, target, label);

                                moves.Add(jointmove);
                            }
                        }
                    }
                }
            }
            #endregion

            //note: automaton creation eliminates unreachable states and deadend states from the product
            var productAutom = Automaton <PushdownLabel <S, T> > .Create(null, initState, finalstates, moves, true, true);

            var product = new PushdownAutomaton <S, T>(nfa.Algebra, productAutom, this.stackSymbols, this.initialStackSymbol);
            return(product);
        }
            /// <summary>
            /// Algorithm 'saturate' in Figure 1 from Finkel-Willems-Wolper paper
            /// 'A Direct Symbolic Approach to Model Checking PushDown Systems'
            /// </summary>
            /// <returns></returns>
            internal HashSet <Trans> Saturate()
            {
                var hash  = new HashSet <Trans>();
                var stack = new SimpleStack <Trans>();

                foreach (var q in this.Q)
                {
                    stack.Push(MkTrans(q, q));
                }

                var direct = new Dictionary <Trans, SimpleStack <Trans> >();
                var trans  = new Dictionary <Trans, SimpleStack <Tuple <Trans, Trans> > >();

                Func <Trans, SimpleStack <Trans> > Direct = (t) =>
                {
                    SimpleStack <Trans> t_stack;
                    if (!direct.TryGetValue(t, out t_stack))
                    {
                        t_stack   = new SimpleStack <Trans>();
                        direct[t] = t_stack;
                    }
                    return(t_stack);
                };

                Func <Trans, SimpleStack <Tuple <Trans, Trans> > > Transfer = (t) =>
                {
                    SimpleStack <Tuple <Trans, Trans> > t_trans;
                    if (!trans.TryGetValue(t, out t_trans))
                    {
                        t_trans  = new SimpleStack <Tuple <Trans, Trans> >();
                        trans[t] = t_trans;
                    }
                    return(t_trans);
                };

                foreach (var a in pda.stackSymbols)
                {
                    foreach (var push in pushMap[a])
                    {
                        foreach (var pop in popMap[a])
                        {
                            //push_pop goes from target of push to source of pop
                            var push_pop = MkTrans(push.Item2, pop.SourceState);
                            //edge goes from source of push to target of pop
                            var edge = MkTrans(push.Item1, pop.TargetState);
                            Direct(push_pop).Push(edge);
                        }
                    }
                }

                foreach (var q in Q)
                {
                    foreach (var p in Q)
                    {
                        var qp       = MkTrans(q, p);
                        var qp_trans = Transfer(qp);
                        foreach (var t in Q)
                        {
                            var pt    = MkTrans(p, t);
                            var qt    = MkTrans(q, t);
                            var pt_qt = new Tuple <Trans, Trans>(pt, qt);
                            var tq    = MkTrans(t, q);
                            var tp    = MkTrans(t, p);
                            var tq_tp = new Tuple <Trans, Trans>(tq, tp);
                            qp_trans.Push(pt_qt);
                            qp_trans.Push(tq_tp);
                        }
                    }
                }

                while (stack.IsNonempty)
                {
                    var alpha = stack.Pop();
                    hash.Add(alpha);
                    stack.PushAll(direct[alpha]);
                    foreach (var pair in Transfer(alpha))
                    {
                        if (hash.Contains(pair.Item1))
                        {
                            stack.Push(pair.Item2);
                        }
                        else
                        {
                            Direct(pair.Item1).Push(pair.Item2);
                        }
                    }
                }

                return(hash);
            }