@@ -52,6 +52,22 @@ namespace nlsat {
52
52
std::swap (c1, c2);
53
53
}
54
54
55
+ struct solver ::ctx {
56
+ params_ref m_params;
57
+ reslimit& m_rlimit;
58
+ small_object_allocator m_allocator;
59
+ unsynch_mpq_manager m_qm;
60
+ pmanager m_pm;
61
+ anum_manager m_am;
62
+ ctx (reslimit& rlim, params_ref const & p):
63
+ m_params (p),
64
+ m_rlimit (rlim),
65
+ m_allocator (" nlsat" ),
66
+ m_pm (rlim, m_qm, &m_allocator),
67
+ m_am (rlim, m_qm, p, &m_allocator)
68
+ {}
69
+ };
70
+
55
71
struct solver ::imp {
56
72
struct dconfig {
57
73
typedef imp value_manager;
@@ -67,13 +83,15 @@ namespace nlsat {
67
83
typedef polynomial::cache cache;
68
84
typedef ptr_vector<interval_set> interval_set_vector;
69
85
70
- reslimit& m_rlimit;
71
- small_object_allocator m_allocator;
72
- bool m_incremental;
73
- unsynch_mpq_manager m_qm;
74
- pmanager m_pm;
75
- cache m_cache;
76
- anum_manager m_am;
86
+ ctx& m_ctx;
87
+ solver& m_solver;
88
+ reslimit& m_rlimit;
89
+ small_object_allocator& m_allocator;
90
+ bool m_incremental;
91
+ unsynch_mpq_manager& m_qm;
92
+ pmanager& m_pm;
93
+ cache m_cache;
94
+ anum_manager& m_am;
77
95
mutable assumption_manager m_asm;
78
96
assignment m_assignment; // partial interpretation
79
97
evaluator m_evaluator;
@@ -185,6 +203,7 @@ namespace nlsat {
185
203
unsigned m_random_seed;
186
204
bool m_inline_vars;
187
205
bool m_log_lemmas;
206
+ bool m_check_lemmas;
188
207
unsigned m_max_conflicts;
189
208
unsigned m_lemma_count;
190
209
@@ -195,13 +214,16 @@ namespace nlsat {
195
214
unsigned m_stages;
196
215
unsigned m_irrational_assignments; // number of irrational witnesses
197
216
198
- imp (solver& s, reslimit& rlim, params_ref const & p, bool incremental):
199
- m_rlimit (rlim),
200
- m_allocator (" nlsat" ),
217
+ imp (solver& s, ctx& c, bool incremental):
218
+ m_ctx (c),
219
+ m_solver (s),
220
+ m_rlimit (c.m_rlimit),
221
+ m_allocator (c.m_allocator),
201
222
m_incremental (incremental),
202
- m_pm (rlim, m_qm, &m_allocator),
223
+ m_qm (c.m_qm),
224
+ m_pm (c.m_pm),
203
225
m_cache (m_pm),
204
- m_am (rlim, m_qm, p, &m_allocator ),
226
+ m_am (c.m_am ),
205
227
m_asm (*this , m_allocator),
206
228
m_assignment (m_am),
207
229
m_evaluator (s, m_assignment, m_pm, m_allocator),
@@ -216,7 +238,7 @@ namespace nlsat {
216
238
m_lemma (s),
217
239
m_lazy_clause (s),
218
240
m_lemma_assumptions (m_asm) {
219
- updt_params (p );
241
+ updt_params (c. m_params );
220
242
reset_statistics ();
221
243
mk_true_bvar ();
222
244
m_lemma_count = 0 ;
@@ -246,6 +268,7 @@ namespace nlsat {
246
268
m_random_seed = p.seed ();
247
269
m_inline_vars = p.inline_vars ();
248
270
m_log_lemmas = p.log_lemmas ();
271
+ m_check_lemmas = p.check_lemmas ();
249
272
m_ism.set_seed (m_random_seed);
250
273
m_explain.set_simplify_cores (m_simplify_cores);
251
274
m_explain.set_minimize_cores (min_cores);
@@ -452,6 +475,10 @@ namespace nlsat {
452
475
453
476
var mk_var (bool is_int) {
454
477
var x = m_pm.mk_var ();
478
+ register_var (x, is_int);
479
+ return x;
480
+ }
481
+ void register_var (var x, bool is_int) {
455
482
SASSERT (x == num_vars ());
456
483
m_is_int. push_back (is_int);
457
484
m_watches. push_back (clause_vector ());
@@ -464,7 +491,6 @@ namespace nlsat {
464
491
SASSERT (m_is_int.size () == m_var2eq.size ());
465
492
SASSERT (m_is_int.size () == m_perm.size ());
466
493
SASSERT (m_is_int.size () == m_inv_perm.size ());
467
- return x;
468
494
}
469
495
470
496
svector<bool > m_found_vars;
@@ -736,6 +762,76 @@ namespace nlsat {
736
762
}
737
763
};
738
764
765
+ void check_lemma (unsigned n, literal const * cls, bool is_valid, assumption_set a) {
766
+ TRACE (" nlsat" , display (tout << " check lemma: " , n, cls) << " \n " ;
767
+ display (tout););
768
+ IF_VERBOSE (0 , display (verbose_stream () << " check lemma: " , n, cls) << " \n " );
769
+ for (clause* c : m_learned) IF_VERBOSE (0 , display (verbose_stream () << " lemma: " , *c) << " \n " );
770
+
771
+ solver solver2 (m_ctx);
772
+ imp& checker = *(solver2.m_imp );
773
+ checker.m_check_lemmas = false ;
774
+ checker.m_log_lemmas = false ;
775
+
776
+ // need to translate Boolean variables and literals
777
+ svector<bool_var> tr;
778
+ for (var x = 0 ; x < m_is_int.size (); ++x) {
779
+ checker.register_var (x, m_is_int[x]);
780
+ }
781
+ bool_var bv = 0 ;
782
+ tr.push_back (bv);
783
+ checker.inc_ref (bv);
784
+ for (bool_var b = 1 ; b < m_atoms.size (); ++b) {
785
+ atom* a = m_atoms[b];
786
+ if (a == nullptr ) {
787
+ bv = checker.mk_bool_var ();
788
+ }
789
+ else if (a->is_ineq_atom ()) {
790
+ ineq_atom& ia = *to_ineq_atom (a);
791
+ unsigned sz = ia.size ();
792
+ ptr_vector<poly> ps;
793
+ svector<bool > is_even;
794
+ for (unsigned i = 0 ; i < sz; ++i) {
795
+ ps.push_back (ia.p (i));
796
+ is_even.push_back (ia.is_even (i));
797
+ }
798
+ bv = checker.mk_ineq_atom (ia.get_kind (), sz, ps.c_ptr (), is_even.c_ptr ());
799
+ }
800
+ else if (a->is_root_atom ()) {
801
+ root_atom& r = *to_root_atom (a);
802
+ bv = checker.mk_root_atom (r.get_kind (), r.x (), r.i (), r.p ());
803
+ }
804
+ else {
805
+ UNREACHABLE ();
806
+ }
807
+ checker.inc_ref (bv);
808
+ tr.push_back (bv);
809
+ }
810
+ if (!is_valid) {
811
+ for (clause* c : m_clauses) {
812
+ if (!a && c->assumptions ()) {
813
+ continue ;
814
+ }
815
+ literal_vector lits;
816
+ for (literal lit : *c) {
817
+ lits.push_back (literal (tr[lit.var ()], lit.sign ()));
818
+ }
819
+ checker.mk_clause (lits.size (), lits.c_ptr (), nullptr );
820
+ }
821
+ }
822
+ for (unsigned i = 0 ; i < n; ++i) {
823
+ literal lit = cls[i];
824
+ literal nlit (tr[lit.var ()], !lit.sign ());
825
+ checker.mk_clause (1 , &nlit, nullptr );
826
+ }
827
+ IF_VERBOSE (0 , verbose_stream () << " check\n " ;);
828
+ lbool r = checker.check ();
829
+ VERIFY (r == l_false);
830
+ for (bool_var b : tr) {
831
+ checker.dec_ref (b);
832
+ }
833
+ }
834
+
739
835
void log_lemma (std::ostream& out, clause const & cls) {
740
836
display_smt2 (out);
741
837
out << " (assert (not " ;
@@ -757,7 +853,10 @@ namespace nlsat {
757
853
std::sort (cls->begin (), cls->end (), lit_lt (*this ));
758
854
TRACE (" nlsat_sort" , display (tout << " #" << m_lemma_count << " after sort:\n " , *cls) << " \n " ;);
759
855
if (learned && m_log_lemmas) {
760
- log_lemma (std::cout, *cls);
856
+ log_lemma (verbose_stream (), *cls);
857
+ }
858
+ if (learned && m_check_lemmas) {
859
+ check_lemma (cls->size (), cls->c_ptr (), false , cls->assumptions ());
761
860
}
762
861
if (learned)
763
862
m_learned.push_back (cls);
@@ -1437,8 +1536,9 @@ namespace nlsat {
1437
1536
sort_watched_clauses ();
1438
1537
lbool r = search_check ();
1439
1538
CTRACE (" nlsat_model" , r == l_true, tout << " model before restore order\n " ; display_assignment (tout););
1440
- if (reordered)
1539
+ if (reordered) {
1441
1540
restore_order ();
1541
+ }
1442
1542
CTRACE (" nlsat_model" , r == l_true, tout << " model\n " ; display_assignment (tout););
1443
1543
CTRACE (" nlsat" , r == l_false, display (tout););
1444
1544
SASSERT (r != l_true || check_satisfied (m_clauses));
@@ -1481,7 +1581,11 @@ namespace nlsat {
1481
1581
}
1482
1582
collect (assumptions, m_clauses);
1483
1583
collect (assumptions, m_learned);
1484
-
1584
+ if (m_check_lemmas) {
1585
+ for (clause* c : m_learned) {
1586
+ check_lemma (c->size (), c->c_ptr (), false , nullptr );
1587
+ }
1588
+ }
1485
1589
assumptions.reset ();
1486
1590
assumptions.append (result);
1487
1591
return r;
@@ -1557,12 +1661,11 @@ namespace nlsat {
1557
1661
1558
1662
void process_antecedent (literal antecedent) {
1559
1663
bool_var b = antecedent.var ();
1560
- TRACE (" nlsat_resolve" , tout << " resolving antecedent, l: \n " ; display (tout , antecedent); tout << " \n " ;);
1664
+ TRACE (" nlsat_resolve" , display ( tout << " resolving antecedent: " , antecedent) << " \n " ;);
1561
1665
if (assigned_value (antecedent) == l_undef) {
1562
1666
// antecedent must be false in the current arith interpretation
1563
1667
SASSERT (value (antecedent) == l_false);
1564
1668
if (!is_marked (b)) {
1565
- TRACE (" nlsat_resolve" , tout << max_var (b) << " " << m_xk << " \n " ;);
1566
1669
SASSERT (is_arith_atom (b) && max_var (b) < m_xk); // must be in a previous stage
1567
1670
TRACE (" nlsat_resolve" , tout << " literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n " ;);
1568
1671
mark (b);
@@ -1630,6 +1733,10 @@ namespace nlsat {
1630
1733
tout << " new valid clause:\n " ;
1631
1734
display (tout, m_lazy_clause.size (), m_lazy_clause.c_ptr ()) << " \n " ;);
1632
1735
1736
+ if (m_check_lemmas) {
1737
+ check_lemma (m_lazy_clause.size (), m_lazy_clause.c_ptr (), true , nullptr );
1738
+ }
1739
+
1633
1740
DEBUG_CODE ({
1634
1741
unsigned sz = m_lazy_clause.size ();
1635
1742
for (unsigned i = 0 ; i < sz; i++) {
@@ -1763,6 +1870,7 @@ namespace nlsat {
1763
1870
*/
1764
1871
bool resolve (clause const & conflict) {
1765
1872
clause const * conflict_clause = &conflict;
1873
+ m_lemma_assumptions = nullptr ;
1766
1874
start:
1767
1875
SASSERT (check_marks ());
1768
1876
TRACE (" nlsat_proof" , tout << " STARTING RESOLUTION\n " ;);
@@ -1854,6 +1962,10 @@ namespace nlsat {
1854
1962
reset_marks (); // remove marks from the literals in m_lemmas.
1855
1963
TRACE (" nlsat" , tout << " new lemma:\n " ; display (tout, m_lemma.size (), m_lemma.c_ptr ()); tout << " \n " ;
1856
1964
tout << " found_decision: " << found_decision << " \n " ;);
1965
+
1966
+ if (false && m_check_lemmas) {
1967
+ check_lemma (m_lemma.size (), m_lemma.c_ptr (), false , m_lemma_assumptions.get ());
1968
+ }
1857
1969
1858
1970
// There are two possibilities:
1859
1971
// 1) m_lemma contains only literals from previous stages, and they
@@ -2146,10 +2258,11 @@ namespace nlsat {
2146
2258
}
2147
2259
2148
2260
bool can_reorder () const {
2149
- for (atom * a : m_atoms) {
2150
- if (a) {
2151
- if (a->is_root_atom ()) return false ;
2152
- }
2261
+ for (clause* c : m_learned) {
2262
+ if (has_root_atom (*c)) return false ;
2263
+ }
2264
+ for (clause* c : m_clauses) {
2265
+ if (has_root_atom (*c)) return false ;
2153
2266
}
2154
2267
return true ;
2155
2268
}
@@ -2159,6 +2272,8 @@ namespace nlsat {
2159
2272
p maps internal variables to their new positions
2160
2273
*/
2161
2274
void reorder (unsigned sz, var const * p) {
2275
+ remove_learned_roots ();
2276
+ SASSERT (can_reorder ());
2162
2277
TRACE (" nlsat_reorder" , tout << " solver before variable reorder\n " ; display (tout);
2163
2278
display_vars (tout);
2164
2279
tout << " \n permutation:\n " ;
@@ -2205,21 +2320,21 @@ namespace nlsat {
2205
2320
}
2206
2321
});
2207
2322
m_pm.rename (sz, p);
2208
- del_ill_formed_lemmas ();
2209
2323
TRACE (" nlsat_bool_assignment_bug" , tout << " before reinit cache\n " ; display_bool_assignment (tout););
2210
2324
reinit_cache ();
2211
2325
m_assignment.swap (new_assignment);
2212
2326
reattach_arith_clauses (m_clauses);
2213
2327
reattach_arith_clauses (m_learned);
2214
2328
TRACE (" nlsat_reorder" , tout << " solver after variable reorder\n " ; display (tout); display_vars (tout););
2215
2329
}
2330
+
2216
2331
2217
2332
/* *
2218
2333
\brief Restore variable order.
2219
2334
*/
2220
2335
void restore_order () {
2221
2336
// m_perm: internal -> external
2222
- // m_inv_perm: external -> internal
2337
+ // m_inv_perm: external -> internal
2223
2338
var_vector p;
2224
2339
p.append (m_perm);
2225
2340
reorder (p.size (), p.c_ptr ());
@@ -2234,10 +2349,10 @@ namespace nlsat {
2234
2349
/* *
2235
2350
\brief After variable reordering some lemmas containing root atoms may be ill-formed.
2236
2351
*/
2237
- void del_ill_formed_lemmas () {
2352
+ void remove_learned_roots () {
2238
2353
unsigned j = 0 ;
2239
2354
for (clause* c : m_learned) {
2240
- if (ill_formed (*c)) {
2355
+ if (has_root_atom (*c)) {
2241
2356
del_clause (c);
2242
2357
}
2243
2358
else {
@@ -2250,15 +2365,11 @@ namespace nlsat {
2250
2365
/* *
2251
2366
\brief Return true if the clause contains an ill formed root atom
2252
2367
*/
2253
- bool ill_formed (clause const & c) {
2368
+ bool has_root_atom (clause const & c) const {
2254
2369
for (literal lit : c) {
2255
2370
bool_var b = lit.var ();
2256
2371
atom * a = m_atoms[b];
2257
- if (a == nullptr )
2258
- continue ;
2259
- if (a->is_ineq_atom ())
2260
- continue ;
2261
- if (to_root_atom (a)->x () < max_var (to_root_atom (a)->p ()))
2372
+ if (a && a->is_root_atom ())
2262
2373
return true ;
2263
2374
}
2264
2375
return false ;
@@ -3236,11 +3347,18 @@ namespace nlsat {
3236
3347
};
3237
3348
3238
3349
solver::solver (reslimit& rlim, params_ref const & p, bool incremental) {
3239
- m_imp = alloc (imp, *this , rlim, p, incremental);
3350
+ m_ctx = alloc (ctx, rlim, p);
3351
+ m_imp = alloc (imp, *this , *m_ctx, incremental);
3352
+ }
3353
+
3354
+ solver::solver (ctx& ctx) {
3355
+ m_ctx = nullptr ;
3356
+ m_imp = alloc (imp, *this , ctx, false );
3240
3357
}
3241
3358
3242
3359
solver::~solver () {
3243
3360
dealloc (m_imp);
3361
+ dealloc (m_ctx);
3244
3362
}
3245
3363
3246
3364
lbool solver::check () {
0 commit comments