20
20
#include " ast/rewriter/rewriter.h"
21
21
#include " ast/rewriter/rewriter_def.h"
22
22
#include " muz/spacer/spacer_generalizers.h"
23
+ #include " smt/smt_solver.h"
23
24
24
25
namespace spacer {
25
26
@@ -74,7 +75,7 @@ struct limit_denominator_rewriter_cfg : public default_rewriter_cfg {
74
75
q2 = tj * q1 + q0;
75
76
p2 = tj * p1 + p0;
76
77
if (q2 >= m_limit) {
77
- num = p2/ q2;
78
+ num = p2 / q2;
78
79
return true ;
79
80
}
80
81
rem = n - tj * d;
@@ -104,11 +105,11 @@ struct limit_denominator_rewriter_cfg : public default_rewriter_cfg {
104
105
};
105
106
} // namespace
106
107
limit_num_generalizer::limit_num_generalizer (context &ctx,
107
- unsigned failure_limit)
108
+ unsigned failure_limit)
108
109
: lemma_generalizer(ctx), m_failure_limit(failure_limit) {}
109
110
110
111
bool limit_num_generalizer::limit_denominators (expr_ref_vector &lits,
111
- rational &limit) {
112
+ rational &limit) {
112
113
ast_manager &m = m_ctx.get_ast_manager ();
113
114
limit_denominator_rewriter_cfg rw_cfg (m, limit);
114
115
rewriter_tpl<limit_denominator_rewriter_cfg> rw (m, false , rw_cfg);
@@ -135,6 +136,10 @@ void limit_num_generalizer::operator()(lemma_ref &lemma) {
135
136
136
137
expr_ref_vector cube (m);
137
138
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 ());
138
143
unsigned weakness = lemma->weakness ();
139
144
rational limit (100 );
140
145
for (unsigned num_failures = 0 ; num_failures < m_failure_limit;
@@ -143,8 +148,33 @@ void limit_num_generalizer::operator()(lemma_ref &lemma) {
143
148
cube.append (lemma->get_cube ());
144
149
// try to limit denominators
145
150
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
+ << " \n into\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\n to\n "
177
+ << cube << " \n " ;);
148
178
lemma->update_cube (lemma->get_pob (), cube);
149
179
lemma->set_level (uses_level);
150
180
// done
0 commit comments