@Override public Formula visitFunction( Formula pF, List<Formula> pArgs, FunctionDeclaration<?> pFunctionDeclaration) { List<Formula> newArgs = Lists.transform(pArgs, f -> fmgrView.visit(f, this)); if ((pFunctionDeclaration.getKind().equals(UF) && pFunctionDeclaration.getName().equalsIgnoreCase("Integer__*_")) || (pFunctionDeclaration.getKind().equals(MUL) && !isConstant(newArgs.get(0)) && !isConstant(newArgs.get(1)))) { assert newArgs.size() == 2; return transformNonLinearMultiplication( newArgs.get(0), newArgs.get(1), pFunctionDeclaration.getType()); } else { return fmgr.makeApplication(pFunctionDeclaration, newArgs); } }
/** * Transform a non linear multiplication operation into a new linear {@link Formula} and adds it * to {@link #additionalAxioms}. The returned {@link Formula} represents the multiplication * opertion's result if that {@link Formula} is satisfied. * * @return a {@link Formula} representing the result of the multiplication operation */ private Formula transformNonLinearMultiplication( Formula a, Formula b, FormulaType<?> formulaType) { BooleanFormulaManagerView bfmgr = fmgrView.getBooleanFormulaManager(); Formula multAux = fmgr.makeVariable( formulaType, TERMINATION_AUX_VARS_PREFIX + "MULT_AUX_VAR_" + ID_GENERATOR.getFreshId()); List<BooleanFormula> cases = Lists.newArrayList(); Formula one = fmgrView.makeNumber(formulaType, 1); Formula minusOne = fmgrView.makeNumber(formulaType, -1); Formula zero = fmgrView.makeNumber(formulaType, 0); BooleanFormula aIsZero = fmgrView.makeEqual(a, zero); BooleanFormula bIsZero = fmgrView.makeEqual(b, zero); BooleanFormula factorIsZero = fmgrView.makeOr(aIsZero, bIsZero); cases.add(fmgrView.makeAnd(factorIsZero, fmgrView.makeEqual(multAux, zero))); BooleanFormula aIsOne = fmgrView.makeEqual(a, one); BooleanFormula bIsOne = fmgrView.makeEqual(b, one); cases.add(fmgrView.makeAnd(bIsOne, fmgrView.makeEqual(multAux, a))); cases.add(fmgrView.makeAnd(aIsOne, fmgrView.makeEqual(multAux, b))); // 0 < a < 1, 0 < b < 1, -1 < a < 0, -1 < b < 0, a > 1, ... BooleanFormula zeroLessALessOne = bfmgr.and(fmgrView.makeLessThan(zero, a, true), fmgrView.makeLessThan(a, one, true)); BooleanFormula zeroLessBLessOne = bfmgr.and(fmgrView.makeLessThan(zero, b, true), fmgrView.makeLessThan(b, one, true)); BooleanFormula minusOneLessALessZero = bfmgr.and(fmgrView.makeLessThan(minusOne, a, true), fmgrView.makeLessThan(a, zero, true)); BooleanFormula minusOneLessBLessZero = bfmgr.and(fmgrView.makeLessThan(minusOne, b, true), fmgrView.makeLessThan(b, zero, true)); BooleanFormula aGreaterOne = bfmgr.and(fmgrView.makeGreaterThan(a, one, true)); BooleanFormula bGreaterOne = bfmgr.and(fmgrView.makeGreaterThan(b, one, true)); BooleanFormula aLessMinuseOne = bfmgr.and(fmgrView.makeLessThan(a, one, true)); BooleanFormula bLessMinuseOne = bfmgr.and(fmgrView.makeLessThan(b, one, true)); // 0 < multAux < 1, -1 < multAux < 0, multAux > 1, ... BooleanFormula zeroLessResultLessOne = bfmgr.and( fmgrView.makeLessThan(zero, multAux, true), fmgrView.makeLessThan(multAux, one, true)); BooleanFormula minusOneLessResultLessZero = bfmgr.and( fmgrView.makeLessThan(minusOne, multAux, true), fmgrView.makeLessThan(multAux, zero, true)); BooleanFormula resultGreaterOne = bfmgr.and(fmgrView.makeGreaterThan(multAux, one, true)); BooleanFormula resultLessMinuseOne = bfmgr.and(fmgrView.makeLessThan(multAux, one, true)); BooleanFormula positiveResult = fmgrView.makeGreaterThan(multAux, zero, true); BooleanFormula negativeResult = fmgrView.makeLessThan(multAux, zero, true); cases.add(bfmgr.and(zeroLessALessOne, zeroLessBLessOne, zeroLessResultLessOne)); cases.add(bfmgr.and(zeroLessALessOne, minusOneLessBLessZero, minusOneLessResultLessZero)); cases.add(bfmgr.and(zeroLessALessOne, bGreaterOne, positiveResult)); cases.add(bfmgr.and(zeroLessALessOne, bLessMinuseOne, negativeResult)); cases.add(bfmgr.and(minusOneLessALessZero, zeroLessBLessOne, minusOneLessResultLessZero)); cases.add(bfmgr.and(minusOneLessALessZero, minusOneLessBLessZero, zeroLessResultLessOne)); cases.add(bfmgr.and(minusOneLessALessZero, bGreaterOne, negativeResult)); cases.add(bfmgr.and(minusOneLessALessZero, bLessMinuseOne, positiveResult)); cases.add(bfmgr.and(aGreaterOne, zeroLessBLessOne, positiveResult)); cases.add(bfmgr.and(aGreaterOne, minusOneLessBLessZero, negativeResult)); cases.add(bfmgr.and(aGreaterOne, bGreaterOne, resultGreaterOne)); cases.add(bfmgr.and(aGreaterOne, bLessMinuseOne, resultLessMinuseOne)); cases.add(bfmgr.and(aLessMinuseOne, zeroLessBLessOne, negativeResult)); cases.add(bfmgr.and(aLessMinuseOne, minusOneLessBLessZero, positiveResult)); cases.add(bfmgr.and(aLessMinuseOne, bGreaterOne, resultLessMinuseOne)); cases.add(bfmgr.and(aLessMinuseOne, bLessMinuseOne, resultGreaterOne)); additionalAxioms.add(bfmgr.or(cases)); return multAux; }