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
00225 SparseVector* sv = osinstance->getObjectiveCoefficients()[ 0];
00226 int nterms = sv->number;
00227 exprGroup::lincoeff lin( nterms);
00228 for ( i = 0; i < nterms; ++i)
00229 {
00230 lin[i].first = couenne->Var( sv->indexes[ i] );
00231 if( osinstance->getObjectiveMaxOrMins()[0] == "min")
00232 {
00233 lin[i].second = sv->values[ i];
00234 }
00235 else
00236 {
00237 lin[i].second = -sv->values[ i];
00238
00239 }
00240 }
00241
00242
00243 OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( -1);
00244 if (exptree != NULL)
00245 {
00246 expression** nl = new expression*[1];
00247 if( osinstance->getObjectiveMaxOrMins()[0] == "min")
00248 {
00249 nl[0] = createCouenneExpression( exptree->m_treeRoot );
00250 }
00251 else
00252 {
00253 nl[ 0] = new exprOpp(createCouenneExpression( exptree->m_treeRoot) );
00254
00255 }
00256 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, nl, 1);
00257 }
00258 else
00259 {
00260 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, NULL, 0);
00261
00262 }
00263
00264
00265 couenne->addObjective(obj_body, "min");
00266
00267
00268
00269 SparseMatrix* sm = osinstance->getLinearConstraintCoefficientsInRowMajor();
00270
00271 int nconss = osinstance->getConstraintNumber();
00272
00273 int row_nonz = 0;
00274 int kount = 0;
00275
00276 double *rowlb = osinstance->getConstraintLowerBounds();
00277 double *rowub = osinstance->getConstraintUpperBounds();
00278
00279 for (i = 0; i < nconss; ++i)
00280 {
00281
00282 row_nonz = 0;
00283 if( sm) row_nonz = sm->starts[ i +1] - sm->starts[ i];
00284 exprGroup::lincoeff con_lin( row_nonz);
00285 for (j = 0; j < row_nonz; ++j)
00286 {
00287 con_lin[j].first = couenne->Var( sm->indexes[ kount] );
00288 con_lin[j].second = sm->values[ kount];
00289 kount++;
00290 }
00291
00292 OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( i);
00293 if (exptree != NULL)
00294 {
00295 expression** nl = new expression*[1];
00296 nl[0] = createCouenneExpression(exptree->m_treeRoot);
00297 con_body = new exprGroup(0., con_lin, nl, 1);
00298 }
00299 else
00300 {
00301 con_body = new exprGroup(0., con_lin, NULL, 0);
00302 }
00303
00304 if (rowlb[ i] == rowub[ i])
00305 {
00306 couenne->addEQConstraint(con_body, new exprConst( rowub[ i] ));
00307 }
00308 else if (rowlb[ i] == -OSDBL_MAX)
00309 {
00310 assert(rowub[ i] != -OSDBL_MAX);
00311 couenne->addLEConstraint(con_body, new exprConst( rowub[ i] ));
00312 }
00313 else if (rowub[ i] == OSDBL_MAX)
00314 {
00315 assert(rowlb[ i] != OSDBL_MAX);
00316 couenne->addGEConstraint(con_body, new exprConst( rowlb[ i] ));
00317 }
00318 else
00319 couenne->addRNGConstraint(con_body, new exprConst( rowlb[ i]), new
00320 exprConst( rowub[ i] ));
00321
00322 }
00323 }
00324 catch(const ErrorClass& eclass)
00325 {
00326 std::cout << "THERE IS AN ERROR" << std::endl;
00327 osresult->setGeneralMessage( eclass.errormsg);
00328 osresult->setGeneralStatusType( "error");
00329 osrl = osrlwriter->writeOSrL( osresult);
00330 throw ErrorClass( osrl) ;
00331 }
00332 }
00333
00334
00335 expression* CouenneSolver::createCouenneExpression(OSnLNode* node)
00336 {
00337
00338 unsigned int i;
00339 switch (node->inodeInt)
00340 {
00341 case OS_PLUS :
00342 return new exprSum(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00343 case OS_SUM :
00344
00345
00346
00347 switch ( node->inumberOfChildren )
00348 {
00349 case 0:
00350
00351 return new exprConst(0.);
00352 case 1:
00353
00354 return createCouenneExpression(node->m_mChildren[0]);
00355 default:
00356
00357 expression** sumargs = new expression*[node->inumberOfChildren];
00358 for(i = 0; i< node->inumberOfChildren; i++)
00359 sumargs[i] = createCouenneExpression(node->m_mChildren[i]);
00360
00361
00362
00363 return new exprSum(sumargs, node->inumberOfChildren);
00364 }
00365 case OS_MINUS :
00366 return new exprSub(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00367 case OS_NEGATE :
00368 return new exprOpp(createCouenneExpression(node->m_mChildren[0]));
00369 case OS_TIMES :
00370 return new exprMul(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00371 case OS_DIVIDE :
00372
00373 if (node->m_mChildren[0]->inodeInt == OS_NUMBER)
00374 return new exprMul(createCouenneExpression(node->m_mChildren[0]), new exprInv(createCouenneExpression(node->m_mChildren[1])));
00375 else
00376 return new exprDiv(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00377 case OS_POWER :
00378
00379 if (node->m_mChildren[1]->inodeInt != OS_NUMBER)
00380 return new exprExp(new exprMul(new exprLog(createCouenneExpression(node->m_mChildren[0])), createCouenneExpression(node->m_mChildren[1])));
00381 else
00382 return new exprPow(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00383 case OS_PRODUCT:
00384 switch ( node->inumberOfChildren )
00385 {
00386 case 0:
00387 return new exprConst(1.);
00388 case 1:
00389 return createCouenneExpression(node->m_mChildren[0]);
00390 default:
00391 expression** args = new expression*[node->inumberOfChildren];
00392 for( i = 0; i < node->inumberOfChildren; i++)
00393 args[i] = createCouenneExpression(node->m_mChildren[i]);
00394 expression* base = new exprMul(args, node->inumberOfChildren);
00395
00396 return base;
00397 }
00398 case OS_ABS :
00399 return new exprAbs(createCouenneExpression(node->m_mChildren[0]));
00400 case OS_SQUARE :
00401 return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(2.));
00402 case OS_SQRT :
00403 return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(0.5));
00404 case OS_LN :
00405 return new exprLog(createCouenneExpression(node->m_mChildren[0]));
00406 case OS_EXP :
00407 return new exprExp(createCouenneExpression(node->m_mChildren[0]));
00408 case OS_SIN :
00409 return new exprSin(createCouenneExpression(node->m_mChildren[0]));
00410 case OS_COS :
00411 return new exprCos(createCouenneExpression(node->m_mChildren[0]));
00412 case OS_MIN :
00413 switch (node->inumberOfChildren==0)
00414 {
00415 case 0:
00416 return new exprConst(0.);
00417 case 1:
00418 return createCouenneExpression(node->m_mChildren[0]);
00419 default:
00420 expression** args = new expression*[node->inumberOfChildren];
00421 for( i = 0; i <node->inumberOfChildren; i++)
00422 args[i] = createCouenneExpression(node->m_mChildren[i]);
00423 expression* base = new exprMin(args, node->inumberOfChildren);
00424
00425 return base;
00426 }
00427 case OS_MAX :
00428 switch (node->inumberOfChildren==0)
00429 {
00430 case 0:
00431 return new exprConst(0.);
00432 case 1:
00433 return createCouenneExpression(node->m_mChildren[0]);
00434 default:
00435 expression** args = new expression*[node->inumberOfChildren];
00436 for(i = 0; i < node->inumberOfChildren; i++)
00437 args[i] = createCouenneExpression(node->m_mChildren[i]);
00438 expression* base = new exprMax(args, node->inumberOfChildren);
00439
00440 return base;
00441 }
00442 case OS_NUMBER :
00443 return new exprConst(((OSnLNodeNumber*)node)->value);
00444 case OS_PI :
00445 assert(false);
00446
00447
00448 case OS_VARIABLE :
00449 {
00450 OSnLNodeVariable* varnode = (OSnLNodeVariable*)node;
00451 if (varnode->coef == 0.)
00452 return new exprConst(0.);
00453 if (varnode->coef == 1.)
00454 return new exprClone(couenne->Variables()[varnode->idx]);
00455 if (varnode->coef == -1.)
00456 return new exprOpp(new exprClone(couenne->Variables()[varnode->idx]));
00457 return new exprMul(new exprConst(varnode->coef), new exprClone(couenne->Variables()[varnode->idx]));
00458 }
00459 default:
00460 cout << node->getTokenName() << " NOT IMPLEMENTED!!" << endl;
00461 break;
00462 }
00463
00464 return NULL;
00465 }
00466
00467
00468 void CouenneSolver::setSolverOptions() throw (ErrorClass)
00469 {
00470 try
00471 {
00472
00473 char *pEnd;
00474 bSetSolverOptions = true;
00475 couenneSetup.initializeOptionsAndJournalist();
00476
00477 couenneSetup.options()->SetIntegerValue("bonmin.bb_log_level", 0);
00478 couenneSetup.options()->SetIntegerValue("bonmin.nlp_log_level", 0 );
00479 if(osoption == NULL && osol.length() > 0)
00480 {
00481 m_osolreader = new OSoLReader();
00482 osoption = m_osolreader->readOSoL( osol);
00483 }
00484
00485 if(osoption != NULL && osoption->getNumberOfSolverOptions() > 0 )
00486 {
00487
00488 int i;
00489 std::vector<SolverOption*> optionsVector;
00490 optionsVector = osoption->getSolverOptions( "couenne",true);
00491 int num_bonmin_options = optionsVector.size();
00492 for(i = 0; i < num_bonmin_options; i++)
00493 {
00494 if(optionsVector[ i]->type == "numeric" )
00495 {
00496
00497 if(optionsVector[ i]->category == "ipopt")
00498 {
00499 couenneSetup.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00500 }
00501 else
00502 {
00503 if(optionsVector[ i]->category == "bonmin" )
00504 {
00505 couenneSetup.options()->SetNumericValue("bonmin."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00506 }
00507 else
00508 {
00509 couenneSetup.options()->SetNumericValue("couenne."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00510 }
00511 }
00512 }
00513 else if(optionsVector[ i]->type == "integer" )
00514 {
00515
00516 if(optionsVector[ i]->category == "ipopt")
00517 {
00518 couenneSetup.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00519 }
00520 else
00521 {
00522 if(optionsVector[ i]->category == "bonmin" )
00523 {
00524 couenneSetup.options()->SetIntegerValue("bonmin."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ));
00525 }
00526 else
00527 {
00528 couenneSetup.options()->SetIntegerValue("couenne."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00529 }
00530 }
00531 }
00532 else if(optionsVector[ i]->type == "string" )
00533 {
00534
00535 if(optionsVector[ i]->category == "ipopt")
00536 {
00537 couenneSetup.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value );
00538 }
00539 else
00540 {
00541 if(optionsVector[ i]->category == "bonmin" )
00542 {
00543 couenneSetup.options()->SetStringValue("bonmin."+optionsVector[ i]->name, optionsVector[ i]->value);
00544 }
00545 else
00546 {
00547 couenneSetup.options()->SetStringValue("couenne."+optionsVector[ i]->name, optionsVector[ i]->value);
00548 }
00549 }
00550
00551 }
00552 }
00553 }
00554 }
00555
00556 catch(const ErrorClass& eclass)
00557 {
00558 std::cout << "THERE IS AN ERROR" << std::endl;
00559 osresult->setGeneralMessage( eclass.errormsg);
00560 osresult->setGeneralStatusType( "error");
00561 osrl = osrlwriter->writeOSrL( osresult);
00562 throw ErrorClass( osrl) ;
00563 }
00564
00565 }
00566
00567
00568 using namespace Ipopt;
00569
00570
00571 void CouenneSolver::solve() throw (ErrorClass)
00572 {
00573 #define PRINTED_PRECISION 1e-5
00574 const int infeasible = 1;
00575
00576 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00577 if(this->bSetSolverOptions == false) setSolverOptions() ;
00578 try
00579 {
00580
00581
00582
00583 char **argv = NULL;
00584 #if COUENNE_VERSION_MAJOR == 0 && COUENNE_VERSION_MINOR <= 4
00585
00586 #endif
00587
00588 bb.setProblem(couenne);
00589
00590
00591
00592 if(osoption == NULL && osol.length() > 0)
00593 {
00594 m_osolreader = new OSoLReader();
00595 osoption = m_osolreader->readOSoL( osol);
00596 }
00597
00598
00599 tminlp = new BonminProblem( osinstance, osoption);
00600
00601 CouenneInterface *ci = NULL;
00602
00603 ci = new CouenneInterface();
00604
00605
00606
00607
00608 ci->initialize (couenneSetup.roptions(),
00609 couenneSetup.options(),
00610 couenneSetup.journalist(),
00611 GetRawPtr( tminlp) );
00612
00613
00614 app_ = new Bonmin::IpoptSolver(couenneSetup.roptions(),
00615 couenneSetup.options(),
00616 couenneSetup.journalist()
00617 );
00618
00619
00620
00621
00622 ci->setModel( GetRawPtr( tminlp) );
00623
00624 ci->setSolver( GetRawPtr( app_) );
00625
00626
00627
00628
00629 bool setupInit = false;
00630 setupInit = couenneSetup.InitializeCouenne(argv, couenne, NULL, ci);
00631
00632
00633
00634 if(setupInit == false)
00635 {
00636 std::string solutionDescription = "";
00637 std::string message = "Couenne solver finishes to the end.";
00638 int solIdx = 0;
00639 if(osresult->setServiceName( "Couenne solver service") != true)
00640 throw ErrorClass("OSResult error: setServiceName");
00641 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00642 throw ErrorClass("OSResult error: setInstanceName");
00643 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00644 throw ErrorClass("OSResult error: setVariableNumer");
00645 if(osresult->setObjectiveNumber( 1) != true)
00646 throw ErrorClass("OSResult error: setObjectiveNumber");
00647 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00648 throw ErrorClass("OSResult error: setConstraintNumber");
00649 if(osresult->setSolutionNumber( 1) != true)
00650 throw ErrorClass("OSResult error: setSolutionNumer");
00651 if(osresult->setGeneralMessage( message) != true)
00652 throw ErrorClass("OSResult error: setGeneralMessage");
00653 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";
00654 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00655 osresult->setGeneralStatusType("normal");
00656 osrl = osrlwriter->writeOSrL( osresult);
00657 return;
00658
00659 }
00660
00661 std::cout << std::endl << std::endl;
00662
00663
00664 if(( ci->isProvenPrimalInfeasible() == false) && (ci -> isProvenOptimal () == false)
00665 && (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() <= 0) )
00666 {
00667 std::string solutionDescription = "";
00668 std::string message = "Success";
00669 int solIdx = 0;
00670 if(osresult->setServiceName( "Couenne solver service") != true)
00671 throw ErrorClass("OSResult error: setServiceName");
00672 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00673 throw ErrorClass("OSResult error: setInstanceName");
00674 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00675 throw ErrorClass("OSResult error: setVariableNumer");
00676 if(osresult->setObjectiveNumber( 1) != true)
00677 throw ErrorClass("OSResult error: setObjectiveNumber");
00678 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00679 throw ErrorClass("OSResult error: setConstraintNumber");
00680 if(osresult->setSolutionNumber( 1) != true)
00681 throw ErrorClass("OSResult error: setSolutionNumer");
00682 if(osresult->setGeneralMessage( message) != true)
00683 throw ErrorClass("OSResult error: setGeneralMessage");
00684 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00685 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00686 osresult->setGeneralStatusType("normal");
00687 osrl = osrlwriter->writeOSrL( osresult);
00688 return;
00689 }
00690
00691
00692
00693
00694
00695
00696 bb ( couenneSetup);
00697
00698
00699
00700
00701
00702 std::cout.precision (10);
00703
00704 CouenneCutGenerator *cg = NULL;
00705
00706 if (bb.model (). cutGenerators ())
00707 cg = dynamic_cast <CouenneCutGenerator *>
00708 (bb.model (). cutGenerators () [0] -> generator ());
00709
00710
00711 double global_opt;
00712 couenneSetup.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
00713
00714
00715
00716
00717 double timeLimit = 0;
00718 couenneSetup.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
00719
00720
00721
00722
00723
00724
00725 status = tminlp->status;
00726 writeResult();
00727
00728 }
00729
00730 catch(const ErrorClass& eclass)
00731 {
00732 osresult->setGeneralMessage( eclass.errormsg);
00733 osresult->setGeneralStatusType( "error");
00734 osrl = osrlwriter->writeOSrL( osresult);
00735 throw ErrorClass( osrl) ;
00736 }
00737
00738
00739
00740 catch(TNLPSolver::UnsolvedError *E)
00741 {
00742 E->writeDiffFiles();
00743 E->printError(std::cerr);
00744
00745
00746
00747
00748 }
00749
00750 catch(OsiTMINLPInterface::SimpleError &E)
00751 {
00752 std::cerr<<E.className()<<"::"<<E.methodName()
00753 <<std::endl
00754 <<E.message()<<std::endl;
00755 }
00756
00757 catch(CoinError &E)
00758 {
00759 std::cerr<<E.className()<<"::"<<E.methodName()
00760 <<std::endl
00761 <<E.message()<<std::endl;
00762 }
00763
00764 catch (Ipopt::OPTION_INVALID &E)
00765 {
00766 std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
00767 }
00768 catch (int generic_error)
00769 {
00770 if (generic_error == infeasible)
00771 printf ("problem infeasible\n");
00772 }
00773
00774 }
00775
00776
00777 void CouenneSolver::writeResult()
00778 {
00779 double *x = NULL;
00780 double *z = NULL;
00781 int i = 0;
00782 int solIdx = 0;
00783 std::string solutionDescription = "";
00784 std::string message = "Couenne solver finishes to the end.";
00785
00786
00787 try
00788 {
00789 if(osinstance->getVariableNumber() > 0) x = new double[osinstance->getVariableNumber() ];
00790 z = new double[1];
00791
00792 if(osresult->setSolverInvoked( "COIN-OR Couenne") != true)
00793 throw ErrorClass("OSResult error: setSolverInvoked");
00794 if(osresult->setServiceName( OSgetVersionInfo()) != true)
00795 throw ErrorClass("OSResult error: setServiceName");
00796 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00797 throw ErrorClass("OSResult error: setInstanceName");
00798
00799
00800
00801
00802 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00803 throw ErrorClass("OSResult error: setVariableNumer");
00804 if(osresult->setObjectiveNumber( 1) != true)
00805 throw ErrorClass("OSResult error: setObjectiveNumber");
00806 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00807 throw ErrorClass("OSResult error: setConstraintNumber");
00808 if(osresult->setSolutionNumber( 1) != true)
00809 throw ErrorClass("OSResult error: setSolutionNumer");
00810 if(osresult->setGeneralMessage( message) != true)
00811 throw ErrorClass("OSResult error: setGeneralMessage");
00812
00813 switch( status)
00814 {
00815 case TMINLP::SUCCESS:
00816 solutionDescription = "SUCCESS[COUENNE]: Algorithm terminated normally at a locally optimal point, satisfying the convergence tolerances.";
00817
00818 osresult->setSolutionStatus(solIdx, "locallyOptimal", solutionDescription);
00819
00820 if(osinstance->getObjectiveNumber() > 0)
00821 {
00822
00823 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
00824
00825 if(fabs(*(z + 0)) == 9.999e+12)
00826 {
00827 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: Continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00828
00829 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00830 break;
00831 }
00832 osresult->setObjectiveValuesDense(solIdx, z);
00833 }
00834
00835
00836 if(osinstance->getVariableNumber() > 0)
00837 {
00838 for(i=0; i < osinstance->getVariableNumber(); i++)
00839 {
00840 *(x + i) = bb.bestSolution()[i];
00841
00842 }
00843 osresult->setPrimalVariableValuesDense(solIdx, x);
00844 }
00845
00846
00847 break;
00848
00849 case TMINLP::LIMIT_EXCEEDED:
00850 solutionDescription = "LIMIT_EXCEEDED[COUENNE]: A resource limit was exceeded, we provide the current solution.";
00851
00852 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
00853
00854
00855
00856 if(osinstance->getObjectiveNumber() > 0)
00857 {
00858 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.model().getColSolution()), true)[ 0];
00859 osresult->setObjectiveValuesDense(solIdx, z);
00860 }
00861
00862 if(osinstance->getVariableNumber() > 0)
00863 {
00864 for(i=0; i < osinstance->getVariableNumber(); i++)
00865 {
00866 *(x + i) = bb.model().getColSolution()[i];
00867
00868 }
00869 osresult->setPrimalVariableValuesDense(solIdx, x);
00870 }
00871 break;
00872
00873 case TMINLP::MINLP_ERROR:
00874 solutionDescription = "MINLP_ERROR [COUENNE]: Algorithm stopped with unspecified error.";
00875
00876 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00877
00878 break;
00879
00880 case TMINLP::CONTINUOUS_UNBOUNDED:
00881 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00882
00883 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00884
00885 break;
00886
00887
00888 case TMINLP::INFEASIBLE:
00889 solutionDescription = "INFEASIBLE [COUENNE]: Problem may be infeasible.";
00890
00891 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
00892 break;
00893
00894 default:
00895 solutionDescription = "OTHER[COUENNE]: other unknown solution status from Couenne solver";
00896 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
00897 }
00898 osresult->setGeneralStatusType("normal");
00899 osrl = osrlwriter->writeOSrL( osresult);
00900 if(osinstance->getVariableNumber() > 0) delete[] x;
00901 x = NULL;
00902 delete[] z;
00903 z = NULL;
00904 }
00905
00906
00907 catch(const ErrorClass& eclass)
00908 {
00909 delete[] x;
00910 x = NULL;
00911 delete[] z;
00912 z = NULL;
00913 osresult->setGeneralMessage( eclass.errormsg);
00914 osresult->setGeneralStatusType( "error");
00915 osrl = osrlwriter->writeOSrL( osresult);
00916 throw ErrorClass( osrl) ;
00917 }
00918
00919
00920 }
00921
00922
00923