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