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
00029 #include "numeric/lpsolve.hxx"
00030 #include "numeric/lpmodel.hxx"
00031 #include "numeric/exception.hxx"
00032 #include "numeric/matrix.hxx"
00033 #include "unoglobal.hxx"
00034 #include "tool/global.hxx"
00035 #include "numeric/type.hxx"
00036 #include "lpsolve/lp_lib.h"
00037
00038 #include <string>
00039 #include <memory>
00040 #include <iostream>
00041 #include <stdio.h>
00042
00043 using namespace ::scsolver::numeric;
00044
00045 namespace scsolver {
00046
00047 namespace numeric { namespace lp {
00048
00049 class LpSolveImpl
00050 {
00051 public:
00052 LpSolveImpl() {}
00053 ~LpSolveImpl() throw() {}
00054
00055 void solve();
00056 Matrix getSolution() const { return m_mxSolution; }
00057
00058 void setModel( Model* model ) { m_pModel = model; }
00059 Model* getModel() const { return m_pModel; }
00060
00061 private:
00062 Matrix m_mxSolution;
00063 Model* m_pModel;
00064 };
00065
00066 void LpSolveImpl::solve()
00067 {
00068 using ::std::vector;
00069
00070 Model* model = getModel();
00071 size_t nDecVarSize = model->getDecisionVarSize();
00072 size_t nConstCount = model->getConstraintCount();
00073
00074 #if SCSOLVER_DEBUG
00075 printf("decision var (%d)\n", nDecVarSize);
00076 printf("constraint (%d)\n", nConstCount);
00077 #endif
00078
00079 lprec* lp = make_lp(0, nDecVarSize);
00080 if ( lp == NULL )
00081 throw RuntimeError( ascii("Initialization error") );
00082
00083 for ( int i = 1; i <= nDecVarSize; ++i )
00084 {
00085 if( model->getVarPositive() )
00086 set_lowbo(lp, i, 0.0);
00087 else
00088 set_unbounded(lp, i);
00089 if ( model->getVarInteger() )
00090 set_int(lp, i, 1);
00091 else
00092 set_int(lp, i, 0);
00093 }
00094
00095
00096 set_add_rowmode( lp, true );
00097 vector<double> row( nDecVarSize );
00098 vector<int> cols( nDecVarSize );
00099 try
00100 {
00101 for ( int i = 0; i < nDecVarSize; ++i )
00102 cols.at(i) = i+1;
00103
00104 for ( int i = 0; i < nConstCount; ++i )
00105 {
00106 for ( int j = 0; j < nDecVarSize; ++j )
00107 row.at(j) = model->getConstraint( i, j );
00108 int nEqual = EQ;
00109 switch ( model->getEquality(i) )
00110 {
00111 case GREATER_EQUAL:
00112 nEqual = GE;
00113 break;
00114 case LESS_EQUAL:
00115 nEqual = LE;
00116 break;
00117 case EQUAL:
00118 nEqual = EQ;
00119 break;
00120 }
00121 add_constraintex( lp, nDecVarSize, &row[0], &cols[0], nEqual,
00122 model->getRhsValue(i) );
00123 }
00124
00125 set_add_rowmode( lp, false );
00126
00127
00128 for ( int i = 0; i < nDecVarSize; ++i )
00129 {
00130 #if SCSOLVER_DEBUG
00131 printf("var %d = %f\n", i+1, model->getCost(i));
00132 #endif
00133 row.at(i) = model->getCost(i);
00134 }
00135 set_obj_fnex( lp, nDecVarSize, &row[0], &cols[0] );
00136 }
00137 catch ( ::std::out_of_range& e )
00138 {
00139 Debug( e.what() );
00140 delete_lp(lp);
00141 throw RuntimeError( ascii(e.what()) );
00142 }
00143
00144
00145 switch ( model->getGoal() )
00146 {
00147 case GOAL_MAXIMIZE:
00148 set_maxim(lp);
00149 break;
00150 case GOAL_MINIMIZE:
00151 set_minim(lp);
00152 break;
00153 default:
00154 delete_lp(lp);
00155 throw RuntimeError( ascii("Unknown goal") );
00156 }
00157
00158 write_LP(lp, stdout);
00159
00160 #if SCSOLVER_DEBUG
00161 set_verbose(lp, IMPORTANT);
00162 #else
00163 set_verbose(lp, NEUTRAL);
00164 #endif
00165
00166 if ( ::solve(lp) == OPTIMAL )
00167 {
00168
00169
00170
00171 get_variables(lp, &row[0]);
00172 Matrix mxSolution( nDecVarSize, 1 );
00173 for ( size_t i = 0; i < nDecVarSize; ++i )
00174 mxSolution( i, 0 ) = row[i];
00175 m_mxSolution.swap( mxSolution );
00176 }
00177 else
00178 {
00179
00180 delete_lp(lp);
00181 throw ModelInfeasible();
00182 }
00183
00184 delete_lp(lp);
00185 }
00186
00187
00188
00189 LpSolve::LpSolve() : m_pImpl( new LpSolveImpl )
00190 {
00191 }
00192
00193 LpSolve::~LpSolve() throw()
00194 {
00195 }
00196
00197 void LpSolve::solve()
00198 {
00199 m_pImpl->setModel( getModel() );
00200 m_pImpl->solve();
00201 setSolution( m_pImpl->getSolution() );
00202 }
00203
00204
00205
00206 }}}