/* Generates a formula representing the fact that for <state> either
         * the eventuality is not promised or that if it is, then there
         * exists a fragment of <stateSet> rooted at <state> such that
         * all the frontier nodes satisfy the eventuallity
         */
        private FormulaNode GenA(FormulaNode stateSet, SymbolicState state)
        {
            List <FormulaNode> terms = new List <FormulaNode>();

            foreach (var e in elementary)
            {
                if (e.GetLogicOperator() != LogicOperator.EX)
                {
                    continue;
                }
                if (e[0].GetLogicOperator() != LogicOperator.ER)
                {
                    continue;
                }

                FormulaNode frag = ComputeAUFragment(e, stateSet, state);

                FormulaNode promised = state.ValueOf(e);

                FormulaNode res = new FormulaNode(LogicOperator.OR, promised, state.ValueOf(e[0][0]));

                res = new FormulaNode(LogicOperator.OR, res, frag);
                terms.Add(res);
            }
            return(JoinTerms(LogicOperator.AND, terms));
        }
        private FormulaNode GenLC1(FormulaNode stateSet, SymbolicState state)
        {
            List <FormulaNode> terms = new List <FormulaNode>();

            foreach (var e in elementary)
            {
                if (e.GetLogicOperator() != LogicOperator.EX)
                {
                    continue;
                }

                string        nextName         = "succ" + uniqueId.GetTicket().ToString();
                SymbolicState next             = new SymbolicState(elementary, nextName);
                FormulaNode   existsInState    = state.ValueOf(e);
                FormulaNode   notExistsInState = new FormulaNode(LogicOperator.NOT, existsInState, null);
                FormulaNode   nextValid        = SymbolicState.Substitute(stateSet, state, next);
                FormulaNode   transition       = GenTransition(state, next);
                FormulaNode   body             = e[0];
                FormulaNode   occursNext       = next.ValueOf(body);
                FormulaNode   hasSucc          = new FormulaNode(LogicOperator.AND, nextValid, transition);
                hasSucc = new FormulaNode(LogicOperator.AND, hasSucc, occursNext);
                hasSucc = next.Quantify(LogicOperator.EXISTS, hasSucc);
                terms.Add(new FormulaNode(LogicOperator.OR, notExistsInState, hasSucc));
            }
            return(JoinTerms(LogicOperator.AND, terms));
        }
        /* Generates a formula representing the fact that for <state> either
         * the eventuality is not promised or that if it is, then there
         * exists a fragment of <stateSet> rooted at <state> that has
         * a frontier node who satisfied the eventuallity
         */
        private FormulaNode GenE(FormulaNode stateSet, SymbolicState state)
        {
            ComputeEUFragments(stateSet, state);

            List <FormulaNode> terms = new List <FormulaNode>();

            foreach (var e in elementary)
            {
                if (e.GetLogicOperator() != LogicOperator.EX)
                {
                    continue;
                }
                if (e[0].GetLogicOperator() != LogicOperator.EU)
                {
                    continue;
                }

                FormulaNode notPromised = new FormulaNode(LogicOperator.NOT);
                notPromised.SetChildren(state.ValueOf(e), null);

                FormulaNode res = new FormulaNode(LogicOperator.OR);
                res.SetChildren(notPromised, new FormulaNode(LogicOperator.NOT));
                res[1].SetChildren(state.ValueOf(e[0][0]), null);

                FormulaNode frag = fragEU[e[0]];

                res = new FormulaNode(LogicOperator.OR, res, frag);
                terms.Add(res);
            }
            return(JoinTerms(LogicOperator.AND, terms));
        }
        /* Check if we reached a fixpoint. That is, if there are no states in <largeSet>
         * which are absent from <smallSet>.
         */
        private bool IsFixpoint(FormulaNode largeSet, FormulaNode smallSet, SymbolicState v)
        {
            FormulaNode notNew       = new FormulaNode(LogicOperator.NOT, smallSet, null);
            FormulaNode stateRemoved = new FormulaNode(LogicOperator.AND, largeSet, notNew);

            stateRemoved = v.Quantify(LogicOperator.EXISTS, stateRemoved);
            return(!FormulaCNF.QBFSAT(stateRemoved));
        }
        /*
         * <au> is an elementary formula of the form EX(ER(p,q))
         */
        private FormulaNode ComputeAUFragment(FormulaNode au, FormulaNode stateSet, SymbolicState state)
        {
#if DEBUG
            Console.WriteLine("Computing fragment for " + au);
#endif
            FormulaNode frag     = FormulaParser.Parse("~TRUE");
            FormulaNode notLeft  = new FormulaNode(LogicOperator.NOT, au[0][0], null);
            FormulaNode notRight = new FormulaNode(LogicOperator.NOT, au[0][1], null);
            while (true)
            {
                string        nextName   = "succ" + uniqueId.GetTicket().ToString();
                SymbolicState next       = new SymbolicState(elementary, nextName);
                FormulaNode   transition = GenTransition(state, next);
                FormulaNode   memberOf   = SymbolicState.Substitute(stateSet, state, next);
                FormulaNode   nextFrag   = SymbolicState.Substitute(frag, state, next);
                FormulaNode   newFrag    = new FormulaNode(LogicOperator.AND, transition, memberOf);
                newFrag = new FormulaNode(LogicOperator.AND, newFrag, nextFrag);
                newFrag = next.Quantify(LogicOperator.EXISTS, newFrag);

                newFrag = new FormulaNode(LogicOperator.AND, state.ValueOf(notLeft.NNF()), newFrag);

                // Add the big conjunction needed for fragAU
                List <FormulaNode> fragTerms = new List <FormulaNode>();

                foreach (FormulaNode el in elementary)
                {
                    if (el.GetLogicOperator() != LogicOperator.EX)
                    {
                        continue;
                    }

                    nextName   = "succ" + uniqueId.GetTicket().ToString();
                    next       = new SymbolicState(elementary, nextName);
                    transition = GenTransition(state, next);
                    memberOf   = SymbolicState.Substitute(stateSet, state, next);
                    nextFrag   = SymbolicState.Substitute(frag, state, next);


                    FormulaNode lhs = state.ValueOf(el);
                    FormulaNode rhs = new FormulaNode(LogicOperator.AND, transition, memberOf);
                    rhs = new FormulaNode(LogicOperator.AND, rhs, nextFrag);
                    rhs = new FormulaNode(LogicOperator.AND, rhs, next.ValueOf(SymbolicState.Substitute(el[0], state, next)));
                    rhs = next.Quantify(LogicOperator.EXISTS, rhs);

                    fragTerms.Add(new FormulaNode(LogicOperator.IMP, lhs, rhs));
                }

                newFrag = new FormulaNode(LogicOperator.AND, newFrag, JoinTerms(LogicOperator.AND, fragTerms));
                newFrag = new FormulaNode(LogicOperator.OR, state.ValueOf(notRight.NNF()), newFrag);

                if (IsFixpoint(newFrag, frag, state))
                {
                    return(frag);
                }

                frag = newFrag;
            }
        }
        /* Generates a formula representing the fact that <state> has a
         * successor in <stateSet>. Does not guarantee that <state> itself
         * belongs to the set.
         */
        private FormulaNode GenSucc(FormulaNode stateSet, SymbolicState state)
        {
            string        nextName   = "succ" + uniqueId.GetTicket().ToString();
            SymbolicState next       = new SymbolicState(elementary, nextName);
            FormulaNode   transition = GenTransition(state, next);
            FormulaNode   memberOf   = SymbolicState.Substitute(stateSet, state, next);
            FormulaNode   result     = new FormulaNode(LogicOperator.AND, transition, memberOf);

            result = next.Quantify(LogicOperator.EXISTS, result);
            return(result);
        }
