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

Generated by: LCOV version 1.10