Пример #1
0
        public static void RunFormula(string formula)
        {
            FormulaNode parsedFormula = null;

            PrintLine();
            Console.WriteLine("formula: " + formula);

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                parsedFormula = FormulaParser.Parse(formula);
            } catch (Exception e)
            {
                Console.WriteLine("Parsing error: " + e.Message);
                return;
            }
            CTLSatisfiabilityChecker checker = new CTLSatisfiabilityChecker(parsedFormula);
            bool res = checker.Check();

            stopwatch.Stop();
            double time = ((double)stopwatch.ElapsedMilliseconds / 1000.0);

            Console.WriteLine("iterations: " + checker.Iterations);
            Console.WriteLine("time: " + time);
            Console.WriteLine("result: " + ConvSAT(res));

            PrintLine();
        }
        /* 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));
        }
        public static FormulaNode JoinTerms(LogicOperator op, List <FormulaNode> terms)
        {
            FormulaNode result;

            if (terms.Count == 0)
            {
                if (op == LogicOperator.AND)
                {
                    return(new FormulaNode(FormulaNode.TRUE_LITERAL));
                }
                if (op == LogicOperator.OR)
                {
                    // Build FALSE as ~TRUE
                    result = new FormulaNode(LogicOperator.NOT);
                    result.SetChildren(new FormulaNode(FormulaNode.TRUE_LITERAL), null);
                    return(result);
                }

                throw new Exception("Join with unsupported logic operator");
            }


            if (terms.Count == 1)
            {
                return(terms[0]);
            }

            result = new FormulaNode(op, terms[0], terms[1]);
            foreach (var t in terms.GetRange(2, terms.Count - 2))
            {
                result = new FormulaNode(op, result, t);
            }

            return(result);
        }
        /* 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));
        }
Пример #5
0
        public static FormulaNode nnfNegate(FormulaNode formula)
        {
            FormulaNode result = new FormulaNode(LogicOperator.NOT);

            result.SetChildren(formula, null);
            return(result.NNF());
        }
        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));
        }
        /* 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;
            }
        }
Пример #9
0
        // We assume that the formula is in QBF
        // (But no other assumption)
        public static bool QBFSAT(FormulaNode formula)
        {
            // First convert the formula to PNF
            formula = formula.NNF().PNF();
            // Then convert it to QBCNF
            QBCNFormula qbcnf = ConvertToCNF(formula);

            return(QBFSolver.Solve(qbcnf));
        }
Пример #10
0
        /* 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);
        }
Пример #11
0
        public FormulaNode Quantify(LogicOperator quantifier, FormulaNode formula)
        {
            FormulaNode result = formula;

            foreach (string name in elementaryNames.Values)
            {
                result = new FormulaNode(quantifier, result, null);
                result.SetName(name);
            }
            return(result);
        }
Пример #12
0
        // For a PNF formula, return the non-quanitifed part
        public FormulaNode GetPropositional()
        {
            FormulaNode res = this;

            while (res.logicOp == LogicOperator.EXISTS ||
                   res.logicOp == LogicOperator.ALL)
            {
                res = res.childNodes[0];
            }

            return(res);
        }
Пример #13
0
        public static FormulaNode CreateTestFormula()
        {
            FormulaNode result = new FormulaNode(LogicOperator.EX);

            result.SetChildren(null, new FormulaNode("b"));

            result = new FormulaNode(LogicOperator.EU);
            FormulaNode a = new FormulaNode(LogicOperator.AG);

            a.SetChildren(new FormulaNode("p"), null);

            result.SetChildren(a, new FormulaNode("q"));
            return(result);
        }
Пример #14
0
        public static ISet <FormulaNode> positiveElementary(FormulaNode formula)
        {
            ISet <FormulaNode>    allElementary = elementaryFormulas(formula);
            HashSet <FormulaNode> result        = new HashSet <FormulaNode>();

            foreach (var f in allElementary)
            {
                if (f.GetLogicOperator() == LogicOperator.VAR ||
                    f.GetLogicOperator() == LogicOperator.EX)
                {
                    result.Add(f);
                }
            }
            return(result);
        }
Пример #15
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);
        }
Пример #16
0
        // replace ->, AF, AG, EF and EG with simpler operators
        public FormulaNode ImplementComplexOperators()
        {
            FormulaNode leftChild    = null;
            FormulaNode rightChild   = null;
            FormulaNode trueFormula  = new FormulaNode(TRUE_LITERAL);
            FormulaNode falseFormula = new FormulaNode(LogicOperator.NOT, trueFormula, null);
            FormulaNode result;

            if (this[0] != null)
            {
                leftChild = this[0].ImplementComplexOperators();
            }
            if (this[1] != null)
            {
                rightChild = this[1].ImplementComplexOperators();
            }
            switch (logicOp)
            {
            // (a -> b) is (~a | b)
            case LogicOperator.IMP:
                FormulaNode left = new FormulaNode(LogicOperator.NOT, leftChild, null);
                return(new FormulaNode(LogicOperator.OR, left, rightChild));

            // EF(f) is EU(TRUE, f)
            case LogicOperator.EF:
                return(new FormulaNode(LogicOperator.EU, trueFormula, leftChild));

            // EG(f) is ER(FALSE, f)
            case LogicOperator.EG:
                return(new FormulaNode(LogicOperator.ER, falseFormula, leftChild));

            // AF(f) is AU(TRUE, f)
            case LogicOperator.AF:
                return(new FormulaNode(LogicOperator.AU, trueFormula, leftChild));

            // AG(f) is AU(FALSE, f)
            case LogicOperator.AG:
                return(new FormulaNode(LogicOperator.AR, falseFormula, leftChild));

            default:
                result = new FormulaNode(logicOp, name);
                result.SetChildren(leftChild, rightChild);
                return(result);
            }
        }
Пример #17
0
        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;
            }
        }
Пример #18
0
        // For a node subformula, assign a number n and return the block
        // xn <-> l op r
        private static TseytinBlock GetTseytinBlocks(FormulaNode node,
                                                     ISet <TseytinBlock> blockSet)
        {
            if (node.GetLogicOperator() == LogicOperator.VAR)
            {
                return(null);
            }

            int    ticket = ticketMachine.GetTicket();
            string left = "", right = "";

            TseytinBlock temp;

            temp = GetTseytinBlocks(node[0], blockSet);
            if (temp == null)
            {
                left = node[0].GetName();
            }
            else
            {
                left = temp.ticket.ToString();
            }

            if (node[1] != null)
            {
                temp = GetTseytinBlocks(node[1], blockSet);
                if (temp == null)
                {
                    right = node[1].GetName();
                }
                else
                {
                    right = temp.ticket.ToString();
                }
            }

            TseytinBlock res = new TseytinBlock(ticket, left, right, node.GetLogicOperator());

            blockSet.Add(res);

            return(res);
        }
Пример #19
0
        // Get a propositional formula and return its (raw) CNF form
        // addedVars: the names of the new variables introduced by the transformation
        private static ISet <ISet <string> > TseytinTransformation(FormulaNode formula, out ISet <string> addedVars)
        {
            ISet <ISet <string> > res      = new HashSet <ISet <string> >();
            ISet <TseytinBlock>   blockSet = new HashSet <TseytinBlock>();

            ticketMachine.Reset();
            TseytinBlock top = GetTseytinBlocks(formula, blockSet);

            if (top == null)
            {
                // The formula is simply a variable - no Tseitin blocks required
                res.Add(new HashSet <string> {
                    formula.GetName()
                });
            }
            else
            {
                // Create a conjunction of all Tseitin blocks
                foreach (TseytinBlock block in blockSet)
                {
                    res.UnionWith(TseytinBlockToCNF(block));
                }

                // Add the requirement that the topmost formula is true
                ISet <string> topClause = new HashSet <string>();
                topClause.Add(top.ticket.ToString());
                res.Add(topClause);
            }

            addedVars = new HashSet <string>();
            foreach (TseytinBlock block in blockSet)
            {
                addedVars.Add(block.ticket.ToString());
            }

            // Force the TRUE variable to true
            res.Add(new HashSet <string> {
                FormulaNode.TRUE_LITERAL
            });

            return(res);
        }
Пример #20
0
        /* 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));
        }
Пример #21
0
        private static void AssertSat(string formulaString, bool expected)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(timelimit), () =>
            {
                FormulaNode formula = FormulaParser.Parse(formulaString);
                Console.WriteLine("\nTEST: " + formulaString);
                var checker = new CTLSatisfiabilityChecker(formula);
                bool result = checker.Check();
                Console.WriteLine("Done");
                if (result != expected)
                {
                    throw new Exception("Wrong SAT value for " + formulaString);
                }
            });

            stopwatch.Stop();
            double time = (double)stopwatch.ElapsedMilliseconds / 1000.0;

            Console.WriteLine("TIME: " + time);
        }
Пример #22
0
        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));
        }
Пример #23
0
        // Change f[x] to f[x/x']
        public FormulaNode Substitute(string original, string replacement)
        {
            if (this.logicOp == LogicOperator.VAR)
            {
                if (this.name == original)
                {
                    return(new FormulaNode(replacement));
                }
                else
                {
                    return(new FormulaNode(this.name));
                }
            }

            FormulaNode res = new FormulaNode(this.logicOp, this.name);

            if ((this.logicOp == LogicOperator.EXISTS ||
                 this.logicOp == LogicOperator.ALL) &&
                (this.name == original))
            {
                res.name = replacement;
            }

            FormulaNode left = null, right = null;

            if (this.childNodes[0] != null)
            {
                left = this.childNodes[0].Substitute(original, replacement);
            }
            if (this.childNodes[1] != null)
            {
                right = this.childNodes[1].Substitute(original, replacement);
            }
            res.SetChildren(left, right);
            return(res);
        }
Пример #24
0
 public void SetChildren(FormulaNode left, FormulaNode right)
 {
     this.childNodes[0] = left;
     this.childNodes[1] = right;
     this.variableSet   = null;
 }
Пример #25
0
        // Get a PNF formula and return its QBCNF
        public static QBCNFormula ConvertToCNF(FormulaNode formula)
        {
            QBCNFormula   res  = new QBCNFormula();
            FormulaNode   node = formula;
            ISet <string> addedVars;

            res.quantifiers = new List <string>();
            while (node.GetLogicOperator() == LogicOperator.EXISTS ||
                   node.GetLogicOperator() == LogicOperator.ALL)
            {
                if (node.GetLogicOperator() == LogicOperator.EXISTS)
                {
                    res.quantifiers.Add("e" + node.GetName());
                }
                else
                {
                    res.quantifiers.Add("a" + node.GetName());
                }
                node = node[0];
            }

            if (res.quantifiers.Count != formula.GetVariables().Count)
            {
                throw new Exception("Non-quantified variables in formula!");
            }

            res.propositional = TseytinTransformation(node, out addedVars);

            //Replace strings with numbers
            ISet <string> literals = res.GetLiterals();
            Dictionary <string, string> changes = new Dictionary <string, string>();

            foreach (string literal in literals)
            {
                int  n;
                bool isNum = int.TryParse(literal, out n);
                if (!changes.ContainsKey(literal) & !isNum)
                {
                    int ticket = ticketMachine.GetTicket();
                    if (literal[0] != '-')
                    {
                        changes.Add(literal, ticket.ToString());
                        changes.Add("-" + literal, (-ticket).ToString());
                    }
                    else
                    {
                        changes.Add(literal, (-ticket).ToString());
                        changes.Add(literal.Substring(1), ticket.ToString());
                    }
                }
            }

            res.ReplaceLiterals(changes);

            // Quantify the Tseytin variables with EXISTS
            foreach (string var in addedVars)
            {
                res.quantifiers.Add("e" + var);
            }

            return(res);
        }
Пример #26
0
        private static FormulaNode Parse(List <Token> tokens)
        {
            FormulaNode  result    = null;
            List <Token> rightSide = new List <Token>();
            BinaryToken  lastOp    = null;

            // the input is a single token - must be an atom or an unparsed string
            if (tokens.Count == 1)
            {
                var tok = tokens[0] as LiteralToken;
                if (tok.type == TokenType.ATOM)
                {
                    return(new FormulaNode(tok.value));
                }

                return(Parse(ToplevelTokenize(tok.value)));
            }

            int minPrecedence = MAX_PRECEDENCE;

            for (int i = 0; i < tokens.Count; i++)
            {
                if (tokens[i] is BinaryToken)
                {
                    var op = tokens[i] as BinaryToken;
                    minPrecedence = Math.Min(minPrecedence, op.precedence);
                }
            }

            if (minPrecedence == MAX_PRECEDENCE)
            {
                // the input didn't contain any toplevel binary operators
                var opToken = tokens[0] as UnaryToken;
                result = new FormulaNode(opToken.logicOperator);
                var operand = Parse(tokens.GetRange(1, tokens.Count - 1));
                if (untilOperators.Contains(opToken.logicOperator))
                {
                    result.SetChildren(operand[0], operand[1]);
                }
                else if (quanitifers.Contains(opToken.logicOperator))
                {
                    result.SetName(operand[0].GetName());
                    result.SetChildren(operand[1], null);
                }
                else
                {
                    result.SetChildren(operand, null);
                }
                return(result);
            }

            // if we got here - split by lowest-precedence binary operator
            foreach (Token t in tokens)
            {
                if (t is BinaryToken)
                {
                    var op = t as BinaryToken;
                    if (op.precedence == minPrecedence)
                    {
                        if (result == null)
                        {
                            result = Parse(rightSide);
                        }
                        else
                        {
                            var leftSide = result;
                            result = new FormulaNode(lastOp.logicOperator);
                            result.SetChildren(leftSide, Parse(rightSide));
                        }
                        rightSide = new List <Token>();
                        lastOp    = op;
                        continue;
                    }
                }
                rightSide.Add(t);
            }
            if (rightSide.Count != 0)
            {
                var leftSide = result;
                result = new FormulaNode(lastOp.logicOperator);
                result.SetChildren(leftSide, Parse(rightSide));
            }

            return(result);
        }
Пример #27
0
        // Transfer the node to NNF
        public FormulaNode NNF()
        {
            if (this.logicOp == LogicOperator.VAR)
            {
                return(new FormulaNode(this.name));
            }

            FormulaNode res = null, left = null, right = null;

            if (this.logicOp != LogicOperator.NOT)
            {
                res = new FormulaNode(this.logicOp, this.name);
                if (this.childNodes[0] != null)
                {
                    left = this.childNodes[0].NNF();
                }
                if (this.childNodes[1] != null)
                {
                    right = this.childNodes[1].NNF();
                }
                res.SetChildren(left, right);
                return(res);
            }

            // If we reached here, our node is "~" and hence we should
            // rearrange the formula tree
            // We note that a "~" should be unary and hence it only
            // has a left child

            switch (this.childNodes[0].logicOp)
            {
            case LogicOperator.EXISTS:
                res = new FormulaNode(LogicOperator.ALL, this.childNodes[0].name);
                break;

            case LogicOperator.ALL:
                res = new FormulaNode(LogicOperator.EXISTS, this.childNodes[0].name);
                break;

            case LogicOperator.AND:
                res = new FormulaNode(LogicOperator.OR);
                break;

            case LogicOperator.OR:
                res = new FormulaNode(LogicOperator.AND);
                break;

            case LogicOperator.NOT:
                return(this.childNodes[0].childNodes[0].NNF());

            case LogicOperator.IMP:
                // ~(a->b) == a & ~b
                res   = new FormulaNode(LogicOperator.AND);
                left  = this.childNodes[0].childNodes[0].NNF();
                right = new FormulaNode(LogicOperator.NOT);
                right.SetChildren(this.childNodes[0].childNodes[1].NNF(), null);
                res.SetChildren(left, right.NNF());
                return(res);

            case LogicOperator.EF:
                res = new FormulaNode(LogicOperator.AG);
                break;

            case LogicOperator.AF:
                res = new FormulaNode(LogicOperator.EG);
                break;

            case LogicOperator.EG:
                res = new FormulaNode(LogicOperator.AF);
                break;

            case LogicOperator.AG:
                res = new FormulaNode(LogicOperator.EF);
                break;

            case LogicOperator.AX:
                res = new FormulaNode(LogicOperator.EX);
                break;

            case LogicOperator.EX:
                res = new FormulaNode(LogicOperator.AX);
                break;

            case LogicOperator.EU:
                res = new FormulaNode(LogicOperator.AR);
                break;

            case LogicOperator.AU:
                res = new FormulaNode(LogicOperator.ER);
                break;

            case LogicOperator.ER:
                res = new FormulaNode(LogicOperator.AU);
                break;

            case LogicOperator.AR:
                res = new FormulaNode(LogicOperator.EU);
                break;

            case LogicOperator.VAR:
                res = new FormulaNode(LogicOperator.NOT);
                res.SetChildren(new FormulaNode(this.childNodes[0].name), null);
                return(res);

            default:
                res = null;
                break;
            }

            if (this.childNodes[0].childNodes[0] != null)
            {
                left = new FormulaNode(LogicOperator.NOT);
                left.SetChildren(this.childNodes[0].childNodes[0].NNF(), null);
                left = left.NNF();
            }
            if (this.childNodes[0].childNodes[1] != null)
            {
                right = new FormulaNode(LogicOperator.NOT);
                right.SetChildren(this.childNodes[0].childNodes[1].NNF(), null);
                right = right.NNF();
            }
            res.SetChildren(left, right);

            return(res);
        }
Пример #28
0
        /* Assumes the formula is in NNF form */
        public static ISet <FormulaNode> elementaryFormulas(FormulaNode formula)
        {
            HashSet <FormulaNode> result = new HashSet <FormulaNode>();

            switch (formula.GetLogicOperator())
            {
            case LogicOperator.AU:
            case LogicOperator.AR:
                // AX(f) is elementary
                FormulaNode ax_f = new FormulaNode(LogicOperator.AX);
                ax_f.SetChildren(formula, null);
                result.Add(ax_f);
                result.Add(nnfNegate(ax_f));
                result.UnionWith(elementaryFormulas(formula[0]));
                result.UnionWith(elementaryFormulas(formula[1]));
                break;

            case LogicOperator.EU:
            case LogicOperator.ER:
                // EX(f) is elementary
                FormulaNode ex_f = new FormulaNode(LogicOperator.EX);
                ex_f.SetChildren(formula, null);
                result.Add(ex_f);
                result.Add(nnfNegate(ex_f));
                result.UnionWith(elementaryFormulas(formula[0]));
                result.UnionWith(elementaryFormulas(formula[1]));
                break;

            case LogicOperator.EX:
            case LogicOperator.AX:
                // the formula itself is elementary
                result.Add(formula);
                result.Add(nnfNegate(formula));
                result.UnionWith(elementaryFormulas(formula[0]));
                break;

            case LogicOperator.OR:
            case LogicOperator.AND:
                result.UnionWith(elementaryFormulas(formula[0]));
                result.UnionWith(elementaryFormulas(formula[1]));
                break;

            case LogicOperator.NOT:
                Debug.Assert(formula[0].GetLogicOperator() == LogicOperator.VAR,
                             "Input to elementaryFormulas must be in NNF form");
                result.UnionWith(elementaryFormulas(formula[0]));
                break;

            case LogicOperator.VAR:
                if (formula.GetName() != FormulaNode.TRUE_LITERAL)
                {
                    result.Add(formula);
                    result.Add(nnfNegate(formula));
                }
                break;

            default:
                throw new Exception("Not implemented");
            }
            return(result);
        }
