/** * Author: Christoph Hillebold <c.hillebold@student.tugraz.at> */ package at.iaik.suraq.main; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import at.iaik.suraq.sexp.Token; import at.iaik.suraq.smtlib.SMTLibObject; import at.iaik.suraq.smtlib.formula.AndFormula; import at.iaik.suraq.smtlib.formula.DomainEq; import at.iaik.suraq.smtlib.formula.DomainTerm; import at.iaik.suraq.smtlib.formula.DomainVariable; import at.iaik.suraq.smtlib.formula.Formula; import at.iaik.suraq.smtlib.formula.ImpliesFormula; import at.iaik.suraq.smtlib.formula.PropositionalEq; import at.iaik.suraq.smtlib.formula.PropositionalTerm; import at.iaik.suraq.smtlib.formula.PropositionalVariable; import at.iaik.suraq.smtlib.formula.UninterpretedFunction; import at.iaik.suraq.smtlib.formula.UninterpretedFunctionInstance; import at.iaik.suraq.smtlib.formula.UninterpretedPredicateInstance; import at.iaik.suraq.util.DebugHelper; /** * This class is used to perform Ackermann's reduction to a given formula. * * @author Hillebold Christoph * */ public class Ackermann { // these flags activate or deactivate Ackermann's reduction // you can separately deactivate it on predicates and functions. private static boolean _isActive = false; private static boolean _isPredicateActive = true; private static boolean _isFunctionActive = true; // active debug writes out some files to see what's going on private static boolean _debug = true; /** * performs the Ackermann's reduction and removes Functions and Predicates * This method adds noDependenceVars (DomainVars) to the * noDependenceVars-List and removes Functions and Predicates from the * noDependenceVars-List * * @param topLevelFormula * formula to work with * @param noDependenceVars * @return */ public Formula performAckermann(Formula topLevelFormula, Set<Token> noDependenceVars) { // For Debugging issues you can deactivate the Ackermann's reduction by // calling Ackermann.setActive(false); if (!Ackermann._isActive) { System.out .println("* INFO: Didn't perform Ackermann, because it was deactivated."); return topLevelFormula; } // Get all UF-Names and store them to a set of Tokens. System.out.println(" Ackermann: getUninterpretedFunctionNames()"); Set<Token> currentUninterpretedFunctions = new HashSet<Token>(); UninterpretedPredicateInstance.method = Ackermann._isPredicateActive; UninterpretedFunctionInstance.method = Ackermann._isFunctionActive; Set<String> ufs = new HashSet<String>(); topLevelFormula.getUninterpretedFunctionNames(ufs, new HashSet<SMTLibObject>()); for (String var : ufs) currentUninterpretedFunctions.add(Token.generate(var)); UninterpretedPredicateInstance.method = true; UninterpretedFunctionInstance.method = true; // this adds UFs as well as UPs... as expected // ////////////////////////////////////////////////////////// // Substitute UF by Variables if (Ackermann._isFunctionActive) { System.out .println(" Ackermann: uninterpretedFunctionsToAuxiliaryVariables(...)"); Map<String, List<DomainVariable>> functionInstances = new HashMap<String, List<DomainVariable>>(); Map<DomainVariable, List<DomainTerm>> instanceParameters = new HashMap<DomainVariable, List<DomainTerm>>(); if (Ackermann._debug) DebugHelper.getInstance().formulaToFile(topLevelFormula, "./debug_aux_func_before.txt"); topLevelFormula = topLevelFormula .uninterpretedFunctionsToAuxiliaryVariables( topLevelFormula, functionInstances, instanceParameters, noDependenceVars); if (Ackermann._debug) DebugHelper.getInstance().formulaToFile(topLevelFormula, "./debug_aux_func_after.txt"); // Add Constraints for these UFs System.out.println(" Ackermann: add UF-constraints(...)"); List<Formula> constraintsList = new ArrayList<Formula>(); addAckermannFunctionConstraints(topLevelFormula, constraintsList, functionInstances, instanceParameters); System.out.println(" Ackermann: added UF-constraints(...): cnt=" + constraintsList.size()); // Generate the Implies formula FC => !flat System.out.println(" Ackermann: ImpliesFormula(...)"); if (constraintsList.size() > 0) { Formula ackermannConstraints = (constraintsList.size() == 1) ? constraintsList .iterator().next() : AndFormula .generate(constraintsList); topLevelFormula = ImpliesFormula.create(ackermannConstraints, topLevelFormula); } else { System.out .println(" Ackermann: There are no FunctionConstraints."); } } else { System.err .println(" *** Warning: Ackermann didn't perform on Functions (disabled)"); } // ////////////////////////////////////////////////////////// if (Ackermann._isPredicateActive) { // Init for UP // constraintsList = new ArrayList<Formula>(); // substitute UP by Variables System.out .println(" Ackermann: uninterpretedPredicatesToAuxiliaryVariables(...)"); Map<String, List<PropositionalVariable>> predicateInstances = new HashMap<String, List<PropositionalVariable>>(); Map<PropositionalVariable, List<DomainTerm>> instanceParametersPredicates = new HashMap<PropositionalVariable, List<DomainTerm>>(); if (Ackermann._debug) DebugHelper.getInstance().formulaToFile(topLevelFormula, "./debug_aux_pred_before.txt"); topLevelFormula = topLevelFormula .uninterpretedPredicatesToAuxiliaryVariables( topLevelFormula, predicateInstances, instanceParametersPredicates, noDependenceVars); if (Ackermann._debug) DebugHelper.getInstance().formulaToFile(topLevelFormula, "./debug_aux_pred_after.txt"); System.out.println(" Ackermann: predicateInstances.size: " + predicateInstances.size()); System.out .println(" Ackermann: instanceParametersPredicates.size: " + instanceParametersPredicates.size()); // Add Constraints for these UPs System.out .println(" Ackermann: addAckermannPredicateConstraints(...)"); // HashSet<Formula> constraints = new HashSet<Formula>(); List<Formula> constraintsList = new ArrayList<Formula>(); addAckermannPredicateConstraints(topLevelFormula, constraintsList, predicateInstances, instanceParametersPredicates); // Generate the Implies formula FC => !flat if (constraintsList.size() > 0) { Formula ackermannConstraints = (constraintsList.size() == 1) ? constraintsList .iterator().next() : AndFormula .generate(constraintsList); topLevelFormula = ImpliesFormula.create(ackermannConstraints, topLevelFormula); } else { System.out .println(" Ackermann: There are no PredicateConstraints."); } } else { System.err .println(" *** Warning: Ackermann didn't perform on Predicates (disabled)"); } // debug check: if (Ackermann._isPredicateActive && Ackermann._isFunctionActive) { Set<UninterpretedFunction> ufs2 = new HashSet<UninterpretedFunction>(); topLevelFormula.getUninterpretedFunctions(ufs2, new HashSet<SMTLibObject>()); System.out.println("Count of UF: " + ufs2.size()); assert (ufs2.isEmpty()); } // ////////////////////////////////////////////////////////// // remove all UF and UP (?) System.out.println(" Ackermann: noDependenceVars.removeall(UF)"); System.out.println(" Anzahl der Variablen bevor dem Entfernen: " + noDependenceVars.size()); System.out.println(" Entfernt werden sollten " + currentUninterpretedFunctions.size() + "Variablen"); noDependenceVars.removeAll(currentUninterpretedFunctions); // may remove too much (functions and predicates) if one is deactivated System.out.println(" Anzahl der Variablen nach dem Entfernen: " + noDependenceVars.size()); // finished. return. System.out.println(" Ackermann: done - return."); return topLevelFormula; } /** * Adds Ackermann constraints according to predicate-instance and * instance-parameter mappings to the constraints. * * @param formula * the main formula to expand * @param constraints * the formula's constraints. * @param predicatPropositionalVariableeInstances * map containing mapping from predicate names to auxiliary * variables. * @param instanceParameters * map containing mapping from auxiliary variables to predicate * instance parameters. */ private void addAckermannPredicateConstraints(Formula formula, List<Formula> constraints, Map<String, List<PropositionalVariable>> predicateInstances, Map<PropositionalVariable, List<DomainTerm>> instanceParameters) { for (Map.Entry<String, List<PropositionalVariable>> entry : predicateInstances .entrySet()) { List<PropositionalVariable> instances = entry.getValue(); for (int i = 0; i < instances.size(); i++) for (int j = (i + 1); j < instances.size(); j++) { List<DomainTerm> params1 = instanceParameters.get(instances .get(i)); List<DomainTerm> params2 = instanceParameters.get(instances .get(j)); List<Formula> parametersEq = new ArrayList<Formula>(); for (int k = 0; k < params1.size(); k++) { // Compute functional consistency constraints List<DomainTerm> list = new ArrayList<DomainTerm>(); list.add(params1.get(k)); list.add(params2.get(k)); parametersEq.add(DomainEq.create(list, true)); } Formula parametersEquivalities; if (parametersEq.size() > 1) parametersEquivalities = AndFormula .generate(parametersEq); else parametersEquivalities = parametersEq.iterator().next(); List<PropositionalTerm> predicateEq = new ArrayList<PropositionalTerm>(); predicateEq.add(instances.get(i)); predicateEq.add(instances.get(j)); constraints.add(ImpliesFormula.create( parametersEquivalities, PropositionalEq.create(predicateEq, true))); } } } /** * Adds Ackermann constraints according to function-instance and * instance-parameter mappings to the constraints. * * @param formula * the main formula to expand * @param constraints * the formula's constraints. * @param functionInstances * map containing mapping from function names to auxiliary * variables. * @param instanceParameters * map containing mapping from auxiliary variables to function * instance parameters. */ private void addAckermannFunctionConstraints(Formula formula, List<Formula> constraints, Map<String, List<DomainVariable>> functionInstances, Map<DomainVariable, List<DomainTerm>> instanceParameters) { for (Map.Entry<String, List<DomainVariable>> entry : functionInstances .entrySet()) { List<DomainVariable> instances = entry.getValue(); for (int i = 0; i < instances.size(); i++) for (int j = (i + 1); j < instances.size(); j++) { // System.out.println(""+instances.get(i).getVarName()+" with "+instances.get(j).getVarName()); List<DomainTerm> params1 = instanceParameters.get(instances .get(i)); List<DomainTerm> params2 = instanceParameters.get(instances .get(j)); List<Formula> parametersEq = new ArrayList<Formula>(); for (int k = 0; k < params1.size(); k++) { // System.out.println(" "+t1.get(k)+"^"+t2.get(k)); // Compute functional consistency constraints List<DomainTerm> list = new ArrayList<DomainTerm>(); list.add(params1.get(k)); list.add(params2.get(k)); parametersEq.add(DomainEq.create(list, true)); } Formula parametersEquivalities = (parametersEq.size() > 1) ? AndFormula .generate(parametersEq) : parametersEq.iterator() .next(); List<DomainTerm> functionEq = new ArrayList<DomainTerm>(); functionEq.add(instances.get(i)); functionEq.add(instances.get(j)); constraints.add(ImpliesFormula.create( parametersEquivalities, DomainEq.create(functionEq, true))); } } } public static boolean isFunctionActive() { return Ackermann._isFunctionActive; } public static void setFunctionActive(boolean _isFunctionActive) { Ackermann._isFunctionActive = _isFunctionActive; } public static boolean isPredicateActive() { return Ackermann._isPredicateActive; } public static void setPredicateActive(boolean _isPredicateActive) { Ackermann._isPredicateActive = _isPredicateActive; } public static void setActive(boolean isActive) { Ackermann._isActive = isActive; } public static boolean isActive() { return Ackermann._isActive; } public static void setDebug(boolean isDebugEnabled) { Ackermann._debug = isDebugEnabled; } public static boolean isDebug() { return Ackermann._debug; } }