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

OsiSpxSolverInterface.cpp

00001 //  LAST EDIT: Tue Nov 27 16:30:04 CET 2001 by Laszlo Ladanyi
00002 //-----------------------------------------------------------------------------
00003 // name:     OSI Interface for SOPLEX
00004 // author:   Tobias Pfender
00005 //           Konrad-Zuse-Zentrum Berlin (Germany)
00006 //           email: pfender@zib.de
00007 // date:     01/16/2002
00008 //-----------------------------------------------------------------------------
00009 // Copyright (C) 2002, Tobias Pfender, International Business Machines
00010 // Corporation and others.  All Rights Reserved.
00011 
00012 #if defined(_MSC_VER)
00013 // Turn off compiler warning about long names
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 // A couple of helper functions
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 // Solve methods
00070 //#############################################################################
00071 
00072 void OsiSpxSolverInterface::initialSolve()
00073 {
00074   if( spxsolver_.type() != soplex::SoPlex::ENTER )
00075     spxsolver_.setType( soplex::SoPlex::ENTER );   // switch to primal simplex
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 );   // switch to dual simplex
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 // Parameter related methods
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       // SOPLEX doesn't support different termination values for primal and dual simplex
00136       // at the moment, setting a termination value is not supported in SOPLEX
00137       // spxsolver_.setTerminationValue( value );
00138       // retval = true;
00139       retval = false;
00140       break;
00141     case OsiPrimalObjectiveLimit:
00142       // SOPLEX doesn't support different termination values for primal and dual simplex
00143       // at the moment, setting a termination value is not supported in SOPLEX
00144       // spxsolver_.setTerminationValue( value );
00145       // retval = true;
00146       retval = false;
00147       break;
00148     case OsiDualTolerance:
00149       // ??? Is delta the correct SOPLEX equivalent of dual tolerance?
00150       // SOPLEX doesn't support different deltas for primal and dual simplex
00151       spxsolver_.setDelta( value );
00152       retval = true;
00153       break;
00154     case OsiPrimalTolerance:
00155       // ??? Is delta the correct SOPLEX equivalent of primal tolerance?
00156       // SOPLEX doesn't support different deltas for primal and dual simplex
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       // at the moment, setting a termination value is not supported in SOPLEX
00203       // value = spxsolver_.terminationValue();
00204       // retval = true;
00205       retval = false;
00206       break;
00207     case OsiPrimalObjectiveLimit:
00208       // at the moment, setting a termination value is not supported in SOPLEX
00209       // value = spxsolver_.terminationValue();
00210       // retval = true;
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 // Methods returning info on how the solution process terminated
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 // WarmStart related methods
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:  // unknown row status
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:  // unknown column status
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 // Hotstart related methods (primarily used in strong branching)
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 ) ); // get some extra space for future hot starts
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 ) ); // get some extra space for future hot starts
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   // be lazy with deallocating memory and do nothing here, deallocate memory in the destructor
00474 }
00475 
00476 //#############################################################################
00477 // Problem information methods (original data)
00478 //#############################################################################
00479 
00480 //------------------------------------------------------------------
00481 // Get number of rows, columns, elements, ...
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 // Get pointer to rim vectors
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       // rowsense is determined with rhs, so invoke rhs
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       // rowrange is determined with rhs, so invoke rhs
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 // Return information on integrality
00621 //------------------------------------------------------------------
00622 
00623 bool OsiSpxSolverInterface::isContinuous( int colNumber ) const
00624 {
00625   return( spxintvars_.number( colNumber ) < 0 );
00626 }
00627 
00628 //------------------------------------------------------------------
00629 // Row and column copies of the matrix ...
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 /* not column ordered */,
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 /* column ordered */,
00702                                   nrows, ncols, nelems,
00703                                   elements, indices, starts, len );      
00704     }
00705   return matrixByCol_;
00706 } 
00707 
00708 //------------------------------------------------------------------
00709 // Get solver's value for infinity
00710 //------------------------------------------------------------------
00711 double OsiSpxSolverInterface::getInfinity() const
00712 {
00713   return soplex::infinity;
00714 }
00715 
00716 //#############################################################################
00717 // Problem information methods (results)
00718 //#############################################################################
00719 
00720 // *FIXME*: what should be done if a certain vector doesn't exist???
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   // Adjust objective function value by constant term in objective function
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   // *FIXME* : must write the method
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   // *FIXME* : must write the method
00838   throw CoinError("method is not yet written", "getPrimalRays",
00839                   "OsiSpxSolverInterface");
00840   return std::vector<double*>();
00841 }
00842 
00843 //#############################################################################
00844 // Problem modifying methods (rim vectors)
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 // Problem modifying methods (matrix)
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 // Methods to input a problem
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   // create defaults if parameter is NULL
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   // copy problem into spxsolver_
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       /* insert empty rows */
01097       rowvec.clear();
01098       for( row = 0; row < nrows; ++row )
01099          rowset.add( therowlb[row], rowvec, therowub[row] );
01100       spxsolver_.addRows( rowset );
01101 
01102       /* create columns */
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       // spxsolver_.changeRange( soplex::Vector( nrows, therowlb ), soplex::Vector( nrows, therowub ) );
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       /* insert empty columns */
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       /* create rows */
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       // spxsolver_.changeObj( soplex::Vector( ncols, theobj ) );
01139       // spxsolver_.changeBounds( soplex::Vector( ncols, thecollb ), soplex::Vector( ncols, thecolub ) );
01140     }
01141 
01142   // switch sense to minimization problem
01143   spxsolver_.changeSense( soplex::SoPlex::MINIMIZE );
01144 
01145   // delete default arrays if neccessary
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 // Read mps files
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   // just call base class method
01319   return OsiSolverInterface::readMps(filename,extension);
01320 }
01321 
01322 //-----------------------------------------------------------------------------
01323 // Write mps files
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"; // SOPLEX cannot write MPS files yet! + "." + e;
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 // Constructors, destructors clone and assignment
01339 //#############################################################################
01340 
01341 //-------------------------------------------------------------------
01342 // Default Constructor 
01343 //-------------------------------------------------------------------
01344 OsiSpxSolverInterface::OsiSpxSolverInterface ()
01345   : OsiSolverInterface(),
01346     spxsolver_(soplex::SoPlex::ENTER, soplex::SoPlex::COLUMN), // default is primal simplex algorithm
01347     spxintvars_(),
01348     hotStartCStat_(NULL),
01349     hotStartCStatSize_(0),
01350     hotStartRStat_(NULL),
01351     hotStartRStatSize_(0),
01352     hotStartMaxIteration_(1000000), // ??? default iteration limit for strong branching is large
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 // Clone
01374 //----------------------------------------------------------------
01375 OsiSolverInterface * OsiSpxSolverInterface::clone(bool copyData) const
01376 {
01377   return( new OsiSpxSolverInterface( *this ) );
01378 }
01379 
01380 //-------------------------------------------------------------------
01381 // Copy constructor 
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   // spxsolver_.setTerminationValue( source.spxsolver_.terminationValue() ); // ???
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 // Destructor 
01418 //-------------------------------------------------------------------
01419 OsiSpxSolverInterface::~OsiSpxSolverInterface ()
01420 {
01421   freeAllMemory();
01422 }
01423 
01424 //----------------------------------------------------------------
01425 // Assignment operator 
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       // spxsolver_.setTerminationValue( source.spxsolver_.terminationValue() );
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 // Applying cuts
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 // Private methods (non-static and static)
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 }

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