3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-06 01:24:08 +00:00
This commit is contained in:
Nikolaj Bjorner 2025-02-27 14:43:11 -08:00
parent 83ee21cd22
commit b784b748d4
5 changed files with 83 additions and 53 deletions

View file

@ -340,7 +340,7 @@ namespace lp {
bool current_solution_is_inf_on_cut() const { bool current_solution_is_inf_on_cut() const {
SASSERT(cut_indices_are_columns()); SASSERT(cut_indices_are_columns());
const auto & x = lrac.m_r_x; const auto & x = lrac.r_x();
impq v = m_t.apply(x); impq v = m_t.apply(x);
mpq sign = m_upper ? one_of_type<mpq>() : -one_of_type<mpq>(); mpq sign = m_upper ? one_of_type<mpq>() : -one_of_type<mpq>();
CTRACE("current_solution_is_inf_on_cut", v * sign <= impq(m_k) * sign, CTRACE("current_solution_is_inf_on_cut", v * sign <= impq(m_k) * sign,
@ -682,7 +682,7 @@ namespace lp {
} }
const impq & int_solver::get_value(unsigned j) const { const impq & int_solver::get_value(unsigned j) const {
return lrac.m_r_x[j]; return lrac.r_x(j);
} }
std::ostream& int_solver::display_column(std::ostream & out, unsigned j) const { std::ostream& int_solver::display_column(std::ostream & out, unsigned j) const {

View file

@ -22,19 +22,21 @@ class lar_core_solver {
vector<numeric_pair<mpq>> m_right_sides_dummy; vector<numeric_pair<mpq>> m_right_sides_dummy;
vector<mpq> m_costs_dummy; vector<mpq> m_costs_dummy;
stacked_value<simplex_strategy_enum> m_stacked_simplex_strategy; stacked_value<simplex_strategy_enum> m_stacked_simplex_strategy;
vector<impq> m_r_x; // the solution
vector<impq> m_backup_x;
public: public:
stacked_vector<column_type> m_column_types; stacked_vector<column_type> m_column_types;
// r - solver fields, for rational numbers // r - solver fields, for rational numbers
vector<numeric_pair<mpq>> m_r_x; // the solution
stacked_vector<numeric_pair<mpq>> m_r_lower_bounds; stacked_vector<numeric_pair<mpq>> m_r_lower_bounds;
stacked_vector<numeric_pair<mpq>> m_r_upper_bounds; stacked_vector<numeric_pair<mpq>> m_r_upper_bounds;
static_matrix<mpq, numeric_pair<mpq>> m_r_A; static_matrix<mpq, numeric_pair<mpq>> m_r_A;
stacked_vector<unsigned> m_r_pushed_basis; stacked_vector<unsigned> m_r_pushed_basis;
vector<unsigned> m_r_basis; vector<unsigned> m_r_basis;
vector<unsigned> m_r_nbasis; vector<unsigned> m_r_nbasis;
std_vector<int> m_r_heading; std_vector<int> m_r_heading;
lp_primal_core_solver<mpq, numeric_pair<mpq>> m_r_solver; // solver in rational numbers lp_primal_core_solver<mpq, numeric_pair<mpq>> m_r_solver; // solver in rational numbers
@ -71,9 +73,24 @@ public:
m_r_solver.print_column_bound_info(m_r_solver.m_basis[row_index], out); m_r_solver.print_column_bound_info(m_r_solver.m_basis[row_index], out);
} }
void prefix_r(); void prefix_r();
// access to x:
void backup_x() { m_backup_x = m_r_x; }
void restore_x() {
m_r_x.reserve(m_m());
for (unsigned i = 0; i < std::min(m_m(), m_backup_x.size()); ++i)
m_r_x[i] = m_backup_x[i];
}
vector<impq> const& r_x() const { return m_r_x; }
impq& r_x(unsigned j) { return m_r_x[j]; }
impq const& r_x(unsigned j) const { return m_r_x[j]; }
void resize_x(unsigned n) { m_r_x.resize(n); }
unsigned m_m() const { return m_r_A.row_count(); } unsigned m_m() const { return m_r_A.row_count(); }

View file

@ -76,7 +76,7 @@ void lar_core_solver::fill_not_improvable_zero_sum() {
unsigned lar_core_solver::get_number_of_non_ints() const { unsigned lar_core_solver::get_number_of_non_ints() const {
unsigned n = 0; unsigned n = 0;
for (auto & x : m_r_solver.m_x) for (auto & x : r_x())
if (!x.is_int()) if (!x.is_int())
n++; n++;
return n; return n;

View file

@ -45,7 +45,7 @@ namespace lp {
bool lar_solver::sizes_are_correct() const { bool lar_solver::sizes_are_correct() const {
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size()); lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_column_types.size());
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size());
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_x.size()); lp_assert(A_r().column_count() == m_mpq_lar_core_solver.r_x().size());
return true; return true;
} }
@ -65,8 +65,8 @@ namespace lp {
} }
std::ostream& lar_solver::print_values(std::ostream& out) const { std::ostream& lar_solver::print_values(std::ostream& out) const {
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.r_x().size(); i++) {
const numeric_pair<mpq>& rp = m_mpq_lar_core_solver.m_r_x[i]; const numeric_pair<mpq>& rp = m_mpq_lar_core_solver.r_x(i);
out << this->get_variable_name(i) << " -> " << rp << "\n"; out << this->get_variable_name(i) << " -> " << rp << "\n";
} }
return out; return out;
@ -264,7 +264,7 @@ namespace lp {
return false; return false;
} }
else { else {
term_max = term.apply(m_mpq_lar_core_solver.m_r_x); term_max = term.apply(m_mpq_lar_core_solver.r_x());
return true; return true;
} }
} }
@ -418,7 +418,7 @@ namespace lp {
bool lar_solver::move_non_basic_column_to_bounds(unsigned j) { bool lar_solver::move_non_basic_column_to_bounds(unsigned j) {
auto& lcs = m_mpq_lar_core_solver; auto& lcs = m_mpq_lar_core_solver;
auto& val = lcs.m_r_x[j]; auto& val = lcs.r_x(j);
switch (lcs.m_column_types()[j]) { switch (lcs.m_column_types()[j]) {
case column_type::boxed: { case column_type::boxed: {
const auto& l = lcs.m_r_lower_bounds()[j]; const auto& l = lcs.m_r_lower_bounds()[j];
@ -458,7 +458,7 @@ namespace lp {
void lar_solver::set_value_for_nbasic_column(unsigned j, const impq& new_val) { void lar_solver::set_value_for_nbasic_column(unsigned j, const impq& new_val) {
lp_assert(!is_base(j)); lp_assert(!is_base(j));
auto& x = m_mpq_lar_core_solver.m_r_x[j]; auto& x = m_mpq_lar_core_solver.r_x(j);
auto delta = new_val - x; auto delta = new_val - x;
x = new_val; x = new_val;
TRACE("lar_solver_feas", tout << "setting " << j << " to " TRACE("lar_solver_feas", tout << "setting " << j << " to "
@ -505,7 +505,7 @@ namespace lp {
if (column_has_term(j)) { if (column_has_term(j)) {
return * m_columns[j].term(); return * m_columns[j].term();
} }
if (j < m_mpq_lar_core_solver.m_r_x.size()) { if (j < m_mpq_lar_core_solver.r_x().size()) {
lar_term r; lar_term r;
r.add_monomial(one_of_type<mpq>(), j); r.add_monomial(one_of_type<mpq>(), j);
return r; return r;
@ -519,41 +519,44 @@ namespace lp {
SASSERT(m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis()); SASSERT(m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis());
lar_term term = get_term_to_maximize(j); lar_term term = get_term_to_maximize(j);
if (term.is_empty()) return lp_status::UNBOUNDED; if (term.is_empty()) return lp_status::UNBOUNDED;
impq prev_value = term.apply(m_mpq_lar_core_solver.m_r_x); m_mpq_lar_core_solver.backup_x();
auto backup = m_mpq_lar_core_solver.m_r_x; impq prev_value = term.apply(m_mpq_lar_core_solver.r_x());
auto restore = [&]() {
m_mpq_lar_core_solver.restore_x();
};
if (!maximize_term_on_feasible_r_solver(term, term_max, nullptr)) { if (!maximize_term_on_feasible_r_solver(term, term_max, nullptr)) {
m_mpq_lar_core_solver.m_r_x = backup; restore();
return lp_status::UNBOUNDED; return lp_status::UNBOUNDED;
} }
impq opt_val = term_max; impq opt_val = term_max;
bool change = false; bool change = false;
for (unsigned j = 0; j < m_mpq_lar_core_solver.m_r_x.size(); j++) { for (unsigned j = 0; j < m_mpq_lar_core_solver.r_x().size(); j++) {
if (!column_is_int(j)) if (!column_is_int(j))
continue; continue;
if (column_value_is_integer(j)) if (column_value_is_integer(j))
continue; continue;
if (m_int_solver->is_base(j)) { if (m_int_solver->is_base(j)) {
if (!remove_from_basis(j)) { // consider a special version of remove_from_basis that would not remove inf_int columns if (!remove_from_basis(j)) { // consider a special version of remove_from_basis that would not remove inf_int columns
m_mpq_lar_core_solver.m_r_x = backup; restore();
term_max = prev_value; term_max = prev_value;
return lp_status::FEASIBLE; // it should not happen return lp_status::FEASIBLE; // it should not happen
} }
} }
if (!column_value_is_integer(j)) { if (!column_value_is_integer(j)) {
term_max = prev_value; term_max = prev_value;
m_mpq_lar_core_solver.m_r_x = backup; restore();
return lp_status::FEASIBLE; return lp_status::FEASIBLE;
} }
change = true; change = true;
} }
if (change) { if (change) {
term_max = term.apply(m_mpq_lar_core_solver.m_r_x); term_max = term.apply(m_mpq_lar_core_solver.r_x());
} }
if (term_max < prev_value) { if (term_max < prev_value) {
term_max = prev_value; term_max = prev_value;
m_mpq_lar_core_solver.m_r_x = backup; restore();
} }
TRACE("lar_solver", print_values(tout);); TRACE("lar_solver", print_values(tout););
if (term_max == opt_val) { if (term_max == opt_val) {
@ -823,7 +826,7 @@ namespace lp {
bool lar_solver::row_is_correct(unsigned i) const { bool lar_solver::row_is_correct(unsigned i) const {
numeric_pair<mpq> r = zero_of_type<numeric_pair<mpq>>(); numeric_pair<mpq> r = zero_of_type<numeric_pair<mpq>>();
for (const auto& c : A_r().m_rows[i]) { for (const auto& c : A_r().m_rows[i]) {
r += c.coeff() * m_mpq_lar_core_solver.m_r_x[c.var()]; r += c.coeff() * m_mpq_lar_core_solver.r_x(c.var());
} }
CTRACE("lar_solver", !is_zero(r), tout << "row = " << i << ", j = " << m_mpq_lar_core_solver.m_r_basis[i] << "\n"; CTRACE("lar_solver", !is_zero(r), tout << "row = " << i << ", j = " << m_mpq_lar_core_solver.m_r_basis[i] << "\n";
print_row(A_r().m_rows[i], tout); tout << " = " << r << "\n"); print_row(A_r().m_rows[i], tout); tout << " = " << r << "\n");
@ -932,7 +935,7 @@ namespace lp {
unsigned bj = m_mpq_lar_core_solver.m_r_solver.m_basis[i]; unsigned bj = m_mpq_lar_core_solver.m_r_solver.m_basis[i];
for (const auto& c : A_r().m_rows[i]) { for (const auto& c : A_r().m_rows[i]) {
if (c.var() == bj) continue; if (c.var() == bj) continue;
const auto& x = m_mpq_lar_core_solver.m_r_x[c.var()]; const auto& x = m_mpq_lar_core_solver.r_x(c.var());
if (!is_zero(x)) if (!is_zero(x))
r -= c.coeff() * x; r -= c.coeff() * x;
} }
@ -1170,7 +1173,7 @@ namespace lp {
if (!init_model()) if (!init_model())
return; return;
unsigned n = m_mpq_lar_core_solver.m_r_x.size(); unsigned n = m_mpq_lar_core_solver.r_x().size();
for (unsigned j = 0; j < n; j++) for (unsigned j = 0; j < n; j++)
variable_values[j] = get_value(j); variable_values[j] = get_value(j);
@ -1180,11 +1183,15 @@ namespace lp {
} }
bool lar_solver::init_model() const { bool lar_solver::init_model() const {
auto& rslv = m_mpq_lar_core_solver.m_r_solver;
lp_assert(A_r().column_count() == rslv.m_costs.size());
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.r_x().size());
lp_assert(A_r().column_count() == rslv.m_d.size());
CTRACE("lar_solver_model",!m_columns_with_changed_bounds.empty(), tout << "non-empty changed bounds\n"); CTRACE("lar_solver_model",!m_columns_with_changed_bounds.empty(), tout << "non-empty changed bounds\n");
TRACE("lar_solver_model", tout << get_status() << "\n"); TRACE("lar_solver_model", tout << get_status() << "\n");
auto status = get_status(); auto status = get_status();
SASSERT((status != lp_status::OPTIMAL && status != lp_status::FEASIBLE) SASSERT((status != lp_status::OPTIMAL && status != lp_status::FEASIBLE)
|| m_mpq_lar_core_solver.m_r_solver.calc_current_x_is_feasible_include_non_basis()); || rslv.calc_current_x_is_feasible_include_non_basis());
if (status != lp_status::OPTIMAL && status != lp_status::FEASIBLE) if (status != lp_status::OPTIMAL && status != lp_status::FEASIBLE)
return false; return false;
if (!m_columns_with_changed_bounds.empty()) if (!m_columns_with_changed_bounds.empty())
@ -1192,12 +1199,12 @@ namespace lp {
m_delta = m_mpq_lar_core_solver.find_delta_for_strict_bounds(mpq(1)); m_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.r_x().size();
do { do {
m_set_of_different_pairs.clear(); m_set_of_different_pairs.clear();
m_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.r_x(j);
mpq x = rp.x + m_delta * rp.y; mpq x = rp.x + m_delta * rp.y;
m_set_of_different_pairs.insert(rp); m_set_of_different_pairs.insert(rp);
m_set_of_different_singles.insert(x); m_set_of_different_singles.insert(x);
@ -1213,8 +1220,8 @@ namespace lp {
void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map<lpvar, mpq>& variable_values) const { void lar_solver::get_model_do_not_care_about_diff_vars(std::unordered_map<lpvar, 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.r_x().size(); i++) {
const impq& rp = m_mpq_lar_core_solver.m_r_x[i]; const impq& rp = m_mpq_lar_core_solver.r_x(i);
variable_values[i] = rp.x + delta * rp.y; variable_values[i] = rp.x + delta * rp.y;
} }
} }
@ -1229,7 +1236,7 @@ namespace lp {
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++) {
if (!m_mpq_lar_core_solver.m_r_x[j].y.is_zero()) { if (!m_mpq_lar_core_solver.r_x(j).y.is_zero()) {
y_is_zero = false; y_is_zero = false;
break; break;
} }
@ -1238,7 +1245,7 @@ namespace lp {
return; return;
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 j = 0; j < number_of_vars(); j++) { for (unsigned j = 0; j < number_of_vars(); j++) {
auto& v = m_mpq_lar_core_solver.m_r_x[j]; auto& v = m_mpq_lar_core_solver.r_x(j);
if (!v.y.is_zero()) { if (!v.y.is_zero()) {
v = impq(v.x + delta * v.y); v = impq(v.x + delta * v.y);
TRACE("lar_solver_feas", tout << "x[" << j << "] = " << v << "\n";); TRACE("lar_solver_feas", tout << "x[" << j << "] = " << v << "\n";);
@ -1448,7 +1455,7 @@ namespace lp {
void lar_solver::remove_last_column_from_tableau() { void lar_solver::remove_last_column_from_tableau() {
auto& rslv = m_mpq_lar_core_solver.m_r_solver; auto& rslv = m_mpq_lar_core_solver.m_r_solver;
unsigned j = A_r().column_count() - 1; unsigned j = A_r().column_count() - 1;
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); lp_assert(A_r().column_count() == rslv.m_costs.size());
if (column_represents_row_in_tableau(j)) { if (column_represents_row_in_tableau(j)) {
remove_last_row_and_column_from_tableau(j); remove_last_row_and_column_from_tableau(j);
if (rslv.m_basis_heading[j] < 0) if (rslv.m_basis_heading[j] < 0)
@ -1457,13 +1464,15 @@ namespace lp {
else { else {
remove_last_column_from_A(); remove_last_column_from_A();
} }
rslv.m_x.pop_back(); m_mpq_lar_core_solver.resize_x(A_r().column_count());
rslv.m_d.pop_back(); rslv.m_d.pop_back();
rslv.m_costs.pop_back(); rslv.m_costs.pop_back();
remove_last_column_from_basis_tableau(j); remove_last_column_from_basis_tableau(j);
lp_assert(m_mpq_lar_core_solver.r_basis_is_OK()); lp_assert(m_mpq_lar_core_solver.r_basis_is_OK());
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size()); lp_assert(A_r().column_count() == rslv.m_costs.size());
lp_assert(A_r().column_count() == m_mpq_lar_core_solver.r_x().size());
lp_assert(A_r().column_count() == rslv.m_d.size());
} }
@ -1611,14 +1620,15 @@ namespace lp {
unsigned j = A_r().column_count(); unsigned j = A_r().column_count();
TRACE("add_var", tout << "j = " << j << std::endl;); TRACE("add_var", tout << "j = " << j << std::endl;);
A_r().add_column(); A_r().add_column();
lp_assert(m_mpq_lar_core_solver.m_r_x.size() == j); lp_assert(m_mpq_lar_core_solver.r_x().size() == j);
// lp_assert(m_mpq_lar_core_solver.m_r_lower_bounds.size() == j && m_mpq_lar_core_solver.m_r_upper_bounds.size() == j); // restore later // lp_assert(m_mpq_lar_core_solver.m_r_lower_bounds.size() == j && m_mpq_lar_core_solver.m_r_upper_bounds.size() == j); // restore later
m_mpq_lar_core_solver.m_r_x.resize(j + 1); m_mpq_lar_core_solver.resize_x(j + 1);
auto& rslv = m_mpq_lar_core_solver.m_r_solver;
m_mpq_lar_core_solver.m_r_lower_bounds.increase_size_by_one(); m_mpq_lar_core_solver.m_r_lower_bounds.increase_size_by_one();
m_mpq_lar_core_solver.m_r_upper_bounds.increase_size_by_one(); m_mpq_lar_core_solver.m_r_upper_bounds.increase_size_by_one();
m_mpq_lar_core_solver.m_r_solver.inf_heap_increase_size_by_one(); rslv.inf_heap_increase_size_by_one();
m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1); rslv.m_costs.resize(j + 1);
m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1); rslv.m_d.resize(j + 1);
lp_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method lp_assert(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method
if (register_in_basis) { if (register_in_basis) {
A_r().add_row(); A_r().add_row();
@ -2011,13 +2021,13 @@ namespace lp {
return m_constraints.add_term_constraint(j, m_columns[j].term(), kind, rs); return m_constraints.add_term_constraint(j, m_columns[j].term(), kind, rs);
} }
struct scoped_backup { struct lar_solver::scoped_backup {
lar_solver& m_s; lar_solver& m_s;
scoped_backup(lar_solver& s) : m_s(s) { scoped_backup(lar_solver& s) : m_s(s) {
m_s.backup_x(); m_s.m_mpq_lar_core_solver.backup_x();
} }
~scoped_backup() { ~scoped_backup() {
m_s.restore_x(); m_s.m_mpq_lar_core_solver.restore_x();
} }
}; };
@ -2311,7 +2321,7 @@ namespace lp {
for (unsigned j = 0; j < column_count(); j++) { for (unsigned j = 0; j < column_count(); j++) {
if (!column_is_int(j)) continue; if (!column_is_int(j)) continue;
if (column_has_term(j)) continue; if (column_has_term(j)) continue;
impq& v = m_mpq_lar_core_solver.m_r_x[j]; impq & v = m_mpq_lar_core_solver.r_x(j);
if (v.is_int()) if (v.is_int())
continue; continue;
TRACE("cube", m_int_solver->display_column(tout, j);); TRACE("cube", m_int_solver->display_column(tout, j););
@ -2348,7 +2358,7 @@ namespace lp {
} }
} }
if (need_to_fix) { if (need_to_fix) {
impq v = t->apply(m_mpq_lar_core_solver.m_r_x); impq v = t->apply(m_mpq_lar_core_solver.r_x());
m_mpq_lar_core_solver.m_r_solver.update_x(j, v); m_mpq_lar_core_solver.m_r_solver.update_x(j, v);
} }
} }
@ -2360,7 +2370,7 @@ namespace lp {
bool lar_solver::sum_first_coords(const lar_term& t, mpq& val) const { bool lar_solver::sum_first_coords(const lar_term& t, mpq& val) const {
val = zero_of_type<mpq>(); val = zero_of_type<mpq>();
for (lar_term::ival c : t) { for (lar_term::ival c : t) {
const auto& x = m_mpq_lar_core_solver.m_r_x[c.j()]; const auto& x = m_mpq_lar_core_solver.r_x(c.j());
if (!is_zero(x.y)) if (!is_zero(x.y))
return false; return false;
val += x.x * c.coeff(); val += x.x * c.coeff();

View file

@ -105,7 +105,7 @@ class lar_solver : public column_namer {
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;
stacked_vector<unsigned> m_usage_in_terms; stacked_vector<unsigned> m_usage_in_terms;
// ((x[j], is_int(j))->j) for fixed j, used in equalities propagation // ((x[j], is_int(j))->j) for fixed j, used in equalities propagation
// maps values to integral fixed vars // maps values to integral fixed vars
@ -139,6 +139,8 @@ class lar_solver : public column_namer {
bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs); bool compare_values(impq const& lhs, lconstraint_kind k, const mpq& rhs);
inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.reset(); } inline void clear_columns_with_changed_bounds() { m_columns_with_changed_bounds.reset(); }
struct scoped_backup;
public: public:
const auto& columns_with_changed_bounds() const { return m_columns_with_changed_bounds; } const auto& columns_with_changed_bounds() const { return m_columns_with_changed_bounds; }
void insert_to_columns_with_changed_bounds(unsigned j); void insert_to_columns_with_changed_bounds(unsigned j);
@ -305,9 +307,7 @@ public:
void get_infeasibility_explanation(explanation&) const; void get_infeasibility_explanation(explanation&) const;
inline void backup_x() { m_backup_x = m_mpq_lar_core_solver.m_r_x; }
inline void restore_x() { m_mpq_lar_core_solver.m_r_x = m_backup_x; }
std::function<void(lpvar)> m_fixed_var_eh; std::function<void(lpvar)> m_fixed_var_eh;
template <typename T> template <typename T>
@ -454,7 +454,7 @@ public:
const impq& new_val, const impq& new_val,
const ChangeReport& after) { const ChangeReport& after) {
lp_assert(!is_base(j)); lp_assert(!is_base(j));
auto& x = m_mpq_lar_core_solver.m_r_x[j]; auto& x = m_mpq_lar_core_solver.r_x(j);
auto delta = new_val - x; auto delta = new_val - x;
x = new_val; x = new_val;
after(j); after(j);
@ -540,6 +540,9 @@ public:
lp_settings const& settings() const; lp_settings const& settings() const;
statistics& stats(); statistics& stats();
void backup_x() { m_mpq_lar_core_solver.backup_x(); }
void restore_x() { m_mpq_lar_core_solver.restore_x(); }
void updt_params(params_ref const& p); void updt_params(params_ref const& p);
column_type get_column_type(unsigned j) const { return m_mpq_lar_core_solver.m_column_types()[j]; } column_type get_column_type(unsigned j) const { return m_mpq_lar_core_solver.m_column_types()[j]; }
const vector<column_type>& get_column_types() const { return m_mpq_lar_core_solver.m_column_types(); } const vector<column_type>& get_column_types() const { return m_mpq_lar_core_solver.m_column_types(); }
@ -693,13 +696,13 @@ public:
void track_touched_rows(bool v); void track_touched_rows(bool v);
bool touched_rows_are_tracked() const; bool touched_rows_are_tracked() const;
~lar_solver() override; ~lar_solver() override;
const vector<impq>& r_x() const { return m_mpq_lar_core_solver.m_r_x; } const vector<impq>& r_x() const { return m_mpq_lar_core_solver.r_x(); }
bool column_is_int(unsigned j) const; bool column_is_int(unsigned j) const;
inline bool column_value_is_int(unsigned j) const { return m_mpq_lar_core_solver.m_r_x[j].is_int(); } inline bool column_value_is_int(unsigned j) const { return m_mpq_lar_core_solver.r_x(j).is_int(); }
inline static_matrix<mpq, impq>& A_r() { return m_mpq_lar_core_solver.m_r_A; } inline static_matrix<mpq, impq>& A_r() { 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; } inline const static_matrix<mpq, impq>& A_r() const { return m_mpq_lar_core_solver.m_r_A; }
// columns // columns
const impq& get_column_value(lpvar j) const { return m_mpq_lar_core_solver.m_r_x[j]; } const impq& get_column_value(lpvar j) const { return m_mpq_lar_core_solver.r_x(j); }
inline lpvar external_to_local(unsigned j) const { inline lpvar external_to_local(unsigned j) const {
lpvar local_j; lpvar local_j;
if (m_var_register.external_is_used(j, local_j)) { if (m_var_register.external_is_used(j, local_j)) {