3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-29 20:05:51 +00:00

update proof formats for new core

- update proof format for quantifier instantiation to track original literals
- update proof replay tools with ability to extract proof object

The formats and features are subject to heavy revisions.

Example
```
(set-option :sat.euf true)
(set-option :sat.smt.proof eufproof.smt2)
(declare-fun f (Int) Int)
(declare-const x Int)
(assert (or (= (f (f (f x))) x) (= (f (f x)) x)))
(assert (not (= (f (f (f (f (f (f x)))))) x)))
(check-sat)
```

eufproof.smt2 is:
```
(declare-fun x () Int)
(declare-fun f (Int) Int)
(define-const $24 Int (f x))
(define-const $25 Int (f $24))
(define-const $26 Int (f $25))
(define-const $27 Bool (= $26 x))
(define-const $28 Bool (= $25 x))
(assume $27 $28)
(define-const $30 Int (f $26))
(define-const $31 Int (f $30))
(define-const $32 Int (f $31))
(define-const $33 Bool (= $32 x))
(assume (not $33))
(declare-fun rup () Proof)
(infer (not $33) rup)
(declare-fun euf (Bool Bool Proof Proof Proof Proof) Proof)
(declare-fun cc (Bool) Proof)
(define-const $42 Bool (= $32 $30))
(define-const $43 Proof (cc $42))
(define-const $40 Bool (= $31 $24))
(define-const $41 Proof (cc $40))
(define-const $38 Bool (= $30 $25))
(define-const $39 Proof (cc $38))
(define-const $36 Bool (= $24 $26))
(define-const $37 Proof (cc $36))
(define-const $34 Bool (not $33))
(define-const $44 Proof (euf $34 $28 $37 $39 $41 $43))
(infer (not $28) $33 $44)
(infer (not $28) rup)
(infer $27 rup)
(declare-fun euf (Bool Bool Proof Proof Proof) Proof)
(define-const $49 Bool (= $32 $26))
(define-const $50 Proof (cc $49))
(define-const $47 Bool (= $31 $25))
(define-const $48 Proof (cc $47))
(define-const $45 Bool (= $24 $30))
(define-const $46 Proof (cc $45))
(define-const $51 Proof (euf $34 $27 $46 $48 $50))
(infer $33 $51)
(infer rup)
```

Example of inspecting proof from Python:

```
from z3 import *

def parse(file):
    s = Solver()
    set_option("solver.proof.save", True)
    set_option("solver.proof.check", False)
    s.from_file(file)
    for step in s.proof().children():
        print(step)

parse("../eufproof.smt2")
```

Proof checking (self-validation) is on by default.
Proof saving is off by default.

You can use the proof logs and the proof terms to retrieve quantifier instantiations from the new core.

The self-checker contains a few built-in tuned checkers but falls back to self-checking inferred clauses using SMT.
This commit is contained in:
Nikolaj Bjorner 2022-09-28 10:40:43 -07:00
parent 9782d4a730
commit 107981f099
40 changed files with 295 additions and 153 deletions

View file

@ -364,36 +364,49 @@ namespace q {
}
}
q_proof_hint* q_proof_hint::mk(euf::solver& s, unsigned n, euf::enode* const* bindings) {
auto* mem = s.get_region().allocate(q_proof_hint::get_obj_size(n));
q_proof_hint* ph = new (mem) q_proof_hint();
ph->m_num_bindings = n;
q_proof_hint* q_proof_hint::mk(euf::solver& s, sat::literal_vector const& lits, unsigned n, euf::enode* const* bindings) {
auto* mem = s.get_region().allocate(q_proof_hint::get_obj_size(n, lits.size()));
q_proof_hint* ph = new (mem) q_proof_hint(n, lits.size());
for (unsigned i = 0; i < n; ++i)
ph->m_bindings[i] = bindings[i]->get_expr();
for (unsigned i = 0; i < lits.size(); ++i)
ph->m_literals[i] = lits[i];
return ph;
}
q_proof_hint* q_proof_hint::mk(euf::solver& s, unsigned n, expr* const* bindings) {
auto* mem = s.get_region().allocate(q_proof_hint::get_obj_size(n));
q_proof_hint* ph = new (mem) q_proof_hint();
ph->m_num_bindings = n;
q_proof_hint* q_proof_hint::mk(euf::solver& s, sat::literal l1, sat::literal l2, unsigned n, expr* const* bindings) {
auto* mem = s.get_region().allocate(q_proof_hint::get_obj_size(n, 2));
q_proof_hint* ph = new (mem) q_proof_hint(n, 2);
for (unsigned i = 0; i < n; ++i)
ph->m_bindings[i] = bindings[i];
ph->m_literals[0] = l1;
ph->m_literals[1] = l2;
return ph;
}
expr* q_proof_hint::get_hint(euf::solver& s) const {
ast_manager& m = s.get_manager();
expr_ref_vector args(m);
sort_ref_vector sorts(m);
for (unsigned i = 0; i < m_num_bindings; ++i) {
args.push_back(m_bindings[i]);
sorts.push_back(args.back()->get_sort());
}
ptr_buffer<sort> sorts;
expr_ref binding(m);
sort* range = m.mk_proof_sort();
func_decl* d = m.mk_func_decl(symbol("inst"), args.size(), sorts.data(), range);
expr* r = m.mk_app(d, args);
return r;
func_decl* d;
for (unsigned i = 0; i < m_num_bindings; ++i)
args.push_back(m_bindings[i]);
for (expr* arg : args)
sorts.push_back(arg->get_sort());
d = m.mk_func_decl(symbol("bind"), args.size(), sorts.data(), range);
binding = m.mk_app(d, args);
args.reset();
sorts.reset();
for (unsigned i = 0; i < m_num_literals; ++i)
args.push_back(s.literal2expr(~m_literals[i]));
args.push_back(binding);
for (expr* arg : args)
sorts.push_back(arg->get_sort());
d = m.mk_func_decl(symbol("inst"), args.size(), sorts.data(), range);
return m.mk_app(d, args);
}
}