@@ -55,6 +55,8 @@ literal_vector collect_induction_literals::pre_select() {
55
55
continue ;
56
56
result.push_back (lit);
57
57
}
58
+ TRACE (" induction" , ctx.display (tout << " literal index: " << m_literal_index << " \n " << result << " \n " ););
59
+
58
60
ctx.push_trail (value_trail<context, unsigned >(m_literal_index));
59
61
m_literal_index = ctx.assigned_literals ().size ();
60
62
return result;
@@ -68,11 +70,6 @@ void collect_induction_literals::model_sweep_filter(literal_vector& candidates)
68
70
vector<expr_ref_vector> values;
69
71
vs (terms, values);
70
72
unsigned j = 0 ;
71
- IF_VERBOSE (1 ,
72
- verbose_stream () << " terms: " << terms << " \n " ;
73
- for (auto const & vec : values) {
74
- verbose_stream () << " assignment: " << vec << " \n " ;
75
- });
76
73
for (unsigned i = 0 ; i < terms.size (); ++i) {
77
74
literal lit = candidates[i];
78
75
bool is_viable_candidate = true ;
@@ -109,14 +106,26 @@ literal_vector collect_induction_literals::operator()() {
109
106
// create_induction_lemmas
110
107
111
108
bool create_induction_lemmas::is_induction_candidate (enode* n) {
112
- expr * e = n->get_owner ();
109
+ app * e = n->get_owner ();
113
110
if (m.is_value (e))
114
111
return false ;
115
- // TBD: filter if n is equivalent to a value.
112
+ bool in_good_context = false ;
113
+ for (enode* p : n->get_parents ()) {
114
+ app* o = p->get_owner ();
115
+ if (o->get_family_id () != m.get_basic_family_id ())
116
+ in_good_context = true ;
117
+ }
118
+ if (!in_good_context)
119
+ return false ;
120
+
121
+ // avoid recursively unfolding skolem terms.
122
+ if (e->get_num_args () > 0 && e->get_family_id () == null_family_id) {
123
+ return false ;
124
+ }
116
125
sort* s = m.get_sort (e);
117
126
if (m_dt.is_datatype (s) && m_dt.is_recursive (s))
118
127
return true ;
119
-
128
+
120
129
// potentially also induction on integers, sequences
121
130
// m_arith.is_int(s)
122
131
// return true;
@@ -160,14 +169,24 @@ enode_vector create_induction_lemmas::induction_positions(enode* n) {
160
169
* TDD: add depth throttle.
161
170
*/
162
171
void create_induction_lemmas::abstract (enode* n, enode* t, expr* x, abstractions& result) {
172
+ std::cout << " abs: " << result.size () << " : " << mk_pp (n->get_owner (), m) << " \n " ;
163
173
if (n->get_root () == t->get_root ()) {
164
174
result.push_back (abstraction (m, x, n->get_owner (), t->get_owner ()));
165
175
}
176
+ #if 0
177
+ // check if n is a s
178
+ if (is_skolem(n->get_owner())) {
179
+ result.push_back(abstraction(m, n->get_owner()));
180
+ return;
181
+ }
182
+ #endif
183
+
166
184
abstraction_args r1, r2;
167
185
r1.push_back (abstraction_arg (m));
168
186
for (enode* arg : enode::args (n)) {
169
187
unsigned n = result.size ();
170
188
abstract (arg, t, x, result);
189
+ std::cout << result.size () << " \n " ;
171
190
for (unsigned i = n; i < result.size (); ++i) {
172
191
abstraction& a = result[i];
173
192
for (auto const & v : r1) {
@@ -193,7 +212,9 @@ void create_induction_lemmas::filter_abstractions(bool sign, abstractions& abs)
193
212
vector<expr_ref_vector> values;
194
213
expr_ref_vector fmls (m);
195
214
for (auto & a : abs ) fmls.push_back (a.m_term );
215
+ std::cout << " sweep\n " ;
196
216
vs (fmls, values);
217
+ std::cout << " done sweep\n " ;
197
218
unsigned j = 0 ;
198
219
for (unsigned i = 0 ; i < fmls.size (); ++i) {
199
220
bool all_cex = true ;
@@ -207,15 +228,17 @@ void create_induction_lemmas::filter_abstractions(bool sign, abstractions& abs)
207
228
abs [j++] = abs .get (i);
208
229
}
209
230
}
231
+ std::cout << " resulting size: " << j << " down from " << abs .size () << " \n " ;
210
232
abs .shrink (j);
211
233
}
212
234
213
235
/*
214
236
* Create simple induction lemmas of the form:
215
237
*
216
- * lit & a.eqs() & is-c(t) => is-c(sk);
217
238
* lit & a.eqs() => alpha
218
- * lit & a.eqs() & is-c(t) => ~beta
239
+ * alpha & is-c(sk) => ~beta
240
+ *
241
+ * alpha & is-c(t) => is-c(sk);
219
242
*
220
243
* where
221
244
* lit = is a formula containing t
@@ -242,50 +265,59 @@ void create_induction_lemmas::create_lemmas(expr* t, expr* sk, abstraction& a, l
242
265
return ;
243
266
expr_ref alpha = a.m_term ;
244
267
auto const & eqs = a.m_eqs ;
268
+ literal alpha_lit = null_literal;
245
269
literal_vector common_literals;
246
270
for (func_decl* c : *m_dt.get_datatype_constructors (s)) {
247
271
func_decl* is_c = m_dt.get_constructor_recognizer (c);
248
272
bool has_1recursive = false ;
249
273
for (func_decl* acc : *m_dt.get_constructor_accessors (c)) {
250
274
if (acc->get_range () != s)
251
275
continue ;
252
- if (common_literals.empty ()) {
253
- common_literals.push_back (~lit);
254
- for (auto const & p : eqs) {
255
- common_literals.push_back (~mk_literal (m.mk_eq(p.first, p.second)));
256
- }
276
+ if (alpha_lit == null_literal) {
277
+ alpha_lit = mk_literal (alpha);
278
+ if (lit.sign ()) alpha_lit.neg ();
257
279
}
258
280
has_1recursive = true ;
259
- literal_vector lits (common_literals);
260
- lits.push_back (~mk_literal (m.mk_app(is_c, t)));
261
281
expr_ref beta (alpha);
262
282
expr_safe_replace rep (m);
263
283
rep.insert (sk, m.mk_app (acc, sk));
264
284
rep (beta);
265
285
literal b_lit = mk_literal (beta);
266
286
if (lit.sign ()) b_lit.neg ();
287
+
288
+ // alpha & is_c(sk) => ~beta
289
+ literal_vector lits;
290
+ lits.push_back (~alpha_lit);
291
+ lits.push_back (~mk_literal (m.mk_app(is_c, sk)));
267
292
lits.push_back (~b_lit);
268
293
add_th_lemma (lits);
269
294
}
295
+
296
+ // alpha & is_c(t) => is_c(sk)
270
297
if (has_1recursive) {
271
- literal_vector lits (common_literals);
298
+ literal_vector lits;
299
+ lits.push_back (~alpha_lit);
272
300
lits.push_back (~mk_literal (m.mk_app(is_c, t)));
273
301
lits.push_back (mk_literal (m.mk_app (is_c, sk)));
274
302
add_th_lemma (lits);
275
303
}
276
304
}
277
- if (!common_literals.empty ()) {
278
- literal_vector lits (common_literals);
279
- literal a_lit = mk_literal (alpha);
280
- if (lit.sign ()) a_lit.neg ();
281
- lits.push_back (a_lit);
305
+
306
+ // phi & eqs => alpha
307
+ if (alpha_lit != null_literal) {
308
+ literal_vector lits;
309
+ lits.push_back (~lit);
310
+ for (auto const & p : eqs) {
311
+ lits.push_back (~mk_literal (m.mk_eq(p.first, p.second)));
312
+ }
313
+ lits.push_back (alpha_lit);
282
314
add_th_lemma (lits);
283
315
}
284
316
}
285
317
286
318
void create_induction_lemmas::add_th_lemma (literal_vector const & lits) {
287
319
IF_VERBOSE (1 , ctx.display_literals_verbose (verbose_stream () << " lemma:\n " , lits) << " \n " );
288
- ctx.mk_clause (lits.size (), lits.c_ptr (), nullptr , smt::CLS_TH_LEMMA);
320
+ ctx.mk_clause (lits.size (), lits.c_ptr (), nullptr , smt::CLS_TH_AXIOM); // CLS_TH_LEMMA, but then should re-instance if GC'ed
289
321
++m_num_lemmas;
290
322
}
291
323
@@ -301,8 +333,8 @@ literal create_induction_lemmas::mk_literal(expr* e) {
301
333
func_decl* create_induction_lemmas::mk_skolem (sort* s) {
302
334
func_decl* f = nullptr ;
303
335
if (!m_sort2skolem.find (s, f)) {
304
- sort* domain[2 ] = { s, m.mk_bool_sort () };
305
- f = m.mk_fresh_func_decl (" sk" , 2 , domain, s);
336
+ sort* domain[3 ] = { m_a. mk_int (), s, m.mk_bool_sort () };
337
+ f = m.mk_fresh_func_decl (" sk" , 3 , domain, s);
306
338
m_pinned.push_back (f);
307
339
m_pinned.push_back (s);
308
340
m_sort2skolem.insert (s, f);
@@ -314,10 +346,11 @@ func_decl* create_induction_lemmas::mk_skolem(sort* s) {
314
346
bool create_induction_lemmas::operator ()(literal lit) {
315
347
unsigned num = m_num_lemmas;
316
348
enode* r = ctx.bool_var2enode (lit.var ());
349
+ unsigned position = 0 ;
317
350
for (enode* n : induction_positions (r)) {
318
351
expr* t = n->get_owner ();
319
352
sort* s = m.get_sort (t);
320
- expr_ref sk (m.mk_app (mk_skolem (s), t, r->get_owner ()), m);
353
+ expr_ref sk (m.mk_app (mk_skolem (s), m_a. mk_int (position), t, r->get_owner ()), m);
321
354
std::cout << " abstract " << mk_pp (t, m) << " " << sk << " \n " ;
322
355
abstractions abs ;
323
356
abstract (r, n, sk, abs );
@@ -326,6 +359,8 @@ bool create_induction_lemmas::operator()(literal lit) {
326
359
for (abstraction& a : abs ) {
327
360
create_lemmas (t, sk, a, lit);
328
361
}
362
+ std::cout << " lemmas created\n " ;
363
+ ++position;
329
364
}
330
365
return m_num_lemmas > num;
331
366
}
@@ -335,6 +370,7 @@ create_induction_lemmas::create_induction_lemmas(context& ctx, ast_manager& m, v
335
370
m(m),
336
371
vs(vs),
337
372
m_dt(m),
373
+ m_a(m),
338
374
m_pinned(m),
339
375
m_num_lemmas(0 )
340
376
{}
0 commit comments