/*
* Created on Apr 19, 2005
*
* Window - Preferences - Java - Code Style - Code Templates
*/
package cs227b.teamIago.resolver;
import java.util.ArrayList;
/**
* @author Nick
*
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Predicate extends Connective {
protected static final Atom aTrue = new Atom("true");
protected static final Atom aDoes = new Atom("does");
protected static final int PRED_OPERATOR_HASH_SEED = 2147005213;
protected static final int PRED_OPERANDS_HASH_SEED = 2147005547;
protected static final int PRED_OPERANDS_HASH_MUL = 2147005921;
/**
* @param operator
* @param operands
*/
public Predicate(String literal, ExpList operands) {
super();
this.operator = new Atom(literal);
this.operands = operands;
buildVolatile(false);
}
public Predicate(String literal, Expression[] opArray) {
this(literal, new ExpList(opArray));
}
/**
* @param operator
* @param operands
*/
public Predicate(Term operator, ExpList operands) {
super();
this.operator = operator;
this.operands = operands;
buildVolatile(false);
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Expression#apply(cs227b.teamIago.resolver.Substitution)
*/
public Expression apply(Substitution sigma) {
return new Predicate(operator,operands.apply(sigma));
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Expression#eval(cs227b.teamIago.resolver.Substitution, cs227b.teamIago.resolver.Theory)
*/
public ArrayList eval(Substitution sigma, Theory t) throws InterruptedException {
Expression s = ground(t,sigma);
if (t.interrupted()) throw new InterruptedException();
if (!s.equals(this)) return s.eval(sigma,t);
t.enterChain(this);
// Check for memoized values
// We're only storing chained,
// so disproven is still fine, but
// don't use proven
if (t.checkDisproven(this)) {
t.exitChain(this,false,null);
return null;
}
ArrayList answers = new ArrayList();
ExpList candidates = t.getCandidates(this);
Substitution psi;
for (int i = 0; i < candidates.size(); i++)
{
if (t.interrupted()) throw new InterruptedException();
psi = mgu(candidates.get(i), sigma,t);
if (psi != null) answers.add(psi);
}
boolean proven = (answers.size() > 0);
t.exitChain(this,proven,answers);
if (proven) return answers;
else return null;
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Evaluable#evalOne(cs227b.teamIago.resolver.Expression, cs227b.teamIago.resolver.Substitution, cs227b.teamIago.resolver.Theory)
*/
public Substitution evalOne(Substitution sigma, Theory t) throws InterruptedException {
Expression s = ground(t,sigma);
if (t.interrupted()) throw new InterruptedException();
if (!s.equals(this)) return s.evalOne(sigma,t);
t.enterChain(this);
// Check for memoized values
// We're only storing chained,
// so disproven is still fine, but
// don't use proven
if (t.checkDisproven(this)) {
t.exitChain(this,false,null);
return null;
}
ExpList candidates = t.getCandidates(this);
Substitution psi;
for (int i = 0; i < candidates.size(); i++)
{
if (t.interrupted()) throw new InterruptedException();
psi = mgu(candidates.get(i), sigma,t);
if (psi != null)
{
t.exitChain(this,true,psi);
return psi;
}
}
t.exitChain(this,false,null);
return null;
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Expression#chain(cs227b.teamIago.resolver.Substitution, cs227b.teamIago.resolver.Theory)
*/
public ArrayList chain(Substitution sigma, Theory t, boolean cond) throws InterruptedException{
Expression s = ground(t,sigma);
if (t.interrupted()) throw new InterruptedException();
if (!s.equals(this)) return s.chain(sigma,t, cond);
ArrayList answers;
t.enterChain(this);
// Check for memoized values
if (!cond) {
if (t.checkDisproven(this)) {
t.exitChain(this,false,null);
return null;
}
answers = t.checkProven(sigma,this);
if (answers != null) {
t.exitChain(this,true,answers);
return answers;
}
}
answers = new ArrayList();
ExpList candidates = t.getCandidates(this);
Substitution psi;
for (int i = 0; i < candidates.size(); i++)
{
Expression e = candidates.get(i);
if (e instanceof Implication)
{
Implication imp = (Implication) e;
psi = mgu(imp.getConsequence(),sigma,t);
if (psi != null)
{
ExpList prem = imp.getPremises();
// prem = prem.apply(sigma);
if (t.interrupted()) throw new InterruptedException();
ArrayList premList = prem.chain(psi,t, cond);
if (premList != null)
answers.addAll(premList);
}
}
else
{
psi = mgu(candidates.get(i), sigma,t);
if (psi != null) answers.add(psi);
}
}
boolean proven = (answers.size() > 0);
t.exitChain(this,proven,answers);
if (proven) {
// Memoize the values returned
// Must decide if this is a rational
// set of answers for this predicate.
// Given that these integrate the incoming
// substitution, this may not be the case!
// Fixed this by storing only the "restriction"
// of the solution set
// (I think)
if (!cond) t.setProven(this,answers);
return answers;
}
else {
// memoize the failure
if (!cond) t.setDisproven(this);
return null;
}
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Expression#chainOne(cs227b.teamIago.resolver.Substitution, cs227b.teamIago.resolver.Theory)
*/
public Substitution chainOne(Substitution sigma, Theory t, boolean cond) throws InterruptedException{
Expression s = ground(t,sigma);
if (t.interrupted()) throw new InterruptedException();
if (!s.equals(this)) return s.chainOne(sigma,t, cond);
t.enterChain(this);
// Check for memoized values
if (!cond) {
ArrayList allSubs = t.checkProven(sigma,this);
if ((allSubs != null) && (allSubs.size() > 0)) {
Substitution psi = (Substitution) allSubs.get(0);
t.exitChain(this,true,psi);
return psi;
}
if (t.checkDisproven(this)) {
t.exitChain(this,false,null);
return null;
}
}
ExpList candidates = t.getCandidates(this);
Substitution psi;
for (int i = 0; i < candidates.size(); i++)
{
if (candidates.get(i) instanceof Implication)
{
Substitution gamma;
psi = null;
Implication imp = (Implication) candidates.get(i);
gamma = mgu(imp.getConsequence(),sigma,t);
if (gamma != null)
{
ExpList prem = imp.getPremises();
// prem = prem.apply(sigma);
if (t.interrupted()) throw new InterruptedException();
psi = prem.chainOne(gamma,t, cond);
}
}
else psi = mgu(candidates.get(i), sigma,t);
if (psi != null)
{
t.exitChain(this,true,psi);
// Don't set proven for a single unifier--
// we need a full solution-set
return psi;
}
}
t.exitChain(this,false,null);
// Memoize failure
if (!cond) t.setDisproven(this);
return null;
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Expression#buildVolatile()
*/
public boolean buildVolatile(boolean impliedVol) {
amVolatile = amVolatile || impliedVol;
boolean connectVol = amVolatile;
if (operator.equals(aTrue)) connectVol = true;
if (operator.equals(aDoes)) connectVol = true;
if (operator instanceof Variable) connectVol = true;
// Note that the words "true" and "does" aren't
// *inherently* volatile--only as the operators in
// predicates.
connectVol = operator.buildVolatile(connectVol) || connectVol;
amVolatile = amVolatile || connectVol;
operands.buildVolatile(false);
return amVolatile;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return ((operator.hashCode()*PRED_OPERATOR_HASH_SEED +
hashProd(operands,PRED_OPERANDS_HASH_MUL,PRED_OPERANDS_HASH_SEED)))
*PRED_OPERATOR_HASH_SEED % HASH_QUAD;
}
/* (non-Javadoc)
* @see cs227b.teamIago.resolver.Expression#mapTo(cs227b.teamIago.resolver.Substitution, cs227b.teamIago.resolver.Expression)
*/
public Substitution mapTo(Substitution sigma, Expression e) {
Substitution psi = null;
if (e instanceof Predicate) {
Predicate other = (Predicate) e;
psi = operator.mapTo(sigma,other.operator);
if (psi != null) psi = operands.mapTo(psi,other.operands);
}
return psi;
}
}