00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #if defined(_MSC_VER)
00014
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
00033
00034 #ifdef DEBUG
00035 #define debugMessage printf
00036 #else
00037 #define debugMessage if( false ) printf
00038 #endif
00039
00040
00041
00042
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
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
00192
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
00211
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
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 );
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 );
00274 else
00275 retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJLLIM, value ) == 0 );
00276 break;
00277 case OsiPrimalObjectiveLimit:
00278 if( getObjSense() == +1 )
00279 retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJLLIM, value ) == 0 );
00280 else
00281 retval = ( CPXsetdblparam( env_, CPX_PARAM_OBJULIM, value ) == 0 );
00282 break;
00283 case OsiDualTolerance:
00284 retval = ( CPXsetdblparam( env_, CPX_PARAM_EPOPT, value ) == 0 );
00285 break;
00286 case OsiPrimalTolerance:
00287 retval = ( CPXsetdblparam( env_, CPX_PARAM_EPRHS, value ) == 0 );
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 );
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 );
00357 else
00358 retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJLLIM, &value ) == 0 );
00359 break;
00360 case OsiPrimalObjectiveLimit:
00361 if( getObjSense() == +1 )
00362 retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJLLIM, &value ) == 0 );
00363 else
00364 retval = ( CPXgetdblparam( env_, CPX_PARAM_OBJULIM, &value ) == 0 );
00365 break;
00366 case OsiDualTolerance:
00367 retval = ( CPXgetdblparam( env_, CPX_PARAM_EPOPT, &value ) == 0 );
00368 break;
00369 case OsiPrimalTolerance:
00370 retval = ( CPXgetdblparam( env_, CPX_PARAM_EPRHS, &value ) == 0 );
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
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
00456
00457
00458 return (stat == CPX_STAT_INFEASIBLE);
00459
00460
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
00480
00481
00482 return (stat == CPX_STAT_UNBOUNDED);
00483
00484
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
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:
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:
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:
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:
00668 retval = false;
00669 goto TERMINATE;
00670 }
00671 }
00672
00673
00674
00675
00676
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
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 ) );
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 ) );
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
00746 }
00747
00748
00749
00750
00751
00752
00753
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
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
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
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
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
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
01005
01006
01007
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 ,
01013 ncols, nrows, nelems,
01014 elements, indices, starts, len );
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
01051
01052
01053
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 ,
01059 nrows, ncols, nelems,
01060 elements, indices, starts, len );
01061 assert( matrixByCol_->getNumCols()==ncols );
01062 assert( matrixByCol_->getNumRows()==nrows );
01063 }
01064 return matrixByCol_;
01065 }
01066
01067
01068
01069
01070 double OsiCpxSolverInterface::getInfinity() const
01071 {
01072 debugMessage("OsiCpxSolverInterface::getInfinity()\n");
01073
01074 return CPX_INFBOUND;
01075 }
01076
01077
01078
01079
01080
01081
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
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
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);
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
01305 throw CoinError("method is not yet written", "getPrimalRays",
01306 "OsiCpxSolverInterface");
01307 return std::vector<double*>();
01308 }
01309
01310
01311
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
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
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
01551
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
01637 if ( colsol_ == NULL )
01638 colsol_ = new double[nc];
01639
01640
01641 CoinDisjointCopyN( cs, nc, colsol_ );
01642
01643
01644
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
01669 if ( rowsol_ == NULL )
01670 rowsol_ = new double[nr];
01671
01672
01673 CoinDisjointCopyN( rs, nr, rowsol_ );
01674
01675
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
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
01761
01762
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
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 )
01961 gutsOfDestructor();
01962 else
01963 {
01964 assert( rowsen != NULL );
01965 assert( rowrhs != NULL );
01966
01967 int i;
01968
01969
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
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
02149 gutsOfDestructor();
02150 return;
02151 }
02152
02153 assert( rowsen != NULL );
02154 assert( rowrhs != NULL );
02155
02156 int i;
02157
02158
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
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
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
02248 return OsiSolverInterface::readMps(filename,extension);
02249 }
02250
02251
02252
02253
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
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
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
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 );
02315 #endif
02316
02317
02318
02319
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
02349
02350
02351
02352
02353
02354 OsiCpxSolverInterface::OsiCpxSolverInterface()
02355 : OsiSolverInterface(),
02356 lp_(NULL),
02357 hotStartCStat_(NULL),
02358 hotStartCStatSize_(0),
02359 hotStartRStat_(NULL),
02360 hotStartRStatSize_(0),
02361 hotStartMaxIteration_(1000000),
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
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
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
02436
02437 OsiCpxSolverInterface::~OsiCpxSolverInterface()
02438 {
02439 debugMessage("OsiCpxSolverInterface::~OsiCpxSolverInterface()\n");
02440
02441 gutsOfDestructor();
02442 decrementInstanceCounter();
02443 }
02444
02445
02446
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
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() )
02498 {
02499 rhs = -getInfinity();
02500 rng = 2*getInfinity();
02501 sns = 'R';
02502 }
02503 else if( lb <= -getInfinity() )
02504 {
02505 rhs = ub;
02506 sns = 'L';
02507 }
02508 else if( ub >= getInfinity() )
02509 {
02510 rhs = lb;
02511 sns = 'G';
02512 }
02513 else if( ub == lb )
02514 {
02515 rhs = ub;
02516 sns = 'E';
02517 }
02518 else
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
02542
02543
02544
02545
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
02556
02557
02558
02559 CPXLPptr OsiCpxSolverInterface::getMutableLpPtr() const
02560 {
02561 if ( lp_ == NULL )
02562 {
02563 int err;
02564 assert(env_ != NULL);
02565 #if 0
02566
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
02575
02576 assert( lp_ != NULL );
02577 }
02578 return lp_;
02579 }
02580
02581
02582
02583 void OsiCpxSolverInterface::gutsOfCopy( const OsiCpxSolverInterface & source )
02584 {
02585
02586 setObjSense(source.getObjSense());
02587
02588
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
02598 resizeColType(source.coltypesize_);
02599 CoinDisjointCopyN( source.coltype_, source.coltypesize_, coltype_ );
02600
02601
02602 setColSolution(source.getColSolution());
02603 setRowPrice(source.getRowPrice());
02604
02605
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
02675 int err;
02676 lp_ = CPXcreateprob( env_, &err, "OSI_CPLEX" );
02677 checkCPXerror( err, "CPXcreateprob", "gutsOfConstructor" );
02678
02679
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
02789 void
02790 OsiCpxSolverInterface::reset()
02791 {
02792 setInitialData();
02793 gutsOfDestructor();
02794 }