25 #include <boost/range/iterator_range.hpp>
26 #include <boost/range/adaptor/indexed.hpp>
40 using Ids = std::vector<int>;
41 using Vals = std::vector<double>;
42 using IdsVals = std::vector<std::pair<row_id, double>>;
43 using RowsInColumnIterator = IdsVals::const_iterator;
50 : m_lp(glp_create_prob()), m_total_col_nr(0), m_total_row_nr(0),
51 m_idx_cols_tmp(1), m_idx_rows_tmp(1), m_val_cols_tmp(1),
52 m_val_rows_tmp(1), m_rows_tmp(1) {
53 glp_term_out(GLP_OFF);
54 glp_init_smcp(&m_glpk_control);
55 glp_load_matrix(m_lp, 0, NULL, NULL, NULL);
56 m_glpk_control.msg_lev = GLP_MSG_OFF;
74 glp_set_obj_dir(m_lp, opt_type == MINIMIZE ? GLP_MIN : GLP_MAX);
87 int colNr = glp_add_cols(m_lp, 1);
89 glp_set_col_bnds(m_lp, colNr, bounds_to_glp_type(lb, ub), lb, ub);
90 glp_set_obj_coef(m_lp, colNr, cost_coef);
91 glp_set_mat_col(m_lp, colNr, 0, NULL, NULL);
95 m_col_idx.
add(m_total_col_nr - 1);
96 return col_id(m_total_col_nr - 1);
107 int rowNr = glp_add_rows(m_lp, 1);
110 glp_set_row_bnds(m_lp, rowNr, bounds_to_glp_type(lb, ub), lb, ub);
114 m_row_idx.
add(m_total_row_nr - 1);
115 auto row =
row_id(m_total_row_nr - 1);
130 glp_set_col_bnds(m_lp, get_col(col), bounds_to_glp_type(lb, ub), lb,
142 glp_set_col_bnds(m_lp, get_col(col), bounds_to_glp_type(lb, ub), lb,
153 glp_set_obj_coef(m_lp, get_col(col), cost_coef);
164 glp_set_row_bnds(m_lp, get_row(row), bounds_to_glp_type(lb, ub), lb,
176 glp_set_row_bnds(m_lp, get_row(row), bounds_to_glp_type(lb, ub), lb,
188 int expr_size = boost::distance(elems);
190 for (
auto elem : elems | boost::adaptors::indexed(1)) {
191 m_idx_cols_tmp[elem.index()] = get_col(elem.value().first);
192 m_val_cols_tmp[elem.index()] = elem.value().second;
195 glp_set_mat_row(m_lp, get_row(row), expr_size, &m_idx_cols_tmp[0],
206 arr[1] = get_col(col);
208 glp_del_cols(m_lp, 1, arr);
218 arr[1] = get_row(row);
220 glp_del_rows(m_lp, 1, arr);
231 return run_simplex(type,
false);
243 return run_simplex(type,
true);
259 return glp_get_col_prim(m_lp, get_col(col));
266 return glp_get_obj_coef(m_lp, get_col(col));
273 return get_col_bounds(col).first;
280 return get_col_bounds(col).second;
289 return glp_get_row_dual(m_lp, get_row(row));
296 return get_row_bounds(row).first;
303 return get_row_bounds(row).second;
311 int size = glp_get_mat_row(m_lp, get_row(row), &m_idx_cols_tmp[0],
313 for (
auto i :
irange(1, size + 1)) {
314 exp += m_val_cols_tmp[i] * get_col_id(m_idx_cols_tmp[i]);
323 boost::iterator_range<RowsInColumnIterator>
325 int size = glp_get_mat_col(m_lp, get_col(col), &m_idx_rows_tmp[0],
327 for (
auto i :
irange(1, size + 1)) {
328 m_rows_tmp[i].first = get_row_id(m_idx_rows_tmp[i]);
329 m_rows_tmp[i].second = m_val_rows_tmp[i];
331 return boost::make_iterator_range(m_rows_tmp.begin() + 1,
332 m_rows_tmp.begin() + size + 1);
342 static int bounds_to_glp_type(
double lb,
double ub) {
345 }
else if (lb == lp_traits::MINUS_INF) {
346 if (ub == lp_traits::PLUS_INF) {
352 if (ub == lp_traits::PLUS_INF) {
364 static std::pair<double, double> glp_type_to_bounds(
double lb,
double ub,
370 return { lp_traits::MINUS_INF, lp_traits::PLUS_INF };
372 return { lp_traits::MINUS_INF, ub };
374 return { lb, lp_traits::PLUS_INF };
401 std::pair<double, double> get_col_bounds(col_id col)
const {
402 auto column = get_col(col);
403 return glp_type_to_bounds(glp_get_col_lb(m_lp, column),
404 glp_get_col_ub(m_lp, column),
405 glp_get_col_type(m_lp, column));
411 std::pair<double, double> get_row_bounds(row_id row)
const {
412 auto row_num = get_row(row);
413 return glp_type_to_bounds(glp_get_row_lb(m_lp, row_num),
414 glp_get_row_ub(m_lp, row_num),
415 glp_get_row_type(m_lp, row_num));
421 int get_col(col_id col)
const {
return m_col_idx.
get_idx(col.get()) + 1; }
426 int get_row(row_id row)
const {
return m_row_idx.
get_idx(row.get()) + 1; }
431 col_id get_col_id(
int col)
const {
432 return col_id(m_col_idx.
get_val(col - 1));
438 row_id get_row_id(
int row)
const {
439 return row_id(m_row_idx.
get_val(row - 1));
448 m_glpk_control.meth = simplex_type_to_glp(type);
449 static const std::string buggy_version =
"4.52";
450 if (!resolve || glp_version() == buggy_version) {
453 glp_adv_basis(m_lp, 0);
455 int ret = glp_simplex(m_lp, &m_glpk_control);
456 if (resolve && ret != 0) {
458 glp_adv_basis(m_lp, 0);
459 ret = glp_simplex(m_lp, &m_glpk_control);
462 return get_primal_type();
471 if (glp_get_status(m_lp) == GLP_OPT) {
475 switch (glp_get_prim_stat(m_lp)) {
482 if (glp_get_dual_stat(m_lp) == GLP_NOFEAS) {
493 void resize_col_tmp() {
494 m_idx_cols_tmp.push_back(0);
495 m_val_cols_tmp.push_back(0);
498 void resize_row_tmp() {
499 m_idx_rows_tmp.push_back(0);
500 m_val_rows_tmp.push_back(0);
501 m_rows_tmp.push_back({ row_id(0), 0 });
506 glp_smcp m_glpk_control;
509 data_structures::eraseable_bimap<int> m_col_idx;
511 data_structures::eraseable_bimap<int> m_row_idx;
516 mutable Ids m_idx_cols_tmp;
517 mutable Ids m_idx_rows_tmp;
518 mutable Vals m_val_cols_tmp;
519 mutable Vals m_val_rows_tmp;
520 mutable IdsVals m_rows_tmp;
524 using glp = detail::lp_base<detail::glp_impl>;
529 #endif // PAAL_GLP_HPP
void delete_row(row_id row)
double get_obj_value() const
double get_upper_bound() const
Upper bound getter.
void set_row_expression(row_id row, const linear_expression &expr)
const Elements & get_elements() const
Returns the iterator range of the elements in the expression.
void set_col_cost(col_id col, double cost_coef)
double get_row_lower_bound(row_id row) const
problem_type solve_simplex(simplex_type type=PRIMAL)
Idx get_idx(const T &t) const
gets index of element t
LP implementation using GLPK.
const T & get_val(Idx i) const
get value for index i
problem_type
LP problem type.
linear_expression get_expression() const
Expression getter.
double get_row_upper_bound(row_id row) const
void set_col_upper_bound(col_id col, double ub)
Idx add(const T &t)
adds element to collection
linear_expression get_row_expression(row_id row) const
double get_col_upper_bound(col_id col) const
auto irange(T begin, T end)
irange
simplex_type
simplex method type
row_id add_row(const double_bounded_expression &constraint)
optimization_type
optimization type
double get_col_coef(col_id col) const
double get_col_lower_bound(col_id col) const
void set_optimization_type(optimization_type opt_type)
problem_type resolve_simplex(simplex_type type=PRIMAL)
void set_col_lower_bound(col_id col, double lb)
int get() const
Returns the id number.
double get_row_dual_value(row_id row) const
boost::iterator_range< RowsInColumnIterator > get_rows_in_column(col_id col) const
void erase(const T &t)
erases element (takes linear time)
void set_row_lower_bound(row_id row, double lb)
void delete_col(col_id col)
col_id add_column(double cost_coef, double lb, double ub)
void set_row_upper_bound(row_id row, double ub)
double get_lower_bound() const
Lower bound getter.
double get_col_value(col_id col) const