/*
* Created on Apr 19, 2005
*
* Something like
* ArrayList<Expression> for Java < 1.5.0
*
* Implements some of the logic functions
*/
package cs227b.teamIago.resolver;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Nick
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class ExpList implements Serializable {
protected ArrayList exps;
protected boolean amVolatile;
protected final int EXPLIST_HASH_SEED = 2147073697;
public ExpList() {
exps = new ArrayList();
amVolatile = false;
}
public ExpList(ArrayList al)
{
this();
if (al == null) return;
for (int i = 0; i < al.size(); i++)
{
Object obj = al.get(i);
if (!(obj instanceof Expression))
{
System.err.println("Error: cannot construct ExpList from ArrayList which contains classes not derived from Expression");
System.exit(-1);
}
add((Expression)obj);
}
}
public ExpList(Expression[] expArray){
this();
addAll(expArray);
}
public ExpList(Collection c) {
this();
addAll(c);
}
public ExpList(ExpList l){
this();
for (int i = 0; i < l.size(); i++) {
exps.add(l.get(i));
}
amVolatile = l.amVolatile;
}
// For purposes of chaining, etc,
// an expression list is treated as an extended
// "and," as with its use for premises
// in the "Implication" class.
public ArrayList chain(Substitution sigma, Theory t, boolean cond) throws InterruptedException
{
t.enterChain(this);
ArrayList psis, deltas, answers;
if (exps.size() == 0)
{
psis = new ArrayList();
psis.add(sigma);
t.exitChain(this,true,psis);
return psis;
}
if (t.interrupted()) throw new InterruptedException();
psis = get(0).chain(sigma,t, cond);
if ((psis == null) || (psis.size() == 0))
{
t.exitChain(this,false,null);
return null;
}
for (int i = 1; i < size(); i++)
{
deltas = new ArrayList();
for (int j = 0; j < psis.size(); j++)
{
ArrayList gammas;
Substitution onePsi;
onePsi = (Substitution) psis.get(j);
if (t.interrupted()) throw new InterruptedException();
gammas = get(i).chain(onePsi,t, cond);
if (gammas != null) deltas.addAll(gammas);
}
if (deltas.size() == 0) {
t.exitChain(this,false,null);
return null;
}
psis = deltas;
}
if (psis.size() > 0) {
t.exitChain(this,true,psis);
return psis;
}
else {
t.exitChain(this,false,null);
return null;
}
}
public Substitution chainOne(Substitution sigma, Theory t, boolean cond) throws InterruptedException
{
t.enterChain(this);
ArrayList psis, deltas, answers;
if (exps.size() == 0)
{
t.exitChain(this,true,sigma);
return sigma;
}
if (t.interrupted()) throw new InterruptedException();
psis = get(0).chain(sigma,t, cond);
if ((psis == null) || (psis.size() == 0))
{
t.exitChain(this,false,null);
return null;
}
int last = exps.size() - 1;
if (last == 0) {
Substitution aleph = (Substitution) psis.get(0);
if (t.interrupted()) throw new InterruptedException();
t.exitChain(this,true,aleph);
return aleph;
}
for (int i = 1; i < last; i++)
{
deltas = new ArrayList();
for (int j = 0; j < psis.size(); j++)
{
ArrayList gammas;
Substitution onePsi;
onePsi = (Substitution) psis.get(j);
if (t.interrupted()) throw new InterruptedException();
gammas = get(i).chain(onePsi,t, cond);
if (gammas != null) deltas.addAll(gammas);
}
if (deltas.size() == 0) {
t.exitChain(this,false,null);
return null;
}
psis = deltas;
}
// It's not that much of a savings, but
// for the last expression,
// we can stop as soon as we find a single
// working unifier if we're only looking for
// one answer.
Expression lastExp = get(last);
for (int k = 0; k < psis.size(); k++)
{
Substitution onePsi, oneGamma;
onePsi = (Substitution) psis.get(k);
if (t.interrupted()) throw new InterruptedException();
oneGamma = lastExp.chainOne(onePsi,t, cond);
if (oneGamma != null) {
t.exitChain(this,true,oneGamma);
return oneGamma;
}
}
t.exitChain(this,false,null);
return null;
}
public ArrayList eval(Substitution sigma, Theory t) throws InterruptedException
{
t.enterChain(this);
ArrayList psis, deltas, answers;
if (exps.size() == 0)
{
psis = new ArrayList();
psis.add(sigma);
t.exitChain(this,true,psis);
return psis;
}
if (t.interrupted()) throw new InterruptedException();
psis = get(0).eval(sigma,t);
for (int i = 0; i < exps.size(); i++)
{
deltas = new ArrayList();
for (int j = 0; j < psis.size(); j++)
{
ArrayList gammas;
Substitution onePsi;
onePsi = (Substitution) psis.get(i);
if (t.interrupted()) throw new InterruptedException();
gammas = get(i).eval(onePsi,t);
if (gammas != null) deltas.addAll(gammas);
}
if (deltas.size() == 0){
t.exitChain(this,false,null);
return null;
}
psis = deltas;
}
if (psis.size() > 0)
{
t.exitChain(this,true,psis);
return psis;
}
else {
t.exitChain(this,false,null);
return null;
}
}
public Substitution evalOne(Substitution sigma, Theory t) throws InterruptedException
{
t.enterChain(this);
ArrayList psis, deltas, answers;
if (exps.size() == 0)
{
t.exitChain(this,true,sigma);
return sigma;
}
psis = get(0).eval(sigma,t);
if ((psis == null) || (psis.size() == 0))
{
t.exitChain(this,false,null);
return null;
}
int last = exps.size() - 1;
if (last == 0) {
Substitution aleph = (Substitution) psis.get(0);
t.exitChain(this,true,aleph);
return aleph;
}
for (int i = 0; i < last; i++)
{
deltas = new ArrayList();
for (int j = 0; j < psis.size(); j++)
{
ArrayList gammas;
Substitution onePsi;
onePsi = (Substitution) psis.get(j);
if (t.interrupted()) throw new InterruptedException();
gammas = get(i).eval(onePsi,t);
if (gammas != null) deltas.addAll(gammas);
}
if (deltas.size() == 0) {
t.exitChain(this,false,null);
return null;
}
psis = deltas;
}
// It's not that much of a savings, but
// for the last expression,
// we can stop as soon as we find a single
// working unifier if we're only looking for
// one answer.
Expression lastExp = get(last);
for (int k = 0; k < psis.size(); k++)
{
Substitution onePsi, oneGamma;
onePsi = (Substitution) psis.get(k);
if (t.interrupted()) throw new InterruptedException();
oneGamma = lastExp.evalOne(onePsi,t);
if (oneGamma != null) {
t.exitChain(this,true,oneGamma);
return oneGamma;
}
}
t.exitChain(this,false,null);
return null;
}
public ExpList removeDuplicates()
{
ExpList culled = new ExpList();
for (int i = 0; i < size(); i++)
{
Expression e = get(i);
if (!culled.contains(e)) culled.add(e);
}
return culled;
}
public boolean occurs(Variable var) {
for (int i = 0; i < exps.size(); i++)
{
if (get(i).occurs(var)) return true;
}
return false;
}
public ExpList apply(Substitution sigma)
{
ExpList dup = new ExpList();
for (int i = 0; i < exps.size(); i++)
dup.exps.add(get(i).apply(sigma));
return dup;
}
public Substitution mgu(ExpList target, Substitution sigma, Theory t)
{
Substitution temp = sigma;
if (target.size() != size()) return null;
for (int i = 0; (temp != null) && (i < size()); i++)
temp = get(i).mgu(target.get(i),temp,t);
return temp;
}
public long getMaxVarNum()
{
long curMax = Long.MIN_VALUE;
for (int i = 0; i < size(); i++)
{
long temp = get(i).getMaxVarNum();
if (temp > curMax) curMax = temp;
}
return curMax;
}
public ExpList getVars()
{
ExpList gather = new ExpList();
for (int i = 0; i < size(); i++)
{
ExpList temp = get(i).getVars();
if (temp != null) gather.addAll(temp);
}
return gather;
}
public ArrayList toArrayList()
{
return exps;
}
/*
*/
public void add(int i, Expression e) {
amVolatile = amVolatile || e.buildVolatile(false);
exps.add(i,e);
}
/*
*/
public boolean add(Expression e) {
amVolatile = amVolatile || e.buildVolatile(false);
return exps.add(e);
}
/*
*/
public boolean add (ExpList l){
boolean flag = true;
for (int i = 0; i < l.size(); i++) {
Expression e = l.get(i);
amVolatile = amVolatile || e.buildVolatile(false);
if (!exps.add(e))
flag = false;
}
return flag;
}
public void addAll(Expression[] eArr) {
if (eArr == null) return;
for (int i = 0; i < eArr.length; ++i) {
amVolatile = amVolatile || eArr[i].buildVolatile(false);
add(eArr[i]);
}
}
public void addAll(Collection c) {
if (c == null) return;
for (Iterator i = c.iterator(); i.hasNext();) {
Object o = i.next();
if (o instanceof Expression) {
Expression e = (Expression) o;
amVolatile = amVolatile || e.buildVolatile(false);
add(e);
}
}
}
public void addAll(ExpList eList) {
if (eList == null) return;
for (int i = 0; i < eList.size(); ++i) {
amVolatile = amVolatile || eList.get(i).buildVolatile(false);
add(eList.get(i));
}
}
/*
*/
public void clear() {
exps.clear();
}
/*
*/
public boolean contains(Expression e) {
return exps.contains(e);
}
public boolean containsAll(ExpList eList) {
if (eList == null) return true;
for (int i = 0; i < eList.size(); ++i) {
if (!contains(eList.get(i))) return false;
}
return true;
}
/*
*/
public Expression get(int i) {
return (Expression) exps.get(i);
}
/*
*/
public int indexOf(Expression e) {
return exps.indexOf(e);
}
/*
*/
public boolean isEmpty() {
return exps.isEmpty();
}
/*
*/
public int lastIndexOf(Expression e) {
return exps.lastIndexOf(e);
}
/*
*/
public Expression remove(int i) {
return (Expression) exps.remove(i);
}
/*
*/
public boolean remove(Expression e) {
return exps.remove(e);
}
/*
*/
public Expression set(int i, Expression e) {
return (Expression) exps.set(i,e);
}
/*
*/
public int size() {
return exps.size();
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
if (obj instanceof ExpList)
{
ExpList other = (ExpList) obj;
if (other.size() != size()) return false;
for (int i = 0; i < size(); i++)
if (!(get(i).equals(other.get(i)))) return false;
return true;
}
else if (obj instanceof Collection) {
Collection c = (Collection) obj;
if (c.size() != size()) return false;
Iterator it = c.iterator();
for (int i = 0; i < size(); i++)
{
if (!(get(i).equals(it.next()))) return false;
}
return true;
}
return false;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer s = new StringBuffer();
for (int i = 0; i < size(); i++)
{
s.append(get(i).toString()).append(' ');
}
return s.toString();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
long tempCode = 0;
for (int i = 0; i < size(); i++)
tempCode += get(i).hashCode();
return (int)tempCode * EXPLIST_HASH_SEED % Expression.HASH_QUAD;
}
public boolean buildVolatile(boolean impliedVol) {
amVolatile = amVolatile || impliedVol;
for (int i = 0; i < exps.size(); ++i) {
amVolatile =
((Expression) exps.get(i)).buildVolatile(false) ||
amVolatile;
}
return amVolatile;
}
public boolean isVolatile() {
return amVolatile;
}
public void resetVolatile() {
amVolatile = false;
}
public Substitution mapTo(Substitution sigma, ExpList eL) {
Substitution psi = sigma;
if (eL.size() != size()) return null;
for (int i = 0; (psi != null) && (i < size()); i++)
psi = get(i).mapTo(psi,eL.get(i));
return psi;
}
}