Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

OsiCpxSolverInterface.cpp

00001 //  LAST EDIT: Tue Nov 27 16:30:04 CET 2001 by Laszlo Ladanyi
00002 //-----------------------------------------------------------------------------
00003 // name:     OSI Interface for CPLEX
00004 // author:   Tobias Pfender
00005 //           Konrad-Zuse-Zentrum Berlin (Germany)
00006 //           email: pfender@zib.de
00007 // date:     09/25/2000
00008 // comments: please scan this file for '???' and read the comments
00009 //-----------------------------------------------------------------------------
00010 // Copyright (C) 2000, Tobias Pfender, International Business Machines
00011 // Corporation and others.  All Rights Reserved.
00012 
00013 #if defined(_MSC_VER)
00014 // Turn off compiler warning about long names
00015 #  pragma warning(disable:4786)
00016 #endif
00017 
00018 #include <iostream>
00019 #include <cassert>
00020 #include <string>
00021 #include <numeric>
00022 
00023 #include "CoinError.hpp"
00024 
00025 #include "OsiCpxSolverInterface.hpp"
00026 #include "OsiRowCut.hpp"
00027 #include "OsiColCut.hpp"
00028 #include "CoinPackedMatrix.hpp"
00029 #include "CoinWarmStartBasis.hpp"
00030 
00031 
00032 // #define DEBUG 1
00033 
00034 #ifdef DEBUG
00035 #define debugMessage printf
00036 #else
00037 #define debugMessage if( false ) printf
00038 #endif
00039 
00040 
00041 //#############################################################################
00042 // A couple of helper functions
00043 //#############################################################################
00044 
00045 inline void freeCacheDouble( double*& ptr )
00046 {
00047   if( ptr != NULL )
00048     {
00049       delete [] ptr;
00050       ptr = NULL;
00051     }
00052 }
00053 
00054 inline void freeCacheChar( char*& ptr )
00055 {
00056   if( ptr != NULL )
00057     {
00058       delete [] ptr;
00059       ptr = NULL;
00060     }
00061 }
00062 
00063 inline void freeCacheMatrix( CoinPackedMatrix*& ptr )
00064 {
00065   if( ptr != NULL )
00066     {
00067       delete ptr;
00068       ptr = NULL;
00069     }
00070 }
00071 
00072 static inline void
00073 checkCPXerror( int err, std::string cpxfuncname, std::string osimethod )
00074 {
00075   if( err != 0 )
00076     {
00077       char s[100];
00078       sprintf( s, "%s returned error %d", cpxfuncname.c_str(), err );
00079       std::cout << "ERROR: " << s << " (" << osimethod << 
00080         " in OsiCpxSolverInterface)" << std::endl;
00081       throw CoinError( s, osimethod.c_str(), "OsiCpxSolverInterface" );
00082     }
00083 }
00084 
00085 void
00086 OsiCpxSolverInterface::switchToLP( void )
00087 {
00088   debugMessage("OsiCpxSolverInterface::switchToLP()\n");
00089 
00090   if( probtypemip_ )
00091   {
00092      CPXLPptr lp = getMutableLpPtr();
00093 
00094 #if CPX_VERSION >= 800
00095      assert(CPXgetprobtype(env_,lp) == CPXPROB_MILP);
00096 #else
00097      assert(CPXgetprobtype(env_,lp) == CPXPROB_MIP);
00098 #endif
00099 
00100      int err = CPXchgprobtype( env_, lp, CPXPROB_LP );
00101      checkCPXerror( err, "CPXchgprobtype", "switchToLP" );
00102      probtypemip_ = false;
00103   }
00104 }
00105 
00106 void
00107 OsiCpxSolverInterface::switchToMIP( void )
00108 {
00109   debugMessage("OsiCpxSolverInterface::switchToMIP()\n");
00110 
00111   if( !probtypemip_ )
00112   {
00113      CPXLPptr lp = getMutableLpPtr();
00114      int nc = getNumCols();
00115      int *cindarray = new int[nc];
00116 
00117      assert(CPXgetprobtype(env_,lp) == CPXPROB_LP);
00118      assert(coltype_ != NULL);
00119 
00120      for( int i = 0; i < nc; ++i )
00121         cindarray[i] = i;
00122 
00123 #if CPX_VERSION >= 800
00124      int err = CPXchgprobtype( env_, lp, CPXPROB_MILP );
00125 #else
00126      int err = CPXchgprobtype( env_, lp, CPXPROB_MIP );
00127 #endif
00128      checkCPXerror( err, "CPXchgprobtype", "switchToMIP" );
00129 
00130      err = CPXchgctype( env_, lp, nc, cindarray, coltype_ );
00131      checkCPXerror( err, "CPXchgctype", "switchToMIP" );
00132 
00133      delete[] cindarray;
00134      probtypemip_ = true;
00135   }
00136 }
00137 
00138 void
00139 OsiCpxSolverInterface::resizeColType( int minsize )
00140 {
00141   debugMessage("OsiCpxSolverInterface::resizeColType()\n");
00142 
00143   if( minsize > coltypesize_ )
00144   {
00145      int newcoltypesize = 2*coltypesize_;
00146      if( minsize > newcoltypesize )
00147         newcoltypesize = minsize;
00148      char *newcoltype = new char[newcoltypesize];
00149 
00150      if( coltype_ != NULL )
00151      {
00152         CoinDisjointCopyN( coltype_, coltypesize_, newcoltype );
00153         delete[] coltype_;
00154      }
00155      coltype_ = newcoltype;
00156      coltypesize_ = newcoltypesize;
00157   }
00158   assert(minsize == 0 || coltype_ != NULL);
00159   assert(coltypesize_ >= minsize);
00160 }
00161 
00162 void
00163 OsiCpxSolverInterface::freeColType()
00164 {
00165   debugMessage("OsiCpxSolverInterface::freeColType()\n");
00166 
00167    if( coltypesize_ > 0 )
00168    {
00169       delete[] coltype_;
00170       coltype_ = NULL;
00171       coltypesize_ = 0;
00172    }
00173    assert(coltype_ == NULL);
00174 }
00175 
00176 
00177 //#############################################################################
00178 // Solve methods
00179 //#############################################################################
00180 
00181 void OsiCpxSolverInterface::initialSolve()
00182 {
00183   debugMessage("OsiCpxSolverInterface::initialSolve()\n");
00184 
00185   switchToLP();
00186 
00187   CPXLPptr lp = getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS );
00188 
00189   int term = CPXprimopt( env_, lp );
00190 
00191   /* If the problem is found infeasible during presolve, resolve it to get a 
00192      proper term code */
00193   if (term == CPXERR_PRESLV_INForUNBD){
00194     CPXsetintparam( env_, CPX_PARAM_PREIND, CPX_OFF );
00195     CPXprimopt( env_, lp );
00196     CPXsetintparam( env_, CPX_PARAM_PREIND, CPX_ON );
00197   }
00198 }
00199 //-----------------------------------------------------------------------------
00200 void OsiCpxSolverInterface::resolve()
00201 {
00202   debugMessage("OsiCpxSolverInterface::resolve()\n");
00203 
00204   switchToLP();
00205 
00206   CPXLPptr lp = getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS );
00207 
00208   int term = CPXdualopt( env_, lp );   
00209 
00210   /* If the problem is found infeasible during presolve, resolve it to get a 
00211      proper term code */
00212   if (term == CPXERR_PRESLV_INForUNBD){
00213     CPXsetintparam( env_, CPX_PARAM_PREIND, CPX_OFF );
00214     CPXdualopt( env_, lp );
00215     CPXsetintparam( env_, CPX_PARAM_PREIND, CPX_ON );
00216   }
00217 }
00218 //-----------------------------------------------------------------------------
00219 void OsiCpxSolverInterface::branchAndBound()
00220 {
00221   debugMessage("OsiCpxSolverInterface::branchAndBound()\n");
00222 
00223   switchToMIP();
00224 
00225   CPXLPptr lp = getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS );
00226 
00227   CPXmipopt( env_, lp );
00228 }
00229 
00230 //#############################################################################
00231 // Parameter related methods
00232 //#############################################################################
00233 
00234 bool
00235 OsiCpxSolverInterface::setIntParam(OsiIntParam key, int value)
00236 {
00237   debugMessage("OsiCpxSolverInterface::setIntParam(%d, %d)\n", key, value);
00238 
00239   bool retval = false;
00240   switch (key)
00241     {
00242     case OsiMaxNumIteration:
00243       retval = ( CPXsetintparam( env_, CPX_PARAM_ITLIM, value ) == 0 );  // ??? OsiMaxNumIteration == #Simplex-iterations ???
00244       break;
00245     case OsiMaxNumIterationHotStart:
00246       if( value >= 0 )
00247         {
00248           hotStartMaxIteration_ = value;
00249           retval = true;
00250         }
00251       else
00252         retval = false;
00253       break;
00254     case OsiLastIntParam:
00255       retval = false;
00256       break;
00257     }
00258   return retval;
00259 }
00260 
00261 //-----------------------------------------------------------------------------
00262 
00263 bool
00264 OsiCpxSolverInterface::setDblParam(OsiDblParam key, double value)
00265 {
00266   debugMessage("OsiCpxSolverInterface::setDblParam(%d, %g)\n", key, value);
00267 
00268   bool retval = false;
00269   switch (key)
00270     {
00271     case OsiDualObjectiveLimit:
00272       if( getObjSense() == +1 )
00273         retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJULIM, value ) == 0 ); // min
00274       else
00275         retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJLLIM, value ) == 0 ); // max
00276       break;
00277     case OsiPrimalObjectiveLimit:
00278       if( getObjSense() == +1 )
00279         retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJLLIM, value ) == 0 ); // min
00280       else
00281         retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJULIM, value ) == 0 ); // max
00282       break;
00283     case OsiDualTolerance:
00284       retval = ( CPXsetdblparam( env_, CPX_PARAM_EPOPT, value ) == 0 ); // ??? OsiDualTolerance == CPLEX Optimality tolerance ???
00285       break;
00286     case OsiPrimalTolerance:
00287       retval = ( CPXsetdblparam( env_, CPX_PARAM_EPRHS, value ) == 0 ); // ??? OsiPrimalTolerance == CPLEX Feasibility tolerance ???
00288       break;
00289     case OsiObjOffset:
00290       retval = OsiSolverInterface::setDblParam(key,value);
00291       break;
00292     case OsiLastDblParam:
00293       retval = false;
00294       break;
00295     }
00296   return retval;
00297 }
00298 
00299 
00300 //-----------------------------------------------------------------------------
00301 
00302 bool
00303 OsiCpxSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
00304 {
00305   debugMessage("OsiCpxSolverInterface::setStrParam(%d, %s)\n", key, value.c_str());
00306 
00307   bool retval=false;
00308   switch (key) {
00309   case OsiProbName:
00310     OsiSolverInterface::setStrParam(key,value);
00311     return retval = true;
00312   case OsiSolverName:
00313     return false;
00314   case OsiLastStrParam:
00315     return false;
00316   }
00317   return false;
00318 }
00319 
00320 //-----------------------------------------------------------------------------
00321 
00322 bool
00323 OsiCpxSolverInterface::getIntParam(OsiIntParam key, int& value) const
00324 {
00325   debugMessage("OsiCpxSolverInterface::getIntParam(%d)\n", key);
00326 
00327   bool retval = false;
00328   switch (key)
00329     {
00330     case OsiMaxNumIteration:
00331       retval = ( CPXgetintparam( env_, CPX_PARAM_ITLIM, &value ) == 0 );  // ??? OsiMaxNumIteration == #Simplex-iterations ???
00332       break;
00333     case OsiMaxNumIterationHotStart:
00334       value = hotStartMaxIteration_;
00335       retval = true;
00336       break;
00337     case OsiLastIntParam:
00338       retval = false;
00339       break;
00340     }
00341   return retval;
00342 }
00343 
00344 //-----------------------------------------------------------------------------
00345 
00346 bool
00347 OsiCpxSolverInterface::getDblParam(OsiDblParam key, double& value) const
00348 {
00349   debugMessage("OsiCpxSolverInterface::getDblParam(%d)\n", key);
00350 
00351   bool retval = false;
00352   switch (key) 
00353     {
00354     case OsiDualObjectiveLimit:
00355       if( getObjSense() == +1 )
00356         retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJULIM, &value ) == 0 ); // min
00357       else
00358         retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJLLIM, &value ) == 0 ); // max
00359       break;
00360     case OsiPrimalObjectiveLimit:
00361       if( getObjSense() == +1 )
00362         retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJLLIM, &value ) == 0 ); // min
00363       else
00364         retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJULIM, &value ) == 0 ); // max
00365       break;
00366     case OsiDualTolerance:
00367       retval = ( CPXgetdblparam( env_, CPX_PARAM_EPOPT, &value ) == 0 ); // ??? OsiDualTolerance == CPLEX Optimality tolerance ???
00368       break;
00369     case OsiPrimalTolerance:
00370       retval = ( CPXgetdblparam( env_, CPX_PARAM_EPRHS, &value ) == 0 ); // ??? OsiPrimalTolerance == CPLEX Feasibility tolerance ???
00371       break;
00372     case OsiObjOffset:
00373       retval = OsiSolverInterface::getDblParam(key, value);
00374       break;
00375     case OsiLastDblParam:
00376       retval = false;
00377       break;
00378     }
00379   return retval;
00380 }
00381 
00382 
00383 //-----------------------------------------------------------------------------
00384 
00385 bool
00386 OsiCpxSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
00387 {
00388   debugMessage("OsiCpxSolverInterface::getStrParam(%d)\n", key);
00389 
00390   switch (key) {
00391   case OsiProbName:
00392     OsiSolverInterface::getStrParam(key, value);
00393     break;
00394   case OsiSolverName:
00395     value = "cplex";
00396     break;
00397   case OsiLastStrParam:
00398     return false;
00399   }
00400 
00401   return true;
00402 }
00403 
00404 //#############################################################################
00405 // Methods returning info on how the solution process terminated
00406 //#############################################################################
00407 
00408 bool OsiCpxSolverInterface::isAbandoned() const
00409 {
00410   debugMessage("OsiCpxSolverInterface::isAbandoned()\n");
00411 
00412   int stat = CPXgetstat( env_, getMutableLpPtr() );
00413 
00414 #if CPX_VERSION >= 800
00415   return (stat == 0 || 
00416           stat == CPX_STAT_NUM_BEST || 
00417           stat == CPX_STAT_NUM_BEST || 
00418           stat == CPX_STAT_ABORT_USER || 
00419           stat == CPX_STAT_ABORT_USER || 
00420           stat == CPX_STAT_ABORT_USER);
00421 #else
00422   return (stat == 0 || 
00423           stat == CPX_NUM_BEST_FEAS || 
00424           stat == CPX_NUM_BEST_INFEAS || 
00425           stat == CPX_ABORT_FEAS || 
00426           stat == CPX_ABORT_INFEAS || 
00427           stat == CPX_ABORT_CROSSOVER);
00428 #endif
00429 }
00430 
00431 bool OsiCpxSolverInterface::isProvenOptimal() const
00432 {
00433   debugMessage("OsiCpxSolverInterface::isProvenOptimal()\n");
00434 
00435   int stat = CPXgetstat( env_, getMutableLpPtr() );
00436 
00437 #if CPX_VERSION >= 800
00438   return ((probtypemip_ == false && 
00439           (stat == CPX_STAT_OPTIMAL || stat == CPX_STAT_OPTIMAL_INFEAS)) ||
00440           probtypemip_ == true && stat == CPXMIP_OPTIMAL);
00441 #else
00442   return ((probtypemip_ == false && 
00443           (stat == CPX_OPTIMAL || stat == CPX_OPTIMAL_INFEAS)) ||
00444           probtypemip_ == true && stat == CPXMIP_OPTIMAL);
00445 #endif
00446 }
00447 
00448 bool OsiCpxSolverInterface::isProvenPrimalInfeasible() const
00449 {
00450   debugMessage("OsiCpxSolverInterface::isProvenPrimalInfeasible()\n");
00451 
00452   int stat = CPXgetstat( env_, getMutableLpPtr() );
00453 
00454 #if CPX_VERSION >= 800
00455   // In CPLEX 8, the return code is with respect
00456   // to the original problem, regardless of the algorithm used to solve it
00457   // --tkr 7/31/03
00458   return (stat == CPX_STAT_INFEASIBLE);
00459   //  return (method == CPX_ALG_PRIMAL && stat == CPX_STAT_INFEASIBLE || 
00460   //  method == CPX_ALG_DUAL && stat == CPX_STAT_UNBOUNDED);
00461 #else
00462 
00463   int method = CPXgetmethod( env_, getMutableLpPtr() );
00464 
00465   return (method == CPX_ALG_PRIMAL && stat == CPX_INFEASIBLE || 
00466           method == CPX_ALG_DUAL && stat == CPX_UNBOUNDED || 
00467           stat == CPX_ABORT_PRIM_INFEAS ||
00468           stat == CPX_ABORT_PRIM_DUAL_INFEAS);
00469 #endif
00470 }
00471 
00472 bool OsiCpxSolverInterface::isProvenDualInfeasible() const
00473 {
00474   debugMessage("OsiCpxSolverInterface::isProvenDualInfeasible()\n");
00475 
00476   int stat = CPXgetstat( env_, getMutableLpPtr() );
00477 
00478 #if CPX_VERSION >= 800
00479   // In CPLEX 8, the return code is with respect
00480   // to the original problem, regardless of the algorithm used to solve it
00481   // --tkr 7/31/03
00482   return (stat == CPX_STAT_UNBOUNDED);
00483   //return (method == CPX_ALG_PRIMAL && stat == CPX_STAT_UNBOUNDED || 
00484   //      method == CPX_ALG_DUAL && stat == CPX_STAT_INFEASIBLE);
00485 #else
00486 
00487   int method = CPXgetmethod( env_, getMutableLpPtr() );
00488 
00489   return (method == CPX_ALG_PRIMAL && stat == CPX_UNBOUNDED || 
00490           method == CPX_ALG_DUAL && stat == CPX_INFEASIBLE || 
00491           stat == CPX_ABORT_DUAL_INFEAS || 
00492           stat == CPX_ABORT_PRIM_DUAL_INFEAS);
00493 #endif
00494 }
00495 
00496 bool OsiCpxSolverInterface::isPrimalObjectiveLimitReached() const
00497 {
00498   debugMessage("OsiCpxSolverInterface::isPrimalObjectiveLimitReached()\n");
00499 
00500   int stat = CPXgetstat( env_, getMutableLpPtr() );
00501   int method = CPXgetmethod( env_, getMutableLpPtr() );
00502 
00503 #if CPX_VERSION >= 800
00504   return method == CPX_ALG_PRIMAL && stat == CPX_STAT_ABORT_OBJ_LIM;
00505 #else
00506   return method == CPX_ALG_PRIMAL && stat == CPX_OBJ_LIM;
00507 #endif
00508 }
00509 
00510 bool OsiCpxSolverInterface::isDualObjectiveLimitReached() const
00511 {
00512   debugMessage("OsiCpxSolverInterface::isDualObjectiveLimitReached()\n");
00513 
00514   int stat = CPXgetstat( env_, getMutableLpPtr() );
00515   int method = CPXgetmethod( env_, getMutableLpPtr() );
00516 
00517 #if CPX_VERSION >= 800
00518   return method == CPX_ALG_DUAL && stat == CPX_STAT_ABORT_OBJ_LIM;
00519 #else
00520   return method == CPX_ALG_DUAL && stat == CPX_OBJ_LIM;
00521 #endif
00522 }
00523 
00524 bool OsiCpxSolverInterface::isIterationLimitReached() const
00525 {
00526   debugMessage("OsiCpxSolverInterface::isIterationLimitReached()\n");
00527 
00528   int stat = CPXgetstat( env_, getMutableLpPtr() );
00529 
00530 #if CPX_VERSION >= 800
00531   return stat == CPX_STAT_ABORT_IT_LIM;
00532 #else
00533   return stat == CPX_IT_LIM_FEAS || stat == CPX_IT_LIM_INFEAS;
00534 #endif
00535 }
00536 
00537 //#############################################################################
00538 // WarmStart related methods
00539 //#############################################################################
00540 
00541 CoinWarmStart* OsiCpxSolverInterface::getWarmStart() const
00542 {
00543   debugMessage("OsiCpxSolverInterface::getWarmStart()\n");
00544 
00545   CoinWarmStartBasis* ws = NULL;
00546   int numcols = getNumCols();
00547   int numrows = getNumRows();
00548   int *cstat = new int[numcols];
00549   int *rstat = new int[numrows];
00550   int restat, i;
00551 
00552   assert(!probtypemip_);
00553 
00554   restat = CPXgetbase( env_, getMutableLpPtr(), cstat, rstat );
00555   if( restat == 0 )
00556     {
00557       ws = new CoinWarmStartBasis;
00558       ws->setSize( numcols, numrows );
00559       
00560       for( i = 0; i < numrows; ++i )
00561         {
00562           switch( rstat[i] )
00563             {
00564             case CPX_BASIC:
00565               ws->setArtifStatus( i, CoinWarmStartBasis::basic );
00566               break;
00567             case CPX_AT_LOWER:
00568               ws->setArtifStatus( i, CoinWarmStartBasis::atLowerBound );
00569               break;
00570             case CPX_AT_UPPER:
00571               ws->setArtifStatus( i, CoinWarmStartBasis::atUpperBound );
00572               break;
00573             default:  // unknown row status
00574               delete ws;
00575               ws = NULL;
00576               goto TERMINATE;
00577             }
00578         }
00579       for( i = 0; i < numcols; ++i )
00580         {
00581           switch( cstat[i] )
00582             {
00583             case CPX_BASIC:
00584               ws->setStructStatus( i, CoinWarmStartBasis::basic );
00585               break;
00586             case CPX_AT_LOWER:
00587               ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound );
00588               break;
00589             case CPX_AT_UPPER:
00590               ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound );
00591               break;
00592             case CPX_FREE_SUPER:
00593               ws->setStructStatus( i, CoinWarmStartBasis::isFree );
00594               break;
00595             default:  // unknown column status
00596               delete ws;
00597               ws = NULL;
00598               goto TERMINATE;
00599             }
00600         }
00601     }
00602  TERMINATE:
00603   delete[] cstat;
00604   delete[] rstat;
00605 
00606   return ws;
00607 }
00608 
00609 //-----------------------------------------------------------------------------
00610 
00611 bool OsiCpxSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
00612 {
00613   debugMessage("OsiCpxSolverInterface::setWarmStart(%p)\n", warmstart);
00614 
00615   const CoinWarmStartBasis* ws = dynamic_cast<const CoinWarmStartBasis*>(warmstart);
00616   int numcols, numrows, i, restat;
00617   int *cstat, *rstat;
00618   bool retval = false;
00619 
00620   if( !ws )
00621     return false;
00622 
00623   numcols = ws->getNumStructural();
00624   numrows = ws->getNumArtificial();
00625   
00626   if( numcols != getNumCols() || numrows != getNumRows() )
00627     return false;
00628 
00629   switchToLP();
00630 
00631   cstat = new int[numcols];
00632   rstat = new int[numrows];
00633   for( i = 0; i < numrows; ++i )
00634     {
00635       switch( ws->getArtifStatus( i ) )
00636         {
00637         case CoinWarmStartBasis::basic:
00638           rstat[i] = CPX_BASIC;
00639           break;
00640         case CoinWarmStartBasis::atLowerBound:
00641           rstat[i] = CPX_AT_LOWER;
00642           break;
00643         case CoinWarmStartBasis::atUpperBound:
00644           rstat[i] = CPX_AT_UPPER;
00645           break;
00646         default:  // unknown row status
00647           retval = false;
00648           goto TERMINATE;
00649         }
00650     }
00651   for( i = 0; i < numcols; ++i )
00652     {
00653       switch( ws->getStructStatus( i ) )
00654         {
00655         case CoinWarmStartBasis::basic:
00656           cstat[i] = CPX_BASIC;
00657           break;
00658         case CoinWarmStartBasis::atLowerBound:
00659           cstat[i] = CPX_AT_LOWER;
00660           break;
00661         case CoinWarmStartBasis::atUpperBound:
00662           cstat[i] = CPX_AT_UPPER;
00663           break;
00664         case CoinWarmStartBasis::isFree:
00665           cstat[i] = CPX_FREE_SUPER;
00666           break;
00667         default:  // unknown row status
00668           retval = false;
00669           goto TERMINATE;
00670         }
00671     }
00672 
00673   // *FIXME* : can this be getMutableLpPtr() ? Does any cached data change by
00674   // *FIXME* : setting warmstart? Or at least wouldn't it be sufficient to
00675   // *FIXME* : clear the cached results but not the problem data?
00676   // -> is fixed by using FREECACHED_RESULTS; only cached solution will be discarded
00677   restat = CPXcopybase( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS ), cstat, rstat );
00678   retval = (restat == 0);
00679  TERMINATE:
00680   delete[] cstat;
00681   delete[] rstat;
00682   return retval;
00683 }
00684 
00685 //#############################################################################
00686 // Hotstart related methods (primarily used in strong branching)
00687 //#############################################################################
00688 
00689 void OsiCpxSolverInterface::markHotStart()
00690 {
00691   debugMessage("OsiCpxSolverInterface::markHotStart()\n");
00692 
00693   int err;
00694   int numcols, numrows;
00695 
00696   assert(!probtypemip_);
00697 
00698   numcols = getNumCols();
00699   numrows = getNumRows();
00700   if( numcols > hotStartCStatSize_ )
00701     {
00702       delete[] hotStartCStat_;
00703       hotStartCStatSize_ = static_cast<int>( 1.2 * static_cast<double>( numcols ) ); // get some extra space for future hot starts
00704       hotStartCStat_ = new int[hotStartCStatSize_];
00705     }
00706   if( numrows > hotStartRStatSize_ )
00707     {
00708       delete[] hotStartRStat_;
00709       hotStartRStatSize_ = static_cast<int>( 1.2 * static_cast<double>( numrows ) ); // get some extra space for future hot starts
00710       hotStartRStat_ = new int[hotStartRStatSize_];
00711     }
00712   err = CPXgetbase( env_, getMutableLpPtr(), hotStartCStat_, hotStartRStat_ );
00713   checkCPXerror( err, "CPXgetbase", "markHotStart" );
00714 }
00715 
00716 void OsiCpxSolverInterface::solveFromHotStart()
00717 {
00718   debugMessage("OsiCpxSolverInterface::solveFromHotStart()\n");
00719 
00720   int err;
00721   int maxiter;
00722 
00723   switchToLP();
00724 
00725   assert( getNumCols() <= hotStartCStatSize_ );
00726   assert( getNumRows() <= hotStartRStatSize_ );
00727   err = CPXcopybase( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS ), hotStartCStat_, hotStartRStat_ );
00728   checkCPXerror( err, "CPXcopybase", "solveFromHotStart" );
00729 
00730   err = CPXgetintparam( env_, CPX_PARAM_ITLIM, &maxiter );
00731   checkCPXerror( err, "CPXgetintparam", "solveFromHotStart" );
00732   err = CPXsetintparam( env_, CPX_PARAM_ITLIM, hotStartMaxIteration_ );
00733   checkCPXerror( err, "CPXsetintparam", "solveFromHotStart" );
00734   
00735   resolve();
00736 
00737   err = CPXsetintparam( env_, CPX_PARAM_ITLIM, maxiter );
00738   checkCPXerror( err, "CPXsetintparam", "solveFromHotStart" );
00739 }
00740 
00741 void OsiCpxSolverInterface::unmarkHotStart()
00742 {
00743   debugMessage("OsiCpxSolverInterface::unmarkHotStart()\n");
00744 
00745   // ??? be lazy with deallocating memory and do nothing here, deallocate memory in the destructor
00746 }
00747 
00748 //#############################################################################
00749 // Problem information methods (original data)
00750 //#############################################################################
00751 
00752 //------------------------------------------------------------------
00753 // Get number of rows, columns, elements, ...
00754 //------------------------------------------------------------------
00755 int OsiCpxSolverInterface::getNumCols() const
00756 {
00757   debugMessage("OsiCpxSolverInterface::getNumCols()\n");
00758 
00759   return CPXgetnumcols( env_, getMutableLpPtr() );
00760 }
00761 int OsiCpxSolverInterface::getNumRows() const
00762 {
00763   debugMessage("OsiCpxSolverInterface::getNumRows()\n");
00764 
00765   return CPXgetnumrows( env_, getMutableLpPtr() );
00766 }
00767 int OsiCpxSolverInterface::getNumElements() const
00768 {
00769   debugMessage("OsiCpxSolverInterface::getNumElements()\n");
00770 
00771   return CPXgetnumnz( env_, getMutableLpPtr() );
00772 }
00773 
00774 //------------------------------------------------------------------
00775 // Get pointer to rim vectors
00776 //------------------------------------------------------------------  
00777 
00778 const double * OsiCpxSolverInterface::getColLower() const
00779 {
00780   debugMessage("OsiCpxSolverInterface::getColLower()\n");
00781 
00782   if( collower_ == NULL )
00783     {
00784       int ncols = CPXgetnumcols( env_, getMutableLpPtr() );
00785       if( ncols > 0 )
00786         {
00787           collower_ = new double[ncols];
00788           CPXgetlb( env_, getMutableLpPtr(), collower_, 0, ncols-1 );
00789         }
00790     }
00791   return collower_;
00792 }
00793 //------------------------------------------------------------------
00794 const double * OsiCpxSolverInterface::getColUpper() const
00795 {
00796   debugMessage("OsiCpxSolverInterface::getColUpper()\n");
00797 
00798   if( colupper_ == NULL )
00799     {
00800       int ncols = CPXgetnumcols( env_, getMutableLpPtr() );
00801       if( ncols > 0 )
00802         {
00803           colupper_ = new double[ncols];
00804           CPXgetub( env_, getMutableLpPtr(), colupper_, 0, ncols-1 );
00805         }
00806     }
00807   return colupper_;
00808 }
00809 //------------------------------------------------------------------
00810 const char * OsiCpxSolverInterface::getRowSense() const
00811 {
00812   debugMessage("OsiCpxSolverInterface::getRowSense()\n");
00813 
00814   if ( rowsense_==NULL )
00815     {      
00816       // rowsense is determined with rhs, so invoke rhs
00817       getRightHandSide();
00818       assert( rowsense_!=NULL || getNumRows() == 0 );
00819     }
00820   return rowsense_;
00821 }
00822 //------------------------------------------------------------------
00823 const double * OsiCpxSolverInterface::getRightHandSide() const
00824 {
00825   debugMessage("OsiCpxSolverInterface::getRightHandSide()\n");
00826 
00827   if ( rhs_==NULL )
00828     {
00829       CPXLPptr lp = getMutableLpPtr();
00830       int nrows = getNumRows();
00831       if( nrows > 0 ) 
00832         {
00833           rhs_ = new double[nrows];
00834           CPXgetrhs( env_, lp, rhs_, 0, nrows-1 );
00835           
00836           assert( rowrange_ == NULL );
00837           rowrange_ = new double[nrows];
00838           CPXgetrngval( env_, lp, rowrange_, 0, nrows-1 );
00839           
00840           assert( rowsense_ == NULL );
00841           rowsense_ = new char[nrows];
00842           CPXgetsense( env_, lp, rowsense_, 0, nrows-1 );
00843           
00844           double inf = getInfinity();
00845           int i;
00846           for ( i = 0; i < nrows; ++i ) 
00847             {  
00848               if ( rowsense_[i] != 'R' ) 
00849                 rowrange_[i]=0.0;
00850               else
00851                 {
00852                   if ( rhs_[i] <= -inf ) 
00853                     {
00854                       rowsense_[i] = 'N';
00855                       rowrange_[i] = 0.0;
00856                       rhs_[i] = 0.0;
00857                     } 
00858                   else 
00859                     {
00860                       if( rowrange_[i] >= 0.0 )
00861                         rhs_[i] = rhs_[i] + rowrange_[i];
00862                       else
00863                         rowrange_[i] = -rowrange_[i];
00864                     }
00865                 }
00866             }
00867         }
00868     }
00869   return rhs_;
00870 }
00871 //------------------------------------------------------------------
00872 const double * OsiCpxSolverInterface::getRowRange() const
00873 {
00874   debugMessage("OsiCpxSolverInterface::getRowRange()\n");
00875 
00876   if ( rowrange_==NULL ) 
00877     {
00878       // rowrange is determined with rhs, so invoke rhs
00879       getRightHandSide();
00880       assert( rowrange_!=NULL || getNumRows() == 0 );
00881     }
00882   return rowrange_;
00883 }
00884 //------------------------------------------------------------------
00885 const double * OsiCpxSolverInterface::getRowLower() const
00886 {
00887   debugMessage("OsiCpxSolverInterface::getRowLower()\n");
00888 
00889   if ( rowlower_ == NULL )
00890     {
00891       int     nrows = getNumRows();
00892       const   char    *rowsense = getRowSense();
00893       const   double  *rhs      = getRightHandSide();
00894       const   double  *rowrange = getRowRange();
00895     
00896       if ( nrows > 0 )
00897         {
00898           rowlower_ = new double[nrows];
00899           
00900           double dum1;
00901           for ( int i = 0;  i < nrows;  i++ )
00902             convertSenseToBound( rowsense[i], rhs[i], rowrange[i],
00903                                  rowlower_[i], dum1 );
00904         }
00905     }
00906   return rowlower_;
00907 }
00908 //------------------------------------------------------------------
00909 const double * OsiCpxSolverInterface::getRowUpper() const
00910 {  
00911   debugMessage("OsiCpxSolverInterface::getRowUpper()\n");
00912 
00913   if ( rowupper_ == NULL )
00914     {
00915       int     nrows = getNumRows();
00916       const   char    *rowsense = getRowSense();
00917       const   double  *rhs      = getRightHandSide();
00918       const   double  *rowrange = getRowRange();
00919       
00920       if ( nrows > 0 ) 
00921         {
00922           rowupper_ = new double[nrows];
00923           
00924           double dum1;
00925           for ( int i = 0;  i < nrows;  i++ )
00926             convertSenseToBound( rowsense[i], rhs[i], rowrange[i],
00927                                  dum1, rowupper_[i] );
00928         }
00929     }
00930   
00931   return rowupper_;
00932 }
00933 //------------------------------------------------------------------
00934 const double * OsiCpxSolverInterface::getObjCoefficients() const
00935 {
00936   debugMessage("OsiCpxSolverInterface::getObjCoefficients()\n");
00937 
00938   if ( obj_==NULL )
00939     {
00940       int ncols = CPXgetnumcols( env_, getMutableLpPtr() );
00941       if( ncols > 0 )
00942         {
00943           obj_ = new double[ncols];
00944           int err = CPXgetobj( env_, getMutableLpPtr(), obj_, 0, ncols-1 );
00945           checkCPXerror( err, "CPXgetobj", "getObjCoefficients" );
00946         }
00947     }
00948   return obj_;
00949 }
00950 //------------------------------------------------------------------
00951 double OsiCpxSolverInterface::getObjSense() const
00952 {
00953   debugMessage("OsiCpxSolverInterface::getObjSense()\n");
00954 
00955   if( CPXgetobjsen( env_, getMutableLpPtr() ) == CPX_MIN )
00956     return +1.0;
00957   else
00958     return -1.0;
00959 }
00960 
00961 //------------------------------------------------------------------
00962 // Return information on integrality
00963 //------------------------------------------------------------------
00964 
00965 bool OsiCpxSolverInterface::isContinuous( int colNumber ) const
00966 {
00967   debugMessage("OsiCpxSolverInterface::isContinuous(%d)\n", colNumber);
00968 
00969   return getCtype()[colNumber] == CPX_CONTINUOUS;
00970 }
00971 
00972 //------------------------------------------------------------------
00973 // Row and column copies of the matrix ...
00974 //------------------------------------------------------------------
00975 
00976 const CoinPackedMatrix * OsiCpxSolverInterface::getMatrixByRow() const
00977 {
00978   debugMessage("OsiCpxSolverInterface::getMatrixByRow()\n");
00979 
00980   if ( matrixByRow_ == NULL ) 
00981     {
00982       int nrows = getNumRows();
00983       int ncols = getNumCols();
00984       int nelems;
00985       int *starts   = new int   [nrows + 1];
00986       int *len      = new int   [nrows];
00987       
00988       int requiredSpace;
00989       int rc = CPXgetrows( env_, getMutableLpPtr(), 
00990                            &nelems, starts, NULL, NULL, 0, &requiredSpace,
00991                            0, nrows-1 );
00992       
00993       assert( -requiredSpace == getNumElements() );
00994       int     *indices  = new int   [-requiredSpace];
00995       double  *elements = new double[-requiredSpace]; 
00996       
00997       rc = CPXgetrows( env_, getMutableLpPtr(), 
00998                        &nelems, starts, indices, elements, -requiredSpace,
00999                        &requiredSpace, 0, nrows-1 );
01000       assert( requiredSpace == 0 );
01001             
01002       matrixByRow_ = new CoinPackedMatrix();
01003       
01004       // Should be able to pass null for length of packed matrix,
01005       // assignMatrix does not seem to allow (even though documentation
01006       // say it is possible to do this). 
01007       // For now compute the length.
01008       starts[nrows] = nelems;
01009       for ( int i = 0; i < nrows; ++i )
01010         len[i]=starts[i+1] - starts[i];
01011       
01012       matrixByRow_->assignMatrix( false /* not column ordered */,
01013                                   ncols, nrows, nelems,
01014                                   elements, indices, starts, len /*NULL*/);
01015       
01016     }
01017   return matrixByRow_;
01018 } 
01019 
01020 //------------------------------------------------------------------
01021 
01022 const CoinPackedMatrix * OsiCpxSolverInterface::getMatrixByCol() const
01023 {
01024   debugMessage("OsiCpxSolverInterface::getMatrixByCol()\n");
01025 
01026   if ( matrixByCol_ == NULL )
01027     {
01028       int nrows = getNumRows();
01029       int ncols = getNumCols();
01030       int nelems;
01031       int *starts = new int   [ncols + 1];
01032       int *len    = new int   [ncols];
01033       
01034       int requiredSpace;
01035       int rc = CPXgetcols( env_, getMutableLpPtr(), 
01036                            &nelems, starts, NULL, NULL, 0, &requiredSpace,
01037                            0, ncols-1 );
01038       assert( -requiredSpace == getNumElements() );
01039       
01040       int     *indices  = new int   [-requiredSpace];
01041       double  *elements = new double[-requiredSpace]; 
01042       
01043       rc = CPXgetcols( env_, getMutableLpPtr(), 
01044                        &nelems, starts, indices, elements, -requiredSpace,
01045                        &requiredSpace, 0, ncols-1 );
01046       assert( requiredSpace == 0);
01047       
01048       matrixByCol_ = new CoinPackedMatrix();
01049       
01050       // Should be able to pass null for length of packed matrix,
01051       // assignMatrix does not seem to allow (even though documentation
01052       // say it is possible to do this). 
01053       // For now compute the length.
01054       starts[ncols] = nelems;
01055       for ( int i = 0; i < ncols; i++ )
01056         len[i]=starts[i+1] - starts[i];
01057       
01058       matrixByCol_->assignMatrix( true /* column ordered */,
01059                                   nrows, ncols, nelems,
01060                                   elements, indices, starts, len /*NULL*/);
01061       assert( matrixByCol_->getNumCols()==ncols );
01062       assert( matrixByCol_->getNumRows()==nrows );
01063     }
01064   return matrixByCol_;
01065 } 
01066 
01067 //------------------------------------------------------------------
01068 // Get solver's value for infinity
01069 //------------------------------------------------------------------
01070 double OsiCpxSolverInterface::getInfinity() const
01071 {
01072   debugMessage("OsiCpxSolverInterface::getInfinity()\n");
01073 
01074   return CPX_INFBOUND;
01075 }
01076 
01077 //#############################################################################
01078 // Problem information methods (results)
01079 //#############################################################################
01080 
01081 // *FIXME*: what should be done if a certain vector doesn't exist???
01082 
01083 const double * OsiCpxSolverInterface::getColSolution() const
01084 {
01085   debugMessage("OsiCpxSolverInterface::getColSolution()\n");
01086 
01087   if( colsol_==NULL )
01088     {
01089       CPXLPptr lp = getMutableLpPtr();
01090       int ncols = CPXgetnumcols( env_, lp );
01091       if( ncols > 0 )
01092         {
01093           colsol_ = new double[ncols]; 
01094 
01095           if( probtypemip_ ) {
01096             int err = CPXgetmipx( env_, lp, colsol_, 0, ncols-1 );
01097             if ( err == CPXERR_NO_INT_SOLN ) 
01098               CoinFillN( colsol_, ncols, 0.0 );
01099             else
01100               checkCPXerror( err, "CPXgetmipx", "getColSolution" );
01101           } else {
01102             int err = CPXgetx( env_, lp, colsol_, 0, ncols-1 );
01103             if ( err == CPXERR_NO_SOLN ) 
01104               CoinFillN( colsol_, ncols, 0.0 );
01105             else
01106               checkCPXerror( err, "CPXgetx", "getColSolution" );
01107           }
01108         }
01109     }
01110   return colsol_;
01111 }
01112 //------------------------------------------------------------------
01113 const double * OsiCpxSolverInterface::getRowPrice() const
01114 {
01115   debugMessage("OsiCpxSolverInterface::getRowPrice()\n");
01116 
01117   if( rowsol_==NULL )
01118     {
01119       int nrows = getNumRows();
01120       if( nrows > 0 )
01121         {
01122           rowsol_ = new double[nrows];
01123           int err = CPXgetpi( env_, getMutableLpPtr(), rowsol_, 0, nrows-1 );
01124           if ( err == CPXERR_NO_SOLN ) 
01125             CoinFillN( rowsol_, nrows, 0.0 );
01126           else
01127             checkCPXerror( err, "CPXgetpi", "getRowPrice" );
01128         }
01129     }
01130   return rowsol_;
01131 }
01132 //------------------------------------------------------------------
01133 const double * OsiCpxSolverInterface::getReducedCost() const
01134 {
01135   debugMessage("OsiCpxSolverInterface::getReducedCost()\n");
01136 
01137   if( redcost_==NULL )
01138     {
01139       int ncols = CPXgetnumcols( env_, getMutableLpPtr() );
01140       if( ncols > 0 )
01141         {
01142           redcost_ = new double[ncols]; 
01143           int err = CPXgetdj( env_, getMutableLpPtr(), redcost_, 0, ncols-1 );
01144           if ( err == CPXERR_NO_SOLN ) 
01145             CoinFillN( redcost_, ncols, 0.0 );
01146           else
01147             checkCPXerror( err, "CPXgetdj", "getReducedCost" );
01148         }
01149     }
01150   return redcost_;
01151 }
01152 //------------------------------------------------------------------
01153 const double * OsiCpxSolverInterface::getRowActivity() const
01154 {
01155   debugMessage("OsiCpxSolverInterface::getRowActivity()\n");
01156 
01157   if( rowact_==NULL )
01158     {
01159       int nrows = getNumRows();
01160       if( nrows > 0 )
01161         {
01162           rowact_ = new double[nrows];
01163           if( probtypemip_ )
01164           {
01165              double *rowslack = new double[nrows];
01166              int err = CPXgetmipslack( env_, getMutableLpPtr(), rowslack, 0, nrows-1 );
01167              if ( err == CPXERR_NO_SOLN || err == CPXERR_NO_INT_SOLN )
01168                 CoinFillN( rowact_, nrows, 0.0 );
01169              else
01170              {
01171                 checkCPXerror( err, "CPXgetmipslack", "getRowActivity" );
01172                 for( int r = 0; r < nrows; ++r )
01173                    rowact_[r] = getRightHandSide()[r] + rowslack[r];
01174              }
01175              delete [] rowslack;
01176           }
01177           else
01178           {
01179              int err = CPXgetax( env_, getMutableLpPtr(), rowact_, 0, nrows-1 );
01180              if ( err == CPXERR_NO_SOLN )
01181                 CoinFillN( rowact_, nrows, 0.0 );
01182              else
01183                 checkCPXerror( err, "CPXgetax", "getRowActivity" );
01184           }
01185         }
01186     }
01187   return rowact_;
01188 }
01189 //------------------------------------------------------------------
01190 double OsiCpxSolverInterface::getObjValue() const
01191 {
01192   debugMessage("OsiCpxSolverInterface::getObjValue()\n");
01193 
01194   double objval = 0.0;
01195   int err;
01196 
01197   CPXLPptr lp = getMutableLpPtr();
01198 
01199   if( probtypemip_ ) {
01200     err = CPXgetmipobjval( env_, lp, &objval);
01201     if ( err == CPXERR_NO_INT_SOLN ) 
01202       // => return 0.0 as objective value (?? is this the correct behaviour ??)
01203       objval = 0.0;
01204     else
01205       checkCPXerror( err, "CPXgetmipobjval", "getObjValue" );
01206   } else {
01207     err = CPXgetobjval( env_, lp, &objval );
01208     if ( err == CPXERR_NO_SOLN ) 
01209       objval = 0.0;
01210     else
01211       checkCPXerror( err, "CPXgetobjval", "getObjValue" );
01212   }
01213 
01214   // Adjust objective function value by constant term in objective function
01215   double objOffset;
01216   getDblParam(OsiObjOffset,objOffset);
01217   objval = objval - objOffset;
01218 
01219   return objval;
01220 }
01221 //------------------------------------------------------------------
01222 int OsiCpxSolverInterface::getIterationCount() const
01223 {
01224   debugMessage("OsiCpxSolverInterface::getIterationCount()\n");
01225 
01226   return CPXgetitcnt( env_, getMutableLpPtr() );
01227 }
01228 //------------------------------------------------------------------
01229 std::vector<double*> OsiCpxSolverInterface::getDualRays(int maxNumRays) const
01230 {
01231   debugMessage("OsiCpxSolverInterface::getDualRays(%d)\n", maxNumRays);
01232 
01233    OsiCpxSolverInterface solver(*this);
01234 
01235    const int numcols = getNumCols();
01236    const int numrows = getNumRows();
01237    int* index = new int[CoinMax(numcols,numrows)];
01238    int i;
01239    for ( i = CoinMax(numcols,numrows)-1; i >= 0; --i) {
01240       index[i] = i;
01241    }
01242    double* obj = new double[CoinMax(numcols,2*numrows)];
01243    CoinFillN(obj, numcols, 0.0);
01244    solver.setObjCoeffSet(index, index+numcols, obj);
01245 
01246    double* clb = new double[2*numrows];
01247    double* cub = new double[2*numrows];
01248 
01249    const double plusone = 1.0;
01250    const double minusone = -1.0;
01251    const char* sense = getRowSense();
01252 
01253    const CoinPackedVectorBase** cols =
01254       new const CoinPackedVectorBase*[2*numrows];
01255    int newcols = 0;
01256    for (i = 0; i < numrows; ++i) {
01257       switch (sense[i]) {
01258       case 'L':
01259          cols[newcols++] =
01260             new CoinShallowPackedVector(1, &index[i], &minusone, false);
01261          break;
01262       case 'G':
01263          cols[newcols++] =
01264             new CoinShallowPackedVector(1, &index[i], &plusone, false);
01265          break;
01266       case 'R':
01267          cols[newcols++] =
01268             new CoinShallowPackedVector(1, &index[i], &minusone, false);
01269          cols[newcols++] =
01270             new CoinShallowPackedVector(1, &index[i], &plusone, false);
01271          break;
01272       case 'N':
01273          break;
01274       }
01275    }
01276 
01277    CoinFillN(obj, newcols, 1.0);
01278    CoinFillN(clb, newcols, 0.0);
01279    CoinFillN(cub, newcols, getInfinity());
01280 
01281    solver.addCols(newcols, cols, clb, cub, obj+numcols);
01282    delete[] index;
01283    delete[] cols;
01284    delete[] clb;
01285    delete[] cub;
01286    delete[] obj;
01287 
01288    solver.setObjSense(1.0); // minimize
01289    solver.initialSolve();
01290 
01291    const double* solverpi = getRowPrice();
01292    double* pi = new double[numrows];
01293    for ( i = numrows - 1; i >= 0; --i) {
01294       pi[i] = -solverpi[i];
01295    }
01296    return std::vector<double*>(1, pi);
01297 }
01298 
01299 //------------------------------------------------------------------
01300 std::vector<double*> OsiCpxSolverInterface::getPrimalRays(int maxNumRays) const
01301 {
01302   debugMessage("OsiCpxSolverInterface::getPrimalRays(%d)\n", maxNumRays);
01303 
01304   // *FIXME* : must write the method -LL
01305   throw CoinError("method is not yet written", "getPrimalRays",
01306                  "OsiCpxSolverInterface");
01307   return std::vector<double*>();
01308 }
01309 
01310 //#############################################################################
01311 // Problem modifying methods (rim vectors)
01312 //#############################################################################
01313 
01314 void OsiCpxSolverInterface::setObjCoeff( int elementIndex, double elementValue )
01315 {
01316   debugMessage("OsiCpxSolverInterface::setObjCoeff(%d, %g)\n", elementIndex, elementValue);
01317 
01318   int err = CPXchgobj(env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_COLUMN ), 1, &elementIndex, &elementValue);
01319   checkCPXerror(err, "CPXchgobj", "setObjCoeff");
01320 }
01321 //-----------------------------------------------------------------------------
01322 void OsiCpxSolverInterface::setObjCoeffSet(const int* indexFirst,
01323                                            const int* indexLast,
01324                                            const double* coeffList)
01325 {
01326   debugMessage("OsiCpxSolverInterface::setObjCoeffSet(%p, %p, %p)\n", indexFirst, indexLast, coeffList);
01327 
01328    const int cnt = indexLast - indexFirst;
01329    int err = CPXchgobj(env_,
01330                        getLpPtr(OsiCpxSolverInterface::FREECACHED_COLUMN), cnt,
01331                        const_cast<int*>(indexFirst),
01332                        const_cast<double*>(coeffList));
01333    checkCPXerror(err, "CPXchgobj", "setObjCoeffSet");
01334 }
01335 //-----------------------------------------------------------------------------
01336 void OsiCpxSolverInterface::setColLower(int elementIndex, double elementValue)
01337 {
01338   debugMessage("OsiCpxSolverInterface::setColLower(%d, %g)\n", elementIndex, elementValue);
01339 
01340   char c = 'L';
01341   int err = CPXchgbds( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_COLUMN ), 1, &elementIndex, &c, &elementValue );
01342   checkCPXerror( err, "CPXchgbds", "setColLower" );
01343 }
01344 //-----------------------------------------------------------------------------
01345 void OsiCpxSolverInterface::setColUpper(int elementIndex, double elementValue)
01346 {  
01347   debugMessage("OsiCpxSolverInterface::setColUpper(%d, %g)\n", elementIndex, elementValue);
01348 
01349   char c = 'U';
01350   int err = CPXchgbds( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_COLUMN ), 1, &elementIndex, &c, &elementValue );
01351   checkCPXerror( err, "CPXchgbds", "setColUpper" );
01352 } 
01353 //-----------------------------------------------------------------------------
01354 void OsiCpxSolverInterface::setColBounds( int elementIndex, double lower, double upper )
01355 {
01356   debugMessage("OsiCpxSolverInterface::setColBounds(%d, %g, %g)\n", elementIndex, lower, upper);
01357 
01358   char c[2] = { 'L', 'U' };
01359   int ind[2];
01360   double bd[2];
01361   int err;
01362 
01363   ind[0] = elementIndex;
01364   ind[1] = elementIndex;
01365   bd[0] = lower;
01366   bd[1] = upper;
01367   err = CPXchgbds( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_COLUMN ), 2, ind, c, bd );
01368   checkCPXerror( err, "CPXchgbds", "setColBounds" );
01369 }
01370 //-----------------------------------------------------------------------------
01371 void OsiCpxSolverInterface::setColSetBounds(const int* indexFirst,
01372                                             const int* indexLast,
01373                                             const double* boundList)
01374 {
01375   debugMessage("OsiCpxSolverInterface::setColSetBounds(%p, %p, %p)\n", indexFirst, indexLast, boundList);
01376 
01377    const int cnt = indexLast - indexFirst;
01378    if (cnt <= 0)
01379       return;
01380 
01381    char* c = new char[2*cnt];
01382    int* ind = new int[2*cnt];
01383    for (int i = 0; i < cnt; ++i) {
01384       register const int j = 2 * i;
01385       c[j] = 'L';
01386       c[j+1] = 'U';
01387       ind[j] = indexFirst[i];
01388       ind[j+1] = indexFirst[i];
01389    }
01390    int err = CPXchgbds( env_,
01391                         getLpPtr(OsiCpxSolverInterface::FREECACHED_COLUMN),
01392                         2*cnt, ind, c, const_cast<double*>(boundList) );
01393    checkCPXerror( err, "CPXchgbds", "setColSetBounds" );
01394    delete[] ind;
01395    delete[] c;
01396    // OsiSolverInterface::setColSetBounds( indexFirst, indexLast, boundList );
01397 }
01398 //-----------------------------------------------------------------------------
01399 void
01400 OsiCpxSolverInterface::setRowLower( int i, double elementValue )
01401 {
01402   debugMessage("OsiCpxSolverInterface::setRowLower(%d, %g)\n", i, elementValue);
01403 
01404   double rhs   = getRightHandSide()[i];
01405   double range = getRowRange()[i];
01406   char   sense = getRowSense()[i];
01407   double lower, upper;
01408 
01409   convertSenseToBound( sense, rhs, range, lower, upper );
01410   if( lower != elementValue ) {
01411       convertBoundToSense( elementValue, upper, sense, rhs, range );
01412       setRowType( i, sense, rhs, range );
01413     }
01414 }
01415 //-----------------------------------------------------------------------------
01416 void
01417 OsiCpxSolverInterface::setRowUpper( int i, double elementValue )
01418 {
01419   debugMessage("OsiCpxSolverInterface::setRowUpper(%d, %g)\n", i, elementValue);
01420 
01421   double rhs   = getRightHandSide()[i];
01422   double range = getRowRange()[i];
01423   char   sense = getRowSense()[i];
01424   double lower, upper;
01425 
01426   convertSenseToBound( sense, rhs, range, lower, upper );
01427   if( upper != elementValue ) {
01428       convertBoundToSense( lower, elementValue, sense, rhs, range );
01429       setRowType( i, sense, rhs, range );
01430   }
01431 }
01432 //-----------------------------------------------------------------------------
01433 void
01434 OsiCpxSolverInterface::setRowBounds( int elementIndex, double lower, double upper )
01435 {
01436   debugMessage("OsiCpxSolverInterface::setRowBounds(%d, %g, %g)\n", elementIndex, lower, upper);
01437 
01438   double rhs, range;
01439   char sense;
01440   
01441   convertBoundToSense( lower, upper, sense, rhs, range );
01442   setRowType( elementIndex, sense, rhs, range );
01443 }
01444 //-----------------------------------------------------------------------------
01445 void
01446 OsiCpxSolverInterface::setRowType(int i, char sense, double rightHandSide,
01447                                   double range)
01448 {
01449   debugMessage("OsiCpxSolverInterface::setRowType(%d, %c, %g, %g)\n", i, sense, rightHandSide, range);
01450 
01451   int err;
01452 
01453   if (sense == 'R') {
01454      assert( range >= 0.0 );
01455      rightHandSide -= range;
01456   }
01457   if (sense == 'N') {
01458      sense = 'R';
01459      rightHandSide = -getInfinity();
01460      range = 2*getInfinity();
01461   }
01462   err = CPXchgsense( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_ROW ),
01463                      1, &i, &sense );
01464   checkCPXerror( err, "CPXchgsense", "setRowType" );
01465   err = CPXchgrhs( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_ROW ),
01466                    1, &i, &rightHandSide );
01467   checkCPXerror( err, "CPXchgrhs", "setRowType" );
01468   err = CPXchgrngval( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_ROW ),
01469                       1, &i, &range );
01470   checkCPXerror( err, "CPXchgrngval", "setRowType" );
01471 }
01472 //-----------------------------------------------------------------------------
01473 void OsiCpxSolverInterface::setRowSetBounds(const int* indexFirst,
01474                                             const int* indexLast,
01475                                             const double* boundList)
01476 {
01477   debugMessage("OsiCpxSolverInterface::setRowSetBounds(%p, %p, %p)\n", indexFirst, indexLast, boundList);
01478 
01479    const int cnt = indexLast - indexFirst;
01480    if (cnt <= 0)
01481       return;
01482 
01483    char* sense = new char[cnt];
01484    double* rhs = new double[cnt];
01485    double* range = new double[cnt];
01486    for (int i = 0; i < cnt; ++i) {
01487       convertBoundToSense(boundList[2*i], boundList[2*i+1],
01488                           sense[i], rhs[i], range[i]);
01489    }
01490    setRowSetTypes(indexFirst, indexLast, sense, rhs, range);
01491    delete[] range;
01492    delete[] rhs;
01493    delete[] sense;
01494    
01495    //  OsiSolverInterface::setRowSetBounds( indexFirst, indexLast, boundList );
01496 }
01497 //-----------------------------------------------------------------------------
01498 void
01499 OsiCpxSolverInterface::setRowSetTypes(const int* indexFirst,
01500                                       const int* indexLast,
01501                                       const char* senseList,
01502                                       const double* rhsList,
01503                                       const double* rangeList)
01504 {
01505   debugMessage("OsiCpxSolverInterface::setRowSetTypes(%p, %p, %p, %p, %p)\n", 
01506      indexFirst, indexLast, senseList, rhsList, rangeList);
01507 
01508    const int cnt = indexLast - indexFirst;
01509    if (cnt <= 0)
01510       return;
01511 
01512    char* sense = new char[cnt];
01513    double* rhs = new double[cnt];
01514    double* range = new double[cnt];
01515    int* rangeind = new int[cnt];
01516    int rangecnt = 0;
01517    for (int i = 0; i < cnt; ++i) {
01518       sense[i] = senseList[i];
01519       rhs[i] = rhsList[i];
01520       if (sense[i] == 'R') {
01521          assert(rangeList[i] >= 0.0);
01522          rhs[i] -= rangeList[i];
01523          rangeind[rangecnt] = indexFirst[i];
01524          range[rangecnt] = rangeList[i];
01525          ++rangecnt;
01526       }
01527       if (sense[i] == 'N') {
01528          sense[i] = 'R';
01529          rhs[i] = -getInfinity();
01530          rangeind[rangecnt] = indexFirst[i];
01531          range[rangecnt] = 2*getInfinity();
01532          ++rangecnt;
01533       }
01534    }
01535    int err;
01536    err = CPXchgsense(env_, getLpPtr(OsiCpxSolverInterface::FREECACHED_ROW),
01537                      cnt, const_cast<int*>(indexFirst), sense);
01538    checkCPXerror( err, "CPXchgsense", "setRowSetTypes" );
01539    err = CPXchgrhs(env_, getLpPtr(OsiCpxSolverInterface::FREECACHED_ROW),
01540                    cnt, const_cast<int*>(indexFirst), rhs);
01541    checkCPXerror( err, "CPXchgrhs", "setRowSetTypes" );
01542    err = CPXchgrngval(env_, getLpPtr(OsiCpxSolverInterface::FREECACHED_ROW),
01543                       rangecnt, rangeind, range);
01544    checkCPXerror( err, "CPXchgrngval", "setRowSetTypes" );
01545 
01546    delete[] rangeind;
01547    delete[] range;
01548    delete[] rhs;
01549    delete[] sense;
01550 //    OsiSolverInterface::setRowSetTypes( indexFirst, indexLast, senseList,
01551 //                                    rhsList, rangeList );
01552 }
01553 //#############################################################################
01554 void
01555 OsiCpxSolverInterface::setContinuous(int index)
01556 {
01557   debugMessage("OsiCpxSolverInterface::setContinuous(%d)\n", index);
01558 
01559   assert(coltype_ != NULL);
01560   assert(coltypesize_ >= getNumCols());
01561 
01562   coltype_[index] = 'C';
01563 
01564   if ( probtypemip_ )
01565     {
01566       CPXLPptr lp = getMutableLpPtr();
01567       int err;
01568       err = CPXchgctype( env_, lp, 1, &index, &coltype_[index] );
01569       checkCPXerror( err, "CPXchgctype", "setContinuous" );
01570     }
01571 }
01572 //-----------------------------------------------------------------------------
01573 void
01574 OsiCpxSolverInterface::setInteger(int index)
01575 {
01576   debugMessage("OsiCpxSolverInterface::setInteger(%d)\n", index);
01577 
01578   assert(coltype_ != NULL);
01579   assert(coltypesize_ >= getNumCols());
01580 
01581   if( getColLower()[index] == 0.0 && getColUpper()[index] == 1.0 )
01582      coltype_[index] = 'B';
01583   else
01584      coltype_[index] = 'I';
01585 
01586   if ( probtypemip_ )
01587     {
01588       CPXLPptr lp = getMutableLpPtr();
01589       int err;
01590       err = CPXchgctype( env_, lp, 1, &index, &coltype_[index] );
01591       checkCPXerror( err, "CPXchgctype", "setInteger" );
01592     }
01593 }
01594 //-----------------------------------------------------------------------------
01595 void
01596 OsiCpxSolverInterface::setContinuous(const int* indices, int len)
01597 {
01598   debugMessage("OsiCpxSolverInterface::setContinuous(%p, %d)\n", indices, len);
01599 
01600   for( int i = 0; i < len; ++i )
01601      setContinuous(indices[i]);
01602 }
01603 //-----------------------------------------------------------------------------
01604 void
01605 OsiCpxSolverInterface::setInteger(const int* indices, int len)
01606 {
01607   debugMessage("OsiCpxSolverInterface::setInteger(%p, %d)\n", indices, len);
01608 
01609   for( int i = 0; i < len; ++i )
01610      setInteger(indices[i]);
01611 }
01612 //#############################################################################
01613 
01614 void OsiCpxSolverInterface::setObjSense(double s) 
01615 {
01616   debugMessage("OsiCpxSolverInterface::setObjSense(%g)\n", s);
01617 
01618   if( s == +1.0 )
01619     CPXchgobjsen( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS ), CPX_MIN );
01620   else
01621     CPXchgobjsen( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_RESULTS ), CPX_MAX );
01622 }
01623  
01624 //-----------------------------------------------------------------------------
01625 
01626 void OsiCpxSolverInterface::setColSolution(const double * cs) 
01627 {
01628   debugMessage("OsiCpxSolverInterface::setColSolution(%p)\n", cs);
01629 
01630   int nc = getNumCols();
01631 
01632   if( cs == NULL )
01633     freeCachedResults();
01634   else if( nc > 0 )
01635     {
01636       // If colsol isn't allocated, then allocate it
01637       if ( colsol_ == NULL )
01638         colsol_ = new double[nc];
01639         
01640       // Copy in new col solution.
01641       CoinDisjointCopyN( cs, nc, colsol_ );
01642       
01643       // CPLEX < 7.0 doesn't support setting a col solution without a row solution
01644       // -> if a row solution exists or CPLEX version >= 7, then pass into CPLEX
01645       if ( rowsol_ != NULL || cpxVersionMajor_ >= 7 )
01646         {
01647           int err = CPXcopystart( env_, getMutableLpPtr(), NULL, NULL, 
01648                                   const_cast<double*>( colsol_ ), 
01649                                   const_cast<double*>( rowsol_ ), 
01650                                   NULL, NULL );
01651           checkCPXerror( err, "CPXcopystart", "setColSolution" );
01652         }
01653     }
01654 }
01655 
01656 //-----------------------------------------------------------------------------
01657 
01658 void OsiCpxSolverInterface::setRowPrice(const double * rs) 
01659 {
01660   debugMessage("OsiCpxSolverInterface::setRowPrice(%p)\n", rs);
01661 
01662   int nr = getNumRows();
01663 
01664   if( rs == NULL )
01665     freeCachedResults();
01666   else if( nr > 0 )
01667     {
01668       // If rowsol isn't allocated, then allocate it
01669       if ( rowsol_ == NULL )
01670         rowsol_ = new double[nr];
01671 
01672       // Copy in new row solution.
01673       CoinDisjointCopyN( rs, nr, rowsol_ );
01674       
01675       // if a col solution exists, then pass into CPLEX
01676       if ( colsol_ != NULL )
01677         {
01678           int err = CPXcopystart( env_, getMutableLpPtr(), NULL, NULL, 
01679                                   const_cast<double*>( colsol_ ), 
01680                                   const_cast<double*>( rowsol_ ), 
01681                                   NULL, NULL );
01682           checkCPXerror( err, "CPXcopystart", "setRowPrice" );
01683         }
01684     }
01685 }
01686 
01687 //#############################################################################
01688 // Problem modifying methods (matrix)
01689 //#############################################################################
01690 void 
01691 OsiCpxSolverInterface::addCol(const CoinPackedVectorBase& vec,
01692                               const double collb, const double colub,   
01693                               const double obj)
01694 {
01695   debugMessage("OsiCpxSolverInterface::addCol(%p, %g, %g, %g)\n", &vec, collb, colub, obj);
01696 
01697   int nc = getNumCols();
01698   assert(coltypesize_ >= nc);
01699 
01700   resizeColType(nc + 1);
01701   coltype_[nc] = 'C';
01702 
01703   int err;
01704   int cmatbeg[2] = {0, vec.getNumElements()};
01705 
01706   err = CPXaddcols( env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ROW ),
01707                     1, vec.getNumElements(), const_cast<double*>(&obj),
01708                     cmatbeg,
01709                     const_cast<int*>(vec.getIndices()),
01710                     const_cast<double*>(vec.getElements()),
01711                     const_cast<double*>(&collb),
01712                     const_cast<double*>(&colub), NULL );
01713   checkCPXerror( err, "CPXaddcols", "addCol" );
01714 }
01715 //-----------------------------------------------------------------------------
01716 void 
01717 OsiCpxSolverInterface::addCols(const int numcols,
01718                                const CoinPackedVectorBase * const * cols,
01719                                const double* collb, const double* colub,   
01720                                const double* obj)
01721 {
01722   debugMessage("OsiCpxSolverInterface::addCols(%d, %p, %p, %p, %p)\n", numcols, cols, collb, colub, obj);
01723 
01724   int nc = getNumCols();
01725   assert(coltypesize_ >= nc);
01726 
01727   resizeColType(nc + numcols);
01728   CoinFillN(&coltype_[nc], numcols, 'C');
01729 
01730   int i;
01731   int nz = 0;
01732   for (i = 0; i < numcols; ++i)
01733     nz += cols[i]->getNumElements();
01734 
01735   int* index = new int[nz];
01736   double* elem = new double[nz];
01737   int* start = new int[numcols+1];
01738 
01739   nz = 0;
01740   start[0] = 0;
01741   for (i = 0; i < numcols; ++i) {
01742     const CoinPackedVectorBase* col = cols[i];
01743     const int len = col->getNumElements();
01744     CoinDisjointCopyN(col->getIndices(), len, index+nz);
01745     CoinDisjointCopyN(col->getElements(), len, elem+nz);
01746     nz += len;
01747     start[i+1] = nz;
01748   }
01749   int err = CPXaddcols(env_, getLpPtr(OsiCpxSolverInterface::KEEPCACHED_ROW),
01750                        numcols, nz, const_cast<double*>(obj),
01751                        start, index, elem, 
01752                        const_cast<double*>(collb),
01753                        const_cast<double*>(colub), NULL );
01754   checkCPXerror( err, "CPXaddcols", "addCols" );
01755 
01756   delete[] start;
01757   delete[] elem;
01758   delete[] index;
01759 
01760 //    int i;
01761 //    for( i = 0; i < numcols; ++i )
01762 //      addCol( *(cols[i]), collb[i], colub[i], obj[i] );
01763 }
01764 //-----------------------------------------------------------------------------
01765 void 
01766 OsiCpxSolverInterface::deleteCols(const int num, const int * columnIndices)
01767 {
01768   debugMessage("OsiCpxSolverInterface::deleteCols(%d, %p)\n", num, columnIndices);
01769 
01770   int ncols = getNumCols();
01771   int *delstat = new int[ncols];
01772   int i, err;
01773 
01774   CoinFillN(delstat, ncols, 0);
01775   for( i = 0; i < num; ++i )
01776     delstat[columnIndices[i]] = 1;
01777   err = CPXdelsetcols( env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_ROW ), delstat );
01778   checkCPXerror( err, "CPXdelsetcols", "deleteCols" );
01779 
01780   for( i = 0; i < ncols; ++i )
01781   {
01782      assert(delstat[i] <= i);
01783      if( delstat[i] != -1 )
01784         coltype_[delstat[i]] = coltype_[i];
01785   }
01786 
01787   delete[] delstat;
01788 }
01789 //-----------------------------------------------------------------------------
01790 void 
01791 OsiCpxSolverInterface::addRow(const CoinPackedVectorBase& vec,
01792                               const double rowlb, const double rowub)
01793 {
01794   debugMessage("OsiCpxSolverInterface::addRow(%p, %g, %g)\n", &vec, rowlb, rowub);
01795 
01796   char sense;
01797   double rhs, range;
01798 
01799   convertBoundToSense( rowlb, rowub, sense, rhs, range );
01800   addRow( vec, sense, rhs, range );
01801 }
01802 //-----------------------------------------------------------------------------
01803 void 
01804 OsiCpxSolverInterface::addRow(const CoinPackedVectorBase& vec,
01805                               const char rowsen, const double rowrhs,   
01806                               const double rowrng)
01807 {
01808   debugMessage("OsiCpxSolverInterface::addRow(%p, %c, %g, %g)\n", &vec, rowsen, rowrhs, rowrng);
01809 
01810   int err;
01811   int rmatbeg = 0;
01812   double rhs;
01813   double range;
01814   char sense = rowsen;
01815 
01816   switch( rowsen )
01817     {
01818     case 'R':
01819       assert( rowrng >= 0.0 );
01820       rhs = rowrhs - rowrng;
01821       range = rowrng;
01822       break;
01823     case 'N':
01824       sense = 'R';
01825       rhs   = -getInfinity();
01826       range = 2*getInfinity();
01827       break;
01828     default:
01829       rhs = rowrhs;
01830       range = 0.0;
01831     }
01832 
01833   err = CPXaddrows( env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_COLUMN ), 0, 1, vec.getNumElements(), 
01834                     &rhs,
01835                     &sense,
01836                     &rmatbeg,
01837                     const_cast<int*>(vec.getIndices()),
01838                     const_cast<double*>(vec.getElements()),
01839                     NULL, NULL );
01840   checkCPXerror( err, "CPXaddrows", "addRow" );
01841   if( rowsen == 'R' )
01842     {
01843       int row = getNumRows() - 1;
01844       err = CPXchgrngval( env_, getLpPtr( OsiCpxSolverInterface::FREECACHED_ROW ), 1, &row, &range );
01845       checkCPXerror( err, "CPXchgrngval", "addRow" );
01846     }
01847 }
01848 //-----------------------------------------------------------------------------
01849 void 
01850 OsiCpxSolverInterface::addRows(const int numrows,
01851                                const CoinPackedVectorBase * const * rows,
01852                                const double* rowlb, const double* rowub)
01853 {
01854   debugMessage("OsiCpxSolverInterface::addRows(%d, %p, %p, %p)\n", numrows, rows, rowlb, rowub);
01855 
01856   int i;
01857 
01858   for( i = 0; i < numrows; ++i )
01859     addRow( *(rows[i]), rowlb[i], rowub[i] );
01860 }
01861 //-----------------------------------------------------------------------------
01862 void 
01863 OsiCpxSolverInterface::addRows(const int numrows,
01864                                const CoinPackedVectorBase * const * rows,
01865                                const char* rowsen, const double* rowrhs,   
01866                                const double* rowrng)
01867 {
01868   debugMessage("OsiCpxSolverInterface::addRows(%d, %p, %p, %p, %p)\n", numrows, rows, rowsen, rowrhs, rowrng);
01869 
01870   int i;
01871 
01872   for( i = 0; i < numrows; ++i )
01873     addRow( *(rows[i]), rowsen[i], rowrhs[i], rowrng[i] );
01874 }
01875 //-----------------------------------------------------------------------------
01876 void 
01877 OsiCpxSolverInterface::deleteRows(const int num, const int * rowIndices)
01878 {
01879   debugMessage("OsiCpxSolverInterface::deleteRows(%d, %p)\n", num, rowIndices);
01880 
01881   int nrows = getNumRows();
01882   int *delstat = new int[nrows];
01883   int i, err;
01884 
01885   CoinFillN( delstat, nrows, 0 );
01886   for( i = 0; i < num; ++i )
01887     delstat[rowIndices[i]] = 1;
01888   err = CPXdelsetrows( env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_COLUMN ), delstat );
01889   checkCPXerror( err, "CPXdelsetrows", "deleteRows" );
01890   delete[] delstat;
01891 }
01892 
01893 //#############################################################################
01894 // Methods to input a problem
01895 //#############################################################################
01896 
01897 void
01898 OsiCpxSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
01899                                     const double* collb, const double* colub,
01900                                     const double* obj,
01901                                     const double* rowlb, const double* rowub )
01902 {
01903   debugMessage("OsiCpxSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p)\n", &matrix, collb, colub, obj, rowlb, rowub);
01904 
01905   const double inf = getInfinity();
01906   
01907   int nrows = matrix.getNumRows();
01908   char   * rowSense = new char  [nrows];
01909   double * rowRhs   = new double[nrows];
01910   double * rowRange = new double[nrows];
01911   
01912   int i;
01913   for ( i = nrows - 1; i >= 0; --i )
01914     {
01915       const double lower = rowlb ? rowlb[i] : -inf;
01916       const double upper = rowub ? rowub[i] : inf;
01917       convertBoundToSense( lower, upper, rowSense[i], rowRhs[i], rowRange[i] );
01918     }
01919 
01920   loadProblem( matrix, collb, colub, obj, rowSense, rowRhs, rowRange ); 
01921   delete [] rowSense;
01922   delete [] rowRhs;
01923   delete [] rowRange;
01924 }
01925                             
01926 //-----------------------------------------------------------------------------
01927 
01928 void
01929 OsiCpxSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
01930                                       double*& collb, double*& colub,
01931                                       double*& obj,
01932                                       double*& rowlb, double*& rowub )
01933 {
01934   debugMessage("OsiCpxSolverInterface::assignProblem()\n");
01935 
01936   loadProblem( *matrix, collb, colub, obj, rowlb, rowub );
01937   delete matrix;   matrix = 0;
01938   delete[] collb;  collb = 0;
01939   delete[] colub;  colub = 0;
01940   delete[] obj;    obj = 0;
01941   delete[] rowlb;  rowlb = 0;
01942   delete[] rowub;  rowub = 0;
01943 }
01944 
01945 //-----------------------------------------------------------------------------
01946 
01947 void
01948 OsiCpxSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
01949                                     const double* collb, const double* colub,
01950                                     const double* obj,
01951                                     const char* rowsen, const double* rowrhs,
01952                                     const double* rowrng )
01953 {
01954   debugMessage("OsiCpxSolverInterface::loadProblem(%p, %p, %p, %p, %p, %p, %p)\n",
01955      &matrix, collb, colub, obj, rowsen, rowrhs, rowrng);
01956 
01957   int nc=matrix.getNumCols();
01958   int nr=matrix.getNumRows();
01959 
01960   if( nr == 0 || nc == 0 )   // empty LP?
01961     gutsOfDestructor();      // -> kill old LP
01962   else
01963     {
01964       assert( rowsen != NULL );
01965       assert( rowrhs != NULL );
01966 
01967       int i;
01968       
01969       // Set column values to defaults if NULL pointer passed
01970       double * clb;  
01971       double * cub;
01972       double * ob;
01973       double * rr = NULL;
01974       double * rhs;
01975       if ( collb!=NULL )
01976         clb=const_cast<double*>(collb);
01977       else
01978         {
01979           clb = new double[nc];
01980           CoinFillN(clb, nc, 0.0);
01981         }
01982       if ( colub!=NULL )
01983         cub=const_cast<double*>(colub);
01984       else
01985         {
01986           cub = new double[nc];
01987           CoinFillN(cub, nc, getInfinity());
01988         }
01989       if ( obj!=NULL )
01990         ob=const_cast<double*>(obj);
01991       else
01992         {
01993           ob = new double[nc];
01994           CoinFillN(ob, nc, 0.0);
01995         }
01996       if ( rowrng != NULL )
01997         {
01998           rhs = new double[nr];
01999           rr = new double[nr];
02000           for ( i=0; i<nr; i++ )
02001             {
02002               if (rowsen[i] == 'R')
02003                 {
02004                   if( rowrng[i] >= 0 )
02005                     {
02006                       rhs[i] = rowrhs[i] - rowrng[i];
02007                       rr[i] = rowrng[i];
02008                     }
02009                   else
02010                     {
02011                       rhs[i] = rowrhs[i];
02012                       rr[i] = -rowrng[i];
02013                     }
02014                 } 
02015               else
02016                 {
02017                   rhs[i] = rowrhs[i];
02018                   rr[i] = 0.0;
02019                 }
02020             }
02021         } 
02022       else
02023         rhs = const_cast<double*>(rowrhs);
02024       
02025       bool freeMatrixRequired = false;
02026       CoinPackedMatrix * m = NULL;
02027       if ( !matrix.isColOrdered() ) 
02028         {
02029           m = new CoinPackedMatrix();
02030           m->reverseOrderedCopyOf(matrix);
02031           freeMatrixRequired = true;
02032         } 
02033       else 
02034         m = const_cast<CoinPackedMatrix *>(&matrix);
02035       
02036       assert( nc == m->getNumCols() );
02037       assert( nr == m->getNumRows() );
02038       assert( m->isColOrdered() ); 
02039       
02040       int objDirection = CPXgetobjsen( env_, getMutableLpPtr() );
02041       
02042       int err = CPXcopylp( env_, getLpPtr(), 
02043                            nc, nr,
02044                            // Leave ObjSense alone(set to current value).
02045                            objDirection,
02046                            ob, 
02047                            rhs,
02048                            const_cast<char *>(rowsen),
02049                            const_cast<int *>(m->getVectorStarts()),
02050                            const_cast<int *>(m->getVectorLengths()),
02051                            const_cast<int *>(m->getIndices()),
02052                            const_cast<double *>(m->getElements()),
02053                            const_cast<double *>(clb), 
02054                            const_cast<double *>(cub), 
02055                            rr );
02056       checkCPXerror( err, "CPXcopylp", "loadProblem" );
02057             
02058       if ( collb == NULL )
02059         delete[] clb;
02060       if ( colub == NULL ) 
02061         delete[] cub;
02062       if ( obj   == NULL )
02063         delete[] ob;
02064       if ( rowrng != NULL ) {
02065         delete[] rr;
02066         delete[] rhs;
02067       }
02068       
02069       if ( freeMatrixRequired ) 
02070         delete m;
02071 
02072       resizeColType(nc);
02073       CoinFillN(coltype_, nc, 'C');
02074     }
02075 }
02076    
02077 //-----------------------------------------------------------------------------
02078 
02079 void
02080 OsiCpxSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
02081                                       double*& collb, double*& colub,
02082                                       double*& obj,
02083                                       char*& rowsen, double*& rowrhs,
02084                                       double*& rowrng )
02085 {
02086   debugMessage("OsiCpxSolverInterface::assignProblem()\n");
02087 
02088    loadProblem( *matrix, collb, colub, obj, rowsen, rowrhs, rowrng );
02089    delete matrix;   matrix = 0;
02090    delete[] collb;  collb = 0;
02091    delete[] colub;  colub = 0;
02092    delete[] obj;    obj = 0;
02093    delete[] rowsen; rowsen = 0;
02094    delete[] rowrhs; rowrhs = 0;
02095    delete[] rowrng; rowrng = 0;
02096 }
02097 
02098 //-----------------------------------------------------------------------------
02099 
02100 void
02101 OsiCpxSolverInterface::loadProblem(const int numcols, const int numrows,
02102                                    const int* start, const int* index,
02103                                    const double* value,
02104                                    const double* collb, const double* colub,   
02105                                    const double* obj,
02106                                    const double* rowlb, const double* rowub )
02107 {
02108   debugMessage("OsiCpxSolverInterface::loadProblem()\n");
02109 
02110   const double inf = getInfinity();
02111   
02112   char   * rowSense = new char  [numrows];
02113   double * rowRhs   = new double[numrows];
02114   double * rowRange = new double[numrows];
02115   
02116   for ( int i = numrows - 1; i >= 0; --i ) {
02117     const double lower = rowlb ? rowlb[i] : -inf;
02118     const double upper = rowub ? rowub[i] : inf;
02119     convertBoundToSense( lower, upper, rowSense[i], rowRhs[i], rowRange[i] );
02120   }
02121 
02122   loadProblem(numcols, numrows, start, index, value, collb, colub, obj,
02123               rowSense, rowRhs, rowRange);
02124   delete [] rowSense;
02125   delete [] rowRhs;
02126   delete [] rowRange;
02127 
02128 }
02129 
02130 //-----------------------------------------------------------------------------
02131 
02132 void
02133 OsiCpxSolverInterface::loadProblem(const int numcols, const int numrows,
02134                                    const int* start, const int* index,
02135                                    const double* value,
02136                                    const double* collb, const double* colub,   
02137                                    const double* obj,
02138                                    const char* rowsen, const double* rowrhs,
02139                                    const double* rowrng )
02140 {
02141   debugMessage("OsiCpxSolverInterface::loadProblem(%d, %d, %p, %p, %p, %p, %p, %p, %p, %p, %p)\n",
02142      numcols, numrows, start, index, value, collb, colub, obj, rowsen, rowrhs, rowrng);
02143 
02144   const int nc = numcols;
02145   const int nr = numrows;
02146 
02147   if( nr == 0 || nc == 0 ) {
02148     // empty LP? -> kill old LP
02149     gutsOfDestructor();
02150     return;
02151   }
02152 
02153   assert( rowsen != NULL );
02154   assert( rowrhs != NULL );
02155       
02156   int i;
02157       
02158   // Set column values to defaults if NULL pointer passed
02159   int * len = new int[nc];
02160   double * clb = new double[nc];  
02161   double * cub = new double[nc];  
02162   double * ob = new double[nc];  
02163   double * rr = new double[nr];
02164   double * rhs = new double[nr];
02165   char * sen = new char[nr];
02166   
02167   for (i = 0; i < nc; ++i) {
02168     len[i] = start[i+1] - start[i];
02169   }
02170 
02171   if ( collb != NULL )
02172     CoinDisjointCopyN(collb, nc, clb);
02173   else
02174     CoinFillN(clb, nc, 0.0);
02175 
02176   if ( colub!=NULL )
02177     CoinDisjointCopyN(colub, nc, cub);
02178   else
02179     CoinFillN(cub, nc, getInfinity());
02180   
02181   if ( obj!=NULL )
02182     CoinDisjointCopyN(obj, nc, ob);
02183   else
02184     CoinFillN(ob, nc, 0.0);
02185   
02186   if ( rowrng != NULL ) {
02187     for ( i=0; i<nr; i++ ) {
02188       if (rowsen[i] == 'R') {
02189         if ( rowrng[i] >= 0 ) {
02190           rhs[i] = rowrhs[i] - rowrng[i];
02191           rr[i] = rowrng[i];
02192         } else {
02193           rhs[i] = rowrhs[i];
02194           rr[i] = -rowrng[i];
02195         }
02196       } else {
02197         rhs[i] = rowrhs[i];
02198         rr[i] = 0.0;
02199       }
02200     }
02201   } else {
02202     CoinDisjointCopyN(rowrhs, nr, rhs);
02203   }
02204 
02205   CoinDisjointCopyN(rowsen, nr, sen);
02206   
02207   int objDirection = CPXgetobjsen( env_, getMutableLpPtr() );
02208       
02209   int err = CPXcopylp( env_, getLpPtr(), 
02210                        nc, nr,
02211                        // Leave ObjSense alone(set to current value).
02212                        objDirection, ob, rhs, sen,
02213                        const_cast<int *>(start), 
02214                        len, const_cast<int *>(index), 
02215                        const_cast<double *>(value),
02216                        clb, cub, rr);
02217 
02218   checkCPXerror( err, "CPXcopylp", "loadProblem" );
02219   
02220   delete[] len;
02221   delete[] clb;
02222   delete[] cub;
02223   delete[] ob;
02224   delete[] rr;
02225   delete[] rhs;
02226   delete[] sen;
02227 
02228   resizeColType(nc);
02229   CoinFillN(coltype_, nc, 'C');
02230 }
02231  
02232 //-----------------------------------------------------------------------------
02233 // Read mps files
02234 //-----------------------------------------------------------------------------
02235 int OsiCpxSolverInterface::readMps( const char * filename,
02236                                      const char * extension )
02237 {
02238   debugMessage("OsiCpxSolverInterface::readMps(%s, %s)\n", filename, extension);
02239 
02240 #if 0
02241   std::string f(filename);
02242   std::string e(extension);
02243   std::string fullname = f + "." + e;
02244   int err = CPXreadcopyprob( env_, getLpPtr(), const_cast<char*>( fullname.c_str() ), NULL );
02245   checkCPXerror( err, "CPXreadcopyprob", "readMps" );
02246 #endif
02247   // just call base class method
02248   return OsiSolverInterface::readMps(filename,extension);
02249 }
02250 
02251 
02252 //-----------------------------------------------------------------------------
02253 // Write mps files
02254 //-----------------------------------------------------------------------------
02255 void OsiCpxSolverInterface::writeMps( const char * filename,
02256                                       const char * extension,
02257                                       double objSense ) const
02258 {
02259   debugMessage("OsiCpxSolverInterface::writeMps(%s, %s, %g)\n", filename, extension, objSense);
02260 
02261   // *FIXME* : this will not output ctype information to the MPS file
02262   char filetype[4] = "MPS";
02263   std::string f(filename);
02264   std::string e(extension);
02265   std::string fullname = f + "." + e;
02266   int err = CPXwriteprob( env_, getMutableLpPtr(), const_cast<char*>( fullname.c_str() ), filetype );
02267   checkCPXerror( err, "CPXwriteprob", "writeMps" );
02268 }
02269 
02270 //#############################################################################
02271 // CPX specific public interfaces
02272 //#############################################################################
02273 
02274 CPXENVptr OsiCpxSolverInterface::getEnvironmentPtr()
02275 {
02276   assert( env_ != NULL );
02277   return env_;
02278 }
02279 
02280 CPXLPptr OsiCpxSolverInterface::getLpPtr( int keepCached )
02281 {
02282   freeCachedData( keepCached );
02283   return getMutableLpPtr();
02284 }
02285 
02286 //-----------------------------------------------------------------------------
02287 
02288 const char * OsiCpxSolverInterface::getCtype() const
02289 {
02290   debugMessage("OsiCpxSolverInterface::getCtype()\n");
02291 
02292   return coltype_;
02293 }
02294 
02295 //#############################################################################
02296 // Static instance counter methods
02297 //#############################################################################
02298 
02299 void OsiCpxSolverInterface::incrementInstanceCounter()
02300 {
02301   if ( numInstances_ == 0 )
02302     {
02303       int err;
02304 
02305 #if CPX_VERSION >= 800
02306       env_ = CPXopenCPLEX( &err );
02307 #else
02308       env_ = CPXopenCPLEXdevelop( &err );
02309 #endif
02310 
02311       checkCPXerror( err, "CPXopenCPLEXdevelop", "incrementInstanceCounter" );
02312       assert( env_ != NULL );
02313 #ifndef NDEBUG
02314       CPXsetintparam( env_, CPX_PARAM_SCRIND, CPX_ON ); // for testing purposes
02315 #endif
02316       //char logfileName[]="cplex.log";
02317       //char filemode[]="a+";
02318       //CPXFILEptr fp = CPXfopen( logfileName, filemode );
02319       //CPXsetlogfile( env_, fp );
02320       err = sscanf( CPXversion( env_ ), "%d.%d.%d", &cpxVersionMajor_, &cpxVersionMinor_, &cpxVersionMinorMinor_ );
02321       assert( err == 3 );
02322     }
02323   numInstances_++;
02324 }
02325 
02326 //-----------------------------------------------------------------------------
02327 
02328 void OsiCpxSolverInterface::decrementInstanceCounter()
02329 {
02330   assert( numInstances_ != 0 );
02331   numInstances_--;
02332   if ( numInstances_ == 0 )
02333     {
02334       int err = CPXcloseCPLEX( &env_ );
02335       checkCPXerror( err, "CPXcloseCPLEX", "decrementInstanceCounter" );
02336       env_ = NULL;
02337     }
02338 }
02339 
02340 //-----------------------------------------------------------------------------
02341 
02342 unsigned int OsiCpxSolverInterface::getNumInstances()
02343 {
02344   return numInstances_;
02345 }
02346 
02347 //#############################################################################
02348 // Constructors, destructors clone and assignment
02349 //#############################################################################
02350 
02351 //-------------------------------------------------------------------
02352 // Default Constructor 
02353 //-------------------------------------------------------------------
02354 OsiCpxSolverInterface::OsiCpxSolverInterface()
02355   : OsiSolverInterface(),
02356     lp_(NULL),
02357     hotStartCStat_(NULL),
02358     hotStartCStatSize_(0),
02359     hotStartRStat_(NULL),
02360     hotStartRStatSize_(0),
02361     hotStartMaxIteration_(1000000), // ??? default iteration limit for strong branching is large
02362     obj_(NULL),
02363     collower_(NULL),
02364     colupper_(NULL),
02365     rowsense_(NULL),
02366     rhs_(NULL),
02367     rowrange_(NULL),
02368     rowlower_(NULL),
02369     rowupper_(NULL),
02370     colsol_(NULL),
02371     rowsol_(NULL),
02372     redcost_(NULL),
02373     rowact_(NULL),
02374     matrixByRow_(NULL),
02375     matrixByCol_(NULL),
02376     coltype_(NULL),
02377     coltypesize_(0),
02378     probtypemip_(false)
02379 {
02380   debugMessage("OsiCpxSolverInterface::OsiCpxSolverInterface()\n");
02381 
02382   incrementInstanceCounter();
02383   gutsOfConstructor();
02384 }
02385 
02386 
02387 //----------------------------------------------------------------
02388 // Clone
02389 //----------------------------------------------------------------
02390 OsiSolverInterface * OsiCpxSolverInterface::clone(bool copyData) const
02391 {
02392   debugMessage("OsiCpxSolverInterface::clone(%d)\n", copyData);
02393 
02394   return( new OsiCpxSolverInterface( *this ) );
02395 }
02396 
02397 //-------------------------------------------------------------------
02398 // Copy constructor 
02399 //-------------------------------------------------------------------
02400 OsiCpxSolverInterface::OsiCpxSolverInterface( const OsiCpxSolverInterface & source )
02401   : OsiSolverInterface(source),
02402     lp_(NULL),
02403     hotStartCStat_(NULL),
02404     hotStartCStatSize_(0),
02405     hotStartRStat_(NULL),
02406     hotStartRStatSize_(0),
02407     hotStartMaxIteration_(source.hotStartMaxIteration_),
02408     obj_(NULL),
02409     collower_(NULL),
02410     colupper_(NULL),
02411     rowsense_(NULL),
02412     rhs_(NULL),
02413     rowrange_(NULL),
02414     rowlower_(NULL),
02415     rowupper_(NULL),
02416     colsol_(NULL),
02417     rowsol_(NULL),
02418     redcost_(NULL),
02419     rowact_(NULL),
02420     matrixByRow_(NULL),
02421     matrixByCol_(NULL),
02422     coltype_(NULL),
02423     coltypesize_(0),
02424     probtypemip_(false)
02425 {
02426   debugMessage("OsiCpxSolverInterface::OsiCpxSolverInterface(%p)\n", &source);
02427 
02428   incrementInstanceCounter();  
02429   gutsOfConstructor();
02430   gutsOfCopy( source );
02431 }
02432 
02433 
02434 //-------------------------------------------------------------------
02435 // Destructor 
02436 //-------------------------------------------------------------------
02437 OsiCpxSolverInterface::~OsiCpxSolverInterface()
02438 {
02439   debugMessage("OsiCpxSolverInterface::~OsiCpxSolverInterface()\n");
02440 
02441   gutsOfDestructor();
02442   decrementInstanceCounter();
02443 }
02444 
02445 //----------------------------------------------------------------
02446 // Assignment operator 
02447 //-------------------------------------------------------------------
02448 OsiCpxSolverInterface& OsiCpxSolverInterface::operator=( const OsiCpxSolverInterface& rhs )
02449 {
02450   debugMessage("OsiCpxSolverInterface::operator=(%p)\n", &rhs);
02451 
02452   if (this != &rhs)
02453     {    
02454       OsiSolverInterface::operator=( rhs );
02455       gutsOfDestructor();
02456       gutsOfConstructor();
02457       if ( rhs.lp_ !=NULL )
02458         gutsOfCopy( rhs );
02459     }
02460   return *this;
02461 }
02462 
02463 //#############################################################################
02464 // Applying cuts
02465 //#############################################################################
02466 
02467 void OsiCpxSolverInterface::applyColCut( const OsiColCut & cc )
02468 {
02469   debugMessage("OsiCpxSolverInterface::applyColCut(%p)\n", &cc);
02470 
02471   const double * cplexColLB = getColLower();
02472   const double * cplexColUB = getColUpper();
02473   const CoinPackedVector & lbs = cc.lbs();
02474   const CoinPackedVector & ubs = cc.ubs();
02475   int i;
02476 
02477   for( i = 0; i < lbs.getNumElements(); ++i ) 
02478     if ( lbs.getElements()[i] > cplexColLB[lbs.getIndices()[i]] )
02479       setColLower( lbs.getIndices()[i], lbs.getElements()[i] );
02480   for( i = 0; i < ubs.getNumElements(); ++i )
02481     if ( ubs.getElements()[i] < cplexColUB[ubs.getIndices()[i]] )
02482       setColUpper( ubs.getIndices()[i], ubs.getElements()[i] );
02483 }
02484 
02485 //-----------------------------------------------------------------------------
02486 
02487 void OsiCpxSolverInterface::applyRowCut( const OsiRowCut & rowCut )
02488 {
02489   debugMessage("OsiCpxSolverInterface::applyRowCut(%p)\n", &rowCut);
02490 
02491   int err = 0;
02492   double rhs = 0.0;
02493   double rng = 0.0;
02494   char sns;
02495   double lb = rowCut.lb();
02496   double ub = rowCut.ub();
02497   if( lb <= -getInfinity() && ub >= getInfinity() )   // free constraint
02498     {
02499       rhs = -getInfinity();
02500       rng = 2*getInfinity();  // CPLEX doesn't support free constraints
02501       sns = 'R';           // -> implement them as ranged rows with infinite bounds
02502     }
02503   else if( lb <= -getInfinity() )  // <= constraint
02504     {
02505       rhs = ub;
02506       sns = 'L';
02507     }
02508   else if( ub >= getInfinity() )  // >= constraint
02509     {
02510       rhs = lb;
02511       sns = 'G';
02512     }
02513   else if( ub == lb )  // = constraint
02514     {
02515       rhs = ub;
02516       sns = 'E';
02517     }
02518   else  // range constraint
02519     {
02520       rhs = lb;
02521       rng = ub - lb;
02522       sns = 'R';
02523     }
02524   int rmatbeg = 0;
02525   err = CPXaddrows( env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_COLUMN ), 0, 1, rowCut.row().getNumElements(),
02526                     &rhs, &sns, &rmatbeg, 
02527                     const_cast<int*>( rowCut.row().getIndices() ), 
02528                     const_cast<double*>( rowCut.row().getElements() ),
02529                     NULL, NULL );
02530   checkCPXerror( err, "CPXaddrows", "applyRowCut" );
02531   if( sns == 'R' )
02532     {
02533       err = CPXchgcoef( env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_COLUMN ), 
02534                         CPXgetnumrows(env_, getLpPtr( OsiCpxSolverInterface::KEEPCACHED_COLUMN ))-1,
02535                         -2, rng );
02536       checkCPXerror( err, "CPXchgcoef", "applyRowCut" );
02537     }
02538 }
02539 
02540 //#############################################################################
02541 // Private methods (non-static and static) and static data
02542 //#############################################################################
02543 
02544 //------------------------------------------------------------------
02545 // Static data
02546 //------------------------------------------------------------------      
02547 CPXENVptr OsiCpxSolverInterface::env_ = NULL;
02548 
02549 int OsiCpxSolverInterface::cpxVersionMajor_ = 0;
02550 int OsiCpxSolverInterface::cpxVersionMinor_ = 0;
02551 int OsiCpxSolverInterface::cpxVersionMinorMinor_ = 0;
02552 unsigned int OsiCpxSolverInterface::numInstances_ = 0;
02553  
02554 //-------------------------------------------------------------------
02555 // Get pointer to CPXLPptr.
02556 // const methods should use getMutableLpPtr().
02557 // non-const methods should use getLpPtr().
02558 //------------------------------------------------------------------- 
02559 CPXLPptr OsiCpxSolverInterface::getMutableLpPtr() const
02560 {
02561   if ( lp_ == NULL )
02562     {
02563       int err;
02564       assert(env_ != NULL);
02565 #if 0
02566       //char pn[] = "OSI_CPLEX";
02567       lp_ = CPXcreateprob( env_, &err, pn );
02568 #else
02569       std::string pn;
02570       getStrParam(OsiProbName,pn);
02571       lp_ = CPXcreateprob( env_, &err, const_cast<char*>(pn.c_str()) );
02572 #endif
02573       checkCPXerror( err, "CPXcreateprob", "getMutableLpPtr" );
02574 //      err = CPXchgprobtype(env_,lp_,CPXPROB_LP);
02575 //      checkCPXerror( err, "CPXchgprobtype", "getMutableLpPtr" );
02576       assert( lp_ != NULL ); 
02577     }
02578   return lp_;
02579 }
02580 
02581 //-------------------------------------------------------------------
02582 
02583 void OsiCpxSolverInterface::gutsOfCopy( const OsiCpxSolverInterface & source )
02584 {
02585   // Set Objective Sense
02586   setObjSense(source.getObjSense());
02587 
02588   // Set Rim and constraints
02589   const double* obj = source.getObjCoefficients();
02590   const double* rhs = source.getRightHandSide();
02591   const char* sense = source.getRowSense();
02592   const CoinPackedMatrix * cols = source.getMatrixByCol();
02593   const double* lb = source.getColLower();
02594   const double* ub = source.getColUpper();
02595   loadProblem(*cols,lb,ub,obj,sense,rhs,source.getRowRange());
02596 
02597   // Set MIP information
02598   resizeColType(source.coltypesize_);
02599   CoinDisjointCopyN( source.coltype_, source.coltypesize_, coltype_ );
02600   
02601   // Set Solution
02602   setColSolution(source.getColSolution());
02603   setRowPrice(source.getRowPrice());
02604 
02605   // Should also copy row and col names.
02606 #if 0
02607   char** cname = new char*[numcols];
02608   char* cnamestore = NULL;
02609   int surplus;
02610   err = CPXgetcolname( env_, source.lp_, cname, NULL, 0, &surplus, 0, numcols-1 );
02611   if( err != CPXERR_NO_NAMES )
02612     {
02613       cnamestore = new char[-surplus];
02614       err = CPXgetcolname( env_, source.lp_, cname, cnamestore, -surplus, &surplus, 0, numcols-1 );
02615       checkCPXerror( err, "CPXgetcolname", "gutsOfCopy" );
02616       assert( surplus == 0 );
02617     }
02618   else
02619     {
02620       delete [] cname;
02621       cname = NULL;
02622     }
02623   
02624   char** rname = new char*[numrows];
02625   char* rnamestore = NULL;
02626   err = CPXgetrowname( env_, source.lp_, rname, NULL, 0, &surplus, 0, numrows-1 );
02627   if( err != CPXERR_NO_NAMES )
02628     {
02629       rnamestore = new char[-surplus];
02630       err = CPXgetrowname( env_, source.lp_, rname, rnamestore, -surplus, &surplus, 0, numrows-1 );
02631       checkCPXerror( err, "CPXgetrowname", "gutsOfCopy" );
02632       assert( surplus == 0 );
02633     }
02634   else
02635     {
02636       delete [] rname;
02637       rname = NULL;
02638     }
02639 
02640   err = CPXcopylpwnames( env_, getLpPtr(), 
02641                          numcols, numrows, objsen, 
02642                          const_cast<double *>(obj), 
02643                          const_cast<double *>(rhs), 
02644                          const_cast<char *>(sense),
02645                          const_cast<int *>(cols->vectorStarts()),
02646                          const_cast<int *>(cols->vectorLengths()),
02647                          const_cast<int *>(cols->indices()),
02648                          const_cast<double *>(cols->elements()),
02649                          const_cast<double *>(lb), 
02650                          const_cast<double *>(ub), 
02651                          rng, 
02652                          cname, rname);
02653   checkCPXerror( err, "CPXcopylpwnames", "gutsOfCopy" );
02654   
02655   if( rname != NULL )
02656     {
02657       delete [] rnamestore;
02658       delete [] rname;
02659     }
02660   if( cname != NULL )
02661     {
02662       delete [] cnamestore;
02663       delete [] cname;
02664     }
02665   delete [] rng;
02666 #endif
02667  
02668 }
02669 
02670 //-------------------------------------------------------------------
02671 void OsiCpxSolverInterface::gutsOfConstructor()
02672 {  
02673 #if 0
02674   // CPXcreateprob was moved to getLpPtr() method.
02675   int err;
02676   lp_ = CPXcreateprob( env_, &err, "OSI_CPLEX" );
02677   checkCPXerror( err, "CPXcreateprob", "gutsOfConstructor" );
02678 //  err = CPXchgprobtype(env_,lp_,CPXPROB_LP);
02679 //  checkCPXerror( err, "CPXchgprobtype", "getMutableLpPtr" );
02680   assert( lp_ != NULL );
02681 #endif
02682 }
02683 
02684 //-------------------------------------------------------------------
02685 void OsiCpxSolverInterface::gutsOfDestructor()
02686 {  
02687   if ( lp_ != NULL )
02688     {
02689       int err = CPXfreeprob( env_, &lp_ );
02690       checkCPXerror( err, "CPXfreeprob", "gutsOfDestructor" );
02691       lp_=NULL;
02692       freeAllMemory();
02693     }
02694   assert( lp_==NULL );
02695   assert( obj_==NULL );
02696   assert( collower_==NULL );
02697   assert( colupper_==NULL );
02698   assert( rowsense_==NULL );
02699   assert( rhs_==NULL );
02700   assert( rowrange_==NULL );
02701   assert( rowlower_==NULL );
02702   assert( rowupper_==NULL );
02703   assert( colsol_==NULL );
02704   assert( rowsol_==NULL );
02705   assert( redcost_==NULL );
02706   assert( rowact_==NULL );
02707   assert( matrixByRow_==NULL );
02708   assert( matrixByCol_==NULL );
02709   assert( coltype_==NULL );
02710   assert( coltypesize_==0 );
02711 }
02712 
02713 //-------------------------------------------------------------------
02715 
02716 void OsiCpxSolverInterface::freeCachedColRim()
02717 {
02718   freeCacheDouble( obj_ );  
02719   freeCacheDouble( collower_ ); 
02720   freeCacheDouble( colupper_ ); 
02721   assert( obj_==NULL );
02722   assert( collower_==NULL );
02723   assert( colupper_==NULL );
02724 }
02725 
02726 void OsiCpxSolverInterface::freeCachedRowRim()
02727 {
02728   freeCacheChar( rowsense_ );
02729   freeCacheDouble( rhs_ );
02730   freeCacheDouble( rowrange_ );
02731   freeCacheDouble( rowlower_ );
02732   freeCacheDouble( rowupper_ );
02733   assert( rowsense_==NULL ); 
02734   assert( rhs_==NULL ); 
02735   assert( rowrange_==NULL ); 
02736   assert( rowlower_==NULL ); 
02737   assert( rowupper_==NULL );
02738  }
02739 
02740 void OsiCpxSolverInterface::freeCachedMatrix()
02741 {
02742   freeCacheMatrix( matrixByRow_ );
02743   freeCacheMatrix( matrixByCol_ );
02744   assert( matrixByRow_==NULL ); 
02745   assert( matrixByCol_==NULL ); 
02746 }
02747 
02748 void OsiCpxSolverInterface::freeCachedResults()
02749 {
02750   freeCacheDouble( colsol_ ); 
02751   freeCacheDouble( rowsol_ );
02752   freeCacheDouble( redcost_ );
02753   freeCacheDouble( rowact_ );
02754   assert( colsol_==NULL );
02755   assert( rowsol_==NULL );
02756   assert( redcost_==NULL );
02757   assert( rowact_==NULL );
02758 }
02759 
02760 
02761 void OsiCpxSolverInterface::freeCachedData( int keepCached )
02762 {
02763   if( !(keepCached & OsiCpxSolverInterface::KEEPCACHED_COLUMN) )
02764     freeCachedColRim();
02765   if( !(keepCached & OsiCpxSolverInterface::KEEPCACHED_ROW) )
02766     freeCachedRowRim();
02767   if( !(keepCached & OsiCpxSolverInterface::KEEPCACHED_MATRIX) )
02768     freeCachedMatrix();
02769   if( !(keepCached & OsiCpxSolverInterface::KEEPCACHED_RESULTS) )
02770     freeCachedResults();
02771 }
02772 
02773 void OsiCpxSolverInterface::freeAllMemory()
02774 {
02775   freeCachedData();
02776   if( hotStartCStat_ != NULL )
02777     delete[] hotStartCStat_;
02778   if( hotStartRStat_ != NULL )
02779     delete[] hotStartRStat_;
02780   hotStartCStat_     = NULL;
02781   hotStartCStatSize_ = 0;
02782   hotStartRStat_     = NULL;
02783   hotStartRStatSize_ = 0;
02784   freeColType();
02785 }
02786 
02787 //#############################################################################
02788 // Resets as if default constructor
02789 void 
02790 OsiCpxSolverInterface::reset()
02791 {
02792   setInitialData(); // clear base class
02793   gutsOfDestructor();
02794 }

Generated on Wed Dec 3 14:35:30 2003 for Osi by doxygen 1.3.5