/// <summary> /// Ask the knowledge base if a given statement about the model is true, given what it knows. /// </summary> /// <param name="query"></param> /// <returns>True if the statement is known to be true, false if it is known to be false or cannot be determined.</returns> public bool Ask(Expression <Predicate <TModel> > query) { // NB: Very raw implementation - there are a number of possible performance improvements that could be made here // Will return to give them a go at some point.. var queryAsCnf = new CNFExpression <TModel>(query); var clauses = sentences.Append(queryAsCnf).SelectMany(s => s.Clauses).ToList(); List <CNFClause <TModel> > newClauses = new List <CNFClause <TModel> >(); while (true) { // TODO-PERFORMANCE: While this is how the source book writes the algorithm, its very inefficient - // we'll end up resolving the same clauses again and again. Need to improve this (and move this // implementation to the benchmarks project as a baseline). foreach (var ci in clauses) { foreach (var cj in clauses) { var resolvents = CNFClause <TModel> .Resolve(ci, cj); if (resolvents.IsEmpty) { return(true); } newClauses.Add(resolvents); } } // if new ⊆ clauses then return false // need clause equality.. clauses.AddRange(newClauses); } return(false); }
public void TestCNFClause() { CNFClause clause1 = new CNFClause(ClauseParser.Parse("a&b&c||d")), clause2 = new CNFClause(ClauseParser.Parse("a=>(b&c||d&e)")); Console.WriteLine("{0}\n{1}", clause1.ToString(), clause2.ToString()); }