00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "BonCbc.hpp"
00012 #include "BonOACutGenerator2.hpp"
00013 #include "BonCbcNlpStrategy.hpp"
00014 #include "BonBabInfos.hpp"
00015 #include "CbcModel.hpp"
00016 #include "CbcBranchActual.hpp"
00017 #include "CbcCutGenerator.hpp"
00018 #include "CbcCompareActual.hpp"
00019 #include "CbcCompareObjective.hpp"
00020 #include "CbcCompareEstimate.hpp"
00021
00022 #include "BonExitCodes.hpp"
00023
00024 #include "BonChooseVariable.hpp"
00025 #include "BonGuessHeuristic.hpp"
00026
00027 #include "BonDiver.hpp"
00028 #include "BonLinearCutsGenerator.hpp"
00029 #include "BonTMINLPLinObj.hpp"
00030
00031 #include "CouenneBab.hpp"
00032 #include "CouenneProblem.hpp"
00033 #include "CouenneRecordBestSol.hpp"
00034
00035
00036 #define CUTOFF_TOL 1e-6
00037
00038 #define SIGNAL
00039 #ifdef SIGNAL
00040
00041 #include "CoinSignal.hpp"
00042
00043
00044 static CbcModel * currentBranchModel = NULL;
00045 extern Bonmin::OACutGenerator2 *currentOA;
00046 extern CbcModel *OAModel;
00047
00048 extern "C" {
00049
00050 static bool interruptedOnce = false;
00051
00052 static void couenne_signal_handler (int whichSignal) {
00053
00054 if (interruptedOnce) {
00055 std::cerr<<"[BREAK]"<<std::endl;
00056
00057 exit (-1);
00058 } else
00059 std::cerr<<"Ctrl+C detected, stopping Couenne..." << std::endl;
00060
00061 if (currentBranchModel) currentBranchModel -> sayEventHappened();
00062 if (OAModel) OAModel -> sayEventHappened();
00063 if (currentOA) currentOA -> parameter ().maxLocalSearchTime_ = 0.;
00064
00065 interruptedOnce = true;
00066 }
00067 }
00068 #endif
00069
00070 using namespace Couenne;
00071 using namespace Bonmin;
00072
00074 CouenneBab::CouenneBab (): Bab (), problem_(NULL) {}
00075
00077 CouenneBab::~CouenneBab () {}
00078
00079 void CouenneBab::setProblem (CouenneProblem *p)
00080 {problem_ = p;}
00081
00082
00084 void CouenneBab::branchAndBound (Bonmin::BabSetupBase & s) {
00085
00086 double remaining_time = s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime) + CoinCpuTime();
00087
00088
00089 OsiBabSolver * babInfo = dynamic_cast<OsiBabSolver *>(s.continuousSolver()->getAuxiliaryInfo());
00090 assert(babInfo);
00091 Bonmin::BabInfo * bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(babInfo);
00092
00093 if (bonBabInfoPtr == NULL) {
00094 bonBabInfoPtr = new Bonmin::BabInfo(*babInfo);
00095 s.continuousSolver()->setAuxiliaryInfo(bonBabInfoPtr);
00096 delete bonBabInfoPtr;
00097 bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(s.continuousSolver()->getAuxiliaryInfo());
00098 }
00099
00100 bonBabInfoPtr->setBabPtr(this);
00101
00102 s.nonlinearSolver()->solver()->setup_global_time_limit(s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime));
00103 OsiSolverInterface * solver = s.continuousSolver()->clone();
00104 delete modelHandler_;
00105 modelHandler_ = s.continuousSolver()->messageHandler()->clone();
00106 model_.passInMessageHandler(modelHandler_);
00107 model_.assignSolver(solver, true);
00108
00109
00110
00111
00112
00113
00114 int specOpt = s.getIntParameter(Bonmin::BabSetupBase::SpecialOption);
00115 if (specOpt) {
00116 model_.setSpecialOptions(specOpt);
00117 if (specOpt==16) {
00118 Bonmin::CbcNlpStrategy strat(s.getIntParameter(Bonmin::BabSetupBase::MaxFailures),
00119 s.getIntParameter(Bonmin::BabSetupBase::MaxInfeasible),
00120 s.getIntParameter(Bonmin::BabSetupBase::FailureBehavior));
00121 model_.setStrategy(strat);
00122 }
00123 }
00124
00125 model_.setMaximumCutPasses(s.getIntParameter(Bonmin::BabSetupBase::NumCutPasses));
00126 model_.setMaximumCutPassesAtRoot(s.getIntParameter(Bonmin::BabSetupBase::NumCutPassesAtRoot));
00127
00128
00129 for (Bonmin::BabSetupBase::CuttingMethods::iterator i = s.cutGenerators().begin() ;
00130 i != s.cutGenerators().end() ; i++) {
00131
00132 Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase *>(i->cgl);
00133 if (oa && oa->reassignLpsolver())
00134 oa->assignLpInterface(model_.solver());
00135 model_.addCutGenerator(i->cgl,i->frequency,i->id.c_str(), i->normal,
00136 i->atSolution);
00137 if(i->always){
00138 model_.cutGenerators()[model_.numberCutGenerators()-1]
00139 ->setMustCallAgain(true);
00140 }
00141 }
00142
00143 for (Bonmin::BabSetupBase::HeuristicMethods::iterator i = s.heuristics().begin() ;
00144 i != s.heuristics().end() ; i++) {
00145 CbcHeuristic * heu = i->heuristic;
00146 heu->setModel(&model_);
00147 model_.addHeuristic(heu, i->id.c_str());
00148 }
00149
00150
00151 int logLevel = s.continuousSolver()->messageHandler()->logLevel();
00152
00153
00154 model_.setLogLevel(s.getIntParameter(Bonmin::BabSetupBase::BabLogLevel));
00155
00156
00157 model_.solver()->messageHandler()->setLogLevel(logLevel);
00158
00159 model_.setPrintFrequency(s.getIntParameter(Bonmin::BabSetupBase::BabLogInterval));
00160
00161 bool ChangedObject = false;
00162
00163 if (s.continuousSolver()->objects()==NULL) {
00164
00165 const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
00166
00167 const int * priorities = nlpSolver->getPriorities();
00168 const double * upPsCosts = nlpSolver->getUpPsCosts();
00169 const double * downPsCosts = nlpSolver->getDownPsCosts();
00170 const int * directions = nlpSolver->getBranchingDirections();
00171 bool hasPseudo = (upPsCosts!=NULL);
00172 model_.findIntegers(true,hasPseudo);
00173 OsiObject ** simpleIntegerObjects = model_.objects();
00174 int numberObjects = model_.numberObjects();
00175 if (priorities != NULL || directions != NULL || hasPseudo) {
00176 ChangedObject = true;
00177 for (int i = 0 ; i < numberObjects ; i++) {
00178 CbcObject * object = dynamic_cast<CbcObject *>
00179 (simpleIntegerObjects[i]);
00180 int iCol = object->columnNumber();
00181 if (priorities)
00182 object->setPriority(priorities[iCol]);
00183 if (directions)
00184 object->setPreferredWay(directions[iCol]);
00185 if (upPsCosts) {
00186 CbcSimpleIntegerPseudoCost * pscObject =
00187 dynamic_cast<CbcSimpleIntegerPseudoCost*> (object);
00188 pscObject->setUpPseudoCost(upPsCosts[iCol]);
00189 pscObject->setDownPseudoCost(downPsCosts[iCol]);
00190 }
00191 }
00192 }
00193
00194 #if 1
00195
00196 const TMINLP::SosInfo * sos = s.nonlinearSolver()->model()->sosConstraints();
00197
00198 if (!s.getIntParameter(Bonmin::BabSetupBase::DisableSos) && sos && sos->num > 0) {
00199
00200
00201
00202 const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver();
00203 const int & numSos = sos->num;
00204 (*nlpSolver->messageHandler())<<"Adding "<<sos->num<<" sos constraints."
00205 <<CoinMessageEol;
00206
00207 CbcObject ** objects = new CbcObject*[numSos];
00208 const int * starts = sos->starts;
00209 const int * indices = sos->indices;
00210 const char * types = sos->types;
00211 const double * weights = sos->weights;
00212
00213 bool hasPriorities = false;
00214 const int * varPriorities = nlpSolver->getPriorities();
00215 int numberObjects = model_.numberObjects();
00216 if (varPriorities)
00217 {
00218 for (int i = 0 ; i < numberObjects ; i++) {
00219 if (varPriorities[i]) {
00220 hasPriorities = true;
00221 break;
00222 }
00223 }
00224 }
00225 const int * sosPriorities = sos->priorities;
00226 if (sosPriorities)
00227 {
00228 for (int i = 0 ; i < numSos ; i++) {
00229 if (sosPriorities[i]) {
00230 hasPriorities = true;
00231 break;
00232 }
00233 }
00234 }
00235 for (int i = 0 ; i < numSos ; i++)
00236 {
00237 int start = starts[i];
00238 int length = starts[i + 1] - start;
00239 #ifdef DO_IT_NWAY
00240 printf("setting nway object\n"),
00241 objects[i] = new CbcNWay(&model_, length, &indices[start],
00242 i);
00243 objects[i]->setPriority(1);
00244 #else
00245 objects[i] = new CbcSOS(&model_, length, &indices[start],
00246 &weights[start], i, types[i]);
00247 objects[i]->setPriority(10);
00248 #endif
00249 if (hasPriorities && sosPriorities && sosPriorities[i]) {
00250 objects[i]->setPriority(sosPriorities[i]);
00251 }
00252 }
00253 model_.addObjects (numSos, objects);
00254 for (int i = 0 ; i < numSos ; i++)
00255 delete objects[i];
00256 delete [] objects;
00257 }
00258 #endif
00259
00260 if (s.objects().size()) {
00261 CbcObject ** objects = new CbcObject *[s.objects().size()];
00262 for (unsigned int i = 0 ; i < s.objects().size() ; i++) {
00263 objects[i] = dynamic_cast<CbcObject *> (s.objects()[i]);
00264 assert(objects[i]);
00265 objects[i]->setModel(&model_);
00266 }
00267 model_.addObjects ((int) s.objects().size(), objects);
00268 delete [] objects;
00269 }
00270
00271 replaceIntegers(model_.objects(), model_.numberObjects());
00272
00273 } else {
00274
00275
00276 assert (s.branchingMethod() != NULL);
00277
00278
00279 model_.addObjects (s.continuousSolver () -> numberObjects (), s.continuousSolver () -> objects ());
00280
00281
00282
00283
00284
00285
00286
00287 CbcBranchDefaultDecision branch;
00288 s.branchingMethod()->setSolver(model_.solver());
00289 BonChooseVariable * strong2 = dynamic_cast<BonChooseVariable *>(s.branchingMethod());
00290 if (strong2)
00291 strong2->setCbcModel(&model_);
00292 branch.setChooseMethod(*s.branchingMethod());
00293
00294 model_.setBranchingMethod(&branch);
00295
00296 model_.solver()->deleteObjects();
00297 }
00298
00299 model_.setDblParam(CbcModel::CbcCutoffIncrement, s.getDoubleParameter(Bonmin::BabSetupBase::CutoffDecr));
00300
00301 model_.setCutoff(s.getDoubleParameter(Bonmin::BabSetupBase::Cutoff) + CUTOFF_TOL);
00302
00303 model_.setDblParam(CbcModel::CbcAllowableGap, s.getDoubleParameter(Bonmin::BabSetupBase::AllowableGap));
00304 model_.setDblParam(CbcModel::CbcAllowableFractionGap, s.getDoubleParameter(Bonmin::BabSetupBase::AllowableFractionGap));
00305
00306
00307
00308 if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::bestBound) {
00309 CbcCompareObjective compare;
00310 model_.setNodeComparison(compare);
00311 }
00312 else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::DFS) {
00313 CbcCompareDepth compare;
00314 model_.setNodeComparison(compare);
00315 }
00316 else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::BFS) {
00317 CbcCompareDefault compare;
00318 compare.setWeight(0.0);
00319 model_.setNodeComparison(compare);
00320 }
00321 else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::dynamic) {
00322 CbcCompareDefault compare;
00323 model_.setNodeComparison(compare);
00324 }
00325 else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::bestGuess) {
00326
00327
00328 CbcCompareEstimate compare;
00329 model_.setNodeComparison(compare);
00330 GuessHeuristic * guessHeu = new GuessHeuristic(model_);
00331 model_.addHeuristic(guessHeu);
00332 delete guessHeu;
00333 }
00334
00335 if (s.treeTraversalMethod() == Bonmin::BabSetupBase::HeapOnly) {
00336
00337 }
00338 else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DiveFromBest) {
00339 CbcDiver treeTraversal;
00340 treeTraversal.initialize(s);
00341 model_.passInTreeHandler(treeTraversal);
00342 }
00343 else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::ProbedDive) {
00344 CbcProbedDiver treeTraversal;
00345 treeTraversal.initialize(s);
00346 model_.passInTreeHandler(treeTraversal);
00347 }
00348 else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DfsDiveFromBest) {
00349 CbcDfsDiver treeTraversal;
00350 treeTraversal.initialize(s);
00351 model_.passInTreeHandler(treeTraversal);
00352 }
00353 else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DfsDiveDynamic) {
00354 CbcDfsDiver treeTraversal;
00355 treeTraversal.initialize(s);
00356 model_.passInTreeHandler(treeTraversal);
00357
00358 DiverCompare compare;
00359 compare.setComparisonDive(*model_.nodeComparison());
00360 compare.setComparisonBound(CbcCompareObjective());
00361 CbcDfsDiver * dfs = dynamic_cast<CbcDfsDiver *> (model_.tree());
00362 assert(dfs);
00363 compare.setDiver(dfs);
00364 model_.setNodeComparison(compare);
00365 }
00366
00367 model_.setNumberStrong(s.getIntParameter(Bonmin::BabSetupBase::NumberStrong));
00368 model_.setNumberBeforeTrust(s.getIntParameter(Bonmin::BabSetupBase::MinReliability));
00369 model_.setNumberPenalties(8);
00370
00371 model_.setDblParam(CbcModel::CbcMaximumSeconds, s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime));
00372
00373 model_.setMaximumNodes(s.getIntParameter(Bonmin::BabSetupBase::MaxNodes));
00374
00375 model_.setMaximumNumberIterations(s.getIntParameter(Bonmin::BabSetupBase::MaxIterations));
00376
00377 model_.setMaximumSolutions(s.getIntParameter(Bonmin::BabSetupBase::MaxSolutions));
00378
00379 model_.setIntegerTolerance(s.getDoubleParameter(Bonmin::BabSetupBase::IntTol));
00380
00381
00382
00383 OsiObject ** objects = model_.objects();
00384
00385 if (specOpt!=16 && objects) {
00386
00387 int numberObjects = model_.numberObjects();
00388 if (objects_ != NULL) {
00389 for (int i = 0 ; i < nObjects_; i++)
00390 delete objects_[i];
00391 }
00392 delete [] objects_;
00393 objects_ = new OsiObject*[numberObjects];
00394 nObjects_ = numberObjects;
00395 for (int i = 0 ; i < numberObjects; i++) {
00396 OsiObject * obj = objects[i];
00397 CbcSimpleInteger * intObj = dynamic_cast<CbcSimpleInteger *> (obj);
00398 if (intObj) {
00399 objects_[i] = intObj->osiObject();
00400 }
00401 else {
00402 CbcSOS * sosObj = dynamic_cast<CbcSOS *>(obj);
00403 if (sosObj) objects_[i] = sosObj->osiObject(model_.solver());
00404 else {
00405 CbcObject * cbcObj = dynamic_cast<CbcObject *>(obj);
00406 if (cbcObj) {
00407 std::cerr<<"Unsupported CbcObject appears in the code"<<std::endl;
00408 throw UNSUPPORTED_CBC_OBJECT;
00409 }
00410 else {
00411 objects_[i]=obj->clone();
00412 }
00413 }
00414 }
00415 }
00416 CbcCutGenerator ** gen = model_.cutGenerators();
00417 int numGen = model_.numberCutGenerators();
00418 for (int i = 0 ; i < numGen ; i++) {
00419 Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase * >(gen[i]->generator());
00420
00421
00422 if (oa)
00423 oa->setObjects(objects_,nObjects_);
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 try {
00446
00447
00448
00449 {
00450 OsiTMINLPInterface * tmpOsi = NULL;
00451 if(s.nonlinearSolver() == s.continuousSolver()){
00452 tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver());
00453 tmpOsi->forceSolverOutput(s.getIntParameter(Bonmin::BabSetupBase::RootLogLevel));
00454 }
00455
00456 model_.initialSolve();
00457
00458 if(tmpOsi != NULL){
00459 tmpOsi->setSolverOutputToDefault();
00460 }
00461 }
00462
00463 int ival;
00464
00465 s.options()->GetEnumValue("enable_dynamic_nlp", ival, "bonmin.");
00466
00467 if(s.nonlinearSolver() == s.continuousSolver() && ival) {
00468
00469 if(!model_.solver()->isProvenOptimal() ){
00470
00471 OsiTMINLPInterface * tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver());
00472 TMINLPLinObj * tmp_tminlp = dynamic_cast<TMINLPLinObj *> (tmpOsi->model());
00473 tmpOsi->setModel(tmp_tminlp->tminlp());
00474 model_.initialSolve();
00475 }
00476 else {
00477 LinearCutsGenerator cgl;
00478 cgl.initialize(s);
00479 OsiCuts cuts;
00480 cgl.generateCuts(*model_.solver(), cuts);
00481 std::vector<const OsiRowCut *> mycuts(cuts.sizeRowCuts());
00482 for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){
00483 mycuts[i] = cuts.rowCutPtr(i);
00484 }
00485 model_. solver () -> applyRowCuts ((int) mycuts.size(), (const OsiRowCut **) &mycuts[0]);
00486 }
00487
00488
00489 OsiTMINLPInterface * nlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver());
00490 if(nlpSolver && nlpSolver->getNewCutoffDecr()!=COIN_DBL_MAX)
00491 model_.setDblParam(CbcModel::CbcCutoffIncrement, nlpSolver->getNewCutoffDecr());
00492
00493 model_.solver()->resolve();
00494 }
00495
00496
00497 model_.passInSolverCharacteristics (bonBabInfoPtr);
00498
00499 continuousRelaxation_ =model_.solver()->getObjValue();
00500 if (specOpt==16)
00501 {
00502 #if 1
00503 const double * colsol = model_.solver()->getColSolution();
00504 const double * duals = model_.solver()->getRowPrice();
00505
00506 OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver());
00507
00508 if(tnlpSolver->problem()->has_x_init() != 2){
00509 model_.solver()->setColSolution(colsol);
00510 model_.solver()->setRowPrice(duals);
00511 }
00512 #else
00513 OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver());
00514 CoinWarmStart * warm = tnlpSolver->solver()->getWarmStart(tnlpSolver->problem());
00515 tnlpSolver->solver()->setWarmStart(warm, tnlpSolver->problem());
00516 delete warm;
00517 #endif
00518
00519 #if 0 // Sometimes primal dual point is problematic in the context of Cut-and-branch
00520 model_.solver()->resolve();
00521 if(!model_.solver()->isProvenOptimal())
00522 model_.solver()->setColSolution(NULL);
00523 #endif
00524 }
00525
00526 #ifdef SIGNAL
00527 CoinSighandler_t saveSignal = SIG_DFL;
00528
00529 saveSignal = signal (SIGINT,couenne_signal_handler);
00530 currentBranchModel = &model_;
00531 #endif
00532
00533
00534
00535
00536 remaining_time -= CoinCpuTime();
00537 model_.setDblParam(CbcModel::CbcMaximumSeconds, remaining_time);
00538 if(remaining_time > 0.)
00539 model_.branchAndBound();
00540 }
00541
00542 catch(TNLPSolver::UnsolvedError *E){
00543 s.nonlinearSolver()->model()->finalize_solution
00544 (TMINLP::MINLP_ERROR, 0, NULL, DBL_MAX);
00545 throw E;
00546 }
00547
00548 numNodes_ = model_.getNodeCount();
00549 bestObj_ = model_.getObjValue();
00550 bestBound_ = model_.getBestPossibleObjValue();
00551 mipIterationCount_ = model_.getIterationCount();
00552
00553 bool hasFailed = false;
00554 if (specOpt==16)
00555 {
00556 CbcNlpStrategy * nlpStrategy = dynamic_cast<CbcNlpStrategy *>(model_.strategy());
00557 if (nlpStrategy)
00558 hasFailed = nlpStrategy->hasFailed();
00559 else
00560 throw -1;
00561 }
00562 else
00563 hasFailed = s.nonlinearSolver()->hasContinuedOnAFailure();
00564
00565
00566
00567
00568 int numberGenerators = model_.numberCutGenerators();
00569 for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
00570 CbcCutGenerator * generator = model_.cutGenerator(iGenerator);
00571
00572 if (true&&!(generator->numberCutsInTotal() || generator->numberColumnCuts()))
00573 continue;
00574 if(modelHandler_->logLevel() >= 1) {
00575 *modelHandler_ << generator->cutGeneratorName()
00576 << "was tried" << generator->numberTimesEntered()
00577 << "times and created" << generator->numberCutsInTotal()+generator->numberColumnCuts()
00578 << "cuts of which" << generator->numberCutsActive()
00579 << "were active after adding rounds of cuts";
00580
00581
00582
00583
00584
00585
00586
00587
00588 }
00589 }
00590
00591 TMINLP::SolverReturn status = TMINLP::MINLP_ERROR;
00592
00593 if (model_.numberObjects()==0) {
00594 if (bestSolution_)
00595 delete [] bestSolution_;
00596 OsiSolverInterface * solver =
00597 (s.nonlinearSolver() == s.continuousSolver())?
00598 model_.solver() : s.nonlinearSolver();
00599 bestSolution_ = new double[solver->getNumCols()];
00600 CoinCopyN(solver->getColSolution(), solver->getNumCols(),
00601 bestSolution_);
00602 bestObj_ = bestBound_ = solver->getObjValue();
00603 }
00604
00605 if (bonBabInfoPtr->bestSolution2().size() > 0) {
00606 assert((int) bonBabInfoPtr->bestSolution2().size() == s.nonlinearSolver()->getNumCols());
00607 if (bestSolution_)
00608 delete [] bestSolution_;
00609 bestSolution_ = new double[s.nonlinearSolver()->getNumCols()];
00610 std::copy(bonBabInfoPtr->bestSolution2().begin(), bonBabInfoPtr->bestSolution2().end(),
00611 bestSolution_);
00612 bestObj_ = (bonBabInfoPtr->bestObj2());
00613 (*s.nonlinearSolver()->messageHandler())<<"\nReal objective function: "
00614 <<bestObj_<<CoinMessageEol;
00615 }
00616 else if (model_.bestSolution()) {
00617 if (bestSolution_)
00618 delete [] bestSolution_;
00619 bestSolution_ = new double[s.nonlinearSolver()->getNumCols()];
00620 CoinCopyN(model_.bestSolution(), s.nonlinearSolver()->getNumCols(), bestSolution_);
00621 }
00622 if(remaining_time <= 0.){
00623 status = TMINLP::LIMIT_EXCEEDED;
00624 if (bestSolution_) {
00625 mipStatus_ = Feasible;
00626 }
00627 else {
00628 mipStatus_ = NoSolutionKnown;
00629 }
00630 }
00631 else if (model_.status() == 0) {
00632 if(model_.isContinuousUnbounded()){
00633 status = TMINLP::CONTINUOUS_UNBOUNDED;
00634 mipStatus_ = UnboundedOrInfeasible;
00635 }
00636 else
00637 if (bestSolution_) {
00638 status = TMINLP::SUCCESS;
00639 mipStatus_ = FeasibleOptimal;
00640 }
00641 else {
00642 status = TMINLP::INFEASIBLE;
00643 mipStatus_ = ProvenInfeasible;
00644 }
00645 }
00646 else if (model_.status() == 1 || model_.status() == 5) {
00647 #if (BONMIN_VERSION_MAJOR > 1) || (BONMIN_VERSION_MINOR > 6)
00648 status = model_.status() == 1 ? TMINLP::LIMIT_EXCEEDED : TMINLP::USER_INTERRUPT;
00649 #else
00650 status = TMINLP::LIMIT_EXCEEDED;
00651 #endif
00652 if (bestSolution_) {
00653 mipStatus_ = Feasible;
00654 }
00655 else {
00656 mipStatus_ = NoSolutionKnown;
00657 }
00658 }
00659 else if (model_.status()==2) {
00660 status = TMINLP::MINLP_ERROR;
00661 }
00662
00663
00664 bool use_RBS_Cbc =
00665 !problem_ ||
00666 !(problem_ -> getRecordBestSol ()) ||
00667 !(problem_ -> getRecordBestSol () -> getHasSol()) ||
00668 (((fabs (bestObj_) < COUENNE_INFINITY / 1e4) &&
00669 (problem_ -> getRecordBestSol () -> getVal () > bestObj_)));
00670
00671
00672 assert(use_RBS_Cbc || problem_ -> getRecordBestSol () -> getSol() != NULL);
00673
00674 s.nonlinearSolver () -> model () -> finalize_solution
00675 (status,
00676 s.nonlinearSolver () -> getNumCols (),
00677 use_RBS_Cbc ? bestSolution_ : problem_ -> getRecordBestSol () -> getSol (),
00678 use_RBS_Cbc ? bestObj_ : problem_ -> getRecordBestSol () -> getVal ());
00679 }
00680
00681 const double * CouenneBab::bestSolution() const {
00682 if(!problem_ ||
00683 !(problem_ -> getRecordBestSol ()) ||
00684 !(problem_ -> getRecordBestSol () -> getHasSol()) ||
00685 (((fabs (bestObj_) < COUENNE_INFINITY / 1e4) &&
00686 (problem_ -> getRecordBestSol () -> getVal () > bestObj_))))
00687 return bestSolution_;
00688 return problem_ -> getRecordBestSol () -> getSol ();
00689 }
00690
00691 double CouenneBab::bestObj() const {
00692 if(!problem_ ||
00693 !(problem_ -> getRecordBestSol ()) ||
00694 !(problem_ -> getRecordBestSol () -> getHasSol()) ||
00695 (((fabs (bestObj_) < COUENNE_INFINITY / 1e4) &&
00696 (problem_ -> getRecordBestSol () -> getVal () > bestObj_))))
00697 return bestObj_;
00698 return problem_ -> getRecordBestSol () -> getVal ();
00699 }