diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index d331b787a..e67c34b11 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -38,6 +38,7 @@ Revision History: #endif #define ENABLE_TERNARY true +#define DYNAMIC_VARS true namespace sat { @@ -243,10 +244,45 @@ namespace sat { // // ----------------------- + void solver::reset_var(bool_var v, bool ext, bool dvar) { + m_watches[2*v].reset(); + m_watches[2*v+1].reset(); + m_assignment[2*v] = l_undef; + m_assignment[2*v+1] = l_undef; + m_justification[2*v] = justification(UINT_MAX); + m_decision[v] = dvar; + m_eliminated[v] = false; + m_external[v] = ext; + m_touched[v] = 0; + m_activity[v] = 0; + m_mark[v] = false; + m_lit_mark[2*v] = false; + m_lit_mark[2*v+1] = false; + m_phase[v] = false; + m_best_phase[v] = false; + m_prev_phase[v] = false; + m_assigned_since_gc[v] = false; + m_last_conflict[v] = 0; + m_last_propagation[v] = 0; + m_participated[v] = 0; + m_canceled[v] = 0; + m_reasoned[v] = 0; + m_case_split_queue.mk_var_eh(v); + m_simplifier.insert_elim_todo(v); + } + bool_var solver::mk_var(bool ext, bool dvar) { m_model_is_current = false; m_stats.m_mk_var++; bool_var v = m_justification.size(); + if (!m_free_vars.empty()) { + v = m_free_vars.back(); + m_free_vars.pop_back(); + m_active_vars.push_back(v); + reset_var(v, ext, dvar); + return v; + } + m_active_vars.push_back(v); m_watches.push_back(watch_list()); m_watches.push_back(watch_list()); m_assignment.push_back(l_undef); @@ -3212,7 +3248,7 @@ namespace sat { for (unsigned i = 0; i < num; i++) { SASSERT(value(lits[i]) != l_undef); unsigned lit_lvl = lvl(lits[i]); - if (m_diff_levels[lit_lvl] == false) { + if (!m_diff_levels[lit_lvl]) { m_diff_levels[lit_lvl] = true; r++; } @@ -3230,14 +3266,13 @@ namespace sat { for (; i < num && glue < max_glue; i++) { SASSERT(value(lits[i]) != l_undef); unsigned lit_lvl = lvl(lits[i]); - if (m_diff_levels[lit_lvl] == false) { + if (!m_diff_levels[lit_lvl]) { m_diff_levels[lit_lvl] = true; glue++; } - } - num = i; + } // reset m_diff_levels. - for (i = 0; i < num; i++) + for (; i-- > 0; ) m_diff_levels[lvl(lits[i])] = false; return glue < max_glue; } @@ -3249,15 +3284,14 @@ namespace sat { for (; i < num && glue < max_glue; i++) { if (value(lits[i]) == l_false) { unsigned lit_lvl = lvl(lits[i]); - if (m_diff_levels[lit_lvl] == false) { + if (!m_diff_levels[lit_lvl]) { m_diff_levels[lit_lvl] = true; glue++; } } } - num = i; // reset m_diff_levels. - for (i = 0; i < num; i++) { + for (; i-- > 0;) { literal lit = lits[i]; if (value(lit) == l_false) { VERIFY(lvl(lit) < m_diff_levels.size()); @@ -3653,9 +3687,12 @@ namespace sat { s.m_trail_lim = m_trail.size(); s.m_clauses_to_reinit_lim = m_clauses_to_reinit.size(); s.m_inconsistent = m_inconsistent; - // m_vars_lim.push(num_vars()); - if (m_ext) + if (m_ext) { +#if DYNAMIC_VARS + m_vars_lim.push(m_active_vars.size()); +#endif m_ext->push(); + } } void solver::pop_reinit(unsigned num_scopes) { @@ -3666,13 +3703,35 @@ namespace sat { } void solver::pop_vars(unsigned num_scopes) { + m_vars_to_reinit.reset(); unsigned old_num_vars = m_vars_lim.pop(num_scopes); - if (old_num_vars == num_vars()) + if (old_num_vars == m_active_vars.size()) return; - IF_VERBOSE(0, verbose_stream() << "new variables created under scope\n";); - for (unsigned v = old_num_vars; v < num_vars(); ++v) { - + init_visited(); + unsigned new_lvl = scope_lvl() - num_scopes; + unsigned old_sz = m_scopes[new_lvl].m_clauses_to_reinit_lim; + for (unsigned i = m_clauses_to_reinit.size(); i-- > old_sz; ) { + clause_wrapper const& cw = m_clauses_to_reinit[i]; + for (unsigned j = cw.size(); j-- > 0; ) + mark_visited(cw[j]); } + for (literal lit : m_lemma) + mark_visited(lit); + + unsigned sz = m_active_vars.size(), j = old_num_vars; + for (unsigned i = old_num_vars; i < sz; ++i) { + bool_var v = m_active_vars[i]; + if (is_visited(v)) { + m_vars_to_reinit.push_back(v); + m_active_vars[j++] = v; + } + else { + set_eliminated(v, true); + m_free_vars.push_back(v); + } + } + m_active_vars.shrink(j); + IF_VERBOSE(0, verbose_stream() << "vars to reinit: " << m_vars_to_reinit << " free vars " << m_free_vars << "\n"); } void solver::shrink_vars(unsigned v) { @@ -3702,7 +3761,9 @@ namespace sat { if (num_scopes == 0) return; if (m_ext) { - // pop_vars(num_scopes); +#if DYNAMIC_VARS + pop_vars(num_scopes); +#endif m_ext->pop(num_scopes); } SASSERT(num_scopes <= scope_lvl()); @@ -3713,7 +3774,7 @@ namespace sat { m_scope_lvl -= num_scopes; m_scopes.shrink(new_lvl); reinit_clauses(s.m_clauses_to_reinit_lim); - if (m_ext) + if (m_ext) m_ext->pop_reinit(); } @@ -3750,18 +3811,6 @@ namespace sat { m_replay_assign.reset(); } - void solver::get_reinit_literals(unsigned n, literal_vector& r) { - unsigned new_lvl = scope_lvl() - n; - unsigned old_sz = m_scopes[new_lvl].m_clauses_to_reinit_lim; - for (unsigned i = m_clauses_to_reinit.size(); i-- > old_sz; ) { - clause_wrapper cw = m_clauses_to_reinit[i]; - for (unsigned j = cw.size(); j-- > 0; ) - r.push_back(cw[j]); - } - for (literal lit : m_lemma) - r.push_back(lit); - } - void solver::reinit_clauses(unsigned old_sz) { unsigned sz = m_clauses_to_reinit.size(); SASSERT(old_sz <= sz); diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index 79eddffac..8ebef6497 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -115,6 +115,7 @@ namespace sat { clause_vector m_clauses; clause_vector m_learned; unsigned m_num_frozen; + unsigned_vector m_active_vars, m_free_vars, m_vars_to_reinit; vector m_watches; svector m_assignment; svector m_justification; @@ -264,6 +265,8 @@ namespace sat { random_gen& rand() { return m_rand; } protected: + void reset_var(bool_var v, bool ext, bool dvar); + inline clause_allocator& cls_allocator() { return m_cls_allocator[m_cls_allocator_idx]; } inline clause_allocator const& cls_allocator() const { return m_cls_allocator[m_cls_allocator_idx]; } inline clause * alloc_clause(unsigned num_lits, literal const * lits, bool learned) { return cls_allocator().mk_clause(num_lits, lits, learned); } @@ -645,7 +648,8 @@ namespace sat { // ----------------------- public: void set_should_simplify() { m_next_simplify = m_conflicts_since_init; } - void get_reinit_literals(unsigned num_scopes, literal_vector& r); + bool_var_vector const& get_vars_to_reinit() const { return m_vars_to_reinit; } + public: void user_push() override; void user_pop(unsigned num_scopes) override; diff --git a/src/sat/smt/bv_ackerman.h b/src/sat/smt/bv_ackerman.h index 0b5b28a8c..abcc5e60b 100644 --- a/src/sat/smt/bv_ackerman.h +++ b/src/sat/smt/bv_ackerman.h @@ -52,7 +52,8 @@ namespace bv { table_t m_table; vv* m_queue { nullptr }; vv* m_tmp_vv { nullptr }; - unsigned m_gc_threshold { 1 }; + + unsigned m_gc_threshold { 100 }; unsigned m_propagate_high_watermark { 10000 }; unsigned m_propagate_low_watermark { 10 }; unsigned m_num_propagations_since_last_gc { 0 }; diff --git a/src/sat/smt/euf_ackerman.cpp b/src/sat/smt/euf_ackerman.cpp index a551db4de..259d8dd30 100644 --- a/src/sat/smt/euf_ackerman.cpp +++ b/src/sat/smt/euf_ackerman.cpp @@ -47,6 +47,7 @@ namespace euf { inf.b = b; inf.c = lca; inf.is_cc = false; + inf.m_count = 0; insert(); } diff --git a/src/sat/smt/euf_ackerman.h b/src/sat/smt/euf_ackerman.h index d794d0276..7b9c4c3d9 100644 --- a/src/sat/smt/euf_ackerman.h +++ b/src/sat/smt/euf_ackerman.h @@ -57,7 +57,7 @@ namespace euf { table_t m_table; inference* m_queue { nullptr }; inference* m_tmp_inference { nullptr }; - unsigned m_gc_threshold { 1 }; + unsigned m_gc_threshold { 100 }; unsigned m_high_watermark { 1000 }; unsigned m_num_propagations_since_last_gc { 0 }; diff --git a/src/sat/smt/euf_solver.cpp b/src/sat/smt/euf_solver.cpp index 171f329ca..71572c905 100644 --- a/src/sat/smt/euf_solver.cpp +++ b/src/sat/smt/euf_solver.cpp @@ -315,6 +315,7 @@ namespace euf { } void solver::pop(unsigned n) { + start_reinit(n); m_egraph.pop(n); for (auto* e : m_solvers) e->pop(n); @@ -328,28 +329,32 @@ namespace euf { } void solver::start_reinit(unsigned n) { - sat::literal_vector lits; - m_reinit_vars.reset(); m_reinit_exprs.reset(); - s().get_reinit_literals(n, lits); - for (sat::literal lit : lits) { - sat::bool_var v = lit.var(); + for (sat::bool_var v : s().get_vars_to_reinit()) { expr* e = bool_var2expr(v); - if (m_reinit_vars.contains(v) || !e) - continue; - m_reinit_vars.push_back(v); m_reinit_exprs.push_back(e); } } void solver::finish_reinit() { - unsigned sz = m_reinit_vars.size(); - for (unsigned i = 0; i < sz; ++i) { - euf::enode* n = get_enode(m_reinit_exprs.get(i)); - if (n) - continue; + SASSERT(s().get_vars_to_reinit().size() == m_reinit_exprs.size()); + if (s().get_vars_to_reinit().empty()) + return; + unsigned i = 0; + obj_map expr2var_replay; + for (sat::bool_var v : s().get_vars_to_reinit()) { + expr* e = m_reinit_exprs.get(i++); + if (!e) + continue; + expr2var_replay.insert(e, v); } + if (expr2var_replay.empty()) + return; + si.set_expr2var_replay(&expr2var_replay); + for (auto const& kv : expr2var_replay) + si.internalize(kv.m_key, true); + si.set_expr2var_replay(nullptr); } void solver::pre_simplify() { @@ -461,6 +466,7 @@ namespace euf { } void solver::pop_reinit() { + finish_reinit(); for (auto* e : m_solvers) e->pop_reinit(); } diff --git a/src/sat/smt/euf_solver.h b/src/sat/smt/euf_solver.h index 5480b6fad..32eee7da2 100644 --- a/src/sat/smt/euf_solver.h +++ b/src/sat/smt/euf_solver.h @@ -118,7 +118,6 @@ namespace euf { // replay expr_ref_vector m_reinit_exprs; - sat::bool_var_vector m_reinit_vars; void start_reinit(unsigned num_scopes); void finish_reinit(); diff --git a/src/sat/smt/sat_smt.h b/src/sat/smt/sat_smt.h index 7b46f89b8..fe1d32df6 100644 --- a/src/sat/smt/sat_smt.h +++ b/src/sat/smt/sat_smt.h @@ -44,6 +44,7 @@ namespace sat { virtual void cache(app* t, literal l) = 0; virtual void push() = 0; virtual void pop(unsigned n) = 0; + virtual void set_expr2var_replay(obj_map* r) = 0; }; class constraint_base { diff --git a/src/sat/tactic/goal2sat.cpp b/src/sat/tactic/goal2sat.cpp index c1eb93ce9..d7feab9dc 100644 --- a/src/sat/tactic/goal2sat.cpp +++ b/src/sat/tactic/goal2sat.cpp @@ -66,6 +66,7 @@ struct goal2sat::imp : public sat::sat_internalizer { sat::solver_core & m_solver; atom2bool_var & m_map; dep2asm_map & m_dep2asm; + obj_map* m_expr2var_replay { nullptr }; sat::literal m_true; bool m_ite_extra; unsigned long long m_max_memory; @@ -189,16 +190,26 @@ struct goal2sat::imp : public sat::sat_internalizer { return m_map.to_bool_var(e); } + + void set_expr2var_replay(obj_map* r) override { + m_expr2var_replay = r; + } + + sat::bool_var mk_bool_var(expr* t) { + force_push(); + sat::bool_var v; + if (!m_expr2var_replay || !m_expr2var_replay->find(t, v)) + v = add_var(true, t); + m_map.insert(t, v); + return v; + } + sat::bool_var add_bool_var(expr* t) override { sat::bool_var v = m_map.to_bool_var(t); - if (v == sat::null_bool_var) { - v = add_var(true, t); - force_push(); - m_map.insert(t, v); - } - else { + if (v == sat::null_bool_var) + v = mk_bool_var(t); + else m_solver.set_external(v); - } return v; } @@ -254,9 +265,7 @@ struct goal2sat::imp : public sat::sat_internalizer { m_unhandled_funs.push_back(to_app(t)->get_decl()); } bool ext = m_default_external || !is_uninterp_const(t) || m_interface_vars.contains(t); - v = add_var(ext, t); - force_push(); - m_map.insert(t, v); + v = mk_bool_var(t); l = sat::literal(v, sign); TRACE("sat", tout << "new_var: " << v << ": " << mk_bounded_pp(t, m, 2) << " " << is_uninterp_const(t) << "\n";); } diff --git a/src/shell/drat_frontend.cpp b/src/shell/drat_frontend.cpp index 561c185e5..801f0a58b 100644 --- a/src/shell/drat_frontend.cpp +++ b/src/shell/drat_frontend.cpp @@ -102,7 +102,7 @@ static void verify_smt(char const* drat_file, char const* smt_file) { dimacs::drat_parser drat(ins, std::cerr); std::function read_theory = [&](char const* r) { if (strcmp(r, "euf") == 0) - return 0; + return ctx.m().get_basic_family_id(); return ctx.m().mk_family_id(symbol(r)); }; drat.set_read_theory(read_theory); diff --git a/src/util/dlist.h b/src/util/dlist.h index 9b6c87066..d5a2c4046 100644 --- a/src/util/dlist.h +++ b/src/util/dlist.h @@ -171,7 +171,10 @@ public: elem->m_prev = elem; } else if (list != elem) { - remove_from(list, elem); + auto* next = elem->m_next; + auto* prev = elem->m_prev; + prev->m_next = next; + next->m_prev = prev; list->m_prev->m_next = elem; elem->m_prev = list->m_prev; elem->m_next = list; diff --git a/src/util/scoped_limit_trail.h b/src/util/scoped_limit_trail.h index 6ea82ab82..1c60032ac 100644 --- a/src/util/scoped_limit_trail.h +++ b/src/util/scoped_limit_trail.h @@ -15,6 +15,7 @@ class scoped_limit_trail { else { for (; m_scopes > 0; --m_scopes) m_lim.push_back(m_last); + m_lim.push_back(n); m_last = n; } }