source/ui/solvemodel.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  The Contents of this file are made available subject to
00004  *  the terms of GNU Lesser General Public License Version 2.1.
00005  *
00006  *
00007  *    GNU Lesser General Public License Version 2.1
00008  *    =============================================
00009  *    Copyright 2005 by Kohei Yoshida.
00010  *    1039 Kingsway Dr., Apex, NC 27502, USA
00011  *
00012  *    This library is free software; you can redistribute it and/or
00013  *    modify it under the terms of the GNU Lesser General Public
00014  *    License version 2.1, as published by the Free Software Foundation.
00015  *
00016  *    This library is distributed in the hope that it will be useful,
00017  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *    Lesser General Public License for more details.
00020  *
00021  *    You should have received a copy of the GNU Lesser General Public
00022  *    License along with this library; if not, write to the Free Software
00023  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00024  *    MA  02111-1307  USA
00025  *
00026  ************************************************************************/
00027 
00028  
00029 #include "solvemodel.hxx"
00030 #include "solver.hxx"
00031 #include "tool/global.hxx"
00032 #include "unoglobal.hxx"
00033 #include "lpbuilder.hxx"
00034 #include "nlpbuilder.hxx"
00035 #include "dialog.hxx"
00036 #include "xcalc.hxx"
00037 #include "option.hxx"
00038 #include "numeric/lpmodel.hxx"
00039 #include "numeric/nlpmodel.hxx"
00040 #include "numeric/matrix.hxx"
00041 #include "numeric/type.hxx"
00042 #include "numeric/lpbase.hxx"
00043 #include "numeric/exception.hxx"
00044 //#include "numeric/lpsimplex.hxx"
00045 #include "numeric/lpsolve.hxx"
00046 #include "numeric/quasinewton.hxx"
00047 #include "numeric/cellfuncobj.hxx"
00048 #ifdef ENABLE_SCSOLVER_UNO_ALGORITHM
00049 #include "numeric/lpuno.hxx"
00050 #endif
00051 
00052 #include <memory>
00053 #include <exception>
00054 #include <vector>
00055 #include <map>
00056 
00057 #include "scsolver.hrc"
00058 
00059 using namespace scsolver::numeric;
00060 using scsolver::numeric::Matrix;
00061 using com::sun::star::table::CellAddress;
00062 using ::std::vector;
00063 using ::std::cout;
00064 using ::std::endl;
00065 using ::std::map;
00066 using ::std::auto_ptr;
00067 using ::std::distance;
00068 
00069 namespace scsolver {
00070 
00071 typedef struct {
00072         short sheet;
00073         long  column;
00074         long  row;
00075 } cell_address_t;
00076 
00082 class ConstantTermStorage
00083 {
00084 public:
00085         ConstantTermStorage() {}
00086         ~ConstantTermStorage() throw() {}
00087 
00088         void setValue(const CellAddress& addr, double value)
00089         {
00090                 size_t key = 0;
00091                 bool isNewKey = false;
00092                 getKeyFromAddress(addr, key, isNewKey);
00093                 if (isNewKey)
00094                         m_List.insert( map<size_t,double>::value_type(key, value) );
00095 #ifdef SCSOLVER_DEBUG
00096                 else
00097                 {
00098                         // Make sure the value is identical.
00099                         if (m_List[key] != value)
00100                                 throw AssertionWrong();
00101                 }
00102 #endif
00103         }
00104 
00105         double getValue(const CellAddress& addr)
00106         {
00107                 size_t key = 0;
00108                 bool isNewKey = false;
00109                 getKeyFromAddress(addr, key, isNewKey);
00110                 if (isNewKey)
00111                 {
00112                         // This should never happen, because we are just querying the 
00113                         // existing value associated with a specified address.
00114                         throw ConstraintError();
00115                 }
00116                 return m_List[key];
00117         }
00118 
00119 private:
00120         map<size_t, double> m_List;
00121         vector<cell_address_t> m_AddrKeys;
00122 
00133         void getKeyFromAddress(const CellAddress& addr, size_t& key, bool& isNewKey)
00134         {
00135                 cell_address_t cell;
00136                 cell.sheet = addr.Sheet;
00137                 cell.column = addr.Column;
00138                 cell.row = addr.Row;
00139                 vector<cell_address_t>::iterator it, 
00140                         itBeg = m_AddrKeys.begin(), itEnd = m_AddrKeys.end();
00141 
00142                 for (it = itBeg; it != itEnd; ++it)
00143                 {
00144                         if (cell.sheet == it->sheet && cell.column == it->column && cell.row == it->row)
00145                         {
00146                                 // Match found.
00147                                 key = distance(itBeg, it);
00148                                 isNewKey = false;
00149                                 return;
00150                         }
00151                 }
00152 
00153                 // Match not found.
00154                 m_AddrKeys.push_back(cell);
00155                 key = m_AddrKeys.size() - 1;
00156                 isNewKey = true;
00157                 return;
00158         }
00159 };
00160 
00167 class CellUpdateSwitch
00168 {
00169 public:
00170         CellUpdateSwitch(CalcInterface* p) :
00171                 m_pCalc(p)
00172         {
00173                 p->disableCellUpdates();
00174         }
00175 
00176         ~CellUpdateSwitch() throw()
00177         {
00178                 m_pCalc->enableCellUpdates();
00179         }
00180 
00181 private:
00182         CellUpdateSwitch();              // disabled
00183         void* operator new(size_t size); // disabled
00184 
00185         CalcInterface* m_pCalc;
00186 };
00187 
00188 class SolveModelImpl
00189 {
00190 public:
00191         SolveModelImpl( SolverImpl* p ) :
00192                 m_pSolverImpl(p),
00193                 m_bSolved(false)
00194         {
00195         }
00196 
00197         ~SolveModelImpl() throw()
00198         {
00199         }
00200 
00206         void solve()
00207         {
00208                 OptModelType type = getSolverImpl()->getOptionData()->getModelType();
00209                 switch (type)
00210                 {
00211                 case OPTMODELTYPE_LP:
00212                 case OPTMODELTYPE_MILP:
00213                         solveLp();
00214                         break;
00215                 case OPTMODELTYPE_NLP:
00216                 case OPTMODELTYPE_MINLP:
00217                         solveNlp();
00218                         break;
00219                 default:
00220                         break;
00221                 }
00222         }
00223 
00230         void solveLp()
00231         {
00232                 using namespace numeric;
00233 
00234                 SolverDialog* pMainDlg = getSolverImpl()->getMainDialog();
00235                 GoalType eGoal = pMainDlg->getGoal();
00236                 if ( eGoal == GOAL_UNKNOWN )
00237                 {
00238                         pMainDlg->showMessage( 
00239                                 pMainDlg->getResStr(SCSOLVER_STR_MSG_GOAL_NOT_SET) );
00240                         return;
00241                 }
00242 
00243                 auto_ptr<LpModelBuilder> pBuilder( new LpModelBuilder );
00244                 pBuilder->setGoal( eGoal );
00245 
00246                 CellAddress addr = resolveObjectiveFuncAddress();
00247                 pBuilder->setObjectiveFormulaAddress(addr);
00248 
00249                 pBuilder->clearDecisionVarAddresses();
00250                 vector<CellAddress> addrs = resolveDecisionVarAddress();
00251                 vector<CellAddress>::iterator it,
00252                         itBeg = addrs.begin(), itEnd = addrs.end();
00253                 for ( it = itBeg; it != itEnd; ++it )
00254                         pBuilder->setDecisionVarAddress(*it);
00255 
00256                 resolveConstraintAddress( pBuilder.get() );
00257                 parseConstraints( pBuilder.get() );
00258 
00259                 lp::Model aModel = pBuilder->getModel();
00260 
00261                 OptionData* pOption = getSolverImpl()->getOptionData();
00262                 aModel.setVarPositive( pOption->getVarPositive() );
00263                 aModel.setVarInteger( pOption->getVarInteger() );
00264 
00265 #if SCSOLVER_DEBUG
00266         aModel.print(); // prints model to stdout
00267 #endif
00268                 aModel.setPrecision( 2 );
00269                 auto_ptr<lp::BaseAlgorithm> algorithm = getLpAlgorithm();
00270 
00271                 aModel.setVerbose(true);
00272                 m_bSolved = false;
00273                 try
00274                 {
00275                         algorithm->setModel( &aModel );
00276                         algorithm->solve();
00277                         m_bSolved = true;
00278                         m_mxSolution = algorithm->getSolution();
00279                         updateCells( pBuilder.get() );
00280                         pMainDlg->showSolutionFound();
00281                 }
00282                 catch( const ModelInfeasible& e )
00283                 {
00284                         Debug( "model infeasible" );
00285                         pMainDlg->showSolutionInfeasible();
00286                 }
00287                 catch( const scsolver::RuntimeError& e )
00288                 {
00289                         // This error message is localizable.
00290                         pMainDlg->showMessage( e.getMessage() );
00291                 }
00292                 catch( const ::std::exception& e )
00293                 {
00294                         // standard exception.  should rarely happen.
00295                         pMainDlg->showMessage(
00296                                 pMainDlg->getResStr(SCSOLVER_STR_MSG_STD_EXCEPTION_CAUGHT) );
00297                 }
00298         }
00299 
00303         void solveNlp()
00304         {
00305                 using namespace numeric;
00306 
00307                 SolverDialog* pMainDlg = getSolverImpl()->getMainDialog();
00308                 GoalType eGoal = pMainDlg->getGoal();
00309                 if ( eGoal == GOAL_UNKNOWN )
00310                 {
00311                         pMainDlg->showMessage(
00312                 pMainDlg->getResStr(SCSOLVER_STR_MSG_GOAL_NOT_SET) );
00313                         return;
00314                 }
00315 
00316         auto_ptr<numeric::CellFuncObj> pFuncObj(
00317             new numeric::CellFuncObj(m_pSolverImpl->getCalcInterface()) );
00318         CellAddress addr = resolveObjectiveFuncAddress();
00319 
00320         // Build the model by using the builder.
00321         NlpModelBuilder builder(m_pSolverImpl);
00322         builder.setFuncObj(pFuncObj.get());
00323         builder.setObjectiveFormulaAddress(addr);
00324         builder.clearDecVarAddresses();
00325         vector<CellAddress> addrs = resolveDecisionVarAddress();
00326         vector<CellAddress>::iterator it, itBeg = addrs.begin(), itEnd = addrs.end();
00327         for ( it = itBeg; it != itEnd; ++it )
00328             builder.appendDecVarAddress(*it);
00329 
00330         nlp::Model model = builder.getModel();
00331         model.setGoal(eGoal);
00332         model.print();
00333 
00334                 auto_ptr<nlp::BaseAlgorithm> algorithm = getNlpAlgorithm();
00335                 m_bSolved = false;
00336                 try
00337                 {
00338                         algorithm->setModel(&model);
00339                         algorithm->solve();
00340                         m_bSolved = true;
00341                         pMainDlg->showSolutionFound();
00342                 }
00343                 catch ( const IterationTimedOut& )
00344                 {
00345                         pMainDlg->showMessage(
00346                                 getSolverImpl()->getResStr(SCSOLVER_STR_MSG_ITERATION_TIMED_OUT) );
00347                 }
00348                 catch ( const MaxIterationReached& )
00349                 {
00350                         pMainDlg->showMessage(
00351                                 getSolverImpl()->getResStr(SCSOLVER_STR_MSG_MAX_ITERATION_REACHED) );
00352                 }
00353                 catch ( const RuntimeError& e )
00354                 {
00355                         pMainDlg->showMessage( e.getMessage() );
00356                 }
00357                 catch ( const ::std::exception& )
00358                 {
00359                         pMainDlg->showMessage(
00360                                 getSolverImpl()->getResStr(SCSOLVER_STR_MSG_STD_EXCEPTION_CAUGHT) );
00361                 }
00362         }
00363 
00364         bool isSolved() const
00365         {
00366                 return m_bSolved;
00367         }
00368 
00369 private:
00370         SolverImpl* m_pSolverImpl;
00371         bool m_bSolved;
00372         Matrix m_mxSolution;
00373         
00374         SolverImpl* getSolverImpl() const
00375         { 
00376                 return m_pSolverImpl; 
00377         }
00378 
00379         auto_ptr<lp::BaseAlgorithm> getLpAlgorithm() const;
00380 
00381         auto_ptr<nlp::BaseAlgorithm> getNlpAlgorithm() const
00382         {
00383                 auto_ptr<nlp::BaseAlgorithm> p( new nlp::QuasiNewton );
00384                 return p;
00385         }
00386 
00394         void parseConstraints( LpModelBuilder* pBuilder )
00395         {
00396                 CellUpdateSwitch aCellUpdate( m_pSolverImpl->getCalcInterface() );
00397 
00398                 // Create a cost vector from the decision variables.
00399 
00400                 vector<CellAddress> aAddrs = pBuilder->getAllDecisionVarAddresses();
00401                 vector<double> aOrigVal;
00402                 vector<CellAddress>::iterator pos;
00403                 vector<CellAddress>::iterator aAddrsBegin = aAddrs.begin(), aAddrsEnd = aAddrs.end();
00404                 CalcInterface* pCalc = m_pSolverImpl->getCalcInterface();
00405                 for ( pos = aAddrsBegin; pos != aAddrsEnd; ++pos )
00406                 {
00407                         // Run through the decision variable cells, store their original formulas,
00408                         // and set "=0" to each of these cells.
00409                         table::CellAddress aAddr = *pos;
00410                         rtl::OUString sFormula = pCalc->getCellFormula( aAddr );
00411                         pBuilder->setTempCellFormula( aAddr, sFormula );
00412                         pCalc->setCellFormula( aAddr, ascii("=0") );
00413                 }
00414 
00415                 // At this point, all decision variables are set to zero.  Go
00416                 // throuth all constraint cells, and store their current value
00417                 // as its constant term for later use.
00418                 vector<ConstraintAddress> aConstAddrs = pBuilder->getAllConstraintAddresses();
00419                 vector<ConstraintAddress>::iterator posCA, posCAEnd = aConstAddrs.end();
00420                 ConstantTermStorage cnConstTerm;
00421                 for (posCA = aConstAddrs.begin(); posCA != posCAEnd; ++posCA)
00422                 {
00423                         if ( !posCA->isLeftCellNumeric() )
00424                         {
00425                                 double fValL = pCalc->getCellValue( posCA->getLeftCellAddr() );
00426                                 cnConstTerm.setValue(posCA->getLeftCellAddr(), fValL);
00427                         }
00428                         if ( !posCA->isRightCellNumeric() )
00429                         {
00430                                 double fValR = pCalc->getCellValue( posCA->getRightCellAddr() );
00431                                 cnConstTerm.setValue(posCA->getRightCellAddr(), fValR);
00432                         }
00433                 }               
00434 
00435                 // Set "=1" to each of the decision variable cells one at a time, and 
00436                 // interpret the formula result.  Also set the constraint matrix size
00437                 // so that it won't get resized at later time (resize is expensive).
00438 
00439                 CellAddress aObjAddr = pBuilder->getObjectiveFormulaAddress();
00440                 
00441                 pBuilder->setConstraintMatrixSize( aConstAddrs.size(), aAddrs.size() );
00442 
00443                 for ( pos = aAddrsBegin; pos != aAddrsEnd; ++pos )
00444                 {
00445                         table::CellAddress aAddr = *pos;
00446                         pCalc->setCellFormula( aAddr, ascii("=1") );
00447 
00448                         double fVal = pCalc->getCellValue( aObjAddr );
00449                         pBuilder->setCostVector( aAddr, fVal );
00450 
00451                         // Go through the constraints to construct constraint matrix
00452                         // as well as the RHS vector.
00453 
00454                         for ( posCA = aConstAddrs.begin(); posCA != posCAEnd; ++posCA )
00455                         {
00456                                 double fValL = 0.0, fConstValL = 0.0;
00457                                 if ( posCA->isLeftCellNumeric() )
00458                                         fConstValL = posCA->getLeftCellValue();
00459                                 else
00460                                 {
00461                                         fValL = pCalc->getCellValue( posCA->getLeftCellAddr() );
00462                                         // Subtract the LHS constant term from the LHS value.
00463                                         fConstValL = cnConstTerm.getValue( posCA->getLeftCellAddr() );
00464                                         fValL -= fConstValL;
00465                                 }
00466 
00467                                 double fValR = 0.0, fConstValR = 0.0;
00468                                 if ( posCA->isRightCellNumeric() )
00469                                         fConstValR = posCA->getRightCellValue();
00470                                 else
00471                                 {
00472                                         fValR = pCalc->getCellValue( posCA->getRightCellAddr() );
00473                                         fConstValR = cnConstTerm.getValue( posCA->getRightCellAddr() );
00474                                         fValL -= fValR - fConstValR;
00475                                 }
00476                                 pBuilder->setConstraintCoefficient( aAddr, *posCA, fValL, fConstValR-fConstValL );
00477                         }               
00478 
00479                         pCalc->setCellFormula( aAddr, ascii("=0") );
00480                 }
00481 
00482                 // Restore the original formulas to the decision variable cells.
00483                 for ( pos = aAddrsBegin; pos != aAddrsEnd; ++pos )
00484                 {
00485                         table::CellAddress aAddr = *pos;
00486                         rtl::OUString sOrigFormula = pBuilder->getTempCellFormula( aAddr );
00487                         pCalc->setCellFormula( aAddr, sOrigFormula );
00488                 }
00489 
00490 #if SCSOLVER_DEBUG
00491                 // Check to ensure the model has the right cost vector.
00492                 for ( pos = aAddrsBegin; pos != aAddrsEnd; ++pos )
00493                 {
00494                         table::CellAddress aAddr = *pos;
00495                         double f = pBuilder->getCostVector( aAddr );
00496                         cout << aAddr.Column << ", " << aAddr.Row << " = " << f << endl;
00497                         cout.flush();
00498                 }
00499 #endif
00500         }
00501 
00502         void resolveConstraintAddress( LpModelBuilder* pBuilder );
00503 
00510         CellAddress resolveObjectiveFuncAddress()
00511         {
00512                 rtl::OUString sTargetCellAddr = m_pSolverImpl->getMainDialog()->getTargetCellAddress();
00513                 if ( !sTargetCellAddr.getLength() )
00514                         throw RuntimeError( getSolverImpl()->getResStr(SCSOLVER_STR_TARGET_NOT_SET) );
00515 
00516                 CellAddress aAddr = m_pSolverImpl->getCalcInterface()->getCellAddress(
00517                         sTargetCellAddr );
00518 
00519                 return aAddr;
00520         }
00521 
00529         vector<CellAddress> resolveDecisionVarAddress()
00530         {
00531                 using com::sun::star::table::CellRangeAddress;
00532         
00533                 rtl::OUString sAddr = m_pSolverImpl->getMainDialog()->getVarCellAddress();
00534                 if ( !sAddr.getLength() )
00535                         throw RuntimeError( 
00536                 getSolverImpl()->getResStr(SCSOLVER_STR_DECISIONVAR_NOT_SET) );
00537 
00538                 CellRangeAddress aRangeAddr = m_pSolverImpl->getCalcInterface()->getCellRangeAddress(sAddr);
00539                 
00540                 // Convert address range into an array of individual cell coordinates.
00541                 sal_Int16 nSheetId = aRangeAddr.Sheet;
00542                 sal_Int32 nSCol = aRangeAddr.StartColumn, nSRow = aRangeAddr.StartRow;
00543                 sal_Int32 nECol = aRangeAddr.EndColumn, nERow = aRangeAddr.EndRow;
00544                 
00545                 vector<CellAddress> cn;
00546                 cn.reserve( (nECol-nSCol)*(nERow-nSRow) );
00547                 for ( sal_Int32 nCol = nSCol; nCol <= nECol; ++nCol )
00548                 {
00549                         for ( sal_Int32 nRow = nSRow; nRow <= nERow; ++nRow )
00550                         {
00551                                 CellAddress addr;
00552                                 addr.Sheet  = nSheetId;
00553                                 addr.Column = nCol;
00554                                 addr.Row    = nRow;
00555                                 cn.push_back(addr);
00556                         }
00557                 }
00558                 return cn;
00559         }
00560 
00561         void updateCells( LpModelBuilder* pBuilder );
00562 };
00563 
00573 auto_ptr<lp::BaseAlgorithm> SolveModelImpl::getLpAlgorithm() const
00574 {
00575 #ifdef ENABLE_SCSOLVER_UNO_ALGORITHM
00576         auto_ptr<lp::BaseAlgorithm> algorithm( new lp::UnoAlgorithm(
00577                 ascii("org.openoffice.sc.solver.LpSolve"), getSolverImpl()->getCalcInterface() ) );
00578 #else
00579         //auto_ptr<lp::BaseAlgorithm> algorithm( new lp::RevisedSimplex );
00580         auto_ptr<lp::BaseAlgorithm> algorithm( new lp::LpSolve );
00581 #endif
00582 
00583         return algorithm;
00584 }
00585 
00586 static bool lcl_isNumeric( const rtl::OUString& sVal )
00587 {
00588         double fVal = sVal.toDouble();
00589         if ( fVal == 0.0 )
00590         {
00591                 if ( sVal.indexOf( ascii("$") ) == 0 )
00592                         return false;
00593                 else
00594                         return true;
00595         }
00596         else
00597                 return true;
00598 }
00599 
00605 void SolveModelImpl::resolveConstraintAddress( LpModelBuilder* pBuilder )
00606 {
00607         vector< ConstraintString > aConstraint = m_pSolverImpl->getMainDialog()->getAllConstraints();
00608         vector< ConstraintString >::const_iterator pos = aConstraint.begin(), posEnd = aConstraint.end();
00609         CalcInterface* pCalc = m_pSolverImpl->getCalcInterface();
00610         pBuilder->clearConstraintAddresses();
00611 
00612         for ( ; pos != posEnd; ++pos)
00613         {
00614                 ConstraintString aConstStr = *pos;
00615                 bool bLHSNumeric = lcl_isNumeric(aConstStr.Left);
00616                 bool bRHSNumeric = lcl_isNumeric(aConstStr.Right);
00617 
00618                 if (bLHSNumeric && bRHSNumeric)
00619                 {
00620                         Debug("Both LHS and RHS values are numeric.  Skipping...");
00621                         continue;
00622                 }
00623 
00624                 // Left hand side cell address
00625                 table::CellRangeAddress aRangeAddrL = pCalc->getCellRangeAddress( aConstStr.Left );
00626                 sal_Int16 nLSheet = aRangeAddrL.Sheet;
00627                 sal_Int32 nLColS  = aRangeAddrL.StartColumn;
00628                 sal_Int32 nLColE  = aRangeAddrL.EndColumn;
00629                 sal_Int32 nLRowS  = aRangeAddrL.StartRow;
00630                 sal_Int32 nLRowE  = aRangeAddrL.EndRow;
00631 
00632                 // Right hand side cell address
00633                 table::CellRangeAddress aRangeAddrR = pCalc->getCellRangeAddress( aConstStr.Right );
00634                 sal_Int16 nRSheet = aRangeAddrR.Sheet;
00635                 sal_Int32 nRColS  = aRangeAddrR.StartColumn;
00636                 sal_Int32 nRColE  = aRangeAddrR.EndColumn;
00637                 sal_Int32 nRRowS  = aRangeAddrR.StartRow;
00638                 sal_Int32 nRRowE  = aRangeAddrR.EndRow;
00639 
00640                 if (bLHSNumeric)
00641                 {
00642                         // Only the right hand side is cell reference.
00643                         for ( sal_Int32 i = 0; i <= nRColE - nRColS; ++i )
00644                         {
00645                                 for ( sal_Int32 j = 0; j <= nRRowE - nRRowS; ++j )
00646                                 {
00647                                         ConstraintAddress aConstAddr;
00648                                         table::CellAddress aAddrR;
00649                                         aAddrR.Sheet  = nRSheet;
00650                                         aAddrR.Row    = nRRowS + j;
00651                                         aAddrR.Column = nRColS + i;
00652                                         aConstAddr.setRightCellAddr( aAddrR );
00653                                         aConstAddr.setEquality( aConstStr.Equal );
00654                                         aConstAddr.setLeftCellValue( aConstStr.Left.toDouble() );
00655 
00656                                         pBuilder->setConstraintAddress( aConstAddr );
00657                                 }
00658                         }
00659                 }
00660                 else if (bRHSNumeric)
00661                 {
00662                         // Only the left hand side is cell reference.
00663                         for ( sal_Int32 i = 0; i <= nLColE - nLColS; ++i )
00664                         {
00665                                 for ( sal_Int32 j = 0; j <= nLRowE - nLRowS; ++j )
00666                                 {
00667                                         ConstraintAddress aConstAddr;
00668                                         table::CellAddress aAddrL;
00669                                         aAddrL.Sheet  = nLSheet;
00670                                         aAddrL.Row    = nLRowS + j;
00671                                         aAddrL.Column = nLColS + i;
00672                                         aConstAddr.setLeftCellAddr( aAddrL );
00673                                         aConstAddr.setEquality( aConstStr.Equal );
00674                                         aConstAddr.setRightCellValue( aConstStr.Right.toDouble() );
00675 
00676                                         pBuilder->setConstraintAddress( aConstAddr );
00677                                 }
00678                         }
00679                 }
00680                 else
00681                 {
00682                         // Both sides are cell reference.
00683                         if ( nLColE - nLColS != nRColE - nRColS || nLRowE - nLRowS != nRRowE - nRRowS )
00684                                 throw RuntimeError(
00685                                         getSolverImpl()->getResStr(SCSOLVER_STR_MSG_CELL_GEOMETRIES_DIFFER) ); // This should not happen !
00686 
00687                         for ( sal_Int32 i = 0; i <= nLColE - nLColS; ++i )
00688                         {
00689                                 for ( sal_Int32 j = 0; j <= nLRowE - nLRowS; ++j )
00690                                 {
00691                                         ConstraintAddress aConstAddr;
00692                                         table::CellAddress aAddrL, aAddrR;
00693                                         aAddrL.Sheet  = nLSheet;
00694                                         aAddrL.Row    = nLRowS + j;
00695                                         aAddrL.Column = nLColS + i;
00696                                         aConstAddr.setLeftCellAddr( aAddrL );
00697                                         aConstAddr.setEquality( aConstStr.Equal );
00698 
00699                                         aAddrR.Sheet  = nRSheet;
00700                                         aAddrR.Row    = nRRowS + j;
00701                                         aAddrR.Column = nRColS + i;
00702                                         aConstAddr.setRightCellAddr( aAddrR );
00703 
00704                                         pBuilder->setConstraintAddress( aConstAddr );
00705                                 }
00706                         }
00707                 }
00708         }
00709 }
00710 
00711 void SolveModelImpl::updateCells( LpModelBuilder* pBuilder )
00712 {
00713         vector<CellAddress> cnAddrs = pBuilder->getAllDecisionVarAddresses();
00714         CalcInterface* pCalc = m_pSolverImpl->getCalcInterface();
00715         OSL_ASSERT( m_mxSolution.rows() == cnAddrs.size() );
00716         vector<CellAddress>::iterator it, itEnd = cnAddrs.end();
00717         size_t nIdx = 0;
00718         for ( it = cnAddrs.begin(); it != itEnd; ++it )
00719                 pCalc->setCellValue( *it, m_mxSolution( nIdx++, 0 ) );
00720 }
00721 
00722 //---------------------------------------------------------------------------
00723 // SolveModel
00724 
00725 SolveModel::SolveModel( SolverImpl* p ) :
00726                 m_pImpl( new SolveModelImpl( p ) )
00727 {
00728 }
00729 
00730 SolveModel::~SolveModel() throw()
00731 {
00732 }
00733 
00734 void SolveModel::solve()
00735 {
00736         m_pImpl->solve();
00737 }
00738 
00739 bool SolveModel::isSolved() const
00740 {
00741         return m_pImpl->isSolved();
00742 }
00743 
00744 
00745 }
00746 
00747                 
00748 
00749 
00750 

Generated on Mon Jul 28 09:13:20 2008 for scsolver by  doxygen 1.5.3