00001
00018 #include "OSLindoSolver.h"
00019 #include "OSiLReader.h"
00020 #include "OSInstance.h"
00021 #include "OSFileUtil.h"
00022 #include "OSErrorClass.h"
00023
00024 #include "OSDataStructures.h"
00025 #include "OSParameters.h"
00026 #include "OSMathUtil.h"
00027
00028 #include "CoinTime.hpp"
00029
00030
00031 #ifdef HAVE_CTIME
00032 # include <ctime>
00033 #else
00034 # ifdef HAVE_TIME_H
00035 # include <time.h>
00036 # else
00037 # error "don't have header file for time"
00038 # endif
00039 #endif
00040 #include <iostream>
00041 #include <sstream>
00042 #include<vector>
00043 #include <map>
00044
00045 using std::cout;
00046 using std::endl;
00047 using std::ostringstream;
00048
00049 #define DEBUG
00050 #ifndef __LINDOI_H__
00051 #define __LINDOI_H__
00052
00053 #ifdef __cplusplus
00054 extern "C" {
00055 #endif
00056
00057 int CALLTYPE LSwriteMPIFile(pLSmodel pModel, char *pszFname);
00058
00059 #ifdef __cplusplus
00060 }
00061 #endif
00062
00063 #endif
00064
00065 #define LINDO_OP_CODE_CONVERSION \
00066 std::map<int, int> nlNodeIdxLindo;\
00067 nlNodeIdxLindo[OS_PLUS] = EP_PLUS; \
00068 nlNodeIdxLindo[OS_SUM] = EP_SUM; \
00069 nlNodeIdxLindo[OS_MINUS] = EP_MINUS; \
00070 nlNodeIdxLindo[OS_NEGATE] = EP_NEGATE; \
00071 nlNodeIdxLindo[OS_TIMES] = EP_MULTIPLY; \
00072 nlNodeIdxLindo[OS_DIVIDE] = EP_DIVIDE; \
00073 nlNodeIdxLindo[OS_POWER] = EP_POWER; \
00074 nlNodeIdxLindo[OS_SQRT] = EP_SQRT; \
00075 nlNodeIdxLindo[OS_LN] = EP_LN; \
00076 nlNodeIdxLindo[OS_EXP] = EP_EXP; \
00077 nlNodeIdxLindo[OS_NUMBER] = EP_PUSH_NUM; \
00078 nlNodeIdxLindo[OS_VARIABLE] = EP_PUSH_VAR;\
00079 nlNodeIdxLindo[OS_IF] = EP_IF; \
00080 nlNodeIdxLindo[OS_ABS] = EP_ABS; \
00081 nlNodeIdxLindo[OS_MAX] = EP_MAX; \
00082 nlNodeIdxLindo[OS_MIN] = EP_MIN; \
00083 nlNodeIdxLindo[OS_SQUARE] = EP_SQR; \
00084 nlNodeIdxLindo[OS_SIN] = EP_SIN; \
00085 nlNodeIdxLindo[OS_COS] = EP_COS;
00086
00087 LindoSolver::LindoSolver():
00088 m_osilreader( NULL),
00089 pEnv_( NULL),
00090 pModel_( NULL),
00091 m_miSlackIdx( NULL),
00092 m_iNumberNewSlacks( 0),
00093 m_mdRhsValue( NULL),
00094 m_mcRowType( NULL),
00095 m_mdVarLB( NULL),
00096 m_mdVarUB( NULL),
00097 m_mdConLB( NULL),
00098 m_mdConUB( NULL),
00099 m_mmcVarName( NULL),
00100 m_msVarName( NULL),
00101 m_msConName( NULL),
00102 m_mcVarType( NULL),
00103 m_mdObjConstant( 0),
00104 osrlwriter( NULL),
00105 cpuTime( 0)
00106
00107 {
00108 #ifdef DEBUG
00109 cout << "Lindo constructor called" << endl;
00110 #endif
00111 osrlwriter = new OSrLWriter();}
00112
00113 LindoSolver::~LindoSolver() {
00114 #ifdef DEBUG
00115 cout << "Lindo destructor called" << endl;
00116 #endif
00117
00118
00119
00120 delete[] m_mmcVarName ;
00121
00122 m_mdConLB = NULL;
00123 m_mdConUB = NULL;
00124 m_msVarName = NULL;
00125 m_mcVarType = NULL;
00126 m_mcRowType = NULL;
00127 m_msConName = NULL;
00128 #ifdef DEBUG
00129 cout << "Delete LSdelete" << endl;
00130 #endif
00131 LSdeleteEnv(&pEnv_);
00132 delete[] m_miSlackIdx;
00133 m_miSlackIdx = NULL;
00134 delete[] m_mdRhsValue;
00135 m_mdRhsValue = NULL;
00136 delete osrlwriter;
00137 osrlwriter = NULL;
00138 delete osresult;
00139 osresult = NULL;
00140 if(m_osilreader != NULL) delete m_osilreader;
00141 m_osilreader = NULL;
00142 cout << "Lindo Solver garbage collection done" << endl;
00143 }
00144
00145
00146 void LindoSolver::buildSolverInstance() throw (ErrorClass) {
00147 try{
00148 osresult = new OSResult();
00149 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00150 OSiLReader* osilreader = NULL;
00151 bool newOSiLReader = false;
00152 if(osinstance == NULL){
00153 osilreader = new OSiLReader();
00154 osinstance = osilreader->readOSiL( osil);
00155 newOSiLReader = true;
00156
00157 }
00158
00159 OSiLWriter osilwriter;
00160
00161 if (osinstance->instanceData->constraints->numberOfConstraints <= 0){
00162 std::cout << "HERE I AM 1 !!!!!!!!!!!!!!!!!!!" << std::endl;
00163 osinstance->setConstraintNumber(1);
00164 osinstance->addConstraint(0, "dummyConstraint", 0, 0, 0);
00165 std::cout << "HERE I AM 2 !!!!!!!!!!!!!!!!!!!" << std::endl;
00166 }
00167
00168 if(osinstance->getVariableNumber() < 0)throw ErrorClass("Cannot have a negative number of decision variables");
00169 std::cout << "Start process variables !!!!!!!!!" << std::endl;
00170 if( !processVariables() ) throw ErrorClass("failed processing variables");
00171 std::cout << "Finish process variables!!!!!!" << std::endl;
00172 std::cout << "Start process constraints" << std::endl;
00173 if( !processConstraints() ) throw ErrorClass("failed processing constraints");
00174 std::cout << "Finish process constraints !!!!!!!!!" << std::endl;
00175 std::cout << "Start generateLindoModel() !!!!!!!!!" << std::endl;
00176 if( !generateLindoModel()) throw ErrorClass("failed generating Lindo model");
00177 std::cout << "Finish generateLindoModel() !!!!!!!!!" << std::endl;
00178 if(m_iNumberNewSlacks > 0 && !addSlackVars()) throw ErrorClass("failed adding slack variables");
00179 if( (osinstance->getNumberOfNonlinearExpressions() > 0 || osinstance->getNumberOfQuadraticTerms() > 0)
00180 && !processNonlinearExpressions()) throw ErrorClass("failed adding nonlinear terms");
00181 this->bCallbuildSolverInstance = true ;
00182
00183 }
00184 catch(const ErrorClass& eclass){
00185 std::cout << "THERE IS AN ERROR" << std::endl;
00186 osresult->setGeneralMessage( eclass.errormsg);
00187 osresult->setGeneralStatusType( "error");
00188 osrl = osrlwriter->writeOSrL( osresult);
00189 throw ErrorClass( osrl) ;
00190 }
00191 }
00192
00193
00194
00195 void LindoSolver::setSolverOptions() throw (ErrorClass) {
00196 try{
00197
00198 }
00199 catch(const ErrorClass& eclass){
00200 std::cout << "THERE IS AN ERROR" << std::endl;
00201 osresult->setGeneralMessage( eclass.errormsg);
00202 osresult->setGeneralStatusType( "error");
00203 osrl = osrlwriter->writeOSrL( osresult);
00204 throw ErrorClass( osrl) ;
00205 }
00206 }
00207
00208
00209 void LindoSolver::solve() {
00210 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00211 try{
00212 double start = CoinCpuTime();
00213 if( optimize() != true) throw ErrorClass("problem optimizing model");
00214 cpuTime = CoinCpuTime() - start;
00215 osresult->setGeneralStatusType("normal");
00216 osresult->setTime(cpuTime);
00217 osrl = osrlwriter->writeOSrL( osresult);
00218 }
00219 catch(const ErrorClass& eclass){
00220 osresult->setGeneralMessage( eclass.errormsg);
00221 osresult->setGeneralStatusType( "error");
00222 osrl = osrlwriter->writeOSrL( osresult);
00223
00224 throw ErrorClass( osrl) ;
00225 }
00226 }
00227
00228 bool LindoSolver::processConstraints(){
00229 int i;
00230 m_iNumberNewSlacks = 0;
00231 try{
00232
00233
00234 m_mdConLB = osinstance->getConstraintLowerBounds();
00235 m_mdConUB = osinstance->getConstraintUpperBounds();
00236 m_msConName = osinstance->getConstraintNames();
00237 m_mdRhsValue = new double[ osinstance->getConstraintNumber()];
00238 m_miSlackIdx = new int[ osinstance->getConstraintNumber()];
00239 m_mcRowType = osinstance->getConstraintTypes();
00240
00241 for(i = 0; i < osinstance->getConstraintNumber(); i++){
00242 switch( m_mcRowType[ i] ){
00243 case 'E':
00244 m_mdRhsValue[ i] = m_mdConUB[ i];
00245
00246
00247 break;
00248 case 'L':
00249 m_mdRhsValue[ i] = m_mdConUB[ i];
00250 break;
00251 case 'G':
00252 m_mdRhsValue[ i] = m_mdConLB[ i];
00253 break;
00254 case 'U':
00255 throw ErrorClass("LINDO cannot handle unbounded constraints");
00256 break;
00257 case 'R':
00258
00259 m_mdRhsValue[ i] = m_mdConUB[ i] ;
00260 m_mcRowType[ i] = 'E';
00261 m_miSlackIdx[ m_iNumberNewSlacks] = i;
00262 m_iNumberNewSlacks++;
00263 break;
00264 }
00265 }
00266 return true;
00267 }
00268 catch(const ErrorClass& eclass){
00269 osresult->setGeneralMessage( eclass.errormsg);
00270 osresult->setGeneralStatusType( "error");
00271 osrl = osrlwriter->writeOSrL( osresult);
00272 throw ;
00273 }
00274 }
00275
00276 bool LindoSolver::addSlackVars(){
00277
00278
00279
00280
00281 if(m_iNumberNewSlacks <= 0) return false;
00282 int i;
00283 ostringstream varName;
00284 char* p;
00285 std::string tmpstring;
00286 char* pachVartypes = new char[m_iNumberNewSlacks];
00287 char** paszVarnames = new char*[m_iNumberNewSlacks];
00288 int* paiAcols = new int[m_iNumberNewSlacks + 1];
00289 int* pacAcols = NULL;
00290 double* padAcoef = new double[m_iNumberNewSlacks];
00291 int* paiArows = new int[m_iNumberNewSlacks];
00292 double* padC = new double[m_iNumberNewSlacks];
00293 double* padL = NULL;
00294 double* padU = new double[m_iNumberNewSlacks];
00295 for(i = 0; i < m_iNumberNewSlacks; i++){
00296 pachVartypes[ i] = 'C';
00297 varName << "xyzabc_" ;
00298 varName << i ;
00299 varName << '\0';
00300 tmpstring = varName.str();
00301 p = new char[tmpstring.size() + 1];
00302 strcpy(p, tmpstring.c_str());
00303 char ch;
00304 ch = ' ';
00305
00306 if( m_iNumberNewSlacks == 1) paszVarnames[i] = &ch;
00307 else paszVarnames[i] = p;
00308 varName << "";
00309 paiAcols[ i] = i;
00310 padAcoef[ i] = 1.0;
00311 paiArows[ i] = m_miSlackIdx[ i];
00312 padC[ i] = 0.0;
00313 padU[ i] = m_mdConUB[ m_miSlackIdx[ i]] - m_mdConLB[ m_miSlackIdx[ i]];
00314 if(padU[ i] - padC[i]< 0) return false;
00315 }
00316 paiAcols[ m_iNumberNewSlacks] = m_iNumberNewSlacks;
00317 #ifdef DEBUG
00318 cout << "The number of new slack variables is: " << m_iNumberNewSlacks << endl;
00319 for(i = 0; i < m_iNumberNewSlacks; i++){
00320 cout<< paszVarnames[ i] << endl;
00321 }
00322 #endif
00323
00324 if(!LSaddVariables(pModel_, m_iNumberNewSlacks, pachVartypes, paszVarnames, paiAcols,
00325 pacAcols, padAcoef, paiArows, padC, padL, padU)){
00326 if(m_iNumberNewSlacks > 0){
00327
00328 delete[] paiAcols;
00329 delete[] padAcoef;
00330 delete[] paiArows;
00331 delete[] padC;
00332 delete[] padU;
00333
00334
00335 if( m_iNumberNewSlacks == 1){
00336 delete paszVarnames;
00337 delete pachVartypes;
00338 }
00339 else{
00340 for(i = 0; i < m_iNumberNewSlacks; i++) delete[] paszVarnames[i];
00341 delete[] paszVarnames;
00342 delete[] pachVartypes;
00343 }
00344 }
00345 return true;
00346 }
00347 else{
00348 return false;
00349 }
00350 }
00351
00352
00353 bool LindoSolver::processVariables(){
00354 int i;
00355 try{
00356 m_mcVarType = osinstance->getVariableTypes();
00357 m_mdVarLB = osinstance->getVariableLowerBounds();
00358 m_mdVarUB = osinstance->getVariableUpperBounds();
00359 m_mmcVarName = new char*[ osinstance->getVariableNumber()];
00360 for(i = 0; i < osinstance->getVariableNumber(); i++){
00361
00362
00363
00364 m_mmcVarName[i] = &osinstance->getVariableNames()[ i][0];
00365 }
00366
00367 for(i = 0; i < osinstance->getVariableNumber() ; i++){
00368 if( osinstance->getVariableTypes()[ i] == 'B'){
00369 m_mdVarUB[ i] = 1.0;
00370 }
00371 }
00372
00373 return true;
00374 }
00375 catch(const ErrorClass& eclass){
00376 osresult->setGeneralMessage( eclass.errormsg);
00377 osresult->setGeneralStatusType( "error");
00378 osrl = osrlwriter->writeOSrL( osresult);
00379 throw ;
00380 }
00381 }
00382
00383
00384
00385 bool LindoSolver::generateLindoModel(){
00386
00387
00388
00389
00390
00391 char *MY_LICENSE_KEY = NULL;
00392 MY_LICENSE_KEY = getenv( "LINDOAPI_LICENSE_FILE");
00393 try{
00394 pEnv_ = LScreateEnv ( &m_iLindoErrorCode, MY_LICENSE_KEY);
00395 lindoAPIErrorCheck("There was an Error Creating the LINDO environment");
00396
00397 pModel_ = LScreateModel ( pEnv_, &m_iLindoErrorCode);
00398 lindoAPIErrorCheck("There was an Error Creating the LINDO Model");
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 int *colLength = NULL;
00418
00419 if(osinstance->getLinearConstraintCoefficientNumber() <= 0){
00420 cout << "LinearConstraintCoefficientNumber = " << osinstance->getLinearConstraintCoefficientNumber() << endl;
00421
00422 int iNumFakeNonz = 1;
00423
00424 int *paiArrayIdx;
00425 paiArrayIdx = new int[ 1];
00426 paiArrayIdx[ 0] = 0;
00427
00428 double *padValArray;
00429 padValArray = new double[ 1];
00430 padValArray[0] = 0;
00431
00432 int *paiArrayBeg;
00433 paiArrayBeg = new int[osinstance->getVariableNumber() + 1];
00434 paiArrayBeg[0] = 0;
00435 for(int kl = 1; kl <= osinstance->getVariableNumber(); kl++){
00436 paiArrayBeg[kl] = 1;
00437 }
00438
00439
00440 m_iLindoErrorCode = LSloadLPData( pModel_, osinstance->getConstraintNumber(), osinstance->getVariableNumber(),
00441 ( osinstance->getObjectiveMaxOrMins()[0] == "min")?LS_MIN:LS_MAX ,
00442 osinstance->getObjectiveConstants()[0],
00443 osinstance->getDenseObjectiveCoefficients()[0],
00444 m_mdRhsValue, m_mcRowType,
00445 iNumFakeNonz,
00446 paiArrayBeg,
00447 colLength, padValArray,
00448 paiArrayIdx,
00449 m_mdVarLB, m_mdVarUB);
00450 lindoAPIErrorCheck("Error with LSloadLPData when the number of nonzeros is 0");
00451 }
00452 else{
00453 m_iLindoErrorCode = LSloadLPData( pModel_, osinstance->getConstraintNumber(), osinstance->getVariableNumber(),
00454 ( osinstance->getObjectiveMaxOrMins()[0] == "min")?LS_MIN:LS_MAX ,
00455 osinstance->getObjectiveConstants()[0], osinstance->getDenseObjectiveCoefficients()[0], m_mdRhsValue, m_mcRowType,
00456 osinstance->getLinearConstraintCoefficientNumber(),
00457 osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts,
00458 colLength, osinstance->getLinearConstraintCoefficientsInColumnMajor()->values,
00459 osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes,
00460 m_mdVarLB, m_mdVarUB);
00461 lindoAPIErrorCheck("Error with LSloadLPData when the number of nonzeros is greater than 0");
00462 }
00463 m_iLindoErrorCode = LSloadVarType(pModel_, m_mcVarType);
00464 lindoAPIErrorCheck("There was an error loading the Lindo Variable Types");
00465 return true;
00466 }
00467 catch( const ErrorClass& eclass){
00468 osresult->setGeneralMessage( eclass.errormsg);
00469 osresult->setGeneralStatusType( "error");
00470 osrl = osrlwriter->writeOSrL( osresult);
00471 throw ;
00472 }
00473 }
00474
00475
00476 bool LindoSolver::optimize(){
00477 double *x, *y, *z;
00478 int solIdx = 0;
00479 ostringstream outStr;
00480 std::string *srcost;
00481 bool isNonlinear = false;
00482 double *drcost;
00483 int nSolStatus;
00484 std::string description = "";
00485
00486 if(osresult->setSolverInvoked( "LINDO Systems, Inc. Lindo API") != true)
00487 throw ErrorClass("OSResult error: setSolverInvoked");
00488 if(osresult->setServiceName( getVersionInfo()) != true)
00489 throw ErrorClass("OSResult error: setServiceName");
00490
00491 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00492 throw ErrorClass("OSResult error: setInstanceName");
00493
00494
00495
00496
00497 if(osinstance->getNumberOfNonlinearObjectives() > 0 || osinstance->getNumberOfNonlinearConstraints() > 0) isNonlinear = true;
00498 try{
00499 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("LINDO NEEDS AN OBJECTIVE FUNCTION");
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 if( isNonlinear == true ){
00513
00514 std::cout << "We are using the LINDO Global Optimizer" << std::endl;
00515 std::cout << "We are using the LINDO Global Optimizer 222" << std::endl;
00516 m_iLindoErrorCode = LSsolveGOP(pModel_, &nSolStatus) ;
00517 lindoAPIErrorCheck("There was an ERROR in the call to the Optimizer solver");
00518 LSgetInfo (pModel_, LS_IINFO_GOP_STATUS, &nSolStatus);
00519 }
00520 else{
00521 std::cout << "We are using the LINDO LSsolveMIP Optimizer" << std::endl;
00522 m_iLindoErrorCode = LSsolveMIP( pModel_, &nSolStatus);
00523 lindoAPIErrorCheck("There was an ERROR in the call to the MIP solver");
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00534 throw ErrorClass("OSResult error: setVariableNumer");
00535 if(osresult->setObjectiveNumber( 1) != true)
00536 throw ErrorClass("OSResult error: setObjectiveNumber");
00537 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00538 throw ErrorClass("OSResult error: setConstraintNumber");
00539 if(osresult->setSolutionNumber( 1) != true)
00540 throw ErrorClass("OSResult error: setSolutionNumer");
00541 cout << "Solution Status = " << nSolStatus << endl;
00542 osresult->setGeneralStatusType("normal");
00543 osresult->setSolutionStatus(solIdx, "optimal", description);
00544 x = new double[ osinstance->getVariableNumber() + m_iNumberNewSlacks];
00545 srcost = new std::string[ osinstance->getVariableNumber() + m_iNumberNewSlacks];
00546 drcost = new double[ osinstance->getVariableNumber() + m_iNumberNewSlacks];
00547 for(int i = 0; i < osinstance->getVariableNumber() + m_iNumberNewSlacks; i++){
00548 drcost[i] = 0.0;
00549 srcost[i] = "";
00550 }
00551 y = new double[ osinstance->getConstraintNumber() ];
00552 z = new double[1];
00553 switch( nSolStatus){
00554 case 1:
00555
00556 cout << "case 1" << endl;
00557 case 8:
00558
00559 cout << "case 8" << endl;
00560 case 2:
00561 cout << "case 2" << endl;
00562
00563
00564 if( (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0 )
00565 || (isNonlinear == false) ){
00566 m_iLindoErrorCode = LSgetMIPPrimalSolution( pModel_, x);
00567 lindoAPIErrorCheck("Error trying to obtain primal solution with integer variables present");
00568 }
00569 else{
00570 m_iLindoErrorCode = LSgetPrimalSolution( pModel_, x);
00571 lindoAPIErrorCheck("Error trying to obtain primal solution with NO integer variables present");
00572 }
00573 osresult->setPrimalVariableValuesDense(solIdx, x);
00574
00575 if( (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0)
00576 || (isNonlinear == false) ){
00577 m_iLindoErrorCode = LSgetMIPDualSolution( pModel_, y);
00578 lindoAPIErrorCheck("Error trying to obtain dual solution with integer variables present");
00579 }
00580 else{
00581 m_iLindoErrorCode = LSgetDualSolution( pModel_, y);
00582 lindoAPIErrorCheck("Error trying to obtain dual solution with NO integer variables present");
00583 }
00584 osresult->setDualVariableValuesDense(solIdx, y);
00585
00586 if( ( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0)
00587 || (isNonlinear == false ) ) {
00588
00589
00590 }
00591 else{
00592 m_iLindoErrorCode = LSgetReducedCosts( pModel_, drcost);
00593 lindoAPIErrorCheck("Error trying to obtain the reduced costs with NO integer variables present");;
00594 }
00595
00596 {
00597 int numberOfOtherVariableResult = 1;
00598 int otherIdx = 0;
00599
00600 osresult->setNumberOfOtherVariableResults(solIdx, numberOfOtherVariableResult);
00601 for(int i = 0; i < osinstance->getVariableNumber() + m_iNumberNewSlacks; i++){
00602 outStr << drcost[i];
00603 srcost[ i] = outStr.str();
00604 outStr.str("");
00605 }
00606 osresult->setAnOtherVariableResultDense(solIdx, otherIdx, "reduced costs", "", "the variable reduced costs", srcost);
00607
00608 if( ( osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() > 0)
00609 || (isNonlinear == false ) ) {
00610 m_iLindoErrorCode = LSgetInfo( pModel_, LS_DINFO_MIP_OBJ, &z[0]);
00611 lindoAPIErrorCheck("Error trying to obtain optimal objective value with integer variables present");
00612 }
00613 else{
00614 LSgetInfo( pModel_, LS_DINFO_GOP_OBJ, &z[0]);
00615 lindoAPIErrorCheck("Error trying to obtain optimal objective value with NO integer variables present");
00616 }
00617 osresult->setObjectiveValuesDense(solIdx, z);
00618 }
00619 break;
00620 case 3:
00621 osresult->setSolutionStatus(solIdx, "infeasible", description);
00622 break;
00623 case 4:
00624 osresult->setSolutionStatus(solIdx, "unbounded", description);
00625 break;
00626 default:
00627 osresult->setSolutionStatus(solIdx, "other", description);
00628 }
00629
00630 delete[] x;
00631 delete[] y;
00632 delete[] z;
00633 delete[] srcost;
00634 delete[] drcost;
00635 return true;
00636 }
00637 catch(const ErrorClass& eclass){
00638
00639 osresult->setGeneralMessage( eclass.errormsg);
00640 osresult->setGeneralStatusType( "error");
00641 osrl = osrlwriter->writeOSrL( osresult);
00642 throw ;
00643 }
00644 }
00645
00646
00647 bool LindoSolver::processQuadraticTerms(){
00648 int nQCnnz = osinstance->getNumberOfQuadraticTerms();
00649 cout << "WE ARE PROCESSING QUADRATIC TERMS" << endl;
00650 try{
00651 if(nQCnnz <= 0)return false;
00652 std::map<std::string, double> mapQuadraticAdjustMap;
00653 std::map<std::string, double>::iterator mapPointer;
00654
00655 int i;
00656 int iVarOneIndex, iVarTwoIndex;
00657 int iRowIndex;
00658 std::string sKey;
00659 double dValue;
00660
00661 int iStringPostionOne, iStringPostionTwo;
00662
00663 int* paiQCrows = osinstance->getQuadraticTerms()->rowIndexes;
00664 int* paiQCcols1 = osinstance->getQuadraticTerms()->varOneIndexes;
00665 int* paiQCcols2 = osinstance->getQuadraticTerms()->varTwoIndexes;
00666 double* padQCcoef = osinstance->getQuadraticTerms()->coefficients;
00667 std::ostringstream ostrRow, ostr1, ostr2;
00668 std::string sIndexRow, sIndex1, sIndex2;
00669
00670 for ( i = 0; i < nQCnnz; i++){
00671 iRowIndex = paiQCrows[i];
00672
00673 if (iRowIndex >= -1){
00674 iVarOneIndex = (paiQCcols1[i] >= paiQCcols2[i])?paiQCcols2[i]:paiQCcols1[i];
00675 iVarTwoIndex = (paiQCcols1[i] <= paiQCcols2[i])?paiQCcols2[i]:paiQCcols1[i];
00676 ostrRow << iRowIndex; ostr2<<iVarTwoIndex; ostr1<<iVarOneIndex;
00677 sIndexRow = ostrRow.str();sIndex2 = ostr2.str(); sIndex1 = ostr1.str();
00678
00679 ostrRow.str("");ostr2.str("");ostr1.str("");
00680
00681 sKey = sIndexRow + "," + sIndex1 + "," + sIndex2;
00682
00683 mapPointer = mapQuadraticAdjustMap.find(sKey);
00684 if (mapPointer != mapQuadraticAdjustMap.end()){
00685 dValue = mapPointer->second;
00686 dValue += padQCcoef[i];
00687 mapQuadraticAdjustMap[sKey] = dValue;
00688 }
00689 else {
00690 mapQuadraticAdjustMap[sKey] = padQCcoef[i];
00691 }
00692 }
00693 }
00694
00695 int iNumberOfQuadraticTerms = 0;
00696 for (mapPointer = mapQuadraticAdjustMap.begin(); mapPointer != mapQuadraticAdjustMap.end(); ++mapPointer){
00697 sKey = mapPointer->first;
00698 dValue = mapPointer->second;
00699 iStringPostionOne = sKey.find_first_of(',');
00700 iStringPostionTwo = sKey.find_last_of(',');
00701
00702 iRowIndex = atoi(sKey.substr(0, iStringPostionOne).c_str());
00703 iVarOneIndex = atoi(sKey.substr(iStringPostionOne + 1, iStringPostionTwo).c_str());
00704 iVarTwoIndex = atoi(sKey.substr(iStringPostionTwo + 1).c_str());
00705
00706 if ( iVarOneIndex == iVarTwoIndex){
00707 dValue *= 2;
00708 }
00709
00710 paiQCrows[iNumberOfQuadraticTerms] = iRowIndex;
00711 paiQCcols1[iNumberOfQuadraticTerms] = iVarOneIndex;
00712 paiQCcols2[iNumberOfQuadraticTerms] = iVarTwoIndex;
00713
00714 padQCcoef[iNumberOfQuadraticTerms] = dValue ;
00715 iNumberOfQuadraticTerms ++;
00716 }
00717
00718 if(!LSloadQCData(pModel_, nQCnnz, paiQCrows, paiQCcols1,
00719 paiQCcols2, padQCcoef)) return true;
00720 else return false;
00721 }
00722 catch(const ErrorClass& eclass){
00723 osresult->setGeneralMessage( eclass.errormsg);
00724 osresult->setGeneralStatusType( "error");
00725 osrl = osrlwriter->writeOSrL( osresult);
00726 throw ;
00727 }
00728 }
00729
00730
00731
00732 bool LindoSolver::processNonlinearExpressions(){
00733
00734 cout << "PROCESS NONLINEAR TERMS" << endl;
00735 osinstance->initializeNonLinearStructures( );
00736
00737 cout << "The number of objectives with nonlinear terms is: " << osinstance->getNumberOfNonlinearObjectives() << endl;
00738 cout << "The number of constraints with nonlinear terms is: " << osinstance->getNumberOfNonlinearConstraints() << endl << endl << endl;
00739
00740
00741
00742 LINDO_OP_CODE_CONVERSION;
00748 std::map<double, int> mapNewNumber;
00749
00751 std::map<double, int>::iterator pos;
00752
00758 std::vector<int> insList;
00759
00760
00766 std::map<int, OSExpressionTree*> allExpTrees;
00767
00773 std::vector<OSnLNode*> postFixVec;
00774
00776 std::map<int, OSExpressionTree*>::iterator posTree;
00777
00787 int *piObjSense = NULL;
00788
00792 double *padVarLowerBounds = NULL;
00793
00797 double *padVarUpperBounds = NULL;
00798
00800 double *padVarval = NULL;
00801
00805 char *pachVarType = NULL;
00806
00809 char *pachConType = NULL;
00810
00812 int iNumNonlinearNonz = 0;
00813
00815 double *padNonlinearNonz = NULL;
00816
00818 int iNumberOfNonlinearConstraints = osinstance->getNumberOfNonlinearConstraints();
00819
00823 int *paiConsBegin = NULL;
00824 if(iNumberOfNonlinearConstraints > 0) paiConsBegin = new int[ iNumberOfNonlinearConstraints];
00825
00829 int *paiConsLength = NULL;
00830 if(iNumberOfNonlinearConstraints > 0) paiConsLength = new int[ iNumberOfNonlinearConstraints];
00831
00833 int iNumberOfNonlinearObjectives = osinstance->getNumberOfNonlinearObjectives();
00834
00838 int *paiObjsBegin = NULL;
00839 if(iNumberOfNonlinearObjectives > 0) paiObjsBegin = new int[ iNumberOfNonlinearObjectives];
00840
00844 int *paiObjsLength = NULL;
00845 if(iNumberOfNonlinearObjectives > 0) paiObjsLength = new int[ iNumberOfNonlinearObjectives];
00846
00847
00853 int iNumberOfNewVariables = 0;
00854
00856 int *paiInsList;
00857
00859 int iInstListLength = 0;
00860
00862 int *paiNonlinearConIndex = NULL;
00863 if(iNumberOfNonlinearConstraints > 0) paiNonlinearConIndex = new int[ iNumberOfNonlinearConstraints];
00864
00865
00866 try{
00867 int i;
00868
00869 int iCountObjs = 0;
00870 int iCountCons = 0;
00871
00872 allExpTrees = osinstance->getAllNonlinearExpressionTreesMod();
00873
00874 for(posTree = allExpTrees.begin(); posTree != allExpTrees.end(); ++posTree){
00875 cout << "HERE IS EXPRESSION TREE " << posTree->first << endl;
00876
00877 postFixVec = posTree->second->m_treeRoot->getPostfixFromExpressionTree();
00878 int iVecSize = postFixVec.size();
00879 int iNodeID;
00880 if(iVecSize > 0){
00881 for(i = 0; i < iVecSize; i++){
00882 iNodeID = postFixVec[i]->inodeInt;
00883 switch (iNodeID){
00884 case OS_SUM:
00885 insList.push_back( nlNodeIdxLindo[ OS_SUM] );
00886 insList.push_back( postFixVec[i]->inumberOfChildren);
00887 cout << "PUSH BACK A SUM" << endl;
00888 break;
00889 case OS_MAX:
00890 insList.push_back( nlNodeIdxLindo[ OS_MAX] );
00891 insList.push_back( postFixVec[i]->inumberOfChildren);
00892 cout << "PUSH BACK A MAX" << endl;
00893 break;
00894 case OS_PRODUCT:
00895 throw ErrorClass("Error: OS_PRODUCT operator not supported by Lindo");
00896 break;
00897 case OS_NUMBER:
00898 OSnLNodeNumber *numNode;
00899 insList.push_back( EP_PUSH_NUM );
00900 numNode = (OSnLNodeNumber*)postFixVec[i];
00901 pos = mapNewNumber.find( numNode->value);
00902 if(pos == mapNewNumber.end() ){
00903 cout << "FOUND A NEW NUMBER " << numNode->value << endl;
00904 insList.push_back( iNumNonlinearNonz);
00905 mapNewNumber[ numNode->value] = iNumNonlinearNonz++;
00906 }
00907 else insList.push_back( pos->second);
00908 break;
00909 case OS_VARIABLE:
00910 OSnLNodeVariable *varNode;
00911 insList.push_back( EP_PUSH_VAR );
00912 varNode = (OSnLNodeVariable*)postFixVec[i];
00913 insList.push_back( varNode->idx );
00914
00915
00916 if(varNode->coef != 1){
00917
00918 insList.push_back( EP_PUSH_NUM );
00919 pos = mapNewNumber.find( varNode->coef);
00920 if(pos == mapNewNumber.end() ){
00921 cout << "FOUND A NEW NUMBER " << varNode->coef << endl;
00922 insList.push_back( iNumNonlinearNonz);
00923 mapNewNumber[ varNode->coef] = iNumNonlinearNonz++;
00924 }
00925 else insList.push_back( pos->second);
00926 insList.push_back( EP_MULTIPLY);
00927 }
00928 break;
00929 default:
00930 insList.push_back( nlNodeIdxLindo[iNodeID] );
00931 break;
00932 }
00933 }
00934
00935 if(posTree->first < 0){
00936
00937
00938 paiObjsBegin[ iCountObjs] = iInstListLength;
00939 paiObjsLength[ iCountObjs] = insList.size() - iInstListLength;
00940 iInstListLength = insList.size();
00941 iCountObjs++;
00942 }
00943 else{
00944
00945 paiConsBegin[ iCountCons] = iInstListLength;
00946 paiConsLength[ iCountCons] = insList.size() - iInstListLength;
00947 paiNonlinearConIndex[ iCountCons] = posTree->first;
00948 cout << "CONSTRAINT ILIST LENGTH = " << iInstListLength << endl;
00949 iInstListLength = insList.size();
00950 iCountCons++;
00951 }
00952 }
00953 postFixVec.clear();
00954 }
00955
00956 padNonlinearNonz = new double[ iNumNonlinearNonz];
00957 for(pos = mapNewNumber.begin(); pos != mapNewNumber.end(); ++pos){
00958 padNonlinearNonz[ pos->second] = pos->first;
00959 cout << "INDEX = " << pos->second << " NUMBER = " << pos->first << endl;
00960 }
00961
00962 paiInsList = new int[ iInstListLength];
00963 copy(insList.begin(), insList.end(), paiInsList);
00964
00965
00966
00967 int nLinearz, nAutoDeriv;
00968
00969
00970 nLinearz = 1;
00971 m_iLindoErrorCode = LSsetModelIntParameter (pModel_,
00972 LS_IPARAM_NLP_LINEARZ, nLinearz);
00973 lindoAPIErrorCheck("Error trying to set the LS_IPARAM_NLP_LINEARZ parameter");
00974
00975
00976
00977
00978 nAutoDeriv = 1;
00979 m_iLindoErrorCode = LSsetModelIntParameter (pModel_,
00980 LS_IPARAM_NLP_AUTODERIV, nAutoDeriv);
00981 lindoAPIErrorCheck("Error trying to set the LS_IPARAM_NLP_AUTODERIV parameter");
00982 #ifdef DEBUG
00983 std::cout << "iNumberOfNonlinearConstraints= " << iNumberOfNonlinearConstraints << std::endl;
00984 std::cout << "iNumberOfNonlinearObjectives= " << iNumberOfNonlinearObjectives << std::endl;
00985 std::cout << "iNumberOfNewVariables = " << iNumberOfNewVariables << std::endl;
00986 std::cout << "iNumNonlinearNonz = " << iNumNonlinearNonz << std::endl;
00987 std::cout << "piObjSense = " << "NULL" << std::endl ;
00988 std::cout << "pachConType = " << "NULL" << std::endl ;
00989 std::cout << "pachVarType = " << "NULL" << std::endl ;
00990 int kl;
00991 std::cout << "Here is the instruction list" << std::endl;
00992 for(kl = 0; kl < iInstListLength; kl++){
00993 cout << "instruction list num " << paiInsList[ kl] << endl;
00994 }
00995 std::cout << "Number of terms in instruction list " << iInstListLength << std::endl;
00996 std::cout << "Here are the constraint indices " << std::endl;
00997 for(kl = 0; kl < iNumberOfNonlinearConstraints; kl++){
00998 cout << "con idx " << paiNonlinearConIndex[ kl] << endl;
00999 }
01000 std::cout << "Here come the nonlinear nonzeros " << std::endl;
01001 for(kl = 0; kl < iNumNonlinearNonz; kl++){
01002 cout << "nonz value = " << padNonlinearNonz[ kl] << endl;
01003 }
01004 std::cout << "padVarval = " << "NULL" << std::endl ;
01005 for(kl = 0; kl < iNumberOfNonlinearObjectives; kl++){
01006 cout << "obj inst begin = " << paiObjsBegin[ kl] << endl;
01007 }
01008 for(kl = 0; kl < iNumberOfNonlinearObjectives; kl++){
01009 cout << "obj inst list length = " << paiObjsLength[ kl] << endl;
01010 }
01011 for(kl = 0; kl < iNumberOfNonlinearConstraints; kl++){
01012 cout << "constraint inst begin = " << paiConsBegin[ kl] << endl;
01013 }
01014 for(kl = 0; kl < iNumberOfNonlinearConstraints; kl++){
01015 cout << "constraints inst list length = " << paiConsLength[ kl] << endl;
01016 }
01017 std::cout << "padVarLowerBounds = " << "NULL" << std::endl ;
01018 std::cout << "padUpperBounds = " << "NULL" << std::endl ;
01019 #endif
01020 m_iLindoErrorCode = LSaddInstruct (pModel_, iNumberOfNonlinearConstraints,
01021 iNumberOfNonlinearObjectives, iNumberOfNewVariables, iNumNonlinearNonz,
01022 piObjSense, pachConType, pachVarType, paiInsList, iInstListLength, paiNonlinearConIndex,
01023 padNonlinearNonz, padVarval, paiObjsBegin, paiObjsLength, paiConsBegin,
01024 paiConsLength, padVarLowerBounds, padVarUpperBounds);
01025 lindoAPIErrorCheck("Error trying to call LSaddInstruct");
01026
01027
01028
01029 if( iNumberOfNonlinearConstraints > 0) delete[] paiConsBegin;
01030 if( iNumberOfNonlinearConstraints > 0) delete[] paiConsLength;
01031 if( iNumberOfNonlinearObjectives > 0) delete[] paiObjsBegin;
01032 if( iNumberOfNonlinearObjectives > 0) delete[] paiObjsLength;
01033 if( iNumberOfNonlinearConstraints > 0) delete[] paiNonlinearConIndex;
01034 if( iNumNonlinearNonz > 0) delete[] padNonlinearNonz;
01035 if( iInstListLength > 0) delete[] paiInsList;
01036 mapNewNumber.clear();
01037
01038 allExpTrees.clear();
01039
01040 insList.clear();
01041
01042 postFixVec.clear();
01043
01044 return true;
01045 }
01046 catch(const ErrorClass& eclass){
01047 osresult->setGeneralMessage( eclass.errormsg);
01048 osresult->setGeneralStatusType( "error");
01049 osrl = osrlwriter->writeOSrL( osresult);
01050 throw ;
01051 }
01052 }
01053
01054
01055
01056 void LindoSolver::dataEchoCheck(){
01057 int i;
01058
01059
01060 cout << "This is problem: " << osinstance->getInstanceName() << endl;
01061 cout << "The problem source is: " << osinstance->getInstanceSource() << endl;
01062 cout << "The problem description is: " << osinstance->getInstanceDescription() << endl;
01063 cout << "number of variables = " << osinstance->getVariableNumber() << endl;
01064 cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
01065
01066
01067 if(osinstance->getVariableNumber() > 0){
01068 for(i = 0; i < osinstance->getVariableNumber(); i++){
01069 if(osinstance->getVariableNames() != NULL) cout << "variable Names " << osinstance->getVariableNames()[ i] << endl;
01070 if(osinstance->getVariableTypes() != NULL) cout << "variable Types " << osinstance->getVariableTypes()[ i] << endl;
01071 if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds " << osinstance->getVariableLowerBounds()[ i] << endl;
01072 if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds " << osinstance->getVariableUpperBounds()[i] << endl;
01073 }
01074 }
01075
01076
01077 if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0){
01078 if( osinstance->getObjectiveMaxOrMins()[0] == "min") cout << "problem is a minimization" << endl;
01079 else cout << "problem is a maximization" << endl;
01080 for(i = 0; i < osinstance->getVariableNumber(); i++){
01081 cout << "OBJ COEFFICIENT = " << osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
01082 }
01083 }
01084
01085 if(osinstance->getConstraintNumber() > 0){
01086 for(i = 0; i < osinstance->getConstraintNumber(); i++){
01087 if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] << endl;
01088 if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] << endl;
01089 if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] << endl;
01090 }
01091 }
01092
01093
01094 cout << endl;
01095 cout << "number of nonzeros = " << osinstance->getLinearConstraintCoefficientNumber() << endl;
01096 if(osinstance->getLinearConstraintCoefficientNumber() > 0){
01097 for(i = 0; i <= osinstance->getVariableNumber(); i++){
01098 cout << "Start Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts[ i] << endl;
01099 }
01100 cout << endl;
01101 for(i = 0; i < osinstance->getLinearConstraintCoefficientNumber(); i++){
01102 cout << "Index Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes[i] << endl;
01103 cout << "Nonzero Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->values[i] << endl;
01104 }
01105 }
01106
01107 cout << "number of qterms = " << osinstance->getNumberOfQuadraticTerms() << endl;
01108 for(int i = 0; i < osinstance->getNumberOfQuadraticTerms(); i++){
01109 cout << "Row Index = " << osinstance->getQuadraticTerms()->rowIndexes[i] << endl;
01110 cout << "Var Index 1 = " << osinstance->getQuadraticTerms()->varOneIndexes[ i] << endl;
01111 cout << "Var Index 2 = " << osinstance->getQuadraticTerms()->varTwoIndexes[ i] << endl;
01112 cout << "Coefficient = " << osinstance->getQuadraticTerms()->coefficients[ i] << endl;
01113 }
01114
01115 }
01116
01117 void LindoSolver::lindoAPIErrorCheck(std::string errormsg) {
01118 try{
01119 ostringstream outStr;
01120 std::string error = errormsg;
01121 char lindoerrormsg[LS_MAX_ERROR_MESSAGE_LENGTH];
01122 if(m_iLindoErrorCode != 0){
01123 outStr << endl;
01124 error = "LINDO ERROR: "+ error;
01125 outStr << error << endl;
01126 outStr << "LINDO ERROR NUMBER: " << m_iLindoErrorCode << endl;
01127 if( pEnv_ != NULL) LSgetErrorMessage(pEnv_, m_iLindoErrorCode, lindoerrormsg);
01128 error = lindoerrormsg;
01129 outStr << "LINDO ERROR MESSAGE: " << error;
01130 outStr << endl;
01131 error = outStr.str();
01132 throw ErrorClass( error);
01133 }
01134 }
01135 catch(const ErrorClass& eclass){
01136 throw ErrorClass( eclass.errormsg);
01137 }
01138 }
01139
01140
01141
01142
01143
01144