LCOV - code coverage report
Current view: top level - libreoffice/sccomp/source/solver - solver.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 248 0.0 %
Date: 2012-12-27 Functions: 0 42 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*************************************************************************
       3             :  *
       4             :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5             :  *
       6             :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7             :  *
       8             :  * OpenOffice.org - a multi-platform office productivity suite
       9             :  *
      10             :  * This file is part of OpenOffice.org.
      11             :  *
      12             :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13             :  * it under the terms of the GNU Lesser General Public License version 3
      14             :  * only, as published by the Free Software Foundation.
      15             :  *
      16             :  * OpenOffice.org is distributed in the hope that it will be useful,
      17             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :  * GNU Lesser General Public License version 3 for more details
      20             :  * (a copy is included in the LICENSE file that accompanied this code).
      21             :  *
      22             :  * You should have received a copy of the GNU Lesser General Public License
      23             :  * version 3 along with OpenOffice.org.  If not, see
      24             :  * <http://www.openoffice.org/license.html>
      25             :  * for a copy of the LGPLv3 License.
      26             :  *
      27             :  ************************************************************************/
      28             : 
      29             : #undef LANGUAGE_NONE
      30             : #define WINAPI __stdcall
      31             : #define LoadInverseLib FALSE
      32             : #define LoadLanguageLib FALSE
      33             : #ifdef SYSTEM_LPSOLVE
      34             : #include <lpsolve/lp_lib.h>
      35             : #else
      36             : #include <lp_lib.h>
      37             : #endif
      38             : #undef LANGUAGE_NONE
      39             : 
      40             : #include "solver.hxx"
      41             : #include "solver.hrc"
      42             : 
      43             : #include <com/sun/star/beans/XPropertySet.hpp>
      44             : #include <com/sun/star/container/XIndexAccess.hpp>
      45             : #include <com/sun/star/frame/XModel.hpp>
      46             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      47             : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
      48             : #include <com/sun/star/sheet/XSpreadsheet.hpp>
      49             : #include <com/sun/star/table/CellAddress.hpp>
      50             : #include <com/sun/star/table/CellRangeAddress.hpp>
      51             : #include <com/sun/star/text/XTextRange.hpp>
      52             : 
      53             : #include <rtl/math.hxx>
      54             : #include <rtl/ustrbuf.hxx>
      55             : #include <cppuhelper/factory.hxx>
      56             : #include <vector>
      57             : #include <boost/unordered_map.hpp>
      58             : 
      59             : #include <tools/resmgr.hxx>
      60             : 
      61             : using namespace com::sun::star;
      62             : 
      63             : using ::rtl::OUString;
      64             : 
      65             : #define C2U(constAsciiStr) (::rtl::OUString( constAsciiStr  ))
      66             : 
      67             : #define STR_NONNEGATIVE   "NonNegative"
      68             : #define STR_INTEGER       "Integer"
      69             : #define STR_TIMEOUT       "Timeout"
      70             : #define STR_EPSILONLEVEL  "EpsilonLevel"
      71             : #define STR_LIMITBBDEPTH  "LimitBBDepth"
      72             : 
      73             : // -----------------------------------------------------------------------
      74             : //  Resources from tools are used for translated strings
      75             : 
      76             : static ResMgr* pSolverResMgr = NULL;
      77             : 
      78           0 : static OUString lcl_GetResourceString( sal_uInt32 nId )
      79             : {
      80           0 :     if (!pSolverResMgr)
      81           0 :         pSolverResMgr = ResMgr::CreateResMgr("solver");
      82             : 
      83           0 :     return String( ResId( nId, *pSolverResMgr ) );
      84             : }
      85             : 
      86             : // -----------------------------------------------------------------------
      87             : 
      88             : namespace
      89             : {
      90             :     enum
      91             :     {
      92             :         PROP_NONNEGATIVE,
      93             :         PROP_INTEGER,
      94             :         PROP_TIMEOUT,
      95             :         PROP_EPSILONLEVEL,
      96             :         PROP_LIMITBBDEPTH
      97             :     };
      98             : }
      99             : 
     100             : // -----------------------------------------------------------------------
     101             : 
     102             : // hash map for the coefficients of a dependent cell (objective or constraint)
     103             : // The size of each vector is the number of columns (variable cells) plus one, first entry is initial value.
     104             : 
     105             : struct ScSolverCellHash
     106             : {
     107           0 :     size_t operator()( const table::CellAddress& rAddress ) const
     108             :     {
     109           0 :         return ( rAddress.Sheet << 24 ) | ( rAddress.Column << 16 ) | rAddress.Row;
     110             :     }
     111             : };
     112             : 
     113           0 : inline bool AddressEqual( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 )
     114             : {
     115           0 :     return rAddr1.Sheet == rAddr2.Sheet && rAddr1.Column == rAddr2.Column && rAddr1.Row == rAddr2.Row;
     116             : }
     117             : 
     118             : struct ScSolverCellEqual
     119             : {
     120           0 :     bool operator()( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 ) const
     121             :     {
     122           0 :         return AddressEqual( rAddr1, rAddr2 );
     123             :     }
     124             : };
     125             : 
     126             : typedef boost::unordered_map< table::CellAddress, std::vector<double>, ScSolverCellHash, ScSolverCellEqual > ScSolverCellHashMap;
     127             : 
     128             : // -----------------------------------------------------------------------
     129             : 
     130           0 : static uno::Reference<table::XCell> lcl_GetCell( const uno::Reference<sheet::XSpreadsheetDocument>& xDoc,
     131             :                                           const table::CellAddress& rPos )
     132             : {
     133           0 :     uno::Reference<container::XIndexAccess> xSheets( xDoc->getSheets(), uno::UNO_QUERY );
     134           0 :     uno::Reference<sheet::XSpreadsheet> xSheet( xSheets->getByIndex( rPos.Sheet ), uno::UNO_QUERY );
     135           0 :     return xSheet->getCellByPosition( rPos.Column, rPos.Row );
     136             : }
     137             : 
     138           0 : static void lcl_SetValue( const uno::Reference<sheet::XSpreadsheetDocument>& xDoc,
     139             :                    const table::CellAddress& rPos, double fValue )
     140             : {
     141           0 :     lcl_GetCell( xDoc, rPos )->setValue( fValue );
     142           0 : }
     143             : 
     144           0 : static double lcl_GetValue( const uno::Reference<sheet::XSpreadsheetDocument>& xDoc,
     145             :                      const table::CellAddress& rPos )
     146             : {
     147           0 :     return lcl_GetCell( xDoc, rPos )->getValue();
     148             : }
     149             : 
     150             : // -------------------------------------------------------------------------
     151             : 
     152           0 : SolverComponent::SolverComponent( const uno::Reference<uno::XComponentContext>& /* rSMgr */ ) :
     153           0 :     OPropertyContainer( GetBroadcastHelper() ),
     154             :     mbMaximize( sal_True ),
     155             :     mbNonNegative( sal_False ),
     156             :     mbInteger( sal_False ),
     157             :     mnTimeout( 100 ),
     158             :     mnEpsilonLevel( 0 ),
     159             :     mbLimitBBDepth( sal_True ),
     160             :     mbSuccess( sal_False ),
     161           0 :     mfResultValue( 0.0 )
     162             : {
     163             :     // for XPropertySet implementation:
     164           0 :     registerProperty( C2U(STR_NONNEGATIVE),  PROP_NONNEGATIVE,  0, &mbNonNegative,  getCppuType( &mbNonNegative )  );
     165           0 :     registerProperty( C2U(STR_INTEGER),      PROP_INTEGER,      0, &mbInteger,      getCppuType( &mbInteger )      );
     166           0 :     registerProperty( C2U(STR_TIMEOUT),      PROP_TIMEOUT,      0, &mnTimeout,      getCppuType( &mnTimeout )      );
     167           0 :     registerProperty( C2U(STR_EPSILONLEVEL), PROP_EPSILONLEVEL, 0, &mnEpsilonLevel, getCppuType( &mnEpsilonLevel ) );
     168           0 :     registerProperty( C2U(STR_LIMITBBDEPTH), PROP_LIMITBBDEPTH, 0, &mbLimitBBDepth, getCppuType( &mbLimitBBDepth ) );
     169           0 : }
     170             : 
     171           0 : SolverComponent::~SolverComponent()
     172             : {
     173           0 : }
     174             : 
     175           0 : IMPLEMENT_FORWARD_XINTERFACE2( SolverComponent, SolverComponent_Base, OPropertyContainer )
     176           0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( SolverComponent, SolverComponent_Base, OPropertyContainer )
     177             : 
     178           0 : cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const
     179             : {
     180           0 :     uno::Sequence<beans::Property> aProps;
     181           0 :     describeProperties( aProps );
     182           0 :     return new cppu::OPropertyArrayHelper( aProps );
     183             : }
     184             : 
     185           0 : cppu::IPropertyArrayHelper& SAL_CALL SolverComponent::getInfoHelper()
     186             : {
     187           0 :     return *getArrayHelper();
     188             : }
     189             : 
     190           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL SolverComponent::getPropertySetInfo() throw(uno::RuntimeException)
     191             : {
     192           0 :     return createPropertySetInfo( getInfoHelper() );
     193             : }
     194             : 
     195             : // XSolverDescription
     196             : 
     197           0 : OUString SAL_CALL SolverComponent::getComponentDescription() throw (uno::RuntimeException)
     198             : {
     199           0 :     return lcl_GetResourceString( RID_SOLVER_COMPONENT );
     200             : }
     201             : 
     202           0 : OUString SAL_CALL SolverComponent::getStatusDescription() throw (uno::RuntimeException)
     203             : {
     204           0 :     return maStatus;
     205             : }
     206             : 
     207           0 : OUString SAL_CALL SolverComponent::getPropertyDescription( const OUString& rPropertyName ) throw (uno::RuntimeException)
     208             : {
     209           0 :     sal_uInt32 nResId = 0;
     210           0 :     sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName );
     211           0 :     switch (nHandle)
     212             :     {
     213             :         case PROP_NONNEGATIVE:
     214           0 :             nResId = RID_PROPERTY_NONNEGATIVE;
     215           0 :             break;
     216             :         case PROP_INTEGER:
     217           0 :             nResId = RID_PROPERTY_INTEGER;
     218           0 :             break;
     219             :         case PROP_TIMEOUT:
     220           0 :             nResId = RID_PROPERTY_TIMEOUT;
     221           0 :             break;
     222             :         case PROP_EPSILONLEVEL:
     223           0 :             nResId = RID_PROPERTY_EPSILONLEVEL;
     224           0 :             break;
     225             :         case PROP_LIMITBBDEPTH:
     226           0 :             nResId = RID_PROPERTY_LIMITBBDEPTH;
     227           0 :             break;
     228             :         default:
     229             :             {
     230             :                 // unknown - leave empty
     231             :             }
     232             :     }
     233           0 :     OUString aRet;
     234           0 :     if ( nResId )
     235           0 :         aRet = lcl_GetResourceString( nResId );
     236           0 :     return aRet;
     237             : }
     238             : 
     239             : // XSolver: settings
     240             : 
     241           0 : uno::Reference<sheet::XSpreadsheetDocument> SAL_CALL SolverComponent::getDocument() throw(uno::RuntimeException)
     242             : {
     243           0 :     return mxDoc;
     244             : }
     245             : 
     246           0 : void SAL_CALL SolverComponent::setDocument( const uno::Reference<sheet::XSpreadsheetDocument>& _document )
     247             :                                 throw(uno::RuntimeException)
     248             : {
     249           0 :     mxDoc = _document;
     250           0 : }
     251             : 
     252           0 : table::CellAddress SAL_CALL SolverComponent::getObjective() throw(uno::RuntimeException)
     253             : {
     254           0 :     return maObjective;
     255             : }
     256             : 
     257           0 : void SAL_CALL SolverComponent::setObjective( const table::CellAddress& _objective ) throw(uno::RuntimeException)
     258             : {
     259           0 :     maObjective = _objective;
     260           0 : }
     261             : 
     262           0 : uno::Sequence<table::CellAddress> SAL_CALL SolverComponent::getVariables() throw(uno::RuntimeException)
     263             : {
     264           0 :     return maVariables;
     265             : }
     266             : 
     267           0 : void SAL_CALL SolverComponent::setVariables( const uno::Sequence<table::CellAddress>& _variables )
     268             :                                 throw(uno::RuntimeException)
     269             : {
     270           0 :     maVariables = _variables;
     271           0 : }
     272             : 
     273           0 : uno::Sequence<sheet::SolverConstraint> SAL_CALL SolverComponent::getConstraints() throw(uno::RuntimeException)
     274             : {
     275           0 :     return maConstraints;
     276             : }
     277             : 
     278           0 : void SAL_CALL SolverComponent::setConstraints( const uno::Sequence<sheet::SolverConstraint>& _constraints )
     279             :                                 throw(uno::RuntimeException)
     280             : {
     281           0 :     maConstraints = _constraints;
     282           0 : }
     283             : 
     284           0 : sal_Bool SAL_CALL SolverComponent::getMaximize() throw(uno::RuntimeException)
     285             : {
     286           0 :     return mbMaximize;
     287             : }
     288             : 
     289           0 : void SAL_CALL SolverComponent::setMaximize( sal_Bool _maximize ) throw(uno::RuntimeException)
     290             : {
     291           0 :     mbMaximize = _maximize;
     292           0 : }
     293             : 
     294             : // XSolver: get results
     295             : 
     296           0 : sal_Bool SAL_CALL SolverComponent::getSuccess() throw(uno::RuntimeException)
     297             : {
     298           0 :     return mbSuccess;
     299             : }
     300             : 
     301           0 : double SAL_CALL SolverComponent::getResultValue() throw(uno::RuntimeException)
     302             : {
     303           0 :     return mfResultValue;
     304             : }
     305             : 
     306           0 : uno::Sequence<double> SAL_CALL SolverComponent::getSolution() throw(uno::RuntimeException)
     307             : {
     308           0 :     return maSolution;
     309             : }
     310             : 
     311             : // -------------------------------------------------------------------------
     312             : 
     313           0 : void SAL_CALL SolverComponent::solve() throw(uno::RuntimeException)
     314             : {
     315           0 :     uno::Reference<frame::XModel> xModel( mxDoc, uno::UNO_QUERY );
     316           0 :     if ( !xModel.is() )
     317           0 :         throw uno::RuntimeException();
     318             : 
     319           0 :     maStatus = OUString();
     320           0 :     mbSuccess = false;
     321             : 
     322           0 :     if ( mnEpsilonLevel < EPS_TIGHT || mnEpsilonLevel > EPS_BAGGY )
     323             :     {
     324           0 :         maStatus = lcl_GetResourceString( RID_ERROR_EPSILONLEVEL );
     325             :         return;
     326             :     }
     327             : 
     328           0 :     xModel->lockControllers();
     329             : 
     330             :     // collect variables in vector (?)
     331             : 
     332           0 :     std::vector<table::CellAddress> aVariableCells;
     333           0 :     for (sal_Int32 nPos=0; nPos<maVariables.getLength(); nPos++)
     334           0 :         aVariableCells.push_back( maVariables[nPos] );
     335           0 :     size_t nVariables = aVariableCells.size();
     336           0 :     size_t nVar = 0;
     337             : 
     338             :     // collect all dependent cells
     339             : 
     340           0 :     ScSolverCellHashMap aCellsHash;
     341           0 :     aCellsHash[maObjective].reserve( nVariables + 1 );                  // objective function
     342             : 
     343           0 :     for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
     344             :     {
     345           0 :         table::CellAddress aCellAddr = maConstraints[nConstrPos].Left;
     346           0 :         aCellsHash[aCellAddr].reserve( nVariables + 1 );                // constraints: left hand side
     347             : 
     348           0 :         if ( maConstraints[nConstrPos].Right >>= aCellAddr )
     349           0 :             aCellsHash[aCellAddr].reserve( nVariables + 1 );            // constraints: right hand side
     350             :     }
     351             : 
     352             :     // set all variables to zero
     353             :     //! store old values?
     354             :     //! use old values as initial values?
     355           0 :     std::vector<table::CellAddress>::const_iterator aVarIter;
     356           0 :     for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter )
     357             :     {
     358           0 :         lcl_SetValue( mxDoc, *aVarIter, 0.0 );
     359             :     }
     360             : 
     361             :     // read initial values from all dependent cells
     362           0 :     ScSolverCellHashMap::iterator aCellsIter;
     363           0 :     for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter )
     364             :     {
     365           0 :         double fValue = lcl_GetValue( mxDoc, aCellsIter->first );
     366           0 :         aCellsIter->second.push_back( fValue );                         // store as first element, as-is
     367             :     }
     368             : 
     369             :     // loop through variables
     370           0 :     for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter )
     371             :     {
     372           0 :         lcl_SetValue( mxDoc, *aVarIter, 1.0 );      // set to 1 to examine influence
     373             : 
     374             :         // read value change from all dependent cells
     375           0 :         for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter )
     376             :         {
     377           0 :             double fChanged = lcl_GetValue( mxDoc, aCellsIter->first );
     378           0 :             double fInitial = aCellsIter->second.front();
     379           0 :             aCellsIter->second.push_back( fChanged - fInitial );
     380             :         }
     381             : 
     382           0 :         lcl_SetValue( mxDoc, *aVarIter, 2.0 );      // minimal test for linearity
     383             : 
     384           0 :         for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter )
     385             :         {
     386           0 :             double fInitial = aCellsIter->second.front();
     387           0 :             double fCoeff   = aCellsIter->second.back();       // last appended: coefficient for this variable
     388           0 :             double fTwo     = lcl_GetValue( mxDoc, aCellsIter->first );
     389             : 
     390           0 :             bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) ||
     391           0 :                            rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff );
     392             :             // second comparison is needed in case fTwo is zero
     393           0 :             if ( !bLinear )
     394           0 :                 maStatus = lcl_GetResourceString( RID_ERROR_NONLINEAR );
     395             :         }
     396             : 
     397           0 :         lcl_SetValue( mxDoc, *aVarIter, 0.0 );      // set back to zero for examining next variable
     398             :     }
     399             : 
     400           0 :     xModel->unlockControllers();
     401             : 
     402           0 :     if ( !maStatus.isEmpty() )
     403             :         return;
     404             : 
     405             :     //
     406             :     // build lp_solve model
     407             :     //
     408             : 
     409           0 :     lprec* lp = make_lp( 0, nVariables );
     410           0 :     if ( !lp )
     411             :         return;
     412             : 
     413           0 :     set_outputfile( lp, const_cast<char*>( "" ) );  // no output
     414             : 
     415             :     // set objective function
     416             : 
     417           0 :     const std::vector<double>& rObjCoeff = aCellsHash[maObjective];
     418           0 :     REAL* pObjVal = new REAL[nVariables+1];
     419           0 :     pObjVal[0] = 0.0;                           // ignored
     420           0 :     for (nVar=0; nVar<nVariables; nVar++)
     421           0 :         pObjVal[nVar+1] = rObjCoeff[nVar+1];
     422           0 :     set_obj_fn( lp, pObjVal );
     423           0 :     delete[] pObjVal;
     424           0 :     set_rh( lp, 0, rObjCoeff[0] );              // constant term of objective
     425             : 
     426             :     // add rows
     427             : 
     428           0 :     set_add_rowmode(lp, TRUE);
     429             : 
     430           0 :     for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
     431             :     {
     432             :         // integer constraints are set later
     433           0 :         sheet::SolverConstraintOperator eOp = maConstraints[nConstrPos].Operator;
     434           0 :         if ( eOp == sheet::SolverConstraintOperator_LESS_EQUAL ||
     435             :              eOp == sheet::SolverConstraintOperator_GREATER_EQUAL ||
     436             :              eOp == sheet::SolverConstraintOperator_EQUAL )
     437             :         {
     438           0 :             double fDirectValue = 0.0;
     439           0 :             bool bRightCell = false;
     440           0 :             table::CellAddress aRightAddr;
     441           0 :             const uno::Any& rRightAny = maConstraints[nConstrPos].Right;
     442           0 :             if ( rRightAny >>= aRightAddr )
     443           0 :                 bRightCell = true;                  // cell specified as right-hand side
     444             :             else
     445           0 :                 rRightAny >>= fDirectValue;         // constant value
     446             : 
     447           0 :             table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left;
     448             : 
     449           0 :             const std::vector<double>& rLeftCoeff = aCellsHash[aLeftAddr];
     450           0 :             REAL* pValues = new REAL[nVariables+1];
     451           0 :             pValues[0] = 0.0;                               // ignored?
     452           0 :             for (nVar=0; nVar<nVariables; nVar++)
     453           0 :                 pValues[nVar+1] = rLeftCoeff[nVar+1];
     454             : 
     455             :             // if left hand cell has a constant term, put into rhs value
     456           0 :             double fRightValue = -rLeftCoeff[0];
     457             : 
     458           0 :             if ( bRightCell )
     459             :             {
     460           0 :                 const std::vector<double>& rRightCoeff = aCellsHash[aRightAddr];
     461             :                 // modify pValues with rhs coefficients
     462           0 :                 for (nVar=0; nVar<nVariables; nVar++)
     463           0 :                     pValues[nVar+1] -= rRightCoeff[nVar+1];
     464             : 
     465           0 :                 fRightValue += rRightCoeff[0];      // constant term
     466             :             }
     467             :             else
     468           0 :                 fRightValue += fDirectValue;
     469             : 
     470           0 :             int nConstrType = LE;
     471           0 :             switch ( eOp )
     472             :             {
     473           0 :                 case sheet::SolverConstraintOperator_LESS_EQUAL:    nConstrType = LE; break;
     474           0 :                 case sheet::SolverConstraintOperator_GREATER_EQUAL: nConstrType = GE; break;
     475           0 :                 case sheet::SolverConstraintOperator_EQUAL:         nConstrType = EQ; break;
     476             :                 default:
     477             :                     OSL_FAIL( "unexpected enum type" );
     478             :             }
     479           0 :             add_constraint( lp, pValues, nConstrType, fRightValue );
     480             : 
     481           0 :             delete[] pValues;
     482             :         }
     483             :     }
     484             : 
     485           0 :     set_add_rowmode(lp, FALSE);
     486             : 
     487             :     // apply settings to all variables
     488             : 
     489           0 :     for (nVar=0; nVar<nVariables; nVar++)
     490             :     {
     491           0 :         if ( !mbNonNegative )
     492           0 :             set_unbounded(lp, nVar+1);          // allow negative (default is non-negative)
     493             :                                                 //! collect bounds from constraints?
     494           0 :         if ( mbInteger )
     495           0 :             set_int(lp, nVar+1, TRUE);
     496             :     }
     497             : 
     498             :     // apply single-var integer constraints
     499             : 
     500           0 :     for (sal_Int32 nConstrPos = 0; nConstrPos < maConstraints.getLength(); ++nConstrPos)
     501             :     {
     502           0 :         sheet::SolverConstraintOperator eOp = maConstraints[nConstrPos].Operator;
     503           0 :         if ( eOp == sheet::SolverConstraintOperator_INTEGER ||
     504             :              eOp == sheet::SolverConstraintOperator_BINARY )
     505             :         {
     506           0 :             table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left;
     507             :             // find variable index for cell
     508           0 :             for (nVar=0; nVar<nVariables; nVar++)
     509           0 :                 if ( AddressEqual( aVariableCells[nVar], aLeftAddr ) )
     510             :                 {
     511           0 :                     if ( eOp == sheet::SolverConstraintOperator_INTEGER )
     512           0 :                         set_int(lp, nVar+1, TRUE);
     513             :                     else
     514           0 :                         set_binary(lp, nVar+1, TRUE);
     515             :                 }
     516             :         }
     517             :     }
     518             : 
     519           0 :     if ( mbMaximize )
     520           0 :         set_maxim(lp);
     521             :     else
     522           0 :         set_minim(lp);
     523             : 
     524           0 :     if ( !mbLimitBBDepth )
     525           0 :         set_bb_depthlimit( lp, 0 );
     526             : 
     527           0 :     set_epslevel( lp, mnEpsilonLevel );
     528           0 :     set_timeout( lp, mnTimeout );
     529             : 
     530             :     // solve model
     531             : 
     532           0 :     int nResult = ::solve( lp );
     533             : 
     534           0 :     mbSuccess = ( nResult == OPTIMAL );
     535           0 :     if ( mbSuccess )
     536             :     {
     537             :         // get solution
     538             : 
     539           0 :         maSolution.realloc( nVariables );
     540             : 
     541           0 :         REAL* pResultVar = NULL;
     542           0 :         get_ptr_variables( lp, &pResultVar );
     543           0 :         for (nVar=0; nVar<nVariables; nVar++)
     544           0 :             maSolution[nVar] = pResultVar[nVar];
     545             : 
     546           0 :         mfResultValue = get_objective( lp );
     547             :     }
     548           0 :     else if ( nResult == INFEASIBLE )
     549           0 :         maStatus = lcl_GetResourceString( RID_ERROR_INFEASIBLE );
     550           0 :     else if ( nResult == UNBOUNDED )
     551           0 :         maStatus = lcl_GetResourceString( RID_ERROR_UNBOUNDED );
     552           0 :     else if ( nResult == TIMEOUT || nResult == SUBOPTIMAL )
     553           0 :         maStatus = lcl_GetResourceString( RID_ERROR_TIMEOUT );
     554             :     // SUBOPTIMAL is assumed to be caused by a timeout, and reported as an error
     555             : 
     556           0 :     delete_lp( lp );
     557             : }
     558             : 
     559             : // -------------------------------------------------------------------------
     560             : 
     561             : // XServiceInfo
     562             : 
     563           0 : uno::Sequence< OUString > SolverComponent_getSupportedServiceNames()
     564             : {
     565           0 :     uno::Sequence< OUString > aServiceNames( 1 );
     566           0 :     aServiceNames[ 0 ] = OUString("com.sun.star.sheet.Solver" );
     567           0 :     return aServiceNames;
     568             : }
     569             : 
     570           0 : OUString SolverComponent_getImplementationName()
     571             : {
     572           0 :     return OUString("com.sun.star.comp.Calc.Solver" );
     573             : }
     574             : 
     575           0 : OUString SAL_CALL SolverComponent::getImplementationName() throw(uno::RuntimeException)
     576             : {
     577           0 :     return SolverComponent_getImplementationName();
     578             : }
     579             : 
     580           0 : sal_Bool SAL_CALL SolverComponent::supportsService( const OUString& rServiceName ) throw(uno::RuntimeException)
     581             : {
     582           0 :     const uno::Sequence< OUString > aServices = SolverComponent_getSupportedServiceNames();
     583           0 :     const OUString* pArray = aServices.getConstArray();
     584           0 :     const OUString* pArrayEnd = pArray + aServices.getLength();
     585           0 :     return ::std::find( pArray, pArrayEnd, rServiceName ) != pArrayEnd;
     586             : }
     587             : 
     588           0 : uno::Sequence<OUString> SAL_CALL SolverComponent::getSupportedServiceNames() throw(uno::RuntimeException)
     589             : {
     590           0 :     return SolverComponent_getSupportedServiceNames();
     591             : }
     592             : 
     593           0 : uno::Reference<uno::XInterface> SolverComponent_createInstance( const uno::Reference<uno::XComponentContext>& rSMgr )
     594             :     throw(uno::Exception)
     595             : {
     596           0 :     return (cppu::OWeakObject*) new SolverComponent( rSMgr );
     597             : }
     598             : 
     599             : // -------------------------------------------------------------------------
     600             : 
     601             : extern "C"
     602             : {
     603           0 :     SAL_DLLPUBLIC_EXPORT void* SAL_CALL solver_component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
     604             :     {
     605           0 :         OUString    aImplName( OUString::createFromAscii( pImplName ) );
     606           0 :         void*       pRet = 0;
     607             : 
     608           0 :         if( pServiceManager )
     609             :         {
     610           0 :             uno::Reference< lang::XSingleComponentFactory > xFactory;
     611           0 :             if( aImplName.equals( SolverComponent_getImplementationName() ) )
     612             :                 xFactory = cppu::createSingleComponentFactory(
     613             :                         SolverComponent_createInstance,
     614             :                         OUString::createFromAscii( pImplName ),
     615           0 :                         SolverComponent_getSupportedServiceNames() );
     616             : 
     617           0 :             if( xFactory.is() )
     618             :             {
     619           0 :                 xFactory->acquire();
     620           0 :                 pRet = xFactory.get();
     621           0 :             }
     622             :         }
     623           0 :         return pRet;
     624             :     }
     625             : }
     626             : 
     627             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10