aima.core.logic.fol.kb.FOLKnowledgeBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aima-core Show documentation
Show all versions of aima-core Show documentation
AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.
The newest version!
package aima.core.logic.fol.kb;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import aima.core.logic.fol.CNFConverter;
import aima.core.logic.fol.StandardizeApart;
import aima.core.logic.fol.StandardizeApartIndexical;
import aima.core.logic.fol.StandardizeApartIndexicalFactory;
import aima.core.logic.fol.StandardizeApartResult;
import aima.core.logic.fol.SubstVisitor;
import aima.core.logic.fol.Unifier;
import aima.core.logic.fol.VariableCollector;
import aima.core.logic.fol.domain.FOLDomain;
import aima.core.logic.fol.inference.FOLOTTERLikeTheoremProver;
import aima.core.logic.fol.inference.InferenceProcedure;
import aima.core.logic.fol.inference.InferenceResult;
import aima.core.logic.fol.inference.proof.Proof;
import aima.core.logic.fol.inference.proof.ProofStepClauseClausifySentence;
import aima.core.logic.fol.kb.data.CNF;
import aima.core.logic.fol.kb.data.Chain;
import aima.core.logic.fol.kb.data.Clause;
import aima.core.logic.fol.kb.data.Literal;
import aima.core.logic.fol.parsing.FOLParser;
import aima.core.logic.fol.parsing.ast.FOLNode;
import aima.core.logic.fol.parsing.ast.Predicate;
import aima.core.logic.fol.parsing.ast.Sentence;
import aima.core.logic.fol.parsing.ast.Term;
import aima.core.logic.fol.parsing.ast.Variable;
/**
* A First Order Logic (FOL) Knowledge Base.
*
* @author Ciaran O'Reilly
*
*/
public class FOLKnowledgeBase {
private FOLParser parser;
private InferenceProcedure inferenceProcedure;
private Unifier unifier;
private SubstVisitor substVisitor;
private VariableCollector variableCollector;
private StandardizeApart standardizeApart;
private CNFConverter cnfConverter;
//
// Persistent data structures
//
// Keeps track of the Sentences in their original form as added to the
// Knowledge base.
private List originalSentences = new ArrayList();
// The KB in clause form
private Set clauses = new LinkedHashSet();
// Keep track of all of the definite clauses in the database
// along with those that represent implications.
private List allDefiniteClauses = new ArrayList();
private List implicationDefiniteClauses = new ArrayList();
// All the facts in the KB indexed by Atomic Sentence name (Note: pg. 279)
private Map> indexFacts = new HashMap>();
// Keep track of indexical keys for uniquely standardizing apart sentences
private StandardizeApartIndexical variableIndexical = StandardizeApartIndexicalFactory
.newStandardizeApartIndexical('v');
private StandardizeApartIndexical queryIndexical = StandardizeApartIndexicalFactory
.newStandardizeApartIndexical('q');
//
// PUBLIC METHODS
//
public FOLKnowledgeBase(FOLDomain domain) {
// Default to Full Resolution if not set.
this(domain, new FOLOTTERLikeTheoremProver());
}
public FOLKnowledgeBase(FOLDomain domain,
InferenceProcedure inferenceProcedure) {
this(domain, inferenceProcedure, new Unifier());
}
public FOLKnowledgeBase(FOLDomain domain,
InferenceProcedure inferenceProcedure, Unifier unifier) {
this.parser = new FOLParser(new FOLDomain(domain));
this.inferenceProcedure = inferenceProcedure;
this.unifier = unifier;
//
this.substVisitor = new SubstVisitor();
this.variableCollector = new VariableCollector();
this.standardizeApart = new StandardizeApart(variableCollector,
substVisitor);
this.cnfConverter = new CNFConverter(parser);
}
public void clear() {
this.originalSentences.clear();
this.clauses.clear();
this.allDefiniteClauses.clear();
this.implicationDefiniteClauses.clear();
this.indexFacts.clear();
}
public InferenceProcedure getInferenceProcedure() {
return inferenceProcedure;
}
public void setInferenceProcedure(InferenceProcedure inferenceProcedure) {
if (null != inferenceProcedure) {
this.inferenceProcedure = inferenceProcedure;
}
}
public Sentence tell(String sentence) {
Sentence s = parser.parse(sentence);
tell(s);
return s;
}
public void tell(List sentences) {
for (Sentence s : sentences) {
tell(s);
}
}
public void tell(Sentence sentence) {
store(sentence);
}
/**
*
* @param querySentence
* @return an InferenceResult.
*/
public InferenceResult ask(String querySentence) {
return ask(parser.parse(querySentence));
}
public InferenceResult ask(Sentence query) {
// Want to standardize apart the query to ensure
// it does not clash with any of the sentences
// in the database
StandardizeApartResult saResult = standardizeApart.standardizeApart(
query, queryIndexical);
// Need to map the result variables (as they are standardized apart)
// to the original queries variables so that the caller can easily
// understand and use the returned set of substitutions
InferenceResult infResult = getInferenceProcedure().ask(this,
saResult.getStandardized());
for (Proof p : infResult.getProofs()) {
Map im = p.getAnswerBindings();
Map em = new LinkedHashMap();
for (Variable rev : saResult.getReverseSubstitution().keySet()) {
em.put((Variable) saResult.getReverseSubstitution().get(rev),
im.get(rev));
}
p.replaceAnswerBindings(em);
}
return infResult;
}
public int getNumberFacts() {
return allDefiniteClauses.size() - implicationDefiniteClauses.size();
}
public int getNumberRules() {
return clauses.size() - getNumberFacts();
}
public List getOriginalSentences() {
return Collections.unmodifiableList(originalSentences);
}
public List getAllDefiniteClauses() {
return Collections.unmodifiableList(allDefiniteClauses);
}
public List getAllDefiniteClauseImplications() {
return Collections.unmodifiableList(implicationDefiniteClauses);
}
public Set getAllClauses() {
return Collections.unmodifiableSet(clauses);
}
// Note: pg 278, FETCH(q) concept.
public synchronized Set