예제 #1
0
 public ImpliesProposition(ASTOpBinary ast) : base(ast)
 {
     if (ast.value != Language.Symbol.IMPLICA)
     {
         throw new Exception("An ImpliesProposition can only be created from an AST if this is a ASTOpBinary of type IMPLICA.");
     }
 }
예제 #2
0
            /// <summary>
            /// Formula extraction.
            /// </summary>
            /// <param name="branch">The current branch to extract from</param>
            private void Extract(AST branch = null)
            {
                if (m_formulas == null)
                {
                    m_formulas = new List <AST>();
                }
                AST current = branch != null ? branch : m_formula;

                switch (current.GetType().Name)
                {
                case "ASTProp":
                case "ASTOpUnary":
                    m_formulas.Add(current);
                    break;

                case "ASTOpBinary":
                    ASTOpBinary binOp = (ASTOpBinary)current;
                    switch (binOp.value)
                    {
                    case Language.Symbol.E:             // Extraction must continue.
                        Extract(binOp.left);
                        Extract(binOp.right);
                        break;

                    case Language.Symbol.OU:            // Already a disjuction. Extraction must return.
                        m_formulas.Add(current);
                        break;

                    default:                            // There should not be other symbols in an CNF formula.
                        break;
                    }
                    break;
                }
            }
예제 #3
0
 public EquivalentProposition(ASTOpBinary ast) : base(ast)
 {
     if (ast.value != Language.Symbol.EQUIVALE)
     {
         throw new Exception("An EquivalentProposition can only be created from an AST if this is a ASTOpBinary of type EQUIVALE.");
     }
 }
예제 #4
0
 public DisjunctiveProposition(ASTOpBinary ast) : base(ast)
 {
     if (ast.value != Language.Symbol.OU)
     {
         throw new Exception("A DisjunctiveProposition can only be created from an AST if this is a ASTOpBinary of type OU.");
     }
 }
예제 #5
0
        protected IEnumerable <Proposition> ConvertFromAST(AST ast, Language.Symbol oper)
        {
            if (ast == null)
            {
                return(null);
            }

            List <Proposition> result = new List <Proposition>();
            string             type   = ast.GetType().Name;

            if (type == "ASTOpBinary")
            {
                ASTOpBinary opBin = ast as ASTOpBinary;
                if (opBin.value == oper)
                {
                    result.AddRange(ConvertFromAST(opBin.left, oper));
                    result.AddRange(ConvertFromAST(opBin.right, oper));
                    return(result);
                }
            }

            // else
            result.Add(Proposition.FromAST(ast));
            return(result);
        }
예제 #6
0
        private static string StrPlain(AST ast, bool innerOR = false)
        {
            if (ast == null)
            {
                return("CLAÚSULA NULA");
            }

            switch (ast.GetType().Name)
            {
            case "ASTProp":
                return(((ASTProp)ast).value.ToString().ToLower());

            case "ASTOpUnary":
                return("(~" + StrPlain(((ASTOpUnary)ast).ast) + ")");

            case "ASTOpBinary":
                ASTOpBinary opBin  = (ASTOpBinary)ast;
                bool        nextOR = (opBin.value == Language.Symbol.OU);
                string      plain  =
                    StrPlain(opBin.left, nextOR) + " " +
                    opBin.value + " " +
                    StrPlain(opBin.right, nextOR);
                if (!innerOR)
                {
                    plain = "(" + plain + ")";
                }
                return(plain);
            } // switch

            return("");
        }
예제 #7
0
        public override bool Equals(object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return(false);
            }

            ASTOpBinary other = obj as ASTOpBinary;

            return
                (this.left.Equals(other.left) &&
                 this.right.Equals(other.right) &&
                 this.value == other.value
                );
        }
예제 #8
0
        /// <summary>
        /// Separates a formula in CNF in its OR components clauses.
        /// </summary>
        /// <param name="astInCnf">An AST in CNF form.</param>
        /// <returns>A enumerable of CnfOr clauses.</returns>
        public static IEnumerable <CnfOr> Separate(AST astInCnf, bool order = false)
        {
            if (astInCnf == null)
            {
                return(null);
            }

            List <CnfOr> result = new List <CnfOr>(1);

            switch (astInCnf.GetType().Name)
            {
            case "ASTProp":
            case "ASTOpUnary":
                result.Add(new CnfOr(astInCnf));
                break;

            case "ASTOpBinary":
                ASTOpBinary opBin = (ASTOpBinary)astInCnf;
                switch (opBin.value)
                {
                case Language.Symbol.OU:                // Form (A|B).
                    result.Add(new CnfOr(astInCnf));
                    break;

                case Language.Symbol.E:                 // Form (A&B).
                    result.AddRange(Separate(opBin.left));
                    result.AddRange(Separate(opBin.right));
                    break;

                case Language.Symbol.IMPLICA:          // Form (P->Q).
                case Language.Symbol.EQUIVALE:         // Form (P<->Q).
                    throw new System.Exception("AST in CNF separation failed. There can't be other binary operator beside & or | in a formula in CNF.");
                }
                break;
            }

            if (order)
            {
                result.Sort();
            }
            return(result);
        }
