mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 11:55:51 +00:00
591 lines
23 KiB
C++
591 lines
23 KiB
C++
/*++
|
|
Copyright (c) 2017 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
<name>
|
|
|
|
Abstract:
|
|
|
|
<abstract>
|
|
|
|
Author:
|
|
|
|
Lev Nachmanson (levnach)
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
// here we are inside lp::lar_solver class
|
|
|
|
bool strategy_is_undecided() const {
|
|
return m_settings.simplex_strategy() == simplex_strategy_enum::undecided;
|
|
}
|
|
|
|
var_index add_var(unsigned ext_j) {
|
|
var_index i;
|
|
SASSERT (ext_j < m_terms_start_index);
|
|
|
|
if (ext_j >= m_terms_start_index)
|
|
throw 0; // todo : what is the right way to exit?
|
|
|
|
if (try_get_val(m_ext_vars_to_columns, ext_j, i)) {
|
|
return i;
|
|
}
|
|
SASSERT(m_vars_to_ul_pairs.size() == A_r().column_count());
|
|
i = A_r().column_count();
|
|
m_vars_to_ul_pairs.push_back (ul_pair(static_cast<unsigned>(-1)));
|
|
add_non_basic_var_to_core_fields(ext_j);
|
|
SASSERT(sizes_are_correct());
|
|
return i;
|
|
}
|
|
|
|
void register_new_ext_var_index(unsigned ext_v) {
|
|
SASSERT(!contains(m_ext_vars_to_columns, ext_v));
|
|
unsigned j = static_cast<unsigned>(m_ext_vars_to_columns.size());
|
|
m_ext_vars_to_columns[ext_v] = j;
|
|
SASSERT(m_columns_to_ext_vars_or_term_indices.size() == j);
|
|
m_columns_to_ext_vars_or_term_indices.push_back(ext_v);
|
|
}
|
|
|
|
void add_non_basic_var_to_core_fields(unsigned ext_j) {
|
|
register_new_ext_var_index(ext_j);
|
|
m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column);
|
|
m_columns_with_changed_bound.increase_size_by_one();
|
|
add_new_var_to_core_fields_for_mpq(false);
|
|
if (use_lu())
|
|
add_new_var_to_core_fields_for_doubles(false);
|
|
}
|
|
|
|
void add_new_var_to_core_fields_for_doubles(bool register_in_basis) {
|
|
unsigned j = A_d().column_count();
|
|
A_d().add_column();
|
|
SASSERT(m_mpq_lar_core_solver.m_d_x.size() == j);
|
|
// SASSERT(m_mpq_lar_core_solver.m_d_low_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j); // restore later
|
|
m_mpq_lar_core_solver.m_d_x.resize(j + 1 );
|
|
m_mpq_lar_core_solver.m_d_low_bounds.resize(j + 1);
|
|
m_mpq_lar_core_solver.m_d_upper_bounds.resize(j + 1);
|
|
SASSERT(m_mpq_lar_core_solver.m_d_heading.size() == j); // as A().column_count() on the entry to the method
|
|
if (register_in_basis) {
|
|
A_d().add_row();
|
|
m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size());
|
|
m_mpq_lar_core_solver.m_d_basis.push_back(j);
|
|
}else {
|
|
m_mpq_lar_core_solver.m_d_heading.push_back(- static_cast<int>(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1);
|
|
m_mpq_lar_core_solver.m_d_nbasis.push_back(j);
|
|
}
|
|
}
|
|
|
|
void add_new_var_to_core_fields_for_mpq(bool register_in_basis) {
|
|
unsigned j = A_r().column_count();
|
|
A_r().add_column();
|
|
SASSERT(m_mpq_lar_core_solver.m_r_x.size() == j);
|
|
// SASSERT(m_mpq_lar_core_solver.m_r_low_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.m_r_low_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.m_inf_set.increase_size_by_one();
|
|
m_mpq_lar_core_solver.m_r_solver.m_costs.resize(j + 1);
|
|
m_mpq_lar_core_solver.m_r_solver.m_d.resize(j + 1);
|
|
SASSERT(m_mpq_lar_core_solver.m_r_heading.size() == j); // as A().column_count() on the entry to the method
|
|
if (register_in_basis) {
|
|
A_r().add_row();
|
|
m_mpq_lar_core_solver.m_r_heading.push_back(m_mpq_lar_core_solver.m_r_basis.size());
|
|
m_mpq_lar_core_solver.m_r_basis.push_back(j);
|
|
if (m_settings.bound_propagation())
|
|
m_rows_with_changed_bounds.insert(A_r().row_count() - 1);
|
|
} else {
|
|
m_mpq_lar_core_solver.m_r_heading.push_back(- static_cast<int>(m_mpq_lar_core_solver.m_r_nbasis.size()) - 1);
|
|
m_mpq_lar_core_solver.m_r_nbasis.push_back(j);
|
|
}
|
|
}
|
|
|
|
|
|
var_index add_term_undecided(const vector<std::pair<mpq, var_index>> & coeffs,
|
|
const mpq &m_v) {
|
|
m_terms.push_back(new lar_term(coeffs, m_v));
|
|
m_orig_terms.push_back(new lar_term(coeffs, m_v));
|
|
return m_terms_start_index + m_terms.size() - 1;
|
|
}
|
|
|
|
// terms
|
|
var_index add_term(const vector<std::pair<mpq, var_index>> & coeffs,
|
|
const mpq &m_v) {
|
|
if (strategy_is_undecided())
|
|
return add_term_undecided(coeffs, m_v);
|
|
|
|
m_terms.push_back(new lar_term(coeffs, m_v));
|
|
m_orig_terms.push_back(new lar_term(coeffs, m_v));
|
|
unsigned adjusted_term_index = m_terms.size() - 1;
|
|
var_index ret = m_terms_start_index + adjusted_term_index;
|
|
if (use_tableau() && !coeffs.empty()) {
|
|
add_row_for_term(m_orig_terms.back(), ret);
|
|
if (m_settings.bound_propagation())
|
|
m_rows_with_changed_bounds.insert(A_r().row_count() - 1);
|
|
}
|
|
SASSERT(m_ext_vars_to_columns.size() == A_r().column_count());
|
|
return ret;
|
|
}
|
|
|
|
void add_row_for_term(const lar_term * term, unsigned term_ext_index) {
|
|
SASSERT(sizes_are_correct());
|
|
add_row_from_term_no_constraint(term, term_ext_index);
|
|
SASSERT(sizes_are_correct());
|
|
}
|
|
|
|
void add_row_from_term_no_constraint(const lar_term * term, unsigned term_ext_index) {
|
|
register_new_ext_var_index(term_ext_index);
|
|
// j will be a new variable
|
|
unsigned j = A_r().column_count();
|
|
ul_pair ul(j);
|
|
m_vars_to_ul_pairs.push_back(ul);
|
|
add_basic_var_to_core_fields();
|
|
if (use_tableau()) {
|
|
auto it = iterator_on_term_with_basis_var(*term, j);
|
|
A_r().fill_last_row_with_pivoting(it,
|
|
m_mpq_lar_core_solver.m_r_solver.m_basis_heading);
|
|
m_mpq_lar_core_solver.m_r_solver.m_b.resize(A_r().column_count(), zero_of_type<mpq>());
|
|
} else {
|
|
fill_last_row_of_A_r(A_r(), term);
|
|
}
|
|
m_mpq_lar_core_solver.m_r_x[j] = get_basic_var_value_from_row_directly(A_r().row_count() - 1);
|
|
if (use_lu())
|
|
fill_last_row_of_A_d(A_d(), term);
|
|
}
|
|
|
|
void add_basic_var_to_core_fields() {
|
|
bool use_lu = m_mpq_lar_core_solver.need_to_presolve_with_double_solver();
|
|
SASSERT(!use_lu || A_r().column_count() == A_d().column_count());
|
|
m_mpq_lar_core_solver.m_column_types.push_back(column_type::free_column);
|
|
m_columns_with_changed_bound.increase_size_by_one();
|
|
m_rows_with_changed_bounds.increase_size_by_one();
|
|
add_new_var_to_core_fields_for_mpq(true);
|
|
if (use_lu)
|
|
add_new_var_to_core_fields_for_doubles(true);
|
|
}
|
|
|
|
constraint_index add_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side) {
|
|
constraint_index ci = m_constraints.size();
|
|
if (!is_term(j)) { // j is a var
|
|
auto vc = new lar_var_constraint(j, kind, right_side);
|
|
m_constraints.push_back(vc);
|
|
update_column_type_and_bound(j, kind, right_side, ci);
|
|
} else {
|
|
add_var_bound_on_constraint_for_term(j, kind, right_side, ci);
|
|
}
|
|
SASSERT(sizes_are_correct());
|
|
return ci;
|
|
}
|
|
|
|
void update_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_index) {
|
|
switch(m_mpq_lar_core_solver.m_column_types[j]) {
|
|
case column_type::free_column:
|
|
update_free_column_type_and_bound(j, kind, right_side, constr_index);
|
|
break;
|
|
case column_type::boxed:
|
|
update_boxed_column_type_and_bound(j, kind, right_side, constr_index);
|
|
break;
|
|
case column_type::low_bound:
|
|
update_low_bound_column_type_and_bound(j, kind, right_side, constr_index);
|
|
break;
|
|
case column_type::upper_bound:
|
|
update_upper_bound_column_type_and_bound(j, kind, right_side, constr_index);
|
|
break;
|
|
case column_type::fixed:
|
|
update_fixed_column_type_and_bound(j, kind, right_side, constr_index);
|
|
break;
|
|
default:
|
|
SASSERT(false); // cannot be here
|
|
}
|
|
}
|
|
|
|
void add_var_bound_on_constraint_for_term(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) {
|
|
SASSERT(is_term(j));
|
|
unsigned adjusted_term_index = adjust_term_index(j);
|
|
unsigned term_j;
|
|
if (try_get_val(m_ext_vars_to_columns, j, term_j)) {
|
|
mpq rs = right_side - m_orig_terms[adjusted_term_index]->m_v;
|
|
m_constraints.push_back(new lar_term_constraint(m_orig_terms[adjusted_term_index], kind, right_side));
|
|
update_column_type_and_bound(term_j, kind, rs, ci);
|
|
}
|
|
else {
|
|
add_constraint_from_term_and_create_new_column_row(j, m_orig_terms[adjusted_term_index], kind, right_side);
|
|
}
|
|
}
|
|
|
|
|
|
void add_constraint_from_term_and_create_new_column_row(unsigned term_j, const lar_term* term,
|
|
lconstraint_kind kind, const mpq & right_side) {
|
|
|
|
add_row_from_term_no_constraint(term, term_j);
|
|
unsigned j = A_r().column_count() - 1;
|
|
update_column_type_and_bound(j, kind, right_side - term->m_v, m_constraints.size());
|
|
m_constraints.push_back(new lar_term_constraint(term, kind, right_side));
|
|
SASSERT(A_r().column_count() == m_mpq_lar_core_solver.m_r_solver.m_costs.size());
|
|
}
|
|
|
|
void decide_on_strategy_and_adjust_initial_state() {
|
|
SASSERT(strategy_is_undecided());
|
|
if (m_vars_to_ul_pairs.size() > m_settings.column_number_threshold_for_using_lu_in_lar_solver) {
|
|
m_settings.simplex_strategy() = simplex_strategy_enum::lu;
|
|
} else {
|
|
m_settings.simplex_strategy() = simplex_strategy_enum::tableau_rows; // todo: when to switch to tableau_costs?
|
|
}
|
|
adjust_initial_state();
|
|
}
|
|
|
|
void adjust_initial_state() {
|
|
switch (m_settings.simplex_strategy()) {
|
|
case simplex_strategy_enum::lu:
|
|
adjust_initial_state_for_lu();
|
|
break;
|
|
case simplex_strategy_enum::tableau_rows:
|
|
adjust_initial_state_for_tableau_rows();
|
|
break;
|
|
case simplex_strategy_enum::tableau_costs:
|
|
SASSERT(false); // not implemented
|
|
case simplex_strategy_enum::undecided:
|
|
adjust_initial_state_for_tableau_rows();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void adjust_initial_state_for_lu() {
|
|
copy_from_mpq_matrix(A_d());
|
|
unsigned n = A_d().column_count();
|
|
m_mpq_lar_core_solver.m_d_x.resize(n);
|
|
m_mpq_lar_core_solver.m_d_low_bounds.resize(n);
|
|
m_mpq_lar_core_solver.m_d_upper_bounds.resize(n);
|
|
m_mpq_lar_core_solver.m_d_heading = m_mpq_lar_core_solver.m_r_heading;
|
|
m_mpq_lar_core_solver.m_d_basis = m_mpq_lar_core_solver.m_r_basis;
|
|
|
|
/*
|
|
unsigned j = A_d().column_count();
|
|
A_d().add_column();
|
|
SASSERT(m_mpq_lar_core_solver.m_d_x.size() == j);
|
|
// SASSERT(m_mpq_lar_core_solver.m_d_low_bounds.size() == j && m_mpq_lar_core_solver.m_d_upper_bounds.size() == j); // restore later
|
|
m_mpq_lar_core_solver.m_d_x.resize(j + 1 );
|
|
m_mpq_lar_core_solver.m_d_low_bounds.resize(j + 1);
|
|
m_mpq_lar_core_solver.m_d_upper_bounds.resize(j + 1);
|
|
SASSERT(m_mpq_lar_core_solver.m_d_heading.size() == j); // as A().column_count() on the entry to the method
|
|
if (register_in_basis) {
|
|
A_d().add_row();
|
|
m_mpq_lar_core_solver.m_d_heading.push_back(m_mpq_lar_core_solver.m_d_basis.size());
|
|
m_mpq_lar_core_solver.m_d_basis.push_back(j);
|
|
}else {
|
|
m_mpq_lar_core_solver.m_d_heading.push_back(- static_cast<int>(m_mpq_lar_core_solver.m_d_nbasis.size()) - 1);
|
|
m_mpq_lar_core_solver.m_d_nbasis.push_back(j);
|
|
}*/
|
|
}
|
|
|
|
void adjust_initial_state_for_tableau_rows() {
|
|
for (unsigned j = 0; j < m_terms.size(); j++) {
|
|
if (contains(m_ext_vars_to_columns, j + m_terms_start_index))
|
|
continue;
|
|
add_row_from_term_no_constraint(m_terms[j], j + m_terms_start_index);
|
|
}
|
|
}
|
|
|
|
// this fills the last row of A_d and sets the basis column: -1 in the last column of the row
|
|
void fill_last_row_of_A_d(static_matrix<double, double> & A, const lar_term* ls) {
|
|
SASSERT(A.row_count() > 0);
|
|
SASSERT(A.column_count() > 0);
|
|
unsigned last_row = A.row_count() - 1;
|
|
SASSERT(A.m_rows[last_row].empty());
|
|
|
|
for (auto & t : ls->m_coeffs) {
|
|
SASSERT(!is_zero(t.second));
|
|
var_index j = t.first;
|
|
A.set(last_row, j, - t.second.get_double());
|
|
}
|
|
|
|
unsigned basis_j = A.column_count() - 1;
|
|
A.set(last_row, basis_j, - 1 );
|
|
}
|
|
|
|
void update_free_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index constr_ind) {
|
|
mpq y_of_bound(0);
|
|
switch (kind) {
|
|
case LT:
|
|
y_of_bound = -1;
|
|
case LE:
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::upper_bound;
|
|
SASSERT(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound);
|
|
SASSERT(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j);
|
|
{
|
|
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
|
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
|
}
|
|
set_upper_bound_witness(j, constr_ind);
|
|
break;
|
|
case GT:
|
|
y_of_bound = 1;
|
|
case GE:
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::low_bound;
|
|
SASSERT(m_mpq_lar_core_solver.m_r_upper_bounds.size() > j);
|
|
{
|
|
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = low;
|
|
}
|
|
set_low_bound_witness(j, constr_ind);
|
|
break;
|
|
case EQ:
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
|
set_upper_bound_witness(j, constr_ind);
|
|
set_low_bound_witness(j, constr_ind);
|
|
break;
|
|
|
|
default:
|
|
SASSERT(false);
|
|
|
|
}
|
|
m_columns_with_changed_bound.insert(j);
|
|
}
|
|
|
|
void update_upper_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) {
|
|
SASSERT(m_mpq_lar_core_solver.m_column_types()[j] == column_type::upper_bound);
|
|
mpq y_of_bound(0);
|
|
switch (kind) {
|
|
case LT:
|
|
y_of_bound = -1;
|
|
case LE:
|
|
{
|
|
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
|
if (up < m_mpq_lar_core_solver.m_r_upper_bounds()[j]) {
|
|
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
|
set_upper_bound_witness(j, ci);
|
|
m_columns_with_changed_bound.insert(j);
|
|
}
|
|
}
|
|
break;
|
|
case GT:
|
|
y_of_bound = 1;
|
|
case GE:
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::boxed;
|
|
{
|
|
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = low;
|
|
set_low_bound_witness(j, ci);
|
|
m_columns_with_changed_bound.insert(j);
|
|
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
} else {
|
|
m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j]? column_type::boxed : column_type::fixed;
|
|
}
|
|
}
|
|
break;
|
|
case EQ:
|
|
{
|
|
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
|
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
set_low_bound_witness(j, ci);
|
|
m_infeasible_column_index = j;
|
|
} else {
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v;
|
|
m_columns_with_changed_bound.insert(j);
|
|
set_low_bound_witness(j, ci);
|
|
set_upper_bound_witness(j, ci);
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
SASSERT(false);
|
|
|
|
}
|
|
}
|
|
|
|
void update_boxed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) {
|
|
SASSERT(m_status == INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::boxed && m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j]));
|
|
mpq y_of_bound(0);
|
|
switch (kind) {
|
|
case LT:
|
|
y_of_bound = -1;
|
|
case LE:
|
|
{
|
|
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
|
if (up < m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
|
set_upper_bound_witness(j, ci);
|
|
m_columns_with_changed_bound.insert(j);
|
|
}
|
|
|
|
if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
SASSERT(false);
|
|
m_infeasible_column_index = j;
|
|
} else {
|
|
if (m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j])
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
|
}
|
|
}
|
|
break;
|
|
case GT:
|
|
y_of_bound = 1;
|
|
case GE:
|
|
{
|
|
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
|
if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = low;
|
|
m_columns_with_changed_bound.insert(j);
|
|
set_low_bound_witness(j, ci);
|
|
}
|
|
if (low > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
} else if ( low == m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
|
}
|
|
}
|
|
break;
|
|
case EQ:
|
|
{
|
|
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
|
if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_upper_bound_witness(j, ci);
|
|
} else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_low_bound_witness(j, ci);
|
|
} else {
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v;
|
|
set_low_bound_witness(j, ci);
|
|
set_upper_bound_witness(j, ci);
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
|
m_columns_with_changed_bound.insert(j);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
SASSERT(false);
|
|
|
|
}
|
|
}
|
|
void update_low_bound_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) {
|
|
SASSERT(m_mpq_lar_core_solver.m_column_types()[j] == column_type::low_bound);
|
|
mpq y_of_bound(0);
|
|
switch (kind) {
|
|
case LT:
|
|
y_of_bound = -1;
|
|
case LE:
|
|
{
|
|
auto up = numeric_pair<mpq>(right_side, y_of_bound);
|
|
m_mpq_lar_core_solver.m_r_upper_bounds[j] = up;
|
|
set_upper_bound_witness(j, ci);
|
|
m_columns_with_changed_bound.insert(j);
|
|
|
|
if (up < m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
} else {
|
|
m_mpq_lar_core_solver.m_column_types[j] = m_mpq_lar_core_solver.m_r_low_bounds()[j] < m_mpq_lar_core_solver.m_r_upper_bounds()[j]? column_type::boxed : column_type::fixed;
|
|
}
|
|
}
|
|
break;
|
|
case GT:
|
|
y_of_bound = 1;
|
|
case GE:
|
|
{
|
|
auto low = numeric_pair<mpq>(right_side, y_of_bound);
|
|
if (low > m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = low;
|
|
m_columns_with_changed_bound.insert(j);
|
|
set_low_bound_witness(j, ci);
|
|
}
|
|
}
|
|
break;
|
|
case EQ:
|
|
{
|
|
auto v = numeric_pair<mpq>(right_side, zero_of_type<mpq>());
|
|
if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_upper_bound_witness(j, ci);
|
|
} else {
|
|
m_mpq_lar_core_solver.m_r_low_bounds[j] = m_mpq_lar_core_solver.m_r_upper_bounds[j] = v;
|
|
set_low_bound_witness(j, ci);
|
|
set_upper_bound_witness(j, ci);
|
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
|
}
|
|
m_columns_with_changed_bound.insert(j);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
SASSERT(false);
|
|
|
|
}
|
|
}
|
|
|
|
void update_fixed_column_type_and_bound(var_index j, lconstraint_kind kind, const mpq & right_side, constraint_index ci) {
|
|
SASSERT(m_status == INFEASIBLE || (m_mpq_lar_core_solver.m_column_types()[j] == column_type::fixed && m_mpq_lar_core_solver.m_r_low_bounds()[j] == m_mpq_lar_core_solver.m_r_upper_bounds()[j]));
|
|
SASSERT(m_status == INFEASIBLE || (m_mpq_lar_core_solver.m_r_low_bounds()[j].y.is_zero() && m_mpq_lar_core_solver.m_r_upper_bounds()[j].y.is_zero()));
|
|
auto v = numeric_pair<mpq>(right_side, mpq(0));
|
|
|
|
mpq y_of_bound(0);
|
|
switch (kind) {
|
|
case LT:
|
|
if (v <= m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_upper_bound_witness(j, ci);
|
|
}
|
|
break;
|
|
case LE:
|
|
{
|
|
if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_upper_bound_witness(j, ci);
|
|
}
|
|
}
|
|
break;
|
|
case GT:
|
|
{
|
|
if (v >= m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index =j;
|
|
set_low_bound_witness(j, ci);
|
|
}
|
|
}
|
|
break;
|
|
case GE:
|
|
{
|
|
if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_low_bound_witness(j, ci);
|
|
}
|
|
}
|
|
break;
|
|
case EQ:
|
|
{
|
|
if (v < m_mpq_lar_core_solver.m_r_low_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_upper_bound_witness(j, ci);
|
|
} else if (v > m_mpq_lar_core_solver.m_r_upper_bounds[j]) {
|
|
m_status = INFEASIBLE;
|
|
m_infeasible_column_index = j;
|
|
set_low_bound_witness(j, ci);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
SASSERT(false);
|
|
|
|
}
|
|
}
|
|
|