/**
* Author: Georg Hofferek <georg.hofferek@iaik.tugraz.at>
*/
package at.iaik.suraq.smtlib.formula;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import at.iaik.suraq.exceptions.SuraqException;
import at.iaik.suraq.sexp.Token;
import at.iaik.suraq.util.FormulaCache;
import at.iaik.suraq.util.Util;
/**
* A formula consisting of the (in)equality of array terms.
*
* @author Georg Hofferek <georg.hofferek@iaik.tugraz.at>
*
*/
public class ArrayEq extends EqualityFormula {
/**
*
*/
private static final long serialVersionUID = 6969625051610060136L;
/**
*
* Constructs a new <code>ArrayEq</code>.
*
* @param terms
* the terms of the (in)equality.
* @param equal
* <code>true</code> if an equality should be constructed,
* <code>false</code> for an inequality.
*
*/
private ArrayEq(Collection<ArrayTerm> arrayTerms, boolean equal) {
super(arrayTerms, equal);
}
public static ArrayEq create(Collection<ArrayTerm> arrayTerms, boolean equal) {
return (ArrayEq) FormulaCache.equalityFormula.put(new ArrayEq(
arrayTerms, equal));
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#deepFormulaCopy()
*/
@Override
public Formula deepFormulaCopy() {
return this;
/*
* List<ArrayTerm> terms = new ArrayList<ArrayTerm>(); for (Term term :
* this.terms) { terms.add((ArrayTerm) term.deepTermCopy()); } return
* new ArrayEq(terms, equal);
*/
}
/**
* @see at.iaik.suraq.smtlib.formula.EqualityFormula#getIndexSet()
*/
@Override
public Set<DomainTerm> getIndexSet() throws SuraqException {
throw new SuraqException(
"Encountered array equality while computing index set. Should have already been removed.");
}
/**
* @see at.iaik.suraq.smtlib.formula.EqualityFormula#removeArrayEqualitiesTerm()
*/
@Override
public Formula removeArrayEqualities() {
throw new RuntimeException(
"Cannot remove array equalities from an array equality.");
}
/**
* Returns an equivalent formula consisting of (an) array property(s).
*
* @return an equivalent formula consisting of (an) array property(s).
*/
public Formula toArrayProperties() {
Formula newFormula;
// FIXME: chillebold: instead of "this" here should be the
// "topLevelFormula"???
DomainVariable index = DomainVariable.create(Util.freshVarNameCached(
this, "index"));
Set<DomainVariable> uVars = new HashSet<DomainVariable>();
uVars.add(index);
if (equal) {
List<ArrayRead> arrayReads = new ArrayList<ArrayRead>();
for (Term term : terms)
arrayReads.add(ArrayRead.create((ArrayTerm) term, index));
try {
newFormula = ArrayProperty.create(uVars,
PropositionalConstant.create(true),
DomainEq.create(arrayReads, true));
} catch (SuraqException exc) {
throw new RuntimeException(
"Unexptected exception while creatin array property to remove array equality.",
exc);
}
} else { // in case of disequality, make property for each pair.
List<Formula> conjuncts = new ArrayList<Formula>();
for (int i = 0; i < terms.size(); i++) {
for (int j = i + 1; i < terms.size(); j++) {
List<ArrayRead> arrayReads = new ArrayList<ArrayRead>();
arrayReads.add(ArrayRead.create((ArrayTerm) terms.get(i),
index));
arrayReads.add(ArrayRead.create((ArrayTerm) terms.get(j),
index));
try {
conjuncts.add(ArrayProperty.create(uVars,
PropositionalConstant.create(true),
DomainEq.create(arrayReads, true)));
} catch (SuraqException exc) {
throw new RuntimeException(
"Unexptected exception while creatin array property to remove array equality.",
exc);
}
}
}
newFormula = AndFormula.generate(conjuncts);
}
return newFormula;
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#arrayPropertiesToFiniteConjunctions(java.util.Set)
*/
@Override
public Formula arrayPropertiesToFiniteConjunctions(Set<DomainTerm> indexSet) {
throw new RuntimeException(
"arrayPropertiesToFiniteConjunctions cannot be called on an ArrayEq.\nRemove array equalities before reducing properties to conjunctions.");
}
/**
* @see at.iaik.suraq.smtlib.formula.EqualityFormula#removeArrayWrites(at.iaik.suraq.smtlib.formula.Formula,
* java.util.Set, java.util.Set)
*/
@Override
public Formula removeArrayWrites(Formula topLevelFormula,
Set<Formula> constraints, Set<Token> noDependenceVars) {
List<Term> pairs = new ArrayList<Term>();
for (Term term : terms) {
if (term instanceof ArrayWrite) {
pairs.add(((ArrayWrite) term).applyWriteAxiom(topLevelFormula,
constraints, noDependenceVars));
} else {
pairs.add(term.removeArrayWritesTerm(topLevelFormula,
constraints, noDependenceVars));
}
}
try {
return EqualityFormula.create(pairs, equal);
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#transformToConsequentsForm()
*/
@Override
public OrFormula transformToConsequentsForm() {
throw new RuntimeException(
"transformToConsequentsForm cannot be called on an ArrayEq.\nArrays should be removed by now.");
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#transformToConsequentsForm(boolean,
* boolean)
*/
@Override
public Formula transformToConsequentsForm(boolean notFlag,
boolean firstLevel) {
throw new RuntimeException(
"transformToConsequentsForm cannot be called on an ArrayEq.\nArrays should be removed by now.");
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#tseitinEncode(java.util.Map)
*/
@Override
public PropositionalVariable tseitinEncode(List<OrFormula> clauses,
Map<PropositionalVariable, Formula> encoding,
Map<Formula, PropositionalVariable> done, int partition) {
throw new RuntimeException(
"Array equalities should have been removed before Tseitin encoding!");
}
@Override
public Formula replaceEquivalences(Formula topLeveFormula,
Map<EqualityFormula, String> replacements,
Set<Token> noDependenceVars) {
throw new RuntimeException(
"ArrayEq cannot be called on an UninterpretedFunctions.\n"
+ "ArrayEq should be removed by now.");
}
public Formula removeDomainITE(Formula topLevelFormula,
Set<Token> noDependenceVars) {
throw new RuntimeException(
"Arrays must be replaced removing DomainITE.");
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#getLiterals(java.util.Set,
* java.util.Set)
*/
@Override
public void getLiterals(Set<Formula> result, Set<Formula> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#numAigNodes(java.util.Set)
*/
@Override
public int numAigNodes(Set<Formula> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#toAig(TreeMap, java.util.Map)
*/
@Override
public int toAig(TreeMap<Integer, Integer[]> aigNodes,
Map<Formula, Integer> done) {
throw new NotImplementedException();
}
/**
* @see at.iaik.suraq.smtlib.formula.Formula#getTerms(java.util.Set,
* java.util.Set)
*/
@Override
public void getTerms(Set<Term> result, Set<Formula> done) {
if (done.contains(this))
return;
result.addAll(terms);
done.add(this);
}
}