eg_cplex.c

Go to the documentation of this file.
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 #ifdef HAVE_CPLEX
00021 #include "eg_config.h"
00022 #include "eg_cplex.h"
00023 // if we are debuggin then we try to explain what have happend with cplex, if not, 
00024 // we just don't care, this allows us to eliminate some overhead and also to define 
00025 // SOME cplex operations as macros, that is WAY faster than a function
00026 char EGcplexErrMsg[1024];
00027 
00028 /* this function is to set any integer parameter of CPLEX, this affects the
00029  * nefironment */
00030 int EGcplexSetIntParam (CPXENVptr env,
00031                         int param,
00032                         int value)
00033 {
00034   int status;
00035   status = CPXsetintparam (env, param, value);
00036   if (status)
00037   {
00038     CPXgeterrorstring (env, status, EGcplexErrMsg);
00039     fprintf (stderr, "en EGcplexSetIntParam, in file %s, line %d\n", __FILE__,
00040              __LINE__);
00041     fprintf (stderr, "%s\n", EGcplexErrMsg);
00042   }
00043   return status;
00044 }
00045 
00046 // create a new CPLEX environment
00047 CPXENVptr EGnewCplexEnv (void)
00048 {
00049 
00050   // local variable
00051   int status;
00052   CPXENVptr res;
00053 
00054   // opening it
00055   res = CPXopenCPLEX (&status);
00056   EXIT (status, "in EGnewCplexEnv, can't open environment");
00057 
00058   // some default configuration
00059   EGcplexSetIntParam (res, CPX_PARAM_SIMDISPLAY, 1);
00060   EGcplexSetIntParam (res, CPX_PARAM_MIPINTERVAL, 1);
00061   EGcplexSetIntParam (res, CPX_PARAM_MIPDISPLAY, 4);
00062 
00063   // ending
00064   return res;
00065 }
00066 
00067 // return a pointer to an initialized EGcplex object
00068 EGcplex_t *EGnewCplex (CPXENVptr env,
00069                        EGmemPool_t * mempool)
00070 {
00071   // local variables
00072   EGcplex_t *res;
00073   char name[8] = "EGcplex";
00074 
00075   // look for memory
00076   res = EGmemPoolSMalloc (mempool, EGcplex_t, 1);
00077 
00078   // we create an environment only if we didn't recive one
00079   if (env)
00080   {
00081     res->env = (CPXENVptr) env;
00082     res->internal = 0;
00083   }
00084   else
00085   {
00086     res->env = EGnewCplexEnv ();
00087     res->internal = 1;
00088   }
00089 
00090   // now we create the problem
00091   res->mempool = mempool;
00092   res->lp = CPXcreateprob (res->env, &(res->status), name);
00093   CPLEXTEST (res, "in EGnewCplex, can't create problem");
00094 
00095   // ending
00096   return res;
00097 }
00098 
00099 // liberate the memory returned by EGnewCplex, __NEVER__ liberate such a memory space with free
00100 void EGfreeCplex (void *Prob)
00101 {
00102 
00103   // first free the LP pointer data
00104   CPXENVptr lenv = ((void *) ((EGcplex_t *) Prob)->env);
00105   ((EGcplex_t *) Prob)->status = CPXfreeprob (lenv, &((EGcplex_t *) Prob)->lp);
00106   CPLEXTEST (((EGcplex_t *) (Prob)), "in EGfreeCplex");
00107 
00108   // if the environment is internal we liberate it
00109   if (((EGcplex_t *) Prob)->internal)
00110     ((EGcplex_t *) Prob)->status = CPXcloseCPLEX (&lenv);
00111   EXIT (((EGcplex_t *) Prob)->status,
00112         "in EGfreeCplex, Can't close CPLEX environment, exiting");
00113 
00114   // ending
00115   EGmemPoolFree (Prob, sizeof (EGcplex_t), ((EGcplex_t *) Prob)->mempool);
00116   return;
00117 }
00118 
00119 // liberate the memory returned by EGnewCplexEnv, __NEVER__ liberate such a memory space with free
00120 void EGfreeCplexEnv (void *env)
00121 {
00122 
00123   // free the environment
00124   CPXENVptr lenv = (CPXENVptr) env;
00125   int status = CPXcloseCPLEX (&lenv);
00126 #if DEBUG > 0
00127   if (status)
00128   {
00129     CPXgeterrorstring (lenv, status, EGcplexErrMsg);
00130     fprintf (stderr, "%s, in file %s, line %d\n", __func__, __FILE__, __LINE__);
00131     fprintf (stderr, "%s\n", EGcplexErrMsg);
00132   }
00133 #endif
00134   WARNING (status, "in EGfreeCplexEnv, Can't close CPLEX environment, exiting");
00135 
00136   // ending
00137   return;
00138 }
00139 
00140 // set the CPLEX environment output on, all problems sharing this environment
00141 // will report to screen
00142 int EGcplexSetScreenOn (EGcplex_t * Prob)
00143 {
00144   Prob->status =
00145     CPXsetintparam ((CPXENVptr) (Prob->env), CPX_PARAM_SCRIND, CPX_ON);
00146   CPLEXTEST (Prob, "in EGcplexSetScreenOn");
00147   return Prob->status;
00148 }
00149 
00150 // indicates the number of cols (or variables) in the problem
00151 int EGcplexGetNumCols (EGcplex_t * Prob,
00152                        int *ncolptr)
00153 {
00154   *ncolptr = CPXgetnumcols (Prob->env, Prob->lp);
00155   return 0;
00156 }
00157 
00158 // Change problem type to MIP.
00159 int EGcplexSetToMip (EGcplex_t * Prob)
00160 {
00161   CPXgetprobtype (Prob->env, Prob->lp);
00162   TEST ((Prob->status == -1), "in EGcplexSetToMip, no problem or enviroment");
00163   if (Prob->status != 1)
00164     Prob->status = CPXchgprobtype (Prob->env, Prob->lp, EGCPXPROB_MIP);
00165   else
00166     Prob->status = 0;
00167   CPLEXTEST (Prob, "in EGcplexSetToMip");
00168   return Prob->status;
00169 }
00170 
00171 // change the type of the i-th variable to 'type', type must
00172 //  be 'B' for binary, 'I' for integer or 'C' for continue
00173 int EGcplexSetCtype (EGcplex_t * Prob,
00174                      int nz,
00175                      int *ind,
00176                      char *types)
00177 {
00178   EGcplexSetToMip (Prob);
00179   TEST ((Prob->status), "in EGcplexSetCtype");
00180   Prob->status = CPXchgctype (Prob->env, Prob->lp, nz, ind, types);
00181   CPLEXTEST (Prob, "in EGcplexSetCtype");
00182   return Prob->status;
00183 }
00184 
00185 // set all variables to type binary
00186 int EGcplexSetAllBin (EGcplex_t * Prob)
00187 {
00188   // local variables
00189   int ncol,
00190     i;
00191   int *ind;
00192   char *type;
00193 
00194   // basic set-up
00195   EGcplexGetNumCols (Prob, &ncol);
00196   CHECKRVAL (Prob->status);
00197   if (!ncol)
00198     return 0;
00199   ind = EGmemPoolSMalloc (Prob->mempool, int, ncol);
00200   type = EGmemPoolSMalloc (Prob->mempool, char,
00201                            ncol);
00202 
00203   // set the information of ind and type
00204   for (i = ncol; i;)
00205   {
00206     i--;
00207     ind[i] = i;
00208     type[i] = 'B';
00209   }
00210 
00211   // call the CPLEX function
00212   EGcplexSetCtype (Prob, ncol, ind, type);
00213   TEST (Prob->status, "in EGcplexSetAllBin");
00214 
00215   // ending
00216   EGmemPoolFree (ind, sizeof (int) * ncol, Prob->mempool);
00217   EGmemPoolFree (type, sizeof (char) * ncol, Prob->mempool);
00218   return Prob->status;
00219 }
00220 
00221 // set all variables to type integer
00222 int EGcplexSetAllInt (EGcplex_t * Prob)
00223 {
00224   // local variables
00225   int ncol,
00226     i;
00227   int *ind;
00228   char *type;
00229 
00230   // basic set-up
00231   EGcplexGetNumCols (Prob, &ncol);
00232   TEST (Prob->status, "in EGcplexSetAllInt");
00233   ind = EGmemPoolSMalloc (Prob->mempool, int,
00234                           ncol);
00235   type = EGmemPoolSMalloc (Prob->mempool, char,
00236                            ncol);
00237 
00238   // set the information of ind and type
00239   for (i = ncol; i;)
00240   {
00241     i--;
00242     ind[i] = i;
00243     type[i] = 'I';
00244   }
00245 
00246   // call the CPLEX function
00247   EGcplexSetCtype (Prob, ncol, ind, type);
00248   TEST (Prob->status, "in EGcplexSetAllInt");
00249 
00250   // ending
00251   EGmemPoolFree (ind, sizeof (int) * ncol, Prob->mempool);
00252   EGmemPoolFree (type, sizeof (char) * ncol, Prob->mempool);
00253   return Prob->status;
00254 }
00255 
00256 // set all variables to type continue
00257 int EGcplexSetAllCon (EGcplex_t * Prob)
00258 {
00259   // local variables
00260   int ncol,
00261     i;
00262   int *ind;
00263   char *type;
00264 
00265   // basic set-up
00266   EGcplexGetNumCols (Prob, &ncol);
00267   TEST (Prob->status, "in EGcplexSetAllCon");
00268   ind = EGmemPoolSMalloc (Prob->mempool, int,
00269                           ncol);
00270   type = EGmemPoolSMalloc (Prob->mempool, char,
00271                            ncol);
00272 
00273   // set the information of ind and type
00274   for (i = ncol; i;)
00275   {
00276     i--;
00277     ind[i] = i;
00278     type[i] = 'C';
00279   }
00280 
00281   // call the CPLEX function
00282   EGcplexSetCtype (Prob, ncol, ind, type);
00283   TEST (Prob->status, "in EGcplexSetAllCon");
00284 
00285   // ending
00286   EGmemPoolFree (ind, sizeof (int) * ncol, Prob->mempool);
00287   EGmemPoolFree (type, sizeof (char) * ncol, Prob->mempool);
00288   return Prob->status;
00289 }
00290 
00291 // directyly add rows to cplex
00292 int EGcplexAddCut (EGcplex_t * Prob,
00293                    void *cbdata,
00294                    int wherefrom,
00295                    int rnz,
00296                    double rhs,
00297                    char sense,
00298                    int *rmind,
00299                    double *rmval)
00300 {
00301   Prob->status =
00302     CPXcutcallbackadd (Prob->env, cbdata, wherefrom, rnz, rhs, sense, rmind,
00303                        rmval);
00304   CPLEXTEST (Prob, "in EGcplexAddCut");
00305   return Prob->status;
00306 }
00307 
00308 // add a callback cut to the LP
00309 int EGcplexAddCallbackCut (EGcplex_t * Prob,
00310                            void *cbdata,
00311                            int wherefrom,
00312                            EGrow_t * row)
00313 {
00314 
00315   /* local variables */
00316   unsigned int i,
00317     rnz = row->list->size;
00318   EGlistNode_t *It1;
00319   int *rmind;
00320   double *rmval;
00321 
00322   /* looking for memory */
00323   rmind = EGmemPoolSMalloc (Prob->mempool, int,
00324                             rnz);
00325   rmval = EGmemPoolSMalloc (Prob->mempool, double,
00326                             rnz);
00327 
00328   /* creating rmatind and rmatval */
00329   for (i = 0, It1 = row->list->begin; It1; It1 = It1->next, i++)
00330   {
00331     rmind[i] = ((EGcplexData_t *) (It1->this))->LPind;
00332     rmval[i] = ((EGcplexData_t *) (It1->this))->coeff;
00333   }
00334 
00335   /* Adding the cut to CPLEX */
00336   EGcplexAddCut (Prob, cbdata, wherefrom, (signed) rnz, row->rhs, row->sense,
00337                  rmind, rmval);
00338   CPLEXTEST (Prob, "In EGcplexAddCallbackCut");
00339 
00340   EGmemPoolFree (rmind, rnz * sizeof (int), Prob->mempool);
00341   EGmemPoolFree (rmval, rnz * sizeof (double), Prob->mempool);
00342 
00343   return 0;
00344 }
00345 
00346 // indicates the number of rows (or restrictions) in the problem
00347 int EGcplexGetNumRows (EGcplex_t * Prob,
00348                        int *nrowptr)
00349 {
00350   *nrowptr = CPXgetnumrows (Prob->env, Prob->lp);
00351   return 0;
00352 }
00353 
00354 /* ========================================================================= */
00355 /* directyly add rows to cplex */
00356 int EGcplexAddRow (EGcplex_t * Prob,
00357                    int rcnt,
00358                    int rnz,
00359                    double *rhs,
00360                    char *sense,
00361                    int *rmbeg,
00362                    int *rmind,
00363                    double *rmval,
00364                    char **rname)
00365 {
00366 
00367 #if __EG_CPLEX_EXTRADEBUG__
00368   /* local variables */
00369   register int row,
00370     ind;
00371   int ncol,
00372     nrow;
00373 
00374   /* basic set-up */
00375   MESSAGE (3, "Performing Sanity tests");
00376   EGcplexGetNumCols (Prob, &ncol);
00377   EGcplexGetNumRows (Prob, &nrow);
00378 
00379   /* test non null arrays */
00380   TEST (!rhs || !rmbeg || (rnz && (!rmind || !rmval)) || !sense || !rname,
00381         "Unacceptable NULL parameter");
00382   TEST (rcnt < 0, "Negative Value for rcnt");
00383   TEST (rnz < 0, "Negative Value for rnz");
00384 
00385   /* loop through every new column added and check if the column is OK */
00386   for (row = 0; row < rcnt; row++)
00387   {
00388     TEST (!(rname[row]), "row[%d]=Null, please select a name", row);
00389     TEST (strlen (rname[row]) > 256, "row[%d] =%s has a too long name, please "
00390           "select a better name", row, rname[row]);
00391     TEST ((sense[row] != 'L') && (sense[row] != 'E') && (sense[row] != 'G'),
00392           "sense[%d]=%c is not well setted", row, sense[row]);
00393     TEST (!finite (rhs[row]), "rhs[%d]=%lf is not a number for "
00394           "row[%d]=%s", row, rhs[row], row, rname[row]);
00395     TEST ((row + 1 < rcnt) && (rmbeg[row] > rmbeg[row + 1]), "rmbeg is not in "
00396           "ascending order");
00397     TEST (rmbeg[row] < 0, "rmbeg[%d] is negative", row);
00398     for (ind = rmbeg[row]; ind < rnz; ind++)
00399     {
00400       if ((row + 1 < rcnt) && (rmbeg[row + 1] <= ind))
00401         break;
00402       TEST ((rmind[ind] < 0)
00403             || (rmind[ind] >= nrow), "rmind[%d]=%d>%d=ncol for " "row[%d]=%s",
00404             ind, rmind[ind], ncol, row, rname[row]);
00405       TEST (!finite (rmval[ind]),
00406             "rmval[%d]=%lf is not a number for " "row[%d]=%s", ind, rmval[ind],
00407             row, rname[row]);
00408     }
00409   }
00410 #endif
00411 
00412   Prob->status = CPXaddrows (Prob->env, Prob->lp, 0, rcnt, rnz, rhs, sense,
00413                              rmbeg, rmind, rmval, 0, rname);
00414   CPLEXTEST (Prob, "in EGcplexAddRow");
00415   return Prob->status;
00416 }
00417 
00418 // add a list of rows to the LP
00419 int EGcplexAddRowList (EGcplex_t * Prob,
00420                        EGlist_t * rows)
00421 {
00422 
00423   // local variables
00424   EGlistNode_t *It1;
00425   EGlistNode_t *It2;
00426   int rnz,
00427     i;
00428   double *rhs;
00429   char *sense;
00430   int *rmbeg;
00431   int *rmind;
00432   double *rmval;
00433   char **rname;
00434   int nrows;
00435   char temp_name[24];
00436 
00437   // if there is nothing to do we exit
00438   if (!rows->size)
00439     return 0;
00440 
00441   // basic set-up
00442   EGcplexGetNumRows (Prob, &nrows);
00443 
00444   // computing rnz
00445   rnz = 0;
00446   for (It1 = rows->begin; It1; It1 = It1->next)
00447     rnz += ((EGrow_t *) (It1->this))->list->size;
00448 
00449   // looking for memory
00450   rhs = EGmemPoolSMalloc (Prob->mempool, double,
00451                           rows->size);
00452   sense = EGmemPoolSMalloc (Prob->mempool, char,
00453                             rows->size);
00454   rmbeg = EGmemPoolSMalloc (Prob->mempool, int,
00455                             rows->size);
00456   rname = EGmemPoolSMalloc (Prob->mempool, char *,
00457                             rows->size);
00458   if (rnz)
00459   {
00460     rmind = EGmemPoolSMalloc (Prob->mempool, int,
00461                               rnz);
00462     rmval = EGmemPoolSMalloc (Prob->mempool, double,
00463                               rnz);
00464   }
00465   else
00466   {
00467     rmind = 0;
00468     rmval = 0;
00469   }
00470 
00471   // now copy information in the rows list in to the CPLEX arrays
00472   rnz = 0;
00473   i = 0;
00474   for (It1 = rows->begin; It1; It1 = It1->next)
00475   {
00476     rmbeg[i] = rnz;
00477     rhs[i] = ((EGrow_t *) (It1->this))->rhs;
00478     sense[i] = ((EGrow_t *) (It1->this))->sense;
00479     if (!(((EGrow_t *) (It1->this))->name))
00480     {
00481       EGmvar (temp_name, 1, "R", nrows + i + 1);
00482       ((EGrow_t *) (It1->this))->name = EGmemPoolSMalloc (Prob->mempool, char,
00483                                                           strlen (temp_name) +
00484                                                           1);
00485       strcpy (((EGrow_t *) (It1->this))->name, temp_name);
00486     }
00487     rname[i] = ((EGrow_t *) (It1->this))->name;
00488     for (It2 = ((EGrow_t *) (It1->this))->list->begin; It2; It2 = It2->next)
00489     {
00490       rmind[rnz] = ((EGcplexData_t *) (It2->this))->LPind;
00491       rmval[rnz] = ((EGcplexData_t *) (It2->this))->coeff;
00492       rnz++;
00493     }
00494     i++;
00495   }
00496 
00497   // now we actually add the rows to the CPLEX problem
00498   Prob->status =
00499     EGcplexAddRow (Prob, (signed) (rows->size), rnz, rhs, sense, rmbeg, rmind,
00500                    rmval, rname);
00501   CPLEXTEST (Prob, "in EGcplexAddRowList");
00502 
00503   // ending
00504   EGmemPoolFree (rhs, rows->size * sizeof (double), Prob->mempool);
00505   EGmemPoolFree (sense, rows->size * sizeof (char), Prob->mempool);
00506   EGmemPoolFree (rmbeg, rows->size * sizeof (int), Prob->mempool);
00507   if (rnz)
00508   {
00509     EGmemPoolFree (rmind, rnz * sizeof (char), Prob->mempool);
00510     EGmemPoolFree (rmval, rnz * sizeof (char), Prob->mempool);
00511   }
00512   EGmemPoolFree (rname, rows->size * sizeof (char *), Prob->mempool);
00513   return Prob->status;
00514 }
00515 
00516 // add an array of rows to the problem
00517 int EGcplexAddRowArray (EGcplex_t * Prob,
00518                         EGrow_t ** Rows,
00519                         unsigned int rsz)
00520 {
00521 
00522   // local variables
00523   unsigned int It1;
00524   EGlistNode_t *It2;
00525   int rnz;
00526   double *rhs;
00527   char *sense;
00528   int *rmbeg;
00529   int *rmind;
00530   double *rmval;
00531   char **rname;
00532   int nrows;
00533   char temp_name[24];
00534 
00535   // if there is nothing to do, we return
00536   if (!rsz)
00537     return 0;
00538 
00539   // basic set-up
00540   EGcplexGetNumRows (Prob, &nrows);
00541 
00542   // computing rnz
00543   rnz = 0;
00544   for (It1 = 0; It1 < rsz; It1++)
00545     rnz += Rows[It1]->list->size;
00546 
00547   // looking for memory
00548   rhs = EGmemPoolSMalloc (Prob->mempool, double,
00549                           rsz);
00550   sense = EGmemPoolSMalloc (Prob->mempool, char,
00551                             rsz);
00552   rmbeg = EGmemPoolSMalloc (Prob->mempool, int,
00553                             rsz);
00554   rname = EGmemPoolSMalloc (Prob->mempool, char *,
00555                             rsz);
00556   if (rnz)
00557   {
00558     rmind = EGmemPoolSMalloc (Prob->mempool, int,
00559                               rnz);
00560     rmval = EGmemPoolSMalloc (Prob->mempool, double,
00561                               rnz);
00562   }
00563   else
00564   {
00565     rmind = 0;
00566     rmval = 0;
00567   }
00568 
00569   // now copy information in the rows list in to the CPLEX arrays
00570   rnz = 0;
00571   for (It1 = 0; It1 < rsz; It1++)
00572   {
00573     rmbeg[It1] = rnz;
00574     rhs[It1] = Rows[It1]->rhs;
00575     sense[It1] = Rows[It1]->sense;
00576     if (!(Rows[It1]->name))
00577     {
00578       EGmvar (temp_name, 1, "R", nrows + 1 + It1);
00579       Rows[It1]->name = EGmemPoolSMalloc (Prob->mempool, char,
00580                                           strlen (temp_name) + 1);
00581       strcpy (Rows[It1]->name, temp_name);
00582     }
00583     rname[It1] = Rows[It1]->name;
00584     for (It2 = Rows[It1]->list->begin; It2; It2 = It2->next)
00585     {
00586       rmind[rnz] = ((EGcplexData_t *) (It2->this))->LPind;
00587       rmval[rnz] = ((EGcplexData_t *) (It2->this))->coeff;
00588       rnz++;
00589     }
00590   }
00591 
00592   // now we actually add the rows to the CPLEX problem
00593   Prob->status =
00594     EGcplexAddRow (Prob, (signed) rsz, rnz, rhs, sense, rmbeg, rmind, rmval,
00595                    rname);
00596   CPLEXTEST (Prob, "in EGcplexAddRowArray");
00597 
00598   // ending
00599   EGmemPoolFree (rhs, rsz * sizeof (double), Prob->mempool);
00600   EGmemPoolFree (sense, rsz * sizeof (char), Prob->mempool);
00601   EGmemPoolFree (rmbeg, rsz * sizeof (int), Prob->mempool);
00602   if (rnz)
00603   {
00604     EGmemPoolFree (rmind, rnz * sizeof (char), Prob->mempool);
00605     EGmemPoolFree (rmval, rnz * sizeof (char), Prob->mempool);
00606   }
00607   EGmemPoolFree (rname, rsz * sizeof (char *), Prob->mempool);
00608   return Prob->status;
00609 }
00610 
00611 /* ========================================================================= */
00612 /* directly add columns to cplex */
00613 int EGcplexAddCol (EGcplex_t * Prob,
00614                    int ccnt,
00615                    int cnz,
00616                    double *cobj,
00617                    int *cmbeg,
00618                    int *cmind,
00619                    double *cmval,
00620                    double *clb,
00621                    double *cub,
00622                    char **cname)
00623 {
00624 
00625 #if __EG_CPLEX_EXTRADEBUG__
00626   /* local variables */
00627   register int col,
00628     ind;
00629   int ncol,
00630     nrow;
00631   unsigned int c1 = 0,
00632     c2 = 0;
00633 
00634   /* basic set-up */
00635   MESSAGE (3, "Performing Sanity tests");
00636   EGcplexGetNumCols (Prob, &ncol);
00637   EGcplexGetNumRows (Prob, &nrow);
00638 
00639   /* test non null arrays */
00640   TEST (!cobj || !cmbeg || (cnz && (!cmind || !cmval)) || !clb || !cub
00641         || !cname, "Unacceptable NULL parameter");
00642   TEST (ccnt < 0, "Negative Value for ccnt");
00643   TEST (cnz < 0, "Negative Value for cnz");
00644 
00645   /* loop through every new column added and check if the column is OK */
00646   for (col = 0; col < ccnt; col++)
00647   {
00648     c1++;
00649     TEST (!(cname[col]), "col[%d]=Null, please select a name", col);
00650     TEST (strlen (cname[col]) > 256, "col[%d] =%s has a too long name, please "
00651           "select a better name", col, cname[col]);
00652     TEST (clb[col] > cub[col], "ub[%d]=%lf<lb[%d]=%lf col %s", col, cub[col],
00653           col, clb[col], cname[col]);
00654     TEST (!finite (cobj[col]),
00655           "cobj[%d]=%lf is not a number for " "col[%d]=%s", col, cobj[col],
00656           col, cname[col]);
00657     TEST ((col + 1 < ccnt)
00658           && (cmbeg[col] > cmbeg[col + 1]),
00659           "cmbeg is not in " "ascending order");
00660     TEST (cmbeg[col] < 0, "cmbeg[%d] is negative", col);
00661     for (ind = cmbeg[col]; ind < cnz; ind++)
00662     {
00663       if ((col + 1 < ccnt) && (cmbeg[col + 1] <= ind))
00664         break;
00665       c2++;
00666       TEST (!finite (cmval[ind]), "cmval[%d]=%lf is not a number for "
00667             "col[%d]=%s", ind, cmval[ind], col, cname[col]);
00668       TEST ((cmind[ind] < 0)
00669             || (cmind[ind] >= nrow),
00670             "cmind[%d]=%d > nrow=%d, " "cmval[%d]=%lf for col[%d]=%s", ind,
00671             cmind[ind], nrow, ind, cmval[ind], col, cname[col]);
00672     }
00673   }
00674   MESSAGE (3, "tested %u columns and %u column coefficients cnz=%d", c1, c2,
00675            cnz);
00676 #endif
00677 
00678   Prob->status = CPXaddcols (Prob->env, Prob->lp, ccnt, cnz, cobj, cmbeg,
00679                              cmind, cmval, clb, cub, cname);
00680   CPLEXTEST (Prob, "in EGcplexAddCol");
00681   return Prob->status;
00682 }
00683 
00684 
00685 // add a list of columns to the problem
00686 int EGcplexAddColList (EGcplex_t * Prob,
00687                        EGlist_t * Cols)
00688 {
00689 
00690   // local variables
00691   EGlistNode_t *It1,
00692    *It2;
00693   int cnz,
00694     i;
00695   double *cobj;
00696   int *cmbeg;
00697   int *cmind;
00698   double *cmval;
00699   double *cub;
00700   double *clb;
00701   char **cname;
00702   int ncols;
00703   char temp_name[24];
00704 
00705   /* ED: For datacheck purposes */
00706   /*
00707    * int num_rows = 0, status = 0;
00708    * CPXLPptr datacheck_lp;
00709    * double *rhs = NULL;
00710    * char *sense = NULL;
00711    * int *matcnt = NULL;
00712    * int j;
00713    */
00714 
00715   /* Basic questios */
00716   if (!Cols->size)
00717     return 0;
00718 
00719   // basic set-up
00720   EGcplexGetNumCols (Prob, &ncols);
00721 
00722   // now we compute cnz
00723   cnz = 0;
00724   for (It1 = Cols->begin; It1; It1 = It1->next)
00725     cnz += ((EGcol_t *) (It1->this))->list->size;
00726 
00727   // now we look for memory
00728   cobj = EGmemPoolSMalloc (Prob->mempool, double,
00729                            Cols->size);
00730   cmbeg = EGmemPoolSMalloc (Prob->mempool, int,
00731                             Cols->size);
00732   cub = EGmemPoolSMalloc (Prob->mempool, double,
00733                           Cols->size);
00734   clb = EGmemPoolSMalloc (Prob->mempool, double,
00735                           Cols->size);
00736   cname = EGmemPoolSMalloc (Prob->mempool, char *,
00737                             Cols->size);
00738   if (cnz)
00739   {
00740     cmind = EGmemPoolSMalloc (Prob->mempool, int,
00741                               cnz);
00742     cmval = EGmemPoolSMalloc (Prob->mempool, double,
00743                               cnz);
00744   }
00745   else
00746   {
00747     cmind = 0;
00748     cmval = 0;
00749   }
00750 
00751   // now we store in those arrays the information
00752   cnz = i = 0;
00753   for (It1 = Cols->begin; It1; It1 = It1->next)
00754   {
00755     cobj[i] = ((EGcol_t *) (It1->this))->obj;
00756     cmbeg[i] = cnz;
00757     cub[i] = ((EGcol_t *) (It1->this))->ub;
00758     clb[i] = ((EGcol_t *) (It1->this))->lb;
00759     if (!(((EGcol_t *) (It1->this))->name))
00760     {
00761       EGmvar (temp_name, 1, "C", ncols + 1 + i);
00762       ((EGcol_t *) (It1->this))->name = EGmemPoolSMalloc (Prob->mempool, char,
00763                                                           strlen (temp_name) +
00764                                                           1);
00765       strcpy (((EGcol_t *) (It1->this))->name, temp_name);
00766     }
00767     cname[i] = ((EGcol_t *) (It1->this))->name;
00768     for (It2 = ((EGcol_t *) (It1->this))->list->begin; It2; It2 = It2->next)
00769     {
00770       cmind[cnz] = ((EGcplexData_t *) (It2->this))->LPind;
00771       cmval[cnz] = ((EGcplexData_t *) (It2->this))->coeff;
00772       cnz++;
00773     }
00774     i++;
00775   }
00776 
00777   // and finally we add this columns to CPLEX
00778   Prob->status =
00779     EGcplexAddCol (Prob, (signed) (Cols->size), cnz, cobj, cmbeg, cmind, cmval,
00780                    clb, cub, cname);
00781   TEST (Prob->status, "in EGcplexAddColList");
00782 
00783 
00784   /* ED: Check if the data is sound */
00785   /*
00786    * fprintf(stderr, "Begin datacheck....\n");
00787    * datacheck_lp = CPXcreateprob (Prob->env, &status, "datacheck");
00788    * 
00789    * status = EGcplexSetIntParam (Prob->env, CPX_PARAM_DATACHECK, 1);
00790    * 
00791    * EGcplexGetNumRows (Prob, &num_rows);
00792    * 
00793    * rhs = EGmemPoolSMalloc(Prob->mempool, double, num_rows);
00794    * sense = EGmemPoolSMalloc(Prob->mempool, char, num_rows);
00795    * 
00796    * status = CPXgetsense (Prob->env, Prob->lp, sense, 0, num_rows-1);
00797    * status = CPXgetrhs (Prob->env, Prob->lp, rhs, 0, num_rows-1);
00798    * 
00799    * matcnt = EGmemPoolSMalloc(Prob->mempool, int, Cols->size);
00800    * for (i = 0; i < Cols->size - 1; i++)
00801    * matcnt[i] = cmbeg[i+1] - cmbeg[i];
00802    * matcnt[Cols->size - 1] = cnz - cmbeg[Cols->size - 1];
00803    * 
00804    * status = CPXcopylp (Prob->env, datacheck_lp,
00805    * Cols->size, num_rows, -1, cobj, rhs, sense, 
00806    * cmbeg, matcnt, cmind, cmval, clb, cub,
00807    * NULL);
00808    * 
00809    * 
00810    * fprintf(stderr, "Status of copylp is %d\n", status);
00811    * 
00812    * EGmemPoolFree(rhs, num_rows * sizeof(double), Prob->mempool);
00813    * EGmemPoolFree(sense, num_rows * sizeof(char), Prob->mempool);
00814    * EGmemPoolFree(matcnt, Cols->size * sizeof(int), Prob->mempool);
00815    * 
00816    * status = CPXfreeprob (Prob->env, &datacheck_lp);
00817    * fprintf(stderr, "End datacheck....\n");
00818    */
00819   /* End datacheck */
00820 
00821 
00822   // ending
00823   EGmemPoolFree (cobj, Cols->size * sizeof (double), Prob->mempool);
00824   EGmemPoolFree (cmbeg, Cols->size * sizeof (int), Prob->mempool);
00825   EGmemPoolFree (cub, Cols->size * sizeof (double), Prob->mempool);
00826   EGmemPoolFree (clb, Cols->size * sizeof (double), Prob->mempool);
00827   EGmemPoolFree (cname, Cols->size * sizeof (char *), Prob->mempool);
00828   if (cnz)
00829   {
00830     EGmemPoolFree (cmind, cnz * sizeof (int), Prob->mempool);
00831     EGmemPoolFree (cmval, cnz * sizeof (double), Prob->mempool);
00832   }
00833   return Prob->status;
00834 }
00835 
00836 // add an array of rows to the problem
00837 int EGcplexAddColArray (EGcplex_t * Prob,
00838                         EGcol_t ** Cols,
00839                         int ccnt)
00840 {
00841 
00842   // local variables
00843   unsigned int It1;
00844   EGlistNode_t *It2;
00845   int cnz;
00846   double *cobj;
00847   int *cmbeg;
00848   int *cmind;
00849   double *cmval;
00850   double *cub;
00851   double *clb;
00852   char **cname;
00853   int ncols;
00854   char temp_name[24];
00855 
00856   /* basic questions */
00857   if (!ccnt)
00858     return 0;
00859 
00860   // basic initialization
00861   EGcplexGetNumCols (Prob, &ncols);
00862 
00863   // now we compute cnz
00864   cnz = 0;
00865   for (It1 = 0; It1 < (unsigned) ccnt; It1++)
00866     cnz += Cols[It1]->list->size;
00867 
00868   // now we look for memory
00869   cobj = EGmemPoolSMalloc (Prob->mempool, double,
00870                            ccnt);
00871   cmbeg = EGmemPoolSMalloc (Prob->mempool, int,
00872                             ccnt);
00873   cub = EGmemPoolSMalloc (Prob->mempool, double,
00874                           ccnt);
00875   clb = EGmemPoolSMalloc (Prob->mempool, double,
00876                           ccnt);
00877   cname = EGmemPoolSMalloc (Prob->mempool, char *,
00878                             ccnt);
00879   if (cnz)
00880   {
00881     cmind = EGmemPoolSMalloc (Prob->mempool, int,
00882                               cnz);
00883     cmval = EGmemPoolSMalloc (Prob->mempool, double,
00884                               cnz);
00885   }
00886   else
00887   {
00888     cmind = 0;
00889     cmval = 0;
00890   }
00891 
00892   // now we store in those arraays the information
00893   cnz = 0;
00894   for (It1 = 0; It1 < (unsigned) ccnt; It1++)
00895   {
00896     cobj[It1] = Cols[It1]->obj;
00897     cmbeg[It1] = cnz;
00898     cub[It1] = Cols[It1]->ub;
00899     clb[It1] = Cols[It1]->lb;
00900     if (!(Cols[It1]->name))
00901     {
00902       EGmvar (temp_name, 1, "C", ncols + It1 + 1);
00903       Cols[It1]->name = EGmemPoolSMalloc (Prob->mempool, char,
00904                                           strlen (temp_name) + 1);
00905       strcpy (Cols[It1]->name, temp_name);
00906     }
00907     cname[It1] = Cols[It1]->name;
00908     for (It2 = Cols[It1]->list->begin; It2; It2 = It2->next)
00909     {
00910       cmind[cnz] = ((EGcplexData_t *) (It2->this))->LPind;
00911       cmval[cnz] = ((EGcplexData_t *) (It2->this))->coeff;
00912       cnz++;
00913     }
00914   }
00915 
00916   // and finally we add this columns to CPLEX
00917   Prob->status =
00918     EGcplexAddCol (Prob, ccnt, cnz, cobj, cmbeg, cmind, cmval, clb, cub, cname);
00919   TEST (Prob->status, "in EGcplexAddColArray");
00920 
00921   // ending
00922   EGmemPoolFree (cobj, ccnt * sizeof (double), Prob->mempool);
00923   EGmemPoolFree (cmbeg, ccnt * sizeof (int), Prob->mempool);
00924   EGmemPoolFree (cub, ccnt * sizeof (double), Prob->mempool);
00925   EGmemPoolFree (clb, ccnt * sizeof (double), Prob->mempool);
00926   EGmemPoolFree (cname, ccnt * sizeof (char *), Prob->mempool);
00927   if (cnz)
00928   {
00929     EGmemPoolFree (cmind, cnz * sizeof (int), Prob->mempool);
00930     EGmemPoolFree (cmval, cnz * sizeof (double), Prob->mempool);
00931   }
00932   return Prob->status;
00933 }
00934 
00935 // Change problem type to LP.
00936 int EGcplexSetToLp (EGcplex_t * Prob)
00937 {
00938   CPXgetprobtype (Prob->env, Prob->lp);
00939   TEST ((Prob->status == -1), "in EGcplexSetToLp, no problem or enviroment");
00940   if (Prob->status)
00941     Prob->status = CPXchgprobtype (Prob->env, Prob->lp, CPXPROB_LP);
00942   CPLEXTEST (Prob, "in EGcplexSetToLp");
00943   return Prob->status;
00944 }
00945 
00946 // Primal Simplex , store the optimization status in Prob->status
00947 // status 0 means a solution is found (not necesarily
00948 // optimal) (see CPLEX manual for other values).
00949 int EGcplexPrimopt (EGcplex_t * Prob)
00950 {
00951   EGcplexSetToLp (Prob);
00952   TEST ((Prob->status), "in EGcplexPrimopt");
00953   Prob->status = CPXprimopt (Prob->env, Prob->lp);
00954   CPLEXTEST (Prob, "in EGcplexPrimopt");
00955   return Prob->status;
00956 }
00957 
00958 // hybrid Network Simplex with metod B;
00959 // B = 'p' (primal) or 'd' (dual), return the optimization
00960 // status in Prob->status, 0 means a solution is found (not necesarily optimal)
00961 // see CPLEX manual for other values).
00962 int EGcplexNetopt (EGcplex_t * Prob,
00963                    const char B)
00964 {
00965   EGcplexSetToLp (Prob);
00966   TEST ((Prob->status), "in EGcplexNetopt");
00967   Prob->status = CPXhybnetopt (Prob->env, Prob->lp, B);
00968   CPLEXTEST (Prob, "in EGcplexNetopt");
00969   return Prob->status;
00970 }
00971 
00972 // Dual Simplex, return the optimization
00973 // status in Prob->status, 0 means a solution is found (not necesarily
00974 // optimzal) (see CPLEX manual for other values).
00975 int EGcplexDualopt (EGcplex_t * Prob)
00976 {
00977   EGcplexSetToLp (Prob);
00978   TEST ((Prob->status), "in EGcplexDualopt");
00979   Prob->status = CPXdualopt (Prob->env, Prob->lp);
00980   CPLEXTEST (Prob, "in EGcplexDualopt");
00981   return Prob->status;
00982 }
00983 
00984 // Mixed Integer Methods , return the optimization status
00985 // 0 means a solution is found (not necesarily optimzal)
00986 // (see CPLEX manual for other values). where <B>maxIntSol</B> is
00987 // the maximun number of integer solution to be found before
00988 // stoping. There are other issues as precision, for that you have to 
00989 // configure the environment, see the environment information
00990 int EGcplexMipopt (EGcplex_t * Prob)
00991 {
00992   EGcplexSetToMip (Prob);
00993   TEST ((Prob->status), "in EGcplexMipopt");
00994   Prob->status = CPXmipopt (Prob->env, Prob->lp);
00995   CPLEXTEST (Prob, "in EGcplexMipopt");
00996   return Prob->status;
00997 }
00998 
00999 // set the problem for minimize (default)
01000 int EGcplexSetToMin (EGcplex_t * Prob)
01001 {
01002   CPXchgobjsen (Prob->env, Prob->lp, CPX_MIN);
01003   return 0;
01004 }
01005 
01006 // set the problem for maximize
01007 int EGcplexSetToMax (EGcplex_t * Prob)
01008 {
01009   CPXchgobjsen (Prob->env, Prob->lp, CPX_MAX);
01010   return 0;
01011 }
01012 
01013 // set the right hand side of the rows in ind to val, nz
01014 // indicate the number of entries in the arrays name and val.
01015 // Prob is the EGcplex_t structure
01016 int EGcplexSetRhs (EGcplex_t * Prob,
01017                    int nz,
01018                    int *ind,
01019                    double *val)
01020 {
01021   Prob->status = CPXchgrhs (Prob->env, Prob->lp, nz, ind, val);
01022   CPLEXTEST (Prob, "in EGcplexSetRhs");
01023   return Prob->status;
01024 }
01025 
01026 /// set the objetive coefficient of the pos-th variable to val
01027 // Prob is the EGcplex_t structure, nz is the length of the arrays
01028 // ind is the array of indices, type is the array of types of bounds to 
01029 // change and val is the new value of the bound
01030 int EGcplexSetObj (EGcplex_t * Prob,
01031                    int nz,
01032                    int *ind,
01033                    double *val)
01034 {
01035   Prob->status = CPXchgobj (Prob->env, Prob->lp, nz, ind, val);
01036   CPLEXTEST (Prob, "in EGcplexSetObj");
01037   return Prob->status;
01038 }
01039 
01040 // set for all the variables in 'bound' the limit 'type' to
01041 // the double stored in the map; type must be one of the
01042 // folowin values : 'U' for the upper limit, 'L' for the
01043 // lower limit and 'B' for both the lower and the upper
01044 // limit.
01045 // Prob is the EGcplex_t structure, nz is the length of the arrays
01046 // ind is the array of indices, type is the array of types of bounds to 
01047 // change and val is the new value of the bound
01048 int EGcplexSetBound (EGcplex_t * Prob,
01049                      int nz,
01050                      int *ind,
01051                      char *type,
01052                      double *val)
01053 {
01054   Prob->status = CPXchgbds (Prob->env, Prob->lp, nz, ind, type, val);
01055   CPLEXTEST (Prob, "in EGcplexSetBound");
01056   return Prob->status;
01057 }
01058 
01059 // deletes rows with index bigger or equal than 'beg' but smaller than 'end'
01060 int EGcplexDelRows (EGcplex_t * Prob,
01061                     int beg,
01062                     int end)
01063 {
01064   Prob->status = CPXdelrows (Prob->env, Prob->lp, beg, end - 1);
01065   CPLEXTEST (Prob, "in EGcplexDelRows");
01066   return Prob->status;
01067 }
01068 
01069 // deletes cols with index bigger or equal than 'beg' but smaller than 'end' 
01070 int EGcplexDelCols (EGcplex_t * Prob,
01071                     int beg,
01072                     int end)
01073 {
01074   Prob->status = CPXdelcols (Prob->env, Prob->lp, beg, end - 1);
01075   CPLEXTEST (Prob, "in EGcplexDelCols");
01076   return Prob->status;
01077 }
01078 
01079 // return the CPLEX status of the problem, that status
01080 // indicates optimality, infeasibility, etc., see (CPLEX manual
01081 // for further information).
01082 int EGcplexGetStat (EGcplex_t * Prob,
01083                     int *statusptr)
01084 {
01085   *statusptr = CPXgetstat (Prob->env, Prob->lp);
01086   return 0;
01087 }
01088 
01089 /* ========================================================================= */
01090 /* return the current objetive value for the problem. */
01091 /* ========================================================================= */
01092 int EGcplexGetBestObjval (EGcplex_t * Prob,
01093                           double *valptr)
01094 {
01095   Prob->status = CPXgetprobtype (Prob->env, Prob->lp);
01096   if (Prob->status == 0)
01097     return 1;
01098   else if (Prob->status == 1)
01099     Prob->status = CPXgetbestobjval (Prob->env, Prob->lp, valptr);
01100   else
01101     TEST (1, "in EGcplexGetBestObjval, unknown problem type");
01102   CPLEXTEST (Prob, "in EGcplexGetBestObjval");
01103   return Prob->status;
01104 }
01105 
01106 
01107 // return the current objetive value for the problem.
01108 int EGcplexGetObjval (EGcplex_t * Prob,
01109                       double *valptr)
01110 {
01111   Prob->status = CPXgetprobtype (Prob->env, Prob->lp);
01112   if (Prob->status == 0)
01113     Prob->status = CPXgetobjval (Prob->env, Prob->lp, valptr);
01114   else if (Prob->status == 1)
01115     Prob->status = CPXgetmipobjval (Prob->env, Prob->lp, valptr);
01116   else
01117     EXIT (1, "in EGcplexGetObjval, unknown problem type");
01118   CPLEXTEST (Prob, "in EGcplexGetObjval");
01119   return Prob->status;
01120 }
01121 
01122 // given an array x of size end - begin and a problem, return the current values for the
01123 // variables in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01124 int EGcplexGetX (EGcplex_t * Prob,
01125                  double *x,
01126                  int begin,
01127                  int end)
01128 {
01129   Prob->status = CPXgetprobtype (Prob->env, Prob->lp);
01130   if (Prob->status == 0)
01131     Prob->status = CPXgetx (Prob->env, Prob->lp, x, begin, end - 1);
01132   else if (Prob->status == 1)
01133     Prob->status = CPXgetmipx (Prob->env, Prob->lp, x, begin, end - 1);
01134   else
01135     EXIT (1, "in EGcplexGetX, unknown problem type");
01136   CPLEXTEST (Prob, "in EGcplexGetX");
01137   return Prob->status;
01138 }
01139 
01140 // given an array x of size end - begin and a problem, return the current dual values for the
01141 // constraint in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01142 int EGcplexGetPi (EGcplex_t * Prob,
01143                   double *x,
01144                   int begin,
01145                   int end)
01146 {
01147   Prob->status = CPXgetprobtype (Prob->env, Prob->lp);
01148   if (Prob->status == 0)
01149     Prob->status = CPXgetpi (Prob->env, Prob->lp, x, begin, end - 1);
01150   else
01151     EXIT (1, "in EGcplexGetPi, unknown problem type or problem is MIP");
01152   CPLEXTEST (Prob, "in EGcplexGetPi");
01153   return Prob->status;
01154 }
01155 
01156 // given an array x of size end - begin and a problem, return the current slack for the
01157 // constraints in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01158 int EGcplexGetSlack (EGcplex_t * Prob,
01159                      double *x,
01160                      int begin,
01161                      int end)
01162 {
01163   Prob->status = CPXgetprobtype (Prob->env, Prob->lp);
01164   if (Prob->status == 0)
01165     Prob->status = CPXgetslack (Prob->env, Prob->lp, x, begin, end - 1);
01166   else if (Prob->status == 1)
01167     Prob->status = CPXgetmipslack (Prob->env, Prob->lp, x, begin, end - 1);
01168   else
01169     EXIT (1, "in EGcplexGetSlack, unknown problem type");
01170   CPLEXTEST (Prob, "in EGcplexGetSlack");
01171   return Prob->status;
01172 }
01173 
01174 // given an array x of size end - begin and a problem, return the current reduced cost values for the
01175 // variables in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01176 int EGcplexGetDj (EGcplex_t * Prob,
01177                   double *x,
01178                   int begin,
01179                   int end)
01180 {
01181   Prob->status = CPXgetprobtype (Prob->env, Prob->lp);
01182   if (Prob->status == 0)
01183     Prob->status = CPXgetdj (Prob->env, Prob->lp, x, begin, end - 1);
01184   else
01185     EXIT (1, "in EGcplexGetDj, unknown problem type or problem is MIP");
01186   CPLEXTEST (Prob, "in EGcplexGetDj");
01187   return Prob->status;
01188 }
01189 
01190 /* return in how many constraints a particular column bellongs */
01191 int EGcplexGetColNZ (EGcplex_t * Prob,
01192                      int cind,
01193                      int *cnz)
01194 {
01195 
01196   /* local variables */
01197   int colnz,
01198     matbeg;
01199 
01200   Prob->status =
01201     CPXgetcols (Prob->env, Prob->lp, &colnz, &matbeg, 0, 0, 0, cnz, cind, cind);
01202   if (Prob->status != 1207)
01203     CPLEXTEST (Prob, "in EGcplexGetColNZ");
01204   *cnz *= -1;
01205 
01206   /* ending */
01207   return Prob->status;
01208 }
01209 
01210 /* return a range of rows */
01211 int EGcplexGetRows (EGcplex_t * Prob,
01212                     int *nz,
01213                     int *rbeg,
01214                     int *rind,
01215                     double *rval,
01216                     int size,
01217                     int *surplus,
01218                     int begin,
01219                     int end)
01220 {
01221   Prob->status =
01222     CPXgetrows (Prob->env, Prob->lp, nz, rbeg, rind, rval, size, surplus,
01223                 begin, end - 1);
01224   if (Prob->status == CPXERR_NEGATIVE_SURPLUS)
01225     return 0;
01226   CPLEXTEST (Prob, "in EGcplexGetRows");
01227   return Prob->status;
01228 }
01229 
01230 int EGcplexGetCols (EGcplex_t * Prob,
01231                     int *nz,
01232                     int *cbeg,
01233                     int *cind,
01234                     double *cval,
01235                     int size,
01236                     int *surplus,
01237                     int begin,
01238                     int end)
01239 {
01240   Prob->status =
01241     CPXgetcols (Prob->env, Prob->lp, nz, cbeg, cind, cval, size, surplus,
01242                 begin, end - 1);
01243   if (Prob->status == CPXERR_NEGATIVE_SURPLUS)
01244     return 0;
01245   CPLEXTEST (Prob, "in EGcplexGetCols");
01246   return Prob->status;
01247 }
01248 
01249 // Return the column names
01250 // Prob is a pointer to a EGcplex_t structure
01251 // begin denote the first column name to take
01252 // end denote the last plus one column name to take
01253 // name is an an array of size end - begin of pointers to char*
01254 // name store is an array of chars of size storesize where the names will be stored
01255 // surplusptr is a pointer to an integer where the size of the non used space in store will be stored
01256 // if *surplusptr is negative, the call had fail
01257 int EGcplexGetColname (EGcplex_t * Prob,
01258                        char **names,
01259                        char *store,
01260                        int storesize,
01261                        int *splusptr,
01262                        int begin,
01263                        int end)
01264 {
01265   Prob->status =
01266     CPXgetcolname (Prob->env, Prob->lp, names, store, storesize, splusptr,
01267                    begin, end - 1);
01268   if (Prob->status != CPXERR_NEGATIVE_SURPLUS)
01269     CPLEXTEST (Prob, "in EGcplexGetColname");
01270   return Prob->status;
01271 }
01272 
01273 // Return the row names
01274 // Prob is a pointer to a EGcplex_t structure
01275 // begin denote the first row name to take
01276 // end denote the last plus one row name to take
01277 // name is an an array of size end - begin of pointers to char*
01278 // name store is an array of chars of size storesize where the names will be stored
01279 // surplusptr is a pointer to an integer where the size of the non used space in store will be stored
01280 // if *surplusptr is negative, the call had fail
01281 int EGcplexGetRowname (EGcplex_t * Prob,
01282                        char **names,
01283                        char *store,
01284                        int storesize,
01285                        int *splusptr,
01286                        int begin,
01287                        int end)
01288 {
01289   Prob->status =
01290     CPXgetrowname (Prob->env, Prob->lp, names, store, storesize, splusptr,
01291                    begin, end - 1);
01292   if (Prob->status != CPXERR_NEGATIVE_SURPLUS)
01293     CPLEXTEST (Prob, "in EGcplexGetRowname");
01294   return Prob->status;
01295 }
01296 
01297 // given an array x of size end - begin and a problem, return the current upper bounds values for the
01298 // variables in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01299 int EGcplexGetUb (EGcplex_t * Prob,
01300                   double *x,
01301                   int begin,
01302                   int end)
01303 {
01304   Prob->status = CPXgetub (Prob->env, Prob->lp, x, begin, end - 1);
01305   CPLEXTEST (Prob, "in EGcplexGetUb");
01306   return Prob->status;
01307 }
01308 
01309 // given an array x of size end - begin and a problem, return the current lower bounds values for the
01310 // variables in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01311 int EGcplexGetLb (EGcplex_t * Prob,
01312                   double *x,
01313                   int begin,
01314                   int end)
01315 {
01316   Prob->status = CPXgetlb (Prob->env, Prob->lp, x, begin, end - 1);
01317   CPLEXTEST (Prob, "in EGcplexGetLb");
01318   return Prob->status;
01319 }
01320 
01321 // given an array x of size end - begin and a problem, return the objective values for the
01322 // variables in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01323 int EGcplexGetObjCoeff (EGcplex_t * Prob,
01324                         double *x,
01325                         int begin,
01326                         int end)
01327 {
01328   Prob->status = CPXgetobj (Prob->env, Prob->lp, x, begin, end - 1);
01329   CPLEXTEST (Prob, "in EGcplexGetObjCoeff");
01330   return Prob->status;
01331 }
01332 
01333 // given an array x of size end - begin and a problem, return the sense values for the
01334 // constraints in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01335 int EGcplexGetSense (EGcplex_t * Prob,
01336                      char *x,
01337                      int begin,
01338                      int end)
01339 {
01340   Prob->status =
01341     CPXgetsense ((CPXENVptr) (Prob->env), Prob->lp, x, begin, end - 1);
01342   CPLEXTEST (Prob, "in EGcplexGetSense");
01343   return Prob->status;
01344 }
01345 
01346 // given an array x of size end - begin and a problem, return the sense values for the
01347 // constraints in the range [begin,end[, i.e. we obtain x[begin],....,x[end-1]
01348 int EGcplexGetRhs (EGcplex_t * Prob,
01349                    double *x,
01350                    int begin,
01351                    int end)
01352 {
01353   Prob->status = CPXgetrhs (Prob->env, Prob->lp, x, begin, end - 1);
01354   CPLEXTEST (Prob, "in EGcplexGetRhs");
01355   return Prob->status;
01356 }
01357 
01358 // save the problem structure in format type, where type must
01359 // be "SAV" for binary matrix and basis file, "MPS" for
01360 // MPS format, "LP" for CPLEX LP format, "REW" or "RMP" for
01361 // MPS format with all names changed to generic names
01362 // or "RLP" for LP format with all names changed to generic
01363 // names.
01364 int EGcplexWriteProb (EGcplex_t * Prob,
01365                       const char *file,
01366                       const char *type)
01367 {
01368 #if CPX_VERSION > 800
01369   Prob->status = CPXwriteprob (Prob->env, Prob->lp, file, type);
01370 #else
01371   char *lfile = strdup (file);
01372   char *ltype = strdup (type);
01373   Prob->status = CPXwriteprob (Prob->env, Prob->lp, lfile, ltype);
01374   free (lfile);
01375   free (ltype);
01376 #endif
01377   CPLEXTEST (Prob, "in EGcplexWriteProb");
01378   return Prob->status;
01379 }
01380 
01381 // add a function callback for Cplex incumber solution during MIP
01382 // note that the callback is asociated to the CPLEX environment and not to the 
01383 // CPLEX problem
01384 int EGcplexAddIncumbentCallBack (EGcplex_t * Prob,
01385                                  int (CPXPUBLIC * callback) (EGCPXENVptr,
01386                                                              void *,
01387                                                              int,
01388                                                              void *,
01389                                                              double,
01390                                                              double *,
01391                                                              int *,
01392                                                              int *),
01393                                  void *cinfo)
01394 {
01395 #if CPX_VERSION > 700
01396   Prob->status =
01397     CPXsetincumbentcallbackfunc ((CPXENVptr) (Prob->env), callback, cinfo);
01398   CPLEXTEST (Prob, "in EGcplexAddIncumbentCallBack");
01399 #else
01400   EXIT (1, "in EGcplexAddIncumbentCallBack, not supported before Cplex 7.1");
01401 #endif
01402   return Prob->status;
01403 }
01404 
01405 // add a function callback for cut generation during MIP
01406 // note that the callback is asociated to the CPLEX environment and not to the 
01407 // CPLEX problem
01408 int EGcplexAddCutCallBack (EGcplex_t * Prob,
01409                            int (CPXPUBLIC * callback) (EGCPXENVptr,
01410                                                        void *,
01411                                                        int,
01412                                                        void *,
01413                                                        int *),
01414                            void *cinfo)
01415 {
01416   Prob->status =
01417     CPXsetcutcallbackfunc ((CPXENVptr) (Prob->env), callback, cinfo);
01418   CPLEXTEST (Prob, "in EGcplexAddIncumbentCallBack");
01419   return Prob->status;
01420 }
01421 
01422 /* this function is to set any integer parameter of CPLEX, this affects the
01423  * nefironment */
01424 int EGcplexSetDblParam (CPXENVptr env,
01425                         int param,
01426                         double value)
01427 {
01428   int status;
01429   status = CPXsetdblparam (env, param, value);
01430   if (status)
01431   {
01432     CPXgeterrorstring (env, status, EGcplexErrMsg);
01433     fprintf (stderr, "en EGcplexSetDblParam, in file %s, line %d\n", __FILE__,
01434              __LINE__);
01435     fprintf (stderr, "%s\n", EGcplexErrMsg);
01436   }
01437   return status;
01438 }
01439 
01440 // set the CPLEX environment output off, all problems sharing this environment
01441 // will not report to screen
01442 int EGcplexSetScreenOff (EGcplex_t * Prob)
01443 {
01444   Prob->status =
01445     CPXsetintparam ((CPXENVptr) (Prob->env), CPX_PARAM_SCRIND, CPX_OFF);
01446   CPLEXTEST (Prob, "in EGcplexSetScreenOff");
01447   return Prob->status;
01448 }
01449 
01450 // set an upper bound for the LP objetive function, this bound will affect all problems
01451 // that share the CPLEX environment
01452 int EGcplexSetULP (EGcplex_t * Prob,
01453                    double ubound)
01454 {
01455   Prob->status =
01456     CPXsetdblparam ((CPXENVptr) (Prob->env), CPX_PARAM_OBJULIM, ubound);
01457   CPLEXTEST (Prob, "in EGcplexSetULP");
01458   return Prob->status;
01459 }
01460 
01461 // set an lower bound for the LP objetive function, this bound will affect all problems
01462 // that share the CPLEX environment
01463 int EGcplexSetLLP (EGcplex_t * Prob,
01464                    double lbound)
01465 {
01466   Prob->status =
01467     CPXsetdblparam ((CPXENVptr) Prob->env, CPX_PARAM_OBJLLIM, lbound);
01468   CPLEXTEST (Prob, "in EGcplexSetLLP");
01469   return Prob->status;
01470 }
01471 
01472 // set an upper bound for the MIP objetive function, this bound will affect all problems
01473 // that share the CPLEX environment
01474 int EGcplexSetUMIP (EGcplex_t * Prob,
01475                     double ubound)
01476 {
01477   Prob->status =
01478     CPXsetdblparam ((CPXENVptr) Prob->env, CPX_PARAM_CUTUP, ubound);
01479   CPLEXTEST (Prob, "in EGcplexSetULP");
01480   return Prob->status;
01481 }
01482 
01483 // set an lower bound for the MIP objetive function, this bound will affect all problems
01484 // that share the CPLEX environment
01485 int EGcplexSetLMIP (EGcplex_t * Prob,
01486                     double lbound)
01487 {
01488   Prob->status =
01489     CPXsetdblparam ((CPXENVptr) Prob->env, CPX_PARAM_CUTLO, lbound);
01490   CPLEXTEST (Prob, "in EGcplexSetLLP");
01491   return Prob->status;
01492 }
01493 
01494 /* ========================================================================= */
01495 /* set the sense of a set of constraints */
01496 /* ========================================================================= */
01497 int EGcplexSetSense (EGcplex_t * Prob,
01498                      int nz,
01499                      int *ind,
01500                      char *sense)
01501 {
01502   Prob->status = CPXchgsense (Prob->env, Prob->lp, nz, ind, sense);
01503   CPLEXTEST (Prob, "in EGcplexSetSense");
01504   return Prob->status;
01505 }
01506 
01507 /* this function, as its name says, is a null cut callback, this is used in
01508  * order to reset or shadow a previous callback asociated to the underlying
01509  * CPXENV. Note that all calbacks are associated to the environment instead of
01510  * the problem. */
01511 /*
01512 int CPXPUBLIC EGcplexNullCutCallBack (EGCPXENVptr env,
01513                                       void *cbdata,
01514                                       int wherefrom,
01515                                       void *cbhandle,
01516                                       int *usercation__p)
01517 {
01518 
01519   return 0;
01520 }
01521 */
01522 EGcutCallBack_f EGcplexNullCutCallBack = 0;
01523 
01524 // this is for testing purposes only, you should call this function before running just to be 
01525 // sure the structures are OK
01526 #endif

Generated on Mon Jan 30 08:48:52 2006 for EGlib by  doxygen 1.4.5