3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00

add init_model, global m_delta, get_value, get_ivalue to push model maintainance into lar_solver #4740

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-11-02 19:21:15 -08:00
parent ab199dedf9
commit ee12e3fb52
5 changed files with 2269 additions and 2211 deletions

View file

@ -14,7 +14,8 @@ lp_settings & lar_solver::settings() { return m_settings;}
lp_settings const& lar_solver::settings() const { return m_settings; } lp_settings const& lar_solver::settings() const { return m_settings; }
void clear() {lp_assert(false); // not implemented void clear() {
lp_assert(false); // not implemented
} }
@ -110,7 +111,8 @@ bool lar_solver::implied_bound_is_correctly_explained(implied_bound const & be,
kind = static_cast<lconstraint_kind>(-kind); kind = static_cast<lconstraint_kind>(-kind);
} }
rs_of_evidence /= ratio; rs_of_evidence /= ratio;
} else { }
else {
lar_term const& t = get_term(be.m_j); lar_term const& t = get_term(be.m_j);
auto first_coeff = t.begin(); auto first_coeff = t.begin();
unsigned j = (*first_coeff).column(); unsigned j = (*first_coeff).column();
@ -407,7 +409,8 @@ bool lar_solver::move_non_basic_column_to_bounds(unsigned j, bool force_change)
else else
set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]); set_value_for_nbasic_column(j, lcs.m_r_upper_bounds()[j]);
return true; return true;
} else if (force_change && m_settings.random_next() % 3 == 0) { }
else if (force_change && m_settings.random_next() % 3 == 0) {
set_value_for_nbasic_column(j, set_value_for_nbasic_column(j,
at_l ? lcs.m_r_upper_bounds()[j] : lcs.m_r_lower_bounds()[j]); at_l ? lcs.m_r_upper_bounds()[j] : lcs.m_r_lower_bounds()[j]);
return true; return true;
@ -510,7 +513,8 @@ lp_status lar_solver::maximize_term(unsigned j_or_term,
auto backup = m_mpq_lar_core_solver.m_r_x; auto backup = m_mpq_lar_core_solver.m_r_x;
if (m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis()) { if (m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis()) {
prev_value = term.apply(m_mpq_lar_core_solver.m_r_x); prev_value = term.apply(m_mpq_lar_core_solver.m_r_x);
} else { }
else {
m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = false; m_mpq_lar_core_solver.m_r_solver.m_look_for_feasible_solution_only = false;
if (solve() != lp_status::OPTIMAL) if (solve() != lp_status::OPTIMAL)
return lp_status::UNBOUNDED; return lp_status::UNBOUNDED;
@ -593,7 +597,8 @@ void lar_solver::register_monoid_in_map(std::unordered_map<var_index, mpq> & coe
auto it = coeffs.find(j); auto it = coeffs.find(j);
if (it == coeffs.end()) { if (it == coeffs.end()) {
coeffs[j] = a; coeffs[j] = a;
} else { }
else {
it->second += a; it->second += a;
} }
} }
@ -606,7 +611,8 @@ void lar_solver::substitute_terms_in_linear_expression(const vector<std::pair<mp
unsigned j = t.second; unsigned j = t.second;
if (!tv::is_term(j)) { if (!tv::is_term(j)) {
register_monoid_in_map(coeffs, t.first, j); register_monoid_in_map(coeffs, t.first, j);
} else { }
else {
const lar_term& term = *m_terms[tv::unmask_term(t.second)]; const lar_term& term = *m_terms[tv::unmask_term(t.second)];
for (auto p : term) { for (auto p : term) {
@ -696,7 +702,8 @@ void lar_solver::change_basic_columns_dependend_on_a_given_nb_column(unsigned j,
(m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj) ? "feas" : "inf") << std::endl;); (m_mpq_lar_core_solver.m_r_solver.column_is_feasible(bj) ? "feas" : "inf") << std::endl;);
} }
} else { }
else {
m_column_buffer.clear(); m_column_buffer.clear();
m_column_buffer.resize(A_r().row_count()); m_column_buffer.resize(A_r().row_count());
m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer); m_mpq_lar_core_solver.m_r_solver.solve_Bd(j, m_column_buffer);
@ -714,10 +721,12 @@ void lar_solver::update_x_and_inf_costs_for_column_with_changed_bounds(unsigned
m_mpq_lar_core_solver.m_r_solver.track_column_feasibility(j); m_mpq_lar_core_solver.m_r_solver.track_column_feasibility(j);
if (was_infeas != m_mpq_lar_core_solver.m_r_solver.inf_set_contains(j)) if (was_infeas != m_mpq_lar_core_solver.m_r_solver.inf_set_contains(j))
m_basic_columns_with_changed_cost.insert(j); m_basic_columns_with_changed_cost.insert(j);
} else { }
else {
m_mpq_lar_core_solver.m_r_solver.track_column_feasibility(j); m_mpq_lar_core_solver.m_r_solver.track_column_feasibility(j);
} }
} else { }
else {
numeric_pair<mpq> delta; numeric_pair<mpq> delta;
if (m_mpq_lar_core_solver.m_r_solver.make_column_feasible(j, delta)) if (m_mpq_lar_core_solver.m_r_solver.make_column_feasible(j, delta))
change_basic_columns_dependend_on_a_given_nb_column(j, delta); change_basic_columns_dependend_on_a_given_nb_column(j, delta);
@ -803,7 +812,8 @@ void lar_solver::add_last_rows_to_lu(lp_primal_core_solver<K,L> & s) {
if (f->m_refactor_counter + columns_to_replace.size() >= 200 || f->has_dense_submatrix()) { if (f->m_refactor_counter + columns_to_replace.size() >= 200 || f->has_dense_submatrix()) {
delete f; delete f;
f = nullptr; f = nullptr;
} else { }
else {
f->add_last_rows_to_B(s.m_basis_heading, columns_to_replace); f->add_last_rows_to_B(s.m_basis_heading, columns_to_replace);
} }
} }
@ -1093,8 +1103,6 @@ void lar_solver::get_infeasibility_explanation(explanation& exp) const {
lp_assert(explanation_is_correct(exp)); lp_assert(explanation_is_correct(exp));
} }
void lar_solver::get_infeasibility_explanation_for_inf_sign( void lar_solver::get_infeasibility_explanation_for_inf_sign(
explanation& exp, explanation& exp,
const vector<std::pair<mpq, unsigned>>& inf_row, const vector<std::pair<mpq, unsigned>>& inf_row,
@ -1115,41 +1123,47 @@ void lar_solver::get_infeasibility_explanation_for_inf_sign(
// (x, y) != (x', y') => (x + delta*y) != (x' + delta*y') // (x, y) != (x', y') => (x + delta*y) != (x' + delta*y')
void lar_solver::get_model(std::unordered_map<var_index, mpq>& variable_values) const { void lar_solver::get_model(std::unordered_map<var_index, mpq>& variable_values) const {
if (!(get_status() == lp_status::OPTIMAL || get_status() == lp_status::FEASIBLE) ||
!m_columns_with_changed_bounds.empty()) {
variable_values.clear(); variable_values.clear();
if (!init_model())
return; return;
unsigned n = m_mpq_lar_core_solver.m_r_x.size();
for (unsigned j = 0; j < n; j++)
variable_values[j] = get_value(column_index(j));
TRACE("lar_solver_model", tout << "delta = " << m_delta << "\nmodel:\n";
for (auto p : variable_values) tout << this->get_variable_name(p.first) << " = " << p.second << "\n";);
} }
bool lar_solver::init_model() const {
if (get_status() != lp_status::OPTIMAL && get_status() != lp_status::FEASIBLE)
return false;
if (!m_columns_with_changed_bounds.empty())
return false;
lp_assert(m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis()); lp_assert(m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis());
variable_values.clear(); m_delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(mpq(1));
mpq delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(mpq(1));
unsigned j; unsigned j;
unsigned n = m_mpq_lar_core_solver.m_r_x.size(); unsigned n = m_mpq_lar_core_solver.m_r_x.size();
std::unordered_set<impq> set_of_different_pairs;
std::unordered_set<mpq> set_of_different_singles;
do { do {
set_of_different_pairs.clear(); m_set_of_different_pairs.clear();
set_of_different_singles.clear(); m_set_of_different_singles.clear();
for (j = 0; j < n; j++) { for (j = 0; j < n; j++) {
const numeric_pair<mpq>& rp = m_mpq_lar_core_solver.m_r_x[j]; const numeric_pair<mpq>& rp = m_mpq_lar_core_solver.m_r_x[j];
set_of_different_pairs.insert(rp); mpq x = rp.x + m_delta * rp.y;
mpq x = rp.x + delta * rp.y; m_set_of_different_pairs.insert(rp);
set_of_different_singles.insert(x); m_set_of_different_singles.insert(x);
if (set_of_different_pairs.size() != set_of_different_singles.size()) { if (m_set_of_different_pairs.size() != m_set_of_different_singles.size()) {
delta /= mpq(2); m_delta /= mpq(2);
break; break;
} }
variable_values[j] = x;
} }
} while (j != n); } while (j != n);
TRACE("lar_solver_model", tout << "delta = " << delta << "\nmodel:\n"; TRACE("lar_solver_model", tout << "delta = " << m_delta << "\nmodel:\n";);
for (auto p : variable_values ) { return true;
tout << this->get_variable_name(p.first) << " = " << p.second << "\n";
});
} }
void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq>& variable_values) const { void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq>& variable_values) const {
mpq delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(mpq(1)); mpq delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(mpq(1));
for (unsigned i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++) { for (unsigned i = 0; i < m_mpq_lar_core_solver.m_r_x.size(); i++) {
@ -1158,6 +1172,30 @@ void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map<var_in
} }
} }
mpq lar_solver::get_value(column_index const& j) const {
SASSERT(get_status() == lp_status::OPTIMAL || get_status() == lp_status::FEASIBLE);
numeric_pair<mpq> const& rp = get_column_value(j);
return rp.x + m_delta * rp.y;
}
mpq lar_solver::get_value(tv const& t) const {
if (t.is_var())
get_value(t.column());
mpq r(0);
for (const auto& p : get_term(t))
r += p.coeff() * get_value(p.column());
return r;
}
impq lar_solver::get_ivalue(tv const& t) const {
if (t.is_var())
get_ivalue(t.column());
impq r;
for (const auto& p : get_term(t))
r += p.coeff() * get_ivalue(p.column());
return r;
}
void lar_solver::get_rid_of_inf_eps() { void lar_solver::get_rid_of_inf_eps() {
bool y_is_zero = true; bool y_is_zero = true;
for (unsigned j = 0; j < number_of_vars(); j++) { for (unsigned j = 0; j < number_of_vars(); j++) {
@ -1218,9 +1256,11 @@ std::ostream& lar_solver::print_term(lar_term const& term, std::ostream & out) c
mpq val = p.coeff(); mpq val = p.coeff();
if (first) { if (first) {
first = false; first = false;
} else if (is_pos(val)) { }
else if (is_pos(val)) {
out << " + "; out << " + ";
} else { }
else {
out << " - "; out << " - ";
val = -val; val = -val;
} }
@ -1258,7 +1298,8 @@ void lar_solver::fill_var_set_for_random_update(unsigned sz, var_index const * v
if (term_is_used_as_row(tv::unmask_term(var))) { if (term_is_used_as_row(tv::unmask_term(var))) {
column_list.push_back(map_term_index_to_column_index(var)); column_list.push_back(map_term_index_to_column_index(var));
} }
} else { }
else {
column_list.push_back(var); column_list.push_back(var);
} }
} }
@ -1354,7 +1395,8 @@ void lar_solver::remove_last_column_from_basis_tableau(unsigned j) {
rslv.m_basis_heading[j_at_last_pos] = i; rslv.m_basis_heading[j_at_last_pos] = i;
} }
rslv.m_basis.pop_back(); // remove j from the basis rslv.m_basis.pop_back(); // remove j from the basis
} else { }
else {
int last_pos = static_cast<int>(rslv.m_nbasis.size()) - 1; int last_pos = static_cast<int>(rslv.m_nbasis.size()) - 1;
lp_assert(last_pos >= 0); lp_assert(last_pos >= 0);
i = -1 - i; i = -1 - i;
@ -1626,7 +1668,8 @@ bool lar_solver::term_coeffs_are_ok(const vector<std::pair<mpq, var_index>> & co
if (!g_is_set) { if (!g_is_set) {
g_is_set = true; g_is_set = true;
g = p.first; g = p.first;
} else { }
else {
g = gcd(g, p.first); g = gcd(g, p.first);
} }
} }
@ -1770,7 +1813,8 @@ void lar_solver::register_in_fixed_var_table(unsigned j, unsigned & equal_to_j)
m_fixed_var_table_int.insert(key, j); m_fixed_var_table_int.insert(key, j);
return; return;
} }
} else { // j is not integral column }
else { // j is not integral column
if (!m_fixed_var_table_real.find(key, k)) { if (!m_fixed_var_table_real.find(key, k)) {
m_fixed_var_table_real.insert(key, j); m_fixed_var_table_real.insert(key, j);
return; return;
@ -1988,7 +2032,8 @@ void lar_solver::update_column_type_and_bound_with_ub(unsigned j, lp::lconstrain
SASSERT(column_has_upper_bound(j)); SASSERT(column_has_upper_bound(j));
if (column_has_lower_bound(j)) { if (column_has_lower_bound(j)) {
update_bound_with_ub_lb(j, kind, right_side, constraint_index); update_bound_with_ub_lb(j, kind, right_side, constraint_index);
} else { }
else {
update_bound_with_ub_no_lb(j, kind, right_side, constraint_index); update_bound_with_ub_no_lb(j, kind, right_side, constraint_index);
} }
} }
@ -1997,7 +2042,8 @@ void lar_solver::update_column_type_and_bound_with_no_ub(unsigned j, lp::lconstr
SASSERT(!column_has_upper_bound(j)); SASSERT(!column_has_upper_bound(j));
if (column_has_lower_bound(j)) { if (column_has_lower_bound(j)) {
update_bound_with_no_ub_lb(j, kind, right_side, constraint_index); update_bound_with_no_ub_lb(j, kind, right_side, constraint_index);
} else { }
else {
update_bound_with_no_ub_no_lb(j, kind, right_side, constraint_index); update_bound_with_no_ub_no_lb(j, kind, right_side, constraint_index);
} }
} }
@ -2257,7 +2303,8 @@ void lar_solver::round_to_integer_solution() {
if (del < -impq(mpq(1, 2))) { if (del < -impq(mpq(1, 2))) {
del = impq(one_of_type<mpq>()) + del; del = impq(one_of_type<mpq>()) + del;
v = impq(ceil(v)); v = impq(ceil(v));
} else { }
else {
v = flv; v = flv;
} }
m_incorrect_columns.insert(j); m_incorrect_columns.insert(j);
@ -2342,10 +2389,12 @@ void lar_solver::set_cut_strategy(unsigned cut_frequency) {
if (cut_frequency < 4) { if (cut_frequency < 4) {
settings().m_int_gomory_cut_period = 2; // do it often settings().m_int_gomory_cut_period = 2; // do it often
settings().set_hnf_cut_period(4); // also create hnf cuts settings().set_hnf_cut_period(4); // also create hnf cuts
} else if (cut_frequency == 4) { // enable all cuts and cube equally }
else if (cut_frequency == 4) { // enable all cuts and cube equally
settings().m_int_gomory_cut_period = 4; settings().m_int_gomory_cut_period = 4;
settings().set_hnf_cut_period(4); settings().set_hnf_cut_period(4);
} else { }
else {
// disable all heuristics except cube // disable all heuristics except cube
settings().m_int_gomory_cut_period = 10000000; settings().m_int_gomory_cut_period = 10000000;
settings().set_hnf_cut_period(100000000); settings().set_hnf_cut_period(100000000);
@ -2360,7 +2409,8 @@ void lar_solver::register_normalized_term(const lar_term& t, lpvar j) {
tout << ", normalized_t="; print_term_as_indices(normalized_t, tout) << "\n";); tout << ", normalized_t="; print_term_as_indices(normalized_t, tout) << "\n";);
if (m_normalized_terms_to_columns.find(normalized_t) == m_normalized_terms_to_columns.end()) { if (m_normalized_terms_to_columns.find(normalized_t) == m_normalized_terms_to_columns.end()) {
m_normalized_terms_to_columns[normalized_t] = std::make_pair(a, j); m_normalized_terms_to_columns[normalized_t] = std::make_pair(a, j);
} else { }
else {
TRACE("lar_solver_terms", tout << "the term has been seen already\n";); TRACE("lar_solver_terms", tout << "the term has been seen already\n";);
} }
} }

View file

@ -137,10 +137,7 @@ class lar_solver : public column_namer {
inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.clear(); } inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.clear(); }
inline void increase_by_one_columns_with_changed_bounds() { m_columns_with_changed_bounds.increase_size_by_one(); } inline void increase_by_one_columns_with_changed_bounds() { m_columns_with_changed_bounds.increase_size_by_one(); }
inline void insert_to_columns_with_changed_bounds(unsigned j) { inline void insert_to_columns_with_changed_bounds(unsigned j) { m_columns_with_changed_bounds.insert(j); }
m_columns_with_changed_bounds.insert(j);
}
void update_column_type_and_bound_check_on_equal(unsigned j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index, unsigned&); void update_column_type_and_bound_check_on_equal(unsigned j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index, unsigned&);
void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index); void update_column_type_and_bound(unsigned j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index);
@ -289,6 +286,11 @@ class lar_solver : public column_namer {
void collect_rounded_rows_to_fix(); void collect_rounded_rows_to_fix();
void register_normalized_term(const lar_term&, lpvar); void register_normalized_term(const lar_term&, lpvar);
void deregister_normalized_term(const lar_term&); void deregister_normalized_term(const lar_term&);
mutable std::unordered_set<impq> m_set_of_different_pairs;
mutable std::unordered_set<mpq> m_set_of_different_singles;
mutable mpq m_delta;
public: public:
const map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>>& fixed_var_table_int() const { const map<mpq, unsigned, obj_hash<mpq>, default_eq<mpq>>& fixed_var_table_int() const {
return m_fixed_var_table_int; return m_fixed_var_table_int;
@ -520,6 +522,10 @@ public:
std::ostream& print_constraint_indices_only(const lar_base_constraint * c, std::ostream & out) const; std::ostream& print_constraint_indices_only(const lar_base_constraint * c, std::ostream & out) const;
std::ostream& print_implied_bound(const implied_bound& be, std::ostream & out) const; std::ostream& print_implied_bound(const implied_bound& be, std::ostream & out) const;
std::ostream& print_values(std::ostream& out) const; std::ostream& print_values(std::ostream& out) const;
bool init_model() const;
mpq get_value(column_index const& j) const;
mpq get_value(tv const& t) const;
impq get_ivalue(tv const& t) const;
void get_model(std::unordered_map<var_index, mpq> & variable_values) const; void get_model(std::unordered_map<var_index, mpq> & variable_values) const;
void get_rid_of_inf_eps(); void get_rid_of_inf_eps();
void get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq> & variable_values) const; void get_model_do_not_care_about_diff_vars(std::unordered_map<var_index, mpq> & variable_values) const;
@ -615,6 +621,7 @@ public:
inline const vector<unsigned> & r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); } inline const vector<unsigned> & r_nbasis() const { return m_mpq_lar_core_solver.r_nbasis(); }
inline bool column_is_real(unsigned j) const { return !column_is_int(j); } inline bool column_is_real(unsigned j) const { return !column_is_int(j); }
lp_status get_status() const; lp_status get_status() const;
bool has_changed_columns() const { return !m_columns_with_changed_bounds.empty(); }
void set_status(lp_status s); void set_status(lp_status s);
lp_status solve(); lp_status solve();
void fill_explanation_from_crossed_bounds_column(explanation & evidence) const; void fill_explanation_from_crossed_bounds_column(explanation & evidence) const;
@ -631,8 +638,8 @@ public:
inline const static_matrix<mpq, impq> & A_r() const { return m_mpq_lar_core_solver.m_r_A; } inline const static_matrix<mpq, impq> & A_r() const { return m_mpq_lar_core_solver.m_r_A; }
// columns // columns
bool column_is_int(column_index const& j) const { return column_is_int((unsigned)j); } bool column_is_int(column_index const& j) const { return column_is_int((unsigned)j); }
const impq& get_value(column_index const& j) const { return get_column_value(j); } const impq& get_ivalue(column_index const& j) const { return get_column_value(j); }
const impq& get_column_value(unsigned j) const { return m_mpq_lar_core_solver.m_r_x[j]; } const impq& get_column_value(column_index const& j) const { return m_mpq_lar_core_solver.m_r_x[j]; }
inline inline
var_index external_to_local(unsigned j) const { var_index external_to_local(unsigned j) const {
var_index local_j; var_index local_j;

View file

@ -36,6 +36,20 @@ typedef unsigned lpvar;
const lpvar null_lpvar = UINT_MAX; const lpvar null_lpvar = UINT_MAX;
const constraint_index null_ci = UINT_MAX; const constraint_index null_ci = UINT_MAX;
class column_index {
unsigned m_index;
friend class lar_solver;
friend class lar_term;
friend nla::core;
operator unsigned() const { return m_index; }
public:
column_index(unsigned j): m_index(j) {}
unsigned index() const { return m_index; }
bool is_null() const { return m_index == null_lpvar; }
};
// index that comes from term or variable. // index that comes from term or variable.
class tv { class tv {
@ -49,6 +63,7 @@ public:
// retrieve the identifier associated with tv // retrieve the identifier associated with tv
unsigned id() const { return unmask_term(m_index); } unsigned id() const { return unmask_term(m_index); }
column_index column() const { SASSERT(is_var()); return column_index(id()); }
// retrieve the raw index. // retrieve the raw index.
unsigned index() const { return m_index; } unsigned index() const { return m_index; }
@ -74,20 +89,6 @@ public:
}; };
class column_index {
unsigned m_index;
friend class lar_solver;
friend class lar_term;
friend nla::core;
operator unsigned() const { return m_index; }
public:
column_index(unsigned j): m_index(j) {}
unsigned index() const { return m_index; }
bool is_null() const { return m_index == null_lpvar; }
};
} }
inline std::ostream& operator<<(std::ostream& out, lp::tv const& t) { inline std::ostream& operator<<(std::ostream& out, lp::tv const& t) {

View file

@ -231,7 +231,6 @@ namespace euf {
return true; return true;
} }
void solver::get_antecedents(literal l, constraint& j, literal_vector& r, bool probing) { void solver::get_antecedents(literal l, constraint& j, literal_vector& r, bool probing) {
expr* e = nullptr; expr* e = nullptr;
euf::enode* n = nullptr; euf::enode* n = nullptr;

View file

@ -1474,6 +1474,7 @@ public:
} }
else { else {
auto I = m_variable_values.find(t2.index()); auto I = m_variable_values.find(t2.index());
std::cout << (I == E) << "\n";
if (I != E) if (I != E)
result += I->second * coeff; result += I->second * coeff;
} }
@ -1619,7 +1620,7 @@ public:
IF_VERBOSE(12, verbose_stream() << "final-check " << lp().get_status() << "\n"); IF_VERBOSE(12, verbose_stream() << "final-check " << lp().get_status() << "\n");
lbool is_sat = l_true; lbool is_sat = l_true;
SASSERT(lp().ax_is_correct()); SASSERT(lp().ax_is_correct());
if (lp().get_status() != lp::lp_status::OPTIMAL) { if (lp().get_status() != lp::lp_status::OPTIMAL || lp().has_changed_columns()) {
is_sat = make_feasible(); is_sat = make_feasible();
} }
final_check_status st = FC_DONE; final_check_status st = FC_DONE;