Exemplo n.º 1
0
        // Artificial Intelligence A Modern Approach (2nd Edition): page 288.
        // COMPOSE(delta, tau) is the substitution whose effect is identical to
        // the effect of applying each substitution in turn. That is,
        // SUBST(COMPOSE(theta1, theta2), p) = SUBST(theta2, SUBST(theta1, p))
        private Dictionary <Variable, Term> compose(FOLKnowledgeBase KB,
                                                    Dictionary <Variable, Term> theta1, Dictionary <Variable, Term> theta2)
        {
            Dictionary <Variable, Term> composed = new Dictionary <Variable, Term>();

            // So that it behaves like:
            // SUBST(theta2, SUBST(theta1, p))
            // There are two steps involved here.
            // See: http://logic.stanford.edu/classes/cs157/2008/notes/chap09.pdf
            // for a detailed discussion:

            // 1. Apply theta2 to the range of theta1.
            foreach (Variable v in theta1.Keys)
            {
                composed.Add(v, KB.subst(theta2, theta1[v]));
            }

            // 2. Adjoin to delta all pairs from tau with different
            // domain variables.
            foreach (Variable v in theta2.Keys)
            {
                if (!theta1.ContainsKey(v))
                {
                    composed.Add(v, theta2[v]);
                }
            }

            return(cascadeSubstitutions(KB, composed));
        }
Exemplo n.º 2
0
        // Artificial Intelligence A Modern Approach (2nd Edition): page 288.
        // COMPOSE(delta, tau) is the substitution whose effect is identical to
        // the effect of applying each substitution in turn. That is,
        // SUBST(COMPOSE(theta1, theta2), p) = SUBST(theta2, SUBST(theta1, p))
        private IMap <Variable, Term> compose(FOLKnowledgeBase KB, IMap <Variable, Term> theta1, IMap <Variable, Term> theta2)
        {
            IMap <Variable, Term> composed = CollectionFactory.CreateInsertionOrderedMap <Variable, Term>();

            // So that it behaves like:
            // SUBST(theta2, SUBST(theta1, p))
            // There are two steps involved here.
            // See: http://logic.stanford.edu/classes/cs157/2008/notes/chap09.pdf
            // for a detailed discussion:

            // 1. Apply theta2 to the range of theta1.
            foreach (Variable v in theta1.GetKeys())
            {
                composed.Put(v, KB.subst(theta2, theta1.Get(v)));
            }

            // 2. Adjoin to delta all pairs from tau with different
            // domain variables.
            foreach (Variable v in theta2.GetKeys())
            {
                if (!theta1.ContainsKey(v))
                {
                    composed.Put(v, theta2.Get(v));
                }
            }

            return(cascadeSubstitutions(KB, composed));
        }
Exemplo n.º 3
0
        // See:
        // http://logic.stanford.edu/classes/cs157/2008/miscellaneous/faq.html#jump165
        // for need for this.
        private Dictionary <Variable, Term> cascadeSubstitutions(FOLKnowledgeBase KB,
                                                                 Dictionary <Variable, Term> theta)
        {
            foreach (Variable v in theta.Keys)
            {
                Term t = theta[v];
                theta.Add(v, KB.subst(theta, t));
            }

            return(theta);
        }
Exemplo n.º 4
0
        // See:
        // http://logic.stanford.edu/classes/cs157/2008/miscellaneous/faq.html#jump165
        // for need for this.
        private IMap <Variable, Term> cascadeSubstitutions(FOLKnowledgeBase KB,
                                                           IMap <Variable, Term> theta)
        {
            foreach (Variable v in theta.GetKeys())
            {
                Term t = theta.Get(v);
                theta.Put(v, KB.subst(theta, t));
            }

            return(theta);
        }
Exemplo n.º 5
0
        // See:
        // http://logic.stanford.edu/classes/cs157/2008/miscellaneous/faq.html#jump165
        // for need for this.
        private Dictionary <Variable, Term> cascadeSubstitutions(FOLKnowledgeBase KB,
                                                                 Dictionary <Variable, Term> theta)
        {
            var keys = theta.Keys.ToList();

            foreach (Variable v in keys)
            {
                theta[v] = KB.subst(theta, theta[v]);
            }

            return(theta);
        }
