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