package de.tu_dresden.inf.ggp06_2.resolver;
import java.util.ArrayList;
import java.util.List;
import de.tu_dresden.inf.ggp06_2.resolver.astvisitors.AbstractVisitor;
import de.tu_dresden.inf.ggp06_2.resolver.fuzzy.FuzzyResolution;
import de.tu_dresden.inf.ggp06_2.resolver.fuzzy.FuzzySubstitution;
import de.tu_dresden.inf.ggp06_2.resolver.scope.GameStateScope;
import de.tu_dresden.inf.ggp06_2.simulator.flags.TimerFlag;
/**
*
* @author Nick (initial author of JavaProver )
* @author Ingo Keller - General Game Playing course student at TUD
* @author Arsen Kostenko - General Game Playing course student at TUD
*
*/
public class Atom extends Term {
/**
* content of this atom
*/
final String literal;
final int hashCode;
/**
* The very only constructor for an atom, since
* no atoms should be possible without their
* string parameter.
*
* @param string Literal of newly created atom.
*/
public Atom(String string) {
literal = string.toUpperCase();
hashCode = literal.hashCode();
}
/**
* @return returns literal propery of current atom.
*/
@Override
public final String toString() {
return literal;
}
/**
* @return Returns an empty list. Literals do not contain variables ;).
*/
@Override
public final List<Variable> getVariables() {
return new ArrayList<Variable>();
}
/**
* @param sigma Substitution to apply
* @return Returns the literal because atoms are immune to
* any subsitutions.
*/
@Override
public final Expression apply(Substitution sigma) {
return this;
}
/**
*
* @param obj Object to compare to.
* @return Returns if supplied object is an atom with
* equal literal.
*/
@Override
public final boolean equals(Object obj) {
return (obj instanceof Atom) && (hashCode == obj.hashCode());
}
/**
*
*
* @param sigma
* @param scope
* @param flag
* @return
* @throws InterruptedException
*/
@Override
protected FuzzyResolution fuzzyEvaluateBody( FuzzySubstitution sigma,
GameStateScope scope,
List<Expression> guard,
TimerFlag flag )
throws InterruptedException {
FuzzyResolution sigmas = null;
if (scope.isProven( this )){
sigmas = new FuzzyResolution();
sigmas.addAll( scope.getProvenForFuzzy( sigma, this ) );
sigmas.setFuzzyValue( Expression.fuzzyOne );
return sigmas;
} else if (scope.isFuzzylyEvaluated(this)){
return scope.getFuzzyResolutionStage( sigma, this );
} else if (guard.contains( this )){
sigmas = new FuzzyResolution();
sigmas.add( sigma );
sigmas.setFuzzyValue( Expression.fuzzyZero );
return sigmas;
}
int size = guard.size();
guard.add( size, this);
sigmas = fuzzyEvaluateSimilarExpressions( sigma, scope, guard, flag );
guard.remove( size );
scope.setFuzzyEvaluationStage( this, sigmas);
return sigmas;
}
/**
*
* @param sigma
* @param sigmas
* @param scope
* @param flag
* @return
* @throws InterruptedException
*/
private FuzzyResolution fuzzyEvaluateSimilarExpressions(
FuzzySubstitution sigma, GameStateScope scope,
List<Expression> guard, TimerFlag flag)
throws InterruptedException {
/*
* A trick about 'resolved' is that if
* some predicate at some point is resolved,
* we want to stop calculating fuzzy value for it.
* However, we would like to keep collecting successful
* substitutions. Therefore 'resolved' acts as a flag,
* indicating that no modifications to fuzzy value of
* current predicate should be done from now on.
*
* For second issue consider following rules:
* (<= (somepred ?x)
* (succ ?x ?y)
* (somepred ?y)
* )
* (somepred 1)
* (succ 2 1)
* (succ 3 2)
* (succ 4 3)
* The rules of 'somepred' kind should be treated as if they are
* combined with a T-Conorm (fuzzy conjunction),
* whereas the rules of 'succ' kind should result only to fuzzy
* truth or fuzzy false (no fuzzy conjunciton is assumed)
*
* Moreover if some candidate (disreguarding which kind) evaluates to
* fuzzy true (higher than a threashold), fuzzy true should be
* returned as the result.
*/
ExpressionList candidates = scope.getSimilarExpressions(this);
FuzzyResolution sigmas = new FuzzyResolution();
for (Expression e : candidates ) {
FuzzyResolution fuzzy = null;
if ( e instanceof Implication ) {
Implication impl = (Implication) e;
ExpressionList prem = impl.getPremises();
if ( flag.interrupted() ) throw Const.interrupt;
fuzzy = prem.fuzzyEvaluate( sigma, scope, guard, flag );
sigmas.addAlternativeResolution( fuzzy );
}
}
scope.setFuzzyEvaluationStage(this, sigmas);
return sigmas;
}
/**
* Basically there are only two successful cases:
* <ul>
* <li>either supplied expression is the same atom
* (in this case no modification are done to supplied
* substitution)</li>
* <li>or supplied expression is a variable
* (in this case variable is asked to find MGU
* with current atom)</li>
* </ul>
* All other cases default to unsuccessful unification.
*
* @param target Expression to unify with.
* @param sigma Substitution to consider while unification.
* @return Returns most general unifier substitution if
* such exists.
*/
@Override
public final Substitution mgu (Expression target, Substitution sigma) {
if ( target instanceof Atom && target.equals(this) )
return sigma;
return (target instanceof Variable) ?
((Variable) target).mgu(this, sigma) :
null;
}
/**
*
* @param var Variable to search for.
* @return Defaults to false, since there are no
* variables that could occure in a literal ;-).
*/
@Override
public final boolean isPresent(Variable var) {
return false;
}
@Override
public final int hashCode() {
return hashCode;
}
@Override
public final boolean isGround() {
return true;
}
@Override
public final Atom getKeyAtom() {
return this;
}
@Override
public final void processVisitor(AbstractVisitor visitor) {
visitor.visitAtom(this);
}
}