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