Skip to content

Add SolverException for Model and Prover due to MathSAT5/Z3 Model Problem (Including a Sneaky Throw for API not Supporting Changes) #501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c4a7a65
Add warning for sneaky SolverExceptions in Model JavaDoc
Jul 29, 2025
b7da958
Throw sneaky SolverExceptions in Mathsat Model instead of confusing I…
Jul 29, 2025
50094eb
Add more sneaky throw warnings to API that may throw a SolverExceptio…
Jul 29, 2025
89837d5
Remove sneaky throw of SolverException from Mathsat native call
Jul 30, 2025
dbbdc31
Remove sneaky throw of SolverException from Z3 model and add Interrup…
Jul 30, 2025
b0e7b44
Add SolverException and InterruptedException to many calls related to…
Jul 30, 2025
0ca8d4f
Remove sneaky throws for Z3 specific code entirely
Jul 30, 2025
cd51b02
Add Solver- and InterruptedException to push() and addConstraint() API
Jul 30, 2025
898832d
Remove warnings about sneaky throws where they can't happen anymore
Jul 30, 2025
c900399
Format: remove warnings about sneaky throws where they can't happen a…
Jul 30, 2025
2166410
Rename exception variable to fit naming schema
Jul 30, 2025
64b21b3
Improve warning for sneaky throws in model iterator() as suggested by…
Jul 30, 2025
0769c11
Allow AbstractEvaluator.evaluateImpl to be overridden so that it can …
Aug 8, 2025
aa370f6
Remove exceptions in the model of SMTInterpol where not necessary
Aug 8, 2025
582e19d
Remove exceptions in OpenSMT2s getModelAssignments() by catching them…
Aug 8, 2025
0e97ab8
Remove exceptions in CVC4s getModelAssignments() by catching them, bu…
Aug 8, 2025
b2fb742
Remove exceptions in CVC5s getModelAssignments() by catching them, bu…
Aug 8, 2025
5afc4ae
Remove exceptions in CVC5s model methods as they are never thrown
Aug 8, 2025
ed7a40a
Remove exceptions in CVC4s model methods as they are never thrown
Aug 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public interface BasicProverEnvironment<T> extends AutoCloseable {
*/
@Nullable
@CanIgnoreReturnValue
default T push(BooleanFormula f) throws InterruptedException {
default T push(BooleanFormula f) throws InterruptedException, SolverException {
push();
return addConstraint(f);
}
Expand All @@ -46,7 +46,7 @@ default T push(BooleanFormula f) throws InterruptedException {
/** Add a constraint to the latest backtracking point. */
@Nullable
@CanIgnoreReturnValue
T addConstraint(BooleanFormula constraint) throws InterruptedException;
T addConstraint(BooleanFormula constraint) throws InterruptedException, SolverException;

/**
* Create a new backtracking point, i.e., a new level on the assertion stack. Each level can hold
Expand All @@ -55,7 +55,7 @@ default T push(BooleanFormula f) throws InterruptedException {
* <p>If formulas are added before creating the first backtracking point, they can not be removed
* via a POP-operation.
*/
void push() throws InterruptedException;
void push() throws InterruptedException, SolverException;

/**
* Get the number of backtracking points/levels on the current stack.
Expand Down Expand Up @@ -87,15 +87,15 @@ boolean isUnsatWithAssumptions(Collection<BooleanFormula> assumptions)
* <p>A model might contain additional symbols with their evaluation, if a solver uses its own
* temporary symbols. There should be at least a value-assignment for each free symbol.
*/
Model getModel() throws SolverException;
Model getModel() throws SolverException, InterruptedException;

/**
* Get a temporary view on the current satisfying assignment. This should be called only
* immediately after an {@link #isUnsat()} call that returned <code>false</code>. The evaluator
* should no longer be used as soon as any constraints are added to, pushed, or popped from the
* prover stack.
*/
default Evaluator getEvaluator() throws SolverException {
default Evaluator getEvaluator() throws SolverException, InterruptedException {
return getModel();
}

Expand All @@ -107,7 +107,8 @@ default Evaluator getEvaluator() throws SolverException {
* <p>Note that if you need to iterate multiple times over the model it may be more efficient to
* use this method instead of {@link #getModel()} (depending on the solver).
*/
default ImmutableList<Model.ValueAssignment> getModelAssignments() throws SolverException {
default ImmutableList<Model.ValueAssignment> getModelAssignments()
throws SolverException, InterruptedException {
try (Model model = getModel()) {
return model.asList();
}
Expand Down
22 changes: 13 additions & 9 deletions src/org/sosy_lab/java_smt/api/Evaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public interface Evaluator extends AutoCloseable {
* @return evaluation of the given formula or <code>null</code> if the solver does not provide a
* better evaluation.
*/
@Nullable <T extends Formula> T eval(T formula);
@Nullable <T extends Formula> T eval(T formula) throws SolverException, InterruptedException;

/**
* Evaluate a given formula substituting the values from the model.
Expand All @@ -62,56 +62,60 @@ public interface Evaluator extends AutoCloseable {
* @return Either of: - Number (Rational/Double/BigInteger/Long/Integer) - Boolean
* @throws IllegalArgumentException if a formula has unexpected type, e.g. Array.
*/
@Nullable Object evaluate(Formula formula);
@Nullable Object evaluate(Formula formula) throws SolverException, InterruptedException;

/**
* Type-safe evaluation for integer formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable BigInteger evaluate(IntegerFormula formula);
@Nullable BigInteger evaluate(IntegerFormula formula)
throws SolverException, InterruptedException;

/**
* Type-safe evaluation for rational formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable Rational evaluate(RationalFormula formula);
@Nullable Rational evaluate(RationalFormula formula) throws SolverException, InterruptedException;

/**
* Type-safe evaluation for boolean formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable Boolean evaluate(BooleanFormula formula);
@Nullable Boolean evaluate(BooleanFormula formula) throws SolverException, InterruptedException;

/**
* Type-safe evaluation for bitvector formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable BigInteger evaluate(BitvectorFormula formula);
@Nullable BigInteger evaluate(BitvectorFormula formula)
throws SolverException, InterruptedException;

/**
* Type-safe evaluation for string formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable String evaluate(StringFormula formula);
@Nullable String evaluate(StringFormula formula) throws SolverException, InterruptedException;

/**
* Type-safe evaluation for enumeration formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable String evaluate(EnumerationFormula formula);
@Nullable String evaluate(EnumerationFormula formula)
throws SolverException, InterruptedException;

/**
* Type-safe evaluation for floating-point formulas.
*
* <p>The formula does not need to be a variable, we also allow complex expression.
*/
@Nullable FloatingPointNumber evaluate(FloatingPointFormula formula);
@Nullable FloatingPointNumber evaluate(FloatingPointFormula formula)
throws SolverException, InterruptedException;

/**
* Free resources associated with this evaluator (existing {@link Formula} instances stay valid,
Expand Down
17 changes: 15 additions & 2 deletions src/org/sosy_lab/java_smt/api/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,27 @@ public interface Model extends Evaluator, Iterable<ValueAssignment>, AutoCloseab
* within a quantified context, some value assignments can be missing in the iteration.
* Please use a direct evaluation query to get the evaluation in such a case.
* </ul>
*
* <p>Warning: This method may throw the checked exceptions SolverException (in case of solver
* failures) and InterruptedException (in case of shutdown requests) although these exceptions are
* not declared with throws.
*/
@Override
default Iterator<ValueAssignment> iterator() {
return asList().iterator();
try {
return asList().iterator();
} catch (SolverException | InterruptedException ex) {
throw sneakyThrow(ex);
}
}

@SuppressWarnings("unchecked")
private static <E extends Throwable> RuntimeException sneakyThrow(Throwable e) throws E {
throw (E) e;
}

/** Build a list of assignments that stays valid after closing the model. */
ImmutableList<ValueAssignment> asList();
ImmutableList<ValueAssignment> asList() throws SolverException, InterruptedException;

/**
* Pretty-printing of the model values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public interface OptimizationProverEnvironment extends BasicProverEnvironment<Vo
* (epsilon is irrelevant here and can be zero). The model returns the optimal assignment x=9.
*/
@Override
Model getModel() throws SolverException;
Model getModel() throws SolverException, InterruptedException;

/** Status of the optimization problem. */
enum OptStatus {
Expand Down
26 changes: 15 additions & 11 deletions src/org/sosy_lab/java_smt/basicimpl/AbstractEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula;
import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula;
import org.sosy_lab.java_smt.api.SolverException;
import org.sosy_lab.java_smt.api.StringFormula;

@SuppressWarnings("ClassTypeParameterName")
Expand All @@ -40,22 +41,22 @@ protected AbstractEvaluator(
@SuppressWarnings("unchecked")
@Nullable
@Override
public final <T extends Formula> T eval(T f) {
public final <T extends Formula> T eval(T f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
TFormulaInfo evaluation = evalImpl(creator.extractInfo(f));
return evaluation == null ? null : (T) creator.encapsulateWithTypeOf(evaluation);
}

@Nullable
@Override
public final BigInteger evaluate(IntegerFormula f) {
public final BigInteger evaluate(IntegerFormula f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
return (BigInteger) evaluateImpl(creator.extractInfo(f));
}

@Nullable
@Override
public Rational evaluate(RationalFormula f) {
public Rational evaluate(RationalFormula f) throws SolverException, InterruptedException {
Object value = evaluateImpl(creator.extractInfo(f));
if (value instanceof BigInteger) {
// We simplified the value internally. Here, we need to convert it back to Rational.
Expand All @@ -67,41 +68,43 @@ public Rational evaluate(RationalFormula f) {

@Nullable
@Override
public final Boolean evaluate(BooleanFormula f) {
public final Boolean evaluate(BooleanFormula f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
return (Boolean) evaluateImpl(creator.extractInfo(f));
}

@Nullable
@Override
public final String evaluate(StringFormula f) {
public final String evaluate(StringFormula f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
return (String) evaluateImpl(creator.extractInfo(f));
}

@Nullable
@Override
public final String evaluate(EnumerationFormula f) {
public final String evaluate(EnumerationFormula f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
return (String) evaluateImpl(creator.extractInfo(f));
}

@Override
public final @Nullable FloatingPointNumber evaluate(FloatingPointFormula f) {
public final @Nullable FloatingPointNumber evaluate(FloatingPointFormula f)
throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
return (FloatingPointNumber) evaluateImpl(creator.extractInfo(f));
}

@Nullable
@Override
public final BigInteger evaluate(BitvectorFormula f) {
public final BigInteger evaluate(BitvectorFormula f)
throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
return (BigInteger) evaluateImpl(creator.extractInfo(f));
}

@Nullable
@Override
public final Object evaluate(Formula f) {
public final Object evaluate(Formula f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
Preconditions.checkArgument(
!(f instanceof ArrayFormula),
Expand All @@ -114,15 +117,16 @@ public final Object evaluate(Formula f) {
* set in the model and evaluation aborts, return <code>null</code>.
*/
@Nullable
protected abstract TFormulaInfo evalImpl(TFormulaInfo formula);
protected abstract TFormulaInfo evalImpl(TFormulaInfo formula)
throws SolverException, InterruptedException;

/**
* Simplify the given formula and replace all symbols with their model values. If a symbol is not
* set in the model and evaluation aborts, return <code>null</code>. Afterward convert the formula
* into a Java object as far as possible, i.e., try to match a primitive or simple type.
*/
@Nullable
protected final Object evaluateImpl(TFormulaInfo f) {
protected Object evaluateImpl(TFormulaInfo f) throws SolverException, InterruptedException {
Preconditions.checkState(!isClosed());
TFormulaInfo evaluatedF = evalImpl(f);
return evaluatedF == null ? null : creator.convertValue(f, evaluatedF);
Expand Down
10 changes: 6 additions & 4 deletions src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.sosy_lab.java_smt.api.BooleanFormula;
import org.sosy_lab.java_smt.api.Evaluator;
import org.sosy_lab.java_smt.api.SolverContext.ProverOptions;
import org.sosy_lab.java_smt.api.SolverException;

public abstract class AbstractProver<T> implements BasicProverEnvironment<T> {

Expand Down Expand Up @@ -88,13 +89,13 @@ public int size() {
}

@Override
public final void push() throws InterruptedException {
public final void push() throws InterruptedException, SolverException {
checkState(!closed);
pushImpl();
assertedFormulas.add(LinkedHashMultimap.create());
}

protected abstract void pushImpl() throws InterruptedException;
protected abstract void pushImpl() throws InterruptedException, SolverException;

@Override
public final void pop() {
Expand All @@ -108,15 +109,16 @@ public final void pop() {

@Override
@CanIgnoreReturnValue
public final @Nullable T addConstraint(BooleanFormula constraint) throws InterruptedException {
public final @Nullable T addConstraint(BooleanFormula constraint)
throws InterruptedException, SolverException {
checkState(!closed);
T t = addConstraintImpl(constraint);
Iterables.getLast(assertedFormulas).put(constraint, t);
return t;
}

protected abstract @Nullable T addConstraintImpl(BooleanFormula constraint)
throws InterruptedException;
throws InterruptedException, SolverException;

protected ImmutableSet<BooleanFormula> getAssertedFormulas() {
ImmutableSet.Builder<BooleanFormula> builder = ImmutableSet.builder();
Expand Down
29 changes: 19 additions & 10 deletions src/org/sosy_lab/java_smt/basicimpl/CachingModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.sosy_lab.java_smt.api.Model;
import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula;
import org.sosy_lab.java_smt.api.NumeralFormula.RationalFormula;
import org.sosy_lab.java_smt.api.SolverException;
import org.sosy_lab.java_smt.api.StringFormula;

public class CachingModel implements Model {
Expand All @@ -35,7 +36,7 @@ public CachingModel(Model pDelegate) {
}

@Override
public ImmutableList<ValueAssignment> asList() {
public ImmutableList<ValueAssignment> asList() throws SolverException, InterruptedException {
if (modelAssignments == null) {
modelAssignments = delegate.asList();
}
Expand All @@ -48,47 +49,55 @@ public void close() {
}

@Override
public <T extends Formula> @Nullable T eval(T formula) {
public <T extends Formula> @Nullable T eval(T formula)
throws SolverException, InterruptedException {
return delegate.eval(formula);
}

@Override
public @Nullable Object evaluate(Formula formula) {
public @Nullable Object evaluate(Formula formula) throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable BigInteger evaluate(IntegerFormula formula) {
public @Nullable BigInteger evaluate(IntegerFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable Rational evaluate(RationalFormula formula) {
public @Nullable Rational evaluate(RationalFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable Boolean evaluate(BooleanFormula formula) {
public @Nullable Boolean evaluate(BooleanFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable BigInteger evaluate(BitvectorFormula formula) {
public @Nullable BigInteger evaluate(BitvectorFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable String evaluate(StringFormula formula) {
public @Nullable String evaluate(StringFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable String evaluate(EnumerationFormula formula) {
public @Nullable String evaluate(EnumerationFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

@Override
public @Nullable FloatingPointNumber evaluate(FloatingPointFormula formula) {
public @Nullable FloatingPointNumber evaluate(FloatingPointFormula formula)
throws SolverException, InterruptedException {
return delegate.evaluate(formula);
}

Expand Down
Loading