Proof format: Cooperating Proof Calculus
Using option proof-format-mode=cpc , cvc5 outputs proofs in the Cooperating Proof Calculus proof format.
This calculus was designed to faithfully represent cvc5’s internal reasoning. As a disclaimer, this means that it treats certain operators differently from the SMT-LIB standard. As an example, cvc5 uses mixed arithmetic internally, where integers and reals can appear together. A comprehensive list of these differences can be found in the Eunoia definition of CPC, as described below.
Ethos is an efficient proof checker written in C++ which can check proofs in the CPC format. For a quick start, the cvc5 repository contains a script to download and install the Ethos checker, and create scripts for generating proofs with cvc5 and checking them with the Ethos proof checker.
The Ethos checker is based on the logical framework Eunoia. The Cooperating Proof Calculus has been formalized in a Eunoia signature, which is contained within the cvc5 repository in this file . Based on this signature, Ethos can check CPC proofs over all theories that are formalized in this signature. For more details on Eunoia and a comprehensive overview of the language supported by the Ethos checker, see the user manual here .
Note that several proof rules in the Cooperating Proof Calculus are not yet supported in Eunoia signatures. Steps that use such rules are printed as trust steps in the proof. A trust step proves an arbitrary formula with no provided justification. The resulting proof contains warnings for trust steps that indicate which internal proof rules were recorded as trust steps in the proof.
Upon successful exit, ethos will return the output incomplete if any trust step is used in the proof, indicating that the reasoning in the proof was incomplete. Otherwise, if all proof steps are fully specified, ethos will return the output correct . All proofs in the cpc format are closed refutations of the input, in that the proof will assume formulas from the input and end with a step proving false.
For more fine-grained proofs, the additional option proof-granularity=dsl-rewrite can be passed to cvc5. This will result in proofs with more detail.
A simple example of cvc5 producing a proof in CPC proof format is shown below. Notice that the concrete syntax of CPC is very similar to the Alethe format. However, the proof rules used by these two formats are different.
$ bin/cvc5 --dump-proofs --proof-format-mode=cpc --proof-granularity=dsl-rewrite ../test/regress/cli/regress0/proofs/qgu-fuzz-1-bool-sat.smt2
unsat
(
(declare-const c Bool)
(declare-const b Bool)
(declare-const d Bool)
(define @t1 () (= b d))
(define @t2 () (or b d))
(define @t3 () (not (ite d c false)))
(define @t4 () (and d d))
(define @t5 () (and d c))
(define @t6 () (not @t1))
(define @t7 () (@list true false))
(assume @p1 (and (or d b) (= c d) @t3 (= @t2 @t1)))
(step @p2 :rule and_elim :premises (@p1) :args (0))
(step @p3 :rule reordering :premises (@p2) :args (@t2))
(step @p4 :rule aci_norm :args ((= @t4 d)))
(step @p5 :rule cong :premises (@p4) :args ((not @t4)))
(step @p6 :rule and_elim :premises (@p1) :args (1))
(step @p7 :rule refl :args (d))
(step @p8 :rule nary_cong :premises (@p7 @p6) :args (@t5))
(step @p9 :rule cong :premises (@p8) :args ((not @t5)))
(step @p10 :rule trans :premises (@p9 @p5))
(step @p11 :rule ite-else-false :args (d c))
(step @p12 :rule cong :premises (@p11) :args (@t3))
(step @p13 :rule trans :premises (@p12 @p10))
(step @p14 :rule and_elim :premises (@p1) :args (2))
(step @p15 :rule eq_resolve :premises (@p14 @p13))
(step @p16 :rule chain_m_resolution :premises (@p3 @p15) :args (b (@list true) (@list d)))
(step @p17 :rule cnf_equiv_pos1 :args (@t1))
(step @p18 :rule reordering :premises (@p17) :args ((or d (not b) @t6)))
(step @p19 :rule chain_m_resolution :premises (@p18 @p15 @p16) :args (@t6 @t7 (@list d b)))
(step @p20 :rule and_elim :premises (@p1) :args (3))
(step @p21 :rule equiv_elim1 :premises (@p20))
(step @p22 :rule reordering :premises (@p21) :args ((or @t1 (not @t2))))
(step @p23 false :rule chain_m_resolution :premises (@p22 @p19 @p3) :args (false @t7 (@list @t1 @t2)))
)
Checking with Logos
Logos is an alternative checker for the CPC format, written in Lean, whose soundness is proven against a formalization of the semantics of SMT-LIB. It accepts the same proof syntax as Ethos, but does not read Eunoia signatures. Its proof rules are compiled from the same Eunoia definition of CPC that is contained in this repository, so that the proof rules of the two checkers come from a single definition. The cvc5 repository contains a script to download and install the Logos checker, and create scripts for generating proofs with cvc5 and checking them with the Logos proof checker.
Logos targets the fragment of CPC that is used by safe builds of cvc5, that is,
builds configured with
./configure.sh
safe
.
The expert CPC rules used by non-safe builds, which are defined in
CpcExpert.eo
, lie outside that
fragment, and Logos will report a parse error on them.
In some very rare cases, a proof in safe mode may lie outside the fragment for
which Logos is proven correct.
For an input outside its scope, Logos reports
incomplete
.
This means that the proof of correctness for Logos does not cover that input;
it does not mean that Logos found the CPC proof to be incorrect.
Because the CI of cvc5 requires proofs in safe mode to be complete, that is,
free of trust steps, every proof rule that a safe build can use is one that
Logos verifies, apart from inputs of the kind just described.
Keeping CPC and Logos in sync
Since that compilation consumes the signature in this repository, a change to
proofs/eo/cpc
must remain in sync with Logos.
The commit of Logos this repository is pinned to is
LOGOS_VERSION
in
contrib/get-logos-checker
, which is the
only place it appears.
The
script
contrib/check-logos-compilation
reads that pin, sets up the Eunoia
compiler that performs the compilation, and reports whether the signature
still compiles and whether that pinned Logos was generated from the current
version of it.
This check does not build Logos or check its Lean proofs.
The
cpc-logos
workflow
additionally requires that the
CI of Logos
has passed at the
pinned commit, which it establishes by querying the result already recorded
for that commit rather than by rerunning that CI.
These two conditions together, that the pinned Logos was generated from the signature in this repository and that the CI of Logos passes at that commit, are what makes the Eunoia definition of CPC here correct with respect to the semantics of SMT-LIB formalized in Logos, up to what the CI of Logos tests.
Changing the CPC signature
Adding a proof rule to
proofs/eo/cpc
, or removing
one, therefore requires a matching change to Logos: the Lean proof of that rule
is written or removed there, and
LOGOS_VERSION
is then moved to the
resulting commit, which moves both the checker that is installed and the
checker that CPC is checked against.
Logos is regenerated and repaired against a new version of the signature by the
procedure documented there
.
Until the pin is moved, the
cpc-logos
workflow fails on the cvc5 pull request that changes the signature.
A rule that is needed in cvc5’s safe mode but cannot readily be proven in Logos does not have to hold up that pull request. There are two ways of proceeding:
-
Guard the new cvc5 reasoning that gives rise to the rule so that it is not available in safe mode. Optionally, proof rules that are not yet ready to be run in safe mode can be added to CpcExpert.eo .
-
Keep the new reasoning in safe mode and have Logos exclude it from its proof, by marking it
:excludein install/defs/Cpc.eos . This unblocks the cvc5 pull request without extending the guarantee above: a proof that uses such a rule will be reportedincompleteby Logos.