diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 57e4d3ec1..397be7684 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -6023,7 +6023,7 @@ END_MLAPI_EXCLUDE \param a - arithmetical term def_API('Z3_optimize_maximize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) */ - unsigned Z3_API Z3_optimize_maximize(Z3_context, Z3_optimize o, Z3_ast t); + unsigned Z3_API Z3_optimize_maximize(Z3_context c, Z3_optimize o, Z3_ast t); /** \brief Add a minimization constraint. @@ -6033,7 +6033,7 @@ END_MLAPI_EXCLUDE def_API('Z3_optimize_minimize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) */ - unsigned Z3_API Z3_optimize_minimize(Z3_context, Z3_optimize o, Z3_ast t); + unsigned Z3_API Z3_optimize_minimize(Z3_context c, Z3_optimize o, Z3_ast t); /** diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index f5d96e740..3f1883749 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -4117,7 +4117,6 @@ namespace polynomial { polynomial_ref H(m_wrapper), C(m_wrapper); polynomial_ref lc_H(m_wrapper); unsigned min_deg_q = UINT_MAX; - var next_x = vars[idx+1]; unsigned counter = 0; for (;; counter++) { @@ -4137,7 +4136,7 @@ namespace polynomial { var q_var = max_var(q); unsigned deg_q = q_var == null_var ? 0 : degree(q, q_var); TRACE("mgcd_detail", tout << "counter: " << counter << "\nidx: " << idx << "\nq: " << q << "\ndeg_q: " << deg_q << "\nmin_deg_q: " << - min_deg_q << "\nnext_x: x" << next_x << "\nmax_var(q): " << q_var << "\n";); + min_deg_q << "\nnext_x: x" << vars[idx+1] << "\nmax_var(q): " << q_var << "\n";); if (deg_q < min_deg_q) { TRACE("mgcd_detail", tout << "reseting...\n";); counter = 0; @@ -5113,10 +5112,9 @@ namespace polynomial { monomial const * m_r = R.m(max_R); numeral const & a_r = R.a(max_R); monomial * m_r_q = 0; - bool q_div_r = div(m_r, m_q, m_r_q); + VERIFY(div(m_r, m_q, m_r_q)); TRACE("polynomial", tout << "m_r: "; m_r->display(tout); tout << "\nm_q: "; m_q->display(tout); tout << "\n"; if (m_r_q) { tout << "m_r_q: "; m_r_q->display(tout); tout << "\n"; }); - SASSERT(q_div_r); m_r_q_ref = m_r_q; m_manager.div(a_r, a_q, a_r_q); C.add(a_r_q, m_r_q); // C <- C + (a_r/a_q)*(m_r/m_q) diff --git a/src/muz/rel/udoc_relation.cpp b/src/muz/rel/udoc_relation.cpp index d3c1f929d..4d1fdf1d2 100644 --- a/src/muz/rel/udoc_relation.cpp +++ b/src/muz/rel/udoc_relation.cpp @@ -1264,6 +1264,21 @@ namespace datalog { return check_kind(t)?alloc(filter_proj_fn, get(t), get_ast_manager(), condition, removed_col_cnt, removed_cols):0; } + relation_join_fn * udoc_plugin::mk_join_project_fn( + relation_base const& t1, relation_base const& t2, + unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned * removed_cols) { + if (check_kind(t1) && check_kind(t2)) + return 0; +#if 0 + return alloc(join_proj_fn, get(t1), ge(t2), + joined_col_cnt, cols1, cols2, + removed_col_cnt, removed_cols); +#endif + else + return 0; + } + diff --git a/src/muz/rel/udoc_relation.h b/src/muz/rel/udoc_relation.h index f040e4745..596a1f0dd 100644 --- a/src/muz/rel/udoc_relation.h +++ b/src/muz/rel/udoc_relation.h @@ -81,6 +81,7 @@ namespace datalog { class udoc_plugin : public relation_plugin { friend class udoc_relation; class join_fn; + class join_project_fn; class project_fn; class union_fn; class rename_fn; @@ -138,6 +139,11 @@ namespace datalog { virtual relation_transformer_fn * mk_filter_interpreted_and_project_fn( const relation_base & t, app * condition, unsigned removed_col_cnt, const unsigned * removed_cols); + virtual relation_join_fn * mk_join_project_fn( + relation_base const& t1, relation_base const& t2, + unsigned joined_col_cnt, const unsigned * cols1, const unsigned * cols2, + unsigned removed_col_cnt, const unsigned * removed_cols); + void disable_fast_pass() { m_disable_fast_pass = true; } }; }; diff --git a/src/opt/inc_sat_solver.cpp b/src/opt/inc_sat_solver.cpp index 5eecf42d7..1c450bbef 100644 --- a/src/opt/inc_sat_solver.cpp +++ b/src/opt/inc_sat_solver.cpp @@ -316,6 +316,7 @@ private: for (; it != end; ++it) { asms.push_back(it->m_value); } + //IF_VERBOSE(0, verbose_stream() << asms << "\n";); } void extract_core(dep2asm_t& dep2asm) { @@ -341,7 +342,7 @@ private: m_core.reset(); for (unsigned i = 0; i < core.size(); ++i) { expr* e; - VERIFY (asm2dep.find(core[i].index(), e)); + VERIFY(asm2dep.find(core[i].index(), e)); m_core.push_back(e); } @@ -397,6 +398,14 @@ private: SASSERT(m_model); // IF_VERBOSE(0, model_smt2_pp(verbose_stream(), m, *(m_model.get()), 0);); + DEBUG_CODE( + for (unsigned i = 0; i < m_fmls.size(); ++i) { + expr_ref tmp(m); + VERIFY(m_model->eval(m_fmls[i].get(), tmp)); + CTRACE("opt", !m.is_true(tmp), + tout << "Evaluation failed: " << mk_pp(m_fmls[i].get(), m) << "\n";); + SASSERT(m.is_true(tmp)); + }); } }; diff --git a/src/opt/maxres.cpp b/src/opt/maxres.cpp index be39a05d5..65e026c07 100644 --- a/src/opt/maxres.cpp +++ b/src/opt/maxres.cpp @@ -64,6 +64,7 @@ Notes: #include "pb_decl_plugin.h" #include "opt_params.hpp" #include "ast_util.h" +#include "smt_solver.h" using namespace opt; @@ -150,6 +151,7 @@ public: } void new_assumption(expr* e, rational const& w) { + IF_VERBOSE(3, verbose_stream() << "new assumption " << mk_pp(e, m) << " " << w << "\n";); TRACE("opt", tout << "insert: " << mk_pp(e, m) << " : " << w << "\n";); m_asm2weight.insert(e, w); m_asms.push_back(e); @@ -171,7 +173,6 @@ public: if (m_cancel) { return l_undef; } - model_ref mdl; switch (is_sat) { case l_true: found_optimum(); @@ -179,7 +180,6 @@ public: case l_false: is_sat = process_unsat(); if (is_sat != l_true) return is_sat; - get_mus_model(mdl); break; case l_undef: return l_undef; @@ -187,6 +187,7 @@ public: break; } } + trace_bounds("maxres"); return l_true; } @@ -370,6 +371,7 @@ public: } void found_optimum() { + IF_VERBOSE(1, verbose_stream() << "found optimum\n";); s().get_model(m_model); DEBUG_CODE( for (unsigned i = 0; i < m_asms.size(); ++i) { @@ -404,6 +406,9 @@ public: while (is_sat == l_false) { core.reset(); s().get_unsat_core(core); + //verify_core(core); + model_ref mdl; + get_mus_model(mdl); is_sat = minimize_core(core); if (is_sat != l_true) { break; @@ -420,18 +425,12 @@ public: break; } remove_soft(core, asms); - TRACE("opt", - display_vec(tout << "core: ", core.size(), core.c_ptr()); - display_vec(tout << "assumptions: ", asms.size(), asms.c_ptr());); is_sat = check_sat_hill_climb(asms); } TRACE("opt", tout << "num cores: " << cores.size() << "\n"; for (unsigned i = 0; i < cores.size(); ++i) { - for (unsigned j = 0; j < cores[i].size(); ++j) { - tout << mk_pp(cores[i][j], m) << " "; - } - tout << "\n"; + display_vec(tout, cores[i].size(), cores[i].c_ptr()); } tout << "num satisfying: " << asms.size() << "\n";); @@ -535,6 +534,7 @@ public: if (m_c.sat_enabled()) { // SAT solver core extracts some model // during unsat core computation. + mdl = 0; s().get_model(mdl); } else { @@ -601,10 +601,7 @@ public: // find the minimal weight: rational w = get_weight(core[0]); for (unsigned i = 1; i < core.size(); ++i) { - rational w2 = get_weight(core[i]); - if (w2 < w) { - w = w2; - } + w = std::min(w, get_weight(core[i])); } // add fresh soft clauses for weights that are above w. for (unsigned i = 0; i < core.size(); ++i) { @@ -614,6 +611,7 @@ public: new_assumption(core[i], w3); } } + return w; } @@ -754,6 +752,7 @@ public: case l_false: core.reset(); s().get_unsat_core(core); + DEBUG_CODE(verify_core(core);); is_sat = minimize_core(core); if (is_sat != l_true) { break; @@ -786,14 +785,9 @@ public: rational upper(0); expr_ref tmp(m); for (unsigned i = 0; i < m_soft.size(); ++i) { - expr* n = m_soft[i]; - VERIFY(mdl->eval(n, tmp)); - if (!m.is_true(tmp)) { + if (!is_true(mdl, m_soft[i])) { upper += m_weights[i]; } - TRACE("opt", tout << mk_pp(n, m) << " |-> " << mk_pp(tmp, m) << "\n";); - CTRACE("opt", !m.is_true(tmp) && !m.is_false(tmp), - tout << mk_pp(n, m) << " |-> " << mk_pp(tmp, m) << "\n";); } if (upper >= m_upper) { return; @@ -804,7 +798,7 @@ public: m_assignment[i] = is_true(m_soft[i]); } m_upper = upper; - // verify_assignment(); + DEBUG_CODE(verify_assignment();); trace_bounds("maxres"); add_upper_bound_block(); @@ -888,6 +882,38 @@ public: } } + void verify_core(exprs const& core) { + IF_VERBOSE(3, verbose_stream() << "verify core\n";); + ref sat_solver = mk_inc_sat_solver(m, m_params); + + for (unsigned i = 0; i < s().get_num_assertions(); ++i) { + sat_solver->assert_expr(s().get_assertion(i)); + } + expr_ref n(m); + for (unsigned i = 0; i < core.size(); ++i) { + IF_VERBOSE(1, verbose_stream() << mk_pp(core[i],m) << " ";); + sat_solver->assert_expr(core[i]); + } + IF_VERBOSE(1, verbose_stream() << "\n";); + lbool is_sat = sat_solver->check_sat(0, 0); + if (is_sat != l_false) { + IF_VERBOSE(0, verbose_stream() << "!!!not a core\n";); + } + + sat_solver = mk_smt_solver(m, m_params, symbol()); + for (unsigned i = 0; i < s().get_num_assertions(); ++i) { + sat_solver->assert_expr(s().get_assertion(i)); + } + for (unsigned i = 0; i < core.size(); ++i) { + sat_solver->assert_expr(core[i]); + } + is_sat = sat_solver->check_sat(0, 0); + if (is_sat == l_true) { + IF_VERBOSE(0, verbose_stream() << "not a core\n";); + } + + } + void verify_assignment() { IF_VERBOSE(0, verbose_stream() << "verify assignment\n";); ref sat_solver = mk_inc_sat_solver(m, m_params); diff --git a/src/qe/qe.cpp b/src/qe/qe.cpp index 17a1ccb1d..7275ff71f 100644 --- a/src/qe/qe.cpp +++ b/src/qe/qe.cpp @@ -1449,11 +1449,19 @@ namespace qe { m_solver.assert_expr(m_fml); if (assumption) m_solver.assert_expr(assumption); - bool is_sat = false; - while (l_true == m_solver.check()) { - is_sat = true; + bool is_sat = false; + lbool res = l_true; + while (res == l_true) { + res = m_solver.check(); + if (res == l_true) is_sat = true; final_check(); } + if (res == l_undef) { + free_vars.append(num_vars, vars); + reset(); + m_solver.pop(1); + return; + } if (!is_sat) { fml = m.mk_false(); @@ -1484,12 +1492,13 @@ namespace qe { ); free_vars.append(m_free_vars); - SASSERT(!m_free_vars.empty() || m_solver.inconsistent()); + if (!m_free_vars.empty() || m_solver.inconsistent()) { - if (m_fml.get() != m_subfml.get()) { - scoped_ptr rp = mk_default_expr_replacer(m); - rp->apply_substitution(to_app(m_subfml.get()), fml, m_fml); - fml = m_fml; + if (m_fml.get() != m_subfml.get()) { + scoped_ptr rp = mk_default_expr_replacer(m); + rp->apply_substitution(to_app(m_subfml.get()), fml, m_fml); + fml = m_fml; + } } reset(); m_solver.pop(1); diff --git a/src/sat/sat_bceq.cpp b/src/sat/sat_bceq.cpp index 65377caed..7ad0ec837 100644 --- a/src/sat/sat_bceq.cpp +++ b/src/sat/sat_bceq.cpp @@ -22,6 +22,7 @@ Revision History: #include"trace.h" #include"bit_vector.h" #include"map.h" +#include"sat_elim_eqs.h" namespace sat { @@ -54,7 +55,7 @@ namespace sat { } } bin_clauses bc; - m_solver.collect_bin_clauses(bc, false); + m_solver.collect_bin_clauses(bc, false); // exclude roots. literal lits[2]; for (unsigned i = 0; i < bc.size(); ++i) { lits[0] = bc[i].first; @@ -215,7 +216,7 @@ namespace sat { m_L.append(new_clauses); m_L_blits.append(new_blits); } - std::cout << "Number left after BCE: " << clauses.size() << "\n"; + if (!clauses.empty()) std::cout << "Number left after BCE: " << clauses.size() << "\n"; return clauses.empty(); } @@ -362,7 +363,13 @@ namespace sat { while (v != i) { if (!m_solver.was_eliminated(v)) { if (last_v != UINT_MAX) { - check_equality(v, last_v); + if (check_equality(v, last_v)) { + // last_v was eliminated. + + } + else { + // TBD: refine partition. + } } last_v = v; } @@ -371,7 +378,7 @@ namespace sat { } } - void bceq::check_equality(unsigned v1, unsigned v2) { + bool bceq::check_equality(unsigned v1, unsigned v2) { TRACE("sat", tout << "check: " << v1 << " = " << v2 << "\n";); uint64 val1 = m_rbits[v1]; uint64 val2 = m_rbits[v2]; @@ -381,9 +388,9 @@ namespace sat { SASSERT(val1 == ~val2); l2.neg(); } - if (is_equiv(l1, l2)) { + if (is_already_equiv(l1, l2)) { TRACE("sat", tout << "Already equivalent: " << l1 << " " << l2 << "\n";); - return; + return false; } literal lits[2]; @@ -397,13 +404,16 @@ namespace sat { } if (is_sat == l_false) { TRACE("sat", tout << "Found equivalent: " << l1 << " " << l2 << "\n";); + assert_equality(l1, l2); } else { TRACE("sat", tout << "Not equivalent: " << l1 << " " << l2 << "\n";); + // TBD: if is_sat == l_true, then refine partition. } + return is_sat == l_false; } - bool bceq::is_equiv(literal l1, literal l2) { + bool bceq::is_already_equiv(literal l1, literal l2) { watch_list const& w1 = m_solver.get_wlist(l1); bool found = false; for (unsigned i = 0; !found && i < w1.size(); ++i) { @@ -420,6 +430,24 @@ namespace sat { return found; } + void bceq::assert_equality(literal l1, literal l2) { + if (l2.sign()) { + l1.neg(); + l2.neg(); + } + literal_vector roots; + bool_var_vector vars; + for (unsigned i = 0; i < m_solver.num_vars(); ++i) { + roots.push_back(literal(i, false)); + } + roots[l2.var()] = l1; + vars.push_back(l2.var()); + elim_eqs elim(m_solver); + for (unsigned i = 0; i < vars.size(); ++i) { + std::cout << "var: " << vars[i] << " root: " << roots[vars[i]] << "\n"; + } + elim(roots, vars); + } void bceq::cleanup() { m_solver.del_clauses(m_bin_clauses.begin(), m_bin_clauses.end()); @@ -430,15 +458,23 @@ namespace sat { void bceq::operator()() { if (!m_solver.m_config.m_bcd) return; flet _disable_bcd(m_solver.m_config.m_bcd, false); + flet _disable_min(m_solver.m_config.m_minimize_core, false); + flet _disable_opt(m_solver.m_config.m_optimize_model, false); + flet _bound_maxc(m_solver.m_config.m_max_conflicts, 1500); + use_list ul; solver s(m_solver.m_params, 0); + s.m_config.m_bcd = false; + s.m_config.m_minimize_core = false; + s.m_config.m_optimize_model = false; + s.m_config.m_max_conflicts = 1500; m_use_list = &ul; m_s = &s; ul.init(m_solver.num_vars()); init(); pure_decompose(); post_decompose(); - std::cout << "Decomposed set " << m_L.size() << "\n"; + std::cout << "Decomposed set " << m_L.size() << " rest: " << m_R.size() << "\n"; TRACE("sat", tout << "Decomposed set " << m_L.size() << "\n"; diff --git a/src/sat/sat_bceq.h b/src/sat/sat_bceq.h index 5552fb255..0b05c45cd 100644 --- a/src/sat/sat_bceq.h +++ b/src/sat/sat_bceq.h @@ -65,8 +65,9 @@ namespace sat { uint64 eval_clause(clause const& cls) const; void verify_sweep(); void extract_partition(); - void check_equality(unsigned v1, unsigned v2); - bool is_equiv(literal l1, literal l2); + bool check_equality(unsigned v1, unsigned v2); + bool is_already_equiv(literal l1, literal l2); + void assert_equality(literal l1, literal l2); public: bceq(solver & s); void operator()(); diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index d2a662b64..aff023b22 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -68,7 +68,10 @@ namespace sat { m_restart_factor = p.restart_factor(); m_random_freq = p.random_freq(); - + m_random_seed = p.random_seed(); + if (m_random_seed == 0) + m_random_seed = _p.get_uint("random_seed", 0); + m_burst_search = p.burst_search(); m_max_conflicts = p.max_conflicts(); diff --git a/src/sat/sat_config.h b/src/sat/sat_config.h index 021810f3d..61ab71605 100644 --- a/src/sat/sat_config.h +++ b/src/sat/sat_config.h @@ -53,6 +53,7 @@ namespace sat { unsigned m_restart_initial; double m_restart_factor; // for geometric case double m_random_freq; + unsigned m_random_seed; unsigned m_burst_search; unsigned m_max_conflicts; diff --git a/src/sat/sat_mus.cpp b/src/sat/sat_mus.cpp index a504a5fe2..c66f8ef6f 100644 --- a/src/sat/sat_mus.cpp +++ b/src/sat/sat_mus.cpp @@ -7,7 +7,7 @@ Module Name: Abstract: - Faster MUS extraction based on Belov et.al. HYB (Algorithm 3, 4) + Faster MUS extraction Author: @@ -33,12 +33,27 @@ namespace sat { m_mus.reset(); m_model.reset(); m_best_value = 0; + m_max_restarts = 10; + m_restart = s.m_stats.m_restart; } - void mus::set_core() { - m_core.append(m_mus); + void mus::set_core() { + m_mus.append(m_core); s.m_core.reset(); - s.m_core.append(m_core); + s.m_core.append(m_mus); + } + + void mus::update_model() { + double new_value = s.m_wsls.evaluate_model(s.m_model); + if (m_model.empty()) { + m_model.append(s.m_model); + m_best_value = new_value; + } + else if (m_best_value > new_value) { + m_model.reset(); + m_model.append(s.m_model); + m_best_value = new_value; + } } lbool mus::operator()() { @@ -56,6 +71,9 @@ namespace sat { TRACE("sat", tout << "old core: " << s.get_core() << "\n";); literal_vector& core = get_core(); literal_vector& mus = m_mus; + if (core.size() > 64) { + return mus2(); + } unsigned delta_time = 0; unsigned core_miss = 0; while (!core.empty()) { @@ -75,41 +93,31 @@ namespace sat { literal lit = core.back(); core.pop_back(); - unsigned sz = mus.size(); - mus.append(core); - if (true || core_miss < 2) { - mus.push_back(~lit); // TBD: measure + lbool is_sat; + { + scoped_append _sa(mus, core); + if (true || core_miss < 2) { + mus.push_back(~lit); // TBD: measure + } + is_sat = s.check(mus.size(), mus.c_ptr()); + TRACE("sat", tout << "mus: " << mus << "\n";); } - lbool is_sat = s.check(mus.size(), mus.c_ptr()); - TRACE("sat", tout << "mus: " << mus << "\n";); switch (is_sat) { case l_undef: - mus.resize(sz); core.push_back(lit); set_core(); return l_undef; case l_true: { SASSERT(value_at(lit, s.get_model()) == l_false); - mus.resize(sz); mus.push_back(lit); + update_model(); if (!core.empty()) { // mr(); // TBD: measure } - double new_value = s.m_wsls.evaluate_model(s.m_model); - if (m_model.empty()) { - m_model.append(s.m_model); - m_best_value = new_value; - } - else if (m_best_value > new_value) { - m_model.reset(); - m_model.append(s.m_model); - m_best_value = new_value; - } break; } case l_false: literal_vector const& new_core = s.get_core(); - mus.resize(sz); if (new_core.contains(~lit)) { IF_VERBOSE(2, verbose_stream() << "miss core " << lit << "\n";); ++core_miss; @@ -141,27 +149,93 @@ namespace sat { IF_VERBOSE(2, verbose_stream() << "(sat.mus.new " << core << ")\n";); return l_true; } + // bisection search. lbool mus::mus2() { - literal_vector& core = get_core(); - literal_vector& mus = m_mus; - while (true) { + literal_set core(get_core()); + literal_set support; + lbool is_sat = qx(core, support, false); + s.m_core.reset(); + s.m_core.append(core.to_vector()); + IF_VERBOSE(2, verbose_stream() << "(sat.mus.new " << s.m_core << ")\n";); + return is_sat; + } -#if 0 - unsigned start = 0; - unsigned len = core.size(); - SASSERT(start < len); - unsigned mid = (len-start+1)/2; - mus.append(mid, core.c_ptr() + start); - start = start + mid; -#endif + lbool mus::qx(literal_set& assignment, literal_set& support, bool has_support) { + lbool is_sat = l_true; + if (s.m_stats.m_restart - m_restart > m_max_restarts) { + IF_VERBOSE(1, verbose_stream() << "restart budget exceeded\n";); + return l_true; } - return l_undef; + if (has_support) { + scoped_append _sa(m_mus, support.to_vector()); + is_sat = s.check(m_mus.size(), m_mus.c_ptr()); + switch (is_sat) { + case l_false: { + literal_set core(s.get_core()); + support &= core; + assignment.reset(); + return l_true; + } + case l_undef: + return l_undef; + case l_true: + update_model(); + break; + default: + break; + } + } + if (assignment.size() == 1) { + return l_true; + } + literal_set assign2; + split(assignment, assign2); + support |= assignment; + is_sat = qx(assign2, support, !assignment.empty()); + unsplit(support, assignment); + if (is_sat != l_true) return is_sat; + support |= assign2; + is_sat = qx(assignment, support, !assign2.empty()); + assignment |= assign2; + unsplit(support, assign2); + return is_sat; + } + + void mus::unsplit(literal_set& A, literal_set& B) { + literal_set A1, B1; + literal_set::iterator it = A.begin(), end = A.end(); + for (; it != end; ++it) { + if (B.contains(*it)) { + B1.insert(*it); + } + else { + A1.insert(*it); + } + } + A = A1; + B = B1; + } + + void mus::split(literal_set& lits1, literal_set& lits2) { + unsigned half = lits1.size()/2; + literal_set lits3; + literal_set::iterator it = lits1.begin(), end = lits1.end(); + for (unsigned i = 0; it != end; ++it, ++i) { + if (i < half) { + lits3.insert(*it); + } + else { + lits2.insert(*it); + } + } + lits1 = lits3; } literal_vector& mus::get_core() { m_core.reset(); + m_mus.reset(); literal_vector& core = m_core; core.append(s.get_core()); for (unsigned i = 0; i < core.size(); ++i) { @@ -175,6 +249,11 @@ namespace sat { return core; } + void mus::verify_core(literal_vector const& core) { + lbool is_sat = s.check(core.size(), core.c_ptr()); + IF_VERBOSE(3, verbose_stream() << "core verification: " << is_sat << " " << core << "\n";); + } + void mus::mr() { sls sls(s); literal_vector tabu; diff --git a/src/sat/sat_mus.h b/src/sat/sat_mus.h index ed7b8b13e..944cceffb 100644 --- a/src/sat/sat_mus.h +++ b/src/sat/sat_mus.h @@ -26,6 +26,8 @@ namespace sat { bool m_is_active; model m_model; // model obtained during minimal unsat core double m_best_value; + unsigned m_restart; + unsigned m_max_restarts; solver& s; @@ -38,10 +40,30 @@ namespace sat { private: lbool mus1(); lbool mus2(); + lbool qx(literal_set& assignment, literal_set& support, bool has_support); void mr(); void reset(); void set_core(); + void update_model(); literal_vector & get_core(); + void verify_core(literal_vector const& lits); + void split(literal_set& src, literal_set& dst); + void intersect(literal_set& dst, literal_set const& src); + void unsplit(literal_set& A, literal_set& B); + class scoped_append { + unsigned m_size; + literal_vector& m_lits; + public: + scoped_append(literal_vector& lits, literal_vector const& other): + m_size(lits.size()), + m_lits(lits) { + m_lits.append(other); + } + ~scoped_append() { + m_lits.resize(m_size); + } + + }; }; }; diff --git a/src/sat/sat_params.pyg b/src/sat/sat_params.pyg index 1e2551740..c5ac97b4e 100644 --- a/src/sat/sat_params.pyg +++ b/src/sat/sat_params.pyg @@ -9,6 +9,7 @@ def_module_params('sat', ('restart.initial', UINT, 100, 'initial restart (number of conflicts)'), ('restart.factor', DOUBLE, 1.5, 'restart increment factor for geometric strategy'), ('random_freq', DOUBLE, 0.01, 'frequency of random case splits'), + ('random_seed', UINT, 0, 'random seed'), ('burst_search', UINT, 100, 'number of conflicts before first global simplification'), ('max_conflicts', UINT, UINT_MAX, 'maximum number of conflicts'), ('gc', SYMBOL, 'glue_psm', 'garbage collection strategy: psm, glue, glue_psm, dyn_psm'), diff --git a/src/sat/sat_simplifier.cpp b/src/sat/sat_simplifier.cpp index 937c7735f..285df1e78 100644 --- a/src/sat/sat_simplifier.cpp +++ b/src/sat/sat_simplifier.cpp @@ -21,7 +21,6 @@ Revision History: #include"sat_simplifier.h" #include"sat_simplifier_params.hpp" #include"sat_solver.h" -#include"sat_bceq.h" #include"stopwatch.h" #include"trace.h" @@ -138,8 +137,10 @@ namespace sat { return; if (!m_subsumption && !m_elim_blocked_clauses && !m_resolution) return; + CASSERT("sat_solver", s.check_invariant()); TRACE("before_simplifier", s.display(tout);); + s.m_cleaner(true); m_last_sub_trail_sz = s.m_trail.size(); TRACE("after_cleanup", s.display(tout);); @@ -157,13 +158,6 @@ namespace sat { if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls)) elim_blocked_clauses(); -#if 1 - // experiment is disabled. - if (!learned) { // && m_equality_inference - bceq bc(s); - bc(); - } -#endif if (!learned) m_num_calls++; @@ -188,23 +182,21 @@ namespace sat { bool vars_eliminated = m_num_elim_vars > old_num_elim_vars; - if (!m_need_cleanup) { + if (m_need_cleanup) { + TRACE("after_simplifier", tout << "cleanning watches...\n";); + cleanup_watches(); + cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists); + cleanup_clauses(s.m_clauses, false, vars_eliminated, true); + } + else { TRACE("after_simplifier", tout << "skipping cleanup...\n";); if (vars_eliminated) { // must remove learned clauses with eliminated variables cleanup_clauses(s.m_learned, true, true, learned_in_use_lists); } - CASSERT("sat_solver", s.check_invariant()); - TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); - free_memory(); - return; } - TRACE("after_simplifier", tout << "cleanning watches...\n";); - cleanup_watches(); - cleanup_clauses(s.m_learned, true, vars_eliminated, learned_in_use_lists); - cleanup_clauses(s.m_clauses, false, vars_eliminated, true); - TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); CASSERT("sat_solver", s.check_invariant()); + TRACE("after_simplifier", s.display(tout); tout << "model_converter:\n"; s.m_mc.display(tout);); free_memory(); } @@ -926,11 +918,11 @@ namespace sat { void process(literal l) { TRACE("blocked_clause", tout << "processing: " << l << "\n";); - if (s.is_external(l.var()) || s.was_eliminated(l.var())) { - return; - } model_converter::entry * new_entry = 0; + if (s.is_external(l.var()) || s.was_eliminated(l.var())) + return; { + m_to_remove.reset(); { clause_use_list & occs = s.m_use_list.get(l); @@ -1186,7 +1178,6 @@ namespace sat { continue; m_visited[l2.index()] = false; } - return res; } @@ -1351,6 +1342,7 @@ namespace sat { } TRACE("resolution", tout << "found var to eliminate, before: " << before_clauses << " after: " << after_clauses << "\n";); + // eliminate variable model_converter::entry & mc_entry = s.m_mc.mk(model_converter::ELIM_VAR, v); save_clauses(mc_entry, m_pos_cls); diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index d97ebed46..a2d39d3ea 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -49,7 +49,7 @@ namespace sat { m_qhead(0), m_scope_lvl(0), m_params(p) { - m_config.updt_params(p); + updt_params(p); m_conflicts_since_gc = 0; m_conflicts = 0; m_next_simplify = 0; @@ -483,7 +483,6 @@ namespace sat { void solver::set_conflict(justification c, literal not_l) { if (m_inconsistent) return; - TRACE("sat", tout << "conflict: " << not_l << "\n";); m_inconsistent = true; m_conflict = c; m_not_l = not_l; @@ -960,7 +959,11 @@ namespace sat { m_stopwatch.start(); m_core.reset(); TRACE("sat", display(tout);); - + + if (m_config.m_bcd) { + bceq bc(*this); + bc(); + } } /** @@ -1737,11 +1740,10 @@ namespace sat { // TBD: // apply optional clause minimization by detecting subsumed literals. // initial experiment suggests it has no effect. - m_mus(); // ignore return value on cancelation. m_model.reset(); m_model.append(m_mus.get_model()); - m_model_is_current = true; + m_model_is_current = !m_model.empty(); } } @@ -2356,7 +2358,7 @@ namespace sat { m_asymm_branch.updt_params(p); m_probing.updt_params(p); m_scc.updt_params(p); - m_rand.set_seed(p.get_uint("random_seed", 0)); + m_rand.set_seed(m_config.m_random_seed); } void solver::collect_param_descrs(param_descrs & d) { diff --git a/src/sat/sat_types.h b/src/sat/sat_types.h index db8de94a9..075c88fa1 100644 --- a/src/sat/sat_types.h +++ b/src/sat/sat_types.h @@ -160,6 +160,12 @@ namespace sat { m_in_set[v] = true; m_set.push_back(v); } + + uint_set& operator=(uint_set const& other) { + m_in_set = other.m_in_set; + m_set = other.m_set; + return *this; + } bool contains(unsigned v) const { return v < m_in_set.size() && m_in_set[v] != 0; @@ -177,10 +183,31 @@ namespace sat { m_in_set[v] = false; return v; } + unsigned size() const { return m_set.size(); } iterator begin() const { return m_set.begin(); } iterator end() const { return m_set.end(); } void reset() { m_set.reset(); m_in_set.reset(); } void cleanup() { m_set.finalize(); m_in_set.finalize(); } + uint_set& operator&=(uint_set const& other) { + unsigned j = 0; + for (unsigned i = 0; i < m_set.size(); ++i) { + if (other.contains(m_set[i])) { + m_set[j] = m_set[i]; + ++j; + } + else { + m_in_set[m_set[i]] = false; + } + } + m_set.resize(j); + return *this; + } + uint_set& operator|=(uint_set const& other) { + for (unsigned i = 0; i < other.m_set.size(); ++i) { + insert(other.m_set[i]); + } + return *this; + } }; typedef uint_set bool_var_set; @@ -188,11 +215,44 @@ namespace sat { class literal_set { uint_set m_set; public: + literal_set(literal_vector const& v) { + for (unsigned i = 0; i < v.size(); ++i) insert(v[i]); + } + literal_set() {} + literal_vector to_vector() const { + literal_vector result; + iterator it = begin(), e = end(); + for (; it != e; ++it) { + result.push_back(*it); + } + return result; + } void insert(literal l) { m_set.insert(l.index()); } bool contains(literal l) const { return m_set.contains(l.index()); } bool empty() const { return m_set.empty(); } + unsigned size() const { return m_set.size(); } void reset() { m_set.reset(); } void cleanup() { m_set.cleanup(); } + class iterator { + uint_set::iterator m_it; + public: + iterator(uint_set::iterator it):m_it(it) {} + literal operator*() const { return to_literal(*m_it); } + iterator& operator++() { ++m_it; return *this; } + iterator operator++(int) { iterator tmp = *this; ++m_it; return tmp; } + bool operator==(iterator const& it) const { return m_it == it.m_it; } + bool operator!=(iterator const& it) const { return m_it != it.m_it; } + }; + iterator begin() const { return iterator(m_set.begin()); } + iterator end() const { return iterator(m_set.end()); } + literal_set& operator&=(literal_set const& other) { + m_set &= other.m_set; + return *this; + } + literal_set& operator|=(literal_set const& other) { + m_set |= other.m_set; + return *this; + } }; struct mem_stat { diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index f68df30ab..6b6223385 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1616,6 +1616,8 @@ namespace smt { unsigned qhead = m_qhead; if (!bcp()) return false; + if (m_cancel_flag) + return true; SASSERT(!inconsistent()); propagate_relevancy(qhead); if (inconsistent()) @@ -3950,7 +3952,7 @@ namespace smt { m_fingerprints.display(tout); ); failure fl = get_last_search_failure(); - if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS || fl == THEORY) { + if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS) { // don't generate model. return; } diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 7414eda83..89ce99524 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1274,8 +1274,10 @@ namespace smt { } } while (m_final_check_idx != old_idx); - if (result == FC_DONE && m_found_unsupported_op) + if (result == FC_DONE && m_found_unsupported_op) { + TRACE("arith", tout << "Found unsupported operation\n";); result = FC_GIVEUP; + } return result; } diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index 4b5388062..b600dd3c0 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -1299,8 +1299,10 @@ namespace smt { } tout << "max: " << max << ", min: " << min << "\n";); - if (m_params.m_arith_ignore_int) + if (m_params.m_arith_ignore_int) { + TRACE("arith", tout << "Ignore int: give up\n";); return FC_GIVEUP; + } if (!gcd_test()) return FC_CONTINUE; diff --git a/src/smt/theory_arith_nl.h b/src/smt/theory_arith_nl.h index d02c9e540..6a7017a29 100644 --- a/src/smt/theory_arith_nl.h +++ b/src/smt/theory_arith_nl.h @@ -2314,13 +2314,15 @@ namespace smt { return FC_DONE; } - if (!m_params.m_nl_arith) + if (!m_params.m_nl_arith) { + TRACE("non_linear", tout << "Non-linear is not enabled\n";); return FC_GIVEUP; + } TRACE("process_non_linear", display(tout);); if (m_nl_rounds > m_params.m_nl_arith_rounds) { - TRACE("non_linear", tout << "GIVE UP non linear problem...\n";); + TRACE("non_linear", tout << "GIVEUP non linear problem...\n";); IF_VERBOSE(3, verbose_stream() << "Max. non linear arithmetic rounds. Increase threshold using NL_ARITH_ROUNDS=\n";); return FC_GIVEUP; } diff --git a/src/smt/theory_diff_logic_def.h b/src/smt/theory_diff_logic_def.h index 85f7f948a..b1f3483a9 100644 --- a/src/smt/theory_diff_logic_def.h +++ b/src/smt/theory_diff_logic_def.h @@ -1066,11 +1066,8 @@ template void theory_diff_logic::get_eq_antecedents( theory_var v1, theory_var v2, unsigned timestamp, conflict_resolution & cr) { imp_functor functor(cr); - bool r; - r = m_graph.find_shortest_zero_edge_path(v1, v2, timestamp, functor); - SASSERT(r); - r = m_graph.find_shortest_zero_edge_path(v2, v1, timestamp, functor); - SASSERT(r); + VERIFY(m_graph.find_shortest_zero_edge_path(v1, v2, timestamp, functor)); + VERIFY(m_graph.find_shortest_zero_edge_path(v2, v1, timestamp, functor)); } template diff --git a/src/util/bit_vector.cpp b/src/util/bit_vector.cpp index b8cbdade2..f0e9e9c67 100644 --- a/src/util/bit_vector.cpp +++ b/src/util/bit_vector.cpp @@ -138,9 +138,8 @@ bool bit_vector::operator==(bit_vector const & source) const { bit_vector & bit_vector::operator|=(bit_vector const & source) { if (size() < source.size()) resize(source.size(), false); - unsigned n1 = num_words(); unsigned n2 = source.num_words(); - SASSERT(n2 <= n1); + SASSERT(n2 <= num_words()); unsigned bit_rest = source.m_num_bits % 32; if (bit_rest == 0) { unsigned i = 0; diff --git a/src/util/cmd_context_types.h b/src/util/cmd_context_types.h index b0a0226e8..e334dc0d2 100644 --- a/src/util/cmd_context_types.h +++ b/src/util/cmd_context_types.h @@ -55,12 +55,12 @@ class cmd_exception : public default_exception { } public: cmd_exception(char const * msg):default_exception(msg), m_line(-1), m_pos(-1) {} - cmd_exception(std::string const & msg):default_exception(msg.c_str()), m_line(-1), m_pos(-1) {} - cmd_exception(std::string const & msg, int line, int pos):default_exception(msg.c_str()), m_line(line), m_pos(pos) {} + cmd_exception(std::string const & msg):default_exception(msg), m_line(-1), m_pos(-1) {} + cmd_exception(std::string const & msg, int line, int pos):default_exception(msg), m_line(line), m_pos(pos) {} cmd_exception(char const * msg, symbol const & s): - default_exception(compose(msg,s).c_str()),m_line(-1),m_pos(-1) {} + default_exception(compose(msg,s)),m_line(-1),m_pos(-1) {} cmd_exception(char const * msg, symbol const & s, int line, int pos): - default_exception(compose(msg,s).c_str()),m_line(line),m_pos(pos) {} + default_exception(compose(msg,s)),m_line(line),m_pos(pos) {} bool has_pos() const { return m_line >= 0; } int line() const { SASSERT(has_pos()); return m_line; } diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 8cb6ed4fc..f5785c072 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -120,7 +120,8 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, double value) { // double === mpf(11, 53) COMPILE_TIME_ASSERT(sizeof(double) == 8); - uint64 raw = *reinterpret_cast(&value); + uint64 raw; + memcpy(&raw, &value, sizeof(double)); bool sign = (raw >> 63) != 0; int64 e = ((raw & 0x7FF0000000000000ull) >> 52) - 1023; uint64 s = raw & 0x000FFFFFFFFFFFFFull; @@ -155,7 +156,8 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, float value) { // single === mpf(8, 24) COMPILE_TIME_ASSERT(sizeof(float) == 4); - unsigned int raw = *reinterpret_cast(&value); + unsigned int raw; + memcpy(&raw, &value, sizeof(float)); bool sign = (raw >> 31) != 0; signed int e = ((raw & 0x7F800000) >> 23) - 127; unsigned int s = raw & 0x007FFFFF; @@ -1288,7 +1290,9 @@ double mpf_manager::to_double(mpf const & x) { if (x.sign) raw = raw | 0x8000000000000000ull; - return *reinterpret_cast(&raw); + double ret; + memcpy(&ret, &raw, sizeof(double)); + return ret; } float mpf_manager::to_float(mpf const & x) { @@ -1318,7 +1322,9 @@ float mpf_manager::to_float(mpf const & x) { if (x.sign) raw = raw | 0x80000000; - return *reinterpret_cast(&raw); + float ret; + memcpy(&ret, &raw, sizeof(float)); + return ret; } bool mpf_manager::is_nan(mpf const & x) { @@ -1679,7 +1685,7 @@ void mpf_manager::round(mpf_rounding_mode rm, mpf & o) { TRACE("mpf_dbg", tout << "OVF2 = " << OVF2 << std::endl;); TRACE("mpf_dbg", tout << "o_has_max_exp = " << o_has_max_exp << std::endl;); - if (!OVFen && SIGovf && o_has_max_exp) + if (!OVFen && OVF2) mk_round_inf(rm, o); else { const mpz & p = m_powers2(o.sbits-1); diff --git a/src/util/mpff.cpp b/src/util/mpff.cpp index 892a7fe24..7678a051e 100644 --- a/src/util/mpff.cpp +++ b/src/util/mpff.cpp @@ -43,8 +43,7 @@ mpff_manager::mpff_manager(unsigned prec, unsigned initial_capacity) { for (unsigned i = 0; i < MPFF_NUM_BUFFERS; i++) m_buffers[i].resize(2 * prec, 0); // Reserve space for zero - unsigned zero_sig_idx = m_id_gen.mk(); - SASSERT(zero_sig_idx == 0); + VERIFY(m_id_gen.mk() == 0); set(m_one, 1); } diff --git a/src/util/mpfx.cpp b/src/util/mpfx.cpp index cf6f8338f..c0b3a1936 100644 --- a/src/util/mpfx.cpp +++ b/src/util/mpfx.cpp @@ -38,8 +38,7 @@ mpfx_manager::mpfx_manager(unsigned int_sz, unsigned frac_sz, unsigned initial_c m_buffer0.resize(2*m_total_sz, 0); m_buffer1.resize(2*m_total_sz, 0); m_buffer2.resize(2*m_total_sz, 0); - unsigned zero_sig_idx = m_id_gen.mk(); - SASSERT(zero_sig_idx == 0); + VERIFY(m_id_gen.mk() == 0); set(m_one, 1); } diff --git a/src/util/mpq.cpp b/src/util/mpq.cpp index eda937029..df4d207a6 100644 --- a/src/util/mpq.cpp +++ b/src/util/mpq.cpp @@ -235,6 +235,9 @@ void mpq_manager::set(mpq & a, char const * val) { SASSERT(str[0] - '0' <= 9); exp = (10*exp) + (str[0] - '0'); } + else if ('/' == str[0]) { + throw default_exception("mixing rational/scientific notation"); + } TRACE("mpq_set", tout << "[exp]: " << exp << ", str[0]: " << (str[0] - '0') << std::endl;); ++str; } diff --git a/src/util/util.h b/src/util/util.h index eb24ece13..cbc19b759 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -24,9 +24,6 @@ Revision History: #include #include #include -#ifdef _MSC_VER -#include -#endif #ifndef SIZE_MAX #define SIZE_MAX std::numeric_limits::max() @@ -99,9 +96,7 @@ COMPILE_TIME_ASSERT(sizeof(unsigned) == 4); // Return the number of 1 bits in v. static inline unsigned get_num_1bits(unsigned v) { -#ifdef _MSC_VER - return __popcnt(v); -#elif defined(__GNUC__) +#ifdef __GNUC__ return __builtin_popcount(v); #else #ifdef Z3DEBUG