00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #if defined(_MSC_VER)
00013
00014 # pragma warning(disable:4786)
00015 #endif
00016
00017 #include <iostream>
00018 #include <cassert>
00019 #include <string>
00020 #include <numeric>
00021
00022 #include "CoinError.hpp"
00023
00024 #include "OsiSpxSolverInterface.hpp"
00025 #include "OsiRowCut.hpp"
00026 #include "OsiColCut.hpp"
00027 #include "CoinPackedMatrix.hpp"
00028 #include "CoinWarmStartBasis.hpp"
00029
00030
00031
00032
00033
00034 inline void freeCacheDouble( double*& ptr )
00035 {
00036 if( ptr != NULL )
00037 {
00038 delete [] ptr;
00039 ptr = NULL;
00040 }
00041 }
00042
00043 inline void freeCacheChar( char*& ptr )
00044 {
00045 if( ptr != NULL )
00046 {
00047 delete [] ptr;
00048 ptr = NULL;
00049 }
00050 }
00051
00052 inline void freeCacheMatrix( CoinPackedMatrix*& ptr )
00053 {
00054 if( ptr != NULL )
00055 {
00056 delete ptr;
00057 ptr = NULL;
00058 }
00059 }
00060
00061 inline void throwSPXerror( std::string error, std::string osimethod )
00062 {
00063 std::cout << "ERROR: " << error << " (" << osimethod <<
00064 " in OsiSpxSolverInterface)" << std::endl;
00065 throw CoinError( error.c_str(), osimethod.c_str(), "OsiSpxSolverInterface" );
00066 }
00067
00068
00069
00070
00071
00072 void OsiSpxSolverInterface::initialSolve()
00073 {
00074 if( spxsolver_.type() != soplex::SoPlex::ENTER )
00075 spxsolver_.setType( soplex::SoPlex::ENTER );
00076 if( spxsolver_.rep() != soplex::SoPlex::COLUMN )
00077 spxsolver_.setRep( soplex::SoPlex::COLUMN );
00078 spxsolver_.solve();
00079 }
00080
00081 void OsiSpxSolverInterface::resolve()
00082 {
00083 if( spxsolver_.type() != soplex::SoPlex::LEAVE )
00084 spxsolver_.setType( soplex::SoPlex::LEAVE );
00085 if( spxsolver_.rep() != soplex::SoPlex::COLUMN )
00086 spxsolver_.setRep( soplex::SoPlex::COLUMN );
00087 spxsolver_.solve();
00088 }
00089
00090 void OsiSpxSolverInterface::branchAndBound()
00091 {
00092 throwSPXerror( "SOPLEX does not provide an internal branch and bound procedure",
00093 "branchAndBound" );
00094 }
00095
00096
00097
00098
00099
00100 bool
00101 OsiSpxSolverInterface::setIntParam(OsiIntParam key, int value)
00102 {
00103 bool retval = false;
00104 switch (key)
00105 {
00106 case OsiMaxNumIteration:
00107 spxsolver_.setTerminationIter( value );
00108 retval = true;
00109 break;
00110 case OsiMaxNumIterationHotStart:
00111 if( value >= 0 )
00112 {
00113 hotStartMaxIteration_ = value;
00114 retval = true;
00115 }
00116 else
00117 retval = false;
00118 break;
00119 case OsiLastIntParam:
00120 retval = false;
00121 break;
00122 }
00123 return retval;
00124 }
00125
00126
00127
00128 bool
00129 OsiSpxSolverInterface::setDblParam(OsiDblParam key, double value)
00130 {
00131 bool retval = false;
00132 switch (key)
00133 {
00134 case OsiDualObjectiveLimit:
00135
00136
00137
00138
00139 retval = false;
00140 break;
00141 case OsiPrimalObjectiveLimit:
00142
00143
00144
00145
00146 retval = false;
00147 break;
00148 case OsiDualTolerance:
00149
00150
00151 spxsolver_.setDelta( value );
00152 retval = true;
00153 break;
00154 case OsiPrimalTolerance:
00155
00156
00157 spxsolver_.setDelta( value );
00158 retval = true;
00159 break;
00160 case OsiObjOffset:
00161 retval = OsiSolverInterface::setDblParam(key,value);
00162 break;
00163 case OsiLastDblParam:
00164 retval = false;
00165 break;
00166 }
00167 return retval;
00168 }
00169
00170
00171
00172 bool
00173 OsiSpxSolverInterface::getIntParam(OsiIntParam key, int& value) const
00174 {
00175 bool retval = false;
00176 switch (key)
00177 {
00178 case OsiMaxNumIteration:
00179 value = spxsolver_.terminationIter();
00180 retval = true;
00181 break;
00182 case OsiMaxNumIterationHotStart:
00183 value = hotStartMaxIteration_;
00184 retval = true;
00185 break;
00186 case OsiLastIntParam:
00187 retval = false;
00188 break;
00189 }
00190 return retval;
00191 }
00192
00193
00194
00195 bool
00196 OsiSpxSolverInterface::getDblParam(OsiDblParam key, double& value) const
00197 {
00198 bool retval = false;
00199 switch (key)
00200 {
00201 case OsiDualObjectiveLimit:
00202
00203
00204
00205 retval = false;
00206 break;
00207 case OsiPrimalObjectiveLimit:
00208
00209
00210
00211 retval = false;
00212 break;
00213 case OsiDualTolerance:
00214 value = spxsolver_.delta();
00215 retval = true;
00216 break;
00217 case OsiPrimalTolerance:
00218 value = spxsolver_.delta();
00219 retval = true;
00220 break;
00221 case OsiObjOffset:
00222 retval = OsiSolverInterface::getDblParam(key, value);
00223 break;
00224 case OsiLastDblParam:
00225 retval = false;
00226 break;
00227 }
00228 return retval;
00229 }
00230
00231 bool
00232 OsiSpxSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
00233 {
00234 bool retval = false;
00235 switch (key) {
00236 case OsiSolverName:
00237 value = "soplex";
00238 break;
00239 case OsiLastStrParam:
00240 return false;
00241 }
00242 return true;
00243 }
00244
00245
00246
00247
00248
00249 bool OsiSpxSolverInterface::isAbandoned() const
00250 {
00251 int stat = spxsolver_.status();
00252
00253 return ( stat == soplex::SoPlex::SINGULAR ||
00254 stat == soplex::SoPlex::ERROR );
00255 }
00256
00257 bool OsiSpxSolverInterface::isProvenOptimal() const
00258 {
00259 int stat = spxsolver_.status();
00260
00261 return ( stat == soplex::SoPlex::OPTIMAL );
00262 }
00263
00264 bool OsiSpxSolverInterface::isProvenPrimalInfeasible() const
00265 {
00266 int stat = spxsolver_.status();
00267
00268 return ( stat == soplex::SoPlex::INFEASIBLE );
00269 }
00270
00271 bool OsiSpxSolverInterface::isProvenDualInfeasible() const
00272 {
00273 int stat = spxsolver_.status();
00274
00275 return ( stat == soplex::SoPlex::UNBOUNDED );
00276 }
00277
00278 bool OsiSpxSolverInterface::isPrimalObjectiveLimitReached() const
00279 {
00280 return ( spxsolver_.status() == soplex::SoPlex::ABORT_VALUE );
00281 }
00282
00283 bool OsiSpxSolverInterface::isDualObjectiveLimitReached() const
00284 {
00285 return ( spxsolver_.status() == soplex::SoPlex::ABORT_VALUE );
00286 }
00287
00288 bool OsiSpxSolverInterface::isIterationLimitReached() const
00289 {
00290 return ( spxsolver_.status() == soplex::SoPlex::ABORT_ITER );
00291 }
00292
00293
00294
00295
00296
00297 CoinWarmStart* OsiSpxSolverInterface::getWarmStart() const
00298 {
00299 CoinWarmStartBasis* ws = NULL;
00300 int numcols = getNumCols();
00301 int numrows = getNumRows();
00302 int i;
00303
00304 ws = new CoinWarmStartBasis();
00305 ws->setSize( numcols, numrows );
00306
00307 for( i = 0; i < numrows; ++i )
00308 {
00309 switch( spxsolver_.getBasisRowStatus( i ) )
00310 {
00311 case soplex::SoPlex::BASIC:
00312 ws->setArtifStatus( i, CoinWarmStartBasis::basic );
00313 break;
00314 case soplex::SoPlex::FIXED:
00315 case soplex::SoPlex::ON_LOWER:
00316 ws->setArtifStatus( i, CoinWarmStartBasis::atLowerBound );
00317 break;
00318 case soplex::SoPlex::ON_UPPER:
00319 ws->setArtifStatus( i, CoinWarmStartBasis::atUpperBound );
00320 break;
00321 case soplex::SoPlex::ZERO:
00322 ws->setArtifStatus( i, CoinWarmStartBasis::isFree );
00323 break;
00324 default:
00325 throwSPXerror( "invalid row status", "getWarmStart" );
00326 break;
00327 }
00328 }
00329
00330 for( i = 0; i < numcols; ++i )
00331 {
00332 switch( spxsolver_.getBasisColStatus( i ) )
00333 {
00334 case soplex::SoPlex::BASIC:
00335 ws->setStructStatus( i, CoinWarmStartBasis::basic );
00336 break;
00337 case soplex::SoPlex::FIXED:
00338 case soplex::SoPlex::ON_LOWER:
00339 ws->setStructStatus( i, CoinWarmStartBasis::atLowerBound );
00340 break;
00341 case soplex::SoPlex::ON_UPPER:
00342 ws->setStructStatus( i, CoinWarmStartBasis::atUpperBound );
00343 break;
00344 case soplex::SoPlex::ZERO:
00345 ws->setStructStatus( i, CoinWarmStartBasis::isFree );
00346 break;
00347 default:
00348 throwSPXerror( "invalid column status", "getWarmStart" );
00349 break;
00350 }
00351 }
00352
00353 return ws;
00354 }
00355
00356
00357
00358 bool OsiSpxSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
00359 {
00360 const CoinWarmStartBasis* ws = dynamic_cast<const CoinWarmStartBasis*>(warmstart);
00361 int numcols, numrows, i;
00362 soplex::SoPlex::VarStatus *cstat, *rstat;
00363 bool retval = false;
00364
00365 if( !ws )
00366 return false;
00367
00368 numcols = ws->getNumStructural();
00369 numrows = ws->getNumArtificial();
00370
00371 if( numcols != getNumCols() || numrows != getNumRows() )
00372 return false;
00373
00374 cstat = new soplex::SoPlex::VarStatus[numcols];
00375 rstat = new soplex::SoPlex::VarStatus[numrows];
00376
00377 for( i = 0; i < numrows; ++i )
00378 {
00379 switch( ws->getArtifStatus( i ) )
00380 {
00381 case CoinWarmStartBasis::basic:
00382 rstat[i] = soplex::SoPlex::BASIC;
00383 break;
00384 case CoinWarmStartBasis::atLowerBound:
00385 rstat[i] = soplex::SoPlex::ON_LOWER;
00386 break;
00387 case CoinWarmStartBasis::atUpperBound:
00388 rstat[i] = soplex::SoPlex::ON_UPPER;
00389 break;
00390 case CoinWarmStartBasis::isFree:
00391 rstat[i] = soplex::SoPlex::ZERO;
00392 break;
00393 default:
00394 retval = false;
00395 goto TERMINATE;
00396 }
00397 }
00398 for( i = 0; i < numcols; ++i )
00399 {
00400 switch( ws->getStructStatus( i ) )
00401 {
00402 case CoinWarmStartBasis::basic:
00403 cstat[i] = soplex::SoPlex::BASIC;
00404 break;
00405 case CoinWarmStartBasis::atLowerBound:
00406 cstat[i] = soplex::SoPlex::ON_LOWER;
00407 break;
00408 case CoinWarmStartBasis::atUpperBound:
00409 cstat[i] = soplex::SoPlex::ON_UPPER;
00410 break;
00411 case CoinWarmStartBasis::isFree:
00412 cstat[i] = soplex::SoPlex::ZERO;
00413 break;
00414 default:
00415 retval = false;
00416 goto TERMINATE;
00417 }
00418 }
00419
00420 spxsolver_.setBasis( rstat, cstat );
00421 retval = true;
00422
00423 TERMINATE:
00424 delete[] cstat;
00425 delete[] rstat;
00426 return retval;
00427 }
00428
00429
00430
00431
00432
00433 void OsiSpxSolverInterface::markHotStart()
00434 {
00435 int numcols, numrows;
00436
00437 numcols = getNumCols();
00438 numrows = getNumRows();
00439 if( numcols > hotStartCStatSize_ )
00440 {
00441 delete[] hotStartCStat_;
00442 hotStartCStatSize_ = static_cast<int>( 1.2 * static_cast<double>( numcols ) );
00443 hotStartCStat_ = new soplex::SoPlex::VarStatus[hotStartCStatSize_];
00444 }
00445 if( numrows > hotStartRStatSize_ )
00446 {
00447 delete[] hotStartRStat_;
00448 hotStartRStatSize_ = static_cast<int>( 1.2 * static_cast<double>( numrows ) );
00449 hotStartRStat_ = new soplex::SoPlex::VarStatus[hotStartRStatSize_];
00450 }
00451 spxsolver_.getBasis( hotStartRStat_, hotStartCStat_ );
00452 }
00453
00454 void OsiSpxSolverInterface::solveFromHotStart()
00455 {
00456 int maxiter;
00457
00458 assert( getNumCols() <= hotStartCStatSize_ );
00459 assert( getNumRows() <= hotStartRStatSize_ );
00460
00461 spxsolver_.setBasis( hotStartRStat_, hotStartCStat_ );
00462
00463 maxiter = spxsolver_.terminationIter();
00464 spxsolver_.setTerminationIter( hotStartMaxIteration_ );
00465
00466 resolve();
00467
00468 spxsolver_.setTerminationIter( maxiter );
00469 }
00470
00471 void OsiSpxSolverInterface::unmarkHotStart()
00472 {
00473
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483 int OsiSpxSolverInterface::getNumCols() const
00484 {
00485 return spxsolver_.nCols();
00486 }
00487 int OsiSpxSolverInterface::getNumRows() const
00488 {
00489 return spxsolver_.nRows();
00490 }
00491 int OsiSpxSolverInterface::getNumElements() const
00492 {
00493 #if 0
00494 return spxsolver_.nNzos();
00495 #else
00496 int retVal = 0;
00497 int nrows = getNumRows();
00498 int row;
00499 for( row = 0; row < nrows; ++row ) {
00500 const soplex::SVector& rowvec = spxsolver_.rowVector( row );
00501 retVal += rowvec.size();
00502 }
00503 return retVal;
00504 #endif
00505 }
00506
00507
00508
00509
00510
00511 const double * OsiSpxSolverInterface::getColLower() const
00512 {
00513 const double * retVal = NULL;
00514 if ( getNumCols()!=0 )
00515 retVal = spxsolver_.lower().get_const_ptr();
00516 return retVal;
00517 }
00518
00519 const double * OsiSpxSolverInterface::getColUpper() const
00520 {
00521 const double * retVal = NULL;
00522 if ( getNumCols()!=0 )
00523 retVal = spxsolver_.upper().get_const_ptr();
00524 return retVal;
00525 }
00526
00527 const char * OsiSpxSolverInterface::getRowSense() const
00528 {
00529 if ( rowsense_ == NULL )
00530 {
00531
00532 getRightHandSide();
00533 assert( rowsense_ != NULL || getNumRows() == 0 );
00534 }
00535 return rowsense_;
00536 }
00537
00538 const double * OsiSpxSolverInterface::getRightHandSide() const
00539 {
00540 if ( rhs_ == NULL )
00541 {
00542 int nrows = getNumRows();
00543 if( nrows > 0 )
00544 {
00545 int row;
00546
00547 assert( rowrange_ == NULL );
00548 assert( rowsense_ == NULL );
00549
00550 rhs_ = new double[nrows];
00551 rowrange_ = new double[nrows];
00552 rowsense_ = new char[nrows];
00553
00554 for( row = 0; row < nrows; ++row )
00555 convertBoundToSense( spxsolver_.lhs( row ), spxsolver_.rhs( row ),
00556 rowsense_[row], rhs_[row], rowrange_[row] );
00557 }
00558 }
00559 return rhs_;
00560 }
00561
00562 const double * OsiSpxSolverInterface::getRowRange() const
00563 {
00564 if ( rowrange_==NULL )
00565 {
00566
00567 getRightHandSide();
00568 assert( rowrange_ != NULL || getNumRows() == 0 );
00569 }
00570 return rowrange_;
00571 }
00572
00573 const double * OsiSpxSolverInterface::getRowLower() const
00574 {
00575 const double * retVal = NULL;
00576 if ( getNumRows() != 0 )
00577 retVal = spxsolver_.lhs().get_const_ptr();
00578 return retVal;
00579 }
00580
00581 const double * OsiSpxSolverInterface::getRowUpper() const
00582 {
00583 const double * retVal = NULL;
00584 if ( getNumRows() != 0 )
00585 retVal = spxsolver_.rhs().get_const_ptr();
00586 return retVal;
00587 }
00588
00589 const double * OsiSpxSolverInterface::getObjCoefficients() const
00590 {
00591 const double * retVal = NULL;
00592 if( obj_ == NULL ) {
00593 if ( getNumCols()!=0 ) {
00594 obj_ = new soplex::DVector( getNumCols() );
00595 spxsolver_.getObj( *obj_ );
00596 retVal = obj_->get_const_ptr();
00597 }
00598 }
00599 else {
00600 retVal = obj_->get_const_ptr();
00601 }
00602 return retVal;
00603 }
00604
00605 double OsiSpxSolverInterface::getObjSense() const
00606 {
00607 switch( spxsolver_.spxSense() )
00608 {
00609 case soplex::SPxLP::MINIMIZE:
00610 return +1.0;
00611 case soplex::SPxLP::MAXIMIZE:
00612 return -1.0;
00613 default:
00614 throwSPXerror( "invalid optimization sense", "getObjSense" );
00615 return 0.0;
00616 }
00617 }
00618
00619
00620
00621
00622
00623 bool OsiSpxSolverInterface::isContinuous( int colNumber ) const
00624 {
00625 return( spxintvars_.number( colNumber ) < 0 );
00626 }
00627
00628
00629
00630
00631
00632 const CoinPackedMatrix * OsiSpxSolverInterface::getMatrixByRow() const
00633 {
00634 if( matrixByRow_ == NULL )
00635 {
00636 int nrows = getNumRows();
00637 int ncols = getNumCols();
00638 int nelems = getNumElements();
00639 double *elements = new double [nelems];
00640 int *indices = new int [nelems];
00641 int *starts = new int [nrows+1];
00642 int *len = new int [nrows];
00643 int row, i, elem;
00644
00645 elem = 0;
00646 for( row = 0; row < nrows; ++row )
00647 {
00648 const soplex::SVector& rowvec = spxsolver_.rowVector( row );
00649 starts[row] = elem;
00650 len [row] = rowvec.size();
00651 for( i = 0; i < len[row]; ++i, ++elem )
00652 {
00653 assert( elem < nelems );
00654 elements[elem] = rowvec.value( i );
00655 indices [elem] = rowvec.index( i );
00656 }
00657 }
00658 starts[nrows] = elem;
00659 assert( elem == nelems );
00660
00661 matrixByRow_ = new CoinPackedMatrix();
00662 matrixByRow_->assignMatrix( false ,
00663 ncols, nrows, nelems,
00664 elements, indices, starts, len );
00665 }
00666 return matrixByRow_;
00667 }
00668
00669
00670
00671 const CoinPackedMatrix * OsiSpxSolverInterface::getMatrixByCol() const
00672 {
00673 if( matrixByCol_ == NULL )
00674 {
00675 int nrows = getNumRows();
00676 int ncols = getNumCols();
00677 int nelems = getNumElements();
00678 double *elements = new double [nelems];
00679 int *indices = new int [nelems];
00680 int *starts = new int [ncols+1];
00681 int *len = new int [ncols];
00682 int col, i, elem;
00683
00684 elem = 0;
00685 for( col = 0; col < ncols; ++col )
00686 {
00687 const soplex::SVector& colvec = spxsolver_.colVector( col );
00688 starts[col] = elem;
00689 len [col] = colvec.size();
00690 for( i = 0; i < len[col]; ++i, ++elem )
00691 {
00692 assert( elem < nelems );
00693 elements[elem] = colvec.value( i );
00694 indices [elem] = colvec.index( i );
00695 }
00696 }
00697 starts[ncols] = elem;
00698 assert( elem == nelems );
00699
00700 matrixByCol_ = new CoinPackedMatrix();
00701 matrixByCol_->assignMatrix( true ,
00702 nrows, ncols, nelems,
00703 elements, indices, starts, len );
00704 }
00705 return matrixByCol_;
00706 }
00707
00708
00709
00710
00711 double OsiSpxSolverInterface::getInfinity() const
00712 {
00713 return soplex::infinity;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722 const double * OsiSpxSolverInterface::getColSolution() const
00723 {
00724 if( colsol_ == NULL )
00725 {
00726 int ncols = getNumCols();
00727 if( ncols > 0 )
00728 {
00729 colsol_ = new soplex::DVector( ncols );
00730 if( isProvenOptimal() )
00731 spxsolver_.getPrimal( *colsol_ );
00732 else
00733 colsol_->clear();
00734 }
00735 else
00736 return NULL;
00737 }
00738 return colsol_->get_const_ptr();
00739 }
00740
00741 const double * OsiSpxSolverInterface::getRowPrice() const
00742 {
00743 if( rowsol_ == NULL )
00744 {
00745 int nrows = getNumRows();
00746 if( nrows > 0 )
00747 {
00748 rowsol_ = new soplex::DVector( nrows );
00749 if( isProvenOptimal() )
00750 spxsolver_.getDual( *rowsol_ );
00751 else
00752 rowsol_->clear();
00753 }
00754 else
00755 return NULL;
00756 }
00757 return rowsol_->get_const_ptr();
00758 }
00759
00760 const double * OsiSpxSolverInterface::getReducedCost() const
00761 {
00762 if( redcost_ == NULL )
00763 {
00764 int ncols = getNumCols();
00765 if( ncols > 0 )
00766 {
00767 redcost_ = new soplex::DVector( ncols );
00768 if( isProvenOptimal() )
00769 spxsolver_.getRdCost( *redcost_ );
00770 else
00771 redcost_->clear();
00772 }
00773 else
00774 return NULL;
00775 }
00776 return redcost_->get_const_ptr();
00777 }
00778
00779 const double * OsiSpxSolverInterface::getRowActivity() const
00780 {
00781 if( rowact_ == NULL )
00782 {
00783 int nrows = getNumRows();
00784 if( nrows > 0 )
00785 {
00786 rowact_ = new soplex::DVector( nrows );
00787 if( isProvenOptimal() )
00788 spxsolver_.getSlacks( *rowact_ );
00789 else
00790 rowact_->clear();
00791 }
00792 else
00793 return NULL;
00794 }
00795 return rowact_->get_const_ptr();
00796 }
00797
00798 double OsiSpxSolverInterface::getObjValue() const
00799 {
00800 double objval;
00801
00802 switch( spxsolver_.status() )
00803 {
00804 case soplex::SoPlex::OPTIMAL:
00805 case soplex::SoPlex::UNBOUNDED:
00806 case soplex::SoPlex::INFEASIBLE:
00807 objval = spxsolver_.value();
00808 break;
00809 default:
00810 objval = 0.0;
00811 break;
00812 }
00813
00814
00815 double objOffset;
00816 getDblParam(OsiObjOffset,objOffset);
00817 objval = objval - objOffset;
00818
00819 return objval;
00820 }
00821
00822 int OsiSpxSolverInterface::getIterationCount() const
00823 {
00824 return spxsolver_.iterations();
00825 }
00826
00827 std::vector<double*> OsiSpxSolverInterface::getDualRays(int maxNumRays) const
00828 {
00829
00830 throw CoinError("method is not yet written", "getDualRays",
00831 "OsiSpxSolverInterface");
00832 return std::vector<double*>();
00833 }
00834
00835 std::vector<double*> OsiSpxSolverInterface::getPrimalRays(int maxNumRays) const
00836 {
00837
00838 throw CoinError("method is not yet written", "getPrimalRays",
00839 "OsiSpxSolverInterface");
00840 return std::vector<double*>();
00841 }
00842
00843
00844
00845
00846
00847 void OsiSpxSolverInterface::setObjCoeff( int elementIndex, double elementValue )
00848 {
00849 spxsolver_.changeObj( elementIndex, elementValue );
00850 freeCachedData( OsiSpxSolverInterface::FREECACHED_COLUMN );
00851 }
00852
00853 void OsiSpxSolverInterface::setColLower(int elementIndex, double elementValue)
00854 {
00855 spxsolver_.changeLower( elementIndex, elementValue );
00856 freeCachedData( OsiSpxSolverInterface::FREECACHED_COLUMN );
00857 }
00858
00859 void OsiSpxSolverInterface::setColUpper(int elementIndex, double elementValue)
00860 {
00861 spxsolver_.changeUpper( elementIndex, elementValue );
00862 freeCachedData( OsiSpxSolverInterface::FREECACHED_COLUMN );
00863 }
00864
00865 void OsiSpxSolverInterface::setColBounds( int elementIndex, double lower, double upper )
00866 {
00867 spxsolver_.changeBounds( elementIndex, lower, upper );
00868 freeCachedData( OsiSpxSolverInterface::FREECACHED_COLUMN );
00869 }
00870
00871 void
00872 OsiSpxSolverInterface::setRowLower( int i, double elementValue )
00873 {
00874 spxsolver_.changeLhs( i, elementValue );
00875 freeCachedData( OsiSpxSolverInterface::FREECACHED_ROW );
00876 }
00877
00878 void
00879 OsiSpxSolverInterface::setRowUpper( int i, double elementValue )
00880 {
00881 spxsolver_.changeRhs( i, elementValue );
00882 freeCachedData( OsiSpxSolverInterface::FREECACHED_ROW );
00883 }
00884
00885 void
00886 OsiSpxSolverInterface::setRowBounds( int elementIndex, double lower, double upper )
00887 {
00888 spxsolver_.changeRange( elementIndex, lower, upper );
00889 freeCachedData( OsiSpxSolverInterface::FREECACHED_ROW );
00890 }
00891
00892 void
00893 OsiSpxSolverInterface::setRowType(int i, char sense, double rightHandSide,
00894 double range)
00895 {
00896 double lower, upper;
00897
00898 convertSenseToBound( sense, rightHandSide, range, lower, upper );
00899 setRowBounds( i, lower, upper );
00900 }
00901
00902 void
00903 OsiSpxSolverInterface::setContinuous(int index)
00904 {
00905 int pos = spxintvars_.number( index );
00906 if( pos >= 0 )
00907 {
00908 spxintvars_.remove( pos );
00909 freeCachedData( OsiSpxSolverInterface::FREECACHED_COLUMN );
00910 }
00911 }
00912
00913 void
00914 OsiSpxSolverInterface::setInteger(int index)
00915 {
00916 int pos = spxintvars_.number( index );
00917 if( pos < 0 )
00918 {
00919 spxintvars_.addIdx( index );
00920 freeCachedData( OsiSpxSolverInterface::FREECACHED_COLUMN );
00921 }
00922 }
00923
00924
00925 void OsiSpxSolverInterface::setObjSense(double s)
00926 {
00927 if( s != getObjSense() )
00928 {
00929 if( s == +1.0 )
00930 spxsolver_.changeSense( soplex::SPxLP::MINIMIZE );
00931 else
00932 spxsolver_.changeSense( soplex::SPxLP::MAXIMIZE );
00933 freeCachedData( OsiSpxSolverInterface::FREECACHED_RESULTS );
00934 }
00935 }
00936
00937
00938
00939 void OsiSpxSolverInterface::setColSolution(const double * cs)
00940 {
00941 int col;
00942 int ncols = getNumCols();
00943
00944 if( colsol_ != NULL )
00945 delete colsol_;
00946
00947 if( ncols > 0 && cs != NULL )
00948 {
00949 colsol_ = new soplex::DVector( ncols );
00950 for( col = 0; col < ncols; ++col )
00951 (*colsol_)[col] = cs[col];
00952 }
00953 else
00954 colsol_ = NULL;
00955 }
00956
00957
00958
00959 void OsiSpxSolverInterface::setRowPrice(const double * rs)
00960 {
00961 int row;
00962 int nrows = getNumRows();
00963
00964 if( rowsol_ != NULL )
00965 delete rowsol_;
00966
00967 if( nrows > 0 && rs != NULL )
00968 {
00969 rowsol_ = new soplex::DVector( nrows );
00970 for( row = 0; row < nrows; ++row )
00971 (*rowsol_)[row] = rs[row];
00972 }
00973 else
00974 rowsol_ = NULL;
00975 }
00976
00977
00978
00979
00980 void
00981 OsiSpxSolverInterface::addCol(const CoinPackedVectorBase& vec,
00982 const double collb, const double colub,
00983 const double obj)
00984 {
00985 soplex::DSVector colvec;
00986
00987 colvec.add( vec.getNumElements(), vec.getIndices(), vec.getElements() );
00988 spxsolver_.addCol( soplex::LPCol( obj, colvec, colub, collb ) );
00989 freeCachedData( OsiSpxSolverInterface::KEEPCACHED_ROW );
00990 }
00991
00992 void
00993 OsiSpxSolverInterface::deleteCols(const int num, const int * columnIndices)
00994 {
00995 spxsolver_.removeCols( const_cast<int*>(columnIndices), num );
00996 freeCachedData( OsiSpxSolverInterface::KEEPCACHED_ROW );
00997 }
00998
00999 void
01000 OsiSpxSolverInterface::addRow(const CoinPackedVectorBase& vec,
01001 const double rowlb, const double rowub)
01002 {
01003 soplex::DSVector rowvec;
01004
01005 rowvec.add( vec.getNumElements(), vec.getIndices(), vec.getElements() );
01006 spxsolver_.addRow( soplex::LPRow( rowlb, rowvec, rowub ) );
01007 freeCachedData( OsiSpxSolverInterface::KEEPCACHED_COLUMN );
01008 }
01009
01010 void
01011 OsiSpxSolverInterface::addRow(const CoinPackedVectorBase& vec,
01012 const char rowsen, const double rowrhs,
01013 const double rowrng)
01014 {
01015 double rowlb, rowub;
01016
01017 convertSenseToBound( rowsen, rowrhs, rowrng, rowlb, rowub );
01018 addRow( vec, rowlb, rowub );
01019 }
01020
01021 void
01022 OsiSpxSolverInterface::deleteRows(const int num, const int * rowIndices)
01023 {
01024 spxsolver_.removeRows( const_cast<int*>(rowIndices), num );
01025 freeCachedData( OsiSpxSolverInterface::KEEPCACHED_COLUMN );
01026 }
01027
01028
01029
01030
01031
01032 void
01033 OsiSpxSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
01034 const double* collb, const double* colub,
01035 const double* obj,
01036 const double* rowlb, const double* rowub )
01037 {
01038 int ncols = matrix.getNumCols();
01039 int nrows = matrix.getNumRows();
01040 const int *length = matrix.getVectorLengths();
01041 const int *start = matrix.getVectorStarts();
01042 const double *elem = matrix.getElements();
01043 const int *index = matrix.getIndices();
01044 double *thecollb, *thecolub, *theobj, *therowlb, *therowub;
01045
01046
01047 if( collb == NULL )
01048 {
01049 thecollb = new double[ncols];
01050 CoinFillN( thecollb, ncols, 0.0 );
01051 }
01052 else
01053 thecollb = const_cast<double*>(collb);
01054 if( colub == NULL )
01055 {
01056 thecolub = new double[ncols];
01057 CoinFillN( thecolub, ncols, getInfinity() );
01058 }
01059 else
01060 thecolub = const_cast<double*>(colub);
01061 if( obj == NULL )
01062 {
01063 theobj = new double[ncols];
01064 CoinFillN( theobj, ncols, 0.0 );
01065 }
01066 else
01067 theobj = const_cast<double*>(obj);
01068 if( rowlb == NULL )
01069 {
01070 therowlb = new double[nrows];
01071 CoinFillN( therowlb, nrows, -getInfinity() );
01072 }
01073 else
01074 therowlb = const_cast<double*>(rowlb);
01075 if( rowub == NULL )
01076 {
01077 therowub = new double[nrows];
01078 CoinFillN( therowub, nrows, +getInfinity() );
01079 }
01080 else
01081 therowub = const_cast<double*>(rowub);
01082
01083
01084 spxsolver_.clear();
01085 spxintvars_.clear();
01086 freeCachedData( OsiSpxSolverInterface::KEEPCACHED_NONE );
01087
01088 if( matrix.isColOrdered() )
01089 {
01090 int row, col, pos;
01091 soplex::LPRowSet rowset( nrows, 0 );
01092 soplex::DSVector rowvec;
01093 soplex::LPColSet colset( ncols, matrix.getNumElements() );
01094 soplex::DSVector colvec;
01095
01096
01097 rowvec.clear();
01098 for( row = 0; row < nrows; ++row )
01099 rowset.add( therowlb[row], rowvec, therowub[row] );
01100 spxsolver_.addRows( rowset );
01101
01102
01103 for( col = 0; col < ncols; ++col )
01104 {
01105 pos = start[col];
01106 colvec.clear();
01107 colvec.add( length[col], &(index[pos]), &(elem[pos]) );
01108 colset.add( theobj[col], thecollb[col], colvec, thecolub[col] );
01109 }
01110
01111 spxsolver_.addCols( colset );
01112
01113 }
01114 else
01115 {
01116 int row, col, pos;
01117 soplex::LPRowSet rowset( nrows, matrix.getNumElements() );
01118 soplex::DSVector rowvec;
01119 soplex::LPColSet colset( ncols, 0 );
01120 soplex::DSVector colvec;
01121
01122
01123 colvec.clear();
01124 for( col = 0; col < ncols; ++col )
01125 colset.add( theobj[col], thecollb[col], colvec, thecolub[col] );
01126 spxsolver_.addCols( colset );
01127
01128
01129 for( row = 0; row < nrows; ++row )
01130 {
01131 pos = start[row];
01132 rowvec.clear();
01133 rowvec.add( length[row], &(index[pos]), &(elem[pos]) );
01134 rowset.add( therowlb[row], rowvec, therowub[row] );
01135 }
01136
01137 spxsolver_.addRows( rowset );
01138
01139
01140 }
01141
01142
01143 spxsolver_.changeSense( soplex::SoPlex::MINIMIZE );
01144
01145
01146 if( collb == NULL )
01147 delete[] thecollb;
01148 if( colub == NULL )
01149 delete[] thecolub;
01150 if( obj == NULL )
01151 delete[] theobj;
01152 if( rowlb == NULL )
01153 delete[] therowlb;
01154 if( rowub == NULL )
01155 delete[] therowub;
01156 }
01157
01158
01159
01160 void
01161 OsiSpxSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
01162 double*& collb, double*& colub,
01163 double*& obj,
01164 double*& rowlb, double*& rowub )
01165 {
01166 loadProblem( *matrix, collb, colub, obj, rowlb, rowub );
01167 delete matrix; matrix = 0;
01168 delete[] collb; collb = 0;
01169 delete[] colub; colub = 0;
01170 delete[] obj; obj = 0;
01171 delete[] rowlb; rowlb = 0;
01172 delete[] rowub; rowub = 0;
01173 }
01174
01175
01176
01177 void
01178 OsiSpxSolverInterface::loadProblem( const CoinPackedMatrix& matrix,
01179 const double* collb, const double* colub,
01180 const double* obj,
01181 const char* rowsen, const double* rowrhs,
01182 const double* rowrng )
01183 {
01184 int nrows = matrix.getNumRows();
01185 double* rowlb = new double[nrows];
01186 double* rowub = new double[nrows];
01187 int row;
01188 char *therowsen;
01189 double *therowrhs, *therowrng;
01190
01191 if( rowsen == NULL )
01192 {
01193 therowsen = new char[nrows];
01194 CoinFillN( therowsen, nrows, 'G' );
01195 }
01196 else
01197 therowsen = const_cast<char*>(rowsen);
01198 if( rowrhs == NULL )
01199 {
01200 therowrhs = new double[nrows];
01201 CoinFillN( therowrhs, nrows, 0.0 );
01202 }
01203 else
01204 therowrhs = const_cast<double*>(rowrhs);
01205 if( rowrng == NULL )
01206 {
01207 therowrng = new double[nrows];
01208 CoinFillN( therowrng, nrows, 0.0 );
01209 }
01210 else
01211 therowrng = const_cast<double*>(rowrng);
01212
01213 for( row = 0; row < nrows; ++row )
01214 convertSenseToBound( therowsen[row], therowrhs[row], therowrng[row], rowlb[row], rowub[row] );
01215
01216 loadProblem( matrix, collb, colub, obj, rowlb, rowub );
01217
01218 if( rowsen == NULL )
01219 delete[] therowsen;
01220 if( rowrhs == NULL )
01221 delete[] therowrhs;
01222 if( rowrng == NULL )
01223 delete[] therowrng;
01224
01225 delete[] rowlb;
01226 delete[] rowub;
01227 }
01228
01229
01230
01231 void
01232 OsiSpxSolverInterface::assignProblem( CoinPackedMatrix*& matrix,
01233 double*& collb, double*& colub,
01234 double*& obj,
01235 char*& rowsen, double*& rowrhs,
01236 double*& rowrng )
01237 {
01238 loadProblem( *matrix, collb, colub, obj, rowsen, rowrhs, rowrng );
01239 delete matrix; matrix = 0;
01240 delete[] collb; collb = 0;
01241 delete[] colub; colub = 0;
01242 delete[] obj; obj = 0;
01243 delete[] rowsen; rowsen = 0;
01244 delete[] rowrhs; rowrhs = 0;
01245 delete[] rowrng; rowrng = 0;
01246 }
01247
01248
01249
01250 void
01251 OsiSpxSolverInterface::loadProblem(const int numcols, const int numrows,
01252 const int* start, const int* index,
01253 const double* value,
01254 const double* collb, const double* colub,
01255 const double* obj,
01256 const double* rowlb, const double* rowub )
01257 {
01258 int col, pos;
01259 soplex::LPColSet colset( numcols, start[numcols] );
01260 soplex::DSVector colvec;
01261
01262 spxsolver_.clear();
01263 spxintvars_.clear();
01264 freeCachedData( OsiSpxSolverInterface::KEEPCACHED_NONE );
01265
01266 for( col = 0; col < numcols; ++col )
01267 {
01268 pos = start[col];
01269 colvec.clear();
01270 colvec.add( start[col+1] - pos, &(index[pos]), &(value[pos]) );
01271 colset.add( obj[col], collb[col], colvec, colub[col] );
01272 }
01273
01274 spxsolver_.addCols( colset );
01275 spxsolver_.changeRange( soplex::Vector( numrows, const_cast<double*>(rowlb) ), soplex::Vector( numrows, const_cast<double*>(rowub) ) );
01276 }
01277
01278
01279
01280 void
01281 OsiSpxSolverInterface::loadProblem(const int numcols, const int numrows,
01282 const int* start, const int* index,
01283 const double* value,
01284 const double* collb, const double* colub,
01285 const double* obj,
01286 const char* rowsen, const double* rowrhs,
01287 const double* rowrng )
01288 {
01289 double* rowlb = new double[numrows];
01290 double* rowub = new double[numrows];
01291 int row;
01292
01293 for( row = 0; row < numrows; ++row )
01294 convertSenseToBound( rowsen[row], rowrhs[row], rowrng[row], rowlb[row], rowub[row] );
01295
01296 loadProblem( numcols, numrows, start, index, value, collb, colub, obj, rowlb, rowub );
01297
01298 delete[] rowlb;
01299 delete[] rowub;
01300 }
01301
01302
01303
01304
01305 int OsiSpxSolverInterface::readMps( const char * filename,
01306 const char * extension )
01307 {
01308 #if 0
01309 std::string f(filename);
01310 std::string e(extension);
01311 std::string fullname = f + "." + e;
01312
01313 spxsolver_.clear();
01314 spxintvars_.clear();
01315 if( !spxsolver_.readFile( fullname.c_str(), NULL, NULL, &spxintvars_ ) )
01316 throwSPXerror( "error reading file <" + fullname + ">", "readMps" );
01317 #endif
01318
01319 return OsiSolverInterface::readMps(filename,extension);
01320 }
01321
01322
01323
01324
01325 void OsiSpxSolverInterface::writeMps( const char * filename,
01326 const char * extension,
01327 double objSense) const
01328 {
01329 std::string f(filename);
01330 std::string e(extension);
01331 std::string fullname = f + ".lp";
01332 spxsolver_.dumpFile( fullname.c_str() );
01333 std::cout << "WARNING: LP file <" << fullname << "> created instead of "
01334 << "MPS file <" << f << "." << e << "> !" << std::endl;
01335 }
01336
01337
01338
01339
01340
01341
01342
01343
01344 OsiSpxSolverInterface::OsiSpxSolverInterface ()
01345 : OsiSolverInterface(),
01346 spxsolver_(soplex::SoPlex::ENTER, soplex::SoPlex::COLUMN),
01347 spxintvars_(),
01348 hotStartCStat_(NULL),
01349 hotStartCStatSize_(0),
01350 hotStartRStat_(NULL),
01351 hotStartRStatSize_(0),
01352 hotStartMaxIteration_(1000000),
01353 obj_(NULL),
01354 rowsense_(NULL),
01355 rhs_(NULL),
01356 rowrange_(NULL),
01357 colsol_(NULL),
01358 rowsol_(NULL),
01359 redcost_(NULL),
01360 rowact_(NULL),
01361 matrixByRow_(NULL),
01362 matrixByCol_(NULL)
01363 {
01364 #ifndef NDEBUG
01365 soplex::Param::setVerbose( 3 );
01366 #else
01367 soplex::Param::setVerbose( 0 );
01368 #endif
01369 }
01370
01371
01372
01373
01374
01375 OsiSolverInterface * OsiSpxSolverInterface::clone(bool copyData) const
01376 {
01377 return( new OsiSpxSolverInterface( *this ) );
01378 }
01379
01380
01381
01382
01383 OsiSpxSolverInterface::OsiSpxSolverInterface( const OsiSpxSolverInterface & source )
01384 : OsiSolverInterface(source),
01385 spxsolver_(source.spxsolver_.type(), source.spxsolver_.rep()),
01386 spxintvars_(source.spxintvars_),
01387 hotStartCStat_(NULL),
01388 hotStartCStatSize_(0),
01389 hotStartRStat_(NULL),
01390 hotStartRStatSize_(0),
01391 hotStartMaxIteration_(source.hotStartMaxIteration_),
01392 obj_(NULL),
01393 rowsense_(NULL),
01394 rhs_(NULL),
01395 rowrange_(NULL),
01396 colsol_(NULL),
01397 rowsol_(NULL),
01398 redcost_(NULL),
01399 rowact_(NULL),
01400 matrixByRow_(NULL),
01401 matrixByCol_(NULL)
01402 {
01403 spxsolver_.loadLP( source.spxsolver_ );
01404 if( source.spxsolver_.basis().status() != soplex::SPxBasis::NO_PROBLEM )
01405 spxsolver_.loadBasis( source.spxsolver_.basis().desc() );
01406 spxsolver_.setTerminationTime ( source.spxsolver_.terminationTime() );
01407 spxsolver_.setTerminationIter ( source.spxsolver_.terminationIter() );
01408
01409 spxsolver_.setPricing( source.spxsolver_.pricing() );
01410 spxsolver_.setDelta ( source.spxsolver_.delta() );
01411 setColSolution(source.getColSolution());
01412 setRowPrice(source.getRowPrice());
01413 }
01414
01415
01416
01417
01418
01419 OsiSpxSolverInterface::~OsiSpxSolverInterface ()
01420 {
01421 freeAllMemory();
01422 }
01423
01424
01425
01426
01427 OsiSpxSolverInterface& OsiSpxSolverInterface::operator=( const OsiSpxSolverInterface& source )
01428 {
01429 if (this != &source)
01430 {
01431 freeAllMemory();
01432
01433 OsiSolverInterface::operator=( source );
01434 spxintvars_ = source.spxintvars_;
01435
01436 spxsolver_.setRep ( source.spxsolver_.rep() );
01437 spxsolver_.setType ( source.spxsolver_.type() );
01438 spxsolver_.loadLP ( source.spxsolver_ );
01439 spxsolver_.loadBasis ( source.spxsolver_.basis().desc() );
01440 spxsolver_.setTerminationTime ( source.spxsolver_.terminationTime() );
01441 spxsolver_.setTerminationIter ( source.spxsolver_.terminationIter() );
01442
01443 spxsolver_.setPricing ( source.spxsolver_.pricing() );
01444 spxsolver_.setDelta ( source.spxsolver_.delta() );
01445 setColSolution(source.getColSolution());
01446 setRowPrice(source.getRowPrice());
01447 hotStartMaxIteration_ = source.hotStartMaxIteration_;
01448 }
01449 return *this;
01450 }
01451
01452
01453
01454
01455
01456 void OsiSpxSolverInterface::applyColCut( const OsiColCut & cc )
01457 {
01458 const double * soplexColLB = getColLower();
01459 const double * soplexColUB = getColUpper();
01460 const CoinPackedVector & lbs = cc.lbs();
01461 const CoinPackedVector & ubs = cc.ubs();
01462 int i;
01463
01464 for( i = 0; i < lbs.getNumElements(); ++i )
01465 if ( lbs.getElements()[i] > soplexColLB[lbs.getIndices()[i]] )
01466 setColLower( lbs.getIndices()[i], lbs.getElements()[i] );
01467 for( i = 0; i < ubs.getNumElements(); ++i )
01468 if ( ubs.getElements()[i] < soplexColUB[ubs.getIndices()[i]] )
01469 setColUpper( ubs.getIndices()[i], ubs.getElements()[i] );
01470 }
01471
01472
01473
01474 void OsiSpxSolverInterface::applyRowCut( const OsiRowCut & rowCut )
01475 {
01476 addRow( rowCut.row(), rowCut.lb(), rowCut.ub() );
01477 }
01478
01479
01480
01481
01482
01483
01485
01486 void OsiSpxSolverInterface::freeCachedColRim()
01487 {
01488 delete obj_;
01489 obj_ = NULL;
01490 }
01491
01492 void OsiSpxSolverInterface::freeCachedRowRim()
01493 {
01494 freeCacheChar ( rowsense_ );
01495 freeCacheDouble( rhs_ );
01496 freeCacheDouble( rowrange_ );
01497 assert( rowsense_ == NULL );
01498 assert( rhs_ == NULL );
01499 assert( rowrange_ == NULL );
01500 }
01501
01502 void OsiSpxSolverInterface::freeCachedMatrix()
01503 {
01504 freeCacheMatrix( matrixByRow_ );
01505 freeCacheMatrix( matrixByCol_ );
01506 assert( matrixByRow_ == NULL );
01507 assert( matrixByCol_ == NULL );
01508 }
01509
01510 void OsiSpxSolverInterface::freeCachedResults()
01511 {
01512 delete colsol_;
01513 delete rowsol_;
01514 delete redcost_;
01515 delete rowact_;
01516 colsol_ = NULL;
01517 rowsol_ = NULL;
01518 redcost_ = NULL;
01519 rowact_ = NULL;
01520 }
01521
01522
01523 void OsiSpxSolverInterface::freeCachedData( int keepCached )
01524 {
01525 if( !(keepCached & OsiSpxSolverInterface::KEEPCACHED_COLUMN) )
01526 freeCachedColRim();
01527 if( !(keepCached & OsiSpxSolverInterface::KEEPCACHED_ROW) )
01528 freeCachedRowRim();
01529 if( !(keepCached & OsiSpxSolverInterface::KEEPCACHED_MATRIX) )
01530 freeCachedMatrix();
01531 if( !(keepCached & OsiSpxSolverInterface::KEEPCACHED_RESULTS) )
01532 freeCachedResults();
01533 }
01534
01535 void OsiSpxSolverInterface::freeAllMemory()
01536 {
01537 freeCachedData();
01538 if( hotStartCStat_ != NULL )
01539 delete[] hotStartCStat_;
01540 if( hotStartRStat_ != NULL )
01541 delete[] hotStartRStat_;
01542 hotStartCStat_ = NULL;
01543 hotStartCStatSize_ = 0;
01544 hotStartRStat_ = NULL;
01545 hotStartRStatSize_ = 0;
01546 spxsolver_.clear();
01547 spxintvars_.clear();
01548 }