예제 #9
0
        private void Extract(AST astInCNF)
        {
            switch (astInCNF.GetType().Name)
            {
            case "ASTProp":
                char letter = (astInCNF as ASTProp).value;
                m_content.Add(new Component(letter));
                break;

            case "ASTOpUnary":
                ASTOpUnary astNeg = astInCNF as ASTOpUnary;
                if (astNeg.ast.GetType().Name != "ASTProp")
                {       // In CNF form, the negation can only refers to a simple proposition.
                    throw new Exception("Error creating a CnfOr : In CNF form, the negation can only refers to a simple proposition.");
                }
                letter = (astNeg.ast as ASTProp).value;
                m_content.Add(new Component(letter, true));
                break;

            case "ASTOpBinary":
                ASTOpBinary opBin = astInCNF as ASTOpBinary;
                switch (opBin.value)
                {
                case Language.Symbol.OU:                // Form (A|B).
                    Extract(opBin.left);
                    Extract(opBin.right);
                    break;

                case Language.Symbol.E:                // Form (A&B).
                case Language.Symbol.IMPLICA:          // Form (P->Q).
                case Language.Symbol.EQUIVALE:         // Form (P<->Q).
                    throw new Exception("Error creating a CnfOr : In CNF form, OR formulas can't contain other operators than OR.");
                }
                break;
            }
        }
예제 #10
0
        // Transitional function. Convert from AST.
        public static Proposition FromAST(AST ast)
        {
            switch (ast.GetType().Name)
            {
            case "ASTProp":
                return(new SingleProposition(ast as ASTProp));

            case "ASTOpUnary":
                return(new NegationProposition(ast as ASTOpUnary));

            case "ASTOpBinary":
                ASTOpBinary opBin = ast as ASTOpBinary;
                switch (opBin.value)
                {
                case Language.Symbol.E:
                    return(new ConjunctiveProposition(opBin));

                case Language.Symbol.OU:
                    return(new DisjunctiveProposition(opBin));

                case Language.Symbol.IMPLICA:
                    return(new ImpliesProposition(opBin));

                case Language.Symbol.EQUIVALE:
                    return(new EquivalentProposition(opBin));

                default:
                    throw new Exception(string.Format(
                                            "The operation {0} is not supported for conversion to Proposition",
                                            opBin.value
                                            ));
                }
            }

            return(null);
        }
예제 #11
0
        /// <summary>
        /// Parsing recursive implementation.
        /// </summary>
        /// <param name="precede">does precedence must be considered in this recursive call?</param>
        /// <returns>the resulting AST node.</returns>
        AST Walk(bool precede = false)
        {
            // Increment the global index.
            m_idx++;
            if (m_idx >= Tokens.Count)
            {
                return(null);
            }

            // Read the current index's token value.
            Token token = Tokens[m_idx];

            AST ast = null;

            switch (token.type)
            {
            case Language.Symbol.PROP:              // a propositional letter.
                ast = new ASTProp(token.value);
                break;

            case Language.Symbol.NAO:               // negation operation.
                ast = new ASTOpUnary(Walk(true), token.type);
                break;

            case Language.Symbol.E:                 // conjunction operation.
            case Language.Symbol.OU:                // disjunction operation.
                ast = new ASTOpBinary(m_current, Walk(true), token.type);
                break;

            case Language.Symbol.IMPLICA:      // implication operation.
            case Language.Symbol.EQUIVALE:     // double implication operation.
                // double implication has lesser precedence over single implication.
                bool bi = token.type == Language.Symbol.EQUIVALE;
                // must continue to parse?
                bool forward =                           // we continue parsing if...
                               m_implFlag == 0 ||        // ... there is no implications awaiting or ...
                               (m_implFlag == 2 && !bi); // ... a double implication awaits and the current is a single implication.
                if (forward)
                {                                        // must continue the parsing.
                        // save current implication flag value...
                    int implications = m_implFlag;
                    // and update the global value.
                    m_implFlag = bi ? 2 : 1;
                    // enter another recursion.
                    ast = new ASTOpBinary(m_current, Walk(false), token.type);
                    // did the last recursive call finished precedence analysis?
                    if (m_implFlag == 0)
                    {
                        precede = false;
                    }
                    // restore previous (saved) implication flag value.
                    m_implFlag = implications;
                }
                else
                {       // must not continue and must return to the last call.
                    m_idx--;
                    ast        = m_current;
                    precede    = true;
                    m_implFlag = 0;
                    break;
                }
                break;

            case Language.Symbol.ABERTURA:          // opening expression symbol.
                // enter a new recursive call, as an AST node must come from the parenthesis' content analysis.
                while (Walk(precede) != null)
                {
                    ast = m_current;
                }
                break;

            case Language.Symbol.FECHAMENTO:        // closing expression symbol.
                return(null);
            }

            // update current AST node.
            m_current = ast;

            // continue the processing as long as there are tokens and no precedence.
            if (!precede && m_idx < Tokens.Count)
            {
                Walk();
            }

            return(m_current);
        }
