00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <osl/diagnose.h>
00029
00030 #include "numeric/lpsimplex.hxx"
00031 #include "numeric/lpmodel.hxx"
00032 #include "tool/global.hxx"
00033
00034 #include <memory>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <algorithm>
00038 #include <vector>
00039 #include <map>
00040 #include <list>
00041
00042 using ::std::vector;
00043 using ::std::string;
00044 using ::std::cout;
00045 using ::std::endl;
00046
00047 namespace scsolver { namespace numeric { namespace lp {
00048
00049 typedef vector<size_t> uInt32Container;
00050 typedef uInt32Container::iterator uInt32Iter;
00051 typedef uInt32Container::const_iterator uInt32CIter;
00052
00053 typedef vector<BoundType> BoundContainer;
00054 typedef BoundContainer::iterator BoundIter;
00055 typedef BoundContainer::const_iterator BoundCIter;
00056
00057 class IllegalTwoPhaseSearch : public ::std::exception
00058 {
00059 virtual const char *what() const throw()
00060 {
00061 return "Illegal nested two phase search detected";
00062 }
00063 };
00064
00065
00066
00067
00068 class RevisedSimplexImpl
00069 {
00070 public:
00071 RevisedSimplexImpl( RevisedSimplex* );
00072 ~RevisedSimplexImpl();
00073
00074 void solve();
00075 void setEnableTwoPhaseSearch( bool b ) { m_bTwoPhaseAllowed = b; }
00076 bool isTwoPhaseSearchEnabled() { return m_bTwoPhaseAllowed; }
00077
00078 private:
00079 RevisedSimplex* m_pSelf;
00080
00081 bool m_bTwoPhaseAllowed;
00082
00083 Matrix m_aBasicInv;
00084 Matrix m_aUpdateMatrix;
00085 Matrix m_aPriceVector;
00086 Matrix m_aX;
00087 size_t m_nIter;
00088
00089 Model m_Model;
00090 Matrix m_A, m_B, m_C;
00091 std::vector<bool> m_aBasicVar;
00092 std::vector<size_t> m_aBasicVarId;
00093
00095 std::list<size_t> m_cnPermVarIndex;
00096
00097 struct ConstDecVar
00098 {
00099 size_t Id;
00100 double Value;
00101 };
00102 std::list<ConstDecVar> m_cnConstDecVarList;
00103
00104
00105
00106
00107 Model* getModel() const { return m_pSelf->getModel(); }
00108
00109 void convertVarRange( Model& );
00110 void runNormalInitSearch();
00111 void runTwoPhaseInitSearch( const std::vector<size_t>& );
00112 void printIterateHeader() const;
00113 bool iterate();
00114
00115 Matrix solvePriceVector( std::vector<size_t>, const Matrix&, const Matrix& );
00116 void getLambda( const Matrix&, const Matrix&, double&, size_t& ) const;
00117 };
00118
00119
00120 RevisedSimplexImpl::RevisedSimplexImpl( RevisedSimplex* p ) : m_pSelf( p ),
00121 m_bTwoPhaseAllowed( true ),
00122 m_aBasicInv( 0, 0 ), m_aUpdateMatrix( 0, 0 ), m_aPriceVector( 0, 0 ),
00123 m_aX( 0, 0 ), m_nIter( 0 )
00124 {
00125 }
00126
00127 RevisedSimplexImpl::~RevisedSimplexImpl()
00128 {
00129 }
00130
00139 void RevisedSimplexImpl::convertVarRange( Model& aModel )
00140 {
00141 size_t nColSize = aModel.getCostVector().cols();
00142
00143 for ( size_t i = 0; i < nColSize; ++i )
00144 {
00145 if ( aModel.isVarBounded( i, BOUND_LOWER ) )
00146 {
00147 double fLBound = aModel.getVarBound( i, BOUND_LOWER );
00148 cout << i << " lower bound: " << fLBound << endl;
00149
00150 vector<double> v( nColSize );
00151 v.at( i ) = 1.0;
00152 aModel.addConstraint( v, GREATER_EQUAL, fLBound );
00153 }
00154
00155 if ( aModel.isVarBounded( i, BOUND_UPPER ) )
00156 {
00157 double fUBound = aModel.getVarBound( i, BOUND_UPPER );
00158 cout << i << " upper bound: " << fUBound << endl;
00159
00160 vector<double> v( nColSize );
00161 v.at( i ) = 1.0;
00162 aModel.addConstraint( v, LESS_EQUAL, fUBound );
00163 }
00164 }
00165 }
00166
00167 void RevisedSimplexImpl::solve()
00168 {
00169
00170
00171
00172
00173
00174
00175
00176 Model aModel( *m_pSelf->getCanonicalModel() );
00177 convertVarRange( aModel );
00178 aModel.print();
00179 Matrix A( aModel.getConstraintMatrix() );
00180 Matrix B( aModel.getRhsVector() );
00181 Matrix C( aModel.getCostVector() );
00182
00183 for ( size_t i = 0; i < A.rows(); ++i )
00184 {
00185 EqualityType eEq = aModel.getEquality( i );
00186 switch( eEq )
00187 {
00188 case LESS_EQUAL:
00189 A( i, A.cols() ) = 1;
00190 break;
00191 case GREATER_EQUAL:
00192 A( i, A.cols() ) = -1;
00193 break;
00194 default:
00195 OSL_ASSERT( eEq == EQUAL );
00196 }
00197 if ( eEq != EQUAL )
00198 C( 0, C.cols() ) = 0;
00199 }
00200
00201 if ( !aModel.getVarPositive() )
00202 {
00203 if ( aModel.getVerbose() )
00204 cout << "non-positive variables are not yet supported" << endl;
00205 throw ModelInfeasible();
00206 }
00207
00208
00209 vector<size_t> aSatRows;
00210 vector<size_t> aNonSatRows;
00211 for ( size_t i = 0; i < A.rows(); ++i )
00212 aNonSatRows.push_back( i );
00213
00214
00215 vector<bool> aBasicVar;
00216 for ( size_t j = 0; j < A.cols(); ++j )
00217 {
00218 bool bNonZeroFound = false;
00219 long nUniqueRowSigned = -1;
00220 aBasicVar.push_back( false );
00221
00222
00223
00224
00225
00226 for ( size_t i = 0; i < A.rows(); ++i )
00227 if ( A( i, j ) != 0.0 )
00228 if ( bNonZeroFound )
00229 {
00230
00231 nUniqueRowSigned = -1;
00232 break;
00233 }
00234 else
00235 {
00236 bNonZeroFound = true;
00237 nUniqueRowSigned = i;
00238 }
00239
00240 if ( nUniqueRowSigned >= 0 )
00241 {
00242
00243
00244 size_t nUniqueRow = nUniqueRowSigned;
00245 double fVal = A( nUniqueRow, j );
00246 double fRHS = B( nUniqueRow, 0 );
00247
00248 if ( ( fVal >= 0.0 && fRHS >= 0.0 ) || ( fVal < 0.0 && fRHS < 0.0 ) )
00249 {
00250
00251 bool bDupMatch = false;
00252 vector<size_t>::iterator pos;
00253 pos = find( aSatRows.begin(), aSatRows.end(), nUniqueRow );
00254 if ( pos == aSatRows.end() )
00255 aSatRows.push_back( nUniqueRow );
00256 else
00257 bDupMatch = true;
00258
00259 pos = remove( aNonSatRows.begin(), aNonSatRows.end(), nUniqueRow );
00260 if ( pos != aNonSatRows.end() )
00261 aNonSatRows.erase( pos, aNonSatRows.end() );
00262 if ( !bDupMatch )
00263 aBasicVar[j] = true;
00264 }
00265 }
00266 }
00267
00268 if ( aModel.getVerbose() )
00269 {
00270 cout << "A:" << endl;
00271 A.print( 0 );
00272 cout << "B:" << endl;
00273 B.print( 0 );
00274 cout << "C:" << endl;
00275 C.print( 0 );
00276
00277 cout << "aSatRows: ";
00278 printElements( aSatRows, " " );
00279 cout << "\t" << "aNonSatRows: ";
00280 printElements( aNonSatRows, " " );
00281 cout << "\t" << "aBasicVar: ";
00282 printElements( aBasicVar, " " );
00283 cout << endl;
00284 }
00285
00286 m_aBasicVar = aBasicVar;
00287
00288 m_Model = aModel;
00289 m_A = A;
00290 m_B = B;
00291 m_C = C;
00292
00293 if ( aNonSatRows.size() > 0 )
00294 runTwoPhaseInitSearch( aNonSatRows );
00295 else
00296 runNormalInitSearch();
00297
00298
00299
00300 m_aUpdateMatrix.clear();
00301 m_aBasicVarId.clear();
00302 vector<bool>::iterator pos;
00303 for ( pos = m_aBasicVar.begin(); pos != m_aBasicVar.end(); ++pos )
00304 if ( *pos )
00305 m_aBasicVarId.push_back( distance( m_aBasicVar.begin(), pos ) );
00306
00307 m_aPriceVector = solvePriceVector( m_aBasicVarId, m_aBasicInv, C );
00308
00309
00310 m_nIter = 0;
00311 while ( !iterate() );
00312
00313 m_pSelf->setCanonicalSolution( m_aX );
00314 if ( m_Model.getVerbose() )
00315 {
00316 cout << "x = ";
00317 m_pSelf->getSolution().trans().print();
00318 }
00319 }
00320
00326 void RevisedSimplexImpl::runNormalInitSearch()
00327 {
00328
00329 if ( m_Model.getVerbose() )
00330 Debug( "two phase method NOT necessary" );
00331
00332 Matrix ABasic( m_A );
00333 vector<size_t> aNonBasicVarId;
00334 vector<bool>::iterator pos;
00335 for ( pos = m_aBasicVar.begin(); pos != m_aBasicVar.end(); ++pos )
00336 if ( !*pos )
00337 aNonBasicVarId.push_back( distance( m_aBasicVar.begin(), pos ) );
00338
00339 if ( m_Model.getVerbose() )
00340 {
00341 cout << "aNonBasicVarId: ";
00342 printElements( aNonBasicVarId );
00343 cout << endl;
00344 }
00345
00346 ABasic.deleteColumns( aNonBasicVarId );
00347 Matrix aBasicInv( ABasic.inverse() );
00348 Matrix XBasic = aBasicInv * m_B;
00349
00350 size_t nRow = 0;
00351 Matrix X( 0, 0 );
00352 for ( size_t j = 0; j < m_A.cols(); ++j )
00353 {
00354
00355 if ( m_aBasicVar.at(j) )
00356 X( j, 0 ) = XBasic( nRow++, 0 );
00357 else
00358 X( j, 0 ) = 0.0;
00359 }
00360
00361
00362
00363 m_aX = X;
00364 m_aBasicInv = aBasicInv;
00365 }
00366
00373 void RevisedSimplexImpl::runTwoPhaseInitSearch( const vector<size_t>& aNonSatRows )
00374 {
00375 if ( !m_bTwoPhaseAllowed )
00376 throw IllegalTwoPhaseSearch();
00377
00378 static const bool bDebugTwoPhase = false;
00379
00380 if ( m_Model.getVerbose() )
00381 Debug( "Entering a two-phase search for initial solution" );
00382
00383 Matrix A2( m_A );
00384
00385 cout << "initial number of column(s): " << A2.cols() << endl;
00386 vector<size_t>::const_iterator nIter, end = aNonSatRows.end();
00387 for ( nIter = aNonSatRows.begin(); nIter != end; ++nIter )
00388 {
00389 size_t nRowId = *nIter;
00390 if ( m_B( nRowId, 0 ) >= 0 )
00391 A2( nRowId, A2.cols() ) = 1;
00392 else
00393 A2( nRowId, A2.cols() ) = -1;
00394 }
00395
00396 cout << A2.cols() - m_A.cols() << " column(s) added" << endl;
00397
00398 auto_ptr<Model> model( new Model );
00399 model->setGoal( GOAL_MINIMIZE );
00400 model->setStandardConstraintMatrix( A2, m_B );
00401 model->setVarPositive( true );
00402 for ( size_t i = 0; i < A2.cols(); ++i )
00403 if ( i < m_A.cols() )
00404 model->setCostVectorElement( i, 0 );
00405 else
00406 model->setCostVectorElement( i, 1 );
00407
00408 if ( bDebugTwoPhase )
00409 model->print();
00410
00411 model->setVerbose( bDebugTwoPhase );
00412 auto_ptr<BaseAlgorithm> algorithm( new RevisedSimplex );
00413
00414
00415
00416 static_cast<RevisedSimplex*>(algorithm.get())->setEnableTwoPhaseSearch( false );
00417
00418 algorithm->setModel( model.get() );
00419 algorithm->solve();
00420 Matrix Xtmp( algorithm->getSolution() );
00421
00422 size_t nANumRow = m_A.rows(), nANumCol = m_A.cols(), nA2NumCol = A2.cols();
00423 for ( size_t i = nANumCol; i < nA2NumCol; ++i )
00424 {
00425 double f = Xtmp( i, 0 );
00426 cout << "f = " << f << endl;
00427 if ( f != 0.0 )
00428 throw ModelInfeasible();
00429 }
00430
00431 Matrix X( 0, 0 );
00432 vector<size_t> aNonBasicVarId;
00433 vector<bool> aBasicVar( m_aBasicVar );
00434
00435 size_t i = nANumCol;
00436 do
00437 {
00438 double f = Xtmp( --i, 0 );
00439 X( i, 0 ) = f;
00440 if ( aNonBasicVarId.size() < nANumCol - nANumRow && f == 0.0 )
00441 {
00442 aBasicVar[i] = false;
00443 aNonBasicVarId.push_back( i );
00444 }
00445 else
00446 aBasicVar[i] = true;
00447 }
00448 while ( i != 0 );
00449
00450 sort( aNonBasicVarId.begin(), aNonBasicVarId.end() );
00451 cout << "aNonBasicVarId = ";
00452 printElements( aNonBasicVarId, " " );
00453
00454 Matrix ABasic( m_A );
00455 ABasic.print( 0 );
00456
00457 cout << "(" << ABasic.rows() << "," << ABasic.cols() << ")" << endl;
00458
00459 ABasic.deleteColumns( aNonBasicVarId );
00460 ABasic.print( 0 );
00461
00462 cout << "(" << ABasic.rows() << "," << ABasic.cols() << ")" << endl;
00463
00464 Matrix aBasicInv( ABasic.inverse() );
00465 cout << "inverse" << endl;
00466 aBasicInv.print();
00467
00468
00469
00470 m_aBasicVar = aBasicVar;
00471 m_aX = X;
00472 m_aBasicInv = aBasicInv;
00473
00474 if ( m_Model.getVerbose() )
00475 Debug( "Two-phase search found an initial solution" );
00476 }
00477
00478 void RevisedSimplexImpl::printIterateHeader() const
00479 {
00480 cout << endl;
00481 string line = repeatString( "-", 70 );
00482
00483 cout << line << endl;
00484 cout << "Iteration " << m_nIter << endl;
00485 cout << line << endl;
00486
00487 cout << "Basic Variable: ";
00488 printElements( m_aBasicVar );
00489 cout << endl;
00490
00491 cout << "x(" << m_nIter << ") = ";
00492 m_aX.trans().print( m_Model.getPrecision() );
00493 cout << "cx = " << (m_C*m_aX).operator()( 0, 0 ) << endl;
00494 cout << line << endl;
00495
00496 cout << "Basic Variable ID: ";
00497 printElements( m_aBasicVarId, " " );
00498 cout << endl << endl;;
00499
00500 cout << "A^(-1)" << endl;
00501 m_aBasicInv.print();
00502
00503 cout << endl << "v = ";
00504 m_aPriceVector.print();
00505 }
00506
00507 bool RevisedSimplexImpl::iterate()
00508 {
00509 bool bVerbose = m_Model.getVerbose();
00510 if ( bVerbose )
00511 printIterateHeader();
00512
00513
00514
00515
00516
00517 vector<size_t> aNonBasicVarId;
00518 vector<bool>::iterator bIter;
00519 for ( bIter = m_aBasicVar.begin(); bIter != m_aBasicVar.end(); ++bIter )
00520 if ( !*bIter )
00521 aNonBasicVarId.push_back( distance( m_aBasicVar.begin(), bIter ) );
00522
00523
00524 vector<size_t>::iterator nIter, nBegin = aNonBasicVarId.begin(), nEnd = aNonBasicVarId.end();
00525 map<size_t,double> fEnterBasicVars;
00526 double fMin, fMax;
00527 size_t nMin, nMax;
00528 for ( nIter = nBegin; nIter != nEnd; ++nIter )
00529 {
00530 size_t nId = *nIter;
00531 double fPrice = m_C( 0, nId ) -
00532 ( m_aPriceVector*m_A.getColumn( nId ) ).operator()( 0, 0 );
00533
00534 if ( bVerbose )
00535 cout << "c(" << nId << ") = " << fPrice << endl;
00536
00537 fEnterBasicVars.insert( make_pair( nId, fPrice ) );
00538 if ( nIter == nBegin )
00539 {
00540 fMin = fMax = fPrice;
00541 nMin = nMax = nId;
00542 }
00543 else
00544 {
00545 if ( fPrice > fMax )
00546 {
00547 fMax = fPrice;
00548 nMax = nId;
00549 }
00550 if ( fPrice < fMin )
00551 {
00552 fMin = fPrice;
00553 nMin = nId;
00554 }
00555 }
00556 }
00557
00558 GoalType eGoal = m_Model.getGoal();
00559 if ( ( eGoal == GOAL_MAXIMIZE && fMax <= 0.0 ) ||
00560 ( eGoal == GOAL_MINIMIZE && fMin >= 0.0 ) )
00561 {
00562 if ( bVerbose )
00563 cout << "Optimum solution reached" << endl;
00564 return true;
00565 }
00566
00567 size_t nEnterVarId = 0;
00568 if ( eGoal == GOAL_MAXIMIZE )
00569 nEnterVarId = nMax;
00570 else if ( eGoal == GOAL_MINIMIZE )
00571 nEnterVarId = nMin;
00572 else
00573 throw;
00574
00575
00576 Matrix dXBasic = m_aBasicInv * m_A.getColumn( nEnterVarId ) * (-1);
00577 Matrix dX( 0, 0 );
00578
00579 OSL_ASSERT( dXBasic.rows() == m_aBasicVarId.size() );
00580
00581 for ( size_t i = 0; i < dXBasic.rows(); ++i )
00582 dX( m_aBasicVarId.at( i ), 0 ) = dXBasic( i, 0 );
00583
00584 nEnd = aNonBasicVarId.end();
00585 for ( nIter = aNonBasicVarId.begin(); nIter != nEnd; ++nIter )
00586 {
00587 size_t nId = *nIter;
00588 dX( nId, 0 ) = nId == nEnterVarId ? 1.0 : 0.0;
00589 }
00590 if ( bVerbose )
00591 {
00592 cout << "dX[" << nEnterVarId << "] = ";
00593 dX.trans().print( m_Model.getPrecision() );
00594 }
00595
00596
00597
00598 bool bNegativeFound = false;
00599 for ( size_t i = 0; i < dX.rows(); ++i )
00600 if ( dX( i, 0 ) < 0.0 )
00601 {
00602 bNegativeFound = true;
00603 break;
00604 }
00605
00606 if ( !bNegativeFound )
00607 {
00608 if ( bVerbose )
00609 cout << "Unbounded model with no solution" << endl;
00610 throw ModelInfeasible();
00611 }
00612
00613
00614 double fLambda;
00615 size_t nLeaveVarId;
00616 getLambda( m_aX, dX, fLambda, nLeaveVarId );
00617
00618 if ( bVerbose )
00619 cout << "lambda = " << fLambda << " x" << nEnterVarId << " enters and "
00620 << "x" << nLeaveVarId << " leaves" << endl;
00621
00622 m_aX += dX*fLambda;
00623 m_aBasicVar[nEnterVarId].flip();
00624 m_aBasicVar[nLeaveVarId].flip();
00625 size_t nIndexLeaveVar;
00626 for ( nIter = m_aBasicVarId.begin(); nIter < m_aBasicVarId.end(); ++nIter )
00627 if ( *nIter == nLeaveVarId )
00628 {
00629 nIndexLeaveVar = distance( m_aBasicVarId.begin(), nIter );
00630 *nIter = nEnterVarId;
00631 break;
00632 }
00633
00634 Matrix E( m_aBasicInv.rows(), m_aBasicInv.cols(), true );
00635 double fLeaveVar = dX( nLeaveVarId, 0 );
00636 for ( size_t i = 0; i < E.rows(); ++i )
00637 {
00638 int nId = m_aBasicVarId.at( i );
00639 double fdXVal = dX( nId, 0 );
00640 if ( i == nIndexLeaveVar )
00641 E( i, i ) = 1.0/fLeaveVar*(-1.0);
00642 else
00643 E( i, nIndexLeaveVar ) = fdXVal / fLeaveVar * (-1.0);
00644 }
00645
00646
00647 m_aBasicInv = E*m_aBasicInv;
00648 m_aPriceVector = solvePriceVector( m_aBasicVarId, m_aBasicInv, m_C );
00649 ++m_nIter;
00650
00651 return false;
00652 }
00653
00654 Matrix RevisedSimplexImpl::solvePriceVector( std::vector<size_t> aBasicVarId,
00655 const Matrix& AInv, const Matrix& C )
00656 {
00657 Matrix c;
00658 std::vector<size_t>::iterator pos;
00659 for ( pos = aBasicVarId.begin(); pos != aBasicVarId.end(); ++pos )
00660 {
00661 size_t i = distance( aBasicVarId.begin(), pos );
00662 double f = C( 0, aBasicVarId.at( i ) );
00663 c( 0, i ) = f;
00664 }
00665 return c*AInv;
00666 }
00667
00668 void RevisedSimplexImpl::getLambda( const Matrix& X, const Matrix& dX,
00669 double& rLambda, size_t& rLeaveVarId ) const
00670 {
00671 OSL_ASSERT( X.rows() == dX.rows() );
00672
00673 double fLambda = 0.0;
00674 size_t nId = 0;
00675 bool bFirst = true;
00676 for ( size_t i = 0; i < X.rows(); ++i )
00677 {
00678 double fXVal = X( i, 0 );
00679 double fdXVal = dX( i, 0 );
00680 if ( fdXVal < 0 )
00681 {
00682 double fVal = fXVal / fdXVal * (-1.0);
00683 if ( bFirst )
00684 {
00685 fLambda = fVal;
00686 nId = i;
00687 bFirst = false;
00688 }
00689 else
00690 {
00691 if ( fVal < fLambda )
00692 {
00693 fLambda = fVal;
00694 nId = i;
00695 }
00696 }
00697 }
00698 }
00699
00700 rLambda = fLambda;
00701 rLeaveVarId = nId;
00702 }
00703
00704
00705
00706
00707
00708 RevisedSimplex::RevisedSimplex() : BaseAlgorithm(),
00709 m_pImpl( new RevisedSimplexImpl( this ) )
00710 {
00711 }
00712
00713 RevisedSimplex::~RevisedSimplex() throw()
00714 {
00715 }
00716
00717 void RevisedSimplex::solve()
00718 {
00719 m_pImpl->solve();
00720 }
00721
00722 void RevisedSimplex::setEnableTwoPhaseSearch( bool b )
00723 {
00724 m_pImpl->setEnableTwoPhaseSearch( b );
00725 }
00726
00727
00728
00729
00730 typedef std::list<size_t> SizeTypeContainer;
00731
00732 class BoundedRevisedSimplexImpl
00733 {
00734 public:
00735 BoundedRevisedSimplexImpl( BoundedRevisedSimplex* );
00736 ~BoundedRevisedSimplexImpl();
00737
00738 void solve();
00739
00740 private:
00741
00747 struct VarBoundary
00748 {
00749 size_t Id;
00750 double Value;
00751 BoundType BoundData;
00752 };
00753
00754 struct EnterBasicVar
00755 {
00756 size_t Id;
00757 double Price;
00758 BoundType BoundData;
00759 };
00760
00761 BoundedRevisedSimplex* m_pSelf;
00762
00763 Matrix m_mxBasicInv;
00764 Matrix m_mxUpdateMatrix;
00765 Matrix m_mxPriceVector;
00766 Matrix m_mxX;
00767 size_t m_nIter;
00768
00769 Matrix m_mxA, m_mxB, m_mxC;
00770 std::vector<bool> m_aBasicVar;
00771 SizeTypeContainer m_aBasicVarId;
00772 SizeTypeContainer m_aNonBasicVarId;
00773 std::vector<size_t> m_aSkipBasicVarId;
00774 std::vector<BoundType> m_aNonBasicVarBoundType;
00775
00776 std::auto_ptr<Model> m_pModel;
00777
00778 Model* getModel() const { return m_pSelf->getModel(); }
00779
00780 bool findInitialSolution();
00781 bool buildInitialVars( vector<VarBoundary>& );
00782 void initialize();
00783 bool iterateVarBoundary( size_t, size_t, vector<VarBoundary>& );
00784 bool isSolutionFeasible( const Matrix& ) const;
00785 const Matrix solvePriceVector( const SizeTypeContainer&, const Matrix&, const Matrix& ) const;
00786
00787 bool iterate();
00788 bool queryEnteringNBVar( EnterBasicVar& );
00789 void calculateNewX( const EnterBasicVar&, size_t&, Matrix& );
00790 void updateNBVars( const EnterBasicVar&, size_t );
00791 void updateInverseBasicMatrix( const EnterBasicVar&, size_t, const Matrix& );
00792 void printIterateHeader() const;
00793 bool isPriceBoundEligible( const EnterBasicVar& ) const;
00794 void getLambda( const Matrix&, const Matrix&, double&, size_t& ) const;
00795
00796 };
00797
00798 BoundedRevisedSimplexImpl::BoundedRevisedSimplexImpl( BoundedRevisedSimplex* p ) :
00799 m_pSelf( p ), m_mxBasicInv( 0, 0 ), m_mxUpdateMatrix( 0, 0 ), m_mxPriceVector( 0, 0 ),
00800 m_mxX( 0, 0 ), m_nIter( 0 ), m_mxA( 0, 0 ), m_mxB( 0, 0 ), m_mxC( 0, 0 )
00801 {
00802 }
00803
00804 BoundedRevisedSimplexImpl::~BoundedRevisedSimplexImpl()
00805 {
00806 }
00807
00808 void BoundedRevisedSimplexImpl::solve()
00809 {
00810 initialize();
00811
00812 if ( !findInitialSolution() )
00813 {
00814 if ( m_pModel->getVerbose() )
00815 cout << "Initial solution not found" << endl;
00816 throw ModelInfeasible();
00817 }
00818
00819 if ( m_pModel->getVerbose() )
00820 cout << "Initial solution found" << endl;
00821
00822 m_mxPriceVector = solvePriceVector( m_aBasicVarId, m_mxBasicInv, m_mxC );
00823
00824 m_nIter = 0;
00825 m_aSkipBasicVarId.clear();
00826
00827 while ( !iterate() );
00828
00829 Matrix mxSolution;
00830 for ( size_t i = 0; i < m_pModel->getCostVector().cols(); ++i )
00831 mxSolution( i, 0 ) = m_mxX( i, 0 );
00832
00833 if ( m_pModel->getVerbose() )
00834 {
00835 cout << "x = ";
00836 mxSolution.trans().print();
00837 }
00838
00839 #ifdef DEBUG
00840 if ( isSolutionFeasible( mxSolution ) )
00841 Debug( "Double-checked to make sure the solution is feasible" );
00842 else
00843 Debug( "Solution not feasible!?" );
00844 #endif
00845
00846 m_pSelf->setCanonicalSolution( mxSolution );
00847 }
00848
00849 void BoundedRevisedSimplexImpl::initialize()
00850 {
00851
00852
00853
00854
00855
00856
00857
00858 m_mxBasicInv.clear();
00859 m_mxUpdateMatrix.clear();
00860
00861 auto_ptr<Model> ptr( new Model( *m_pSelf->getCanonicalModel() ) );
00862 m_pModel = ptr;
00863
00864 m_mxA = m_pModel->getConstraintMatrix();
00865 m_mxB = m_pModel->getRhsVector();
00866 m_mxC = m_pModel->getCostVector();
00867
00868
00869
00870
00871 if ( m_mxA.cols() < m_mxC.cols() )
00872 {
00873 size_t nNewCol = m_mxA.cols();
00874 nNewCol += m_mxC.cols() - m_mxA.cols();
00875 m_mxA.resize( m_mxA.rows(), nNewCol );
00876 }
00877
00878 const size_t nRowSizeA = m_mxA.rows();
00879 for ( size_t i = 0; i < nRowSizeA; ++i )
00880 {
00881 EqualityType eEq = m_pModel->getEquality( i );
00882 switch( eEq )
00883 {
00884 case LESS_EQUAL:
00885 m_mxA( i, m_mxA.cols() ) = 1;
00886 break;
00887 case GREATER_EQUAL:
00888 m_mxA( i, m_mxA.cols() ) = -1;
00889 break;
00890 default:
00891 OSL_ASSERT( eEq == EQUAL );
00892 }
00893 if ( eEq != EQUAL )
00894 {
00895 size_t nCol = m_mxC.cols();
00896 m_pModel->setCostVectorElement( nCol, 0 );
00897 m_pModel->setVarBound( nCol, BOUND_LOWER, 0 );
00898 m_mxC( 0, nCol ) = 0;
00899 }
00900 }
00901
00902 if ( m_pModel->getVerbose() )
00903 {
00904 m_pModel->print();
00905 cout << "A:" << endl;
00906 m_mxA.print();
00907 cout << "B:" << endl;
00908 m_mxB.print();
00909 cout << "C:" << endl;
00910 m_mxC.print();
00911 }
00912 }
00913
00914 void BoundedRevisedSimplexImpl::printIterateHeader() const
00915 {
00916 cout << endl;
00917 string line = repeatString( "-", 70 );
00918
00919 cout << line << endl;
00920 cout << "Iteration " << m_nIter << endl;
00921 cout << line << endl;
00922
00923 cout << "x(" << m_nIter << ") = ";
00924 m_mxX.trans().print( getModel()->getPrecision() );
00925 cout << "cx = " << (m_mxC*m_mxX).operator()( 0, 0 ) << endl;
00926 cout << line << endl;
00927
00928 cout << "Basic Variable ID: ";
00929 printElements( m_aBasicVarId );
00930 cout << endl << endl;;
00931
00932 SizeTypeContainer::const_iterator itr,
00933 itrBeg = m_aNonBasicVarId.begin(),
00934 itrEnd = m_aNonBasicVarId.end();
00935 for ( itr = itrBeg; itr != itrEnd; ++itr )
00936 {
00937 cout << *itr << ": ";
00938 int idx = distance( itrBeg, itr );
00939 switch ( m_aNonBasicVarBoundType.at( idx ) )
00940 {
00941 case BOUND_LOWER:
00942 cout << "L" << endl;
00943 break;
00944 case BOUND_UPPER:
00945 cout << "U" << endl;
00946 break;
00947 default:
00948 OSL_ASSERT( !"wrong bound type" );
00949 }
00950 }
00951 cout << endl;
00952
00953 cout << "A^(-1) (shortcut calculation)" << endl;
00954 m_mxBasicInv.print();
00955
00956 cout << endl << "v = ";
00957 m_mxPriceVector.print();
00958 }
00959
00960 bool BoundedRevisedSimplexImpl::isPriceBoundEligible( const EnterBasicVar& aVar ) const
00961 {
00962 bool b;
00963
00964 switch ( m_pModel->getGoal() )
00965 {
00966 case GOAL_MAXIMIZE:
00967
00968
00969
00970 b = ( aVar.Price > 0.0 && aVar.BoundData == BOUND_LOWER ) ||
00971 ( aVar.Price < 0.0 && aVar.BoundData == BOUND_UPPER );
00972 break;
00973
00974 case GOAL_MINIMIZE:
00975
00976
00977
00978 b = ( aVar.Price < 0.0 && aVar.BoundData == BOUND_LOWER ) ||
00979 ( aVar.Price > 0.0 && aVar.BoundData == BOUND_UPPER );
00980 break;
00981 default:
00982 OSL_ASSERT( !"wrong goal" );
00983 }
00984
00985 return b;
00986 }
00987
00988 void BoundedRevisedSimplexImpl::getLambda( const Matrix& X, const Matrix& dX,
00989 double& rLambda, size_t& rLeaveVarId ) const
00990 {
00991 OSL_ASSERT( X.rows() == dX.rows() );
00992 double fLmdPos = 0.0, fLmdNeg = 0.0, fLmd = 0.0;
00993 size_t nId;
00994
00995 for ( size_t i = 0; i < X.rows(); ++i )
00996 {
00997 double fXVal = X( i, 0 );
00998 double fdXVal = dX( i, 0 );
00999 if ( fdXVal > 0.0 && m_pModel->isVarBounded( i, BOUND_UPPER ) )
01000 {
01001
01002 double fUpper = m_pModel->getVarBound( i, BOUND_UPPER );
01003 double fTmp = ( fUpper - fXVal ) / fdXVal;
01004 if ( ( fLmdPos != 0.0 && fLmdPos > fTmp ) || fLmdPos == 0.0 )
01005 {
01006 cout << "pos: " << fTmp << " " << i << endl;
01007 fLmdPos = fTmp;
01008 }
01009 }
01010 else if ( fdXVal < 0.0 && m_pModel->isVarBounded( i, BOUND_LOWER ) )
01011 {
01012
01013 double fLower = m_pModel->getVarBound( i, BOUND_LOWER );
01014 double fTmp = ( fXVal - fLower ) / ( fdXVal*(-1) );
01015 if ( ( fLmdNeg != 0.0 && fLmdNeg > fTmp ) || fLmdNeg == 0.0 )
01016 {
01017 cout << "neg: " << fTmp << " " << i << endl;
01018 fLmdNeg = fTmp;
01019 }
01020 }
01021
01022 double fLmdTmp;
01023 if ( fLmdPos != 0.0 && fLmdNeg != 0.0 )
01024 fLmdTmp = min( fLmdPos, fLmdNeg );
01025 else if ( fLmdPos != 0.0 )
01026 fLmdTmp = fLmdPos;
01027 else if ( fLmdNeg != 0.0 )
01028 fLmdTmp = fLmdNeg;
01029 else
01030 fLmdTmp = 0.0;
01031
01032 if ( ( fLmdTmp != 0.0 && fLmdTmp < fLmd ) || fLmd == 0.0 )
01033 {
01034 fLmd = fLmdTmp;
01035 nId = i;
01036 }
01037 }
01038 std::swap( fLmd, rLambda );
01039 std::swap( nId, rLeaveVarId );
01040 }
01041
01042 bool BoundedRevisedSimplexImpl::iterate()
01043 {
01044 if ( getModel()->getVerbose() )
01045 printIterateHeader();
01046
01047 EnterBasicVar aEnterVar;
01048 if ( queryEnteringNBVar( aEnterVar ) )
01049 return true;
01050
01051 size_t nLeaveVarId;
01052 Matrix mxDX;
01053 calculateNewX( aEnterVar, nLeaveVarId, mxDX );
01054 updateNBVars( aEnterVar, nLeaveVarId );
01055 updateInverseBasicMatrix( aEnterVar, nLeaveVarId, mxDX );
01056
01057 ++m_nIter;
01058 return false;
01059 }
01060
01066 bool BoundedRevisedSimplexImpl::queryEnteringNBVar( EnterBasicVar& rEnterVar )
01067 {
01068 SizeTypeContainer aEnterBasicVarId;
01069 vector<EnterBasicVar> aEnterBasicVars;
01070
01071 SizeTypeContainer::const_iterator itr,
01072 itrBeg = m_aNonBasicVarId.begin(),
01073 itrEnd = m_aNonBasicVarId.end();
01074
01075
01076
01077 for ( itr = itrBeg; itr != itrEnd; ++itr )
01078 {
01079 size_t nId = *itr;
01080
01081
01082 if ( m_pModel->isVarBounded( nId, BOUND_LOWER ) )
01083 {
01084 double fBoundVal = m_pModel->getVarBound( nId, BOUND_LOWER );
01085 if ( m_pModel->isVarBounded( nId, BOUND_UPPER ) &&
01086 fBoundVal == m_pModel->getVarBound( nId, BOUND_UPPER ) )
01087 {
01088 Debug( "queryEnteringNBVar: Constant equivalent variable found" );
01089 continue;
01090 }
01091 }
01092
01093 EnterBasicVar aVar;
01094 aEnterBasicVarId.push_back( nId );
01095 aVar.Id = nId;
01096
01097 aVar.BoundData = m_aNonBasicVarBoundType.at(
01098 distance( itrBeg, itr ) );
01099
01100
01101 aVar.Price = m_mxC( 0, nId ) -
01102 ( m_mxPriceVector*m_mxA.getColumn( nId ) ).operator()( 0, 0 );
01103
01104 if ( getModel()->getVerbose() )
01105 cout << "c(" << aVar.Id << ") = " << aVar.Price << endl;
01106 aEnterBasicVars.push_back( aVar );
01107 }
01108
01109 bool bFirstEnterVarFound = false;
01110 itrBeg = aEnterBasicVarId.begin();
01111 itrEnd = aEnterBasicVarId.end();
01112 for ( itr = itrBeg; itr != itrEnd; ++itr )
01113 {
01114 size_t i = distance( itrBeg, itr );
01115 EnterBasicVar aVar = aEnterBasicVars.at( i );
01116 OSL_ASSERT( aVar.Id == *itr );
01117
01118 if ( isPriceBoundEligible( aVar ) )
01119 {
01120 if ( !bFirstEnterVarFound )
01121 {
01122 bFirstEnterVarFound = true;
01123 rEnterVar = aVar;
01124 }
01125 else if ( abs( rEnterVar.Price ) < abs( aVar.Price ) )
01126 rEnterVar = aVar;
01127 }
01128 }
01129
01130 if ( !bFirstEnterVarFound )
01131 {
01132 if ( getModel()->getVerbose() )
01133 cout << "Optimum solution reached" << endl;
01134 return true;
01135 }
01136 return false;
01137 }
01138
01144 void BoundedRevisedSimplexImpl::calculateNewX( const EnterBasicVar& aEnterVar,
01145 size_t& nLeaveVarId, Matrix& mxDX )
01146 {
01147 Matrix mxB = m_mxA.getColumn( aEnterVar.Id );
01148 if ( aEnterVar.BoundData == BOUND_LOWER )
01149 mxB *= (-1);
01150
01151 Matrix dXBasic( m_mxBasicInv*mxB );
01152
01153 Matrix dX;
01154 SizeTypeContainer::const_iterator itr,
01155 itrBeg = m_aBasicVarId.begin(), itrEnd = m_aBasicVarId.end();
01156 for ( itr = itrBeg; itr != itrEnd; ++itr )
01157 dX( *itr, 0 ) = dXBasic( distance( itrBeg, itr ), 0 );
01158
01159 itrBeg = m_aNonBasicVarId.begin(), itrEnd = m_aNonBasicVarId.end();
01160
01161 for ( itr = itrBeg; itr != itrEnd; ++itr )
01162 {
01163 size_t nId = *itr;
01164 if ( nId == aEnterVar.Id )
01165 {
01166 switch ( aEnterVar.BoundData )
01167 {
01168 case BOUND_LOWER:
01169 dX( nId, 0 ) = 1.0;
01170 break;
01171 case BOUND_UPPER:
01172 dX( nId, 0 ) = -1.0;
01173 break;
01174 default:
01175 OSL_ASSERT( !"wrong bound type" );
01176 }
01177 }
01178 else
01179 dX( nId, 0 ) = 0.0;
01180 }
01181
01182 if ( getModel()->getVerbose() )
01183 {
01184 cout << "dX[" << aEnterVar.Id << "] = ";
01185 dX.trans().print( getModel()->getPrecision() );
01186 }
01187
01188 double fLambda;
01189 getLambda( m_mxX, dX, fLambda, nLeaveVarId );
01190
01191 if ( fLambda == 0.0 )
01192 {
01193 if ( m_pModel->getVerbose() )
01194 cout << "Unbounded model with no solution";
01195 throw ModelInfeasible();
01196 }
01197
01198 if ( m_pModel->getVerbose() )
01199 cout << "lambda = " << fLambda << " x_" << nLeaveVarId << " leaves and x_"
01200 << aEnterVar.Id << " enters" << endl;
01201
01202 m_mxX += dX*fLambda;
01203 mxDX = dX;
01204 }
01205
01209 void BoundedRevisedSimplexImpl::updateNBVars( const EnterBasicVar& aEnterVar, size_t nLeaveVarId )
01210 {
01211
01212
01213
01214 SizeTypeContainer::iterator itr,
01215 itrBeg = m_aNonBasicVarId.begin(),
01216 itrEnd = m_aNonBasicVarId.end();
01217
01218 BoundIter itr2,
01219 itr2Beg = m_aNonBasicVarBoundType.begin(),
01220 itr2End = m_aNonBasicVarBoundType.end();
01221
01222 for ( itr = itrBeg, itr2 = itr2Beg ; itr != itrEnd; ++itr, ++itr2 )
01223 if ( *itr == aEnterVar.Id )
01224 {
01225 OSL_ASSERT( *itr2 == aEnterVar.BoundData );
01226 m_aNonBasicVarId.erase( itr );
01227 m_aNonBasicVarBoundType.erase( itr2 );
01228 break;
01229 }
01230 OSL_ASSERT ( itr != itrEnd && itr2 != itr2End );
01231
01232
01233
01234
01235 if ( m_pModel->isVarBounded( nLeaveVarId, BOUND_LOWER ) &&
01236 m_mxX( nLeaveVarId, 0 ) == m_pModel->getVarBound( nLeaveVarId, BOUND_LOWER ) )
01237 {
01238 m_aNonBasicVarId.push_back( nLeaveVarId );
01239 m_aNonBasicVarBoundType.push_back( BOUND_LOWER );
01240 }
01241 else if ( m_pModel->isVarBounded( nLeaveVarId, BOUND_UPPER ) &&
01242 m_mxX( nLeaveVarId, 0 ) == m_pModel->getVarBound( nLeaveVarId, BOUND_UPPER ) )
01243 {
01244 m_aNonBasicVarId.push_back( nLeaveVarId );
01245 m_aNonBasicVarBoundType.push_back( BOUND_UPPER );
01246 }
01247
01248 OSL_ASSERT( m_pModel->isVarBounded( nLeaveVarId, BOUND_LOWER ) ||
01249 m_pModel->isVarBounded( nLeaveVarId, BOUND_UPPER ) );
01250 }
01251
01252 void BoundedRevisedSimplexImpl::updateInverseBasicMatrix( const EnterBasicVar& aEnterVar, size_t nLeaveVarId, const Matrix& mxDX )
01253 {
01254
01255
01256
01257 SizeTypeContainer::iterator itrBeg = m_aBasicVarId.begin(), itrEnd = m_aBasicVarId.end();
01258 SizeTypeContainer::iterator itr = find( itrBeg, itrEnd, nLeaveVarId );
01259 if ( itr != itrEnd )
01260 {
01261 *itr = aEnterVar.Id;
01262 size_t nIndexLeaveVar = distance( itrBeg, itr );
01263 OSL_ASSERT( m_mxBasicInv.isSquare() );
01264 Matrix mxE( m_mxBasicInv.rows(), m_mxBasicInv.cols(), true );
01265 double fLeaveVar = mxDX( nLeaveVarId, 0 );
01266
01267 for ( SizeTypeContainer::iterator itr2 = itrBeg;
01268 itr2 != itrEnd; ++itr2 )
01269 {
01270 size_t nBVarId = *itr2, nRowId = distance( itrBeg, itr2 );
01271 double fDXVal = mxDX( nBVarId, 0 );
01272 if ( nRowId == nIndexLeaveVar )
01273 if ( aEnterVar.BoundData == BOUND_LOWER )
01274 mxE( nRowId, nRowId ) = -1.0 / fLeaveVar;
01275 else
01276 mxE( nRowId, nRowId ) = 1.0 / fLeaveVar;
01277 else
01278 mxE( nRowId, nIndexLeaveVar ) = fDXVal / fLeaveVar * (-1.0);
01279 }
01280
01281 if ( m_pModel->getVerbose() )
01282 {
01283 cout << "E:";
01284 mxE.print( m_pModel->getPrecision() );
01285 }
01286
01287 m_mxBasicInv = mxE * m_mxBasicInv;
01288 m_mxPriceVector = solvePriceVector( m_aBasicVarId, m_mxBasicInv, m_mxC );
01289 }
01290 }
01291
01299 bool BoundedRevisedSimplexImpl::findInitialSolution()
01300 {
01301 m_pModel->print();
01302 size_t nNumInitNonBasic = m_mxA.cols() - m_mxB.rows();
01303 if ( m_pModel->getVerbose() )
01304 {
01305 const string line = repeatString( "-", 70 );
01306 cout << endl << line << endl;
01307 cout << "Initial solution search" << endl << line << endl;
01308 cout << "nNumInitNonBasic = " << nNumInitNonBasic << endl;
01309 }
01310
01311 vector<VarBoundary> aArray;
01312 return iterateVarBoundary( 0, nNumInitNonBasic, aArray );
01313 }
01314
01335 bool BoundedRevisedSimplexImpl::buildInitialVars( vector<VarBoundary>& cnNonBasic )
01336 {
01337 Debug( "buildInitialVars" );
01338 Debug( "mxA" );
01339 m_mxA.print();
01340 Debug( "mxB" );
01341 m_mxB.print();
01342 Debug( "mxC" );
01343 m_mxC.print();
01344
01345 size_t nCostSize = m_mxC.cols();
01346
01347 std::list<size_t> cnBasicId;
01348 for ( size_t i = 0; i < nCostSize; ++i )
01349 cnBasicId.push_back( i );
01350
01351 Matrix mxInitX( nCostSize, 1 );
01352
01353 Debug( "All IDs: " );
01354 printElements( cnBasicId );
01355
01356 Matrix mxLHSSum( m_mxA.rows(), 1 );
01357 SizeTypeContainer cnNBColId;
01358 std::vector<BoundType> cnNBBoundType;
01359 cout << "NonBasicID: ";
01360
01361 std::vector<VarBoundary>::const_iterator itr,
01362 itrBeg = cnNonBasic.begin(), itrEnd = cnNonBasic.end();
01363 for ( itr = itrBeg; itr != itrEnd; ++itr )
01364 {
01365 double fNBVal = itr->Value;
01366 size_t nColId = itr->Id;
01367 cout << nColId << " ";
01368 mxInitX( nColId, 0 ) = fNBVal;
01369 cnNBBoundType.push_back( itr->BoundData );
01370 cnNBColId.push_back( nColId );
01371 cnBasicId.remove( nColId );
01372 for ( size_t nRowId = 0; nRowId < m_mxA.rows(); ++nRowId )
01373 mxLHSSum( nRowId, 0 ) += m_mxA( nRowId, nColId ) * fNBVal;
01374 }
01375 cout << endl;
01376
01377 Debug( "Basic IDs: " );
01378 printElements( cnBasicId );
01379
01380 Matrix mxBasic( m_mxA );
01381 mxBasic.deleteColumns( toVector<SizeTypeContainer, size_t>(cnNBColId) );
01382
01383
01384 Matrix mxBasicInv = mxBasic.inverse();
01385 Matrix mxNewRHS = m_mxB - mxLHSSum;
01386 Matrix mxBaseX = mxBasicInv*mxNewRHS;
01387
01388 mxBasic.print();
01389 mxLHSSum.print();
01390 Debug( "initial basic variable:" );
01391 mxBaseX.print();
01392
01393
01394
01395
01396
01397
01398
01399
01400 std::list<size_t>::const_iterator itrLt,
01401 itrLtBeg = cnBasicId.begin(), itrLtEnd = cnBasicId.end();
01402 for ( itrLt = itrLtBeg; itrLt != itrLtEnd; ++itrLt )
01403 {
01404 size_t nVarId = *itrLt;
01405 double fBaseVal = mxBaseX( distance( itrLtBeg, itrLt ), 0 );
01406
01407
01408 if ( m_pModel->isVarBounded( nVarId, BOUND_LOWER ) )
01409 {
01410 double fBound = m_pModel->getVarBound( nVarId, BOUND_LOWER );
01411 if ( fBaseVal < fBound )
01412 {
01413 cout << nVarId << " basic variable (" << fBaseVal << ") < lower bound ("
01414 << fBound << ")" << endl;
01415 return false;
01416 }
01417 }
01418
01419
01420 if ( m_pModel->isVarBounded( nVarId, BOUND_UPPER ) )
01421 {
01422 double fBound = m_pModel->getVarBound( nVarId, BOUND_UPPER );
01423 if ( fBaseVal > fBound )
01424 {
01425 cout << nVarId << " basic variable (" << fBaseVal << ") > upper bound ("
01426 << fBound << ")" << endl;
01427 return false;
01428 }
01429 }
01430 mxInitX( nVarId, 0 ) = fBaseVal;
01431 }
01432
01433 Debug( "initial X:" );
01434 mxInitX.trans().print();
01435
01436 m_mxX.swap( mxInitX );
01437 m_mxBasicInv.swap( mxBasicInv );
01438 swap( m_aBasicVarId, cnBasicId );
01439 swap( m_aNonBasicVarId, cnNBColId );
01440 swap( m_aNonBasicVarBoundType, cnNBBoundType );
01441
01442 return true;
01443 }
01444
01457 bool BoundedRevisedSimplexImpl::iterateVarBoundary( size_t nIdx, size_t nUpper,
01458 vector<VarBoundary>& aArray )
01459 {
01460 if ( aArray.size() == nUpper )
01461 {
01462 cout << "array size maxed: " << aArray.size() << endl;
01463 return buildInitialVars( aArray );
01464 }
01465
01466 if ( nIdx > m_mxC.cols() )
01467
01468 return false;
01469
01470
01471
01472
01473 BoundType e[2] = { BOUND_LOWER, BOUND_UPPER };
01474 for ( size_t i = 0; i < 2; ++i )
01475 if ( m_pModel->isVarBounded( nIdx, e[i] ) )
01476 {
01477 cout << "index: a" << nIdx << "a\tarray size: " << aArray.size() << "\t";
01478 if ( i == 0 )
01479 cout << "lower" << endl;
01480 else
01481 cout << "upper" << endl;
01482 VarBoundary temp;
01483 temp.Id = nIdx;
01484 temp.Value = m_pModel->getVarBound( nIdx, e[i] );
01485 temp.BoundData = e[i];
01486 aArray.push_back( temp );
01487 if ( m_pModel->getVerbose() )
01488 {
01489 cout << nIdx << " bounded at ";
01490 if ( e[i] == BOUND_LOWER )
01491 cout << "lower end";
01492 else
01493 cout << "upper end";
01494 cout << " (" << temp.Value << ")" << endl;
01495 }
01496 break;
01497 #if 0
01498 if ( iterateVarBoundary( nIdx+1, nUpper, aArray ) )
01499 return true;
01500 aArray.pop_back();
01501 #endif
01502 }
01503
01504 return iterateVarBoundary( nIdx+1, nUpper, aArray );
01505 #if 0
01506 return false;
01507 #endif
01508 }
01509
01510 bool BoundedRevisedSimplexImpl::isSolutionFeasible( const Matrix& mxX ) const
01511 {
01512 OSL_ASSERT( m_mxC.cols() == mxX.rows() );
01513
01514 for ( size_t i = 0; i < mxX.rows(); ++i )
01515 {
01516 double fVal = mxX( i, 0 );
01517 if ( ( m_pModel->isVarBounded( i, BOUND_LOWER ) &&
01518 fVal < m_pModel->getVarBound( i, BOUND_LOWER ) ) ||
01519 ( m_pModel->isVarBounded( i, BOUND_UPPER ) &&
01520 fVal > m_pModel->getVarBound( i, BOUND_UPPER ) ) )
01521 return false;
01522 }
01523
01524 if ( m_mxA*mxX != m_mxB )
01525 return false;
01526
01527 return true;
01528 }
01529
01530 const Matrix BoundedRevisedSimplexImpl::solvePriceVector(
01531 const SizeTypeContainer& aBasicVarId,
01532 const Matrix& mxAInv, const Matrix& mxC ) const
01533 {
01534 Matrix c;
01535 SizeTypeContainer::const_iterator itr;
01536 SizeTypeContainer::const_iterator itrBeg = aBasicVarId.begin();
01537 SizeTypeContainer::const_iterator itrEnd = aBasicVarId.end();
01538 for ( itr = itrBeg; itr != itrEnd; ++itr )
01539 {
01540 int idx = distance( itrBeg, itr );
01541 c( 0, idx ) = mxC( 0, *itr );
01542 }
01543 return c*mxAInv;
01544 }
01545
01546
01547
01548
01549
01550 BoundedRevisedSimplex::BoundedRevisedSimplex() : BaseAlgorithm(),
01551 m_pImpl( new BoundedRevisedSimplexImpl( this ) )
01552 {
01553 }
01554
01555 BoundedRevisedSimplex::~BoundedRevisedSimplex() throw()
01556 {
01557 }
01558
01559 void BoundedRevisedSimplex::solve()
01560 {
01561 m_pImpl->solve();
01562 }
01563
01564
01565 }}}}