00001
00017 #include <iostream>
00018
00019
00020
00021 #include "OSDataStructures.h"
00022 #include "OSParameters.h"
00023 #include "OSMathUtil.h"
00024 #include "OSCouenneSolver.h"
00025 #include "BonBonminSetup.hpp"
00026 # include <cppad/cppad.hpp>
00027
00028
00029
00030
00031
00032 #include "CouenneConfig.h"
00033 #include "CouenneTypes.hpp"
00034 #include "CouenneJournalist.hpp"
00035 #include "CouenneExprClone.hpp"
00036 #include "CouenneExprGroup.hpp"
00037 #include "CouenneExprAbs.hpp"
00038 #include "CouenneExprConst.hpp"
00039 #include "CouenneExprCos.hpp"
00040 #include "CouenneExprDiv.hpp"
00041 #include "CouenneExprExp.hpp"
00042 #include "CouenneExprInv.hpp"
00043 #include "CouenneExprLog.hpp"
00044 #include "CouenneExprMax.hpp"
00045 #include "CouenneExprMin.hpp"
00046 #include "CouenneExprMul.hpp"
00047 #include "CouenneExprOpp.hpp"
00048 #include "CouenneExprPow.hpp"
00049 #include "CouenneExprSin.hpp"
00050 #include "CouenneExprSub.hpp"
00051 #include "CouenneExprSum.hpp"
00052 #include "CouenneExprVar.hpp"
00053 using namespace Couenne;
00054
00055
00056
00057
00058
00059 #include "BonOsiTMINLPInterface.hpp"
00060 #include "BonIpoptSolver.hpp"
00061
00062
00063 #include "CoinTime.hpp"
00064 #include "BonminConfig.h"
00065 #include "BonCouenneInterface.hpp"
00066
00067
00068 #include "BonCouenneSetup.hpp"
00069
00070
00071 #ifdef COIN_HAS_FILTERSQP
00072 #include "BonFilterSolver.hpp"
00073 #endif
00074
00075 #include "CbcCutGenerator.hpp"
00076 #include "CouenneProblem.hpp"
00077 #include "CouenneCutGenerator.hpp"
00078 #include "CouenneBab.hpp"
00079
00080 #include <cstddef>
00081 #include <cstdlib>
00082 #include <cctype>
00083 #include <cassert>
00084 #include <stack>
00085 #include <string>
00086 #include <iostream>
00087
00088
00089
00090 using namespace Bonmin;
00091 using namespace Couenne;
00092 using std::cout;
00093 using std::endl;
00094 using std::ostringstream;
00095
00096
00097 CouenneSolver::CouenneSolver()
00098 {
00099 using namespace Ipopt;
00100 osrlwriter = new OSrLWriter();
00101 osresult = new OSResult();
00102 m_osilreader = NULL;
00103 m_osolreader = NULL;
00104 couenneErrorMsg = "";
00105 couenne = NULL;
00106 con_body = NULL;
00107 obj_body = NULL;
00108 }
00109
00110 CouenneSolver::~CouenneSolver()
00111 {
00112 #ifdef DEBUG
00113 cout << "inside CouenneSolver destructor" << endl;
00114 #endif
00115
00116 if(couenne != NULL)
00117 {
00118
00120
00121 }
00122 if(con_body != NULL)
00123 {
00124
00125 }
00126 if(obj_body != NULL)
00127 {
00128
00129 }
00130 if(m_osilreader != NULL)
00131 {
00132
00133 delete m_osilreader;
00134
00135 }
00136 m_osilreader = NULL;
00137 if(m_osolreader != NULL) delete m_osolreader;
00138 m_osolreader = NULL;
00139 delete osresult;
00140 osresult = NULL;
00141 delete osrlwriter;
00142 osrlwriter = NULL;
00143
00144
00145 #ifdef DEBUG
00146 cout << "leaving CouenneSolver destructor" << endl;
00147 #endif
00148
00149 }
00150
00151
00152 void CouenneSolver::buildSolverInstance() throw (ErrorClass)
00153 {
00154
00155 try
00156 {
00157 this->bCallbuildSolverInstance = true;
00158
00159
00160
00161
00162
00163 int i, j;
00164
00165 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00166 if(osinstance == NULL)
00167 {
00168 m_osilreader = new OSiLReader();
00169 osinstance = m_osilreader->readOSiL( osil);
00170 }
00171
00172
00173
00174
00175 osinstance->initForAlgDiff( );
00176
00177
00178
00179 couenne = new CouenneProblem(NULL, NULL, NULL);
00180 int n_allvars = osinstance->getVariableNumber();
00181 if( n_allvars < 0 )throw ErrorClass("Couenne solver Cannot have a negatiave number of Variables");
00182 #ifdef DEBUG
00183 std::cout << "NUMBER OF VARIABLES = " << n_allvars << std::endl;
00184 #endif
00185 if(n_allvars > 0)
00186 {
00187
00188 CouNumber *x_ = (CouNumber *) malloc ((n_allvars) * sizeof (CouNumber));
00189 CouNumber *lb = NULL, *ub = NULL;
00190
00191
00192 ub = osinstance->getVariableUpperBounds();
00193 lb = osinstance->getVariableLowerBounds();
00194
00195
00196 char *varType;
00197 varType = osinstance->getVariableTypes();
00198 for (i = 0; i < n_allvars; ++i)
00199 {
00200 if( (varType[i] == 'B') || (varType[i]) == 'I' )
00201 {
00202 couenne->addVariable(true, couenne->domain() );
00203 }
00204 else
00205 {
00206
00207 couenne->addVariable(false, couenne->domain() );
00208
00209 }
00210
00211 x_[i] = 0.;
00212 }
00213
00214 couenne->domain()->push(n_allvars, x_, lb, ub);
00215 free(x_);
00216 }
00217
00218
00219
00220
00221 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Couenne NEEDS AN OBJECTIVE FUNCTION");
00222
00223
00224 if (osinstance->getObjectiveNumber() > 1)
00225 throw ErrorClass("Solver cannot handle multiple objectives --- please delete all but one");
00226
00227
00228
00229
00230 SparseVector* sv = osinstance->getObjectiveCoefficients()[ 0];
00231 int nterms = sv->number;
00232 exprGroup::lincoeff lin( nterms);
00233 for ( i = 0; i < nterms; ++i)
00234 {
00235 lin[i].first = couenne->Var( sv->indexes[ i] );
00236 if( osinstance->getObjectiveMaxOrMins()[0] == "min")
00237 {
00238 lin[i].second = sv->values[ i];
00239 }
00240 else
00241 {
00242 lin[i].second = -sv->values[ i];
00243
00244 }
00245 }
00246
00247
00248 OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( -1);
00249 if (exptree != NULL)
00250 {
00251 expression** nl = new expression*[1];
00252 if( osinstance->getObjectiveMaxOrMins()[0] == "min")
00253 {
00254 nl[0] = createCouenneExpression( exptree->m_treeRoot );
00255 }
00256 else
00257 {
00258 nl[ 0] = new exprOpp(createCouenneExpression( exptree->m_treeRoot) );
00259
00260 }
00261 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, nl, 1);
00262 }
00263 else
00264 {
00265 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, NULL, 0);
00266
00267 }
00268
00269
00270 couenne->addObjective(obj_body, "min");
00271
00272
00273
00274 SparseMatrix* sm = osinstance->getLinearConstraintCoefficientsInRowMajor();
00275
00276 int nconss = osinstance->getConstraintNumber();
00277
00278 int row_nonz = 0;
00279 int kount = 0;
00280
00281 double *rowlb = osinstance->getConstraintLowerBounds();
00282 double *rowub = osinstance->getConstraintUpperBounds();
00283
00284 for (i = 0; i < nconss; ++i)
00285 {
00286
00287 row_nonz = 0;
00288 if( sm) row_nonz = sm->starts[ i +1] - sm->starts[ i];
00289 exprGroup::lincoeff con_lin( row_nonz);
00290 for (j = 0; j < row_nonz; ++j)
00291 {
00292 con_lin[j].first = couenne->Var( sm->indexes[ kount] );
00293 con_lin[j].second = sm->values[ kount];
00294 kount++;
00295 }
00296
00297 OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( i);
00298 if (exptree != NULL)
00299 {
00300 expression** nl = new expression*[1];
00301 nl[0] = createCouenneExpression(exptree->m_treeRoot);
00302 con_body = new exprGroup(0., con_lin, nl, 1);
00303 }
00304 else
00305 {
00306 con_body = new exprGroup(0., con_lin, NULL, 0);
00307 }
00308
00309 if (rowlb[ i] == rowub[ i])
00310 {
00311 couenne->addEQConstraint(con_body, new exprConst( rowub[ i] ));
00312 }
00313 else if (rowlb[ i] == -OSDBL_MAX)
00314 {
00315 assert(rowub[ i] != -OSDBL_MAX);
00316 couenne->addLEConstraint(con_body, new exprConst( rowub[ i] ));
00317 }
00318 else if (rowub[ i] == OSDBL_MAX)
00319 {
00320 assert(rowlb[ i] != OSDBL_MAX);
00321 couenne->addGEConstraint(con_body, new exprConst( rowlb[ i] ));
00322 }
00323 else
00324 couenne->addRNGConstraint(con_body, new exprConst( rowlb[ i]), new
00325 exprConst( rowub[ i] ));
00326
00327 }
00328 }
00329 catch(const ErrorClass& eclass)
00330 {
00331 std::cout << "THERE IS AN ERROR" << std::endl;
00332 osresult->setGeneralMessage( eclass.errormsg);
00333 osresult->setGeneralStatusType( "error");
00334 osrl = osrlwriter->writeOSrL( osresult);
00335 throw ErrorClass( osrl) ;
00336 }
00337 }
00338
00339
00340 expression* CouenneSolver::createCouenneExpression(OSnLNode* node)
00341 {
00342
00343 unsigned int i;
00344 switch (node->inodeInt)
00345 {
00346 case OS_PLUS :
00347 return new exprSum(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00348 case OS_SUM :
00349
00350
00351
00352 switch ( node->inumberOfChildren )
00353 {
00354 case 0:
00355
00356 return new exprConst(0.);
00357 case 1:
00358
00359 return createCouenneExpression(node->m_mChildren[0]);
00360 default:
00361
00362 expression** sumargs = new expression*[node->inumberOfChildren];
00363 for(i = 0; i< node->inumberOfChildren; i++)
00364 sumargs[i] = createCouenneExpression(node->m_mChildren[i]);
00365
00366
00367
00368 return new exprSum(sumargs, node->inumberOfChildren);
00369 }
00370 case OS_MINUS :
00371 return new exprSub(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00372 case OS_NEGATE :
00373 return new exprOpp(createCouenneExpression(node->m_mChildren[0]));
00374 case OS_TIMES :
00375 return new exprMul(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00376 case OS_DIVIDE :
00377
00378 if (node->m_mChildren[0]->inodeInt == OS_NUMBER)
00379 return new exprMul(createCouenneExpression(node->m_mChildren[0]), new exprInv(createCouenneExpression(node->m_mChildren[1])));
00380 else
00381 return new exprDiv(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00382 case OS_POWER :
00383
00384 if (node->m_mChildren[1]->inodeInt != OS_NUMBER)
00385 return new exprExp(new exprMul(new exprLog(createCouenneExpression(node->m_mChildren[0])), createCouenneExpression(node->m_mChildren[1])));
00386 else
00387 return new exprPow(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00388 case OS_PRODUCT:
00389 switch ( node->inumberOfChildren )
00390 {
00391 case 0:
00392 return new exprConst(1.);
00393 case 1:
00394 return createCouenneExpression(node->m_mChildren[0]);
00395 default:
00396 expression** args = new expression*[node->inumberOfChildren];
00397 for( i = 0; i < node->inumberOfChildren; i++)
00398 args[i] = createCouenneExpression(node->m_mChildren[i]);
00399 expression* base = new exprMul(args, node->inumberOfChildren);
00400
00401 return base;
00402 }
00403 case OS_ABS :
00404 return new exprAbs(createCouenneExpression(node->m_mChildren[0]));
00405 case OS_SQUARE :
00406 return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(2.));
00407 case OS_SQRT :
00408 return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(0.5));
00409 case OS_LN :
00410 return new exprLog(createCouenneExpression(node->m_mChildren[0]));
00411 case OS_EXP :
00412 return new exprExp(createCouenneExpression(node->m_mChildren[0]));
00413 case OS_SIN :
00414 return new exprSin(createCouenneExpression(node->m_mChildren[0]));
00415 case OS_COS :
00416 return new exprCos(createCouenneExpression(node->m_mChildren[0]));
00417 case OS_MIN :
00418 switch (node->inumberOfChildren==0)
00419 {
00420 case 0:
00421 return new exprConst(0.);
00422 case 1:
00423 return createCouenneExpression(node->m_mChildren[0]);
00424 default:
00425 expression** args = new expression*[node->inumberOfChildren];
00426 for( i = 0; i <node->inumberOfChildren; i++)
00427 args[i] = createCouenneExpression(node->m_mChildren[i]);
00428 expression* base = new exprMin(args, node->inumberOfChildren);
00429
00430 return base;
00431 }
00432 case OS_MAX :
00433 switch (node->inumberOfChildren==0)
00434 {
00435 case 0:
00436 return new exprConst(0.);
00437 case 1:
00438 return createCouenneExpression(node->m_mChildren[0]);
00439 default:
00440 expression** args = new expression*[node->inumberOfChildren];
00441 for(i = 0; i < node->inumberOfChildren; i++)
00442 args[i] = createCouenneExpression(node->m_mChildren[i]);
00443 expression* base = new exprMax(args, node->inumberOfChildren);
00444
00445 return base;
00446 }
00447 case OS_NUMBER :
00448 return new exprConst(((OSnLNodeNumber*)node)->value);
00449 case OS_PI :
00450 assert(false);
00451
00452
00453 case OS_VARIABLE :
00454 {
00455 OSnLNodeVariable* varnode = (OSnLNodeVariable*)node;
00456 if (varnode->coef == 0.)
00457 return new exprConst(0.);
00458 if (varnode->coef == 1.)
00459 return new exprClone(couenne->Variables()[varnode->idx]);
00460 if (varnode->coef == -1.)
00461 return new exprOpp(new exprClone(couenne->Variables()[varnode->idx]));
00462 return new exprMul(new exprConst(varnode->coef), new exprClone(couenne->Variables()[varnode->idx]));
00463 }
00464 default:
00465 cout << node->getTokenName() << " NOT IMPLEMENTED!!" << endl;
00466 break;
00467 }
00468
00469 return NULL;
00470 }
00471
00472
00473 void CouenneSolver::setSolverOptions() throw (ErrorClass)
00474 {
00475 try
00476 {
00477
00478 char *pEnd;
00479 bSetSolverOptions = true;
00480 couenneSetup.initializeOptionsAndJournalist();
00481
00482 couenneSetup.options()->SetIntegerValue("bonmin.bb_log_level", 0);
00483 couenneSetup.options()->SetIntegerValue("bonmin.nlp_log_level", 0 );
00484 if(osoption == NULL && osol.length() > 0)
00485 {
00486 m_osolreader = new OSoLReader();
00487 osoption = m_osolreader->readOSoL( osol);
00488 }
00489
00490 if(osoption != NULL && osoption->getNumberOfSolverOptions() > 0 )
00491 {
00492
00493 int i;
00494 std::vector<SolverOption*> optionsVector;
00495 optionsVector = osoption->getSolverOptions( "couenne",true);
00496 int num_bonmin_options = optionsVector.size();
00497 for(i = 0; i < num_bonmin_options; i++)
00498 {
00499 if(optionsVector[ i]->type == "numeric" )
00500 {
00501
00502 if(optionsVector[ i]->category == "ipopt")
00503 {
00504 couenneSetup.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00505 }
00506 else
00507 {
00508 if(optionsVector[ i]->category == "bonmin" )
00509 {
00510 couenneSetup.options()->SetNumericValue("bonmin."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00511 }
00512 else
00513 {
00514 couenneSetup.options()->SetNumericValue("couenne."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00515 }
00516 }
00517 }
00518 else if(optionsVector[ i]->type == "integer" )
00519 {
00520
00521 if(optionsVector[ i]->category == "ipopt")
00522 {
00523 couenneSetup.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00524 }
00525 else
00526 {
00527 if(optionsVector[ i]->category == "bonmin" )
00528 {
00529 couenneSetup.options()->SetIntegerValue("bonmin."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ));
00530 }
00531 else
00532 {
00533 couenneSetup.options()->SetIntegerValue("couenne."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00534 }
00535 }
00536 }
00537 else if(optionsVector[ i]->type == "string" )
00538 {
00539
00540 if(optionsVector[ i]->category == "ipopt")
00541 {
00542 couenneSetup.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value );
00543 }
00544 else
00545 {
00546 if(optionsVector[ i]->category == "bonmin" )
00547 {
00548 couenneSetup.options()->SetStringValue("bonmin."+optionsVector[ i]->name, optionsVector[ i]->value);
00549 }
00550 else
00551 {
00552 couenneSetup.options()->SetStringValue("couenne."+optionsVector[ i]->name, optionsVector[ i]->value);
00553 }
00554 }
00555
00556 }
00557 }
00558 }
00559 }
00560
00561 catch(const ErrorClass& eclass)
00562 {
00563 std::cout << "THERE IS AN ERROR" << std::endl;
00564 osresult->setGeneralMessage( eclass.errormsg);
00565 osresult->setGeneralStatusType( "error");
00566 osrl = osrlwriter->writeOSrL( osresult);
00567 throw ErrorClass( osrl) ;
00568 }
00569
00570 }
00571
00572
00573 using namespace Ipopt;
00574
00575
00576 void CouenneSolver::solve() throw (ErrorClass)
00577 {
00578 #define PRINTED_PRECISION 1e-5
00579 const int infeasible = 1;
00580
00581 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00582 if(this->bSetSolverOptions == false) setSolverOptions() ;
00583 try
00584 {
00585
00586
00587
00588 char **argv = NULL;
00589 #if COUENNE_VERSION_MAJOR == 0 && COUENNE_VERSION_MINOR <= 4
00590
00591 #endif
00592
00593 bb.setProblem(couenne);
00594
00595
00596
00597 if(osoption == NULL && osol.length() > 0)
00598 {
00599 m_osolreader = new OSoLReader();
00600 osoption = m_osolreader->readOSoL( osol);
00601 }
00602
00603
00604 tminlp = new BonminProblem( osinstance, osoption);
00605
00606 CouenneInterface *ci = NULL;
00607
00608 ci = new CouenneInterface();
00609
00610
00611
00612
00613 ci->initialize (couenneSetup.roptions(),
00614 couenneSetup.options(),
00615 couenneSetup.journalist(),
00616 GetRawPtr( tminlp) );
00617
00618
00619 app_ = new Bonmin::IpoptSolver(couenneSetup.roptions(),
00620 couenneSetup.options(),
00621 couenneSetup.journalist()
00622 );
00623
00624
00625
00626
00627 ci->setModel( GetRawPtr( tminlp) );
00628
00629 ci->setSolver( GetRawPtr( app_) );
00630
00631
00632
00633
00634 bool setupInit = false;
00635 setupInit = couenneSetup.InitializeCouenne(argv, couenne, NULL, ci);
00636
00637
00638
00639 if(setupInit == false)
00640 {
00641 std::string solutionDescription = "";
00642 std::string message = "Couenne solver finishes to the end.";
00643 int solIdx = 0;
00644 if(osresult->setServiceName( "Couenne solver service") != true)
00645 throw ErrorClass("OSResult error: setServiceName");
00646 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00647 throw ErrorClass("OSResult error: setInstanceName");
00648 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00649 throw ErrorClass("OSResult error: setVariableNumer");
00650 if(osresult->setObjectiveNumber( 1) != true)
00651 throw ErrorClass("OSResult error: setObjectiveNumber");
00652 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00653 throw ErrorClass("OSResult error: setConstraintNumber");
00654 if(osresult->setSolutionNumber( 1) != true)
00655 throw ErrorClass("OSResult error: setSolutionNumer");
00656 if(osresult->setGeneralMessage( message) != true)
00657 throw ErrorClass("OSResult error: setGeneralMessage");
00658 solutionDescription = "COUENNE INITIALIZE PROBLEM: \n There was a problem with Couenne Initialize: \n the problem could be infeasible \n there may be zero decision variables";
00659 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00660 osresult->setGeneralStatusType("normal");
00661 osrl = osrlwriter->writeOSrL( osresult);
00662 return;
00663
00664 }
00665
00666 std::cout << std::endl << std::endl;
00667
00668
00669 if(( ci->isProvenPrimalInfeasible() == false) && (ci -> isProvenOptimal () == false)
00670 && (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() <= 0) )
00671 {
00672 std::string solutionDescription = "";
00673 std::string message = "Success";
00674 int solIdx = 0;
00675 if(osresult->setServiceName( "Couenne solver service") != true)
00676 throw ErrorClass("OSResult error: setServiceName");
00677 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00678 throw ErrorClass("OSResult error: setInstanceName");
00679 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00680 throw ErrorClass("OSResult error: setVariableNumer");
00681 if(osresult->setObjectiveNumber( 1) != true)
00682 throw ErrorClass("OSResult error: setObjectiveNumber");
00683 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00684 throw ErrorClass("OSResult error: setConstraintNumber");
00685 if(osresult->setSolutionNumber( 1) != true)
00686 throw ErrorClass("OSResult error: setSolutionNumer");
00687 if(osresult->setGeneralMessage( message) != true)
00688 throw ErrorClass("OSResult error: setGeneralMessage");
00689 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00690 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00691 osresult->setGeneralStatusType("normal");
00692 osrl = osrlwriter->writeOSrL( osresult);
00693 return;
00694 }
00695
00696
00697
00698
00699
00700
00701 bb ( couenneSetup);
00702
00703
00704
00705
00706
00707 std::cout.precision (10);
00708
00709 CouenneCutGenerator *cg = NULL;
00710
00711 if (bb.model (). cutGenerators ())
00712 cg = dynamic_cast <CouenneCutGenerator *>
00713 (bb.model (). cutGenerators () [0] -> generator ());
00714
00715
00716 double global_opt;
00717 couenneSetup.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
00718
00719
00720
00721
00722 double timeLimit = 0;
00723 couenneSetup.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
00724
00725
00726
00727
00728
00729
00730 status = tminlp->status;
00731 writeResult();
00732
00733 }
00734
00735 catch(const ErrorClass& eclass)
00736 {
00737 osresult->setGeneralMessage( eclass.errormsg);
00738 osresult->setGeneralStatusType( "error");
00739 osrl = osrlwriter->writeOSrL( osresult);
00740 throw ErrorClass( osrl) ;
00741 }
00742
00743
00744
00745 catch(TNLPSolver::UnsolvedError *E)
00746 {
00747 E->writeDiffFiles();
00748 E->printError(std::cerr);
00749
00750
00751
00752
00753 }
00754
00755 catch(OsiTMINLPInterface::SimpleError &E)
00756 {
00757 std::cerr<<E.className()<<"::"<<E.methodName()
00758 <<std::endl
00759 <<E.message()<<std::endl;
00760 }
00761
00762 catch(CoinError &E)
00763 {
00764 std::cerr<<E.className()<<"::"<<E.methodName()
00765 <<std::endl
00766 <<E.message()<<std::endl;
00767 }
00768
00769 catch (Ipopt::OPTION_INVALID &E)
00770 {
00771 std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
00772 }
00773 catch (int generic_error)
00774 {
00775 if (generic_error == infeasible)
00776 printf ("problem infeasible\n");
00777 }
00778
00779 }
00780
00781
00782 void CouenneSolver::writeResult()
00783 {
00784 double *x = NULL;
00785 double *z = NULL;
00786 int i = 0;
00787 int solIdx = 0;
00788 std::string solutionDescription = "";
00789 std::string message = "Couenne solver finishes to the end.";
00790
00791
00792 try
00793 {
00794 if(osinstance->getVariableNumber() > 0) x = new double[osinstance->getVariableNumber() ];
00795 z = new double[1];
00796
00797 if(osresult->setSolverInvoked( "COIN-OR Couenne") != true)
00798 throw ErrorClass("OSResult error: setSolverInvoked");
00799 if(osresult->setServiceName( OSgetVersionInfo()) != true)
00800 throw ErrorClass("OSResult error: setServiceName");
00801 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00802 throw ErrorClass("OSResult error: setInstanceName");
00803
00804
00805
00806
00807 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00808 throw ErrorClass("OSResult error: setVariableNumer");
00809 if(osresult->setObjectiveNumber( 1) != true)
00810 throw ErrorClass("OSResult error: setObjectiveNumber");
00811 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00812 throw ErrorClass("OSResult error: setConstraintNumber");
00813 if(osresult->setSolutionNumber( 1) != true)
00814 throw ErrorClass("OSResult error: setSolutionNumer");
00815 if(osresult->setGeneralMessage( message) != true)
00816 throw ErrorClass("OSResult error: setGeneralMessage");
00817
00818 switch( status)
00819 {
00820 case TMINLP::SUCCESS:
00821 solutionDescription = "SUCCESS[COUENNE]: Algorithm terminated normally at a locally optimal point, satisfying the convergence tolerances.";
00822
00823 osresult->setSolutionStatus(solIdx, "locallyOptimal", solutionDescription);
00824
00825 if(osinstance->getObjectiveNumber() > 0)
00826 {
00827
00828 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
00829
00830 if(fabs(*(z + 0)) == 9.999e+12)
00831 {
00832 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: Continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00833
00834 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00835 break;
00836 }
00837 osresult->setObjectiveValuesDense(solIdx, z);
00838 }
00839
00840
00841 if(osinstance->getVariableNumber() > 0)
00842 {
00843 for(i=0; i < osinstance->getVariableNumber(); i++)
00844 {
00845 *(x + i) = bb.bestSolution()[i];
00846
00847 }
00848 osresult->setPrimalVariableValuesDense(solIdx, x);
00849 }
00850
00851
00852 break;
00853
00854 case TMINLP::LIMIT_EXCEEDED:
00855 solutionDescription = "LIMIT_EXCEEDED[COUENNE]: A resource limit was exceeded, we provide the current solution.";
00856
00857 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
00858
00859
00860
00861 if(osinstance->getObjectiveNumber() > 0)
00862 {
00863 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.model().getColSolution()), true)[ 0];
00864 osresult->setObjectiveValuesDense(solIdx, z);
00865 }
00866
00867 if(osinstance->getVariableNumber() > 0)
00868 {
00869 for(i=0; i < osinstance->getVariableNumber(); i++)
00870 {
00871 *(x + i) = bb.model().getColSolution()[i];
00872
00873 }
00874 osresult->setPrimalVariableValuesDense(solIdx, x);
00875 }
00876 break;
00877
00878 case TMINLP::MINLP_ERROR:
00879 solutionDescription = "MINLP_ERROR [COUENNE]: Algorithm stopped with unspecified error.";
00880
00881 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00882
00883 break;
00884
00885 case TMINLP::CONTINUOUS_UNBOUNDED:
00886 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00887
00888 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00889
00890 break;
00891
00892
00893 case TMINLP::INFEASIBLE:
00894 solutionDescription = "INFEASIBLE [COUENNE]: Problem may be infeasible.";
00895
00896 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
00897 break;
00898
00899 default:
00900 solutionDescription = "OTHER[COUENNE]: other unknown solution status from Couenne solver";
00901 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
00902 }
00903 osresult->setGeneralStatusType("normal");
00904 osrl = osrlwriter->writeOSrL( osresult);
00905 if(osinstance->getVariableNumber() > 0) delete[] x;
00906 x = NULL;
00907 delete[] z;
00908 z = NULL;
00909 }
00910
00911
00912 catch(const ErrorClass& eclass)
00913 {
00914 delete[] x;
00915 x = NULL;
00916 delete[] z;
00917 z = NULL;
00918 osresult->setGeneralMessage( eclass.errormsg);
00919 osresult->setGeneralStatusType( "error");
00920 osrl = osrlwriter->writeOSrL( osresult);
00921 throw ErrorClass( osrl) ;
00922 }
00923
00924
00925 }
00926
00927
00928