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  SCIP_Real newbound;
614 
615  assert(lastfixedvar != NULL);
616  assert(SCIPvarGetType(lastfixedvar) != SCIP_VARTYPE_CONTINUOUS);
617 
619 
620  if( lastfixedlower )
621  {
622  newbound = SCIPvarGetUbLocal(lastfixedvar);
623 
624  if( SCIPisInfinity(scip, newbound) )
625  {
626  newbound = SCIPvarGetLbLocal(lastfixedvar) + 1.0;
627 
628  /* increase lower bound */
629  SCIP_CALL( SCIPchgVarLbProbing(scip, lastfixedvar, newbound) );
630  }
631  else
632  {
633  /* fix the last variable, which was fixed to the opposite bound */
634  SCIP_CALL( SCIPfixVarProbing(scip, lastfixedvar, newbound) );
635  }
636  }
637  else
638  {
639  newbound = SCIPvarGetLbLocal(lastfixedvar);
640 
641  if( SCIPisInfinity(scip, -newbound) )
642  {
643  newbound = SCIPvarGetUbLocal(lastfixedvar) - 1.0;
644 
645  /* decrease lower bound */
646  SCIP_CALL( SCIPchgVarUbProbing(scip, lastfixedvar, newbound) );
647  }
648  else
649  {
650  /* fix the last variable, which was fixed to the opposite bound */
651  SCIP_CALL( SCIPfixVarProbing(scip, lastfixedvar, newbound) );
652  }
653  }
654 
655  /* propagate fixings */
656  SCIP_CALL( SCIPpropagateProbing(scip, heurdata->maxproprounds, &infeasible, NULL) );
657 
658  SCIPdebugMsg(scip, "backtracking ended with %sfeasible problem\n", (infeasible ? "in" : ""));
659  }
660 
661  if( infeasible )
662  goto TERMINATE;
663 
664  /* check that we had enough fixings */
665  npscands = SCIPgetNPseudoBranchCands(scip);
666 
667  SCIPdebugMsg(scip, "npscands=%d, oldnpscands=%d, heurdata->minfixingrate=%g\n", npscands, oldnpscands, heurdata->minfixingrate);
668 
669  /* check fixing rate */
670  if( npscands > oldnpscands * (1 - heurdata->minfixingrate) )
671  {
672  SCIPdebugMsg(scip, "--> too few fixings\n");
673 
674  goto TERMINATE;
675  }
676 
677  /*************************** Probing LP Solving ***************************/
678 
679  lpstatus = SCIP_LPSOLSTAT_ERROR;
680  lperror = FALSE;
681  /* solve lp only if the problem is still feasible */
682  if( solvelp )
683  {
684  SCIPdebugMsg(scip, "starting solving vbound-lp at time %g\n", SCIPgetSolvingTime(scip));
685 
686  /* solve LP; errors in the LP solver should not kill the overall solving process, if the LP is just needed for a
687  * heuristic. hence in optimized mode, the return code is caught and a warning is printed, only in debug mode,
688  * SCIP will stop.
689  */
690 #ifdef NDEBUG
691  {
692  SCIP_Bool retstat;
693  retstat = SCIPsolveProbingLP(scip, -1, &lperror, NULL);
694  if( retstat != SCIP_OKAY )
695  {
696  SCIPwarningMessage(scip, "Error while solving LP in vbound heuristic; LP solve terminated with code <%d>\n",
697  retstat);
698  }
699  }
700 #else
701  SCIP_CALL( SCIPsolveProbingLP(scip, -1, &lperror, NULL) );
702 #endif
703  SCIPdebugMsg(scip, "ending solving vbound-lp at time %g\n", SCIPgetSolvingTime(scip));
704 
705  lpstatus = SCIPgetLPSolstat(scip);
706 
707  SCIPdebugMsg(scip, " -> new LP iterations: %" SCIP_LONGINT_FORMAT "\n", SCIPgetNLPIterations(scip));
708  SCIPdebugMsg(scip, " -> error=%u, status=%d\n", lperror, lpstatus);
709  }
710 
711  /* check if this is a feasible solution */
712  if( lpstatus == SCIP_LPSOLSTAT_OPTIMAL && !lperror )
713  {
714  SCIP_Bool stored;
715  SCIP_Bool success;
716 
717  /* copy the current LP solution to the working solution */
718  SCIP_CALL( SCIPlinkLPSol(scip, newsol) );
719 
720  SCIP_CALL( SCIProundSol(scip, newsol, &success) );
721 
722  if( success )
723  {
724  SCIPdebugMsg(scip, "vbound heuristic found roundable primal solution: obj=%g\n",
725  SCIPgetSolOrigObj(scip, newsol));
726 
727  /* check solution for feasibility, and add it to solution store if possible.
728  * Neither integrality nor feasibility of LP rows have to be checked, because they
729  * are guaranteed by the heuristic at this stage.
730  */
731 #ifdef SCIP_DEBUG
732  SCIP_CALL( SCIPtrySol(scip, newsol, TRUE, TRUE, TRUE, TRUE, TRUE, &stored) );
733 #else
734  SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, TRUE, FALSE, FALSE, &stored) );
735 #endif
736 
737  foundsol = TRUE;
738 
739  if( stored )
740  {
741  SCIPdebugMsg(scip, "found feasible solution:\n");
742  *result = SCIP_FOUNDSOL;
743  }
744  }
745  }
746  else
747  {
748  SCIP_CALL( SCIPclearSol(scip, newsol) );
749  }
750 
751  /*************************** END Probing LP Solving ***************************/
752 
753  /* if no solution has been found --> fix all other variables by subscip if necessary */
754  if( !foundsol && !lperror && lpstatus != SCIP_LPSOLSTAT_INFEASIBLE && lpstatus != SCIP_LPSOLSTAT_OBJLIMIT)
755  {
756  SCIP* subscip;
757  SCIP_VAR** subvars;
758  SCIP_HASHMAP* varmap;
759  SCIP_Bool valid;
760  int i;
761 
762  /* check whether there is enough time and memory left */
763  SCIP_CALL( SCIPcheckCopyLimits(scip, &valid) );
764 
765  if( !valid )
766  goto TERMINATE;
767 
768  /* create subproblem */
769  SCIP_CALL( SCIPcreate(&subscip) );
770 
771  /* create the variable mapping hash map */
772  SCIP_CALL( SCIPhashmapCreate(&varmap, SCIPblkmem(subscip), nvars) );
773 
774  SCIP_CALL( SCIPcopyConsCompression(scip, subscip, varmap, NULL, "_vbounds", NULL, NULL, 0, FALSE, FALSE, TRUE, NULL) );
775 
776  if( heurdata->copycuts )
777  {
778  /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
779  SCIP_CALL( SCIPcopyCuts(scip, subscip, varmap, NULL, FALSE, NULL) );
780  }
781 
782  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
783 
784  for( i = 0; i < nvars; i++ )
785  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmap, vars[i]);
786 
787  /* free hash map */
788  SCIPhashmapFree(&varmap);
789 
790  /* do not abort subproblem on CTRL-C */
791  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
792 
793 #ifdef SCIP_DEBUG
794  /* for debugging, enable full output */
795  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
796  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
797 #else
798  /* disable statistic timing inside sub SCIP and output to console */
799  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
800  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
801 #endif
802 
803  /* set limits for the subproblem */
804  SCIP_CALL( SCIPcopyLimits(scip, subscip) );
805  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", nstallnodes) );
806  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", heurdata->maxnodes) );
807 
808  /* forbid call of heuristics and separators solving sub-CIPs */
809  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
810 
811  /* disable cutting plane separation */
813 
814  /* disable expensive presolving */
816 #if 0
817  /* use best estimate node selection */
818  if( SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
819  {
820  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/4) );
821  }
822 #endif
823  /* use inference branching */
824  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
825  {
826  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
827  }
828 
829  /* disable conflict analysis */
830  if( !SCIPisParamFixed(subscip, "conflict/enable") )
831  {
832  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", FALSE) );
833  }
834 
835  /* speed up sub-SCIP by not checking dual LP feasibility */
836  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
837 
838  /* employ a limit on the number of enforcement rounds in the quadratic constraint handlers; this fixes the issue that
839  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
840  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
841  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no decutions shall be
842  * made for the original SCIP
843  */
844  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
845  {
846  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 10) );
847  }
848 
849  /* if there is already a solution, add an objective cutoff */
850  if( SCIPgetNSols(scip) > 0 )
851  {
852  SCIP_Real upperbound;
853  SCIP_Real minimprove;
854  SCIP_Real cutoff;
855 
856  minimprove = heurdata->minimprove;
857  assert( !SCIPisInfinity(scip,SCIPgetUpperbound(scip)) );
858 
859  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
860 
861  if( !SCIPisInfinity(scip,-1.0*SCIPgetLowerbound(scip)) )
862  {
863  cutoff = (1-minimprove)*SCIPgetUpperbound(scip) + minimprove*SCIPgetLowerbound(scip);
864  }
865  else
866  {
867  if( SCIPgetUpperbound ( scip ) >= 0 )
868  cutoff = ( 1 - minimprove ) * SCIPgetUpperbound ( scip );
869  else
870  cutoff = ( 1 + minimprove ) * SCIPgetUpperbound ( scip );
871  }
872  cutoff = MIN(upperbound, cutoff);
873  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
874  }
875 
876  /* solve the subproblem */
877  /* Errors in the LP solver should not kill the overall solving process, if the LP is just needed for a heuristic.
878  * Hence in optimized mode, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
879  */
880 #ifdef NDEBUG
881  {
882  SCIP_RETCODE retstat;
883  retstat = SCIPpresolve(subscip);
884  if( retstat != SCIP_OKAY )
885  {
886  SCIPwarningMessage(scip, "Error while presolving subMIP in vbounds heuristic; sub-SCIP terminated with code <%d>\n", retstat);
887  }
888  }
889 #else
890  SCIP_CALL_ABORT( SCIPpresolve(subscip) );
891 #endif
892 
893  SCIPdebugMsg(scip, "vbounds heuristic presolved subproblem: %d vars, %d cons\n", SCIPgetNVars(subscip), SCIPgetNConss(subscip));
894 
895  /* after presolving, we should have at least reached a certain fixing rate over ALL variables (including continuous)
896  * to ensure that not only the MIP but also the LP relaxation is easy enough
897  */
898  if( ( nvars - SCIPgetNVars(subscip) ) / (SCIP_Real)nvars >= heurdata->minfixingrate )
899  {
900  SCIP_SOL** subsols;
901  SCIP_Bool success;
902  int nsubsols;
903 
904  SCIPstatistic( nprevars = SCIPgetNVars(subscip) );
905 
906  SCIPdebugMsg(scip, "solving subproblem: nstallnodes=%" SCIP_LONGINT_FORMAT ", maxnodes=%" SCIP_LONGINT_FORMAT "\n", nstallnodes, heurdata->maxnodes);
907 
908 #ifdef NDEBUG
909  {
910  SCIP_RETCODE retstat;
911  retstat = SCIPsolve(subscip);
912  if( retstat != SCIP_OKAY )
913  {
914  SCIPwarningMessage(scip, "Error while solving subMIP in vbounds heuristic; sub-SCIP terminated with code <%d>\n",retstat);
915  }
916  }
917 #else
918  SCIP_CALL_ABORT( SCIPsolve(subscip) );
919 #endif
920 
921  /* check, whether a solution was found; due to numerics, it might happen that not all solutions are feasible ->
922  * try all solutions until one was accepted
923  */
924  nsubsols = SCIPgetNSols(subscip);
925  subsols = SCIPgetSols(subscip);
926  success = FALSE;
927 
928  for( i = 0; i < nsubsols && !success; ++i )
929  {
930  SCIP_CALL( createNewSol(scip, subscip, subvars, newsol, subsols[i], &success) );
931  }
932  if( success )
933  *result = SCIP_FOUNDSOL;
934  }
935 
936 #ifdef SCIP_DEBUG
937  SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
938 #endif
939 
940  /* free subproblem */
941  SCIPfreeBufferArray(scip, &subvars);
942  SCIP_CALL( SCIPfree(&subscip) );
943  }
944 
945  TERMINATE:
946 
947 #ifdef SCIP_STATISTIC
948  SCIP_CALL( SCIPstopClock(scip, clock) );
949  SCIPstatisticMessage("vbound: tighten=%d obj=%d nvars=%d presolnvars=%d ratio=%.2f infeas=%d found=%d time=%.2f\n",
950  tighten, obj, nvars, nprevars, (nvars - nprevars) / (SCIP_Real)nvars, infeasible,
951  foundsol ? 1 : 0, SCIPclockGetTime(clock) );
952 #endif
953 
954  SCIPstatistic( SCIP_CALL( SCIPfreeClock(scip, &clock) ) );
955 
956  /* free solution */
957  SCIP_CALL( SCIPfreeSol(scip, &newsol) );
958 
959  /* exit probing mode */
960  SCIP_CALL( SCIPendProbing(scip) );
961 
962  return SCIP_OKAY;
963 }
964 
965 
966 /*
967  * Callback methods of primal heuristic
968  */
969 
970 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
971 static
972 SCIP_DECL_HEURCOPY(heurCopyVbounds)
973 { /*lint --e{715}*/
974  assert(scip != NULL);
975  assert(heur != NULL);
976  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
977 
978  /* call inclusion method of heuristic */
980 
981  return SCIP_OKAY;
982 }
983 
984 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
985 static
986 SCIP_DECL_HEURFREE(heurFreeVbounds)
987 { /*lint --e{715}*/
988  SCIP_HEURDATA* heurdata;
989 
990  /* free heuristic data */
991  heurdata = SCIPheurGetData(heur);
992 
993  SCIPfreeBlockMemory(scip, &heurdata);
994  SCIPheurSetData(heur, NULL);
995 
996  return SCIP_OKAY;
997 }
998 
999 
1000 /** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed) */
1001 static
1002 SCIP_DECL_HEUREXITSOL(heurExitsolVbounds)
1003 { /*lint --e{715}*/
1004  SCIP_HEURDATA* heurdata;
1005  int v;
1006 
1007  heurdata = SCIPheurGetData(heur);
1008  assert(heurdata != NULL);
1009 
1010  /* release all variables */
1011  for( v = 0; v < heurdata->nvbvars; ++v )
1012  {
1013  SCIP_CALL( SCIPreleaseVar(scip, &heurdata->vbvars[v]) );
1014  }
1015 
1016  /* free varbounds array */
1017  SCIPfreeBlockMemoryArrayNull(scip, &heurdata->vbbounds, heurdata->nvbvars);
1018  SCIPfreeBlockMemoryArrayNull(scip, &heurdata->vbvars, heurdata->nvbvars);
1019 
1020  /* reset heuristic data structure */
1021  heurdataReset(heurdata);
1022 
1023  return SCIP_OKAY;
1024 }
1025 
1026 /** execution method of primal heuristic */
1027 static
1028 SCIP_DECL_HEUREXEC(heurExecVbounds)
1029 { /*lint --e{715}*/
1030  SCIP_HEURDATA* heurdata;
1031 
1032  assert( heur != NULL );
1033  assert( scip != NULL );
1034  assert( result != NULL );
1035 
1036  *result = SCIP_DIDNOTRUN;
1037 
1038  if( SCIPgetNPseudoBranchCands(scip) == 0 )
1039  return SCIP_OKAY;
1040 
1041  heurdata = SCIPheurGetData(heur);
1042  assert(heurdata != NULL);
1043 
1044  if( !heurdata->initialized )
1045  {
1046  SCIP_CALL( initializeCandsLists(scip, heurdata) );
1047  }
1048 
1049  if( !heurdata->applicable )
1050  return SCIP_OKAY;
1051 
1052  /* try variable bounds */
1053  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, TRUE, result) );
1054  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, TRUE, FALSE, result) );
1055  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, FALSE, result) );
1056  SCIP_CALL( applyVbounds(scip, heur, heurdata, heurdata->vbvars, heurdata->nvbvars, FALSE, TRUE, result) );
1057 
1058  return SCIP_OKAY;
1059 }
1060 
1061 /*
1062  * primal heuristic specific interface methods
1063  */
1064 
1065 /** creates the vbounds primal heuristic and includes it in SCIP */
1067  SCIP* scip /**< SCIP data structure */
1068  )
1069 {
1070  SCIP_HEURDATA* heurdata;
1071  SCIP_HEUR* heur;
1072 
1073  /* create vbounds primal heuristic data */
1074  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1075  heurdataReset(heurdata);
1076 
1077  /* include primal heuristic */
1078  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1080  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecVbounds, heurdata) );
1081 
1082  assert(heur != NULL);
1083 
1084  /* set non-NULL pointers to callback methods */
1085  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyVbounds) );
1086  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeVbounds) );
1087  SCIP_CALL( SCIPsetHeurExitsol(scip, heur, heurExitsolVbounds) );
1088 
1089  /* add variable bounds primal heuristic parameters */
1090  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1091  "minimum percentage of integer variables that have to be fixable",
1092  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1093 
1094  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1095  "maximum number of nodes to regard in the subproblem",
1096  &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1097 
1098  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1099  "number of nodes added to the contingent of the total nodes",
1100  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1101 
1102  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1103  "minimum number of nodes required to start the subproblem",
1104  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1105 
1106  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1107  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1108  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1109 
1110  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1111  "factor by which " HEUR_NAME " heuristic should at least improve the incumbent",
1112  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1113 
1114  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxproprounds",
1115  "maximum number of propagation rounds during probing (-1 infinity)",
1116  &heurdata->maxproprounds, TRUE, DEFAULT_MAXPROPROUNDS, -1, INT_MAX/4, NULL, NULL) );
1117 
1118  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1119  "should all active cuts from cutpool be copied to constraints in subproblem?",
1120  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1121 
1122  return SCIP_OKAY;
1123 }
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:8159
#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:37847
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:45371
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5130
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17383
#define HEUR_USESSUBSCIP
Definition: heur_vbounds.c:54
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21958
#define DEFAULT_NODESOFS
Definition: heur_vbounds.c:60
#define getVarIndex(idx)
Definition: heur_vbounds.c:108
SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
Definition: scip.c:40680
SCIP_RETCODE SCIPbacktrackProbing(SCIP *scip, int probingdepth)
Definition: scip.c:35291
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:41609
SCIP_RETCODE SCIPincludeHeurVbounds(SCIP *scip)
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6576
int SCIPgetProbingDepth(SCIP *scip)
Definition: scip.c:35264
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17361
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:46110
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12120
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17225
int SCIPgetNPseudoBranchCands(SCIP *scip)
Definition: scip.c:36665
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition: scip.c:18461
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:45180
#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:11554
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39108
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2764
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:4265
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:4164
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:3856
SCIP_RETCODE SCIPcutoffNode(SCIP *scip, SCIP_NODE *node)
Definition: scip.c:41023
#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:17403
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5104
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9219
#define DEFAULT_MINIMPROVE
Definition: heur_vbounds.c:58
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16862
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:21973
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:8034
SCIP_RETCODE SCIPchgVarLbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:35367
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17373
#define DEFAULT_MAXNODES
Definition: heur_vbounds.c:56
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:45129
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2902
SCIP_RETCODE SCIPconstructLP(SCIP *scip, SCIP_Bool *cutoff)
Definition: scip.c:28904
#define SCIP_LONGINT_MAX
Definition: def.h:131
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22003
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:21956
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:4237
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:44659
#define HEUR_NAME
Definition: heur_vbounds.c:46
#define getUbIndex(idx)
Definition: heur_vbounds.c:107
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:10759
#define HEUR_PRIORITY
Definition: heur_vbounds.c:49
SCIP_Bool SCIPisLPConstructed(SCIP *scip)
Definition: scip.c:28881
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7172
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:15846
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1181
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:45078
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:4373
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8095
SCIP_RETCODE SCIPpropagateProbing(SCIP *scip, int maxproprounds, SCIP_Bool *cutoff, SCIP_Longint *ndomredsfound)
Definition: scip.c:35650
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38219
SCIP_RETCODE SCIPfixVarProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real fixedval)
Definition: scip.c:35484
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:4602
SCIP_RETCODE SCIPpresolve(SCIP *scip)
Definition: scip.c:15685
#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:3057
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45753
static SCIP_DECL_HEURCOPY(heurCopyVbounds)
Definition: heur_vbounds.c:974
SCIP_RETCODE SCIPendProbing(SCIP *scip)
Definition: scip.c:35326
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16555
SCIP_Real SCIPclockGetTime(SCIP_CLOCK *clck)
Definition: clock.c:428
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2797
#define NULL
Definition: lpi_spx1.cpp:137
#define HEUR_FREQ
Definition: heur_vbounds.c:50
#define SCIP_CALL(x)
Definition: def.h:316
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:42550
SCIP_RETCODE SCIPsolveProbingLP(SCIP *scip, int itlim, SCIP_Bool *lperror, SCIP_Bool *cutoff)
Definition: scip.c:35886
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17425
#define DEFAULT_MINNODES
Definition: heur_vbounds.c:59
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1307
static SCIP_DECL_HEUREXEC(heurExecVbounds)
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:28863
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21991
#define DEFAULT_COPYCUTS
Definition: heur_vbounds.c:63
SCIP_RETCODE SCIPclearSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:37983
#define SCIP_Bool
Definition: def.h:61
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:28948
static SCIP_DECL_HEUREXITSOL(heurExitsolVbounds)
SCIP_RETCODE SCIProundSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool *success)
Definition: scip.c:39300
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11114
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42321
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4660
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:37806
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17017
LNS heuristic uses the variable lower and upper bounds to determine the search neighborhood.
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39059
SCIP_Real SCIPgetSolOrigObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38268
SCIP_RETCODE SCIPflushLP(SCIP *scip)
Definition: scip.c:28928
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:46061
#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:39976
#define SCIP_MAXTREEDEPTH
Definition: def.h:252
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:11680
#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:12728
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8907
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11635
#define SCIPstatistic(x)
Definition: pub_message.h:101
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:18427
#define SCIP_Real
Definition: def.h:145
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:17415
#define SCIP_Longint
Definition: def.h:130
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip.c:4128
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16720
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38084
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8079
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17235
#define SCIPfreeBlockMemoryArrayNull(scip, ptr, num)
Definition: scip.h:21976
SCIP_RETCODE SCIPnewProbingNode(SCIP *scip)
Definition: scip.c:35231
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:45494
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:42699
SCIP_RETCODE SCIPstartProbing(SCIP *scip)
Definition: scip.c:35185
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:89
#define SCIP_CALL_ABORT(x)
Definition: def.h:295
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1092
static SCIP_DECL_HEURFREE(heurFreeVbounds)
Definition: heur_vbounds.c:988
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:41409
SCIP_RETCODE SCIPchgVarUbProbing(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:35411
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:45163
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:4293
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5055
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4718
#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:4211
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16842
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:774
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37178