Skip to content

Commit a85c9c3

Browse files
committed
possible solution for the new callback in UserPropagator.
Tests are missing, as I could not yet find any actual callback triggering the method.
1 parent 39669ad commit a85c9c3

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

src/org/sosy_lab/java_smt/api/UserPropagator.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,25 @@ public interface UserPropagator {
110110
* @param theoryExpr The expression to observe.
111111
*/
112112
void registerExpression(BooleanFormula theoryExpr);
113+
114+
/**
115+
* The on_binding method allows custom user-defined propagators to intercept and control
116+
* quantifier instantiations during solving. This callback is invoked whenever the solver performs
117+
* a quantifier instantiation (i.e., binds a quantifier to a specific instance). It provides a
118+
* hook for the user propagator to inspect the quantifier and its instantiation.
119+
*
120+
* <p>The default implementation does nothing and accepts all instantiations. It serves for
121+
* backward compatibility in the API.
122+
*
123+
* @param quantifiedVar The quantified variable being instantiated. This is a BooleanFormula
124+
* representing the variable in the quantifier.
125+
* @param instantiation The specific instantiation being applied to the quantified variable. It
126+
* has the same formula type as the quantified variable.
127+
* @since Z3 release 4.15.3
128+
* @return By returning false, the callback signals that the instantiation should be discarded by
129+
* the solver.
130+
*/
131+
default <T extends Formula> boolean onBinding(T quantifiedVar, T instantiation) {
132+
return true;
133+
}
113134
}

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.Map;
1616
import java.util.Optional;
1717
import org.sosy_lab.java_smt.api.BooleanFormula;
18+
import org.sosy_lab.java_smt.api.Formula;
1819
import org.sosy_lab.java_smt.api.PropagatorBackend;
1920
import org.sosy_lab.java_smt.api.UserPropagator;
2021

@@ -28,7 +29,7 @@ final class Z3UserPropagator extends UserPropagatorBase implements PropagatorBac
2829
/* We use this map to reuse existing formula wrappers and avoid creating unnecessary phantom
2930
references (if enabled). This is particularly useful, because the user propagator frequently
3031
reports the same formulas. */
31-
private final Map<Long, BooleanFormula> canonicalizer = new HashMap<>();
32+
private final Map<Long, Formula> canonicalizer = new HashMap<>();
3233

3334
Z3UserPropagator(
3435
long ctx,
@@ -70,7 +71,7 @@ protected void eqWrapper(long pL, long pL1) {}
7071
@Override
7172
protected void fixedWrapper(long lvar, long lvalue) {
7273
assert lvalue == z3True || lvalue == z3False;
73-
userPropagator.onKnownValue(encapsulate(lvar), lvalue == z3True);
74+
userPropagator.onKnownValue(encapsulateBoolean(lvar), lvalue == z3True);
7475
}
7576

7677
// TODO: This method is called if Z3 re-instantiates a user propagator for a sub-problem
@@ -91,7 +92,12 @@ protected void createdWrapper(long le) {}
9192
protected void decideWrapper(long lvar, int bit, boolean isPositive) {
9293
// We currently only allow tracking of decision on boolean formulas,
9394
// so we ignore the <bit> parameter
94-
userPropagator.onDecision(encapsulate(lvar), isPositive);
95+
userPropagator.onDecision(encapsulateBoolean(lvar), isPositive);
96+
}
97+
98+
@Override
99+
protected boolean onBindingWrapper(long quantifiedVar, long instantiation) {
100+
return userPropagator.onBinding(encapsulate(quantifiedVar), encapsulate(instantiation));
95101
}
96102

97103
// ===========================================================================
@@ -160,12 +166,16 @@ private long[] extractInfoFromArray(BooleanFormula[] formulaArray) {
160166
return formulaInfos;
161167
}
162168

163-
private BooleanFormula encapsulate(final long z3Expr) {
169+
private BooleanFormula encapsulateBoolean(final long z3Expr) {
170+
return (BooleanFormula) encapsulate(z3Expr);
171+
}
172+
173+
private Formula encapsulate(final long z3Expr) {
164174
// Due to pointer alignment, the lowest 2-3 bits are always 0 which can lead to
165175
// more collisions in the hashmap. To counteract, we fill the lowest bits by rotating the
166176
// value. The rotation guarantees a bijective transformation.
167177
return canonicalizer.computeIfAbsent(
168-
Long.rotateRight(z3Expr, 3), key -> creator.encapsulateBoolean(z3Expr));
178+
Long.rotateRight(z3Expr, 3), key -> creator.encapsulateWithTypeOf(z3Expr));
169179
}
170180

171181
@Override

0 commit comments

Comments
 (0)