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

spacer: fixes lim_num_generalizer

Must check that newly constructed generalization blocks
the proof obligation.

Was only checking that generalization is entailed by the transition system!
This commit is contained in:
Arie Gurfinkel 2019-09-11 21:53:13 +02:00 committed by Nikolaj Bjorner
parent 63840806d8
commit 1b83c677ea
2 changed files with 44 additions and 12 deletions

View file

@ -20,6 +20,7 @@
#include "ast/rewriter/rewriter.h" #include "ast/rewriter/rewriter.h"
#include "ast/rewriter/rewriter_def.h" #include "ast/rewriter/rewriter_def.h"
#include "muz/spacer/spacer_generalizers.h" #include "muz/spacer/spacer_generalizers.h"
#include "smt/smt_solver.h"
namespace spacer { namespace spacer {
@ -135,6 +136,10 @@ void limit_num_generalizer::operator()(lemma_ref &lemma) {
expr_ref_vector cube(m); expr_ref_vector cube(m);
// create a solver to check whether updated cube is in a generalization
ref<solver> sol = mk_smt_solver(m, params_ref::get_empty(), symbol::null);
SASSERT(lemma->has_pob());
sol->assert_expr(lemma->get_pob()->post());
unsigned weakness = lemma->weakness(); unsigned weakness = lemma->weakness();
rational limit(100); rational limit(100);
for (unsigned num_failures = 0; num_failures < m_failure_limit; for (unsigned num_failures = 0; num_failures < m_failure_limit;
@ -143,8 +148,33 @@ void limit_num_generalizer::operator()(lemma_ref &lemma) {
cube.append(lemma->get_cube()); cube.append(lemma->get_cube());
// try to limit denominators // try to limit denominators
if (!limit_denominators(cube, limit)) return; if (!limit_denominators(cube, limit)) return;
// check that the result is inductive
if (pt.check_inductive(lemma->level(), cube, uses_level, weakness)) { bool failed = false;
// check that pob->post() ==> cube
for (auto *lit : cube) {
solver::scoped_push _p_(*sol);
expr_ref nlit(m);
nlit = m.mk_not(lit);
sol->assert_expr(nlit);
lbool res = sol->check_sat(0, nullptr);
if (res == l_false) {
// good
} else {
failed = true;
TRACE("spacer.limnum", tout << "Failed to generalize: "
<< lemma->get_cube()
<< "\ninto\n"
<< cube << "\n";);
break;
}
}
// check that !cube & F & Tr ==> !cube'
if (!failed && pt.check_inductive(lemma->level(), cube, uses_level, weakness)) {
TRACE("spacer",
tout << "Reduced fractions from:\n"
<< lemma->get_cube() << "\n\nto\n"
<< cube << "\n";);
lemma->update_cube(lemma->get_pob(), cube); lemma->update_cube(lemma->get_pob(), cube);
lemma->set_level(uses_level); lemma->set_level(uses_level);
// done // done

View file

@ -2655,11 +2655,6 @@ void context::init_lemma_generalizers()
{ {
reset_lemma_generalizers(); reset_lemma_generalizers();
if (m_use_lim_num_gen) {
// first, to get small numbers before any other smt calls
m_lemma_generalizers.push_back(alloc(limit_num_generalizer, *this, 5));
}
if (m_q3_qgen) { if (m_q3_qgen) {
m_lemma_generalizers.push_back(alloc(lemma_bool_inductive_generalizer, m_lemma_generalizers.push_back(alloc(lemma_bool_inductive_generalizer,
*this, 0, true)); *this, 0, true));
@ -2678,6 +2673,12 @@ void context::init_lemma_generalizers()
m_lemma_generalizers.push_back(alloc(lemma_bool_inductive_generalizer, *this, 0)); m_lemma_generalizers.push_back(alloc(lemma_bool_inductive_generalizer, *this, 0));
} }
// after the lemma is minimized (maybe should also do before)
if (m_use_lim_num_gen) {
m_lemma_generalizers.push_back(alloc(limit_num_generalizer, *this, 5));
}
if (m_use_array_eq_gen) { if (m_use_array_eq_gen) {
m_lemma_generalizers.push_back(alloc(lemma_array_eq_generalizer, *this)); m_lemma_generalizers.push_back(alloc(lemma_array_eq_generalizer, *this));
} }
@ -3054,6 +3055,7 @@ lbool context::solve_core (unsigned from_lvl)
if (m_params.print_statistics()) { if (m_params.print_statistics()) {
statistics st; statistics st;
collect_statistics(st); collect_statistics(st);
st.display_smt2(verbose_stream());
}; };
); );