1 // (C) Copyright International Business Machines Corporation, Carnegie Mellon University 2004, 2007 2 // All Rights Reserved. 3 // This code is published under the Eclipse Public License. 4 // 5 // Authors : 6 // Pierre Bonami, Carnegie Mellon University, 7 // Carl D. Laird, Carnegie Mellon University, 8 // Andreas Waechter, International Business Machines Corporation 9 // 10 // Date : 12/01/2004 11 12 13 #ifndef OsiTMINLPInterface_H 14 #define OsiTMINLPInterface_H 15 16 #define INT_BIAS 0e-8 17 18 #include <string> 19 #include <iostream> 20 21 #include "OsiSolverInterface.hpp" 22 #include "CoinWarmStartBasis.hpp" 23 24 #include "BonCutStrengthener.hpp" 25 //#include "BonRegisteredOptions.hpp" 26 27 namespace Bonmin { 28 class TMINLP; 29 class TMINLP2TNLP; 30 class TMINLP2OsiLP; 31 class TNLP2FPNLP; 32 class TNLPSolver; 33 class RegisteredOptions; 34 class StrongBranchingSolver; 35 36 /** Solvers for solving nonlinear programs.*/ 37 enum Solver{ 38 EIpopt=0 /** <a href="http://projects.coin-or.org/Ipopt"> Ipopt </a> interior point algorithm.*/, 39 EFilterSQP /** <a href="http://www-unix.mcs.anl.gov/~leyffer/solvers.html"> filterSQP </a> Sequential Quadratic Programming algorithm.*/, 40 EAll/** Use all solvers.*/ 41 }; 42 /** 43 This is class provides an Osi interface for a Mixed Integer Linear Program 44 expressed as a TMINLP 45 (so that we can use it for example as the continuous solver in Cbc). 46 */ 47 48 class OsiTMINLPInterface : public OsiSolverInterface 49 { 50 friend class BonminParam; 51 52 public: 53 54 //############################################################################# 55 56 /**Error class to throw exceptions from OsiTMINLPInterface. 57 * Inherited from CoinError, we just want to have a different class to be able to catch 58 * errors thrown by OsiTMINLPInterface. 59 */ 60 class SimpleError : public CoinError 61 { 62 private: 63 SimpleError(); 64 65 public: 66 ///Alternate constructor using strings SimpleError(std::string message,std::string methodName,std::string f=std::string (),int l=-1)67 SimpleError(std::string message, 68 std::string methodName, 69 std::string f = std::string(), 70 int l = -1) 71 : 72 CoinError(message,methodName,std::string("OsiTMINLPInterface"), f, l) 73 {} 74 } 75 ; 76 77 #ifdef __LINE__ 78 #define SimpleError(x, y) SimpleError((x), (y), __FILE__, __LINE__) 79 #endif 80 81 // Error when problem is not solved newUnsolvedError(int num,Ipopt::SmartPtr<TMINLP2TNLP> problem,std::string name)82 TNLPSolver::UnsolvedError * newUnsolvedError(int num, Ipopt::SmartPtr<TMINLP2TNLP> problem, std::string name){ 83 return app_->newUnsolvedError(num, problem, name); 84 } 85 //############################################################################# 86 87 enum WarmStartModes{ 88 None, 89 FakeBasis, 90 Optimum, 91 InteriorPoint}; 92 93 /** Type of the messages specifically written by OsiTMINLPInterface.*/ 94 enum MessagesTypes{ 95 SOLUTION_FOUND/**found a feasible solution*/, 96 INFEASIBLE_SOLUTION_FOUND/**found an infeasible problem*/, 97 UNSOLVED_PROBLEM_FOUND/**found an unsolved problem*/, 98 WARNING_RESOLVING /** Warn that a problem is resolved*/, 99 WARN_SUCCESS_WS/** Problem not solved with warm start but solved without*/, 100 WARN_SUCCESS_RANDOM/** Subproblem not solve with warm start but solved with random point*/, 101 WARN_CONTINUING_ON_FAILURE/** a failure occured but is continuing*/, 102 SUSPECT_PROBLEM/** Output the number of the problem.*/, 103 SUSPECT_PROBLEM2/** Output the number of the problem.*/, 104 IPOPT_SUMMARY /** Output summary statistics on Ipopt solution.*/, 105 BETTER_SOL /** Found a better solution with random values.*/, 106 LOG_HEAD/** Head of "civilized" log.*/, 107 LOG_FIRST_LINE/** First line (first solve) of log.*/, 108 LOG_LINE/**standard line (retry solving) of log.*/, 109 ALTERNATE_OBJECTIVE/** Recomputed integer feasible with alternate objective function*/, 110 WARN_RESOLVE_BEFORE_INITIAL_SOLVE /** resolve() has been called but there 111 was no previous call to initialSolve(). 112 */, 113 ERROR_NO_TNLPSOLVER /** Trying to access non-existent TNLPSolver*/, 114 WARNING_NON_CONVEX_OA /** Warn that there are equality or ranged constraints and OA may works bad.*/, 115 SOLVER_DISAGREE_STATUS /** Different solver gives different status for problem.*/, 116 SOLVER_DISAGREE_VALUE /** Different solver gives different optimal value for problem.*/, 117 OSITMINLPINTERFACE_DUMMY_END 118 }; 119 120 //############################################################################# 121 122 123 /** Messages written by an OsiTMINLPInterface. */ 124 class Messages : public CoinMessages 125 { 126 public: 127 /// Constructor 128 Messages(); 129 }; 130 131 132 //############################################################################# 133 134 135 /**@name Constructors and destructors */ 136 //@{ 137 /// Default Constructor 138 OsiTMINLPInterface(); 139 140 /** Facilitator to initialize interface. */ 141 void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions, 142 Ipopt::SmartPtr<Ipopt::OptionsList> options, 143 Ipopt::SmartPtr<Ipopt::Journalist> journalist, 144 const std::string & prefix, 145 Ipopt::SmartPtr<TMINLP> tminlp); 146 147 /** Facilitator to initialize interface. */ initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions,Ipopt::SmartPtr<Ipopt::OptionsList> options,Ipopt::SmartPtr<Ipopt::Journalist> journalist,Ipopt::SmartPtr<TMINLP> tminlp)148 void initialize(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions, 149 Ipopt::SmartPtr<Ipopt::OptionsList> options, 150 Ipopt::SmartPtr<Ipopt::Journalist> journalist, 151 Ipopt::SmartPtr<TMINLP> tminlp){ 152 initialize(roptions, options, journalist, "bonmin.", tminlp); 153 } 154 155 /** Set the model to be solved by interface.*/ 156 void setModel(Ipopt::SmartPtr<TMINLP> tminlp); 157 /** Set the solver to be used by interface.*/ 158 void setSolver(Ipopt::SmartPtr<TNLPSolver> app); 159 /** Sets the TMINLP2TNLP to be used by the interface.*/ 160 void use(Ipopt::SmartPtr<TMINLP2TNLP> tminlp2tnlp); 161 /** Copy constructor 162 */ 163 OsiTMINLPInterface (const OsiTMINLPInterface &); 164 165 /** Virtual copy constructor */ 166 OsiSolverInterface * clone(bool copyData = true) const; 167 168 /// Assignment operator 169 OsiTMINLPInterface & operator=(const OsiTMINLPInterface& rhs); 170 171 /// Destructor 172 virtual ~OsiTMINLPInterface (); 173 174 175 /// Read parameter file 176 void readOptionFile(const std::string & fileName); 177 178 /// Retrieve OsiTMINLPApplication option list 179 const Ipopt::SmartPtr<Ipopt::OptionsList> options() const; 180 /// Retrieve OsiTMINLPApplication option list 181 Ipopt::SmartPtr<Ipopt::OptionsList> options(); 182 prefix() const183 const char * prefix() const{ 184 if(!IsValid(app_)) { 185 messageHandler()->message(ERROR_NO_TNLPSOLVER, messages_)<<CoinMessageEol; 186 return NULL; 187 } 188 else 189 return app_->prefix(); 190 } 191 //@} 192 //--------------------------------------------------------------------------- 193 /**@name Solve methods */ 194 //@{ 195 /// Solve initial continuous relaxation 196 virtual void initialSolve(); 197 198 /// Solve initial continuous relaxation (precising from where) 199 virtual void initialSolve(const char * whereFrom); 200 201 /** Resolve the continuous relaxation after problem modification. 202 initialSolve may or may not have been called before this is called. In 203 any case, this must solve the problem, and speed the process up if it 204 can reuse any remnants of data that might exist from a previous solve. 205 */ 206 virtual void resolve(); 207 208 /** Resolve the continuous relaxation after problem modification. 209 initialSolve may or may not have been called before this is called. In 210 any case, this must solve the problem, and speed the process up if it 211 can reuse any remnants of data that might exist from a previous solve. 212 */ 213 virtual void resolve(const char * whereFrom); 214 215 /** Resolve the problem with different random starting points to try to find 216 a better solution (only makes sense for a non-convex problem.*/ 217 virtual void resolveForCost(int numretry, bool keepWs); 218 219 /** Method to be called when a problem has failed to be solved. Will try 220 to resolve it with different settings. 221 */ 222 virtual void resolveForRobustness(int numretry); 223 224 /// Nescessary for compatibility with OsiSolverInterface but does nothing. branchAndBound()225 virtual void branchAndBound() 226 { 227 throw SimpleError("Function not implemented for OsiTMINLPInterface","branchAndBound()"); 228 } 229 //@} 230 231 232 233 //--------------------------------------------------------------------------- 234 ///@name Methods returning info on how the solution process terminated 235 //@{ 236 /// Are there a numerical difficulties? 237 virtual bool isAbandoned() const; 238 /// Is optimality proven? 239 virtual bool isProvenOptimal() const; 240 /// Is primal infeasiblity proven? 241 virtual bool isProvenPrimalInfeasible() const; 242 /// Is dual infeasiblity proven? 243 virtual bool isProvenDualInfeasible() const; 244 /// Is the given primal objective limit reached? 245 virtual bool isPrimalObjectiveLimitReached() const; 246 /// Is the given dual objective limit reached? 247 virtual bool isDualObjectiveLimitReached() const; 248 /// Iteration limit reached? 249 virtual bool isIterationLimitReached() const; 250 251 ///Warn solver that branch-and-bound is continuing after a failure continuingOnAFailure()252 void continuingOnAFailure() 253 { 254 hasContinuedAfterNlpFailure_ = true; 255 } 256 257 258 //Added by Claudia 259 getNewCutoffDecr()260 double getNewCutoffDecr() 261 { 262 return newCutoffDecr; 263 } 264 setNewCutoffDecr(double d)265 void setNewCutoffDecr(double d) 266 { 267 newCutoffDecr = d; 268 } 269 270 271 /// Did we continue on a failure hasContinuedOnAFailure()272 bool hasContinuedOnAFailure() 273 { 274 return hasContinuedAfterNlpFailure_; 275 } 276 /// tell to ignore the failures (don't throw, don't fathom, don't report) ignoreFailures()277 void ignoreFailures() 278 { 279 pretendFailIsInfeasible_ = 2; 280 } 281 /// Force current solution to be infeasible forceInfeasible()282 void forceInfeasible() 283 { 284 problem_->set_obj_value(1e200); 285 } 286 /// Force current solution to be branched on (make it fractionnal with small objective) forceBranchable()287 void forceBranchable() 288 { 289 problem_->set_obj_value(-1e200); 290 problem_->force_fractionnal_sol(); 291 } 292 //@} 293 294 295 //--------------------------------------------------------------------------- 296 /**@name Parameter set/get methods 297 298 The set methods return true if the parameter was set to the given value, 299 false otherwise. There can be various reasons for failure: the given 300 parameter is not applicable for the solver (e.g., refactorization 301 frequency for the clp algorithm), the parameter is not yet implemented 302 for the solver or simply the value of the parameter is out of the range 303 the solver accepts. If a parameter setting call returns false check the 304 details of your solver. 305 306 The get methods return true if the given parameter is applicable for the 307 solver and is implemented. In this case the value of the parameter is 308 returned in the second argument. Otherwise they return false. 309 */ 310 //@{ 311 // Set an integer parameter 312 bool setIntParam(OsiIntParam key, int value); 313 // Set an double parameter 314 bool setDblParam(OsiDblParam key, double value); 315 // Set a string parameter 316 bool setStrParam(OsiStrParam key, const std::string & value); 317 // Get an integer parameter 318 bool getIntParam(OsiIntParam key, int& value) const; 319 // Get an double parameter 320 bool getDblParam(OsiDblParam key, double& value) const; 321 // Get a string parameter 322 bool getStrParam(OsiStrParam key, std::string& value) const; 323 324 // Get the push values for starting point getPushFact() const325 inline double getPushFact() const 326 { 327 return pushValue_; 328 } 329 330 //@} 331 332 333 //--------------------------------------------------------------------------- 334 /**@name Problem information methods 335 336 These methods call the solver's query routines to return 337 information about the problem referred to by the current object. 338 Querying a problem that has no data associated with it result in 339 zeros for the number of rows and columns, and NULL pointers from 340 the methods that return vectors. 341 342 Const pointers returned from any data-query method are valid as 343 long as the data is unchanged and the solver is not called. 344 */ 345 //@{ 346 /// Get number of columns 347 virtual int getNumCols() const; 348 349 /// Get number of rows 350 virtual int getNumRows() const; 351 352 ///get name of variables 353 const OsiSolverInterface::OsiNameVec& getVarNames() ; 354 /// Get pointer to array[getNumCols()] of column lower bounds 355 virtual const double * getColLower() const; 356 357 /// Get pointer to array[getNumCols()] of column upper bounds 358 virtual const double * getColUpper() const; 359 360 /** Get pointer to array[getNumRows()] of row constraint senses. 361 <ul> 362 <li>'L': <= constraint 363 <li>'E': = constraint 364 <li>'G': >= constraint 365 <li>'R': ranged constraint 366 <li>'N': free constraint 367 </ul> 368 */ 369 virtual const char * getRowSense() const; 370 371 /** Get pointer to array[getNumRows()] of rows right-hand sides 372 <ul> 373 <li> if rowsense()[i] == 'L' then rhs()[i] == rowupper()[i] 374 <li> if rowsense()[i] == 'G' then rhs()[i] == rowlower()[i] 375 <li> if rowsense()[i] == 'R' then rhs()[i] == rowupper()[i] 376 <li> if rowsense()[i] == 'N' then rhs()[i] == 0.0 377 </ul> 378 */ 379 virtual const double * getRightHandSide() const; 380 381 /** Get pointer to array[getNumRows()] of row ranges. 382 <ul> 383 <li> if rowsense()[i] == 'R' then 384 rowrange()[i] == rowupper()[i] - rowlower()[i] 385 <li> if rowsense()[i] != 'R' then 386 rowrange()[i] is 0.0 387 </ul> 388 */ 389 virtual const double * getRowRange() const; 390 391 /// Get pointer to array[getNumRows()] of row lower bounds 392 virtual const double * getRowLower() const; 393 394 /// Get pointer to array[getNumRows()] of row upper bounds 395 virtual const double * getRowUpper() const; 396 397 /** Get objective function sense (1 for min (default), -1 for max) 398 * Always minimizes */ getObjSense() const399 virtual double getObjSense() const 400 { 401 return 1; 402 } 403 404 /// Return true if column is continuous 405 virtual bool isContinuous(int colNumber) const; 406 407 /// Return true if column is binary 408 virtual bool isBinary(int columnNumber) const; 409 410 /** Return true if column is integer. 411 Note: This function returns true if the the column 412 is binary or a general integer. 413 */ 414 virtual bool isInteger(int columnNumber) const; 415 416 /// Return true if column is general integer 417 virtual bool isIntegerNonBinary(int columnNumber) const; 418 419 /// Return true if column is binary and not fixed at either bound 420 virtual bool isFreeBinary(int columnNumber) const; 421 422 /// Get solver's value for infinity 423 virtual double getInfinity() const; 424 425 ///Get priorities on integer variables. getPriorities() const426 const int * getPriorities() const 427 { 428 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo(); 429 if(branch) 430 return branch->priorities; 431 else return NULL; 432 } 433 ///get prefered branching directions getBranchingDirections() const434 const int * getBranchingDirections() const 435 { 436 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo(); 437 if(branch) 438 return branch->branchingDirections; 439 else return NULL; 440 } getUpPsCosts() const441 const double * getUpPsCosts() const 442 { 443 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo(); 444 if(branch) 445 return branch->upPsCosts; 446 else return NULL; 447 } getDownPsCosts() const448 const double * getDownPsCosts() const 449 { 450 const TMINLP::BranchingInfo * branch = tminlp_->branchingInfo(); 451 if(branch) 452 return branch->downPsCosts; 453 else return NULL; 454 } 455 456 457 //@} 458 459 /**@name Methods related to querying the solution */ 460 //@{ 461 /// Get pointer to array[getNumCols()] of primal solution vector 462 virtual const double * getColSolution() const; 463 464 /// Get pointer to array[getNumRows()] of dual prices 465 virtual const double * getRowPrice() const; 466 467 /// Get a pointer to array[getNumCols()] of reduced costs 468 virtual const double * getReducedCost() const; 469 470 /** Get pointer to array[getNumRows()] of row activity levels (constraint 471 matrix times the solution vector */ 472 virtual const double * getRowActivity() const; 473 474 475 /** Get how many iterations it took to solve the problem (whatever 476 "iteration" mean to the solver. 477 * \todo Figure out what it could mean for Ipopt. 478 */ 479 virtual int getIterationCount() const; 480 481 /** get total number of calls to solve.*/ nCallOptimizeTNLP()482 int nCallOptimizeTNLP() 483 { 484 return nCallOptimizeTNLP_; 485 } 486 /** get total time taken to solve NLP's. */ totalNlpSolveTime()487 double totalNlpSolveTime() 488 { 489 return totalNlpSolveTime_; 490 } 491 /** get total number of iterations */ totalIterations()492 int totalIterations() 493 { 494 return totalIterations_; 495 } 496 497 498 //@} 499 //------------------------------------------------------------------------- 500 /**@name Methods to modify the objective, bounds, and solution 501 */ 502 //@{ 503 504 /** Set a single column lower bound. 505 Use -getInfinity() for -infinity. */ 506 virtual void setColLower( int elementIndex, double elementValue ); 507 508 /** Set a single column upper bound. 509 Use getInfinity() for infinity. */ 510 virtual void setColUpper( int elementIndex, double elementValue ); 511 512 /** Set the lower bounds for all columns 513 array [getNumCols()] is an array of values for the objective. 514 */ 515 virtual void setColLower(const double * array); 516 517 /** Set the upper bounds for all columns 518 array [getNumCols()] is an array of values for the objective. 519 */ 520 virtual void setColUpper(const double * array); 521 522 523 /** Set a single row lower bound. 524 Use -getInfinity() for -infinity. */ 525 virtual void setRowLower( int elementIndex, double elementValue ); 526 527 /** Set a single row upper bound. 528 Use getInfinity() for infinity. */ 529 virtual void setRowUpper( int elementIndex, double elementValue ); 530 531 /** Set the type of a single row */ 532 virtual void setRowType(int index, char sense, double rightHandSide, 533 double range); 534 535 536 /** \brief Set the objective function sense (disabled). 537 * (1 for min (default), -1 for max) 538 \todo Make it work. 539 \bug Can not treat maximisation problems. */ 540 virtual void setObjSense(double s); 541 542 /** Set the primal solution variable values 543 Set the values for the starting point. 544 \warning getColSolution will never return this vector (unless it is optimal). 545 */ 546 virtual void setColSolution(const double *colsol); 547 548 /** Set dual solution variable values. 549 set the values for the starting point. 550 \warning getRowPrice will never return this vector (unless it is optimal). 551 */ 552 virtual void setRowPrice(const double * rowprice); 553 554 //@} 555 556 557 //--------------------------------------------------------------------------- 558 /**@name WarmStart related methods (those should really do nothing for the moment)*/ 559 //@{ 560 561 /*! \brief Get an empty warm start object 562 563 This routine returns an empty CoinWarmStartBasis object. Its purpose is 564 to provide a way to give a client a warm start basis object of the 565 appropriate type, which can resized and modified as desired. 566 */ 567 virtual CoinWarmStart *getEmptyWarmStart () const; 568 569 /** Get warmstarting information */ 570 virtual CoinWarmStart* getWarmStart() const; 571 572 /** Set warmstarting information. Return true/false depending on whether 573 the warmstart information was accepted or not. */ 574 virtual bool setWarmStart(const CoinWarmStart* warmstart); 575 setWarmStartMode(int mode)576 void setWarmStartMode(int mode) { 577 warmStartMode_ = (WarmStartModes) mode; 578 } getWarmStartMode()579 WarmStartModes getWarmStartMode() { 580 return warmStartMode_; 581 } 582 583 void randomStartingPoint(); 584 585 //Returns true if a basis is available basisIsAvailable() const586 virtual bool basisIsAvailable() const 587 { 588 // Throw an exception 589 throw SimpleError("Needs coding for this interface", "basisIsAvailable"); 590 } 591 592 593 //@} 594 595 //------------------------------------------------------------------------- 596 /**@name Methods to set variable type */ 597 //@{ 598 /** Set the index-th variable to be a continuous variable */ 599 virtual void setContinuous(int index); 600 /** Set the index-th variable to be an integer variable */ 601 virtual void setInteger(int index); 602 //@} 603 604 //Set numIterationSuspect_ setNumIterationSuspect(int value)605 void setNumIterationSuspect(int value) 606 { 607 numIterationSuspect_ = value; 608 } 609 610 /**@name Dummy functions 611 * Functions which have to be implemented in an OsiSolverInterface, 612 * but which do not do anything (but throwing exceptions) here in the case of a 613 * minlp solved using an nlp solver for continuous relaxations */ 614 //@{ 615 616 /** Cbc will understand that no matrix exsits if return -1 617 */ getNumElements() const618 virtual int getNumElements() const 619 { 620 return -1; 621 } 622 623 624 /** This returns the objective function gradient at the current 625 * point. It seems to be required for Cbc's pseudo cost 626 * initialization 627 */ 628 virtual const double * getObjCoefficients() const; 629 630 /** We have to keep this but it will return NULL. 631 */ getMatrixByRow() const632 virtual const CoinPackedMatrix * getMatrixByRow() const 633 { 634 return NULL; 635 } 636 637 638 /** We have to keep this but it will return NULL. 639 */ getMatrixByCol() const640 virtual const CoinPackedMatrix * getMatrixByCol() const 641 { 642 return NULL; 643 } 644 645 /** We have to keep this but it will throw an error. 646 */ setObjCoeff(int elementIndex,double elementValue)647 virtual void setObjCoeff( int elementIndex, double elementValue ) 648 { 649 throw SimpleError("OsiTMINLPInterface does not implement this function.", 650 "setObjCoeff"); 651 } 652 653 /** We have to keep this but it will throw an error. 654 */ addCol(const CoinPackedVectorBase & vec,const double collb,const double colub,const double obj)655 virtual void addCol(const CoinPackedVectorBase& vec, 656 const double collb, const double colub, 657 const double obj) 658 { 659 throw SimpleError("OsiTMINLPInterface does not implement this function.", 660 "addCol"); 661 } 662 /** We have to keep this but it will throw an error. 663 */ deleteCols(const int num,const int * colIndices)664 virtual void deleteCols(const int num, const int * colIndices) 665 { 666 throw SimpleError("OsiTMINLPInterface does not implement this function.", 667 "deleteCols"); 668 } 669 670 /** We have to keep this but it will throw an error. 671 */ addRow(const CoinPackedVectorBase & vec,const double rowlb,const double rowub)672 virtual void addRow(const CoinPackedVectorBase& vec, 673 const double rowlb, const double rowub) 674 { 675 throw SimpleError("OsiTMINLPInterface does not implement this function.", 676 "addRow"); 677 } 678 /** We have to keep this but it will throw an error. 679 */ addRow(const CoinPackedVectorBase & vec,const char rowsen,const double rowrhs,const double rowrng)680 virtual void addRow(const CoinPackedVectorBase& vec, 681 const char rowsen, const double rowrhs, 682 const double rowrng) 683 { 684 throw SimpleError("OsiTMINLPInterface model does not implement this function.", 685 "addRow"); 686 } 687 /** We have to keep this but it will throw an error. 688 */ deleteRows(const int num,const int * rowIndices)689 virtual void deleteRows(const int num, const int * rowIndices) 690 { 691 if(num) 692 freeCachedRowRim(); 693 problem_->removeCuts(num, rowIndices); 694 } 695 696 697 /** We have to keep this but it will throw an error 698 */ loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)699 virtual void loadProblem(const CoinPackedMatrix& matrix, 700 const double* collb, const double* colub, 701 const double* obj, 702 const double* rowlb, const double* rowub) 703 { 704 throw SimpleError("OsiTMINLPInterface does not implement this function.", 705 "loadProblem"); 706 } 707 708 709 /** We have to keep this but it will throw an error. 710 */ assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,double * & rowlb,double * & rowub)711 virtual void assignProblem(CoinPackedMatrix*& matrix, 712 double*& collb, double*& colub, double*& obj, 713 double*& rowlb, double*& rowub) 714 { 715 throw SimpleError("OsiTMINLPInterface does not implement this function.", 716 "assignProblem"); 717 } 718 719 /** We have to keep this but it will throw an error. 720 */ loadProblem(const CoinPackedMatrix & matrix,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)721 virtual void loadProblem(const CoinPackedMatrix& matrix, 722 const double* collb, const double* colub, 723 const double* obj, 724 const char* rowsen, const double* rowrhs, 725 const double* rowrng) 726 { 727 throw SimpleError("OsiTMINLPInterface does not implement this function.", 728 "loadProblem"); 729 } 730 731 /** We have to keep this but it will throw an error. 732 */ assignProblem(CoinPackedMatrix * & matrix,double * & collb,double * & colub,double * & obj,char * & rowsen,double * & rowrhs,double * & rowrng)733 virtual void assignProblem(CoinPackedMatrix*& matrix, 734 double*& collb, double*& colub, double*& obj, 735 char*& rowsen, double*& rowrhs, 736 double*& rowrng) 737 { 738 throw SimpleError("OsiTMINLPInterface does not implement this function.", 739 "assignProblem"); 740 } 741 742 743 /** We have to keep this but it will throw an error. 744 */ loadProblem(const int numcols,const int numrows,const int * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const double * rowlb,const double * rowub)745 virtual void loadProblem(const int numcols, const int numrows, 746 const int* start, const int* index, 747 const double* value, 748 const double* collb, const double* colub, 749 const double* obj, 750 const double* rowlb, const double* rowub) 751 { 752 throw SimpleError("OsiTMINLPInterface does not implement this function.", 753 "loadProblem"); 754 } 755 756 /** We have to keep this but it will throw an error. 757 */ loadProblem(const int numcols,const int numrows,const int * start,const int * index,const double * value,const double * collb,const double * colub,const double * obj,const char * rowsen,const double * rowrhs,const double * rowrng)758 virtual void loadProblem(const int numcols, const int numrows, 759 const int* start, const int* index, 760 const double* value, 761 const double* collb, const double* colub, 762 const double* obj, 763 const char* rowsen, const double* rowrhs, 764 const double* rowrng) 765 { 766 throw SimpleError("OsiTMINLPInterface model does not implement this function.", 767 "loadProblem"); 768 } 769 770 /** We have to keep this but it will throw an error. 771 */ readMps(const char * filename,const char * extension="mps")772 virtual int readMps(const char *filename, 773 const char *extension = "mps") 774 { 775 throw SimpleError("OsiTMINLPInterface does not implement this function.", 776 "readMps"); 777 } 778 779 780 /** We have to keep this but it will throw an error. 781 */ writeMps(const char * filename,const char * extension="mps",double objSense=0.0) const782 virtual void writeMps(const char *filename, 783 const char *extension = "mps", 784 double objSense=0.0) const 785 { 786 throw SimpleError("OsiTMINLPInterface does not implement this function.", 787 "writeMps"); 788 } 789 790 /** Throws an error */ getDualRays(int maxNumRays,bool fullRay=false) const791 virtual std::vector<double*> getDualRays(int maxNumRays, bool fullRay = false) const 792 { 793 throw SimpleError("OsiTMINLPInterface does not implement this function.", 794 "getDualRays"); 795 } 796 797 /** Throws an error */ getPrimalRays(int maxNumRays) const798 virtual std::vector<double*> getPrimalRays(int maxNumRays) const 799 { 800 throw SimpleError("OsiTMINLPInterface does not implement this function.", 801 "getPrimalRays"); 802 } 803 804 //@} 805 806 807 808 //--------------------------------------------------------------------------- 809 810 811 812 /**@name Control of Ipopt output 813 */ 814 //@{ setSolverOutputToDefault()815 void setSolverOutputToDefault(){ 816 app_->setOutputToDefault();} forceSolverOutput(int log_level)817 void forceSolverOutput(int log_level){ 818 app_->forceSolverOutput(log_level);} 819 //@} 820 821 /**@name Sets and Getss */ 822 //@{ 823 /// Get objective function value (can't use default) 824 virtual double getObjValue() const; 825 826 //@} 827 828 /** get pointer to the TMINLP2TNLP adapter */ problem() const829 const TMINLP2TNLP * problem() const 830 { 831 return GetRawPtr(problem_); 832 } 833 problem()834 TMINLP2TNLP * problem() 835 { 836 return GetRawPtr(problem_); 837 } 838 model() const839 const TMINLP * model() const 840 { 841 return GetRawPtr(tminlp_); 842 } 843 model()844 Bonmin::TMINLP * model() 845 { 846 return GetRawPtr(tminlp_); 847 } 848 solver() const849 const Bonmin::TNLPSolver * solver() const 850 { 851 return GetRawPtr(app_); 852 } 853 debug_apps() const854 const std::list<Ipopt::SmartPtr<TNLPSolver> >& debug_apps() const{ 855 return debug_apps_; 856 } 857 solver()858 TNLPSolver * solver() 859 { 860 return GetRawPtr(app_); 861 } 862 /** \name Methods to build outer approximations */ 863 //@{ 864 /** \name Methods to build outer approximations */ 865 //@{ 866 /** \brief Extract a linear relaxation of the MINLP. 867 * Use user-provided point to build first-order outer-approximation constraints at the optimum. 868 * And put it in an OsiSolverInterface. 869 */ 870 virtual void extractLinearRelaxation(OsiSolverInterface &si, const double *x, 871 bool getObj = 1); 872 873 /** Add constraint corresponding to objective function.*/ 874 virtual void addObjectiveFunction(OsiSolverInterface &si, const double * x); 875 #if 1 876 /** \brief Extract a linear relaxation of the MINLP. 877 * Solve the continuous relaxation and takes first-order outer-approximation constraints at the optimum. 878 * The put everything in an OsiSolverInterface. 879 */ extractLinearRelaxation(OsiSolverInterface & si,bool getObj=1,bool solveNlp=1)880 virtual void extractLinearRelaxation(OsiSolverInterface &si, bool getObj = 1, 881 bool solveNlp = 1){ 882 if(solveNlp) 883 initialSolve("build initial OA"); 884 extractLinearRelaxation(si, getColSolution(), getObj); 885 if(solveNlp){ 886 app_->enableWarmStart(); 887 setColSolution(problem()->x_sol()); 888 setRowPrice(problem()->duals_sol()); 889 } 890 } 891 #endif 892 /** Get the outer approximation constraints at the current optimal point. 893 If x2 is different from NULL only add cuts violated by x2. 894 (Only get outer-approximations of nonlinear constraints of the problem.)*/ getOuterApproximation(OsiCuts & cs,int getObj,const double * x2,bool global)895 void getOuterApproximation(OsiCuts &cs, int getObj, const double * x2, bool global) 896 { 897 getOuterApproximation(cs, getColSolution(), getObj, x2, global); 898 } 899 900 /** Get the outer approximation constraints at provided point. 901 If x2 is different from NULL only add cuts violated by x2. 902 (Only get outer-approximations of nonlinear constraints of the problem.)*/ getOuterApproximation(OsiCuts & cs,const double * x,int getObj,const double * x2,bool global)903 void getOuterApproximation(OsiCuts &cs, const double * x, int getObj, const double * x2, bool global){ 904 getOuterApproximation(cs, x, getObj, x2, 0., global);} 905 906 /** Get the outer approximation constraints at provided point. 907 If x2 is different from NULL only add cuts violated by x2 by more than delta. 908 (Only get outer-approximations of nonlinear constraints of the problem.)*/ 909 virtual void getOuterApproximation(OsiCuts &cs, const double * x, int getObj, const double * x2, 910 double theta, bool global); 911 912 /** Get the outer approximation at provided point for given constraint. */ 913 virtual void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber, 914 const double * x, 915 const double * x2, bool global); 916 917 /** Get the outer approximation at current optimal point for given constraint. */ getConstraintOuterApproximation(OsiCuts & cs,int constraintNumber,const double * x2,bool global)918 void getConstraintOuterApproximation(OsiCuts & cs, int constraintNumber, 919 const double * x2, bool global){ 920 getConstraintOuterApproximation(cs, constraintNumber, getColSolution(),x2,global); 921 } 922 923 924 /** Get a benders cut from solution.*/ 925 void getBendersCut(OsiCuts &cs, bool global); 926 927 /** Given a point x_bar this solves the problem of finding the point which minimize a convex 928 *combination between the distance to x_bar and the original objective function f(x): 929 * \f$ min a * (\sum\limits_{i=1}^n ||x_{ind[i]} -\overline{x}_i)||_L) + (1 - a)* s *f(x) \f$ 930 * \return Distance between feasibility set a x_bar on components in ind 931 * \param n number of elements in array x_bar and ind 932 * \param s scaling of the original objective. 933 * \param a Combination to take between feasibility and original objective (must be between 0 and 1). 934 * \param L L-norm to use (can be either 1 or 2). 935 */ 936 double solveFeasibilityProblem(size_t n, const double * x_bar, const int* ind, double a, double s, int L); 937 938 /** Given a point x_bar this solves the problem of finding the point which minimize 939 * the distance to x_bar while satisfying the additional cutoff constraint: 940 * \f$ min \sum\limits_{i=1}^n ||x_{ind[i]} -\overline{x}_i)||_L$ 941 * \return Distance between feasibility set a x_bar on components in ind 942 * \param n number of elements in array x_bar and ind 943 * \param L L-norm to use (can be either 1 or 2). 944 * \param cutoff objective function value of a known integer feasible solution 945 */ 946 double solveFeasibilityProblem(size_t n, const double * x_bar, const int* ind, int L, double cutoff); 947 948 /** Given a point x_bar setup feasibility problem and switch so that every call to initialSolve or resolve will 949 solve it.*/ 950 void switchToFeasibilityProblem(size_t n, const double * x_bar, const int* ind, double a, double s, int L); 951 952 /** Given a point x_bar setup feasibility problem and switch so that every call to initialSolve or resolve will 953 solve it. This is to be used in the local branching heuristic */ 954 void switchToFeasibilityProblem(size_t n, const double * x_bar, const int* ind, 955 double rhs_local_branching_constraint); 956 957 /** switch back to solving original problem.*/ 958 void switchToOriginalProblem(); 959 960 /** round solution and check its feasibility.*/ round_and_check(double tolerance,OsiObject ** objects=0,int nObjects=-1)961 void round_and_check(double tolerance, 962 OsiObject ** objects = 0, int nObjects = -1){ 963 if(!problem_->check_solution(objects, nObjects)){ 964 optimizationStatus_ = TNLPSolver::provenInfeasible; 965 } 966 } 967 //@} 968 969 /** \name output for OA cut generation 970 \todo All OA code here should be moved to a separate class sometime.*/ 971 //@{ 972 /** OA Messages types.*/ 973 enum OaMessagesTypes { 974 CUT_NOT_VIOLATED_ENOUGH = 0/** Says that one cut has been generarted, where from, which is the violation.*/, 975 VIOLATED_OA_CUT_GENERATED/** Cut is not violated enough, give violation.*/, 976 OA_CUT_GENERATED/** Print the cut which has been generated.*/, 977 OA_MESSAGES_DUMMY_END/** Dummy end.*/}; 978 /** Class to store OA Messages.*/ 979 class OaMessages :public CoinMessages{ 980 public: 981 /** Default constructor.*/ 982 OaMessages(); 983 }; 984 /** Like a CoinMessageHandler but can print a cut also.*/ 985 class OaMessageHandler : public CoinMessageHandler{ 986 public: 987 /** Default constructor.*/ OaMessageHandler()988 OaMessageHandler():CoinMessageHandler(){ 989 } 990 /** Constructor to put to file pointer (fp won't be closed).*/ OaMessageHandler(FILE * fp)991 OaMessageHandler(FILE * fp):CoinMessageHandler(fp){ 992 } 993 /** Destructor.*/ ~OaMessageHandler()994 virtual ~OaMessageHandler(){ 995 } 996 /** Copy constructor.*/ OaMessageHandler(const OaMessageHandler & other)997 OaMessageHandler(const OaMessageHandler &other): 998 CoinMessageHandler(other){} 999 /** Constructor from a regular CoinMessageHandler.*/ OaMessageHandler(const CoinMessageHandler & other)1000 OaMessageHandler(const CoinMessageHandler &other): 1001 CoinMessageHandler(other){} 1002 /** Assignment operator.*/ operator =(const OaMessageHandler & rhs)1003 OaMessageHandler & operator=(const OaMessageHandler &rhs){ 1004 CoinMessageHandler::operator=(rhs); 1005 return *this;} 1006 /** Virtual copy */ clone() const1007 virtual CoinMessageHandler* clone() const{ 1008 return new OaMessageHandler(*this);} 1009 /** print an OsiRowCut.*/ 1010 void print(OsiRowCut &row); 1011 }; setOaMessageHandler(const CoinMessageHandler & handler)1012 void setOaMessageHandler(const CoinMessageHandler &handler){ 1013 delete oaHandler_; 1014 oaHandler_ = new OaMessageHandler(handler); 1015 } 1016 //@} 1017 1018 //----------------------------------------------------------------------- 1019 /** Apply a collection of cuts. 1020 */ applyCuts(const OsiCuts & cs,double effectivenessLb=0.0)1021 virtual ApplyCutsReturnCode applyCuts(const OsiCuts & cs, 1022 double effectivenessLb = 0.0){ 1023 freeCachedRowRim(); 1024 problem_->addCuts(cs); 1025 ApplyCutsReturnCode rc; 1026 return rc;} 1027 1028 /** Add a collection of linear cuts to problem formulation.*/ 1029 virtual void applyRowCuts(int numberCuts, const OsiRowCut * cuts); 1030 1031 1032 /** Add a collection of linear cuts to the problem formulation */ applyRowCuts(int numberCuts,const OsiRowCut ** cuts)1033 virtual void applyRowCuts(int numberCuts, const OsiRowCut ** cuts) 1034 { 1035 if(numberCuts) 1036 freeCachedRowRim(); 1037 problem_->addCuts(numberCuts, cuts); 1038 } 1039 1040 /** Get infinity norm of constraint violation for x. Put into 1041 obj the objective value of x.*/ 1042 double getConstraintsViolation(const double * x, double & obj); 1043 1044 /** Get infinity norm of constraint violation for x and error in objective 1045 value where obj is the estimated objective value of x.*/ 1046 double getNonLinearitiesViolation(const double *x, const double obj); 1047 1048 //--------------------------------------------------------------------------- 1049 1050 void extractInterfaceParams(); 1051 1052 1053 /** To set some application specific defaults. */ 1054 virtual void setAppDefaultOptions(Ipopt::SmartPtr<Ipopt::OptionsList> Options); 1055 1056 /** Register all possible options to Bonmin */ 1057 static void registerOptions (Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions); 1058 regOptions()1059 Ipopt::SmartPtr<Bonmin::RegisteredOptions> regOptions(){ 1060 if(IsValid(app_)) 1061 return app_->roptions(); 1062 else 1063 return NULL; 1064 } 1065 1066 /** @name Methods related to strong branching */ 1067 //@{ 1068 /// Set the strong branching solver 1069 void SetStrongBrachingSolver(Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver); 1070 /// Create a hot start snapshot of the optimization process. In our 1071 /// case, we initialize the StrongBrachingSolver. 1072 virtual void markHotStart(); 1073 /// Optimize starting from the hot start snapshot. In our case, we 1074 /// call the StrongBranchingSolver to give us an approximate 1075 /// solution for the current state of the bounds 1076 virtual void solveFromHotStart(); 1077 /// Delete the hot start snapshot. In our case we deactivate the 1078 /// StrongBrachingSolver. 1079 virtual void unmarkHotStart(); 1080 //@} 1081 1082 /// Get values of tiny_ and very_tiny_ get_tolerances(double & tiny,double & very_tiny,double & rhsRelax,double & infty)1083 void get_tolerances(double &tiny, double&very_tiny, double &rhsRelax, double &infty){ 1084 tiny = tiny_; 1085 very_tiny = veryTiny_; 1086 rhsRelax = rhsRelax_; 1087 infty = infty_; 1088 } 1089 1090 void set_linearizer(Ipopt::SmartPtr<TMINLP2OsiLP> linearizer); 1091 1092 Ipopt::SmartPtr<TMINLP2OsiLP> linearizer(); 1093 protected: 1094 1095 //@} 1096 1097 enum RandomGenerationType{ 1098 uniform =0, perturb=1, perturb_suffix=2}; 1099 /// Initialize data structures for storing the jacobian 1100 int initializeJacobianArrays(); 1101 1102 ///@name Virtual callbacks for application specific stuff 1103 //@{ appName()1104 virtual std::string appName() 1105 { 1106 return "bonmin"; 1107 } 1108 //@} 1109 ///@name Protected methods 1110 //@{ 1111 1112 /** Call Ipopt to solve or resolve the problem and check for errors.*/ 1113 void solveAndCheckErrors(bool doResolve, bool throwOnFailure, 1114 const char * whereFrom); 1115 1116 1117 /** Add a linear cut to the problem formulation. 1118 */ applyRowCut(const OsiRowCut & rc)1119 virtual void applyRowCut( const OsiRowCut & rc ) 1120 { 1121 const OsiRowCut * cut = &rc; 1122 problem_->addCuts(1, &cut); 1123 } 1124 /** We have to keep this but it will throw an error. 1125 */ applyColCut(const OsiColCut & cc)1126 virtual void applyColCut( const OsiColCut & cc ) 1127 { 1128 throw SimpleError("Ipopt model does not implement this function.", 1129 "applyColCut"); 1130 } 1131 1132 // /** Read the name of the variables in an ampl .col file. */ 1133 // void readVarNames() const; 1134 1135 //@} 1136 1137 /**@name Model and solver */ 1138 //@{ 1139 /** TMINLP model.*/ 1140 Ipopt::SmartPtr<TMINLP> tminlp_; 1141 /** Adapter for a MINLP to a NLP */ 1142 Ipopt::SmartPtr<TMINLP2TNLP> problem_; 1143 /** Problem currently optimized (may be problem_ or feasibilityProblem_)*/ 1144 Ipopt::SmartPtr<Ipopt::TNLP> problem_to_optimize_; 1145 /** Is true if and only if in feasibility mode.*/ 1146 bool feasibility_mode_; 1147 /** Solver for a TMINLP. */ 1148 Ipopt::SmartPtr<TNLPSolver> app_; 1149 1150 /** Alternate solvers for TMINLP.*/ 1151 std::list<Ipopt::SmartPtr<TNLPSolver> > debug_apps_; 1152 /** Do we use the other solvers?*/ 1153 bool testOthers_; 1154 //@} 1155 1156 /** Warmstart information for reoptimization */ 1157 CoinWarmStart* warmstart_; 1158 1159 /**@name Cached information on the problem */ 1160 //@{ 1161 /** Free cached data relative to variables */ 1162 void freeCachedColRim(); 1163 /** Free cached data relative to constraints */ 1164 void freeCachedRowRim(); 1165 /** Free all cached data*/ 1166 void freeCachedData(); 1167 /** Extract rowsense_ vector rhs_ vector and rowrange_ vector from the lower and upper bounds 1168 * on the constraints */ 1169 void extractSenseRhsAndRange() const; 1170 /// Pointer to dense vector of row sense indicators 1171 mutable char *rowsense_; 1172 1173 /// Pointer to dense vector of row right-hand side values 1174 mutable double *rhs_; 1175 1176 /// Pointer to dense vector of slack upper bounds for range constraints (undefined for non-range rows) 1177 mutable double *rowrange_; 1178 /** Pointer to dense vector of reduced costs 1179 \warning Always 0. with Ipopt*/ 1180 mutable double *reducedCosts_; 1181 /** DualObjectiveLimit is used to store the cutoff in Cbc*/ 1182 double OsiDualObjectiveLimit_; 1183 /** does the file variable names exists (will check automatically).*/ 1184 mutable bool hasVarNamesFile_; 1185 //@} 1186 /// number of time NLP has been solved 1187 int nCallOptimizeTNLP_; 1188 /// Total solution time of NLP 1189 double totalNlpSolveTime_; 1190 /// toatal number of iterations 1191 int totalIterations_; 1192 /// max radius for random point 1193 double maxRandomRadius_; 1194 /// Method to pick a random starting point. 1195 int randomGenerationType_; 1196 /// Maximum perturbation value 1197 double max_perturbation_; 1198 /// Ipopt value for pushing initial point inside the bounds 1199 double pushValue_; 1200 /// Number of times problem will be resolved in initialSolve (root node) 1201 int numRetryInitial_; 1202 /// Number of times problem will be resolved in resolve 1203 int numRetryResolve_; 1204 /// Number of times infeasible problem will be resolved. 1205 int numRetryInfeasibles_; 1206 /// Number of times problem will be resolved in case of a failure 1207 int numRetryUnsolved_; 1208 /// If infeasibility for a problem is less than this, let's be carrefull. It might be feasible 1209 double infeasibility_epsilon_; 1210 1211 1212 //Added by Claudia 1213 /// Dynamic cutOff_ 1214 int dynamicCutOff_; 1215 /// coeff_var_threshold_ 1216 double coeff_var_threshold_; 1217 /// first_perc_for_cutoff_decr_ 1218 double first_perc_for_cutoff_decr_; 1219 /// second_perc_for_cutoff_decr_ 1220 double second_perc_for_cutoff_decr_; 1221 1222 1223 /** Messages specific to an OsiTMINLPInterface. */ 1224 Messages messages_; 1225 /** If not 0 when a problem is not solved (failed to be solved) 1226 will pretend that it is infeasible. If == 1 will care 1227 (i.e. record the fact issue messages to user), if ==2 don't care (somebody else will) */ 1228 int pretendFailIsInfeasible_; 1229 1230 mutable int pretendSucceededNext_; 1231 1232 /** did we ever continue optimization ignoring a failure. */ 1233 bool hasContinuedAfterNlpFailure_; 1234 /** number iterations above which a problem is considered suspect (-1 is considered \f$+ \infty \f$). 1235 If in a call to solve a problem takes more than that number of iterations it will be output to files.*/ 1236 int numIterationSuspect_ ; 1237 /** Has problem been optimized since last change (include setColSolution). 1238 If yes getColSolution will return Ipopt point, otherwise will return 1239 initial point.*/ 1240 bool hasBeenOptimized_; 1241 /** A fake objective function (all variables to 1) to please Cbc 1242 pseudo costs initialization. AW: I changed this, it will now be 1243 the objective gradient at current point. */ 1244 mutable double * obj_; 1245 /** flag to say wether options have been printed or not.*/ 1246 static bool hasPrintedOptions; 1247 1248 /** Adapter for TNLP to a feasibility problem */ 1249 Ipopt::SmartPtr<TNLP2FPNLP> feasibilityProblem_; 1250 1251 /** Adapter for TMINLP to an Osi LP */ 1252 Ipopt::SmartPtr<TMINLP2OsiLP> linearizer_; 1253 1254 /** \name Arrays to store Jacobian matrix */ 1255 //@{ 1256 /** Row indices.*/ 1257 int * jRow_; 1258 /** Column indices.*/ 1259 int * jCol_; 1260 /** Values */ 1261 double * jValues_; 1262 /** Number of elements.*/ 1263 int nnz_jac; 1264 //@} 1265 1266 ///Store the types of the constraints (linear and nonlinear). 1267 Ipopt::TNLP::LinearityType * constTypes_; 1268 /** Number of nonlinear constraint 1269 */ 1270 int nNonLinear_; 1271 /** Value for small non-zero element which we will try to remove cleanly in OA cuts.*/ 1272 double tiny_; 1273 /** Value for small non-zero element which we will take the risk to ignore in OA cuts.*/ 1274 double veryTiny_; 1275 /** Amount by which to relax OA constraints RHSes*/ 1276 double rhsRelax_; 1277 /** Value for infinity. */ 1278 double infty_; 1279 /** status of last optimization. */ 1280 TNLPSolver::ReturnStatus optimizationStatus_; 1281 /** Flag indicating if the warm start methods actually do something.*/ 1282 WarmStartModes warmStartMode_; 1283 /** Is it the first solve (for random starting point at root options).*/ 1284 bool firstSolve_; 1285 /** Object for strengthening cuts */ 1286 Ipopt::SmartPtr<CutStrengthener> cutStrengthener_; 1287 1288 /** \name output for OA cut generation 1289 \todo All OA code here should be moved to a separate class sometime.*/ 1290 //@{ 1291 /** OA Messages.*/ 1292 OaMessages oaMessages_; 1293 /** OA Message handler. */ 1294 OaMessageHandler * oaHandler_; 1295 //@} 1296 1297 double newCutoffDecr; 1298 protected: 1299 /** Facilitator to create an application. */ 1300 void createApplication(Ipopt::SmartPtr<Bonmin::RegisteredOptions> roptions, 1301 Ipopt::SmartPtr<Ipopt::OptionsList> options, 1302 Ipopt::SmartPtr<Ipopt::Journalist> journalist, 1303 const std::string & prefix); 1304 ///Constructor without model only for derived classes 1305 OsiTMINLPInterface(Ipopt::SmartPtr<TNLPSolver> app); 1306 1307 /** Internal set warm start.*/ 1308 bool internal_setWarmStart(const CoinWarmStart* ws); 1309 1310 /** internal get warm start.*/ 1311 CoinWarmStart* internal_getWarmStart() const; 1312 1313 /** Procedure that builds a fake basis. Only tries to make basis consistent with constraints activity.*/ 1314 CoinWarmStart* build_fake_basis() const; 1315 private: 1316 1317 /** solver to be used for all strong branching solves */ 1318 Ipopt::SmartPtr<StrongBranchingSolver> strong_branching_solver_; 1319 /** status of last optimization before hot start was marked. */ 1320 TNLPSolver::ReturnStatus optimizationStatusBeforeHotStart_; 1321 static const char * OPT_SYMB; 1322 static const char * FAILED_SYMB; 1323 static const char * INFEAS_SYMB; 1324 static const char * TIME_SYMB; 1325 static const char * UNBOUND_SYMB; 1326 /** Get status as a char * for log.*/ statusAsString(TNLPSolver::ReturnStatus r)1327 const char * statusAsString(TNLPSolver::ReturnStatus r){ 1328 if(r == TNLPSolver::solvedOptimal || r == TNLPSolver::solvedOptimalTol){ 1329 return OPT_SYMB;} 1330 else if(r == TNLPSolver::provenInfeasible){ 1331 return INFEAS_SYMB;} 1332 else if(r == TNLPSolver::unbounded){ 1333 return UNBOUND_SYMB;} 1334 else if(r == TNLPSolver::timeLimit){ 1335 return TIME_SYMB;} 1336 else return FAILED_SYMB; 1337 } statusAsString()1338 const char * statusAsString(){ 1339 return statusAsString(optimizationStatus_);} 1340 }; 1341 } 1342 #endif 1343