예제 #1
0
        /// <summary>
        /// <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>
        /// </summary>
        /// <param name="KB"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public IInferenceResult Ask(FOLKnowledgeBase KB, ISentence query)
        {
            // Assertions on the type of queries this Inference procedure
            // supports
            if (!(query is IAtomicSentence))
            {
                throw new ArgumentOutOfRangeException("query", "Only Atomic Queries are supported.");
            }

            var ansHandler = new FCAskAnswerHandler();

            var alpha = new Literal((IAtomicSentence)query);

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

            // Ensure query is not already a know fact before
            // attempting forward chaining.
            ISet <IDictionary <Variable, ITerm> > 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())
                {
                    var standardizedImpl = 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 (IDictionary <Variable, ITerm> theta in KB.Fetch(this.Invert(standardizedImpl.GetNegativeLiterals())))
                    {
                        // q' <- SUBST(theta, q)
                        Literal qPrime = KB.Subst(theta, standardizedImpl.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(standardizedImpl, qPrime, theta);
                            // theta <- UNIFY(q', alpha)

                            // if theta is not fail then return theta
                            if (KB.Unify(qPrime.AtomicSentence, alpha.AtomicSentence) != null)
                            {
                                foreach (Literal l in newSentences)
                                {
                                    ISentence s;
                                    if (l.IsPositiveLiteral())
                                    {
                                        s = l.AtomicSentence;
                                    }
                                    else
                                    {
                                        s = new NotSentence(l.AtomicSentence);
                                    }
                                    KB.tell(s);
                                }
                                ansHandler.SetAnswers(KB.Fetch(alpha));
                                return(ansHandler);
                            }
                        }
                    }
                }
                // add new to KB
                foreach (Literal l in newSentences)
                {
                    ISentence s;
                    if (l.IsPositiveLiteral())
                    {
                        s = l.AtomicSentence;
                    }
                    else
                    {
                        s = new NotSentence(l.AtomicSentence);
                    }
                    KB.tell(s);
                }
            } while (newSentences.Count > 0);

            // return false
            return(ansHandler);
        }