Example #7
0
        /* Replace the variables describing the state <from> with the ones that describe
         * state <to>
         */
        public static FormulaNode Substitute(FormulaNode formula, SymbolicState from, SymbolicState to)
        {
            if (formula.GetLogicOperator() == LogicOperator.VAR)
            {
                if (from.nameToElementary.Keys.Contains(formula.GetName()))
                {
                    // this variable represents an elementary formula
                    var elementary = from.nameToElementary[formula.GetName()];
                    return(new FormulaNode(to.elementaryNames[elementary]));
                }
                else
                {
                    return(new FormulaNode(formula.GetName()));
                }
            }

            if (formula.GetLogicOperator() == LogicOperator.ALL ||
                formula.GetLogicOperator() == LogicOperator.EXISTS)
            {
                FormulaNode result = new FormulaNode(formula.GetLogicOperator());
                if (from.nameToElementary.Keys.Contains(formula.GetName()))
                {
                    // this variable represents an elementary formula
                    var elementary = from.nameToElementary[formula.GetName()];
                    result.SetName(to.elementaryNames[elementary]);
                }
                else
                {
                    result.SetName(formula.GetName());
                }
                result.SetChildren(Substitute(formula[0], from, to), null);
                return(result);
            }

            FormulaNode res = new FormulaNode(formula.GetLogicOperator());

            FormulaNode left  = Substitute(formula[0], from, to);
            FormulaNode right = null;

            if (formula[1] != null)
            {
                right = Substitute(formula[1], from, to);
            }
            res.SetChildren(left, right);
            return(res);
        }
        private void ComputeEUFragments(FormulaNode stateSet, SymbolicState state)
        {
            #if DEBUG
            Console.WriteLine("Compute fragments");
#endif
            foreach (var e in elementary)
            {
                if (e.GetLogicOperator() != LogicOperator.EX)
                {
                    continue;
                }
                if (e[0].GetLogicOperator() != LogicOperator.EU)
                {
                    continue;
                }
#if DEBUG
                Console.WriteLine("Computing fragment for " + e);
#endif
                FormulaNode frag = FormulaParser.Parse("~TRUE");
                while (true)
                {
                    string        nextName   = "succ" + uniqueId.GetTicket().ToString();
                    SymbolicState next       = new SymbolicState(elementary, nextName);
                    FormulaNode   transition = GenTransition(state, next);
                    FormulaNode   memberOf   = SymbolicState.Substitute(stateSet, state, next);
                    FormulaNode   nextFrag   = SymbolicState.Substitute(frag, state, next);
                    FormulaNode   newFrag    = new FormulaNode(LogicOperator.AND, transition, memberOf);
                    newFrag = new FormulaNode(LogicOperator.AND, newFrag, nextFrag);
                    newFrag = next.Quantify(LogicOperator.EXISTS, newFrag);

                    newFrag = new FormulaNode(LogicOperator.AND, state.ValueOf(e[0][0]), newFrag);
                    newFrag = new FormulaNode(LogicOperator.OR, state.ValueOf(e[0][1]), newFrag);

                    if (IsFixpoint(newFrag, frag, state))
                    {
                        break;
                    }

                    frag = newFrag;
                }
                fragEU[e[0]] = frag;
            }
        }
        /* Generate the transition relation R */
        private FormulaNode GenTransition(SymbolicState from, SymbolicState to)
        {
            List <FormulaNode> terms = new List <FormulaNode>();

            foreach (var e in elementary)
            {
                if (e.GetLogicOperator() != LogicOperator.EX)
                {
                    continue;
                }

                // if e = EX(g), generate the term "e(from) | ~g(to)"
                FormulaNode body    = e[0]; // the formula inside the EX
                FormulaNode notBody = CTLUtils.nnfNegate(body);
                FormulaNode left    = from.ValueOf(e);
                FormulaNode right   = to.ValueOf(notBody);
                terms.Add(new FormulaNode(LogicOperator.OR, left, right));
            }

            return(JoinTerms(LogicOperator.AND, terms));
        }
        public bool Check()
        {
            SymbolicState v = new SymbolicState(elementary, "v");

            // initially, all possible states belong to the structure
            FormulaNode states = new FormulaNode(FormulaNode.TRUE_LITERAL);
            FormulaNode oldStates;

            while (true)
            {
                iterations++;
#if DEBUG
                Console.WriteLine("Iteration " + iterations.ToString());
#endif
                oldStates = states;
                FormulaNode succ = GenSucc(states, v);
                FormulaNode lc1  = GenLC1(states, v);
                FormulaNode e    = GenE(states, v);
                FormulaNode a    = GenA(states, v);

                states = new FormulaNode(LogicOperator.AND, states, succ);
                states = new FormulaNode(LogicOperator.AND, states, lc1);
                states = new FormulaNode(LogicOperator.AND, states, e);
                states = new FormulaNode(LogicOperator.AND, states, a);
                if (IsFixpoint(oldStates, states, v))
                {
                    break;
                }
            }
#if DEBUG
            Console.WriteLine("Reached fixpoint. Checking for satisfying state");
#endif
            FormulaNode formulaValue    = v.ValueOf(normalized);
            FormulaNode formulaAndValid = new FormulaNode(LogicOperator.AND, states, formulaValue);
            FormulaNode sat             = v.Quantify(LogicOperator.EXISTS, formulaAndValid);
            return(FormulaCNF.QBFSAT(sat));
        }