mirror of
https://github.com/Z3Prover/z3
synced 2025-06-21 13:23:39 +00:00
adding stubs to find fixed variables
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
ef943347ee
commit
c48dc69050
3 changed files with 112 additions and 58 deletions
|
@ -1382,11 +1382,62 @@ namespace lp {
|
||||||
// the lower/upper bound is not strict.
|
// the lower/upper bound is not strict.
|
||||||
// the LP obtained by making the bound strict is infeasible
|
// the LP obtained by making the bound strict is infeasible
|
||||||
// -> the column has to be fixed
|
// -> the column has to be fixed
|
||||||
bool is_fixed_at_bound(column_index const& j) {
|
bool lar_solver::is_fixed_at_bound(column_index const& j) {
|
||||||
NOT_IMPLEMENTED_YET();
|
if (column_is_fixed(j))
|
||||||
|
return false;
|
||||||
|
mpq val;
|
||||||
|
if (!has_value(j, val))
|
||||||
|
return false;
|
||||||
|
lp::lconstraint_kind k;
|
||||||
|
if (column_has_upper_bound(j) &&
|
||||||
|
get_upper_bound(j).x == val) {
|
||||||
|
verbose_stream() << "check upper " << j << "\n";
|
||||||
|
push();
|
||||||
|
if (column_is_int(j))
|
||||||
|
k = LE, val -= 1;
|
||||||
|
else
|
||||||
|
k = LT;
|
||||||
|
auto ci = mk_var_bound(j, k, val);
|
||||||
|
update_column_type_and_bound(j, k, val, ci);
|
||||||
|
auto st = find_feasible_solution();
|
||||||
|
pop(1);
|
||||||
|
return st == lp_status::INFEASIBLE;
|
||||||
|
}
|
||||||
|
if (column_has_lower_bound(j) &&
|
||||||
|
get_lower_bound(j).x == val) {
|
||||||
|
verbose_stream() << "check lower " << j << "\n";
|
||||||
|
push();
|
||||||
|
if (column_is_int(j))
|
||||||
|
k = GE, val += 1;
|
||||||
|
else
|
||||||
|
k = GT;
|
||||||
|
auto ci = mk_var_bound(j, k, val);
|
||||||
|
update_column_type_and_bound(j, k, val, ci);
|
||||||
|
auto st = find_feasible_solution();
|
||||||
|
pop(1);
|
||||||
|
return st == lp_status::INFEASIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lar_solver::has_fixed_at_bound() {
|
||||||
|
verbose_stream() << "has-fixed-at-bound\n";
|
||||||
|
unsigned num_fixed = 0;
|
||||||
|
for (unsigned j = 0; j < A_r().m_columns.size(); ++j) {
|
||||||
|
auto ci = column_index(j);
|
||||||
|
if (is_fixed_at_bound(ci)) {
|
||||||
|
++num_fixed;
|
||||||
|
verbose_stream() << "fixed " << j << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
verbose_stream() << "num fixed " << num_fixed << "\n";
|
||||||
|
if (num_fixed > 0)
|
||||||
|
find_feasible_solution();
|
||||||
|
return num_fixed > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// below is the initialization functionality of lar_solver
|
// below is the initialization functionality of lar_solver
|
||||||
|
|
||||||
bool lar_solver::strategy_is_undecided() const {
|
bool lar_solver::strategy_is_undecided() const {
|
||||||
|
|
|
@ -367,6 +367,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_fixed_at_bound(column_index const& j);
|
bool is_fixed_at_bound(column_index const& j);
|
||||||
|
bool has_fixed_at_bound();
|
||||||
|
|
||||||
bool is_fixed(column_index const& j) const { return column_is_fixed(j); }
|
bool is_fixed(column_index const& j) const { return column_is_fixed(j); }
|
||||||
inline column_index to_column_index(unsigned v) const { return column_index(external_to_column_index(v)); }
|
inline column_index to_column_index(unsigned v) const { return column_index(external_to_column_index(v)); }
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "ast/ast_ll_pp.h"
|
#include "ast/ast_ll_pp.h"
|
||||||
#include "util/cancel_eh.h"
|
#include "util/cancel_eh.h"
|
||||||
#include "util/scoped_timer.h"
|
#include "util/scoped_timer.h"
|
||||||
|
#include "util/distribution.h"
|
||||||
|
|
||||||
typedef lp::var_index lpvar;
|
typedef lp::var_index lpvar;
|
||||||
|
|
||||||
|
@ -1646,6 +1647,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned m_final_check_idx = 0;
|
unsigned m_final_check_idx = 0;
|
||||||
|
distribution m_dist { 0 };
|
||||||
|
|
||||||
final_check_status final_check_eh() {
|
final_check_status final_check_eh() {
|
||||||
if (propagate_core())
|
if (propagate_core())
|
||||||
|
@ -1657,34 +1659,53 @@ 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, result = FC_DONE;
|
bool giveup = false;
|
||||||
m_final_check_idx = 0; // remove to experiment.
|
final_check_status st = FC_DONE;
|
||||||
|
// m_final_check_idx = 0; // remove to experiment.
|
||||||
unsigned old_idx = m_final_check_idx;
|
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));
|
||||||
|
|
||||||
|
// if (lp().has_fixed_at_bound()) // explain and propagate.
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
distribution dist(++m_final_check_idx);
|
m_dist.reset();
|
||||||
|
m_dist.push(0, 1);
|
||||||
|
m_dist.push(1, 1);
|
||||||
|
m_dist.push(2, 1);
|
||||||
|
|
||||||
dist.add(0, 2);
|
for (auto idx : m_dist) {
|
||||||
dist.add(1, 1);
|
|
||||||
dist.add(1, 1);
|
|
||||||
|
|
||||||
for (auto idx : dist) {
|
|
||||||
if (!m.inc())
|
if (!m.inc())
|
||||||
return FC_GIVEUP;
|
return FC_GIVEUP;
|
||||||
|
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (assume_eqs())
|
||||||
|
st = FC_CONTINUE;
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
st = check_nla();
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
st = check_lia();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (st) {
|
||||||
|
case FC_DONE:
|
||||||
|
break;
|
||||||
|
case FC_CONTINUE:
|
||||||
|
return st;
|
||||||
|
case FC_GIVEUP:
|
||||||
|
giveup = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#else
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!m.inc())
|
if (!m.inc())
|
||||||
|
@ -1696,22 +1717,10 @@ public:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (assume_eqs())
|
if (assume_eqs())
|
||||||
st = FC_CONTINUE;
|
st = FC_CONTINUE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
switch (check_nla()) {
|
st = 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;
|
break;
|
||||||
}
|
}
|
||||||
m_final_check_idx = (m_final_check_idx + 1) % 3;
|
m_final_check_idx = (m_final_check_idx + 1) % 3;
|
||||||
|
@ -1721,14 +1730,15 @@ public:
|
||||||
case FC_CONTINUE:
|
case FC_CONTINUE:
|
||||||
return st;
|
return st;
|
||||||
case FC_GIVEUP:
|
case FC_GIVEUP:
|
||||||
result = st;
|
giveup = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (old_idx != m_final_check_idx);
|
while (old_idx != m_final_check_idx);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (result == FC_GIVEUP)
|
if (giveup)
|
||||||
return result;
|
return FC_GIVEUP;
|
||||||
for (expr* e : m_not_handled) {
|
for (expr* e : m_not_handled) {
|
||||||
if (!ctx().is_relevant(e))
|
if (!ctx().is_relevant(e))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1963,14 +1973,12 @@ public:
|
||||||
TRACE("arith", tout << "canceled\n";);
|
TRACE("arith", tout << "canceled\n";);
|
||||||
return FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
}
|
}
|
||||||
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 FC_GIVEUP;
|
return FC_GIVEUP;
|
||||||
|
|
||||||
switch (cr) {
|
switch (cr) {
|
||||||
case lp::lia_move::sat:
|
case lp::lia_move::sat:
|
||||||
lia_check = FC_DONE;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lp::lia_move::branch: {
|
case lp::lia_move::branch: {
|
||||||
|
@ -1993,9 +2001,8 @@ 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 = FC_CONTINUE;
|
|
||||||
++m_stats.m_branch;
|
++m_stats.m_branch;
|
||||||
break;
|
return FC_CONTINUE;
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
@ -2021,8 +2028,7 @@ 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 = FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case lp::lia_move::conflict:
|
case lp::lia_move::conflict:
|
||||||
TRACE("arith", tout << "conflict\n";);
|
TRACE("arith", tout << "conflict\n";);
|
||||||
|
@ -2031,18 +2037,19 @@ public:
|
||||||
return FC_CONTINUE;
|
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 = FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
break;
|
|
||||||
case lp::lia_move::continue_with_check:
|
case lp::lia_move::continue_with_check:
|
||||||
lia_check = FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if (lia_check != l_false && !check_idiv_bounds())
|
if (!check_idiv_bounds())
|
||||||
return FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
|
|
||||||
return lia_check;
|
if (assume_eqs())
|
||||||
|
return FC_CONTINUE;
|
||||||
|
|
||||||
|
return FC_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nla::lemma m_lemma;
|
nla::lemma m_lemma;
|
||||||
|
@ -2079,36 +2086,31 @@ public:
|
||||||
set_conflict_or_lemma(core, false);
|
set_conflict_or_lemma(core, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool check_nla_continue() {
|
final_check_status check_nla_continue() {
|
||||||
m_a1 = nullptr; m_a2 = nullptr;
|
m_a1 = nullptr; m_a2 = nullptr;
|
||||||
lbool r = m_nla->check(m_nla_lemma_vector);
|
lbool r = m_nla->check(m_nla_lemma_vector);
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case l_false: {
|
case l_false:
|
||||||
for (const nla::lemma & l : m_nla_lemma_vector)
|
for (const nla::lemma & l : m_nla_lemma_vector)
|
||||||
false_case_of_check_nla(l);
|
false_case_of_check_nla(l);
|
||||||
break;
|
return FC_CONTINUE;
|
||||||
}
|
|
||||||
case l_true:
|
case l_true:
|
||||||
if (assume_eqs()) {
|
return assume_eqs()? FC_CONTINUE: FC_DONE;
|
||||||
return l_false;
|
default:
|
||||||
}
|
return FC_GIVEUP;
|
||||||
break;
|
|
||||||
case l_undef:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool check_nla() {
|
final_check_status check_nla() {
|
||||||
if (!m.inc()) {
|
if (!m.inc()) {
|
||||||
TRACE("arith", tout << "canceled\n";);
|
TRACE("arith", tout << "canceled\n";);
|
||||||
return l_undef;
|
return FC_GIVEUP;
|
||||||
}
|
}
|
||||||
CTRACE("arith",!m_nla, tout << "no nla\n";);
|
CTRACE("arith",!m_nla, tout << "no nla\n";);
|
||||||
if (!m_nla)
|
if (!m_nla)
|
||||||
return l_true;
|
return FC_DONE;
|
||||||
if (!m_nla->need_check())
|
if (!m_nla->need_check())
|
||||||
return l_true;
|
return FC_DONE;
|
||||||
return check_nla_continue();
|
return check_nla_continue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue