package aima.logic; import java.util.Hashtable; /** * The HashBindings class implements the <code>Bindings</code> interface * using a <code>Hashtable</code>. * * <p> * Note: This implementation may not be appropriate for the various * theorem provers which need an implementation of <code>Bindings</code> * that allow bindings to be cheaply extended in several different * directions. For that, consider using <code>ListBindings</code>. * * @author Michael S. Braverman * @see ListBindings */ public class HashBindings implements Bindings { /** * Obtains the Failure (representing no consistent <code>Bindings</code>) * object. * * @return The failure bindings object. * */ public Bindings getFailure() { return FAILURE; } /** * Obtains the Empty (representing no current bindings) object. * * @return The empty bindings object. * */ static public Bindings getEmpty() { return EMPTYBINDINGS; } /** * Determine if the given <code>Variable</code> is currently bound. * * @return true iff the <code>Variable</code> is bound. * @param var The variable to check. */ public boolean isBound(Variable var) { return (getBinding(var) != null); } /** * Determine if this <code>HashBindings</code> object represents the * Empty (no current bindings) object. * * @return true iff this object is the Empty bindings object. */ public boolean isEmpty() { return (this == EMPTYBINDINGS); } /** * Determine if this <code>HashBindings</code> object represents the * Failure (no consistent bindings) object. * * @return true iff this object is the Failure bindings object. */ public boolean isFailure() { return (this == FAILURE); } /** * Get the current binding of the given <code>Variable</code>. * * @return The value associated with the variable. * @param var The variable to look up. */ public Object getBinding(Variable var) { return theTable.get(var); } /** * Extends this <code>HashBindings</code> object with an association between * the given <code>Variable</code> and value. * * <p> * Note: This method changes the <code>HashBindings</code> * object on which it is invoked. This is fine, and efficient, for * simple unification applications, but will not work well for the * various theorem provers which may want to share a * <code>Bindings</code> instance (or part thereof) among many lines * of of reasoning. Instead, consider using a * <code>ListBindings</code> instance to manage * <code>Bindings</code> for such applications. * * @return An extended <code>HashBindings</code> object. * @param var The variable to bind. * @param val The value to which the <code>Variable</code> is to be bound. * @see ListBindings */ public Bindings extendBindings (Variable var, Object val) { HashBindings result = this; if (this == EMPTYBINDINGS) { result = new HashBindings(); } result.theTable.put(var,val); return result; } /** * Returns a <code>String</code> representation of this object. * * @return a <code>String</code> representation of this object. */ public String toString () { if (this == EMPTYBINDINGS) { return "[Bindings Empty]"; } else if (this == FAILURE) { return "[Bindings *FAILURE*]"; } else { return "[Bindings: "+ theTable.toString() +"]"; } } /** * Placeholder (private) so one can not create their own * <code>HashBindings</code>, and must instead start with the initial * bindings returned by <code>getEmpty</code> and extend from there. * * @see getEmpty */ private HashBindings() { theTable = new Hashtable(); } /** * Contains the <code>Hashtable</code> object the actually stores * the <code>Variable</code> bindings. */ private Hashtable theTable; /** * Indicates an empty set of bindings (indicating unification * success, with no variables) */ /* (defconstant +no-bindings+ '((nil)) "Indicates unification success, with no variables.") */ static private Bindings EMPTYBINDINGS = new HashBindings(); /** * Indicates no consistent binding (unification failure). * * @see getFailure() */ /* (defconstant +fail+ nil "Indicates unification failure") */ static private Bindings FAILURE = new HashBindings(); /** * Tests out the functionality of this class. * @param args Ignored. */ static public void main(String [] args) { System.err.println(FAILURE); System.err.println(EMPTYBINDINGS); Bindings b = HashBindings.getEmpty(); // test to make sure that variables with the same base name // (but maybe represented by different Variable instances) // refer to the same variable in the Bindings object. // (We need want this to be the case since it is difficult // to intern Variables, so we allow two Variables that just // "look alike" to be the same variable with respect to // the Bindings object) // Note that since this is a HashBindings object, only the final // bound value of a given variable will be present in the // final Bindings (compare with ListBindings) b = b.extendBindings(new Variable("x"), new Integer(1)); b = b.extendBindings(new Variable("y"), new Integer(2)); b = b.extendBindings(new Variable("y"), new Integer(3)); b = b.extendBindings(new Variable("y"), new Integer(4)); b = b.extendBindings(new Variable("z"), new Integer(5)); b = b.extendBindings(new Variable("x"), new Integer(5)); System.err.println(b); } }