mirror of
https://github.com/Z3Prover/z3
synced 2025-06-19 20:33:38 +00:00
add instrumentation to theory_lra for shuffling final check
This commit is contained in:
parent
3029fb24a1
commit
d2e3e4895e
2 changed files with 145 additions and 58 deletions
|
@ -248,9 +248,8 @@ branch y_i >= ceil(y0_i) is impossible.
|
||||||
|
|
||||||
bool hnf_cutter::init_terms_for_hnf_cut() {
|
bool hnf_cutter::init_terms_for_hnf_cut() {
|
||||||
clear();
|
clear();
|
||||||
for (unsigned i = 0; i < lra.terms().size() && !is_full(); i++) {
|
for (unsigned i = 0; i < lra.terms().size() && !is_full(); i++)
|
||||||
try_add_term_to_A_for_hnf(tv::term(i));
|
try_add_term_to_A_for_hnf(tv::term(i));
|
||||||
}
|
|
||||||
return hnf_has_var_with_non_integral_value();
|
return hnf_has_var_with_non_integral_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1539,10 +1539,14 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool assume_eqs() {
|
bool assume_eqs() {
|
||||||
|
if (delayed_assume_eqs())
|
||||||
|
return true;
|
||||||
|
|
||||||
TRACE("arith", display(tout););
|
TRACE("arith", display(tout););
|
||||||
random_update();
|
random_update();
|
||||||
m_model_eqs.reset();
|
m_model_eqs.reset();
|
||||||
|
|
||||||
theory_var sz = static_cast<theory_var>(th.get_num_vars());
|
theory_var sz = static_cast<theory_var>(th.get_num_vars());
|
||||||
unsigned old_sz = m_assume_eq_candidates.size();
|
unsigned old_sz = m_assume_eq_candidates.size();
|
||||||
unsigned num_candidates = 0;
|
unsigned num_candidates = 0;
|
||||||
|
@ -1639,6 +1643,8 @@ public:
|
||||||
return FC_GIVEUP;
|
return FC_GIVEUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned m_final_check_idx = 0;
|
||||||
|
|
||||||
final_check_status final_check_eh() {
|
final_check_status final_check_eh() {
|
||||||
if (propagate_core())
|
if (propagate_core())
|
||||||
return FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
|
@ -1649,44 +1655,79 @@ public:
|
||||||
if (!lp().is_feasible() || lp().has_changed_columns()) {
|
if (!lp().is_feasible() || lp().has_changed_columns()) {
|
||||||
is_sat = make_feasible();
|
is_sat = make_feasible();
|
||||||
}
|
}
|
||||||
final_check_status st = FC_DONE;
|
final_check_status st = FC_DONE, result = FC_DONE;
|
||||||
|
m_final_check_idx = 0; // remove to experiment.
|
||||||
|
unsigned old_idx = m_final_check_idx;
|
||||||
|
|
||||||
switch (is_sat) {
|
switch (is_sat) {
|
||||||
case l_true:
|
case l_true:
|
||||||
TRACE("arith", display(tout));
|
TRACE("arith", display(tout));
|
||||||
|
|
||||||
switch (check_lia()) {
|
#if 0
|
||||||
case l_true:
|
distribution dist(++m_final_check_idx);
|
||||||
break;
|
|
||||||
case l_false:
|
|
||||||
return FC_CONTINUE;
|
|
||||||
case l_undef:
|
|
||||||
TRACE("arith", tout << "check-lia giveup\n";);
|
|
||||||
if (ctx().get_fparams().m_arith_ignore_int)
|
|
||||||
return FC_GIVEUP;
|
|
||||||
st = FC_CONTINUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (check_nla()) {
|
dist.add(0, 2);
|
||||||
case l_true:
|
dist.add(1, 1);
|
||||||
break;
|
dist.add(1, 1);
|
||||||
case l_false:
|
|
||||||
return FC_CONTINUE;
|
for (auto idx : dist) {
|
||||||
case l_undef:
|
if (!m.inc())
|
||||||
TRACE("arith", tout << "check-nra giveup\n";);
|
return FC_GIVEUP;
|
||||||
st = FC_GIVEUP;
|
|
||||||
break;
|
switch (idx) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (delayed_assume_eqs()) {
|
do {
|
||||||
++m_stats.m_assume_eqs;
|
if (!m.inc())
|
||||||
return FC_CONTINUE;
|
return FC_GIVEUP;
|
||||||
}
|
|
||||||
if (assume_eqs()) {
|
switch (m_final_check_idx) {
|
||||||
++m_stats.m_assume_eqs;
|
case 0:
|
||||||
return FC_CONTINUE;
|
if (assume_eqs()) {
|
||||||
|
++m_stats.m_assume_eqs;
|
||||||
|
st = FC_CONTINUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
st = check_lia();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
switch (check_nla()) {
|
||||||
|
case l_true:
|
||||||
|
st = FC_DONE;
|
||||||
|
break;
|
||||||
|
case l_false:
|
||||||
|
st = FC_CONTINUE;
|
||||||
|
break;
|
||||||
|
case l_undef:
|
||||||
|
TRACE("arith", tout << "check-nra giveup\n";);
|
||||||
|
st = FC_GIVEUP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_final_check_idx = (m_final_check_idx + 1) % 3;
|
||||||
|
switch (st) {
|
||||||
|
case FC_DONE:
|
||||||
|
break;
|
||||||
|
case FC_CONTINUE:
|
||||||
|
return st;
|
||||||
|
case FC_GIVEUP:
|
||||||
|
result = st;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while (old_idx != m_final_check_idx);
|
||||||
|
|
||||||
|
if (result == FC_GIVEUP)
|
||||||
|
return result;
|
||||||
for (expr* e : m_not_handled) {
|
for (expr* e : m_not_handled) {
|
||||||
if (!ctx().is_relevant(e))
|
if (!ctx().is_relevant(e))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1914,21 +1955,21 @@ public:
|
||||||
visitor.display_asserts(out, fmls, true);
|
visitor.display_asserts(out, fmls, true);
|
||||||
out << "(check-sat)\n";
|
out << "(check-sat)\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool check_lia() {
|
final_check_status check_lia() {
|
||||||
TRACE("arith",);
|
TRACE("arith",);
|
||||||
if (!m.inc()) {
|
if (!m.inc()) {
|
||||||
TRACE("arith", tout << "canceled\n";);
|
TRACE("arith", tout << "canceled\n";);
|
||||||
return l_undef;
|
return FC_CONTINUE;
|
||||||
}
|
}
|
||||||
lbool lia_check = l_undef;
|
final_check_status lia_check = FC_GIVEUP;
|
||||||
auto cr = m_lia->check(&m_explanation);
|
auto cr = m_lia->check(&m_explanation);
|
||||||
if (cr != lp::lia_move::sat && ctx().get_fparams().m_arith_ignore_int)
|
if (cr != lp::lia_move::sat && ctx().get_fparams().m_arith_ignore_int)
|
||||||
return l_undef;
|
return FC_GIVEUP;
|
||||||
|
|
||||||
switch (cr) {
|
switch (cr) {
|
||||||
case lp::lia_move::sat:
|
case lp::lia_move::sat:
|
||||||
lia_check = l_true;
|
lia_check = FC_DONE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lp::lia_move::branch: {
|
case lp::lia_move::branch: {
|
||||||
|
@ -1951,13 +1992,13 @@ public:
|
||||||
// TBD: ctx().force_phase(ctx().get_literal(b));
|
// TBD: ctx().force_phase(ctx().get_literal(b));
|
||||||
// at this point we have a new unassigned atom that the
|
// at this point we have a new unassigned atom that the
|
||||||
// SAT core assigns a value to
|
// SAT core assigns a value to
|
||||||
lia_check = l_false;
|
lia_check = FC_CONTINUE;
|
||||||
++m_stats.m_branch;
|
++m_stats.m_branch;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lp::lia_move::cut: {
|
case lp::lia_move::cut: {
|
||||||
if (ctx().get_fparams().m_arith_ignore_int)
|
if (ctx().get_fparams().m_arith_ignore_int)
|
||||||
return l_undef;
|
return FC_GIVEUP;
|
||||||
TRACE("arith", tout << "cut\n";);
|
TRACE("arith", tout << "cut\n";);
|
||||||
++m_stats.m_gomory_cuts;
|
++m_stats.m_gomory_cuts;
|
||||||
// m_explanation implies term <= k
|
// m_explanation implies term <= k
|
||||||
|
@ -1979,26 +2020,26 @@ public:
|
||||||
ctx().display_lemma_as_smt_problem(tout << "new cut:\n", m_core.size(), m_core.data(), m_eqs.size(), m_eqs.data(), lit);
|
ctx().display_lemma_as_smt_problem(tout << "new cut:\n", m_core.size(), m_core.data(), m_eqs.size(), m_eqs.data(), lit);
|
||||||
display(tout););
|
display(tout););
|
||||||
assign(lit, m_core, m_eqs, m_params);
|
assign(lit, m_core, m_eqs, m_params);
|
||||||
lia_check = l_false;
|
lia_check = FC_CONTINUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case lp::lia_move::conflict:
|
case lp::lia_move::conflict:
|
||||||
TRACE("arith", tout << "conflict\n";);
|
TRACE("arith", tout << "conflict\n";);
|
||||||
// ex contains unsat core
|
// ex contains unsat core
|
||||||
set_conflict();
|
set_conflict();
|
||||||
return l_false;
|
return FC_CONTINUE;
|
||||||
case lp::lia_move::undef:
|
case lp::lia_move::undef:
|
||||||
TRACE("arith", tout << "lia undef\n";);
|
TRACE("arith", tout << "lia undef\n";);
|
||||||
lia_check = l_undef;
|
lia_check = FC_CONTINUE;
|
||||||
break;
|
break;
|
||||||
case lp::lia_move::continue_with_check:
|
case lp::lia_move::continue_with_check:
|
||||||
lia_check = l_undef;
|
lia_check = FC_CONTINUE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if (lia_check != l_false && !check_idiv_bounds())
|
if (lia_check != l_false && !check_idiv_bounds())
|
||||||
return l_false;
|
return FC_CONTINUE;
|
||||||
|
|
||||||
return lia_check;
|
return lia_check;
|
||||||
}
|
}
|
||||||
|
@ -2188,7 +2229,6 @@ public:
|
||||||
set_evidence(j, m_core, m_eqs);
|
set_evidence(j, m_core, m_eqs);
|
||||||
m_explanation.add_pair(j, v);
|
m_explanation.add_pair(j, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void propagate_bounds_with_lp_solver() {
|
void propagate_bounds_with_lp_solver() {
|
||||||
if (!should_propagate())
|
if (!should_propagate())
|
||||||
|
@ -2202,13 +2242,16 @@ public:
|
||||||
|
|
||||||
if (is_infeasible()) {
|
if (is_infeasible()) {
|
||||||
get_infeasibility_explanation_and_set_conflict();
|
get_infeasibility_explanation_and_set_conflict();
|
||||||
|
// verbose_stream() << "unsat\n";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
unsigned count = 0, prop = 0;
|
||||||
for (auto& ib : m_bp.ibounds()) {
|
for (auto& ib : m_bp.ibounds()) {
|
||||||
m.inc();
|
m.inc();
|
||||||
if (ctx().inconsistent())
|
if (ctx().inconsistent())
|
||||||
break;
|
break;
|
||||||
propagate_lp_solver_bound(ib);
|
++prop;
|
||||||
|
count += propagate_lp_solver_bound(ib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2229,12 +2272,14 @@ public:
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void propagate_lp_solver_bound(const lp::implied_bound& be) {
|
|
||||||
|
#if 0
|
||||||
|
unsigned propagate_lp_solver_bound_dry_run(const lp::implied_bound& be) {
|
||||||
lpvar vi = be.m_j;
|
lpvar vi = be.m_j;
|
||||||
theory_var v = lp().local_to_external(vi);
|
theory_var v = lp().local_to_external(vi);
|
||||||
|
|
||||||
if (v == null_theory_var)
|
if (v == null_theory_var)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
TRACE("arith", tout << "v" << v << " " << be.kind() << " " << be.m_bound << "\n";);
|
TRACE("arith", tout << "v" << v << " " << be.kind() << " " << be.m_bound << "\n";);
|
||||||
|
|
||||||
|
@ -2242,20 +2287,58 @@ public:
|
||||||
|
|
||||||
if (m_unassigned_bounds[v] == 0 && !should_refine_bounds()) {
|
if (m_unassigned_bounds[v] == 0 && !should_refine_bounds()) {
|
||||||
TRACE("arith", tout << "return\n";);
|
TRACE("arith", tout << "return\n";);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
lp_bounds const& bounds = m_bounds[v];
|
lp_bounds const& bounds = m_bounds[v];
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
unsigned count = 0;
|
||||||
for (unsigned i = 0; i < bounds.size(); ++i) {
|
for (unsigned i = 0; i < bounds.size(); ++i) {
|
||||||
api_bound* b = bounds[i];
|
api_bound* b = bounds[i];
|
||||||
if (ctx().get_assignment(b->get_lit()) != l_undef) {
|
if (ctx().get_assignment(b->get_lit()) != l_undef)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
literal lit = is_bound_implied(be.kind(), be.m_bound, *b);
|
literal lit = is_bound_implied(be.kind(), be.m_bound, *b);
|
||||||
if (lit == null_literal) {
|
if (lit == null_literal)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
TRACE("arith", tout << lit << " bound: " << *b << " first: " << first << "\n";);
|
TRACE("arith", tout << lit << " bound: " << *b << " first: " << first << "\n";);
|
||||||
|
ctx().display_literal_verbose(verbose_stream() << "miss ", lit) << "\n";
|
||||||
|
display(verbose_stream());
|
||||||
|
TRACE("arith", ctx().display_literal_verbose(tout << "miss ", lit) << "\n");
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned propagate_lp_solver_bound(const lp::implied_bound& be) {
|
||||||
|
lpvar vi = be.m_j;
|
||||||
|
theory_var v = lp().local_to_external(vi);
|
||||||
|
|
||||||
|
if (v == null_theory_var)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TRACE("arith", tout << "v" << v << " " << be.kind() << " " << be.m_bound << "\n";);
|
||||||
|
|
||||||
|
reserve_bounds(v);
|
||||||
|
|
||||||
|
if (m_unassigned_bounds[v] == 0 && !should_refine_bounds()) {
|
||||||
|
TRACE("arith", tout << "return\n";);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lp_bounds const& bounds = m_bounds[v];
|
||||||
|
bool first = true;
|
||||||
|
unsigned count = 0;
|
||||||
|
for (unsigned i = 0; i < bounds.size(); ++i) {
|
||||||
|
api_bound* b = bounds[i];
|
||||||
|
if (ctx().get_assignment(b->get_lit()) != l_undef)
|
||||||
|
continue;
|
||||||
|
literal lit = is_bound_implied(be.kind(), be.m_bound, *b);
|
||||||
|
if (lit == null_literal)
|
||||||
|
continue;
|
||||||
|
TRACE("arith", tout << lit << " bound: " << *b << " first: " << first << "\n";);
|
||||||
|
|
||||||
|
++count;
|
||||||
|
|
||||||
lp().settings().stats().m_num_of_implied_bounds ++;
|
lp().settings().stats().m_num_of_implied_bounds ++;
|
||||||
if (first) {
|
if (first) {
|
||||||
|
@ -2274,6 +2357,8 @@ public:
|
||||||
display_evidence(tout, m_explanation);
|
display_evidence(tout, m_explanation);
|
||||||
lp().print_implied_bound(be, tout);
|
lp().print_implied_bound(be, tout);
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
DEBUG_CODE(
|
DEBUG_CODE(
|
||||||
for (auto& lit : m_core) {
|
for (auto& lit : m_core) {
|
||||||
VERIFY(ctx().get_assignment(lit) == l_true);
|
VERIFY(ctx().get_assignment(lit) == l_true);
|
||||||
|
@ -2283,7 +2368,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_refine_bounds() && first)
|
if (should_refine_bounds() && first)
|
||||||
refine_bound(v, be);
|
refine_bound(v, be);
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void refine_bound(theory_var v, const lp::implied_bound& be) {
|
void refine_bound(theory_var v, const lp::implied_bound& be) {
|
||||||
|
@ -2907,7 +2994,7 @@ public:
|
||||||
propagate_eqs(b.tv(), ci, k, b, value.get_rational());
|
propagate_eqs(b.tv(), ci, k, b, value.get_rational());
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if (propagation_mode() != BP_NONE)
|
if (should_propagate())
|
||||||
lp().mark_rows_for_bound_prop(b.tv().id());
|
lp().mark_rows_for_bound_prop(b.tv().id());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3928,5 +4015,6 @@ void theory_lra::setup() {
|
||||||
}
|
}
|
||||||
template class lp::lp_bound_propagator<smt::theory_lra::imp>;
|
template class lp::lp_bound_propagator<smt::theory_lra::imp>;
|
||||||
template void lp::lar_solver::propagate_bounds_for_touched_rows<smt::theory_lra::imp>(lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
template void lp::lar_solver::propagate_bounds_for_touched_rows<smt::theory_lra::imp>(lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
||||||
|
template void lp::lar_solver::check_missed_propagations<smt::theory_lra::imp>(lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
||||||
template void lp::lar_solver::explain_implied_bound<smt::theory_lra::imp>(const lp::implied_bound&, lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
template void lp::lar_solver::explain_implied_bound<smt::theory_lra::imp>(const lp::implied_bound&, lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
||||||
template void lp::lar_solver::calculate_implied_bounds_for_row<smt::theory_lra::imp>(unsigned int, lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
template unsigned lp::lar_solver::calculate_implied_bounds_for_row<smt::theory_lra::imp>(unsigned int, lp::lp_bound_propagator<smt::theory_lra::imp>&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue