///////////////////////////////////////////////////////////////////////
// STANFORD LOGIC GROUP //
// General Game Playing Project //
// //
// Sample Player Implementation //
// //
// (c) 2007. See LICENSE and CONTRIBUTORS. //
///////////////////////////////////////////////////////////////////////
/**
*
*/
package stanfordlogic.prover;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import stanfordlogic.gdl.SymbolTable;
import stanfordlogic.game.GameManager;
/**
*
* @author Based on code by Team Camembert: David Haley, Pierre-Yves Laligand
*/
public class Substitution
{
final private Map<TermVariable, Term> substitutions_;
public Substitution()
{
substitutions_ = new TreeMap<TermVariable, Term>();
}
public Substitution(Map<TermVariable, Term> substs)
{
substitutions_ = substs;
}
public void addMapping(TermVariable from, Term to)
{
// Is there already a mapping for 'to'?
Term mapping = substitutions_.get(to);
if ( mapping != null )
substitutions_.put(from, mapping);
else
substitutions_.put(from, to.clone());
// Fix everything that maps to 'from'.
updateMappings(from, to);
}
private void updateMappings(TermVariable from, Term to)
{
for ( TermVariable key : substitutions_.keySet() )
{
Term mapping = getMapping(key);
if ( mapping.equals(from) )
substitutions_.put(key, to);
else if ( mapping instanceof TermFunction )
{
updateFunction( (TermFunction) mapping, from, to );
((TermFunction) mapping).updateHasVariables();
}
}
}
private void updateFunction(TermFunction f, TermVariable from, Term to)
{
for ( int i = 0; i < f.getArity(); i++ )
{
Term arg = f.getTerm(i);
if ( arg.equals(from) )
f.arguments_[i] = to;
else if ( arg instanceof TermFunction )
updateFunction( (TermFunction) arg, from, to );
}
}
public Expression apply(Expression exp)
{
// If we don't have any mappings, don't bother with substitution
if ( substitutions_.size() == 0 )
return exp;
return exp.applySubstitution(this);
}
public Expression [] apply(Expression [] exprs)
{
// If we don't have any mappings, don't bother with substitution
if ( substitutions_.size() == 0 )
return exprs;
Expression [] result = new Expression[exprs.length];
int i = 0;
for ( Expression s : exprs )
result[i++] = apply(s);
return result;
}
public Term getMapping(TermVariable var)
{
return substitutions_.get(var);
}
public void removeMapping(TermVariable var)
{
substitutions_.remove(var);
}
public Substitution copy()
{
Substitution result = new Substitution();
for ( TermVariable key : substitutions_.keySet() )
result.substitutions_.put(key, substitutions_.get(key).clone());
return result;
}
public Substitution copy(Substitution add)
{
Substitution result = this.copy();
for ( TermVariable key : add.substitutions_.keySet() )
result.addMapping(key, add.substitutions_.get(key));
return result;
}
public Set<TermVariable> getMappedVars()
{
return substitutions_.keySet();
}
/**
* Gets the mapping for a function.
* Iterates over all the Term of the functions and recursively tries to map them.
*
* @param func The function whose mappings to compute.
* @return The function after all substitutions have been made.
*/
public TermFunction getMapping(TermFunction func)
{
TermFunction result = new TermFunction(true, func.functionName_, func.arguments_);
for ( int i = 0; i < result.getArity(); i++ )
{
if(result.arguments_[i] instanceof TermVariable)
{
Term replacement = getMapping((TermVariable) result.arguments_[i]);
if(replacement != null)
result.arguments_[i] = replacement;
}
else if(result.arguments_[i] instanceof TermFunction)
{
Term replacement = getMapping((TermFunction) result.arguments_[i]);
if(replacement != null)
result.arguments_[i] = replacement;
}
}
return result;
}
public int numMappings()
{
return substitutions_.size();
}
@Override
public String toString()
{
return toString(GameManager.getSymbolTable());
}
public String toString(SymbolTable symtab)
{
StringBuilder sb = new StringBuilder();
sb.append("{ ");
Set<TermVariable> keys = substitutions_.keySet();
for ( TermVariable tv : keys )
{
sb.append( tv.toString(symtab) );
sb.append( " <- " );
sb.append( getMapping(tv).toString(symtab) );
sb.append(". ");
}
sb.append("}");
return sb.toString();
}
@Override
public boolean equals( Object obj )
{
if ( this == obj )
return true;
if ( obj instanceof Substitution == false )
return false;
Substitution sub = (Substitution) obj;
return substitutions_.equals(sub.substitutions_);
}
}