diff --git a/src/math/lp/lp_core_solver_base.h b/src/math/lp/lp_core_solver_base.h index 1bd8fe2df..7f861ff5f 100644 --- a/src/math/lp/lp_core_solver_base.h +++ b/src/math/lp/lp_core_solver_base.h @@ -590,32 +590,29 @@ public: return out; } - out << "[" << j << "]\t"; - + out << "[" << j << "] " << std::setw(6) << " := " << m_x[j]; + if (m_basis_heading[j] >= 0) + out << " base\t"; + else + out << " \t"; switch (m_column_types[j]) { case column_type::fixed: case column_type::boxed: - out << " [" << m_lower_bounds[j] << ", " << m_upper_bounds[j] << "]"; + out << "[" << m_lower_bounds[j] << ", " << m_upper_bounds[j] << "]"; break; case column_type::lower_bound: - out << " [" << m_lower_bounds[j] << "," << "oo" << "]"; + out << "[" << m_lower_bounds[j] << ", oo" << "]"; break; case column_type::upper_bound: - out << " [-oo, " << m_upper_bounds[j] << ']'; + out << "[-oo, " << m_upper_bounds[j] << ']'; break; case column_type::free_column: - out << " [-oo, oo]"; + out << "[-oo, oo]"; break; default: lp_assert(false); } - // out << "basis heading = " << m_basis_heading[j] << std::endl; - out << "\tx = " << m_x[j]; - if (m_basis_heading[j] >= 0) - out << " base\n"; - else - out << " \n"; - return out; + return out << "\n"; } bool column_is_free(unsigned j) const { return this->m_column_types[j] == column_type::free_column; } diff --git a/src/model/func_interp.cpp b/src/model/func_interp.cpp index 11e93bf09..dc5b78b0f 100644 --- a/src/model/func_interp.cpp +++ b/src/model/func_interp.cpp @@ -215,6 +215,13 @@ void func_interp::insert_new_entry(expr * const * args, expr * r) { m_entries.push_back(new_entry); } +void func_interp::del_entry(unsigned idx) { + auto* e = m_entries[idx]; + m_entries[idx] = m_entries.back(); + m_entries.pop_back(); + e->deallocate(m(), m_arity); +} + bool func_interp::eval_else(expr * const * args, expr_ref & result) const { if (m_else == nullptr) return false; diff --git a/src/model/func_interp.h b/src/model/func_interp.h index 2eec81168..115013008 100644 --- a/src/model/func_interp.h +++ b/src/model/func_interp.h @@ -109,6 +109,7 @@ public: ptr_vector::const_iterator end() const { return m_entries.end(); } func_entry const * const * get_entries() const { return m_entries.c_ptr(); } func_entry const * get_entry(unsigned idx) const { return m_entries[idx]; } + void del_entry(unsigned idx); expr * get_max_occ_result() const; void compress(); diff --git a/src/qe/mbp/mbp_arith.cpp b/src/qe/mbp/mbp_arith.cpp index 0cbae132c..42e48649b 100644 --- a/src/qe/mbp/mbp_arith.cpp +++ b/src/qe/mbp/mbp_arith.cpp @@ -37,7 +37,14 @@ namespace mbp { ast_manager& m; arith_util a; - bool m_check_purified; // check that variables are properly pure + bool m_check_purified { true }; // check that variables are properly pure + bool m_apply_projection { false }; + + + imp(ast_manager& m) : + m(m), a(m) {} + + ~imp() {} void insert_mul(expr* x, rational const& v, obj_map& ts) { // TRACE("qe", tout << "Adding variable " << mk_pp(x, m) << " " << v << "\n";); @@ -238,11 +245,6 @@ namespace mbp { return rational(b.is_pos()?-1:1); } - imp(ast_manager& m): - m(m), a(m), m_check_purified(true) {} - - ~imp() {} - bool operator()(model& model, app* v, app_ref_vector& vars, expr_ref_vector& lits) { app_ref_vector vs(m); vs.push_back(v); @@ -271,6 +273,7 @@ namespace mbp { model_evaluator eval(model); TRACE("qe", tout << model;); eval.set_model_completion(true); + compute_def |= m_apply_projection; opt::model_based_opt mbo; obj_map tids; @@ -341,15 +344,19 @@ namespace mbp { for (unsigned v : real_vars) tout << "v" << v << " " << mk_pp(index2expr[v], m) << "\n"; mbo.display(tout);); vector defs = mbo.project(real_vars.size(), real_vars.c_ptr(), compute_def); - TRACE("qe", mbo.display(tout << "mbo result\n"); - for (auto const& d : defs) tout << "def: " << d << "\n";); + vector rows; mbo.get_live_rows(rows); rows2fmls(rows, index2expr, fmls); + TRACE("qe", mbo.display(tout << "mbo result\n"); + for (auto const& d : defs) tout << "def: " << d << "\n"; + tout << fmls << "\n";); vector result; if (compute_def) - optdefs2mbpdef(defs, index2expr, real_vars, result); + optdefs2mbpdef(defs, index2expr, real_vars, result); + if (m_apply_projection) + apply_projection(result, fmls); return result; } @@ -523,6 +530,20 @@ namespace mbp { } } + void apply_projection(vector& defs, expr_ref_vector& fmls) { + if (fmls.empty() || defs.empty()) + return; + expr_safe_replace subst(m); + for (auto const& d : defs) + subst.insert(d.var, d.term); + unsigned j = 0; + expr_ref tmp(m); + for (expr* fml : fmls) { + subst(fml, tmp); + fmls[j++] = tmp; + } + } + }; arith_project_plugin::arith_project_plugin(ast_manager& m):project_plugin(m) { @@ -549,6 +570,10 @@ namespace mbp { m_imp->m_check_purified = check_purified; } + void arith_project_plugin::set_apply_projection(bool f) { + m_imp->m_apply_projection = f; + } + family_id arith_project_plugin::get_family_id() { return m_imp->a.get_family_id(); } diff --git a/src/qe/mbp/mbp_arith.h b/src/qe/mbp/mbp_arith.h index 2a66e0abc..51d80a870 100644 --- a/src/qe/mbp/mbp_arith.h +++ b/src/qe/mbp/mbp_arith.h @@ -41,6 +41,11 @@ namespace mbp { */ void set_check_purified(bool check_purified); + /** + * \brief apply projection + */ + void set_apply_projection(bool apply_project); + }; bool arith_project(model& model, app* var, expr_ref_vector& lits); diff --git a/src/qe/mbp/mbp_plugin.cpp b/src/qe/mbp/mbp_plugin.cpp index 3a73e8b50..344e4d8f0 100644 --- a/src/qe/mbp/mbp_plugin.cpp +++ b/src/qe/mbp/mbp_plugin.cpp @@ -327,10 +327,10 @@ namespace mbp { void project_plugin::purify(euf_inverter& inv, model& mdl, app_ref_vector const& vars, expr_ref_vector& lits) { TRACE("mbp", tout << lits << "\n" << mdl << "\n";); + model_evaluator eval(mdl); extract_literals(mdl, vars, lits); if (!m.inc()) return; - model_evaluator eval(mdl); eval.set_expand_array_equalities(true); m_non_ground.reset(); m_to_visit.reset(); @@ -341,7 +341,6 @@ namespace mbp { m_non_ground.mark(v); for (unsigned i = 0; m.inc() && i < lits.size(); ++i) lits[i] = purify(inv, eval, lits.get(i), lits); - std::cout << m_pure_eqs << "\n"; lits.append(m_pure_eqs); TRACE("mbp", tout << lits << "\n";); } diff --git a/src/sat/smt/arith_axioms.cpp b/src/sat/smt/arith_axioms.cpp index 2b74b328d..f1ebe7d79 100644 --- a/src/sat/smt/arith_axioms.cpp +++ b/src/sat/smt/arith_axioms.cpp @@ -296,21 +296,19 @@ namespace arith { return lp::EQ; } - void solver::mk_eq_axiom(theory_var v1, theory_var v2) { + void solver::mk_eq_axiom(bool is_eq, theory_var v1, theory_var v2) { if (is_bool(v1)) return; expr* e1 = var2expr(v1); expr* e2 = var2expr(v2); - if (e1 == e2) + if (is_eq && m.are_equal(e1, e2)) return; + if (!is_eq && m.are_distinct(e1, e2)) + return; literal le, ge; if (a.is_numeral(e1)) std::swap(e1, e2); - if (a.is_numeral(e1)) { - add_unit(~mk_literal(m.mk_eq(e1, e2))); - std::cout << "two numerals\n"; - return; - } + SASSERT(!a.is_numeral(e1)); literal eq = eq_internalize(e1, e2); if (a.is_numeral(e2)) { le = mk_literal(a.mk_le(e1, e2)); @@ -321,8 +319,11 @@ namespace arith { expr_ref zero(a.mk_numeral(rational(0), a.is_int(e1)), m); rewrite(diff); if (a.is_numeral(diff)) { - std::cout << "diff " << diff << " " << mk_pp(e1, m) << " " << mk_pp(e2, m) << "\n"; - if (zero == diff) + if (is_eq && a.is_zero(diff)) + return; + if (!is_eq && !a.is_zero(diff)) + return; + if (a.is_zero(diff)) add_unit(eq); else add_unit(~eq); @@ -331,8 +332,8 @@ namespace arith { le = mk_literal(a.mk_le(diff, zero)); ge = mk_literal(a.mk_ge(diff, zero)); } - std::cout << mk_pp(e1, m) << " " << mk_pp(e2, m) << " "; - std::cout << le << " " << ge << "\n"; + // std::cout << "eq " << mk_pp(e1, m) << " " << mk_pp(e2, m) << " "; + // std::cout << le << " " << ge << "\n"; add_clause(~eq, le); add_clause(~eq, ge); add_clause(~le, ~ge, eq); diff --git a/src/sat/smt/arith_internalize.cpp b/src/sat/smt/arith_internalize.cpp index 974bd03c9..7f8daa0db 100644 --- a/src/sat/smt/arith_internalize.cpp +++ b/src/sat/smt/arith_internalize.cpp @@ -21,6 +21,7 @@ Author: namespace arith { sat::literal solver::internalize(expr* e, bool sign, bool root, bool learned) { + force_push(); flet _is_learned(m_is_redundant, learned); internalize_atom(e); literal lit = ctx.expr2literal(e); @@ -30,6 +31,7 @@ namespace arith { } void solver::internalize(expr* e, bool redundant) { + force_push(); flet _is_learned(m_is_redundant, redundant); if (m.is_bool(e)) internalize_atom(e); diff --git a/src/sat/smt/arith_solver.cpp b/src/sat/smt/arith_solver.cpp index 44023c085..d1eddf1a7 100644 --- a/src/sat/smt/arith_solver.cpp +++ b/src/sat/smt/arith_solver.cpp @@ -583,7 +583,7 @@ namespace arith { } void solver::push_core() { - TRACE("arith", tout << "push\n";); + TRACE("arith_verbose", tout << "push\n";); m_scopes.push_back(scope()); scope& sc = m_scopes.back(); sc.m_bounds_lim = m_bounds_trail.size(); @@ -596,11 +596,11 @@ namespace arith { if (m_nla) m_nla->push(); th_euf_solver::push_core(); + } void solver::pop_core(unsigned num_scopes) { TRACE("arith", tout << "pop " << num_scopes << "\n";); - th_euf_solver::pop_core(num_scopes); unsigned old_size = m_scopes.size() - num_scopes; del_bounds(m_scopes[old_size].m_bounds_lim); m_idiv_terms.shrink(m_scopes[old_size].m_idiv_lim); @@ -613,7 +613,8 @@ namespace arith { m_new_bounds.reset(); if (m_nla) m_nla->pop(num_scopes); - TRACE("arith", tout << "num scopes: " << num_scopes << " new scope level: " << m_scopes.size() << "\n";); + TRACE("arith_verbose", tout << "num scopes: " << num_scopes << " new scope level: " << m_scopes.size() << "\n";); + th_euf_solver::pop_core(num_scopes); } void solver::del_bounds(unsigned old_size) { @@ -964,7 +965,7 @@ namespace arith { return sat::check_result::CR_CONTINUE; case l_undef: TRACE("arith", tout << "check feasible is undef\n";); - return m.inc() ? sat::check_result::CR_CONTINUE : sat::check_result::CR_GIVEUP; + return sat::check_result::CR_CONTINUE; case l_true: break; default: diff --git a/src/sat/smt/arith_solver.h b/src/sat/smt/arith_solver.h index dcd856831..2e1eff67c 100644 --- a/src/sat/smt/arith_solver.h +++ b/src/sat/smt/arith_solver.h @@ -303,7 +303,7 @@ namespace arith { void refine_bound(theory_var v, const lp::implied_bound& be); literal is_bound_implied(lp::lconstraint_kind k, rational const& value, api_bound const& b) const; void assert_bound(bool is_true, api_bound& b); - void mk_eq_axiom(theory_var v1, theory_var v2); + void mk_eq_axiom(bool is_eq, theory_var v1, theory_var v2); void assert_idiv_mod_axioms(theory_var u, theory_var v, theory_var w, rational const& r); api_bound* mk_var_bound(sat::literal lit, theory_var v, lp_api::bound_kind bk, rational const& bound); lp::lconstraint_kind bound2constraint_kind(bool is_int, lp_api::bound_kind bk, bool is_true); @@ -423,8 +423,8 @@ namespace arith { void collect_statistics(statistics& st) const override; euf::th_solver* clone(euf::solver& ctx) override; bool use_diseqs() const override { return true; } - void new_eq_eh(euf::th_eq const& eq) override { mk_eq_axiom(eq.v1(), eq.v2()); } - void new_diseq_eh(euf::th_eq const& de) override { mk_eq_axiom(de.v1(), de.v2()); } + void new_eq_eh(euf::th_eq const& eq) override { mk_eq_axiom(true, eq.v1(), eq.v2()); } + void new_diseq_eh(euf::th_eq const& de) override { mk_eq_axiom(false, de.v1(), de.v2()); } bool unit_propagate() override; void init_model() override; void add_value(euf::enode* n, model& mdl, expr_ref_vector& values) override; diff --git a/src/sat/smt/euf_solver.cpp b/src/sat/smt/euf_solver.cpp index bdac9b3e8..17f8dc2fa 100644 --- a/src/sat/smt/euf_solver.cpp +++ b/src/sat/smt/euf_solver.cpp @@ -402,12 +402,15 @@ namespace euf { if (!init_relevancy()) give_up = true; - for (auto* e : m_solvers) + for (auto* e : m_solvers) { + if (!m.inc()) + return sat::check_result::CR_GIVEUP; switch (e->check()) { case sat::check_result::CR_CONTINUE: cont = true; break; case sat::check_result::CR_GIVEUP: give_up = true; break; default: break; } + } if (cont) return sat::check_result::CR_CONTINUE; if (give_up) diff --git a/src/sat/smt/q_mbi.cpp b/src/sat/smt/q_mbi.cpp index 485f7f642..6aa326ffb 100644 --- a/src/sat/smt/q_mbi.cpp +++ b/src/sat/smt/q_mbi.cpp @@ -39,6 +39,7 @@ namespace q { { auto* ap = alloc(mbp::arith_project_plugin, m); ap->set_check_purified(false); + ap->set_apply_projection(true); add_plugin(ap); add_plugin(alloc(mbp::datatype_project_plugin, m)); add_plugin(alloc(mbp::array_project_plugin, m)); @@ -186,11 +187,13 @@ namespace q { expr_ref mbqi::solver_project(model& mdl, q_body& qb) { for (app* v : qb.vars) m_model->register_decl(v->get_decl(), mdl(v)); + std::cout << "Project\n"; + std::cout << *m_model << "\n"; + std::cout << qb.vbody << "\n"; expr_ref_vector fmls(qb.vbody); app_ref_vector vars(qb.vars); mbp::project_plugin proj(m); proj.purify(m_model_fixer, *m_model, vars, fmls); - std::cout << "fmls\n" << fmls << "\n"; for (unsigned i = 0; i < vars.size(); ++i) { app* v = vars.get(i); auto* p = get_plugin(v); diff --git a/src/sat/smt/q_model_fixer.cpp b/src/sat/smt/q_model_fixer.cpp index dd01761ec..94dde44c7 100644 --- a/src/sat/smt/q_model_fixer.cpp +++ b/src/sat/smt/q_model_fixer.cpp @@ -103,15 +103,17 @@ namespace q { void model_fixer::add_projection_functions(model& mdl, ptr_vector const& qs) { func_decl_set fns; + TRACE("q", tout << mdl << "\n";); collect_partial_functions(qs, fns); for (func_decl* f : fns) add_projection_functions(mdl, f); + TRACE("q", tout << mdl << "\n";); } void model_fixer::add_projection_functions(model& mdl, func_decl* f) { // update interpretation of f so that the graph of f is fully determined by the // ground values of its arguments. - TRACE("q", tout << mdl << "\n";); + func_interp* fi = mdl.get_func_interp(f); if (!fi) return; @@ -120,8 +122,12 @@ namespace q { expr_ref_vector args(m); for (unsigned i = 0; i < f->get_arity(); ++i) args.push_back(add_projection_function(mdl, f, i)); - if (!fi->get_else() && fi->num_entries() > 0) - fi->set_else(fi->get_entry(ctx.s().rand()(fi->num_entries()))->get_result()); + if (!fi->get_else() && fi->num_entries() > 0) { + unsigned idx = ctx.s().rand()(fi->num_entries()); + func_entry const* e = fi->get_entry(idx); + fi->set_else(e->get_result()); + fi->del_entry(idx); + } bool has_projection = false; for (expr* arg : args) has_projection |= !is_var(arg); @@ -132,7 +138,6 @@ namespace q { new_fi->set_else(m.mk_app(f_new, args)); mdl.update_func_interp(f, new_fi); mdl.register_decl(f_new, fi); - TRACE("q", tout << mdl << "\n";); } expr_ref model_fixer::add_projection_function(model& mdl, func_decl* f, unsigned idx) { diff --git a/src/sat/smt/sat_th.cpp b/src/sat/smt/sat_th.cpp index 686a898d5..e53b7ec13 100644 --- a/src/sat/smt/sat_th.cpp +++ b/src/sat/smt/sat_th.cpp @@ -217,8 +217,8 @@ namespace euf { return n; } - unsigned th_propagation::get_obj_size(unsigned num_lits, unsigned num_eqs) { - return sizeof(th_propagation) + sizeof(sat::literal) * num_lits + sizeof(enode_pair) * num_eqs; + size_t th_propagation::get_obj_size(unsigned num_lits, unsigned num_eqs) { + return sat::constraint_base::obj_size(sizeof(th_propagation) + sizeof(sat::literal) * num_lits + sizeof(enode_pair) * num_eqs); } th_propagation::th_propagation(unsigned n_lits, sat::literal const* lits, unsigned n_eqs, enode_pair const* eqs) { diff --git a/src/sat/smt/sat_th.h b/src/sat/smt/sat_th.h index 83ae823c4..af04df97b 100644 --- a/src/sat/smt/sat_th.h +++ b/src/sat/smt/sat_th.h @@ -161,7 +161,7 @@ namespace euf { virtual void push_core(); virtual void pop_core(unsigned n); void force_push() { - CTRACE("euf", m_num_scopes > 0, tout << "push-core " << m_num_scopes << "\n";); + CTRACE("euf_verbose", m_num_scopes > 0, tout << "push-core " << m_num_scopes << "\n";); for (; m_num_scopes > 0; --m_num_scopes) push_core(); } @@ -194,7 +194,7 @@ namespace euf { unsigned m_num_eqs; sat::literal* m_literals; enode_pair* m_eqs; - static unsigned get_obj_size(unsigned num_lits, unsigned num_eqs); + static size_t get_obj_size(unsigned num_lits, unsigned num_eqs); th_propagation(unsigned n_lits, sat::literal const* lits, unsigned n_eqs, enode_pair const* eqs); public: static th_propagation* mk(th_euf_solver& th, sat::literal_vector const& lits, enode_pair_vector const& eqs); diff --git a/src/util/region.cpp b/src/util/region.cpp index 3cf3f502f..dd5fbd760 100644 --- a/src/util/region.cpp +++ b/src/util/region.cpp @@ -21,9 +21,33 @@ Revision History: #ifdef Z3DEBUG void region::display_mem_stats(std::ostream & out) const { - out << "num. objects: " << m_chuncks.size() << "\n"; + out << "num. objects: " << m_chunks.size() << "\n"; } +void * region::allocate(size_t size) { + char * r = alloc_svect(char, size); + m_chunks.push_back(r); + return r; +} + +void region::reset() { + for (auto* c : m_chunks) + dealloc_svect(c); + m_chunks.reset(); + m_scopes.reset(); +} + +void region::pop_scope() { + unsigned old_size = m_scopes.back(); + m_scopes.pop_back(); + ptr_vector::iterator it = m_chunks.begin() + old_size; + ptr_vector::iterator end = m_chunks.end(); + for (; it != end; ++it) + dealloc_svect(*it); + m_chunks.shrink(old_size); +} + + #else #include "util/tptr.h" diff --git a/src/util/region.h b/src/util/region.h index c55eb3f04..f3f0d35ab 100644 --- a/src/util/region.h +++ b/src/util/region.h @@ -25,44 +25,23 @@ Revision History: #include "util/vector.h" class region { - ptr_vector m_chuncks; + ptr_vector m_chunks; unsigned_vector m_scopes; public: ~region() { reset(); } - void * allocate(size_t size) { - char * r = alloc_svect(char, size); - m_chuncks.push_back(r); - return r; - } - void reset() { - ptr_vector::iterator it = m_chuncks.begin(); - ptr_vector::iterator end = m_chuncks.end(); - for (; it != end; ++it) { - dealloc_svect(*it); - } - m_chuncks.reset(); - m_scopes.reset(); - } + void * allocate(size_t size); + + void reset(); void push_scope() { - m_scopes.push_back(m_chuncks.size()); + m_scopes.push_back(m_chunks.size()); } - - void pop_scope() { - unsigned old_size = m_scopes.back(); - m_scopes.pop_back(); - ptr_vector::iterator it = m_chuncks.begin() + old_size; - ptr_vector::iterator end = m_chuncks.end(); - for (; it != end; ++it) { - dealloc_svect(*it); - } - m_chuncks.shrink(old_size); - } + void pop_scope(); void pop_scope(unsigned num_scopes) { for (unsigned i = 0; i < num_scopes; i++) {