예제 #12
0
        }  // Extractor class

        #endregion Inner classes

        #region Public functions

        /// <summary>
        /// Convert the formula to conjuntive normal form.
        /// </summary>
        /// <param name="ast">original abstract syntatic tree representinf the formula.</param>
        /// <returns>formula in CNF.</returns>
        public static AST Convert(AST ast)
        {
            if (ast == null)
            {
                return(ast);
            }

            switch (ast.GetType().Name)
            {
            case "ASTProp":
                return(ast);

            case "ASTOpBinary":
                ASTOpBinary opBin = ast as ASTOpBinary;
                switch (opBin.value)
                {
                case Language.Symbol.E:                 // Form (P&Q).
                    AST left  = Convert(opBin.left);
                    AST right = Convert(opBin.right);
                    return(new ASTOpBinary(left, right, Language.Symbol.E));

                case Language.Symbol.OU:                // Form (P|Q).
                    left  = Convert(opBin.left);
                    right = Convert(opBin.right);
                    return(Distribute(left, right));

                case Language.Symbol.IMPLICA:           // Form (P->Q). Equivalent to (~P|Q)
                    return(Convert(
                               new ASTOpBinary(
                                   new ASTOpUnary(opBin.left, Language.Symbol.NAO),
                                   opBin.right, Language.Symbol.OU)
                               ));

                case Language.Symbol.EQUIVALE:         // Form (P<->Q). Equivalent to (P&Q)|(~P&~Q).
                    left  = new ASTOpBinary(opBin.left, opBin.right, Language.Symbol.E);
                    right = new ASTOpBinary(
                        new ASTOpUnary(opBin.left, Language.Symbol.NAO),
                        new ASTOpUnary(opBin.right, Language.Symbol.NAO),
                        Language.Symbol.E
                        );
                    return(Convert(new ASTOpBinary(left, right, Language.Symbol.OU)));
                }
                break;

            case "ASTOpUnary":
                AST p = (ast as ASTOpUnary).ast;
                switch (p.GetType().Name)
                {
                case "ASTProp":                 // Form ~P ... return ~P
                    return(ast);

                case "ASTOpUnary":              // Form ~(~P) - double negation ... return Convert(P)
                    return(Convert((p as ASTOpUnary).ast));

                case "ASTOpBinary":
                    opBin = (ASTOpBinary)p;
                    Language.Symbol op = opBin.value;
                    if (op != Language.Symbol.E && op != Language.Symbol.OU)
                    {         // Not yet in CNF.
                        AST pInNcf = Convert(p);
                        return(Convert(new ASTOpUnary(pInNcf, Language.Symbol.NAO)));
                    }
                    AST             left       = new ASTOpUnary(opBin.left, Language.Symbol.NAO);
                    AST             right      = new ASTOpUnary(opBin.right, Language.Symbol.NAO);
                    Language.Symbol deMorganOp = Language.Symbol.INVALIDO;
                    if (opBin.value == Language.Symbol.E)
                    {
                        // Form ~(P&Q): from DeMorgan's Law, return Convert(~P|~Q)
                        deMorganOp = Language.Symbol.OU;
                    }
                    else if (opBin.value == Language.Symbol.OU)
                    {
                        // Form ~(P|Q): from DeMorgan's Law, return Convert(~P&~Q)
                        deMorganOp = Language.Symbol.E;
                    }
                    return(Convert(new ASTOpBinary(left, right, deMorganOp)));
                }
                break;
            }

            return(null);
        }
예제 #13
0
 // transitional constructor
 public BinaryOperation(ASTOpBinary ast)
 {
     Left  = Proposition.FromAST(ast.left);
     Right = Proposition.FromAST(ast.right);
 }