Skip to content

Commit 92e6afb

Browse files
authored
Merge pull request #535 from sosy-lab/fix_Z3_bound_variable_substitution
Fix Z3 bound variable substitution
2 parents 7d89b87 + b54cb3b commit 92e6afb

File tree

2 files changed

+92
-2
lines changed

2 files changed

+92
-2
lines changed

src/org/sosy_lab/java_smt/solvers/z3/Z3FormulaCreator.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,11 @@ private <R> R visitQuantifier(FormulaVisitor<R> pVisitor, BooleanFormula pFormul
588588
int numBound = Native.getQuantifierNumBound(environment, pF);
589589
long[] freeVars = new long[numBound];
590590
for (int i = 0; i < numBound; i++) {
591-
long varName = Native.getQuantifierBoundName(environment, pF, i);
592-
long varSort = Native.getQuantifierBoundSort(environment, pF, i);
591+
// The indices are reversed according to
592+
// https://github.com/Z3Prover/z3/issues/7970#issuecomment-3407924907
593+
int inverseIndex = numBound - 1 - i;
594+
long varName = Native.getQuantifierBoundName(environment, pF, inverseIndex);
595+
long varSort = Native.getQuantifierBoundSort(environment, pF, inverseIndex);
593596
long freeVar = Native.mkConst(environment, varName, varSort);
594597
Native.incRef(environment, freeVar);
595598
freeVars[i] = freeVar;

src/org/sosy_lab/java_smt/test/SolverVisitorTest.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1661,4 +1661,91 @@ public void testSl() throws SolverException, InterruptedException {
16611661
assertThat(f2).isEqualTo(f);
16621662
assertThatFormula(f).isEquivalentTo(f2);
16631663
}
1664+
1665+
@Test
1666+
public void testQuantifierAndBoundVariablesWithIntegers() {
1667+
requireQuantifiers();
1668+
requireArrays();
1669+
requireIntegers();
1670+
requireVisitor();
1671+
1672+
IntegerFormula four = imgr.makeNumber(4);
1673+
IntegerFormula var1 = imgr.makeVariable("var1");
1674+
IntegerFormula var2 = imgr.makeVariable("var2");
1675+
IntegerFormula var3 = imgr.makeVariable("var3");
1676+
1677+
ArrayFormula<IntegerFormula, IntegerFormula> array1 =
1678+
amgr.makeArray("array1", FormulaType.IntegerType, FormulaType.IntegerType);
1679+
ArrayFormula<IntegerFormula, IntegerFormula> array2 =
1680+
amgr.makeArray("array2", FormulaType.IntegerType, FormulaType.IntegerType);
1681+
1682+
IntegerFormula bvIndex = imgr.add(var2, imgr.multiply(four, var1));
1683+
BooleanFormula body = amgr.equivalence(array2, amgr.store(array1, bvIndex, var3));
1684+
1685+
List<? extends Formula> freeVars = ImmutableList.of(var2, var3, array2);
1686+
List<? extends Formula> boundVars = ImmutableList.of(var1, array1);
1687+
List<? extends Formula> allVars = ImmutableList.of(var1, var2, var3, array1, array2);
1688+
Map<String, Formula> variablesInBody = mgr.extractVariables(body);
1689+
assertThat(variablesInBody.values()).containsExactlyElementsIn(allVars);
1690+
1691+
for (Quantifier quantifier : Quantifier.values()) {
1692+
BooleanFormula quantifiedFormula = qmgr.mkQuantifier(quantifier, boundVars, body);
1693+
1694+
Map<String, Formula> variablesInQuantifiedFormula = mgr.extractVariables(quantifiedFormula);
1695+
Map<String, Formula> variablesAndUFsInQuantifiedFormula =
1696+
mgr.extractVariablesAndUFs(quantifiedFormula);
1697+
1698+
assertThat(variablesAndUFsInQuantifiedFormula).isEqualTo(variablesInQuantifiedFormula);
1699+
assertThat(variablesInQuantifiedFormula.values()).containsExactlyElementsIn(freeVars);
1700+
assertThat(variablesInQuantifiedFormula.values()).containsNoneIn(boundVars);
1701+
1702+
// TODO: add collection of bound variables through new visitor implementation and test
1703+
// failure of the old
1704+
}
1705+
}
1706+
1707+
@Test
1708+
public void testQuantifierAndBoundVariablesWithBitvectors() {
1709+
requireQuantifiers();
1710+
requireArrays();
1711+
requireBitvectors();
1712+
requireVisitor();
1713+
1714+
int bvLen = 32;
1715+
BitvectorType bvType = FormulaType.getBitvectorTypeWithSize(bvLen);
1716+
1717+
BitvectorFormula four = bvmgr.makeBitvector(bvLen, 4);
1718+
BitvectorFormula var1 = bvmgr.makeVariable(bvType, "var1");
1719+
BitvectorFormula var2 = bvmgr.makeVariable(bvType, "var2");
1720+
BitvectorFormula var3 = bvmgr.makeVariable(bvType, "var3");
1721+
1722+
ArrayFormula<BitvectorFormula, BitvectorFormula> array1 =
1723+
amgr.makeArray("array1", bvType, bvType);
1724+
ArrayFormula<BitvectorFormula, BitvectorFormula> array2 =
1725+
amgr.makeArray("array2", bvType, bvType);
1726+
1727+
BitvectorFormula bvIndex = bvmgr.add(var2, bvmgr.multiply(four, var1));
1728+
BooleanFormula body = amgr.equivalence(array2, amgr.store(array1, bvIndex, var3));
1729+
1730+
List<? extends Formula> freeVars = ImmutableList.of(var2, var3, array2);
1731+
List<? extends Formula> boundVars = ImmutableList.of(var1, array1);
1732+
List<? extends Formula> allVars = ImmutableList.of(var1, var2, var3, array1, array2);
1733+
Map<String, Formula> variablesInBody = mgr.extractVariables(body);
1734+
assertThat(variablesInBody.values()).containsExactlyElementsIn(allVars);
1735+
1736+
for (Quantifier quantifier : Quantifier.values()) {
1737+
BooleanFormula quantifiedFormula = qmgr.mkQuantifier(quantifier, boundVars, body);
1738+
1739+
Map<String, Formula> variablesInQuantifiedFormula = mgr.extractVariables(quantifiedFormula);
1740+
Map<String, Formula> variablesAndUFsInQuantifiedFormula =
1741+
mgr.extractVariablesAndUFs(quantifiedFormula);
1742+
1743+
assertThat(variablesAndUFsInQuantifiedFormula).isEqualTo(variablesInQuantifiedFormula);
1744+
assertThat(variablesInQuantifiedFormula.values()).containsExactlyElementsIn(freeVars);
1745+
assertThat(variablesInQuantifiedFormula.values()).containsNoneIn(boundVars);
1746+
1747+
// TODO: add collection of bound variables through new visitor implementation and test
1748+
// failure of the old
1749+
}
1750+
}
16641751
}

0 commit comments

Comments
 (0)