mirror of
https://github.com/Z3Prover/z3
synced 2025-04-30 04:15: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:
parent
9782d4a730
commit
107981f099
40 changed files with 295 additions and 153 deletions
|
@ -251,6 +251,17 @@ namespace arith {
|
|||
if (hi_sup != end) mk_bound_axiom(b, *hi_sup);
|
||||
}
|
||||
|
||||
void solver::add_farkas_clause(sat::literal l1, sat::literal l2) {
|
||||
arith_proof_hint* bound_params = nullptr;
|
||||
if (ctx.use_drat()) {
|
||||
m_arith_hint.set_type(ctx, hint_type::farkas_h);
|
||||
m_arith_hint.add_lit(rational(1), ~l1);
|
||||
m_arith_hint.add_lit(rational(1), ~l2);
|
||||
bound_params = m_arith_hint.mk(ctx);
|
||||
}
|
||||
add_clause(l1, l2, bound_params);
|
||||
}
|
||||
|
||||
void solver::mk_bound_axiom(api_bound& b1, api_bound& b2) {
|
||||
literal l1(b1.get_lit());
|
||||
literal l2(b2.get_lit());
|
||||
|
@ -263,55 +274,45 @@ namespace arith {
|
|||
if (k1 == k2 && kind1 == kind2) return;
|
||||
SASSERT(k1 != k2 || kind1 != kind2);
|
||||
|
||||
auto bin_clause = [&](sat::literal l1, sat::literal l2) {
|
||||
arith_proof_hint* bound_params = nullptr;
|
||||
if (ctx.use_drat()) {
|
||||
m_arith_hint.set_type(ctx, hint_type::farkas_h);
|
||||
m_arith_hint.add_lit(rational(1), ~l1);
|
||||
m_arith_hint.add_lit(rational(1), ~l2);
|
||||
bound_params = m_arith_hint.mk(ctx);
|
||||
}
|
||||
add_clause(l1, l2, bound_params);
|
||||
};
|
||||
|
||||
if (kind1 == lp_api::lower_t) {
|
||||
if (kind2 == lp_api::lower_t) {
|
||||
if (k2 <= k1)
|
||||
bin_clause(~l1, l2);
|
||||
add_farkas_clause(~l1, l2);
|
||||
else
|
||||
bin_clause(l1, ~l2);
|
||||
add_farkas_clause(l1, ~l2);
|
||||
}
|
||||
else if (k1 <= k2)
|
||||
// k1 <= k2, k1 <= x or x <= k2
|
||||
bin_clause(l1, l2);
|
||||
add_farkas_clause(l1, l2);
|
||||
else {
|
||||
// k1 > hi_inf, k1 <= x => ~(x <= hi_inf)
|
||||
bin_clause(~l1, ~l2);
|
||||
add_farkas_clause(~l1, ~l2);
|
||||
if (v_is_int && k1 == k2 + rational(1))
|
||||
// k1 <= x or x <= k1-1
|
||||
bin_clause(l1, l2);
|
||||
add_farkas_clause(l1, l2);
|
||||
}
|
||||
}
|
||||
else if (kind2 == lp_api::lower_t) {
|
||||
if (k1 >= k2)
|
||||
// k1 >= lo_inf, k1 >= x or lo_inf <= x
|
||||
bin_clause(l1, l2);
|
||||
add_farkas_clause(l1, l2);
|
||||
else {
|
||||
// k1 < k2, k2 <= x => ~(x <= k1)
|
||||
bin_clause(~l1, ~l2);
|
||||
add_farkas_clause(~l1, ~l2);
|
||||
if (v_is_int && k1 == k2 - rational(1))
|
||||
// x <= k1 or k1+l <= x
|
||||
bin_clause(l1, l2);
|
||||
add_farkas_clause(l1, l2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// kind1 == A_UPPER, kind2 == A_UPPER
|
||||
if (k1 >= k2)
|
||||
// k1 >= k2, x <= k2 => x <= k1
|
||||
bin_clause(l1, ~l2);
|
||||
add_farkas_clause(l1, ~l2);
|
||||
else
|
||||
// k1 <= hi_sup , x <= k1 => x <= hi_sup
|
||||
bin_clause(~l1, l2);
|
||||
add_farkas_clause(~l1, l2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,9 +422,9 @@ namespace arith {
|
|||
ge = mk_literal(a.mk_ge(diff, zero));
|
||||
}
|
||||
++m_stats.m_assert_diseq;
|
||||
add_clause(~eq, le);
|
||||
add_clause(~eq, ge);
|
||||
add_clause(~le, ~ge, eq);
|
||||
add_farkas_clause(~eq, le);
|
||||
add_farkas_clause(~eq, ge);
|
||||
add_clause(~le, ~ge, eq, explain_triangle_eq(le, ge, eq));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue