/// <summary>
        /// Checks whether the expression is in NNF
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        bool IsNNF(BoolExpr node)
        {
            switch (node.Op)
            {
            case OperatorType.LEAF:
                return(true);

            case OperatorType.AND:
            case OperatorType.OR:
                return(IsNNF(node.Right) && IsNNF(node.Left));

            case OperatorType.NOT:
                return(node.Right.Op == OperatorType.LEAF);

            default:
                return(false);
            }
        }
        /// <summary>
        /// Converts expression to only use negation, conjunction, and disjunction operators
        /// </summary>
        /// <param name="node"></param>
        /// <param name="steps"></param>
        void ConvertOperators(ref BoolExpr node, IList <ConversionStep> steps)
        {
            if (node == null || node.Op == OperatorType.LEAF)
            {
                return;
            }

            if (Rewrite.Implication(ref node))
            {
                if (node.Parent == null)
                {
                    Root = node;
                }
                steps.Add(new ConversionStep(ToString(), "Implication"));
            }

            if (Rewrite.Equivalence(ref node))
            {
                if (node.Parent == null)
                {
                    Root = node;
                }
                steps.Add(new ConversionStep(ToString(), "Equivalence"));
            }

            if (Rewrite.XOR(ref node))
            {
                if (node.Parent == null)
                {
                    Root = node;
                }
                steps.Add(new ConversionStep(ToString(), "Xor"));
            }

            var right = node.Right;
            var left  = node.Left;

            ConvertOperators(ref left, steps);
            ConvertOperators(ref right, steps);
            node.Right = right;
            node.Left  = left;
        }
        /// <summary>
        /// Checks wheter the only operators used in the expression are the negation, disjunction, and conjunction operators
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        bool BasicOperators(BoolExpr node)
        {
            switch (node.Op)
            {
            case OperatorType.LEAF:
                return(true);

            case OperatorType.AND:
                return(BasicOperators(node.Right) && BasicOperators(node.Left));

            case OperatorType.OR:
                return(BasicOperators(node.Right) && BasicOperators(node.Left));

            case OperatorType.NOT:
                return(BasicOperators(node.Right));

            default:
                return(false);
            }
        }
        /// <summary>
        /// Converts the tree to CDNF
        /// </summary>
        /// <param name="variables"></param>
        /// <param name="reverse"></param>
        /// <returns></returns>
        public IList <ConversionStep> Evaluate(IEnumerable <string> variables, bool reverse = false)
        {
            BoolExpr root;
            var      steps = new ObservableCollection <ConversionStep>();

            steps.Add(new ConversionStep(ToString(), "Input"));

            if (!BasicOperators(Root))
            {
                root = Root;
                ConvertOperators(ref root, steps);
                Root = root;
            }
            Debug.Assert(BasicOperators(Root));

            if (!IsNNF(Root))
            {
                root = Root;
                ConvertToNNF(ref root, steps);
                Root = root;
            }
            Debug.Assert(IsNNF(Root));

            if (!IsDNF(Root))
            {
                root = Root;
                ConvertNNFtoDNF(ref root, steps);
                Root = root;
            }
            Debug.Assert(IsDNF(Root));

            // convert to DNFList
            var d = new DNFExpression(Root, variables);

            steps.Add(new ConversionStep(d.ToString(), "Association"));
            d.ConvertToCDNF(steps, reverse);
            return(steps);
        }
Beispiel #5
0
        public static BoolExpr CreateBinary(string op, BoolExpr left, BoolExpr right)
        {
            switch (op)
            {
            case "AND":
                return(new BoolExprConjunction(left, right));

            case "OR":
                return(new BoolExprDisjunction(left, right));

            case "CONDITIONAL":
                return(new BoolExprConditional(left, right));

            case "BICONDITIONAL":
                return(new BoolExprBiconditional(left, right));

            case "XOR":
                return(new BoolExprXOR(left, right));

            default:
                throw new Exception();
            }
        }
        /// <summary>
        /// Applies the distribution rule to an expression
        /// </summary>
        /// <param name="node"></param>
        /// <param name="steps"></param>
        void ApplyDistribution(ref BoolExpr node, IList <ConversionStep> steps)
        {
            if (node == null || node.Op == OperatorType.LEAF)
            {
                return;
            }

            // try to apply distribution
            if (Rewrite.Distribution(ref node))
            {
                if (node.Parent == null)
                {
                    Root = node;
                }
                steps.Add(new ConversionStep(ToString(), "Distribution"));
            }
            var right = node.Right;
            var left  = node.Left;

            ApplyDistribution(ref left, steps);
            ApplyDistribution(ref right, steps);
            node.Right = right;
            node.Left  = left;
        }
        /// <summary>
        /// Converts expression to negation normal form
        /// </summary>
        /// <param name="node"></param>
        /// <param name="steps"></param>
        void ConvertToNNF(ref BoolExpr node, IList <ConversionStep> steps)
        {
            if (node == null || node.Op == OperatorType.LEAF)
            {
                return;
            }

            // try to apply DN as many times as possible
            while (Rewrite.DN(ref node))
            {
                if (node.Parent == null)
                {
                    Root = node;
                }
                steps.Add(new ConversionStep(ToString(), "Double Negation"));
            }

            // try to apply DeM
            if (Rewrite.DeM(ref node))
            {
                if (node.Parent == null)
                {
                    Root = node;
                }
                steps.Add(new ConversionStep(ToString(), "DeMorgan's"));
            }


            var right = node.Right;
            var left  = node.Left;

            ConvertToNNF(ref left, steps);
            ConvertToNNF(ref right, steps);
            node.Right = right;
            node.Left  = left;
        }
Beispiel #8
0
 public BoolExprXOR(BoolExpr left, BoolExpr right) : base(OperatorType.XOR, left, right)
 {
     Lit = LogicalSymbols.XOr.ToString();
 }
Beispiel #9
0
 public BoolExprBiconditional(BoolExpr left, BoolExpr right) : base(OperatorType.BICONDITIONAL, left, right)
 {
     Lit = LogicalSymbols.Biconditional.ToString();
 }
Beispiel #10
0
 public BoolExprDisjunction(BoolExpr left, BoolExpr right) : base(OperatorType.OR, left, right)
 {
     Lit = LogicalSymbols.Or.ToString();
 }
Beispiel #11
0
 public BoolExprConjunction(BoolExpr left, BoolExpr right) : base(OperatorType.AND, left, right)
 {
     Lit = LogicalSymbols.And.ToString();
 }
Beispiel #12
0
 public BoolExprNegation(BoolExpr child) : base(OperatorType.NOT, null, child)
 {
 }
Beispiel #13
0
 public BoolExprBinary(OperatorType op, BoolExpr left, BoolExpr right) : base(op, left, right)
 {
 }
Beispiel #14
0
 public static BoolExpr CreateNot(BoolExpr child) => new BoolExprNegation(child);