Scippy

SCIP

Solving Constraint Integer Programs

heur_veclendiving.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_veclendiving.c
17  * @brief LP diving heuristic that rounds variables with long column vectors
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_veclendiving.h"
27 
28 
29 #define HEUR_NAME "veclendiving"
30 #define HEUR_DESC "LP diving heuristic that rounds variables with long column vectors"
31 #define HEUR_DISPCHAR 'v'
32 #define HEUR_PRIORITY -1003100
33 #define HEUR_FREQ 10
34 #define HEUR_FREQOFS 4
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(heurCopyVeclendiving)
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(heurFreeVeclendiving) /*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(heurInitVeclendiving) /*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(heurExitVeclendiving) /*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(heurExecVeclendiving) /*lint --e{715}*/
169 { /*lint --e{715}*/
170  SCIP_HEURDATA* heurdata;
171  SCIP_LPSOLSTAT lpsolstat;
172  SCIP_VAR** lpcands;
173  SCIP_Real* lpcandssol;
174  SCIP_Real* lpcandsfrac;
175  SCIP_Real searchubbound;
176  SCIP_Real searchavgbound;
177  SCIP_Real searchbound;
178  SCIP_Real objval;
179  SCIP_Bool lperror;
180  SCIP_Bool cutoff;
181  SCIP_Bool backtracked;
182  SCIP_Bool backtrack;
183  SCIP_Bool roundup;
184  SCIP_Longint ncalls;
185  SCIP_Longint nsolsfound;
186  SCIP_Longint nlpiterations;
187  SCIP_Longint maxnlpiterations;
188  int nlpcands;
189  int startnlpcands;
190  int depth;
191  int maxdepth;
192  int maxdivedepth;
193  int divedepth;
194 
195  assert(heur != NULL);
196  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
197  assert(scip != NULL);
198  assert(result != NULL);
199  assert(SCIPhasCurrentNodeLP(scip));
200 
201  *result = SCIP_DELAYED;
202 
203  /* do not call heuristic of node was already detected to be infeasible */
204  if( nodeinfeasible )
205  return SCIP_OKAY;
206 
207  /* only call heuristic, if an optimal LP solution is at hand */
209  return SCIP_OKAY;
210 
211  /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
212  if( SCIPisGE(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)) )
213  return SCIP_OKAY;
214 
215  /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
216  if( !SCIPisLPSolBasic(scip) )
217  return SCIP_OKAY;
218 
219  /* don't dive two times at the same node */
220  if( SCIPgetLastDivenode(scip) == SCIPgetNNodes(scip) && SCIPgetDepth(scip) > 0 )
221  return SCIP_OKAY;
222 
223  *result = SCIP_DIDNOTRUN;
224 
225  /* get heuristic's data */
226  heurdata = SCIPheurGetData(heur);
227  assert(heurdata != NULL);
228 
229  /* only try to dive, if we are in the correct part of the tree, given by minreldepth and maxreldepth */
230  depth = SCIPgetDepth(scip);
231  maxdepth = SCIPgetMaxDepth(scip);
232  maxdepth = MAX(maxdepth, 30);
233  if( depth < heurdata->minreldepth*maxdepth || depth > heurdata->maxreldepth*maxdepth )
234  return SCIP_OKAY;
235 
236  /* calculate the maximal number of LP iterations until heuristic is aborted */
237  nlpiterations = SCIPgetNNodeLPIterations(scip);
238  ncalls = SCIPheurGetNCalls(heur);
239  nsolsfound = 10*SCIPheurGetNBestSolsFound(heur) + heurdata->nsuccess;
240  maxnlpiterations = (SCIP_Longint)((1.0 + 10.0*(nsolsfound+1.0)/(ncalls+1.0)) * heurdata->maxlpiterquot * nlpiterations);
241  maxnlpiterations += heurdata->maxlpiterofs;
242 
243  /* don't try to dive, if we took too many LP iterations during diving */
244  if( heurdata->nlpiterations >= maxnlpiterations )
245  return SCIP_OKAY;
246 
247  /* allow at least a certain number of LP iterations in this dive */
248  maxnlpiterations = MAX(maxnlpiterations, heurdata->nlpiterations + MINLPITER);
249 
250  /* get fractional variables that should be integral */
251  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
252 
253  /* don't try to dive, if there are no fractional variables */
254  if( nlpcands == 0 )
255  return SCIP_OKAY;
256 
257  /* calculate the objective search bound */
258  if( SCIPgetNSolsFound(scip) == 0 )
259  {
260  if( heurdata->maxdiveubquotnosol > 0.0 )
261  searchubbound = SCIPgetLowerbound(scip)
262  + heurdata->maxdiveubquotnosol * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
263  else
264  searchubbound = SCIPinfinity(scip);
265  if( heurdata->maxdiveavgquotnosol > 0.0 )
266  searchavgbound = SCIPgetLowerbound(scip)
267  + heurdata->maxdiveavgquotnosol * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
268  else
269  searchavgbound = SCIPinfinity(scip);
270  }
271  else
272  {
273  if( heurdata->maxdiveubquot > 0.0 )
274  searchubbound = SCIPgetLowerbound(scip)
275  + heurdata->maxdiveubquot * (SCIPgetCutoffbound(scip) - SCIPgetLowerbound(scip));
276  else
277  searchubbound = SCIPinfinity(scip);
278  if( heurdata->maxdiveavgquot > 0.0 )
279  searchavgbound = SCIPgetLowerbound(scip)
280  + heurdata->maxdiveavgquot * (SCIPgetAvgLowerbound(scip) - SCIPgetLowerbound(scip));
281  else
282  searchavgbound = SCIPinfinity(scip);
283  }
284  searchbound = MIN(searchubbound, searchavgbound);
285  if( SCIPisObjIntegral(scip) )
286  searchbound = SCIPceil(scip, searchbound);
287 
288  /* calculate the maximal diving depth: 10 * min{number of integer variables, max depth} */
289  maxdivedepth = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
290  maxdivedepth = MIN(maxdivedepth, maxdepth);
291  maxdivedepth *= 10;
292 
293 
294  *result = SCIP_DIDNOTFIND;
295 
296  /* start diving */
297  SCIP_CALL( SCIPstartProbing(scip) );
298 
299  /* enables collection of variable statistics during probing */
300  SCIPenableVarHistory(scip);
301 
302  /* get LP objective value */
303  lpsolstat = SCIP_LPSOLSTAT_OPTIMAL;
304  objval = SCIPgetLPObjval(scip);
305 
306  SCIPdebugMessage("(node %"SCIP_LONGINT_FORMAT") executing veclendiving heuristic: depth=%d, %d fractionals, dualbound=%g, searchbound=%g\n",
307  SCIPgetNNodes(scip), SCIPgetDepth(scip), nlpcands, SCIPgetDualbound(scip), SCIPretransformObj(scip, searchbound));
308 
309  /* dive as long we are in the given objective, depth and iteration limits and fractional variables exist, but
310  * - if possible, we dive at least with the depth 10
311  * - if the number of fractional variables decreased at least with 1 variable per 2 dive depths, we continue diving
312  */
313  lperror = FALSE;
314  cutoff = FALSE;
315  divedepth = 0;
316  startnlpcands = nlpcands;
317  roundup = FALSE;
318  while( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL && nlpcands > 0
319  && (divedepth < 10
320  || nlpcands <= startnlpcands - divedepth/2
321  || (divedepth < maxdivedepth && heurdata->nlpiterations < maxnlpiterations && objval < searchbound))
322  && !SCIPisStopped(scip) )
323  {
324  SCIP_VAR* var;
325  SCIP_Real bestscore;
326  SCIP_Bool bestcandroundup;
327  SCIP_Bool allroundable;
328  int bestcand;
329  int c;
330 
331  SCIP_CALL( SCIPnewProbingNode(scip) );
332  divedepth++;
333 
334  /* choose variable fixing:
335  * - round variables in direction where objective value gets worse; for zero objective coefficient, round upwards
336  * - round variable with least objective value deficit per row the variable appears in
337  * (we want to "fix" as many rows as possible with the least damage to the objective function)
338  */
339  bestcand = -1;
340  bestcandroundup = FALSE;
341  bestscore = SCIP_REAL_MAX;
342  allroundable = TRUE;
343  for( c = 0; c < nlpcands; ++c )
344  {
345  SCIP_Real obj;
346  SCIP_Real frac;
347  SCIP_Real objdelta;
348  SCIP_Real score;
349  int colveclen;
350 
351  var = lpcands[c];
352  frac = lpcandsfrac[c];
353  obj = SCIPvarGetObj(var);
354  roundup = (obj >= 0.0);
355  objdelta = (roundup ? (1.0-frac)*obj : -frac * obj);
356  assert(objdelta >= 0.0);
357 
358  colveclen = (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN ? SCIPcolGetNNonz(SCIPvarGetCol(var)) : 0);
359 
360  /* check whether the variable is roundable */
361  allroundable = allroundable && (SCIPvarMayRoundDown(var) || SCIPvarMayRoundUp(var));
362 
363  /* smaller score is better */
364  score = (objdelta + SCIPsumepsilon(scip))/((SCIP_Real)colveclen+1.0);
365 
366  /* prefer decisions on binary variables */
367  if( SCIPvarGetType(var) != SCIP_VARTYPE_BINARY )
368  score *= 1000.0;
369 
370  /* check, if candidate is new best candidate */
371  if( score < bestscore )
372  {
373  bestcand = c;
374  bestscore = score;
375  bestcandroundup = roundup;
376  }
377 
378  /*SCIPdebugMessage(" <%s>: sol=%g, obj=%g, objdelta=%g, colveclen=%d -> score=%g (bestscore=%g)\n",
379  SCIPvarGetName(var), lpcandssol[c], obj, objdelta, colveclen, score, bestscore);*/
380  }
381  assert(bestcand != -1);
382 
383  /* if all candidates are roundable, try to round the solution */
384  if( allroundable )
385  {
386  SCIP_Bool success;
387 
388  /* create solution from diving LP and try to round it */
389  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
390  SCIP_CALL( SCIProundSol(scip, heurdata->sol, &success) );
391 
392  if( success )
393  {
394  SCIPdebugMessage("veclendiving found roundable primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
395 
396  /* try to add solution to SCIP */
397  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
398 
399  /* check, if solution was feasible and good enough */
400  if( success )
401  {
402  SCIPdebugMessage(" -> solution was feasible and good enough\n");
403  *result = SCIP_FOUNDSOL;
404  }
405  }
406  }
407 
408  var = lpcands[bestcand];
409 
410  backtracked = FALSE;
411  do
412  {
413  backtrack = FALSE;
414  /* if the variable is already fixed or if the solution value is outside the domain, numerical troubles may have
415  * occured or variable was fixed by propagation while backtracking => Abort diving!
416  */
417  if( SCIPvarGetLbLocal(var) >= SCIPvarGetUbLocal(var) - 0.5 )
418  {
419  SCIPdebugMessage("Selected variable <%s> already fixed to [%g,%g] (solval: %.9f), diving aborted \n",
420  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
421  cutoff = TRUE;
422  break;
423  }
424  if( SCIPisFeasLT(scip, lpcandssol[bestcand], SCIPvarGetLbLocal(var)) || SCIPisFeasGT(scip, lpcandssol[bestcand], SCIPvarGetUbLocal(var)) )
425  {
426  SCIPdebugMessage("selected variable's <%s> solution value is outside the domain [%g,%g] (solval: %.9f), diving aborted\n",
427  SCIPvarGetName(var), SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var), lpcandssol[bestcand]);
428  assert(backtracked);
429  break;
430  }
431 
432  /* apply rounding of best candidate */
433  if( bestcandroundup == !backtracked )
434  {
435  /* round variable up */
436  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
437  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
438  SCIPvarGetName(var), lpcandssol[bestcand], SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
439  SCIPfeasCeil(scip, lpcandssol[bestcand]), SCIPvarGetUbLocal(var));
440 
441  SCIP_CALL( SCIPchgVarLbProbing(scip, var, SCIPfeasCeil(scip, lpcandssol[bestcand])) );
442  roundup = TRUE;
443  }
444  else
445  {
446  /* round variable down */
447  SCIPdebugMessage(" dive %d/%d, LP iter %"SCIP_LONGINT_FORMAT"/%"SCIP_LONGINT_FORMAT": var <%s>, sol=%g, oldbounds=[%g,%g], newbounds=[%g,%g]\n",
448  divedepth, maxdivedepth, heurdata->nlpiterations, maxnlpiterations,
449  SCIPvarGetName(var), lpcandssol[bestcand], SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var),
450  SCIPvarGetLbLocal(var), SCIPfeasFloor(scip, lpcandssol[bestcand]));
451 
452  SCIP_CALL( SCIPchgVarUbProbing(scip, var, SCIPfeasFloor(scip, lpcandssol[bestcand])) );
453  roundup = FALSE;
454  }
455 
456  /* apply domain propagation */
457  SCIP_CALL( SCIPpropagateProbing(scip, 0, &cutoff, NULL) );
458  if( !cutoff )
459  {
460  /* resolve the diving LP */
461  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
462  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
463  */
464 #ifdef NDEBUG
465  SCIP_RETCODE retstat;
466  nlpiterations = SCIPgetNLPIterations(scip);
467  retstat = SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff);
468  if( retstat != SCIP_OKAY )
469  {
470  SCIPwarningMessage(scip, "Error while solving LP in Veclendiving heuristic; LP solve terminated with code <%d>\n",retstat);
471  }
472 #else
473  nlpiterations = SCIPgetNLPIterations(scip);
474  SCIP_CALL( SCIPsolveProbingLP(scip, MAX((int)(maxnlpiterations - heurdata->nlpiterations), MINLPITER), &lperror, &cutoff) );
475 #endif
476 
477  if( lperror )
478  break;
479 
480  /* update iteration count */
481  heurdata->nlpiterations += SCIPgetNLPIterations(scip) - nlpiterations;
482 
483  /* get LP solution status, objective value, and fractional variables, that should be integral */
484  lpsolstat = SCIPgetLPSolstat(scip);
485  assert(cutoff || (lpsolstat != SCIP_LPSOLSTAT_OBJLIMIT && lpsolstat != SCIP_LPSOLSTAT_INFEASIBLE &&
486  (lpsolstat != SCIP_LPSOLSTAT_OPTIMAL || SCIPisLT(scip, SCIPgetLPObjval(scip), SCIPgetCutoffbound(scip)))));
487  }
488 
489  /* perform backtracking if a cutoff was detected */
490  if( cutoff && !backtracked && heurdata->backtrack )
491  {
492  SCIPdebugMessage(" *** cutoff detected at level %d - backtracking\n", SCIPgetProbingDepth(scip));
494  SCIP_CALL( SCIPnewProbingNode(scip) );
495  backtracked = TRUE;
496  backtrack = TRUE;
497  }
498  else
499  backtrack = FALSE;
500  }
501  while( backtrack );
502 
503  if( !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
504  {
505  SCIP_Real oldobjval;
506 
507  /* get new objective value */
508  oldobjval = objval;
509  objval = SCIPgetLPObjval(scip);
510 
511  /* update pseudo cost values */
512  if( SCIPisGT(scip, objval, oldobjval) )
513  {
514  if( roundup )
515  {
516  assert(bestcandroundup || backtracked);
517  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[bestcand], 1.0-lpcandsfrac[bestcand],
518  objval - oldobjval, 1.0) );
519  }
520  else
521  {
522  assert(!bestcandroundup || backtracked);
523  SCIP_CALL( SCIPupdateVarPseudocost(scip, lpcands[bestcand], 0.0-lpcandsfrac[bestcand],
524  objval - oldobjval, 1.0) );
525  }
526  }
527 
528  /* get new fractional variables */
529  SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, &lpcandsfrac, &nlpcands, NULL, NULL) );
530  }
531  SCIPdebugMessage(" -> lpsolstat=%d, objval=%g/%g, nfrac=%d\n", lpsolstat, objval, searchbound, nlpcands);
532  }
533 
534  /* check if a solution has been found */
535  if( nlpcands == 0 && !lperror && !cutoff && lpsolstat == SCIP_LPSOLSTAT_OPTIMAL )
536  {
537  SCIP_Bool success;
538 
539  /* create solution from diving LP */
540  SCIP_CALL( SCIPlinkLPSol(scip, heurdata->sol) );
541  SCIPdebugMessage("veclendiving found primal solution: obj=%g\n", SCIPgetSolOrigObj(scip, heurdata->sol));
542 
543  /* try to add solution to SCIP */
544  SCIP_CALL( SCIPtrySol(scip, heurdata->sol, FALSE, FALSE, FALSE, FALSE, &success) );
545 
546  /* check, if solution was feasible and good enough */
547  if( success )
548  {
549  SCIPdebugMessage(" -> solution was feasible and good enough\n");
550  *result = SCIP_FOUNDSOL;
551  }
552  }
553 
554  /* end diving */
555  SCIP_CALL( SCIPendProbing(scip) );
556 
557  if( *result == SCIP_FOUNDSOL )
558  heurdata->nsuccess++;
559 
560  SCIPdebugMessage("veclendiving heuristic finished\n");
561 
562  return SCIP_OKAY;
563 }
564 
565 
566 /*
567  * heuristic specific interface methods
568  */
569 
570 /** creates the veclendiving heuristic and includes it in SCIP */
572  SCIP* scip /**< SCIP data structure */
573  )
574 {
575  SCIP_HEURDATA* heurdata;
576  SCIP_HEUR* heur;
577 
578  /* create Veclendiving primal heuristic data */
579  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
580 
581  /* include primal heuristic */
582  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
584  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecVeclendiving, heurdata) );
585 
586  assert(heur != NULL);
587 
588  /* set non-NULL pointers to callback methods */
589  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyVeclendiving) );
590  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeVeclendiving) );
591  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitVeclendiving) );
592  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitVeclendiving) );
593 
594  /* veclendiving heuristic parameters */
596  "heuristics/veclendiving/minreldepth",
597  "minimal relative depth to start diving",
598  &heurdata->minreldepth, TRUE, DEFAULT_MINRELDEPTH, 0.0, 1.0, NULL, NULL) );
600  "heuristics/veclendiving/maxreldepth",
601  "maximal relative depth to start diving",
602  &heurdata->maxreldepth, TRUE, DEFAULT_MAXRELDEPTH, 0.0, 1.0, NULL, NULL) );
604  "heuristics/veclendiving/maxlpiterquot",
605  "maximal fraction of diving LP iterations compared to node LP iterations",
606  &heurdata->maxlpiterquot, FALSE, DEFAULT_MAXLPITERQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
608  "heuristics/veclendiving/maxlpiterofs",
609  "additional number of allowed LP iterations",
610  &heurdata->maxlpiterofs, FALSE, DEFAULT_MAXLPITEROFS, 0, INT_MAX, NULL, NULL) );
612  "heuristics/veclendiving/maxdiveubquot",
613  "maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound) where diving is performed (0.0: no limit)",
614  &heurdata->maxdiveubquot, TRUE, DEFAULT_MAXDIVEUBQUOT, 0.0, 1.0, NULL, NULL) );
616  "heuristics/veclendiving/maxdiveavgquot",
617  "maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound) where diving is performed (0.0: no limit)",
618  &heurdata->maxdiveavgquot, TRUE, DEFAULT_MAXDIVEAVGQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
620  "heuristics/veclendiving/maxdiveubquotnosol",
621  "maximal UBQUOT when no solution was found yet (0.0: no limit)",
622  &heurdata->maxdiveubquotnosol, TRUE, DEFAULT_MAXDIVEUBQUOTNOSOL, 0.0, 1.0, NULL, NULL) );
624  "heuristics/veclendiving/maxdiveavgquotnosol",
625  "maximal AVGQUOT when no solution was found yet (0.0: no limit)",
626  &heurdata->maxdiveavgquotnosol, TRUE, DEFAULT_MAXDIVEAVGQUOTNOSOL, 0.0, SCIP_REAL_MAX, NULL, NULL) );
628  "heuristics/veclendiving/backtrack",
629  "use one level of backtracking if infeasibility is encountered?",
630  &heurdata->backtrack, FALSE, DEFAULT_BACKTRACK, NULL, NULL) );
631 
632  return SCIP_OKAY;
633 }
634 
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:29936
#define HEUR_NAME
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_MAXDIVEAVGQUOTNOSOL
#define HEUR_TIMING
static SCIP_DECL_HEUREXEC(heurExecVeclendiving)
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
#define DEFAULT_MAXDIVEUBQUOTNOSOL
#define HEUR_PRIORITY
#define HEUR_FREQ
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 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
#define DEFAULT_MINRELDEPTH
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
static SCIP_DECL_HEURFREE(heurFreeVeclendiving)
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:10116
#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
#define DEFAULT_MAXRELDEPTH
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:24136
#define SCIPdebugMessage
Definition: pub_message.h:77
static SCIP_DECL_HEUREXIT(heurExitVeclendiving)
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
#define DEFAULT_MAXDIVEAVGQUOT
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
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31855
#define DEFAULT_MAXDIVEUBQUOT
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_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:15907
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
#define MINLPITER
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_DISPCHAR
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip.c:9683
static SCIP_DECL_HEURCOPY(heurCopyVeclendiving)
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
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16093
#define HEUR_MAXDEPTH
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:38349
#define HEUR_USESSUBSCIP
#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
#define DEFAULT_BACKTRACK
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 MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:29476
#define HEUR_FREQOFS
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:29607
SCIP_RETCODE SCIPincludeHeurVeclendiving(SCIP *scip)
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:34833
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:31444
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_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:15953
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_HEURINIT(heurInitVeclendiving)
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 DEFAULT_MAXLPITEROFS
LP diving heuristic that rounds variables with long column vectors.
#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 HEUR_DESC
#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_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
int SCIPcolGetNNonz(SCIP_COL *col)
Definition: lp.c:18481
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:37719
#define DEFAULT_MAXLPITERQUOT
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
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:32673