Scippy

SCIP

Solving Constraint Integer Programs

heur_nlpdiving.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_nlpdiving.c
17  * @brief NLP diving heuristic that chooses fixings w.r.t. the fractionalities
18  * @author Timo Berthold
19  * @author Stefan Vigerske
20  */
21 
22 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
23 
24 #include <assert.h>
25 #include <string.h>
26 
27 #include "scip/heur_nlpdiving.h"
28 #include "scip/heur_subnlp.h" /* for NLP initialization */
29 #include "scip/heur_undercover.h" /* for cover computation */
30 #include "nlpi/nlpi.h" /* for NLP statistics, currently */
31 
32 
33 #define HEUR_NAME "nlpdiving"
34 #define HEUR_DESC "NLP diving heuristic that chooses fixings w.r.t. the fractionalities"
35 #define HEUR_DISPCHAR 'd'
36 #define HEUR_PRIORITY -1003000
37 #define HEUR_FREQ 10
38 #define HEUR_FREQOFS 3
39 #define HEUR_MAXDEPTH -1
40 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
41 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
42 
43 /* event handler properties */
44 #define EVENTHDLR_NAME "Nlpdiving"
45 #define EVENTHDLR_DESC "bound change event handler for " HEUR_NAME " heuristic"
46 
47 
48 /*
49  * Default parameter settings
50  */
51 
52 #define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
53 #define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
54 #define DEFAULT_MAXNLPITERABS 200 /**< minimial absolute number of allowed NLP iterations */
55 #define DEFAULT_MAXNLPITERREL 10 /**< additional allowed number of NLP iterations relative to successfully found solutions */
56 #define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
57  * where diving is performed (0.0: no limit) */
58 #define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
59  * where diving is performed (0.0: no limit) */
60 #define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
61 #define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
62 #define DEFAULT_MINSUCCQUOT 0.1 /**< heuristic will not run if less then this percentage of calls succeeded (0.0: no limit) */
63 #define DEFAULT_MAXFEASNLPS 10 /**< maximal number of NLPs with feasible solution to solve during one dive */
64 #define DEFAULT_FIXQUOT 0.2 /**< percentage of fractional variables that should be fixed before the next NLP solve */
65 #define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
66 #define DEFAULT_LP FALSE /**< should the LP relaxation be solved before the NLP relaxation? */
67 #define DEFAULT_PREFERLPFRACS FALSE /**< prefer variables that are also fractional in LP solution? */
68 #define DEFAULT_PREFERCOVER TRUE /**< should variables in a minimal cover be preferred? */
69 #define DEFAULT_SOLVESUBMIP FALSE /**< should a sub-MIP be solved if all cover variables are fixed? */
70 #define DEFAULT_NLPSTART 's' /**< which point should be used as starting point for the NLP solver? */
71 #define DEFAULT_VARSELRULE 'd' /**< which variable selection should be used? ('f'ractionality, 'c'oefficient,
72  * 'p'seudocost, 'g'uided, 'd'ouble)
73  */
74 #define DEFAULT_NLPFASTFAIL TRUE /**< should the NLP solver stop early if it converges slow? */
75 #define DEFAULT_RANDSEED 97 /**< initial random seed */
76 
77 #define MINNLPITER 10 /**< minimal number of NLP iterations allowed in each NLP solving call */
78 
79 /* locally defined heuristic data */
80 struct SCIP_HeurData
81 {
82  SCIP_SOL* sol; /**< working solution */
83  SCIP_Real minreldepth; /**< minimal relative depth to start diving */
84  SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
85  int maxnlpiterabs; /**< minimial absolute number of allowed NLP iterations */
86  int maxnlpiterrel; /**< additional allowed number of NLP iterations relative to successfully found solutions */
87  SCIP_Real maxdiveubquot; /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
88  * where diving is performed (0.0: no limit) */
89  SCIP_Real maxdiveavgquot; /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
90  * where diving is performed (0.0: no limit) */
91  SCIP_Real maxdiveubquotnosol; /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
92  SCIP_Real maxdiveavgquotnosol;/**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
93  int maxfeasnlps; /**< maximal number of NLPs with feasible solution to solve during one dive */
94  SCIP_Real minsuccquot; /**< heuristic will not run if less then this percentage of calls succeeded (0.0: no limit) */
95  SCIP_Real fixquot; /**< percentage of fractional variables that should be fixed before the next NLP solve */
96  SCIP_Bool backtrack; /**< use one level of backtracking if infeasibility is encountered? */
97  SCIP_Bool lp; /**< should the LP relaxation be solved before the NLP relaxation? */
98  SCIP_Bool preferlpfracs; /**< prefer variables that are also fractional in LP solution? */
99  SCIP_Bool prefercover; /**< should variables in a minimal cover be preferred? */
100  SCIP_Bool solvesubmip; /**< should a sub-MIP be solved if all cover variables are fixed? */
101  SCIP_Bool nlpfastfail; /**< should the NLP solver stop early if it converges slow? */
102  char nlpstart; /**< which point should be used as starting point for the NLP solver? */
103  char varselrule; /**< which variable selection should be used? ('f'ractionality, 'c'oefficient,
104  * 'p'seudocost, 'g'uided, 'd'ouble)
105  */
106 
107  int nnlpiterations; /**< NLP iterations used in this heuristic */
108  int nsuccess; /**< number of runs that produced at least one feasible solution */
109  int nfixedcovervars; /**< number of variables in the cover that are already fixed */
110 #ifdef SCIP_STATISTIC
111  int nnlpsolves; /**< number of NLP solves */
112  int nfailcutoff; /**< number of fails due to cutoff */
113  int nfaildepth; /**< number of fails due to too deep */
114  int nfailnlperror; /**< number of fails due to NLP error */
115 #endif
116  SCIP_EVENTHDLR* eventhdlr; /**< event handler for bound change events */
117  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
118 };
119 
120 
121 /*
122  * local methods
123  */
124 
125 /** gets fractional variables of last NLP solution along with solution values and fractionalities
126  *
127  * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
128  * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
129  *
130  * @pre This method can be called if SCIP is in one of the following stages:
131  * - \ref SCIP_STAGE_INITSOLVE
132  * - \ref SCIP_STAGE_SOLVING
133  */
134 static
136  SCIP* scip, /**< SCIP data structure */
137  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
138  SCIP_VAR*** nlpcands, /**< pointer to store the array of NLP fractional variables, or NULL */
139  SCIP_Real** nlpcandssol, /**< pointer to store the array of NLP fractional variables solution values, or NULL */
140  SCIP_Real** nlpcandsfrac, /**< pointer to store the array of NLP fractional variables fractionalities, or NULL */
141  int* nnlpcands /**< pointer to store the number of NLP fractional variables , or NULL */
142  )
143 {
144  int c;
145 
146  assert(scip != NULL);
147  assert(heurdata != NULL);
148  assert(nlpcands != NULL);
149  assert(nlpcandssol != NULL);
150  assert(nlpcandsfrac != NULL);
151  assert(nnlpcands != NULL);
152 
153  /* get fractional variables that should be integral */
154  SCIP_CALL( SCIPgetNLPFracVars(scip, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, NULL) );
155 
156  /* values may be outside the domain in exact arithmetic, but inside the domain within relative tolerance, and still
157  * slightly fractional, because SCIPisFeasIntegral() uses absolute tolerance; project value onto domain to avoid this
158  * (example: primsol=29.99999853455704, lower bound = 30)
159  */
160  for( c = 0; c < *nnlpcands; ++c )
161  {
162  assert(!SCIPisFeasIntegral(scip, (*nlpcandssol)[c]));
163 
164  if( (*nlpcandssol)[c] < SCIPvarGetLbLocal((*nlpcands)[c]) || (*nlpcandssol)[c] > SCIPvarGetUbLocal((*nlpcands)[c]) )
165  {
166  SCIP_Real newval;
167 
168  newval = ((*nlpcandssol)[c] < SCIPvarGetLbLocal((*nlpcands)[c]))
169  ? SCIPvarGetLbLocal((*nlpcands)[c]) - 0.5*SCIPfeastol(scip)
170  : SCIPvarGetUbLocal((*nlpcands)[c]) + 0.5*SCIPfeastol(scip);
171 
172  assert(SCIPisFeasIntegral(scip, newval));
173 
174  SCIP_CALL( SCIPsetSolVal(scip, heurdata->sol, (*nlpcands)[c], newval) );
175 
176  (*nnlpcands)--;
177 
178  if( c < *nnlpcands )
179  {
180  (*nlpcands)[c] = (*nlpcands)[*nnlpcands];
181  (*nlpcandssol)[c] = (*nlpcandssol)[*nnlpcands];
182  (*nlpcandsfrac)[c] = (*nlpcandsfrac)[*nnlpcands];
183  }
184  }
185  }
186 
187  /* prefer decisions on variables which are also fractional in LP solution */
188  if( heurdata->preferlpfracs && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
189  {
190  for( c = 0; c < *nnlpcands; ++c )
191  {
192  if( SCIPisFeasIntegral(scip, SCIPgetSolVal(scip, NULL, (*nlpcands)[c])) )
193  (*nlpcandsfrac)[c] *= 100.0;
194  }
195  }
196 
197  return SCIP_OKAY;
198 }
199 
200 /** finds best candidate variable w.r.t. fractionality:
201  * - prefer variables that may not be rounded without destroying NLP feasibility:
202  * - of these variables, round least fractional variable in corresponding direction
203  * - if all remaining fractional variables may be rounded without destroying NLP feasibility:
204  * - round variable with least increasing objective value
205  * - binary variables are prefered
206  * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
207  * also be prefered if a correpsonding parameter is set
208  */
209 static
211  SCIP* scip, /**< original SCIP data structure */
212  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
213  SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
214  SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
215  SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
216  int nnlpcands, /**< number of NLP fractional variables */
217  SCIP_HASHMAP* varincover, /**< hash map for variables */
218  SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
219  int* bestcand, /**< pointer to store the index of the best candidate variable */
220  SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
221  SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
222  )
223 {
224  SCIP_Real bestobjgain;
225  SCIP_Real bestfrac;
226  SCIP_Bool bestcandmayrounddown;
227  SCIP_Bool bestcandmayroundup;
228  int c;
229 
230  /* check preconditions */
231  assert(scip != NULL);
232  assert(heurdata != NULL);
233  assert(nlpcands != NULL);
234  assert(nlpcandssol != NULL);
235  assert(nlpcandsfrac != NULL);
236  assert(covercomputed == (varincover != NULL));
237  assert(bestcand != NULL);
238  assert(bestcandmayround != NULL);
239  assert(bestcandroundup != NULL);
240 
241  bestcandmayrounddown = TRUE;
242  bestcandmayroundup = TRUE;
243  bestobjgain = SCIPinfinity(scip);
244  bestfrac = SCIP_INVALID;
245 
246  for( c = 0; c < nnlpcands; ++c )
247  {
248  SCIP_VAR* var;
249  SCIP_Bool mayrounddown;
250  SCIP_Bool mayroundup;
251  SCIP_Bool roundup;
252  SCIP_Real frac;
253  SCIP_Real obj;
254  SCIP_Real objgain;
255 
256  var = nlpcands[c];
257 
258  mayrounddown = SCIPvarMayRoundDown(var);
259  mayroundup = SCIPvarMayRoundUp(var);
260  frac = nlpcandsfrac[c];
261  obj = SCIPvarGetObj(var);
262 
263  /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
264  if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
265  continue;
266 
267  if( mayrounddown || mayroundup )
268  {
269  /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
270  if( bestcandmayrounddown || bestcandmayroundup )
271  {
272  /* choose rounding direction:
273  * - if variable may be rounded in both directions, round corresponding to the fractionality
274  * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
275  * the current fractional solution
276  */
277  if( mayrounddown && mayroundup )
278  {
279  if( SCIPisEQ(scip, frac, 0.5) )
280  roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
281  else
282  roundup = (frac > 0.5);
283  }
284  else
285  roundup = mayrounddown;
286 
287  if( roundup )
288  {
289  frac = 1.0 - frac;
290  objgain = frac*obj;
291  }
292  else
293  objgain = -frac*obj;
294 
295  /* penalize too small fractions */
296  if( SCIPisEQ(scip, frac, 0.01) )
297  {
298  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
299  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
300  */
301  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
302  objgain *= 1000.0;
303  }
304  else if( frac < 0.01 )
305  objgain *= 1000.0;
306 
307  /* prefer decisions on binary variables */
308  if( !SCIPvarIsBinary(var) )
309  objgain *= 1000.0;
310 
311  /* prefer decisions on cover variables */
312  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
313  objgain *= 1000.0;
314 
315  /* check, if candidate is new best candidate */
316  if( SCIPisLT(scip, objgain, bestobjgain) || (SCIPisEQ(scip, objgain, bestobjgain) && frac < bestfrac) )
317  {
318  *bestcand = c;
319  bestobjgain = objgain;
320  bestfrac = frac;
321  bestcandmayrounddown = mayrounddown;
322  bestcandmayroundup = mayroundup;
323  *bestcandroundup = roundup;
324  }
325  }
326  }
327  else
328  {
329  /* the candidate may not be rounded */
330  if( SCIPisEQ(scip, frac, 0.5) )
331  roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
332  else if( frac < 0.5 )
333  roundup = FALSE;
334  else
335  roundup = TRUE;
336 
337  /* adjust fractional part */
338  if( roundup )
339  frac = 1.0 - frac;
340 
341  /* penalize too small fractions */
342  if( SCIPisEQ(scip, frac, 0.01) )
343  {
344  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
345  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
346  */
347  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
348  frac += 10.0;
349  }
350  else if( frac < 0.01 )
351  frac += 10.0;
352 
353  /* prefer decisions on binary variables */
354  if( !SCIPvarIsBinary(var) )
355  frac *= 1000.0;
356 
357  /* prefer decisions on cover variables */
358  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
359  frac *= 1000.0;
360 
361  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
362  if( bestcandmayrounddown || bestcandmayroundup || frac < bestfrac )
363  {
364  *bestcand = c;
365  bestfrac = frac;
366  bestcandmayrounddown = FALSE;
367  bestcandmayroundup = FALSE;
368  *bestcandroundup = roundup;
369  }
370  assert(bestfrac < SCIP_INVALID);
371  }
372  }
373 
374  *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
375 
376  return SCIP_OKAY;
377 }
378 
379 /** finds best candidate variable w.r.t. vector length:
380  * - round variable with a small ratio between the increase in the objective and the locking numbers
381  * - binary variables are prefered
382  * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
383  * also be prefered if a corresponding parameter is set
384  */
385 static
387  SCIP* scip, /**< original SCIP data structure */
388  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
389  SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
390  SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
391  SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
392  int nnlpcands, /**< number of NLP fractional variables */
393  SCIP_HASHMAP* varincover, /**< hash map for variables */
394  SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
395  int* bestcand, /**< pointer to store the index of the best candidate variable */
396  SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
397  SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
398  )
399 {
400  SCIP_Real bestscore;
401  int c;
402 
403  /* check preconditions */
404  assert(scip != NULL);
405  assert(heurdata != NULL);
406  assert(nlpcands != NULL);
407  assert(nlpcandsfrac != NULL);
408  assert(nlpcandssol != NULL);
409  assert(bestcand != NULL);
410  assert(bestcandmayround != NULL);
411  assert(bestcandroundup != NULL);
412 
413  *bestcandmayround = TRUE;
414  bestscore = SCIP_REAL_MAX;
415 
416  /* get best candidate */
417  for( c = 0; c < nnlpcands; ++c )
418  {
419  SCIP_VAR* var;
420 
421  SCIP_Real obj;
422  SCIP_Real objdelta;
423  SCIP_Real frac;
424  SCIP_Real score;
425 
426  int nlocks;
427 
428  SCIP_Bool roundup;
429 
430  var = nlpcands[c];
431 
432  /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
433  if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
434  continue;
435 
436  frac = nlpcandsfrac[c];
437  obj = SCIPvarGetObj(var);
438  roundup = (obj >= 0.0);
439  objdelta = (roundup ? (1.0-frac)*obj : -frac * obj);
440  assert(objdelta >= 0.0);
441 
442  /* check whether the variable is roundable */
443  *bestcandmayround = *bestcandmayround && (SCIPvarMayRoundDown(var) || SCIPvarMayRoundUp(var));
444  nlocks = SCIPvarGetNLocksDown(var) + SCIPvarGetNLocksUp(var);
445 
446  /* smaller score is better */
447  score = (objdelta + SCIPsumepsilon(scip))/((SCIP_Real)nlocks+1.0);
448 
449  /* prefer decisions on binary variables */
450  if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
451  score *= 1000.0;
452 
453  /* prefer decisions on cover variables */
454  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
455  score *= 1000;
456 
457  /* check, if candidate is new best candidate */
458  if( score < bestscore )
459  {
460  *bestcand = c;
461  bestscore = score;
462  *bestcandroundup = roundup;
463  }
464  }
465 
466  return SCIP_OKAY;
467 }
468 
469 
470 /** finds best candidate variable w.r.t. locking numbers:
471  * - prefer variables that may not be rounded without destroying LP feasibility:
472  * - of these variables, round variable with least number of locks in corresponding direction
473  * - if all remaining fractional variables may be rounded without destroying LP feasibility:
474  * - round variable with least number of locks in opposite of its feasible rounding direction
475  * - binary variables are prefered
476  * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
477  * also be prefered if a correpsonding parameter is set
478  */
479 static
481  SCIP* scip, /**< original SCIP data structure */
482  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
483  SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
484  SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
485  SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
486  int nnlpcands, /**< number of NLP fractional variables */
487  SCIP_HASHMAP* varincover, /**< hash map for variables */
488  SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
489  int* bestcand, /**< pointer to store the index of the best candidate variable */
490  SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
491  SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
492  )
493 {
494  SCIP_Bool bestcandmayrounddown;
495  SCIP_Bool bestcandmayroundup;
496  int bestnviolrows; /* number of violated rows for best candidate */
497  SCIP_Real bestcandfrac; /* fractionality of best candidate */
498  int c;
499 
500  /* check preconditions */
501  assert(scip != NULL);
502  assert(heurdata != NULL);
503  assert(nlpcands != NULL);
504  assert(nlpcandsfrac != NULL);
505  assert(nlpcandssol != NULL);
506  assert(bestcand != NULL);
507  assert(bestcandmayround != NULL);
508  assert(bestcandroundup != NULL);
509 
510  bestcandmayrounddown = TRUE;
511  bestcandmayroundup = TRUE;
512  bestnviolrows = INT_MAX;
513  bestcandfrac = SCIP_INVALID;
514 
515  /* get best candidate */
516  for( c = 0; c < nnlpcands; ++c )
517  {
518  SCIP_VAR* var;
519 
520  int nlocksdown;
521  int nlocksup;
522  int nviolrows;
523 
524  SCIP_Bool mayrounddown;
525  SCIP_Bool mayroundup;
526  SCIP_Bool roundup;
527  SCIP_Real frac;
528 
529  var = nlpcands[c];
530  mayrounddown = SCIPvarMayRoundDown(var);
531  mayroundup = SCIPvarMayRoundUp(var);
532  frac = nlpcandsfrac[c];
533 
534  /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
535  if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
536  continue;
537 
538  if( mayrounddown || mayroundup )
539  {
540  /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
541  if( bestcandmayrounddown || bestcandmayroundup )
542  {
543  /* choose rounding direction:
544  * - if variable may be rounded in both directions, round corresponding to the fractionality
545  * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
546  * the current fractional solution
547  */
548  if( mayrounddown && mayroundup )
549  {
550  if( SCIPisEQ(scip, frac, 0.5) )
551  roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
552  else
553  roundup = (frac > 0.5);
554  }
555  else
556  roundup = mayrounddown;
557 
558  if( roundup )
559  {
560  frac = 1.0 - frac;
561  nviolrows = SCIPvarGetNLocksUp(var);
562  }
563  else
564  nviolrows = SCIPvarGetNLocksDown(var);
565 
566  /* penalize too small fractions */
567  if( SCIPisEQ(scip, frac, 0.01) )
568  {
569  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
570  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
571  */
572  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
573  nviolrows *= 100;
574  }
575  else if( frac < 0.01 )
576  nviolrows *= 100;
577 
578  /* prefer decisions on binary variables */
579  if( !SCIPvarIsBinary(var) )
580  nviolrows *= 1000;
581 
582  /* prefer decisions on cover variables */
583  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
584  nviolrows *= 1000;
585 
586  /* check, if candidate is new best candidate */
587  assert( (0.0 < frac && frac < 1.0) || SCIPvarIsBinary(var) );
588  if( nviolrows + frac < bestnviolrows + bestcandfrac )
589  {
590  *bestcand = c;
591  bestnviolrows = nviolrows;
592  bestcandfrac = frac;
593  bestcandmayrounddown = mayrounddown;
594  bestcandmayroundup = mayroundup;
595  *bestcandroundup = roundup;
596  }
597  }
598  }
599  else
600  {
601  /* the candidate may not be rounded */
602  nlocksdown = SCIPvarGetNLocksDown(var);
603  nlocksup = SCIPvarGetNLocksUp(var);
604 
605  roundup = (nlocksdown > nlocksup);
606  if( !roundup )
607  {
608  roundup = (nlocksdown == nlocksup);
609  if( SCIPisEQ(scip, frac, 0.5) )
610  roundup = (roundup && (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0));
611  else
612  roundup = (roundup && frac > 0.5);
613  }
614 
615  if( roundup )
616  {
617  nviolrows = nlocksup;
618  frac = 1.0 - frac;
619  }
620  else
621  nviolrows = nlocksdown;
622 
623  /* penalize too small fractions */
624  if( SCIPisEQ(scip, frac, 0.01) )
625  {
626  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
627  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
628  */
629  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
630  nviolrows *= 100;
631  }
632  else if( frac < 0.01 )
633  nviolrows *= 100;
634 
635  /* prefer decisions on binary variables */
636  if( !SCIPvarIsBinary(var) )
637  nviolrows *= 100;
638 
639  /* prefer decisions on cover variables */
640  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
641  nviolrows *= 1000;
642 
643  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
644  assert((0.0 < frac && frac < 1.0) || SCIPvarIsBinary(var));
645  if( bestcandmayrounddown || bestcandmayroundup || nviolrows + frac < bestnviolrows + bestcandfrac )
646  {
647  *bestcand = c;
648  bestnviolrows = nviolrows;
649  bestcandfrac = frac;
650  bestcandmayrounddown = FALSE;
651  bestcandmayroundup = FALSE;
652  *bestcandroundup = roundup;
653  }
654  assert(bestcandfrac < SCIP_INVALID);
655  }
656  }
657 
658  *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
659 
660  return SCIP_OKAY;
661 }
662 
663 /** calculates the pseudocost score for a given variable w.r.t. a given solution value and a given rounding direction */
664 static
665 void calcPscostQuot(
666  SCIP* scip, /**< SCIP data structure */
667  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
668  SCIP_VAR* var, /**< problem variable */
669  SCIP_Real primsol, /**< primal solution of variable */
670  SCIP_Real frac, /**< fractionality of variable */
671  int rounddir, /**< -1: round down, +1: round up, 0: select due to pseudo cost values */
672  SCIP_Real* pscostquot, /**< pointer to store pseudo cost quotient */
673  SCIP_Bool* roundup, /**< pointer to store whether the variable should be rounded up */
674  SCIP_Bool prefvar /**< should this variable be preferred because it is in a minimal cover? */
675  )
676 {
677  SCIP_Real pscostdown;
678  SCIP_Real pscostup;
679 
680  assert(heurdata != NULL);
681  assert(pscostquot != NULL);
682  assert(roundup != NULL);
683  assert(SCIPisEQ(scip, frac, primsol - SCIPfeasFloor(scip, primsol)));
684 
685  /* bound fractions to not prefer variables that are nearly integral */
686  frac = MAX(frac, 0.1);
687  frac = MIN(frac, 0.9);
688 
689  /* get pseudo cost quotient */
690  pscostdown = SCIPgetVarPseudocostVal(scip, var, 0.0-frac);
691  pscostup = SCIPgetVarPseudocostVal(scip, var, 1.0-frac);
692  assert(pscostdown >= 0.0 && pscostup >= 0.0);
693 
694  /* choose rounding direction
695  *
696  * to avoid performance variability caused by numerics we use random numbers to decide whether we want to roundup or
697  * round down if the values to compare are equal within tolerances.
698  */
699  if( rounddir == -1 )
700  *roundup = FALSE;
701  else if( rounddir == +1 )
702  *roundup = TRUE;
703  else if( SCIPisLT(scip, primsol, SCIPvarGetRootSol(var) - 0.4)
704  || (SCIPisEQ(scip, primsol, SCIPvarGetRootSol(var) - 0.4) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
705  *roundup = FALSE;
706  else if( SCIPisGT(scip, primsol, SCIPvarGetRootSol(var) + 0.4)
707  || (SCIPisEQ(scip, primsol, SCIPvarGetRootSol(var) + 0.4) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
708  *roundup = TRUE;
709  else if( SCIPisLT(scip, frac, 0.3) || (SCIPisEQ(scip, frac, 0.3) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
710  *roundup = FALSE;
711  else if( SCIPisGT(scip, frac, 0.7) || (SCIPisEQ(scip, frac, 0.7) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0) )
712  *roundup = TRUE;
713  else if( SCIPisLT(scip, pscostdown, pscostup)
714  || (SCIPisEQ(scip, pscostdown, pscostup) && SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0))
715  *roundup = FALSE;
716  else
717  *roundup = TRUE;
718 
719  /* calculate pseudo cost quotient */
720  if( *roundup )
721  *pscostquot = sqrt(frac) * (1.0+pscostdown) / (1.0+pscostup);
722  else
723  *pscostquot = sqrt(1.0-frac) * (1.0+pscostup) / (1.0+pscostdown);
724 
725  /* prefer decisions on binary variables */
726  if( SCIPvarIsBinary(var) )
727  (*pscostquot) *= 1000.0;
728 
729  /* prefer decisions on cover variables */
730  if( prefvar )
731  (*pscostquot) *= 1000.0;
732 }
733 
734 /** finds best candidate variable w.r.t. pseudo costs:
735  * - prefer variables that may not be rounded without destroying LP feasibility:
736  * - of these variables, round variable with largest rel. difference of pseudo cost values in corresponding
737  * direction
738  * - if all remaining fractional variables may be rounded without destroying LP feasibility:
739  * - round variable in the objective value direction
740  * - binary variables are prefered
741  * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
742  * also be prefered if a correpsonding parameter is set
743  */
744 static
746  SCIP* scip, /**< original SCIP data structure */
747  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
748  SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
749  SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
750  SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
751  int nnlpcands, /**< number of NLP fractional variables */
752  SCIP_HASHMAP* varincover, /**< hash map for variables */
753  SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
754  int* bestcand, /**< pointer to store the index of the best candidate variable */
755  SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
756  SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
757  )
758 {
759  SCIP_Bool bestcandmayrounddown;
760  SCIP_Bool bestcandmayroundup;
761  SCIP_Real bestpscostquot;
762  int c;
763 
764  /* check preconditions */
765  assert(scip != NULL);
766  assert(heurdata != NULL);
767  assert(nlpcands != NULL);
768  assert(nlpcandsfrac != NULL);
769  assert(nlpcandssol != NULL);
770  assert(bestcand != NULL);
771  assert(bestcandmayround != NULL);
772  assert(bestcandroundup != NULL);
773 
774  bestcandmayrounddown = TRUE;
775  bestcandmayroundup = TRUE;
776  bestpscostquot = -1.0;
777 
778  for( c = 0; c < nnlpcands; ++c )
779  {
780  SCIP_VAR* var;
781  SCIP_Real primsol;
782 
783  SCIP_Bool mayrounddown;
784  SCIP_Bool mayroundup;
785  SCIP_Bool roundup;
786  SCIP_Bool prefvar;
787  SCIP_Real frac;
788  SCIP_Real pscostquot;
789 
790  var = nlpcands[c];
791  mayrounddown = SCIPvarMayRoundDown(var);
792  mayroundup = SCIPvarMayRoundUp(var);
793  primsol = nlpcandssol[c];
794  frac = nlpcandsfrac[c];
795  prefvar = covercomputed && heurdata->prefercover && SCIPhashmapExists(varincover, var);
796  pscostquot = SCIP_INVALID;
797 
798  if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
799  continue;
800 
801  if( mayrounddown || mayroundup )
802  {
803  /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
804  if( bestcandmayrounddown || bestcandmayroundup )
805  {
806  /* choose rounding direction:
807  * - if variable may be rounded in both directions, round corresponding to the pseudo cost values
808  * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
809  * the current fractional solution
810  */
811  roundup = FALSE;
812  if( mayrounddown && mayroundup )
813  calcPscostQuot(scip, heurdata, var, primsol, frac, 0, &pscostquot, &roundup, prefvar);
814  else if( mayrounddown )
815  calcPscostQuot(scip, heurdata, var, primsol, frac, +1, &pscostquot, &roundup, prefvar);
816  else
817  calcPscostQuot(scip, heurdata, var, primsol, frac, -1, &pscostquot, &roundup, prefvar);
818 
819  assert(!SCIPisInfinity(scip,ABS(pscostquot)));
820 
821  /* check, if candidate is new best candidate */
822  if( pscostquot > bestpscostquot )
823  {
824  *bestcand = c;
825  bestpscostquot = pscostquot;
826  bestcandmayrounddown = mayrounddown;
827  bestcandmayroundup = mayroundup;
828  *bestcandroundup = roundup;
829  }
830  }
831  }
832  else
833  {
834  /* the candidate may not be rounded: calculate pseudo cost quotient and preferred direction */
835  calcPscostQuot(scip, heurdata, var, primsol, frac, 0, &pscostquot, &roundup, prefvar);
836  assert(!SCIPisInfinity(scip,ABS(pscostquot)));
837 
838  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
839  if( bestcandmayrounddown || bestcandmayroundup || pscostquot > bestpscostquot )
840  {
841  *bestcand = c;
842  bestpscostquot = pscostquot;
843  bestcandmayrounddown = FALSE;
844  bestcandmayroundup = FALSE;
845  *bestcandroundup = roundup;
846  }
847  }
848  }
849 
850  *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
851 
852  return SCIP_OKAY;
853 }
854 
855 /** finds best candidate variable w.r.t. the incumbent solution:
856  * - prefer variables that may not be rounded without destroying LP feasibility:
857  * - of these variables, round a variable to its value in direction of incumbent solution, and choose the
858  * variable that is closest to its rounded value
859  * - if all remaining fractional variables may be rounded without destroying LP feasibility:
860  * - round variable in direction that destroys LP feasibility (other direction is checked by SCIProundSol())
861  * - round variable with least increasing objective value
862  * - binary variables are prefered
863  * - variables in a minimal cover or variables that are also fractional in an optimal LP solution might
864  * also be prefered if a correpsonding parameter is set
865  */
866 static
868  SCIP* scip, /**< original SCIP data structure */
869  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
870  SCIP_VAR** nlpcands, /**< array of NLP fractional variables */
871  SCIP_Real* nlpcandssol, /**< array of NLP fractional variables solution values */
872  SCIP_Real* nlpcandsfrac, /**< array of NLP fractional variables fractionalities */
873  int nnlpcands, /**< number of NLP fractional variables */
874  SCIP_SOL* bestsol, /**< incumbent solution */
875  SCIP_HASHMAP* varincover, /**< hash map for variables */
876  SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
877  int* bestcand, /**< pointer to store the index of the best candidate variable */
878  SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
879  SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
880  )
881 {
882  SCIP_Real bestobjgain;
883  SCIP_Real bestfrac;
884  SCIP_Bool bestcandmayrounddown;
885  SCIP_Bool bestcandmayroundup;
886  int c;
887 
888  /* check preconditions */
889  assert(scip != NULL);
890  assert(heurdata != NULL);
891  assert(nlpcands != NULL);
892  assert(nlpcandsfrac != NULL);
893  assert(nlpcandssol != NULL);
894  assert(bestcand != NULL);
895  assert(bestcandmayround != NULL);
896  assert(bestcandroundup != NULL);
897 
898  bestcandmayrounddown = TRUE;
899  bestcandmayroundup = TRUE;
900  bestobjgain = SCIPinfinity(scip);
901  bestfrac = SCIP_INVALID;
902 
903  for( c = 0; c < nnlpcands; ++c )
904  {
905  SCIP_VAR* var;
906  SCIP_Real bestsolval;
907  SCIP_Real solval;
908  SCIP_Real obj;
909  SCIP_Real frac;
910  SCIP_Real objgain;
911 
912  SCIP_Bool mayrounddown;
913  SCIP_Bool mayroundup;
914  SCIP_Bool roundup;
915 
916  var = nlpcands[c];
917  mayrounddown = SCIPvarMayRoundDown(var);
918  mayroundup = SCIPvarMayRoundUp(var);
919  solval = nlpcandssol[c];
920  frac = nlpcandsfrac[c];
921  obj = SCIPvarGetObj(var);
922  bestsolval = SCIPgetSolVal(scip, bestsol, var);
923 
924  /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
925  if( SCIPisLT(scip, solval, SCIPvarGetLbLocal(var)) || SCIPisGT(scip, solval, SCIPvarGetUbLocal(var)) )
926  continue;
927 
928  /* select default rounding direction
929  * try to avoid variability; decide randomly if the LP solution can contain some noise
930  */
931  if( SCIPisEQ(scip, solval, bestsolval) )
932  roundup = (SCIPrandomGetInt(heurdata->randnumgen, 0, 1) == 0);
933  else
934  roundup = (solval < bestsolval);
935 
936  if( mayrounddown || mayroundup )
937  {
938  /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
939  if( bestcandmayrounddown || bestcandmayroundup )
940  {
941  /* choose rounding direction:
942  * - if variable may be rounded in both directions, round corresponding to its value in incumbent solution
943  * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
944  * the current fractional solution with SCIProundSol()
945  */
946  if( !mayrounddown || !mayroundup )
947  roundup = mayrounddown;
948 
949  if( roundup )
950  {
951  frac = 1.0 - frac;
952  objgain = frac*obj;
953  }
954  else
955  objgain = -frac*obj;
956 
957  /* penalize too small fractions */
958  if( SCIPisEQ(scip, frac, 0.01) )
959  {
960  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
961  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
962  */
963  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
964  objgain *= 1000.0;
965  }
966  else if( frac < 0.01 )
967  objgain *= 1000.0;
968 
969  /* prefer decisions on binary variables */
970  if( !SCIPvarIsBinary(var) )
971  objgain *= 1000.0;
972 
973  /* prefer decisions on cover variables */
974  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
975  objgain *= 1000.0;
976 
977  /* check, if candidate is new best candidate */
978  if( SCIPisLT(scip, objgain, bestobjgain) || (SCIPisEQ(scip, objgain, bestobjgain) && frac < bestfrac) )
979  {
980  *bestcand = c;
981  bestobjgain = objgain;
982  bestfrac = frac;
983  bestcandmayrounddown = mayrounddown;
984  bestcandmayroundup = mayroundup;
985  *bestcandroundup = roundup;
986  }
987  }
988  }
989  else
990  {
991  /* the candidate may not be rounded */
992  if( roundup )
993  frac = 1.0 - frac;
994 
995  /* penalize too small fractions */
996  if( SCIPisEQ(scip, frac, 0.01) )
997  {
998  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
999  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
1000  */
1001  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
1002  frac += 10.0;
1003  }
1004  else if( frac < 0.01 )
1005  frac += 10.0;
1006 
1007  /* prefer decisions on binary variables */
1008  if( !SCIPvarIsBinary(var) )
1009  frac *= 1000.0;
1010 
1011  /* prefer decisions on cover variables */
1012  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
1013  frac *= 1000.0;
1014 
1015  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
1016  if( bestcandmayrounddown || bestcandmayroundup || frac < bestfrac )
1017  {
1018  *bestcand = c;
1019  bestfrac = frac;
1020  bestcandmayrounddown = FALSE;
1021  bestcandmayroundup = FALSE;
1022  *bestcandroundup = roundup;
1023  }
1024  }
1025  }
1026 
1027  *bestcandmayround = bestcandmayroundup || bestcandmayrounddown;
1028 
1029  return SCIP_OKAY;
1030 }
1031 
1032 /** finds best candidate variable w.r.t. both, the LP and the NLP solution:
1033  * - choose a variable for which the sum of the distances from the relaxations' solutions to a common
1034  * integer value is minimal
1035  * - binary variables are prefered
1036  * - variables in a minimal cover might be prefered if a corresponding parameter is set
1037  */
1038 static
1040  SCIP* scip, /**< original SCIP data structure */
1041  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1042  SCIP_VAR** pseudocands, /**< array of non-fixed variables */
1043  SCIP_Real* pseudocandsnlpsol, /**< array of NLP solution values */
1044  SCIP_Real* pseudocandslpsol, /**< array of LP solution values */
1045  int npseudocands, /**< number of NLP fractional variables */
1046  SCIP_HASHMAP* varincover, /**< hash map for variables */
1047  SCIP_Bool covercomputed, /**< has a minimal cover been computed? */
1048  int* bestcand, /**< pointer to store the index of the best candidate variable */
1049  SCIP_Real* bestboundval, /**< pointer to store the bound, the best candidate should be rounded to */
1050  SCIP_Bool* bestcandmayround, /**< pointer to store whether best candidate is trivially roundable */
1051  SCIP_Bool* bestcandroundup /**< pointer to store whether best candidate should be rounded up */
1052  )
1053 {
1054  SCIP_Real bestfrac;
1055  int c;
1056 
1057  /* check preconditions */
1058  assert(scip != NULL);
1059  assert(heurdata != NULL);
1060  assert(pseudocands != NULL);
1061  assert(pseudocandsnlpsol != NULL);
1062  assert(pseudocandslpsol != NULL);
1063  assert(covercomputed == (varincover != NULL));
1064  assert(bestcand != NULL);
1065  assert(bestcandmayround != NULL);
1066  assert(bestcandroundup != NULL);
1067 
1068  bestfrac = SCIP_INVALID;
1069 
1070  for( c = 0; c < npseudocands; ++c )
1071  {
1072  SCIP_VAR* var;
1073  SCIP_Bool mayround;
1074  SCIP_Bool roundup;
1075 
1076  SCIP_Real frac;
1077  SCIP_Real lpsol;
1078  SCIP_Real nlpsol;
1079  SCIP_Real lpsolfloor;
1080  SCIP_Real nlpsolfloor;
1081  SCIP_Real lpsolceil;
1082  SCIP_Real nlpsolceil;
1083  SCIP_Real boundval;
1084  SCIP_Real floorval;
1085  SCIP_Real ceilval;
1086 
1087  var = pseudocands[c];
1088  lpsol = pseudocandslpsol[c];
1089  nlpsol = pseudocandsnlpsol[c];
1090 
1091  assert(SCIPvarGetUbLocal(var)-SCIPvarGetLbLocal(var) > 0.5);
1092  assert(SCIPisLE(scip, SCIPvarGetLbLocal(var), lpsol) && SCIPisLE(scip, lpsol, SCIPvarGetUbLocal(var)));
1093 
1094  /* since we are not solving the NLP after each fixing, the old NLP solution might be outside the propagated bounds */
1095  if( SCIPisLT(scip, nlpsol, SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpsol, SCIPvarGetUbLocal(var)) )
1096  continue;
1097 
1098  mayround = SCIPvarMayRoundDown(var) || SCIPvarMayRoundUp(var);
1099 
1100  /* if this candidate is trivially roundable, and we already know a candidate that is not, continue */
1101  if( mayround && !(*bestcandmayround) )
1102  continue;
1103 
1104  if( SCIPisFeasEQ(scip, lpsol, nlpsol) && SCIPisFeasIntegral(scip, lpsol))
1105  continue;
1106 
1107  lpsolfloor = SCIPfeasFloor(scip, lpsol);
1108  nlpsolfloor = SCIPfeasFloor(scip, nlpsol);
1109  lpsolceil = SCIPfeasCeil(scip, lpsol);
1110  nlpsolceil = SCIPfeasCeil(scip, nlpsol);
1111  floorval = MIN(lpsolfloor,nlpsolfloor);
1112  ceilval = MAX(lpsolceil,nlpsolceil);
1113  /* if both values are in the same interval, find out which integer is (in sum) the closer one, this will be the
1114  * new bound. The minima and maxima are necessary since one or both values with be integer
1115  */
1116  if( SCIPvarIsBinary(var) || ceilval-floorval < 1.5 )
1117  {
1118 
1119  frac = 0.33*(lpsol-floorval) + 0.67*(nlpsol-floorval);
1120  if( frac < 0.5 )
1121  {
1122  roundup = FALSE;
1123  boundval = MIN(lpsolfloor,nlpsolfloor);
1124  }
1125  else
1126  {
1127  roundup = TRUE;
1128  frac = 1.0-frac;
1129  boundval = MAX(nlpsolceil,lpsolceil);
1130  }
1131  }
1132  else
1133  {
1134  /* determine new bound in the middle of both relaxations, such that the NLP stays feasible */
1135  SCIP_Real midval;
1136  midval = (nlpsol+lpsol)/2.0;
1137  roundup = nlpsol > lpsol;
1138  frac = ABS(nlpsol-lpsol);
1139 
1140  if( roundup )
1141  boundval = SCIPfeasCeil(scip, midval);
1142  else
1143  boundval = SCIPfeasFloor(scip, midval);
1144 
1145  assert(roundup == SCIPisGT(scip, nlpsol, boundval));
1146  }
1147 
1148  /* penalize too small fractions */
1149  if( SCIPisEQ(scip, frac, 0.01) )
1150  {
1151  /* try to avoid variability; decide randomly if the LP solution can contain some noise.
1152  * use a 1:SCIP_PROBINGSCORE_PENALTYRATIO chance for increasing the fractionality, i.e., the score.
1153  */
1154  if( SCIPrandomGetInt(heurdata->randnumgen, 0, SCIP_PROBINGSCORE_PENALTYRATIO) == 0 )
1155  frac += 10.0;
1156  }
1157  else if( frac < 0.01 )
1158  frac += 10.0;
1159 
1160  /* prefer decisions on binary variables */
1161  if( !SCIPvarIsBinary(var) )
1162  frac *= 1000.0;
1163 
1164  /* prefer decisions on cover variables */
1165  if( covercomputed && heurdata->prefercover && !SCIPhashmapExists(varincover, var) )
1166  frac *= 1000.0;
1167 
1168  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
1169  if( frac < bestfrac || (*bestcandmayround && !mayround) )
1170  {
1171  *bestcand = c;
1172  bestfrac = frac;
1173  *bestcandmayround = FALSE;
1174  *bestcandroundup = roundup;
1175  *bestboundval = boundval;
1176  }
1177  assert(bestfrac < SCIP_INVALID);
1178  }
1179 
1180  if( *bestcandroundup )
1181  *bestboundval -= 0.5;
1182  else
1183  *bestboundval += 0.5;
1184 
1185  return SCIP_OKAY;
1186 }
1187 
1188 /** creates a new solution for the original problem by copying the solution of the subproblem */
1189 static
1191  SCIP* scip, /**< original SCIP data structure */
1192  SCIP* subscip, /**< SCIP structure of the subproblem */
1193  SCIP_HEUR* heur, /**< heuristic structure */
1194  SCIP_HASHMAP* varmap, /**< hash map for variables */
1195  SCIP_SOL* subsol, /**< solution of the subproblem */
1196  SCIP_Bool* success /**< used to store whether new solution was found or not */
1197  )
1198 {
1199  SCIP_VAR** vars; /* the original problem's variables */
1200  SCIP_VAR** subvars;
1201  SCIP_Real* subsolvals; /* solution values of the subproblem */
1202  SCIP_SOL* newsol; /* solution to be created for the original problem */
1203  int nvars; /* the original problem's number of variables */
1204  int i;
1205 
1206  assert(scip != NULL);
1207  assert(subscip != NULL);
1208  assert(subsol != NULL);
1209 
1210  /* get variables' data */
1211  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1212 
1213  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
1214  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
1215  */
1216  assert(nvars <= SCIPgetNOrigVars(subscip));
1217 
1218  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
1219  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
1220 
1221  for( i = 0; i < nvars; i++ )
1222  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
1223 
1224  /* copy the solution */
1225  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
1226 
1227  /* create new solution for the original problem */
1228  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
1229  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
1230 
1231  /* try to add new solution to scip and free it immediately */
1232  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
1233 
1234  SCIPfreeBufferArray(scip, &subvars);
1235  SCIPfreeBufferArray(scip, &subsolvals);
1236 
1237  return SCIP_OKAY;
1238 }
1239 
1240 /** todo setup and solve the subMIP */
1241 static
1243  SCIP* scip, /**< SCIP data structure */
1244  SCIP* subscip, /**< NLP diving subscip */
1245  SCIP_HEUR* heur, /**< heuristic data structure */
1246  SCIP_VAR** covervars, /**< variables in the cover, should be fixed locally */
1247  int ncovervars, /**< number of variables in the cover */
1248  SCIP_Bool* success /**< pointer to store whether a solution was found */
1249  )
1250 {
1251  SCIP_HASHMAP* varmap;
1252  SCIP_SOL** subsols;
1253  int c;
1254  int nsubsols;
1255 
1256  assert(subscip != NULL);
1257  assert(scip != NULL);
1258  assert(heur != NULL);
1259 
1260  /* create the variable mapping hash map */
1261  SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), SCIPgetNVars(scip)) );
1262 
1263  *success = FALSE;
1264 
1265  /* copy original problem to subproblem; do not copy pricers */
1266  SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmap, NULL, "undercoversub", NULL, NULL, 0, FALSE, FALSE, TRUE, NULL) );
1267 
1268  /* assert that cover variables are fixed in source and target SCIP */
1269  for( c = 0; c < ncovervars; c++)
1270  {
1271  assert(SCIPisFeasEQ(scip, SCIPvarGetLbLocal(covervars[c]), SCIPvarGetUbLocal(covervars[c])));
1272  assert(SCIPisFeasEQ(scip, SCIPvarGetLbGlobal((SCIP_VAR*) SCIPhashmapGetImage(varmap, covervars[c])),
1273  SCIPvarGetUbGlobal((SCIP_VAR*) SCIPhashmapGetImage(varmap, covervars[c]))));
1274  }
1275 
1276  /* set parameters for sub-SCIP */
1277 
1278  /* do not abort subproblem on CTRL-C */
1279  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
1280 
1281 #ifdef SCIP_DEBUG
1282  /* for debugging, enable full output */
1283  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
1284  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
1285 #else
1286  /* disable statistic timing inside sub SCIP and output to console */
1287  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
1288  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
1289 #endif
1290 
1291  /* set limits for the subproblem */
1292  SCIP_CALL( SCIPcopyLimits(scip, subscip) );
1293  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", (SCIP_Longint)100) );
1294  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", (SCIP_Longint)500) );
1295 
1296  /* forbid recursive call of heuristics and separators solving sub-SCIPs */
1297  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
1298 
1299  /* disable cutting plane separation */
1301 
1302  /* disable expensive presolving */
1304 
1305  /* use best estimate node selection */
1306  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
1307  {
1308  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
1309  }
1310 
1311  /* use inference branching */
1312  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
1313  {
1314  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
1315  }
1316 
1317  /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
1318  if( !SCIPisParamFixed(subscip, "conflict/enable") )
1319  {
1320  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
1321  }
1322  if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
1323  {
1324  SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
1325  }
1326  if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
1327  {
1328  SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
1329  }
1330 
1331  if( SCIPgetNSols(scip) > 0 )
1332  {
1333  SCIP_Real upperbound;
1334  SCIP_Real cutoffbound;
1335  SCIP_Real minimprove;
1336 
1337  assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );
1338 
1339  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
1340  minimprove = 0.01;
1341 
1342  if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
1343  {
1344  cutoffbound = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
1345  }
1346  else
1347  {
1348  if( SCIPgetUpperbound(scip) >= 0 )
1349  cutoffbound = (1 - minimprove)*SCIPgetUpperbound(scip);
1350  else
1351  cutoffbound = (1 + minimprove)*SCIPgetUpperbound(scip);
1352  }
1353  cutoffbound = MIN(upperbound, cutoffbound);
1354  SCIP_CALL( SCIPsetObjlimit(subscip, cutoffbound) );
1355  }
1356 
1357  SCIP_CALL_ABORT( SCIPsolve(subscip) );
1358 
1359  /* check, whether a solution was found;
1360  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
1361  */
1362  nsubsols = SCIPgetNSols(subscip);
1363  subsols = SCIPgetSols(subscip);
1364  for( c = 0; c < nsubsols && !(*success); ++c )
1365  {
1366  SCIP_CALL( createNewSol(scip, subscip, heur, varmap, subsols[c], success) );
1367  }
1368 
1369  SCIPhashmapFree(&varmap);
1370 
1371  return SCIP_OKAY;
1372 }
1373 
1374 
1375 /** solves subproblem and passes best feasible solution to original SCIP instance */
1376 static
1378  SCIP* scip, /**< SCIP data structure of the original problem */
1379  SCIP_HEUR* heur, /**< heuristic data structure */
1380  SCIP_VAR** covervars, /**< variables in the cover, should be fixed locally */
1381  int ncovervars, /**< number of variables in the cover */
1382  SCIP_Bool* success /**< pointer to store whether a solution was found */
1383  )
1384 {
1385  SCIP* subscip;
1386 
1387  SCIP_RETCODE retcode;
1388 
1389 
1390  /* check whether there is enough time and memory left */
1391  SCIP_CALL( SCIPcheckCopyLimits(scip, success) );
1392 
1393  if( !(*success) )
1394  return SCIP_OKAY;
1395 
1396  /* create subproblem */
1397  SCIP_CALL( SCIPcreate(&subscip) );
1398 
1399  retcode = doSolveSubMIP(scip, subscip, heur, covervars, ncovervars, success);
1400 
1401  /* free sub-SCIP even if an error occurred during the subscip solve */
1402  SCIP_CALL( SCIPfree(&subscip) );
1403 
1404  SCIP_CALL( retcode );
1405 
1406  return SCIP_OKAY;
1407 }
1408 
1409 /* ---------------- Callback methods of event handler ---------------- */
1410 
1411 /* exec the event handler
1412  *
1413  * We update the number of variables fixed in the cover
1414  */
1415 static
1416 SCIP_DECL_EVENTEXEC(eventExecNlpdiving)
1417 {
1418  SCIP_EVENTTYPE eventtype;
1419  SCIP_HEURDATA* heurdata;
1420  SCIP_VAR* var;
1421 
1422  SCIP_Real oldbound;
1423  SCIP_Real newbound;
1424  SCIP_Real otherbound;
1425 
1426  assert(eventhdlr != NULL);
1427  assert(eventdata != NULL);
1428  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
1429  assert(event != NULL);
1430 
1431  heurdata = (SCIP_HEURDATA*)eventdata;
1432  assert(heurdata != NULL);
1433  assert(0 <= heurdata->nfixedcovervars && heurdata->nfixedcovervars <= SCIPgetNVars(scip));
1434 
1435  oldbound = SCIPeventGetOldbound(event);
1436  newbound = SCIPeventGetNewbound(event);
1437  var = SCIPeventGetVar(event);
1438 
1439  eventtype = SCIPeventGetType(event);
1440  otherbound = (eventtype & SCIP_EVENTTYPE_LBCHANGED) ? SCIPvarGetUbLocal(var) : SCIPvarGetLbLocal(var);
1441 
1442  switch( eventtype )
1443  {
1446  /* if cover variable is now fixed */
1447  if( SCIPisFeasEQ(scip, newbound, otherbound) && !SCIPisFeasEQ(scip, oldbound, otherbound) )
1448  {
1449  assert(!SCIPisEQ(scip, oldbound, otherbound));
1450  ++(heurdata->nfixedcovervars);
1451  }
1452  break;
1455  /* if cover variable is now unfixed */
1456  if( SCIPisFeasEQ(scip, oldbound, otherbound) && !SCIPisFeasEQ(scip, newbound, otherbound) )
1457  {
1458  assert(!SCIPisEQ(scip, newbound, otherbound));
1459  --(heurdata->nfixedcovervars);
1460  }
1461  break;
1462  default:
1463  SCIPerrorMessage("invalid event type.\n");
1464  return SCIP_INVALIDDATA;
1465  }
1466  assert(0 <= heurdata->nfixedcovervars && heurdata->nfixedcovervars <= SCIPgetNVars(scip));
1467 
1468  /* SCIPdebugMsg(scip, "changed bound of cover variable <%s> from %f to %f (nfixedcovervars: %d).\n", SCIPvarGetName(var),
1469  oldbound, newbound, heurdata->nfixedcovervars); */
1470 
1471  return SCIP_OKAY;
1472 }
1473 
1474 
1475 /*
1476  * Callback methods
1477  */
1478 
1479 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1480 static
1481 SCIP_DECL_HEURCOPY(heurCopyNlpdiving)
1482 { /*lint --e{715}*/
1483  assert(scip != NULL);
1484  assert(heur != NULL);
1485  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1486 
1487  /* call inclusion method of primal heuristic */
1489 
1490  return SCIP_OKAY;
1491 }
1492 
1493 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1494 static
1495 SCIP_DECL_HEURFREE(heurFreeNlpdiving) /*lint --e{715}*/
1496 { /*lint --e{715}*/
1497  SCIP_HEURDATA* heurdata;
1498 
1499  assert(heur != NULL);
1500  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1501  assert(scip != NULL);
1502 
1503  /* free heuristic data */
1504  heurdata = SCIPheurGetData(heur);
1505  assert(heurdata != NULL);
1506  SCIPfreeBlockMemory(scip, &heurdata);
1507  SCIPheurSetData(heur, NULL);
1508 
1509  return SCIP_OKAY;
1510 }
1511 
1512 
1513 /** initialization method of primal heuristic (called after problem was transformed) */
1514 static
1515 SCIP_DECL_HEURINIT(heurInitNlpdiving) /*lint --e{715}*/
1516 { /*lint --e{715}*/
1517  SCIP_HEURDATA* heurdata;
1518 
1519  assert(heur != NULL);
1520  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1521 
1522  /* get heuristic data */
1523  heurdata = SCIPheurGetData(heur);
1524  assert(heurdata != NULL);
1525 
1526  /* create working solution */
1527  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
1528 
1529  /* create random number generator */
1530  SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED) );
1531 
1532  /* initialize data */
1533  heurdata->nnlpiterations = 0;
1534  heurdata->nsuccess = 0;
1535  heurdata->nfixedcovervars = 0;
1536  SCIPstatistic(
1537  heurdata->nnlpsolves = 0;
1538  heurdata->nfailcutoff = 0;
1539  heurdata->nfaildepth = 0;
1540  heurdata->nfailnlperror = 0;
1541  );
1542 
1543  return SCIP_OKAY;
1544 }
1545 
1546 
1547 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
1548 static
1549 SCIP_DECL_HEUREXIT(heurExitNlpdiving) /*lint --e{715}*/
1550 { /*lint --e{715}*/
1551  SCIP_HEURDATA* heurdata;
1552 
1553  assert(heur != NULL);
1554  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1555 
1556  /* get heuristic data */
1557  heurdata = SCIPheurGetData(heur);
1558  assert(heurdata != NULL);
1559 
1560  /* free random number generator */
1561  SCIPfreeRandom(scip, &heurdata->randnumgen);
1562 
1563  /* free working solution */
1564  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
1565 
1566  SCIPstatistic(
1567  if( strstr(SCIPgetProbName(scip), "_covering") == NULL && SCIPheurGetNCalls(heur) > 0 )
1568  {
1569  SCIPstatisticMessage("%-30s %5" SCIP_LONGINT_FORMAT " sols in %5" SCIP_LONGINT_FORMAT " runs, %6.1fs, %7d NLP iters in %5d NLP solves, %5.1f avg., %3d%% success %3d%% cutoff %3d%% depth %3d%% nlperror\n",
1571  heurdata->nnlpiterations, heurdata->nnlpsolves, heurdata->nnlpiterations/MAX(1.0,(SCIP_Real)heurdata->nnlpsolves),
1572  (100*heurdata->nsuccess) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfailcutoff) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfaildepth) / (int)SCIPheurGetNCalls(heur), (100*heurdata->nfailnlperror) / (int)SCIPheurGetNCalls(heur)
1573  );
1574  }
1575  );
1576 
1577  return SCIP_OKAY;
1578 }
1579 
1580 
1581 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
1582 static
1583 SCIP_DECL_HEURINITSOL(heurInitsolNlpdiving)
1584 { /*lint --e{715}*/
1585  SCIP_HEUR* nlpheur;
1586 
1588  return SCIP_OKAY;
1589 
1590  /* find NLP local search heuristic */
1591  nlpheur = SCIPfindHeur(scip, "subnlp");
1592 
1593  /* add global linear constraints to NLP relaxation */
1594  if( nlpheur != NULL )
1595  {
1597  }
1598 
1599  return SCIP_OKAY;
1600 }
1601 
1602 
1603 /** execution method of primal heuristic */
1604 static
1605 SCIP_DECL_HEUREXEC(heurExecNlpdiving)
1606 { /*lint --e{715}*/
1607  SCIP_HEURDATA* heurdata;
1608  SCIP_NLPSOLSTAT nlpsolstat;
1609  SCIP_LPSOLSTAT lpsolstat;
1610  SCIP_SOL* nlpstartsol;
1611  SCIP_SOL* bestsol;
1612  SCIP_VAR** nlpcands;
1613  SCIP_VAR** covervars;
1614  SCIP_Real* nlpcandssol;
1615  SCIP_Real* nlpcandsfrac;
1616  SCIP_Real* pseudocandslpsol;
1617  SCIP_Real* pseudocandsnlpsol;
1618  SCIP_HASHMAP* varincover;
1619  SCIP_Real searchubbound;
1620  SCIP_Real searchavgbound;
1621  SCIP_Real searchbound;
1622  SCIP_Real objval;
1623  SCIP_Real oldobjval;
1624  SCIP_Real fixquot;
1625  SCIP_Real bestboundval;
1626  SCIP_Real timelim;
1627  SCIP_Bool bestcandmayround;
1628  SCIP_Bool bestcandroundup;
1629  SCIP_Bool nlperror;
1630  SCIP_Bool lperror;
1631  SCIP_Bool cutoff;
1632  SCIP_Bool backtracked;
1633  SCIP_Bool solvenlp;
1634  SCIP_Bool covercomputed;
1635  SCIP_Bool solvesubmip;
1636  SCIP_Longint ncalls;
1637  SCIP_Longint nsolsfound;
1638  int avgnnlpiterations;
1639  int maxnnlpiterations;
1640  int npseudocands;
1641  int nlpbranchcands;
1642  int ncovervars;
1643  int nnlpcands;
1644  int startnnlpcands;
1645  int depth;
1646  int maxdepth;
1647  int maxdivedepth;
1648  int divedepth;
1649  int lastnlpsolvedepth;
1650  int nfeasnlps;
1651  int bestcand;
1652  int origiterlim;
1653  int origfastfail;
1654  int c;
1655  int backtrackdepth; /* depth where to go when backtracking */
1656  SCIP_VAR* backtrackvar; /* (first) variable to fix differently in backtracking */
1657  SCIP_Real backtrackvarval; /* (fractional) value of backtrack variable */
1658  SCIP_Bool backtrackroundup; /* whether variable should be rounded up in backtracking */
1659 
1660  backtrackdepth = -1;
1661  backtrackvar = NULL;
1662  backtrackvarval = 0.0;
1663  backtrackroundup = FALSE;
1664  bestsol = NULL;
1665  pseudocandsnlpsol = NULL;
1666  pseudocandslpsol = NULL;
1667  covervars = NULL;
1668 
1669  assert(heur != NULL);
1670  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1671  assert(scip != NULL);
1672  assert(result != NULL);
1673  /* assert(SCIPhasCurrentNodeLP(scip)); */
1674 
1675  *result = SCIP_DIDNOTRUN;
1676 
1677  /* do not call heuristic of node was already detected to be infeasible */
1678  if( nodeinfeasible )
1679  return SCIP_OKAY;
1680 
1681  /* only call heuristic, if an NLP relaxation has been constructed */
1682  if( !SCIPisNLPConstructed(scip) || SCIPgetNNlpis(scip) == 0 )
1683  return SCIP_OKAY;
1684 
1685  /* only call heuristic, if the current node will not be cutoff, e.g., due to a (integer and NLP-)feasible LP solution */
1686  if( SCIPisFeasGE(scip, SCIPgetLocalLowerbound(scip), SCIPgetUpperbound(scip)) )
1687  return SCIP_OKAY;
1688 
1689  /* get heuristic's data */
1690  heurdata = SCIPheurGetData(heur);
1691  assert(heurdata != NULL);
1692 
1693  /* do not call heuristic, if it barely succeded */
1694  if( (SCIPheurGetNSolsFound(heur) + 1.0) / (SCIP_Real)(SCIPheurGetNCalls(heur) + 1.0) < heurdata->minsuccquot )
1695  return SCIP_OKAY;
1696 
1697  *result = SCIP_DELAYED;
1698 
1699  /* don't dive two times at the same node */
1700  if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
1701  return SCIP_OKAY;
1702 
1703  *result = SCIP_DIDNOTRUN;
1704 
1705  /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
1706  depth = SCIPgetDepth(scip);
1707  maxdepth = SCIPgetMaxDepth(scip);
1708  maxdepth = MAX(maxdepth, 30);
1709  if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
1710  return SCIP_OKAY;
1711 
1712  /* calculate the maximal number of NLP iterations until heuristic is aborted
1713  * maximal number is maxnlpiterabs plus a success-depending multiplier of maxnlpiterrel
1714  */
1715  ncalls = SCIPheurGetNCalls(heur);
1716  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
1717  maxnnlpiterations = heurdata->maxnlpiterabs;
1718  maxnnlpiterations += (int)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxnlpiterrel);
1719 
1720  /* don't try to dive, if we took too many NLP iterations during diving */
1721  if( heurdata->nnlpiterations >= maxnnlpiterations )
1722  return SCIP_OKAY;
1723 
1724  /* allow at least a bit more than the so far average number of NLP iterations per dive */
1725  avgnnlpiterations = (int)(heurdata->nnlpiterations / MAX(ncalls, 1.0));
1726  maxnnlpiterations = (int)MAX((SCIP_Real) maxnnlpiterations, (SCIP_Real) heurdata->nnlpiterations + 1.2*avgnnlpiterations);
1727 
1728  /* don't try to dive, if there are no unfixed discrete variables */
1729  SCIP_CALL( SCIPgetPseudoBranchCands(scip, NULL, &npseudocands, NULL) );
1730  if( npseudocands == 0 )
1731  return SCIP_OKAY;
1732 
1733  /* set time limit for NLP solver */
1734  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelim) );
1735  if( !SCIPisInfinity(scip, timelim) )
1736  timelim -= SCIPgetSolvingTime(scip);
1737  /* possibly exit if time is up (need to check here, since the paramter has to be >= 0) */
1738  if ( timelim <= 0.0 )
1739  return SCIP_OKAY;
1740  SCIP_CALL( SCIPsetNLPRealPar(scip, SCIP_NLPPAR_TILIM, timelim) );
1741 
1742  *result = SCIP_DIDNOTFIND;
1743 
1744 #ifdef SCIP_DEBUG
1745  /* SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_VERBLEVEL, 1) ); */
1746 #endif
1747 
1748  /* set iteration limit */
1749  SCIP_CALL( SCIPgetNLPIntPar(scip, SCIP_NLPPAR_ITLIM, &origiterlim) );
1750  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_ITLIM, maxnnlpiterations - heurdata->nnlpiterations) );
1751 
1752  /* set whether NLP solver should fail fast */
1753  SCIP_CALL( SCIPgetNLPIntPar(scip, SCIP_NLPPAR_FASTFAIL, &origfastfail) );
1754  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_FASTFAIL, (int)heurdata->nlpfastfail) );
1755 
1756  /* set starting point to lp solution */
1757  SCIP_CALL( SCIPsetNLPInitialGuessSol(scip, NULL) );
1758 
1759  /* solve NLP relaxation, if not solved already */
1760  nlpsolstat = SCIPgetNLPSolstat(scip);
1761  if( nlpsolstat > SCIP_NLPSOLSTAT_FEASIBLE )
1762  {
1763  SCIP_NLPSTATISTICS* nlpstatistics;
1764 
1765  SCIP_CALL( SCIPsolveNLP(scip) );
1766  SCIPstatistic( ++heurdata->nnlpsolves );
1767 
1768  /* update iteration count */
1770  {
1771  SCIP_CALL( SCIPnlpStatisticsCreate(SCIPblkmem(scip), &nlpstatistics) );
1772  SCIP_CALL( SCIPgetNLPStatistics(scip, nlpstatistics) );
1773  heurdata->nnlpiterations += SCIPnlpStatisticsGetNIterations(nlpstatistics);
1774  SCIPnlpStatisticsFree(SCIPblkmem(scip), &nlpstatistics);
1775  }
1776 
1777  nlpsolstat = SCIPgetNLPSolstat(scip);
1778 
1779  /* give up, if no feasible solution found */
1780  if( nlpsolstat >= SCIP_NLPSOLSTAT_LOCINFEASIBLE )
1781  {
1782  SCIPdebugMsg(scip, "initial NLP infeasible or not solvable --> stop\n");
1783 
1784  SCIPstatistic(
1786  heurdata->nfailcutoff++;
1787  else
1788  heurdata->nfailnlperror++;
1789  )
1790 
1791  /* reset changed NLP parameters */
1792  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_ITLIM, origiterlim) );
1793  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_FASTFAIL, origfastfail) );
1794 
1795  return SCIP_OKAY;
1796  }
1797  }
1798 
1799  /* get NLP solution */
1800  SCIP_CALL( SCIPlinkNLPSol(scip, heurdata->sol) );
1801 
1802  /* get fractional variables that should be integral */
1803  SCIP_CALL( getNLPFracVars(scip, heurdata, &nlpcands, &nlpcandssol, &nlpcandsfrac, &nnlpcands) );
1804  assert(nnlpcands <= npseudocands);
1805 
1806  /* get LP candidates if LP solution is optimal */
1807  lpsolstat = SCIPgetLPSolstat(scip);
1808  if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
1809  nlpbranchcands = SCIPgetNLPBranchCands(scip);
1810  else
1811  nlpbranchcands = 0;
1812 
1813  /* don't try to dive, if there are no fractional variables */
1814  if( nnlpcands == 0 )
1815  {
1816  SCIP_Bool success;
1817 
1818  /* check, if solution was feasible and good enough
1819  *
1820  * Note that even if the NLP solver found a feasible solution it does not mean that is satisfy the integrality
1821  * conditions for fixed variables. This happens because the NLP solver uses relative tolerances for the bound
1822  * constraints but SCIP uses absolute tolerances for checking the integrality conditions.
1823  */
1824 #ifdef SCIP_DEBUG
1825  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, TRUE, TRUE, &success) );
1826 #else
1827  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, TRUE, TRUE, &success) );
1828 #endif
1829  if( success )
1830  {
1831  SCIPdebugMsg(scip, " -> solution of first NLP was integral, feasible, and good enough\n");
1832  *result = SCIP_FOUNDSOL;
1833  }
1834 
1835  /* reset changed NLP parameters */
1836  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_ITLIM, origiterlim) );
1837  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_FASTFAIL, origfastfail) );
1838 
1839  return SCIP_OKAY;
1840  }
1841 
1842  /* for guided diving: don't dive, if no feasible solutions exist */
1843  if( heurdata->varselrule == 'g' && SCIPgetNSols(scip) == 0 )
1844  return SCIP_OKAY;
1845 
1846  /* for guided diving: get best solution that should guide the search; if this solution lives in the original variable space,
1847  * we cannot use it since it might violate the global bounds of the current problem
1848  */
1849  if( heurdata->varselrule == 'g' && SCIPsolIsOriginal(SCIPgetBestSol(scip)) )
1850  return SCIP_OKAY;
1851 
1852  nlpstartsol = NULL;
1853  assert(nlpcandsfrac != NULL);
1854  assert(nlpcands != NULL);
1855  assert(nlpcandssol != NULL);
1856 
1857  /* save solution of first NLP, if we may use it later */
1858  if( heurdata->nlpstart != 'n' )
1859  {
1860  SCIP_CALL( SCIPcreateNLPSol(scip, &nlpstartsol, heur) );
1861  SCIP_CALL( SCIPunlinkSol(scip, nlpstartsol) );
1862  }
1863 
1864  /* calculate the objective search bound */
1865  if( SCIPgetNSolsFound(scip) == 0 )
1866  {
1867  if( heurdata->maxdiveubquotnosol > 0.0 )
1868  searchubbound = SCIPgetLowerbound(scip)
1869  + heurdata->maxdiveubquotnosol * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
1870  else
1871  searchubbound = SCIPinfinity(scip);
1872  if( heurdata->maxdiveavgquotnosol > 0.0 )
1873  searchavgbound = SCIPgetLowerbound(scip)
1874  + heurdata->maxdiveavgquotnosol * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
1875  else
1876  searchavgbound = SCIPinfinity(scip);
1877  }
1878  else
1879  {
1880  if( heurdata->maxdiveubquot > 0.0 )
1881  searchubbound = SCIPgetLowerbound(scip)
1882  + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
1883  else
1884  searchubbound = SCIPinfinity(scip);
1885  if( heurdata->maxdiveavgquot > 0.0 )
1886  searchavgbound = SCIPgetLowerbound(scip)
1887  + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
1888  else
1889  searchavgbound = SCIPinfinity(scip);
1890  }
1891  searchbound = MIN(searchubbound, searchavgbound);
1892  if( SCIPisObjIntegral(scip) )
1893  searchbound = SCIPceil(scip, searchbound);
1894 
1895  /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
1896  maxdivedepth = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
1897  maxdivedepth = MIN(maxdivedepth, maxdepth);
1898  maxdivedepth *= 10;
1899 
1900  covercomputed = FALSE;
1901  varincover = NULL;
1902 
1903  /* compute cover, if required */
1904  if( heurdata->prefercover || heurdata->solvesubmip )
1905  {
1906  SCIP_Real timelimit;
1907  SCIP_Real memorylimit;
1908 
1909  /* get limits */
1910  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
1911  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
1912  if( !SCIPisInfinity(scip, timelimit) )
1913  timelimit -= SCIPgetSolvingTime(scip);
1914 
1915  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1916  if( !SCIPisInfinity(scip, memorylimit) )
1917  {
1918  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1919  memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1920  }
1921 
1922  /* compute cover */
1923  ncovervars = -1;
1924  SCIP_CALL( SCIPallocBufferArray(scip, &covervars, SCIPgetNVars(scip)) );
1925  if( memorylimit > 2.0*SCIPgetMemExternEstim(scip)/1048576.0 && timelimit > 0.05 )
1926  {
1927  SCIP_CALL( SCIPcomputeCoverUndercover(scip, &ncovervars, covervars, timelimit, memorylimit, SCIPinfinity(scip), FALSE, FALSE, FALSE, 'u', &covercomputed) );
1928  }
1929 
1930  if( covercomputed )
1931  {
1932  /* a cover can be empty, if the cover computation reveals that all nonlinear constraints are linear w.r.t. current variable fixations */
1933  assert(ncovervars >= 0);
1934 
1935  /* create hash map */
1936  SCIP_CALL( SCIPhashmapCreate(&varincover, SCIPblkmem(scip), ncovervars) );
1937 
1938  /* process variables in the cover */
1939  for( c = 0; c < ncovervars; c++ )
1940  {
1941  /* insert variable into hash map */
1942  if( SCIPvarGetType(covervars[c]) < SCIP_VARTYPE_IMPLINT )
1943  {
1944  assert(!SCIPhashmapExists(varincover, covervars[c]));
1945  SCIP_CALL( SCIPhashmapInsert(varincover, covervars[c], (void*) (size_t) (c+1)) );
1946  }
1947 
1948  /* catch bound change events of cover variables */
1949  assert(heurdata->eventhdlr != NULL);
1950  SCIP_CALL( SCIPcatchVarEvent(scip, covervars[c], SCIP_EVENTTYPE_BOUNDCHANGED, heurdata->eventhdlr,
1951  (SCIP_EVENTDATA*) heurdata, NULL) );
1952  assert(!SCIPisFeasEQ(scip, SCIPvarGetLbLocal(covervars[c]), SCIPvarGetUbLocal(covervars[c])));
1953  }
1954  }
1955  }
1956  else
1957  {
1958  covervars = NULL;
1959  ncovervars = 0;
1960  }
1961 
1962  /* start diving */
1963  SCIP_CALL( SCIPstartProbing(scip) );
1964 
1965  /* enables collection of variable statistics during probing */
1966  SCIPenableVarHistory(scip);
1967 
1968  /* get NLP objective value*/
1969  objval = SCIPgetNLPObjval(scip);
1970 
1971  SCIPdebugMsg(scip, "(node %" SCIP_LONGINT_FORMAT ") executing nlpdiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
1972  SCIPgetNNodes(scip), SCIPgetDepth(scip), nnlpcands, SCIPgetDualbound(scip), SCIPretransformObj(scip, searchbound));
1973 
1974  /* store a copy of the best solution, if guided diving should be used */
1975  if( heurdata->varselrule == 'g' )
1976  {
1977  assert(SCIPgetNSols(scip) > 0);
1978  assert(!SCIPsolIsOriginal(SCIPgetBestSol(scip)));
1979 
1980  SCIP_CALL( SCIPcreateSolCopy(scip, &bestsol, SCIPgetBestSol(scip)) );
1981  }
1982 
1983  /* if double diving should be used, create arrays to hold to entire LP and NLP solution */
1984  if( heurdata->varselrule == 'd' )
1985  {
1986  SCIP_CALL( SCIPallocBufferArray(scip, &pseudocandslpsol, npseudocands) );
1987  SCIP_CALL( SCIPallocBufferArray(scip, &pseudocandsnlpsol, npseudocands) );
1988  }
1989 
1990  /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
1991  * - if possible, we dive at least with the depth 10
1992  * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
1993  */
1994  nlperror = FALSE;
1995  lperror = FALSE;
1996  cutoff = FALSE;
1997  divedepth = 0;
1998  lastnlpsolvedepth = 0;
1999  backtracked = FALSE; /* whether we are in backtracking */
2000  fixquot = heurdata->fixquot;
2001  nfeasnlps = 1;
2002  startnnlpcands = nnlpcands;
2003  solvesubmip = heurdata->solvesubmip;
2004 
2005  while( !nlperror && !cutoff && (nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE || nlpsolstat == SCIP_NLPSOLSTAT_UNKNOWN) && nnlpcands > 0
2006  && (nfeasnlps < heurdata->maxfeasnlps
2007  || nnlpcands <= startnnlpcands - divedepth/2
2008  || (nfeasnlps < maxdivedepth && heurdata->nnlpiterations < maxnnlpiterations && objval < searchbound))
2009  && !SCIPisStopped(scip) )
2010  {
2011  SCIP_VAR* var;
2012  SCIP_Bool updatepscost;
2013 
2014  /* open a new probing node if this will not exceed the maximal tree depth, otherwise stop here */
2015  if( SCIPgetDepth(scip) < SCIP_MAXTREEDEPTH )
2016  {
2017  SCIP_CALL( SCIPnewProbingNode(scip) );
2018  divedepth++;
2019  }
2020  else
2021  break;
2022 
2023  bestcand = -1;
2024  bestcandmayround = TRUE;
2025  bestcandroundup = FALSE;
2026  bestboundval = SCIP_INVALID;
2027  updatepscost = TRUE;
2028  var = NULL;
2029 
2030  /* find best candidate variable */
2031  switch( heurdata->varselrule )
2032  {
2033  case 'c':
2034  SCIP_CALL( chooseCoefVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2035  &bestcand, &bestcandmayround, &bestcandroundup) );
2036  if( bestcand >= 0 )
2037  {
2038  var = nlpcands[bestcand];
2039  bestboundval = nlpcandssol[bestcand];
2040  }
2041  break;
2042  case 'v':
2043  SCIP_CALL( chooseVeclenVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2044  &bestcand, &bestcandmayround, &bestcandroundup) );
2045  if( bestcand >= 0 )
2046  {
2047  var = nlpcands[bestcand];
2048  bestboundval = nlpcandssol[bestcand];
2049  }
2050  break;
2051  case 'p':
2052  SCIP_CALL( choosePscostVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2053  &bestcand, &bestcandmayround, &bestcandroundup) );
2054  if( bestcand >= 0 )
2055  {
2056  var = nlpcands[bestcand];
2057  bestboundval = nlpcandssol[bestcand];
2058  }
2059  break;
2060  case 'g':
2061  SCIP_CALL( chooseGuidedVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, bestsol, varincover, covercomputed,
2062  &bestcand, &bestcandmayround, &bestcandroundup) );
2063  if( bestcand >= 0 )
2064  {
2065  var = nlpcands[bestcand];
2066  bestboundval = nlpcandssol[bestcand];
2067  }
2068  break;
2069  case 'd':
2070  /* double diving only works if we have both relaxations at hand, otherwise we fall back to fractional diving */
2071  if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
2072  {
2073  SCIP_VAR** pseudocands;
2074 
2075  SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, &npseudocands, NULL) );
2076  assert(backtrackdepth > 0 || nnlpcands <= npseudocands);
2077  assert(SCIPgetNLPBranchCands(scip) <= npseudocands);
2078  SCIP_CALL( SCIPgetSolVals(scip, NULL, npseudocands, pseudocands, pseudocandslpsol) );
2079  SCIP_CALL( SCIPgetSolVals(scip, heurdata->sol, npseudocands, pseudocands, pseudocandsnlpsol) );
2080  SCIP_CALL( chooseDoubleVar(scip, heurdata, pseudocands, pseudocandsnlpsol, pseudocandslpsol, npseudocands,
2081  varincover, covercomputed, &bestcand, &bestboundval, &bestcandmayround, &bestcandroundup) );
2082  if( bestcand >= 0 )
2083  var = pseudocands[bestcand];
2084  break;
2085  }
2086  else
2087  updatepscost = FALSE;
2088  /*lint -fallthrough*/
2089  case 'f':
2090  SCIP_CALL( chooseFracVar(scip, heurdata, nlpcands, nlpcandssol, nlpcandsfrac, nnlpcands, varincover, covercomputed,
2091  &bestcand, &bestcandmayround, &bestcandroundup) );
2092  if( bestcand >= 0 )
2093  {
2094  var = nlpcands[bestcand];
2095  bestboundval = nlpcandssol[bestcand];
2096  }
2097  break;
2098  default:
2099  SCIPerrorMessage("invalid variable selection rule\n");
2100  return SCIP_INVALIDDATA;
2101  }
2102 
2103  /* if all candidates are roundable, try to round the solution
2104  * if var == NULL (i.e., bestcand == -1), then all solution candidates are outside bounds
2105  * this should only happen if they are slightly outside bounds (i.e., still within feastol, relative tolerance),
2106  * but far enough out to be considered as fractional (within feastol, but using absolute tolerance)
2107  * in this case, we also try our luck with rounding
2108  */
2109  if( (var == NULL || bestcandmayround) && backtrackdepth == -1 )
2110  {
2111  SCIP_Bool success;
2112 
2113  /* create solution from diving NLP and try to round it */
2114  SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
2115 
2116  if( success )
2117  {
2118  SCIPdebugMsg(scip, "nlpdiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
2119 
2120  /* try to add solution to SCIP */
2121 #ifdef SCIP_DEBUG
2122  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, FALSE, TRUE, &success) );
2123 #else
2124  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, TRUE, &success) );
2125 #endif
2126 
2127  /* check, if solution was feasible and good enough */
2128  if( success )
2129  {
2130  SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
2131  *result = SCIP_FOUNDSOL;
2132  }
2133  }
2134  }
2135 
2136  /* if all variables have been found to be essentially integral (even though there is some numerical doubt, see comment above), then stop */
2137  if( var == NULL )
2138  break;
2139 
2140  do
2141  {
2142  SCIP_Real frac;
2143  frac = SCIP_INVALID;
2144 
2145  if( backtracked && backtrackdepth > 0 )
2146  {
2147  assert(backtrackvar != NULL);
2148 
2149  /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
2150  * occured or variable was fixed by propagation while backtracking => Abort diving!
2151  */
2152  if( SCIPvarGetLbLocal(backtrackvar) >= SCIPvarGetUbLocal(backtrackvar) - 0.5 )
2153  {
2154  SCIPdebugMsg(scip, "Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
2155  SCIPvarGetName(backtrackvar), SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar), backtrackvarval);
2156  cutoff = TRUE;
2157  break;
2158  }
2159  if( SCIPisFeasLT(scip, backtrackvarval, SCIPvarGetLbLocal(backtrackvar)) || SCIPisFeasGT(scip, backtrackvarval, SCIPvarGetUbLocal(backtrackvar)) )
2160  {
2161  SCIPdebugMsg(scip, "selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
2162  SCIPvarGetName(backtrackvar), SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar), backtrackvarval);
2163  assert(backtracked);
2164  break;
2165  }
2166 
2167  /* round backtrack variable up or down */
2168  if( backtrackroundup )
2169  {
2170  SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2171  divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2172  SCIPvarGetName(backtrackvar), backtrackvarval, SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar),
2173  SCIPfeasCeil(scip, backtrackvarval), SCIPvarGetUbLocal(backtrackvar));
2174  SCIP_CALL( SCIPchgVarLbProbing(scip, backtrackvar, SCIPfeasCeil(scip, backtrackvarval)) );
2175  }
2176  else
2177  {
2178  SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2179  divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2180  SCIPvarGetName(backtrackvar), backtrackvarval, SCIPvarGetLbLocal(backtrackvar), SCIPvarGetUbLocal(backtrackvar),
2181  SCIPvarGetLbLocal(backtrackvar), SCIPfeasFloor(scip, backtrackvarval));
2182  SCIP_CALL( SCIPchgVarUbProbing(scip, backtrackvar, SCIPfeasFloor(scip, backtrackvarval)) );
2183  }
2184 
2185  /* forget about backtrack variable */
2186  backtrackdepth = -1;
2187 
2188  /* for pseudo cost computation */
2189  bestcandroundup = backtrackroundup;
2190  frac = SCIPfrac(scip, backtrackvarval);
2191  var = backtrackvar;
2192  }
2193  else
2194  {
2195  assert(var != NULL);
2196 
2197  /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
2198  * occured or variable was fixed by propagation while backtracking => Abort diving!
2199  */
2200  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
2201  {
2202  SCIPdebugMsg(scip, "Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
2203  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), bestboundval);
2204  cutoff = TRUE;
2205  break;
2206  }
2207  if( SCIPisFeasLT(scip, bestboundval, SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, bestboundval, SCIPvarGetUbLocal(var)) )
2208  {
2209  SCIPdebugMsg(scip, "selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
2210  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), bestboundval);
2211  assert(backtracked);
2212  break;
2213  }
2214 
2215  /* apply rounding of best candidate */
2216  if( bestcandroundup == !backtracked )
2217  {
2218  /* round variable up */
2219  SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, round=%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2220  divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2221  SCIPvarGetName(var), bestcandmayround,
2222  bestboundval, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
2223  SCIPfeasCeil(scip, bestboundval), SCIPvarGetUbLocal(var));
2224  SCIP_CALL( SCIPchgVarLbProbing(scip, var, SCIPfeasCeil(scip, bestboundval)) );
2225 
2226  /* remember variable for backtracking, if we have none yet (e.g., we are just after NLP solve) or we are half way to the next NLP solve */
2227  if( backtrackdepth == -1 || (divedepth - lastnlpsolvedepth == (int)(MIN(fixquot * nnlpcands, nlpbranchcands)/2.0)) )
2228  {
2229  backtrackdepth = divedepth;
2230  backtrackvar = var;
2231  backtrackvarval = bestboundval;
2232  backtrackroundup = FALSE;
2233  }
2234  }
2235  else
2236  {
2237  /* round variable down */
2238  SCIPdebugMsg(scip, " dive %d/%d, NLP iter %d/%d: var <%s>, round=%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
2239  divedepth, maxdivedepth, heurdata->nnlpiterations, maxnnlpiterations,
2240  SCIPvarGetName(var), bestcandmayround,
2241  bestboundval, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
2242  SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, bestboundval));
2243  SCIP_CALL( SCIPchgVarUbProbing(scip, var, SCIPfeasFloor(scip, bestboundval)) );
2244 
2245  /* remember variable for backtracking, if we have none yet (e.g., we are just after NLP solve) or we are half way to the next NLP solve */
2246  if( backtrackdepth == -1 || (divedepth - lastnlpsolvedepth == (int)(MIN(fixquot * nnlpcands, nlpbranchcands)/2.0)) )
2247  {
2248  backtrackdepth = divedepth;
2249  backtrackvar = var;
2250  backtrackvarval = bestboundval;
2251  backtrackroundup = TRUE;
2252  }
2253  }
2254 
2255  /* for pseudo-cost computation */
2256  if( updatepscost && SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL )
2257  {
2258  if( heurdata->varselrule == 'd' )
2259  {
2260  assert(pseudocandsnlpsol != NULL);
2261  assert(0 <= bestcand && bestcand < npseudocands);
2262  frac = SCIPfrac(scip, pseudocandsnlpsol[bestcand]);
2263  }
2264  else
2265  frac = nlpcandsfrac[bestcand];
2266  }
2267  }
2268 
2269  /* apply domain propagation */
2270  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
2271  if( cutoff )
2272  {
2273  SCIPdebugMsg(scip, " *** cutoff detected in propagation at level %d\n", SCIPgetProbingDepth(scip));
2274  }
2275 
2276  /* if all variables in the cover are fixed or there is no fractional variable in the cover,
2277  * then solve a sub-MIP
2278  */
2279  if( !cutoff && solvesubmip && covercomputed &&
2280  (heurdata->nfixedcovervars == ncovervars ||
2281  (heurdata->nfixedcovervars >= (ncovervars+1)/2 && !SCIPhashmapExists(varincover, var))) )
2282  {
2283  int probingdepth;
2284 
2285  solvesubmip = FALSE;
2286  probingdepth = SCIPgetProbingDepth(scip);
2287  assert(probingdepth >= 1);
2288  assert(covervars != NULL);
2289 
2290  if( heurdata->nfixedcovervars != ncovervars )
2291  {
2292  /* fix all remaining cover variables */
2293  for( c = 0; c < ncovervars && !cutoff ; c++ )
2294  {
2295  SCIP_Real lb;
2296  SCIP_Real ub;
2297  lb = SCIPvarGetLbLocal(covervars[c]);
2298  ub = SCIPvarGetUbLocal(covervars[c]);
2299  if( !SCIPisFeasEQ(scip, lb, ub) )
2300  {
2301  SCIP_Real nlpsolval;
2302 
2303  /* adopt lpsolval w.r.t. intermediate bound changes by propagation */
2304  nlpsolval = SCIPvarGetNLPSol(covervars[c]);
2305  nlpsolval = MIN(nlpsolval,ub);
2306  nlpsolval = MAX(nlpsolval,lb);
2307  assert(SCIPvarGetType(covervars[c]) == SCIP_VARTYPE_CONTINUOUS || SCIPisFeasIntegral(scip, nlpsolval));
2308 
2309  /* open a new probing node if this will not exceed the maximal tree depth,
2310  * otherwise fix all the remaining variables at the same probing node
2311  * @todo do we need a new probing node for each fixing? if one of these fixings leads to a cutoff
2312  * we backtrack to the last probing node before we started to fix the covervars (and we do
2313  * not solve the probing LP). thus, it would be less work load in SCIPendProbing
2314  * and SCIPbacktrackProbing.
2315  */
2316  if( SCIP_MAXTREEDEPTH > SCIPgetDepth(scip) )
2317  {
2318  SCIP_CALL( SCIPnewProbingNode(scip) );
2319  }
2320 
2321  /* fix and propagate */
2322  assert(SCIPisLbBetter(scip, nlpsolval, lb, ub) || SCIPisUbBetter(scip, nlpsolval, lb, ub));
2323 
2324  if( SCIPisLbBetter(scip, nlpsolval, lb, ub) )
2325  {
2326  SCIP_CALL( SCIPchgVarLbProbing(scip, covervars[c], nlpsolval) );
2327  }
2328  if( SCIPisUbBetter(scip, nlpsolval, lb, ub) )
2329  {
2330  SCIP_CALL( SCIPchgVarUbProbing(scip, covervars[c], nlpsolval) );
2331  }
2332 
2333  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
2334  }
2335  }
2336  }
2337 
2338  /* solve sub-MIP or return to standard diving */
2339  if( cutoff )
2340  {
2341  SCIP_CALL( SCIPbacktrackProbing(scip, probingdepth) );
2342  }
2343  else
2344  {
2345  SCIP_Bool success;
2346  success = FALSE;
2347 
2348  SCIP_CALL( solveSubMIP(scip, heur, covervars, ncovervars, &success));
2349  if( success )
2350  *result = SCIP_FOUNDSOL;
2351  backtracked = TRUE; /* to avoid backtracking */
2352  nnlpcands = 0; /* to force termination */
2353  cutoff = TRUE;
2354  }
2355  }
2356 
2357  /* resolve the diving LP */
2358  if( !cutoff && !lperror && (heurdata->lp || heurdata->varselrule == 'd')
2360  {
2361  SCIP_CALL( SCIPsolveProbingLP(scip, 100, &lperror, &cutoff) );
2362 
2363  /* get LP solution status, objective value, and fractional variables, that should be integral */
2364  lpsolstat = SCIPgetLPSolstat(scip);
2365  assert(cutoff || (lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT && lpsolstat != SCIP_LPSOLSTAT_INFEASIBLE &&
2366  (lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || SCIPisLT(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)))));
2367 
2368  if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
2369  {
2370  nlpbranchcands = SCIPgetNLPBranchCands(scip);
2371 
2372  /* get new objective value */
2373  oldobjval = objval;
2374  objval = SCIPgetLPObjval(scip);
2375 
2376  /* update pseudo cost values */
2377  if( updatepscost && SCIPisGT(scip, objval, oldobjval) )
2378  {
2379  assert(frac != SCIP_INVALID); /*lint !e777*/
2380  if( bestcandroundup )
2381  {
2382  SCIP_CALL( SCIPupdateVarPseudocost(scip, var, 1.0-frac, objval - oldobjval, 1.0) );
2383  }
2384  else
2385  {
2386  SCIP_CALL( SCIPupdateVarPseudocost(scip, var, 0.0-frac, objval - oldobjval, 1.0) );
2387  }
2388  }
2389  }
2390  else
2391  {
2392  nlpbranchcands = 0;
2393  }
2394 
2395  if( cutoff )
2396  {
2397  SCIPdebugMsg(scip, " *** cutoff detected in LP solving at level %d, lpsolstat = %d\n", SCIPgetProbingDepth(scip), lpsolstat);
2398  }
2399  }
2400  else
2401  lpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
2402 
2403  /* check whether we want to solve the NLP, which is the case if
2404  * - we are in backtracking, or
2405  * - we have (actively) fixed/rounded fixquot*nnlpcands variables
2406  * - all fractional variables were rounded/fixed (due to fixing and domain propagation)
2407  */
2408  solvenlp = backtracked;
2409  if( !solvenlp && !cutoff )
2410  {
2411  solvenlp = (lastnlpsolvedepth < divedepth - fixquot * nnlpcands);
2412  if( !solvenlp )
2413  {
2414  /* check if fractional NLP variables are left (some may have been fixed by propagation) */
2415  for( c = 0; c < nnlpcands; ++c )
2416  {
2417  var = nlpcands[c];
2418  if( SCIPisLT(scip, nlpcandssol[c], SCIPvarGetLbLocal(var)) || SCIPisGT(scip, nlpcandssol[c], SCIPvarGetUbLocal(var)) )
2419  continue;
2420  else
2421  break;
2422  }
2423  if( c == nnlpcands )
2424  solvenlp = TRUE;
2425  }
2426  }
2427 
2428  nlpsolstat = SCIP_NLPSOLSTAT_UNKNOWN;
2429 
2430  /* resolve the diving NLP */
2431  if( !cutoff && solvenlp )
2432  {
2433  SCIP_NLPTERMSTAT termstat;
2434  SCIP_NLPSTATISTICS* nlpstatistics;
2435 
2436  /* set iteration limit, allow at least MINNLPITER many iterations */
2437  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_ITLIM, MAX(maxnnlpiterations - heurdata->nnlpiterations, MINNLPITER)) );
2438 
2439  /* set time limit for NLP solver */
2440  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelim) );
2441  if( !SCIPisInfinity(scip, timelim) )
2442  timelim = MAX(0.0, timelim-SCIPgetSolvingTime(scip));/*lint !e666*/
2443  SCIP_CALL( SCIPsetNLPRealPar(scip, SCIP_NLPPAR_TILIM, timelim) );
2444 
2445  /* set start solution, if we are in backtracking (previous NLP solve was infeasible) */
2446  if( heurdata->nlpstart != 'n' && backtracked )
2447  {
2448  assert(nlpstartsol != NULL);
2449 
2450  SCIPdebugMsg(scip, "setting NLP initial guess\n");
2451 
2452  SCIP_CALL( SCIPsetNLPInitialGuessSol(scip, nlpstartsol) );
2453  }
2454 
2455  SCIP_CALL( SCIPsolveNLP(scip) );
2456  SCIPstatistic( ++heurdata->nnlpsolves );
2457 
2458  termstat = SCIPgetNLPTermstat(scip);
2459  if( termstat >= SCIP_NLPTERMSTAT_NUMERR )
2460  {
2461  if( termstat >= SCIP_NLPTERMSTAT_LICERR )
2462  {
2464  "Error while solving NLP in nlpdiving heuristic; NLP solve terminated with code <%d>\n", termstat);
2465  }
2466  nlperror = TRUE;
2467  break;
2468  }
2469 
2470  /* update iteration count */
2471  SCIP_CALL( SCIPnlpStatisticsCreate(SCIPblkmem(scip), &nlpstatistics) );
2472  SCIP_CALL( SCIPgetNLPStatistics(scip, nlpstatistics) );
2473  heurdata->nnlpiterations += SCIPnlpStatisticsGetNIterations(nlpstatistics);
2474  SCIPnlpStatisticsFree(SCIPblkmem(scip), &nlpstatistics);
2475 
2476  /* get NLP solution status, objective value, and fractional variables, that should be integral */
2477  nlpsolstat = SCIPgetNLPSolstat(scip);
2478  cutoff = (nlpsolstat > SCIP_NLPSOLSTAT_FEASIBLE);
2479 
2480  if( cutoff )
2481  {
2482  SCIPdebugMsg(scip, " *** cutoff detected in NLP solving at level %d, nlpsolstat: %d\n", SCIPgetProbingDepth(scip), nlpsolstat);
2483  }
2484  else
2485  {
2486  SCIP_CALL( SCIPlinkNLPSol(scip, heurdata->sol) );
2487 
2488  /* remember that we have solve NLP on this depth successfully */
2489  lastnlpsolvedepth = divedepth;
2490  /* forget previous backtrack variable, we will never go back to a depth before the current one */
2491  backtrackdepth = -1;
2492  /* store NLP solution for warmstarting, if nlpstart is 'f' */
2493  if( heurdata->nlpstart == 'f' )
2494  {
2495  assert(nlpstartsol != NULL);
2496 
2497  /* copy NLP solution values into nlpstartsol, is there a better way to do this???? */
2498  SCIP_CALL( SCIPlinkNLPSol(scip, nlpstartsol) );
2499  SCIP_CALL( SCIPunlinkSol(scip, nlpstartsol) );
2500  }
2501  /* increase counter on number of NLP solves with feasible solution */
2502  ++nfeasnlps;
2503  }
2504  }
2505 
2506  /* perform backtracking if a cutoff was detected */
2507  if( cutoff && !backtracked && heurdata->backtrack )
2508  {
2509  if( backtrackdepth == -1 )
2510  {
2511  /* backtrack one step */
2512  SCIPdebugMsg(scip, " *** cutoff detected at level %d - backtracking one step\n", SCIPgetProbingDepth(scip));
2514 
2515  /* after backtracking there has to be at least one open node without exceeding the maximal tree depth */
2516  assert(SCIP_MAXTREEDEPTH > SCIPgetDepth(scip));
2517 
2518  SCIP_CALL( SCIPnewProbingNode(scip) );
2519  }
2520  else
2521  {
2522  /* if we have a stored a depth for backtracking, go there */
2523  SCIPdebugMsg(scip, " *** cutoff detected at level %d - backtracking to depth %d\n", SCIPgetProbingDepth(scip), backtrackdepth);
2524  SCIP_CALL( SCIPbacktrackProbing(scip, backtrackdepth-1) );
2525 
2526  /* after backtracking there has to be at least one open node without exceeding the maximal tree depth */
2527  assert(SCIP_MAXTREEDEPTH > SCIPgetDepth(scip));
2528 
2529  SCIP_CALL( SCIPnewProbingNode(scip) );
2530  divedepth = backtrackdepth;
2531 
2532  /* do not update pseudocosts if backtracking by more than one level */
2533  updatepscost = FALSE;
2534 
2535  /* in case, we are feasible after backtracking, fix less variables at once in continuing diving
2536  * @todo should we remember the fixquot in heurdata for the next run?
2537  */
2538  fixquot *= 0.5;
2539  }
2540  /* remember that we are backtracking now */
2541  backtracked = TRUE;
2542  }
2543  else
2544  backtracked = FALSE;
2545  }
2546  while( backtracked );
2547 
2548  if( !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2549  {
2550  /* get new fractional variables */
2551  SCIP_CALL( getNLPFracVars(scip, heurdata, &nlpcands, &nlpcandssol, &nlpcandsfrac, &nnlpcands) );
2552  }
2553  SCIPdebugMsg(scip, " -> nlpsolstat=%d, objval=%g/%g, nfrac nlp=%d lp=%d\n", nlpsolstat, objval, searchbound, nnlpcands, nlpbranchcands);
2554  }
2555 
2556  /*lint --e{774}*/
2557  SCIPdebugMsg(scip, "NLP nlpdiving ABORT due to ");
2558  if( nlperror || (nlpsolstat > SCIP_NLPSOLSTAT_LOCINFEASIBLE && nlpsolstat != SCIP_NLPSOLSTAT_UNKNOWN) )
2559  {
2560  SCIPdebugMsgPrint(scip, "NLP bad status - nlperror: %ud nlpsolstat: %d \n", nlperror, nlpsolstat);
2561  SCIPstatistic( heurdata->nfailnlperror++ );
2562  }
2563  else if( SCIPisStopped(scip) || cutoff )
2564  {
2565  SCIPdebugMsgPrint(scip, "LIMIT hit - stop: %ud cutoff: %ud \n", SCIPisStopped(scip), cutoff);
2566  SCIPstatistic( heurdata->nfailcutoff++ );
2567  }
2568  else if(! (divedepth < 10
2569  || nnlpcands <= startnnlpcands - divedepth/2
2570  || (divedepth < maxdivedepth && heurdata->nnlpiterations < maxnnlpiterations && objval < searchbound) ) )
2571  {
2572  SCIPdebugMsgPrint(scip, "TOO DEEP - divedepth: %4d cands halfed: %d ltmaxdepth: %d ltmaxiter: %d bound: %d\n", divedepth,
2573  (nnlpcands > startnnlpcands - divedepth/2), (divedepth >= maxdivedepth), (heurdata->nnlpiterations >= maxnnlpiterations),
2574  (objval >= searchbound));
2575  SCIPstatistic( heurdata->nfaildepth++ );
2576  }
2577  else if( nnlpcands == 0 && !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2578  {
2579  SCIPdebugMsgPrint(scip, "SUCCESS\n");
2580  }
2581  else
2582  {
2583  SCIPdebugMsgPrint(scip, "UNKNOWN, very mysterical reason\n"); /* see also special case var == NULL (bestcand == -1) after choose*Var above */
2584  }
2585 
2586  /* check if a solution has been found */
2587  if( nnlpcands == 0 && !nlperror && !cutoff && nlpsolstat <= SCIP_NLPSOLSTAT_FEASIBLE )
2588  {
2589  SCIP_Bool success;
2590 
2591  /* create solution from diving NLP */
2592  SCIPdebugMsg(scip, "nlpdiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
2593 
2594  /* try to add solution to SCIP
2595  *
2596  * Note that even if the NLP solver found a feasible solution it does not mean that is satisfy the integrality
2597  * conditions for fixed variables. This happens because the NLP solver uses relative tolerances for the bound
2598  * constraints but SCIP uses absolute tolerances for checking the integrality conditions.
2599  */
2600 #ifdef SCIP_DEBUG
2601  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, TRUE, TRUE, FALSE, TRUE, TRUE, &success) );
2602 #else
2603  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, TRUE, TRUE, &success) );
2604 #endif
2605 
2606  /* check, if solution was feasible and good enough */
2607  if( success )
2608  {
2609  SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
2610  *result = SCIP_FOUNDSOL;
2611  }
2612  else
2613  {
2614  SCIPdebugMsg(scip, " -> solution was not accepted\n");
2615  }
2616  }
2617 
2618  /* end diving */
2619  SCIP_CALL( SCIPendProbing(scip) );
2620 
2621  /* free hash map and drop variable bound change events */
2622  if( covercomputed )
2623  {
2624  assert(heurdata->eventhdlr != NULL);
2625  assert(heurdata->nfixedcovervars >= 0); /* variables might have been globally fixed in propagation */
2626  assert(varincover != NULL);
2627  assert(covervars != NULL);
2628 
2629  SCIPhashmapFree(&varincover);
2630 
2631  /* drop bound change events of cover variables */
2632  for( c = 0; c < ncovervars; c++ )
2633  {
2634  SCIP_CALL( SCIPdropVarEvent(scip, covervars[c], SCIP_EVENTTYPE_BOUNDCHANGED, heurdata->eventhdlr, (SCIP_EVENTDATA*)heurdata, -1) );
2635  }
2636  }
2637  else
2638  assert(varincover == NULL);
2639 
2640  /* free array of cover variables */
2641  if( heurdata->prefercover || heurdata->solvesubmip )
2642  {
2643  assert(covervars != NULL || !covercomputed);
2644  if( covervars != NULL )
2645  SCIPfreeBufferArray(scip, &covervars);
2646  }
2647  else
2648  assert(covervars == NULL);
2649 
2650  /* free NLP start solution */
2651  if( nlpstartsol != NULL )
2652  {
2653  SCIP_CALL( SCIPfreeSol(scip, &nlpstartsol) );
2654  }
2655 
2656  /* reset changed NLP parameters */
2657  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_ITLIM, origiterlim) );
2658  SCIP_CALL( SCIPsetNLPIntPar(scip, SCIP_NLPPAR_FASTFAIL, origfastfail) );
2659 
2660  /* free copied best solution */
2661  if( heurdata->varselrule == 'g' )
2662  {
2663  assert(bestsol != NULL);
2664  SCIP_CALL( SCIPfreeSol(scip, &bestsol) );
2665  }
2666  else
2667  assert(bestsol == NULL);
2668 
2669  /* free arrays of LP and NLP solution */
2670  if( heurdata->varselrule == 'd' )
2671  {
2672  assert(pseudocandsnlpsol != NULL);
2673  assert(pseudocandsnlpsol != NULL);
2674  SCIPfreeBufferArray(scip, &pseudocandslpsol);
2675  SCIPfreeBufferArray(scip, &pseudocandsnlpsol);
2676  }
2677  else
2678  {
2679  assert(pseudocandsnlpsol == NULL);
2680  assert(pseudocandsnlpsol == NULL);
2681  }
2682 
2683  if( *result == SCIP_FOUNDSOL )
2684  heurdata->nsuccess++;
2685 
2686  SCIPdebugMsg(scip, "nlpdiving heuristic finished\n");
2687 
2688  return SCIP_OKAY;
2689 }
2690 
2691 
2692 /*
2693  * heuristic specific interface methods
2694  */
2695 
2696 /** creates the nlpdiving heuristic and includes it in SCIP */
2698  SCIP* scip /**< SCIP data structure */
2699  )
2700 {
2701  SCIP_HEURDATA* heurdata;
2702  SCIP_HEUR* heur = NULL;
2703 
2704  /* create heuristic data */
2705  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
2706 
2707  /* include heuristic */
2709  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecNlpdiving, heurdata) );
2710 
2711  assert(heur != NULL);
2712  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyNlpdiving) );
2713  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeNlpdiving) );
2714  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitNlpdiving) );
2715  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitNlpdiving) );
2716  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolNlpdiving) );
2717 
2718  /* get event handler for bound change events */
2719  heurdata->eventhdlr = NULL;
2720  /* create event handler for bound change events */
2721  SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &heurdata->eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC,
2722  eventExecNlpdiving, NULL) );
2723  if ( heurdata->eventhdlr == NULL )
2724  {
2725  SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
2726  return SCIP_PLUGINNOTFOUND;
2727  }
2728 
2729  /* nlpdiving heuristic parameters */
2731  "heuristics/" HEUR_NAME "/minreldepth",
2732  "minimal relative depth to start diving",
2733  &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
2735  "heuristics/" HEUR_NAME "/maxreldepth",
2736  "maximal relative depth to start diving",
2737  &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
2738  SCIP_CALL( SCIPaddIntParam(scip,
2739  "heuristics/" HEUR_NAME "/maxnlpiterabs",
2740  "minimial absolute number of allowed NLP iterations",
2741  &heurdata->maxnlpiterabs, FALSE, DEFAULT_MAXNLPITERABS, 0, INT_MAX, NULL, NULL) );
2742  SCIP_CALL( SCIPaddIntParam(scip,
2743  "heuristics/" HEUR_NAME "/maxnlpiterrel",
2744  "additional allowed number of NLP iterations relative to successfully found solutions",
2745  &heurdata->maxnlpiterrel, FALSE, DEFAULT_MAXNLPITERREL, 0, INT_MAX, NULL, NULL) );
2747  "heuristics/" HEUR_NAME "/maxdiveubquot",
2748  "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
2749  &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
2751  "heuristics/" HEUR_NAME "/maxdiveavgquot",
2752  "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
2753  &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2755  "heuristics/" HEUR_NAME "/maxdiveubquotnosol",
2756  "maximal UBQUOT when no solution was found yet (0.0: no limit)",
2757  &heurdata->maxdiveubquotnosol, TRUE, DEFAULT_MAXDIVEUBQUOTNOSOL, 0.0, 1.0, NULL, NULL) );
2759  "heuristics/" HEUR_NAME "/maxdiveavgquotnosol",
2760  "maximal AVGQUOT when no solution was found yet (0.0: no limit)",
2761  &heurdata->maxdiveavgquotnosol, TRUE, DEFAULT_MAXDIVEAVGQUOTNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
2762  SCIP_CALL( SCIPaddIntParam(scip,
2763  "heuristics/" HEUR_NAME "/maxfeasnlps",
2764  "maximal number of NLPs with feasible solution to solve during one dive",
2765  &heurdata->maxfeasnlps, FALSE, DEFAULT_MAXFEASNLPS, 1, INT_MAX, NULL, NULL) );
2767  "heuristics/" HEUR_NAME "/backtrack",
2768  "use one level of backtracking if infeasibility is encountered?",
2769  &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
2771  "heuristics/" HEUR_NAME "/lp",
2772  "should the LP relaxation be solved before the NLP relaxation?",
2773  &heurdata->lp, TRUE, DEFAULT_LP, NULL, NULL) );
2775  "heuristics/" HEUR_NAME "/preferlpfracs",
2776  "prefer variables that are also fractional in LP solution?",
2777  &heurdata->preferlpfracs, TRUE, DEFAULT_PREFERLPFRACS, NULL, NULL) );
2779  "heuristics/" HEUR_NAME "/minsuccquot",
2780  "heuristic will not run if less then this percentage of calls succeeded (0.0: no limit)",
2781  &heurdata->minsuccquot, FALSE, DEFAULT_MINSUCCQUOT, 0.0, 1.0, NULL, NULL) );
2783  "heuristics/" HEUR_NAME "/fixquot",
2784  "percentage of fractional variables that should be fixed before the next NLP solve",
2785  &heurdata->fixquot, FALSE, DEFAULT_FIXQUOT, 0.0, 1.0, NULL, NULL) );
2787  "heuristics/" HEUR_NAME "/prefercover",
2788  "should variables in a minimal cover be preferred?",
2789  &heurdata->prefercover, FALSE, DEFAULT_PREFERCOVER, NULL, NULL) );
2791  "heuristics/" HEUR_NAME "/solvesubmip",
2792  "should a sub-MIP be solved if all cover variables are fixed?",
2793  &heurdata->solvesubmip, FALSE, DEFAULT_SOLVESUBMIP, NULL, NULL) );
2795  "heuristics/" HEUR_NAME "/nlpfastfail",
2796  "should the NLP solver stop early if it converges slow?",
2797  &heurdata->nlpfastfail, FALSE, DEFAULT_NLPFASTFAIL, NULL, NULL) );
2799  "heuristics/" HEUR_NAME "/nlpstart",
2800  "which point should be used as starting point for the NLP solver? ('n'one, last 'f'easible, from dive's'tart)",
2801  &heurdata->nlpstart, TRUE, DEFAULT_NLPSTART, "fns", NULL, NULL) );
2803  "heuristics/" HEUR_NAME "/varselrule",
2804  "which variable selection should be used? ('f'ractionality, 'c'oefficient, 'p'seudocost, 'g'uided, 'd'ouble, 'v'eclen)",
2805  &heurdata->varselrule, FALSE, DEFAULT_VARSELRULE, "fcpgdv", NULL, NULL) );
2806 
2807  return SCIP_OKAY;
2808 }
#define HEUR_FREQOFS
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2465
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
Definition: scip.c:48626
static SCIP_DECL_HEUREXIT(heurExitNlpdiving)
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HASHMAP *varmap, SCIP_SOL *subsol, SCIP_Bool *success)
#define HEUR_NAME
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:46306
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5158
enum SCIP_NlpTermStat SCIP_NLPTERMSTAT
Definition: type_nlpi.h:84
SCIP_Real SCIPfeastol(SCIP *scip)
Definition: scip.c:46443
NLP diving heuristic that chooses fixings w.r.t. the fractionalities.
#define DEFAULT_BACKTRACK
SCIP_Bool SCIPisNLPConstructed(SCIP *scip)
Definition: scip.c:31233
#define DEFAULT_RANDSEED
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
SCIP_RETCODE SCIPgetNLPIntPar(SCIP *scip, SCIP_NLPPARAM type, int *ival)
Definition: scip.c:31767
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:35964
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47311
#define DEFAULT_MAXFEASNLPS
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41226
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:35937
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:43453
SCIP_Bool SCIPisUbBetter(SCIP *scip, SCIP_Real newub, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:47661
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
#define HEUR_TIMING
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4489
SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip.c:26031
#define DEFAULT_NLPSTART
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1344
SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
Definition: scip.c:43619
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed)
Definition: scip.c:48608
static SCIP_RETCODE chooseVeclenVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:8177
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12252
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
internal methods for NLPI solver interfaces
#define DEFAULT_MAXDIVEAVGQUOT
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
SCIP_NLPSOLSTAT SCIPgetNLPSolstat(SCIP *scip)
Definition: scip.c:31616
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
static SCIP_RETCODE chooseFracVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12758
int SCIPgetMaxDepth(SCIP *scip)
Definition: scip.c:43095
static SCIP_RETCODE chooseGuidedVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_SOL *bestsol, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47350
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11686
Undercover primal heuristic for MINLPs.
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39832
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
#define DEFAULT_MAXDIVEUBQUOT
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:4192
SCIP_RETCODE SCIPcopyConsCompression(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:3884
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPgetLocalLowerbound(SCIP *scip)
Definition: scip.c:13408
#define SCIPstatisticMessage
Definition: pub_message.h:104
SCIP_RETCODE SCIPsolveNLP(SCIP *scip)
Definition: scip.c:31593
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5132
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9269
SCIP_Real SCIPgetAvgLowerbound(SCIP *scip)
Definition: scip.c:43234
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define DEFAULT_MINRELDEPTH
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:8084
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:9366
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:36040
#define DEFAULT_MAXRELDEPTH
SCIP_RETCODE SCIPsetNLPIntPar(SCIP *scip, SCIP_NLPPARAM type, int ival)
Definition: scip.c:31795
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
void SCIPnlpStatisticsFree(BMS_BLKMEM *blkmem, SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:801
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:748
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1119
#define DEFAULT_VARSELRULE
#define DEFAULT_SOLVESUBMIP
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip.c:37034
#define SCIP_EVENTTYPE_BOUNDCHANGED
Definition: type_event.h:108
#define SCIPdebugMsgPrint
Definition: scip.h:456
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4265
#define MINNLPITER
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47435
static SCIP_RETCODE chooseDoubleVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **pseudocands, SCIP_Real *pseudocandsnlpsol, SCIP_Real *pseudocandslpsol, int npseudocands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Real *bestboundval, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47423
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:10891
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3025
#define SCIP_EVENTTYPE_LBRELAXED
Definition: type_event.h:64
SCIP_RETCODE SCIPupdateVarPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip.c:25997
SCIP_RETCODE SCIPlinkNLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38602
SCIP_Bool SCIPisLbBetter(SCIP *scip, SCIP_Real newlb, SCIP_Real oldlb, SCIP_Real oldub)
Definition: scip.c:47646
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:29737
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_Real SCIPeventGetNewbound(SCIP_EVENT *event)
Definition: event.c:1162
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:38168
SCIP_NLPTERMSTAT SCIPgetNLPTermstat(SCIP *scip)
Definition: scip.c:31638
static SCIP_RETCODE getNLPFracVars(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR ***nlpcands, SCIP_Real **nlpcandssol, SCIP_Real **nlpcandsfrac, int *nnlpcands)
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip.c:8193
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:16115
SCIP_RETCODE SCIPaddLinearConsToNlpHeurSubNlp(SCIP *scip, SCIP_HEUR *heur, SCIP_Bool addcombconss, SCIP_Bool addcontconss)
Definition: heur_subnlp.c:2391
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip.c:8225
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4401
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8145
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:36314
enum SCIP_NlpSolStat SCIP_NLPSOLSTAT
Definition: type_nlpi.h:69
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38948
SCIP_Real SCIPgetDualbound(SCIP *scip)
Definition: scip.c:43256
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4630
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:35999
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
int SCIPgetNNlpis(SCIP *scip)
Definition: scip.c:9602
SCIP_RETCODE SCIPsetNLPInitialGuessSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31561
static SCIP_RETCODE choosePscostVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
#define SCIP_EVENTTYPE_UBRELAXED
Definition: type_event.h:66
#define HEUR_PRIORITY
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
#define SCIP_EVENTTYPE_LBTIGHTENED
Definition: type_event.h:63
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47337
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:36550
SCIP_RETCODE SCIPcomputeCoverUndercover(SCIP *scip, int *coversize, SCIP_VAR **cover, SCIP_Real timelimit, SCIP_Real memorylimit, SCIP_Real objlimit, SCIP_Bool globalbounds, SCIP_Bool onlyconvexify, SCIP_Bool coverbd, char coveringobj, SCIP_Bool *success)
#define DEFAULT_MAXNLPITERREL
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1360
#define EVENTHDLR_NAME
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1324
#define SCIP_PROBINGSCORE_PENALTYRATIO
Definition: def.h:292
SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
Definition: scip.c:37340
SCIP_Longint SCIPgetLastDivenode(SCIP *scip)
Definition: scip.c:35772
static SCIP_RETCODE solveSubMIP(SCIP *scip, SCIP_HEUR *heur, SCIP_VAR **covervars, int ncovervars, SCIP_Bool *success)
static SCIP_DECL_HEUREXEC(heurExecNlpdiving)
SCIP_RETCODE SCIPsetNLPRealPar(SCIP *scip, SCIP_NLPPARAM type, SCIP_Real dval)
Definition: scip.c:31851
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38771
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
Definition: event.c:982
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPgetNLPStatistics(SCIP *scip, SCIP_NLPSTATISTICS *statistics)
Definition: scip.c:31663
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:29293
#define HEUR_MAXDEPTH
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:40024
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11246
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17663
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define MAX(x, y)
Definition: tclique_def.h:75
static SCIP_DECL_HEURFREE(heurFreeNlpdiving)
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:40794
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4688
#define DEFAULT_MAXDIVEUBQUOTNOSOL
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:38535
void SCIPenableVarHistory(SCIP *scip)
Definition: scip.c:25958
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:41272
static SCIP_DECL_EVENTEXEC(eventExecNlpdiving)
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38994
#define SCIP_EVENTTYPE_UBTIGHTENED
Definition: type_event.h:65
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
#define HEUR_USESSUBSCIP
static SCIP_DECL_HEURINIT(heurInitNlpdiving)
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:40700
#define SCIP_MAXTREEDEPTH
Definition: def.h:286
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip.c:4862
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
#define SCIP_REAL_MAX
Definition: def.h:150
#define DEFAULT_PREFERLPFRACS
SCIP_RETCODE SCIPincludeHeurNlpdiving(SCIP *scip)
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip.c:11386
SCIP_RETCODE SCIPcreateNLPSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37948
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:29372
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:39882
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
static SCIP_RETCODE chooseCoefVar(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **nlpcands, SCIP_Real *nlpcandssol, SCIP_Real *nlpcandsfrac, int nnlpcands, SCIP_HASHMAP *varincover, SCIP_Bool covercomputed, int *bestcand, SCIP_Bool *bestcandmayround, SCIP_Bool *bestcandroundup)
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4349
#define HEUR_DESC
static void calcPscostQuot(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var, SCIP_Real primsol, SCIP_Real frac, int rounddir, SCIP_Real *pscostquot, SCIP_Bool *roundup, SCIP_Bool prefvar)
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:46774
#define DEFAULT_FIXQUOT
NLP local search primal heuristic using sub-SCIPs.
SCIP_RETCODE SCIPnlpStatisticsCreate(BMS_BLKMEM *blkmem, SCIP_NLPSTATISTICS **statistics)
Definition: nlpi.c:784
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:8161
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip.c:39126
SCIP_Real SCIPeventGetOldbound(SCIP_EVENT *event)
Definition: event.c:1138
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:46800
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8957
SCIP_RETCODE SCIPgetNLPFracVars(SCIP *scip, SCIP_VAR ***fracvars, SCIP_Real **fracvarssol, SCIP_Real **fracvarsfrac, int *nfracvars, int *npriofracvars)
Definition: scip.c:31736
#define SCIPstatistic(x)
Definition: pub_message.h:101
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
#define DEFAULT_PREFERCOVER
#define EVENTHDLR_DESC
#define SCIP_INVALID
Definition: def.h:169
int SCIPnlpStatisticsGetNIterations(SCIP_NLPSTATISTICS *statistics)
Definition: nlpi.c:816
#define SCIP_Longint
Definition: def.h:134
SCIP_Longint SCIPheurGetNSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1334
SCIP_RETCODE SCIPunlinkSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38740
SCIP_Real SCIPfrac(SCIP *scip, SCIP_Real val)
Definition: scip.c:47185
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip.c:4156
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
#define HEUR_FREQ
#define DEFAULT_MAXNLPITERABS
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38813
SCIP_Real SCIPgetNLPObjval(SCIP *scip)
Definition: scip.c:31687
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8129
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:35904
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:46429
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:35858
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2874
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47161
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1109
static SCIP_DECL_HEURCOPY(heurCopyNlpdiving)
SCIP_Real SCIPheurGetTime(SCIP_HEUR *heur)
Definition: heur.c:1386
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:42133
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:36084
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
static SCIP_RETCODE doSolveSubMIP(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **covervars, int ncovervars, SCIP_Bool *success)
#define HEUR_DISPCHAR
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4321
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5083
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3280
static SCIP_DECL_HEURINITSOL(heurInitsolNlpdiving)
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4746
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3272
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
#define DEFAULT_MINSUCCQUOT
#define DEFAULT_LP
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:780
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37878
#define DEFAULT_NLPFASTFAIL
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134