Scippy

SCIP

Solving Constraint Integer Programs

heur_gins.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-2018 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_gins.c
17  * @brief LNS heuristic that tries to delimit the search region to a neighborhood in the constraint graph
18  * @author Gregor Hendel
19  *
20  * Graph Induced Neighborhood Search (GINS) is a Large Neighborhood Search Heuristic that attempts to improve
21  * an incumbent solution by fixing a suitable percentage of integer variables to the incumbent and
22  * solving the resulting, smaller and presumably easier sub-MIP.
23  *
24  * Its search neighborhoods are based on distances in a bipartite graph \f$G\f$ with the variables and constraints as nodes
25  * and an edge between a variable and a constraint, if the variable is part of the constraint.
26  * Given an integer \f$k\f$, the \f$k\f$-neighborhood of a variable \f$v\f$ in \f$G\f$ is the set of variables, whose nodes
27  * are connected to \f$v\f$ by a path not longer than \f$2 \cdot k\f$. Intuitively, a judiciously chosen neighborhood size
28  * allows to consider a local portion of the overall problem.
29  *
30  * An initial variable selection is made by randomly sampling different neighborhoods across the whole main problem.
31  * The neighborhood that offers the largest potential for improvement is selected to become the local search neighborhood,
32  * while all variables outside the neighborhood are fixed to their incumbent solution values.
33  *
34  * GINS also supports a rolling horizon approach, during which several local neighborhoods are considered
35  * with increasing distance to the variable selected for the initial sub-problem. The rolling horizon approach ends
36  * if no improvement could be found or a sufficient part of the problem component variables has been part of
37  * at least one neighborhood.
38  */
39 
40 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
41 
42 #include <assert.h>
43 #include <string.h>
44 #include "scip/scip.h"
45 #include "scip/scipdefplugins.h"
46 #include "scip/heur_gins.h"
47 #include "scip/pub_misc.h"
48 
49 #define HEUR_NAME "gins"
50 #define HEUR_DESC "gins works on k-neighborhood in a variable-constraint graph"
51 #define HEUR_DISPCHAR 'K'
52 #define HEUR_PRIORITY -1103000
53 #define HEUR_FREQ 20
54 #define HEUR_FREQOFS 8
55 #define HEUR_MAXDEPTH -1
56 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
57 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
58 
59 #define DEFAULT_NODESOFS 500 /**< number of nodes added to the contingent of the total nodes */
60 #define DEFAULT_MAXNODES 5000 /**< maximum number of nodes to regard in the subproblem */
61 #define DEFAULT_MINIMPROVE 0.01 /**< factor by which Gins should at least improve the incumbent */
62 #define DEFAULT_MINNODES 50 /**< minimum number of nodes to regard in the subproblem */
63 #define DEFAULT_MINFIXINGRATE 0.66 /**< minimum percentage of integer variables that have to be fixed */
64 #define DEFAULT_NODESQUOT 0.15 /**< subproblem nodes in relation to nodes of the original problem */
65 #define DEFAULT_NWAITINGNODES 100 /**< number of nodes without incumbent change that heuristic should wait */
66 #define DEFAULT_USELPROWS FALSE /**< should subproblem be created out of the rows in the LP rows,
67  **< otherwise, the copy constructors of the constraints handlers are used */
68 #define DEFAULT_COPYCUTS TRUE /**< if DEFAULT_USELPROWS is FALSE, then should all active cuts from the
69  **< cutpool of the original scip be copied to constraints of the subscip */
70 #define DEFAULT_BESTSOLLIMIT 3 /**< limit on number of improving incumbent solutions in sub-CIP */
71 #define DEFAULT_FIXCONTVARS FALSE /**< should continuous variables outside the neighborhoods get fixed? */
72 #define DEFAULT_POTENTIAL 'r' /**< the reference point to compute the neighborhood potential: (r)oot or (p)seudo solution */
73 #define DEFAULT_MAXDISTANCE 3 /**< maximum distance to selected variable to enter the subproblem, or -1 to
74  * select the distance that best approximates the minimum fixing rate from below */
75 #define DEFAULT_RANDSEED 71
76 #define DEFAULT_RELAXDENSECONSS FALSE /**< should dense constraints (at least as dense as 1 - minfixingrate) be
77  * ignored by connectivity graph? */
78 #define DEFAULT_USEROLLINGHORIZON TRUE /**< should the heuristic solve a sequence of sub-MIP's around the first selected variable */
79 #define DEFAULT_ROLLHORIZONLIMFAC 0.4 /**< limiting percentage for variables already used in sub-SCIPs to terminate rolling
80  * horizon approach */
81 #ifdef SCIP_STATISTIC
82 #define NHISTOGRAMBINS 10 /* number of bins for histograms */
83 #endif
84 /*
85  * Data structures
86  */
87 
88 /** rolling horizon data structure to control multiple LNS heuristic runs away from an original source variable
89  *
90  */
91 struct RollingHorizon
92 {
93  SCIP_VGRAPH* variablegraph; /**< variable graph data structure for breadth-first-search neighborhoods */
94  int* distances; /**< distances of the heuristic rolling horizon from the original source
95  * variable indexed by probindex */
96  SCIP_Bool* used; /**< array that represents for every variable whether it has been used
97  * in a neighborhood indexed by probindex */
98  int lastmaxdistance; /**< the last distance k for a neighborhood, will be decreased
99  * during the rolling horizon if the selected neighborhood is too large */
100  int lastdistance; /**< last distance from originally selected variable in iteration zero */
101  int distancessize; /**< size of the distances and used arrays */
102  int niterations; /**< counter for the number of rolling horizon iterations */
103  int nused; /**< counts the number variables that have been part of any neighborhood
104  * during the rolling horizon approach */
105  int nnonreachable; /**< counter for the number of nonreachable variables (distance -1) from
106  * the initially selected variable */
107 };
109 
110 /** primal heuristic data */
111 struct SCIP_HeurData
112 {
113  int nodesofs; /**< number of nodes added to the contingent of the total nodes */
114  int maxnodes; /**< maximum number of nodes to regard in the subproblem */
115  int minnodes; /**< minimum number of nodes to regard in the subproblem */
116  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
117  int nwaitingnodes; /**< number of nodes without incumbent change that heuristic should wait */
118  SCIP_Real minimprove; /**< factor by which Gins should at least improve the incumbent */
119  SCIP_Longint usednodes; /**< nodes already used by Gins in earlier calls */
120  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
121  SCIP_Real rollhorizonlimfac; /**< limiting percentage for variables already used in sub-SCIPs to terminate
122  * rolling horizon approach */
123  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
124  SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
125  SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
126  * to constraints in subproblem? */
127  SCIP_Bool fixcontvars; /**< should continuous variables outside the neighborhoods get fixed? */
128  int bestsollimit; /**< limit on number of improving incumbent solutions in sub-CIP */
129  int maxdistance; /**< maximum distance to selected variable to enter the subproblem, or -1 to
130  * select the distance that best approximates the minimum fixing rate from below */
131  int sumneighborhoodvars;/**< neighborhood variables sum over all seen neighborhoods */
132  int sumdiscneighborhoodvars; /**< neighborhood discrete variables sum over all seen neighboorhoods */
133  int nneighborhoods; /**< number of calculated neighborhoods */
134  int nsubmips; /**< counter for the number of sub-MIP's that can be higher than the number of
135  * calls of this heuristic */
136  SCIP_Bool relaxdenseconss; /**< should dense constraints (at least as dense as 1 - minfixingrate) be
137  * ignored by connectivity graph? */
138  SCIP_Bool userollinghorizon; /**< should the heuristic solve a sequence of sub-MIP's around the first
139  * selected variable */
140  char potential; /**< the reference point to compute the neighborhood potential: (r)oot or
141  * (p)seudo solution */
142  int maxseendistance; /**< maximum of all distances between two variables */
143 #ifdef SCIP_STATISTIC
144  int consvarshist[NHISTOGRAMBINS]; /**< histogram that summarizes the densities of the constraints */
145  int consdiscvarshist[NHISTOGRAMBINS]; /**< histogram that summarizes the discrete variable densities of the constraints */
146  int conscontvarshist[NHISTOGRAMBINS]; /**< histogram that summarizes the continuous variable densities of the constraints */
147 #endif
148  int nrelaxedconstraints; /**< number of constraints that were relaxed */
149  int nfailures; /**< counter for the number of unsuccessful runs of this heuristic */
150  SCIP_Longint nextnodenumber; /**< the next node number at which the heuristic should be called again */
151 };
152 
153 /** represents limits for the sub-SCIP solving process */
154 struct SolveLimits
155 {
156  SCIP_Longint nodelimit; /**< maximum number of solving nodes for the sub-SCIP */
157  SCIP_Real memorylimit; /**< memory limit for the sub-SCIP */
158  SCIP_Real timelimit; /**< time limit for the sub-SCIP */
159 };
160 typedef struct SolveLimits SOLVELIMITS;
161 
162 /*
163  * Local methods
164  */
166 #ifdef SCIP_STATISTIC
167 /** resets a histogram */
168 static
169 void resetHistogram(
170  int* histogram /**< the histogram */
171  )
172 {
173  BMSclearMemoryArray(histogram, NHISTOGRAMBINS);
174 }
175 
176 /** adds a ratio to the histogram at the right position */
177 static
178 void addHistogramEntry(
179  int* histogram, /**< the histogram */
180  int value, /**< the value */
181  int basevalue /**< base value */
182  )
183 {
184  SCIP_Real ratio;
185  int index;
186  assert(value <= basevalue);
187  ratio = value/ MAX(1.0, (SCIP_Real)basevalue);
188 
189  index = (int)(ratio * NHISTOGRAMBINS);
190  ++histogram[index];
191 }
192 
193 #endif
194 
195 /** create a rolling horizon data structure */
196 static
198  SCIP* scip, /**< SCIP data structure */
199  ROLLINGHORIZON** rollinghorizon /**< pointer to rolling horizon data structure */
200  )
201 {
202  int size;
203  assert(scip != NULL);
204  assert(rollinghorizon != NULL);
205 
206  size = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
207  SCIP_CALL( SCIPallocBlockMemory(scip, rollinghorizon) );
208  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*rollinghorizon)->distances, size) );
209  SCIP_CALL( SCIPallocClearBlockMemoryArray(scip, &(*rollinghorizon)->used, size) );
210  (*rollinghorizon)->distancessize = size;
211  (*rollinghorizon)->variablegraph = NULL;
212  (*rollinghorizon)->lastdistance = -1;
213  (*rollinghorizon)->niterations = 0;
214  (*rollinghorizon)->nused = 0;
215 
216  return SCIP_OKAY;
217 }
218 
219 /** free a rolling horizon data structure */
220 static
222  SCIP* scip, /**< SCIP data structure */
223  ROLLINGHORIZON** rollinghorizon /**< pointer to rolling horizon data structure */
224  )
225 {
227  assert(scip != NULL);
228  assert(rollinghorizon != NULL);
229  assert(*rollinghorizon != NULL);
230 
231  if( (*rollinghorizon)->variablegraph != NULL )
232  {
233  SCIPvariableGraphFree(scip, &(*rollinghorizon)->variablegraph);
234  }
235 
236  SCIPfreeBlockMemoryArray(scip, &(*rollinghorizon)->distances, (*rollinghorizon)->distancessize);
237  SCIPfreeBlockMemoryArray(scip, &(*rollinghorizon)->used, (*rollinghorizon)->distancessize);
238  SCIPfreeBlockMemory(scip, rollinghorizon);
239  return SCIP_OKAY;
240 }
241 
242 /** is there potential to run another iteration of the rolling horizon approach? */
243 static
245  SCIP* scip, /**< SCIP data structure */
246  ROLLINGHORIZON* rollinghorizon, /**< rolling horizon data structure */
247  SCIP_HEURDATA* heurdata /**< heuristic data */
248  )
249 {
250  int maxnused = (int)(heurdata->rollhorizonlimfac * (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)
251  - rollinghorizon->nnonreachable));
252 
253  /* run again if a certain percentage of the reachable variables (in the same connected component)
254  * was not used in a previous neighborhood
255  */
256  return (rollinghorizon->nused < maxnused);
257 }
258 
259 /** store the distances from the selected variable permanently for the rolling horizon approach */
260 static
262  SCIP* scip, /**< SCIP data structure */
263  ROLLINGHORIZON* rollinghorizon, /**< rolling horizon data structure */
264  int* distances /**< breadth-first distances indexed by Probindex of variables */
265  )
266 {
267  int i;
268  BMScopyMemoryArray(rollinghorizon->distances, distances, rollinghorizon->distancessize);
269  rollinghorizon->lastdistance = 0;
270  rollinghorizon->nnonreachable = 0;
271 
272  /* collect number of nonreachable variables */
273  for( i = 0; i < rollinghorizon->distancessize; ++i )
274  {
275  if( distances[i] == -1 )
276  ++rollinghorizon->nnonreachable;
277  }
278 }
279 
280 /** get the potential of a subset of variables (distance to a reference point such as the pseudo-solution or root
281  * LP solution)
282  */
283 static
285  SCIP* scip, /**< SCIP data structure */
286  SCIP_HEURDATA* heurdata, /**< heuristic data */
287  SCIP_SOL* sol, /**< solution */
288  SCIP_VAR** vars, /**< variable array */
289  int nvars /**< length of variable array */
290  )
291 {
292  SCIP_Real potential;
293  int i;
294 
295  assert(scip != NULL);
296  assert(vars != NULL);
297  assert(sol != NULL);
298 
299  if( nvars == 0 )
300  return 0.0;
301 
302  potential = 0.0;
303 
304  for( i = 0; i < nvars; ++i )
305  {
306  SCIP_Real objdelta;
307  SCIP_VAR* var;
308  SCIP_Real referencepoint;
309  SCIP_Real varobj;
310 
311  var = vars[i];
312  assert(var != NULL);
313  varobj = SCIPvarGetObj(var);
314 
315  if( SCIPisZero(scip, varobj) )
316  continue;
317 
318  /* determine the reference point for potential computation */
319  switch( heurdata->potential )
320  {
321  /* use difference to pseudo solution using the bound in the objective direction */
322  case 'p':
323  referencepoint = SCIPvarGetObj(var) > 0.0 ? SCIPvarGetLbGlobal(var) : SCIPvarGetUbGlobal(var);
324  break;
325 
326  /* use root LP solution difference */
327  case 'r':
328  referencepoint = SCIPvarGetRootSol(var);
329  break;
330  default:
331  SCIPerrorMessage("Unknown potential computation %c specified\n", heurdata->potential);
332  referencepoint = 0.0;
333  break;
334  }
335 
336  if( SCIPisInfinity(scip, REALABS(referencepoint)) )
337  continue;
338 
339  /* calculate the delta to the variables best bound */
340  objdelta = (SCIPgetSolVal(scip, sol, var) - referencepoint) * SCIPvarGetObj(var);
341  potential += objdelta;
342  }
343 
344  return potential;
345 }
346 
347 /** is the variable in the current neighborhood which is given by the breadth-first distances from a central variable? */
348 static
350  SCIP_VAR* var, /**< problem variable */
351  int* distances, /**< breadth-first distances indexed by Probindex of variables */
352  int maxdistance /**< maximum distance (inclusive) to be considered for neighborhoods */
353  )
354 {
355  assert(var != NULL);
356  assert(distances != NULL);
357  assert(maxdistance >= 0);
358  assert(SCIPvarGetProbindex(var) >= 0);
359 
360  return (distances[SCIPvarGetProbindex(var)] != -1 && distances[SCIPvarGetProbindex(var)] <= maxdistance);
361 }
362 
363 /** fixes variables in subproblem based on long breadth-first distances in variable graph */
364 static
366  SCIP* scip, /**< SCIP data structure */
367  SCIP_HEURDATA* heurdata, /**< heuristic data */
368  ROLLINGHORIZON* rollinghorizon, /**< rolling horizon data structure to save relevant information, or NULL if not needed */
369  SCIP_SOL* sol, /**< solution in main SCIP for fixing values */
370  SCIP_VAR** vars, /**< variables in the main SCIP */
371  SCIP_VAR** fixedvars, /**< buffer to store variables that should be fixed */
372  SCIP_Real* fixedvals, /**< buffer to store fixing values for fixed variables */
373  int* distances, /**< breadth-first distances indexed by Probindex of variables */
374  int maxdistance, /**< maximum distance (inclusive) to be considered for neighborhoods */
375  int* nfixings /**< pointer to store number of fixed variables */
376  )
377 {
378  int i;
379  int nbinvars;
380  int nintvars;
381  int nvars;
382  int nvarstofix;
383 
384  SCIP_CALL( SCIPgetVarsData(scip, NULL, &nvars, &nbinvars, &nintvars, NULL, NULL) );
385 
386  nvarstofix = heurdata->fixcontvars ? nvars : nbinvars + nintvars;
387  *nfixings = 0;
388 
389  /* change bounds of variables of the subproblem */
390  for( i = 0; i < nvarstofix; i++ )
391  {
392  /* fix all variables that are too far away from this variable according to maxdistance */
393  if( distances[i] == -1 || distances[i] > maxdistance )
394  {
395  SCIP_Real solval;
396  SCIP_Real lb;
397  SCIP_Real ub;
398 
399  solval = SCIPgetSolVal(scip, sol, vars[i]);
400  lb = SCIPvarGetLbGlobal(vars[i]);
401  ub = SCIPvarGetUbGlobal(vars[i]);
402  assert(SCIPisLE(scip, lb, ub));
403 
404  /* due to dual reductions, it may happen that the solution value is not in the variable's domain anymore */
405  if( SCIPisLT(scip, solval, lb) )
406  solval = lb;
407  else if( SCIPisGT(scip, solval, ub) )
408  solval = ub;
409 
410  /* perform the bound change */
411  if( !SCIPisInfinity(scip, solval) && !SCIPisInfinity(scip, -solval) )
412  {
413  fixedvars[*nfixings] = vars[i];
414  fixedvals[*nfixings] = solval;
415  ++(*nfixings);
416  }
417  }
418  else if( rollinghorizon != NULL && i < nbinvars + nintvars && ! rollinghorizon->used[i] )
419  {
420  ++rollinghorizon->nused;
421  rollinghorizon->used[i] = TRUE;
422  }
423  }
424 
425  if( rollinghorizon != NULL )
426  {
427  rollinghorizon->lastmaxdistance = maxdistance;
428  rollinghorizon->niterations++;
429  }
430 
431  return SCIP_OKAY;
432 }
433 
434 /** determine the maximum allowed distance to stay within the restriction to fix at least minfixingrate many non
435  * neighborhood variables
436  */
437 static
439  SCIP* scip, /**< SCIP data structure */
440  SCIP_HEURDATA* heurdata, /**< heuristic data */
441  int* distances, /**< breadth-first distances indexed by Probindex of variables */
442  int* choosevardistance /**< pointer to store the computed maximum distance */
443  )
444 {
445  int* distancescopy;
446  int nrelevantdistances;
447  int criticalidx;
448  int zeropos;
449  int nvars;
450  int nbinvars;
451  int nintvars;
452 
453  SCIP_CALL( SCIPgetVarsData(scip, NULL, &nvars, &nbinvars, &nintvars, NULL, NULL) );
454 
455  nrelevantdistances = (heurdata->fixcontvars ? nvars : (nbinvars + nintvars));
456 
457  /* copy the relevant distances of either the discrete or all problem variables and sort them */
458  SCIP_CALL( SCIPduplicateBufferArray(scip, &distancescopy, distances, nrelevantdistances) );
459  SCIPsortInt(distancescopy, nrelevantdistances);
460 
461  /* distances can be infinite in the case of multiple connected components; therefore, search for the index of the
462  * zero entry, which is the unique representative of the chosen variable in the sorted distances
463  */
464  zeropos = -1;
465 
466  /* TODO: use selection method instead */
467  (void)SCIPsortedvecFindInt(distancescopy, 0, nrelevantdistances, &zeropos);
468  assert(zeropos >= 0);
469 
470  /* determine the critical index to look for an appropriate neighborhood distance, starting from the zero position */
471  criticalidx = zeropos + (int)((1.0 - heurdata->minfixingrate) * nrelevantdistances);
472  criticalidx = MIN(criticalidx, nrelevantdistances - 1);
473 
474  /* determine the maximum breadth-first distance such that the neighborhood size stays small enough (below 1-minfixingrate)*/
475  *choosevardistance = distancescopy[criticalidx];
476 
477  /* we set the distance to exactly the distance at the critical index. If the distance at critical index is not the
478  * last one before the distance increases, we decrease the choosevardistance such that the entire neighborhood
479  * fits into the minfixingrate restriction
480  */
481  if( criticalidx != nrelevantdistances - 1 && distancescopy[criticalidx + 1] == *choosevardistance )
482  (*choosevardistance)--;
483 
484  /* update the maximum distance */
485  heurdata->maxseendistance = MAX(heurdata->maxseendistance, distancescopy[nrelevantdistances - 1]);
486 
487  SCIPfreeBufferArray(scip, &distancescopy);
488 
489  return SCIP_OKAY;
490 }
491 
492 /** gets the average size of a discrete neighborhood over all variables tested */
493 static
495  SCIP_HEURDATA* heurdata /**< heuristic data */
496  )
497 {
498  return heurdata->sumdiscneighborhoodvars / (MAX(1.0, (SCIP_Real)heurdata->nneighborhoods));
499 }
500 
501 /** select a good starting variable at the first iteration of a rolling horizon approach */
502 static
504  SCIP* scip, /**< SCIP data structure */
505  SCIP_HEURDATA* heurdata, /**< heuristic data */
506  SCIP_VGRAPH* vargraph, /**< variable graph data structure to work on */
507  int* distances, /**< breadth-first distances indexed by Probindex of variables */
508  SCIP_VAR** selvar, /**< pointer to store the selected variable */
509  int* selvarmaxdistance /**< maximal distance k to consider for selected variable neighborhood */
510  )
511 {
512  SCIP_SOL* sol;
513  SCIP_VAR** vars; /* original scip variables */
514  int nbinvars;
515  int nintvars;
516  int nvars;
517  int nsearched;
518  int searchlimit;
519  int nintegralvarsleft;
520  int nintegralvarsbound;
521  int v;
522  SCIP_VAR** varscopy;
523  int maxdistance;
524  SCIP_Real maxpotential;
525 
526  assert(vargraph != NULL);
527  assert(scip != NULL);
528  assert(heurdata != NULL);
529  assert(selvar != NULL);
530  sol = SCIPgetBestSol(scip);
531  assert(sol != NULL);
532 
533  /* get required data of the original problem */
534  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
535 
536  /* copy SCIP variables */
537  SCIP_CALL( SCIPduplicateBufferArray(scip, &varscopy, vars, nbinvars + nintvars) );
538  nsearched = 0;
539  maxpotential = SCIP_REAL_MIN;
540 
541  /* determine upper bound on neighborhood size */
542  nintegralvarsbound = (int)((1.0 - heurdata->minfixingrate) * (nbinvars + nintvars));
543 
544  /* maximum distance from selected variable for breadth-first search (if set to -1, we compute an exhaustive breadth-first
545  * search and sort the variables by their distance)
546  */
547  maxdistance = (heurdata->maxdistance == - 1 ? INT_MAX : heurdata->maxdistance);
548 
549  nintegralvarsleft = nbinvars + nintvars;
550  *selvar = NULL;
551 
552  /* sort inactive variables to the end of the array */
553  for( v = nintegralvarsleft - 1; v >= 0; --v )
554  {
555  if( ! SCIPvarIsActive(varscopy[v]) )
556  {
557  varscopy[v] = varscopy[nintegralvarsleft - 1];
558  --nintegralvarsleft;
559  }
560  }
561 
562  /* adjust the search limit */
563  searchlimit = heurdata->nneighborhoods < 10 ? 5 : (int)(nintegralvarsleft / heurdataAvgDiscreteNeighborhoodSize(heurdata));
564  searchlimit = MIN(searchlimit, 10);
565 
566  /* multi variable potential: choose different disjoint neighborhoods, compare their potential */
567  while( nsearched < searchlimit && nintegralvarsleft > 0 )
568  {
569  SCIP_VAR** neighborhood;
570  SCIP_VAR* choosevar;
571  int neighborhoodsize;
572  int ndiscvarsneighborhood;
573  int choosevardistance;
574 
575  ++nsearched;
576 
577  /* select a variable to start with randomly, but make sure it is active */
578  do
579  {
580  int idx = SCIPrandomGetInt(heurdata->randnumgen, 0, nintegralvarsleft - 1);
581  choosevar = varscopy[idx];
582  assert(choosevar != NULL);
583  /* sort inactive variables to the end */
584  if( SCIPvarGetProbindex(choosevar) < 0 )
585  {
586  varscopy[idx] = varscopy[nintegralvarsleft - 1];
587  --nintegralvarsleft;
588  }
589  }
590  while( SCIPvarGetProbindex(choosevar) < 0 && nintegralvarsleft > 0);
591 
592  /* if there was no variable chosen, there are no active variables left */
593  if( SCIPvarGetProbindex(choosevar) < 0 )
594  {
595  SCIPdebugMsg(scip, "No active variable left to perform breadth-first search\n");
596  break;
597  }
598 
599  assert(SCIPvarIsIntegral(choosevar));
600 
601  /* get neighborhood storage */
602  SCIP_CALL( SCIPallocBufferArray(scip, &neighborhood, nvars) );
603 
604  /* determine breadth-first distances from the chosen variable */
605  SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, vargraph, &choosevar, 1, distances, maxdistance, INT_MAX, INT_MAX) );
606 
607  /* use either automatic or user-defined max-distance for neighborhood in variable constraint graph */
608  if( heurdata->maxdistance != -1 )
609  {
610  choosevardistance = heurdata->maxdistance;
611  }
612  else
613  {
614  SCIP_CALL( determineMaxDistance(scip, heurdata, distances, &choosevardistance) );
615  }
616 
617  ndiscvarsneighborhood = 0;
618  neighborhoodsize = 0;
619 
620  /* loop over variables and determine neighborhood */
621  for( v = nvars - 1; v >= 0; --v )
622  {
623  SCIP_VAR* currvar;
624  currvar = vars[v];
625 
626  /* put variable in the neighborhood */
627  if( isVariableInNeighborhood(currvar, distances, choosevardistance) )
628  {
629  neighborhood[neighborhoodsize++] = currvar;
630 
631  /* increase discrete variables counter */
632  if( SCIPvarIsIntegral(currvar) )
633  ++ndiscvarsneighborhood;
634  }
635  }
636 
637  /* check if neighborhood contains too many integer variables in order to satisfy the minimum fixing rate */
638  if( ndiscvarsneighborhood >= nintegralvarsbound || ndiscvarsneighborhood <= 1 )
639  {
640  SCIPdebugMsg(scip, "Too many or too few discrete variables in neighboorhood: %d (%d)\n",
641  ndiscvarsneighborhood, nbinvars + nintvars);
642  }
643  else
644  {
645  /* compare the neighborhood potential to the best potential found so far */
646  SCIP_Real potential = getPotential(scip, heurdata, sol, neighborhood, neighborhoodsize);
647 
648  /* big potential, take this variable */
649  if( potential > maxpotential )
650  {
651  maxpotential = potential;
652  *selvar = choosevar;
653  *selvarmaxdistance = choosevardistance;
654  }
655  }
656 
657  /* sort neighborhood variables to the end so that this neighborhood is not considered in further samples */
658  for( v = nintegralvarsleft - 1; v >= 0; --v )
659  {
660  SCIP_VAR* currvar;
661  currvar = vars[v];
662 
663  if( isVariableInNeighborhood(currvar, distances, choosevardistance) )
664  {
665  varscopy[v] = varscopy[nintegralvarsleft - 1];
666  --nintegralvarsleft;
667  }
668  }
669 
670  heurdata->sumdiscneighborhoodvars += ndiscvarsneighborhood;
671  heurdata->sumneighborhoodvars += neighborhoodsize;
672  ++heurdata->nneighborhoods;
673 
674  /* free current neighborhood */
675  SCIPfreeBufferArray(scip, &neighborhood);
676  }
677 
678  SCIPfreeBufferArray(scip, &varscopy);
679 
680  /* maybe no variable has a positive delta */
681  if( !SCIPisPositive(scip, maxpotential) || *selvar == NULL )
682  {
683  SCIPdebugMsg(scip, "Stopping with maxpotential %15.9f and selected variable %s\n",
684  maxpotential, *selvar != NULL ? SCIPvarGetName(*selvar) : "none");
685  *selvar = NULL;
686  }
687 
688  return SCIP_OKAY;
689 }
690 
691 /** select the next variable using the rolling horizon */
692 static
694  SCIP* scip, /**< SCIP data structure */
695  SCIP_HEURDATA* heurdata, /**< heuristic data */
696  ROLLINGHORIZON* rollinghorizon, /**< rolling horizon data structure to save relevant information, or NULL if not needed */
697  int* distances, /**< breadth-first distances indexed by Probindex of variables */
698  SCIP_VAR** selvar, /**< pointer to store the selected variable */
699  int* selvarmaxdistance /**< maximal distance k to consider for selected variable neighborhood */
700  )
701 {
702  SCIP_VAR** vars; /* original scip variables */
703  int i;
704  int nbinvars;
705  int nintvars;
706  int minunuseddistance;
707 
708  assert(scip != NULL);
709  assert(rollinghorizon != NULL);
710  assert(distances != NULL);
711  assert(selvar != NULL);
712  assert(selvarmaxdistance != NULL);
713 
714  SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
715 
716  /* loop over the variables that are left and pick the variable with
717  * - the smallest, always nondecreasing distance
718  * - that was not used before in a neighborhood
719  */
720  do
721  {
722  minunuseddistance = INT_MAX;
723  *selvarmaxdistance = rollinghorizon->lastmaxdistance;
724  *selvar = NULL;
725  for( i = 0; i < nbinvars + nintvars && minunuseddistance > rollinghorizon->lastdistance; ++i )
726  {
727  if( rollinghorizon->distances[i] >= rollinghorizon->lastdistance
728  && rollinghorizon->distances[i] < minunuseddistance && ! rollinghorizon->used[i] )
729  {
730  minunuseddistance = rollinghorizon->distances[i];
731  *selvar = vars[i];
732  }
733  }
734 
735  /* if no variable could be selected, we can stop */
736  if( *selvar == NULL )
737  {
738  *selvarmaxdistance = 0;
739  return SCIP_OKAY;
740  }
741 
742  /* determine the distances to other variables from this variable */
743  SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, rollinghorizon->variablegraph, selvar, 1, distances, *selvarmaxdistance, INT_MAX, INT_MAX) );
744 
745  SCIP_CALL( determineMaxDistance(scip, heurdata, distances, selvarmaxdistance) );
746 
747  /* mark this variable as used in order to not find it again */
748  if( *selvarmaxdistance == 0 )
749  {
750  rollinghorizon->used[SCIPvarGetProbindex(*selvar)] = TRUE;
751  rollinghorizon->nused++;
752  *selvar = NULL;
753  }
754 
755  } while( rollingHorizonRunAgain(scip, rollinghorizon, heurdata) && (*selvar == NULL || *selvarmaxdistance == 0) );
756 
757  /* breadth-first search determines the distances of all variables
758  * that are no more than maxdistance away from the start variable
759  */
760  assert(*selvarmaxdistance <= rollinghorizon->lastmaxdistance);
761  *selvarmaxdistance = MIN(*selvarmaxdistance, rollinghorizon->lastmaxdistance);
762  rollinghorizon->lastdistance = minunuseddistance;
763  rollinghorizon->lastmaxdistance = *selvarmaxdistance;
764 
765  return SCIP_OKAY;
766 }
767 
768 /** determines the graph-induced variable fixings */
769 static
771  SCIP* scip, /**< original SCIP data structure */
772  SCIP_VAR** fixedvars, /**< buffer to store variables that should be fixed */
773  SCIP_Real* fixedvals, /**< buffer to store fixing values for fixed variables */
774  int* nfixings, /**< pointer to store the number of fixed variables */
775  SCIP_HEURDATA* heurdata, /**< heuristic data */
776  ROLLINGHORIZON* rollinghorizon, /**< rolling horizon data structure to save relevant information, or NULL if not needed */
777  SCIP_Bool* success /**< used to store whether the creation of the subproblem worked */
778  )
779 {
780  SCIP_VAR** vars;
781  SCIP_SOL* sol; /* pool of solutions */
782  int* distances;
783  SCIP_VGRAPH* vargraph;
784  SCIP_VAR* selvar;
785  int nvars;
786  int nbinvars;
787  int nintvars;
788  int fixthreshold;
789 
790  int selvarmaxdistance;
791 
792  assert(fixedvars != NULL);
793  assert(fixedvals != NULL);
794  assert(nfixings != NULL);
795 
796  *success = TRUE;
797  *nfixings = 0;
798  selvarmaxdistance = 0;
799  sol = SCIPgetBestSol(scip);
800  assert(sol != NULL);
801 
802  /* get required data of the original problem */
803  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
804 
805  /* create variable graph */
806  SCIPdebugMsg(scip, "Creating variable constraint graph\n");
807 
808  /* get the saved variable graph, or create a new one */
809  if( rollinghorizon != NULL )
810  {
811  if( rollinghorizon->niterations == 0 )
812  {
813  SCIP_CALL( SCIPvariableGraphCreate(scip, &rollinghorizon->variablegraph, heurdata->relaxdenseconss, 1.0 - heurdata->minfixingrate, &heurdata->nrelaxedconstraints) );
814  }
815  else
816  assert(rollinghorizon->variablegraph != NULL);
817 
818  vargraph = rollinghorizon->variablegraph;
819  }
820  else
821  {
822  SCIP_CALL( SCIPvariableGraphCreate(scip, &vargraph, heurdata->relaxdenseconss, 1.0 - heurdata->minfixingrate, &heurdata->nrelaxedconstraints) );
823  }
824 
825  /* allocate buffer memory to hold distances */
826  SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
827 
828  selvar = NULL;
829 
830  /* in the first iteration of the rolling horizon approach, we select an initial variable */
831  if( rollinghorizon == NULL || rollinghorizon->niterations == 0 )
832  {
833  SCIP_CALL( selectInitialVariable(scip, heurdata, vargraph, distances, &selvar, &selvarmaxdistance) );
834 
835  /* collect and save the distances in the rolling horizon data structure */
836  if( selvar != NULL && rollinghorizon != NULL )
837  {
838  /* collect distances in the variable graph of all variables to the selected variable */
839  SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, vargraph, &selvar, 1, distances, INT_MAX, INT_MAX, INT_MAX) );
840  rollingHorizonStoreDistances(scip, rollinghorizon, distances);
841  rollinghorizon->lastmaxdistance = selvarmaxdistance;
842  }
843  }
844  else
845  {
846  /* select the next variable, if variables are left */
847  SCIP_CALL( selectNextVariable(scip, heurdata, rollinghorizon, distances, &selvar, &selvarmaxdistance) );
848  }
849 
850  assert(selvar == NULL || selvarmaxdistance > 0);
851  if( selvar == NULL )
852  {
853  *success = FALSE;
854  }
855  else
856  {
857  SCIPdebugMsg(scip, "Selected variable <%s> as central variable for a <%d>-neighborhood\n",
858  SCIPvarGetName(selvar), selvarmaxdistance);
859 
860  /* fix variables that are not in the neighborhood around the selected variable */
861  SCIP_CALL( fixNonNeighborhoodVariables(scip, heurdata, rollinghorizon, sol, vars, fixedvars, fixedvals, distances,
862  selvarmaxdistance, nfixings) );
863 
864  fixthreshold = (int)(heurdata->minfixingrate * (heurdata->fixcontvars ? nvars : (nbinvars + nintvars)));
865 
866  /* compare actual number of fixings to limit; if we fixed not enough variables we terminate here;
867  * we also terminate if no discrete variables are left
868  */
869  if( *nfixings < fixthreshold )
870  {
871  SCIPdebugMsg(scip, "Fixed %d < %d variables in gins heuristic, stopping", *nfixings, fixthreshold);
872  *success = FALSE;
873  }
874  }
875 
877  if( rollinghorizon == NULL )
878  SCIPvariableGraphFree(scip, &vargraph);
879 
880  return SCIP_OKAY;
881 }
882 
883 /** creates a new solution for the original problem by copying the solution of the subproblem */
884 static
886  SCIP* scip, /**< original SCIP data structure */
887  SCIP* subscip, /**< SCIP structure of the subproblem */
888  SCIP_VAR** subvars, /**< the variables of the subproblem */
889  SCIP_HEUR* heur, /**< gins heuristic structure */
890  SCIP_SOL* subsol, /**< solution of the subproblem */
891  SCIP_Bool* success /**< used to store whether new solution was found or not */
892  )
893 {
894  SCIP_VAR** vars; /* the original problem's variables */
895  int nvars;
896  SCIP_Real* subsolvals; /* solution values of the subproblem */
897  SCIP_SOL* newsol; /* solution to be created for the original problem */
898 
899  assert(scip != NULL);
900  assert(subscip != NULL);
901  assert(subvars != NULL);
902  assert(subsol != NULL);
903 
904  /* get variables' data */
905  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
906 
907  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
908  * since constraint copying may have required the copy of variables that are fixed in the main SCIP
909  */
910  assert(nvars <= SCIPgetNOrigVars(subscip));
911 
912  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
913 
914  /* copy the solution */
915  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
916 
917  /* create new solution for the original problem */
918  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
919  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
920 
921  /* try to add new solution to scip and free it immediately */
922  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
923 
924  SCIPfreeBufferArray(scip, &subsolvals);
925 
926  return SCIP_OKAY;
927 }
928 
929 /** set sub-SCIP solving limits */
930 static
932  SCIP* subscip, /**< SCIP data structure */
933  SOLVELIMITS* solvelimits /**< pointer to solving limits data structure */
934  )
935 {
936  assert(subscip != NULL);
937  assert(solvelimits != NULL);
938 
939  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", solvelimits->nodelimit) );
940  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", solvelimits->timelimit) );
941  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", solvelimits->memorylimit) );
942 
943  return SCIP_OKAY;
944 }
945 
946 /** set up the sub-SCIP */
947 static
949  SCIP* scip, /**< SCIP data structure */
950  SCIP* subscip, /**< sub-SCIP data structure */
951  SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
952  SCIP_HEUR* heur /**< this heuristic */
953  )
954 {
955  SCIP_HEURDATA* heurdata;
956  SCIP_Real cutoff;
957  SCIP_Real upperbound;
958 
959  heurdata = SCIPheurGetData(heur);
960 
961  /* do not abort subproblem on CTRL-C */
962  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
963 
964  /* disable output to console */
965  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
966 
967  /* disable statistic timing inside sub SCIP */
968  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
969 
970  SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsollimit) );
971 
972  /* forbid recursive call of heuristics and separators solving subMIPs */
973  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
974 
975  /* disable cutting plane separation */
977 
978  /* disable expensive presolving */
980 
981  /* use best estimate node selection */
982  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
983  {
984  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
985  }
986 
987  /* use inference branching */
988  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
989  {
990  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
991  }
992 
993  /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
994  if( !SCIPisParamFixed(subscip, "conflict/enable") )
995  {
996  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
997  }
998  if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
999  {
1000  SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
1001  }
1002  if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
1003  {
1004  SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
1005  }
1006 
1007  /* speed up sub-SCIP by not checking dual LP feasibility */
1008  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
1009 
1010  /* employ a limit on the number of enforcement rounds in the quadratic constraint handlers; this fixes the issue that
1011  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
1012  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
1013  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no decutions shall be
1014  * made for the original SCIP
1015  */
1016  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
1017  {
1018  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 10) );
1019  }
1020 
1021  /* add an objective cutoff */
1022  assert( !SCIPisInfinity(scip, SCIPgetUpperbound(scip)) );
1023 
1024  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
1025  if( !SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
1026  {
1027  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip)
1028  + heurdata->minimprove * SCIPgetLowerbound(scip);
1029  }
1030  else
1031  {
1032  if( SCIPgetUpperbound(scip) >= 0 )
1033  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
1034  else
1035  cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
1036  }
1037  cutoff = MIN(upperbound, cutoff);
1038  SCIP_CALL(SCIPsetObjlimit(subscip, cutoff));
1039 
1040  /* set solve limits for sub-SCIP */
1041  SCIP_CALL( setLimits(subscip, solvelimits) );
1042 
1043  return SCIP_OKAY;
1044 }
1045 
1046 /** determine limits for a sub-SCIP */
1047 static
1049  SCIP* scip, /**< SCIP data structure */
1050  SCIP_HEUR* heur, /**< this heuristic */
1051  SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
1052  SCIP_Bool* runagain /**< can we solve another sub-SCIP with these limits */
1053  )
1054 {
1055  SCIP_HEURDATA* heurdata;
1056  SCIP_Real maxnnodesr;
1057  SCIP_Longint maxnnodes;
1058  assert(scip != NULL);
1059  assert(heur != NULL);
1060  assert(solvelimits != NULL);
1061  assert(runagain != NULL);
1062 
1063  heurdata = SCIPheurGetData(heur);
1064 
1065  /* check whether there is enough time and memory left */
1066  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &solvelimits->timelimit) );
1067  if( !SCIPisInfinity(scip, solvelimits->timelimit) )
1068  solvelimits->timelimit -= SCIPgetSolvingTime(scip);
1069  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &solvelimits->memorylimit) );
1070 
1071  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1072  if( !SCIPisInfinity(scip, solvelimits->memorylimit) )
1073  {
1074  solvelimits->memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1075  solvelimits->memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1076  }
1077 
1078  /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
1079  if( solvelimits->timelimit <= 0.0 || solvelimits->memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
1080  *runagain = FALSE;
1081 
1082  /* calculate the maximal number of branching nodes until heuristic is aborted */
1083  maxnnodesr = heurdata->nodesquot * SCIPgetNNodes(scip);
1084 
1085  /* reward gins if it succeeded often, count the setup costs for the sub-MIP as 100 nodes */
1086  maxnnodesr *= 1.0 + 2.0 * (SCIPheurGetNBestSolsFound(heur)+1.0)/(heurdata->nsubmips + 1.0);
1087  maxnnodes = (SCIP_Longint)(maxnnodesr - 100.0 * heurdata->nsubmips);
1088  maxnnodes += heurdata->nodesofs;
1089 
1090  /* determine the node limit for the current process */
1091  solvelimits->nodelimit = maxnnodes - heurdata->usednodes;
1092  solvelimits->nodelimit = MIN(solvelimits->nodelimit, heurdata->maxnodes);
1093 
1094  /* check whether we have enough nodes left to call subproblem solving */
1095  if( solvelimits->nodelimit < heurdata->minnodes )
1096  *runagain = FALSE;
1097 
1098  return SCIP_OKAY;
1099 }
1100 
1101 /** updates heurdata after a run of GINS */
1102 static
1104  SCIP* scip, /**< original SCIP data structure */
1105  SCIP_HEURDATA* heurdata /**< primal heuristic data */
1106  )
1107 {
1108  /* increase number of failures, calculate next node at which GINS should be called and update actual solutions */
1109  heurdata->nfailures++;
1110  heurdata->nextnodenumber = (heurdata->nfailures <= 25
1111  ? SCIPgetNNodes(scip) + 100*(2LL << heurdata->nfailures) /*lint !e703*/
1112  : SCIP_LONGINT_MAX);
1113 }
1114 
1115 #ifdef SCIP_STATISTIC
1116 /** gets the average neighborhood size of all selected variables */
1117 static
1118 SCIP_Real heurdataAvgNeighborhoodSize(
1119  SCIP_HEURDATA* heurdata /**< heuristic data */
1120  )
1121 {
1122  return heurdata->sumneighborhoodvars / (MAX(1.0, (SCIP_Real)heurdata->nneighborhoods));
1123 }
1124 
1125 /** prints a histogram */
1126 static
1127 void printHistogram(
1128  SCIP* scip, /**< SCIP data structure */
1129  int* histogram, /**< histogram values */
1130  const char* name /**< display name of this histogram */
1131  )
1132 {
1133  int i;
1134 
1135  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Gins: %s", name);
1136 
1137  /* write out entries of this histogram */
1138  for( i = 0; i < NHISTOGRAMBINS; ++i )
1139  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, " %d", histogram[i]);
1140  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "\n");
1141 }
1142 #endif
1143 
1144 /*
1145  * Callback methods of primal heuristic
1146  */
1147 
1148 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1149 static
1150 SCIP_DECL_HEURCOPY(heurCopyGins)
1151 { /*lint --e{715}*/
1152  assert(scip != NULL);
1153  assert(heur != NULL);
1154  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1156  /* call inclusion method of primal heuristic */
1157  SCIP_CALL( SCIPincludeHeurGins(scip) );
1158 
1159  return SCIP_OKAY;
1160 }
1161 
1162 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
1163 static
1164 SCIP_DECL_HEURFREE(heurFreeGins)
1165 { /*lint --e{715}*/
1166  SCIP_HEURDATA* heurdata;
1167 
1168  assert(heur != NULL);
1169  assert(scip != NULL);
1170 
1171  /* get heuristic data */
1172  heurdata = SCIPheurGetData(heur);
1173  assert(heurdata != NULL);
1174 
1175  /* free heuristic data */
1176  SCIPfreeBlockMemory(scip, &heurdata);
1177  SCIPheurSetData(heur, NULL);
1178 
1179  return SCIP_OKAY;
1180 }
1181 
1182 /** initialization method of primal heuristic (called after problem was transformed) */
1183 static
1184 SCIP_DECL_HEURINIT(heurInitGins)
1185 { /*lint --e{715}*/
1186  SCIP_HEURDATA* heurdata;
1187 
1188  assert(heur != NULL);
1189  assert(scip != NULL);
1190 
1191  /* get heuristic's data */
1192  heurdata = SCIPheurGetData(heur);
1193  assert(heurdata != NULL);
1194  assert(heurdata->randnumgen == NULL);
1195 
1196  /* initialize data */
1197  heurdata->usednodes = 0;
1198  SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED) );
1199  heurdata->sumdiscneighborhoodvars = heurdata->sumneighborhoodvars = 0;
1200  heurdata->nneighborhoods = 0;
1201  heurdata->maxseendistance = 0;
1202  heurdata->nsubmips = 0;
1203  heurdata->nfailures = 0;
1204  heurdata->nextnodenumber = 0;
1205 
1206 #ifdef SCIP_STATISTIC
1207  resetHistogram(heurdata->conscontvarshist);
1208  resetHistogram(heurdata->consdiscvarshist);
1209  resetHistogram(heurdata->conscontvarshist);
1210 #endif
1211 
1212  return SCIP_OKAY;
1213 }
1214 
1215 /** initialization method of primal heuristic (called after problem was transformed) */
1216 static
1217 SCIP_DECL_HEUREXIT(heurExitGins)
1218 { /*lint --e{715}*/
1219  SCIP_HEURDATA* heurdata;
1220 
1221  assert(heur != NULL);
1222  assert(scip != NULL);
1223 
1224  /* get heuristic's data */
1225  heurdata = SCIPheurGetData(heur);
1226  assert(heurdata != NULL);
1227 
1228  SCIPstatistic(
1229  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Gins: Avg Neighborhood size: %.1f Avg. discrete neighboorhood vars: %.1f\n",
1230  heurdataAvgNeighborhoodSize(heurdata), heurdataAvgDiscreteNeighborhoodSize(heurdata));
1231  SCIPverbMessage(scip, SCIP_VERBLEVEL_HIGH, NULL, "Gins: Max seen distance %d\n", heurdata->maxseendistance);
1232  printHistogram(scip, heurdata->consvarshist, "Constraint density histogram");
1233  printHistogram(scip, heurdata->conscontvarshist, "Constraint continuous density histogram");
1234  printHistogram(scip, heurdata->consdiscvarshist, "Constraint discrete density histogram");
1235  )
1236 
1237  SCIPfreeRandom(scip, &heurdata->randnumgen);
1238  heurdata->randnumgen = NULL;
1239 
1240  return SCIP_OKAY;
1241 }
1242 
1243 /** execution method of primal heuristic */
1244 static
1245 SCIP_DECL_HEUREXEC(heurExecGins)
1246 { /*lint --e{715}*/
1247 
1248  SCIP_HEURDATA* heurdata; /* heuristic's data */
1249  SCIP* subscip; /* the subproblem created by gins */
1250  SCIP_VAR** vars; /* original problem's variables */
1251  SCIP_VAR** subvars; /* subproblem's variables */
1252  SCIP_VAR** fixedvars;
1253  SCIP_Real* fixedvals;
1254  ROLLINGHORIZON* rollinghorizon; /* data structure for rolling horizon approach */
1255  SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
1256 
1257  int nvars; /* number of original problem's variables */
1258  int i;
1259  int nfixedvars;
1260  SOLVELIMITS solvelimits;
1261  SCIP_Bool runagain;
1262 
1263  SCIP_Bool success;
1264 
1265  assert(heur != NULL);
1266  assert(scip != NULL);
1267  assert(result != NULL);
1268 
1269  /* get heuristic's data */
1270  heurdata = SCIPheurGetData(heur);
1271  assert(heurdata != NULL);
1272 
1273  *result = SCIP_DELAYED;
1274 
1275  /* only call heuristic, if feasible solution is available */
1276  if( SCIPgetNSols(scip) <= 0 )
1277  return SCIP_OKAY;
1278 
1279  /* in case of many unsuccessful calls, the nextnodenumber is increased to prevent us from running too often */
1280  if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
1281  return SCIP_OKAY;
1282 
1283  /* only call heuristic, if the best solution comes from transformed problem */
1284  assert(SCIPgetBestSol(scip) != NULL);
1285  if( SCIPsolIsOriginal(SCIPgetBestSol(scip)) )
1286  return SCIP_OKAY;
1287 
1288  /* only call heuristic, if enough nodes were processed since last incumbent */
1289  if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip,SCIPgetBestSol(scip)) < heurdata->nwaitingnodes )
1290  return SCIP_OKAY;
1291 
1292  *result = SCIP_DIDNOTRUN;
1293 
1294  /* only call heuristic, if discrete variables are present */
1295  if( SCIPgetNBinVars(scip) == 0 && SCIPgetNIntVars(scip) == 0 )
1296  return SCIP_OKAY;
1297 
1298  if( SCIPisStopped(scip) )
1299  return SCIP_OKAY;
1300 
1301  runagain = TRUE;
1302 
1303  /* determine solving limits for the sub-SCIP for the first time */
1304  SCIP_CALL( determineLimits(scip, heur, &solvelimits, &runagain) );
1305 
1306  if( ! runagain )
1307  return SCIP_OKAY;
1308 
1309  *result = SCIP_DIDNOTFIND;
1310 
1311  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
1312  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nvars) );
1313  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nvars) );
1314 
1315  /* only create a rolling horizon data structure if we need to keep it */
1316  if( heurdata->userollinghorizon )
1317  SCIP_CALL( rollingHorizonCreate(scip, &rollinghorizon) );
1318  else
1319  rollinghorizon = NULL;
1320 
1321  do
1322  {
1323  /* create a new problem, by fixing all variables except for a small neighborhood */
1324  SCIP_CALL( determineVariableFixings(scip, fixedvars, fixedvals, &nfixedvars, heurdata, rollinghorizon, &success) );
1325 
1326  /* terminate if it was not possible to create the subproblem */
1327  if( !success )
1328  {
1329  SCIPdebugMsg(scip, "Could not create the subproblem -> skip call\n");
1330 
1331  /* do not count this as a call to the heuristic */
1332  *result = SCIP_DIDNOTRUN;
1333 
1334  /* count this as a failure and increase the number of waiting nodes until the next call */
1335  updateFailureStatistic(scip, heurdata);
1336  goto TERMINATE;
1337  }
1338 
1339  /* initializing the subproblem */
1340  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
1341  SCIP_CALL( SCIPcreate(&subscip) );
1342  ++heurdata->nsubmips;
1343 
1344  /* create the variable mapping hash map */
1345  SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
1346 
1347  /* create a problem copy as sub SCIP */
1348  SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "gins", fixedvars, fixedvals, nfixedvars,
1349  heurdata->uselprows, heurdata->copycuts, &success, NULL) );
1350 
1351  for( i = 0; i < nvars; i++ )
1352  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
1353 
1354  /* free hash map */
1355  SCIPhashmapFree(&varmapfw);
1356 
1357  /* set up limits for the subproblem */
1358  SCIP_CALL( setupSubScip(scip, subscip, &solvelimits, heur) );
1359 
1360  /* solve the subproblem */
1361  SCIPdebugMsg(scip, "Solve Gins subMIP\n");
1362 
1363  /* Errors in solving the subproblem should not kill the overall solving process
1364  * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop.
1365  */
1366  SCIP_CALL_ABORT( SCIPsolve(subscip) );
1367 
1368  /* transfer variable statistics from sub-SCIP */
1369  SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
1370 
1371  heurdata->usednodes += SCIPgetNNodes(subscip);
1372 
1373  /* check, whether a solution was found */
1374  if( SCIPgetNSols(subscip) > 0 )
1375  {
1376  SCIP_SOL** subsols;
1377  int nsubsols;
1378 
1379  /* check, whether a solution was found;
1380  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted
1381  */
1382  nsubsols = SCIPgetNSols(subscip);
1383  subsols = SCIPgetSols(subscip);
1384  success = FALSE;
1385  for( i = 0; i < nsubsols && !success; ++i )
1386  {
1387  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &success) );
1388  }
1389  if( success )
1390  *result = SCIP_FOUNDSOL;
1391  }
1392 
1393  /* free subproblem */
1394  SCIPfreeBufferArray(scip, &subvars);
1395  SCIP_CALL( SCIPfree(&subscip) );
1396 
1397  /* check if we want to run another rolling horizon iteration */
1398  runagain = (*result == SCIP_FOUNDSOL) && heurdata->userollinghorizon;
1399  if( runagain )
1400  {
1401  assert(rollinghorizon != NULL);
1402  SCIP_CALL( determineLimits(scip, heur, &solvelimits, &runagain ) );
1403  runagain = runagain && rollingHorizonRunAgain(scip, rollinghorizon, heurdata);
1404  }
1405 
1406  } while( runagain );
1407 
1408  /* delay the heuristic in case it was not successful */
1409  if( *result != SCIP_FOUNDSOL )
1410  updateFailureStatistic(scip, heurdata);
1411 
1412 TERMINATE:
1413 
1414  /* only free the rolling horizon data structure if we need to keep it */
1415  if( heurdata->userollinghorizon )
1416  {
1417  SCIP_CALL( rollingHorizonFree(scip, &rollinghorizon) );
1418  }
1419 
1420  SCIPfreeBufferArray(scip, &fixedvals);
1421  SCIPfreeBufferArray(scip, &fixedvars);
1422 
1423  return SCIP_OKAY;
1424 }
1425 
1426 /*
1427  * primal heuristic specific interface methods
1428  */
1429 
1430 /** creates the gins primal heuristic and includes it in SCIP */
1432  SCIP* scip /**< SCIP data structure */
1433  )
1434 {
1435  SCIP_HEURDATA* heurdata;
1436  SCIP_HEUR* heur;
1437 
1438  /* create Gins primal heuristic data */
1439  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1440  heurdata->randnumgen = NULL;
1441 
1442  /* include primal heuristic */
1443  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1445  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecGins, heurdata) );
1446 
1447  assert(heur != NULL);
1448 
1449  /* set non-NULL pointers to callback methods */
1450  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyGins) );
1451  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeGins) );
1452  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitGins) );
1453  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitGins) );
1454 
1455  /* add gins primal heuristic parameters */
1456  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1457  "number of nodes added to the contingent of the total nodes",
1458  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0, INT_MAX, NULL, NULL) );
1459 
1460  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1461  "maximum number of nodes to regard in the subproblem",
1462  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0, INT_MAX, NULL, NULL) );
1463 
1464  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1465  "minimum number of nodes required to start the subproblem",
1466  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0, INT_MAX, NULL, NULL) );
1467 
1468  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
1469  "number of nodes without incumbent change that heuristic should wait",
1470  &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0, INT_MAX, NULL, NULL) );
1471 
1472  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1473  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1474  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1475 
1476  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1477  "percentage of integer variables that have to be fixed",
1478  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, SCIPsumepsilon(scip), 1.0-SCIPsumepsilon(scip), NULL, NULL) );
1479 
1480  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1481  "factor by which " HEUR_NAME " should at least improve the incumbent",
1482  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1483 
1484  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
1485  "should subproblem be created out of the rows in the LP rows?",
1486  &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
1487 
1488  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1489  "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
1490  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1491 
1492  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/fixcontvars",
1493  "should continuous variables outside the neighborhoods be fixed?",
1494  &heurdata->fixcontvars, TRUE, DEFAULT_FIXCONTVARS, NULL, NULL) );
1495 
1496  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/bestsollimit",
1497  "limit on number of improving incumbent solutions in sub-CIP",
1498  &heurdata->bestsollimit, FALSE, DEFAULT_BESTSOLLIMIT, -1, INT_MAX, NULL, NULL) );
1499 
1500  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxdistance",
1501  "maximum distance to selected variable to enter the subproblem, or -1 to select the distance "
1502  "that best approximates the minimum fixing rate from below",
1503  &heurdata->maxdistance, FALSE, DEFAULT_MAXDISTANCE, -1, INT_MAX, NULL, NULL) );
1504 
1505  SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/potential",
1506  "the reference point to compute the neighborhood potential: (r)oot or (p)seudo solution",
1507  &heurdata->potential, TRUE, DEFAULT_POTENTIAL, "pr", NULL, NULL) );
1508 
1509  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/userollinghorizon",
1510  "should the heuristic solve a sequence of sub-MIP's around the first selected variable",
1511  &heurdata->userollinghorizon, TRUE, DEFAULT_USEROLLINGHORIZON, NULL, NULL) );
1512 
1513  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/relaxdenseconss",
1514  "should dense constraints (at least as dense as 1 - minfixingrate) be ignored by connectivity graph?",
1515  &heurdata->relaxdenseconss, TRUE, DEFAULT_RELAXDENSECONSS, NULL, NULL) );
1516 
1517  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rollhorizonlimfac",
1518  "limiting percentage for variables already used in sub-SCIPs to terminate rolling horizon approach",
1519  &heurdata->rollhorizonlimfac, TRUE, DEFAULT_ROLLHORIZONLIMFAC, 0.0, 1.0, NULL, NULL) );
1520 
1521  return SCIP_OKAY;
1522 }
SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
Definition: sol.c:2465
static SCIP_Real heurdataAvgDiscreteNeighborhoodSize(SCIP_HEURDATA *heurdata)
Definition: heur_gins.c:499
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
Definition: scip.c:48626
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
static SCIP_RETCODE rollingHorizonCreate(SCIP *scip, ROLLINGHORIZON **rollinghorizon)
Definition: heur_gins.c:202
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:46306
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5158
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
SCIP_RETCODE SCIPincludeHeurGins(SCIP *scip)
Definition: heur_gins.c:1436
static void rollingHorizonStoreDistances(SCIP *scip, ROLLINGHORIZON *rollinghorizon, int *distances)
Definition: heur_gins.c:266
static SCIP_DECL_HEURCOPY(heurCopyGins)
Definition: heur_gins.c:1155
#define DEFAULT_MAXDISTANCE
Definition: heur_gins.c:75
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
#define HEUR_FREQ
Definition: heur_gins.c:53
#define DEFAULT_NODESOFS
Definition: heur_gins.c:59
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4489
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1344
void SCIPvariableGraphFree(SCIP *scip, SCIP_VGRAPH **vargraph)
Definition: heur.c:1776
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed)
Definition: scip.c:48608
#define SCIPallocClearBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22591
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:8177
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47088
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12252
static SCIP_RETCODE selectNextVariable(SCIP *scip, SCIP_HEURDATA *heurdata, ROLLINGHORIZON *rollinghorizon, int *distances, SCIP_VAR **selvar, int *selvarmaxdistance)
Definition: heur_gins.c:698
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12758
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11686
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39832
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
static SCIP_RETCODE determineVariableFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixings, SCIP_HEURDATA *heurdata, ROLLINGHORIZON *rollinghorizon, SCIP_Bool *success)
Definition: heur_gins.c:775
static SCIP_RETCODE setLimits(SCIP *subscip, SOLVELIMITS *solvelimits)
Definition: heur_gins.c:936
#define TRUE
Definition: def.h:63
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5132
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9269
#define DEFAULT_MAXNODES
Definition: heur_gins.c:60
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
#define DEFAULT_MINFIXINGRATE
Definition: heur_gins.c:63
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define HEUR_DISPCHAR
Definition: heur_gins.c:51
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
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:8084
SCIP_Real timelimit
Definition: heur_alns.c:405
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:9366
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
#define SCIP_LONGINT_MAX
Definition: def.h:135
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:748
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1119
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
static SCIP_RETCODE determineMaxDistance(SCIP *scip, SCIP_HEURDATA *heurdata, int *distances, int *choosevardistance)
Definition: heur_gins.c:443
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4804
#define SCIPdebugMsg
Definition: scip.h:455
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:4265
#define DEFAULT_ROLLHORIZONLIMFAC
Definition: heur_gins.c:83
int lastmaxdistance
Definition: heur_gins.c:103
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_RETCODE SCIPvariableGraphCreate(SCIP *scip, SCIP_VGRAPH **vargraph, SCIP_Bool relaxdenseconss, SCIP_Real relaxdensity, int *nrelaxedconstraints)
Definition: heur.c:1738
SCIP_Real memorylimit
Definition: heur_alns.c:404
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:16115
#define HEUR_NAME
Definition: heur_gins.c:49
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
#define DEFAULT_FIXCONTVARS
Definition: heur_gins.c:73
#define DEFAULT_USEROLLINGHORIZON
Definition: heur_gins.c:82
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4401
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8145
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38948
static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_gins.c:1108
SCIP_VGRAPH * variablegraph
Definition: heur_gins.c:98
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4630
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition: scip.c:2428
LNS heuristic that tries to delimit the search region to a neighborhood in the constraint graph...
static SCIP_RETCODE setupSubScip(SCIP *scip, SCIP *subscip, SOLVELIMITS *solvelimits, SCIP_HEUR *heur)
Definition: heur_gins.c:953
#define DEFAULT_RELAXDENSECONSS
Definition: heur_gins.c:79
#define REALABS(x)
Definition: def.h:173
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
#define HEUR_FREQOFS
Definition: heur_gins.c:54
#define DEFAULT_POTENTIAL
Definition: heur_gins.c:74
static SCIP_DECL_HEURFREE(heurFreeGins)
Definition: heur_gins.c:1169
#define DEFAULT_NODESQUOT
Definition: heur_gins.c:64
SCIP_Longint nodelimit
Definition: heur_alns.c:403
void SCIPverbMessage(SCIP *scip, SCIP_VERBLEVEL msgverblevel, FILE *file, const char *formatstr,...)
Definition: scip.c:1360
static SCIP_DECL_HEUREXEC(heurExecGins)
Definition: heur_gins.c:1250
SCIP_Bool SCIPsortedvecFindInt(int *intarray, int val, int len, int *pos)
#define DEFAULT_BESTSOLLIMIT
Definition: heur_gins.c:72
#define DEFAULT_MINNODES
Definition: heur_gins.c:62
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
#define DEFAULT_USELPROWS
Definition: heur_gins.c:66
public data structures and miscellaneous methods
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPvariablegraphBreadthFirst(SCIP *scip, SCIP_VGRAPH *vargraph, SCIP_VAR **startvars, int nstartvars, int *distances, int maxdistance, int maxvars, int maxbinintvars)
Definition: heur.c:1435
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11246
#define DEFAULT_COPYCUTS
Definition: heur_gins.c:69
static SCIP_RETCODE selectInitialVariable(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VGRAPH *vargraph, int *distances, SCIP_VAR **selvar, int *selvarmaxdistance)
Definition: heur_gins.c:508
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPtrySolFree(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:40794
static SCIP_Bool rollingHorizonRunAgain(SCIP *scip, ROLLINGHORIZON *rollinghorizon, SCIP_HEURDATA *heurdata)
Definition: heur_gins.c:249
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4688
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
#define HEUR_PRIORITY
Definition: heur_gins.c:52
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip.c:4862
#define HEUR_TIMING
Definition: heur_gins.c:56
#define SCIP_REAL_MIN
Definition: def.h:151
static SCIP_DECL_HEURINIT(heurInitGins)
Definition: heur_gins.c:1189
static SCIP_RETCODE determineLimits(SCIP *scip, SCIP_HEUR *heur, SOLVELIMITS *solvelimits, SCIP_Bool *runagain)
Definition: heur_gins.c:1053
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:39882
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4349
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:46774
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, SCIP_Bool *success)
Definition: heur_gins.c:890
#define DEFAULT_MINIMPROVE
Definition: heur_gins.c:61
static SCIP_RETCODE fixNonNeighborhoodVariables(SCIP *scip, SCIP_HEURDATA *heurdata, ROLLINGHORIZON *rollinghorizon, SCIP_SOL *sol, SCIP_VAR **vars, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *distances, int maxdistance, int *nfixings)
Definition: heur_gins.c:370
int * distances
Definition: heur_gins.c:99
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:8161
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:46800
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8957
SCIP_RETCODE SCIPcopyLargeNeighborhoodSearch(SCIP *sourcescip, SCIP *subscip, SCIP_HASHMAP *varmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool uselprows, SCIP_Bool copycuts, SCIP_Bool *success, SCIP_Bool *valid)
Definition: heuristics.c:903
#define SCIPstatistic(x)
Definition: pub_message.h:101
#define SCIP_Real
Definition: def.h:149
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
void SCIPsortInt(int *intarray, int len)
static SCIP_DECL_HEUREXIT(heurExitGins)
Definition: heur_gins.c:1222
#define SCIP_Longint
Definition: def.h:134
static SCIP_Real getPotential(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL *sol, SCIP_VAR **vars, int nvars)
Definition: heur_gins.c:289
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38813
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47076
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46989
static SCIP_RETCODE rollingHorizonFree(SCIP *scip, ROLLINGHORIZON **rollinghorizon)
Definition: heur_gins.c:226
#define HEUR_MAXDEPTH
Definition: heur_gins.c:55
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8129
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:46429
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
#define DEFAULT_NWAITINGNODES
Definition: heur_gins.c:65
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1109
SCIP_Bool * used
Definition: heur_gins.c:101
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:42133
#define HEUR_DESC
Definition: heur_gins.c:50
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
static SCIP_Bool isVariableInNeighborhood(SCIP_VAR *var, int *distances, int maxdistance)
Definition: heur_gins.c:354
#define HEUR_USESSUBSCIP
Definition: heur_gins.c:57
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
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:4321
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5083
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4746
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:4239
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:780
#define DEFAULT_RANDSEED
Definition: heur_gins.c:78
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37878
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:39207