mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08: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:
parent
63840806d8
commit
1b83c677ea
|
@ -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 {
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ struct limit_denominator_rewriter_cfg : public default_rewriter_cfg {
|
||||||
q2 = tj * q1 + q0;
|
q2 = tj * q1 + q0;
|
||||||
p2 = tj * p1 + p0;
|
p2 = tj * p1 + p0;
|
||||||
if (q2 >= m_limit) {
|
if (q2 >= m_limit) {
|
||||||
num = p2/q2;
|
num = p2 / q2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
rem = n - tj * d;
|
rem = n - tj * d;
|
||||||
|
@ -104,11 +105,11 @@ struct limit_denominator_rewriter_cfg : public default_rewriter_cfg {
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
limit_num_generalizer::limit_num_generalizer(context &ctx,
|
limit_num_generalizer::limit_num_generalizer(context &ctx,
|
||||||
unsigned failure_limit)
|
unsigned failure_limit)
|
||||||
: lemma_generalizer(ctx), m_failure_limit(failure_limit) {}
|
: lemma_generalizer(ctx), m_failure_limit(failure_limit) {}
|
||||||
|
|
||||||
bool limit_num_generalizer::limit_denominators(expr_ref_vector &lits,
|
bool limit_num_generalizer::limit_denominators(expr_ref_vector &lits,
|
||||||
rational &limit) {
|
rational &limit) {
|
||||||
ast_manager &m = m_ctx.get_ast_manager();
|
ast_manager &m = m_ctx.get_ast_manager();
|
||||||
limit_denominator_rewriter_cfg rw_cfg(m, limit);
|
limit_denominator_rewriter_cfg rw_cfg(m, limit);
|
||||||
rewriter_tpl<limit_denominator_rewriter_cfg> rw(m, false, rw_cfg);
|
rewriter_tpl<limit_denominator_rewriter_cfg> rw(m, false, rw_cfg);
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -3051,9 +3052,10 @@ lbool context::solve_core (unsigned from_lvl)
|
||||||
|
|
||||||
STRACE("spacer_progress", tout << "\n* LEVEL " << lvl << "\n";);
|
STRACE("spacer_progress", tout << "\n* LEVEL " << lvl << "\n";);
|
||||||
IF_VERBOSE(1,
|
IF_VERBOSE(1,
|
||||||
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());
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue