More doc.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
20 ///\brief Implementation of the LEMON-GLPK lp solver interface.
22 #include <lemon/lp_glpk.h>
27 LpGlpk::LpGlpk() : Parent() {
28 rows = _lp_bits::LpId(1);
29 cols = _lp_bits::LpId(1);
30 lp = lpx_create_prob();
32 ///\todo control function for this:
33 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
37 LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
38 rows = _lp_bits::LpId(1);
39 cols = _lp_bits::LpId(1);
40 lp = lpx_create_prob();
42 ///\todo control function for this:
43 lpx_set_int_parm(lp, LPX_K_DUAL, 1);
45 //Coefficient matrix, row bounds
46 lpx_add_rows(lp, lpx_get_num_rows(glp.lp));
47 lpx_add_cols(lp, lpx_get_num_cols(glp.lp));
49 int ind[1+lpx_get_num_cols(glp.lp)];
50 Value val[1+lpx_get_num_cols(glp.lp)];
51 for (int i=1;i<=lpx_get_num_rows(glp.lp);++i)
53 len=lpx_get_mat_row(glp.lp,i,ind,val);
54 lpx_set_mat_row(lp, i,len,ind,val);
55 lpx_set_row_bnds(lp,i,lpx_get_row_type(glp.lp,i),
56 lpx_get_row_lb(glp.lp,i),lpx_get_row_ub(glp.lp,i));
59 //Objective function, coloumn bounds
60 lpx_set_obj_dir(lp, lpx_get_obj_dir(glp.lp));
61 //Objectif function's constant term treated separately
62 lpx_set_obj_coef(lp,0,lpx_get_obj_coef(glp.lp,0));
63 for (int i=1;i<=lpx_get_num_cols(glp.lp);++i)
65 lpx_set_obj_coef(lp,i,lpx_get_obj_coef(glp.lp,i));
66 lpx_set_col_bnds(lp,i,lpx_get_col_type(glp.lp,i),
67 lpx_get_col_lb(glp.lp,i),lpx_get_col_ub(glp.lp,i));
75 int LpGlpk::_addCol() {
76 int i=lpx_add_cols(lp, 1);
77 _setColLowerBound(i, -INF);
78 _setColUpperBound(i, INF);
85 LpSolverBase &LpGlpk::_newLp()
87 LpGlpk* newlp=new LpGlpk;
93 LpSolverBase &LpGlpk::_copyLp()
95 LpGlpk* newlp=new LpGlpk(*this);
99 int LpGlpk::_addRow() {
100 int i=lpx_add_rows(lp, 1);
105 void LpGlpk::_eraseCol(int i) {
108 lpx_del_cols(lp, 1, ca);
111 void LpGlpk::_eraseRow(int i) {
114 lpx_del_rows(lp, 1, ra);
117 void LpGlpk::_getColName(int c, std::string & name) const
120 char *n = lpx_get_col_name(lp,c);
125 void LpGlpk::_setColName(int c, const std::string & name)
127 lpx_set_col_name(lp,c,const_cast<char*>(name.c_str()));
131 int LpGlpk::_colByName(const std::string& name) const
133 int k = lpx_find_col(lp, const_cast<char*>(name.c_str()));
134 return k > 0 ? k : -1;
138 void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
140 std::vector<int> indices;
141 std::vector<Value> values;
143 indices.push_back(0);
146 for(ConstRowIterator it=b; it!=e; ++it) {
147 indices.push_back(it->first);
148 values.push_back(it->second);
151 lpx_set_mat_row(lp, i, values.size() - 1, &indices[0], &values[0]);
154 void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
156 int length = lpx_get_mat_row(lp, ix, 0, 0);
158 std::vector<int> indices(length + 1);
159 std::vector<Value> values(length + 1);
161 lpx_get_mat_row(lp, ix, &indices[0], &values[0]);
163 for (int i = 1; i <= length; ++i) {
164 *b = std::make_pair(indices[i], values[i]);
169 void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
171 std::vector<int> indices;
172 std::vector<Value> values;
174 indices.push_back(0);
177 for(ConstColIterator it=b; it!=e; ++it) {
178 indices.push_back(it->first);
179 values.push_back(it->second);
182 lpx_set_mat_col(lp, ix, values.size() - 1, &indices[0], &values[0]);
185 void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
187 int length = lpx_get_mat_col(lp, ix, 0, 0);
189 std::vector<int> indices(length + 1);
190 std::vector<Value> values(length + 1);
192 lpx_get_mat_col(lp, ix, &indices[0], &values[0]);
194 for (int i = 1; i <= length; ++i) {
195 *b = std::make_pair(indices[i], values[i]);
200 void LpGlpk::_setCoeff(int ix, int jx, Value value)
203 if (lpx_get_num_cols(lp) < lpx_get_num_rows(lp)) {
205 int length=lpx_get_mat_row(lp, ix, 0, 0);
207 std::vector<int> indices(length + 2);
208 std::vector<Value> values(length + 2);
210 lpx_get_mat_row(lp, ix, &indices[0], &values[0]);
212 //The following code does not suppose that the elements of the
213 //array indices are sorted
215 for (int i = 1; i <= length; ++i) {
225 values[length]=value;
228 lpx_set_mat_row(lp, ix, length, &indices[0], &values[0]);
232 int length=lpx_get_mat_col(lp, jx, 0, 0);
234 std::vector<int> indices(length + 2);
235 std::vector<Value> values(length + 2);
237 lpx_get_mat_col(lp, jx, &indices[0], &values[0]);
239 //The following code does not suppose that the elements of the
240 //array indices are sorted
242 for (int i = 1; i <= length; ++i) {
252 values[length]=value;
255 lpx_set_mat_col(lp, jx, length, &indices[0], &values[0]);
259 LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
262 int length=lpx_get_mat_row(lp, ix, 0, 0);
264 std::vector<int> indices(length + 1);
265 std::vector<Value> values(length + 1);
267 lpx_get_mat_row(lp, ix, &indices[0], &values[0]);
269 //The following code does not suppose that the elements of the
270 //array indices are sorted
271 for (int i = 1; i <= length; ++i) {
281 void LpGlpk::_setColLowerBound(int i, Value lo)
286 int b=lpx_get_col_type(lp, i);
287 double up=lpx_get_col_ub(lp, i);
292 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
298 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
307 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
313 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
315 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
324 LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
326 int b=lpx_get_col_type(lp, i);
331 return lpx_get_col_lb(lp, i);
337 void LpGlpk::_setColUpperBound(int i, Value up)
342 int b=lpx_get_col_type(lp, i);
343 double lo=lpx_get_col_lb(lp, i);
350 lpx_set_col_bnds(lp, i, LPX_FR, lo, up);
354 lpx_set_col_bnds(lp, i, LPX_LO, lo, up);
362 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
365 lpx_set_col_bnds(lp, i, LPX_UP, lo, up);
371 lpx_set_col_bnds(lp, i, LPX_FX, lo, up);
373 lpx_set_col_bnds(lp, i, LPX_DB, lo, up);
381 LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
383 int b=lpx_get_col_type(lp, i);
388 return lpx_get_col_ub(lp, i);
394 void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
397 if (lb==INF || ub==-INF) {
403 lpx_set_row_bnds(lp, i, LPX_FR, lb, ub);
406 lpx_set_row_bnds(lp, i, LPX_UP, lb, ub);
411 lpx_set_row_bnds(lp, i, LPX_LO, lb, ub);
416 lpx_set_row_bnds(lp, i, LPX_FX, lb, ub);
419 lpx_set_row_bnds(lp, i, LPX_DB, lb, ub);
426 void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
429 int b=lpx_get_row_type(lp, i);
436 lb=lpx_get_row_lb(lp, i);
445 ub=lpx_get_row_ub(lp, i);
450 void LpGlpk::_setObjCoeff(int i, Value obj_coef)
452 //i=0 means the constant term (shift)
453 lpx_set_obj_coef(lp, i, obj_coef);
456 LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
457 //i=0 means the constant term (shift)
458 return lpx_get_obj_coef(lp, i);
461 void LpGlpk::_clearObj()
463 for (int i=0;i<=lpx_get_num_cols(lp);++i){
464 lpx_set_obj_coef(lp, i, 0);
468 LpGlpk::SolveExitStatus LpGlpk::_solve()
470 // A way to check the problem to be solved
471 //lpx_write_cpxlp(lp,"naittvan.cpx");
474 int i = lpx_simplex(lp);
484 LpGlpk::Value LpGlpk::_getPrimal(int i) const
486 return lpx_get_col_prim(lp,i);
489 LpGlpk::Value LpGlpk::_getDual(int i) const
491 return lpx_get_row_dual(lp,i);
494 LpGlpk::Value LpGlpk::_getPrimalValue() const
496 return lpx_get_obj_val(lp);
498 bool LpGlpk::_isBasicCol(int i) const
500 return (lpx_get_col_stat(lp, i)==LPX_BS);
504 LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
506 int stat= lpx_get_status(lp);
508 case LPX_UNDEF://Undefined (no solve has been run yet)
510 case LPX_NOFEAS://There is no feasible solution (primal, I guess)
511 case LPX_INFEAS://Infeasible
513 case LPX_UNBND://Unbounded
515 case LPX_FEAS://Feasible
517 case LPX_OPT://Feasible
520 return UNDEFINED; //to avoid gcc warning
525 LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
527 switch (lpx_get_dual_stat(lp)) {
528 case LPX_D_UNDEF://Undefined (no solve has been run yet)
530 case LPX_D_NOFEAS://There is no dual feasible solution
531 // case LPX_D_INFEAS://Infeasible
533 case LPX_D_FEAS://Feasible
534 switch (lpx_get_status(lp)) {
543 return UNDEFINED; //to avoid gcc warning
548 LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
550 //int stat= lpx_get_status(lp);
551 int statp= lpx_get_prim_stat(lp);
552 int statd= lpx_get_dual_stat(lp);
553 if (statp==LPX_P_FEAS && statd==LPX_D_FEAS)
554 return PRIMAL_DUAL_FEASIBLE;
555 if (statp==LPX_P_FEAS && statd==LPX_D_NOFEAS)
556 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
557 if (statp==LPX_P_NOFEAS && statd==LPX_D_FEAS)
558 return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
559 if (statp==LPX_P_NOFEAS && statd==LPX_D_NOFEAS)
560 return PRIMAL_DUAL_INFEASIBLE;
565 void LpGlpk::_setMax()
567 lpx_set_obj_dir(lp, LPX_MAX);
570 void LpGlpk::_setMin()
572 lpx_set_obj_dir(lp, LPX_MIN);
575 bool LpGlpk::_isMax() const
577 return (lpx_get_obj_dir(lp)==LPX_MAX);
582 void LpGlpk::messageLevel(int m)
584 lpx_set_int_parm(lp, LPX_K_MSGLEV, m);
587 void LpGlpk::presolver(bool b)
589 lpx_set_int_parm(lp, LPX_K_PRESOL, b);
593 } //END OF NAMESPACE LEMON