00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "numeric/lpuno.hxx"
00029 #include "numeric/lpmodel.hxx"
00030 #include "numeric/matrix.hxx"
00031 #include "xcalc.hxx"
00032 #include "tool/global.hxx"
00033 #include "unoglobal.hxx"
00034
00035 #include "org/openoffice/sc/solver/XLpModel.hpp"
00036 #include "org/openoffice/sc/solver/XLpAlgorithm.hpp"
00037 #include "org/openoffice/sc/solver/Goal.hpp"
00038 #include "org/openoffice/sc/solver/Equality.hpp"
00039 #include "com/sun/star/uno/RuntimeException.hpp"
00040
00041 #include <exception>
00042
00043 using namespace ::com::sun::star::uno;
00044
00045 namespace scsolver { namespace numeric { namespace lp {
00046
00047 class UnoServiceNotFound : public ::std::exception
00048 {
00049 const char* what() const throw() { return "UNO Servcie not found"; }
00050 };
00051
00052 class LpModelNotFound : public ::std::exception
00053 {
00054 const char* what() const throw() { return "LpModel service not found"; }
00055 };
00056
00057 class UnknownGoal : public ::std::exception
00058 {
00059 const char* what() const throw() { return "Unknown goal"; }
00060 };
00061
00062 class UnknownConstraintType : public ::std::exception
00063 {
00064 const char* what() const throw() { return "Unknown constraint type"; }
00065 };
00066
00067 class UnoAlgorithmImpl
00068 {
00069 public:
00070 UnoAlgorithmImpl( const rtl::OUString& service, CalcInterface* pCalc ) :
00071 m_sServiceName( service ),
00072 m_pCalc( pCalc ),
00073 m_mxSolution( 0, 0 ),
00074 m_pModel( NULL )
00075 {
00076 }
00077
00078 ~UnoAlgorithmImpl() throw()
00079 {
00080 }
00081
00082 void solve();
00083 Matrix getSolution() const;
00084
00085 void setModel( Model* p ) { m_pModel = p; }
00086 Model* getModel() const { return m_pModel; }
00087
00088 const rtl::OUString getServiceName() const { return m_sServiceName; }
00089
00090 private:
00091 rtl::OUString m_sServiceName;
00092 CalcInterface* m_pCalc;
00093 Matrix m_mxSolution;
00094 Model* m_pModel;
00095
00096 CalcInterface* getCalcInterface() const { return m_pCalc; }
00097 };
00098
00108 void UnoAlgorithmImpl::solve()
00109 {
00110 using namespace ::org::openoffice::sc::solver;
00111 using numeric::Matrix;
00112
00113 static const rtl::OUString sLpModelSrv = ascii( "org.openoffice.sc.solver.LpModel" );
00114
00115 Reference< uno::XComponentContext > xCC = getCalcInterface()->getComponentContext();
00116 Reference< lang::XMultiComponentFactory > xSM = getCalcInterface()->getServiceManager();
00117
00118 Reference< uno::XInterface > svModel = xSM->createInstanceWithContext( sLpModelSrv, xCC );
00119 if ( svModel == NULL )
00120 throw LpModelNotFound();
00121
00122 Reference< XLpModel > xModel( svModel, UNO_QUERY );
00123
00124 numeric::lp::Model* model = getModel();
00125
00126
00127
00128
00129
00130 switch ( model->getGoal() )
00131 {
00132 case GOAL_MINIMIZE:
00133 xModel->setGoal( Goal_MINIMIZE );
00134 break;
00135 case GOAL_MAXIMIZE:
00136 xModel->setGoal( Goal_MAXIMIZE );
00137 break;
00138 default:
00139 throw UnknownGoal();
00140 }
00141
00142
00143
00144 Matrix mxCosts = model->getCostVector();
00145 size_t nDecVarSize = mxCosts.cols();
00146 xModel->setDecisionVarSize( nDecVarSize );
00147 for ( size_t i = 0; i < nDecVarSize; ++i )
00148 xModel->setCost( i, mxCosts( 0, i ) );
00149
00150
00151
00152 Matrix mxConstraint = model->getConstraintMatrix();
00153 Matrix mxRhs = model->getRhsVector();
00154
00155 size_t nConstraintSize = mxConstraint.rows();
00156 xModel->setConstraintCount( nConstraintSize );
00157 for ( size_t i = 0; i < nConstraintSize; ++i )
00158 {
00159 for ( size_t j = 0; j < nDecVarSize; ++j )
00160 xModel->setConstraint( i, j, mxConstraint( i, j ) );
00161
00162 switch ( model->getEquality(i) )
00163 {
00164 case GREATER_EQUAL:
00165 xModel->setEquality( i, Equality_GREATER_EQUAL );
00166 break;
00167 case EQUAL:
00168 xModel->setEquality( i, Equality_EQUAL );
00169 break;
00170 case LESS_EQUAL:
00171 xModel->setEquality( i, Equality_LESS_EQUAL );
00172 break;
00173 default:
00174 throw UnknownConstraintType();
00175 }
00176
00177 xModel->setRhsValue( i, mxRhs( i, 0 ) );
00178 }
00179
00180
00181
00182 Reference< uno::XInterface > algorithm = xSM->createInstanceWithContext( getServiceName(), xCC );
00183 if ( algorithm == NULL )
00184 throw UnoServiceNotFound();
00185
00186 Reference< XLpAlgorithm > xAlgorithm( algorithm, UNO_QUERY );
00187 xAlgorithm->setModel( xModel );
00188 try
00189 {
00190 xAlgorithm->solve();
00191 }
00192 catch ( const RuntimeException& e )
00193 {
00194 throw lp::ModelInfeasible();
00195 }
00196
00197 Matrix mxSol( nDecVarSize, 1 );
00198 for ( size_t i = 0; i < nDecVarSize; ++i )
00199 mxSol( i, 0 ) = xAlgorithm->getVar(i);
00200
00201 m_mxSolution.swap( mxSol );
00202 }
00203
00204 Matrix UnoAlgorithmImpl::getSolution() const
00205 {
00206 return m_mxSolution;
00207 }
00208
00209
00210
00211
00212 UnoAlgorithm::UnoAlgorithm( const rtl::OUString& service, CalcInterface* pCalc ) :
00213 m_pImpl( new UnoAlgorithmImpl( service, pCalc ) )
00214 {
00215 }
00216
00217 UnoAlgorithm::~UnoAlgorithm() throw()
00218 {
00219 }
00220
00221 void UnoAlgorithm::solve()
00222 {
00223 m_pImpl->setModel( getModel() );
00224 m_pImpl->solve();
00225 setSolution( m_pImpl->getSolution() );
00226 }
00227
00228 }}}}