From 077bdc73f2bcd625be1030fa8ff630c3dbd83657 Mon Sep 17 00:00:00 2001 From: Matúš Kukan Date: Thu, 27 Mar 2014 14:51:46 +0100 Subject: sccomp: Share common code and have only one library. And use constructor feature for UNO implementations. Change-Id: I42b6a6f417049cc8e2d44b74c7adc552680b1f2d --- sccomp/source/solver/CoinMPSolver.cxx | 344 ++++++++++++++ sccomp/source/solver/LpsolveSolver.cxx | 336 ++++++++++++++ sccomp/source/solver/SolverComponent.cxx | 270 +++++++++++ sccomp/source/solver/SolverComponent.hxx | 158 +++++++ sccomp/source/solver/coinmpsolver.component | 5 +- sccomp/source/solver/lpsolvesolver.component | 26 ++ sccomp/source/solver/solver-lpsolve.cxx | 631 -------------------------- sccomp/source/solver/solver.component | 25 -- sccomp/source/solver/solver.cxx | 639 --------------------------- sccomp/source/solver/solver.hxx | 120 ----- 10 files changed, 1137 insertions(+), 1417 deletions(-) create mode 100644 sccomp/source/solver/CoinMPSolver.cxx create mode 100644 sccomp/source/solver/LpsolveSolver.cxx create mode 100644 sccomp/source/solver/SolverComponent.cxx create mode 100644 sccomp/source/solver/SolverComponent.hxx create mode 100644 sccomp/source/solver/lpsolvesolver.component delete mode 100644 sccomp/source/solver/solver-lpsolve.cxx delete mode 100644 sccomp/source/solver/solver.component delete mode 100644 sccomp/source/solver/solver.cxx delete mode 100644 sccomp/source/solver/solver.hxx (limited to 'sccomp/source') diff --git a/sccomp/source/solver/CoinMPSolver.cxx b/sccomp/source/solver/CoinMPSolver.cxx new file mode 100644 index 000000000000..13ecd3bcf956 --- /dev/null +++ b/sccomp/source/solver/CoinMPSolver.cxx @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include "SolverComponent.hxx" +#include "solver.hrc" + +#include +#include +#include + +#include +#include + +using namespace com::sun::star; + +class CoinMPSolver : public SolverComponent +{ +public: + CoinMPSolver() {} + virtual ~CoinMPSolver() SAL_OVERRIDE {} + +private: + virtual void SAL_CALL solve() throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual OUString SAL_CALL getImplementationName() + throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + return OUString("com.sun.star.comp.Calc.CoinMPSolver"); + } +}; + +void SAL_CALL CoinMPSolver::solve() throw(uno::RuntimeException, std::exception) +{ + uno::Reference xModel( mxDoc, uno::UNO_QUERY ); + if ( !xModel.is() ) + throw uno::RuntimeException(); + + maStatus = ""; + mbSuccess = false; + + xModel->lockControllers(); + + // collect variables in vector (?) + + std::vector aVariableCells; + for (sal_Int32 nPos=0; nPos>= aCellAddr ) + aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side + } + + // set all variables to zero + //! store old values? + //! use old values as initial values? + std::vector::const_iterator aVarIter; + for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) + { + SolverComponent::SetValue( mxDoc, *aVarIter, 0.0 ); + } + + // read initial values from all dependent cells + ScSolverCellHashMap::iterator aCellsIter; + for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) + { + double fValue = SolverComponent::GetValue( mxDoc, aCellsIter->first ); + aCellsIter->second.push_back( fValue ); // store as first element, as-is + } + + // loop through variables + for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) + { + SolverComponent::SetValue( mxDoc, *aVarIter, 1.0 ); // set to 1 to examine influence + + // read value change from all dependent cells + for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) + { + double fChanged = SolverComponent::GetValue( mxDoc, aCellsIter->first ); + double fInitial = aCellsIter->second.front(); + aCellsIter->second.push_back( fChanged - fInitial ); + } + + SolverComponent::SetValue( mxDoc, *aVarIter, 2.0 ); // minimal test for linearity + + for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) + { + double fInitial = aCellsIter->second.front(); + double fCoeff = aCellsIter->second.back(); // last appended: coefficient for this variable + double fTwo = SolverComponent::GetValue( mxDoc, aCellsIter->first ); + + bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || + rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); + // second comparison is needed in case fTwo is zero + if ( !bLinear ) + maStatus = SolverComponent::GetResourceString( RID_ERROR_NONLINEAR ); + } + + SolverComponent::SetValue( mxDoc, *aVarIter, 0.0 ); // set back to zero for examining next variable + } + + xModel->unlockControllers(); + + if ( !maStatus.isEmpty() ) + return; + + // + // build parameter arrays for CoinMP + // + + // set objective function + + const std::vector& rObjCoeff = aCellsHash[maObjective]; + double* pObjectCoeffs = new double[nVariables]; + for (nVar=0; nVar>= aRightAddr ) + bRightCell = true; // cell specified as right-hand side + else + rRightAny >>= fDirectValue; // constant value + + table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left; + + const std::vector& rLeftCoeff = aCellsHash[aLeftAddr]; + double* pValues = &pCompMatrix[nConstrPos * nVariables]; + for (nVar=0; nVar& rRightCoeff = aCellsHash[aRightAddr]; + // modify pValues with rhs coefficients + for (nVar=0; nVar const &) +{ + return cppu::acquire(new CoinMPSolver()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/LpsolveSolver.cxx b/sccomp/source/solver/LpsolveSolver.cxx new file mode 100644 index 000000000000..3c2a014ac602 --- /dev/null +++ b/sccomp/source/solver/LpsolveSolver.cxx @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * + * for a copy of the LGPLv3 License. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + * + ************************************************************************/ + +#include "sal/config.h" +#include + +#undef LANGUAGE_NONE +#if defined SAL_W32 +#define WINAPI __stdcall +#endif +#define LoadInverseLib FALSE +#define LoadLanguageLib FALSE +#ifdef SYSTEM_LPSOLVE +#include +#else +#include +#endif +#undef LANGUAGE_NONE + +#include "SolverComponent.hxx" +#include "solver.hrc" + +#include +#include +#include +#include +#include +#include + +using namespace com::sun::star; + +class LpsolveSolver : public SolverComponent +{ +public: + LpsolveSolver() {} + virtual ~LpsolveSolver() SAL_OVERRIDE {} + +private: + virtual void SAL_CALL solve() throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual OUString SAL_CALL getImplementationName() + throw(css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + return OUString("com.sun.star.comp.Calc.LpsolveSolver"); + } +}; + +void SAL_CALL LpsolveSolver::solve() throw(uno::RuntimeException, std::exception) +{ + uno::Reference xModel( mxDoc, uno::UNO_QUERY ); + if ( !xModel.is() ) + throw uno::RuntimeException(); + + maStatus = ""; + mbSuccess = false; + + if ( mnEpsilonLevel < EPS_TIGHT || mnEpsilonLevel > EPS_BAGGY ) + { + maStatus = SolverComponent::GetResourceString( RID_ERROR_EPSILONLEVEL ); + return; + } + + xModel->lockControllers(); + + // collect variables in vector (?) + + std::vector aVariableCells; + for (sal_Int32 nPos=0; nPos>= aCellAddr ) + aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side + } + + // set all variables to zero + //! store old values? + //! use old values as initial values? + std::vector::const_iterator aVarIter; + for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) + { + SolverComponent::SetValue( mxDoc, *aVarIter, 0.0 ); + } + + // read initial values from all dependent cells + ScSolverCellHashMap::iterator aCellsIter; + for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) + { + double fValue = SolverComponent::GetValue( mxDoc, aCellsIter->first ); + aCellsIter->second.push_back( fValue ); // store as first element, as-is + } + + // loop through variables + for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) + { + SolverComponent::SetValue( mxDoc, *aVarIter, 1.0 ); // set to 1 to examine influence + + // read value change from all dependent cells + for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) + { + double fChanged = SolverComponent::GetValue( mxDoc, aCellsIter->first ); + double fInitial = aCellsIter->second.front(); + aCellsIter->second.push_back( fChanged - fInitial ); + } + + SolverComponent::SetValue( mxDoc, *aVarIter, 2.0 ); // minimal test for linearity + + for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) + { + double fInitial = aCellsIter->second.front(); + double fCoeff = aCellsIter->second.back(); // last appended: coefficient for this variable + double fTwo = SolverComponent::GetValue( mxDoc, aCellsIter->first ); + + bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || + rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); + // second comparison is needed in case fTwo is zero + if ( !bLinear ) + maStatus = SolverComponent::GetResourceString( RID_ERROR_NONLINEAR ); + } + + SolverComponent::SetValue( mxDoc, *aVarIter, 0.0 ); // set back to zero for examining next variable + } + + xModel->unlockControllers(); + + if ( !maStatus.isEmpty() ) + return; + + + // build lp_solve model + + + lprec* lp = make_lp( 0, nVariables ); + if ( !lp ) + return; + + set_outputfile( lp, const_cast( "" ) ); // no output + + // set objective function + + const std::vector& rObjCoeff = aCellsHash[maObjective]; + REAL* pObjVal = new REAL[nVariables+1]; + pObjVal[0] = 0.0; // ignored + for (nVar=0; nVar>= aRightAddr ) + bRightCell = true; // cell specified as right-hand side + else + rRightAny >>= fDirectValue; // constant value + + table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left; + + const std::vector& rLeftCoeff = aCellsHash[aLeftAddr]; + REAL* pValues = new REAL[nVariables+1]; + pValues[0] = 0.0; // ignored? + for (nVar=0; nVar& rRightCoeff = aCellsHash[aRightAddr]; + // modify pValues with rhs coefficients + for (nVar=0; nVar const &) +{ + return cppu::acquire(new LpsolveSolver()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/SolverComponent.cxx b/sccomp/source/solver/SolverComponent.cxx new file mode 100644 index 000000000000..bb20cfe20c52 --- /dev/null +++ b/sccomp/source/solver/SolverComponent.cxx @@ -0,0 +1,270 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "SolverComponent.hxx" +#include "solver.hrc" + +#include +#include +#include +#include + +#include +#include + +#include + +using namespace com::sun::star; + + +#define STR_NONNEGATIVE "NonNegative" +#define STR_INTEGER "Integer" +#define STR_TIMEOUT "Timeout" +#define STR_EPSILONLEVEL "EpsilonLevel" +#define STR_LIMITBBDEPTH "LimitBBDepth" + + +// Resources from tools are used for translated strings + +ResMgr* SolverComponent::pSolverResMgr = NULL; + +OUString SolverComponent::GetResourceString( sal_uInt32 nId ) +{ + if (!pSolverResMgr) + pSolverResMgr = ResMgr::CreateResMgr("solver"); + + return ResId(nId, *pSolverResMgr).toString(); +} + +size_t ScSolverCellHash::operator()( const css::table::CellAddress& rAddress ) const +{ + return ( rAddress.Sheet << 24 ) | ( rAddress.Column << 16 ) | rAddress.Row; +} + +bool ScSolverCellEqual::operator()( const css::table::CellAddress& rAddr1, const css::table::CellAddress& rAddr2 ) const +{ + return AddressEqual( rAddr1, rAddr2 ); +} + +namespace +{ + enum + { + PROP_NONNEGATIVE, + PROP_INTEGER, + PROP_TIMEOUT, + PROP_EPSILONLEVEL, + PROP_LIMITBBDEPTH + }; +} + +uno::Reference SolverComponent::GetCell( const uno::Reference& xDoc, + const table::CellAddress& rPos ) +{ + uno::Reference xSheets( xDoc->getSheets(), uno::UNO_QUERY ); + uno::Reference xSheet( xSheets->getByIndex( rPos.Sheet ), uno::UNO_QUERY ); + return xSheet->getCellByPosition( rPos.Column, rPos.Row ); +} + +void SolverComponent::SetValue( const uno::Reference& xDoc, + const table::CellAddress& rPos, double fValue ) +{ + SolverComponent::GetCell( xDoc, rPos )->setValue( fValue ); +} + +double SolverComponent::GetValue( const uno::Reference& xDoc, + const table::CellAddress& rPos ) +{ + return SolverComponent::GetCell( xDoc, rPos )->getValue(); +} + +SolverComponent::SolverComponent() : + OPropertyContainer( GetBroadcastHelper() ), + mbMaximize( sal_True ), + mbNonNegative( sal_False ), + mbInteger( sal_False ), + mnTimeout( 100 ), + mnEpsilonLevel( 0 ), + mbLimitBBDepth( sal_True ), + mbSuccess( sal_False ), + mfResultValue( 0.0 ) +{ + // for XPropertySet implementation: + registerProperty( STR_NONNEGATIVE, PROP_NONNEGATIVE, 0, &mbNonNegative, getCppuType( &mbNonNegative ) ); + registerProperty( STR_INTEGER, PROP_INTEGER, 0, &mbInteger, getCppuType( &mbInteger ) ); + registerProperty( STR_TIMEOUT, PROP_TIMEOUT, 0, &mnTimeout, getCppuType( &mnTimeout ) ); + registerProperty( STR_EPSILONLEVEL, PROP_EPSILONLEVEL, 0, &mnEpsilonLevel, getCppuType( &mnEpsilonLevel ) ); + registerProperty( STR_LIMITBBDEPTH, PROP_LIMITBBDEPTH, 0, &mbLimitBBDepth, getCppuType( &mbLimitBBDepth ) ); +} + +SolverComponent::~SolverComponent() +{ +} + +IMPLEMENT_FORWARD_XINTERFACE2( SolverComponent, SolverComponent_Base, OPropertyContainer ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( SolverComponent, SolverComponent_Base, OPropertyContainer ) + +cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const +{ + uno::Sequence aProps; + describeProperties( aProps ); + return new cppu::OPropertyArrayHelper( aProps ); +} + +cppu::IPropertyArrayHelper& SAL_CALL SolverComponent::getInfoHelper() +{ + return *getArrayHelper(); +} + +uno::Reference SAL_CALL SolverComponent::getPropertySetInfo() throw(uno::RuntimeException, std::exception) +{ + return createPropertySetInfo( getInfoHelper() ); +} + +// XSolverDescription + +OUString SAL_CALL SolverComponent::getComponentDescription() throw (uno::RuntimeException, std::exception) +{ + return SolverComponent::GetResourceString( RID_SOLVER_COMPONENT ); +} + +OUString SAL_CALL SolverComponent::getStatusDescription() throw (uno::RuntimeException, std::exception) +{ + return maStatus; +} + +OUString SAL_CALL SolverComponent::getPropertyDescription( const OUString& rPropertyName ) throw (uno::RuntimeException, std::exception) +{ + sal_uInt32 nResId = 0; + sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName ); + switch (nHandle) + { + case PROP_NONNEGATIVE: + nResId = RID_PROPERTY_NONNEGATIVE; + break; + case PROP_INTEGER: + nResId = RID_PROPERTY_INTEGER; + break; + case PROP_TIMEOUT: + nResId = RID_PROPERTY_TIMEOUT; + break; + case PROP_EPSILONLEVEL: + nResId = RID_PROPERTY_EPSILONLEVEL; + break; + case PROP_LIMITBBDEPTH: + nResId = RID_PROPERTY_LIMITBBDEPTH; + break; + default: + { + // unknown - leave empty + } + } + OUString aRet; + if ( nResId ) + aRet = SolverComponent::GetResourceString( nResId ); + return aRet; +} + +// XSolver: settings + +uno::Reference SAL_CALL SolverComponent::getDocument() throw(uno::RuntimeException, std::exception) +{ + return mxDoc; +} + +void SAL_CALL SolverComponent::setDocument( const uno::Reference& _document ) + throw(uno::RuntimeException, std::exception) +{ + mxDoc = _document; +} + +table::CellAddress SAL_CALL SolverComponent::getObjective() throw(uno::RuntimeException, std::exception) +{ + return maObjective; +} + +void SAL_CALL SolverComponent::setObjective( const table::CellAddress& _objective ) throw(uno::RuntimeException, std::exception) +{ + maObjective = _objective; +} + +uno::Sequence SAL_CALL SolverComponent::getVariables() throw(uno::RuntimeException, std::exception) +{ + return maVariables; +} + +void SAL_CALL SolverComponent::setVariables( const uno::Sequence& _variables ) + throw(uno::RuntimeException, std::exception) +{ + maVariables = _variables; +} + +uno::Sequence SAL_CALL SolverComponent::getConstraints() throw(uno::RuntimeException, std::exception) +{ + return maConstraints; +} + +void SAL_CALL SolverComponent::setConstraints( const uno::Sequence& _constraints ) + throw(uno::RuntimeException, std::exception) +{ + maConstraints = _constraints; +} + +sal_Bool SAL_CALL SolverComponent::getMaximize() throw(uno::RuntimeException, std::exception) +{ + return mbMaximize; +} + +void SAL_CALL SolverComponent::setMaximize( sal_Bool _maximize ) throw(uno::RuntimeException, std::exception) +{ + mbMaximize = _maximize; +} + +// XSolver: get results + +sal_Bool SAL_CALL SolverComponent::getSuccess() throw(uno::RuntimeException, std::exception) +{ + return mbSuccess; +} + +double SAL_CALL SolverComponent::getResultValue() throw(uno::RuntimeException, std::exception) +{ + return mfResultValue; +} + +uno::Sequence SAL_CALL SolverComponent::getSolution() throw(uno::RuntimeException, std::exception) +{ + return maSolution; +} + +// XServiceInfo + +sal_Bool SAL_CALL SolverComponent::supportsService( const OUString& rServiceName ) throw(uno::RuntimeException, std::exception) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence SAL_CALL SolverComponent::getSupportedServiceNames() throw(uno::RuntimeException, std::exception) +{ + uno::Sequence< OUString > aServiceNames( 1 ); + aServiceNames[ 0 ] = "com.sun.star.sheet.Solver"; + return aServiceNames; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/SolverComponent.hxx b/sccomp/source/solver/SolverComponent.hxx new file mode 100644 index 000000000000..2d1c2e77c9d2 --- /dev/null +++ b/sccomp/source/solver/SolverComponent.hxx @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef SOLVER_HXX +#define SOLVER_HXX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class ResMgr; + +// hash map for the coefficients of a dependent cell (objective or constraint) +// The size of each vector is the number of columns (variable cells) plus one, first entry is initial value. + +struct ScSolverCellHash +{ + size_t operator()( const css::table::CellAddress& rAddress ) const; +}; + +inline bool AddressEqual( const css::table::CellAddress& rAddr1, const css::table::CellAddress& rAddr2 ) +{ + return rAddr1.Sheet == rAddr2.Sheet && rAddr1.Column == rAddr2.Column && rAddr1.Row == rAddr2.Row; +} + +struct ScSolverCellEqual +{ + bool operator()( const css::table::CellAddress& rAddr1, const css::table::CellAddress& rAddr2 ) const; +}; + +typedef boost::unordered_map< css::table::CellAddress, std::vector, ScSolverCellHash, ScSolverCellEqual > ScSolverCellHashMap; + +typedef cppu::WeakImplHelper3< + com::sun::star::sheet::XSolver, + com::sun::star::sheet::XSolverDescription, + com::sun::star::lang::XServiceInfo > + SolverComponent_Base; + +class SolverComponent : public comphelper::OMutexAndBroadcastHelper, + public comphelper::OPropertyContainer, + public comphelper::OPropertyArrayUsageHelper< SolverComponent >, + public SolverComponent_Base +{ +protected: + static ResMgr* pSolverResMgr; + + // settings + com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument > mxDoc; + com::sun::star::table::CellAddress maObjective; + com::sun::star::uno::Sequence< com::sun::star::table::CellAddress > maVariables; + com::sun::star::uno::Sequence< com::sun::star::sheet::SolverConstraint > maConstraints; + sal_Bool mbMaximize; + // set via XPropertySet + sal_Bool mbNonNegative; + sal_Bool mbInteger; + sal_Int32 mnTimeout; + sal_Int32 mnEpsilonLevel; + sal_Bool mbLimitBBDepth; + // results + sal_Bool mbSuccess; + double mfResultValue; + com::sun::star::uno::Sequence< double > maSolution; + OUString maStatus; + + static OUString GetResourceString( sal_uInt32 nId ); + static css::uno::Reference GetCell( + const css::uno::Reference& xDoc, + const css::table::CellAddress& rPos ); + static void SetValue( + const css::uno::Reference& xDoc, + const css::table::CellAddress& rPos, double fValue ); + static double GetValue( + const css::uno::Reference& xDoc, + const css::table::CellAddress& rPos ); + +public: + SolverComponent(); + virtual ~SolverComponent(); + + DECLARE_XINTERFACE() + DECLARE_XTYPEPROVIDER() + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() + throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE; // from OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE; // from OPropertyArrayUsageHelper + + // XSolver + virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument > SAL_CALL getDocument() + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual void SAL_CALL setDocument( const ::com::sun::star::uno::Reference< + ::com::sun::star::sheet::XSpreadsheetDocument >& _document ) + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::com::sun::star::table::CellAddress SAL_CALL getObjective() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual void SAL_CALL setObjective( const ::com::sun::star::table::CellAddress& _objective ) + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::table::CellAddress > SAL_CALL getVariables() + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual void SAL_CALL setVariables( const ::com::sun::star::uno::Sequence< + ::com::sun::star::table::CellAddress >& _variables ) + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::SolverConstraint > SAL_CALL getConstraints() + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual void SAL_CALL setConstraints( const ::com::sun::star::uno::Sequence< + ::com::sun::star::sheet::SolverConstraint >& _constraints ) + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::sal_Bool SAL_CALL getMaximize() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual void SAL_CALL setMaximize( ::sal_Bool _maximize ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + + virtual ::sal_Bool SAL_CALL getSuccess() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual double SAL_CALL getResultValue() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getSolution() + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + + virtual void SAL_CALL solve() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE = 0; + + // XSolverDescription + virtual OUString SAL_CALL getComponentDescription() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual OUString SAL_CALL getStatusDescription() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual OUString SAL_CALL getPropertyDescription( const OUString& aPropertyName ) + throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw(::com::sun::star::uno::RuntimeException, std::exception) = 0; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/coinmpsolver.component b/sccomp/source/solver/coinmpsolver.component index 0feb3d0b4f13..3ddeeea4af47 100644 --- a/sccomp/source/solver/coinmpsolver.component +++ b/sccomp/source/solver/coinmpsolver.component @@ -7,9 +7,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - - + diff --git a/sccomp/source/solver/lpsolvesolver.component b/sccomp/source/solver/lpsolvesolver.component new file mode 100644 index 000000000000..76e2f3bbf722 --- /dev/null +++ b/sccomp/source/solver/lpsolvesolver.component @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/sccomp/source/solver/solver-lpsolve.cxx b/sccomp/source/solver/solver-lpsolve.cxx deleted file mode 100644 index 0c8e811de128..000000000000 --- a/sccomp/source/solver/solver-lpsolve.cxx +++ /dev/null @@ -1,631 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - * - ************************************************************************/ - -#include "sal/config.h" -#include - -#undef LANGUAGE_NONE -#if defined SAL_W32 -#define WINAPI __stdcall -#endif -#define LoadInverseLib FALSE -#define LoadLanguageLib FALSE -#ifdef SYSTEM_LPSOLVE -#include -#else -#include -#endif -#undef LANGUAGE_NONE - -#include "solver.hxx" -#include "solver.hrc" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -using namespace com::sun::star; - - -#define STR_NONNEGATIVE "NonNegative" -#define STR_INTEGER "Integer" -#define STR_TIMEOUT "Timeout" -#define STR_EPSILONLEVEL "EpsilonLevel" -#define STR_LIMITBBDEPTH "LimitBBDepth" - - -// Resources from tools are used for translated strings - -static ResMgr* pSolverResMgr = NULL; - -static OUString lcl_GetResourceString( sal_uInt32 nId ) -{ - if (!pSolverResMgr) - pSolverResMgr = ResMgr::CreateResMgr("solver"); - - return ResId(nId, *pSolverResMgr).toString(); -} - - - -namespace -{ - enum - { - PROP_NONNEGATIVE, - PROP_INTEGER, - PROP_TIMEOUT, - PROP_EPSILONLEVEL, - PROP_LIMITBBDEPTH - }; -} - - - -// hash map for the coefficients of a dependent cell (objective or constraint) -// The size of each vector is the number of columns (variable cells) plus one, first entry is initial value. - -struct ScSolverCellHash -{ - size_t operator()( const table::CellAddress& rAddress ) const - { - return ( rAddress.Sheet << 24 ) | ( rAddress.Column << 16 ) | rAddress.Row; - } -}; - -inline bool AddressEqual( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 ) -{ - return rAddr1.Sheet == rAddr2.Sheet && rAddr1.Column == rAddr2.Column && rAddr1.Row == rAddr2.Row; -} - -struct ScSolverCellEqual -{ - bool operator()( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 ) const - { - return AddressEqual( rAddr1, rAddr2 ); - } -}; - -typedef boost::unordered_map< table::CellAddress, std::vector, ScSolverCellHash, ScSolverCellEqual > ScSolverCellHashMap; - - - -static uno::Reference lcl_GetCell( const uno::Reference& xDoc, - const table::CellAddress& rPos ) -{ - uno::Reference xSheets( xDoc->getSheets(), uno::UNO_QUERY ); - uno::Reference xSheet( xSheets->getByIndex( rPos.Sheet ), uno::UNO_QUERY ); - return xSheet->getCellByPosition( rPos.Column, rPos.Row ); -} - -static void lcl_SetValue( const uno::Reference& xDoc, - const table::CellAddress& rPos, double fValue ) -{ - lcl_GetCell( xDoc, rPos )->setValue( fValue ); -} - -static double lcl_GetValue( const uno::Reference& xDoc, - const table::CellAddress& rPos ) -{ - return lcl_GetCell( xDoc, rPos )->getValue(); -} - - - -SolverComponent::SolverComponent( const uno::Reference& /* rSMgr */ ) : - OPropertyContainer( GetBroadcastHelper() ), - mbMaximize( sal_True ), - mbNonNegative( sal_False ), - mbInteger( sal_False ), - mnTimeout( 100 ), - mnEpsilonLevel( 0 ), - mbLimitBBDepth( sal_True ), - mbSuccess( sal_False ), - mfResultValue( 0.0 ) -{ - // for XPropertySet implementation: - registerProperty( STR_NONNEGATIVE, PROP_NONNEGATIVE, 0, &mbNonNegative, getCppuType( &mbNonNegative ) ); - registerProperty( STR_INTEGER, PROP_INTEGER, 0, &mbInteger, getCppuType( &mbInteger ) ); - registerProperty( STR_TIMEOUT, PROP_TIMEOUT, 0, &mnTimeout, getCppuType( &mnTimeout ) ); - registerProperty( STR_EPSILONLEVEL, PROP_EPSILONLEVEL, 0, &mnEpsilonLevel, getCppuType( &mnEpsilonLevel ) ); - registerProperty( STR_LIMITBBDEPTH, PROP_LIMITBBDEPTH, 0, &mbLimitBBDepth, getCppuType( &mbLimitBBDepth ) ); -} - -SolverComponent::~SolverComponent() -{ -} - -IMPLEMENT_FORWARD_XINTERFACE2( SolverComponent, SolverComponent_Base, OPropertyContainer ) -IMPLEMENT_FORWARD_XTYPEPROVIDER2( SolverComponent, SolverComponent_Base, OPropertyContainer ) - -cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const -{ - uno::Sequence aProps; - describeProperties( aProps ); - return new cppu::OPropertyArrayHelper( aProps ); -} - -cppu::IPropertyArrayHelper& SAL_CALL SolverComponent::getInfoHelper() -{ - return *getArrayHelper(); -} - -uno::Reference SAL_CALL SolverComponent::getPropertySetInfo() throw(uno::RuntimeException, std::exception) -{ - return createPropertySetInfo( getInfoHelper() ); -} - -// XSolverDescription - -OUString SAL_CALL SolverComponent::getComponentDescription() throw (uno::RuntimeException, std::exception) -{ - return lcl_GetResourceString( RID_SOLVER_COMPONENT ); -} - -OUString SAL_CALL SolverComponent::getStatusDescription() throw (uno::RuntimeException, std::exception) -{ - return maStatus; -} - -OUString SAL_CALL SolverComponent::getPropertyDescription( const OUString& rPropertyName ) throw (uno::RuntimeException, std::exception) -{ - sal_uInt32 nResId = 0; - sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName ); - switch (nHandle) - { - case PROP_NONNEGATIVE: - nResId = RID_PROPERTY_NONNEGATIVE; - break; - case PROP_INTEGER: - nResId = RID_PROPERTY_INTEGER; - break; - case PROP_TIMEOUT: - nResId = RID_PROPERTY_TIMEOUT; - break; - case PROP_EPSILONLEVEL: - nResId = RID_PROPERTY_EPSILONLEVEL; - break; - case PROP_LIMITBBDEPTH: - nResId = RID_PROPERTY_LIMITBBDEPTH; - break; - default: - { - // unknown - leave empty - } - } - OUString aRet; - if ( nResId ) - aRet = lcl_GetResourceString( nResId ); - return aRet; -} - -// XSolver: settings - -uno::Reference SAL_CALL SolverComponent::getDocument() throw(uno::RuntimeException, std::exception) -{ - return mxDoc; -} - -void SAL_CALL SolverComponent::setDocument( const uno::Reference& _document ) - throw(uno::RuntimeException, std::exception) -{ - mxDoc = _document; -} - -table::CellAddress SAL_CALL SolverComponent::getObjective() throw(uno::RuntimeException, std::exception) -{ - return maObjective; -} - -void SAL_CALL SolverComponent::setObjective( const table::CellAddress& _objective ) throw(uno::RuntimeException, std::exception) -{ - maObjective = _objective; -} - -uno::Sequence SAL_CALL SolverComponent::getVariables() throw(uno::RuntimeException, std::exception) -{ - return maVariables; -} - -void SAL_CALL SolverComponent::setVariables( const uno::Sequence& _variables ) - throw(uno::RuntimeException, std::exception) -{ - maVariables = _variables; -} - -uno::Sequence SAL_CALL SolverComponent::getConstraints() throw(uno::RuntimeException, std::exception) -{ - return maConstraints; -} - -void SAL_CALL SolverComponent::setConstraints( const uno::Sequence& _constraints ) - throw(uno::RuntimeException, std::exception) -{ - maConstraints = _constraints; -} - -sal_Bool SAL_CALL SolverComponent::getMaximize() throw(uno::RuntimeException, std::exception) -{ - return mbMaximize; -} - -void SAL_CALL SolverComponent::setMaximize( sal_Bool _maximize ) throw(uno::RuntimeException, std::exception) -{ - mbMaximize = _maximize; -} - -// XSolver: get results - -sal_Bool SAL_CALL SolverComponent::getSuccess() throw(uno::RuntimeException, std::exception) -{ - return mbSuccess; -} - -double SAL_CALL SolverComponent::getResultValue() throw(uno::RuntimeException, std::exception) -{ - return mfResultValue; -} - -uno::Sequence SAL_CALL SolverComponent::getSolution() throw(uno::RuntimeException, std::exception) -{ - return maSolution; -} - -void SAL_CALL SolverComponent::solve() throw(uno::RuntimeException, std::exception) -{ - uno::Reference xModel( mxDoc, uno::UNO_QUERY ); - if ( !xModel.is() ) - throw uno::RuntimeException(); - - maStatus = ""; - mbSuccess = false; - - if ( mnEpsilonLevel < EPS_TIGHT || mnEpsilonLevel > EPS_BAGGY ) - { - maStatus = lcl_GetResourceString( RID_ERROR_EPSILONLEVEL ); - return; - } - - xModel->lockControllers(); - - // collect variables in vector (?) - - std::vector aVariableCells; - for (sal_Int32 nPos=0; nPos>= aCellAddr ) - aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side - } - - // set all variables to zero - //! store old values? - //! use old values as initial values? - std::vector::const_iterator aVarIter; - for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) - { - lcl_SetValue( mxDoc, *aVarIter, 0.0 ); - } - - // read initial values from all dependent cells - ScSolverCellHashMap::iterator aCellsIter; - for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) - { - double fValue = lcl_GetValue( mxDoc, aCellsIter->first ); - aCellsIter->second.push_back( fValue ); // store as first element, as-is - } - - // loop through variables - for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) - { - lcl_SetValue( mxDoc, *aVarIter, 1.0 ); // set to 1 to examine influence - - // read value change from all dependent cells - for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) - { - double fChanged = lcl_GetValue( mxDoc, aCellsIter->first ); - double fInitial = aCellsIter->second.front(); - aCellsIter->second.push_back( fChanged - fInitial ); - } - - lcl_SetValue( mxDoc, *aVarIter, 2.0 ); // minimal test for linearity - - for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) - { - double fInitial = aCellsIter->second.front(); - double fCoeff = aCellsIter->second.back(); // last appended: coefficient for this variable - double fTwo = lcl_GetValue( mxDoc, aCellsIter->first ); - - bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || - rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); - // second comparison is needed in case fTwo is zero - if ( !bLinear ) - maStatus = lcl_GetResourceString( RID_ERROR_NONLINEAR ); - } - - lcl_SetValue( mxDoc, *aVarIter, 0.0 ); // set back to zero for examining next variable - } - - xModel->unlockControllers(); - - if ( !maStatus.isEmpty() ) - return; - - - // build lp_solve model - - - lprec* lp = make_lp( 0, nVariables ); - if ( !lp ) - return; - - set_outputfile( lp, const_cast( "" ) ); // no output - - // set objective function - - const std::vector& rObjCoeff = aCellsHash[maObjective]; - REAL* pObjVal = new REAL[nVariables+1]; - pObjVal[0] = 0.0; // ignored - for (nVar=0; nVar>= aRightAddr ) - bRightCell = true; // cell specified as right-hand side - else - rRightAny >>= fDirectValue; // constant value - - table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left; - - const std::vector& rLeftCoeff = aCellsHash[aLeftAddr]; - REAL* pValues = new REAL[nVariables+1]; - pValues[0] = 0.0; // ignored? - for (nVar=0; nVar& rRightCoeff = aCellsHash[aRightAddr]; - // modify pValues with rhs coefficients - for (nVar=0; nVar SolverComponent_getSupportedServiceNames() -{ - uno::Sequence< OUString > aServiceNames( 1 ); - aServiceNames[ 0 ] = "com.sun.star.sheet.Solver"; - return aServiceNames; -} - -OUString SolverComponent_getImplementationName() -{ - return OUString("com.sun.star.comp.Calc.Solver"); -} - -OUString SAL_CALL SolverComponent::getImplementationName() throw(uno::RuntimeException, std::exception) -{ - return SolverComponent_getImplementationName(); -} - -sal_Bool SAL_CALL SolverComponent::supportsService( const OUString& rServiceName ) throw(uno::RuntimeException, std::exception) -{ - return cppu::supportsService(this, rServiceName); -} - -uno::Sequence SAL_CALL SolverComponent::getSupportedServiceNames() throw(uno::RuntimeException, std::exception) -{ - return SolverComponent_getSupportedServiceNames(); -} - -uno::Reference SolverComponent_createInstance( const uno::Reference& rSMgr ) - throw(uno::Exception) -{ - return (cppu::OWeakObject*) new SolverComponent( rSMgr ); -} - -extern "C" -{ - SAL_DLLPUBLIC_EXPORT void* SAL_CALL solver_component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) - { - OUString aImplName( OUString::createFromAscii( pImplName ) ); - void* pRet = 0; - - if( pServiceManager ) - { - uno::Reference< lang::XSingleComponentFactory > xFactory; - if( aImplName.equals( SolverComponent_getImplementationName() ) ) - xFactory = cppu::createSingleComponentFactory( - SolverComponent_createInstance, - OUString::createFromAscii( pImplName ), - SolverComponent_getSupportedServiceNames() ); - - if( xFactory.is() ) - { - xFactory->acquire(); - pRet = xFactory.get(); - } - } - return pRet; - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/solver.component b/sccomp/source/solver/solver.component deleted file mode 100644 index fd0690b62468..000000000000 --- a/sccomp/source/solver/solver.component +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - diff --git a/sccomp/source/solver/solver.cxx b/sccomp/source/solver/solver.cxx deleted file mode 100644 index 76ac1af7ae6e..000000000000 --- a/sccomp/source/solver/solver.cxx +++ /dev/null @@ -1,639 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include - -#include "solver.hxx" -#include "solver.hrc" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -using namespace com::sun::star; - - -#define STR_NONNEGATIVE "NonNegative" -#define STR_INTEGER "Integer" -#define STR_TIMEOUT "Timeout" -#define STR_EPSILONLEVEL "EpsilonLevel" -#define STR_LIMITBBDEPTH "LimitBBDepth" - - -// Resources from tools are used for translated strings - -static ResMgr* pSolverResMgr = NULL; - -static OUString lcl_GetResourceString( sal_uInt32 nId ) -{ - if (!pSolverResMgr) - pSolverResMgr = ResMgr::CreateResMgr("solver"); - - return ResId(nId, *pSolverResMgr).toString(); -} - - - -namespace -{ - enum - { - PROP_NONNEGATIVE, - PROP_INTEGER, - PROP_TIMEOUT, - PROP_EPSILONLEVEL, - PROP_LIMITBBDEPTH - }; -} - - - -// hash map for the coefficients of a dependent cell (objective or constraint) -// The size of each vector is the number of columns (variable cells) plus one, first entry is initial value. - -struct ScSolverCellHash -{ - size_t operator()( const table::CellAddress& rAddress ) const - { - return ( rAddress.Sheet << 24 ) | ( rAddress.Column << 16 ) | rAddress.Row; - } -}; - -inline bool AddressEqual( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 ) -{ - return rAddr1.Sheet == rAddr2.Sheet && rAddr1.Column == rAddr2.Column && rAddr1.Row == rAddr2.Row; -} - -struct ScSolverCellEqual -{ - bool operator()( const table::CellAddress& rAddr1, const table::CellAddress& rAddr2 ) const - { - return AddressEqual( rAddr1, rAddr2 ); - } -}; - -typedef boost::unordered_map< table::CellAddress, std::vector, ScSolverCellHash, ScSolverCellEqual > ScSolverCellHashMap; - - - -static uno::Reference lcl_GetCell( const uno::Reference& xDoc, - const table::CellAddress& rPos ) -{ - uno::Reference xSheets( xDoc->getSheets(), uno::UNO_QUERY ); - uno::Reference xSheet( xSheets->getByIndex( rPos.Sheet ), uno::UNO_QUERY ); - return xSheet->getCellByPosition( rPos.Column, rPos.Row ); -} - -static void lcl_SetValue( const uno::Reference& xDoc, - const table::CellAddress& rPos, double fValue ) -{ - lcl_GetCell( xDoc, rPos )->setValue( fValue ); -} - -static double lcl_GetValue( const uno::Reference& xDoc, - const table::CellAddress& rPos ) -{ - return lcl_GetCell( xDoc, rPos )->getValue(); -} - - - -SolverComponent::SolverComponent( const uno::Reference& /* rSMgr */ ) : - OPropertyContainer( GetBroadcastHelper() ), - mbMaximize( sal_True ), - mbNonNegative( sal_False ), - mbInteger( sal_False ), - mnTimeout( 100 ), - mnEpsilonLevel( 0 ), - mbLimitBBDepth( sal_True ), - mbSuccess( sal_False ), - mfResultValue( 0.0 ) -{ - // for XPropertySet implementation: - registerProperty( STR_NONNEGATIVE, PROP_NONNEGATIVE, 0, &mbNonNegative, getCppuType( &mbNonNegative ) ); - registerProperty( STR_INTEGER, PROP_INTEGER, 0, &mbInteger, getCppuType( &mbInteger ) ); - registerProperty( STR_TIMEOUT, PROP_TIMEOUT, 0, &mnTimeout, getCppuType( &mnTimeout ) ); - registerProperty( STR_EPSILONLEVEL, PROP_EPSILONLEVEL, 0, &mnEpsilonLevel, getCppuType( &mnEpsilonLevel ) ); - registerProperty( STR_LIMITBBDEPTH, PROP_LIMITBBDEPTH, 0, &mbLimitBBDepth, getCppuType( &mbLimitBBDepth ) ); -} - -SolverComponent::~SolverComponent() -{ -} - -IMPLEMENT_FORWARD_XINTERFACE2( SolverComponent, SolverComponent_Base, OPropertyContainer ) -IMPLEMENT_FORWARD_XTYPEPROVIDER2( SolverComponent, SolverComponent_Base, OPropertyContainer ) - -cppu::IPropertyArrayHelper* SolverComponent::createArrayHelper() const -{ - uno::Sequence aProps; - describeProperties( aProps ); - return new cppu::OPropertyArrayHelper( aProps ); -} - -cppu::IPropertyArrayHelper& SAL_CALL SolverComponent::getInfoHelper() -{ - return *getArrayHelper(); -} - -uno::Reference SAL_CALL SolverComponent::getPropertySetInfo() throw(uno::RuntimeException, std::exception) -{ - return createPropertySetInfo( getInfoHelper() ); -} - -// XSolverDescription - -OUString SAL_CALL SolverComponent::getComponentDescription() throw (uno::RuntimeException, std::exception) -{ - return lcl_GetResourceString( RID_COINMP_SOLVER_COMPONENT ); -} - -OUString SAL_CALL SolverComponent::getStatusDescription() throw (uno::RuntimeException, std::exception) -{ - return maStatus; -} - -OUString SAL_CALL SolverComponent::getPropertyDescription( const OUString& rPropertyName ) throw (uno::RuntimeException, std::exception) -{ - sal_uInt32 nResId = 0; - sal_Int32 nHandle = getInfoHelper().getHandleByName( rPropertyName ); - switch (nHandle) - { - case PROP_NONNEGATIVE: - nResId = RID_PROPERTY_NONNEGATIVE; - break; - case PROP_INTEGER: - nResId = RID_PROPERTY_INTEGER; - break; - case PROP_TIMEOUT: - nResId = RID_PROPERTY_TIMEOUT; - break; - case PROP_EPSILONLEVEL: - nResId = RID_PROPERTY_EPSILONLEVEL; - break; - case PROP_LIMITBBDEPTH: - nResId = RID_PROPERTY_LIMITBBDEPTH; - break; - default: - { - // unknown - leave empty - } - } - OUString aRet; - if ( nResId ) - aRet = lcl_GetResourceString( nResId ); - return aRet; -} - -// XSolver: settings - -uno::Reference SAL_CALL SolverComponent::getDocument() throw(uno::RuntimeException, std::exception) -{ - return mxDoc; -} - -void SAL_CALL SolverComponent::setDocument( const uno::Reference& _document ) - throw(uno::RuntimeException, std::exception) -{ - mxDoc = _document; -} - -table::CellAddress SAL_CALL SolverComponent::getObjective() throw(uno::RuntimeException, std::exception) -{ - return maObjective; -} - -void SAL_CALL SolverComponent::setObjective( const table::CellAddress& _objective ) throw(uno::RuntimeException, std::exception) -{ - maObjective = _objective; -} - -uno::Sequence SAL_CALL SolverComponent::getVariables() throw(uno::RuntimeException, std::exception) -{ - return maVariables; -} - -void SAL_CALL SolverComponent::setVariables( const uno::Sequence& _variables ) - throw(uno::RuntimeException, std::exception) -{ - maVariables = _variables; -} - -uno::Sequence SAL_CALL SolverComponent::getConstraints() throw(uno::RuntimeException, std::exception) -{ - return maConstraints; -} - -void SAL_CALL SolverComponent::setConstraints( const uno::Sequence& _constraints ) - throw(uno::RuntimeException, std::exception) -{ - maConstraints = _constraints; -} - -sal_Bool SAL_CALL SolverComponent::getMaximize() throw(uno::RuntimeException, std::exception) -{ - return mbMaximize; -} - -void SAL_CALL SolverComponent::setMaximize( sal_Bool _maximize ) throw(uno::RuntimeException, std::exception) -{ - mbMaximize = _maximize; -} - -// XSolver: get results - -sal_Bool SAL_CALL SolverComponent::getSuccess() throw(uno::RuntimeException, std::exception) -{ - return mbSuccess; -} - -double SAL_CALL SolverComponent::getResultValue() throw(uno::RuntimeException, std::exception) -{ - return mfResultValue; -} - -uno::Sequence SAL_CALL SolverComponent::getSolution() throw(uno::RuntimeException, std::exception) -{ - return maSolution; -} - -void SAL_CALL SolverComponent::solve() throw(uno::RuntimeException, std::exception) -{ - uno::Reference xModel( mxDoc, uno::UNO_QUERY ); - if ( !xModel.is() ) - throw uno::RuntimeException(); - - maStatus = ""; - mbSuccess = false; - - xModel->lockControllers(); - - // collect variables in vector (?) - - std::vector aVariableCells; - for (sal_Int32 nPos=0; nPos>= aCellAddr ) - aCellsHash[aCellAddr].reserve( nVariables + 1 ); // constraints: right hand side - } - - // set all variables to zero - //! store old values? - //! use old values as initial values? - std::vector::const_iterator aVarIter; - for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) - { - lcl_SetValue( mxDoc, *aVarIter, 0.0 ); - } - - // read initial values from all dependent cells - ScSolverCellHashMap::iterator aCellsIter; - for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) - { - double fValue = lcl_GetValue( mxDoc, aCellsIter->first ); - aCellsIter->second.push_back( fValue ); // store as first element, as-is - } - - // loop through variables - for ( aVarIter = aVariableCells.begin(); aVarIter != aVariableCells.end(); ++aVarIter ) - { - lcl_SetValue( mxDoc, *aVarIter, 1.0 ); // set to 1 to examine influence - - // read value change from all dependent cells - for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) - { - double fChanged = lcl_GetValue( mxDoc, aCellsIter->first ); - double fInitial = aCellsIter->second.front(); - aCellsIter->second.push_back( fChanged - fInitial ); - } - - lcl_SetValue( mxDoc, *aVarIter, 2.0 ); // minimal test for linearity - - for ( aCellsIter = aCellsHash.begin(); aCellsIter != aCellsHash.end(); ++aCellsIter ) - { - double fInitial = aCellsIter->second.front(); - double fCoeff = aCellsIter->second.back(); // last appended: coefficient for this variable - double fTwo = lcl_GetValue( mxDoc, aCellsIter->first ); - - bool bLinear = rtl::math::approxEqual( fTwo, fInitial + 2.0 * fCoeff ) || - rtl::math::approxEqual( fInitial, fTwo - 2.0 * fCoeff ); - // second comparison is needed in case fTwo is zero - if ( !bLinear ) - maStatus = lcl_GetResourceString( RID_ERROR_NONLINEAR ); - } - - lcl_SetValue( mxDoc, *aVarIter, 0.0 ); // set back to zero for examining next variable - } - - xModel->unlockControllers(); - - if ( !maStatus.isEmpty() ) - return; - - // - // build parameter arrays for CoinMP - // - - // set objective function - - const std::vector& rObjCoeff = aCellsHash[maObjective]; - double* pObjectCoeffs = new double[nVariables]; - for (nVar=0; nVar>= aRightAddr ) - bRightCell = true; // cell specified as right-hand side - else - rRightAny >>= fDirectValue; // constant value - - table::CellAddress aLeftAddr = maConstraints[nConstrPos].Left; - - const std::vector& rLeftCoeff = aCellsHash[aLeftAddr]; - double* pValues = &pCompMatrix[nConstrPos * nVariables]; - for (nVar=0; nVar& rRightCoeff = aCellsHash[aRightAddr]; - // modify pValues with rhs coefficients - for (nVar=0; nVar SolverComponent_getSupportedServiceNames() -{ - uno::Sequence< OUString > aServiceNames( 1 ); - aServiceNames[ 0 ] = "com.sun.star.sheet.Solver"; - return aServiceNames; -} - -OUString SolverComponent_getImplementationName() -{ - return OUString("com.sun.star.comp.Calc.CoinMPSolver"); -} - -OUString SAL_CALL SolverComponent::getImplementationName() throw(uno::RuntimeException, std::exception) -{ - return SolverComponent_getImplementationName(); -} - -sal_Bool SAL_CALL SolverComponent::supportsService( const OUString& rServiceName ) throw(uno::RuntimeException, std::exception) -{ - return cppu::supportsService(this, rServiceName); -} - -uno::Sequence SAL_CALL SolverComponent::getSupportedServiceNames() throw(uno::RuntimeException, std::exception) -{ - return SolverComponent_getSupportedServiceNames(); -} - -uno::Reference SolverComponent_createInstance( const uno::Reference& rSMgr ) - throw(uno::Exception) -{ - return (cppu::OWeakObject*) new SolverComponent( rSMgr ); -} - -extern "C" -{ - SAL_DLLPUBLIC_EXPORT void* SAL_CALL coinmp_component_getFactory( const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) - { - OUString aImplName( OUString::createFromAscii( pImplName ) ); - void* pRet = 0; - - if( pServiceManager ) - { - uno::Reference< lang::XSingleComponentFactory > xFactory; - if( aImplName.equals( SolverComponent_getImplementationName() ) ) - xFactory = cppu::createSingleComponentFactory( - SolverComponent_createInstance, - OUString::createFromAscii( pImplName ), - SolverComponent_getSupportedServiceNames() ); - - if( xFactory.is() ) - { - xFactory->acquire(); - pRet = xFactory.get(); - } - } - return pRet; - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sccomp/source/solver/solver.hxx b/sccomp/source/solver/solver.hxx deleted file mode 100644 index 223c7d132f36..000000000000 --- a/sccomp/source/solver/solver.hxx +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef SOLVER_HXX -#define SOLVER_HXX - -#include -#include -#include -#include -#include -#include -#include -#include - -typedef cppu::WeakImplHelper3< - com::sun::star::sheet::XSolver, - com::sun::star::sheet::XSolverDescription, - com::sun::star::lang::XServiceInfo > - SolverComponent_Base; - -class SolverComponent : public comphelper::OMutexAndBroadcastHelper, - public comphelper::OPropertyContainer, - public comphelper::OPropertyArrayUsageHelper< SolverComponent >, - public SolverComponent_Base -{ - // settings - com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument > mxDoc; - com::sun::star::table::CellAddress maObjective; - com::sun::star::uno::Sequence< com::sun::star::table::CellAddress > maVariables; - com::sun::star::uno::Sequence< com::sun::star::sheet::SolverConstraint > maConstraints; - sal_Bool mbMaximize; - // set via XPropertySet - sal_Bool mbNonNegative; - sal_Bool mbInteger; - sal_Int32 mnTimeout; - sal_Int32 mnEpsilonLevel; - sal_Bool mbLimitBBDepth; - // results - sal_Bool mbSuccess; - double mfResultValue; - com::sun::star::uno::Sequence< double > maSolution; - OUString maStatus; - -public: - SolverComponent( const com::sun::star::uno::Reference< - com::sun::star::uno::XComponentContext >& rxMSF ); - virtual ~SolverComponent(); - - DECLARE_XINTERFACE() - DECLARE_XTYPEPROVIDER() - - virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() - throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE; // from OPropertySetHelper - virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const SAL_OVERRIDE; // from OPropertyArrayUsageHelper - - // XSolver - virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument > SAL_CALL getDocument() - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual void SAL_CALL setDocument( const ::com::sun::star::uno::Reference< - ::com::sun::star::sheet::XSpreadsheetDocument >& _document ) - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::com::sun::star::table::CellAddress SAL_CALL getObjective() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual void SAL_CALL setObjective( const ::com::sun::star::table::CellAddress& _objective ) - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::table::CellAddress > SAL_CALL getVariables() - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual void SAL_CALL setVariables( const ::com::sun::star::uno::Sequence< - ::com::sun::star::table::CellAddress >& _variables ) - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::SolverConstraint > SAL_CALL getConstraints() - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual void SAL_CALL setConstraints( const ::com::sun::star::uno::Sequence< - ::com::sun::star::sheet::SolverConstraint >& _constraints ) - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::sal_Bool SAL_CALL getMaximize() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual void SAL_CALL setMaximize( ::sal_Bool _maximize ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - - virtual ::sal_Bool SAL_CALL getSuccess() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual double SAL_CALL getResultValue() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::com::sun::star::uno::Sequence< double > SAL_CALL getSolution() - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - - virtual void SAL_CALL solve() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - - // XSolverDescription - virtual OUString SAL_CALL getComponentDescription() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual OUString SAL_CALL getStatusDescription() throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual OUString SAL_CALL getPropertyDescription( const OUString& aPropertyName ) - throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - - // XServiceInfo - virtual OUString SAL_CALL getImplementationName() - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; - virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() - throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit