Scippy

SCIP

Solving Constraint Integer Programs

heur_vbounds.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-2016 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_vbounds.c
17  * @brief LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood
18  * @author Timo Berthold
19  * @author Stefan Heinz
20  * @author Jens Schulz
21  * @author Gerald Gamrath
22  *
23  * @todo allow smaller fixing rate for probing LP?
24  * @todo allow smaller fixing rate after presolve if total number of variables is small (<= 1000)?
25  */
26 
27 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
28 
29 #include <assert.h>
30 #include <string.h>
31 
32 #include "scip/scip.h"
33 #include "scip/scipdefplugins.h"
34 #include "scip/heur_vbounds.h"
35 
36 #ifdef SCIP_STATISTIC
37 #include "scip/clock.h"
38 #endif
39 
40 #define HEUR_NAME "vbounds"
41 #define HEUR_DESC "LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood"
42 #define HEUR_DISPCHAR 'V'
43 #define HEUR_PRIORITY -1106000
44 #define HEUR_FREQ -1
45 #define HEUR_FREQOFS 0
46 #define HEUR_MAXDEPTH -1
47 #define HEUR_TIMING SCIP_HEURTIMING_BEFORENODE
48 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
49 
50 #define DEFAULT_MAXNODES 5000LL /* maximum number of nodes to regard in the subproblem */
51 #define DEFAULT_MINFIXINGRATE 0.25 /* minimum percentage of integer variables that have to be fixed */
52 #define DEFAULT_MINIMPROVE 0.01 /* factor by which vbounds heuristic should at least improve the incumbent */
53 #define DEFAULT_MINNODES 500LL /* minimum number of nodes to regard in the subproblem */
54 #define DEFAULT_NODESOFS 500LL /* number of nodes added to the contingent of the total nodes */
55 #define DEFAULT_NODESQUOT 0.1 /* subproblem nodes in relation to nodes of the original problem */
56 #define DEFAULT_MAXPROPROUNDS 2 /* maximum number of propagation rounds during probing */
57 #define DEFAULT_COPYCUTS TRUE /**< should all active cuts from the cutpool of the original scip be copied to
58  * constraints of the subscip
59  */
60 
61 
62 /*
63  * Data structures
64  */
65 
66 /** primal heuristic data */
67 struct SCIP_HeurData
68 {
69  SCIP_VAR** vbvars; /**< topological sorted variables with respect to the variable bounds */
70  SCIP_BOUNDTYPE* vbbounds; /**< topological sorted variables with respect to the variable bounds */
71  int nvbvars; /**< number of variables in variable lower bound array */
72  SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
73  SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
74  SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
75  SCIP_Longint usednodes; /**< nodes already used by vbounds heuristic in earlier calls */
76  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
77  SCIP_Real minimprove; /**< factor by which vbounds heuristic should at least improve the incumbent */
78  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
79  int maxproprounds; /**< maximum number of propagation rounds during probing */
80  SCIP_Bool initialized; /**< are the candidate list initialized? */
81  SCIP_Bool applicable; /**< is the heuristic applicable? */
82  SCIP_Bool copycuts; /**< should all active cuts from cutpool be copied to constraints in
83  * subproblem?
84  */
85 };
86 
87 /**@name Propagator defines
88  *
89  * @{
90  *
91  * The propagator works on indices representing a bound of a variable. This index will be called bound index in the
92  * following. For a given active variable with problem index i (note that active variables have problem indices
93  * between 0 and nactivevariable - 1), the bound index of its lower bound is 2*i, the bound index of its upper
94  * bound is 2*i + 1. The other way around, a given bound index i corresponds to the variable with problem index
95  * i/2 (rounded down), and to the lower bound, if i is even, to the upper bound if i is odd.
96  * The following macros can be used to convert bound index into variable problem index and boundtype and vice versa.
97  */
98 #define getLbIndex(idx) (2*(idx))
99 #define getUbIndex(idx) (2*(idx)+1)
100 #define getVarIndex(idx) ((idx)/2)
101 #define getBoundtype(idx) (((idx) % 2 == 0) ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER)
102 #define isIndexLowerbound(idx) ((idx) % 2 == 0)
105 /*
106  * Hash map callback methods
107  */
108 
109 /*
110  * Local methods
111  */
112 
113 /** reset heuristic data structure */
114 static
115 void heurdataReset(
116  SCIP_HEURDATA* heurdata /**< structure containing heurdata */
117  )
118 {
119  heurdata->vbvars = NULL;
120  heurdata->vbbounds = NULL;
121  heurdata->nvbvars = 0;
122  heurdata->initialized = FALSE;
123  heurdata->applicable = FALSE;
124 }
125 
126 
127 /** performs depth-first-search in the implicitly given directed graph from the given start index */
128 static
130  SCIP* scip, /**< SCIP data structure */
131  int startnode, /**< node to start the depth-first-search */
132  SCIP_Bool* visited, /**< array to store for each node, whether it was already visited */
133  int* dfsstack, /**< array of size number of nodes to store the stack;
134  * only needed for performance reasons */
135  int* stacknextedge, /**< array of size number of nodes to store the number of adjacent nodes
136  * already visited for each node on the stack; only needed for
137  * performance reasons */
138  int* dfsnodes, /**< array of nodes that can be reached starting at startnode, in reverse
139  * dfs order */
140  int* ndfsnodes /**< pointer to store number of nodes that can be reached starting at
141  * startnode */
142  )
143 {
144  SCIP_VAR** vars;
145  SCIP_VAR* startvar;
146  SCIP_VAR** vbvars;
147  SCIP_Real* coefs;
148  SCIP_Bool lower;
149  int stacksize;
150  int curridx;
151  int idx;
152  int nvbvars;
153  int i;
154 
155  assert(startnode >= 0);
156  assert(startnode < 2 * SCIPgetNVars(scip));
157  assert(visited != NULL);
158  assert(visited[startnode] == FALSE);
159  assert(dfsstack != NULL);
160  assert(dfsnodes != NULL);
161  assert(ndfsnodes != NULL);
162 
163  vars = SCIPgetVars(scip);
164 
165  /* put start node on the stack */
166  dfsstack[0] = startnode;
167  stacknextedge[0] = 0;
168  stacksize = 1;
169  idx = -1;
170 
171  /* we run until no more bounds indices are on the stack, i.e. all changed bounds were propagated */
172  while( stacksize > 0 )
173  {
174  /* get next node from stack */
175  curridx = dfsstack[stacksize - 1];
176 
177  /* mark current node as visited */
178  assert(visited[curridx] == (stacknextedge[stacksize - 1] > 0));
179  visited[curridx] = TRUE;
180 
181  startvar = vars[getVarIndex(curridx)];
182  lower = isIndexLowerbound(curridx);
183 
184  /* go over edges corresponding to varbounds */
185  if( lower )
186  {
187  vbvars = SCIPvarGetVlbVars(startvar);
188  coefs = SCIPvarGetVlbCoefs(startvar);
189  nvbvars = SCIPvarGetNVlbs(startvar);
190  }
191  else
192  {
193  vbvars = SCIPvarGetVubVars(startvar);
194  coefs = SCIPvarGetVubCoefs(startvar);
195  nvbvars = SCIPvarGetNVubs(startvar);
196  }
197 
198  /* iterate over all vbounds for the given bound */
199  for( i = stacknextedge[stacksize - 1]; i < nvbvars; ++i )
200  {
201  if( !SCIPvarIsActive(vbvars[i]) )
202  continue;
203 
204  idx = (SCIPisPositive(scip, coefs[i]) == lower) ? getLbIndex(SCIPvarGetProbindex(vbvars[i])) : getUbIndex(SCIPvarGetProbindex(vbvars[i]));
205  assert(idx >= 0);
206 
207  /* break when the first unvisited node is reached */
208  if( !visited[idx] )
209  break;
210  }
211 
212  /* we stopped because we found an unhandled node and not because we reached the end of the list */
213  if( i < nvbvars )
214  {
215  assert(!visited[idx]);
216 
217  /* put the adjacent node onto the stack */
218  dfsstack[stacksize] = idx;
219  stacknextedge[stacksize] = 0;
220  stacknextedge[stacksize - 1] = i + 1;
221  stacksize++;
222  assert(stacksize <= 2* SCIPgetNVars(scip));
223 
224  /* restart while loop, get next index from stack */
225  continue;
226  }
227 
228  /* the current node was completely handled, remove it from stack */
229  stacksize--;
230 
231  if( (stacksize > 0 || nvbvars > 0) && SCIPvarGetType(startvar) != SCIP_VARTYPE_CONTINUOUS )
232  {
233  /* store node in the sorted nodes array */
234  dfsnodes[(*ndfsnodes)] = curridx;
235  (*ndfsnodes)++;
236  }
237  else
238  visited[curridx] = FALSE;
239  }
240 
241  return SCIP_OKAY;
242 }
243 
244 
245 /** sort the bounds of variables topologically */
246 static
248  SCIP* scip, /**< SCIP data structure */
249  int* vbvars, /**< array to store variable bounds in topological order */
250  int* nvbvars /**< array to store number of variable bounds in the graph */
251  )
252 {
253  int* dfsstack;
254  int* stacknextedge;
255  SCIP_Bool* inqueue;
256  int nbounds;
257  int i;
258 
259  assert(scip != NULL);
260 
261  nbounds = 2 * SCIPgetNVars(scip);
262 
263  SCIP_CALL( SCIPallocBufferArray(scip, &dfsstack, nbounds) );
264  SCIP_CALL( SCIPallocBufferArray(scip, &stacknextedge, nbounds) );
265  SCIP_CALL( SCIPallocBufferArray(scip, &inqueue, nbounds) );
266  BMSclearMemoryArray(inqueue, nbounds);
267 
268  /* while there are unvisited nodes, run dfs starting from one of these nodes; the dfs orders are stored in the
269  * topoorder array, later dfs calls are just appended after the stacks of previous dfs calls, which gives us a
270  * reverse topological order
271  */
272  for( i = 0; i < nbounds; ++i )
273  {
274  if( !inqueue[i] )
275  {
276  SCIP_CALL( dfs(scip, i, inqueue, dfsstack, stacknextedge, vbvars, nvbvars) );
277  }
278  }
279  assert(*nvbvars <= nbounds);
280 
281  SCIPfreeBufferArray(scip, &inqueue);
282  SCIPfreeBufferArray(scip, &stacknextedge);
283  SCIPfreeBufferArray(scip, &dfsstack);
284 
285  return SCIP_OKAY;
286 }
287 
288 /** initialize candidate lists */
289 static
291  SCIP* scip, /**< original SCIP data structure */
292  SCIP_HEURDATA* heurdata /**< structure containing heurdata */
293  )
294 {
295  SCIP_VAR** vars;
296  int* vbs;
297  int nvars;
298  int nvbs;
299  int v;
300 
301  SCIPdebugMessage("initialize variable bound heuristic (%s)\n", SCIPgetProbName(scip));
302 
303  vars = SCIPgetVars(scip);
304  nvars = SCIPgetNVars(scip);
305  nvbs = 0;
306 
307  /* allocate memory for the arrays of the heurdata */
308  SCIP_CALL( SCIPallocBufferArray(scip, &vbs, 2 * nvars) );
309 
310  /* create the topological sorted variable array with respect to the variable bounds */
311  SCIP_CALL( topologicalSort(scip, vbs, &nvbs) );
312 
313  /* check if the candidate list contains enough candidates */
314  if( nvbs >= heurdata->minfixingrate * nvars )
315  {
316  SCIP_CALL( SCIPallocMemoryArray(scip, &heurdata->vbvars, nvbs) );
317  SCIP_CALL( SCIPallocMemoryArray(scip, &heurdata->vbbounds, nvbs) );
318 
319  /* capture variable candidate list */
320  for( v = 0; v < nvbs; ++v )
321  {
322  heurdata->vbvars[v] = vars[getVarIndex(vbs[v])];
323  heurdata->vbbounds[v] = getBoundtype(vbs[v]);
324 
325  SCIP_CALL( SCIPcaptureVar(scip, heurdata->vbvars[v]) );
326  }
327 
328  heurdata->nvbvars = nvbs;
329  heurdata->applicable = TRUE;
330  }
331 
332  /* free buffer arrays */
333  SCIPfreeBufferArray(scip, &vbs);
334 
335  /* initialize data */
336  heurdata->usednodes = 0;
337  heurdata->initialized = TRUE;
338 
339  SCIPstatisticMessage("vbvars %.3g (%s)\n",
340  (nvbs * 100.0) / nvars, SCIPgetProbName(scip));
341 
342  return SCIP_OKAY;
343 }
344 
345 /** apply variable bound fixing during probing */
346 static
348  SCIP* scip, /**< original SCIP data structure */
349  SCIP_HEURDATA* heurdata, /**< structure containing heurdata */
350  SCIP_VAR** vars, /**< variables to fix during probing */
351  int nvbvars, /**< number of variables in the variable bound graph */
352  SCIP_Bool forward, /**< should fixings be done forward w.r.t. the vbound graph? */
353  SCIP_Bool tighten, /**< should variables be fixed to cause other fixings? */
354  SCIP_Bool obj, /**< should the objective be taken into account? */
355  SCIP_Bool* infeasible, /**< pointer to store whether problem is infeasible */
356  SCIP_VAR** lastvar, /**< last fixed variable */
357  SCIP_Bool* fixedtolb /**< was last fixed variable fixed to its lower bound? */
358  )
359 {
360  SCIP_VAR* var;
361  SCIP_BOUNDTYPE bound;
362  int v;
363 
364  /* for each variable in topological order: start at best bound (MINIMIZE: neg coeff --> ub, pos coeff: lb) */
365  for( v = 0; v < nvbvars && !(*infeasible); ++v )
366  {
367  var = forward ? vars[v] : vars[nvbvars - 1 - v];
368  bound = forward ? heurdata->vbbounds[v] : heurdata->vbbounds[nvbvars - 1 - v];
369 
370  /*SCIPdebugMessage("topoorder[%d]: %s(%s) (%s)\n", v,
371  bound == SCIP_BOUNDTYPE_UPPER ? "ub" : "lb", SCIPvarGetName(var),
372  SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS ? "c" : "d");*/
373 
374  /* only check integer or binary variables */
376  continue;
377 
378  /* skip variables which are already fixed */
379  if( SCIPvarGetLbLocal(var) + 0.5 > SCIPvarGetUbLocal(var) )
380  continue;
381 
382  if( obj && ((SCIPvarGetObj(var) >= 0) == (bound == SCIP_BOUNDTYPE_LOWER)) )
383  continue;
384 
385  /* only open a new probing node if we will not exceed the maximal tree depth */
386  if( SCIPgetDepthLimit(scip) > SCIPgetDepth(scip) )
387  {
388  SCIP_CALL( SCIPnewProbingNode(scip) );
389  }
390 
391  *lastvar = var;
392 
393  if( obj ? (tighten == (SCIPvarGetObj(var) >= 0)) : (tighten == (bound == SCIP_BOUNDTYPE_UPPER)) )
394  {
395  /* fix variable to lower bound */
396  SCIP_CALL( SCIPfixVarProbing(scip, var, SCIPvarGetLbLocal(var)) );
397  SCIPdebugMessage("fixing %d: variable <%s> to lower bound <%g> (%d pseudo cands)\n",
399  *fixedtolb = TRUE;
400  }
401  else
402  {
403  assert((obj && (tighten == (SCIPvarGetObj(var) < 0)))
404  || (!obj && (tighten == (bound == SCIP_BOUNDTYPE_LOWER))));
405  /* fix variable to upper bound */
406  SCIP_CALL( SCIPfixVarProbing(scip, var, SCIPvarGetUbLocal(var)) );
407  SCIPdebugMessage("fixing %d: variable <%s> to upper bound <%g> (%d pseudo cands)\n",
409  *fixedtolb = FALSE;
410  }
411 
412  /* check if problem is already infeasible */
413  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, infeasible, NULL) );
414  }
415 
416  SCIPdebugMessage("probing ended with %sfeasible problem\n", (*infeasible) ? "in" : "");
417 
418  return SCIP_OKAY;
419 }
420 
421 /** creates a new solution for the original problem by copying the solution of the subproblem */
422 static
424  SCIP* scip, /**< original SCIP data structure */
425  SCIP* subscip, /**< SCIP structure of the subproblem */
426  SCIP_VAR** subvars, /**< the variables of the subproblem */
427  SCIP_SOL* newsol, /**< working solution */
428  SCIP_SOL* subsol, /**< solution of the subproblem */
429  SCIP_Bool* success /**< used to store whether new solution was found or not */
430  )
431 {
432  SCIP_VAR** vars; /* the original problem's variables */
433  int nvars;
434  SCIP_Real* subsolvals; /* solution values of the subproblem */
435 
436  assert( scip != NULL );
437  assert( subscip != NULL );
438  assert( subvars != NULL );
439  assert( subsol != NULL );
440 
441  /* get variables' data */
442  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
443 
444  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
445  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
446  */
447  assert( nvars <= SCIPgetNOrigVars(subscip) );
448 
449  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
450 
451  /* copy the solution */
452  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
453 
454  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
455 
456  /* try to add new solution to scip and free it immediately */
457  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, TRUE, TRUE, TRUE, success) );
458 
459  SCIPfreeBufferArray(scip, &subsolvals);
460 
461  return SCIP_OKAY;
462 }
463 
464 /** main procedure of the vbounds heuristic */
465 static
467  SCIP* scip, /**< original SCIP data structure */
468  SCIP_HEUR* heur, /**< heuristic */
469  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
470  SCIP_VAR** vbvars, /**< variables to fix during probing */
471  int nvbvars, /**< number of variables to fix */
472  SCIP_Bool forward, /**< should fixings be done forward w.r.t. the vbound graph? */
473  SCIP_Bool tighten, /**< should variables be fixed to cause other fixings? */
474  SCIP_Bool obj, /**< should the objective be taken into account? */
475  SCIP_RESULT* result /**< pointer to store the result */
476  )
477 {
478  SCIPstatistic( SCIP_CLOCK* clock; )
479  SCIP_VAR** vars;
480  SCIP_VAR* lastfixedvar = NULL;
481  SCIP_SOL* newsol;
482  SCIP_Real timelimit; /* timelimit for the subproblem */
483  SCIP_Real memorylimit;
484  SCIP_Longint nstallnodes; /* number of stalling nodes for the subproblem */
485  SCIP_LPSOLSTAT lpstatus;
486  SCIP_Bool infeasible;
487  SCIP_Bool lastfixedlower = TRUE;
488  SCIP_Bool lperror;
489  SCIP_Bool solvelp;
490  SCIP_Bool foundsol = FALSE;
491  int oldnpscands;
492  int npscands;
493  int nvars;
494  SCIPstatistic( int nprevars = nvars; )
495 
496  assert(heur != NULL);
497  assert(heurdata != NULL);
498  assert(nvbvars > 0);
499 
500  /* initialize default values */
501  infeasible = FALSE;
502 
503  /* get variable data of original problem */
504  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
505 
506  if( nvbvars < nvars * heurdata->minfixingrate )
507  return SCIP_OKAY;
508 
509  if( *result == SCIP_DIDNOTRUN )
510  *result = SCIP_DIDNOTFIND;
511 
512  oldnpscands = SCIPgetNPseudoBranchCands(scip);
513 
514  /* calculate the maximal number of branching nodes until heuristic is aborted */
515  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
516 
517  /* reward variable bounds heuristic if it succeeded often */
518  nstallnodes = (SCIP_Longint)(nstallnodes * 3.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur) + 1.0));
519  nstallnodes -= 100 * SCIPheurGetNCalls(heur); /* count the setup costs for the sub-MIP as 100 nodes */
520  nstallnodes += heurdata->nodesofs;
521 
522  /* determine the node limit for the current process */
523  nstallnodes -= heurdata->usednodes;
524  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
525 
526  /* check whether we have enough nodes left to call subproblem solving */
527  if( nstallnodes < heurdata->minnodes )
528  {
529  SCIPdebugMessage("skipping " HEUR_NAME ": nstallnodes=%" SCIP_LONGINT_FORMAT ", minnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->minnodes);
530  return SCIP_OKAY;
531  }
532 
533  if( SCIPisStopped(scip) )
534  return SCIP_OKAY;
535 
536  SCIPstatistic( SCIP_CALL( SCIPcreateClock(scip, &clock) ) );
537  SCIPstatistic( SCIP_CALL( SCIPstartClock(scip, clock) ) );
538 
539  SCIPdebugMessage("apply variable bounds heuristic at node %lld on %d variable bounds\n",
540  SCIPnodeGetNumber(SCIPgetCurrentNode(scip)), nvbvars);
541 
542  /* check whether the LP should be solved at the current node in the tree to determine whether the heuristic
543  * is allowed to solve an LP
544  */
545  solvelp = SCIPhasCurrentNodeLP(scip);
546 
547  if( !SCIPisLPConstructed(scip) && solvelp )
548  {
549  SCIP_Bool nodecutoff;
550 
551  SCIP_CALL( SCIPconstructLP(scip, &nodecutoff) );
552  SCIP_CALL( SCIPflushLP(scip) );
553  if( nodecutoff )
554  return SCIP_OKAY;
555  }
556 
557 
558  /* start probing */
559  SCIP_CALL( SCIPstartProbing(scip) );
560 
561  /* create temporary solution */
562  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
563 
564  /* apply the variable fixings */
565  SCIP_CALL( applyVboundsFixings(scip, heurdata, vbvars, nvbvars, forward, tighten, obj, &infeasible,
566  &lastfixedvar, &lastfixedlower) );
567 
568  /* try to repair probing */
569  if( infeasible )
570  {
571  assert(lastfixedvar != NULL);
572 
574 
575  /* fix the last variable, which was fixed the reverse bound */
576  SCIP_CALL( SCIPfixVarProbing(scip, lastfixedvar,
577  lastfixedlower ? SCIPvarGetUbLocal(lastfixedvar) : SCIPvarGetLbLocal(lastfixedvar)) );
578 
579  /* propagate fixings */
580  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, &infeasible, NULL) );
581 
582  SCIPdebugMessage("backtracking ended with %sfeasible problem\n", (infeasible ? "in" : ""));
583  }
584 
585  /* check that we had enough fixings */
586  npscands = SCIPgetNPseudoBranchCands(scip);
587 
588  SCIPdebugMessage("npscands=%d, oldnpscands=%d, heurdata->minfixingrate=%g\n", npscands, oldnpscands, heurdata->minfixingrate);
589 
590  /* check fixing rate */
591  if( npscands > oldnpscands * (1 - heurdata->minfixingrate) )
592  {
593  SCIPdebugMessage("--> too few fixings\n");
594 
595  goto TERMINATE;
596  }
597 
598  /*************************** Probing LP Solving ***************************/
599 
600  lpstatus = SCIP_LPSOLSTAT_ERROR;
601  lperror = FALSE;
602  /* solve lp only if the problem is still feasible */
603  if( !infeasible && solvelp )
604  {
605  SCIPdebugMessage("starting solving vbound-lp at time %g\n", SCIPgetSolvingTime(scip));
606 
607  /* solve LP; errors in the LP solver should not kill the overall solving process, if the LP is just needed for a
608  * heuristic. hence in optimized mode, the return code is caught and a warning is printed, only in debug mode,
609  * SCIP will stop.
610  */
611 #ifdef NDEBUG
612  {
613  SCIP_Bool retstat;
614  retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
615  if( retstat != SCIP_OKAY )
616  {
617  SCIPwarningMessage(scip, "Error while solving LP in vbound heuristic; LP solve terminated with code <%d>\n",
618  retstat);
619  }
620  }
621 #else
622  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
623 #endif
624  SCIPdebugMessage("ending solving vbound-lp at time %g\n", SCIPgetSolvingTime(scip));
625 
626  lpstatus = SCIPgetLPSolstat(scip);
627 
628  SCIPdebugMessage(" -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
629  SCIPdebugMessage(" -> error=%u, status=%d\n", lperror, lpstatus);
630  }
631 
632  /* check if this is a feasible solution */
633  if( lpstatus == SCIP_LPSOLSTAT_OPTIMAL && !lperror )
634  {
635  SCIP_Bool stored;
636  SCIP_Bool success;
637 
638  /* copy the current LP solution to the working solution */
639  SCIP_CALL( SCIPlinkLPSol(scip, newsol) );
640 
641  SCIP_CALL( SCIProundSol(scip, newsol, &success) );
642 
643  if( success )
644  {
645  SCIPdebugMessage("vbound heuristic found roundable primal solution: obj=%g\n",
646  SCIPgetSolOrigObj(scip, newsol));
647 
648  /* check solution for feasibility, and add it to solution store if possible.
649  * Neither integrality nor feasibility of LP rows have to be checked, because they
650  * are guaranteed by the heuristic at this stage.
651  */
652 #ifdef SCIP_DEBUG
653  SCIP_CALL( SCIPtrySol(scip, newsol, TRUE, TRUE, TRUE, TRUE, &stored) );
654 #else
655  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, TRUE, FALSE, FALSE, &stored) );
656 #endif
657 
658  foundsol = TRUE;
659 
660  if( stored )
661  {
662  SCIPdebugMessage("found feasible solution:\n");
663  *result = SCIP_FOUNDSOL;
664  }
665  }
666  }
667  else
668  {
669  SCIP_CALL( SCIPclearSol(scip, newsol) );
670  }
671 
672  /*************************** END Probing LP Solving ***************************/
673 
674  /* if no solution has been found --> fix all other variables by subscip if necessary */
675  if( !foundsol && lpstatus != SCIP_LPSOLSTAT_INFEASIBLE && lpstatus != SCIP_LPSOLSTAT_OBJLIMIT && !infeasible )
676  {
677  SCIP* subscip;
678  SCIP_VAR** subvars;
679  SCIP_HASHMAP* varmap;
680  SCIP_Bool valid;
681  int i;
682 
683  valid = FALSE;
684 
685  /* create subproblem */
686  SCIP_CALL( SCIPcreate(&subscip) );
687 
688  /* create the variable mapping hash map */
689  SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
690 
691  SCIP_CALL( SCIPcopy(scip, subscip, varmap, NULL, "_vbounds", FALSE, FALSE, TRUE, &valid) );
692 
693  if( heurdata->copycuts )
694  {
695  /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
696  SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, FALSE, NULL) );
697  }
698 
699  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
700 
701  for( i = 0; i < nvars; i++ )
702  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
703 
704  /* free hash map */
705  SCIPhashmapFree(&varmap);
706 
707  /* do not abort subproblem on CTRL-C */
708  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
709 
710  /* disable output to console */
711  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
712 
713  /* check whether there is enough time and memory left */
714  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
715  if( !SCIPisInfinity(scip, timelimit) )
716  timelimit -= SCIPgetSolvingTime(scip);
717  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
718 
719  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
720  if( !SCIPisInfinity(scip, memorylimit) )
721  {
722  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
723  memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
724  }
725 
726  /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
727  if( timelimit <= 0.0 || memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
728  {
729  /* free subproblem */
730  SCIPfreeBufferArray(scip, &subvars);
731  SCIP_CALL( SCIPfree(&subscip) );
732 
733  goto TERMINATE;
734  }
735 
736 #ifndef SCIP_DEBUG
737  /* disable statistic timing inside sub SCIP */
738  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
739 #endif
740 
741  /* set limits for the subproblem */
742  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
743  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
744  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
745  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
746 
747  /* forbid call of heuristics and separators solving sub-CIPs */
748  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
749 
750  /* disable cutting plane separation */
752 
753  /* disable expensive presolving */
755 #if 0
756  /* use best estimate node selection */
757  if( SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
758  {
759  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/4) );
760  }
761 #endif
762  /* use inference branching */
763  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
764  {
765  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
766  }
767 
768  /* disable conflict analysis */
769  if( !SCIPisParamFixed(subscip, "conflict/enable") )
770  {
771  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", FALSE) );
772  }
773 
774  /* employ a limit on the number of enforcement rounds in the quadratic constraint handlers; this fixes the issue that
775  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
776  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
777  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no decutions shall be
778  * made for the original SCIP
779  */
780  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
781  {
782  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 10) );
783  }
784 
785 #ifdef SCIP_DEBUG
786  /* for debugging vbounds heuristic, enable MIP output */
787  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
788  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
789 #endif
790 
791  /* if there is already a solution, add an objective cutoff */
792  if( SCIPgetNSols(scip) > 0 )
793  {
794  SCIP_Real upperbound;
795  SCIP_Real minimprove;
796  SCIP_Real cutoff;
797 
798  minimprove = heurdata->minimprove;
799  cutoff = SCIPinfinity(scip);
800  assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );
801 
802  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
803 
804  if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
805  {
806  cutoff = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
807  }
808  else
809  {
810  if( SCIPgetUpperbound ( scip ) >= 0 )
811  cutoff = ( 1 - minimprove ) * SCIPgetUpperbound ( scip );
812  else
813  cutoff = ( 1 + minimprove ) * SCIPgetUpperbound ( scip );
814  }
815  cutoff = MIN(upperbound, cutoff);
816  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
817  }
818 
819  /* solve the subproblem */
820  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
821  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
822  */
823 #ifdef NDEBUG
824  {
825  SCIP_RETCODE retstat;
826  retstat = SCIPpresolve(subscip);
827  if( retstat != SCIP_OKAY )
828  {
829  SCIPwarningMessage(scip, "Error while presolving subMIP in vbounds heuristic; sub-SCIP terminated with code <%d>\n", retstat);
830  }
831  }
832 #else
833  SCIP_CALL( SCIPpresolve(subscip) );
834 #endif
835 
836  SCIPdebugMessage("vbounds heuristic presolved subproblem: %d vars, %d cons\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip));
837 
838  /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
839  * to ensure that not only the MIP but also the LP relaxation is easy enough
840  */
841  if( ( nvars - SCIPgetNVars(subscip) ) / (SCIP_Real)nvars >= heurdata->minfixingrate )
842  {
843  SCIP_SOL** subsols;
844  SCIP_Bool success;
845  int nsubsols;
846 
847  SCIPstatistic( nprevars = SCIPgetNVars(subscip) );
848 
849  SCIPdebugMessage("solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
850 
851 #ifdef NDEBUG
852  {
853  SCIP_RETCODE retstat;
854  retstat = SCIPsolve(subscip);
855  if( retstat != SCIP_OKAY )
856  {
857  SCIPwarningMessage(scip, "Error while solving subMIP in vbounds heuristic; sub-SCIP terminated with code <%d>\n",retstat);
858  }
859  }
860 #else
861  SCIP_CALL( SCIPsolve(subscip) );
862 #endif
863 
864  /* check, whether a solution was found; due to numerics, it might happen that not all solutions are feasible ->
865  * try all solutions until one was accepted
866  */
867  nsubsols = SCIPgetNSols(subscip);
868  subsols = SCIPgetSols(subscip);
869  success = FALSE;
870 
871  for( i = 0; i < nsubsols && !success; ++i )
872  {
873  SCIP_CALL( createNewSol(scip, subscip, subvars, newsol, subsols[i], &success) );
874  }
875  if( success )
876  *result = SCIP_FOUNDSOL;
877  }
878 
879 #ifdef SCIP_DEBUG
880  SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
881 #endif
882 
883  /* free subproblem */
884  SCIPfreeBufferArray(scip, &subvars);
885  SCIP_CALL( SCIPfree(&subscip) );
886  }
887 
888  TERMINATE:
889 
890 #ifdef SCIP_STATISTIC
891  SCIP_CALL( SCIPstopClock(scip, clock) );
892  SCIPstatisticMessage("vbound: forward=%d tighten=%d obj=%d nvars=%d presolnvars=%d ratio=%.2f infeas=%d found=%d time=%.2f\n",
893  forward, tighten, obj, nvars, nprevars, (nvars - nprevars) / (SCIP_Real)nvars, infeasible,
894  foundsol ? 1 : 0, SCIPclockGetTime(clock) );
895 #endif
896 
897  SCIPstatistic( SCIP_CALL( SCIPfreeClock(scip, &clock) ) );
898 
899  /* free solution */
900  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
901 
902  /* exit probing mode */
903  SCIP_CALL( SCIPendProbing(scip) );
904 
905  return SCIP_OKAY;
906 }
907 
908 
909 /*
910  * Callback methods of primal heuristic
911  */
912 
913 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
914 static
915 SCIP_DECL_HEURCOPY(heurCopyVbounds)
916 { /*lint --e{715}*/
917  assert(scip != NULL);
918  assert(heur != NULL);
919  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
920 
921  /* call inclusion method of heuristic */
923 
924  return SCIP_OKAY;
925 }
926 
927 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
928 static
929 SCIP_DECL_HEURFREE(heurFreeVbounds)
930 { /*lint --e{715}*/
931  SCIP_HEURDATA* heurdata;
932 
933  /* free heuristic data */
934  heurdata = SCIPheurGetData(heur);
935 
936  SCIPfreeMemory(scip, &heurdata);
937  SCIPheurSetData(heur, NULL);
938 
939  return SCIP_OKAY;
940 }
941 
942 
943 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
944 static
945 SCIP_DECL_HEUREXITSOL(heurExitsolVbounds)
946 { /*lint --e{715}*/
947  SCIP_HEURDATA* heurdata;
948  int v;
949 
950  heurdata = SCIPheurGetData(heur);
951  assert(heurdata != NULL);
952 
953  /* release all variables */
954  for( v = 0; v < heurdata->nvbvars; ++v )
955  {
956  SCIP_CALL( SCIPreleaseVar(scip, &heurdata->vbvars[v]) );
957  }
958 
959  /* free varbounds array */
960  SCIPfreeMemoryArrayNull(scip, &heurdata->vbbounds);
961  SCIPfreeMemoryArrayNull(scip, &heurdata->vbvars);
962 
963  /* reset heuristic data structure */
964  heurdataReset(heurdata);
965 
966  return SCIP_OKAY;
967 }
968 
969 /** execution method of primal heuristic */
970 static
971 SCIP_DECL_HEUREXEC(heurExecVbounds)
972 { /*lint --e{715}*/
973  SCIP_HEURDATA* heurdata;
974 
975  assert( heur != NULL );
976  assert( scip != NULL );
977  assert( result != NULL );
978 
979  *result = SCIP_DIDNOTRUN;
980 
981  if( SCIPgetNPseudoBranchCands(scip) == 0 )
982  return SCIP_OKAY;
983 
984  heurdata = SCIPheurGetData(heur);
985  assert(heurdata != NULL);
986 
987  if( !heurdata->initialized )
988  {
989  SCIP_CALL( initializeCandsLists(scip, heurdata) );
990  }
991 
992  if( !heurdata->applicable )
993  return SCIP_OKAY;
994 
995  /* try variable bounds */
996  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, TRUE, TRUE, result) );
997  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, TRUE, FALSE, result) );
998  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, FALSE, FALSE, result) );
999  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, FALSE, TRUE, result) );
1000 #if 0
1001  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, TRUE, TRUE, result) );
1002  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, TRUE, FALSE, result) );
1003  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, FALSE, TRUE, result) );
1004  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, FALSE, FALSE, result) );
1005 #endif
1006  return SCIP_OKAY;
1007 }
1008 
1009 /*
1010  * primal heuristic specific interface methods
1011  */
1012 
1013 /** creates the vbounds primal heuristic and includes it in SCIP */
1015  SCIP* scip /**< SCIP data structure */
1016  )
1017 {
1018  SCIP_HEURDATA* heurdata;
1019  SCIP_HEUR* heur;
1020 
1021  /* create vbounds primal heuristic data */
1022  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
1023  heurdataReset(heurdata);
1024 
1025  /* include primal heuristic */
1026  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1028  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecVbounds, heurdata) );
1029 
1030  assert(heur != NULL);
1031 
1032  /* set non-NULL pointers to callback methods */
1033  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyVbounds) );
1034  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeVbounds) );
1035  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolVbounds) );
1036 
1037  /* add variable bounds primal heuristic parameters */
1038  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1039  "minimum percentage of integer variables that have to be fixable",
1040  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1041 
1042  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1043  "maximum number of nodes to regard in the subproblem",
1044  &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1045 
1046  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1047  "number of nodes added to the contingent of the total nodes",
1048  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1049 
1050  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1051  "minimum number of nodes required to start the subproblem",
1052  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1053 
1054  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1055  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1056  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1057 
1058  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1059  "factor by which " HEUR_NAME " heuristic should at least improve the incumbent",
1060  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1061 
1062  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
1063  "maximum number of propagation rounds during probing (-1 infinity)",
1064  &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
1065 
1066  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1067  "should all active cuts from cutpool be copied to constraints in subproblem?",
1068  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1069 
1070  return SCIP_OKAY;
1071 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
#define HEUR_TIMING
Definition: heur_vbounds.c:47
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
#define DEFAULT_NODESQUOT
Definition: heur_vbounds.c:55
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:32788
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40767
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:40329
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:10698
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
#define HEUR_USESSUBSCIP
Definition: heur_vbounds.c:48
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
#define DEFAULT_NODESOFS
Definition: heur_vbounds.c:54
#define getVarIndex(idx)
Definition: heur_vbounds.c:102
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40818
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1273
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7297
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:32250
static SCIP_RETCODE applyVboundsFixings(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, int nvbvars, SCIP_Bool forward, SCIP_Bool tighten, SCIP_Bool obj, SCIP_Bool *infeasible, SCIP_VAR **lastvar, SCIP_Bool *fixedtolb)
Definition: heur_vbounds.c:349
static void heurdataReset(SCIP_HEURDATA *heurdata)
Definition: heur_vbounds.c:117
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:37454
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:10653
internal methods for clocks and timing issues
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:40801
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17261
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17291
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:7252
#define isIndexLowerbound(idx)
Definition: heur_vbounds.c:104
static SCIP_RETCODE initializeCandsLists(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_vbounds.c:292
#define SCIPallocMemoryArray(scip, ptr, num)
Definition: scip.h:20528
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:32552
#define FALSE
Definition: def.h:56
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:41009
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4046
int SCIPgetNPseudoBranchCands(SCIP *scip)
Definition: scip.c:33489
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIPstatisticMessage
Definition: pub_message.h:104
#define SCIP_CALL(x)
Definition: def.h:266
#define DEFAULT_MINIMPROVE
Definition: heur_vbounds.c:52
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4109
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_SOL *newsol, SCIP_SOL *subsol, SCIP_Bool *success)
Definition: heur_vbounds.c:425
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:26439
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define SCIPdebugMessage
Definition: pub_message.h:77
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:85
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
#define DEFAULT_MAXNODES
Definition: heur_vbounds.c:50
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
#define SCIP_LONGINT_MAX
Definition: def.h:113
enum SCIP_LPSolStat SCIP_LPSOLSTAT
Definition: type_lp.h:42
#define HEUR_NAME
Definition: heur_vbounds.c:40
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:38393
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35066
SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:2883
#define getUbIndex(idx)
Definition: heur_vbounds.c:101
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7016
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:35668
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:3547
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:3573
#define HEUR_PRIORITY
Definition: heur_vbounds.c:43
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:11138
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition: scip.c:26372
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
int SCIPgetNConss(SCIP *scip)
Definition: scip.c:11736
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip.c:26395
SCIP_RETCODE SCIPcopy(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:3254
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17303
static SCIP_RETCODE topologicalSort(SCIP *scip, int *vbvars, int *nvbvars)
Definition: heur_vbounds.c:249
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:32223
#define HEUR_DESC
Definition: heur_vbounds.c:41
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
#define DEFAULT_MINFIXINGRATE
Definition: heur_vbounds.c:51
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
static SCIP_DECL_HEURCOPY(heurCopyVbounds)
Definition: heur_vbounds.c:917
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4457
#define HEUR_FREQ
Definition: heur_vbounds.c:44
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:35020
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip.c:14342
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:26354
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:766
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:35717
#define DEFAULT_MINNODES
Definition: heur_vbounds.c:53
int SCIPgetDepthLimit(SCIP *scip)
Definition: scip.c:38190
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:16884
static SCIP_DECL_HEUREXEC(heurExecVbounds)
Definition: heur_vbounds.c:973
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:38534
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:16850
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
#define DEFAULT_COPYCUTS
Definition: heur_vbounds.c:57
#define SCIP_Bool
Definition: def.h:53
static SCIP_RETCODE applyVbounds(SCIP *scip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_VAR **vbvars, int nvbvars, SCIP_Bool forward, SCIP_Bool tighten, SCIP_Bool obj, SCIP_RESULT *result)
Definition: heur_vbounds.c:468
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4001
static SCIP_DECL_HEUREXITSOL(heurExitsolVbounds)
Definition: heur_vbounds.c:947
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17313
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:3709
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:4382
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:41396
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
Definition: scip.c:32415
LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood.
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:32153
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17249
SCIP_RETCODE SCIPsetHeurExitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXITSOL((*heurexitsol)))
Definition: scip.c:7377
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:32285
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4431
#define SCIPstatistic(x)
Definition: pub_message.h:101
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:36779
#define getLbIndex(idx)
Definition: heur_vbounds.c:100
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34648
static SCIP_RETCODE dfs(SCIP *scip, int startnode, SCIP_Bool *visited, int *dfsstack, int *stacknextedge, int *dfsnodes, int *ndfsnodes)
Definition: heur_vbounds.c:131
SCIP_RETCODE SCIPincludeHeurVbounds(SCIP *scip)
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:14503
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
#define getBoundtype(idx)
Definition: heur_vbounds.c:103
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17271
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1293
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
#define HEUR_FREQOFS
Definition: heur_vbounds.c:45
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:692
#define SCIPfreeMemoryArrayNull(scip, ptr)
Definition: scip.h:20545
#define HEUR_MAXDEPTH
Definition: heur_vbounds.c:46
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:7313
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8436
#define SCIP_Real
Definition: def.h:127
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:32190
SCIP_RETCODE SCIPflushLP(SCIP *scip)
Definition: scip.c:26419
#define MIN(x, y)
Definition: memory.c:67
SCIP_RETCODE SCIPclearSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:34784
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:10194
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:9941
#define SCIP_Longint
Definition: def.h:112
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:40716
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:34885
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:3938
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3797
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8124
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:41697
static SCIP_DECL_HEURFREE(heurFreeVbounds)
Definition: heur_vbounds.c:931
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:3629
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:41132
default SCIP plugins
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:36217
#define HEUR_DISPCHAR
Definition: heur_vbounds.c:42
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:37372
#define DEFAULT_MAXPROPROUNDS
Definition: heur_vbounds.c:56
SCIP callable library.
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:34607
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:41409
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:35909