2 * lemon/lp_cplex.cc - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #include<lemon/lp_cplex.h>
20 ///\brief Implementation of the LEMON-CPLEX lp solver interface.
23 LpCplex::LpCplex() : LpSolverBase() {
25 // env = CPXopenCPLEXdevelop(&status);
26 env = CPXopenCPLEX(&status);
27 lp = CPXcreateprob(env, &status, "LP problem");
35 LpSolverBase &LpCplex::_newLp()
37 //The first approach opens a new environment
38 LpCplex* newlp=new LpCplex();
42 LpSolverBase &LpCplex::_copyLp() {
43 //The first approach opens a new environment
44 LpCplex* newlp=new LpCplex();
45 //The routine CPXcloneprob can be used to create a new CPLEX problem
46 //object and copy all the problem data from an existing problem
47 //object to it. Solution and starting information is not copied.
48 newlp->lp = CPXcloneprob(env, lp, &status);
52 int LpCplex::_addCol()
54 int i = CPXgetnumcols(env, lp);
56 lb[0]=-INF;//-CPX_INFBOUND;
57 ub[0]=INF;//CPX_INFBOUND;
58 status = CPXnewcols(env, lp, 1, NULL, lb, ub, NULL, NULL);
63 int LpCplex::_addRow()
65 //We want a row that is not constrained
67 sense[0]='L';//<= constraint
70 int i = CPXgetnumrows(env, lp);
71 status = CPXnewrows(env, lp, 1, rhs, sense, NULL, NULL);
76 void LpCplex::_eraseCol(int i) {
77 CPXdelcols(env, lp, i, i);
80 void LpCplex::_eraseRow(int i) {
81 CPXdelrows(env, lp, i, i);
84 void LpCplex::_getColName(int col, std::string &name)
88 CPXgetcolname(env, lp, 0, 0, 0, &storespace, col, col);
94 ///\bug return code unchecked for error
95 CPXgetcolname(env, lp, names, buf, storespace, &dontcare, col, col);
99 void LpCplex::_setColName(int col, const std::string &name)
103 names[0] = const_cast<char*>(name.c_str());
104 ///\bug return code unchecked for error
105 CPXchgcolname(env, lp, 1, &col, names);
108 ///\warning Data at index 0 is ignored in the arrays.
109 void LpCplex::_setRowCoeffs(int i,
112 Value const * values )
114 int rowlist[length+1];
116 for (int k=1;k<=length;++k){
119 status = CPXchgcoeflist(env, lp,
122 const_cast<int * >(indices+1),
123 const_cast<Value * >(values+1));
126 void LpCplex::_setColCoeffs(int i,
129 Value const * values)
131 int collist[length+1];
133 for (int k=1;k<=length;++k){
136 status = CPXchgcoeflist(env, lp,
138 const_cast<int * >(indices+1),
140 const_cast<Value * >(values+1));
143 void LpCplex::_setCoeff(int row, int col, Value value)
145 CPXchgcoef(env, lp, row, col, value);
148 void LpCplex::_setColLowerBound(int i, Value value)
156 status = CPXchgbds(env, lp, 1, indices, lu, bd);
160 void LpCplex::_setColUpperBound(int i, Value value)
168 status = CPXchgbds(env, lp, 1, indices, lu, bd);
171 //This will be easier to implement
172 void LpCplex::_setRowBounds(int i, Value lb, Value ub)
175 if (lb==INF || ub==-INF) {
186 CPXchgsense(env, lp, cnt, indices, sense);
187 CPXchgcoef(env, lp, i, -1, ub);
193 CPXchgsense(env, lp, cnt, indices, sense);
194 CPXchgcoef(env, lp, i, -1, lb);
199 CPXchgsense(env, lp, cnt, indices, sense);
200 CPXchgcoef(env, lp, i, -1, lb);
204 CPXchgsense(env, lp, cnt, indices, sense);
205 CPXchgcoef(env, lp, i, -1, lb);
206 CPXchgcoef(env, lp, i, -2, ub-lb);
212 // void LpCplex::_setRowLowerBound(int i, Value value)
214 // //Not implemented, obsolete
217 // void LpCplex::_setRowUpperBound(int i, Value value)
219 // //Not implemented, obsolete
220 // // //TODO Ezt kell meg megirni
221 // // //type of the problem
223 // // status = CPXgetsense(env, lp, sense, i, i);
225 // // status = CPXgetrhs(env, lp, rhs, i, i);
227 // // switch (sense[0]) {
228 // // case 'L'://<= constraint
230 // // case 'E'://= constraint
232 // // case 'G'://>= constraint
234 // // case 'R'://ranged constraint
240 // // status = CPXchgcoef(env, lp, i, -2, value_rng);
243 void LpCplex::_setObjCoeff(int i, Value obj_coef)
245 CPXchgcoef(env, lp, -1, i, obj_coef);
248 void LpCplex::_clearObj()
250 for (int i=0;i< CPXgetnumcols(env, lp);++i){
251 CPXchgcoef(env, lp, -1, i, 0);
255 // The routine returns zero unless an error occurred during the
256 // optimization. Examples of errors include exhausting available
257 // memory (CPXERR_NO_MEMORY) or encountering invalid data in the
258 // CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
259 // user-specified CPLEX limit, or proving the model infeasible or
260 // unbounded, are not considered errors. Note that a zero return
261 // value does not necessarily mean that a solution exists. Use query
262 // routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
263 // further information about the status of the optimization.
264 LpCplex::SolveExitStatus LpCplex::_solve()
267 status = CPXlpopt(env, lp);
268 //status = CPXprimopt(env, lp);
270 //We want to exclude some cases
271 switch (CPXgetstat(env, lp)){
273 case CPX_IT_LIM_FEAS:
274 case CPX_IT_LIM_INFEAS:
275 case CPX_TIME_LIM_FEAS:
276 case CPX_TIME_LIM_INFEAS:
287 LpCplex::Value LpCplex::_getPrimal(int i)
290 CPXgetx(env, lp, &x, i, i);
294 LpCplex::Value LpCplex::_getDual(int i)
297 CPXgetpi(env, lp, &y, i, i);
301 LpCplex::Value LpCplex::_getPrimalValue()
304 //method = CPXgetmethod (env, lp);
305 //printf("CPXgetprobtype %d \n",CPXgetprobtype(env,lp));
306 status = CPXgetobjval(env, lp, &objval);
307 //printf("Objective value: %g \n",objval);
310 bool LpCplex::_isBasicCol(int i) {
311 int cstat[CPXgetnumcols(env, lp)];
312 CPXgetbase(env, lp, cstat, NULL);
313 return (cstat[i]==CPX_BASIC);
316 //7.5-os cplex statusai (Vigyazat: a 9.0-asei masok!)
317 // 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.
319 // For Simplex, Barrier
321 // Optimal solution found
323 // Problem infeasible
327 // Objective limit exceeded in Phase II
329 // Iteration limit exceeded in Phase II
330 // 6 CPX_IT_LIM_INFEAS
331 // Iteration limit exceeded in Phase I
332 // 7 CPX_TIME_LIM_FEAS
333 // Time limit exceeded in Phase II
334 // 8 CPX_TIME_LIM_INFEAS
335 // Time limit exceeded in Phase I
336 // 9 CPX_NUM_BEST_FEAS
337 // Problem non-optimal, singularities in Phase II
338 // 10 CPX_NUM_BEST_INFEAS
339 // Problem non-optimal, singularities in Phase I
340 // 11 CPX_OPTIMAL_INFEAS
341 // Optimal solution found, unscaled infeasibilities
343 // Aborted in Phase II
344 // 13 CPX_ABORT_INFEAS
345 // Aborted in Phase I
346 // 14 CPX_ABORT_DUAL_INFEAS
347 // Aborted in barrier, dual infeasible
348 // 15 CPX_ABORT_PRIM_INFEAS
349 // Aborted in barrier, primal infeasible
350 // 16 CPX_ABORT_PRIM_DUAL_INFEAS
351 // Aborted in barrier, primal and dual infeasible
352 // 17 CPX_ABORT_PRIM_DUAL_FEAS
353 // Aborted in barrier, primal and dual feasible
354 // 18 CPX_ABORT_CROSSOVER
355 // Aborted in crossover
357 // Infeasible or unbounded
361 // Ezeket hova tegyem:
362 // ??case CPX_ABORT_DUAL_INFEAS
363 // ??case CPX_ABORT_CROSSOVER
364 // ??case CPX_INForUNBD
367 //Some more interesting stuff:
369 // CPX_PARAM_LPMETHOD 1062 int LPMETHOD
374 // 4 Standard Barrier
376 // Description: Method for linear optimization.
377 // 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
379 void statusSwitch(CPXENVptr env,int& stat){
381 CPXgetintparam (env,CPX_PARAM_LPMETHOD,&lpmethod);
383 if (stat==CPX_UNBOUNDED){
387 if (stat==CPX_INFEASIBLE)
393 LpCplex::SolutionStatus LpCplex::_getPrimalStatus()
396 int stat = CPXgetstat(env, lp);
397 statusSwitch(env,stat);
398 //CPXgetstat(env, lp);
399 //printf("A primal status: %d, CPX_OPTIMAL=%d \n",stat,CPX_OPTIMAL);
402 return UNDEFINED; //Undefined
403 case CPX_OPTIMAL://Optimal
405 case CPX_UNBOUNDED://Unbounded
406 return INFEASIBLE;//In case of dual simplex
408 case CPX_INFEASIBLE://Infeasible
409 // case CPX_IT_LIM_INFEAS:
410 // case CPX_TIME_LIM_INFEAS:
411 // case CPX_NUM_BEST_INFEAS:
412 // case CPX_OPTIMAL_INFEAS:
413 // case CPX_ABORT_INFEAS:
414 // case CPX_ABORT_PRIM_INFEAS:
415 // case CPX_ABORT_PRIM_DUAL_INFEAS:
416 return INFINITE;//In case of dual simplex
419 // case CPX_IT_LIM_FEAS:
420 // case CPX_TIME_LIM_FEAS:
421 // case CPX_NUM_BEST_FEAS:
422 // case CPX_ABORT_FEAS:
423 // case CPX_ABORT_PRIM_DUAL_FEAS:
426 return UNDEFINED; //Everything else comes here
432 //9.0-as cplex verzio statusai
433 // CPX_STAT_ABORT_DUAL_OBJ_LIM
434 // CPX_STAT_ABORT_IT_LIM
435 // CPX_STAT_ABORT_OBJ_LIM
436 // CPX_STAT_ABORT_PRIM_OBJ_LIM
437 // CPX_STAT_ABORT_TIME_LIM
438 // CPX_STAT_ABORT_USER
439 // CPX_STAT_FEASIBLE_RELAXED
440 // CPX_STAT_INFEASIBLE
441 // CPX_STAT_INForUNBD
444 // CPX_STAT_OPTIMAL_FACE_UNBOUNDED
445 // CPX_STAT_OPTIMAL_INFEAS
446 // CPX_STAT_OPTIMAL_RELAXED
447 // CPX_STAT_UNBOUNDED
449 LpCplex::SolutionStatus LpCplex::_getDualStatus()
451 int stat = CPXgetstat(env, lp);
452 statusSwitch(env,stat);
455 return UNDEFINED; //Undefined
456 case CPX_OPTIMAL://Optimal
461 return UNDEFINED; //Everything else comes here
466 LpCplex::ProblemTypes LpCplex::_getProblemType()
468 int stat = CPXgetstat(env, lp);
470 case CPX_OPTIMAL://Optimal
471 return PRIMAL_DUAL_FEASIBLE;
473 return PRIMAL_FEASIBLE_DUAL_INFEASIBLE;
474 // return PRIMAL_INFEASIBLE_DUAL_FEASIBLE;
475 // return PRIMAL_DUAL_INFEASIBLE;
477 //Seems to be that this is all we can say for sure
485 void LpCplex::_setMax()
487 CPXchgobjsen(env, lp, CPX_MAX);
489 void LpCplex::_setMin()
491 CPXchgobjsen(env, lp, CPX_MIN);