00001 /* EGlib "Efficient General Library" provides some basic structures and 00002 * algorithms commons in many optimization algorithms. 00003 * 00004 * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea. 00005 * 00006 * This library is free software; you can redistribute it and/or modify it 00007 * under the terms of the GNU Lesser General Public License as published by the 00008 * Free Software Foundation; either version 2.1 of the License, or (at your 00009 * option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, but 00012 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 00013 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00014 * License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this library; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 * */ 00020 /* ========================================================================= */ 00021 /* this is the header file for the CPLEX structure 00022 * 00023 * 2004-04-07 - Fiz free of null arrays (Renan Garcia) 00024 * 2003-05-19 - Fix a bug in EGcplexAdd{Col,Row}* related to malloc if size zero 00025 * 2003-05-07 - Fix some memory leacks in EGcplexSetAll* 00026 * 2003-05-06 - Add the EGcplexNullCutCallback. 00027 * - Add suport for getting the number of nonzeros of a given column. 00028 * - Fix EGcplexGetPi function 00029 * 2003-04-11 - Change macros to extern inline functions support EGmemPool 00030 * 2003-04-14 - Fix include problems with inline declarations 00031 * 2003-04-15 - Fix CPXENVptr problems with compile warnings 00032 * - Add more compiling warning messages and options 00033 * 00034 * */ 00035 /* ========================================================================= */ 00036 00037 #include <stdlib.h> 00038 #include <string.h> 00039 #include <stdio.h> 00040 #include "eg_macros.h" 00041 #include "eg_mempool.h" 00042 #include "eg_cplexTypes.h" 00043 #include "eg_list.h" 00044 #include "eg_col.h" 00045 #include "eg_row.h" 00046 #include "eg_io.h" 00047 #include "cplex.h" 00048 #ifdef HAVE_CPLEX 00049 #ifndef __EG_CPLEX_H__ 00050 #define __EG_CPLEX_H__ 00051 00052 /* ========================================================================= */ 00053 /* first some definitions to be able to work with cplex prior 8.1 and after 81 */ 00054 /* ========================================================================= */ 00055 #if CPX_VERSION < 800 00056 #define EGCPXPROB_MIP CPXPROB_MIP 00057 typedef CPXENVptr EGCPXENVptr; 00058 #else 00059 #define EGCPXPROB_MIP CPXPROB_MILP 00060 typedef CPXCENVptr EGCPXENVptr; 00061 #endif 00062 00063 /* ========================================================================= */ 00064 /* if we are debuggin then we try to explain what have happend with cplex, if 00065 * not, we just don't care, this allows us to eliminate some overhead and also 00066 * to define SOME cplex operations as macros, that is WAY faster than a 00067 * function */ 00068 /* ========================================================================= */ 00069 #if DEBUG >= 0 00070 extern char EGcplexErrMsg[]; 00071 00072 /* ========================================================================= */ 00073 /* the use of CPLEXTEST depends on two things, first, that the status of the 00074 * CPLEX call was stored on Prob->status and that the macro recived as 00075 * parameter the EGcplex_t* as A and that B is a printable char* */ 00076 /* ========================================================================= */ 00077 #define CPLEXTEST(Prob,Mesg) {if(Prob->status){ \ 00078 CPXgeterrorstring(Prob->env,Prob->status,EGcplexErrMsg);\ 00079 fprintf(stderr,"%s, in file %s, line %d\n",Mesg,__FILE__,__LINE__);\ 00080 fprintf(stderr,"%s\n",EGcplexErrMsg); }} 00081 #else 00082 #define CPLEXTEST(Prob,B) ; 00083 #endif 00084 00085 /* ========================================================================= */ 00086 /* structure to store a CPLEX problem */ 00087 /* ========================================================================= */ 00088 typedef struct 00089 { 00090 CPXENVptr env; 00091 EGmemPool_t *mempool; 00092 CPXLPptr lp; 00093 int status; 00094 char internal; 00095 } 00096 EGcplex_t; 00097 00098 /* ========================================================================= */ 00099 /* return a pointer to an initialized EGcplex object if the invironment is 00100 * null, it will create an ionternal environment that will be released when we 00101 * free it through EGfreeCplex */ 00102 /* ========================================================================= */ 00103 EGcplex_t *EGnewCplex (CPXENVptr env, 00104 EGmemPool_t * mempool); 00105 00106 /* ========================================================================= */ 00107 /* create a new CPLEX environment */ 00108 /* ========================================================================= */ 00109 CPXENVptr EGnewCplexEnv (void); 00110 00111 /* ========================================================================= */ 00112 /* liberate the memory returned by EGnewCplex, __NEVER__ liberate such a 00113 * memory space with free */ 00114 /* ========================================================================= */ 00115 void EGfreeCplex (void *); 00116 00117 /* ========================================================================= */ 00118 /* liberate the memory returned by EGnewCplexEnv, __NEVER__ liberate such a 00119 * memory space with free */ 00120 /* ========================================================================= */ 00121 void EGfreeCplexEnv (void *); 00122 00123 /* ========================================================================= */ 00124 /* set all variables to type binary */ 00125 /* ========================================================================= */ 00126 int EGcplexSetAllBin (EGcplex_t *); 00127 00128 /* ========================================================================= */ 00129 /* set all variables to type integer */ 00130 /* ========================================================================= */ 00131 int EGcplexSetAllInt (EGcplex_t *); 00132 00133 /* ========================================================================= */ 00134 /* set all variables to type continue */ 00135 /* ========================================================================= */ 00136 int EGcplexSetAllCon (EGcplex_t *); 00137 00138 /* ========================================================================= */ 00139 /* add a callback-cut to the problem */ 00140 /* ========================================================================= */ 00141 int EGcplexAddCallbackCut (EGcplex_t * Prob, 00142 void *cbdata, 00143 int wherefrom, 00144 EGrow_t * row); 00145 00146 /* ========================================================================= */ 00147 /* add a list of rows to the problem */ 00148 /* ========================================================================= */ 00149 int EGcplexAddRowList (EGcplex_t *, 00150 EGlist_t *); 00151 00152 /* ========================================================================= */ 00153 /* add an array of rows to the problem */ 00154 /* ========================================================================= */ 00155 int EGcplexAddRowArray (EGcplex_t *, 00156 EGrow_t **, 00157 unsigned int); 00158 00159 /* ========================================================================= */ 00160 /* add a list of columns to the problem */ 00161 /* ========================================================================= */ 00162 int EGcplexAddColList (EGcplex_t *, 00163 EGlist_t *); 00164 00165 /* ========================================================================= */ 00166 /* add an array of rows to the problem */ 00167 /* ========================================================================= */ 00168 int EGcplexAddColArray (EGcplex_t *, 00169 EGcol_t **, 00170 int); 00171 00172 /* ========================================================================= */ 00173 /* Change problem type to LP. */ 00174 /* ========================================================================= */ 00175 extern inline int EGcplexSetToLp (EGcplex_t * Prob) 00176 { 00177 CPXgetprobtype (Prob->env, Prob->lp); 00178 TEST ((Prob->status == -1), "no problem or enviroment"); 00179 if (Prob->status) 00180 Prob->status = CPXchgprobtype (Prob->env, Prob->lp, CPXPROB_LP); 00181 CHECKRVAL (Prob->status); 00182 return Prob->status; 00183 } 00184 00185 /* ========================================================================= */ 00186 /* Change problem type to MIP. */ 00187 /* ========================================================================= */ 00188 extern inline int EGcplexSetToMip (EGcplex_t * Prob) 00189 { 00190 CPXgetprobtype (Prob->env, Prob->lp); 00191 TEST ((Prob->status == -1), "in EGcplexSetToMip, no problem or enviroment"); 00192 if (Prob->status != 1) 00193 Prob->status = CPXchgprobtype (Prob->env, Prob->lp, EGCPXPROB_MIP); 00194 else 00195 Prob->status = 0; 00196 CPLEXTEST (Prob, "in EGcplexSetToMip"); 00197 return Prob->status; 00198 } 00199 00200 /* ========================================================================= */ 00201 /* Primal Simplex , store the optimization status in Prob->status status 0 00202 * means a solution is found (not necesarily optimal) (see CPLEX manual for 00203 * other values). */ 00204 /* ========================================================================= */ 00205 extern inline int EGcplexPrimopt (EGcplex_t * Prob) 00206 { 00207 EGcplexSetToLp (Prob); 00208 TEST ((Prob->status), "in EGcplexPrimopt"); 00209 Prob->status = CPXprimopt (Prob->env, Prob->lp); 00210 CPLEXTEST (Prob, "in EGcplexPrimopt"); 00211 return Prob->status; 00212 } 00213 00214 /* ========================================================================= */ 00215 /* hybrid Network Simplex with metod B; B = 'p' (primal) or 'd' (dual), return 00216 * the optimization status in Prob->status, 0 means a solution is found (not 00217 * necesarily optimal) see CPLEX manual for other values). */ 00218 /* ========================================================================= */ 00219 extern inline int EGcplexNetopt (EGcplex_t * Prob, 00220 const char B) 00221 { 00222 EGcplexSetToLp (Prob); 00223 TEST ((Prob->status), "in EGcplexNetopt"); 00224 Prob->status = CPXhybnetopt (Prob->env, Prob->lp, B); 00225 CPLEXTEST (Prob, "in EGcplexNetopt"); 00226 return Prob->status; 00227 } 00228 00229 /* ========================================================================= */ 00230 /* Dual Simplex, return the optimization status in Prob->status, 0 means a 00231 * solution is found (not necesarily optimzal) (see CPLEX manual for other 00232 * values). */ 00233 /* ========================================================================= */ 00234 extern inline int EGcplexDualopt (EGcplex_t * Prob) 00235 { 00236 EGcplexSetToLp (Prob); 00237 TEST ((Prob->status), "in EGcplexDualopt"); 00238 Prob->status = CPXdualopt (Prob->env, Prob->lp); 00239 CPLEXTEST (Prob, "in EGcplexDualopt"); 00240 return Prob->status; 00241 } 00242 00243 /* ========================================================================= */ 00244 /* Mixed Integer Methods , return the optimization status 0 means a solution 00245 * is found (not necesarily optimzal) (see CPLEX manual for other values). 00246 * where <B>maxIntSol</B> is the maximun number of integer solution to be found 00247 * before stoping. There are other issues as precision, for that you have to 00248 * configure the environment, see the environment information */ 00249 /* ========================================================================= */ 00250 extern inline int EGcplexMipopt (EGcplex_t * Prob) 00251 { 00252 EGcplexSetToMip (Prob); 00253 TEST ((Prob->status), "in EGcplexMipopt"); 00254 Prob->status = CPXmipopt (Prob->env, Prob->lp); 00255 CPLEXTEST (Prob, "in EGcplexMipopt"); 00256 return Prob->status; 00257 } 00258 00259 /* ========================================================================= */ 00260 /* change the type of the i-th variable to 'type', type must be 'B' for 00261 * binary, 'I' for integer or 'C' for continue */ 00262 /* ========================================================================= */ 00263 extern inline int EGcplexSetCtype (EGcplex_t * Prob, 00264 int nz, 00265 int *ind, 00266 char *types) 00267 { 00268 EGcplexSetToMip (Prob); 00269 TEST ((Prob->status), "in EGcplexSetCtype"); 00270 Prob->status = CPXchgctype (Prob->env, Prob->lp, nz, ind, types); 00271 CPLEXTEST (Prob, "in EGcplexSetCtype"); 00272 return Prob->status; 00273 } 00274 00275 /* ========================================================================= */ 00276 /* set the problem for minimize (default) */ 00277 /* ========================================================================= */ 00278 extern inline int EGcplexSetToMin (EGcplex_t * Prob) 00279 { 00280 CPXchgobjsen (Prob->env, Prob->lp, CPX_MIN); 00281 return 0; 00282 } 00283 00284 /* ========================================================================= */ 00285 /* set the problem for maximize */ 00286 /* ========================================================================= */ 00287 extern inline int EGcplexSetToMax (EGcplex_t * Prob) 00288 { 00289 CPXchgobjsen (Prob->env, Prob->lp, CPX_MAX); 00290 return 0; 00291 } 00292 00293 /* ========================================================================= */ 00294 /* set the right hand side of the rows in ind to val, nz indicate the number 00295 * of entries in the arrays name and val. Prob is the EGcplex_t structure */ 00296 /* ========================================================================= */ 00297 extern inline int EGcplexSetRhs (EGcplex_t * Prob, 00298 int nz, 00299 int *ind, 00300 double *val) 00301 { 00302 Prob->status = CPXchgrhs (Prob->env, Prob->lp, nz, ind, val); 00303 CPLEXTEST (Prob, "in EGcplexSetRhs"); 00304 return Prob->status; 00305 } 00306 00307 /* ========================================================================= */ 00308 /* set the sense of a set of constraints */ 00309 /* ========================================================================= */ 00310 extern inline int EGcplexSetSense (EGcplex_t * Prob, 00311 int nz, 00312 int *ind, 00313 char *sense) 00314 { 00315 Prob->status = CPXchgsense (Prob->env, Prob->lp, nz, ind, sense); 00316 CPLEXTEST (Prob, "in EGcplexSetSense"); 00317 return Prob->status; 00318 } 00319 00320 /* ========================================================================= */ 00321 /* set the objetive coefficient of the pos-th variable to val Prob is the 00322 * EGcplex_t structure, nz is the length of the arrays ind is the array of 00323 * indices, type is the array of types of bounds to change and val is the new 00324 * value of the bound */ 00325 /* ========================================================================= */ 00326 extern inline int EGcplexSetObj (EGcplex_t * Prob, 00327 int nz, 00328 int *ind, 00329 double *val) 00330 { 00331 Prob->status = CPXchgobj (Prob->env, Prob->lp, nz, ind, val); 00332 CPLEXTEST (Prob, "in EGcplexSetObj"); 00333 return Prob->status; 00334 } 00335 00336 /* ========================================================================= */ 00337 /* set for all the variables in 'bound' the limit 'type' to the double stored 00338 * in the map; type must be one of the folowin values : 'U' for the upper 00339 * limit, 'L' for the lower limit and 'B' for both the lower and the upper 00340 * limit. Prob is the EGcplex_t structure, nz is the length of the arrays ind 00341 * is the array of indices, type is the array of types of bounds to change and 00342 * val is the new value of the bound */ 00343 /* ========================================================================= */ 00344 extern inline int EGcplexSetBound (EGcplex_t * Prob, 00345 int nz, 00346 int *ind, 00347 char *type, 00348 double *val) 00349 { 00350 Prob->status = CPXchgbds (Prob->env, Prob->lp, nz, ind, type, val); 00351 CPLEXTEST (Prob, "in EGcplexSetBound"); 00352 return Prob->status; 00353 } 00354 00355 /* ========================================================================= */ 00356 /* indicates the number of rows (or restrictions) in the problem */ 00357 /* ========================================================================= */ 00358 extern inline int EGcplexGetNumRows (EGcplex_t * Prob, 00359 int *nrowptr) 00360 { 00361 *nrowptr = CPXgetnumrows (Prob->env, Prob->lp); 00362 return 0; 00363 } 00364 00365 /* ========================================================================= */ 00366 /* indicates the number of cols (or variables) in the problem */ 00367 /* ========================================================================= */ 00368 extern inline int EGcplexGetNumCols (EGcplex_t * Prob, 00369 int *ncolptr) 00370 { 00371 *ncolptr = CPXgetnumcols (Prob->env, Prob->lp); 00372 return 0; 00373 } 00374 00375 /* ========================================================================= */ 00376 /* directly add columns to cplex */ 00377 /* ========================================================================= */ 00378 int EGcplexAddCol (EGcplex_t * Prob, 00379 int ccnt, 00380 int cnz, 00381 double *cobj, 00382 int *cmbeg, 00383 int *cmind, 00384 double *cmval, 00385 double *clb, 00386 double *cub, 00387 char **cname); 00388 00389 /* ========================================================================= */ 00390 /* directyly add rows to cplex */ 00391 /* ========================================================================= */ 00392 int EGcplexAddRow (EGcplex_t * Prob, 00393 int rcnt, 00394 int rnz, 00395 double *rhs, 00396 char *sense, 00397 int *rmbeg, 00398 int *rmind, 00399 double *rmval, 00400 char **rname); 00401 00402 /* ========================================================================= */ 00403 /* directyly add rows to cplex (in a callback function) */ 00404 /* ========================================================================= */ 00405 extern inline int EGcplexAddCut (EGcplex_t * Prob, 00406 void *cbdata, 00407 int wherefrom, 00408 int rnz, 00409 double rhs, 00410 char sense, 00411 int *rmind, 00412 double *rmval) 00413 { 00414 Prob->status = 00415 CPXcutcallbackadd (Prob->env, cbdata, wherefrom, rnz, rhs, sense, rmind, 00416 rmval); 00417 CPLEXTEST (Prob, "in EGcplexAddCut"); 00418 return Prob->status; 00419 } 00420 00421 /* ========================================================================= */ 00422 /* deletes rows with index bigger or equal than 'beg' but smaller than 'end' */ 00423 /* ========================================================================= */ 00424 extern inline int EGcplexDelRows (EGcplex_t * Prob, 00425 int beg, 00426 int end) 00427 { 00428 Prob->status = CPXdelrows (Prob->env, Prob->lp, beg, end - 1); 00429 CPLEXTEST (Prob, "in EGcplexDelRows"); 00430 return Prob->status; 00431 } 00432 00433 /* ========================================================================= */ 00434 /* deletes cols with index bigger or equal than 'beg' but smaller than 'end' */ 00435 /* ========================================================================= */ 00436 extern inline int EGcplexDelCols (EGcplex_t * Prob, 00437 int beg, 00438 int end) 00439 { 00440 Prob->status = CPXdelcols (Prob->env, Prob->lp, beg, end - 1); 00441 CPLEXTEST (Prob, "in EGcplexDelCols"); 00442 return Prob->status; 00443 } 00444 00445 /* ========================================================================= */ 00446 /* return the CPLEX status of the problem, that status indicates optimality, 00447 * infeasibility, etc., see (CPLEX manual for further information). */ 00448 /* ========================================================================= */ 00449 extern inline int EGcplexGetStat (EGcplex_t * Prob, 00450 int *statusptr) 00451 { 00452 *statusptr = CPXgetstat (Prob->env, Prob->lp); 00453 return 0; 00454 } 00455 00456 /* ========================================================================= */ 00457 /* return the current objetive value for the problem. */ 00458 /* ========================================================================= */ 00459 extern inline int EGcplexGetBestObjval (EGcplex_t * Prob, 00460 double *valptr) 00461 { 00462 Prob->status = CPXgetprobtype (Prob->env, Prob->lp); 00463 if (Prob->status == 0) 00464 return 1; 00465 else if (Prob->status == 1) 00466 Prob->status = CPXgetbestobjval (Prob->env, Prob->lp, valptr); 00467 else 00468 TEST (1, "in EGcplexGetBestObjval, unknown problem type"); 00469 CPLEXTEST (Prob, "in EGcplexGetBestObjval"); 00470 return Prob->status; 00471 } 00472 00473 /* ========================================================================= */ 00474 /* return the current objetive value for the problem. */ 00475 /* ========================================================================= */ 00476 extern inline int EGcplexGetObjval (EGcplex_t * Prob, 00477 double *valptr) 00478 { 00479 Prob->status = CPXgetprobtype (Prob->env, Prob->lp); 00480 if (Prob->status == 0) 00481 Prob->status = CPXgetobjval (Prob->env, Prob->lp, valptr); 00482 else if (Prob->status == 1) 00483 Prob->status = CPXgetmipobjval (Prob->env, Prob->lp, valptr); 00484 else 00485 EXIT (1, "in EGcplexGetObjval, unknown problem type"); 00486 CPLEXTEST (Prob, "in EGcplexGetObjval"); 00487 return Prob->status; 00488 } 00489 00490 /* ========================================================================= */ 00491 /* given an array x of size end - begin and a problem, return the current 00492 * values for the variables in the range [begin,end[, i.e. we obtain 00493 * x[begin],....,x[end-1] */ 00494 /* ========================================================================= */ 00495 extern inline int EGcplexGetX (EGcplex_t * Prob, 00496 double *x, 00497 int begin, 00498 int end) 00499 { 00500 Prob->status = CPXgetprobtype (Prob->env, Prob->lp); 00501 if (Prob->status == 0) 00502 Prob->status = CPXgetx (Prob->env, Prob->lp, x, begin, end - 1); 00503 else if (Prob->status == 1) 00504 Prob->status = CPXgetmipx (Prob->env, Prob->lp, x, begin, end - 1); 00505 else 00506 EXIT (1, "in EGcplexGetX, unknown problem type"); 00507 CPLEXTEST (Prob, "in EGcplexGetX"); 00508 return Prob->status; 00509 } 00510 00511 /* ========================================================================= */ 00512 /* given an array x of size end - begin and a problem, return the current 00513 * dual values for the constraint in the range [begin,end[, i.e. we obtain 00514 * x[begin],....,x[end-1] */ 00515 /* ========================================================================= */ 00516 extern inline int EGcplexGetPi (EGcplex_t * Prob, 00517 double *x, 00518 int begin, 00519 int end) 00520 { 00521 Prob->status = CPXgetprobtype (Prob->env, Prob->lp); 00522 if (Prob->status == 0) 00523 Prob->status = CPXgetpi (Prob->env, Prob->lp, x, begin, end - 1); 00524 else 00525 EXIT (1, "in EGcplexGetPi, unknown problem type or problem is MIP"); 00526 CPLEXTEST (Prob, "in EGcplexGetPi"); 00527 return Prob->status; 00528 } 00529 00530 /* ========================================================================= */ 00531 /* given an array x of size end - begin and a problem, return the current 00532 * slack for the constraints in the range [begin,end[, i.e. we obtain 00533 * x[begin],....,x[end-1] */ 00534 /* ========================================================================= */ 00535 extern inline int EGcplexGetSlack (EGcplex_t * Prob, 00536 double *x, 00537 int begin, 00538 int end) 00539 { 00540 Prob->status = CPXgetprobtype (Prob->env, Prob->lp); 00541 if (Prob->status == 0) 00542 Prob->status = CPXgetslack (Prob->env, Prob->lp, x, begin, end - 1); 00543 else if (Prob->status == 1) 00544 Prob->status = CPXgetmipslack (Prob->env, Prob->lp, x, begin, end - 1); 00545 else 00546 EXIT (1, "in EGcplexGetSlack, unknown problem type"); 00547 CPLEXTEST (Prob, "in EGcplexGetSlack"); 00548 return Prob->status; 00549 } 00550 00551 /* ========================================================================= */ 00552 /* given an array x of size end - begin and a problem, return the current 00553 * reduced cost values for the variables in the range [begin,end[, i.e. we 00554 * obtain x[begin],....,x[end-1] */ 00555 /* ========================================================================= */ 00556 extern inline int EGcplexGetDj (EGcplex_t * Prob, 00557 double *x, 00558 int begin, 00559 int end) 00560 { 00561 Prob->status = CPXgetprobtype (Prob->env, Prob->lp); 00562 if (Prob->status == 0) 00563 Prob->status = CPXgetdj (Prob->env, Prob->lp, x, begin, end - 1); 00564 else 00565 EXIT (1, "in EGcplexGetDj, unknown problem type or problem is MIP"); 00566 CPLEXTEST (Prob, "in EGcplexGetDj"); 00567 return Prob->status; 00568 } 00569 00570 /* ========================================================================= */ 00571 /* return in how many constraints a particular column bellongs */ 00572 /* ========================================================================= */ 00573 extern inline int EGcplexGetColNZ (EGcplex_t * Prob, 00574 int cind, 00575 int *cnz) 00576 { 00577 00578 /* local variables */ 00579 int colnz, 00580 matbeg; 00581 00582 Prob->status = 00583 CPXgetcols (Prob->env, Prob->lp, &colnz, &matbeg, 0, 0, 0, cnz, cind, cind); 00584 if (Prob->status != 1207) 00585 CPLEXTEST (Prob, "in EGcplexGetColNZ"); 00586 *cnz *= -1; 00587 00588 /* ending */ 00589 return 0; 00590 } 00591 00592 /* ========================================================================= */ 00593 /* Return the column names Prob is a pointer to a EGcplex_t structure begin 00594 * denote the first column name to take end denote the last plus one column 00595 * name to take name is an an array of size end - begin of pointers to char* 00596 * name store is an array of chars of size storesize where the names will be 00597 * stored surplusptr is a pointer to an integer where the size of the non used 00598 * space in store will be stored if *surplusptr is negative, the call had fail 00599 * */ 00600 /* ========================================================================= */ 00601 extern inline int EGcplexGetColname (EGcplex_t * Prob, 00602 char **names, 00603 char *store, 00604 int storesize, 00605 int *splusptr, 00606 int begin, 00607 int end) 00608 { 00609 Prob->status = 00610 CPXgetcolname (Prob->env, Prob->lp, names, store, storesize, splusptr, 00611 begin, end - 1); 00612 if (Prob->status != CPXERR_NEGATIVE_SURPLUS) 00613 CPLEXTEST (Prob, "in EGcplexGetColname"); 00614 return Prob->status; 00615 } 00616 00617 /* ========================================================================= */ 00618 /* Return a range of row coefficients and indices. Prob is a pointer to a 00619 * EGcplex_t structure, begin denote the first row to take, end denote the last 00620 * plus one row name to take, nz is the size of the arrays rbeg, rind and rval. 00621 * if *surplusptr is negative, the call had fail */ 00622 /* ========================================================================= */ 00623 extern inline int EGcplexGetRows (EGcplex_t * Prob, 00624 int *nz, 00625 int *rbeg, 00626 int *rind, 00627 double *rval, 00628 int size, 00629 int *surplus, 00630 int begin, 00631 int end) 00632 { 00633 Prob->status = 00634 CPXgetrows (Prob->env, Prob->lp, nz, rbeg, rind, rval, size, surplus, 00635 begin, end - 1); 00636 if (Prob->status == CPXERR_NEGATIVE_SURPLUS) 00637 return 0; 00638 CPLEXTEST (Prob, "in EGcplexGetRows"); 00639 return Prob->status; 00640 } 00641 00642 extern inline int EGcplexGetCols (EGcplex_t * Prob, 00643 int *nz, 00644 int *cbeg, 00645 int *cind, 00646 double *cval, 00647 int size, 00648 int *surplus, 00649 int begin, 00650 int end) 00651 { 00652 Prob->status = 00653 CPXgetcols (Prob->env, Prob->lp, nz, cbeg, cind, cval, size, surplus, 00654 begin, end - 1); 00655 if (Prob->status == CPXERR_NEGATIVE_SURPLUS) 00656 return 0; 00657 CPLEXTEST (Prob, "in EGcplexGetCols"); 00658 return Prob->status; 00659 } 00660 00661 /* ========================================================================= */ 00662 /* Return the row names Prob is a pointer to a EGcplex_t structure begin 00663 * denote the first row name to take end denote the last plus one row name to 00664 * take name is an an array of size end - begin of pointers to char* name 00665 * store is an array of chars of size storesize where the names will be stored 00666 * surplusptr is a pointer to an integer where the size of the non used space 00667 * in store will be stored if *surplusptr is negative, the call had fail */ 00668 /* ========================================================================= */ 00669 extern inline int EGcplexGetRowname (EGcplex_t * Prob, 00670 char **names, 00671 char *store, 00672 int storesize, 00673 int *splusptr, 00674 int begin, 00675 int end) 00676 { 00677 Prob->status = 00678 CPXgetrowname (Prob->env, Prob->lp, names, store, storesize, splusptr, 00679 begin, end - 1); 00680 if (Prob->status != CPXERR_NEGATIVE_SURPLUS) 00681 CPLEXTEST (Prob, "in EGcplexGetRowname"); 00682 return Prob->status; 00683 } 00684 00685 /* ========================================================================= */ 00686 /* given an array x of size end - begin and a problem, return the current 00687 * upper bounds values for the variables in the range [begin,end[, i.e. we 00688 * obtain x[begin],....,x[end-1] */ 00689 /* ========================================================================= */ 00690 extern inline int EGcplexGetUb (EGcplex_t * Prob, 00691 double *x, 00692 int begin, 00693 int end) 00694 { 00695 Prob->status = CPXgetub (Prob->env, Prob->lp, x, begin, end - 1); 00696 CPLEXTEST (Prob, "in EGcplexGetUb"); 00697 return Prob->status; 00698 } 00699 00700 /* ========================================================================= */ 00701 /* given an array x of size end - begin and a problem, return the current 00702 * lower bounds values for the variables in the range [begin,end[, i.e. we 00703 * obtain x[begin],....,x[end-1] */ 00704 /* ========================================================================= */ 00705 extern inline int EGcplexGetLb (EGcplex_t * Prob, 00706 double *x, 00707 int begin, 00708 int end) 00709 { 00710 Prob->status = CPXgetlb (Prob->env, Prob->lp, x, begin, end - 1); 00711 CPLEXTEST (Prob, "in EGcplexGetLb"); 00712 return Prob->status; 00713 } 00714 00715 /* ========================================================================= */ 00716 /* given an array x of size end - begin and a problem, return the objective 00717 * values for the variables in the range [begin,end[, i.e. we obtain 00718 * x[begin],....,x[end-1] */ 00719 /* ========================================================================= */ 00720 extern inline int EGcplexGetObjCoeff (EGcplex_t * Prob, 00721 double *x, 00722 int begin, 00723 int end) 00724 { 00725 Prob->status = CPXgetobj (Prob->env, Prob->lp, x, begin, end - 1); 00726 CPLEXTEST (Prob, "in EGcplexGetObjCoeff"); 00727 return Prob->status; 00728 } 00729 00730 /* ========================================================================= */ 00731 /* given an array x of size end - begin and a problem, return the sense 00732 * values for the constraints in the range [begin,end[, i.e. we obtain 00733 * x[begin],....,x[end-1] */ 00734 /* ========================================================================= */ 00735 extern inline int EGcplexGetSense (EGcplex_t * Prob, 00736 char *x, 00737 int begin, 00738 int end) 00739 { 00740 Prob->status = 00741 CPXgetsense ((EGCPXENVptr) (Prob->env), Prob->lp, x, begin, end - 1); 00742 CPLEXTEST (Prob, "in EGcplexGetSense"); 00743 return Prob->status; 00744 } 00745 00746 /* ========================================================================= */ 00747 /* given an array x of size end - begin and a problem, return the sense values 00748 * for the constraints in the range [begin,end[, i.e. we obtain 00749 * x[begin],....,x[end-1] */ 00750 /* ========================================================================= */ 00751 extern inline int EGcplexGetRhs (EGcplex_t * Prob, 00752 double *x, 00753 int begin, 00754 int end) 00755 { 00756 Prob->status = CPXgetrhs (Prob->env, Prob->lp, x, begin, end - 1); 00757 CPLEXTEST (Prob, "in EGcplexGetRhs"); 00758 return Prob->status; 00759 } 00760 00761 /* ========================================================================= */ 00762 /* save the problem structure in format type, where type must be "SAV" for 00763 * binary matrix and basis file, "MPS" for MPS format, "LP" for CPLEX LP 00764 * format, "REW" or "RMP" for MPS format with all names changed to generic 00765 * names or "RLP" for LP format with all names changed to generic names. */ 00766 /* ========================================================================= */ 00767 extern inline int EGcplexWriteProb (EGcplex_t * Prob, 00768 const char *file, 00769 const char *type) 00770 { 00771 #if CPX_VERSION > 800 00772 Prob->status = CPXwriteprob (Prob->env, Prob->lp, file, type); 00773 #else 00774 char *lfile = strdup (file); 00775 char *ltype = strdup (type); 00776 Prob->status = CPXwriteprob (Prob->env, Prob->lp, lfile, ltype); 00777 free (lfile); 00778 free (ltype); 00779 #endif 00780 CPLEXTEST (Prob, "in EGcplexWriteProb"); 00781 return Prob->status; 00782 } 00783 00784 /* ========================================================================= */ 00785 /* add a function callback for Cplex incumber solution during MIP note that 00786 * the callback is asociated to the CPLEX environment and not to the CPLEX 00787 * problem */ 00788 /* ========================================================================= */ 00789 extern inline int EGcplexAddIncumbentCallBack (EGcplex_t * Prob, 00790 int (CPXPUBLIC * 00791 callback) (EGCPXENVptr, 00792 void *, 00793 int, 00794 void *, 00795 double, 00796 double *, 00797 int *, 00798 int *), 00799 void *cinfo) 00800 { 00801 #if CPX_VERSION > 700 00802 Prob->status = 00803 CPXsetincumbentcallbackfunc ((CPXENVptr) (Prob->env), callback, cinfo); 00804 CPLEXTEST (Prob, "in EGcplexAddIncumbentCallBack"); 00805 #else 00806 EXIT (1, "in EGcplexAddIncumbentCallBack, not supported before Cplex 7.1"); 00807 #endif 00808 return Prob->status; 00809 } 00810 00811 /* ========================================================================= */ 00812 /* add a function callback for cut generation during MIP note that the 00813 * callback is asociated to the CPLEX environment and not to the CPLEX 00814 * problem */ 00815 /* ========================================================================= */ 00816 extern inline int EGcplexAddCutCallBack (EGcplex_t * Prob, 00817 int (CPXPUBLIC * 00818 callback) (EGCPXENVptr, 00819 void *, 00820 int, 00821 void *, 00822 int *), 00823 void *cinfo) 00824 { 00825 Prob->status = 00826 CPXsetcutcallbackfunc ((CPXENVptr) (Prob->env), callback, cinfo); 00827 CPLEXTEST (Prob, "in EGcplexAddIncumbentCallBack"); 00828 return Prob->status; 00829 } 00830 00831 /* ========================================================================= */ 00832 /* this function is to set any integer parameter of CPLEX, this affects the 00833 * nefironment */ 00834 /* ========================================================================= */ 00835 extern inline int EGcplexSetDblParam (CPXENVptr env, 00836 int param, 00837 double value) 00838 { 00839 int status; 00840 status = CPXsetdblparam ((CPXENVptr) env, param, value); 00841 if (status) 00842 { 00843 CPXgeterrorstring (env, status, EGcplexErrMsg); 00844 fprintf (stderr, "in EGcplexSetDblParam, in file %s, line %d\n", __FILE__, 00845 __LINE__); 00846 fprintf (stderr, "%s\n", EGcplexErrMsg); 00847 } 00848 return status; 00849 } 00850 00851 /* ========================================================================= */ 00852 /* this function is to set any integer parameter of CPLEX, this affects the 00853 * nefironment */ 00854 /* ========================================================================= */ 00855 extern inline int EGcplexSetIntParam (CPXENVptr env, 00856 int param, 00857 int value) 00858 { 00859 int status; 00860 status = CPXsetintparam ((CPXENVptr) env, param, value); 00861 if (status) 00862 { 00863 CPXgeterrorstring (env, status, EGcplexErrMsg); 00864 fprintf (stderr, "in EGcplexSetIntParam, in file %s, line %d\n", __FILE__, 00865 __LINE__); 00866 fprintf (stderr, "%s\n", EGcplexErrMsg); 00867 } 00868 return status; 00869 } 00870 00871 /* ========================================================================= */ 00872 /* set the CPLEX environment output off, all problems sharing this environment 00873 * will not report to screen */ 00874 /* ========================================================================= */ 00875 extern inline int EGcplexSetScreenOff (EGcplex_t * Prob) 00876 { 00877 Prob->status = 00878 CPXsetintparam ((CPXENVptr) (Prob->env), CPX_PARAM_SCRIND, CPX_OFF); 00879 CPLEXTEST (Prob, "in EGcplexSetScreenOff"); 00880 return Prob->status; 00881 } 00882 00883 /* ========================================================================= */ 00884 /* set the CPLEX environment output on, all problems sharing this environment 00885 * will report to screen */ 00886 /* ========================================================================= */ 00887 extern inline int EGcplexSetScreenOn (EGcplex_t * Prob) 00888 { 00889 Prob->status = 00890 CPXsetintparam ((CPXENVptr) (Prob->env), CPX_PARAM_SCRIND, CPX_ON); 00891 CPLEXTEST (Prob, "in EGcplexSetScreenOn"); 00892 return Prob->status; 00893 } 00894 00895 /* ========================================================================= */ 00896 /* set an upper bound for the LP objetive function, this bound will affect all 00897 * problems that share the CPLEX environment */ 00898 /* ========================================================================= */ 00899 extern inline int EGcplexSetULP (EGcplex_t * Prob, 00900 double ubound) 00901 { 00902 Prob->status = 00903 CPXsetdblparam ((CPXENVptr) (Prob->env), CPX_PARAM_OBJULIM, ubound); 00904 CPLEXTEST (Prob, "in EGcplexSetULP"); 00905 return Prob->status; 00906 } 00907 00908 /* ========================================================================= */ 00909 /* set an lower bound for the LP objetive function, this bound will affect all 00910 * problems that share the CPLEX environment */ 00911 /* ========================================================================= */ 00912 extern inline int EGcplexSetLLP (EGcplex_t * Prob, 00913 double lbound) 00914 { 00915 Prob->status = 00916 CPXsetdblparam ((CPXENVptr) Prob->env, CPX_PARAM_OBJLLIM, lbound); 00917 CPLEXTEST (Prob, "in EGcplexSetLLP"); 00918 return Prob->status; 00919 } 00920 00921 /* ========================================================================= */ 00922 /* set an upper bound for the MIP objetive function, this bound will affect 00923 * all problems that share the CPLEX environment */ 00924 /* ========================================================================= */ 00925 extern inline int EGcplexSetUMIP (EGcplex_t * Prob, 00926 double ubound) 00927 { 00928 Prob->status = 00929 CPXsetdblparam ((CPXENVptr) Prob->env, CPX_PARAM_CUTUP, ubound); 00930 CPLEXTEST (Prob, "in EGcplexSetUMIP"); 00931 return Prob->status; 00932 } 00933 00934 /* ========================================================================= */ 00935 /* set an lower bound for the MIP objetive function, this bound will affect 00936 * all problems that share the CPLEX environment */ 00937 /* ========================================================================= */ 00938 extern inline int EGcplexSetLMIP (EGcplex_t * Prob, 00939 double lbound) 00940 { 00941 Prob->status = 00942 CPXsetdblparam ((CPXENVptr) Prob->env, CPX_PARAM_CUTLO, lbound); 00943 CPLEXTEST (Prob, "in EGcplexSetLLP"); 00944 return Prob->status; 00945 } 00946 00947 /* ========================================================================= */ 00948 /* this function, as its name says, is a null cut callback, this is used in 00949 * order to reset or shadow a previous callback asociated to the underlying 00950 * CPXENV. Note that all calbacks are associated to the environment instead of 00951 * the problem. */ 00952 /* ========================================================================= */ 00953 typedef int CPXPUBLIC (*EGcutCallBack_f) (EGCPXENVptr, 00954 void *, 00955 int, 00956 void *, 00957 int *); 00958 extern EGcutCallBack_f EGcplexNullCutCallBack; 00959 /* 00960 int CPXPUBLIC EGcplexNullCutCallBack (EGCPXENVptr, 00961 void *cbdata, 00962 int wherefrom, 00963 void *cbhandle, 00964 int *usercation__p); 00965 */ 00966 #endif 00967 #endif
1.4.5