Skip to content

Conversation

@gcarpio21
Copy link
Member

@gcarpio21 gcarpio21 commented Jan 16, 2026

Objective

This PR aims to extend support for retrieving proofs of unsatisfiability from the CVC5 solver according to a general proof interface that would be used to do the same for other capable solvers. It is a step in closing the issue #558 .

Key Changes

  • Introduced Proof, and ProofRule as the main components for handling proofs.
  • Implemented proof retrieval for the CVC solver.
  • Added multiple tests for retrieving proofs in edges cases and different theories.

It is now possible to enable proof generating capabilities from CVC5 by passing ProverOptions.GENERATE_PROOFS when creating a new ProverEnvironment instance. Then when a query returns UNSAT one can call getProof() to retrieve the proof of unsatisfiability.

…objects in `BasicProverEnvironment` and multiple classes that implement said interface: `BasicProverEnvironmentWithAssumptionsWrapper`, `DebuggingBasicProverEnvironment`, `LoggingBasicProverEnvironment`, `StatisticsBasicProverEnvironment`, `SynchronizedBasicProverEnvironment`, `SynchronizedBasicProverEnvironmentWithContext`.
…objects in abstract class `AbstractProver` as well as flag `generateProofs` and method `checkGenerateProofs`.
…oof objects from the solvers into `Proof` objects.
…mpl` handles transformation from the solver's native proof into the common `Proof`.
…ing common `Proof`s from solvers. Conditions include: different theories, trivial proofs, simple proofs, not enabling proof production, etc.
@gcarpio21 gcarpio21 requested a review from baierd January 16, 2026 19:11
@gcarpio21 gcarpio21 self-assigned this Jan 16, 2026
@gcarpio21 gcarpio21 linked an issue Jan 16, 2026 that may be closed by this pull request
9 tasks
@gcarpio21 gcarpio21 removed a link to an issue Jan 19, 2026
9 tasks
Copy link
Contributor

@baierd baierd left a comment

Choose a reason for hiding this comment

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

Partial review. I will continue tomorrow.

*
* @param <T> The type of the proof object.
*/
public abstract class ProofFrame<T> {
Copy link
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
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
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.

import org.sosy_lab.java_smt.api.Formula;

/** A proof node in the proof DAG of a proof. */
public interface Proof {
Copy link
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
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).

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

private final Set<Proof> children = new LinkedHashSet<>();
Copy link
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.

import org.sosy_lab.java_smt.api.Formula;

/** A proof node in the proof DAG of a proof. */
public interface Proof {
Copy link
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).

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

/** Get the name of the proof rule. */
Copy link
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.

*/
GENERATE_UNSAT_CORE_OVER_ASSUMPTIONS,

/** Whether the solver should generate proofs for unsatisfiable formulas. */
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a note about Z3 here please? The Z3 proof situation might be confusing for users.

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean about it needing proof generation enabled on the context object?

I was thinking to leave that out for this, as the only solver with proof generation should be CVC5 for now. Once it is turn for Z3 then I would add the corresponding note.

}
}

// Traverses a proof and asserts that certain values are not null, instances, etc.
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like the name could be improved into something like varifyProofObjectValidity. (checkProof might be misunderstood such that the proof itself is checked for validity, but you are only checking the objects inside.) Also JavaDoc with more information would be helpful here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants