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);
        }
예제 #2
0
        public static FormulaNode nnfNegate(FormulaNode formula)
        {
            FormulaNode result = new FormulaNode(LogicOperator.NOT);

            result.SetChildren(formula, null);
            return(result.NNF());
        }
        /* 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));
        }
예제 #4
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);
        }
예제 #5
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);
        }
예제 #6
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);
            }
        }
예제 #7
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);
        }
예제 #8
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);
        }
예제 #9
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);
        }
예제 #10
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);
        }
예제 #11
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);
        }