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 #include<lemon/lp_cplex.h>
23 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
26 LpCplex::LpCplex() : LpSolverBase() {
28 // env = CPXopenCPLEXdevelop(&status);
29 env = CPXopenCPLEX(&status);
30 lp = CPXcreateprob(env, &status, "LP problem");
38 LpSolverBase &LpCplex::_newLp()
40 //The first approach opens a new environment
41 LpCplex* newlp=new LpCplex();
45 LpSolverBase &LpCplex::_copyLp() {
46 //The first approach opens a new environment
47 LpCplex* newlp=new LpCplex();
48 //The routine CPXcloneprob can be used to create a new CPLEX problem
49 //object and copy all the problem data from an existing problem
50 //object to it. Solution and starting information is not copied.
51 newlp->lp = CPXcloneprob(env, lp, &status);
55 int LpCplex::_addCol()
57 int i = CPXgetnumcols(env, lp);
59 lb[0]=-INF;//-CPX_INFBOUND;
60 ub[0]=INF;//CPX_INFBOUND;
61 status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
66 int LpCplex::_addRow()
68 //We want a row that is not constrained
70 sense[0]='L';//<= constraint
73 int i = CPXgetnumrows(env, lp);
74 status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
79 void LpCplex::_eraseCol(int i) {
80 CPXdelcols(env, lp, i, i);
83 void LpCplex::_eraseRow(int i) {
84 CPXdelrows(env, lp, i, i);
87 void LpCplex::_getColName(int col, std::string &name)
91 CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
97 ///\bug return code unchecked for error
98 CPXgetcolname(env, lp, names, buf, storespace, &dontcare, col, col);
102 void LpCplex::_setColName(int col, const std::string &name)
106 names[0] = const_cast<char*>(name.c_str());
107 ///\bug return code unchecked for error
108 CPXchgcolname(env, lp, 1, &col, names);
111 ///\warning Data at index 0 is ignored in the arrays.
112 void LpCplex::_setRowCoeffs(int i, LpRowIterator b, LpRowIterator e)
114 std::vector<int> indices;
115 std::vector<int> rowlist;
116 std::vector<Value> values;
118 for(LpRowIterator it=b; it!=e; ++it) {
119 indices.push_back(it->first);
120 values.push_back(it->second);
121 rowlist.push_back(i);
124 status = CPXchgcoeflist(env, lp, values.size(),
125 &rowlist[0], &indices[0], &values[0]);
128 void LpCplex::_setColCoeffs(int i, LpColIterator b, LpColIterator e)
130 std::vector<int> indices;
131 std::vector<int> collist;
132 std::vector<Value> values;
134 for(LpColIterator it=b; it!=e; ++it) {
135 indices.push_back(it->first);
136 values.push_back(it->second);
137 collist.push_back(i);
140 status = CPXchgcoeflist(env, lp, values.size(),
141 &indices[0], &collist[0], &values[0]);
144 void LpCplex::_setCoeff(int row, int col, Value value)
146 CPXchgcoef(env, lp, row, col, value);
149 void LpCplex::_setColLowerBound(int i, Value value)
157 status = CPXchgbds(env, lp, 1, indices, lu, bd);
161 void LpCplex::_setColUpperBound(int i, Value value)
169 status = CPXchgbds(env, lp, 1, indices, lu, bd);
172 //This will be easier to implement
173 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
176 if (lb==INF || ub==-INF) {
187 CPXchgsense(env, lp, cnt, indices, sense);
188 CPXchgcoef(env, lp, i, -1, ub);
194 CPXchgsense(env, lp, cnt, indices, sense);
195 CPXchgcoef(env, lp, i, -1, lb);
200 CPXchgsense(env, lp, cnt, indices, sense);
201 CPXchgcoef(env, lp, i, -1, lb);
205 CPXchgsense(env, lp, cnt, indices, sense);
206 CPXchgcoef(env, lp, i, -1, lb);
207 CPXchgcoef(env, lp, i, -2, ub-lb);
213 // void LpCplex::_setRowLowerBound(int i, Value value)
215 // //Not implemented, obsolete
218 // void LpCplex::_setRowUpperBound(int i, Value value)
220 // //Not implemented, obsolete
221 // // //TODO Ezt kell meg megirni
222 // // //type of the problem
224 // // status = CPXgetsense(env, lp, sense, i, i);
226 // // status = CPXgetrhs(env, lp, rhs, i, i);
228 // // switch (sense[0]) {
229 // // case 'L'://<= constraint
231 // // case 'E'://= constraint
233 // // case 'G'://>= constraint
235 // // case 'R'://ranged constraint
241 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
244 void LpCplex::_setObjCoeff(int i, Value obj_coef)
246 CPXchgcoef(env, lp, -1, i, obj_coef);
249 void LpCplex::_clearObj()
251 for (int i=0;i< CPXgetnumcols(env, lp);++i){
252 CPXchgcoef(env, lp, -1, i, 0);
256 // The routine returns zero unless an error occurred during the
257 // optimization. Examples of errors include exhausting available
258 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
259 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
260 // user-specified CPLEX limit, or proving the model infeasible or
261 // unbounded, are not considered errors. Note that a zero return
262 // value does not necessarily mean that a solution exists. Use query
263 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
264 // further information about the status of the optimization.
265 LpCplex::SolveExitStatus LpCplex::_solve()
268 status = CPXlpopt(env, lp);
269 //status = CPXprimopt(env, lp);
270 #if CPX_VERSION >= 800
277 switch (CPXgetstat(env, lp))
279 case CPX_STAT_OPTIMAL:
280 case CPX_STAT_INFEASIBLE:
281 case CPX_STAT_UNBOUNDED:
289 //We want to exclude some cases
290 switch (CPXgetstat(env, lp)){
292 case CPX_IT_LIM_FEAS:
293 case CPX_IT_LIM_INFEAS:
294 case CPX_TIME_LIM_FEAS:
295 case CPX_TIME_LIM_INFEAS:
307 LpCplex::Value LpCplex::_getPrimal(int i)
310 CPXgetx(env, lp, &x, i, i);
314 LpCplex::Value LpCplex::_getDual(int i)
317 CPXgetpi(env, lp, &y, i, i);
321 LpCplex::Value LpCplex::_getPrimalValue()
324 //method = CPXgetmethod (env, lp);
325 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
326 status = CPXgetobjval(env, lp, &objval);
327 //printf("Objective value: %g \n",objval);
330 bool LpCplex::_isBasicCol(int i) {
331 int cstat[CPXgetnumcols(env, lp)];
332 CPXgetbase(env, lp, cstat, NULL);
333 return (cstat[i]==CPX_BASIC);
336 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
337 // This table lists the statuses, returned by the CPXgetstat() routine, for solutions to LP problems or mixed integer problems. If no solution exists, the return value is zero.
339 // For Simplex, Barrier
341 // Optimal solution found
343 // Problem infeasible
347 // Objective limit exceeded in Phase II
349 // Iteration limit exceeded in Phase II
350 // 6 CPX_IT_LIM_INFEAS
351 // Iteration limit exceeded in Phase I
352 // 7 CPX_TIME_LIM_FEAS
353 // Time limit exceeded in Phase II
354 // 8 CPX_TIME_LIM_INFEAS
355 // Time limit exceeded in Phase I
356 // 9 CPX_NUM_BEST_FEAS
357 // Problem non-optimal, singularities in Phase II
358 // 10 CPX_NUM_BEST_INFEAS
359 // Problem non-optimal, singularities in Phase I
360 // 11 CPX_OPTIMAL_INFEAS
361 // Optimal solution found, unscaled infeasibilities
363 // Aborted in Phase II
364 // 13 CPX_ABORT_INFEAS
365 // Aborted in Phase I
366 // 14 CPX_ABORT_DUAL_INFEAS
367 // Aborted in barrier, dual infeasible
368 // 15 CPX_ABORT_PRIM_INFEAS
369 // Aborted in barrier, primal infeasible
370 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
371 // Aborted in barrier, primal and dual infeasible
372 // 17 CPX_ABORT_PRIM_DUAL_FEAS
373 // Aborted in barrier, primal and dual feasible
374 // 18 CPX_ABORT_CROSSOVER
375 // Aborted in crossover
377 // Infeasible or unbounded
381 // Ezeket hova tegyem:
382 // ??case CPX_ABORT_DUAL_INFEAS
383 // ??case CPX_ABORT_CROSSOVER
384 // ??case CPX_INForUNBD
387 //Some more interesting stuff:
389 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
394 // 4 Standard Barrier
396 // Description: Method for linear optimization.
397 // Determines which algorithm is used when CPXlpopt() (or "optimize" in the Interactive Optimizer) is called. Currently the behavior of the "Automatic" setting is that CPLEX simply invokes the dual simplex method, but this capability may be expanded in the future so that CPLEX chooses the method based on problem characteristics
399 void statusSwitch(CPXENVptr env,int& stat){
400 #if CPX_VERSION < 900
402 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
404 if (stat==CPX_UNBOUNDED){
408 if (stat==CPX_INFEASIBLE)
415 LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
417 //Unboundedness not treated well: the following is from cplex 9.0 doc
418 // About Unboundedness
420 // The treatment of models that are unbounded involves a few
421 // subtleties. Specifically, a declaration of unboundedness means that
422 // ILOG CPLEX has determined that the model has an unbounded
423 // ray. Given any feasible solution x with objective z, a multiple of
424 // the unbounded ray can be added to x to give a feasible solution
425 // with objective z-1 (or z+1 for maximization models). Thus, if a
426 // feasible solution exists, then the optimal objective is
427 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
428 // a feasible solution exists. Users can call the routine CPXsolninfo
429 // to determine whether ILOG CPLEX has also concluded that the model
430 // has a feasible solution.
432 int stat = CPXgetstat(env, lp);
433 #if CPX_VERSION >= 800
436 case CPX_STAT_OPTIMAL:
438 case CPX_STAT_UNBOUNDED:
440 case CPX_STAT_INFEASIBLE:
446 statusSwitch(env,stat);
447 //CPXgetstat(env, lp);
448 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
451 return UNDEFINED; //Undefined
452 case CPX_OPTIMAL://Optimal
454 case CPX_UNBOUNDED://Unbounded
455 return INFEASIBLE;//In case of dual simplex
457 case CPX_INFEASIBLE://Infeasible
458 // case CPX_IT_LIM_INFEAS:
459 // case CPX_TIME_LIM_INFEAS:
460 // case CPX_NUM_BEST_INFEAS:
461 // case CPX_OPTIMAL_INFEAS:
462 // case CPX_ABORT_INFEAS:
463 // case CPX_ABORT_PRIM_INFEAS:
464 // case CPX_ABORT_PRIM_DUAL_INFEAS:
465 return INFINITE;//In case of dual simplex
468 // case CPX_IT_LIM_FEAS:
469 // case CPX_TIME_LIM_FEAS:
470 // case CPX_NUM_BEST_FEAS:
471 // case CPX_ABORT_FEAS:
472 // case CPX_ABORT_PRIM_DUAL_FEAS:
475 return UNDEFINED; //Everything else comes here
481 //9.0-as cplex verzio statusai
482 // CPX_STAT_ABORT_DUAL_OBJ_LIM
483 // CPX_STAT_ABORT_IT_LIM
484 // CPX_STAT_ABORT_OBJ_LIM
485 // CPX_STAT_ABORT_PRIM_OBJ_LIM
486 // CPX_STAT_ABORT_TIME_LIM
487 // CPX_STAT_ABORT_USER
488 // CPX_STAT_FEASIBLE_RELAXED
489 // CPX_STAT_INFEASIBLE
490 // CPX_STAT_INForUNBD
493 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
494 // CPX_STAT_OPTIMAL_INFEAS
495 // CPX_STAT_OPTIMAL_RELAXED
496 // CPX_STAT_UNBOUNDED
498 LpCplex::SolutionStatus LpCplex::_getDualStatus()
500 int stat = CPXgetstat(env, lp);
501 #if CPX_VERSION >= 800
504 case CPX_STAT_OPTIMAL:
506 case CPX_STAT_UNBOUNDED:
512 statusSwitch(env,stat);
515 return UNDEFINED; //Undefined
516 case CPX_OPTIMAL://Optimal
521 return UNDEFINED; //Everything else comes here
527 LpCplex::ProblemTypes LpCplex::_getProblemType()
529 int stat = CPXgetstat(env, lp);
530 #if CPX_VERSION >= 800
533 case CPX_STAT_OPTIMAL:
534 return PRIMAL_DUAL_FEASIBLE;
535 case CPX_STAT_UNBOUNDED:
536 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
542 case CPX_OPTIMAL://Optimal
543 return PRIMAL_DUAL_FEASIBLE;
545 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
546 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
547 // return PRIMAL_DUAL_INFEASIBLE;
549 //Seems to be that this is all we can say for sure
558 void LpCplex::_setMax()
560 CPXchgobjsen(env, lp, CPX_MAX);
562 void LpCplex::_setMin()
564 CPXchgobjsen(env, lp, CPX_MIN);