Scippy

SCIP

Solving Constraint Integer Programs

heur_fracdiving.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_fracdiving.c
17  * @brief LP diving heuristic that chooses fixings w.r.t. the fractionalities
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_fracdiving.h"
27 
28 
29 #define HEUR_NAME "fracdiving"
30 #define HEUR_DESC "LP diving heuristic that chooses fixings w.r.t. the fractionalities"
31 #define HEUR_DISPCHAR 'f'
32 #define HEUR_PRIORITY -1003000
33 #define HEUR_FREQ 10
34 #define HEUR_FREQOFS 3
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 /* locally defined heuristic data */
60 struct SCIP_HeurData
61 {
62  SCIP_SOL* sol; /**< working solution */
63  SCIP_Real minreldepth; /**< minimal relative depth to start diving */
64  SCIP_Real maxreldepth; /**< maximal relative depth to start diving */
65  SCIP_Real maxlpiterquot; /**< maximal fraction of diving LP iterations compared to node LP iterations */
66  int maxlpiterofs; /**< additional number of allowed LP iterations */
67  SCIP_Real maxdiveubquot; /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
68  * where diving is performed (0.0: no limit) */
69  SCIP_Real maxdiveavgquot; /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
70  * where diving is performed (0.0: no limit) */
71  SCIP_Real maxdiveubquotnosol; /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
72  SCIP_Real maxdiveavgquotnosol;/**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
73  SCIP_Bool backtrack; /**< use one level of backtracking if infeasibility is encountered? */
74  SCIP_Longint nlpiterations; /**< LP iterations used in this heuristic */
75  int nsuccess; /**< number of runs that produced at least one feasible solution */
76 };
77 
78 
79 /*
80  * local methods
81  */
82 
83 
84 /*
85  * Callback methods
86  */
87 
88 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
89 static
90 SCIP_DECL_HEURCOPY(heurCopyFracdiving)
91 { /*lint --e{715}*/
92  assert(scip != NULL);
93  assert(heur != NULL);
94  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
95 
96  /* call inclusion method of primal heuristic */
98 
99  return SCIP_OKAY;
100 }
101 
102 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
103 static
104 SCIP_DECL_HEURFREE(heurFreeFracdiving) /*lint --e{715}*/
105 { /*lint --e{715}*/
106  SCIP_HEURDATA* heurdata;
107 
108  assert(heur != NULL);
109  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
110  assert(scip != NULL);
111 
112  /* free heuristic data */
113  heurdata = SCIPheurGetData(heur);
114  assert(heurdata != NULL);
115  SCIPfreeMemory(scip, &heurdata);
116  SCIPheurSetData(heur, NULL);
117 
118  return SCIP_OKAY;
119 }
120 
121 
122 /** initialization method of primal heuristic (called after problem was transformed) */
123 static
124 SCIP_DECL_HEURINIT(heurInitFracdiving) /*lint --e{715}*/
125 { /*lint --e{715}*/
126  SCIP_HEURDATA* heurdata;
127 
128  assert(heur != NULL);
129  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
130 
131  /* get heuristic data */
132  heurdata = SCIPheurGetData(heur);
133  assert(heurdata != NULL);
134 
135  /* create working solution */
136  SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
137 
138  /* initialize data */
139  heurdata->nlpiterations = 0;
140  heurdata->nsuccess = 0;
141 
142  return SCIP_OKAY;
143 }
144 
145 
146 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
147 static
148 SCIP_DECL_HEUREXIT(heurExitFracdiving) /*lint --e{715}*/
149 { /*lint --e{715}*/
150  SCIP_HEURDATA* heurdata;
151 
152  assert(heur != NULL);
153  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
154 
155  /* get heuristic data */
156  heurdata = SCIPheurGetData(heur);
157  assert(heurdata != NULL);
158 
159  /* free working solution */
160  SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
161 
162  return SCIP_OKAY;
163 }
164 
165 
166 /** execution method of primal heuristic */
167 static
168 SCIP_DECL_HEUREXEC(heurExecFracdiving) /*lint --e{715}*/
169 { /*lint --e{715}*/
170  SCIP_HEURDATA* heurdata;
171  SCIP_LPSOLSTAT lpsolstat;
172  SCIP_VAR* var;
173  SCIP_VAR** lpcands;
174  SCIP_Real* lpcandssol;
175  SCIP_Real* lpcandsfrac;
176  SCIP_Real searchubbound;
177  SCIP_Real searchavgbound;
178  SCIP_Real searchbound;
179  SCIP_Real objval;
180  SCIP_Real oldobjval;
181  SCIP_Real obj;
182  SCIP_Real objgain;
183  SCIP_Real bestobjgain;
184  SCIP_Real frac;
185  SCIP_Real bestfrac;
186  SCIP_Bool bestcandmayrounddown;
187  SCIP_Bool bestcandmayroundup;
188  SCIP_Bool bestcandroundup;
189  SCIP_Bool mayrounddown;
190  SCIP_Bool mayroundup;
191  SCIP_Bool roundup;
192  SCIP_Bool lperror;
193  SCIP_Bool cutoff;
194  SCIP_Bool backtracked;
195  SCIP_Bool backtrack;
196  SCIP_Longint ncalls;
197  SCIP_Longint nsolsfound;
198  SCIP_Longint nlpiterations;
199  SCIP_Longint maxnlpiterations;
200  int nlpcands;
201  int startnlpcands;
202  int depth;
203  int maxdepth;
204  int maxdivedepth;
205  int divedepth;
206  int bestcand;
207  int c;
208 
209  assert(heur != NULL);
210  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
211  assert(scip != NULL);
212  assert(result != NULL);
213  assert(SCIPhasCurrentNodeLP(scip));
214 
215  *result = SCIP_DELAYED;
216 
217  /* do not call heuristic of node was already detected to be infeasible */
218  if( nodeinfeasible )
219  return SCIP_OKAY;
220 
221  /* only call heuristic, if an optimal LP solution is at hand */
223  return SCIP_OKAY;
224 
225  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
226  if( SCIPisGE(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)) )
227  return SCIP_OKAY;
228 
229  /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
230  if( !SCIPisLPSolBasic(scip) )
231  return SCIP_OKAY;
232 
233  /* don't dive two times at the same node */
234  if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
235  return SCIP_OKAY;
236 
237  *result = SCIP_DIDNOTRUN;
238 
239  /* get heuristic's data */
240  heurdata = SCIPheurGetData(heur);
241  assert(heurdata != NULL);
242 
243  /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
244  depth = SCIPgetDepth(scip);
245  maxdepth = SCIPgetMaxDepth(scip);
246  maxdepth = MAX(maxdepth, 30);
247  if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
248  return SCIP_OKAY;
249 
250  /* calculate the maximal number of LP iterations until heuristic is aborted */
251  nlpiterations = SCIPgetNNodeLPIterations(scip);
252  ncalls = SCIPheurGetNCalls(heur);
253  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
254  maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
255  maxnlpiterations += heurdata->maxlpiterofs;
256 
257  /* don't try to dive, if we took too many LP iterations during diving */
258  if( heurdata->nlpiterations >= maxnlpiterations )
259  return SCIP_OKAY;
260 
261  /* allow at least a certain number of LP iterations in this dive */
262  maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
263 
264  /* get fractional variables that should be integral */
265  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
266 
267  /* don't try to dive, if there are no fractional variables */
268  if( nlpcands == 0 )
269  return SCIP_OKAY;
270 
271  /* calculate the objective search bound */
272  if( SCIPgetNSolsFound(scip) == 0 )
273  {
274  if( heurdata->maxdiveubquotnosol > 0.0 )
275  searchubbound = SCIPgetLowerbound(scip)
276  + heurdata->maxdiveubquotnosol * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
277  else
278  searchubbound = SCIPinfinity(scip);
279  if( heurdata->maxdiveavgquotnosol > 0.0 )
280  searchavgbound = SCIPgetLowerbound(scip)
281  + heurdata->maxdiveavgquotnosol * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
282  else
283  searchavgbound = SCIPinfinity(scip);
284  }
285  else
286  {
287  if( heurdata->maxdiveubquot > 0.0 )
288  searchubbound = SCIPgetLowerbound(scip)
289  + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
290  else
291  searchubbound = SCIPinfinity(scip);
292  if( heurdata->maxdiveavgquot > 0.0 )
293  searchavgbound = SCIPgetLowerbound(scip)
294  + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
295  else
296  searchavgbound = SCIPinfinity(scip);
297  }
298  searchbound = MIN(searchubbound, searchavgbound);
299  if( SCIPisObjIntegral(scip) )
300  searchbound = SCIPceil(scip, searchbound);
301 
302  /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
303  maxdivedepth = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
304  maxdivedepth = MIN(maxdivedepth, maxdepth);
305  maxdivedepth *= 10;
306 
307 
308  *result = SCIP_DIDNOTFIND;
309 
310  /* start diving */
311  SCIP_CALL( SCIPstartProbing(scip) );
312 
313  /* enables collection of variable statistics during probing */
314  SCIPenableVarHistory(scip);
315 
316  /* get LP objective value*/
317  lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
318  objval = SCIPgetLPObjval(scip);
319 
320  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") executing fracdiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
321  SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), SCIPretransformObj(scip, searchbound));
322 
323  /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
324  * - if possible, we dive at least with the depth 10
325  * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
326  */
327  lperror = FALSE;
328  cutoff = FALSE;
329  divedepth = 0;
330  bestcandmayrounddown = FALSE;
331  bestcandmayroundup = FALSE;
332  startnlpcands = nlpcands;
333  roundup = FALSE;
334  while( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0
335  && (divedepth < 10
336  || nlpcands <= startnlpcands - divedepth/2
337  || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations && objval < searchbound))
338  && !SCIPisStopped(scip) )
339  {
340  SCIP_CALL( SCIPnewProbingNode(scip) );
341  divedepth++;
342 
343  /* choose variable fixing:
344  * - prefer variables that may not be rounded without destroying LP feasibility:
345  * - of these variables, round least fractional variable in corresponding direction
346  * - if all remaining fractional variables may be rounded without destroying LP feasibility:
347  * - round variable with least increasing objective value
348  */
349  bestcand = -1;
350  bestobjgain = SCIPinfinity(scip);
351  bestfrac = SCIP_INVALID;
352  bestcandmayrounddown = TRUE;
353  bestcandmayroundup = TRUE;
354  bestcandroundup = FALSE;
355  for( c = 0; c < nlpcands; ++c )
356  {
357  var = lpcands[c];
358  mayrounddown = SCIPvarMayRoundDown(var);
359  mayroundup = SCIPvarMayRoundUp(var);
360  frac = lpcandsfrac[c];
361  obj = SCIPvarGetObj(var);
362  if( mayrounddown || mayroundup )
363  {
364  /* the candidate may be rounded: choose this candidate only, if the best candidate may also be rounded */
365  if( bestcandmayrounddown || bestcandmayroundup )
366  {
367  /* choose rounding direction:
368  * - if variable may be rounded in both directions, round corresponding to the fractionality
369  * - otherwise, round in the infeasible direction, because feasible direction is tried by rounding
370  * the current fractional solution
371  */
372  if( mayrounddown && mayroundup )
373  roundup = (frac > 0.5);
374  else
375  roundup = mayrounddown;
376 
377  if( roundup )
378  {
379  frac = 1.0 - frac;
380  objgain = frac*obj;
381  }
382  else
383  objgain = -frac*obj;
384 
385  /* penalize too small fractions */
386  if( frac < 0.01 )
387  objgain *= 1000.0;
388 
389  /* prefer decisions on binary variables */
390  if( !SCIPvarIsBinary(var) )
391  objgain *= 1000.0;
392 
393  /* check, if candidate is new best candidate */
394  if( SCIPisLT(scip, objgain, bestobjgain) || (SCIPisEQ(scip, objgain, bestobjgain) && frac < bestfrac) )
395  {
396  bestcand = c;
397  bestobjgain = objgain;
398  bestfrac = frac;
399  bestcandmayrounddown = mayrounddown;
400  bestcandmayroundup = mayroundup;
401  bestcandroundup = roundup;
402  }
403  }
404  }
405  else
406  {
407  /* the candidate may not be rounded */
408  if( frac < 0.5 )
409  roundup = FALSE;
410  else
411  {
412  roundup = TRUE;
413  frac = 1.0 - frac;
414  }
415 
416  /* penalize too small fractions */
417  if( frac < 0.01 )
418  frac += 10.0;
419 
420  /* prefer decisions on binary variables */
421  if( !SCIPvarIsBinary(var) )
422  frac *= 1000.0;
423 
424  /* check, if candidate is new best candidate: prefer unroundable candidates in any case */
425  if( bestcandmayrounddown || bestcandmayroundup || frac < bestfrac )
426  {
427  bestcand = c;
428  bestfrac = frac;
429  bestcandmayrounddown = FALSE;
430  bestcandmayroundup = FALSE;
431  bestcandroundup = roundup;
432  }
433  assert(bestfrac < SCIP_INVALID);
434  }
435  }
436  assert(bestcand != -1);
437 
438  /* if all candidates are roundable, try to round the solution */
439  if( bestcandmayrounddown || bestcandmayroundup )
440  {
441  SCIP_Bool success;
442 
443  /* create solution from diving LP and try to round it */
444  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
445  SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
446 
447  if( success )
448  {
449  SCIPdebugMessage("fracdiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
450 
451  /* try to add solution to SCIP */
452  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
453 
454  /* check, if solution was feasible and good enough */
455  if( success )
456  {
457  SCIPdebugMessage(" -> solution was feasible and good enough\n");
458  *result = SCIP_FOUNDSOL;
459  }
460  }
461  }
462 
463  var = lpcands[bestcand];
464 
465  backtracked = FALSE;
466  do
467  {
468  backtrack = FALSE;
469  /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
470  * occured or variable was fixed by propagation while backtracking => Abort diving!
471  */
472  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
473  {
474  SCIPdebugMessage("Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
475  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
476  cutoff = TRUE;
477  break;
478  }
479  if( SCIPisFeasLT(scip, lpcandssol[bestcand], SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, lpcandssol[bestcand], SCIPvarGetUbLocal(var)) )
480  {
481  SCIPdebugMessage("selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
482  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
483  assert(backtracked);
484  break;
485  }
486 
487  /* apply rounding of best candidate */
488  if( bestcandroundup == !backtracked )
489  {
490  /* round variable up */
491  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, round=%u/%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
492  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
493  SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
494  lpcandssol[bestcand], SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
495  SCIPfeasCeil(scip, lpcandssol[bestcand]), SCIPvarGetUbLocal(var));
496  SCIP_CALL( SCIPchgVarLbProbing(scip, var, SCIPfeasCeil(scip, lpcandssol[bestcand])) );
497  roundup = TRUE;
498  }
499  else
500  {
501  /* round variable down */
502  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, round=%u/%u, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
503  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
504  SCIPvarGetName(var), bestcandmayrounddown, bestcandmayroundup,
505  lpcandssol[bestcand], SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
506  SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, lpcandssol[bestcand]));
507  SCIP_CALL( SCIPchgVarUbProbing(scip, var, SCIPfeasFloor(scip, lpcandssol[bestcand])) );
508  roundup = FALSE;
509  }
510 
511  /* apply domain propagation */
512  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
513  if( !cutoff )
514  {
515  /* resolve the diving LP */
516  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
517  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
518  */
519 #ifdef NDEBUG
520  SCIP_RETCODE retstat;
521  nlpiterations = SCIPgetNLPIterations(scip);
522  retstat = SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff);
523  if( retstat != SCIP_OKAY )
524  {
525  SCIPwarningMessage(scip, "Error while solving LP in Fracdiving heuristic; LP solve terminated with code <%d>\n",retstat);
526  }
527 #else
528  nlpiterations = SCIPgetNLPIterations(scip);
529  SCIP_CALL( SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff) );
530 #endif
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/%g, nfrac=%d\n", lpsolstat, objval, searchbound, 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("fracdiving 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  if( *result == SCIP_FOUNDSOL )
610  heurdata->nsuccess++;
611 
612  SCIPdebugMessage("fracdiving heuristic finished\n");
613 
614  return SCIP_OKAY;
615 }
616 
617 
618 /*
619  * heuristic specific interface methods
620  */
621 
622 /** creates the fracdiving heuristic and includes it in SCIP */
624  SCIP* scip /**< SCIP data structure */
625  )
626 {
627  SCIP_HEURDATA* heurdata;
628  SCIP_HEUR* heur;
629 
630  /* create Fracdiving primal heuristic data */
631  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
632 
633  /* include primal heuristic */
634  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
636  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecFracdiving, heurdata) );
637 
638  assert(heur != NULL);
639 
640  /* set non-NULL pointers to callback methods */
641  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyFracdiving) );
642  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeFracdiving) );
643  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitFracdiving) );
644  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitFracdiving) );
645 
646  /* fracdiving heuristic parameters */
648  "heuristics/fracdiving/minreldepth",
649  "minimal relative depth to start diving",
650  &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
652  "heuristics/fracdiving/maxreldepth",
653  "maximal relative depth to start diving",
654  &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
656  "heuristics/fracdiving/maxlpiterquot",
657  "maximal fraction of diving LP iterations compared to node LP iterations",
658  &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
660  "heuristics/fracdiving/maxlpiterofs",
661  "additional number of allowed LP iterations",
662  &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
664  "heuristics/fracdiving/maxdiveubquot",
665  "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
666  &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
668  "heuristics/fracdiving/maxdiveavgquot",
669  "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
670  &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
672  "heuristics/fracdiving/maxdiveubquotnosol",
673  "maximal UBQUOT when no solution was found yet (0.0: no limit)",
674  &heurdata->maxdiveubquotnosol, TRUE, DEFAULT_MAXDIVEUBQUOTNOSOL, 0.0, 1.0, NULL, NULL) );
676  "heuristics/fracdiving/maxdiveavgquotnosol",
677  "maximal AVGQUOT when no solution was found yet (0.0: no limit)",
678  &heurdata->maxdiveavgquotnosol, TRUE, DEFAULT_MAXDIVEAVGQUOTNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
680  "heuristics/fracdiving/backtrack",
681  "use one level of backtracking if infeasibility is encountered?",
682  &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
683 
684  return SCIP_OKAY;
685 }
686 
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
static SCIP_DECL_HEUREXIT(heurExitFracdiving)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
#define HEUR_PRIORITY
#define HEUR_DISPCHAR
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:591
#define DEFAULT_MAXDIVEUBQUOT
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
void SCIPenableVarHistory(SCIP *scip)
Definition: scip.c:21124
#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
#define HEUR_MAXDEPTH
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:29766
#define FALSE
Definition: def.h:52
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10116
#define HEUR_DESC
#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
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
LP diving heuristic that chooses fixings w.r.t. the fractionalities.
#define SCIPdebugMessage
Definition: pub_message.h:77
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
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:35061
#define MINLPITER
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31855
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
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
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip.c:9683
static SCIP_DECL_HEURCOPY(heurCopyFracdiving)
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:29546
int SCIPgetMaxDepth(SCIP *scip)
Definition: scip.c:34883
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:30856
#define DEFAULT_MAXLPITERQUOT
#define HEUR_TIMING
#define DEFAULT_MAXLPITEROFS
#define DEFAULT_MINRELDEPTH
#define DEFAULT_MAXDIVEAVGQUOTNOSOL
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
#define DEFAULT_MAXDIVEAVGQUOT
static SCIP_DECL_HEUREXEC(heurExecFracdiving)
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 HEUR_NAME
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPincludeHeurFracdiving(SCIP *scip)
#define DEFAULT_MAXRELDEPTH
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:29476
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:29607
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:34833
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31444
static SCIP_DECL_HEURINIT(heurInitFracdiving)
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
static SCIP_DECL_HEURFREE(heurFreeFracdiving)
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
SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
Definition: scip.c:35410
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:10161
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 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 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
#define DEFAULT_BACKTRACK
#define DEFAULT_MAXDIVEUBQUOTNOSOL
SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
Definition: scip.c:34442
#define HEUR_FREQ
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
#define HEUR_FREQOFS
#define HEUR_USESSUBSCIP
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:34065
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:31403
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:32673