//Determine KB logic based on given model public bool isTrue(knowledgeBase kB) { bool kbLogic = true; foreach (sentence s in kB.Sentences) { kbLogic = kbLogic && isTrue(s); } return(kbLogic); }
//Check all models based on given symbols public void CheckAll(knowledgeBase kB, sentence query, List <propositionalSymbol> symbols, model model) { if (symbols.Count == 0) { if (model.isTrue(kB)) { if (model.isTrue(query)) { modelEntailments++; } //return model.isTrue(query); } //else return true; } else { propositionalSymbol s = new propositionalSymbol(symbols.First()); //rest of the symbols List <propositionalSymbol> rest = new List <propositionalSymbol>(); rest.AddRange(symbols); rest.RemoveAt(0); //Initialize model for true branch model mleft = new model(); mleft.getCellList.AddRange(model.getCellList); mleft.getCellList.Add(new cell(s, true)); //Initialize model for false branch model mright = new model(); mright.getCellList.AddRange(model.getCellList); mright.getCellList.Add(new cell(s, false)); //Recursive call CheckAll(kB, query, rest, mleft); CheckAll(kB, query, rest, mright); } }
//Backward chaining algorithm public bool BCEntails(knowledgeBase kB, sentence query) { //Initialize list for storing implication clause only List <sentence> implication = new List <sentence>(); int factsCount; //Add query to open list if (!open.Any(x => x.getSymbol == query.Symbols.First().getSymbol)) { open.Add(query.Symbols.First()); } //Return false if the query is not an atomic sentence if (!query.isAtomicSentence()) { return(false); } //Construct simpler sentences in each KB sentences and add atomic sentences to known facts list foreach (sentence s in kB.Sentences) { if (!s.isAtomicSentence()) { if (s.Children.Count == 0) { s.constructChildren(); } implication.Add(s); } else { if (!facts.Any(x => x.getSymbol == s.Symbols.First().getSymbol)) { facts.Add(s.Symbols.First()); } } } //If the query is a known fact in KB if (facts.Any(x => x.getSymbol == query.Symbols.First().getSymbol)) { trace.Add(query.Symbols.First()); return(true); } //Return false if the query is not a conclusion of any of KB sentences if (!implication.Any(x => x.Children.Last().Symbols.First().getSymbol == query.Symbols.First().getSymbol)) { return(false); } //Loop through KB foreach (sentence s in implication) { //Check if query match any conclusions in KB if (s.Children.Last().Symbols.Any(x => x.getSymbol == query.Symbols.First().getSymbol)) { //Check whether if conjunction premise consists of only one single atomic sentence if (s.Children.First().isAtomicSentence()) { //Check if if (!facts.Any(x => x.getSymbol == s.Children.First().Symbols.First().getSymbol)) { if (!open.Any(x => x.getSymbol == s.Children.First().Symbols.First().getSymbol)) { open.Add(s.Children.First().Symbols.First()); } } else { //Check for duplication if (!trace.Any(x => x.getSymbol == s.Children.First().Symbols.First().getSymbol)) { trace.Add(s.Children.First().Symbols.First()); } trace.Add(query.Symbols.First()); facts.Add(query.Symbols.First()); open.RemoveAll(x => x.getSymbol == query.Symbols.First().getSymbol); } } else { factsCount = 0; foreach (propositionalSymbol p in s.Children.First().Symbols) { //Check if symbol is still yet to be known if (open.Any(x => x.getSymbol == p.getSymbol)) { agenda.Enqueue(p); continue; } //Check if each symbol in conjunction premise is a known fact if (facts.Any(x => x.getSymbol == p.getSymbol)) { if (!trace.Any(x => x.getSymbol == p.getSymbol)) { trace.Add(p); } factsCount++; } //Check if conjunction premise fully consists of known facts if (factsCount == s.Children.First().Symbols.Count) { facts.Add(s.Children.Last().Symbols.First()); trace.Add(s.Children.Last().Symbols.First()); open.RemoveAll(x => x.getSymbol == s.Children.Last().Symbols.First().getSymbol); } //Check if symbol is already inferred if (!trace.Any(x => x.getSymbol == p.getSymbol)) { open.Add(p); agenda.Enqueue(p); } } } } } //Make recursive call as long as there is more to expand in the agenda or open list if (agenda.Count != 0) { return(BCEntails(kB, new sentence(agenda.Dequeue()))); } else { if (open.Count == 0) { return(true); } else { sentence openPullFirst = new sentence(open.First()); open.Remove(open.First()); return(BCEntails(kB, openPullFirst)); } } }
//Forward chaining algorithm public bool FCEntails(knowledgeBase kB, sentence query) { Dictionary <sentence, int> count = new Dictionary <sentence, int>(); Queue <propositionalSymbol> agenda = new Queue <propositionalSymbol>(); propositionalSymbol p; List <sentence> hornClause = new List <sentence>(); //Construct simpler sentences in each KB sentences and allocate KB atomic sentences into agenda foreach (sentence s in kB.Sentences) { if (!s.isAtomicSentence()) { s.constructChildren(); } else { agenda.Enqueue(s.Symbols.Last()); } } //Allocate horn clause list from KB foreach (sentence s in kB.Sentences) { if (s.isImplicationClause()) { hornClause.Add(s); } } //Count number of symbols on conjunction side foreach (sentence s in hornClause) { count.Add(s, s.Children.First().Symbols.Count); } while (agenda.Count != 0) { p = agenda.Dequeue(); if (!InferredSymbols.Contains(p)) { inferred.Add(p); foreach (sentence s in hornClause) { if (s.Children.First().Symbols.Any(x => x.getSymbol == p.getSymbol)) { count[s]--; if (count[s] == 0) { if (s.Symbols.Last().getSymbol == query.Symbols.First().getSymbol) { inferred.Add(s.Symbols.Last()); return(true); } agenda.Enqueue(s.Symbols.Last()); } } } } } return(false); }
//Check entailment of alpha from KB public void Entails(knowledgeBase kB, sentence query, List <propositionalSymbol> symbols) { CheckAll(kB, query, symbols, new model()); }