mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 13:28:47 +00:00
roll back in maximize_term if the integrality is broken
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
f21b60a6e1
commit
cf0952c232
|
@ -1586,6 +1586,10 @@ var_index lar_solver::add_var(unsigned ext_j, bool is_int) {
|
||||||
return local_j;
|
return local_j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lar_solver::has_int_var() const {
|
||||||
|
return m_var_register.has_int_var();
|
||||||
|
}
|
||||||
|
|
||||||
void lar_solver::register_new_ext_var_index(unsigned ext_v, bool is_int) {
|
void lar_solver::register_new_ext_var_index(unsigned ext_v, bool is_int) {
|
||||||
lp_assert(!m_var_register.external_is_used(ext_v));
|
lp_assert(!m_var_register.external_is_used(ext_v));
|
||||||
m_var_register.add_var(ext_v, is_int);
|
m_var_register.add_var(ext_v, is_int);
|
||||||
|
|
|
@ -95,18 +95,19 @@ public:
|
||||||
stacked_vector<ul_pair> m_columns_to_ul_pairs;
|
stacked_vector<ul_pair> m_columns_to_ul_pairs;
|
||||||
constraint_set m_constraints;
|
constraint_set m_constraints;
|
||||||
// the set of column indices j such that bounds have changed for j
|
// the set of column indices j such that bounds have changed for j
|
||||||
u_set m_columns_with_changed_bound;
|
u_set m_columns_with_changed_bound;
|
||||||
u_set m_rows_with_changed_bounds;
|
u_set m_rows_with_changed_bounds;
|
||||||
u_set m_basic_columns_with_changed_cost;
|
u_set m_basic_columns_with_changed_cost;
|
||||||
// these are basic columns with the value changed, so the the corresponding row in the tableau
|
// these are basic columns with the value changed, so the the corresponding row in the tableau
|
||||||
// does not sum to zero anymore
|
// does not sum to zero anymore
|
||||||
u_set m_incorrect_columns;
|
u_set m_incorrect_columns;
|
||||||
stacked_value<int> m_crossed_bounds_column_index; // such can be found at the initialization step
|
stacked_value<int> m_crossed_bounds_column_index; // such can be found at the initialization step
|
||||||
stacked_value<unsigned> m_term_count;
|
stacked_value<unsigned> m_term_count;
|
||||||
vector<lar_term*> m_terms;
|
vector<lar_term*> m_terms;
|
||||||
indexed_vector<mpq> m_column_buffer;
|
indexed_vector<mpq> m_column_buffer;
|
||||||
std::unordered_map<lar_term, std::pair<mpq, unsigned>, term_hasher, term_comparer>
|
std::unordered_map<lar_term, std::pair<mpq, unsigned>, term_hasher, term_comparer>
|
||||||
m_normalized_terms_to_columns;
|
m_normalized_terms_to_columns;
|
||||||
|
vector<impq> m_backup_x;
|
||||||
// end of fields
|
// end of fields
|
||||||
|
|
||||||
const vector<lar_term*> & terms() const { return m_terms; }
|
const vector<lar_term*> & terms() const { return m_terms; }
|
||||||
|
@ -127,6 +128,7 @@ public:
|
||||||
bool column_value_is_int(unsigned j) const {
|
bool column_value_is_int(unsigned j) const {
|
||||||
return m_mpq_lar_core_solver.m_r_x[j].is_int();
|
return m_mpq_lar_core_solver.m_r_x[j].is_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const impq& get_column_value(unsigned j) const {
|
const impq& get_column_value(unsigned j) const {
|
||||||
return m_mpq_lar_core_solver.m_r_x[j];
|
return m_mpq_lar_core_solver.m_r_x[j];
|
||||||
|
@ -643,5 +645,7 @@ public:
|
||||||
bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>& ) const;
|
bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>& ) const;
|
||||||
bool try_to_patch(lpvar, const mpq&, const std::function<bool (lpvar)>& blocker,const std::function<void (lpvar)>& change_report);
|
bool try_to_patch(lpvar, const mpq&, const std::function<bool (lpvar)>& blocker,const std::function<void (lpvar)>& change_report);
|
||||||
bool inside_bounds(lpvar, const impq&) const;
|
bool inside_bounds(lpvar, const impq&) const;
|
||||||
|
void backup_x() { m_backup_x = m_mpq_lar_core_solver.m_r_x; }
|
||||||
|
void restore_x() { m_mpq_lar_core_solver.m_r_x = m_backup_x; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,13 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_int_var() const {
|
||||||
|
for (const auto & vi : m_local_to_external) {
|
||||||
|
if (vi.is_integer())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool local_is_int(unsigned j) const {
|
bool local_is_int(unsigned j) const {
|
||||||
return m_local_to_external[j & m_locals_mask_inverted].is_integer();
|
return m_local_to_external[j & m_locals_mask_inverted].is_integer();
|
||||||
|
|
|
@ -3548,6 +3548,9 @@ public:
|
||||||
lp::impq term_max;
|
lp::impq term_max;
|
||||||
lp::lp_status st;
|
lp::lp_status st;
|
||||||
lpvar vi = 0;
|
lpvar vi = 0;
|
||||||
|
if (has_int()) {
|
||||||
|
lp().backup_x();
|
||||||
|
}
|
||||||
if (!can_get_bound(v)) {
|
if (!can_get_bound(v)) {
|
||||||
TRACE("arith", tout << "cannot get bound for v" << v << "\n";);
|
TRACE("arith", tout << "cannot get bound for v" << v << "\n";);
|
||||||
st = lp::lp_status::UNBOUNDED;
|
st = lp::lp_status::UNBOUNDED;
|
||||||
|
@ -3558,6 +3561,11 @@ public:
|
||||||
else {
|
else {
|
||||||
vi = get_lpvar(v);
|
vi = get_lpvar(v);
|
||||||
st = lp().maximize_term(vi, term_max);
|
st = lp().maximize_term(vi, term_max);
|
||||||
|
if (has_int() && lp().has_inf_int()) {
|
||||||
|
st = lp::lp_status::FEASIBLE;
|
||||||
|
lp().restore_x();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
switch (st) {
|
switch (st) {
|
||||||
case lp::lp_status::OPTIMAL: {
|
case lp::lp_status::OPTIMAL: {
|
||||||
|
|
Loading…
Reference in a new issue