Skip to content

Commit 1b83c67

Browse files
agurfinkelNikolajBjorner
authored andcommitted
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!
1 parent 6384080 commit 1b83c67

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

src/muz/spacer/spacer_arith_generalizers.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ast/rewriter/rewriter.h"
2121
#include "ast/rewriter/rewriter_def.h"
2222
#include "muz/spacer/spacer_generalizers.h"
23+
#include "smt/smt_solver.h"
2324

2425
namespace spacer {
2526

@@ -74,7 +75,7 @@ struct limit_denominator_rewriter_cfg : public default_rewriter_cfg {
7475
q2 = tj * q1 + q0;
7576
p2 = tj * p1 + p0;
7677
if (q2 >= m_limit) {
77-
num = p2/q2;
78+
num = p2 / q2;
7879
return true;
7980
}
8081
rem = n - tj * d;
@@ -104,11 +105,11 @@ struct limit_denominator_rewriter_cfg : public default_rewriter_cfg {
104105
};
105106
} // namespace
106107
limit_num_generalizer::limit_num_generalizer(context &ctx,
107-
unsigned failure_limit)
108+
unsigned failure_limit)
108109
: lemma_generalizer(ctx), m_failure_limit(failure_limit) {}
109110

110111
bool limit_num_generalizer::limit_denominators(expr_ref_vector &lits,
111-
rational &limit) {
112+
rational &limit) {
112113
ast_manager &m = m_ctx.get_ast_manager();
113114
limit_denominator_rewriter_cfg rw_cfg(m, limit);
114115
rewriter_tpl<limit_denominator_rewriter_cfg> rw(m, false, rw_cfg);
@@ -135,6 +136,10 @@ void limit_num_generalizer::operator()(lemma_ref &lemma) {
135136

136137
expr_ref_vector cube(m);
137138

139+
// create a solver to check whether updated cube is in a generalization
140+
ref<solver> sol = mk_smt_solver(m, params_ref::get_empty(), symbol::null);
141+
SASSERT(lemma->has_pob());
142+
sol->assert_expr(lemma->get_pob()->post());
138143
unsigned weakness = lemma->weakness();
139144
rational limit(100);
140145
for (unsigned num_failures = 0; num_failures < m_failure_limit;
@@ -143,8 +148,33 @@ void limit_num_generalizer::operator()(lemma_ref &lemma) {
143148
cube.append(lemma->get_cube());
144149
// try to limit denominators
145150
if (!limit_denominators(cube, limit)) return;
146-
// check that the result is inductive
147-
if (pt.check_inductive(lemma->level(), cube, uses_level, weakness)) {
151+
152+
bool failed = false;
153+
// check that pob->post() ==> cube
154+
for (auto *lit : cube) {
155+
solver::scoped_push _p_(*sol);
156+
expr_ref nlit(m);
157+
nlit = m.mk_not(lit);
158+
sol->assert_expr(nlit);
159+
lbool res = sol->check_sat(0, nullptr);
160+
if (res == l_false) {
161+
// good
162+
} else {
163+
failed = true;
164+
TRACE("spacer.limnum", tout << "Failed to generalize: "
165+
<< lemma->get_cube()
166+
<< "\ninto\n"
167+
<< cube << "\n";);
168+
break;
169+
}
170+
}
171+
172+
// check that !cube & F & Tr ==> !cube'
173+
if (!failed && pt.check_inductive(lemma->level(), cube, uses_level, weakness)) {
174+
TRACE("spacer",
175+
tout << "Reduced fractions from:\n"
176+
<< lemma->get_cube() << "\n\nto\n"
177+
<< cube << "\n";);
148178
lemma->update_cube(lemma->get_pob(), cube);
149179
lemma->set_level(uses_level);
150180
// done

src/muz/spacer/spacer_context.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2655,11 +2655,6 @@ void context::init_lemma_generalizers()
26552655
{
26562656
reset_lemma_generalizers();
26572657

2658-
if (m_use_lim_num_gen) {
2659-
// first, to get small numbers before any other smt calls
2660-
m_lemma_generalizers.push_back(alloc(limit_num_generalizer, *this, 5));
2661-
}
2662-
26632658
if (m_q3_qgen) {
26642659
m_lemma_generalizers.push_back(alloc(lemma_bool_inductive_generalizer,
26652660
*this, 0, true));
@@ -2678,6 +2673,12 @@ void context::init_lemma_generalizers()
26782673
m_lemma_generalizers.push_back(alloc(lemma_bool_inductive_generalizer, *this, 0));
26792674
}
26802675

2676+
// after the lemma is minimized (maybe should also do before)
2677+
if (m_use_lim_num_gen) {
2678+
m_lemma_generalizers.push_back(alloc(limit_num_generalizer, *this, 5));
2679+
}
2680+
2681+
26812682
if (m_use_array_eq_gen) {
26822683
m_lemma_generalizers.push_back(alloc(lemma_array_eq_generalizer, *this));
26832684
}
@@ -3051,9 +3052,10 @@ lbool context::solve_core (unsigned from_lvl)
30513052

30523053
STRACE("spacer_progress", tout << "\n* LEVEL " << lvl << "\n";);
30533054
IF_VERBOSE(1,
3054-
if (m_params.print_statistics ()) {
3055+
if (m_params.print_statistics()) {
30553056
statistics st;
3056-
collect_statistics (st);
3057+
collect_statistics(st);
3058+
st.display_smt2(verbose_stream());
30573059
};
30583060
);
30593061

0 commit comments

Comments
 (0)