mirror of
https://github.com/Z3Prover/z3
synced 2025-06-09 07:33:24 +00:00
replace lp_assert(false) with UNREACHABLE
This commit is contained in:
parent
3efe91c3e3
commit
8b0aa22631
23 changed files with 654 additions and 891 deletions
|
@ -139,7 +139,7 @@ template <typename T, typename X> void core_solver_pretty_printer<T, X>::adjust_
|
||||||
case column_type::free_column:
|
case column_type::free_column:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,9 +114,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_column_to_indexed_vector(unsigned entering, indexed_vector<mpq> &w ) const {
|
|
||||||
lp_assert(false); // not implemented
|
|
||||||
}
|
|
||||||
general_matrix operator*(const general_matrix & m) const {
|
general_matrix operator*(const general_matrix & m) const {
|
||||||
lp_assert(m.row_count() == column_count());
|
lp_assert(m.row_count() == column_count());
|
||||||
general_matrix ret(row_count(), m.column_count());
|
general_matrix ret(row_count(), m.column_count());
|
||||||
|
@ -172,23 +169,6 @@ public:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool create_upper_triangle(general_matrix& m, vector<mpq>& x) {
|
|
||||||
// for (unsigned i = 1; i < m.row_count(); i++) {
|
|
||||||
// lp_assert(false); // to be continued
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bool solve_A_x_equal_b(const general_matrix& m, vector<mpq>& x, const vector<mpq>& b) const {
|
|
||||||
// auto m_copy = m;
|
|
||||||
// // for square matrices
|
|
||||||
// lp_assert(row_count() == b.size());
|
|
||||||
// lp_assert(x.size() == column_count());
|
|
||||||
// lp_assert(row_count() == column_count());
|
|
||||||
// x = b;
|
|
||||||
// create_upper_triangle(copy_of_m, x);
|
|
||||||
// solve_on_triangle(copy_of_m, x);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
void transpose_rows(unsigned i, unsigned l) {
|
void transpose_rows(unsigned i, unsigned l) {
|
||||||
lp_assert(i != l);
|
lp_assert(i != l);
|
||||||
|
|
|
@ -44,7 +44,7 @@ inline std::string lconstraint_kind_string(lconstraint_kind t) {
|
||||||
case EQ: return std::string("=");
|
case EQ: return std::string("=");
|
||||||
case NE: return std::string("!=");
|
case NE: return std::string("!=");
|
||||||
}
|
}
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
return std::string(); // it is unreachable
|
return std::string(); // it is unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ public:
|
||||||
case column_type::fixed:
|
case column_type::fixed:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ public:
|
||||||
case column_type::fixed:
|
case column_type::fixed:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,7 +466,7 @@ namespace lp {
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lp_unreachable(); // wrong mode
|
UNREACHABLE(); // wrong mode
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -802,7 +802,7 @@ namespace lp {
|
||||||
case GT: return left_side_val > constr.rhs();
|
case GT: return left_side_val > constr.rhs();
|
||||||
case EQ: return left_side_val == constr.rhs();
|
case EQ: return left_side_val == constr.rhs();
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return false; // it is unreachable
|
return false; // it is unreachable
|
||||||
}
|
}
|
||||||
|
@ -857,7 +857,7 @@ namespace lp {
|
||||||
case EQ: lp_assert(rs != zero_of_type<mpq>());
|
case EQ: lp_assert(rs != zero_of_type<mpq>());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1816,7 +1816,7 @@ namespace lp {
|
||||||
adjust_initial_state_for_tableau_rows();
|
adjust_initial_state_for_tableau_rows();
|
||||||
break;
|
break;
|
||||||
case simplex_strategy_enum::tableau_costs:
|
case simplex_strategy_enum::tableau_costs:
|
||||||
lp_assert(false); // not implemented
|
UNREACHABLE(); // not implemented
|
||||||
case simplex_strategy_enum::undecided:
|
case simplex_strategy_enum::undecided:
|
||||||
adjust_initial_state_for_tableau_rows();
|
adjust_initial_state_for_tableau_rows();
|
||||||
break;
|
break;
|
||||||
|
@ -1905,7 +1905,7 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if (m_mpq_lar_core_solver.m_r_upper_bounds[j] == m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
if (m_mpq_lar_core_solver.m_r_upper_bounds[j] == m_mpq_lar_core_solver.m_r_lower_bounds[j]) {
|
||||||
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
m_mpq_lar_core_solver.m_column_types[j] = column_type::fixed;
|
||||||
|
@ -1959,7 +1959,7 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2009,7 +2009,7 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) {
|
void lar_solver::update_bound_with_no_ub_no_lb(var_index j, lconstraint_kind kind, const mpq& right_side, constraint_index ci) {
|
||||||
|
@ -2050,7 +2050,7 @@ namespace lp {
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ public:
|
||||||
return p.coeff().is_one();
|
return p.coeff().is_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ inline std::string lia_move_to_string(lia_move m) {
|
||||||
case lia_move::unsat:
|
case lia_move::unsat:
|
||||||
return "unsat";
|
return "unsat";
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
};
|
};
|
||||||
return "strange";
|
return "strange";
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::prin
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::basis_heading_is_correct() const ;
|
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::basis_heading_is_correct() const ;
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_dual_feasible(unsigned int) const;
|
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_dual_feasible(unsigned int) const;
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::print_statistics_with_iterations_and_nonzeroes_and_cost_and_check_that_the_time_is_over(char const*, std::ostream &);
|
||||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::set_non_basic_x_to_correct_bounds();
|
|
||||||
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::add_delta_to_entering(unsigned int, const lp::mpq&);
|
template void lp::lp_core_solver_base<lp::mpq, lp::mpq>::add_delta_to_entering(unsigned int, const lp::mpq&);
|
||||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init();
|
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init();
|
||||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init_basis_heading_and_non_basic_columns_vector();
|
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::init_basis_heading_and_non_basic_columns_vector();
|
||||||
|
@ -61,7 +60,6 @@ template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::calc
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_feasible(unsigned int) const;
|
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::column_is_feasible(unsigned int) const;
|
||||||
// template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_linear_combination_of_column_indices(vector<std::pair<lp::mpq, unsigned int>, std::allocator<std::pair<lp::mpq, unsigned int> > > const&, std::ostream&) const;
|
// template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::print_linear_combination_of_column_indices(vector<std::pair<lp::mpq, unsigned int>, std::allocator<std::pair<lp::mpq, unsigned int> > > const&, std::ostream&) const;
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::column_is_feasible(unsigned int) const;
|
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::column_is_feasible(unsigned int) const;
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::snap_non_basic_x_to_bound();
|
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq>>::pivot_column_tableau(unsigned int, unsigned int);
|
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq>>::pivot_column_tableau(unsigned int, unsigned int);
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::pivot_column_tableau(unsigned int, unsigned int);
|
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::pivot_column_tableau(unsigned int, unsigned int);
|
||||||
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::transpose_rows_tableau(unsigned int, unsigned int);
|
template void lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::transpose_rows_tableau(unsigned int, unsigned int);
|
||||||
|
@ -70,6 +68,5 @@ template bool lp::lp_core_solver_base<lp::mpq, lp::mpq>::inf_set_is_correct() co
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::infeasibility_costs_are_correct() const;
|
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::infeasibility_costs_are_correct() const;
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq >::infeasibility_costs_are_correct() const;
|
template bool lp::lp_core_solver_base<lp::mpq, lp::mpq >::infeasibility_costs_are_correct() const;
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::remove_from_basis(unsigned int);
|
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::remove_from_basis(unsigned int);
|
||||||
template bool lp::lp_core_solver_base<lp::mpq, lp::numeric_pair<lp::mpq> >::remove_from_basis(unsigned int, lp::numeric_pair<lp::mpq> const&);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -173,8 +173,6 @@ public:
|
||||||
|
|
||||||
void set_total_iterations(unsigned s) { m_total_iterations = s; }
|
void set_total_iterations(unsigned s) { m_total_iterations = s; }
|
||||||
|
|
||||||
void set_non_basic_x_to_correct_bounds();
|
|
||||||
|
|
||||||
bool at_bound(const X &x, const X & bound) const {
|
bool at_bound(const X &x, const X & bound) const {
|
||||||
return !below_bound(x, bound) && !above_bound(x, bound);
|
return !below_bound(x, bound) && !above_bound(x, bound);
|
||||||
}
|
}
|
||||||
|
@ -300,45 +298,6 @@ public:
|
||||||
|
|
||||||
std::string column_name(unsigned column) const;
|
std::string column_name(unsigned column) const;
|
||||||
|
|
||||||
bool snap_non_basic_x_to_bound() {
|
|
||||||
bool ret = false;
|
|
||||||
for (unsigned j : non_basis())
|
|
||||||
ret = snap_column_to_bound(j) || ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool snap_column_to_bound(unsigned j) {
|
|
||||||
switch (m_column_types[j]) {
|
|
||||||
case column_type::fixed:
|
|
||||||
if (x_is_at_bound(j))
|
|
||||||
break;
|
|
||||||
m_x[j] = m_lower_bounds[j];
|
|
||||||
return true;
|
|
||||||
case column_type::boxed:
|
|
||||||
if (x_is_at_bound(j))
|
|
||||||
break; // we should preserve x if possible
|
|
||||||
// snap randomly
|
|
||||||
if (m_settings.random_next() % 2 == 1)
|
|
||||||
m_x[j] = m_lower_bounds[j];
|
|
||||||
else
|
|
||||||
m_x[j] = m_upper_bounds[j];
|
|
||||||
return true;
|
|
||||||
case column_type::lower_bound:
|
|
||||||
if (x_is_at_lower_bound(j))
|
|
||||||
break;
|
|
||||||
m_x[j] = m_lower_bounds[j];
|
|
||||||
return true;
|
|
||||||
case column_type::upper_bound:
|
|
||||||
if (x_is_at_upper_bound(j))
|
|
||||||
break;
|
|
||||||
m_x[j] = m_upper_bounds[j];
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool make_column_feasible(unsigned j, numeric_pair<mpq> & delta) {
|
bool make_column_feasible(unsigned j, numeric_pair<mpq> & delta) {
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
lp_assert(m_basis_heading[j] < 0);
|
lp_assert(m_basis_heading[j] < 0);
|
||||||
|
@ -384,7 +343,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove_from_basis(unsigned j);
|
bool remove_from_basis(unsigned j);
|
||||||
bool remove_from_basis(unsigned j, const impq&);
|
|
||||||
bool pivot_column_general(unsigned j, unsigned j_basic, indexed_vector<T> & w);
|
bool pivot_column_general(unsigned j, unsigned j_basic, indexed_vector<T> & w);
|
||||||
void init_basic_part_of_basis_heading() {
|
void init_basic_part_of_basis_heading() {
|
||||||
unsigned m = m_basis.size();
|
unsigned m = m_basis.size();
|
||||||
|
@ -456,31 +414,6 @@ public:
|
||||||
change_basis_unconditionally(leaving, entering);
|
change_basis_unconditionally(leaving, entering);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool non_basic_column_is_set_correctly(unsigned j) const {
|
|
||||||
if (j >= this->m_n())
|
|
||||||
return false;
|
|
||||||
switch (this->m_column_types[j]) {
|
|
||||||
case column_type::fixed:
|
|
||||||
case column_type::boxed:
|
|
||||||
if (!this->x_is_at_bound(j))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case column_type::lower_bound:
|
|
||||||
if (!this->x_is_at_lower_bound(j))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case column_type::upper_bound:
|
|
||||||
if (!this->x_is_at_upper_bound(j))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
case column_type::free_column:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lp_assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool non_basic_columns_are_set_correctly() const {
|
bool non_basic_columns_are_set_correctly() const {
|
||||||
for (unsigned j : this->m_nbasis)
|
for (unsigned j : this->m_nbasis)
|
||||||
if (!column_is_feasible(j)) {
|
if (!column_is_feasible(j)) {
|
||||||
|
@ -540,13 +473,11 @@ public:
|
||||||
out << "[-oo, oo]";
|
out << "[-oo, oo]";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return out << "\n";
|
return out << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool column_is_free(unsigned j) const { return this->m_column_types[j] == column_type::free_column; }
|
|
||||||
|
|
||||||
bool column_is_fixed(unsigned j) const { return this->m_column_types[j] == column_type::fixed; }
|
bool column_is_fixed(unsigned j) const { return this->m_column_types[j] == column_type::fixed; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -579,16 +510,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only check for basic columns
|
|
||||||
bool calc_current_x_is_feasible() const {
|
|
||||||
unsigned i = this->m_m();
|
|
||||||
while (i--) {
|
|
||||||
if (!column_is_feasible(m_basis[i]))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void transpose_rows_tableau(unsigned i, unsigned ii);
|
void transpose_rows_tableau(unsigned i, unsigned ii);
|
||||||
|
|
||||||
void pivot_to_reduced_costs_tableau(unsigned i, unsigned j);
|
void pivot_to_reduced_costs_tableau(unsigned i, unsigned j);
|
||||||
|
|
|
@ -166,26 +166,6 @@ print_statistics_with_cost_and_check_that_the_time_is_over(X cost, std::ostream
|
||||||
return time_is_over();
|
return time_is_over();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename X> void lp_core_solver_base<T, X>::
|
|
||||||
set_non_basic_x_to_correct_bounds() {
|
|
||||||
for (unsigned j : non_basis()) {
|
|
||||||
switch (m_column_types[j]) {
|
|
||||||
case column_type::boxed:
|
|
||||||
m_x[j] = m_d[j] < 0? m_upper_bounds[j]: m_lower_bounds[j];
|
|
||||||
break;
|
|
||||||
case column_type::lower_bound:
|
|
||||||
m_x[j] = m_lower_bounds[j];
|
|
||||||
lp_assert(column_is_dual_feasible(j));
|
|
||||||
break;
|
|
||||||
case column_type::upper_bound:
|
|
||||||
m_x[j] = m_upper_bounds[j];
|
|
||||||
lp_assert(column_is_dual_feasible(j));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||||
column_is_dual_feasible(unsigned j) const {
|
column_is_dual_feasible(unsigned j) const {
|
||||||
switch (m_column_types[j]) {
|
switch (m_column_types[j]) {
|
||||||
|
@ -201,9 +181,9 @@ column_is_dual_feasible(unsigned j) const {
|
||||||
case column_type::free_column:
|
case column_type::free_column:
|
||||||
return numeric_traits<X>::is_zero(m_d[j]);
|
return numeric_traits<X>::is_zero(m_d[j]);
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
template <typename T, typename X> bool lp_core_solver_base<T, X>::
|
||||||
|
@ -257,7 +237,7 @@ template <typename T, typename X> bool lp_core_solver_base<T, X>::column_is_feas
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return false; // it is unreachable
|
return false; // it is unreachable
|
||||||
}
|
}
|
||||||
|
@ -453,18 +433,6 @@ template <typename T, typename X> bool lp_core_solver_base<T, X>::remove_from_ba
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename X> bool lp_core_solver_base<T, X>::remove_from_basis(unsigned basic_j, const impq& val) {
|
|
||||||
indexed_vector<T> w(m_basis.size()); // the buffer
|
|
||||||
unsigned i = m_basis_heading[basic_j];
|
|
||||||
for (auto &c : m_A.m_rows[i]) {
|
|
||||||
if (c.var() == basic_j)
|
|
||||||
continue;
|
|
||||||
if (pivot_column_general(c.var(), basic_j, w))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename X> bool
|
template <typename T, typename X> bool
|
||||||
lp_core_solver_base<T, X>::infeasibility_costs_are_correct() const {
|
lp_core_solver_base<T, X>::infeasibility_costs_are_correct() const {
|
||||||
|
@ -513,7 +481,7 @@ lp_core_solver_base<T, X>::infeasibility_cost_is_correct_for_column(unsigned j)
|
||||||
case column_type::free_column:
|
case column_type::free_column:
|
||||||
return is_zero(this->m_costs[j]);
|
return is_zero(this->m_costs[j]);
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,24 +19,25 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <list>
|
|
||||||
#include <limits>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include "util/vector.h"
|
|
||||||
#include <set>
|
|
||||||
#include <math.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <algorithm>
|
|
||||||
#include "math/lp/static_matrix.h"
|
|
||||||
#include "math/lp/core_solver_pretty_printer.h"
|
#include "math/lp/core_solver_pretty_printer.h"
|
||||||
#include "math/lp/lp_core_solver_base.h"
|
#include "math/lp/lp_core_solver_base.h"
|
||||||
|
#include "math/lp/static_matrix.h"
|
||||||
#include "math/lp/u_set.h"
|
#include "math/lp/u_set.h"
|
||||||
|
#include "util/vector.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <limits>
|
||||||
|
#include <list>
|
||||||
|
#include <math.h>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
namespace lp {
|
namespace lp {
|
||||||
|
|
||||||
// This core solver solves (Ax=b, lower_bound_values \leq x \leq upper_bound_values, maximize costs*x )
|
// This core solver solves (Ax=b, lower_bound_values \leq x \leq
|
||||||
// The right side b is given implicitly by x and the basis
|
// upper_bound_values, maximize costs*x ) The right side b is given implicitly
|
||||||
|
// by x and the basis
|
||||||
template <typename T, typename X>
|
template <typename T, typename X>
|
||||||
class lp_primal_core_solver : public lp_core_solver_base<T, X> {
|
class lp_primal_core_solver : public lp_core_solver_base<T, X> {
|
||||||
public:
|
public:
|
||||||
|
@ -51,10 +52,7 @@ public:
|
||||||
|
|
||||||
std::list<unsigned> m_non_basis_list;
|
std::list<unsigned> m_non_basis_list;
|
||||||
void sort_non_basis();
|
void sort_non_basis();
|
||||||
int choose_entering_column(unsigned number_of_benefitial_columns_to_go_over);
|
|
||||||
int choose_entering_column_tableau();
|
int choose_entering_column_tableau();
|
||||||
int choose_entering_column_presize(unsigned number_of_benefitial_columns_to_go_over);
|
|
||||||
|
|
||||||
|
|
||||||
bool needs_to_grow(unsigned bj) const {
|
bool needs_to_grow(unsigned bj) const {
|
||||||
lp_assert(!this->column_is_feasible(bj));
|
lp_assert(!this->column_is_feasible(bj));
|
||||||
|
@ -68,7 +66,7 @@ public:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lp_assert(false); // unreachable
|
UNREACHABLE(); // unreachable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,12 +83,10 @@ public:
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
lp_assert(false); // unreachable
|
UNREACHABLE(); // unreachable
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool monoid_can_decrease(const row_cell<T> &rc) const {
|
bool monoid_can_decrease(const row_cell<T> &rc) const {
|
||||||
unsigned j = rc.var();
|
unsigned j = rc.var();
|
||||||
lp_assert(this->column_is_feasible(j));
|
lp_assert(this->column_is_feasible(j));
|
||||||
|
@ -120,7 +116,7 @@ public:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lp_assert(false); // unreachable
|
UNREACHABLE(); // unreachable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,11 +149,12 @@ public:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lp_assert(false); // unreachable
|
UNREACHABLE(); // unreachable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned get_number_of_basic_vars_that_might_become_inf(unsigned j) const { // consider looking at the signs here: todo
|
unsigned get_number_of_basic_vars_that_might_become_inf(
|
||||||
|
unsigned j) const { // consider looking at the signs here: todo
|
||||||
unsigned r = 0;
|
unsigned r = 0;
|
||||||
for (const auto &cc : this->m_A.m_columns[j]) {
|
for (const auto &cc : this->m_A.m_columns[j]) {
|
||||||
unsigned k = this->m_basis[cc.var()];
|
unsigned k = this->m_basis[cc.var()];
|
||||||
|
@ -167,7 +164,6 @@ public:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int find_beneficial_column_in_row_tableau_rows_bland_mode(int i, T &a_ent) {
|
int find_beneficial_column_in_row_tableau_rows_bland_mode(int i, T &a_ent) {
|
||||||
int j = -1;
|
int j = -1;
|
||||||
unsigned bj = this->m_basis[i];
|
unsigned bj = this->m_basis[i];
|
||||||
|
@ -197,7 +193,8 @@ public:
|
||||||
int find_beneficial_column_in_row_tableau_rows(int i, T &a_ent) {
|
int find_beneficial_column_in_row_tableau_rows(int i, T &a_ent) {
|
||||||
if (m_bland_mode_tableau)
|
if (m_bland_mode_tableau)
|
||||||
return find_beneficial_column_in_row_tableau_rows_bland_mode(i, a_ent);
|
return find_beneficial_column_in_row_tableau_rows_bland_mode(i, a_ent);
|
||||||
// a short row produces short infeasibility explanation and benefits at least one pivot operation
|
// a short row produces short infeasibility explanation and benefits at
|
||||||
|
// least one pivot operation
|
||||||
int choice = -1;
|
int choice = -1;
|
||||||
int nchoices = 0;
|
int nchoices = 0;
|
||||||
unsigned num_of_non_free_basics = 1000000;
|
unsigned num_of_non_free_basics = 1000000;
|
||||||
|
@ -223,13 +220,13 @@ public:
|
||||||
choice = k;
|
choice = k;
|
||||||
nchoices = 1;
|
nchoices = 1;
|
||||||
} else if (damage == num_of_non_free_basics &&
|
} else if (damage == num_of_non_free_basics &&
|
||||||
this->m_A.m_columns[j].size() <= len && (this->m_settings.random_next() % (++nchoices))) {
|
this->m_A.m_columns[j].size() <= len &&
|
||||||
|
(this->m_settings.random_next() % (++nchoices))) {
|
||||||
choice = k;
|
choice = k;
|
||||||
len = this->m_A.m_columns[j].size();
|
len = this->m_A.m_columns[j].size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (choice == -1) {
|
if (choice == -1) {
|
||||||
m_inf_row_index_for_tableau = i;
|
m_inf_row_index_for_tableau = i;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -239,7 +236,8 @@ public:
|
||||||
return rc.var();
|
return rc.var();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_jump_to_another_bound_on_entering(unsigned entering, const X & theta, X & t, bool & unlimited);
|
bool try_jump_to_another_bound_on_entering(unsigned entering, const X &theta,
|
||||||
|
X &t, bool &unlimited);
|
||||||
bool try_jump_to_another_bound_on_entering_unlimited(unsigned entering, X &t);
|
bool try_jump_to_another_bound_on_entering_unlimited(unsigned entering, X &t);
|
||||||
int find_leaving_and_t_tableau(unsigned entering, X &t);
|
int find_leaving_and_t_tableau(unsigned entering, X &t);
|
||||||
|
|
||||||
|
@ -252,29 +250,37 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
void limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(
|
||||||
|
unsigned j, const T &m, X &theta, bool &unlimited) {
|
||||||
lp_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound);
|
lp_assert(m < 0 && this->m_column_types[j] == column_type::upper_bound);
|
||||||
limit_inf_on_upper_bound_m_neg(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited);
|
limit_inf_on_upper_bound_m_neg(m, this->m_x[j], this->m_upper_bounds[j],
|
||||||
|
theta, unlimited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void limit_theta_on_basis_column_for_inf_case_m_neg_lower_bound(
|
||||||
void limit_theta_on_basis_column_for_inf_case_m_neg_lower_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
unsigned j, const T &m, X &theta, bool &unlimited) {
|
||||||
lp_assert(m < 0 && this->m_column_types[j] == column_type::lower_bound);
|
lp_assert(m < 0 && this->m_column_types[j] == column_type::lower_bound);
|
||||||
limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_lower_bounds[j], theta, unlimited);
|
limit_inf_on_bound_m_neg(m, this->m_x[j], this->m_lower_bounds[j], theta,
|
||||||
|
unlimited);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void limit_theta_on_basis_column_for_inf_case_m_pos_lower_bound(
|
||||||
void limit_theta_on_basis_column_for_inf_case_m_pos_lower_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
unsigned j, const T &m, X &theta, bool &unlimited) {
|
||||||
lp_assert(m > 0 && this->m_column_types[j] == column_type::lower_bound);
|
lp_assert(m > 0 && this->m_column_types[j] == column_type::lower_bound);
|
||||||
limit_inf_on_lower_bound_m_pos(m, this->m_x[j], this->m_lower_bounds[j], theta, unlimited);
|
limit_inf_on_lower_bound_m_pos(m, this->m_x[j], this->m_lower_bounds[j],
|
||||||
|
theta, unlimited);
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(unsigned j, const T & m, X & theta, bool & unlimited) {
|
void limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(
|
||||||
|
unsigned j, const T &m, X &theta, bool &unlimited) {
|
||||||
lp_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound);
|
lp_assert(m > 0 && this->m_column_types[j] == column_type::upper_bound);
|
||||||
limit_inf_on_bound_m_pos(m, this->m_x[j], this->m_upper_bounds[j], theta, unlimited);
|
limit_inf_on_bound_m_pos(m, this->m_x[j], this->m_upper_bounds[j], theta,
|
||||||
|
unlimited);
|
||||||
};
|
};
|
||||||
|
|
||||||
void get_bound_on_variable_and_update_leaving_precisely(unsigned j, vector<unsigned> & leavings, T m, X & t, T & abs_of_d_of_leaving);
|
void get_bound_on_variable_and_update_leaving_precisely(
|
||||||
|
unsigned j, vector<unsigned> &leavings, T m, X &t,
|
||||||
|
T &abs_of_d_of_leaving);
|
||||||
|
|
||||||
X get_max_bound(vector<X> &b);
|
X get_max_bound(vector<X> &b);
|
||||||
|
|
||||||
|
@ -291,49 +297,48 @@ public:
|
||||||
|
|
||||||
// return 0 if the reduced cost at entering is close enough to the refreshed
|
// return 0 if the reduced cost at entering is close enough to the refreshed
|
||||||
// 1 if it is way off, and 2 if it is unprofitable
|
// 1 if it is way off, and 2 if it is unprofitable
|
||||||
int refresh_reduced_cost_at_entering_and_check_that_it_is_off(unsigned entering);
|
int refresh_reduced_cost_at_entering_and_check_that_it_is_off(
|
||||||
|
unsigned entering);
|
||||||
|
|
||||||
void backup_and_normalize_costs();
|
void backup_and_normalize_costs();
|
||||||
|
|
||||||
void advance_on_entering_and_leaving(int entering, int leaving, X & t);
|
|
||||||
void advance_on_entering_and_leaving_tableau(int entering, int leaving, X &t);
|
void advance_on_entering_and_leaving_tableau(int entering, int leaving, X &t);
|
||||||
void advance_on_entering_equal_leaving(int entering, X & t);
|
|
||||||
void advance_on_entering_equal_leaving_tableau(int entering, X &t);
|
void advance_on_entering_equal_leaving_tableau(int entering, X &t);
|
||||||
|
|
||||||
bool need_to_switch_costs() const {
|
bool need_to_switch_costs() const {
|
||||||
if (this->m_settings.simplex_strategy() == simplex_strategy_enum::tableau_rows)
|
if (this->m_settings.simplex_strategy() ==
|
||||||
|
simplex_strategy_enum::tableau_rows)
|
||||||
return false;
|
return false;
|
||||||
// lp_assert(calc_current_x_is_feasible() == current_x_is_feasible());
|
// lp_assert(calc_current_x_is_feasible() ==
|
||||||
|
// current_x_is_feasible());
|
||||||
return this->current_x_is_feasible() == this->using_infeas_costs();
|
return this->current_x_is_feasible() == this->using_infeas_costs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void advance_on_entering(int entering);
|
|
||||||
void advance_on_entering_tableau(int entering);
|
void advance_on_entering_tableau(int entering);
|
||||||
void advance_on_entering_precise(int entering);
|
|
||||||
void push_forward_offset_in_non_basis(unsigned &offset_in_nb);
|
void push_forward_offset_in_non_basis(unsigned &offset_in_nb);
|
||||||
|
|
||||||
unsigned get_number_of_non_basic_column_to_try_for_enter();
|
unsigned get_number_of_non_basic_column_to_try_for_enter();
|
||||||
|
|
||||||
|
|
||||||
// returns the number of iterations
|
// returns the number of iterations
|
||||||
unsigned solve();
|
unsigned solve();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void find_feasible_solution();
|
void find_feasible_solution();
|
||||||
|
|
||||||
// bool is_tiny() const {return this->m_m < 10 && this->m_n < 20;}
|
// bool is_tiny() const {return this->m_m < 10 && this->m_n < 20;}
|
||||||
|
|
||||||
void one_iteration_tableau();
|
void one_iteration_tableau();
|
||||||
|
|
||||||
// this version assumes that the leaving already has the right value, and does not update it
|
// this version assumes that the leaving already has the right value, and does
|
||||||
void update_x_tableau_rows(unsigned entering, unsigned leaving, const X& delta) {
|
// not update it
|
||||||
|
void update_x_tableau_rows(unsigned entering, unsigned leaving,
|
||||||
|
const X &delta) {
|
||||||
this->add_delta_to_x(entering, delta);
|
this->add_delta_to_x(entering, delta);
|
||||||
if (!this->using_infeas_costs()) {
|
if (!this->using_infeas_costs()) {
|
||||||
for (const auto &c : this->m_A.m_columns[entering]) {
|
for (const auto &c : this->m_A.m_columns[entering]) {
|
||||||
if (leaving != this->m_basis[c.var()]) {
|
if (leaving != this->m_basis[c.var()]) {
|
||||||
this->add_delta_to_x_and_track_feasibility(this->m_basis[c.var()], - delta * this->m_A.get_val(c));
|
this->add_delta_to_x_and_track_feasibility(
|
||||||
|
this->m_basis[c.var()], -delta * this->m_A.get_val(c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // using_infeas_costs() == true
|
} else { // using_infeas_costs() == true
|
||||||
|
@ -360,8 +365,8 @@ public:
|
||||||
this->change_basis(entering, leaving);
|
this->change_basis(entering, leaving);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void advance_on_entering_and_leaving_tableau_rows(int entering, int leaving,
|
||||||
void advance_on_entering_and_leaving_tableau_rows(int entering, int leaving, const X &theta ) {
|
const X &theta) {
|
||||||
update_basis_and_x_tableau_rows(entering, leaving, theta);
|
update_basis_and_x_tableau_rows(entering, leaving, theta);
|
||||||
this->track_column_feasibility(entering);
|
this->track_column_feasibility(entering);
|
||||||
}
|
}
|
||||||
|
@ -397,7 +402,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void one_iteration_tableau_rows() {
|
void one_iteration_tableau_rows() {
|
||||||
int leaving = find_smallest_inf_column();
|
int leaving = find_smallest_inf_column();
|
||||||
if (leaving == -1) {
|
if (leaving == -1) {
|
||||||
|
@ -417,7 +421,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
T a_ent;
|
T a_ent;
|
||||||
int entering = find_beneficial_column_in_row_tableau_rows(this->m_basis_heading[leaving], a_ent);
|
int entering = find_beneficial_column_in_row_tableau_rows(
|
||||||
|
this->m_basis_heading[leaving], a_ent);
|
||||||
if (entering == -1) {
|
if (entering == -1) {
|
||||||
this->set_status(lp_status::INFEASIBLE);
|
this->set_status(lp_status::INFEASIBLE);
|
||||||
return;
|
return;
|
||||||
|
@ -433,19 +438,24 @@ public:
|
||||||
|
|
||||||
void decide_on_status_when_cannot_find_entering() {
|
void decide_on_status_when_cannot_find_entering() {
|
||||||
lp_assert(!need_to_switch_costs());
|
lp_assert(!need_to_switch_costs());
|
||||||
this->set_status(this->current_x_is_feasible()? lp_status::OPTIMAL: lp_status::INFEASIBLE);
|
this->set_status(this->current_x_is_feasible() ? lp_status::OPTIMAL
|
||||||
|
: lp_status::INFEASIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_theta_on_basis_column_for_feas_case_m_neg_no_check(unsigned j, const T & m, X & theta, bool & unlimited) {
|
void limit_theta_on_basis_column_for_feas_case_m_neg_no_check(
|
||||||
|
unsigned j, const T &m, X &theta, bool &unlimited) {
|
||||||
lp_assert(m < 0);
|
lp_assert(m < 0);
|
||||||
limit_theta((this->m_lower_bounds[j] - this->m_x[j]) / m, theta, unlimited);
|
limit_theta((this->m_lower_bounds[j] - this->m_x[j]) / m, theta, unlimited);
|
||||||
if (theta < zero_of_type<X>()) theta = zero_of_type<X>();
|
if (theta < zero_of_type<X>())
|
||||||
|
theta = zero_of_type<X>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool limit_inf_on_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
bool limit_inf_on_bound_m_neg(const T &m, const X &x, const X &bound,
|
||||||
|
X &theta, bool &unlimited) {
|
||||||
// x gets smaller
|
// x gets smaller
|
||||||
lp_assert(m < 0);
|
lp_assert(m < 0);
|
||||||
if (this->below_bound(x, bound)) return false;
|
if (this->below_bound(x, bound))
|
||||||
|
return false;
|
||||||
if (this->above_bound(x, bound)) {
|
if (this->above_bound(x, bound)) {
|
||||||
limit_theta((bound - x) / m, theta, unlimited);
|
limit_theta((bound - x) / m, theta, unlimited);
|
||||||
} else {
|
} else {
|
||||||
|
@ -455,10 +465,12 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool limit_inf_on_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
bool limit_inf_on_bound_m_pos(const T &m, const X &x, const X &bound,
|
||||||
|
X &theta, bool &unlimited) {
|
||||||
// x gets larger
|
// x gets larger
|
||||||
lp_assert(m > 0);
|
lp_assert(m > 0);
|
||||||
if (this->above_bound(x, bound)) return false;
|
if (this->above_bound(x, bound))
|
||||||
|
return false;
|
||||||
if (this->below_bound(x, bound)) {
|
if (this->below_bound(x, bound)) {
|
||||||
limit_theta((bound - x) / m, theta, unlimited);
|
limit_theta((bound - x) / m, theta, unlimited);
|
||||||
} else {
|
} else {
|
||||||
|
@ -469,16 +481,17 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_inf_on_lower_bound_m_pos(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
void limit_inf_on_lower_bound_m_pos(const T &m, const X &x, const X &bound,
|
||||||
|
X &theta, bool &unlimited) {
|
||||||
// x gets larger
|
// x gets larger
|
||||||
lp_assert(m > 0);
|
lp_assert(m > 0);
|
||||||
if (this->below_bound(x, bound)) {
|
if (this->below_bound(x, bound)) {
|
||||||
limit_theta((bound - x) / m, theta, unlimited);
|
limit_theta((bound - x) / m, theta, unlimited);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_inf_on_upper_bound_m_neg(const T & m, const X & x, const X & bound, X & theta, bool & unlimited) {
|
void limit_inf_on_upper_bound_m_neg(const T &m, const X &x, const X &bound,
|
||||||
|
X &theta, bool &unlimited) {
|
||||||
// x gets smaller
|
// x gets smaller
|
||||||
lp_assert(m < 0);
|
lp_assert(m < 0);
|
||||||
if (this->above_bound(x, bound)) {
|
if (this->above_bound(x, bound)) {
|
||||||
|
@ -486,7 +499,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_theta_on_basis_column_for_inf_case_m_pos_boxed(unsigned j, const T & m, X & theta, bool & unlimited) {
|
void limit_theta_on_basis_column_for_inf_case_m_pos_boxed(unsigned j,
|
||||||
|
const T &m,
|
||||||
|
X &theta,
|
||||||
|
bool &unlimited) {
|
||||||
const X &x = this->m_x[j];
|
const X &x = this->m_x[j];
|
||||||
const X &lbound = this->m_lower_bounds[j];
|
const X &lbound = this->m_lower_bounds[j];
|
||||||
|
|
||||||
|
@ -503,7 +519,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void limit_theta_on_basis_column_for_inf_case_m_neg_boxed(unsigned j, const T & m, X & theta, bool & unlimited) {
|
void limit_theta_on_basis_column_for_inf_case_m_neg_boxed(unsigned j,
|
||||||
|
const T &m,
|
||||||
|
X &theta,
|
||||||
|
bool &unlimited) {
|
||||||
// lp_assert(m < 0 && this->m_column_type[j] == column_type::boxed);
|
// lp_assert(m < 0 && this->m_column_type[j] == column_type::boxed);
|
||||||
const X &x = this->m_x[j];
|
const X &x = this->m_x[j];
|
||||||
const X &ubound = this->m_upper_bounds[j];
|
const X &ubound = this->m_upper_bounds[j];
|
||||||
|
@ -519,18 +538,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void limit_theta_on_basis_column_for_feas_case_m_pos(unsigned j, const T & m, X & theta, bool & unlimited) {
|
|
||||||
lp_assert(m > 0);
|
|
||||||
if (this->below_bound(this->m_x[j], this->m_upper_bounds[j])) {
|
|
||||||
limit_theta((this->m_upper_bounds[j] - this->m_x[j]) / m, theta, unlimited);
|
|
||||||
if (theta < zero_of_type<X>()) {
|
|
||||||
theta = zero_of_type<X>();
|
|
||||||
unlimited = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void limit_theta_on_basis_column_for_feas_case_m_pos_no_check(unsigned j, const T & m, X & theta, bool & unlimited ) {
|
void limit_theta_on_basis_column_for_feas_case_m_pos_no_check(
|
||||||
|
unsigned j, const T &m, X &theta, bool &unlimited) {
|
||||||
lp_assert(m > 0);
|
lp_assert(m > 0);
|
||||||
limit_theta((this->m_upper_bounds[j] - this->m_x[j]) / m, theta, unlimited);
|
limit_theta((this->m_upper_bounds[j] - this->m_x[j]) / m, theta, unlimited);
|
||||||
if (theta < zero_of_type<X>()) {
|
if (theta < zero_of_type<X>()) {
|
||||||
|
@ -545,27 +555,34 @@ public:
|
||||||
// x[j] + t * m <= this->m_upper_bounds[j] ( if m > 0)
|
// x[j] + t * m <= this->m_upper_bounds[j] ( if m > 0)
|
||||||
void limit_theta_on_basis_column(unsigned j, T m, X &theta, bool &unlimited) {
|
void limit_theta_on_basis_column(unsigned j, T m, X &theta, bool &unlimited) {
|
||||||
switch (this->m_column_types[j]) {
|
switch (this->m_column_types[j]) {
|
||||||
case column_type::free_column: break;
|
case column_type::free_column:
|
||||||
|
break;
|
||||||
case column_type::upper_bound:
|
case column_type::upper_bound:
|
||||||
if (this->current_x_is_feasible()) {
|
if (this->current_x_is_feasible()) {
|
||||||
if (m > 0)
|
if (m > 0)
|
||||||
limit_theta_on_basis_column_for_feas_case_m_pos_no_check(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_feas_case_m_pos_no_check(j, m, theta,
|
||||||
|
unlimited);
|
||||||
} else { // inside of feasibility_loop
|
} else { // inside of feasibility_loop
|
||||||
if (m > 0)
|
if (m > 0)
|
||||||
limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_inf_case_m_pos_upper_bound(
|
||||||
|
j, m, theta, unlimited);
|
||||||
else
|
else
|
||||||
limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_inf_case_m_neg_upper_bound(
|
||||||
|
j, m, theta, unlimited);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case column_type::lower_bound:
|
case column_type::lower_bound:
|
||||||
if (this->current_x_is_feasible()) {
|
if (this->current_x_is_feasible()) {
|
||||||
if (m < 0)
|
if (m < 0)
|
||||||
limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta,
|
||||||
|
unlimited);
|
||||||
} else {
|
} else {
|
||||||
if (m < 0)
|
if (m < 0)
|
||||||
limit_theta_on_basis_column_for_inf_case_m_neg_lower_bound(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_inf_case_m_neg_lower_bound(
|
||||||
|
j, m, theta, unlimited);
|
||||||
else
|
else
|
||||||
limit_theta_on_basis_column_for_inf_case_m_pos_lower_bound(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_inf_case_m_pos_lower_bound(
|
||||||
|
j, m, theta, unlimited);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// case fixed:
|
// case fixed:
|
||||||
|
@ -574,39 +591,42 @@ public:
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// if (m < 0)
|
// if (m < 0)
|
||||||
// limit_theta_on_basis_column_for_inf_case_m_neg_fixed(j, m, theta);
|
// limit_theta_on_basis_column_for_inf_case_m_neg_fixed(j, m,
|
||||||
|
// theta);
|
||||||
// else
|
// else
|
||||||
// limit_theta_on_basis_column_for_inf_case_m_pos_fixed(j, m, theta);
|
// limit_theta_on_basis_column_for_inf_case_m_pos_fixed(j, m,
|
||||||
|
// theta);
|
||||||
// break;
|
// break;
|
||||||
case column_type::fixed:
|
case column_type::fixed:
|
||||||
case column_type::boxed:
|
case column_type::boxed:
|
||||||
if (this->current_x_is_feasible()) {
|
if (this->current_x_is_feasible()) {
|
||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
limit_theta_on_basis_column_for_feas_case_m_pos_no_check(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_feas_case_m_pos_no_check(j, m, theta,
|
||||||
|
unlimited);
|
||||||
} else {
|
} else {
|
||||||
limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_feas_case_m_neg_no_check(j, m, theta,
|
||||||
|
unlimited);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (m > 0) {
|
if (m > 0) {
|
||||||
limit_theta_on_basis_column_for_inf_case_m_pos_boxed(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_inf_case_m_pos_boxed(j, m, theta,
|
||||||
|
unlimited);
|
||||||
} else {
|
} else {
|
||||||
limit_theta_on_basis_column_for_inf_case_m_neg_boxed(j, m, theta, unlimited);
|
limit_theta_on_basis_column_for_inf_case_m_neg_boxed(j, m, theta,
|
||||||
|
unlimited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if (!unlimited && theta < zero_of_type<X>()) {
|
if (!unlimited && theta < zero_of_type<X>()) {
|
||||||
theta = zero_of_type<X>();
|
theta = zero_of_type<X>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool column_is_benefitial_for_entering_basis(unsigned j) const;
|
bool column_is_benefitial_for_entering_basis(unsigned j) const;
|
||||||
bool column_is_benefitial_for_entering_basis_precise(unsigned j) const;
|
|
||||||
bool can_enter_basis(unsigned j);
|
|
||||||
void init_infeasibility_costs();
|
void init_infeasibility_costs();
|
||||||
|
|
||||||
void init_infeasibility_cost_for_column(unsigned j);
|
void init_infeasibility_cost_for_column(unsigned j);
|
||||||
|
@ -619,7 +639,6 @@ public:
|
||||||
|
|
||||||
bool basis_column_is_set_correctly(unsigned j) const {
|
bool basis_column_is_set_correctly(unsigned j) const {
|
||||||
return this->m_A.m_columns[j].size() == 1;
|
return this->m_A.m_columns[j].size() == 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool basis_columns_are_set_correctly() const {
|
bool basis_columns_are_set_correctly() const {
|
||||||
|
@ -627,7 +646,8 @@ public:
|
||||||
if (!basis_column_is_set_correctly(j))
|
if (!basis_column_is_set_correctly(j))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return this->m_basis_heading.size() == this->m_A.column_count() && this->m_basis.size() == this->m_A.row_count();
|
return this->m_basis_heading.size() == this->m_A.column_count() &&
|
||||||
|
this->m_basis.size() == this->m_A.row_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_run_tableau();
|
void init_run_tableau();
|
||||||
|
@ -635,7 +655,8 @@ public:
|
||||||
void update_inf_cost_for_column_tableau(unsigned j);
|
void update_inf_cost_for_column_tableau(unsigned j);
|
||||||
|
|
||||||
// the delta is between the old and the new cost (old - new)
|
// the delta is between the old and the new cost (old - new)
|
||||||
void update_reduced_cost_for_basic_column_cost_change(const T & delta, unsigned j) {
|
void update_reduced_cost_for_basic_column_cost_change(const T &delta,
|
||||||
|
unsigned j) {
|
||||||
lp_assert(this->m_basis_heading[j] >= 0);
|
lp_assert(this->m_basis_heading[j] >= 0);
|
||||||
unsigned i = static_cast<unsigned>(this->m_basis_heading[j]);
|
unsigned i = static_cast<unsigned>(this->m_basis_heading[j]);
|
||||||
for (const row_cell<T> &rc : this->m_A.m_rows[i]) {
|
for (const row_cell<T> &rc : this->m_A.m_rows[i]) {
|
||||||
|
@ -655,68 +676,23 @@ public:
|
||||||
m_left_basis_repeated = 0;
|
m_left_basis_repeated = 0;
|
||||||
}
|
}
|
||||||
// stage1 constructor
|
// stage1 constructor
|
||||||
lp_primal_core_solver(static_matrix<T, X> & A,
|
lp_primal_core_solver(
|
||||||
|
static_matrix<T, X> &A,
|
||||||
vector<X> &b, // the right side vector
|
vector<X> &b, // the right side vector
|
||||||
vector<X> & x, // the number of elements in x needs to be at least as large as the number of columns in A
|
vector<X> &x, // the number of elements in x needs to be at least as large
|
||||||
vector<unsigned> & basis,
|
// as the number of columns in A
|
||||||
vector<unsigned> & nbasis,
|
vector<unsigned> &basis, vector<unsigned> &nbasis, vector<int> &heading,
|
||||||
vector<int> & heading,
|
vector<T> &costs, const vector<column_type> &column_type_array,
|
||||||
vector<T> & costs,
|
const vector<X> &lower_bound_values, const vector<X> &upper_bound_values,
|
||||||
const vector<column_type> & column_type_array,
|
lp_settings &settings, const column_namer &column_names)
|
||||||
const vector<X> & lower_bound_values,
|
: lp_core_solver_base<T, X>(A, // b,
|
||||||
const vector<X> & upper_bound_values,
|
basis, nbasis, heading, x, costs, settings,
|
||||||
lp_settings & settings,
|
column_names, column_type_array,
|
||||||
const column_namer& column_names):
|
lower_bound_values, upper_bound_values),
|
||||||
lp_core_solver_base<T, X>(A, // b,
|
|
||||||
basis,
|
|
||||||
nbasis,
|
|
||||||
heading,
|
|
||||||
x,
|
|
||||||
costs,
|
|
||||||
settings,
|
|
||||||
column_names,
|
|
||||||
column_type_array,
|
|
||||||
lower_bound_values,
|
|
||||||
upper_bound_values),
|
|
||||||
m_bland_mode_threshold(1000) {
|
m_bland_mode_threshold(1000) {
|
||||||
this->set_status(lp_status::UNKNOWN);
|
this->set_status(lp_status::UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool initial_x_is_correct() {
|
|
||||||
std::set<unsigned> basis_set;
|
|
||||||
for (unsigned i = 0; i < this->m_A.row_count(); i++) {
|
|
||||||
basis_set.insert(this->m_basis[i]);
|
|
||||||
}
|
|
||||||
for (unsigned j = 0; j < this->m_n(); j++) {
|
|
||||||
if (this->column_has_lower_bound(j) && this->m_x[j] < numeric_traits<T>::zero()) {
|
|
||||||
LP_OUT(this->m_settings, "low bound for variable " << j << " does not hold: this->m_x[" << j << "] = " << this->m_x[j] << " is negative " << std::endl);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->column_has_upper_bound(j) && this->m_x[j] > this->m_upper_bounds[j]) {
|
|
||||||
LP_OUT(this->m_settings, "upper bound for " << j << " does not hold: " << this->m_upper_bounds[j] << ">" << this->m_x[j] << std::endl);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (basis_set.find(j) != basis_set.end()) continue;
|
|
||||||
if (this->m_column_types[j] == column_type::lower_bound) {
|
|
||||||
if (numeric_traits<T>::zero() != this->m_x[j]) {
|
|
||||||
LP_OUT(this->m_settings, "only low bound is set for " << j << " but low bound value " << numeric_traits<T>::zero() << " is not equal to " << this->m_x[j] << std::endl);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this->m_column_types[j] == column_type::boxed) {
|
|
||||||
if (this->m_upper_bounds[j] != this->m_x[j] && !numeric_traits<T>::is_zero(this->m_x[j])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
friend core_solver_pretty_printer<T, X>;
|
friend core_solver_pretty_printer<T, X>;
|
||||||
};
|
};
|
||||||
}
|
} // namespace lp
|
||||||
|
|
|
@ -53,10 +53,6 @@ void lp_primal_core_solver<T, X>::sort_non_basis() {
|
||||||
|
|
||||||
template <typename T, typename X>
|
template <typename T, typename X>
|
||||||
bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis(unsigned j) const {
|
bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis(unsigned j) const {
|
||||||
return column_is_benefitial_for_entering_basis_precise(j);
|
|
||||||
}
|
|
||||||
template <typename T, typename X>
|
|
||||||
bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precise(unsigned j) const {
|
|
||||||
const T& dj = this->m_d[j];
|
const T& dj = this->m_d[j];
|
||||||
TRACE("lar_solver", tout << "dj=" << dj << "\n";);
|
TRACE("lar_solver", tout << "dj=" << dj << "\n";);
|
||||||
switch (this->m_column_types[j]) {
|
switch (this->m_column_types[j]) {
|
||||||
|
@ -88,56 +84,12 @@ bool lp_primal_core_solver<T, X>::column_is_benefitial_for_entering_basis_precis
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename X>
|
|
||||||
int lp_primal_core_solver<T, X>::choose_entering_column_presize(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1)
|
|
||||||
if (number_of_benefitial_columns_to_go_over == 0)
|
|
||||||
return -1;
|
|
||||||
if (this->m_basis_sort_counter == 0) {
|
|
||||||
sort_non_basis();
|
|
||||||
this->m_basis_sort_counter = 20;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this->m_basis_sort_counter--;
|
|
||||||
}
|
|
||||||
unsigned j_nz = this->m_m() + 1; // this number is greater than the max column size
|
|
||||||
std::list<unsigned>::iterator entering_iter = m_non_basis_list.end();
|
|
||||||
for (auto non_basis_iter = m_non_basis_list.begin(); number_of_benefitial_columns_to_go_over && non_basis_iter != m_non_basis_list.end(); ++non_basis_iter) {
|
|
||||||
unsigned j = *non_basis_iter;
|
|
||||||
if (!column_is_benefitial_for_entering_basis(j))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// if we are here then j is a candidate to enter the basis
|
|
||||||
unsigned t = this->m_columns_nz[j];
|
|
||||||
if (t < j_nz) {
|
|
||||||
j_nz = t;
|
|
||||||
entering_iter = non_basis_iter;
|
|
||||||
if (number_of_benefitial_columns_to_go_over)
|
|
||||||
number_of_benefitial_columns_to_go_over--;
|
|
||||||
} else if (t == j_nz && this->m_settings.random_next() % 2 == 0) {
|
|
||||||
entering_iter = non_basis_iter;
|
|
||||||
}
|
|
||||||
}// while (number_of_benefitial_columns_to_go_over && initial_offset_in_non_basis != offset_in_nb);
|
|
||||||
if (entering_iter == m_non_basis_list.end())
|
|
||||||
return -1;
|
|
||||||
unsigned entering = *entering_iter;
|
|
||||||
m_sign_of_entering_delta = this->m_d[entering] > 0 ? 1 : -1;
|
|
||||||
m_non_basis_list.erase(entering_iter);
|
|
||||||
m_non_basis_list.push_back(entering);
|
|
||||||
return entering;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename X>
|
|
||||||
int lp_primal_core_solver<T, X>::choose_entering_column(unsigned number_of_benefitial_columns_to_go_over) { // at this moment m_y = cB * B(-1)
|
|
||||||
return choose_entering_column_presize(number_of_benefitial_columns_to_go_over);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_another_bound_on_entering(unsigned entering,
|
template <typename T, typename X> bool lp_primal_core_solver<T, X>::try_jump_to_another_bound_on_entering(unsigned entering,
|
||||||
const X & theta,
|
const X & theta,
|
||||||
X & t,
|
X & t,
|
||||||
|
@ -278,24 +230,6 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::backup_an
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename X>
|
|
||||||
void lp_primal_core_solver<T, X>::advance_on_entering_equal_leaving(int entering, X & t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename X>void lp_primal_core_solver<T, X>::advance_on_entering_and_leaving(int entering, int leaving, X & t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_entering_precise(int entering) {
|
|
||||||
lp_assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::advance_on_entering(int entering) {
|
|
||||||
lp_assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename X> void lp_primal_core_solver<T, X>::push_forward_offset_in_non_basis(unsigned & offset_in_nb) {
|
template <typename T, typename X> void lp_primal_core_solver<T, X>::push_forward_offset_in_non_basis(unsigned & offset_in_nb) {
|
||||||
if (++offset_in_nb == this->m_nbasis.size())
|
if (++offset_in_nb == this->m_nbasis.size())
|
||||||
offset_in_nb = 0;
|
offset_in_nb = 0;
|
||||||
|
@ -377,7 +311,7 @@ lp_primal_core_solver<T, X>::get_infeasibility_cost_for_column(unsigned j) const
|
||||||
ret = numeric_traits<T>::zero();
|
ret = numeric_traits<T>::zero();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
ret = numeric_traits<T>::zero(); // does not matter
|
ret = numeric_traits<T>::zero(); // does not matter
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -427,7 +361,7 @@ lp_primal_core_solver<T, X>::init_infeasibility_cost_for_column(unsigned j) {
|
||||||
this->m_costs[j] = numeric_traits<T>::zero();
|
this->m_costs[j] = numeric_traits<T>::zero();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +392,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_column
|
||||||
out << "( _" << this->m_x[j] << "_)" << std::endl;
|
out << "( _" << this->m_x[j] << "_)" << std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +414,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::print_bound_
|
||||||
out << "inf, inf" << std::endl;
|
out << "inf, inf" << std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ unsigned lp_primal_core_solver<T, X>::solve() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case lp_status::TENTATIVE_UNBOUNDED:
|
case lp_status::TENTATIVE_UNBOUNDED:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
case lp_status::UNBOUNDED:
|
case lp_status::UNBOUNDED:
|
||||||
if (this->current_x_is_infeasible()) {
|
if (this->current_x_is_infeasible()) {
|
||||||
|
@ -132,7 +132,7 @@ unsigned lp_primal_core_solver<T, X>::solve() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lp_status::UNSTABLE:
|
case lp_status::UNSTABLE:
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -31,7 +31,7 @@ std::string column_type_to_string(column_type t) {
|
||||||
case column_type::lower_bound: return "lower_bound";
|
case column_type::lower_bound: return "lower_bound";
|
||||||
case column_type::upper_bound: return "upper_bound";
|
case column_type::upper_bound: return "upper_bound";
|
||||||
case column_type::free_column: return "free_column";
|
case column_type::free_column: return "free_column";
|
||||||
default: lp_unreachable();
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
return "unknown"; // it is unreachable
|
return "unknown"; // it is unreachable
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ const char* lp_status_to_string(lp_status status) {
|
||||||
case lp_status::UNSTABLE: return "UNSTABLE";
|
case lp_status::UNSTABLE: return "UNSTABLE";
|
||||||
case lp_status::CANCELLED: return "CANCELLED";
|
case lp_status::CANCELLED: return "CANCELLED";
|
||||||
default:
|
default:
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
return "UNKNOWN"; // it is unreachable
|
return "UNKNOWN"; // it is unreachable
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ lp_status lp_status_from_string(std::string status) {
|
||||||
if (status == "FEASIBLE") return lp_status::FEASIBLE;
|
if (status == "FEASIBLE") return lp_status::FEASIBLE;
|
||||||
if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED;
|
if (status == "TIME_EXHAUSTED") return lp_status::TIME_EXHAUSTED;
|
||||||
if (status == "EMPTY") return lp_status::EMPTY;
|
if (status == "EMPTY") return lp_status::EMPTY;
|
||||||
lp_unreachable();
|
UNREACHABLE();
|
||||||
return lp_status::UNKNOWN; // it is unreachable
|
return lp_status::UNKNOWN; // it is unreachable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,6 @@ inline void throw_exception(std::string && str) {
|
||||||
typedef z3_exception exception;
|
typedef z3_exception exception;
|
||||||
|
|
||||||
#define lp_assert(_x_) { SASSERT(_x_); }
|
#define lp_assert(_x_) { SASSERT(_x_); }
|
||||||
inline void lp_unreachable() { lp_assert(false); }
|
|
||||||
template <typename X> inline X zero_of_type() { return numeric_traits<X>::zero(); }
|
template <typename X> inline X zero_of_type() { return numeric_traits<X>::zero(); }
|
||||||
template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); }
|
template <typename X> inline X one_of_type() { return numeric_traits<X>::one(); }
|
||||||
template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); }
|
template <typename X> inline bool is_zero(const X & v) { return numeric_traits<X>::is_zero(v); }
|
||||||
|
|
|
@ -171,7 +171,7 @@ struct solver::imp {
|
||||||
lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even);
|
lit = m_nlsat->mk_ineq_literal(nlsat::atom::kind::EQ, 1, ps, is_even);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
lp_assert(false); // unreachable
|
UNREACHABLE(); // unreachable
|
||||||
}
|
}
|
||||||
m_nlsat->mk_clause(1, &lit, a);
|
m_nlsat->mk_clause(1, &lit, a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,8 @@ public:
|
||||||
template <typename X, typename Y>
|
template <typename X, typename Y>
|
||||||
struct convert_struct {
|
struct convert_struct {
|
||||||
static X convert(const Y & y){ return X(y);}
|
static X convert(const Y & y){ return X(y);}
|
||||||
static bool below_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false;}
|
static bool below_bound_numeric(const X &, const X &, const Y &) { /*UNREACHABLE();*/ return false;}
|
||||||
static bool above_bound_numeric(const X &, const X &, const Y &) { /*lp_unreachable();*/ return false; }
|
static bool above_bound_numeric(const X &, const X &, const Y &) { /*UNREACHABLE();*/ return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ struct numeric_pair {
|
||||||
}
|
}
|
||||||
|
|
||||||
numeric_pair operator/(const numeric_pair &) const {
|
numeric_pair operator/(const numeric_pair &) const {
|
||||||
// lp_unreachable();
|
// UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -199,7 +199,7 @@ struct numeric_pair {
|
||||||
}
|
}
|
||||||
|
|
||||||
numeric_pair operator*(const numeric_pair & /*a*/) const {
|
numeric_pair operator*(const numeric_pair & /*a*/) const {
|
||||||
// lp_unreachable();
|
// UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
numeric_pair& operator+=(const numeric_pair & a) {
|
numeric_pair& operator+=(const numeric_pair & a) {
|
||||||
|
@ -275,14 +275,14 @@ numeric_pair<T> operator/(const numeric_pair<T> & r, const X & a) {
|
||||||
return numeric_pair<T>(r.x / a, r.y / a);
|
return numeric_pair<T>(r.x / a, r.y / a);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> double get_double(const lp::numeric_pair<T> & ) { /* lp_unreachable(); */ return 0;}
|
template <typename T> double get_double(const lp::numeric_pair<T> & ) { /* UNREACHABLE(); */ return 0;}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class numeric_traits<lp::numeric_pair<T>> {
|
class numeric_traits<lp::numeric_pair<T>> {
|
||||||
public:
|
public:
|
||||||
static lp::numeric_pair<T> zero() { return lp::numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); }
|
static lp::numeric_pair<T> zero() { return lp::numeric_pair<T>(numeric_traits<T>::zero(), numeric_traits<T>::zero()); }
|
||||||
static bool is_zero(const lp::numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); }
|
static bool is_zero(const lp::numeric_pair<T> & v) { return numeric_traits<T>::is_zero(v.x) && numeric_traits<T>::is_zero(v.y); }
|
||||||
static double get_double(const lp::numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate
|
static double get_double(const lp::numeric_pair<T> & v){ return numeric_traits<T>::get_double(v.x); } // just return the double of the first coordinate
|
||||||
static double one() { /*lp_unreachable();*/ return 0;}
|
static double one() { /*UNREACHABLE();*/ return 0;}
|
||||||
static bool is_pos(const numeric_pair<T> &p) {
|
static bool is_pos(const numeric_pair<T> &p) {
|
||||||
return numeric_traits<T>::is_pos(p.x) ||
|
return numeric_traits<T>::is_pos(p.x) ||
|
||||||
(numeric_traits<T>::is_zero(p.x) && numeric_traits<T>::is_pos(p.y));
|
(numeric_traits<T>::is_zero(p.x) && numeric_traits<T>::is_pos(p.y));
|
||||||
|
|
|
@ -31,7 +31,6 @@ template std::set<std::pair<unsigned, unsigned>> lp::static_matrix<lp::mpq, lp::
|
||||||
template void static_matrix<mpq, mpq>::add_column_to_vector(mpq const&, unsigned int, mpq*) const;
|
template void static_matrix<mpq, mpq>::add_column_to_vector(mpq const&, unsigned int, mpq*) const;
|
||||||
template void static_matrix<mpq, mpq>::add_columns_at_the_end(unsigned int);
|
template void static_matrix<mpq, mpq>::add_columns_at_the_end(unsigned int);
|
||||||
template bool static_matrix<mpq, mpq>::is_correct() const;
|
template bool static_matrix<mpq, mpq>::is_correct() const;
|
||||||
template void static_matrix<mpq, mpq>::copy_column_to_indexed_vector(unsigned int, indexed_vector<mpq>&) const;
|
|
||||||
|
|
||||||
template mpq static_matrix<mpq, mpq>::get_balance() const;
|
template mpq static_matrix<mpq, mpq>::get_balance() const;
|
||||||
template mpq static_matrix<mpq, mpq>::get_elem(unsigned int, unsigned int) const;
|
template mpq static_matrix<mpq, mpq>::get_elem(unsigned int, unsigned int) const;
|
||||||
|
@ -47,7 +46,6 @@ template static_matrix<mpq, mpq>::static_matrix(unsigned int, unsigned int);
|
||||||
#ifdef Z3DEBUG
|
#ifdef Z3DEBUG
|
||||||
template bool static_matrix<mpq, numeric_pair<mpq> >::is_correct() const;
|
template bool static_matrix<mpq, numeric_pair<mpq> >::is_correct() const;
|
||||||
#endif
|
#endif
|
||||||
template void static_matrix<mpq, numeric_pair<mpq> >::copy_column_to_indexed_vector(unsigned int, indexed_vector<mpq>&) const;
|
|
||||||
template mpq static_matrix<mpq, numeric_pair<mpq> >::get_elem(unsigned int, unsigned int) const;
|
template mpq static_matrix<mpq, numeric_pair<mpq> >::get_elem(unsigned int, unsigned int) const;
|
||||||
template void static_matrix<mpq, numeric_pair<mpq> >::init_empty_matrix(unsigned int, unsigned int);
|
template void static_matrix<mpq, numeric_pair<mpq> >::init_empty_matrix(unsigned int, unsigned int);
|
||||||
template void static_matrix<mpq, numeric_pair<mpq> >::set(unsigned int, unsigned int, mpq const&);
|
template void static_matrix<mpq, numeric_pair<mpq> >::set(unsigned int, unsigned int, mpq const&);
|
||||||
|
|
|
@ -168,8 +168,6 @@ public:
|
||||||
|
|
||||||
std::set<std::pair<unsigned, unsigned>> get_domain();
|
std::set<std::pair<unsigned, unsigned>> get_domain();
|
||||||
|
|
||||||
void copy_column_to_indexed_vector(unsigned j, indexed_vector<T> & v) const;
|
|
||||||
|
|
||||||
T get_max_abs_in_row(unsigned row) const;
|
T get_max_abs_in_row(unsigned row) const;
|
||||||
void add_column_to_vector (const T & a, unsigned j, T * v) const {
|
void add_column_to_vector (const T & a, unsigned j, T * v) const {
|
||||||
for (const auto & it : m_columns[j]) {
|
for (const auto & it : m_columns[j]) {
|
||||||
|
@ -222,7 +220,7 @@ public:
|
||||||
virtual void set_number_of_columns(unsigned /*n*/) { }
|
virtual void set_number_of_columns(unsigned /*n*/) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
T get_max_val_in_row(unsigned /* i */) const { lp_unreachable(); }
|
T get_max_val_in_row(unsigned /* i */) const { UNREACHABLE(); }
|
||||||
|
|
||||||
T get_balance() const;
|
T get_balance() const;
|
||||||
|
|
||||||
|
|
|
@ -174,14 +174,6 @@ std::set<std::pair<unsigned, unsigned>> static_matrix<T, X>::get_domain() {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename X> void static_matrix<T, X>::copy_column_to_indexed_vector (unsigned j, indexed_vector<T> & v) const {
|
|
||||||
lp_assert(j < m_columns.size());
|
|
||||||
for (auto & it : m_columns[j]) {
|
|
||||||
const T& val = get_val(it);
|
|
||||||
if (!is_zero(val))
|
|
||||||
v.set_value(val, it.var());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename X> T static_matrix<T, X>::get_max_abs_in_row(unsigned row) const {
|
template <typename T, typename X> T static_matrix<T, X>::get_max_abs_in_row(unsigned row) const {
|
||||||
T ret = numeric_traits<T>::zero();
|
T ret = numeric_traits<T>::zero();
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct gomory_test {
|
||||||
|
|
||||||
|
|
||||||
void report_conflict_from_gomory_cut(mpq &k) {
|
void report_conflict_from_gomory_cut(mpq &k) {
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjust_term_and_k_for_some_ints_case_gomory(lar_term& t, mpq& k, mpq &lcm_den) {
|
void adjust_term_and_k_for_some_ints_case_gomory(lar_term& t, mpq& k, mpq &lcm_den) {
|
||||||
|
|
|
@ -1365,7 +1365,7 @@ void test_gomory_cut_0() {
|
||||||
if (j == 2)
|
if (j == 2)
|
||||||
return zero_of_type<mpq>();
|
return zero_of_type<mpq>();
|
||||||
if (j == 3) return mpq(3);
|
if (j == 3) return mpq(3);
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return zero_of_type<mpq>();
|
return zero_of_type<mpq>();
|
||||||
},
|
},
|
||||||
[](unsigned j) { // at_low_p
|
[](unsigned j) { // at_low_p
|
||||||
|
@ -1375,7 +1375,7 @@ void test_gomory_cut_0() {
|
||||||
return true;
|
return true;
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return true;
|
return true;
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[](unsigned j) { // at_upper
|
[](unsigned j) { // at_upper
|
||||||
|
@ -1385,31 +1385,31 @@ void test_gomory_cut_0() {
|
||||||
return true;
|
return true;
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return false;
|
return false;
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[](unsigned j) { // lower_bound
|
[](unsigned j) { // lower_bound
|
||||||
if (j == 1) {
|
if (j == 1) {
|
||||||
lp_assert(false); //unlimited from below
|
UNREACHABLE(); //unlimited from below
|
||||||
return impq(0);
|
return impq(0);
|
||||||
}
|
}
|
||||||
if (j == 2)
|
if (j == 2)
|
||||||
return impq(0);
|
return impq(0);
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return impq(3);
|
return impq(3);
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return impq(0);
|
return impq(0);
|
||||||
},
|
},
|
||||||
[](unsigned j) { // upper
|
[](unsigned j) { // upper
|
||||||
if (j == 1) {
|
if (j == 1) {
|
||||||
lp_assert(false); //unlimited from above
|
UNREACHABLE(); //unlimited from above
|
||||||
return impq(0);
|
return impq(0);
|
||||||
}
|
}
|
||||||
if (j == 2)
|
if (j == 2)
|
||||||
return impq(0);
|
return impq(0);
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return impq(10);
|
return impq(10);
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return impq(0);
|
return impq(0);
|
||||||
},
|
},
|
||||||
[] (unsigned) { return 0; },
|
[] (unsigned) { return 0; },
|
||||||
|
@ -1437,7 +1437,7 @@ void test_gomory_cut_1() {
|
||||||
return mpq(4363334, 2730001);
|
return mpq(4363334, 2730001);
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return mpq(1);
|
return mpq(1);
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return zero_of_type<mpq>();
|
return zero_of_type<mpq>();
|
||||||
},
|
},
|
||||||
[](unsigned j) { // at_low_p
|
[](unsigned j) { // at_low_p
|
||||||
|
@ -1447,7 +1447,7 @@ void test_gomory_cut_1() {
|
||||||
return false;
|
return false;
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return true;
|
return true;
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[](unsigned j) { // at_upper
|
[](unsigned j) { // at_upper
|
||||||
|
@ -1457,19 +1457,19 @@ void test_gomory_cut_1() {
|
||||||
return false;
|
return false;
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return true;
|
return true;
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[](unsigned j) { // lower_bound
|
[](unsigned j) { // lower_bound
|
||||||
if (j == 1) {
|
if (j == 1) {
|
||||||
lp_assert(false); //unlimited from below
|
UNREACHABLE(); //unlimited from below
|
||||||
return impq(0);
|
return impq(0);
|
||||||
}
|
}
|
||||||
if (j == 2)
|
if (j == 2)
|
||||||
return impq(1);
|
return impq(1);
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return impq(1);
|
return impq(1);
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return impq(0);
|
return impq(0);
|
||||||
},
|
},
|
||||||
[](unsigned j) { // upper
|
[](unsigned j) { // upper
|
||||||
|
@ -1480,7 +1480,7 @@ void test_gomory_cut_1() {
|
||||||
return impq(3333);
|
return impq(3333);
|
||||||
if (j == 3)
|
if (j == 3)
|
||||||
return impq(10000);
|
return impq(10000);
|
||||||
lp_assert(false);
|
UNREACHABLE();
|
||||||
return impq(0);
|
return impq(0);
|
||||||
},
|
},
|
||||||
[] (unsigned) { return 0; },
|
[] (unsigned) { return 0; },
|
||||||
|
|
|
@ -272,7 +272,7 @@ namespace lp {
|
||||||
} else if (el.m_head == "+") {
|
} else if (el.m_head == "+") {
|
||||||
add_sum(c, el.m_elems);
|
add_sum(c, el.m_elems);
|
||||||
} else {
|
} else {
|
||||||
lp_assert(false); // unexpected input
|
UNREACHABLE(); // unexpected input
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue