///////////////////////////////////////////////////////////////////////
// STANFORD LOGIC GROUP //
// General Game Playing Project //
// //
// Sample Player Implementation //
// //
// (c) 2007. See LICENSE and CONTRIBUTORS. //
///////////////////////////////////////////////////////////////////////
/**
*
*/
package stanfordlogic.prover;
import java.util.Map;
import stanfordlogic.gdl.SymbolTable;
/**
*
* @author Based on code by Team Camembert: David Haley, Pierre-Yves Laligand
*/
public class TermVariable extends Term
{
private int varName_;
public TermVariable(int varName)
{
varName_ = varName;
}
private static int nextUnique_ = 290;
public static void setUniqueStart(int start)
{
nextUnique_ = start;
}
/**
* Make a new unique variable.
*
* @return
*/
public static TermVariable makeTermVariable()
{
TermVariable obj = new TermVariable(nextUnique_++);
//THINK: make nextUnique 'rotate', no need to have it too big
return obj;
}
@Override
public Term applySubstitution( Substitution sigma )
{
// Does sigma apply to our variable?
Term replacement = sigma.getMapping(this);
if ( replacement == null )
return this; // nothing to change!
// Otherwise, return the variable's replacement
return replacement;
}
@Override
public int getTotalColumns()
{
// Only need one column: variable name
return 1;
}
@Override
public Term clone()
{
return new TermVariable(this.varName_);
}
@Override
public String toString( SymbolTable symtab )
{
return "?var" + varName_;
}
@Override
protected int compareTo( TermObject t )
{
// Obj < Func < Var
return 1;
}
@Override
protected int compareTo( TermFunction t )
{
// Obj < Func < Var
return 1;
}
@Override
protected int compareTo( TermVariable t )
{
return Integer.signum( this.varName_ - t.varName_ );
}
@Override
public boolean hasVariables()
{
return true;
}
@Override
public boolean hasTermFunction( int functionName )
{
// false by definition
return false;
}
@Override
public boolean hasVariable( int varName )
{
return varName_ == varName;
}
public int getName()
{
return varName_;
}
@Override
public boolean equals( Object obj )
{
if ( obj instanceof TermVariable == false )
return false;
// Two variables are equal if and only if they have the same (name in this context)
return varName_ == ((TermVariable) obj).varName_;
}
@Override
public int hashCode()
{
return varName_;
}
@Override
public boolean canMapVariables( Term other, Map<TermVariable, TermVariable> varMap )
{
if ( other instanceof TermVariable == false )
return false;
// Both are variables, so either the first has mapped to no variable,
// or first must map to second
TermVariable mapped = varMap.get(this);
if ( mapped == null )
{
varMap.put(this, (TermVariable) other);
return true;
}
else
{
return mapped.equals(other);
}
}
@Override
public Term uniquefy( Map<TermVariable, TermVariable> newVarMap )
{
TermVariable newVar = newVarMap.get(this);
if ( newVar == null )
{
newVar = makeTermVariable();
newVarMap.put(this, newVar);
}
return newVar;
}
@Override
public boolean mgu( Term t, Substitution subsSoFar )
{
if ( t instanceof TermObject )
{
Term replacement = subsSoFar.getMapping( this );
if ( replacement != null )
{
// If there's already a replacement, it has to be equal to the term object
if ( replacement.equals(t) == false )
return false;
// The replacement equals this, so we're ok
else
return true;
}
// There was no replacement:
else
{
// Add a mapping for the variable to this term-object
subsSoFar.addMapping( this, t);
return true;
}
}
else if ( t instanceof TermVariable )
{
TermVariable it = (TermVariable) t;
Term myReplacement = subsSoFar.getMapping(this);
Term itsReplacement = subsSoFar.getMapping(it);
if ( itsReplacement == null )
{
// just map 'it' to me (or my replacement)
if ( myReplacement == null )
{
if(!equals(it))
subsSoFar.addMapping(it, this);
}
else
{
if(!(myReplacement instanceof TermVariable) || !((TermVariable) myReplacement).equals(it))
subsSoFar.addMapping(it, myReplacement);
}
return true;
}
// At this point, 'it' has a replacement.
if ( myReplacement == null )
{
// I don't have a replacement, so map me to it, or to its replacement
if ( itsReplacement == null )
{
subsSoFar.addMapping(this, it);
}
else
{
if(!(itsReplacement instanceof TermVariable) || !((TermVariable) itsReplacement).equals(this))
subsSoFar.addMapping(this, itsReplacement);
}
return true;
}
// At this point, both term variables have replacements.
// So make sure that they are the same!
if ( myReplacement.equals(itsReplacement) )
return true;
else
return false;
}
else if ( t instanceof TermFunction )
{
Term myReplacement = subsSoFar.getMapping(this);
// Case 1: I have a replacement
if ( myReplacement != null )
{
// See if my replacement can be unified with the function
return myReplacement.mgu(t, subsSoFar);
}
// Case 2: I have no replacement
else
{
TermFunction itsReplacement = subsSoFar.getMapping((TermFunction) t);
if(itsReplacement.hasVariable(this))
{
return false;
}
// just set my replacement to the function
subsSoFar.addMapping(this, itsReplacement);
return true;
}
}
else
{
throw new IllegalArgumentException(
"TermVariable.mgu: Don't know how to handle term of type "
+ t.getClass().getName() );
}
}
}