Exemplo n.º 6
0
        // END-InferenceProcedure
        //

        //
        // PRIVATE METHODS
        //

        /**
         * <code>
         * function FOL-BC-ASK(KB, goals, theta) returns a set of substitutions
         *   input: KB, a knowledge base
         *          goals, a list of conjuncts forming a query (theta already applied)
         *          theta, the current substitution, initially the empty substitution {}
         * </code>
         */
        private List <List <ProofStepBwChGoal> > folbcask(FOLKnowledgeBase KB,
                                                          BCAskAnswerHandler ansHandler, List <Literal> goals,
                                                          Dictionary <Variable, Term> theta)
        {
            List <List <ProofStepBwChGoal> > thisLevelProofSteps = new List <List <ProofStepBwChGoal> >();

            // local variables: answers, a set of substitutions, initially empty

            // if goals is empty then return {theta}
            if (goals.Count == 0)
            {
                thisLevelProofSteps.Add(new List <ProofStepBwChGoal>());
                return(thisLevelProofSteps);
            }

            // qDelta <- SUBST(theta, FIRST(goals))
            Literal qDelta = KB.subst(theta, goals[0]);

            // for each sentence r in KB where
            // STANDARDIZE-APART(r) = (p1 ^ ... ^ pn => q)
            foreach (Clause r in KB.getAllDefiniteClauses())
            {
                Clause r2 = KB.standardizeApart(r);
                // and thetaDelta <- UNIFY(q, qDelta) succeeds
                Dictionary <Variable, Term> thetaDelta = KB.unify(r2.getPositiveLiterals()
                                                                  [0].getAtomicSentence(), qDelta.getAtomicSentence());
                if (null != thetaDelta)
                {
                    // new_goals <- [p1,...,pn|REST(goals)]
                    List <Literal> newGoals = new List <Literal>(r2
                                                                 .getNegativeLiterals());
                    newGoals.AddRange(goals.Skip(1));
                    // answers <- FOL-BC-ASK(KB, new_goals, COMPOSE(thetaDelta,
                    // theta)) U answers
                    Dictionary <Variable, Term>      composed             = compose(KB, thetaDelta, theta);
                    List <List <ProofStepBwChGoal> > lowerLevelProofSteps = folbcask(
                        KB, ansHandler, newGoals, composed);

                    ansHandler.addProofStep(lowerLevelProofSteps, r2, qDelta,
                                            composed);

                    thisLevelProofSteps.AddRange(lowerLevelProofSteps);
                }
            }

            // return answers
            return(thisLevelProofSteps);
        }
Exemplo n.º 7
0
        /**
         * <code>
         * function FOL-BC-ASK(KB, goals, theta) returns a set of substitutions
         *   input: KB, a knowledge base
         *          goals, a list of conjuncts forming a query (theta already applied)
         *          theta, the current substitution, initially the empty substitution {}
         * </code>
         */
        private ICollection <ICollection <ProofStepBwChGoal> > folbcask(FOLKnowledgeBase KB,
                                                                        BCAskAnswerHandler ansHandler, ICollection <Literal> goals,
                                                                        IMap <Variable, Term> theta)
        {
            ICollection <ICollection <ProofStepBwChGoal> > thisLevelProofSteps = CollectionFactory.CreateQueue <ICollection <ProofStepBwChGoal> >();

            // local variables: answers, a set of substitutions, initially empty

            // if goals is empty then return {theta}
            if (goals.IsEmpty())
            {
                thisLevelProofSteps.Add(CollectionFactory.CreateQueue <ProofStepBwChGoal>());
                return(thisLevelProofSteps);
            }

            // qDelta <- SUBST(theta, FIRST(goals))
            Literal qDelta = KB.subst(theta, goals.Get(0));

            // for each sentence r in KB where
            // STANDARDIZE-APART(r) = (p1 ^ ... ^ pn => q)
            foreach (Clause rIter in KB.getAllDefiniteClauses())
            {
                Clause r = rIter;
                r = KB.standardizeApart(r);
                // and thetaDelta <- UNIFY(q, qDelta) succeeds
                IMap <Variable, Term> thetaDelta = KB.unify(r.getPositiveLiterals()
                                                            .Get(0).getAtomicSentence(), qDelta.getAtomicSentence());
                if (null != thetaDelta)
                {
                    // new_goals <- [p1,...,pn|REST(goals)]
                    ICollection <Literal> newGoals = CollectionFactory.CreateQueue <Literal>(r.getNegativeLiterals());
                    newGoals.AddAll(goals.subList(1, goals.Size()));
                    // answers <- FOL-BC-ASK(KB, new_goals, COMPOSE(thetaDelta,
                    // theta)) U answers
                    IMap <Variable, Term> composed = compose(KB, thetaDelta, theta);
                    ICollection <ICollection <ProofStepBwChGoal> > lowerLevelProofSteps = folbcask(
                        KB, ansHandler, newGoals, composed);

                    ansHandler.addProofStep(lowerLevelProofSteps, r, qDelta, composed);

                    thisLevelProofSteps.AddAll(lowerLevelProofSteps);
                }
            }

            // return answers
            return(thisLevelProofSteps);
        }
