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
00029 #include "numeric/lpmodel.hxx"
00030 #include "numeric/lpbase.hxx"
00031 #include "numeric/matrix.hxx"
00032 #include "tool/global.hxx"
00033
00034 #include <iostream>
00035 #include <sstream>
00036 #include <algorithm>
00037 #include <vector>
00038 #include <map>
00039
00040 using ::std::vector;
00041 using ::std::string;
00042 using ::std::map;
00043 using ::std::cout;
00044 using ::std::endl;
00045 using ::std::ostringstream;
00046 using ::scsolver::numeric::Matrix;
00047 using ::std::distance;
00048 using ::std::find;
00049
00050 namespace scsolver { namespace numeric { namespace lp {
00051
00052 class NonBoundingException : public ::std::exception
00053 {
00054 public:
00055 virtual const char* what() const throw()
00056 {
00057 return "Non bounding exception";
00058 }
00059 };
00060
00061 struct AttrBound
00062 {
00063 bool Enabled;
00064 double Value;
00065 };
00066
00067 struct VarBounds
00068 {
00069 AttrBound Upper;
00070 AttrBound Lower;
00071 };
00072
00073 typedef map<size_t,VarBounds> VarBoundMap;
00074
00075 class ModelImpl
00076 {
00077 public:
00078 ModelImpl();
00079 ModelImpl( const ModelImpl& );
00080 ~ModelImpl() throw();
00081 void swap( ModelImpl& ) throw();
00082 void print() const;
00083
00084 size_t getDecisionVarSize() const { return m_mxCost.cols(); }
00085 size_t getConstraintCount() const { return m_mxConstraint.rows(); }
00086
00087 double getCost( size_t rowid ) const { return m_mxCost( 0, rowid ); }
00088 Matrix getCostVector() const { return m_mxCost; }
00089 void setCostVectorElement( size_t, double );
00090 void setCostVector( const std::vector<double>& );
00091 void deleteCostVectorElements( const std::vector<size_t>& );
00092
00093 AttrBound getVarBoundAttribute( size_t, BoundType ) const;
00094 double getVarBound( size_t, BoundType ) const;
00095 void setVarBound( size_t, BoundType, double );
00096 bool isVarBounded( size_t, BoundType ) const;
00097 void deleteVarRanges( const std::vector<size_t>& );
00098
00099 void deleteVariables( const std::vector<size_t>& );
00100
00101 GoalType getGoal() const { return m_eGoal; }
00102 void setGoal( GoalType e ) { m_eGoal = e; }
00103
00104 double getObjectiveFuncConstant() const { return m_fObjFuncConstant; }
00105 void setObjectiveFuncConstant( double f ) { m_fObjFuncConstant = f; }
00106
00107 unsigned long getPrecision() const { return m_nPrecision; }
00108 void setPrecision( unsigned long n ) { m_nPrecision = n; }
00109
00110 bool getVarPositive() const { return m_bVarPositive; }
00111 void setVarPositive( bool b ) { m_bVarPositive = b; }
00112
00113 bool getVarInteger() const
00114 {
00115 return m_bVarInteger;
00116 }
00117
00118 void setVarInteger( bool b )
00119 {
00120 m_bVarInteger = b;
00121 }
00122
00123 bool getVerbose() const { return m_bVerbose; }
00124 void setVerbose( bool b ) { m_bVerbose = b; }
00125
00126 double getConstraint( size_t, size_t ) const;
00127 Matrix getConstraintMatrix() const { return m_mxConstraint; }
00128 Matrix getRhsVector() const { return m_mxRHS; }
00129 double getRhsValue( size_t ) const;
00130 void setRhsValue( size_t, double );
00131 vector<EqualityType> getEqualityVector() const { return m_eEqualities; }
00132 EqualityType getEqualityByRowId( size_t i ) const { return m_eEqualities.at( i ); }
00133 void addConstraint( const std::vector<double>&, EqualityType, double );
00134 void setStandardConstraintMatrix( const Matrix&, const Matrix& );
00135 void deleteConstraintMatrixColumns( const std::vector<size_t>& );
00136
00137 private:
00138 Matrix m_mxCost;
00139 Matrix m_mxConstraint;
00140 Matrix m_mxRHS;
00141
00142 vector<VarBounds> m_cnVarRanges;
00143 vector<EqualityType> m_eEqualities;
00144
00145 GoalType m_eGoal;
00146 unsigned long m_nPrecision;
00147 bool m_bVarPositive;
00148 bool m_bVarInteger;
00149
00150 bool m_bVerbose;
00151 double m_fObjFuncConstant;
00152 };
00153
00154
00155 ModelImpl::ModelImpl() :
00156 m_mxCost( 0, 0 ), m_mxConstraint( 0, 0 ), m_mxRHS( 0, 0 ),
00157 m_nPrecision( 2 ), m_bVarPositive( true ), m_bVerbose( false ),
00158 m_fObjFuncConstant( 0.0 )
00159 {
00160 }
00161
00162 ModelImpl::ModelImpl( const ModelImpl& other ) :
00163 m_mxCost( other.m_mxCost ),
00164 m_mxConstraint( other.m_mxConstraint ),
00165 m_mxRHS( other.m_mxRHS ),
00166 m_cnVarRanges( other.m_cnVarRanges ),
00167 m_eEqualities( other.m_eEqualities ),
00168 m_eGoal( other.m_eGoal ),
00169 m_nPrecision( other.m_nPrecision ),
00170 m_bVarPositive( other.m_bVarPositive ),
00171 m_bVerbose( other.m_bVerbose )
00172 {
00173 }
00174
00175 ModelImpl::~ModelImpl() throw()
00176 {
00177 }
00178
00179 void ModelImpl::swap( ModelImpl& other ) throw()
00180 {
00181 m_mxCost.swap( other.m_mxCost );
00182 m_mxConstraint.swap( other.m_mxConstraint );
00183 m_mxRHS.swap( other.m_mxRHS );
00184 std::swap( m_cnVarRanges, other.m_cnVarRanges );
00185 std::swap( m_eEqualities, other.m_eEqualities );
00186 std::swap( m_eGoal, other.m_eGoal );
00187 std::swap( m_nPrecision, other.m_nPrecision );
00188 std::swap( m_bVarPositive, other.m_bVarPositive );
00189 std::swap( m_bVarInteger, other.m_bVarInteger );
00190 std::swap( m_bVerbose, other.m_bVerbose );
00191 }
00192
00193 void ModelImpl::setCostVectorElement( size_t nId, double fVal )
00194 {
00195
00196 m_mxCost( 0, nId ) = fVal;
00197 }
00198
00199 void ModelImpl::setCostVector( const std::vector<double>& cn )
00200 {
00201 std::vector<double>::const_iterator it,
00202 itBeg = cn.begin(), itEnd = cn.end();
00203 for ( it = itBeg; it != itEnd; ++it )
00204 {
00205 size_t nDist = std::distance( itBeg, it );
00206 setCostVectorElement( nDist, *it );
00207 }
00208 }
00209
00210 void ModelImpl::deleteCostVectorElements( const std::vector<size_t>& cn )
00211 {
00212 m_mxCost.deleteColumns( cn );
00213 }
00214
00215 AttrBound ModelImpl::getVarBoundAttribute( size_t i, BoundType e ) const
00216 {
00217 AttrBound ab;
00218 if ( i >= m_cnVarRanges.size() )
00219 {
00220
00221 ab.Enabled = false;
00222 ab.Value = 0.0;
00223 }
00224 else
00225 {
00226 VarBounds vb = m_cnVarRanges[i];
00227 switch ( e )
00228 {
00229 case BOUND_LOWER:
00230 ab = vb.Lower;
00231 break;
00232 case BOUND_UPPER:
00233 ab = vb.Upper;
00234 break;
00235 default:
00236 OSL_ASSERT( !"unknown boundary" );
00237 }
00238 }
00239
00240 return ab;
00241 }
00242
00243 double ModelImpl::getVarBound( size_t i, BoundType e ) const
00244 {
00245 AttrBound ab = getVarBoundAttribute( i, e );
00246 if ( ab.Enabled )
00247 return ab.Value;
00248 else
00249 throw NonBoundingException();
00250 }
00251
00252 void ModelImpl::setVarBound( size_t nVarId, BoundType e, double fBound )
00253 {
00254 size_t nSize = m_cnVarRanges.size();
00255 cout << "size is " << nSize << " and request is " << nVarId << endl;
00256 if ( nVarId >= nSize )
00257 {
00258
00259 for ( size_t i = 0; i < nVarId + 1 - nSize; ++i )
00260 {
00261 cout << "inserting new VarBounds at " << i << endl;
00262 VarBounds vb;
00263 vb.Lower.Enabled = false;
00264 vb.Lower.Value = 0.0;
00265 vb.Upper.Enabled = false;
00266 vb.Upper.Value = 0.0;
00267 m_cnVarRanges.push_back( vb );
00268 }
00269 }
00270
00271 switch ( e )
00272 {
00273 case BOUND_LOWER:
00274
00275 m_cnVarRanges[nVarId].Lower.Enabled = true;
00276 m_cnVarRanges[nVarId].Lower.Value = fBound;
00277 break;
00278 case BOUND_UPPER:
00279 m_cnVarRanges[nVarId].Upper.Enabled = true;
00280 m_cnVarRanges[nVarId].Upper.Value = fBound;
00281 break;
00282 default:
00283 OSL_ASSERT( !"unknown boundary" );
00284 }
00285 }
00286
00287 bool ModelImpl::isVarBounded( size_t i, BoundType e ) const
00288 {
00289 AttrBound ab = getVarBoundAttribute( i, e );
00290 return ab.Enabled;
00291 }
00292
00293 void ModelImpl::deleteVarRanges( const std::vector<size_t>& cnVarIds )
00294 {
00295 vector<size_t> Ids( cnVarIds );
00296 ::std::sort( Ids.begin(), Ids.end() );
00297 vector<VarBounds>::iterator itr,
00298 itrBeg = m_cnVarRanges.begin(), itrEnd = m_cnVarRanges.end();
00299
00300 vector<VarBounds> cnVarRanges( m_cnVarRanges.size() );
00301 for ( itr = itrBeg; itr != itrEnd; ++itr )
00302 {
00303 size_t nCurId = distance( itrBeg, itr );
00304 if ( find( cnVarIds.begin(), cnVarIds.end(), nCurId ) == cnVarIds.end() )
00305
00306 cnVarRanges.push_back( *itr );
00307 }
00308 m_cnVarRanges.swap( cnVarRanges );
00309 }
00310
00311 void ModelImpl::deleteVariables( const std::vector<size_t>& cnVarIds )
00312 {
00313 Debug( "deleteVariables" );
00314 deleteCostVectorElements( cnVarIds );
00315 deleteConstraintMatrixColumns( cnVarIds );
00316 deleteVarRanges( cnVarIds );
00317 }
00318
00319 double ModelImpl::getConstraint( size_t nRow, size_t nCol ) const
00320 {
00321 return m_mxConstraint( nRow, nCol );
00322 }
00323
00324 double ModelImpl::getRhsValue( size_t nId ) const
00325 {
00326 return m_mxRHS( nId, 0 );
00327 }
00328
00329 void ModelImpl::setRhsValue( size_t nId, double fVal )
00330 {
00331 m_mxRHS( nId, 0 ) = fVal;
00332 }
00333
00334 void ModelImpl::addConstraint( const std::vector<double>& aConst, EqualityType eEqual, double fRHS )
00335 {
00336 size_t nRowId = m_mxConstraint.rows();
00337 vector<double>::const_iterator pos;
00338 for ( pos = aConst.begin(); pos != aConst.end(); ++pos )
00339 {
00340 size_t nColId = distance( aConst.begin(), pos );
00341 m_mxConstraint( nRowId, nColId ) = *pos;
00342 }
00343 m_eEqualities.push_back( eEqual );
00344
00345
00346 m_mxRHS( m_mxRHS.rows(), 0 ) = fRHS;
00347 }
00348
00349 void ModelImpl::setStandardConstraintMatrix( const Matrix& A, const Matrix& B )
00350 {
00351 if ( A.rows() != B.rows() )
00352 throw MatrixSizeMismatch();
00353
00354 for ( size_t i = 0; i < A.rows(); ++i )
00355 {
00356 vector<double> aConst;
00357 for ( size_t j = 0; j < A.cols(); ++j )
00358 aConst.push_back( A( i, j ) );
00359 addConstraint( aConst, EQUAL, B( i, 0 ) );
00360 }
00361 }
00362
00363 void ModelImpl::deleteConstraintMatrixColumns( const std::vector<size_t>& cn )
00364 {
00365 m_mxConstraint.deleteColumns( cn );
00366 }
00367
00368 void ModelImpl::print() const
00369 {
00370 using namespace ::boost::numeric::ublas;
00371 size_t nColSpace = 2;
00372 string sX = "x_";
00373 cout << endl << repeatString( "-", 70 ) << endl;
00374 string sGoal;
00375 if ( m_eGoal == GOAL_MAXIMIZE )
00376 sGoal = "max";
00377 else if ( m_eGoal == GOAL_MINIMIZE )
00378 sGoal = "min";
00379 else
00380
00381 sGoal = "unknown";
00382
00383 ostringstream osLine;
00384 osLine << "Objective: ";
00385 bool bFirst = true;
00386 for ( size_t j = 0; j < m_mxCost.cols(); ++j )
00387 {
00388 double fVal = m_mxCost( 0, j );
00389 if ( fVal != 0.0 )
00390 {
00391 if ( bFirst )
00392 {
00393 bFirst = false;
00394 osLine << fVal << sX << j;
00395 }
00396 else
00397 {
00398 if ( fVal > 0.0 )
00399 osLine << " + " << fVal << sX << j;
00400 else
00401 osLine << " - " << abs(fVal) << sX << j;
00402 }
00403 }
00404 }
00405 osLine << " (" << sGoal << ")";
00406 cout << osLine.str() << endl << repeatString( "-", 70 ) << endl;
00407 cout << "Subject to Constraints:" << endl << endl;
00408 matrix< string > mElements = m_mxConstraint.getDisplayElements( 0, nColSpace, true );
00409 matrix< string > mRHS = m_mxRHS.getDisplayElements( 0, nColSpace, false );
00410
00411
00412 for ( size_t i = 0; i < m_mxConstraint.rows(); ++i )
00413 {
00414 osLine.str( "" );
00415 for ( size_t j = 0; j < m_mxConstraint.cols(); ++j )
00416 {
00417 string s = mElements( i, j );
00418 double f = m_mxConstraint( i, j );
00419 ostringstream osVar;
00420 osVar << s << sX << j;
00421 if ( f == 0.0 )
00422 osLine << repeatString( " ", osVar.str().length() );
00423 else
00424 osLine << osVar.str();
00425 }
00426
00427 osLine << repeatString( " ", nColSpace );
00428
00429 switch ( m_eEqualities.at( i ) )
00430 {
00431 case GREATER_EQUAL:
00432 osLine << ">=";
00433 break;
00434 case EQUAL:
00435 osLine << " =";
00436 break;
00437 case LESS_EQUAL:
00438 osLine << "<=";
00439 break;
00440 default:
00441 OSL_ASSERT( !"wrong case" );
00442 }
00443
00444 osLine << repeatString( " ", nColSpace ) << m_mxRHS( i, 0 );
00445 cout << osLine.str() << endl;
00446 }
00447 cout << repeatString( "-", 70 ) << endl;
00448
00449 if ( m_bVarPositive )
00450 {
00451 cout << "All decision variables are assumed positive" << endl;
00452 cout << repeatString( "-", 70 ) << endl;
00453 }
00454
00455
00456 Matrix mxCost = getCostVector();
00457 osLine.str( "" );
00458 for ( size_t i = 0; i < mxCost.cols(); ++i )
00459 {
00460 osLine << "x_" << i << ": ";
00461 bool bLower = isVarBounded( i, BOUND_LOWER );
00462 bool bUpper = isVarBounded( i, BOUND_UPPER );
00463 if ( bLower || bUpper )
00464 {
00465 if ( bLower )
00466 {
00467 double fBound = getVarBound( i, BOUND_LOWER );
00468 osLine << fBound;
00469 }
00470 else
00471 osLine << "[none]";
00472
00473 osLine << " - ";
00474
00475 if ( bUpper )
00476 {
00477 double fBound = getVarBound( i, BOUND_UPPER );
00478 osLine << fBound;
00479 }
00480 else
00481 osLine << "[none]";
00482 }
00483 else
00484 osLine << "[unbounded]";
00485 osLine << endl;
00486 }
00487 cout << osLine.str();
00488 cout << repeatString( "-", 70 ) << endl;
00489 }
00490
00491
00492
00493
00494
00495 Model::Model() : m_pImpl( new ModelImpl() )
00496 {
00497 }
00498
00499 Model::Model( const Model& other ) : m_pImpl( new ModelImpl( *other.m_pImpl.get() ) )
00500 {
00501 }
00502
00503 Model::~Model()
00504 {
00505 }
00506
00507 void Model::print() const
00508 {
00509 m_pImpl->print();
00510 }
00511
00512 size_t Model::getDecisionVarSize() const
00513 {
00514 return m_pImpl->getDecisionVarSize();
00515 }
00516
00517 size_t Model::getConstraintCount() const
00518 {
00519 return m_pImpl->getConstraintCount();
00520 }
00521
00522 double Model::getCost( size_t rowid ) const
00523 {
00524 return m_pImpl->getCost( rowid );
00525 }
00526
00532 Matrix Model::getCostVector() const
00533 {
00534 return m_pImpl->getCostVector();
00535 }
00536
00537 void Model::setCostVectorElement( size_t i, double fVal )
00538 {
00539 m_pImpl->setCostVectorElement( i, fVal );
00540 }
00541
00542 void Model::setCostVector( const std::vector<double>& cn )
00543 {
00544 m_pImpl->setCostVector( cn );
00545 }
00546
00547
00551 double Model::getVarBound( size_t i, BoundType e ) const
00552 {
00553 return m_pImpl->getVarBound( i, e );
00554 }
00555
00556 void Model::setVarBound( size_t i, BoundType e, double fValue )
00557 {
00558 m_pImpl->setVarBound( i, e, fValue );
00559 }
00560
00561 bool Model::isVarBounded( size_t i, BoundType e ) const
00562 {
00563 return m_pImpl->isVarBounded( i, e );
00564 }
00565
00566 void Model::deleteVariables( const std::vector<size_t>& cnVarIds )
00567 {
00568 m_pImpl->deleteVariables( cnVarIds );
00569 }
00570
00571 GoalType Model::getGoal() const
00572 {
00573 return m_pImpl->getGoal();
00574 }
00575
00576 void Model::setGoal( GoalType e )
00577 {
00578 m_pImpl->setGoal( e );
00579 }
00580
00581 double Model::getObjectiveFuncConstant() const
00582 {
00583 return m_pImpl->getObjectiveFuncConstant();
00584 }
00585
00586 void Model::setObjectiveFuncConstant( double f )
00587 {
00588 m_pImpl->setObjectiveFuncConstant( f );
00589 }
00590
00591 unsigned long Model::getPrecision() const
00592 {
00593 return m_pImpl->getPrecision();
00594 }
00595
00596 void Model::setPrecision( unsigned long i )
00597 {
00598 m_pImpl->setPrecision( i );
00599 }
00600
00601 bool Model::getVarPositive() const
00602 {
00603 return m_pImpl->getVarPositive();
00604 }
00605
00606 void Model::setVarPositive( bool b )
00607 {
00608 m_pImpl->setVarPositive( b );
00609 }
00610
00611 bool Model::getVarInteger() const
00612 {
00613 return m_pImpl->getVarInteger();
00614 }
00615
00616 void Model::setVarInteger( bool b )
00617 {
00618 m_pImpl->setVarInteger( b );
00619 }
00620
00621 bool Model::getVerbose() const
00622 {
00623 return m_pImpl->getVerbose();
00624 }
00625
00626 void Model::setVerbose( bool b )
00627 {
00628 m_pImpl->setVerbose( b );
00629 }
00630
00631 double Model::getConstraint( size_t nRow, size_t nCol ) const
00632 {
00633 return m_pImpl->getConstraint( nRow, nCol );
00634 }
00635
00636 Matrix Model::getConstraintMatrix() const
00637 {
00638 return m_pImpl->getConstraintMatrix();
00639 }
00640
00641 Matrix Model::getRhsVector() const
00642 {
00643 return m_pImpl->getRhsVector();
00644 }
00645
00646 double Model::getRhsValue( size_t nId ) const
00647 {
00648 return m_pImpl->getRhsValue( nId );
00649 }
00650
00651 void Model::setRhsValue( size_t nId, double fVal )
00652 {
00653 m_pImpl->setRhsValue( nId, fVal );
00654 }
00655
00656 std::vector<EqualityType> Model::getEqualityVector() const
00657 {
00658 return m_pImpl->getEqualityVector();
00659 }
00660
00661 EqualityType Model::getEquality( size_t i ) const
00662 {
00663 return m_pImpl->getEqualityByRowId( i );
00664 }
00665
00666 void Model::addConstraint( const std::vector< double >& v, EqualityType e, double fRhs )
00667 {
00668 m_pImpl->addConstraint( v, e, fRhs );
00669 }
00670
00671 void Model::setStandardConstraintMatrix( const Matrix& mxConst, const Matrix& mxRhs )
00672 {
00673 m_pImpl->setStandardConstraintMatrix( mxConst, mxRhs );
00674 }
00675
00676
00677 }}}
00678
00679
00680