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,
115 Value const * values )
117 int rowlist[length+1];
119 for (int k=1;k<=length;++k){
122 status = CPXchgcoeflist(env, lp,
125 const_cast<int * >(indices+1),
126 const_cast<Value * >(values+1));
129 void LpCplex::_setColCoeffs(int i,
132 Value const * values)
134 int collist[length+1];
136 for (int k=1;k<=length;++k){
139 status = CPXchgcoeflist(env, lp,
141 const_cast<int * >(indices+1),
143 const_cast<Value * >(values+1));
146 void LpCplex::_setCoeff(int row, int col, Value value)
148 CPXchgcoef(env, lp, row, col, value);
151 void LpCplex::_setColLowerBound(int i, Value value)
159 status = CPXchgbds(env, lp, 1, indices, lu, bd);
163 void LpCplex::_setColUpperBound(int i, Value value)
171 status = CPXchgbds(env, lp, 1, indices, lu, bd);
174 //This will be easier to implement
175 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
178 if (lb==INF || ub==-INF) {
189 CPXchgsense(env, lp, cnt, indices, sense);
190 CPXchgcoef(env, lp, i, -1, ub);
196 CPXchgsense(env, lp, cnt, indices, sense);
197 CPXchgcoef(env, lp, i, -1, lb);
202 CPXchgsense(env, lp, cnt, indices, sense);
203 CPXchgcoef(env, lp, i, -1, lb);
207 CPXchgsense(env, lp, cnt, indices, sense);
208 CPXchgcoef(env, lp, i, -1, lb);
209 CPXchgcoef(env, lp, i, -2, ub-lb);
215 // void LpCplex::_setRowLowerBound(int i, Value value)
217 // //Not implemented, obsolete
220 // void LpCplex::_setRowUpperBound(int i, Value value)
222 // //Not implemented, obsolete
223 // // //TODO Ezt kell meg megirni
224 // // //type of the problem
226 // // status = CPXgetsense(env, lp, sense, i, i);
228 // // status = CPXgetrhs(env, lp, rhs, i, i);
230 // // switch (sense[0]) {
231 // // case 'L'://<= constraint
233 // // case 'E'://= constraint
235 // // case 'G'://>= constraint
237 // // case 'R'://ranged constraint
243 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
246 void LpCplex::_setObjCoeff(int i, Value obj_coef)
248 CPXchgcoef(env, lp, -1, i, obj_coef);
251 void LpCplex::_clearObj()
253 for (int i=0;i< CPXgetnumcols(env, lp);++i){
254 CPXchgcoef(env, lp, -1, i, 0);
258 // The routine returns zero unless an error occurred during the
259 // optimization. Examples of errors include exhausting available
260 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
261 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
262 // user-specified CPLEX limit, or proving the model infeasible or
263 // unbounded, are not considered errors. Note that a zero return
264 // value does not necessarily mean that a solution exists. Use query
265 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
266 // further information about the status of the optimization.
267 LpCplex::SolveExitStatus LpCplex::_solve()
270 status = CPXlpopt(env, lp);
271 //status = CPXprimopt(env, lp);
272 #if CPX_VERSION >= 800
279 switch (CPXgetstat(env, lp))
281 case CPX_STAT_OPTIMAL:
282 case CPX_STAT_INFEASIBLE:
283 case CPX_STAT_UNBOUNDED:
291 //We want to exclude some cases
292 switch (CPXgetstat(env, lp)){
294 case CPX_IT_LIM_FEAS:
295 case CPX_IT_LIM_INFEAS:
296 case CPX_TIME_LIM_FEAS:
297 case CPX_TIME_LIM_INFEAS:
309 LpCplex::Value LpCplex::_getPrimal(int i)
312 CPXgetx(env, lp, &x, i, i);
316 LpCplex::Value LpCplex::_getDual(int i)
319 CPXgetpi(env, lp, &y, i, i);
323 LpCplex::Value LpCplex::_getPrimalValue()
326 //method = CPXgetmethod (env, lp);
327 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
328 status = CPXgetobjval(env, lp, &objval);
329 //printf("Objective value: %g \n",objval);
332 bool LpCplex::_isBasicCol(int i) {
333 int cstat[CPXgetnumcols(env, lp)];
334 CPXgetbase(env, lp, cstat, NULL);
335 return (cstat[i]==CPX_BASIC);
338 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
339 // 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.
341 // For Simplex, Barrier
343 // Optimal solution found
345 // Problem infeasible
349 // Objective limit exceeded in Phase II
351 // Iteration limit exceeded in Phase II
352 // 6 CPX_IT_LIM_INFEAS
353 // Iteration limit exceeded in Phase I
354 // 7 CPX_TIME_LIM_FEAS
355 // Time limit exceeded in Phase II
356 // 8 CPX_TIME_LIM_INFEAS
357 // Time limit exceeded in Phase I
358 // 9 CPX_NUM_BEST_FEAS
359 // Problem non-optimal, singularities in Phase II
360 // 10 CPX_NUM_BEST_INFEAS
361 // Problem non-optimal, singularities in Phase I
362 // 11 CPX_OPTIMAL_INFEAS
363 // Optimal solution found, unscaled infeasibilities
365 // Aborted in Phase II
366 // 13 CPX_ABORT_INFEAS
367 // Aborted in Phase I
368 // 14 CPX_ABORT_DUAL_INFEAS
369 // Aborted in barrier, dual infeasible
370 // 15 CPX_ABORT_PRIM_INFEAS
371 // Aborted in barrier, primal infeasible
372 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
373 // Aborted in barrier, primal and dual infeasible
374 // 17 CPX_ABORT_PRIM_DUAL_FEAS
375 // Aborted in barrier, primal and dual feasible
376 // 18 CPX_ABORT_CROSSOVER
377 // Aborted in crossover
379 // Infeasible or unbounded
383 // Ezeket hova tegyem:
384 // ??case CPX_ABORT_DUAL_INFEAS
385 // ??case CPX_ABORT_CROSSOVER
386 // ??case CPX_INForUNBD
389 //Some more interesting stuff:
391 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
396 // 4 Standard Barrier
398 // Description: Method for linear optimization.
399 // 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
401 void statusSwitch(CPXENVptr env,int& stat){
402 #if CPX_VERSION < 900
404 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
406 if (stat==CPX_UNBOUNDED){
410 if (stat==CPX_INFEASIBLE)
417 LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
419 //Unboundedness not treated well: the following is from cplex 9.0 doc
420 // About Unboundedness
422 // The treatment of models that are unbounded involves a few
423 // subtleties. Specifically, a declaration of unboundedness means that
424 // ILOG CPLEX has determined that the model has an unbounded
425 // ray. Given any feasible solution x with objective z, a multiple of
426 // the unbounded ray can be added to x to give a feasible solution
427 // with objective z-1 (or z+1 for maximization models). Thus, if a
428 // feasible solution exists, then the optimal objective is
429 // unbounded. Note that ILOG CPLEX has not necessarily concluded that
430 // a feasible solution exists. Users can call the routine CPXsolninfo
431 // to determine whether ILOG CPLEX has also concluded that the model
432 // has a feasible solution.
434 int stat = CPXgetstat(env, lp);
435 #if CPX_VERSION >= 800
438 case CPX_STAT_OPTIMAL:
440 case CPX_STAT_UNBOUNDED:
442 case CPX_STAT_INFEASIBLE:
448 statusSwitch(env,stat);
449 //CPXgetstat(env, lp);
450 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
453 return UNDEFINED; //Undefined
454 case CPX_OPTIMAL://Optimal
456 case CPX_UNBOUNDED://Unbounded
457 return INFEASIBLE;//In case of dual simplex
459 case CPX_INFEASIBLE://Infeasible
460 // case CPX_IT_LIM_INFEAS:
461 // case CPX_TIME_LIM_INFEAS:
462 // case CPX_NUM_BEST_INFEAS:
463 // case CPX_OPTIMAL_INFEAS:
464 // case CPX_ABORT_INFEAS:
465 // case CPX_ABORT_PRIM_INFEAS:
466 // case CPX_ABORT_PRIM_DUAL_INFEAS:
467 return INFINITE;//In case of dual simplex
470 // case CPX_IT_LIM_FEAS:
471 // case CPX_TIME_LIM_FEAS:
472 // case CPX_NUM_BEST_FEAS:
473 // case CPX_ABORT_FEAS:
474 // case CPX_ABORT_PRIM_DUAL_FEAS:
477 return UNDEFINED; //Everything else comes here
483 //9.0-as cplex verzio statusai
484 // CPX_STAT_ABORT_DUAL_OBJ_LIM
485 // CPX_STAT_ABORT_IT_LIM
486 // CPX_STAT_ABORT_OBJ_LIM
487 // CPX_STAT_ABORT_PRIM_OBJ_LIM
488 // CPX_STAT_ABORT_TIME_LIM
489 // CPX_STAT_ABORT_USER
490 // CPX_STAT_FEASIBLE_RELAXED
491 // CPX_STAT_INFEASIBLE
492 // CPX_STAT_INForUNBD
495 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
496 // CPX_STAT_OPTIMAL_INFEAS
497 // CPX_STAT_OPTIMAL_RELAXED
498 // CPX_STAT_UNBOUNDED
500 LpCplex::SolutionStatus LpCplex::_getDualStatus()
502 int stat = CPXgetstat(env, lp);
503 #if CPX_VERSION >= 800
506 case CPX_STAT_OPTIMAL:
508 case CPX_STAT_UNBOUNDED:
514 statusSwitch(env,stat);
517 return UNDEFINED; //Undefined
518 case CPX_OPTIMAL://Optimal
523 return UNDEFINED; //Everything else comes here
529 LpCplex::ProblemTypes LpCplex::_getProblemType()
531 int stat = CPXgetstat(env, lp);
532 #if CPX_VERSION >= 800
535 case CPX_STAT_OPTIMAL:
536 return PRIMAL_DUAL_FEASIBLE;
537 case CPX_STAT_UNBOUNDED:
538 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
544 case CPX_OPTIMAL://Optimal
545 return PRIMAL_DUAL_FEASIBLE;
547 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
548 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
549 // return PRIMAL_DUAL_INFEASIBLE;
551 //Seems to be that this is all we can say for sure
560 void LpCplex::_setMax()
562 CPXchgobjsen(env, lp, CPX_MAX);
564 void LpCplex::_setMin()
566 CPXchgobjsen(env, lp, CPX_MIN);