3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-22 13:53:39 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-02-05 19:36:07 -08:00
parent f1c8754527
commit 3ef05ced2f
9 changed files with 103 additions and 133 deletions

View file

@ -1,11 +1,12 @@
def_module_params('lp', def_module_params('lp',
export=True, export=True,
description='Parameters for the LP arithmetic solver core',
params=( params=(
('rep_freq', UINT, 0, 'the report frequency, in how many iterations print the cost and other info '), ('rep_freq', UINT, 0, 'the report frequency, in how many iterations print the cost and other info '),
('min', BOOL, False, 'minimize cost'), ('min', BOOL, False, 'minimize cost'),
('print_stats', BOOL, False, 'print statistic'), ('print_stats', BOOL, False, 'print statistic'),
('simplex_strategy', UINT, 0, 'simplex strategy for the solver'), ('simplex_strategy', UINT, 0, 'simplex strategy for the solver'),
('enable_hnf', BOOL, True, 'enable hnf cuts'), ('enable_hnf', BOOL, True, 'enable hnf (Hermite Normal Form) cuts'),
('bprop_on_pivoted_rows', BOOL, True, 'propagate bounds on rows changed by the pivot operation'), ('bprop_on_pivoted_rows', BOOL, True, 'propagate bounds on rows changed by the pivot operation'),
('nla', BOOL, False, 'call nonlinear integer solver with incremental linearization'), ('nla', BOOL, False, 'call nonlinear integer solver with incremental linearization'),
('print_ext_var_names', BOOL, False, 'print external variable names') ('print_ext_var_names', BOOL, False, 'print external variable names')

View file

@ -1,5 +1,6 @@
def_module_params('nla', def_module_params('nla',
export=True, export=True,
description='Parameters for non-linear arithmetic solving',
params=( params=(
('order', BOOL, True, 'run order lemmas'), ('order', BOOL, True, 'run order lemmas'),
('tangents', BOOL, True, 'run tangent lemmas'), ('tangents', BOOL, True, 'run tangent lemmas'),

View file

@ -455,7 +455,8 @@ void asserted_formulas::propagate_values() {
unsigned num_prop = 0; unsigned num_prop = 0;
unsigned num_iterations = 0; unsigned num_iterations = 0;
while (!inconsistent() && ++num_iterations < 2) { unsigned delta_prop = m_formulas.size();
while (!inconsistent() && m_formulas.size()/20 < delta_prop) {
m_expr2depth.reset(); m_expr2depth.reset();
m_scoped_substitution.push(); m_scoped_substitution.push();
unsigned prop = num_prop; unsigned prop = num_prop;
@ -478,9 +479,7 @@ void asserted_formulas::propagate_values() {
m_scoped_substitution.pop(1); m_scoped_substitution.pop(1);
flush_cache(); flush_cache();
TRACE("propagate_values", tout << "after:\n"; display(tout);); TRACE("propagate_values", tout << "after:\n"; display(tout););
if (num_prop == prop) { delta_prop = prop - num_prop;
break;
}
num_prop = prop; num_prop = prop;
} }
TRACE("asserted_formulas", tout << num_prop << "\n";); TRACE("asserted_formulas", tout << num_prop << "\n";);
@ -493,7 +492,6 @@ unsigned asserted_formulas::propagate_values(unsigned i) {
expr_ref new_n(m); expr_ref new_n(m);
proof_ref new_pr(m); proof_ref new_pr(m);
m_rewriter(n, new_n, new_pr); m_rewriter(n, new_n, new_pr);
TRACE("propagate_values", tout << n << "\n" << new_n << "\n";);
if (m.proofs_enabled()) { if (m.proofs_enabled()) {
proof * pr = m_formulas[i].get_proof(); proof * pr = m_formulas[i].get_proof();
new_pr = m.mk_modus_ponens(pr, new_pr); new_pr = m.mk_modus_ponens(pr, new_pr);
@ -504,7 +502,7 @@ unsigned asserted_formulas::propagate_values(unsigned i) {
m_inconsistent = true; m_inconsistent = true;
} }
update_substitution(new_n, new_pr); update_substitution(new_n, new_pr);
return n != new_n ? 1 : 0; return (n != new_n) ? 1 : 0;
} }
bool asserted_formulas::update_substitution(expr* n, proof* pr) { bool asserted_formulas::update_substitution(expr* n, proof* pr) {

View file

@ -1804,7 +1804,7 @@ namespace smt {
} }
} }
bool_var var; bool_var var;
lbool phase; lbool phase = l_undef;
m_case_split_queue->next_case_split(var, phase); m_case_split_queue->next_case_split(var, phase);
if (var == null_bool_var) { if (var == null_bool_var) {
@ -1836,13 +1836,13 @@ namespace smt {
// assigning a quantifier to false is equivalent to make it irrelevant. // assigning a quantifier to false is equivalent to make it irrelevant.
phase = l_false; phase = l_false;
} }
literal l(var, false);
if (phase != l_undef) { if (phase != l_undef) {
is_pos = phase == l_true; is_pos = phase == l_true;
} }
else { else {
bool_var_data & d = m_bdata[var]; bool_var_data & d = m_bdata[var];
if (d.try_true_first()) { if (d.try_true_first()) {
is_pos = true; is_pos = true;
} }
@ -1851,21 +1851,25 @@ namespace smt {
case PS_THEORY: case PS_THEORY:
if (m_phase_cache_on && d.m_phase_available) { if (m_phase_cache_on && d.m_phase_available) {
is_pos = m_bdata[var].m_phase; is_pos = m_bdata[var].m_phase;
break;
} }
else if (!m_phase_cache_on && d.is_theory_atom()) { if (!m_phase_cache_on && d.is_theory_atom()) {
theory * th = m_theories.get_plugin(d.get_theory()); theory * th = m_theories.get_plugin(d.get_theory());
lbool ph = th->get_phase(var); lbool th_phase = th->get_phase(var);
if (ph != l_undef) { if (th_phase != l_undef) {
is_pos = ph == l_true; is_pos = th_phase == l_true;
} break;
else {
is_pos = m_phase_default;
} }
} }
else { if (m_lit_occs[l.index()] == 0) {
TRACE("phase_selection", tout << "setting to false\n";); is_pos = false;
is_pos = m_phase_default; break;
} }
if (m_lit_occs[(~l).index()] == 0) {
is_pos = true;
break;
}
is_pos = m_phase_default;
break; break;
case PS_CACHING: case PS_CACHING:
case PS_CACHING_CONSERVATIVE: case PS_CACHING_CONSERVATIVE:
@ -1889,8 +1893,7 @@ namespace smt {
is_pos = (m_random() % 2 == 0); is_pos = (m_random() % 2 == 0);
break; break;
case PS_OCCURRENCE: { case PS_OCCURRENCE: {
literal l(var); is_pos = m_lit_occs[l.index()] > m_lit_occs[(~l).index()];
is_pos = m_lit_occs[l.index()].size() > m_lit_occs[(~l).index()].size();
break; break;
} }
default: default:
@ -1900,10 +1903,9 @@ namespace smt {
} }
} }
TRACE("decide", tout << "case split " << (is_pos?"pos":"neg") << " p" << var << "\n" if (!is_pos) l.neg();
<< "activity: " << get_activity(var) << "\n";); TRACE("decide", tout << "case split " << l << "\n" << "activity: " << get_activity(var) << "\n";);
assign(l, b_justification::mk_axiom(), true);
assign(literal(var, !is_pos), b_justification::mk_axiom(), true);
return true; return true;
} }
@ -1989,19 +1991,18 @@ namespace smt {
/** /**
\brief Update the index used for backward subsumption. \brief Update the index used for backward subsumption.
*/ */
void context::remove_lit_occs(clause * cls) { void context::remove_lit_occs(clause const& cls) {
unsigned num_lits = cls->get_num_literals(); int nbv = get_num_bool_vars();
for (unsigned i = 0; i < num_lits; i++) { for (literal l : cls) {
literal l = cls->get_literal(i); if (l.var() < nbv)
m_lit_occs[l.index()].erase(cls); dec_ref(l);
} }
} }
void context::remove_cls_occs(clause * cls) { void context::remove_cls_occs(clause * cls) {
remove_watch_literal(cls, 0); remove_watch_literal(cls, 0);
remove_watch_literal(cls, 1); remove_watch_literal(cls, 1);
if (lit_occs_enabled()) remove_lit_occs(*cls);
remove_lit_occs(cls);
} }
/** /**
@ -2254,19 +2255,9 @@ namespace smt {
} }
} }
unsigned num = cls->get_num_literals(); unsigned num = cls->get_num_literals();
if (lit_occs_enabled()) { remove_lit_occs(*cls);
for (unsigned j = 0; j < num; j++) {
literal l = cls->get_literal(j);
if (l.var() < static_cast<int>(num_bool_vars)) {
// This boolean variable was not deleted during backtracking
//
// So, remove it from lit_occs.
m_lit_occs[l.index()].erase(cls);
}
}
}
unsigned ilvl = 0; unsigned ilvl = 0;
(void)ilvl; (void)ilvl;
@ -2297,8 +2288,7 @@ namespace smt {
add_watch_literal(cls, 0); add_watch_literal(cls, 0);
add_watch_literal(cls, 1); add_watch_literal(cls, 1);
if (lit_occs_enabled()) add_lit_occs(*cls);
add_lit_occs(cls);
literal l1 = cls->get_literal(0); literal l1 = cls->get_literal(0);
literal l2 = cls->get_literal(1); literal l2 = cls->get_literal(1);
@ -2342,7 +2332,6 @@ namespace smt {
v.reset(); v.reset();
} }
CASSERT("reinit_clauses", check_clauses(m_lemmas)); CASSERT("reinit_clauses", check_clauses(m_lemmas));
CASSERT("reinit_clauses", check_lit_occs());
TRACE("reinit_clauses_bug", display_watch_lists(tout);); TRACE("reinit_clauses_bug", display_watch_lists(tout););
} }
@ -2498,23 +2487,24 @@ namespace smt {
unsigned i = 2; unsigned i = 2;
unsigned j = i; unsigned j = i;
bool is_taut = false;
for(; i < s; i++) { for(; i < s; i++) {
literal l = cls[i]; literal l = cls[i];
switch(get_assignment(l)) { switch(get_assignment(l)) {
case l_false: case l_false:
if (m.proofs_enabled()) if (m.proofs_enabled())
simp_lits.push_back(~l); simp_lits.push_back(~l);
if (lit_occs_enabled()) dec_ref(l);
m_lit_occs[l.index()].erase(&cls);
break; break;
case l_true:
is_taut = true;
// fallthrough
case l_undef: case l_undef:
if (i != j) { if (i != j) {
cls.swap_lits(i, j); cls.swap_lits(i, j);
} }
j++; j++;
break; break;
case l_true:
return true;
} }
} }
@ -2524,6 +2514,10 @@ namespace smt {
SASSERT(j >= 2); SASSERT(j >= 2);
} }
if (is_taut) {
return true;
}
if (m.proofs_enabled() && !simp_lits.empty()) { if (m.proofs_enabled() && !simp_lits.empty()) {
SASSERT(m_scope_lvl == m_base_lvl); SASSERT(m_scope_lvl == m_base_lvl);
justification * js = cls.get_justification(); justification * js = cls.get_justification();

View file

@ -170,7 +170,7 @@ namespace smt {
ptr_vector<expr> m_bool_var2expr; // bool_var -> expr ptr_vector<expr> m_bool_var2expr; // bool_var -> expr
signed_char_vector m_assignment; //!< mapping literal id -> assignment lbool signed_char_vector m_assignment; //!< mapping literal id -> assignment lbool
vector<watch_list> m_watches; //!< per literal vector<watch_list> m_watches; //!< per literal
vector<clause_set> m_lit_occs; //!< index for backward subsumption unsigned_vector m_lit_occs; //!< occurrence count of literals
svector<bool_var_data> m_bdata; //!< mapping bool_var -> data svector<bool_var_data> m_bdata; //!< mapping bool_var -> data
svector<double> m_activity; svector<double> m_activity;
clause_vector m_aux_clauses; clause_vector m_aux_clauses;
@ -637,8 +637,6 @@ namespace smt {
void remove_watch_literal(clause * cls, unsigned idx); void remove_watch_literal(clause * cls, unsigned idx);
void remove_lit_occs(clause * cls);
void remove_cls_occs(clause * cls); void remove_cls_occs(clause * cls);
void del_clause(bool log, clause * cls); void del_clause(bool log, clause * cls);
@ -841,9 +839,13 @@ namespace smt {
void mk_ite_cnstr(app * n); void mk_ite_cnstr(app * n);
bool lit_occs_enabled() const { return m_fparams.m_phase_selection==PS_OCCURRENCE; } void dec_ref(literal l) { SASSERT(m_lit_occs[l.index()] > 0); m_lit_occs[l.index()]--; }
void add_lit_occs(clause * cls); void inc_ref(literal l) { m_lit_occs[l.index()]++; }
void remove_lit_occs(clause const& cls);
void add_lit_occs(clause const& cls);
public: public:
void ensure_internalized(expr* e); void ensure_internalized(expr* e);
@ -1423,9 +1425,6 @@ namespace smt {
bool check_missing_diseq_conflict() const; bool check_missing_diseq_conflict() const;
bool check_lit_occs(literal l) const;
bool check_lit_occs() const;
#endif #endif
// ----------------------------------- // -----------------------------------
// //
@ -1571,6 +1570,8 @@ namespace smt {
void get_guessed_literals(expr_ref_vector & result); void get_guessed_literals(expr_ref_vector & result);
bool split_binary(app* o, expr*& a, expr_ref& b, expr_ref& c);
void internalize_assertion(expr * n, proof * pr, unsigned generation); void internalize_assertion(expr * n, proof * pr, unsigned generation);
void internalize_proxies(expr_ref_vector const& asms, vector<std::pair<expr*,expr_ref>>& asm2proxy); void internalize_proxies(expr_ref_vector const& asms, vector<std::pair<expr*,expr_ref>>& asm2proxy);

View file

@ -32,10 +32,8 @@ namespace smt {
bool context::check_clause(clause const * cls) const { bool context::check_clause(clause const * cls) const {
SASSERT(is_watching_clause(~cls->get_literal(0), cls)); SASSERT(is_watching_clause(~cls->get_literal(0), cls));
SASSERT(is_watching_clause(~cls->get_literal(1), cls)); SASSERT(is_watching_clause(~cls->get_literal(1), cls));
if (lit_occs_enabled()) { for (literal l : *cls) {
for (literal l : *cls) { SASSERT(m_lit_occs[l.index()] > 0);
SASSERT(m_lit_occs[l.index()].contains(const_cast<clause*>(cls)));
}
} }
return true; return true;
} }
@ -84,37 +82,6 @@ namespace smt {
return true; return true;
} }
bool context::check_lit_occs(literal l) const {
clause_set const & v = m_lit_occs[l.index()];
for (clause * cls : v) {
unsigned num = cls->get_num_literals();
unsigned i = 0;
for (; i < num; i++)
if (cls->get_literal(i) == l)
break;
CTRACE("lit_occs", !(i < num), tout << i << " " << num << "\n"; display_literal(tout, l); tout << "\n";
display_clause(tout, cls); tout << "\n";
tout << "l: " << l.index() << " cls: ";
for (unsigned j = 0; j < num; j++) {
tout << cls->get_literal(j).index() << " ";
}
tout << "\n";
display_clause_detail(tout, cls); tout << "\n";);
SASSERT(i < num);
}
return true;
}
bool context::check_lit_occs() const {
if (lit_occs_enabled()) {
unsigned num_lits = get_num_bool_vars() * 2;
for (unsigned l_idx = 0; l_idx < num_lits; ++l_idx) {
check_lit_occs(to_literal(l_idx));
}
}
return true;
}
bool context::check_enode(enode * n) const { bool context::check_enode(enode * n) const {
SASSERT(n->check_invariant()); SASSERT(n->check_invariant());
bool is_true_eq = n->is_true_eq(); bool is_true_eq = n->is_true_eq();
@ -136,7 +103,6 @@ namespace smt {
} }
bool context::check_invariant() const { bool context::check_invariant() const {
check_lit_occs();
check_bin_watch_lists(); check_bin_watch_lists();
check_clauses(m_aux_clauses); check_clauses(m_aux_clauses);
check_clauses(m_lemmas); check_clauses(m_lemmas);

View file

@ -182,8 +182,30 @@ namespace smt {
} }
} }
bool context::split_binary(app* o, expr*& a, expr_ref& b, expr_ref& c) {
expr* x = nullptr, *y = nullptr, *ny = nullptr, *z = nullptr, *u = nullptr;
if (m.is_or(o, x, y) &&
m.is_not(y, ny) &&
m.is_or(ny, z, u)) {
a = x;
b = m.is_not(z, z) ? z : m.mk_not(z);
c = m.is_not(u, u) ? u : m.mk_not(u);
return true;
}
if (m.is_or(o, y, x) &&
m.is_not(y, ny) &&
m.is_or(ny, z, u)) {
a = x;
b = m.is_not(z, z) ? z : m.mk_not(z);
c = m.is_not(u, u) ? u : m.mk_not(u);
return true;
}
return false;
}
#define DEEP_EXPR_THRESHOLD 1024 #define DEEP_EXPR_THRESHOLD 1024
/** /**
\brief Internalize an expression asserted into the logical context using the given proof as a justification. \brief Internalize an expression asserted into the logical context using the given proof as a justification.
@ -226,6 +248,19 @@ namespace smt {
} }
case OP_OR: { case OP_OR: {
literal_buffer lits; literal_buffer lits;
expr* a = nullptr;
expr_ref b(m), c(m);
// perform light-weight rewriting on clauses.
if (!relevancy() && split_binary(to_app(n), a, b, c)) {
internalize(a, true);
internalize(b, true);
internalize(c, true);
literal lits2[2] = { get_literal(a), get_literal(b) };
literal lits3[2] = { get_literal(a), get_literal(c) };
mk_root_clause(2, lits2, pr);
mk_root_clause(2, lits3, pr);
break;
}
for (expr * arg : *to_app(n)) { for (expr * arg : *to_app(n)) {
internalize(arg, true); internalize(arg, true);
lits.push_back(get_literal(arg)); lits.push_back(get_literal(arg));
@ -882,11 +917,9 @@ namespace smt {
SASSERT(m_assignment.size() == m_watches.size()); SASSERT(m_assignment.size() == m_watches.size());
m_watches[l.index()] .reset(); m_watches[l.index()] .reset();
m_watches[not_l.index()] .reset(); m_watches[not_l.index()] .reset();
if (lit_occs_enabled()) { m_lit_occs.reserve(aux, 0);
m_lit_occs.reserve(aux); m_lit_occs[l.index()] = 0;
m_lit_occs[l.index()] .reset(); m_lit_occs[not_l.index()] = 0;
m_lit_occs[not_l.index()] .reset();
}
bool_var_data & data = m_bdata[v]; bool_var_data & data = m_bdata[v];
unsigned iscope_lvl = m_scope_lvl; // record when the boolean variable was internalized. unsigned iscope_lvl = m_scope_lvl; // record when the boolean variable was internalized.
data.init(iscope_lvl); data.init(iscope_lvl);
@ -1357,11 +1390,14 @@ namespace smt {
if (j && !j->in_region()) if (j && !j->in_region())
m_justifications.push_back(j); m_justifications.push_back(j);
assign(lits[0], j); assign(lits[0], j);
inc_ref(lits[0]);
return nullptr; return nullptr;
case 2: case 2:
if (use_binary_clause_opt(lits[0], lits[1], lemma)) { if (use_binary_clause_opt(lits[0], lits[1], lemma)) {
literal l1 = lits[0]; literal l1 = lits[0];
literal l2 = lits[1]; literal l2 = lits[1];
inc_ref(l1);
inc_ref(l2);
m_watches[(~l1).index()].insert_literal(l2); m_watches[(~l1).index()].insert_literal(l2);
m_watches[(~l2).index()].insert_literal(l1); m_watches[(~l2).index()].insert_literal(l1);
if (get_assignment(l2) == l_false) { if (get_assignment(l2) == l_false) {
@ -1425,8 +1461,7 @@ namespace smt {
assign(cls->get_literal(0), b_justification(cls)); assign(cls->get_literal(0), b_justification(cls));
} }
if (lit_occs_enabled()) add_lit_occs(*cls);
add_lit_occs(cls);
TRACE("add_watch_literal_bug", display_clause_detail(tout, cls);); TRACE("add_watch_literal_bug", display_clause_detail(tout, cls););
TRACE("mk_clause_result", display_clause_detail(tout, cls);); TRACE("mk_clause_result", display_clause_detail(tout, cls););
@ -1435,9 +1470,9 @@ namespace smt {
}} }}
} }
void context::add_lit_occs(clause * cls) { void context::add_lit_occs(clause const& cls) {
for (literal l : *cls) { for (literal l : cls) {
m_lit_occs[l.index()].insert(cls); inc_ref(l);
} }
} }

View file

@ -37,7 +37,7 @@ namespace smt {
// try first sequential with a low conflict budget to make super easy problems cheap // try first sequential with a low conflict budget to make super easy problems cheap
ctx.get_fparams().m_max_conflicts = std::min(thread_max_conflicts, 40u); ctx.get_fparams().m_max_conflicts = std::min(thread_max_conflicts, 40u);
result = ctx.check(asms.size(), asms.c_ptr()); result = ctx.check(asms.size(), asms.c_ptr());
if (result != l_undef || ctx.m_num_conflicts < max_conflicts) { if (result != l_undef || (result == l_undef && ctx.m_num_conflicts < ctx.get_fparams().m_max_conflicts)) {
return result; return result;
} }
#else #else

View file

@ -2189,32 +2189,6 @@ public:
nla::lemma m_lemma; nla::lemma m_lemma;
// lp::lar_term mk_term(nla::polynomial const& poly) {
// lp::lar_term term;
// for (auto const& mon : poly) {
// SASSERT(!mon.empty());
// if (mon.size() == 1) {
// term.add_var(mon[0]);
// }
// else {
// // create the expression corresponding to the product.
// // internalize it.
// // extract the theory var representing the product.
// // convert the theory var back to lpvar
// expr_ref_vector mul(m);
// for (lpvar v : mon) {
// theory_var w = lp().local_to_external(v);
// mul.push_back(get_enode(w)->get_owner());
// }
// app_ref t(a.mk_mul(mul.size(), mul.c_ptr()), m);
// VERIFY(internalize_term(t));
// theory_var w = ctx().get_enode(t)->get_th_var(get_id());
// term.add_var(lp().external_to_local(w));
// }
// }
// return term;
// }
void false_case_of_check_nla() { void false_case_of_check_nla() {
literal_vector core; literal_vector core;
for (auto const& ineq : m_lemma.ineqs()) { for (auto const& ineq : m_lemma.ineqs()) {