mirror of
https://github.com/Z3Prover/z3
synced 2025-07-21 11:52:05 +00:00
debug tighten_bounds
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
f4f199faf7
commit
e4e4e8c7b8
2 changed files with 94 additions and 51 deletions
|
@ -176,6 +176,7 @@ namespace lp {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class dioph_eq::imp {
|
class dioph_eq::imp {
|
||||||
|
int deb_count = 0;
|
||||||
// This class represents a term with an added constant number c, in form sum
|
// This class represents a term with an added constant number c, in form sum
|
||||||
// {x_i*a_i} + c.
|
// {x_i*a_i} + c.
|
||||||
class term_o : public lar_term {
|
class term_o : public lar_term {
|
||||||
|
@ -252,9 +253,8 @@ namespace lp {
|
||||||
|
|
||||||
std::ostream& print_bounds(std::ostream& out) {
|
std::ostream& print_bounds(std::ostream& out) {
|
||||||
out << "bounds:\n";
|
out << "bounds:\n";
|
||||||
for (unsigned v = 0; v < m_var_register.size(); ++v) {
|
for (unsigned v = 0; v < lra.column_count(); ++v) {
|
||||||
unsigned j = m_var_register.local_to_external(v);
|
lra.print_column_info(v, out);
|
||||||
lra.print_column_info(j, out);
|
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -1080,9 +1080,10 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entries_are_ok() {
|
bool entries_are_ok() {
|
||||||
|
if (lra.settings().get_cancel_flag()) return true;
|
||||||
for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++) {
|
for (unsigned ei = 0; ei < m_e_matrix.row_count(); ei++) {
|
||||||
if (entry_invariant(ei) == false) {
|
if (entry_invariant(ei) == false) {
|
||||||
TRACE("dioph_deb_eq", tout << "bad entry:"; print_entry(ei, tout););
|
TRACE("dio", tout << "bad entry:"; print_entry(ei, tout););
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (belongs_to_f(ei)) {
|
if (belongs_to_f(ei)) {
|
||||||
|
@ -1478,15 +1479,27 @@ namespace lp {
|
||||||
lra.print_explanation(out, lra.flatten(b.m_dep));
|
lra.print_explanation(out, lra.flatten(b.m_dep));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// h is the entry that is ready to be moved to S
|
// h is the entry that is ready to be moved to S
|
||||||
lia_move tighten_bounds(unsigned h) {
|
lia_move tighten_bounds(unsigned h) {
|
||||||
|
SASSERT(entry_invariant(h));
|
||||||
protected_queue q;
|
protected_queue q;
|
||||||
copy_row_to_espace_in_lar_indices(h);
|
copy_row_to_espace(h);
|
||||||
|
remove_fresh_from_espace();
|
||||||
|
|
||||||
|
// change m_espace indices from local to lar_solver: have to restore for clear to work
|
||||||
|
for (auto & p: m_espace.m_data) {
|
||||||
|
SASSERT(!var_is_fresh(p.m_j));
|
||||||
|
p.m_j = local_to_lar_solver(p.m_j);
|
||||||
|
|
||||||
|
}
|
||||||
TRACE("dio", tout << "bp on entry:"; print_entry(h, tout) << std::endl;);
|
TRACE("dio", tout << "bp on entry:"; print_entry(h, tout) << std::endl;);
|
||||||
|
|
||||||
m_prop_bounds.clear();
|
m_prop_bounds.clear();
|
||||||
bound_analyzer_on_row<term_with_index, dioph_eq::imp>::analyze_row(m_espace, impq(-m_sum_of_fixed[h]), *this);
|
bound_analyzer_on_row<term_with_index, dioph_eq::imp>::analyze_row(m_espace, impq(-m_sum_of_fixed[h]), *this);
|
||||||
|
//restore m_espace to local variables
|
||||||
|
for (auto & p: m_espace.m_data) p.m_j = lar_solver_to_local(p.m_j);
|
||||||
|
|
||||||
TRACE("dio", tout << "prop_bounds:\n";
|
TRACE("dio", tout << "prop_bounds:\n";
|
||||||
for (auto& pb: m_prop_bounds) {
|
for (auto& pb: m_prop_bounds) {
|
||||||
print_prop_bound(pb, tout);
|
print_prop_bound(pb, tout);
|
||||||
|
@ -1508,8 +1521,7 @@ namespace lp {
|
||||||
auto st = lra.find_feasible_solution();
|
auto st = lra.find_feasible_solution();
|
||||||
if (st == lp_status::INFEASIBLE) {
|
if (st == lp_status::INFEASIBLE) {
|
||||||
lra.get_infeasibility_explanation(m_infeas_explanation);
|
lra.get_infeasibility_explanation(m_infeas_explanation);
|
||||||
TRACE("dio", tout << "inf explanation:\n"; lra.print_explanation(tout, m_infeas_explanation););
|
TRACE("dio", tout << "inf explanation:\n"; lra.print_explanation(tout, m_infeas_explanation);); return lia_move::conflict;
|
||||||
return lia_move::conflict;
|
|
||||||
}
|
}
|
||||||
TRACE("dio", tout << "lra is feasible\n";);
|
TRACE("dio", tout << "lra is feasible\n";);
|
||||||
|
|
||||||
|
@ -1870,11 +1882,21 @@ namespace lp {
|
||||||
lra.stats().m_dio_rewrite_conflicts++;
|
lra.stats().m_dio_rewrite_conflicts++;
|
||||||
return lia_move::conflict;
|
return lia_move::conflict;
|
||||||
}
|
}
|
||||||
|
lia_move r;
|
||||||
while (rewrite_eqs(f_vector)) {}
|
do {
|
||||||
|
r = rewrite_eqs(f_vector);
|
||||||
|
if (lra.settings().get_cancel_flag()) return lia_move::undef;
|
||||||
|
if (r == lia_move::continue_with_check) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
|
if (r == lia_move::conflict) {
|
||||||
if (m_conflict_index != UINT_MAX) {
|
if (m_conflict_index != UINT_MAX) {
|
||||||
lra.stats().m_dio_rewrite_conflicts++;
|
lra.stats().m_dio_rewrite_conflicts++;
|
||||||
|
} else {
|
||||||
|
lra.stats().m_dio_bound_propagation_conflicts++;
|
||||||
|
}
|
||||||
return lia_move::conflict;
|
return lia_move::conflict;
|
||||||
}
|
}
|
||||||
TRACE("dio", print_int_inf_vars(tout) << "\n";
|
TRACE("dio", print_int_inf_vars(tout) << "\n";
|
||||||
|
@ -2412,10 +2434,14 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entry_invariant(unsigned ei) const {
|
bool entry_invariant(unsigned ei) const {
|
||||||
|
if (lra.settings().get_cancel_flag())
|
||||||
|
return true;
|
||||||
for (const auto& p : m_e_matrix.m_rows[ei]) {
|
for (const auto& p : m_e_matrix.m_rows[ei]) {
|
||||||
if (!p.coeff().is_int()) {
|
if (!p.coeff().is_int()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (var_is_fresh(p.var()))
|
||||||
|
continue;
|
||||||
unsigned j = local_to_lar_solver(p.var());
|
unsigned j = local_to_lar_solver(p.var());
|
||||||
if (is_fixed(j))
|
if (is_fixed(j))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2424,8 +2450,9 @@ namespace lp {
|
||||||
bool ret =
|
bool ret =
|
||||||
term_to_lar_solver(remove_fresh_vars(get_term_from_entry(ei))) ==
|
term_to_lar_solver(remove_fresh_vars(get_term_from_entry(ei))) ==
|
||||||
fix_vars(open_ml(m_l_matrix.m_rows[ei]));
|
fix_vars(open_ml(m_l_matrix.m_rows[ei]));
|
||||||
|
if (!ret) {
|
||||||
CTRACE("dioph_deb_eq", !ret,
|
enable_trace("dio");
|
||||||
|
CTRACE("dio", !ret,
|
||||||
{
|
{
|
||||||
tout << "get_term_from_entry(" << ei << "):";
|
tout << "get_term_from_entry(" << ei << "):";
|
||||||
print_term_o(get_term_from_entry(ei), tout) << std::endl;
|
print_term_o(get_term_from_entry(ei), tout) << std::endl;
|
||||||
|
@ -2439,7 +2466,7 @@ namespace lp {
|
||||||
tout << "rs:";
|
tout << "rs:";
|
||||||
print_term_o(fix_vars(open_ml(m_l_matrix.m_rows[ei])), tout) << std::endl;
|
print_term_o(fix_vars(open_ml(m_l_matrix.m_rows[ei])), tout) << std::endl;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2454,7 +2481,7 @@ namespace lp {
|
||||||
while (!q.empty()) {
|
while (!q.empty()) {
|
||||||
unsigned xt = q.pop_front(); // xt is a fresh var
|
unsigned xt = q.pop_front(); // xt is a fresh var
|
||||||
const lar_term& fresh_t = m_fresh_k2xt_terms.get_by_val(xt).first;
|
const lar_term& fresh_t = m_fresh_k2xt_terms.get_by_val(xt).first;
|
||||||
TRACE("dio", print_lar_term_L(fresh_t, tout););
|
TRACE("dio_remove_fresh", print_lar_term_L(fresh_t, tout););
|
||||||
SASSERT(fresh_t.get_coeff(xt).is_minus_one());
|
SASSERT(fresh_t.get_coeff(xt).is_minus_one());
|
||||||
if (!t.contains(xt))
|
if (!t.contains(xt))
|
||||||
continue;
|
continue;
|
||||||
|
@ -2513,12 +2540,11 @@ namespace lp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// it clears the row, and puts the term in the work vector
|
void copy_row_to_espace(unsigned ei) {
|
||||||
void copy_row_to_espace_in_lar_indices(unsigned ei) {
|
|
||||||
m_espace.clear();
|
m_espace.clear();
|
||||||
auto& row = m_e_matrix.m_rows[ei];
|
auto& row = m_e_matrix.m_rows[ei];
|
||||||
for (const auto& cell : row)
|
for (const auto& cell : row)
|
||||||
m_espace.add(cell.coeff(), local_to_lar_solver(cell.var()));
|
m_espace.add(cell.coeff(), cell.var());
|
||||||
}
|
}
|
||||||
|
|
||||||
// it clears the row, and puts the term in the work vector
|
// it clears the row, and puts the term in the work vector
|
||||||
|
@ -2604,10 +2630,20 @@ namespace lp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (print_column_info) {
|
if (print_column_info) {
|
||||||
|
bool has_fresh;
|
||||||
|
for (const auto& p : m_e_matrix[i] ) {
|
||||||
|
if (var_is_fresh(p.var())) {
|
||||||
|
has_fresh = true;
|
||||||
|
tout << "has fresh var:" << p.var() << "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_fresh) {
|
||||||
for (const auto& p : get_term_from_entry(i)) {
|
for (const auto& p : get_term_from_entry(i)) {
|
||||||
lra.print_column_info(local_to_lar_solver(p.var()), out) << "\n";
|
lra.print_column_info(local_to_lar_solver(p.var()), out) << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
out << "}\n";
|
out << "}\n";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -2630,27 +2666,38 @@ namespace lp {
|
||||||
std::vector<unsigned> deb_upd;
|
std::vector<unsigned> deb_upd;
|
||||||
for (unsigned j : m_new_fixed_columns) {
|
for (unsigned j : m_new_fixed_columns) {
|
||||||
SASSERT(is_fixed(j));
|
SASSERT(is_fixed(j));
|
||||||
j = lar_solver_to_local(j);
|
unsigned lj = lar_solver_to_local(j);
|
||||||
for (auto & c : m_e_matrix.m_columns[j]) {
|
auto & lj_col = m_e_matrix.m_columns[lj];
|
||||||
|
while (lj_col.size()) {
|
||||||
|
auto & c = lj_col.back();
|
||||||
unsigned ei = c.var();
|
unsigned ei = c.var();
|
||||||
m_sum_of_fixed[ei] += lra.get_lower_bound(j).x;
|
TRACE("dio", tout << "entry was:"; print_entry(ei, tout) << "\n");
|
||||||
unsigned offset_in_row = c.offset();
|
deb_upd.push_back(ei);
|
||||||
m_e_matrix.remove_element(ei, m_e_matrix.m_rows[ei][offset_in_row]);
|
auto& row_el = m_e_matrix.m_rows[ei][c.offset()];
|
||||||
|
m_sum_of_fixed[ei] += row_el.coeff() * lra.get_lower_bound(j).x;
|
||||||
|
m_e_matrix.remove_element(ei, row_el);
|
||||||
|
TRACE("dio", tout << "entry became:"; print_entry(ei, tout) << "\n");
|
||||||
|
|
||||||
if (belongs_to_s(ei)) {
|
if (belongs_to_s(ei)) {
|
||||||
remove_from_S(ei);
|
remove_from_S(ei);
|
||||||
f_vector.push_back(ei);
|
f_vector.push_back(ei);
|
||||||
}
|
}
|
||||||
|
if (m_e_matrix.m_rows[ei].size() == 0 && !m_sum_of_fixed[ei].is_zero()) {
|
||||||
|
m_conflict_index = ei; // have to continue to finish the update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SASSERT(entries_are_ok());
|
}
|
||||||
|
m_new_fixed_columns.reset();
|
||||||
|
for (unsigned ei: deb_upd) {
|
||||||
|
SASSERT(entry_invariant(ei));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is the step 6 or 7 of the algorithm
|
// this is the step 6 or 7 of the algorithm
|
||||||
// returns true if an equlity was rewritten and false otherwise
|
// returns lia_move::continue_with_check of the progress has been made, lia_move::undef if done, and lia_move::conflict if a conflict ha been found
|
||||||
bool rewrite_eqs(std_vector<unsigned>& f_vector) {
|
lia_move rewrite_eqs(std_vector<unsigned>& f_vector) {
|
||||||
if (f_vector.size() == 0)
|
if (f_vector.size() == 0)
|
||||||
return false;
|
return lia_move::undef;
|
||||||
unsigned h = -1, kh = 0; // the initial value of kh does not matter, assign to remove the warning
|
unsigned h = -1, kh = 0; // the initial value of kh does not matter, assign to remove the warning
|
||||||
unsigned n = 0; // number of choices for a fresh variable
|
unsigned n = 0; // number of choices for a fresh variable
|
||||||
mpq min_ahk;
|
mpq min_ahk;
|
||||||
|
@ -2666,7 +2713,7 @@ namespace lp {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_conflict_index = ei;
|
m_conflict_index = ei;
|
||||||
return false;
|
return lia_move::conflict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2674,7 +2721,7 @@ namespace lp {
|
||||||
mpq gcd;
|
mpq gcd;
|
||||||
if (!normalize_e_by_gcd(ei, gcd)) {
|
if (!normalize_e_by_gcd(ei, gcd)) {
|
||||||
m_conflict_index = ei;
|
m_conflict_index = ei;
|
||||||
return false;
|
return lia_move::conflict;
|
||||||
}
|
}
|
||||||
if (!gcd.is_one())
|
if (!gcd.is_one())
|
||||||
ahk /= gcd;
|
ahk /= gcd;
|
||||||
|
@ -2699,18 +2746,20 @@ namespace lp {
|
||||||
if (min_ahk.is_one() && h_markovich_number == 0)
|
if (min_ahk.is_one() && h_markovich_number == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (h == UINT_MAX) return false;
|
if (h == UINT_MAX) return lia_move::undef;
|
||||||
SASSERT(h == f_vector[ih]);
|
SASSERT(h == f_vector[ih]);
|
||||||
if (min_ahk.is_one()) {
|
if (min_ahk.is_one()) {
|
||||||
TRACE("dioph_eq", tout << "push to S:\n"; print_entry(h, tout););
|
TRACE("dioph_eq", tout << "push to S:\n"; print_entry(h, tout););
|
||||||
SASSERT(m_new_fixed_columns.size() == 0);
|
SASSERT(m_new_fixed_columns.size() == 0);
|
||||||
if (tighten_bounds(h) == lia_move::conflict){
|
if (tighten_bounds(h) == lia_move::conflict){
|
||||||
return false;
|
return lia_move::conflict;
|
||||||
}
|
}
|
||||||
if (m_new_fixed_columns.size()) { // Need to update all entries containing the new fixed columns.
|
if (m_new_fixed_columns.size()) { // Need to update all entries containing the new fixed columns.
|
||||||
// The previous calculations in the loop might be invalid
|
// The previous calculations in the loop might be invalid
|
||||||
update_entries_with_new_fixed(f_vector);
|
update_entries_with_new_fixed(f_vector);
|
||||||
return true;
|
if (m_conflict_index != static_cast<unsigned>(-1))
|
||||||
|
return lia_move::conflict;
|
||||||
|
return lia_move::continue_with_check;
|
||||||
}
|
}
|
||||||
move_entry_from_f_to_s(kh, h);
|
move_entry_from_f_to_s(kh, h);
|
||||||
eliminate_var_in_f(h, kh, kh_sign);
|
eliminate_var_in_f(h, kh, kh_sign);
|
||||||
|
@ -2719,9 +2768,11 @@ namespace lp {
|
||||||
}
|
}
|
||||||
f_vector.pop_back();
|
f_vector.pop_back();
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
fresh_var_step(h, kh, min_ahk * mpq(kh_sign));
|
fresh_var_step(h, kh, min_ahk * mpq(kh_sign));
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
return lia_move::continue_with_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -93,15 +93,8 @@ public:
|
||||||
operator T () const { return m_matrix.get_elem(m_row, m_col); }
|
operator T () const { return m_matrix.get_elem(m_row, m_col); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ref_row {
|
|
||||||
const static_matrix & m_matrix;
|
|
||||||
unsigned m_row;
|
|
||||||
public:
|
|
||||||
ref_row(const static_matrix & m, unsigned row): m_matrix(m), m_row(row) {}
|
|
||||||
T operator[](unsigned col) const { return m_matrix.get_elem(m_row, col); }
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
const auto & operator[](unsigned i) const { return m_rows[i]; }
|
||||||
|
|
||||||
const T & get_val(const column_cell & c) const {
|
const T & get_val(const column_cell & c) const {
|
||||||
return m_rows[c.var()][c.offset()].coeff();
|
return m_rows[c.var()][c.offset()].coeff();
|
||||||
|
@ -457,7 +450,6 @@ public:
|
||||||
return column_container(j, *this);
|
return column_container(j, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref_row operator[](unsigned i) const { return ref_row(*this, i);}
|
|
||||||
typedef T coefftype;
|
typedef T coefftype;
|
||||||
typedef X argtype;
|
typedef X argtype;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue