Scippy

SCIP

Solving Constraint Integer Programs

heur_linesearchdiving.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-2014 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_linesearchdiving.c
17  * @brief LP diving heuristic that fixes variables with a large difference to their root solution
18  * @author Tobias Achterberg
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 
27 
28 
29 #define HEUR_NAME "linesearchdiving"
30 #define HEUR_DESC "LP diving heuristic that chooses fixings following the line from root solution to current solution"
31 #define HEUR_DISPCHAR 'l'
32 #define HEUR_PRIORITY -1006000
33 #define HEUR_FREQ 10
34 #define HEUR_FREQOFS 6
35 #define HEUR_MAXDEPTH -1
36 #define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
37 #define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
38 
39 
40 /*
41  * Default parameter settings
42  */
43 
44 #define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
45 #define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
46 #define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
47 #define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
48 #define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
49  * where diving is performed (0.0: no limit) */
50 #define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
51  * where diving is performed (0.0: no limit) */
52 #define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
53 #define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
54 #define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
55 
56 #define MINLPITER 10000 /**< minimal number of LP iterations allowed in each LP solving call */
57 
58 
59 /*
60  * Data structures
61  */
62 
63 /** primal heuristic data */
64 struct SCIP_HeurData
65 {
66  SCIP_SOL* sol; /**< working solution */
67  SCIP_Real minreldepth; /**< minimal relative depth to start diving */
68  SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
69  SCIP_Real maxlpiterquot; /**< maximal fraction of diving LP iterations compared to node LP iterations */
70  int maxlpiterofs; /**< additional number of allowed LP iterations */
71  SCIP_Real maxdiveubquot; /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
72  * where diving is performed (0.0: no limit) */
73  SCIP_Real maxdiveavgquot; /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
74  * where diving is performed (0.0: no limit) */
75  SCIP_Real maxdiveubquotnosol; /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
76  SCIP_Real maxdiveavgquotnosol;/**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
77  SCIP_Bool backtrack; /**< use one level of backtracking if infeasibility is encountered? */
78  SCIP_Longint nlpiterations; /**< LP iterations used in this heuristic */
79  int nsuccess; /**< number of runs that produced at least one feasible solution */
80 };
81 
82 
83 /*
84  * Local methods
85  */
86 
87 
88 /*
89  * Callback methods of primal heuristic
90  */
91 
92 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
93 static
94 SCIP_DECL_HEURCOPY(heurCopyLinesearchdiving)
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(heurFreeLinesearchdiving)
109 { /*lint --e{715}*/
110  SCIP_HEURDATA* heurdata;
111 
112  assert(heur != NULL);
113  assert(scip != NULL);
114 
115  /* free heuristic data */
116  heurdata = SCIPheurGetData(heur);
117  assert(heurdata != NULL);
118  SCIPfreeMemory(scip, &heurdata);
119  SCIPheurSetData(heur, NULL);
120 
121  return SCIP_OKAY;
122 }
123 
124 
125 /** initialization method of primal heuristic (called after problem was transformed) */
126 static
127 SCIP_DECL_HEURINIT(heurInitLinesearchdiving)
128 { /*lint --e{715}*/
129  SCIP_HEURDATA* heurdata;
130 
131  assert(heur != NULL);
132 
133  /* get heuristic data */
134  heurdata = SCIPheurGetData(heur);
135  assert(heurdata != NULL);
136 
137  /* create working solution */
138  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
139 
140  /* initialize data */
141  heurdata->nlpiterations = 0;
142  heurdata->nsuccess = 0;
143 
144  return SCIP_OKAY;
145 }
146 
147 
148 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
149 static
150 SCIP_DECL_HEUREXIT(heurExitLinesearchdiving)
151 { /*lint --e{715}*/
152  SCIP_HEURDATA* heurdata;
153 
154  assert(heur != NULL);
155 
156  /* get heuristic data */
157  heurdata = SCIPheurGetData(heur);
158  assert(heurdata != NULL);
159 
160  /* free working solution */
161  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
162 
163  return SCIP_OKAY;
164 }
165 
166 
167 /** execution method of primal heuristic */
168 static
169 SCIP_DECL_HEUREXEC(heurExecLinesearchdiving)
170 { /*lint --e{715}*/
171  SCIP_HEURDATA* heurdata;
172  SCIP_LPSOLSTAT lpsolstat;
173  SCIP_VAR* var;
174  SCIP_VAR** lpcands;
175  SCIP_Real* lpcandssol;
176  SCIP_Real* lpcandsfrac;
177  SCIP_Real searchubbound;
178  SCIP_Real searchavgbound;
179  SCIP_Real searchbound;
180  SCIP_Real objval;
181  SCIP_Real oldobjval;
182  SCIP_Real solval;
183  SCIP_Real rootsolval;
184  SCIP_Real distquot;
185  SCIP_Real bestdistquot;
186  SCIP_Bool roundup;
187  SCIP_Bool bestcandroundup;
188  SCIP_Bool lperror;
189  SCIP_Bool cutoff;
190  SCIP_Bool backtracked;
191  SCIP_Bool success;
192  SCIP_Longint ncalls;
193  SCIP_Longint nsolsfound;
194  SCIP_Longint nlpiterations;
195  SCIP_Longint maxnlpiterations;
196  int nlpcands;
197  int startnlpcands;
198  int depth;
199  int maxdepth;
200  int maxdivedepth;
201  int divedepth;
202  int bestcand;
203  int c;
204 
205  assert(heur != NULL);
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 */
221  if( SCIPisGE(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)) )
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 */
229  if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
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 try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
239  depth = SCIPgetDepth(scip);
240  maxdepth = SCIPgetMaxDepth(scip);
241  maxdepth = MAX(maxdepth, 30);
242  if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
243  return SCIP_OKAY;
244 
245  /* calculate the maximal number of LP iterations until heuristic is aborted */
246  nlpiterations = SCIPgetNNodeLPIterations(scip);
247  ncalls = SCIPheurGetNCalls(heur);
248  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
249  maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
250  maxnlpiterations += heurdata->maxlpiterofs;
251 
252  /* don't try to dive, if we took too many LP iterations during diving */
253  if( heurdata->nlpiterations >= maxnlpiterations )
254  return SCIP_OKAY;
255 
256  /* allow at least a certain number of LP iterations in this dive */
257  maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
258 
259  /* get fractional variables that should be integral */
260  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
261 
262  /* don't try to dive, if there are no fractional variables */
263  if( nlpcands == 0 )
264  return SCIP_OKAY;
265 
266  /* calculate the objective search bound */
267  if( SCIPgetNSolsFound(scip) == 0 )
268  {
269  if( heurdata->maxdiveubquotnosol > 0.0 )
270  searchubbound = SCIPgetLowerbound(scip)
271  + heurdata->maxdiveubquotnosol * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
272  else
273  searchubbound = SCIPinfinity(scip);
274  if( heurdata->maxdiveavgquotnosol > 0.0 )
275  searchavgbound = SCIPgetLowerbound(scip)
276  + heurdata->maxdiveavgquotnosol * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
277  else
278  searchavgbound = SCIPinfinity(scip);
279  }
280  else
281  {
282  if( heurdata->maxdiveubquot > 0.0 )
283  searchubbound = SCIPgetLowerbound(scip)
284  + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
285  else
286  searchubbound = SCIPinfinity(scip);
287  if( heurdata->maxdiveavgquot > 0.0 )
288  searchavgbound = SCIPgetLowerbound(scip)
289  + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
290  else
291  searchavgbound = SCIPinfinity(scip);
292  }
293  searchbound = MIN(searchubbound, searchavgbound);
294  if( SCIPisObjIntegral(scip) )
295  searchbound = SCIPceil(scip, searchbound);
296 
297  /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
298  maxdivedepth = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
299  maxdivedepth = MIN(maxdivedepth, maxdepth);
300  maxdivedepth *= 10;
301 
302  *result = SCIP_DIDNOTFIND;
303 
304  /* start diving */
305  SCIP_CALL( SCIPstartProbing(scip) );
306 
307  /* enables collection of variable statistics during probing */
308  SCIPenableVarHistory(scip);
309 
310  /* get LP objective value */
311  lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
312  objval = SCIPgetLPObjval(scip);
313 
314  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") executing linesearchdiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
315  SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), SCIPretransformObj(scip, searchbound));
316 
317  /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
318  * - if possible, we dive at least with the depth 10
319  * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
320  */
321  lperror = FALSE;
322  cutoff = FALSE;
323  divedepth = 0;
324  startnlpcands = nlpcands;
325  while( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0
326  && (divedepth < 10
327  || nlpcands <= startnlpcands - divedepth/2
328  || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations && objval < searchbound))
329  && !SCIPisStopped(scip) )
330  {
331  SCIP_CALL( SCIPnewProbingNode(scip) );
332  divedepth++;
333 
334  /* choose variable fixing:
335  * - in the projected space of fractional variables, extend the line segment connecting the root solution and
336  * the current LP solution up to the point, where one of the fractional variables becomes integral
337  * - round this variable to the integral value
338  */
339  bestcand = 0;
340  bestdistquot = SCIPinfinity(scip);
341  bestcandroundup = FALSE;
342  for( c = 0; c < nlpcands; ++c )
343  {
344  var = lpcands[c];
345  solval = lpcandssol[c];
346  rootsolval = SCIPvarGetRootSol(var);
347 
348  /* calculate distance to integral value divided by distance to root solution */
349  if( SCIPisLT(scip, solval, rootsolval) )
350  {
351  roundup = FALSE;
352  distquot = (solval - SCIPfeasFloor(scip, solval)) / (rootsolval - solval);
353 
354  /* avoid roundable candidates */
355  if( SCIPvarMayRoundDown(var) )
356  distquot *= 1000.0;
357  }
358  else if( SCIPisGT(scip, solval, rootsolval) )
359  {
360  roundup = TRUE;
361  distquot = (SCIPfeasCeil(scip, solval) - solval) / (solval - rootsolval);
362 
363  /* avoid roundable candidates */
364  if( SCIPvarMayRoundUp(var) )
365  distquot *= 1000.0;
366  }
367  else
368  {
369  roundup = FALSE;
370  distquot = SCIPinfinity(scip);
371  }
372 
373  /* check, if candidate is new best candidate */
374  if( distquot < bestdistquot )
375  {
376  bestcand = c;
377  bestcandroundup = roundup;
378  bestdistquot = distquot;
379  }
380  }
381 
382  /* create solution from diving LP and try to round it */
383  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
384  SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
385  if( success )
386  {
387  SCIPdebugMessage("linesearchdiving found roundable primal solution: obj=%g\n",
388  SCIPgetSolOrigObj(scip, heurdata->sol));
389 
390  /* try to add solution to SCIP */
391  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
392 
393  /* check, if solution was feasible and good enough */
394  if( success )
395  {
396  SCIPdebugMessage(" -> solution was feasible and good enough\n");
397  *result = SCIP_FOUNDSOL;
398  }
399  }
400 
401  /* apply rounding of best candidate */
402  var = lpcands[bestcand];
403 
404  backtracked = FALSE;
405  do
406  {
407  /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
408  * occured or variable was fixed by propagation while backtracking => Abort diving!
409  */
410  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
411  {
412  SCIPdebugMessage("selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
413  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
414  cutoff = TRUE;
415  break;
416  }
417  if( SCIPisFeasLT(scip, lpcandssol[bestcand], SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, lpcandssol[bestcand], SCIPvarGetUbLocal(var)) )
418  {
419  SCIPdebugMessage("selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
420  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
421  assert(backtracked);
422  break;
423  }
424 
425  /* apply rounding of best candidate */
426  if( bestcandroundup == !backtracked )
427  {
428  /* round variable up */
429  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, sol=%g, root=%g, [%g,%g] -> [%g,%g]\n",
430  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
431  SCIPvarGetName(var), lpcandssol[bestcand], SCIPvarGetRootSol(var),
433  SCIPfeasCeil(scip, lpcandssol[bestcand]), SCIPvarGetUbLocal(var));
434  SCIP_CALL( SCIPchgVarLbProbing(scip, var, SCIPfeasCeil(scip, lpcandssol[bestcand])) );
435  }
436  else
437  {
438  /* round variable down */
439  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, sol=%g, root=%g, [%g,%g] -> [%g,%g]\n",
440  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
441  SCIPvarGetName(var), lpcandssol[bestcand], SCIPvarGetRootSol(var),
443  SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, lpcandssol[bestcand]));
444  SCIP_CALL( SCIPchgVarUbProbing(scip, var, SCIPfeasFloor(scip, lpcandssol[bestcand])) );
445  }
446 
447  /* apply domain propagation */
448  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
449  if( !cutoff )
450  {
451  /* resolve the diving LP */
452  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
453  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
454  */
455 #ifdef NDEBUG
456  SCIP_RETCODE retstat;
457  nlpiterations = SCIPgetNLPIterations(scip);
458  retstat = SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff);
459  if( retstat != SCIP_OKAY )
460  {
461  SCIPwarningMessage(scip, "Error while solving LP in Linesearchdiving heuristic; LP solve terminated with code <%d>\n",retstat);
462  }
463 #else
464  nlpiterations = SCIPgetNLPIterations(scip);
465  SCIP_CALL( SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff) );
466 #endif
467 
468  if( lperror )
469  break;
470 
471  /* update iteration count */
472  heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;
473 
474  /* get LP solution status, objective value, and fractional variables, that should be integral */
475  lpsolstat = SCIPgetLPSolstat(scip);
476  assert(cutoff || (lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT && lpsolstat != SCIP_LPSOLSTAT_INFEASIBLE &&
477  (lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || SCIPisLT(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)))));
478  }
479 
480  /* perform backtracking if a cutoff was detected */
481  if( cutoff && !backtracked && heurdata->backtrack )
482  {
483  SCIPdebugMessage(" *** cutoff detected at level %d - backtracking\n", SCIPgetProbingDepth(scip));
485  SCIP_CALL( SCIPnewProbingNode(scip) );
486  backtracked = TRUE;
487  }
488  else
489  backtracked = FALSE;
490  }
491  while( backtracked );
492 
493  if( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
494  {
495  /* get new objective value */
496  oldobjval = objval;
497  objval = SCIPgetLPObjval(scip);
498 
499  /* update pseudo cost values */
500  if( SCIPisGT(scip, objval, oldobjval) )
501  {
502  if( bestcandroundup )
503  {
504  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[bestcand], 1.0-lpcandsfrac[bestcand],
505  objval - oldobjval, 1.0) );
506  }
507  else
508  {
509  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[bestcand], 0.0-lpcandsfrac[bestcand],
510  objval - oldobjval, 1.0) );
511  }
512  }
513 
514  /* get new fractional variables */
515  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
516  }
517  SCIPdebugMessage(" -> lpsolstat=%d, objval=%g, nfrac=%d\n", lpsolstat, objval, nlpcands);
518  }
519 
520  /* check if a solution has been found */
521  if( nlpcands == 0 && !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
522  {
523  /* create solution from diving LP */
524  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
525  SCIPdebugMessage("linesearchdiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
526 
527  /* try to add solution to SCIP */
528  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
529 
530  /* check, if solution was feasible and good enough */
531  if( success )
532  {
533  SCIPdebugMessage(" -> solution was feasible and good enough\n");
534  *result = SCIP_FOUNDSOL;
535  }
536  }
537 
538  /* end diving */
539  SCIP_CALL( SCIPendProbing(scip) );
540 
541  if( *result == SCIP_FOUNDSOL )
542  heurdata->nsuccess++;
543 
544  SCIPdebugMessage("linesearchdiving heuristic finished\n");
545 
546  return SCIP_OKAY;
547 }
548 
549 
550 /*
551  * primal heuristic specific interface methods
552  */
553 
554 /** creates the linesearchdiving primal heuristic and includes it in SCIP */
556  SCIP* scip /**< SCIP data structure */
557  )
558 {
559  SCIP_HEURDATA* heurdata;
560  SCIP_HEUR* heur;
561 
562  /* create Linesearchdiving primal heuristic data */
563  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
564 
565  /* include primal heuristic */
566  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
568  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecLinesearchdiving, heurdata) );
569 
570  assert(heur != NULL);
571 
572  /* set non-NULL pointers to callback methods */
573  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyLinesearchdiving) );
574  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeLinesearchdiving) );
575  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitLinesearchdiving) );
576  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitLinesearchdiving) );
577 
578  /* add linesearchdiving primal heuristic parameters */
580  "heuristics/linesearchdiving/minreldepth",
581  "minimal relative depth to start diving",
582  &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
584  "heuristics/linesearchdiving/maxreldepth",
585  "maximal relative depth to start diving",
586  &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
588  "heuristics/linesearchdiving/maxlpiterquot",
589  "maximal fraction of diving LP iterations compared to node LP iterations",
590  &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
592  "heuristics/linesearchdiving/maxlpiterofs",
593  "additional number of allowed LP iterations",
594  &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
596  "heuristics/linesearchdiving/maxdiveubquot",
597  "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
598  &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
600  "heuristics/linesearchdiving/maxdiveavgquot",
601  "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
602  &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
604  "heuristics/linesearchdiving/maxdiveubquotnosol",
605  "maximal UBQUOT when no solution was found yet (0.0: no limit)",
606  &heurdata->maxdiveubquotnosol, TRUE, DEFAULT_MAXDIVEUBQUOTNOSOL, 0.0, 1.0, NULL, NULL) );
608  "heuristics/linesearchdiving/maxdiveavgquotnosol",
609  "maximal AVGQUOT when no solution was found yet (0.0: no limit)",
610  &heurdata->maxdiveavgquotnosol, TRUE, DEFAULT_MAXDIVEAVGQUOTNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
612  "heuristics/linesearchdiving/backtrack",
613  "use one level of backtracking if infeasibility is encountered?",
614  &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
615 
616  return SCIP_OKAY;
617 }
618