Scippy

SCIP

Solving Constraint Integer Programs

heur_rootsoldiving.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 visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_rootsoldiving.c
17  * @brief LP diving heuristic that changes variable's objective values using root LP solution as guide
18  * @author Kati Wolter
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include "blockmemshell/memory.h"
25 #include "scip/pub_heur.h"
26 #include "scip/pub_message.h"
27 #include "scip/pub_var.h"
28 #include "scip/scip_branch.h"
29 #include "scip/scip_general.h"
30 #include "scip/scip_heur.h"
31 #include "scip/scip_lp.h"
32 #include "scip/scip_mem.h"
33 #include "scip/scip_message.h"
34 #include "scip/scip_numerics.h"
35 #include "scip/scip_param.h"
36 #include "scip/scip_prob.h"
37 #include "scip/scip_sol.h"
38 #include "scip/scip_solvingstats.h"
39 #include "scip/scip_tree.h"
40 #include <string.h>
41 
42 #define HEUR_NAME "rootsoldiving"
43 #define HEUR_DESC "LP diving heuristic that changes variable's objective values using root LP solution as guide"
44 #define HEUR_DISPCHAR 'S'
45 #define HEUR_PRIORITY -1005000
46 #define HEUR_FREQ 20
47 #define HEUR_FREQOFS 5
48 #define HEUR_MAXDEPTH -1
49 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
50 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
51 
52 
53 /*
54  * Default parameter settings
55  */
56 
57 #define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
58 #define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
59 #define DEFAULT_MAXLPITERQUOT 0.01 /**< maximal fraction of diving LP iterations compared to node LP iterations */
60 #define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
61 #define DEFAULT_MAXSOLS -1 /**< total number of feasible solutions found up to which heuristic is called
62  * (-1: no limit) */
63 #define DEFAULT_DEPTHFAC 0.5 /**< maximal diving depth: number of binary/integer variables times depthfac */
64 #define DEFAULT_DEPTHFACNOSOL 2.0 /**< maximal diving depth factor if no feasible solution was found yet */
65 
66 #define MINLPITER 10000 /**< minimal number of LP iterations allowed in each LP solving call */
67 #define DEFAULT_ALPHA 0.9 /**< soft rounding factor to fade out objective coefficients */
68 
69 
70 /* locally defined heuristic data */
71 struct SCIP_HeurData
72 {
73  SCIP_SOL* sol; /**< working solution */
74  SCIP_Real minreldepth; /**< minimal relative depth to start diving */
75  SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
76  SCIP_Real maxlpiterquot; /**< maximal fraction of diving LP iterations compared to node LP iterations */
77  int maxlpiterofs; /**< additional number of allowed LP iterations */
78  int maxsols; /**< total number of feasible solutions found up to which heuristic is called
79  * (-1: no limit) */
80  SCIP_Real depthfac; /**< maximal diving depth: number of binary/integer variables times depthfac */
81  SCIP_Real depthfacnosol; /**< maximal diving depth factor if no feasible solution was found yet */
82  SCIP_Real alpha; /**< soft rounding factor to fade out objective coefficients */
83  SCIP_Longint nlpiterations; /**< LP iterations used in this heuristic */
84  int nsuccess; /**< number of runs that produced at least one feasible solution */
85 };
86 
87 
88 /*
89  * Callback methods
90  */
91 
92 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
93 static
94 SCIP_DECL_HEURCOPY(heurCopyRootsoldiving)
95 { /*lint --e{715}*/
96  assert(scip != NULL);
97  assert(heur != NULL);
98  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
99 
100  /* call inclusion method of primal heuristic */
102 
103  return SCIP_OKAY;
104 }
105 
106 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
107 static
108 SCIP_DECL_HEURFREE(heurFreeRootsoldiving) /*lint --e{715}*/
109 { /*lint --e{715}*/
110  SCIP_HEURDATA* heurdata;
111 
112  assert(heur != NULL);
113  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
114  assert(scip != NULL);
115 
116  /* free heuristic data */
117  heurdata = SCIPheurGetData(heur);
118  assert(heurdata != NULL);
119  SCIPfreeBlockMemory(scip, &heurdata);
120  SCIPheurSetData(heur, NULL);
121 
122  return SCIP_OKAY;
123 }
124 
125 
126 /** initialization method of primal heuristic (called after problem was transformed) */
127 static
128 SCIP_DECL_HEURINIT(heurInitRootsoldiving) /*lint --e{715}*/
129 { /*lint --e{715}*/
130  SCIP_HEURDATA* heurdata;
131 
132  assert(heur != NULL);
133  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
134 
135  /* get heuristic data */
136  heurdata = SCIPheurGetData(heur);
137  assert(heurdata != NULL);
138 
139  /* create working solution */
140  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
141 
142  /* initialize data */
143  heurdata->nlpiterations = 0;
144  heurdata->nsuccess = 0;
145 
146  return SCIP_OKAY;
147 }
148 
149 
150 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
151 static
152 SCIP_DECL_HEUREXIT(heurExitRootsoldiving) /*lint --e{715}*/
153 { /*lint --e{715}*/
154  SCIP_HEURDATA* heurdata;
155 
156  assert(heur != NULL);
157  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
158 
159  /* get heuristic data */
160  heurdata = SCIPheurGetData(heur);
161  assert(heurdata != NULL);
162 
163  /* free working solution */
164  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
165 
166  return SCIP_OKAY;
167 }
168 
169 
170 /** execution method of primal heuristic */
171 static
172 SCIP_DECL_HEUREXEC(heurExecRootsoldiving) /*lint --e{715}*/
173 { /*lint --e{715}*/
174  SCIP_HEURDATA* heurdata;
175  SCIP_VAR** vars;
176  SCIP_Real* rootsol;
177  SCIP_Real* objchgvals;
178  int* softroundings;
179  int* intvalrounds;
180  int nvars;
181  int nbinvars;
182  int nintvars;
183  int nlpcands;
184  SCIP_LPSOLSTAT lpsolstat;
185  SCIP_Real absstartobjval;
186  SCIP_Real objstep;
187  SCIP_Real alpha;
188  SCIP_Real oldobj;
189  SCIP_Real newobj;
190  SCIP_Bool lperror;
191  SCIP_Bool lpsolchanged;
192  SCIP_Longint nsolsfound;
193  SCIP_Longint ncalls;
194  SCIP_Longint nlpiterations;
195  SCIP_Longint maxnlpiterations;
196  int depth;
197  int maxdepth;
198  int maxdivedepth;
199  int divedepth;
200  int startnlpcands;
201  int ncycles;
202  int i;
203 
204  assert(heur != NULL);
205  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
206  assert(scip != NULL);
207  assert(result != NULL);
208  assert(SCIPhasCurrentNodeLP(scip));
209 
210  *result = SCIP_DELAYED;
211 
212  /* do not call heuristic of node was already detected to be infeasible */
213  if( nodeinfeasible )
214  return SCIP_OKAY;
215 
216  /* only call heuristic, if an optimal LP solution is at hand */
218  return SCIP_OKAY;
219 
220  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
222  return SCIP_OKAY;
223 
224  /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
225  if( !SCIPisLPSolBasic(scip) )
226  return SCIP_OKAY;
227 
228  /* don't dive two times at the same node */
230  return SCIP_OKAY;
231 
232  *result = SCIP_DIDNOTRUN;
233 
234  /* get heuristic's data */
235  heurdata = SCIPheurGetData(heur);
236  assert(heurdata != NULL);
237 
238  /* only apply heuristic, if only a few solutions have been found */
239  if( heurdata->maxsols >= 0 && SCIPgetNSolsFound(scip) >= heurdata->maxsols )
240  return SCIP_OKAY;
241 
242  /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
243  depth = SCIPgetDepth(scip);
244  maxdepth = SCIPgetMaxDepth(scip);
245  maxdepth = MAX(maxdepth, 30);
246  if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
247  return SCIP_OKAY;
248 
249  /* calculate the maximal number of LP iterations until heuristic is aborted */
250  nlpiterations = SCIPgetNNodeLPIterations(scip);
251  ncalls = SCIPheurGetNCalls(heur);
252  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
253  maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
254  maxnlpiterations += heurdata->maxlpiterofs;
255 
256  /* don't try to dive, if we took too many LP iterations during diving */
257  if( heurdata->nlpiterations >= maxnlpiterations )
258  return SCIP_OKAY;
259 
260  /* allow at least a certain number of LP iterations in this dive */
261  maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
262 
263  /* get number of fractional variables, that should be integral */
264  nlpcands = SCIPgetNLPBranchCands(scip);
265 
266  /* don't try to dive, if there are no fractional variables */
267  if( nlpcands == 0 )
268  return SCIP_OKAY;
269 
270  /* calculate the maximal diving depth */
272  if( SCIPgetNSolsFound(scip) == 0 )
273  maxdivedepth = (int)(heurdata->depthfacnosol * nvars);
274  else
275  maxdivedepth = (int)(heurdata->depthfac * nvars);
276  maxdivedepth = MAX(maxdivedepth, 10);
277 
278  *result = SCIP_DIDNOTFIND;
279 
280  /* get all variables of LP */
281  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
282 
283  /* get root solution value of all binary and integer variables */
284  SCIP_CALL( SCIPallocBufferArray(scip, &rootsol, nbinvars + nintvars) );
285  for( i = 0; i < nbinvars + nintvars; i++ )
286  rootsol[i] = SCIPvarGetRootSol(vars[i]);
287 
288  /* get current LP objective value, and calculate length of a single step in an objective coefficient */
289  absstartobjval = SCIPgetLPObjval(scip);
290  absstartobjval = ABS(absstartobjval);
291  absstartobjval = MAX(absstartobjval, 1.0);
292  objstep = absstartobjval / 10.0;
293 
294  /* initialize array storing the preferred soft rounding directions and counting the integral value rounds */
295  SCIP_CALL( SCIPallocBufferArray(scip, &softroundings, nbinvars + nintvars) );
296  BMSclearMemoryArray(softroundings, nbinvars + nintvars);
297  SCIP_CALL( SCIPallocBufferArray(scip, &intvalrounds, nbinvars + nintvars) );
298  BMSclearMemoryArray(intvalrounds, nbinvars + nintvars);
299 
300  /* allocate temporary memory for buffering objective changes */
301  SCIP_CALL( SCIPallocBufferArray(scip, &objchgvals, nbinvars + nintvars) );
302 
303  /* start diving */
305 
306  SCIPdebugMsg(scip, "(node %" SCIP_LONGINT_FORMAT ") executing rootsoldiving heuristic: depth=%d, %d fractionals, dualbound=%g, maxnlpiterations=%" SCIP_LONGINT_FORMAT ", maxdivedepth=%d, LPobj=%g, objstep=%g\n",
307  SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), maxnlpiterations, maxdivedepth,
308  SCIPgetLPObjval(scip), objstep);
309 
310  lperror = FALSE;
311  divedepth = 0;
312  lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
313  alpha = heurdata->alpha;
314  ncycles = 0;
315  lpsolchanged = TRUE;
316  startnlpcands = nlpcands;
317  while( !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0 && ncycles < 10
318  && (divedepth < 10
319  || nlpcands <= startnlpcands - divedepth/2
320  || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations))
321  && !SCIPisStopped(scip) )
322  {
323  SCIP_Bool success;
324  int hardroundingidx;
325  int hardroundingdir;
326  SCIP_Real hardroundingoldbd;
327  SCIP_Real hardroundingnewbd;
328  SCIP_Bool boundschanged;
329 
330  SCIP_RETCODE retcode;
331 
332  /* create solution from diving LP and try to round it */
333  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
334  SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
335 
336  if( success )
337  {
338  SCIPdebugMsg(scip, "rootsoldiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
339 
340  /* try to add solution to SCIP */
341  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
342 
343  /* check, if solution was feasible and good enough */
344  if( success )
345  {
346  SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
347  *result = SCIP_FOUNDSOL;
348  }
349  }
350 
351  divedepth++;
352  hardroundingidx = -1;
353  hardroundingdir = 0;
354  hardroundingoldbd = 0.0;
355  hardroundingnewbd = 0.0;
356  boundschanged = FALSE;
357 
358  SCIPdebugMsg(scip, "dive %d/%d, LP iter %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT ":\n", divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);
359 
360  /* round solution x* from diving LP:
361  * - x~_j = down(x*_j) if x*_j is integer or binary variable and x*_j <= root solution_j
362  * - x~_j = up(x*_j) if x*_j is integer or binary variable and x*_j > root solution_j
363  * - x~_j = x*_j if x*_j is continuous variable
364  * change objective function in diving LP:
365  * - if x*_j is integral, or j is a continuous variable, set obj'_j = alpha * obj_j
366  * - otherwise, set obj'_j = alpha * obj_j + sign(x*_j - x~_j)
367  */
368  for( i = 0; i < nbinvars + nintvars; i++ )
369  {
370  SCIP_VAR* var;
371  SCIP_Real solval;
372 
373  var = vars[i];
374  oldobj = SCIPgetVarObjDive(scip, var);
375  newobj = oldobj;
376 
377  solval = SCIPvarGetLPSol(var);
378  if( SCIPisFeasIntegral(scip, solval) )
379  {
380  /* if the variable became integral after a soft rounding, count the rounds; after a while, fix it to its
381  * current integral value;
382  * otherwise, fade out the objective value
383  */
384  if( softroundings[i] != 0 && lpsolchanged )
385  {
386  intvalrounds[i]++;
387  if( intvalrounds[i] == 5 && SCIPgetVarLbDive(scip, var) < SCIPgetVarUbDive(scip, var) - 0.5 )
388  {
389  /* use exact integral value, if the variable is only integral within numerical tolerances */
390  solval = SCIPfloor(scip, solval+0.5);
391  SCIPdebugMsg(scip, " -> fixing <%s> = %g\n", SCIPvarGetName(var), solval);
392  SCIP_CALL( SCIPchgVarLbDive(scip, var, solval) );
393  SCIP_CALL( SCIPchgVarUbDive(scip, var, solval) );
394  boundschanged = TRUE;
395  }
396  }
397  else
398  newobj = alpha * oldobj;
399  }
400  else if( solval <= rootsol[i] )
401  {
402  /* if the variable was soft rounded most of the time downwards, round it downwards by changing the bounds;
403  * otherwise, apply soft rounding by changing the objective value
404  */
405  softroundings[i]--;
406  if( softroundings[i] <= -10 && hardroundingidx == -1 )
407  {
408  SCIPdebugMsg(scip, " -> hard rounding <%s>[%g] <= %g\n",
409  SCIPvarGetName(var), solval, SCIPfeasFloor(scip, solval));
410  hardroundingidx = i;
411  hardroundingdir = -1;
412  hardroundingoldbd = SCIPgetVarUbDive(scip, var);
413  hardroundingnewbd = SCIPfeasFloor(scip, solval);
414  SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd) );
415  boundschanged = TRUE;
416  }
417  else
418  newobj = alpha * oldobj + objstep;
419  }
420  else
421  {
422  /* if the variable was soft rounded most of the time upwards, round it upwards by changing the bounds;
423  * otherwise, apply soft rounding by changing the objective value
424  */
425  softroundings[i]++;
426  if( softroundings[i] >= +10 && hardroundingidx == -1 )
427  {
428  SCIPdebugMsg(scip, " -> hard rounding <%s>[%g] >= %g\n",
429  SCIPvarGetName(var), solval, SCIPfeasCeil(scip, solval));
430  hardroundingidx = i;
431  hardroundingdir = +1;
432  hardroundingoldbd = SCIPgetVarLbDive(scip, var);
433  hardroundingnewbd = SCIPfeasCeil(scip, solval);
434  SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd) );
435  boundschanged = TRUE;
436  }
437  else
438  newobj = alpha * oldobj - objstep;
439  }
440 
441  /* remember the objective change */
442  objchgvals[i] = newobj;
443  }
444 
445  /* apply objective changes if there was no bound change */
446  if( !boundschanged )
447  {
448  /* apply cached changes on integer variables */
449  for( i = 0; i < nbinvars + nintvars; ++i )
450  {
451  SCIP_VAR* var;
452 
453  var = vars[i];
454  SCIPdebugMsg(scip, " -> i=%d var <%s>, solval=%g, rootsol=%g, oldobj=%g, newobj=%g\n",
455  i, SCIPvarGetName(var), SCIPvarGetLPSol(var), rootsol[i], SCIPgetVarObjDive(scip, var), objchgvals[i]);
456 
457  SCIP_CALL( SCIPchgVarObjDive(scip, var, objchgvals[i]) );
458  }
459 
460  /* fade out the objective values of the continuous variables */
461  for( i = nbinvars + nintvars; i < nvars; i++ )
462  {
463  SCIP_VAR* var;
464 
465  var = vars[i];
466  oldobj = SCIPgetVarObjDive(scip, var);
467  newobj = alpha * oldobj;
468 
469  SCIPdebugMsg(scip, " -> i=%d var <%s>, solval=%g, oldobj=%g, newobj=%g\n",
470  i, SCIPvarGetName(var), SCIPvarGetLPSol(var), oldobj, newobj);
471 
472  SCIP_CALL( SCIPchgVarObjDive(scip, var, newobj) );
473  }
474  }
475 
476  SOLVEAGAIN:
477  /* resolve the diving LP */
478  nlpiterations = SCIPgetNLPIterations(scip);
479 
480  retcode = SCIPsolveDiveLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, NULL);
481  lpsolstat = SCIPgetLPSolstat(scip);
482 
483  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
484  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
485  */
486  if( retcode != SCIP_OKAY )
487  {
488 #ifndef NDEBUG
489  if( lpsolstat != SCIP_LPSOLSTAT_UNBOUNDEDRAY )
490  {
491  SCIP_CALL( retcode );
492  }
493 #endif
494  SCIPwarningMessage(scip, "Error while solving LP in Rootsoldiving heuristic; LP solve terminated with code <%d>\n", retcode);
495  SCIPwarningMessage(scip, "This does not affect the remaining solution procedure --> continue\n");
496  }
497 
498  if( lperror )
499  break;
500 
501  /* update iteration count */
502  heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;
503 
504  /* if no LP iterations were performed, we stayed at the same solution -> count this cycling */
505  lpsolchanged = (SCIPgetNLPIterations(scip) != nlpiterations);
506  if( lpsolchanged )
507  ncycles = 0;
508  else if( !boundschanged ) /* do not count if integral variables have been fixed */
509  ncycles++;
510 
511  /* get LP solution status and number of fractional variables, that should be integral */
512  if( lpsolstat == SCIP_LPSOLSTAT_INFEASIBLE && hardroundingidx != -1 )
513  {
514  SCIP_VAR* var;
515 
516  var = vars[hardroundingidx];
517 
518  /* round the hard rounded variable to the opposite direction and resolve the LP */
519  if( hardroundingdir == -1 )
520  {
521  SCIPdebugMsg(scip, " -> opposite hard rounding <%s> >= %g\n", SCIPvarGetName(var), hardroundingnewbd + 1.0);
522  SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingoldbd) );
523  SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingnewbd + 1.0) );
524  }
525  else
526  {
527  SCIPdebugMsg(scip, " -> opposite hard rounding <%s> <= %g\n", SCIPvarGetName(var), hardroundingnewbd - 1.0);
528  SCIP_CALL( SCIPchgVarLbDive(scip, var, hardroundingoldbd) );
529  SCIP_CALL( SCIPchgVarUbDive(scip, var, hardroundingnewbd - 1.0) );
530  }
531  hardroundingidx = -1;
532  goto SOLVEAGAIN;
533  }
534  if( lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
535  nlpcands = SCIPgetNLPBranchCands(scip);
536  SCIPdebugMsg(scip, " -> lpsolstat=%d, nfrac=%d\n", lpsolstat, nlpcands);
537  }
538 
539  SCIPdebugMsg(scip, "---> diving finished: lpsolstat = %d, depth %d/%d, LP iter %" SCIP_LONGINT_FORMAT "/%" SCIP_LONGINT_FORMAT "\n",
540  lpsolstat, divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations);
541 
542  /* check if a solution has been found */
543  if( nlpcands == 0 && !lperror && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
544  {
545  SCIP_Bool success;
546 
547  /* create solution from diving LP */
548  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
549  SCIPdebugMsg(scip, "rootsoldiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
550 
551  /* try to add solution to SCIP */
552  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
553 
554  /* check, if solution was feasible and good enough */
555  if( success )
556  {
557  SCIPdebugMsg(scip, " -> solution was feasible and good enough\n");
558  *result = SCIP_FOUNDSOL;
559  }
560  }
561 
562  /* end diving */
564 
565  if( *result == SCIP_FOUNDSOL )
566  heurdata->nsuccess++;
567 
568  /* free temporary memory */
569  SCIPfreeBufferArray(scip, &objchgvals);
570  SCIPfreeBufferArray(scip, &intvalrounds);
571  SCIPfreeBufferArray(scip, &softroundings);
572  SCIPfreeBufferArray(scip, &rootsol);
573 
574  SCIPdebugMsg(scip, "rootsoldiving heuristic finished\n");
575 
576  return SCIP_OKAY;
577 }
578 
579 
580 /*
581  * heuristic specific interface methods
582  */
583 
584 /** creates the rootsoldiving heuristic and includes it in SCIP */
586  SCIP* scip /**< SCIP data structure */
587  )
588 {
589  SCIP_HEURDATA* heurdata;
590  SCIP_HEUR* heur;
591 
592  /* create Rootsoldiving primal heuristic data */
593  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
594 
595  /* include primal heuristic */
596  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
598  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecRootsoldiving, heurdata) );
599 
600  assert(heur != NULL);
601 
602  /* set non-NULL pointers to callback methods */
603  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyRootsoldiving) );
604  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeRootsoldiving) );
605  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitRootsoldiving) );
606  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitRootsoldiving) );
607 
608  /* rootsoldiving heuristic parameters */
610  "heuristics/rootsoldiving/minreldepth",
611  "minimal relative depth to start diving",
612  &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
614  "heuristics/rootsoldiving/maxreldepth",
615  "maximal relative depth to start diving",
616  &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
618  "heuristics/rootsoldiving/maxlpiterquot",
619  "maximal fraction of diving LP iterations compared to node LP iterations",
620  &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
622  "heuristics/rootsoldiving/maxlpiterofs",
623  "additional number of allowed LP iterations",
624  &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
626  "heuristics/rootsoldiving/maxsols",
627  "total number of feasible solutions found up to which heuristic is called (-1: no limit)",
628  &heurdata->maxsols, TRUE, DEFAULT_MAXSOLS, -1, INT_MAX, NULL, NULL) );
630  "heuristics/rootsoldiving/depthfac",
631  "maximal diving depth: number of binary/integer variables times depthfac",
632  &heurdata->depthfac, TRUE, DEFAULT_DEPTHFAC, 0.0, SCIP_REAL_MAX, NULL, NULL) );
634  "heuristics/rootsoldiving/depthfacnosol",
635  "maximal diving depth factor if no feasible solution was found yet",
636  &heurdata->depthfacnosol, TRUE, DEFAULT_DEPTHFACNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
638  "heuristics/rootsoldiving/alpha",
639  "soft rounding factor to fade out objective coefficients",
640  &heurdata->alpha, TRUE, DEFAULT_ALPHA, 0.0, 1.0, NULL, NULL) );
641 
642  return SCIP_OKAY;
643 }
644 
int SCIPgetNIntVars(SCIP *scip)
Definition: scip_prob.c:2134
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1075
#define NULL
Definition: def.h:239
#define HEUR_NAME
public methods for SCIP parameter handling
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
public methods for memory management
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1400
SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
#define DEFAULT_MAXRELDEPTH
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:280
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
#define HEUR_DISPCHAR
SCIP_RETCODE SCIPincludeHeurRootsoldiving(SCIP *scip)
#define HEUR_FREQ
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12827
int SCIPgetMaxDepth(SCIP *scip)
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:1918
#define FALSE
Definition: def.h:65
#define TRUE
Definition: def.h:64
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPchgVarLbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_lp.c:2301
#define DEFAULT_ALPHA
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
public methods for problem variables
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:114
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_heur.c:187
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:142
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1175
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:97
int SCIPgetNLPBranchCands(SCIP *scip)
Definition: scip_branch.c:417
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip_message.c:203
#define SCIPdebugMsg
Definition: scip_message.h:88
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_param.c:155
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
public methods for numerical tolerances
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
#define DEFAULT_MAXLPITEROFS
public methods for querying solving statistics
public methods for the branch-and-bound tree
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip_lp.c:670
SCIP_Real SCIPgetVarUbDive(SCIP *scip, SCIP_VAR *var)
Definition: scip_lp.c:2527
static SCIP_DECL_HEUREXEC(heurExecRootsoldiving)
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1254
SCIP_RETCODE SCIPsolveDiveLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip_lp.c:2560
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:248
SCIP_Real SCIPgetDualbound(SCIP *scip)
#define DEFAULT_MAXSOLS
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16729
#define HEUR_MAXDEPTH
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17717
#define HEUR_TIMING
#define SCIP_CALL(x)
Definition: def.h:351
#define HEUR_PRIORITY
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1380
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:141
#define DEFAULT_MINRELDEPTH
public methods for primal heuristic plugins and divesets
SCIP_Longint SCIPgetLastDivenode(SCIP *scip)
Definition: scip_lp.c:2627
SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:130
LP diving heuristic that changes variables&#39; objective values using root LP solution as guide...
#define SCIP_Bool
Definition: def.h:62
#define DEFAULT_DEPTHFAC
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:226
static SCIP_DECL_HEURFREE(heurFreeRootsoldiving)
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip_sol.c:2521
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:715
SCIP_RETCODE SCIPchgVarUbDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip_lp.c:2333
#define HEUR_USESSUBSCIP
static SCIP_DECL_HEUREXIT(heurExitRootsoldiving)
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:1034
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:1493
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_sol.c:3197
int SCIPgetNBinVars(SCIP *scip)
Definition: scip_prob.c:2089
public methods for the LP relaxation, rows and columns
#define SCIP_REAL_MAX
Definition: def.h:151
#define SCIP_LONGINT_FORMAT
Definition: def.h:142
public methods for branching rule plugins and branching
general public methods
#define MAX(x, y)
Definition: def.h:208
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip_lp.c:305
SCIP_RETCODE SCIPchgVarObjDive(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip_lp.c:2260
#define DEFAULT_MAXLPITERQUOT
public methods for solutions
public methods for message output
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:264
#define SCIP_Real
Definition: def.h:150
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:739
public methods for message handling
#define HEUR_DESC
#define MINLPITER
#define SCIP_Longint
Definition: def.h:135
SCIP_Real SCIPgetVarLbDive(SCIP *scip, SCIP_VAR *var)
Definition: scip_lp.c:2498
SCIP_RETCODE SCIPstartDive(SCIP *scip)
Definition: scip_lp.c:2124
static SCIP_DECL_HEURCOPY(heurCopyRootsoldiving)
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:232
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
#define HEUR_FREQOFS
public methods for primal heuristics
SCIP_RETCODE SCIPendDive(SCIP *scip)
Definition: scip_lp.c:2173
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1165
SCIP_Longint SCIPgetNNodes(SCIP *scip)
public methods for global and local (sub)problems
SCIP_Real SCIPgetVarObjDive(SCIP *scip, SCIP_VAR *var)
Definition: scip_lp.c:2469
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_param.c:211
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
#define ABS(x)
Definition: def.h:204
static SCIP_DECL_HEURINIT(heurInitRootsoldiving)
#define DEFAULT_DEPTHFACNOSOL
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:377
memory allocation routines