17 #include "CbcCutGenerator.hpp"
20 #include "CoinHelperFunctions.hpp"
25 using namespace Ipopt;
26 using namespace Couenne;
28 NlpSolveHeuristic::NlpSolveHeuristic():
33 numberSolvePerLevel_(-1),
35 setHeuristicName(
"NlpSolveHeuristic");
39 CbcHeuristic(model), nlp_(&nlp), hasCloned_(cloneNlp),maxNlpInf_(
maxNlpInf_0),
40 numberSolvePerLevel_(-1),
42 setHeuristicName(
"NlpSolveHeuristic");
48 CbcHeuristic(other), nlp_(other.nlp_),
49 hasCloned_(other.hasCloned_),
50 maxNlpInf_(other.maxNlpInf_),
51 numberSolvePerLevel_(other.numberSolvePerLevel_),
52 couenne_(other.couenne_){
65 CbcHeuristic::operator=(rhs);
108 int noSolution = 1, maxTime = 2;
120 const int depth = (model_ -> currentNode ()) ? model_ -> currentNode () -> depth () : 0;
123 couenne_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"NLP Heuristic: "); fflush (stdout);
127 if (CoinCpuTime () >
couenne_ -> getMaxCpuTime ())
130 OsiSolverInterface * solver = model_ -> solver();
132 OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo();
144 bool too_deep =
false;
153 if (CoinDrand48 () > 1. / CoinMax
162 double *lower =
new double [
couenne_ -> nVars ()];
163 double *upper =
new double [
couenne_ -> nVars ()];
168 CoinCopyN (solver->getColLower(),
nlp_ -> getNumCols (), lower);
169 CoinCopyN (solver->getColUpper(),
nlp_ -> getNumCols (), upper);
176 const double *
solution = solver->getColSolution();
177 OsiBranchingInformation
info (solver,
true);
178 const int & numberObjects = model_->numberObjects();
179 OsiObject ** objects = model_->objects();
180 double maxInfeasibility = 0;
182 bool haveRoundedIntVars =
false;
184 for (
int i = 0 ; i < numberObjects ; i++) {
192 maxInfeasibility = CoinMax ( maxInfeasibility, infeas = couObj->
infeasibility(&info, dummy));
202 OsiSimpleInteger * intObj =
dynamic_cast<OsiSimpleInteger *
>(objects[i]);
205 const int & i = intObj -> columnNumber ();
207 double value = solution [i];
208 if (value < lower[i])
210 else if (value > upper[i])
213 double rounded = floor (value + 0.5);
216 haveRoundedIntVars =
true;
236 bool skipOnInfeasibility =
false;
238 double *Y =
new double [
couenne_ -> nVars ()];
239 CoinFillN (Y,
couenne_ -> nVars (), 0.);
240 CoinCopyN (solution,
nlp_ -> getNumCols (), Y);
249 if (haveRoundedIntVars)
250 skipOnInfeasibility = (
couenne_ -> getIntegerCandidate (solution, Y, lower, upper) < 0);
259 bool foundSolution =
false;
261 if (haveRoundedIntVars && skipOnInfeasibility)
264 for (
int i =
couenne_ -> nOrigVars (); i--;)
266 if (
couenne_ -> Var (i) -> isDefinedInteger ())
267 lower [i] = upper [i] = Y [i] =
268 (CoinDrand48 () < 0.5) ?
272 else if (lower [i] > upper [i]) {
277 double swap = lower [i];
278 lower [i] = upper [i];
293 double * saveColLower = CoinCopyOfArray (
nlp_ -> getColLower (),
nlp_ -> getNumCols ());
294 double * saveColUpper = CoinCopyOfArray (
nlp_ -> getColUpper (),
nlp_ -> getNumCols ());
296 for (
int i =
nlp_ -> getNumCols (); i--;) {
298 if (lower [i] > upper [i]) {
299 double swap = lower [i];
300 lower [i] = upper [i];
304 if (Y [i] < lower [i]) Y [i] = lower [i];
305 else if (Y [i] > upper [i]) Y [i] = upper [i];
308 nlp_ -> setColLower (lower);
309 nlp_ -> setColUpper (upper);
310 nlp_ -> setColSolution (Y);
314 nlp_ -> options () -> SetNumericValue (
"max_cpu_time", CoinMax (0.1,
couenne_ -> getMaxCpuTime () - CoinCpuTime ()));
315 nlp_ -> initialSolve ();
319 double obj = (
nlp_ -> isProvenOptimal()) ?
nlp_ -> getObjValue (): COIN_DBL_MAX;
321 if (
nlp_ -> isProvenOptimal () &&
322 couenne_ -> checkNLP (
nlp_ -> getColSolution (), obj,
true) &&
328 double* tmpSolution =
new double [nVars];
329 CoinCopyN (
nlp_ -> getColSolution(),
nlp_ -> getNumCols(), tmpSolution);
343 #ifdef FM_USE_REL_VIOL_CONS
344 printf(
"NlpSolveHeuristic::solution(): ### ERROR: checkNLP(): returns true, checkNLP2() returns false\n");
360 if (obj < objectiveValue) {
363 *lb = solver -> getColLower (),
364 *ub = solver -> getColUpper ();
368 for (
int i=0; i < nVars; i++, lb++, ub++) {
371 if (t < *lb) t = *lb;
372 else if (t > *ub) t = *ub;
377 foundSolution =
true;
378 objectiveValue = obj;
379 CoinCopyN (tmpSolution, nVars, newSolution);
381 delete [] tmpSolution;
384 nlp_ -> setColLower (saveColLower);
385 nlp_ -> setColUpper (saveColUpper);
387 delete [] saveColLower;
388 delete [] saveColUpper;
398 if (foundSolution)
couenne_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"solution found, obj. %g\n", objectiveValue);
402 return foundSolution;
410 if (e==noSolution) {
if (depth <= 0)
couenne_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"no solution.\n");
return 0;}
411 else if (e==maxTime) {
if (depth <= 0)
couenne_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"time limit reached.\n");
return 0;}
412 else {
if (depth <= 0)
couenne_ -> Jnlst () -> Printf (J_ERROR,
J_COUENNE,
"solution found, obj. %g\n", objectiveValue);
return 1;}
434 roptions -> AddStringOption2
435 (
"local_optimization_heuristic",
436 "Search for local solutions of MINLPs",
440 "If enabled, a heuristic based on Ipopt is used to find feasible solutions for the problem. "
441 "It is highly recommended that this option is left enabled, as it would be difficult to find feasible solutions otherwise.");
443 roptions -> AddLowerBoundedIntegerOption
444 (
"log_num_local_optimization_per_level",
445 "Specify the logarithm of the number of local optimizations to perform"
446 " on average for each level of given depth of the tree.",
448 2,
"Solve as many nlp's at the nodes for each level of the tree. "
449 "Nodes are randomly selected. If for a "
450 "given level there are less nodes than this number nlp are solved for every nodes. "
451 "For example if parameter is 8, nlp's are solved for all node until level 8, "
452 "then for half the node at level 9, 1/4 at level 10.... "
453 "Value -1 specify to perform at all nodes.");
void setCouenneProblem(CouenneProblem *)
set the couenne problem to use.
NlpSolveHeuristic()
Default constructor.
void update(const double *givenSol, const int givenCard, const double givenVal, const double givenMaxViol)
void fint fint fint real fint real real real real real real real real real fint real fint fint fint real fint fint fint fint * info
OsiObject for auxiliary variables $w=f(x)$.
void setNlp(Bonmin::OsiTMINLPInterface &nlp, bool cloneNlp=true)
Set the nlp solver.
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
virtual int solution(double &objectiveValue, double *newSolution)
Run heuristic, return 1 if a better solution than the one passed is found and 0 otherwise.
OsiSolverInterface * clone(bool copyData=true) const
Virtual copy constructor.
bool checkNLP2(const double *solution, const double obj, const bool careAboutObj, const bool stopAtFirstViol, const bool checkAll, const double precision) const
Return true if either solution or recomputed_solution obtained using getAuxs() from the original vari...
const double maxNlpInf_0
A heuristic to call an NlpSolver if all CouenneObjects are close to be satisfied (for other integer o...
virtual int getNumCols() const
Get number of columns.
virtual CbcHeuristic * clone() const
Clone.
NlpSolveHeuristic & operator=(const NlpSolveHeuristic &rhs)
Assignment operator.
Bonmin::OsiTMINLPInterface * nlp_
Pointer to an nlp solver interface.
void fint fint fint real fint real real real real real real real real real * e
CouenneRecordBestSol * getRecordBestSol() const
returns recorded best solution
int numberSolvePerLevel_
Number of nlp's solved for each given level of the tree.
bool hasCloned_
is nlp_ cloned or just a pointer?
double maxNlpInf_
maximum nlp infeasibility under which try to solve problem with Ipopt.
Class for MINLP problems with symbolic information.
double getModSolVal() const
CouenneProblem * couenne_
Pointer to a couenne representation of the problem.
double CouNumber
main number type in Couenne
bool infeasibleNode()
Say if current node is found feasible by cut generators.
We will throw this error when a problem is not solved.
double getFeasTol()
returns feasibility tolerance
void setNlpSolution(const double *sol, int numcols, double objValue)
Pass a solution found by an nlp solver.
const Ipopt::EJournalCategory J_COUENNE(Ipopt::J_USER8)
virtual double infeasibility(const OsiBranchingInformation *info, int &way) const
compute infeasibility of this variable, |w - f(x)| (where w is the auxiliary variable defined as w = ...
void setHasNlpSolution(bool b)
Say if has an nlp solution.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions >)
initialize options
Bonmin class for passing info between components of branch-and-cuts.
virtual ~NlpSolveHeuristic()
Destructor.