Exemplo n.º 8
0
        // START-InferenceProcedure

        /**
         * <code>
         * function FOL-FC-ASK(KB, alpha) returns a substitution or false
         *   inputs: KB, the knowledge base, a set of first order definite clauses
         *           alpha, the query, an atomic sentence
         * </code>
         */
        public InferenceResult ask(FOLKnowledgeBase KB, Sentence query)
        {
            // Assertions on the type of queries this Inference procedure
            // supports
            if (!(query is AtomicSentence))
            {
                throw new ArgumentException(
                          "Only Atomic Queries are supported.");
            }

            FCAskAnswerHandler ansHandler = new FCAskAnswerHandler();

            Literal alpha = new Literal((AtomicSentence)query);

            // local variables: new, the new sentences inferred on each iteration
            List <Literal> newSentences = new List <Literal>();

            // Ensure query is not already a know fact before
            // attempting forward chaining.
            List <Dictionary <Variable, Term> > answers = KB.fetch(alpha);

            if (answers.Count > 0)
            {
                ansHandler.addProofStep(new ProofStepFoChAlreadyAFact(alpha));
                ansHandler.setAnswers(answers);
                return(ansHandler);
            }

            // repeat until new is empty
            do
            {
                // new <- {}
                newSentences.Clear();
                // for each rule in KB do
                // (p1 ^ ... ^ pn => q) <-STANDARDIZE-VARIABLES(rule)
                foreach (Clause impl in KB.getAllDefiniteClauseImplications())
                {
                    Clause impl2 = KB.standardizeApart(impl);
                    // for each theta such that SUBST(theta, p1 ^ ... ^ pn) =
                    // SUBST(theta, p'1 ^ ... ^ p'n)
                    // --- for some p'1,...,p'n in KB
                    foreach (Dictionary <Variable, Term> theta in KB.fetch(invert(new List <Literal>(impl2
                                                                                                     .getNegativeLiterals()))))
                    {
                        // q' <- SUBST(theta, q)
                        Literal qPrime = KB.subst(theta, impl.getPositiveLiterals()
                                                  [0]);
                        // if q' does not unify with some sentence already in KB or
                        // new then do
                        if (!KB.isRenaming(qPrime) &&
                            !KB.isRenaming(qPrime, newSentences))
                        {
                            // add q' to new
                            newSentences.Add(qPrime);
                            ansHandler.addProofStep(impl, qPrime, theta);
                            // theta <- UNIFY(q', alpha)
                            Dictionary <Variable, Term> theta2 = KB.unify(qPrime.getAtomicSentence(), alpha
                                                                          .getAtomicSentence());
                            // if theta is not fail then return theta
                            if (null != theta2)
                            {
                                foreach (Literal l in newSentences)
                                {
                                    Sentence s = null;
                                    if (l.isPositiveLiteral())
                                    {
                                        s = l.getAtomicSentence();
                                    }
                                    else
                                    {
                                        s = new NotSentence(l.getAtomicSentence());
                                    }
                                    KB.tell(s);
                                }
                                ansHandler.setAnswers(KB.fetch(alpha));
                                return(ansHandler);
                            }
                        }
                    }
                }
                // add new to KB
                foreach (Literal l in newSentences)
                {
                    Sentence s = null;
                    if (l.isPositiveLiteral())
                    {
                        s = l.getAtomicSentence();
                    }
                    else
                    {
                        s = new NotSentence(l.getAtomicSentence());
                    }
                    KB.tell(s);
                }
            } while (newSentences.Count > 0);
            // return false
            return(ansHandler);
        }