Skip to content

Commit 5eafd01

Browse files
committed
Princess: improve visiting quantified formulas.
Generate fresh variable names based on the quantified formula to avoid different results when visiting the same formula twice.
1 parent b2469a8 commit 5eafd01

File tree

1 file changed

+21
-9
lines changed

1 file changed

+21
-9
lines changed

src/org/sosy_lab/java_smt/solvers/princess/PrincessFormulaCreator.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111
import static com.google.common.base.Preconditions.checkArgument;
1212
import static org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier.EXISTS;
1313
import static org.sosy_lab.java_smt.api.QuantifiedFormulaManager.Quantifier.FORALL;
14+
import static org.sosy_lab.java_smt.solvers.princess.PrincessEnvironment.toITermSeq;
1415
import static org.sosy_lab.java_smt.solvers.princess.PrincessEnvironment.toSeq;
1516
import static scala.collection.JavaConverters.asJava;
1617
import static scala.collection.JavaConverters.asJavaCollection;
17-
import static scala.collection.JavaConverters.asScala;
1818

1919
import ap.basetypes.IdealInt;
2020
import ap.parser.IAtom;
@@ -54,10 +54,10 @@
5454
import com.google.common.collect.Table;
5555
import java.lang.reflect.InvocationTargetException;
5656
import java.util.HashMap;
57+
import java.util.LinkedHashMap;
5758
import java.util.List;
5859
import java.util.Map;
5960
import java.util.Set;
60-
import org.sosy_lab.common.UniqueIdGenerator;
6161
import org.sosy_lab.common.rationals.Rational;
6262
import org.sosy_lab.java_smt.api.ArrayFormula;
6363
import org.sosy_lab.java_smt.api.BitvectorFormula;
@@ -185,8 +185,10 @@ class PrincessFormulaCreator
185185
*/
186186
private final Table<Sort, Sort, Sort> arraySortCache = HashBasedTable.create();
187187

188-
// Keeps track of the bound/free variables created when visiting quantified terms.
189-
private final UniqueIdGenerator boundVariablesId = new UniqueIdGenerator();
188+
/** This map keeps track of the bound/free variables created when visiting quantified terms. */
189+
// TODO should we use a WeakHashMap?
190+
// We do not cleanup in other places, too, and the number of quantified formulas is small.
191+
private final Map<IFormula, String> boundVariableNames = new LinkedHashMap<>();
190192

191193
PrincessFormulaCreator(PrincessEnvironment pEnv) {
192194
super(
@@ -538,14 +540,14 @@ private <R> R visitQuantifier(FormulaVisitor<R> visitor, BooleanFormula f, IQuan
538540

539541
// Princess uses de-Bruijn indices, so we have index 0 here for the most outer quantified scope
540542
IVariable boundVariable = input.sort().boundVariable(0);
541-
String boundVariableName = "__JAVASMT__BOUND_VARIABLE_" + boundVariablesId.getFreshId();
543+
String boundVariableName = getFreshVariableNameForBody(body);
544+
542545
// Currently, Princess supports only non-boolean bound variables, so we can cast to ITerm.
543546
ITerm substitutionVariable = (ITerm) makeVariable(boundVariable.sort(), boundVariableName);
544547

545-
// substitute the bound variable with a new variable,
546-
// and un-shift the remaining de-Bruijn indices.
547-
IFormula substitutedBody =
548-
IFormula.subst(body, asScala(List.of(substitutionVariable)).toList(), -1);
548+
// substitute the bound variable with index 0 with a new variable, and un-shift the remaining
549+
// de-Bruijn indices, such that the next nested bound variable has index 0.
550+
IFormula substitutedBody = IFormula.subst(body, toITermSeq(substitutionVariable).toList(), -1);
549551

550552
return visitor.visitQuantifier(
551553
f,
@@ -554,6 +556,16 @@ private <R> R visitQuantifier(FormulaVisitor<R> visitor, BooleanFormula f, IQuan
554556
encapsulateBoolean(substitutedBody));
555557
}
556558

559+
/**
560+
* Get a fresh variable name for the given formula. We compute the same variable name for the same
561+
* body, such that a user gets the same substituted body when visiting a quantified formulas
562+
* several times.
563+
*/
564+
private String getFreshVariableNameForBody(IFormula body) {
565+
return boundVariableNames.computeIfAbsent(
566+
body, k -> "__JAVASMT__BOUND_VARIABLE_" + boundVariableNames.size());
567+
}
568+
557569
private boolean isBitvectorOperationWithAdditionalArgument(FunctionDeclarationKind kind) {
558570
switch (kind) {
559571
case BV_NOT:

0 commit comments

Comments
 (0)