/**
* 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.Serializable;
import java.io.Writer;
import java.math.BigInteger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import at.iaik.suraq.exceptions.SuraqException;
import at.iaik.suraq.sexp.Token;
import at.iaik.suraq.smtlib.SMTLibObject;
import at.iaik.suraq.util.HashTagContainer;
/**
*
* This represents formulas in the fragment introduced in the MemoCODE'11 paper.
*
* @author Georg Hofferek <georg.hofferek@iaik.tugraz.at>
*
*/
public interface Formula extends SMTLibObject, Serializable {
@Override
public boolean equals(Object formula);
/**
* Returns a deep copy of the formula.
*
* @return a deep copy of the formula
*/
public Formula deepFormulaCopy();
/**
* Computes the index set of this formula. (Cf. Bradley/Manna, p. 295) The
* set does <em>not</em> yet include the new variable <code>lambda</code>.
*
* @return the index set.
* @throws SuraqException
* if the formula contains array write expressions, or
* computation otherwise fails.
*/
public Set<DomainTerm> getIndexSet() throws SuraqException;
/**
* Returns a copy of this formula in negation normal form.
*
* @return a copy of this formula in negation normal form.
* @throws SuraqException
* if the formula cannot be converted to NNF, e.g. due to
* resulting invalid array properties.
*/
public Formula negationNormalForm() throws SuraqException;
/**
* Returns a new formula that is a version of this formula, with
* substitutions performed according to the given map. E.g., the local terms
* of a function macro's body are converted to the (more) global terms of
* the macro's instance. Terms which are not found in the map are returned
* unchanged.
*
* @param paramMap
* the map to convert local terms to the caller's scope
* @return a (new) formula, converted according to the given map.
*/
public Formula substituteFormula(Map<Token, ? extends Term> paramMap,
Map<SMTLibObject, SMTLibObject> done);
@Override
public Formula substituteUninterpretedFunction(
Map<Token, UninterpretedFunction> substitutions,
Map<SMTLibObject, SMTLibObject> done);
/**
* Replaces all array equalities in this formula by equivalent array
* properties.
*/
public Formula removeArrayEqualities();
/**
* Reduces all array properties in this formula to finite conjunctions over
* the given index set. The index set must already include the special
* variable lambda.
*
* @param indexSet
* the index set.
*/
public Formula arrayPropertiesToFiniteConjunctions(Set<DomainTerm> indexSet);
/**
* Simplifies this formula by (Boolean) constant propagation and some
* limited constraint propagation. If the formula cannot be simplified, it
* is returned unchanged (not copied!). Otherwise a simplified formula is
* returned. Unchanged subformulas are not copied!
*
* @return this formula, simplified by constant propagation and some
* constraint propagation.
*/
public Formula simplify();
/**
* Returns a (new) flattened version of this formula. I.e., macro instances
* are replaced by their respective instantiations.
*
* @return a flattened copy of this formula.
*/
public Formula flatten();
/**
* Recursively replaces all array writes by applying the write axiom.
*
* @param topLevelFormula
* The top-level formula on which the recursion started. (Needed
* to determine fresh variable names.)
* @param constraints
* A set to which constraints coming from write-axiom application
* will be added.
* @param noDependenceVars
* A set of variables on which the controller may not depend.
* Newly created variables on which the controller may not depend
* are added to this set during recursion.
*
*/
public Formula removeArrayWrites(Formula topLevelFormula,
Set<Formula> constraints, Set<Token> noDependenceVars);
/**
* Replaces all array-read expressions with uninterpreted function instances
* of the same name.
*
* FIXME: This does not deal with <code>define-fun</code> macros right, if
* array variables are used as macro parameters. Since uninterpreted
* functions cannot be used as macro parameters, one would have something
* more complex, such as making copies of macros.
*
*
* @param noDependenceVars
* the variables on which the controller may not depend. New such
* variables are added to this set during recursion.
*
*/
public Formula arrayReadsToUninterpretedFunctions(
Set<Token> noDependenceVars);
/**
* Replaces all indices of array reads which are not simple domain variables
* with fresh simple domain variables. Corresponding equality constraints
* are added to the given set.
*
* @param topLevelFormula
* the top level formula (for finding fresh variable names).
* @param constraints
* the set to add new constraints to.
* @param noDependenceVars
* the set of variables on which the controller may not depend.
* New variables might be added to this set.
*/
public Formula makeArrayReadsSimple(Formula topLevelFormula,
Set<Formula> constraints, Set<Token> noDependenceVars);
/**
* Creates a copy of this formula in which instances of uninterpreted
* predicates (functions of return type Bool) are replaced with auxiliary
* variables and generates corresponding constraints.
*
* @param topLeveFormula
* the top level formula (for finding fresh variable names).
* @param constraints
* the set to add new constraints to.
* @param noDependenceVars
* the set of variables on which the controller may not depend.
* New variables might be added to this set.
* @return a new formula with uninterpreted predicates replaced by auxiliary
* variables.
*/
/*
* public Formula uninterpretedPredicatesToAuxiliaryVariables( Formula
* topLeveFormula, Set<Formula> constraints, Set<Token> noDependenceVars);
*/
/**
* Transforms formulas to consequent formulas. Consequent formulas should
* have the following structure: - each atom is either a positive equality
* of two terms, a propositional variable, or an uninterpreted predicate. -
* each literal is either an atom or a negation of an atom. - formula is
* always an OR-formula which consists of at least one literal.
*
* @return if transformation is possible, returns formula, otherwise returns
* null.
*
*/
public OrFormula transformToConsequentsForm();
/**
* Transforms formulas to consequent formulas. Consequent formulas should
* have the following structure: - each atom is either a positive equality
* of two terms, a propositional variable, or an uninterpreted predicate. -
* each literal is either an atom or a negation of an atom. - formula is
* always an OR-formula which consists of at least one literal.
*
* @param notFlag
* indicates that the number of NOT operations occurred so far is
* even or odd . (notFlag=true equals an odd number)
* @param firstLevel
* indicates that the function call appeared in the first
* recursion step.
* @return if transformation is possible, returns formula, otherwise returns
* null.
*
*/
public Formula transformToConsequentsForm(boolean notFlag,
boolean firstLevel);
/**
* Performs Tseitin encoding to transform a formula into CNF.
*
* @param clauses
* a (call-by-reference) parameter to which all the clauses of
* the CNF will be added.
*
* @param encoding
* a (call-by-reference) parameter, which will contain the
* mapping of Tseitin variables to the formulas they represent.
* @param done
* a map of formulas already encoded (to avoid encoding them
* again)
* @param partition
* the partition that is encoded (used to assign fresh Tseitin
* variables to)
* @return the Tseitin variable that represents <code>this</code> formula,
* or the formula itself if it is a literal/constant.
*/
public Formula tseitinEncode(List<OrFormula> clauses,
Map<PropositionalVariable, Formula> encoding,
Map<Formula, PropositionalVariable> done, int partition);
/**
* Replaces instances of uninterpreted predicates in formula with auxiliary
* boolean variables.
*
* @param topLeveFormula
* the top level formula (for finding fresh variable names).
*
* @param predicateInstances
* map containing mapping from predicate names to boolean
* auxiliary variables.
*
* @param instanceParameters
* map containing mapping from boolean auxiliary variables to
* predicate instance parameters.
*
* @return a new formula with uninterpreted predicates replaced by boolean
* auxiliary variables.
*/
public Formula uninterpretedPredicatesToAuxiliaryVariables(
Formula topLeveFormula,
Map<String, List<PropositionalVariable>> predicateInstances,
Map<PropositionalVariable, List<DomainTerm>> instanceParameters,
Set<Token> noDependenceVars);
/**
* Replaces instances of uninterpreted functions in formula with auxiliary
* variables.
*
* @param topLeveFormula
* the top level formula (for finding fresh variable names).
*
* @param functionInstances
* map containing mapping from function names to domain auxiliary
* variables.
*
* @param instanceParameters
* map containing mapping from domain auxiliary variables to
* function instance parameters.
*
* @return a new formula with uninterpreted predicates replaced by auxiliary
* domain variables.
*/
public Formula uninterpretedFunctionsToAuxiliaryVariables(
Formula topLeveFormula,
Map<String, List<DomainVariable>> functionInstances,
Map<DomainVariable, List<DomainTerm>> instanceParameters,
Set<Token> noDependenceVars);
public Formula replaceEquivalences(Formula topLeveFormula,
Map<EqualityFormula, String> replacements,
Set<Token> noDependenceVars);
public Formula removeDomainITE(Formula topLevelFormula,
Set<Token> noDependenceVars, List<Formula> andPreList);
public Formula removeArrayITE(Formula topLevelFormula,
Set<Token> noDependenceVars, Collection<Formula> constraints);
/**
* Writes this formula to the given <code>writer</code>, using veriT style
* hashTags, given via <code>tagContainer</code>. This is used to write
* veriT-style proofs.
*
*
* @param writer
* @param tagContainer
* @param handleThisWithTagContainer
* whether or not to try to handle <code>this</code> formula via
* the <code>tagContainer</code>
*/
public void writeOut(BufferedWriter writer, HashTagContainer tagContainer,
boolean handleThisWithTagContainer) throws IOException;
/**
* Writes this formula to the given writer. This method should write the
* same thing <code>toString</code> would produce.
*
* @param writer
* @throws IOException
*/
public void writeTo(Writer writer) throws IOException;
/**
* Writes this formula to the given <code>writer</code>, using the given
* <code>definitions</code>. The <code>definitions</code> must contain all
* the formulas and terms that are directly referenced by this formula.
*
* @param writer
* @param definitions
* @throws IOException
*/
public void writeTo(Writer writer, Map<SMTLibObject, String> definitions)
throws IOException;
/**
* Adds all literals of this formula to <code>result</code>. Uses
* <code>done</code> as a cache to avoid DAG-unrolling.
*
* @param result
* @param done
*/
public void getLiterals(Set<Formula> result, Set<Formula> done);
/**
* Computes the number of AIG nodes necessary to encode this formula in a
* DAG-aware way.
*
* @param done
* cache to avoid unrolling the DAG.
* @return the number of AIG nodes
*/
public int numAigNodes(Set<Formula> done);
/**
* Computes AIG nodes corresponding to the formula
*
* @param aigNodes
* the definition of the nodes
* @param done
* cache mapping (sub)formulas to AIGER literals (initialize with
* ground literals of the formula)
* @return the AIGER variable representing this formula
*/
public int toAig(TreeMap<Integer, Integer[]> aigNodes,
Map<Formula, Integer> done);
/**
* Computes the size of this formula (in terms of nodes in the syntax tree),
* either with or without expansion of the DAG. Both computations are done
* DAG-aware.
*
* @param expandDAG
* @param done
* @return
*/
public BigInteger size(boolean expandDAG, Map<Formula, BigInteger> done);
/**
* Computes the parent-mapping in this formula. I.e., a node maps to a set
* of its parents.
*
* @param parents
* results will be written to this map
* @param done
* used for DAG-awareness.
*/
public void computeParents(Map<Formula, Set<Formula>> parents,
Set<Formula> done);
/**
* Computes the set of all subformulas which have only "leafs" as their
* subformulas. "Leafs" are constants, variables, equalities, predicates.
*
* @param onlyLeafChildren
* @param done
*/
public void computeSubformulasWithOnlyLeafChildren(
Set<Formula> onlyLeafChildren, Set<Formula> leaves,
Set<Formula> done);
/**
*
* @param formulaSet
* @return <code>true</code> iff this formula depends only on formulas from
* <code>formulaSet</code>.
*/
public boolean dependsOnlyOn(Set<Formula> formulaSet);
/**
* Adds all terms in this formula to the <code>result</code> set. Only adds
* top-level terms, not their subterms.
*
* @param result
* @param done
* cache to avoid unrolling the DAG.
*/
public void getTerms(Set<Term> result, Set<Formula> done);
}