lemon/lp_glpk.cc
changeset 460 76ec7bd57026
parent 458 7afc121e0689
equal deleted inserted replaced
0:1db3032e03cd 1:00264c0fde1e
    15  * purpose.
    15  * purpose.
    16  *
    16  *
    17  */
    17  */
    18 
    18 
    19 ///\file
    19 ///\file
    20 ///\brief Implementation of the LEMON-GLPK lp solver interface.
    20 ///\brief Implementation of the LEMON GLPK LP and MIP solver interface.
    21 
    21 
    22 #include <lemon/lp_glpk.h>
    22 #include <lemon/lp_glpk.h>
    23 //#include <iostream>
       
    24 
       
    25 extern "C" {
       
    26 #include <glpk.h>
    23 #include <glpk.h>
    27 }
    24 
    28 
    25 #include <lemon/assert.h>
    29 #if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION > 15)
       
    30 #define LEMON_glp(func) (glp_##func)
       
    31 #define LEMON_lpx(func) (lpx_##func)
       
    32 
       
    33 #define LEMON_GLP(def) (GLP_##def)
       
    34 #define LEMON_LPX(def) (LPX_##def)
       
    35 
       
    36 #else
       
    37 
       
    38 #define LEMON_glp(func) (lpx_##func)
       
    39 #define LEMON_lpx(func) (lpx_##func)
       
    40 
       
    41 #define LEMON_GLP(def) (LPX_##def)
       
    42 #define LEMON_LPX(def) (LPX_##def)
       
    43 
       
    44 #endif
       
    45 
    26 
    46 namespace lemon {
    27 namespace lemon {
    47 
    28 
    48   LpGlpk::LpGlpk() : Parent() {
    29   // GlpkBase members
    49     solved = false;
    30 
    50     rows = _lp_bits::LpId(1);
    31   GlpkBase::GlpkBase() : LpBase() {
    51     cols = _lp_bits::LpId(1);
    32     lp = glp_create_prob();
    52     lp = LEMON_glp(create_prob)();
    33     glp_create_index(lp);
    53     LEMON_glp(create_index)(lp);
    34   }
    54     messageLevel(0);
    35 
    55   }
    36   GlpkBase::GlpkBase(const GlpkBase &other) : LpBase() {
    56 
    37     lp = glp_create_prob();
    57   LpGlpk::LpGlpk(const LpGlpk &glp) : Parent() {
    38     glp_copy_prob(lp, other.lp, GLP_ON);
    58     solved = false;
    39     glp_create_index(lp);
    59     rows = _lp_bits::LpId(1);
    40     rows = other.rows;
    60     cols = _lp_bits::LpId(1);
    41     cols = other.cols;
    61     lp = LEMON_glp(create_prob)();
    42   }
    62     LEMON_glp(create_index)(lp);
    43 
    63     messageLevel(0);
    44   GlpkBase::~GlpkBase() {
    64     //Coefficient matrix, row bounds
    45     glp_delete_prob(lp);
    65     LEMON_glp(add_rows)(lp, LEMON_glp(get_num_rows)(glp.lp));
    46   }
    66     LEMON_glp(add_cols)(lp, LEMON_glp(get_num_cols)(glp.lp));
    47 
    67     int len;
    48   int GlpkBase::_addCol() {
    68     std::vector<int> ind(1+LEMON_glp(get_num_cols)(glp.lp));
    49     int i = glp_add_cols(lp, 1);
    69     std::vector<Value> val(1+LEMON_glp(get_num_cols)(glp.lp));
    50     glp_set_col_bnds(lp, i, GLP_FR, 0.0, 0.0);
    70     for (int i=1;i<=LEMON_glp(get_num_rows)(glp.lp);++i)
       
    71       {
       
    72         len=LEMON_glp(get_mat_row)(glp.lp,i,&*ind.begin(),&*val.begin());
       
    73         LEMON_glp(set_mat_row)(lp, i,len,&*ind.begin(),&*val.begin());
       
    74         LEMON_glp(set_row_bnds)(lp,i,
       
    75                                 LEMON_glp(get_row_type)(glp.lp,i),
       
    76                                 LEMON_glp(get_row_lb)(glp.lp,i),
       
    77                                 LEMON_glp(get_row_ub)(glp.lp,i));
       
    78       }
       
    79 
       
    80     //Objective function, coloumn bounds
       
    81     LEMON_glp(set_obj_dir)(lp, LEMON_glp(get_obj_dir)(glp.lp));
       
    82     //Objectif function's constant term treated separately
       
    83     LEMON_glp(set_obj_coef)(lp,0,LEMON_glp(get_obj_coef)(glp.lp,0));
       
    84     for (int i=1;i<=LEMON_glp(get_num_cols)(glp.lp);++i)
       
    85       {
       
    86         LEMON_glp(set_obj_coef)(lp,i,
       
    87                                 LEMON_glp(get_obj_coef)(glp.lp,i));
       
    88         LEMON_glp(set_col_bnds)(lp,i,
       
    89                                 LEMON_glp(get_col_type)(glp.lp,i),
       
    90                                 LEMON_glp(get_col_lb)(glp.lp,i),
       
    91                                 LEMON_glp(get_col_ub)(glp.lp,i));
       
    92       }
       
    93     rows = glp.rows;
       
    94     cols = glp.cols;
       
    95   }
       
    96 
       
    97   LpGlpk::~LpGlpk() {
       
    98     LEMON_glp(delete_prob)(lp);
       
    99   }
       
   100 
       
   101   int LpGlpk::_addCol() {
       
   102     int i=LEMON_glp(add_cols)(lp, 1);
       
   103     LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), 0.0, 0.0);
       
   104     solved = false;
       
   105     return i;
    51     return i;
   106   }
    52   }
   107 
    53 
   108   ///\e
    54   int GlpkBase::_addRow() {
   109 
    55     int i = glp_add_rows(lp, 1);
   110 
    56     glp_set_row_bnds(lp, i, GLP_FR, 0.0, 0.0);
   111   LpSolverBase* LpGlpk::_newLp()
       
   112   {
       
   113     LpGlpk* newlp = new LpGlpk;
       
   114     return newlp;
       
   115   }
       
   116 
       
   117   ///\e
       
   118 
       
   119   LpSolverBase* LpGlpk::_copyLp()
       
   120   {
       
   121     LpGlpk *newlp = new LpGlpk(*this);
       
   122     return newlp;
       
   123   }
       
   124 
       
   125   int LpGlpk::_addRow() {
       
   126     int i=LEMON_glp(add_rows)(lp, 1);
       
   127     solved = false;
       
   128     return i;
    57     return i;
   129   }
    58   }
   130 
    59 
   131 
    60   void GlpkBase::_eraseCol(int i) {
   132   void LpGlpk::_eraseCol(int i) {
       
   133     int ca[2];
    61     int ca[2];
   134     ca[1]=i;
    62     ca[1] = i;
   135     LEMON_glp(del_cols)(lp, 1, ca);
    63     glp_del_cols(lp, 1, ca);
   136     solved = false;
    64   }
   137   }
    65 
   138 
    66   void GlpkBase::_eraseRow(int i) {
   139   void LpGlpk::_eraseRow(int i) {
       
   140     int ra[2];
    67     int ra[2];
   141     ra[1]=i;
    68     ra[1] = i;
   142     LEMON_glp(del_rows)(lp, 1, ra);
    69     glp_del_rows(lp, 1, ra);
   143     solved = false;
    70   }
   144   }
    71 
   145 
    72   void GlpkBase::_eraseColId(int i) {
   146   void LpGlpk::_getColName(int c, std::string & name) const
    73     cols.eraseIndex(i);
   147   {
    74     cols.shiftIndices(i);
   148 
    75   }
   149     const char *n = LEMON_glp(get_col_name)(lp,c);
    76 
   150     name = n?n:"";
    77   void GlpkBase::_eraseRowId(int i) {
   151   }
    78     rows.eraseIndex(i);
   152 
    79     rows.shiftIndices(i);
   153 
    80   }
   154   void LpGlpk::_setColName(int c, const std::string & name)
    81 
   155   {
    82   void GlpkBase::_getColName(int c, std::string& name) const {
   156     LEMON_glp(set_col_name)(lp,c,const_cast<char*>(name.c_str()));
    83     const char *str = glp_get_col_name(lp, c);
   157 
    84     if (str) name = str;
   158   }
    85     else name.clear();
   159 
    86   }
   160   int LpGlpk::_colByName(const std::string& name) const
    87 
   161   {
    88   void GlpkBase::_setColName(int c, const std::string & name) {
   162     int k = LEMON_glp(find_col)(lp, const_cast<char*>(name.c_str()));
    89     glp_set_col_name(lp, c, const_cast<char*>(name.c_str()));
       
    90 
       
    91   }
       
    92 
       
    93   int GlpkBase::_colByName(const std::string& name) const {
       
    94     int k = glp_find_col(lp, const_cast<char*>(name.c_str()));
   163     return k > 0 ? k : -1;
    95     return k > 0 ? k : -1;
   164   }
    96   }
   165 
    97 
   166 
    98   void GlpkBase::_getRowName(int r, std::string& name) const {
   167   void LpGlpk::_setRowCoeffs(int i, ConstRowIterator b, ConstRowIterator e)
    99     const char *str = glp_get_row_name(lp, r);
   168   {
   100     if (str) name = str;
   169     std::vector<int> indices;
   101     else name.clear();
       
   102   }
       
   103 
       
   104   void GlpkBase::_setRowName(int r, const std::string & name) {
       
   105     glp_set_row_name(lp, r, const_cast<char*>(name.c_str()));
       
   106 
       
   107   }
       
   108 
       
   109   int GlpkBase::_rowByName(const std::string& name) const {
       
   110     int k = glp_find_row(lp, const_cast<char*>(name.c_str()));
       
   111     return k > 0 ? k : -1;
       
   112   }
       
   113 
       
   114   void GlpkBase::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
       
   115     std::vector<int> indexes;
   170     std::vector<Value> values;
   116     std::vector<Value> values;
   171 
   117 
   172     indices.push_back(0);
   118     indexes.push_back(0);
   173     values.push_back(0);
   119     values.push_back(0);
   174 
   120 
   175     for(ConstRowIterator it=b; it!=e; ++it) {
   121     for(ExprIterator it = b; it != e; ++it) {
   176       indices.push_back(it->first);
   122       indexes.push_back(it->first);
   177       values.push_back(it->second);
   123       values.push_back(it->second);
   178     }
   124     }
   179 
   125 
   180     LEMON_glp(set_mat_row)(lp, i, values.size() - 1,
   126     glp_set_mat_row(lp, i, values.size() - 1,
   181                                 &indices[0], &values[0]);
   127                     &indexes.front(), &values.front());
   182 
   128   }
   183     solved = false;
   129 
   184   }
   130   void GlpkBase::_getRowCoeffs(int ix, InsertIterator b) const {
   185 
   131     int length = glp_get_mat_row(lp, ix, 0, 0);
   186   void LpGlpk::_getRowCoeffs(int ix, RowIterator b) const
   132 
   187   {
   133     std::vector<int> indexes(length + 1);
   188     int length = LEMON_glp(get_mat_row)(lp, ix, 0, 0);
       
   189 
       
   190     std::vector<int> indices(length + 1);
       
   191     std::vector<Value> values(length + 1);
   134     std::vector<Value> values(length + 1);
   192 
   135 
   193     LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
   136     glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
   194 
   137 
   195     for (int i = 1; i <= length; ++i) {
   138     for (int i = 1; i <= length; ++i) {
   196       *b = std::make_pair(indices[i], values[i]);
   139       *b = std::make_pair(indexes[i], values[i]);
   197       ++b;
   140       ++b;
   198     }
   141     }
   199   }
   142   }
   200 
   143 
   201   void LpGlpk::_setColCoeffs(int ix, ConstColIterator b, ConstColIterator e) {
   144   void GlpkBase::_setColCoeffs(int ix, ExprIterator b,
   202 
   145                                      ExprIterator e) {
   203     std::vector<int> indices;
   146 
       
   147     std::vector<int> indexes;
   204     std::vector<Value> values;
   148     std::vector<Value> values;
   205 
   149 
   206     indices.push_back(0);
   150     indexes.push_back(0);
   207     values.push_back(0);
   151     values.push_back(0);
   208 
   152 
   209     for(ConstColIterator it=b; it!=e; ++it) {
   153     for(ExprIterator it = b; it != e; ++it) {
   210       indices.push_back(it->first);
   154       indexes.push_back(it->first);
   211       values.push_back(it->second);
   155       values.push_back(it->second);
   212     }
   156     }
   213 
   157 
   214     LEMON_glp(set_mat_col)(lp, ix, values.size() - 1,
   158     glp_set_mat_col(lp, ix, values.size() - 1,
   215                                 &indices[0], &values[0]);
   159                     &indexes.front(), &values.front());
   216 
   160   }
   217     solved = false;
   161 
   218   }
   162   void GlpkBase::_getColCoeffs(int ix, InsertIterator b) const {
   219 
   163     int length = glp_get_mat_col(lp, ix, 0, 0);
   220   void LpGlpk::_getColCoeffs(int ix, ColIterator b) const
   164 
   221   {
   165     std::vector<int> indexes(length + 1);
   222     int length = LEMON_glp(get_mat_col)(lp, ix, 0, 0);
       
   223 
       
   224     std::vector<int> indices(length + 1);
       
   225     std::vector<Value> values(length + 1);
   166     std::vector<Value> values(length + 1);
   226 
   167 
   227     LEMON_glp(get_mat_col)(lp, ix, &indices[0], &values[0]);
   168     glp_get_mat_col(lp, ix, &indexes.front(), &values.front());
   228 
   169 
   229     for (int i = 1; i <= length; ++i) {
   170     for (int i = 1; i  <= length; ++i) {
   230       *b = std::make_pair(indices[i], values[i]);
   171       *b = std::make_pair(indexes[i], values[i]);
   231       ++b;
   172       ++b;
   232     }
   173     }
   233   }
   174   }
   234 
   175 
   235   void LpGlpk::_setCoeff(int ix, int jx, Value value)
   176   void GlpkBase::_setCoeff(int ix, int jx, Value value) {
   236   {
   177 
   237 
   178     if (glp_get_num_cols(lp) < glp_get_num_rows(lp)) {
   238     if (LEMON_glp(get_num_cols)(lp) < LEMON_glp(get_num_rows)(lp)) {
   179 
   239 
   180       int length = glp_get_mat_row(lp, ix, 0, 0);
   240       int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
   181 
   241 
   182       std::vector<int> indexes(length + 2);
   242       std::vector<int> indices(length + 2);
       
   243       std::vector<Value> values(length + 2);
   183       std::vector<Value> values(length + 2);
   244 
   184 
   245       LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
   185       glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
   246 
   186 
   247       //The following code does not suppose that the elements of the
   187       //The following code does not suppose that the elements of the
   248       //array indices are sorted
   188       //array indexes are sorted
   249       bool found=false;
   189       bool found = false;
   250       for (int i = 1; i <= length; ++i) {
   190       for (int i = 1; i  <= length; ++i) {
   251         if (indices[i]==jx){
   191         if (indexes[i] == jx) {
   252           found=true;
   192           found = true;
   253           values[i]=value;
   193           values[i] = value;
   254           break;
   194           break;
   255         }
   195         }
   256       }
   196       }
   257       if (!found){
   197       if (!found) {
   258         ++length;
   198         ++length;
   259         indices[length]=jx;
   199         indexes[length] = jx;
   260         values[length]=value;
   200         values[length] = value;
   261       }
   201       }
   262 
   202 
   263       LEMON_glp(set_mat_row)(lp, ix, length, &indices[0], &values[0]);
   203       glp_set_mat_row(lp, ix, length, &indexes.front(), &values.front());
   264 
   204 
   265     } else {
   205     } else {
   266 
   206 
   267       int length=LEMON_glp(get_mat_col)(lp, jx, 0, 0);
   207       int length = glp_get_mat_col(lp, jx, 0, 0);
   268 
   208 
   269       std::vector<int> indices(length + 2);
   209       std::vector<int> indexes(length + 2);
   270       std::vector<Value> values(length + 2);
   210       std::vector<Value> values(length + 2);
   271 
   211 
   272       LEMON_glp(get_mat_col)(lp, jx, &indices[0], &values[0]);
   212       glp_get_mat_col(lp, jx, &indexes.front(), &values.front());
   273 
   213 
   274       //The following code does not suppose that the elements of the
   214       //The following code does not suppose that the elements of the
   275       //array indices are sorted
   215       //array indexes are sorted
   276       bool found=false;
   216       bool found = false;
   277       for (int i = 1; i <= length; ++i) {
   217       for (int i = 1; i <= length; ++i) {
   278         if (indices[i]==ix){
   218         if (indexes[i] == ix) {
   279           found=true;
   219           found = true;
   280           values[i]=value;
   220           values[i] = value;
   281           break;
   221           break;
   282         }
   222         }
   283       }
   223       }
   284       if (!found){
   224       if (!found) {
   285         ++length;
   225         ++length;
   286         indices[length]=ix;
   226         indexes[length] = ix;
   287         values[length]=value;
   227         values[length] = value;
   288       }
   228       }
   289 
   229 
   290       LEMON_glp(set_mat_col)(lp, jx, length, &indices[0], &values[0]);
   230       glp_set_mat_col(lp, jx, length, &indexes.front(), &values.front());
   291     }
   231     }
   292 
   232 
   293     solved = false;
   233   }
   294   }
   234 
   295 
   235   GlpkBase::Value GlpkBase::_getCoeff(int ix, int jx) const {
   296   LpGlpk::Value LpGlpk::_getCoeff(int ix, int jx) const
   236 
   297   {
   237     int length = glp_get_mat_row(lp, ix, 0, 0);
   298 
   238 
   299     int length=LEMON_glp(get_mat_row)(lp, ix, 0, 0);
   239     std::vector<int> indexes(length + 1);
   300 
       
   301     std::vector<int> indices(length + 1);
       
   302     std::vector<Value> values(length + 1);
   240     std::vector<Value> values(length + 1);
   303 
   241 
   304     LEMON_glp(get_mat_row)(lp, ix, &indices[0], &values[0]);
   242     glp_get_mat_row(lp, ix, &indexes.front(), &values.front());
   305 
   243 
   306     //The following code does not suppose that the elements of the
   244     for (int i = 1; i  <= length; ++i) {
   307     //array indices are sorted
   245       if (indexes[i] == jx) {
   308     for (int i = 1; i <= length; ++i) {
       
   309       if (indices[i]==jx){
       
   310         return values[i];
   246         return values[i];
   311       }
   247       }
   312     }
   248     }
       
   249 
   313     return 0;
   250     return 0;
   314 
   251   }
   315   }
   252 
   316 
   253   void GlpkBase::_setColLowerBound(int i, Value lo) {
   317 
   254     LEMON_ASSERT(lo != INF, "Invalid bound");
   318   void LpGlpk::_setColLowerBound(int i, Value lo)
   255 
   319   {
   256     int b = glp_get_col_type(lp, i);
   320     if (lo==INF) {
   257     double up = glp_get_col_ub(lp, i);
   321       //FIXME error
   258     if (lo == -INF) {
   322     }
       
   323     int b=LEMON_glp(get_col_type)(lp, i);
       
   324     double up=LEMON_glp(get_col_ub)(lp, i);
       
   325     if (lo==-INF) {
       
   326       switch (b) {
   259       switch (b) {
   327       case LEMON_GLP(FR):
   260       case GLP_FR:
   328       case LEMON_GLP(LO):
   261       case GLP_LO:
   329         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
   262         glp_set_col_bnds(lp, i, GLP_FR, lo, up);
   330         break;
   263         break;
   331       case LEMON_GLP(UP):
   264       case GLP_UP:
   332         break;
   265         break;
   333       case LEMON_GLP(DB):
   266       case GLP_DB:
   334       case LEMON_GLP(FX):
   267       case GLP_FX:
   335         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
   268         glp_set_col_bnds(lp, i, GLP_UP, lo, up);
   336         break;
   269         break;
   337       default: ;
   270       default:
   338         //FIXME error
   271         break;
   339       }
   272       }
   340     } else {
   273     } else {
   341       switch (b) {
   274       switch (b) {
   342       case LEMON_GLP(FR):
   275       case GLP_FR:
   343       case LEMON_GLP(LO):
   276       case GLP_LO:
   344         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
   277         glp_set_col_bnds(lp, i, GLP_LO, lo, up);
   345         break;
   278         break;
   346       case LEMON_GLP(UP):
   279       case GLP_UP:
   347       case LEMON_GLP(DB):
   280       case GLP_DB:
   348       case LEMON_GLP(FX):
   281       case GLP_FX:
   349         if (lo==up)
   282         if (lo == up)
   350           LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
   283           glp_set_col_bnds(lp, i, GLP_FX, lo, up);
   351         else
   284         else
   352           LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
   285           glp_set_col_bnds(lp, i, GLP_DB, lo, up);
   353         break;
   286         break;
   354       default: ;
   287       default:
   355         //FIXME error
   288         break;
   356       }
   289       }
   357     }
   290     }
   358 
   291   }
   359     solved = false;
   292 
   360   }
   293   GlpkBase::Value GlpkBase::_getColLowerBound(int i) const {
   361 
   294     int b = glp_get_col_type(lp, i);
   362   LpGlpk::Value LpGlpk::_getColLowerBound(int i) const
   295     switch (b) {
   363   {
   296     case GLP_LO:
   364     int b=LEMON_glp(get_col_type)(lp, i);
   297     case GLP_DB:
       
   298     case GLP_FX:
       
   299       return glp_get_col_lb(lp, i);
       
   300     default:
       
   301       return -INF;
       
   302     }
       
   303   }
       
   304 
       
   305   void GlpkBase::_setColUpperBound(int i, Value up) {
       
   306     LEMON_ASSERT(up != -INF, "Invalid bound");
       
   307 
       
   308     int b = glp_get_col_type(lp, i);
       
   309     double lo = glp_get_col_lb(lp, i);
       
   310     if (up == INF) {
   365       switch (b) {
   311       switch (b) {
   366       case LEMON_GLP(LO):
   312       case GLP_FR:
   367       case LEMON_GLP(DB):
   313       case GLP_LO:
   368       case LEMON_GLP(FX):
   314         break;
   369         return LEMON_glp(get_col_lb)(lp, i);
   315       case GLP_UP:
   370       default: ;
   316         glp_set_col_bnds(lp, i, GLP_FR, lo, up);
   371         return -INF;
   317         break;
   372       }
   318       case GLP_DB:
   373   }
   319       case GLP_FX:
   374 
   320         glp_set_col_bnds(lp, i, GLP_LO, lo, up);
   375   void LpGlpk::_setColUpperBound(int i, Value up)
   321         break;
   376   {
   322       default:
   377     if (up==-INF) {
   323         break;
   378       //FIXME error
       
   379     }
       
   380     int b=LEMON_glp(get_col_type)(lp, i);
       
   381     double lo=LEMON_glp(get_col_lb)(lp, i);
       
   382     if (up==INF) {
       
   383       switch (b) {
       
   384       case LEMON_GLP(FR):
       
   385       case LEMON_GLP(LO):
       
   386         break;
       
   387       case LEMON_GLP(UP):
       
   388         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FR), lo, up);
       
   389         break;
       
   390       case LEMON_GLP(DB):
       
   391       case LEMON_GLP(FX):
       
   392         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(LO), lo, up);
       
   393         break;
       
   394       default: ;
       
   395         //FIXME error
       
   396       }
   324       }
   397     } else {
   325     } else {
   398       switch (b) {
   326       switch (b) {
   399       case LEMON_GLP(FR):
   327       case GLP_FR:
   400         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
   328         glp_set_col_bnds(lp, i, GLP_UP, lo, up);
   401         break;
   329         break;
   402       case LEMON_GLP(UP):
   330       case GLP_UP:
   403         LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(UP), lo, up);
   331         glp_set_col_bnds(lp, i, GLP_UP, lo, up);
   404         break;
   332         break;
   405       case LEMON_GLP(LO):
   333       case GLP_LO:
   406       case LEMON_GLP(DB):
   334       case GLP_DB:
   407       case LEMON_GLP(FX):
   335       case GLP_FX:
   408         if (lo==up)
   336         if (lo == up)
   409           LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(FX), lo, up);
   337           glp_set_col_bnds(lp, i, GLP_FX, lo, up);
   410         else
   338         else
   411           LEMON_glp(set_col_bnds)(lp, i, LEMON_GLP(DB), lo, up);
   339           glp_set_col_bnds(lp, i, GLP_DB, lo, up);
   412         break;
   340         break;
   413       default: ;
   341       default:
   414         //FIXME error
   342         break;
   415       }
   343       }
   416     }
   344     }
   417 
   345 
   418     solved = false;
   346   }
   419   }
   347 
   420 
   348   GlpkBase::Value GlpkBase::_getColUpperBound(int i) const {
   421   LpGlpk::Value LpGlpk::_getColUpperBound(int i) const
   349     int b = glp_get_col_type(lp, i);
   422   {
       
   423     int b=LEMON_glp(get_col_type)(lp, i);
       
   424       switch (b) {
   350       switch (b) {
   425       case LEMON_GLP(UP):
   351       case GLP_UP:
   426       case LEMON_GLP(DB):
   352       case GLP_DB:
   427       case LEMON_GLP(FX):
   353       case GLP_FX:
   428         return LEMON_glp(get_col_ub)(lp, i);
   354         return glp_get_col_ub(lp, i);
   429       default: ;
   355       default:
   430         return INF;
   356         return INF;
   431       }
   357       }
   432   }
   358   }
   433 
   359 
   434   void LpGlpk::_setRowBounds(int i, Value lb, Value ub)
   360   void GlpkBase::_setRowLowerBound(int i, Value lo) {
   435   {
   361     LEMON_ASSERT(lo != INF, "Invalid bound");
   436     //Bad parameter
   362 
   437     if (lb==INF || ub==-INF) {
   363     int b = glp_get_row_type(lp, i);
   438       //FIXME error
   364     double up = glp_get_row_ub(lp, i);
   439     }
   365     if (lo == -INF) {
   440 
   366       switch (b) {
   441     if (lb == -INF){
   367       case GLP_FR:
   442       if (ub == INF){
   368       case GLP_LO:
   443         LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FR), lb, ub);
   369         glp_set_row_bnds(lp, i, GLP_FR, lo, up);
   444       }
   370         break;
   445       else{
   371       case GLP_UP:
   446         LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(UP), lb, ub);
   372         break;
   447       }
   373       case GLP_DB:
   448     }
   374       case GLP_FX:
   449     else{
   375         glp_set_row_bnds(lp, i, GLP_UP, lo, up);
   450       if (ub==INF){
   376         break;
   451         LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(LO), lb, ub);
   377       default:
   452 
   378         break;
   453       }
   379       }
   454       else{
   380     } else {
   455         if (lb == ub){
   381       switch (b) {
   456           LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(FX), lb, ub);
   382       case GLP_FR:
       
   383       case GLP_LO:
       
   384         glp_set_row_bnds(lp, i, GLP_LO, lo, up);
       
   385         break;
       
   386       case GLP_UP:
       
   387       case GLP_DB:
       
   388       case GLP_FX:
       
   389         if (lo == up)
       
   390           glp_set_row_bnds(lp, i, GLP_FX, lo, up);
       
   391         else
       
   392           glp_set_row_bnds(lp, i, GLP_DB, lo, up);
       
   393         break;
       
   394       default:
       
   395         break;
       
   396       }
       
   397     }
       
   398 
       
   399   }
       
   400 
       
   401   GlpkBase::Value GlpkBase::_getRowLowerBound(int i) const {
       
   402     int b = glp_get_row_type(lp, i);
       
   403     switch (b) {
       
   404     case GLP_LO:
       
   405     case GLP_DB:
       
   406     case GLP_FX:
       
   407       return glp_get_row_lb(lp, i);
       
   408     default:
       
   409       return -INF;
       
   410     }
       
   411   }
       
   412 
       
   413   void GlpkBase::_setRowUpperBound(int i, Value up) {
       
   414     LEMON_ASSERT(up != -INF, "Invalid bound");
       
   415 
       
   416     int b = glp_get_row_type(lp, i);
       
   417     double lo = glp_get_row_lb(lp, i);
       
   418     if (up == INF) {
       
   419       switch (b) {
       
   420       case GLP_FR:
       
   421       case GLP_LO:
       
   422         break;
       
   423       case GLP_UP:
       
   424         glp_set_row_bnds(lp, i, GLP_FR, lo, up);
       
   425         break;
       
   426       case GLP_DB:
       
   427       case GLP_FX:
       
   428         glp_set_row_bnds(lp, i, GLP_LO, lo, up);
       
   429         break;
       
   430       default:
       
   431         break;
       
   432       }
       
   433     } else {
       
   434       switch (b) {
       
   435       case GLP_FR:
       
   436         glp_set_row_bnds(lp, i, GLP_UP, lo, up);
       
   437         break;
       
   438       case GLP_UP:
       
   439         glp_set_row_bnds(lp, i, GLP_UP, lo, up);
       
   440         break;
       
   441       case GLP_LO:
       
   442       case GLP_DB:
       
   443       case GLP_FX:
       
   444         if (lo == up)
       
   445           glp_set_row_bnds(lp, i, GLP_FX, lo, up);
       
   446         else
       
   447           glp_set_row_bnds(lp, i, GLP_DB, lo, up);
       
   448         break;
       
   449       default:
       
   450         break;
       
   451       }
       
   452     }
       
   453   }
       
   454 
       
   455   GlpkBase::Value GlpkBase::_getRowUpperBound(int i) const {
       
   456     int b = glp_get_row_type(lp, i);
       
   457     switch (b) {
       
   458     case GLP_UP:
       
   459     case GLP_DB:
       
   460     case GLP_FX:
       
   461       return glp_get_row_ub(lp, i);
       
   462     default:
       
   463       return INF;
       
   464     }
       
   465   }
       
   466 
       
   467   void GlpkBase::_setObjCoeffs(ExprIterator b, ExprIterator e) {
       
   468     for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
       
   469       glp_set_obj_coef(lp, i, 0.0);
       
   470     }
       
   471     for (ExprIterator it = b; it != e; ++it) {
       
   472       glp_set_obj_coef(lp, it->first, it->second);
       
   473     }
       
   474   }
       
   475 
       
   476   void GlpkBase::_getObjCoeffs(InsertIterator b) const {
       
   477     for (int i = 1; i <= glp_get_num_cols(lp); ++i) {
       
   478       Value val = glp_get_obj_coef(lp, i);
       
   479       if (val != 0.0) {
       
   480         *b = std::make_pair(i, val);
       
   481         ++b;
       
   482       }
       
   483     }
       
   484   }
       
   485 
       
   486   void GlpkBase::_setObjCoeff(int i, Value obj_coef) {
       
   487     //i = 0 means the constant term (shift)
       
   488     glp_set_obj_coef(lp, i, obj_coef);
       
   489   }
       
   490 
       
   491   GlpkBase::Value GlpkBase::_getObjCoeff(int i) const {
       
   492     //i = 0 means the constant term (shift)
       
   493     return glp_get_obj_coef(lp, i);
       
   494   }
       
   495 
       
   496   void GlpkBase::_setSense(GlpkBase::Sense sense) {
       
   497     switch (sense) {
       
   498     case MIN:
       
   499       glp_set_obj_dir(lp, GLP_MIN);
       
   500       break;
       
   501     case MAX:
       
   502       glp_set_obj_dir(lp, GLP_MAX);
       
   503       break;
       
   504     }
       
   505   }
       
   506 
       
   507   GlpkBase::Sense GlpkBase::_getSense() const {
       
   508     switch(glp_get_obj_dir(lp)) {
       
   509     case GLP_MIN:
       
   510       return MIN;
       
   511     case GLP_MAX:
       
   512       return MAX;
       
   513     default:
       
   514       LEMON_ASSERT(false, "Wrong sense");
       
   515       return GlpkBase::Sense();
       
   516     }
       
   517   }
       
   518 
       
   519   void GlpkBase::_clear() {
       
   520     glp_erase_prob(lp);
       
   521     rows.clear();
       
   522     cols.clear();
       
   523   }
       
   524 
       
   525   // LpGlpk members
       
   526 
       
   527   LpGlpk::LpGlpk()
       
   528     : LpBase(), GlpkBase(), LpSolver() {
       
   529     messageLevel(MESSAGE_NO_OUTPUT);
       
   530   }
       
   531 
       
   532   LpGlpk::LpGlpk(const LpGlpk& other)
       
   533     : LpBase(other), GlpkBase(other), LpSolver(other) {
       
   534     messageLevel(MESSAGE_NO_OUTPUT);
       
   535   }
       
   536 
       
   537   LpGlpk* LpGlpk::_newSolver() const { return new LpGlpk; }
       
   538   LpGlpk* LpGlpk::_cloneSolver() const { return new LpGlpk(*this); }
       
   539 
       
   540   const char* LpGlpk::_solverName() const { return "LpGlpk"; }
       
   541 
       
   542   void LpGlpk::_clear_temporals() {
       
   543     _primal_ray.clear();
       
   544     _dual_ray.clear();
       
   545   }
       
   546 
       
   547   LpGlpk::SolveExitStatus LpGlpk::_solve() {
       
   548     return solvePrimal();
       
   549   }
       
   550 
       
   551   LpGlpk::SolveExitStatus LpGlpk::solvePrimal() {
       
   552     _clear_temporals();
       
   553 
       
   554     glp_smcp smcp;
       
   555     glp_init_smcp(&smcp);
       
   556 
       
   557     switch (_message_level) {
       
   558     case MESSAGE_NO_OUTPUT:
       
   559       smcp.msg_lev = GLP_MSG_OFF;
       
   560       break;
       
   561     case MESSAGE_ERROR_MESSAGE:
       
   562       smcp.msg_lev = GLP_MSG_ERR;
       
   563       break;
       
   564     case MESSAGE_NORMAL_OUTPUT:
       
   565       smcp.msg_lev = GLP_MSG_ON;
       
   566       break;
       
   567     case MESSAGE_FULL_OUTPUT:
       
   568       smcp.msg_lev = GLP_MSG_ALL;
       
   569       break;
       
   570     }
       
   571 
       
   572     if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
       
   573     return SOLVED;
       
   574   }
       
   575 
       
   576   LpGlpk::SolveExitStatus LpGlpk::solveDual() {
       
   577     _clear_temporals();
       
   578 
       
   579     glp_smcp smcp;
       
   580     glp_init_smcp(&smcp);
       
   581 
       
   582     switch (_message_level) {
       
   583     case MESSAGE_NO_OUTPUT:
       
   584       smcp.msg_lev = GLP_MSG_OFF;
       
   585       break;
       
   586     case MESSAGE_ERROR_MESSAGE:
       
   587       smcp.msg_lev = GLP_MSG_ERR;
       
   588       break;
       
   589     case MESSAGE_NORMAL_OUTPUT:
       
   590       smcp.msg_lev = GLP_MSG_ON;
       
   591       break;
       
   592     case MESSAGE_FULL_OUTPUT:
       
   593       smcp.msg_lev = GLP_MSG_ALL;
       
   594       break;
       
   595     }
       
   596     smcp.meth = GLP_DUAL;
       
   597 
       
   598     if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
       
   599     return SOLVED;
       
   600   }
       
   601 
       
   602   LpGlpk::Value LpGlpk::_getPrimal(int i) const {
       
   603     return glp_get_col_prim(lp, i);
       
   604   }
       
   605 
       
   606   LpGlpk::Value LpGlpk::_getDual(int i) const {
       
   607     return glp_get_row_dual(lp, i);
       
   608   }
       
   609 
       
   610   LpGlpk::Value LpGlpk::_getPrimalValue() const {
       
   611     return glp_get_obj_val(lp);
       
   612   }
       
   613 
       
   614   LpGlpk::VarStatus LpGlpk::_getColStatus(int i) const {
       
   615     switch (glp_get_col_stat(lp, i)) {
       
   616     case GLP_BS:
       
   617       return BASIC;
       
   618     case GLP_UP:
       
   619       return UPPER;
       
   620     case GLP_LO:
       
   621       return LOWER;
       
   622     case GLP_NF:
       
   623       return FREE;
       
   624     case GLP_NS:
       
   625       return FIXED;
       
   626     default:
       
   627       LEMON_ASSERT(false, "Wrong column status");
       
   628       return LpGlpk::VarStatus();
       
   629     }
       
   630   }
       
   631 
       
   632   LpGlpk::VarStatus LpGlpk::_getRowStatus(int i) const {
       
   633     switch (glp_get_row_stat(lp, i)) {
       
   634     case GLP_BS:
       
   635       return BASIC;
       
   636     case GLP_UP:
       
   637       return UPPER;
       
   638     case GLP_LO:
       
   639       return LOWER;
       
   640     case GLP_NF:
       
   641       return FREE;
       
   642     case GLP_NS:
       
   643       return FIXED;
       
   644     default:
       
   645       LEMON_ASSERT(false, "Wrong row status");
       
   646       return LpGlpk::VarStatus();
       
   647     }
       
   648   }
       
   649 
       
   650   LpGlpk::Value LpGlpk::_getPrimalRay(int i) const {
       
   651     if (_primal_ray.empty()) {
       
   652       int row_num = glp_get_num_rows(lp);
       
   653       int col_num = glp_get_num_cols(lp);
       
   654 
       
   655       _primal_ray.resize(col_num + 1, 0.0);
       
   656 
       
   657       int index = glp_get_unbnd_ray(lp);
       
   658       if (index != 0) {
       
   659         // The primal ray is found in primal simplex second phase
       
   660         LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
       
   661                       glp_get_col_stat(lp, index - row_num)) != GLP_BS,
       
   662                      "Wrong primal ray");
       
   663 
       
   664         bool negate = glp_get_obj_dir(lp) == GLP_MAX;
       
   665 
       
   666         if (index > row_num) {
       
   667           _primal_ray[index - row_num] = 1.0;
       
   668           if (glp_get_col_dual(lp, index - row_num) > 0) {
       
   669             negate = !negate;
       
   670           }
       
   671         } else {
       
   672           if (glp_get_row_dual(lp, index) > 0) {
       
   673             negate = !negate;
       
   674           }
   457         }
   675         }
   458         else{
   676 
   459           LEMON_glp(set_row_bnds)(lp, i, LEMON_GLP(DB), lb, ub);
   677         std::vector<int> ray_indexes(row_num + 1);
       
   678         std::vector<Value> ray_values(row_num + 1);
       
   679         int ray_length = glp_eval_tab_col(lp, index, &ray_indexes.front(),
       
   680                                           &ray_values.front());
       
   681 
       
   682         for (int i = 1; i <= ray_length; ++i) {
       
   683           if (ray_indexes[i] > row_num) {
       
   684             _primal_ray[ray_indexes[i] - row_num] = ray_values[i];
       
   685           }
   460         }
   686         }
   461       }
   687 
   462     }
   688         if (negate) {
   463 
   689           for (int i = 1; i <= col_num; ++i) {
   464     solved = false;
   690             _primal_ray[i] = - _primal_ray[i];
   465   }
   691           }
   466 
   692         }
   467   void LpGlpk::_getRowBounds(int i, Value &lb, Value &ub) const
   693       } else {
   468   {
   694         for (int i = 1; i <= col_num; ++i) {
   469 
   695           _primal_ray[i] = glp_get_col_prim(lp, i);
   470     int b=LEMON_glp(get_row_type)(lp, i);
   696         }
   471     switch (b) {
   697       }
   472     case LEMON_GLP(FR):
   698     }
   473     case LEMON_GLP(UP):
   699     return _primal_ray[i];
   474       lb = -INF;
   700   }
   475         break;
   701 
       
   702   LpGlpk::Value LpGlpk::_getDualRay(int i) const {
       
   703     if (_dual_ray.empty()) {
       
   704       int row_num = glp_get_num_rows(lp);
       
   705 
       
   706       _dual_ray.resize(row_num + 1, 0.0);
       
   707 
       
   708       int index = glp_get_unbnd_ray(lp);
       
   709       if (index != 0) {
       
   710         // The dual ray is found in dual simplex second phase
       
   711         LEMON_ASSERT((index <= row_num ? glp_get_row_stat(lp, index) :
       
   712                       glp_get_col_stat(lp, index - row_num)) == GLP_BS,
       
   713 
       
   714                      "Wrong dual ray");
       
   715 
       
   716         int idx;
       
   717         bool negate = false;
       
   718 
       
   719         if (index > row_num) {
       
   720           idx = glp_get_col_bind(lp, index - row_num);
       
   721           if (glp_get_col_prim(lp, index - row_num) >
       
   722               glp_get_col_ub(lp, index - row_num)) {
       
   723             negate = true;
       
   724           }
       
   725         } else {
       
   726           idx = glp_get_row_bind(lp, index);
       
   727           if (glp_get_row_prim(lp, index) > glp_get_row_ub(lp, index)) {
       
   728             negate = true;
       
   729           }
       
   730         }
       
   731 
       
   732         _dual_ray[idx] = negate ?  - 1.0 : 1.0;
       
   733 
       
   734         glp_btran(lp, &_dual_ray.front());
       
   735       } else {
       
   736         double eps = 1e-7;
       
   737         // The dual ray is found in primal simplex first phase
       
   738         // We assume that the glpk minimizes the slack to get feasible solution
       
   739         for (int i = 1; i <= row_num; ++i) {
       
   740           int index = glp_get_bhead(lp, i);
       
   741           if (index <= row_num) {
       
   742             double res = glp_get_row_prim(lp, index);
       
   743             if (res > glp_get_row_ub(lp, index) + eps) {
       
   744               _dual_ray[i] = -1;
       
   745             } else if (res < glp_get_row_lb(lp, index) - eps) {
       
   746               _dual_ray[i] = 1;
       
   747             } else {
       
   748               _dual_ray[i] = 0;
       
   749             }
       
   750             _dual_ray[i] *= glp_get_rii(lp, index);
       
   751           } else {
       
   752             double res = glp_get_col_prim(lp, index - row_num);
       
   753             if (res > glp_get_col_ub(lp, index - row_num) + eps) {
       
   754               _dual_ray[i] = -1;
       
   755             } else if (res < glp_get_col_lb(lp, index - row_num) - eps) {
       
   756               _dual_ray[i] = 1;
       
   757             } else {
       
   758               _dual_ray[i] = 0;
       
   759             }
       
   760             _dual_ray[i] /= glp_get_sjj(lp, index - row_num);
       
   761           }
       
   762         }
       
   763 
       
   764         glp_btran(lp, &_dual_ray.front());
       
   765 
       
   766         for (int i = 1; i <= row_num; ++i) {
       
   767           _dual_ray[i] /= glp_get_rii(lp, i);
       
   768         }
       
   769       }
       
   770     }
       
   771     return _dual_ray[i];
       
   772   }
       
   773 
       
   774   LpGlpk::ProblemType LpGlpk::_getPrimalType() const {
       
   775     if (glp_get_status(lp) == GLP_OPT)
       
   776       return OPTIMAL;
       
   777     switch (glp_get_prim_stat(lp)) {
       
   778     case GLP_UNDEF:
       
   779       return UNDEFINED;
       
   780     case GLP_FEAS:
       
   781     case GLP_INFEAS:
       
   782       if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
       
   783         return UNBOUNDED;
       
   784       } else {
       
   785         return UNDEFINED;
       
   786       }
       
   787     case GLP_NOFEAS:
       
   788       return INFEASIBLE;
   476     default:
   789     default:
   477       lb=LEMON_glp(get_row_lb)(lp, i);
   790       LEMON_ASSERT(false, "Wrong primal type");
   478     }
   791       return  LpGlpk::ProblemType();
   479 
   792     }
   480     switch (b) {
   793   }
   481     case LEMON_GLP(FR):
   794 
   482     case LEMON_GLP(LO):
   795   LpGlpk::ProblemType LpGlpk::_getDualType() const {
   483       ub = INF;
   796     if (glp_get_status(lp) == GLP_OPT)
   484         break;
   797       return OPTIMAL;
       
   798     switch (glp_get_dual_stat(lp)) {
       
   799     case GLP_UNDEF:
       
   800       return UNDEFINED;
       
   801     case GLP_FEAS:
       
   802     case GLP_INFEAS:
       
   803       if (glp_get_prim_stat(lp) == GLP_NOFEAS) {
       
   804         return UNBOUNDED;
       
   805       } else {
       
   806         return UNDEFINED;
       
   807       }
       
   808     case GLP_NOFEAS:
       
   809       return INFEASIBLE;
   485     default:
   810     default:
   486       ub=LEMON_glp(get_row_ub)(lp, i);
   811       LEMON_ASSERT(false, "Wrong primal type");
   487     }
   812       return  LpGlpk::ProblemType();
   488 
   813     }
   489   }
   814   }
   490 
   815 
   491   void LpGlpk::_setObjCoeff(int i, Value obj_coef)
   816   void LpGlpk::presolver(bool b) {
   492   {
   817     lpx_set_int_parm(lp, LPX_K_PRESOL, b ? 1 : 0);
   493     //i=0 means the constant term (shift)
   818   }
   494     LEMON_glp(set_obj_coef)(lp, i, obj_coef);
   819 
   495 
   820   void LpGlpk::messageLevel(MessageLevel m) {
   496     solved = false;
   821     _message_level = m;
   497   }
   822   }
   498 
   823 
   499   LpGlpk::Value LpGlpk::_getObjCoeff(int i) const {
   824   // MipGlpk members
   500     //i=0 means the constant term (shift)
   825 
   501     return LEMON_glp(get_obj_coef)(lp, i);
   826   MipGlpk::MipGlpk()
   502   }
   827     : LpBase(), GlpkBase(), MipSolver() {
   503 
   828     messageLevel(MESSAGE_NO_OUTPUT);
   504   void LpGlpk::_clearObj()
   829   }
   505   {
   830 
   506     for (int i=0;i<=LEMON_glp(get_num_cols)(lp);++i){
   831   MipGlpk::MipGlpk(const MipGlpk& other)
   507       LEMON_glp(set_obj_coef)(lp, i, 0);
   832     : LpBase(), GlpkBase(other), MipSolver() {
   508     }
   833     messageLevel(MESSAGE_NO_OUTPUT);
   509 
   834   }
   510     solved = false;
   835 
   511   }
   836   void MipGlpk::_setColType(int i, MipGlpk::ColTypes col_type) {
   512 
   837     switch (col_type) {
   513   LpGlpk::SolveExitStatus LpGlpk::_solve()
   838     case INTEGER:
   514   {
   839       glp_set_col_kind(lp, i, GLP_IV);
   515     // A way to check the problem to be solved
   840       break;
   516     //LEMON_glp(write_cpxlp(lp,"naittvan.cpx");
   841     case REAL:
   517 
   842       glp_set_col_kind(lp, i, GLP_CV);
   518     LEMON_lpx(std_basis)(lp);
   843       break;
   519     int i =  LEMON_lpx(simplex)(lp);
   844     }
   520 
   845   }
   521     switch (i) {
   846 
   522     case LEMON_LPX(E_OK):
   847   MipGlpk::ColTypes MipGlpk::_getColType(int i) const {
   523       solved = true;
   848     switch (glp_get_col_kind(lp, i)) {
   524       return SOLVED;
   849     case GLP_IV:
       
   850     case GLP_BV:
       
   851       return INTEGER;
   525     default:
   852     default:
   526       return UNSOLVED;
   853       return REAL;
   527     }
   854     }
   528   }
   855 
   529 
   856   }
   530   LpGlpk::Value LpGlpk::_getPrimal(int i) const
   857 
   531   {
   858   MipGlpk::SolveExitStatus MipGlpk::_solve() {
   532     return LEMON_glp(get_col_prim)(lp,i);
   859     glp_smcp smcp;
   533   }
   860     glp_init_smcp(&smcp);
   534 
   861 
   535   LpGlpk::Value LpGlpk::_getDual(int i) const
   862     switch (_message_level) {
   536   {
   863     case MESSAGE_NO_OUTPUT:
   537     return LEMON_glp(get_row_dual)(lp,i);
   864       smcp.msg_lev = GLP_MSG_OFF;
   538   }
   865       break;
   539 
   866     case MESSAGE_ERROR_MESSAGE:
   540   LpGlpk::Value LpGlpk::_getPrimalValue() const
   867       smcp.msg_lev = GLP_MSG_ERR;
   541   {
   868       break;
   542     return LEMON_glp(get_obj_val)(lp);
   869     case MESSAGE_NORMAL_OUTPUT:
   543   }
   870       smcp.msg_lev = GLP_MSG_ON;
   544   bool LpGlpk::_isBasicCol(int i) const
   871       break;
   545   {
   872     case MESSAGE_FULL_OUTPUT:
   546     return (LEMON_glp(get_col_stat)(lp, i)==LEMON_GLP(BS));
   873       smcp.msg_lev = GLP_MSG_ALL;
   547   }
   874       break;
   548 
   875     }
   549 
   876     smcp.meth = GLP_DUAL;
   550   LpGlpk::SolutionStatus LpGlpk::_getPrimalStatus() const
   877 
   551   {
   878     if (glp_simplex(lp, &smcp) != 0) return UNSOLVED;
   552     if (!solved) return UNDEFINED;
   879     if (glp_get_status(lp) != GLP_OPT) return SOLVED;
   553     int stat=  LEMON_lpx(get_status)(lp);
   880 
   554     switch (stat) {
   881     glp_iocp iocp;
   555     case LEMON_LPX(UNDEF)://Undefined (no solve has been run yet)
   882     glp_init_iocp(&iocp);
   556       return UNDEFINED;
   883 
   557     case LEMON_LPX(NOFEAS)://There is no feasible solution (primal, I guess)
   884     switch (_message_level) {
   558     case LEMON_LPX(INFEAS)://Infeasible
   885     case MESSAGE_NO_OUTPUT:
   559       return INFEASIBLE;
   886       iocp.msg_lev = GLP_MSG_OFF;
   560     case LEMON_LPX(UNBND)://Unbounded
   887       break;
   561       return INFINITE;
   888     case MESSAGE_ERROR_MESSAGE:
   562     case LEMON_LPX(FEAS)://Feasible
   889       iocp.msg_lev = GLP_MSG_ERR;
   563       return FEASIBLE;
   890       break;
   564     case LEMON_LPX(OPT)://Feasible
   891     case MESSAGE_NORMAL_OUTPUT:
   565       return OPTIMAL;
   892       iocp.msg_lev = GLP_MSG_ON;
   566     default:
   893       break;
   567       return UNDEFINED; //to avoid gcc warning
   894     case MESSAGE_FULL_OUTPUT:
   568       //FIXME error
   895       iocp.msg_lev = GLP_MSG_ALL;
   569     }
   896       break;
   570   }
   897     }
   571 
   898 
   572   LpGlpk::SolutionStatus LpGlpk::_getDualStatus() const
   899     if (glp_intopt(lp, &iocp) != 0) return UNSOLVED;
   573   {
   900     return SOLVED;
   574     if (!solved) return UNDEFINED;
   901   }
   575     switch (LEMON_lpx(get_dual_stat)(lp)) {
   902 
   576     case LEMON_LPX(D_UNDEF)://Undefined (no solve has been run yet)
   903 
   577       return UNDEFINED;
   904   MipGlpk::ProblemType MipGlpk::_getType() const {
   578     case LEMON_LPX(D_NOFEAS)://There is no dual feasible solution
   905     switch (glp_get_status(lp)) {
   579 //    case LEMON_LPX(D_INFEAS://Infeasible
   906     case GLP_OPT:
   580       return INFEASIBLE;
   907       switch (glp_mip_status(lp)) {
   581     case LEMON_LPX(D_FEAS)://Feasible
   908       case GLP_UNDEF:
   582       switch (LEMON_lpx(get_status)(lp)) {
   909         return UNDEFINED;
   583       case LEMON_LPX(NOFEAS):
   910       case GLP_NOFEAS:
   584         return INFINITE;
   911         return INFEASIBLE;
   585       case LEMON_LPX(OPT):
   912       case GLP_FEAS:
       
   913         return FEASIBLE;
       
   914       case GLP_OPT:
   586         return OPTIMAL;
   915         return OPTIMAL;
   587       default:
   916       default:
   588         return FEASIBLE;
   917         LEMON_ASSERT(false, "Wrong problem type.");
       
   918         return MipGlpk::ProblemType();
       
   919       }
       
   920     case GLP_NOFEAS:
       
   921       return INFEASIBLE;
       
   922     case GLP_INFEAS:
       
   923     case GLP_FEAS:
       
   924       if (glp_get_dual_stat(lp) == GLP_NOFEAS) {
       
   925         return UNBOUNDED;
       
   926       } else {
       
   927         return UNDEFINED;
   589       }
   928       }
   590     default:
   929     default:
   591       return UNDEFINED; //to avoid gcc warning
   930       LEMON_ASSERT(false, "Wrong problem type.");
   592       //FIXME error
   931       return MipGlpk::ProblemType();
   593     }
   932     }
   594   }
   933   }
   595 
   934 
   596   LpGlpk::ProblemTypes LpGlpk::_getProblemType() const
   935   MipGlpk::Value MipGlpk::_getSol(int i) const {
   597   {
   936     return glp_mip_col_val(lp, i);
   598     if (!solved) return UNKNOWN;
   937   }
   599       //int stat=  LEMON_glp(get_status(lp);
   938 
   600     int statp=  LEMON_lpx(get_prim_stat)(lp);
   939   MipGlpk::Value MipGlpk::_getSolValue() const {
   601     int statd=  LEMON_lpx(get_dual_stat)(lp);
   940     return glp_mip_obj_val(lp);
   602     if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_FEAS))
   941   }
   603         return PRIMAL_DUAL_FEASIBLE;
   942 
   604     if (statp==LEMON_LPX(P_FEAS) && statd==LEMON_LPX(D_NOFEAS))
   943   MipGlpk* MipGlpk::_newSolver() const { return new MipGlpk; }
   605         return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
   944   MipGlpk* MipGlpk::_cloneSolver() const {return new MipGlpk(*this); }
   606     if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_FEAS))
   945 
   607         return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
   946   const char* MipGlpk::_solverName() const { return "MipGlpk"; }
   608     if (statp==LEMON_LPX(P_NOFEAS) && statd==LEMON_LPX(D_NOFEAS))
   947 
   609         return PRIMAL_DUAL_INFEASIBLE;
   948   void MipGlpk::messageLevel(MessageLevel m) {
   610     //In all other cases
   949     _message_level = m;
   611     return UNKNOWN;
   950   }
   612   }
       
   613 
       
   614   void LpGlpk::_setMax()
       
   615   {
       
   616     solved = false;
       
   617     LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MAX));
       
   618   }
       
   619 
       
   620   void LpGlpk::_setMin()
       
   621   {
       
   622     solved = false;
       
   623     LEMON_glp(set_obj_dir)(lp, LEMON_GLP(MIN));
       
   624   }
       
   625 
       
   626   bool LpGlpk::_isMax() const
       
   627   {
       
   628     return (LEMON_glp(get_obj_dir)(lp)==LEMON_GLP(MAX));
       
   629   }
       
   630 
       
   631 
       
   632 
       
   633   void LpGlpk::messageLevel(int m)
       
   634   {
       
   635     LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_MSGLEV), m);
       
   636   }
       
   637 
       
   638   void LpGlpk::presolver(bool b)
       
   639   {
       
   640     LEMON_lpx(set_int_parm)(lp, LEMON_LPX(K_PRESOL), b);
       
   641   }
       
   642 
       
   643 
   951 
   644 } //END OF NAMESPACE LEMON
   952 } //END OF NAMESPACE LEMON