Scippy

SCIP

Solving Constraint Integer Programs

heur_guideddiving.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_guideddiving.c
17  * @brief LP diving heuristic that chooses fixings in direction of incumbent solutions
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 
26 #include "scip/heur_guideddiving.h"
27 
28 
29 #define HEUR_NAME "guideddiving"
30 #define HEUR_DESC "LP diving heuristic that chooses fixings in direction of incumbent solutions"
31 #define HEUR_DISPCHAR 'g'
32 #define HEUR_PRIORITY -1007000
33 #define HEUR_FREQ 10
34 #define HEUR_FREQOFS 7
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_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
53 
54 #define MINLPITER 10000 /**< minimal number of LP iterations allowed in each LP solving call */
55 
56 
57 /* locally defined heuristic data */
58 struct SCIP_HeurData
59 {
60  SCIP_SOL* sol; /**< working solution */
61  SCIP_Real minreldepth; /**< minimal relative depth to start diving */
62  SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
63  SCIP_Real maxlpiterquot; /**< maximal fraction of diving LP iterations compared to node LP iterations */
64  int maxlpiterofs; /**< additional number of allowed LP iterations */
65  SCIP_Real maxdiveubquot; /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
66  * where diving is performed (0.0: no limit) */
67  SCIP_Real maxdiveavgquot; /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
68  * where diving is performed (0.0: no limit) */
69  SCIP_Bool backtrack; /**< use one level of backtracking if infeasibility is encountered? */
70  SCIP_Longint nlpiterations; /**< LP iterations used in this heuristic */
71  int nsuccess; /**< number of runs that produced at least one feasible solution */
72 };
73 
74 
75 /*
76  * local methods
77  */
78 
79 
80 /*
81  * Callback methods
82  */
83 
84 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
85 static
86 SCIP_DECL_HEURCOPY(heurCopyGuideddiving)
87 { /*lint --e{715}*/
88  assert(scip != NULL);
89  assert(heur != NULL);
90  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
91 
92  /* call inclusion method of primal heuristic */
94 
95  return SCIP_OKAY;
96 }
97 
98 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
99 static
100 SCIP_DECL_HEURFREE(heurFreeGuideddiving) /*lint --e{715}*/
101 { /*lint --e{715}*/
102  SCIP_HEURDATA* heurdata;
103 
104  assert(heur != NULL);
105  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
106  assert(scip != NULL);
107 
108  /* free heuristic data */
109  heurdata = SCIPheurGetData(heur);
110  assert(heurdata != NULL);
111  SCIPfreeMemory(scip, &heurdata);
112  SCIPheurSetData(heur, NULL);
113 
114  return SCIP_OKAY;
115 }
116 
117 
118 /** initialization method of primal heuristic (called after problem was transformed) */
119 static
120 SCIP_DECL_HEURINIT(heurInitGuideddiving) /*lint --e{715}*/
121 { /*lint --e{715}*/
122  SCIP_HEURDATA* heurdata;
123 
124  assert(heur != NULL);
125  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
126 
127  /* get heuristic data */
128  heurdata = SCIPheurGetData(heur);
129  assert(heurdata != NULL);
130 
131  /* create working solution */
132  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
133 
134  /* initialize data */
135  heurdata->nlpiterations = 0;
136  heurdata->nsuccess = 0;
137 
138  return SCIP_OKAY;
139 }
140 
141 
142 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
143 static
144 SCIP_DECL_HEUREXIT(heurExitGuideddiving) /*lint --e{715}*/
145 { /*lint --e{715}*/
146  SCIP_HEURDATA* heurdata;
147 
148  assert(heur != NULL);
149  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
150 
151  /* get heuristic data */
152  heurdata = SCIPheurGetData(heur);
153  assert(heurdata != NULL);
154 
155  /* free working solution */
156  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
157 
158  return SCIP_OKAY;
159 }
160 
161 
162 /** execution method of primal heuristic */
163 static
164 SCIP_DECL_HEUREXEC(heurExecGuideddiving) /*lint --e{715}*/
165 { /*lint --e{715}*/
166  SCIP_HEURDATA* heurdata;
167  SCIP_LPSOLSTAT lpsolstat;
168  SCIP_SOL* bestsol;
169  SCIP_VAR* var;
170  SCIP_VAR** lpcands;
171  SCIP_Real* lpcandssol;
172  SCIP_Real* lpcandsfrac;
173  SCIP_Real searchubbound;
174  SCIP_Real searchavgbound;
175  SCIP_Real searchbound;
176  SCIP_Real objval;
177  SCIP_Real oldobjval;
178  SCIP_Real obj;
179  SCIP_Real objgain;
180  SCIP_Real bestobjgain;
181  SCIP_Real frac;
182  SCIP_Real bestfrac;
183  SCIP_Real solval;
184  SCIP_Real bestsolval;
185  SCIP_Bool bestcandmayrounddown;
186  SCIP_Bool bestcandmayroundup;
187  SCIP_Bool bestcandroundup;
188  SCIP_Bool mayrounddown;
189  SCIP_Bool mayroundup;
190  SCIP_Bool roundup;
191  SCIP_Bool lperror;
192  SCIP_Bool cutoff;
193  SCIP_Bool backtracked;
194  SCIP_Bool backtrack;
195  SCIP_Longint ncalls;
196  SCIP_Longint nsolsfound;
197  SCIP_Longint nlpiterations;
198  SCIP_Longint maxnlpiterations;
199  int nlpcands;
200  int startnlpcands;
201  int depth;
202  int maxdepth;
203  int maxdivedepth;
204  int divedepth;
205  int bestcand;
206  int c;
207 
208  assert(heur != NULL);
209  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
210  assert(scip != NULL);
211  assert(result != NULL);
212  assert(SCIPhasCurrentNodeLP(scip));
213 
214  *result = SCIP_DELAYED;
215 
216  /* do not call heuristic of node was already detected to be infeasible */
217  if( nodeinfeasible )
218  return SCIP_OKAY;
219 
220  /* only call heuristic, if an optimal LP solution is at hand */
222  return SCIP_OKAY;
223 
224  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
225  if( SCIPisGE(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)) )
226  return SCIP_OKAY;
227 
228  /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
229  if( !SCIPisLPSolBasic(scip) )
230  return SCIP_OKAY;
231 
232  /* don't dive two times at the same node */
233  if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
234  return SCIP_OKAY;
235 
236  *result = SCIP_DIDNOTRUN;
237 
238  /* don't dive, if no feasible solutions exist */
239  if( SCIPgetNSols(scip) == 0 )
240  return SCIP_OKAY;
241 
242  /* get heuristic's data */
243  heurdata = SCIPheurGetData(heur);
244  assert(heurdata != NULL);
245 
246  /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
247  depth = SCIPgetDepth(scip);
248  maxdepth = SCIPgetMaxDepth(scip);
249  maxdepth = MAX(maxdepth, 30);
250  if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
251  return SCIP_OKAY;
252 
253  /* calculate the maximal number of LP iterations until heuristic is aborted */
254  nlpiterations = SCIPgetNNodeLPIterations(scip);
255  ncalls = SCIPheurGetNCalls(heur);
256  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
257  maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
258  maxnlpiterations += heurdata->maxlpiterofs;
259 
260  /* don't try to dive, if we took too many LP iterations during diving */
261  if( heurdata->nlpiterations >= maxnlpiterations )
262  return SCIP_OKAY;
263 
264  /* allow at least a certain number of LP iterations in this dive */
265  maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
266 
267  /* get fractional variables that should be integral */
268  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
269 
270  /* don't try to dive, if there are no fractional variables */
271  if( nlpcands == 0 )
272  return SCIP_OKAY;
273 
274  /* calculate the objective search bound */
275  if( heurdata->maxdiveubquot > 0.0 )
276  searchubbound = SCIPgetLowerbound(scip)
277  + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
278  else
279  searchubbound = SCIPinfinity(scip);
280  if( heurdata->maxdiveavgquot > 0.0 )
281  searchavgbound = SCIPgetLowerbound(scip)
282  + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
283  else
284  searchavgbound = SCIPinfinity(scip);
285  searchbound = MIN(searchubbound, searchavgbound);
286  if( SCIPisObjIntegral(scip) )
287  searchbound = SCIPceil(scip, searchbound);
288 
289  /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
290  maxdivedepth = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
291  maxdivedepth = MIN(maxdivedepth, maxdepth);
292  maxdivedepth *= 10;
293 
294  /* get best solution that should guide the search; if this solution lives in the original variable space,
295  * we cannot use it since it might violate the global bounds of the current problem
296  */
297  if( SCIPsolIsOriginal(SCIPgetBestSol(scip)) )
298  return SCIP_OKAY;
299 
300  /* store a copy of the best solution */
301  SCIP_CALL( SCIPcreateSolCopy(scip, &bestsol, SCIPgetBestSol(scip)) );
302 
303  *result = SCIP_DIDNOTFIND;
304 
305  /* start diving */
306  SCIP_CALL( SCIPstartProbing(scip) );
307 
308  /* enables collection of variable statistics during probing */
309  SCIPenableVarHistory(scip);
310 
311  /* get LP objective value */
312  lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
313  objval = SCIPgetLPObjval(scip);
314 
315  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") executing guideddiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
316  SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), SCIPretransformObj(scip, searchbound));
317 
318  /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
319  * - if possible, we dive at least with the depth 10
320  * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
321  */
322  lperror = FALSE;
323  cutoff = FALSE;
324  divedepth = 0;
325  bestcandmayrounddown = FALSE;
326  bestcandmayroundup = FALSE;
327  startnlpcands = nlpcands;
328  roundup = FALSE;
329  while( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0
330  && (divedepth < 10
331  || nlpcands <= startnlpcands - divedepth/2
332  || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations && objval < searchbound))
333  && !SCIPisStopped(scip) )
334  {
335  SCIP_CALL( SCIPnewProbingNode(scip) );
336  divedepth++;
337 
338  /* choose variable fixing:
339  * - prefer variables that may not be rounded without destroying LP feasibility:
340  * - of these variables, round a variable to its value in direction of incumbent solution, and choose the
341  * variable that is closest to its rounded value
342  * - if all remaining fractional variables may be rounded without destroying LP feasibility:
343  * - round variable in direction that destroys LP feasibility (other direction is checked by SCIProundSol())
344  * - round variable with least increasing objective value
345  */
346  bestcand = -1;
347  bestobjgain = SCIPinfinity(scip);
348  bestfrac = SCIP_INVALID;
349  bestcandmayrounddown = TRUE;
350  bestcandmayroundup = TRUE;
351  bestcandroundup = FALSE;
352  for( c = 0; c < nlpcands; ++c )
353  {
354  var = lpcands[c];
355  mayrounddown = SCIPvarMayRoundDown(var);
356  mayroundup = SCIPvarMayRoundUp(var);
357  solval = lpcandssol[c];
358  frac = lpcandsfrac[c];
359  obj = SCIPvarGetObj(var);
360  bestsolval = SCIPgetSolVal(scip, bestsol, var);
361 
362  /* select default rounding direction */
363  roundup = (solval < bestsolval);
364 
365  if( mayrounddown || mayroundup )
366  {
367  /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
368  if( bestcandmayrounddown || bestcandmayroundup )
369  {
370  /* choose rounding direction:
371  * - if variable may be rounded in both directions, round corresponding to its value in incumbent solution
372  * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
373  * the current fractional solution with SCIProundSol()
374  */
375  if( !mayrounddown || !mayroundup )
376  roundup = mayrounddown;
377 
378  if( roundup )
379  {
380  frac = 1.0 - frac;
381  objgain = frac*obj;
382  }
383  else
384  objgain = -frac*obj;
385 
386  /* penalize too small fractions */
387  if( frac < 0.01 )
388  objgain *= 1000.0;
389 
390  /* prefer decisions on binary variables */
391  if( !SCIPvarIsBinary(var) )
392  objgain *= 1000.0;
393 
394  /* check, if candidate is new best candidate */
395  if( SCIPisLT(scip, objgain, bestobjgain) || (SCIPisEQ(scip, objgain, bestobjgain) && frac < bestfrac) )
396  {
397  bestcand = c;
398  bestobjgain = objgain;
399  bestfrac = frac;
400  bestcandmayrounddown = mayrounddown;
401  bestcandmayroundup = mayroundup;
402  bestcandroundup = roundup;
403  }
404  }
405  }
406  else
407  {
408  /* the candidate may not be rounded */
409  if( roundup )
410  frac = 1.0 - frac;
411 
412  /* penalize too small fractions */
413  if( frac < 0.01 )
414  frac += 10.0;
415 
416  /* prefer decisions on binary variables */
417  if( !SCIPvarIsBinary(var) )
418  frac *= 1000.0;
419 
420  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
421  if( bestcandmayrounddown || bestcandmayroundup || frac < bestfrac )
422  {
423  bestcand = c;
424  bestfrac = frac;
425  bestcandmayrounddown = FALSE;
426  bestcandmayroundup = FALSE;
427  bestcandroundup = roundup;
428  }
429  }
430  }
431  assert(bestcand != -1);
432 
433  /* if all candidates are roundable, try to round the solution */
434  if( bestcandmayrounddown || bestcandmayroundup )
435  {
436  SCIP_Bool success;
437 
438  /* create solution from diving LP and try to round it */
439  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
440  SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
441 
442  if( success )
443  {
444  SCIPdebugMessage("guideddiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
445 
446  /* try to add solution to SCIP */
447  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
448 
449  /* check, if solution was feasible and good enough */
450  if( success )
451  {
452  SCIPdebugMessage(" -> solution was feasible and good enough\n");
453  *result = SCIP_FOUNDSOL;
454  }
455  }
456  }
457 
458  var = lpcands[bestcand];
459 
460  backtracked = FALSE;
461 
462 
463  do
464  {
465  backtrack = FALSE;
466  /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
467  * occured or variable was fixed by propagation while backtracking => Abort diving!
468  */
469  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
470  {
471  SCIPdebugMessage("Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
472  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
473  cutoff = TRUE;
474  break;
475  }
476  if( SCIPisFeasLT(scip, lpcandssol[bestcand], SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, lpcandssol[bestcand], SCIPvarGetUbLocal(var)) )
477  {
478  SCIPdebugMessage("selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
479  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
480  assert(backtracked);
481  break;
482  }
483 
484  /* apply rounding of best candidate */
485  if( bestcandroundup == !backtracked )
486  {
487  /* round variable up */
488  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, round=%u/%u, sol=%g, bestsol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
489  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
490  SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
491  lpcandssol[bestcand], SCIPgetSolVal(scip, bestsol, var),
493  SCIPfeasCeil(scip, lpcandssol[bestcand]), SCIPvarGetUbLocal(var));
494  SCIP_CALL( SCIPchgVarLbProbing(scip, var, SCIPfeasCeil(scip, lpcandssol[bestcand])) );
495  roundup = TRUE;
496  }
497  else
498  {
499  /* round variable down */
500  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, round=%u/%u, sol=%g, bestsol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
501  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
502  SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
503  lpcandssol[bestcand], SCIPgetSolVal(scip, bestsol, var),
505  SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, lpcandssol[bestcand]));
506  SCIP_CALL( SCIPchgVarUbProbing(scip, var, SCIPfeasFloor(scip, lpcandssol[bestcand])) );
507  roundup = FALSE;
508  }
509 
510  /* apply domain propagation */
511  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
512  if( !cutoff )
513  {
514  /* resolve the diving LP */
515  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
516  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
517  */
518 #ifdef NDEBUG
519  SCIP_RETCODE retstat;
520  nlpiterations = SCIPgetNLPIterations(scip);
521  retstat = SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff);
522  if( retstat != SCIP_OKAY )
523  {
524  SCIPwarningMessage(scip, "Error while solving LP in Guideddiving heuristic; LP solve terminated with code <%d>\n",retstat);
525  }
526 #else
527  nlpiterations = SCIPgetNLPIterations(scip);
528  SCIP_CALL( SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff) );
529 #endif
530 
531  if( lperror )
532  break;
533 
534  /* update iteration count */
535  heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;
536 
537  /* get LP solution status, objective value, and fractional variables, that should be integral */
538  lpsolstat = SCIPgetLPSolstat(scip);
539  assert(cutoff || (lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT && lpsolstat != SCIP_LPSOLSTAT_INFEASIBLE &&
540  (lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || SCIPisLT(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)))));
541  }
542 
543  /* perform backtracking if a cutoff was detected */
544  if( cutoff && !backtracked && heurdata->backtrack )
545  {
546  SCIPdebugMessage(" *** cutoff detected at level %d - backtracking\n", SCIPgetProbingDepth(scip));
548  SCIP_CALL( SCIPnewProbingNode(scip) );
549  backtracked = TRUE;
550  backtrack = TRUE;
551  }
552  else
553  backtrack = FALSE;
554  }
555  while( backtrack );
556 
557  if( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
558  {
559  /* get new objective value */
560  oldobjval = objval;
561  objval = SCIPgetLPObjval(scip);
562 
563  /* update pseudo cost values */
564  if( SCIPisGT(scip, objval, oldobjval) )
565  {
566  if( roundup )
567  {
568  assert(bestcandroundup || backtracked );
569  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[bestcand], 1.0-lpcandsfrac[bestcand],
570  objval - oldobjval, 1.0) );
571  }
572  else
573  {
574  assert(!bestcandroundup || backtracked);
575  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[bestcand], 0.0-lpcandsfrac[bestcand],
576  objval - oldobjval, 1.0) );
577  }
578  }
579 
580  /* get new fractional variables */
581  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
582  }
583  SCIPdebugMessage(" -> lpsolstat=%d, objval=%g, nfrac=%d\n", lpsolstat, objval, nlpcands);
584  }
585 
586  /* check if a solution has been found */
587  if( nlpcands == 0 && !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
588  {
589  SCIP_Bool success;
590 
591  /* create solution from diving LP */
592  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
593  SCIPdebugMessage("guideddiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
594 
595  /* try to add solution to SCIP */
596  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
597 
598  /* check, if solution was feasible and good enough */
599  if( success )
600  {
601  SCIPdebugMessage(" -> solution was feasible and good enough\n");
602  *result = SCIP_FOUNDSOL;
603  }
604  }
605 
606  /* end diving */
607  SCIP_CALL( SCIPendProbing(scip) );
608 
609  /* free copied best solution */
610  SCIP_CALL( SCIPfreeSol(scip, &bestsol) );
611 
612  if( *result == SCIP_FOUNDSOL )
613  heurdata->nsuccess++;
614 
615  SCIPdebugMessage("guideddiving heuristic finished\n");
616 
617  return SCIP_OKAY;
618 }
619 
620 
621 /*
622  * heuristic specific interface methods
623  */
624 
625 /** creates the guideddiving heuristic and includes it in SCIP */
627  SCIP* scip /**< SCIP data structure */
628  )
629 {
630  SCIP_HEURDATA* heurdata;
631  SCIP_HEUR* heur;
632 
633  /* create Guideddiving primal heuristic data */
634  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
635 
636  /* include primal heuristic */
637  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
639  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecGuideddiving, heurdata) );
640 
641  assert(heur != NULL);
642 
643  /* set non-NULL pointers to callback methods */
644  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyGuideddiving) );
645  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeGuideddiving) );
646  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitGuideddiving) );
647  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitGuideddiving) );
648 
649  /* guideddiving heuristic parameters */
651  "heuristics/guideddiving/minreldepth",
652  "minimal relative depth to start diving",
653  &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
655  "heuristics/guideddiving/maxreldepth",
656  "maximal relative depth to start diving",
657  &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
659  "heuristics/guideddiving/maxlpiterquot",
660  "maximal fraction of diving LP iterations compared to node LP iterations",
661  &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
663  "heuristics/guideddiving/maxlpiterofs",
664  "additional number of allowed LP iterations",
665  &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
667  "heuristics/guideddiving/maxdiveubquot",
668  "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
669  &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
671  "heuristics/guideddiving/maxdiveavgquot",
672  "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
673  &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
675  "heuristics/guideddiving/backtrack",
676  "use one level of backtracking if infeasibility is encountered?",
677  &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
678 
679  return SCIP_OKAY;
680 }
681 
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38254
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:29936
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
Definition: scip.c:30002
SCIP_Real SCIPgetAvgLowerbound(SCIP *scip)
Definition: scip.c:35019
#define DEFAULT_MINRELDEPTH
#define HEUR_MAXDEPTH
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
#define MINLPITER
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:591
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:717
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7014
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:29573
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:15968
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3269
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1206
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38667
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:34147
static SCIP_DECL_HEURINIT(heurInitGuideddiving)
void SCIPenableVarHistory(SCIP *scip)
Definition: scip.c:21124
#define HEUR_PRIORITY
#define NULL
Definition: lpi_spx.cpp:129
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1111
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:38803
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, unsigned int timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:6969
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:29766
#define FALSE
Definition: def.h:52
#define DEFAULT_MAXDIVEAVGQUOT
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10116
SCIP_RETCODE SCIPincludeHeurGuideddiving(SCIP *scip)
#define TRUE
Definition: def.h:51
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPupdateVarPseudocost(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: scip.c:21163
LP diving heuristic that chooses fixings in direction of incumbent solutions.
static SCIP_DECL_HEURCOPY(heurCopyGuideddiving)
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:44
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:35229
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:24136
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:31775
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
SCIP_Real SCIPgetLPObjval(SCIP *scip)
Definition: scip.c:24179
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:38815
#define DEFAULT_MAXLPITERQUOT
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:35061
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31855
#define HEUR_TIMING
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:32432
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:3388
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:3414
static SCIP_DECL_HEURFREE(heurFreeGuideddiving)
#define HEUR_USESSUBSCIP
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38273
SCIP_Real SCIPgetDualbound(SCIP *scip)
Definition: scip.c:35040
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:19159
#define HEUR_FREQOFS
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip.c:9683
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:29546
int SCIPgetMaxDepth(SCIP *scip)
Definition: scip.c:34883
#define DEFAULT_MAXRELDEPTH
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:30856
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
#define SCIP_CALL(x)
Definition: def.h:258
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:24051
SCIP_Bool SCIPisFeasGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38705
SCIP_Longint SCIPgetLastDivenode(SCIP *scip)
Definition: scip.c:29390
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:512
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38311
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
#define SCIP_Bool
Definition: def.h:49
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip.c:31962
#define DEFAULT_MAXLPITEROFS
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPcreateSolCopy(SCIP *scip, SCIP_SOL **sol, SCIP_SOL *sourcesol)
Definition: scip.c:31124
static SCIP_DECL_HEUREXIT(heurExitGuideddiving)
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:29476
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:29607
#define HEUR_DESC
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:34833
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31444
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2119
#define DEFAULT_MAXDIVEUBQUOT
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:7062
SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:38330
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7046
#define SCIP_REAL_MAX
Definition: def.h:124
SCIP_Real SCIPceil(SCIP *scip, SCIP_Real val)
Definition: scip.c:38482
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:737
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:19176
static SCIP_DECL_HEUREXEC(heurExecGuideddiving)
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10161
#define HEUR_FREQ
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:29674
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:7030
#define DEFAULT_BACKTRACK
#define SCIP_Real
Definition: def.h:123
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:29513
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:29640
#define MIN(x, y)
Definition: memory.c:59
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3277
#define SCIP_INVALID
Definition: def.h:142
#define HEUR_DISPCHAR
#define SCIP_Longint
Definition: def.h:107
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:502
SCIP_Bool SCIPisLPSolBasic(SCIP *scip)
Definition: scip.c:24544
SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
Definition: scip.c:34442
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:32531
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:3470
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:32978
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:34065
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:31403
#define HEUR_NAME
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:32673