/** * Author: Georg Hofferek <georg.hofferek@iaik.tugraz.at> */ package at.iaik.suraq.smtlib.formula; import java.io.BufferedWriter; import java.io.IOException; import java.io.Writer; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import at.iaik.suraq.exceptions.SuraqException; import at.iaik.suraq.sexp.SExpression; import at.iaik.suraq.sexp.Token; import at.iaik.suraq.smtlib.SMTLibObject; import at.iaik.suraq.util.FormulaCache; import at.iaik.suraq.util.HashTagContainer; /** * @author Georg Hofferek <georg.hofferek@iaik.tugraz.at> * */ public class FormulaTerm extends PropositionalTerm { /** * */ private static final long serialVersionUID = -7262583554346618516L; /** * The formula that represents this term. */ private final Formula formula; /** * * Constructs a new <code>FormulaTerm</code>. * * @param formula * the formula that represents this term. */ private FormulaTerm(Formula formula) { this.formula = formula.deepFormulaCopy(); } /** * Creates and returns a new <code>FormulaTerm</code> for the given * <code>formula</code>, unless the <code>formula</code> is already a * <code>PropositionalTerm</code>, in which case it is returned unaltered. * * @param formula * the formula to encapsulate * @return either a <code>FormulaTerm</code> encapsulating * <code>formula</code>, or <code>formula</code> itself, if it * already is a <code>PropositionalTerm</code>. */ public static PropositionalTerm create(Formula formula) { if (formula instanceof PropositionalTerm) return (PropositionalTerm) formula; else return FormulaCache.formulaTerm.put(new FormulaTerm(formula)); } /** * @see at.iaik.suraq.smtlib.formula.Formula#deepFormulaCopy() */ @Override public Formula deepFormulaCopy() { return this; // experimental // return new FormulaTerm(formula); } /** * returns the formula of the <code>FormulaTerm</code>. * * @return the formula */ public Formula getFormula() { return formula.deepFormulaCopy(); } /** * @see at.iaik.suraq.smtlib.formula.Formula#negationNormalForm() */ @Override public Formula negationNormalForm() throws SuraqException { return FormulaTerm.create(formula.negationNormalForm()); } /** * @see at.iaik.suraq.smtlib.formula.Formula#substituteFormula(Map) */ @Override public Formula substituteFormula(Map<Token, ? extends Term> paramMap, Map<SMTLibObject, SMTLibObject> done) { if (done.containsKey(this)) { assert (done.get(this) != null); assert (done.get(this) instanceof Formula); return (Formula) done.get(this); } Formula result = FormulaTerm.create(formula.substituteFormula(paramMap, done)); assert (result != null); done.put(this, result); return result; } /** * @see at.iaik.suraq.smtlib.formula.PropositionalTerm#flatten() */ @Override public PropositionalTerm flatten() { return FormulaTerm.create(formula.flatten()); } /** * @see at.iaik.suraq.smtlib.formula.Term#deepTermCopy() */ @Override public Term deepTermCopy() { return (FormulaTerm) deepFormulaCopy(); } /** * @see at.iaik.suraq.smtlib.formula.Term#getArrayVariables() */ @Override public void getArrayVariables(Set<ArrayVariable> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getArrayVariables(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Term#getDomainVariables() */ @Override public void getDomainVariables(Set<DomainVariable> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getDomainVariables(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Term#getPropositionalVariables() */ @Override public void getPropositionalVariables(Set<PropositionalVariable> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getPropositionalVariables(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Term#getFunctionMacroNames() */ @Override public void getFunctionMacroNames(Set<String> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getFunctionMacroNames(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Term#getFunctionMacros() */ @Override public void getFunctionMacros(Set<FunctionMacro> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getFunctionMacros(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Term#getUninterpretedFunctionNames() */ @Override public void getUninterpretedFunctionNames(Set<String> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getUninterpretedFunctionNames(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Term#substituteTerm(Map) */ @Override public Term substituteTerm(Map<Token, ? extends Term> paramMap, Map<SMTLibObject, SMTLibObject> done) { return (FormulaTerm) substituteFormula(paramMap, done); } /** * @see at.iaik.suraq.smtlib.formula.Term#getIndexSet() */ @Override public Set<DomainTerm> getIndexSet() throws SuraqException { return formula.getIndexSet(); } /** * @see at.iaik.suraq.smtlib.formula.Term#toSmtlibV2() */ @Override public SExpression toSmtlibV2() { return formula.toSmtlibV2(); } /** * @see at.iaik.suraq.smtlib.formula.Term#arrayPropertiesToFiniteConjunctions(java.util.Set) */ @Override public Formula arrayPropertiesToFiniteConjunctions(Set<DomainTerm> indexSet) { if (formula instanceof ArrayProperty) return FormulaTerm.create(((ArrayProperty) formula) .toFiniteConjunction(indexSet)); // TODO: the line before maybe returns something wrong because // toFiniteConjunction returns And else return FormulaTerm.create(formula .arrayPropertiesToFiniteConjunctions(indexSet)); } @Override public Term arrayPropertiesToFiniteConjunctionsTerm(Set<DomainTerm> indexSet) { if (formula instanceof ArrayProperty) return FormulaTerm.create(((ArrayProperty) formula) .toFiniteConjunction(indexSet)); // TODO: the line before maybe returns something wrong because // toFiniteConjunction returns And else return FormulaTerm.create(formula .arrayPropertiesToFiniteConjunctions(indexSet)); } /** * @see at.iaik.suraq.smtlib.formula.Term#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) { return FormulaTerm.create(formula.removeArrayWrites(topLevelFormula, constraints, noDependenceVars)); } @Override public Term removeArrayWritesTerm(Formula topLevelFormula, Set<Formula> constraints, Set<Token> noDependenceVars) { return FormulaTerm.create(formula.removeArrayWrites(topLevelFormula, constraints, noDependenceVars)); } /** * @see at.iaik.suraq.smtlib.formula.Term#arrayReadsToUninterpretedFunctions(java.util.Set) */ @Override public Formula arrayReadsToUninterpretedFunctions( Set<Token> noDependenceVars) { return FormulaTerm.create(formula .arrayReadsToUninterpretedFunctions(noDependenceVars)); } @Override public Term arrayReadsToUninterpretedFunctionsTerm( Set<Token> noDependenceVars) { return FormulaTerm.create(formula .arrayReadsToUninterpretedFunctions(noDependenceVars)); } /** * @see at.iaik.suraq.smtlib.formula.Term#getUninterpretedFunctions() */ @Override public void getUninterpretedFunctions(Set<UninterpretedFunction> result, Set<SMTLibObject> done) { if (done.contains(this)) return; formula.getUninterpretedFunctions(result, done); done.add(this); } /** * * @see at.iaik.suraq.smtlib.formula.Term#substituteUninterpretedFunction(java.util.Map, * java.util.Map) */ @Override public PropositionalTerm substituteUninterpretedFunction( Map<Token, UninterpretedFunction> substitutions, Map<SMTLibObject, SMTLibObject> done) { if (done.get(this) != null) { assert (done.get(this) instanceof FormulaTerm); return (FormulaTerm) done.get(this); } Formula formula = this.formula; if (formula instanceof UninterpretedPredicateInstance) { Token key = ((UninterpretedFunctionInstance) formula).getFunction() .getName(); if (substitutions.containsKey(key)) { try { formula = UninterpretedPredicateInstance.create( substitutions.get(key), ((UninterpretedFunctionInstance) formula) .getParameters()); } catch (SuraqException exc) { throw new RuntimeException( "Unexpected situation while subsituting uninterpreted function"); } } List<DomainTerm> paramNew = new ArrayList<DomainTerm>(); for (DomainTerm param : ((UninterpretedFunctionInstance) formula) .getParameters()) paramNew.add(param.substituteUninterpretedFunction( substitutions, done)); try { formula = UninterpretedPredicateInstance.create( ((UninterpretedPredicateInstance) formula) .getFunction(), paramNew, assertPartition); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } // (UninterpretedFunction function,List<DomainTerm> parameters, int // partition // ... create new formula with parameters... } formula = formula.substituteUninterpretedFunction(substitutions, done); PropositionalTerm result = FormulaTerm.create(formula); done.put(this, result); return result; } /** * @see at.iaik.suraq.smtlib.formula.Term#makeArrayReadsSimple(at.iaik.suraq.smtlib.formula.Formula, * java.util.Set, java.util.Set) */ @Override public Formula makeArrayReadsSimple(Formula topLevelFormula, Set<Formula> constraints, Set<Token> noDependenceVars) { return FormulaTerm.create(formula.makeArrayReadsSimple(topLevelFormula, constraints, noDependenceVars)); } @Override public Term makeArrayReadsSimpleTerm(Formula topLevelFormula, Set<Formula> constraints, Set<Token> noDependenceVars) { return FormulaTerm.create(formula.makeArrayReadsSimple(topLevelFormula, constraints, noDependenceVars)); } /** * @see at.iaik.suraq.smtlib.formula.Term#uninterpretedPredicatesToAuxiliaryVariables(at.iaik.suraq.smtlib.formula.Formula, * java.util.Set, java.util.Set) */ /* * @Override public FormulaTerm uninterpretedPredicatesToAuxiliaryVariables( * Formula topLeveFormula, Set<Formula> constraints, Set<Token> * noDependenceVars) { return new FormulaTerm( * formula.uninterpretedPredicatesToAuxiliaryVariables( topLeveFormula, * constraints, noDependenceVars)); } */ /** * Returns the elements assert-partition. * * @return assert-partition of the element. */ @Override public Set<Integer> getPartitionsFromSymbols() { return formula.getPartitionsFromSymbols(); } /** * @see at.iaik.suraq.smtlib.formula.Formula#transformToConsequentsForm() */ @Override public OrFormula transformToConsequentsForm() { return (OrFormula) transformToConsequentsForm(false, true); } /** * @see at.iaik.suraq.smtlib.formula.Formula#transformToConsequentsForm(boolean, * boolean) */ @Override public Formula transformToConsequentsForm(boolean notFlag, boolean firstLevel) { return this.formula.transformToConsequentsForm(notFlag, firstLevel); } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return formula.hashCode(); } /** * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof FormulaTerm)) return false; if (this.formula == ((FormulaTerm) obj).formula) return true; if (this.hashCode() != obj.hashCode()) return false; return formula.equals(((FormulaTerm) obj).formula); } /** * @see at.iaik.suraq.smtlib.formula.Formula#tseitinEncode(java.util.List, * java.util.Map) */ @Override public Formula tseitinEncode(List<OrFormula> clauses, Map<PropositionalVariable, Formula> encoding, Map<Formula, PropositionalVariable> done, int partition) { return formula.tseitinEncode(clauses, encoding, done, partition); } /** * @see at.iaik.suraq.formula.Term#uninterpretedPredicatesToAuxiliaryVariables(at.iaik.suraq.formula.Formula, * java.util.Map, java.util.Map) */ @Override public Formula uninterpretedPredicatesToAuxiliaryVariables( Formula topLeveFormula, Map<String, List<PropositionalVariable>> predicateInstances, Map<PropositionalVariable, List<DomainTerm>> instanceParameters, Set<Token> noDependenceVars) { Formula formula = this.formula; if (formula instanceof UninterpretedPredicateInstance) formula = ((UninterpretedPredicateInstance) formula) .applyReplaceUninterpretedPredicates(topLeveFormula, predicateInstances, instanceParameters, noDependenceVars); else formula = formula.uninterpretedPredicatesToAuxiliaryVariables( topLeveFormula, predicateInstances, instanceParameters, noDependenceVars); return FormulaTerm.create(formula); } @Override public Term uninterpretedPredicatesToAuxiliaryVariablesTerm( Formula topLeveFormula, Map<String, List<PropositionalVariable>> predicateInstances, Map<PropositionalVariable, List<DomainTerm>> instanceParameters, Set<Token> noDependenceVars) { Formula formula = this.formula; if (formula instanceof UninterpretedPredicateInstance) formula = ((UninterpretedPredicateInstance) formula) .applyReplaceUninterpretedPredicates(topLeveFormula, predicateInstances, instanceParameters, noDependenceVars); else formula = formula.uninterpretedPredicatesToAuxiliaryVariables( topLeveFormula, predicateInstances, instanceParameters, noDependenceVars); return FormulaTerm.create(formula); } /** * @see at.iaik.suraq.formula.Term#uninterpretedFunctionsToAuxiliaryVariables(at.iaik.suraq.formula.Formula, * java.util.Map, java.util.Map) */ @Override public Formula uninterpretedFunctionsToAuxiliaryVariables( Formula topLeveFormula, Map<String, List<DomainVariable>> functionInstances, Map<DomainVariable, List<DomainTerm>> instanceParameters, Set<Token> noDependenceVars) { return FormulaTerm .create(formula.uninterpretedFunctionsToAuxiliaryVariables( topLeveFormula, functionInstances, instanceParameters, noDependenceVars)); } @Override public Term uninterpretedFunctionsToAuxiliaryVariablesTerm( Formula topLeveFormula, Map<String, List<DomainVariable>> functionInstances, Map<DomainVariable, List<DomainTerm>> instanceParameters, Set<Token> noDependenceVars) { return FormulaTerm .create(formula.uninterpretedFunctionsToAuxiliaryVariables( topLeveFormula, functionInstances, instanceParameters, noDependenceVars)); } @Override public Formula replaceEquivalences(Formula topLevelFormula, Map<EqualityFormula, String> replacements, Set<Token> noDependenceVars) { Formula formula = this.formula.replaceEquivalences(topLevelFormula, replacements, noDependenceVars); return FormulaTerm.create(formula); } @Override public PropositionalTerm removeDomainITE(Formula topLevelFormula, Set<Token> noDependenceVars, List<Formula> andPreList) { Formula formula = this.formula.removeDomainITE(topLevelFormula, noDependenceVars, andPreList); return FormulaTerm.create(formula); } /** * @see at.iaik.suraq.smtlib.formula.Formula#uninterpretedFunctionsBackToArrayReads(java.util.Set) */ @Override public Formula uninterpretedFunctionsBackToArrayReads( Set<ArrayVariable> arrayVars, Map<SMTLibObject, SMTLibObject> done) { if (done.get(this) != null) return (Formula) done.get(this); Formula result = FormulaTerm.create((Formula) formula .uninterpretedFunctionsBackToArrayReads(arrayVars, done)); done.put(this, result); return result; } /** * @see at.iaik.suraq.smtlib.formula.Term#removeArrayITE(at.iaik.suraq.smtlib.formula.Formula, * java.util.Set, java.util.Collection) */ @Override public PropositionalTerm removeArrayITE(Formula topLevelFormula, Set<Token> noDependenceVars, Collection<Formula> constraints) { return FormulaTerm.create(formula.removeArrayITE(topLevelFormula, noDependenceVars, constraints)); } /** * @see at.iaik.suraq.smtlib.formula.Formula#writeOut(java.io.BufferedWriter, * at.iaik.suraq.util.HashTagContainer, boolean) */ @Override public void writeOut(BufferedWriter writer, HashTagContainer tagContainer, boolean handleThisWithTagContainer) throws IOException { formula.writeOut(writer, tagContainer, handleThisWithTagContainer); } /** * @see at.iaik.suraq.smtlib.formula.Term#writeOut(java.io.BufferedWriter, * at.iaik.suraq.util.HashTagContainer) */ @Override public void writeOut(BufferedWriter writer, HashTagContainer tagContainer) throws IOException { writeOut(writer, tagContainer, true); } /** * @see at.iaik.suraq.smtlib.formula.Term#writeTo(java.io.Writer) */ @Override public void writeTo(Writer writer) throws IOException { formula.writeTo(writer); } /** * @see at.iaik.suraq.smtlib.formula.Formula#writeTo(java.io.Writer, * java.util.Map) */ @Override public void writeTo(Writer writer, Map<SMTLibObject, String> definitions) throws IOException { formula.writeTo(writer, definitions); } /** * @see at.iaik.suraq.smtlib.formula.Formula#getLiterals(java.util.Set, * java.util.Set) */ @Override public void getLiterals(Set<Formula> result, Set<Formula> done) { if (done.contains(this)) return; formula.getLiterals(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Formula#numAigNodes(java.util.Set) */ @Override public int numAigNodes(Set<Formula> done) { if (done.contains(this)) return 0; int result = formula.numAigNodes(done); done.add(this); return result; } /** * @see at.iaik.suraq.smtlib.formula.Formula#toAig(TreeMap, java.util.Map) */ @Override public int toAig(TreeMap<Integer, Integer[]> aigNodes, Map<Formula, Integer> done) { return formula.toAig(aigNodes, done); } /** * @see at.iaik.suraq.smtlib.formula.Formula#size(boolean, java.util.Map) */ @Override public BigInteger size(boolean expandDAG, Map<Formula, BigInteger> done) { return formula.size(expandDAG, done); } /** * @see at.iaik.suraq.smtlib.formula.Formula#computeParents(java.util.Map, * java.util.Set) */ @Override public void computeParents(Map<Formula, Set<Formula>> parents, Set<Formula> done) { if (done.contains(this)) return; Set<Formula> childsParents = parents.get(formula); if (childsParents == null) { childsParents = new TreeSet<Formula>(); parents.put(formula, childsParents); } assert (childsParents != null); childsParents.add(this); formula.computeParents(parents, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Formula#computeSubformulasWithOnlyLeafChildren(java.util.Set, * java.util.HashSet) */ @Override public void computeSubformulasWithOnlyLeafChildren( Set<Formula> onlyLeafChildren, Set<Formula> leaves, Set<Formula> done) { if (done.contains(this)) return; if (leaves.contains(this)) { done.add(this); return; } boolean result = true; if (!leaves.contains(formula)) result = false; formula.computeSubformulasWithOnlyLeafChildren(onlyLeafChildren, leaves, done); if (result) onlyLeafChildren.add(this); done.add(this); return; } /** * @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; formula.getTerms(result, done); done.add(this); } /** * @see at.iaik.suraq.smtlib.formula.Formula#dependsOnlyOn(java.util.Set) */ @Override public boolean dependsOnlyOn(Set<Formula> formulaSet) { return formula.dependsOnlyOn(formulaSet); } }