@@ -24,6 +24,7 @@ namespace sls {
24
24
25
25
array_plugin::array_plugin (context& ctx):
26
26
plugin (ctx),
27
+ euf (ctx.euf()),
27
28
a (m)
28
29
{
29
30
m_fid = a.get_family_id ();
@@ -36,36 +37,67 @@ namespace sls {
36
37
m_kv = nullptr ;
37
38
init_egraph (*m_g);
38
39
saturate (*m_g);
39
- #if 0
40
40
if (m_g->inconsistent ()) {
41
41
resolve_conflict ();
42
42
return false ;
43
43
}
44
- #endif
45
44
return !m_g->inconsistent ();
46
45
}
47
46
48
47
49
48
void array_plugin::resolve_conflict () {
49
+ ++m_stats.m_num_conflicts ;
50
50
auto & g = *m_g;
51
51
SASSERT (g.inconsistent ());
52
- unsigned n = 0 ;
53
- sat::literal_vector lits;
54
52
ptr_vector<size_t > explain;
55
53
g.begin_explain ();
56
54
g.explain <size_t >(explain, nullptr );
57
55
g.end_explain ();
58
56
59
- verbose_stream () << " conflict\n " ;
57
+ IF_VERBOSE (3 , verbose_stream () << " array conflict\n " );
58
+ bool has_missing_axiom = false ;
60
59
for (auto p : explain) {
61
- if (is_literal (p)) {
62
- sat::literal l = to_literal (p);
63
- verbose_stream () << l << " " << mk_bounded_pp (ctx.atom (l.var ()), m) << " " << ctx.is_unit (l) << " \n " ;
60
+ if (is_index (p)) {
61
+ has_missing_axiom = true ;
62
+ unsigned idx = to_index (p);
63
+ auto [t, sto, sel] = m_delayed_axioms[idx];
64
+ switch (t) {
65
+ case store_axiom1:
66
+ add_store_axiom1 (sto->get_app ());
67
+ break ;
68
+ case store_axiom2_down:
69
+ case store_axiom2_up:
70
+ add_store_axiom2 (sto->get_app (), sel->get_app ());
71
+ break ;
72
+ case map_axiom:
73
+ case const_axiom:
74
+ add_eq_axiom (sto, sel);
75
+ break ;
76
+ default :
77
+ UNREACHABLE ();
78
+ break ;
79
+ }
64
80
}
65
- else {
66
- verbose_stream () << mk_bounded_pp (to_expr (p), m) << " == " << mk_bounded_pp (ctx.get_value (to_expr (p)), m) << " \n " ;
81
+ }
82
+ if (has_missing_axiom)
83
+ return ;
84
+
85
+ sat::literal_vector lits;
86
+ for (auto p : explain) {
87
+ if (is_enode (p)) {
88
+ auto n = to_enode (p);
89
+ auto v = ctx.get_value (n->get_expr ());
90
+ lits.push_back (~ctx.mk_literal (m.mk_eq (n->get_expr (), v)));
91
+ if (a.is_store (n->get_expr ()))
92
+ add_store_axiom1 (n->get_app ());
67
93
}
94
+ else if (is_literal (p)) {
95
+ sat::literal l = to_literal (p);
96
+ lits.push_back (~l);
97
+ }
68
98
}
99
+ IF_VERBOSE (3 , verbose_stream () << " add conflict clause\n " );
100
+ ctx.add_clause (lits);
69
101
}
70
102
71
103
// b ~ a[i -> v]
@@ -141,13 +173,12 @@ namespace sls {
141
173
if (nmap->get_root () == nsel->get_root ())
142
174
return ;
143
175
if (!are_distinct (nsel, nmap)) {
144
- g.merge (nmap, nsel, nullptr );
176
+ g.merge (nmap, nsel, to_ptr ( map_axiom_index (nmap, nsel)) );
145
177
g.propagate ();
146
178
if (!g.inconsistent ())
147
179
return ;
148
180
}
149
- expr_ref eq (m.mk_eq (nmap->get_expr (), nsel->get_expr ()), m);
150
- ctx.add_theory_axiom (eq);
181
+ add_eq_axiom (nmap, nsel);
151
182
}
152
183
153
184
euf::enode* array_plugin::mk_select (euf::egraph& g, euf::enode* b, euf::enode* sel) {
@@ -175,10 +206,10 @@ namespace sls {
175
206
auto nsel = mk_select (g, n, n);
176
207
VERIFY (!g.inconsistent ());
177
208
if (!are_distinct (nsel, val)) {
178
- g.merge (nsel, val, nullptr );
209
+ g.merge (nsel, val, to_ptr ( store_axiom1_index (n)) );
179
210
g.propagate ();
180
211
if (!g.inconsistent ())
181
- return ;
212
+ return ;
182
213
}
183
214
add_store_axiom1 (n->get_app ());
184
215
}
@@ -195,7 +226,7 @@ namespace sls {
195
226
return ;
196
227
auto nsel = mk_select (g, sto->get_arg (0 ), sel);
197
228
if (!are_distinct (nsel, sel)) {
198
- g.merge (nsel, sel, nullptr );
229
+ g.merge (nsel, sel, to_ptr ( store_axiom2_down_index (sto, sel)) );
199
230
g.propagate ();
200
231
if (!g.inconsistent ())
201
232
return ;
@@ -215,7 +246,7 @@ namespace sls {
215
246
return ;
216
247
auto nsel = mk_select (g, sto, sel);
217
248
if (!are_distinct (nsel, sel)) {
218
- g.merge (nsel, sel, nullptr );
249
+ g.merge (nsel, sel, to_ptr ( store_axiom2_up_index (sto, sel)) );
219
250
g.propagate ();
220
251
if (!g.inconsistent ())
221
252
return ;
@@ -234,13 +265,13 @@ namespace sls {
234
265
auto val = cn->get_arg (0 );
235
266
auto nsel = mk_select (g, cn, sel);
236
267
if (!are_distinct (nsel, sel)) {
237
- g.merge (nsel, sel, nullptr );
268
+ g.merge (nsel, sel, to_ptr ( const_axiom_index (val, nsel)) );
238
269
g.propagate ();
239
270
if (!g.inconsistent ())
240
271
return ;
241
272
}
242
- expr_ref eq (m. mk_eq (val-> get_expr (), nsel-> get_expr ()), m) ;
243
- ctx. add_theory_axiom (eq );
273
+ ++m_stats. m_num_axioms ;
274
+ add_eq_axiom (val, nsel );
244
275
}
245
276
246
277
bool array_plugin::are_distinct (euf::enode* a, euf::enode* b) {
@@ -270,6 +301,7 @@ namespace sls {
270
301
expr_ref sel (a.mk_select (args), m);
271
302
expr_ref eq (m.mk_eq (sel, to_app (sto)->get_arg (sto->get_num_args () - 1 )), m);
272
303
IF_VERBOSE (3 , verbose_stream () << " add store axiom 1 " << mk_bounded_pp (sto, m) << " \n " );
304
+ ++m_stats.m_num_axioms ;
273
305
ctx.add_theory_axiom (eq);
274
306
}
275
307
@@ -291,6 +323,7 @@ namespace sls {
291
323
for (unsigned i = 1 ; i < sel->get_num_args () - 1 ; ++i)
292
324
ors.push_back (m.mk_eq (sel->get_arg (i), sto->get_arg (i)));
293
325
IF_VERBOSE (3 , verbose_stream () << " add store axiom 2 " << mk_bounded_pp (sto, m) << " " << mk_bounded_pp (sel, m) << " \n " );
326
+ ++m_stats.m_num_axioms ;
294
327
ctx.add_theory_axiom (m.mk_or (ors));
295
328
}
296
329
@@ -307,21 +340,24 @@ namespace sls {
307
340
n1 = n1 ? n1 : g.mk (t, 0 , args.size (), args.data ());
308
341
if (a.is_array (t))
309
342
continue ;
343
+ if (m.is_bool (t))
344
+ continue ;
310
345
auto v = ctx.get_value (t);
311
346
IF_VERBOSE (3 , verbose_stream () << " init " << mk_bounded_pp (t, m) << " := " << mk_bounded_pp (v, m) << " " << g.inconsistent () << " \n " );
312
347
n2 = g.find (v);
313
348
n2 = n2 ? n2: g.mk (v, 0 , 0 , nullptr );
314
- g.merge (n1, n2, to_ptr (t ));
349
+ g.merge (n1, n2, to_ptr (n1 ));
315
350
}
316
351
for (auto lit : ctx.root_literals ()) {
317
352
if (!ctx.is_true (lit) || lit.sign ())
318
353
continue ;
319
354
auto e = ctx.atom (lit.var ());
320
355
expr* x = nullptr , * y = nullptr ;
321
356
if (e && m.is_eq (e, x, y))
322
- g.merge (g.find (x), g.find (y), to_ptr (lit) );
357
+ g.merge (g.find (x), g.find (y), nullptr );
323
358
324
359
}
360
+ g.propagate ();
325
361
326
362
IF_VERBOSE (3 , display (verbose_stream ()));
327
363
@@ -388,4 +424,9 @@ namespace sls {
388
424
}
389
425
return out;
390
426
}
427
+
428
+ void array_plugin::collect_statistics (statistics& st) const {
429
+ st.update (" sls-array-conflicts" , m_stats.m_num_conflicts );
430
+ st.update (" sls-array-axioms" , m_stats.m_num_axioms );
431
+ }
391
432
}
0 commit comments