/////////////////////////////////////////////////////////////////////// // STANFORD LOGIC GROUP // // General Game Playing Project // // // // Sample Player Implementation // // // // (c) 2007. See LICENSE and CONTRIBUTORS. // /////////////////////////////////////////////////////////////////////// /** * */ package stanfordlogic.knowledge; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.Iterator; import java.util.List; import stanfordlogic.prover.Fact; import stanfordlogic.prover.GroundFact; import stanfordlogic.prover.Substitution; import stanfordlogic.prover.VariableFact; import stanfordlogic.gdl.SymbolTable; import stanfordlogic.game.GameManager; /** The knowledge base is a collection of what is true in the * current state of the world. * * @author Based on code by Team Camembert: David Haley, Pierre-Yves Laligand */ public abstract class KnowledgeBase { /** Hash codes */ protected Object cleanHash_ = null; protected Object modHash_ = null; /** * Setter for the hash object. * * @param hash The object used for the hashing. * @param clean True if we're setting the 'clean' hash. */ public void setHash(Object hash, boolean clean) { if(clean) cleanHash_ = hash; else modHash_ = hash; } /** * Getter for the hash object. * * @param clean True if we're getting the 'clean' hash. * @return The object used for hashing the knowledge base. */ public Object getHash(boolean clean) { if(clean) return cleanHash_; return modHash_; } /** * Initialize it with a set of facts * @param symtab * The symbol table to use for the facts in this knowledge base. * @param facts * The facts to store in the KB */ public void loadWithFacts(List<GroundFact> facts) { for(GroundFact fact: facts) setTrue(fact); } /** * Clear all relations such that nothing is true anymore. */ public abstract void clear(); /** * Get the number of facts true in the current state. * * @return The number of true facts. */ public abstract int getNumFacts(); public abstract boolean isTrue(GroundFact fact); public boolean isTrue(Fact fact) { // If it's not a ground fact, it's false if ( fact instanceof GroundFact == false ) return false; return isTrue( (GroundFact) fact ); } /** * Mark a given fact as 'true' in the current state. * * @param fact Fact to set as true. */ public abstract void setTrue(GroundFact fact); /** * Mark a given fact as 'false' in the current state. * Note that given 'negation as failure' this means the same * thing as removing a fact from the database. * * @param fact Fact to set as false. */ public abstract void setFalse(GroundFact fact); /** * Get the GDL state as a string. Note that in many cases using * the Writer version of this method will be more efficient, since the string * memory doesn't have to be allocated twice. * * @return A string containing the state of this knowledge base in GDL sentences. */ public String stateToGdl() { ByteArrayOutputStream output = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(output); stateToGdl(ps); ps.flush(); return output.toString(); } /** * Write the state in GDL to a Writer (character stream). Uses the Game Manager's * symbol table. * * @param target The Writer to output to. */ final public void stateToGdl(PrintStream target) { stateToGdl(target, GameManager.getSymbolTable()); } public abstract void stateToGdl(PrintStream target, SymbolTable symTab); /** * Return a sorted list of facts true in this database. The ordering is * according to the elements' Comparable interface. * * @return A list of all facts in this database. */ public List<GroundFact> getFacts() { return getFacts(true); } /** * Get an iterator for the facts in this knowledge base. Contrary to * getFacts(), this method tries to create the smallest amount of memory * possible. The iterator is backed by the kb's facts, which means that * if you change the kb during iteration the state of the iterator will * probably be undefined. * * @return An iterator over the kb facts. */ public abstract Iterator<GroundFact> getIterator(); /** * Similar to getIterator, but returns an iterable. * * @return An iterable over the kb facts. */ final public Iterable<GroundFact> getIterable() { return new Iterable<GroundFact>() { public Iterator<GroundFact> iterator() { return getIterator(); } }; } /** * Get the number of differences with another kb. A 'difference' is defined * as a fact in one KB but not the other. * * <p> * Formally: # differences = #(this - other) + #(other - this) * * @param otherKb * The KB to compare differences with. * @return The number of differences between the two kb. */ public int getDifferences(KnowledgeBase otherKb) { int count = 0; // Count things in this but not in other Iterator<GroundFact> myIt = this.getIterator(); while ( myIt.hasNext() ) { if ( otherKb.isTrue(myIt.next()) == false ) count++; } // Count things in other but not in this Iterator<GroundFact> otherIt = otherKb.getIterator(); while ( otherIt.hasNext() ) { if ( this.isTrue(otherIt.next()) == false ) count++; } return count; } /** * Return a list of all facts true in this database. * * @param sorted True if the list should be sorted. * @return A list of all facts true in this database. */ public abstract List<GroundFact> getFacts(boolean sorted); /** * Retrieves all the facts in the kb that are unifiable with the input (variable) fact. * @param fact The template fact to match kb facts against * @return A list of fact that are unifiable. */ public abstract List<Substitution> getUnifiable(VariableFact fact); }