Skip to content
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d7f226a
Added interfaces for handling general proofs of unsatisfiability: `Pr…
gcarpio21 Dec 20, 2025
9647cd5
Added abstract class implementing the proof interface `AbstractProof`.
gcarpio21 Dec 20, 2025
570eb5c
Added the implementation of method `getProof` for retrieving `Proof` …
gcarpio21 Dec 20, 2025
0fd0070
Added the implementation of method `getProof` for retrieving `Proof` …
gcarpio21 Dec 20, 2025
6272b50
Added the abstract class `ProofFrame` for transformation of native pr…
gcarpio21 Dec 20, 2025
0f8c032
Added `GENERATE_PROOFS` to `ProverOptions` in `SolverContext`.
gcarpio21 Dec 20, 2025
b9dc850
Implemented method `getProof` in `CVC5AbstractProver` for retrieving …
gcarpio21 Dec 20, 2025
d3e69b1
Added enum `CVC5ProofRule` for the different proof rules used by CVC5.
gcarpio21 Dec 20, 2025
1b79e82
Added class `CV5Proof` which extends `AbstractProof`. `generateProofI…
gcarpio21 Dec 20, 2025
9f2ac63
Added method `requireProofGeneration` to `SolverBasedTest0`.
gcarpio21 Dec 20, 2025
dcc728a
In `ProverEnvironmentTest` added multiple methods for testing retriev…
gcarpio21 Dec 20, 2025
f849437
In `ProverEnvironmentTest` fixed "MissingFail" and "UnusedVariable" w…
gcarpio21 Jan 10, 2026
7abe581
Added file `package-info.java` to package `proofs`.
gcarpio21 Jan 10, 2026
f1fa31a
Added missing documentation in interface `Proof`.
gcarpio21 Jan 10, 2026
f5e3376
Fixed multiple checkstyle warnings.
gcarpio21 Jan 10, 2026
27847d8
Formatting changes
gcarpio21 Jan 10, 2026
8213c7a
Added `CVC5ProofRule` `CHAIN_M_RESOLUTION`.
gcarpio21 Jan 10, 2026
6a133f6
Implemented refaster suggestion.
gcarpio21 Jan 10, 2026
72c9697
Fixed "unused" warning in `ProverEnvironmentTest`.
gcarpio21 Jan 10, 2026
50a9b16
Removed unnecessary method from the `ProofRule` interface.
gcarpio21 Jan 16, 2026
32da899
Merge branch 'master' into 558-add-general-proof-api
gcarpio21 Jan 19, 2026
ed64164
Proofs: Changed `children` in `AbstractProof` to type `ImmutableSet`.…
gcarpio21 Jan 20, 2026
f037077
Proofs: Fixed year in copyright header.
gcarpio21 Jan 20, 2026
77d77a8
Fixed formatting
gcarpio21 Jan 20, 2026
c2cdbae
Proofs: fixed documentation for proof retrieval code.
gcarpio21 Jan 20, 2026
ab4e485
Proofs: added `Z3_WITH_INTERPOLATION` to the solvers to exclude durin…
gcarpio21 Jan 20, 2026
d1a18f9
Revert "Proofs: Changed `children` in `AbstractProof` to type `Immuta…
gcarpio21 Jan 20, 2026
98daf50
Proofs: Fixed header year, deleted unneeded comments.
gcarpio21 Jan 20, 2026
71fbd4b
Proofs: Field `children` of `AbstractProof` now is an `ImmutableSet`.
gcarpio21 Jan 21, 2026
0cdc9b0
Proofs: Moved `ProofFrame` inside `AbstractProof`. Changed return typ…
gcarpio21 Jan 22, 2026
230924a
Proofs: changed modifier of `CVC5Proof` constructor to private.
gcarpio21 Jan 22, 2026
47922a9
Proofs: return type of `getChildren` from the general proof API chang…
gcarpio21 Jan 22, 2026
7f94d1b
Proofs: renamed parameters, changed signatures and types in `Abstract…
gcarpio21 Jan 22, 2026
127a0af
Proofs: renamed parameters and changed types in `CVC5Proof` to comply…
gcarpio21 Jan 22, 2026
e969884
Proofs: renamed parameters in `ProverEnvironmentTest` to comply with …
gcarpio21 Jan 22, 2026
1e01011
Proofs: made `CVC5` `final`.
gcarpio21 Jan 26, 2026
c59874b
Proofs: removed unused import in `ProverEnvironmentTest`.
gcarpio21 Jan 26, 2026
1684258
Merge branch 'master' into 558-add-general-proof-api
gcarpio21 Jan 27, 2026
f750ce1
Proofs: renamed helper function for testing in `ProverEnvironmentTest`.
gcarpio21 Jan 28, 2026
be6ae14
Proofs: added more documentation to the `ProofRule` interface.
gcarpio21 Jan 28, 2026
58cf62c
Proofs: added more documentation in `ProverEnvironmentTest`.
gcarpio21 Jan 28, 2026
3fcf9f0
Proofs: Renamed `Proof` into `ProofNode`.
gcarpio21 Jan 30, 2026
4329cbf
Proofs: Added `AbstractProof`.
gcarpio21 Jan 30, 2026
f6489e8
Proofs: `AbstractProof` implements `Proof`. `getProof` in `BasicProve…
gcarpio21 Jan 30, 2026
76d8d71
Update year in copyright.
gcarpio21 Feb 17, 2026
cdca7ce
Proofs: Fix no exception when passing null to constructor of `Abstrac…
gcarpio21 Feb 17, 2026
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
7 changes: 7 additions & 0 deletions src/org/sosy_lab/java_smt/api/BasicProverEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Optional;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.sosy_lab.java_smt.api.SolverContext.ProverOptions;
import org.sosy_lab.java_smt.api.proofs.Proof;

/**
* Super interface for {@link ProverEnvironment} and {@link InterpolatingProverEnvironment} that
Expand Down Expand Up @@ -160,6 +161,12 @@ default ImmutableMap<String, String> getStatistics() {
return ImmutableMap.of();
}

/**
* Get proof of unsatisfiability of the conjuction of the current satck of all formulas. Should
* only be called after {@link #isUnsat()} returned <code>true</code>.
Comment thread
gcarpio21 marked this conversation as resolved.
Outdated
*/
Proof getProof() throws SolverException, InterruptedException;

/**
* Closes the prover environment. The object should be discarded, and should not be used after
* closing. The first call of this method will close the prover instance, further calls are
Expand Down
8 changes: 8 additions & 0 deletions src/org/sosy_lab/java_smt/api/SolverContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ enum ProverOptions {
*/
GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS,

/**
* Whether the solver should generate proofs for unsatisfiable formulas. For Z3, this parameter
* is context(not solver)-based, so for setting it, the extra option in the {@link
* org.sosy_lab.common.configuration.Configuration} instance: "requireProofs" should be set to
Comment thread
gcarpio21 marked this conversation as resolved.
Outdated
* "true".
*/
GENERATE_PROOFS,

/** Whether the solver should enable support for formulae build in SL theory. */
ENABLE_SEPARATION_LOGIC
}
Expand Down
43 changes: 43 additions & 0 deletions src/org/sosy_lab/java_smt/api/proofs/Proof.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* This file is part of JavaSMT,
* an API wrapper for a collection of SMT solvers:
* https://github.com/sosy-lab/java-smt
*
* SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
Comment thread
gcarpio21 marked this conversation as resolved.
Outdated
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.sosy_lab.java_smt.api.proofs;

import java.util.Optional;
import java.util.Set;
import org.sosy_lab.java_smt.api.Formula;

/** A proof node in the proof DAG of a proof. */
public interface Proof {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the name of this class should be ProofNode.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this was named ProofNode in the past and was changed due to me requesting it.

In general: the Proof interface/object should hold all proofs themselves, and provide API to access them (similar to the model). The problem with this being called Proof can be seen in the API, e.g. ImmutableSet<Proof> getChildren();. If getChildren() returns a Proof, it is clear that there is a problem, as the Proof should only exist as one central element. Hence i was wrong in wanting to rename this interface to Proof, and it should be called ProofNode as @gcarpio21 named it correctly initially!

We should then add a new interface Proof, that has the API to return the root (and only ever the root) of the proof DAG (and potentially more in the future).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been renamed and now there is a new Proof interface, which allows retrieval of the root node


/** Get the children of the proof node. */
Set<Proof> getChildren();

/**
* Check if the proof node is a leaf.
*
* @return True if the proof node is a leaf, false otherwise.
*/
boolean isLeaf();

/**
* Get the formula of the proof node.
*
* @return The formula of the proof node.
*/
Optional<Formula> getFormula();

/**
* Get the rule of the proof node.
*
* @return The rule of the proof node.
*/
ProofRule getRule();
}
53 changes: 53 additions & 0 deletions src/org/sosy_lab/java_smt/api/proofs/ProofFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* This file is part of JavaSMT,
* an API wrapper for a collection of SMT solvers:
* https://github.com/sosy-lab/java-smt
*
* SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.sosy_lab.java_smt.api.proofs;

/**
* Stores proof related information and gets stored in a stack when processing proofs. Each frame
* contains a proof object and the number of arguments it has.
*
* @param <T> The type of the proof object.
*/
public abstract class ProofFrame<T> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do i see it correctly that this class is only needed to generate the proof?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is wrapper that helps process the proofs, I did not want to repeat code over all solvers so I put the class in this directory.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this class inside AbstractProof I think this better fits the structure of the project. I was thinking of taking the proof interfaces out of the proofs package into the api one for the same reason.

final T proof;
int numArgs = 0;
boolean visited;

protected ProofFrame(T proof) {
this.proof = proof;
this.visited = false;
}

/** Get the proof object. */
public T getProof() {
return proof;
}

/** Get the number of arguments the proof object has. */
public int getNumArgs() {
return numArgs;
}

/** Check if the frame has been visited. */
public boolean isVisited() {
return visited;
}

/** Set the frame as visited. */
public void setAsVisited(boolean isVisited) {
this.visited = isVisited;
}

/** Set the number of arguments the proof object has. */
public void setNumArgs(int numArgs) {
this.numArgs = numArgs;
}
}
18 changes: 18 additions & 0 deletions src/org/sosy_lab/java_smt/api/proofs/ProofRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* This file is part of JavaSMT,
* an API wrapper for a collection of SMT solvers:
* https://github.com/sosy-lab/java-smt
*
* SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.sosy_lab.java_smt.api.proofs;

/** A proof rule from a given proof format. */
public interface ProofRule {

/** Get the name of the proof rule. */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example would be helpful for users to understand. Especially since distinct solvers can return distinct rules.

String getName();
}
14 changes: 14 additions & 0 deletions src/org/sosy_lab/java_smt/api/proofs/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* This file is part of JavaSMT,
* an API wrapper for a collection of SMT solvers:
* https://github.com/sosy-lab/java-smt
*
* SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* This package is meant to provide abstract classes and interfaces that are inherited and used all
* over to process proofs from the solvers.
*/
package org.sosy_lab.java_smt.api.proofs;
110 changes: 110 additions & 0 deletions src/org/sosy_lab/java_smt/basicimpl/AbstractProof.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* This file is part of JavaSMT,
* an API wrapper for a collection of SMT solvers:
* https://github.com/sosy-lab/java-smt
*
* SPDX-FileCopyrightText: 2024 Dirk Beyer <https://www.sosy-lab.org>
*
* SPDX-License-Identifier: Apache-2.0
*/

package org.sosy_lab.java_smt.basicimpl;

import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.sosy_lab.java_smt.api.Formula;
import org.sosy_lab.java_smt.api.proofs.Proof;
import org.sosy_lab.java_smt.api.proofs.ProofRule;

/**
* A proof DAG of a proof.
*
* @author Gabriel Carpio
*/
public abstract class AbstractProof implements Proof {

// protected abstract class Transformation {
Comment thread
gcarpio21 marked this conversation as resolved.
Outdated
// protected <TFormulaInfo, TType, TEnv, TFuncDecl, T> Transformation(
// FormulaCreator<TFormulaInfo, TType, TEnv, TFuncDecl> formulaCreator, T proof) {}

// protected abstract Proof generateProof();
// }

private final Set<Proof> children = new LinkedHashSet<>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try using immutable data-structures as far as possible.
You can find a good guide as to why and when to use mutable and immutable data-structures in CPAcheckers style-guide here.

private ProofRule rule;
protected Optional<Formula> formula = Optional.empty();

protected AbstractProof(ProofRule rule, @Nullable Formula formula) {
this.rule = rule;
this.formula = Optional.ofNullable(formula);
}

// TODO: Use Optional instead of nullable
Comment thread
gcarpio21 marked this conversation as resolved.
Outdated
@Override
public Optional<Formula> getFormula() {
return this.formula;
}

@Override
public Set<Proof> getChildren() {
return this.children;
}

protected void addChild(Proof child) {
this.children.add(child);
}

@Override
public ProofRule getRule() {
return rule;
}

@Override
public boolean isLeaf() {
return getChildren().isEmpty();
}

// void setRule(ProofRule rule) {
// this.rule = rule;
// }

public void setFormula(@Nullable Formula pFormula) {
formula = Optional.ofNullable(pFormula);
}

public void setRule(ProofRule pRule) {
rule = pRule;
}

// use this for debugging
public String proofAsString() {
return proofAsString(0);
}

protected String proofAsString(int indentLevel) {
StringBuilder sb = new StringBuilder();
String indent = " ".repeat(indentLevel);

String sFormula = getFormula().map(Object::toString).orElse("null");

sb.append(indent).append("Formula: ").append(sFormula).append("\n");
sb.append(indent).append("Rule: ").append(getRule().getName()).append("\n");
sb.append(indent)
.append("No. Children: ")
.append(this.isLeaf() ? 0 : getChildren().size())
.append("\n");
sb.append(indent).append("leaf: ").append(isLeaf()).append("\n");

int i = 0;
if (!isLeaf()) {
for (Proof child : getChildren()) {
sb.append(indent).append("Child ").append(++i).append(":\n");
sb.append(((AbstractProof) child).proofAsString(indentLevel + 1));
}
}

return sb.toString();
}
}
16 changes: 16 additions & 0 deletions src/org/sosy_lab/java_smt/basicimpl/AbstractProver.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.sosy_lab.java_smt.api.OptimizationProverEnvironment.OptStatus;
import org.sosy_lab.java_smt.api.SolverContext.ProverOptions;
import org.sosy_lab.java_smt.api.SolverException;
import org.sosy_lab.java_smt.api.proofs.Proof;

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

Expand All @@ -40,6 +41,7 @@ public abstract class AbstractProver<T> implements BasicProverEnvironment<T> {
protected final boolean generateAllSat;
protected final boolean generateUnsatCores;
private final boolean generateUnsatCoresOverAssumptions;
protected final boolean generateProofs;
protected final boolean enableSL;

// flags for status
Expand All @@ -64,6 +66,7 @@ protected AbstractProver(Set<ProverOptions> pOptions) {
generateUnsatCores = pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE);
generateUnsatCoresOverAssumptions =
pOptions.contains(ProverOptions.GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS);
generateProofs = pOptions.contains(ProverOptions.GENERATE_PROOFS);
enableSL = pOptions.contains(ProverOptions.ENABLE_SEPARATION_LOGIC);

assertedFormulas.add(LinkedHashMultimap.create());
Expand Down Expand Up @@ -97,6 +100,13 @@ protected final void checkGenerateUnsatCoresOverAssumptions() {
Preconditions.checkState(!wasLastSatCheckSatisfiable);
}

protected final void checkGenerateProofs() {
Preconditions.checkState(generateProofs, TEMPLATE, ProverOptions.GENERATE_PROOFS);
Preconditions.checkState(!closed);
Preconditions.checkState(!changedSinceLastSatQuery);
Preconditions.checkState(!wasLastSatCheckSatisfiable);
}

protected final void checkGenerateInterpolants() {
Preconditions.checkState(!closed);
Preconditions.checkState(
Expand Down Expand Up @@ -276,4 +286,10 @@ public void close() {
closeAllEvaluators();
closed = true;
}

@Override
public Proof getProof() throws InterruptedException, SolverException {
throw new UnsupportedOperationException(
"Proof generation is not available for the current solver.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.sosy_lab.java_smt.api.BooleanFormula;
import org.sosy_lab.java_smt.api.Model;
import org.sosy_lab.java_smt.api.SolverException;
import org.sosy_lab.java_smt.api.proofs.Proof;

public class BasicProverWithAssumptionsWrapper<T, P extends BasicProverEnvironment<T>>
implements BasicProverEnvironment<T> {
Expand Down Expand Up @@ -128,4 +129,9 @@ public <R> R allSat(AllSatCallback<R> pCallback, List<BooleanFormula> pImportant
clearAssumptions();
return delegate.allSat(pCallback, pImportant);
}

@Override
public Proof getProof() throws SolverException, InterruptedException {
return delegate.getProof();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.sosy_lab.java_smt.api.BooleanFormula;
import org.sosy_lab.java_smt.api.Model;
import org.sosy_lab.java_smt.api.SolverException;
import org.sosy_lab.java_smt.api.proofs.Proof;

class DebuggingBasicProverEnvironment<T> implements BasicProverEnvironment<T> {
private final BasicProverEnvironment<T> delegate;
Expand Down Expand Up @@ -93,6 +94,11 @@ public Optional<List<BooleanFormula>> unsatCoreOverAssumptions(
return delegate.unsatCoreOverAssumptions(assumptions);
}

@Override
public Proof getProof() throws SolverException, InterruptedException {
return delegate.getProof();
}

@Override
public void close() {
debugging.assertThreadLocal();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.sosy_lab.java_smt.api.Model;
import org.sosy_lab.java_smt.api.Model.ValueAssignment;
import org.sosy_lab.java_smt.api.SolverException;
import org.sosy_lab.java_smt.api.proofs.Proof;

/** Wraps a basic prover environment with a logging object. */
class LoggingBasicProverEnvironment<T> implements BasicProverEnvironment<T> {
Expand Down Expand Up @@ -120,6 +121,12 @@ public ImmutableMap<String, String> getStatistics() {
return wrapped.getStatistics();
}

@Override
public Proof getProof() throws SolverException, InterruptedException {
Proof p = wrapped.getProof();
return p;
}

@Override
public void close() {
wrapped.close();
Expand Down
Loading