Пример #29
0
 public FormulaNode(LogicOperator logicOp, FormulaNode left, FormulaNode right)
 {
     this.logicOp  = logicOp;
     childNodes[0] = left;
     childNodes[1] = right;
 }
Пример #30
0
        // Trnasfer the node to PNF (the formula is assumed to be in NNF)
        // We assume that the formula also has no temporal operators
        public FormulaNode PNF()
        {
            if (this.logicOp == LogicOperator.VAR)
            {
                return(new FormulaNode(this.name));
            }

            FormulaNode   res = null, left = null, right = null;
            ISet <string> leftSet, rightSet;
            string        varname;

            if (this.logicOp == LogicOperator.NOT)
            {
                res = new FormulaNode(LogicOperator.NOT);
                res.SetChildren(new FormulaNode(this.childNodes[0].name), null);
                return(res);
            }

            if (this.logicOp == LogicOperator.EXISTS ||
                this.logicOp == LogicOperator.ALL)
            {
                res = new FormulaNode(this.logicOp, this.name);
                res.SetChildren(this.childNodes[0].PNF(), null);
                return(res);
            }

            // Since we assume NNF, all NOT nodes are next to variables
            // Thus all of the remaining operators are binary
            left  = this.childNodes[0].PNF();
            right = this.childNodes[1].PNF();

            leftSet  = left.GetVariables();
            rightSet = right.GetVariables();

            if (this.logicOp == LogicOperator.AND ||
                this.logicOp == LogicOperator.OR)
            {
                FormulaNode temp;
                if (left.logicOp == LogicOperator.EXISTS ||
                    left.logicOp == LogicOperator.ALL)
                {
                    if (rightSet.Contains(left.name))
                    {
                        varname = UniquePNFVariable();
                        left    = left.Substitute(left.name, varname);
                    }

                    res  = new FormulaNode(left.logicOp, left.name);
                    temp = new FormulaNode(this.logicOp);
                    temp.SetChildren(left.childNodes[0], right);
                    res.SetChildren(temp.PNF(), null);
                }
                else if (right.logicOp == LogicOperator.EXISTS ||
                         right.logicOp == LogicOperator.ALL)
                {
                    if (leftSet.Contains(right.name))
                    {
                        varname = UniquePNFVariable();
                        right   = right.Substitute(right.name, varname);
                    }

                    res  = new FormulaNode(right.logicOp, right.name);
                    temp = new FormulaNode(this.logicOp);
                    temp.SetChildren(left, right.childNodes[0]);
                    res.SetChildren(temp.PNF(), null);
                }
                else
                {
                    res = new FormulaNode(this.logicOp);
                    res.SetChildren(left, right);
                }
            }

            // For convenience, we get rid of "->" operators
            if (this.logicOp == LogicOperator.IMP)
            {
                res = new FormulaNode(LogicOperator.OR);
                res.SetChildren(new FormulaNode(LogicOperator.NOT), right);
                res.childNodes[0].SetChildren(left, null);
                res = res.NNF().PNF();
            }

            return(res);
        }