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