/// <summary> /// <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> /// </summary> /// <param name="KB"></param> /// <param name="ansHandler"></param> /// <param name="goals"></param> /// <param name="theta"></param> /// <returns></returns> private IList <IList <ProofStepBwChGoal> > Folbcask(FOLKnowledgeBase KB, BCAskAnswerHandler ansHandler, IList <Literal> goals, IDictionary <Variable, ITerm> theta) { var thisLevelProofSteps = new List <IList <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()) { var standardizedR = KB.StandardizeApart(r); // and thetaDelta <- UNIFY(q, qDelta) succeeds IDictionary <Variable, ITerm> thetaDelta = KB.Unify(standardizedR.GetPositiveLiterals()[0].AtomicSentence, qDelta.AtomicSentence); if (null != thetaDelta) { // new_goals <- [p1,...,pn|REST(goals)] var newGoals = new List <Literal>(standardizedR.GetNegativeLiterals()); newGoals.AddRange(goals.Skip(1)); // answers <- FOL-BC-ASK(KB, new_goals, COMPOSE(thetaDelta, // theta)) U answers IDictionary <Variable, ITerm> composed = this.Compose(KB, thetaDelta, theta); IList <IList <ProofStepBwChGoal> > lowerLevelProofSteps = this.Folbcask( KB, ansHandler, newGoals, composed); ansHandler.AddProofStep(lowerLevelProofSteps, standardizedR, qDelta, composed); thisLevelProofSteps.AddRange(lowerLevelProofSteps); } } // return answers return(thisLevelProofSteps); }
public IInferenceResult Ask(FOLKnowledgeBase kb, ISentence alpha) { // clauses <- the set of clauses in CNF representation of KB ^ ~alpha ISet <Clause> clauses = new HashedSet <Clause>(); foreach (Clause c in kb.GetAllClauses()) { var standardizedC = kb.StandardizeApart(c); standardizedC.SetStandardizedApartCheckNotRequired(); clauses.UnionWith(standardizedC.GetFactors()); } ISentence notAlpha = new NotSentence(alpha); // Want to use an answer literal to pull // query variables where necessary Literal answerLiteral = kb.CreateAnswerLiteral(notAlpha); ISet <Variable> answerLiteralVariables = kb .CollectAllVariables(answerLiteral.AtomicSentence); Clause answerClause = new Clause(); if (answerLiteralVariables.Count > 0) { ISentence notAlphaWithAnswer = new ConnectedSentence(Connectors.Or, notAlpha, answerLiteral.AtomicSentence); foreach (Clause c in kb.ConvertToClauses(notAlphaWithAnswer)) { var standardizedC = kb.StandardizeApart(c); standardizedC.SetProofStep(new ProofStepGoal(standardizedC)); standardizedC.SetStandardizedApartCheckNotRequired(); clauses.UnionWith(standardizedC.GetFactors()); } answerClause.AddLiteral(answerLiteral); } else { foreach (Clause c in kb.ConvertToClauses(notAlpha)) { var standardizedC = kb.StandardizeApart(c); standardizedC.SetProofStep(new ProofStepGoal(standardizedC)); standardizedC.SetStandardizedApartCheckNotRequired(); clauses.UnionWith(standardizedC.GetFactors()); } } var ansHandler = new TFMAnswerHandler(answerLiteral, answerLiteralVariables, answerClause, this.MaxQueryTime); // new <- {} ISet <Clause> newClauses = new HashedSet <Clause>(); ISet <Clause> toAdd = new HashedSet <Clause>(); // loop do int noOfPrevClauses = clauses.Count; do { if (Tracer != null) { Tracer.StepStartWhile(clauses, clauses.Count, newClauses .Count); } newClauses.Clear(); // for each Ci, Cj in clauses do Clause[] clausesA = new Clause[clauses.Count]; clausesA = clauses.ToArray(); // Basically, using the simple T)wo F)inger M)ethod here. for (int i = 0; i < clausesA.Length; i++) { Clause cI = clausesA[i]; if (null != Tracer) { Tracer.StepOuterFor(cI); } for (int j = i; j < clausesA.Length; j++) { Clause cJ = clausesA[j]; if (null != Tracer) { Tracer.StepInnerFor(cI, cJ); } // resolvent <- FOL-RESOLVE(Ci, Cj) ISet <Clause> resolvents = cI.BinaryResolvents(cJ); if (resolvents.Count > 0) { toAdd.Clear(); // new <- new <UNION> resolvent foreach (Clause rc in resolvents) { toAdd.UnionWith(rc.GetFactors()); } if (null != Tracer) { Tracer.StepResolved(cI, cJ, toAdd); } ansHandler.CheckForPossibleAnswers(toAdd); if (ansHandler.IsComplete()) { break; } newClauses.UnionWith(toAdd); } if (ansHandler.IsComplete()) { break; } } if (ansHandler.IsComplete()) { break; } } noOfPrevClauses = clauses.Count; // clauses <- clauses <UNION> new clauses.UnionWith(newClauses); if (ansHandler.IsComplete()) { break; } // if new is a <SUBSET> of clauses then finished // searching for an answer // (i.e. when they were added the # clauses // did not increase). } while (noOfPrevClauses < clauses.Count); if (null != Tracer) { Tracer.StepFinished(clauses, ansHandler); } return(ansHandler); }
public IInferenceResult Ask(FOLKnowledgeBase KB, ISentence alpha) { ISet<Clause> sos = new HashedSet<Clause>(); ISet<Clause> usable = new HashedSet<Clause>(); // Usable set will be the set of clauses in the KB, // are assuming this is satisfiable as using the // ISet of Support strategy. //foreach (var standardizedC in KB.GetAllClauses().Select(c => KB.StandardizeApart(c))) foreach (var standardizedC in KB.GetAllClauses()) { standardizedC.SetStandardizedApartCheckNotRequired(); usable.UnionWith(standardizedC.GetFactors()); } // Ensure reflexivity axiom is added to usable if using paramodulation. if (this.UseParamodulation) { // Reflexivity Axiom: x = x var reflexivityAxiom = new TermEquality(new Variable("x"), new Variable("x")); var reflexivityClause = new Clause(); reflexivityClause.AddLiteral(new Literal(reflexivityAxiom)); reflexivityClause = KB.StandardizeApart(reflexivityClause); reflexivityClause.SetStandardizedApartCheckNotRequired(); usable.Add(reflexivityClause); } ISentence notAlpha = new NotSentence(alpha); // Want to use an answer literal to pull // query variables where necessary var answerLiteral = KB.CreateAnswerLiteral(notAlpha); var answerLiteralVariables = KB .CollectAllVariables(answerLiteral.AtomicSentence); var answerClause = new Clause(); if (answerLiteralVariables.Count > 0) { ISentence notAlphaWithAnswer = new ConnectedSentence(Connectors.Or, notAlpha, answerLiteral.AtomicSentence); // foreach (var standardizedC in // KB.ConvertToClauses(notAlphaWithAnswer).Select(KB.StandardizeApart)) foreach (var standardizedC in KB.ConvertToClauses(notAlphaWithAnswer)) { Clause c = KB.StandardizeApart(standardizedC); c.SetProofStep(new ProofStepGoal(c)); c.SetStandardizedApartCheckNotRequired(); sos.UnionWith(c.GetFactors()); } answerClause.AddLiteral(answerLiteral); } else { //foreach (var standardizedC in // KB.ConvertToClauses(notAlpha).Select(KB.StandardizeApart)) foreach (var standardizedC in KB.ConvertToClauses(notAlpha)) { Clause c = KB.StandardizeApart(standardizedC); c.SetProofStep(new ProofStepGoal(c)); c.SetStandardizedApartCheckNotRequired(); sos.UnionWith(standardizedC.GetFactors()); } } // Ensure all subsumed clauses are removed usable.ExceptWith(SubsumptionElimination.FindSubsumedClauses(usable)); sos.ExceptWith(SubsumptionElimination.FindSubsumedClauses(sos)); var ansHandler = new OTTERAnswerHandler(answerLiteral, answerLiteralVariables, answerClause, this.MaxQueryTime); var idxdClauses = new IndexedClauses(LightestClauseHeuristic, sos, usable); return this.Otter(ansHandler, idxdClauses, sos, usable); }
/// <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); }