Skip to content

Commit 88f0e4a

Browse files
fix #2592 #2593 #2597 #2573 - duplicates, also fix #2603
Signed-off-by: Nikolaj Bjorner <[email protected]>
1 parent fe7a7fe commit 88f0e4a

File tree

6 files changed

+160
-39
lines changed

6 files changed

+160
-39
lines changed

src/math/polynomial/polynomial.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2370,7 +2370,7 @@ namespace polynomial {
23702370
TRACE("polynomial",
23712371
tout << "leaked polynomials\n";
23722372
for (unsigned i = 0; i < m_polynomials.size(); i++) {
2373-
if (m_polynomials[i] != 0) {
2373+
if (m_polynomials[i] != nullptr) {
23742374
m_polynomials[i]->display(tout, m_manager);
23752375
tout << "\n";
23762376
}

src/nlsat/nlsat_explain.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,8 @@ namespace nlsat {
198198
*/
199199
void reset_already_added() {
200200
SASSERT(m_result != 0);
201-
unsigned sz = m_result->size();
202-
for (unsigned i = 0; i < sz; i++)
203-
m_already_added_literal[(*m_result)[i].index()] = false;
201+
for (literal lit : *m_result)
202+
m_already_added_literal[lit.index()] = false;
204203
}
205204

206205

src/nlsat/nlsat_params.pyg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ def_module_params('nlsat',
66
('lazy', UINT, 0, "how lazy the solver is."),
77
('reorder', BOOL, True, "reorder variables."),
88
('log_lemmas', BOOL, False, "display lemmas as self-contained SMT formulas"),
9+
('check_lemmas', BOOL, False, "check lemmas on the fly using an independent nlsat solver"),
910
('simplify_conflicts', BOOL, True, "simplify conflicts using equalities before resolving them in nlsat solver."),
1011
('minimize_conflicts', BOOL, False, "minimize conflicts"),
1112
('randomize', BOOL, True, "randomize selection of a witness in nlsat."),

src/nlsat/nlsat_solver.cpp

Lines changed: 152 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ namespace nlsat {
5252
std::swap(c1, c2);
5353
}
5454

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+
5571
struct solver::imp {
5672
struct dconfig {
5773
typedef imp value_manager;
@@ -67,13 +83,15 @@ namespace nlsat {
6783
typedef polynomial::cache cache;
6884
typedef ptr_vector<interval_set> interval_set_vector;
6985

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;
7795
mutable assumption_manager m_asm;
7896
assignment m_assignment; // partial interpretation
7997
evaluator m_evaluator;
@@ -185,6 +203,7 @@ namespace nlsat {
185203
unsigned m_random_seed;
186204
bool m_inline_vars;
187205
bool m_log_lemmas;
206+
bool m_check_lemmas;
188207
unsigned m_max_conflicts;
189208
unsigned m_lemma_count;
190209

@@ -195,13 +214,16 @@ namespace nlsat {
195214
unsigned m_stages;
196215
unsigned m_irrational_assignments; // number of irrational witnesses
197216

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),
201222
m_incremental(incremental),
202-
m_pm(rlim, m_qm, &m_allocator),
223+
m_qm(c.m_qm),
224+
m_pm(c.m_pm),
203225
m_cache(m_pm),
204-
m_am(rlim, m_qm, p, &m_allocator),
226+
m_am(c.m_am),
205227
m_asm(*this, m_allocator),
206228
m_assignment(m_am),
207229
m_evaluator(s, m_assignment, m_pm, m_allocator),
@@ -216,7 +238,7 @@ namespace nlsat {
216238
m_lemma(s),
217239
m_lazy_clause(s),
218240
m_lemma_assumptions(m_asm) {
219-
updt_params(p);
241+
updt_params(c.m_params);
220242
reset_statistics();
221243
mk_true_bvar();
222244
m_lemma_count = 0;
@@ -246,6 +268,7 @@ namespace nlsat {
246268
m_random_seed = p.seed();
247269
m_inline_vars = p.inline_vars();
248270
m_log_lemmas = p.log_lemmas();
271+
m_check_lemmas = p.check_lemmas();
249272
m_ism.set_seed(m_random_seed);
250273
m_explain.set_simplify_cores(m_simplify_cores);
251274
m_explain.set_minimize_cores(min_cores);
@@ -452,6 +475,10 @@ namespace nlsat {
452475

453476
var mk_var(bool is_int) {
454477
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) {
455482
SASSERT(x == num_vars());
456483
m_is_int. push_back(is_int);
457484
m_watches. push_back(clause_vector());
@@ -464,7 +491,6 @@ namespace nlsat {
464491
SASSERT(m_is_int.size() == m_var2eq.size());
465492
SASSERT(m_is_int.size() == m_perm.size());
466493
SASSERT(m_is_int.size() == m_inv_perm.size());
467-
return x;
468494
}
469495

470496
svector<bool> m_found_vars;
@@ -736,6 +762,76 @@ namespace nlsat {
736762
}
737763
};
738764

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+
739835
void log_lemma(std::ostream& out, clause const& cls) {
740836
display_smt2(out);
741837
out << "(assert (not ";
@@ -757,7 +853,10 @@ namespace nlsat {
757853
std::sort(cls->begin(), cls->end(), lit_lt(*this));
758854
TRACE("nlsat_sort", display(tout << "#" << m_lemma_count << " after sort:\n", *cls) << "\n";);
759855
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());
761860
}
762861
if (learned)
763862
m_learned.push_back(cls);
@@ -1437,8 +1536,9 @@ namespace nlsat {
14371536
sort_watched_clauses();
14381537
lbool r = search_check();
14391538
CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout););
1440-
if (reordered)
1539+
if (reordered) {
14411540
restore_order();
1541+
}
14421542
CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout););
14431543
CTRACE("nlsat", r == l_false, display(tout););
14441544
SASSERT(r != l_true || check_satisfied(m_clauses));
@@ -1481,7 +1581,11 @@ namespace nlsat {
14811581
}
14821582
collect(assumptions, m_clauses);
14831583
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+
}
14851589
assumptions.reset();
14861590
assumptions.append(result);
14871591
return r;
@@ -1557,12 +1661,11 @@ namespace nlsat {
15571661

15581662
void process_antecedent(literal antecedent) {
15591663
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";);
15611665
if (assigned_value(antecedent) == l_undef) {
15621666
// antecedent must be false in the current arith interpretation
15631667
SASSERT(value(antecedent) == l_false);
15641668
if (!is_marked(b)) {
1565-
TRACE("nlsat_resolve", tout << max_var(b) << " " << m_xk << "\n";);
15661669
SASSERT(is_arith_atom(b) && max_var(b) < m_xk); // must be in a previous stage
15671670
TRACE("nlsat_resolve", tout << "literal is unassigned, but it is false in arithmetic interpretation, adding it to lemma\n";);
15681671
mark(b);
@@ -1630,6 +1733,10 @@ namespace nlsat {
16301733
tout << "new valid clause:\n";
16311734
display(tout, m_lazy_clause.size(), m_lazy_clause.c_ptr()) << "\n";);
16321735

1736+
if (m_check_lemmas) {
1737+
check_lemma(m_lazy_clause.size(), m_lazy_clause.c_ptr(), true, nullptr);
1738+
}
1739+
16331740
DEBUG_CODE({
16341741
unsigned sz = m_lazy_clause.size();
16351742
for (unsigned i = 0; i < sz; i++) {
@@ -1763,6 +1870,7 @@ namespace nlsat {
17631870
*/
17641871
bool resolve(clause const & conflict) {
17651872
clause const * conflict_clause = &conflict;
1873+
m_lemma_assumptions = nullptr;
17661874
start:
17671875
SASSERT(check_marks());
17681876
TRACE("nlsat_proof", tout << "STARTING RESOLUTION\n";);
@@ -1854,6 +1962,10 @@ namespace nlsat {
18541962
reset_marks(); // remove marks from the literals in m_lemmas.
18551963
TRACE("nlsat", tout << "new lemma:\n"; display(tout, m_lemma.size(), m_lemma.c_ptr()); tout << "\n";
18561964
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+
}
18571969

18581970
// There are two possibilities:
18591971
// 1) m_lemma contains only literals from previous stages, and they
@@ -2146,10 +2258,11 @@ namespace nlsat {
21462258
}
21472259

21482260
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;
21532266
}
21542267
return true;
21552268
}
@@ -2159,6 +2272,8 @@ namespace nlsat {
21592272
p maps internal variables to their new positions
21602273
*/
21612274
void reorder(unsigned sz, var const * p) {
2275+
remove_learned_roots();
2276+
SASSERT(can_reorder());
21622277
TRACE("nlsat_reorder", tout << "solver before variable reorder\n"; display(tout);
21632278
display_vars(tout);
21642279
tout << "\npermutation:\n";
@@ -2205,21 +2320,21 @@ namespace nlsat {
22052320
}
22062321
});
22072322
m_pm.rename(sz, p);
2208-
del_ill_formed_lemmas();
22092323
TRACE("nlsat_bool_assignment_bug", tout << "before reinit cache\n"; display_bool_assignment(tout););
22102324
reinit_cache();
22112325
m_assignment.swap(new_assignment);
22122326
reattach_arith_clauses(m_clauses);
22132327
reattach_arith_clauses(m_learned);
22142328
TRACE("nlsat_reorder", tout << "solver after variable reorder\n"; display(tout); display_vars(tout););
22152329
}
2330+
22162331

22172332
/**
22182333
\brief Restore variable order.
22192334
*/
22202335
void restore_order() {
22212336
// m_perm: internal -> external
2222-
// m_inv_perm: external -> internal
2337+
// m_inv_perm: external -> internal
22232338
var_vector p;
22242339
p.append(m_perm);
22252340
reorder(p.size(), p.c_ptr());
@@ -2234,10 +2349,10 @@ namespace nlsat {
22342349
/**
22352350
\brief After variable reordering some lemmas containing root atoms may be ill-formed.
22362351
*/
2237-
void del_ill_formed_lemmas() {
2352+
void remove_learned_roots() {
22382353
unsigned j = 0;
22392354
for (clause* c : m_learned) {
2240-
if (ill_formed(*c)) {
2355+
if (has_root_atom(*c)) {
22412356
del_clause(c);
22422357
}
22432358
else {
@@ -2250,15 +2365,11 @@ namespace nlsat {
22502365
/**
22512366
\brief Return true if the clause contains an ill formed root atom
22522367
*/
2253-
bool ill_formed(clause const & c) {
2368+
bool has_root_atom(clause const & c) const {
22542369
for (literal lit : c) {
22552370
bool_var b = lit.var();
22562371
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())
22622373
return true;
22632374
}
22642375
return false;
@@ -3236,11 +3347,18 @@ namespace nlsat {
32363347
};
32373348

32383349
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);
32403357
}
32413358

32423359
solver::~solver() {
32433360
dealloc(m_imp);
3361+
dealloc(m_ctx);
32443362
}
32453363

32463364
lbool solver::check() {

0 commit comments

Comments
 (0)