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