Scippy

SCIP

Solving Constraint Integer Programs

heur_crossover.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2016 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_crossover.c
17  * @brief crossover primal heuristic
18  * @author Timo Berthold
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include "scip/scip.h"
27 #include "scip/scipdefplugins.h"
28 #include "scip/cons_linear.h"
29 #include "scip/heur_crossover.h"
30 #include "scip/pub_misc.h"
31 
32 #define HEUR_NAME "crossover"
33 #define HEUR_DESC "LNS heuristic that fixes all variables that are identic in a couple of solutions"
34 #define HEUR_DISPCHAR 'C'
35 #define HEUR_PRIORITY -1104000
36 #define HEUR_FREQ 30
37 #define HEUR_FREQOFS 0
38 #define HEUR_MAXDEPTH -1
39 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
40 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
41 
42 #define DEFAULT_MAXNODES 5000LL /* maximum number of nodes to regard in the subproblem */
43 #define DEFAULT_MINIMPROVE 0.01 /* factor by which Crossover should at least improve the incumbent */
44 #define DEFAULT_MINNODES 50LL /* minimum number of nodes to regard in the subproblem */
45 #define DEFAULT_MINFIXINGRATE 0.666 /* minimum percentage of integer variables that have to be fixed */
46 #define DEFAULT_NODESOFS 500LL /* number of nodes added to the contingent of the total nodes */
47 #define DEFAULT_NODESQUOT 0.1 /* subproblem nodes in relation to nodes of the original problem */
48 #define DEFAULT_LPLIMFAC 2.0 /* factor by which the limit on the number of LP depends on the node limit */
49 #define DEFAULT_NUSEDSOLS 3 /* number of solutions that will be taken into account */
50 #define DEFAULT_NWAITINGNODES 200LL /* number of nodes without incumbent change heuristic should wait */
51 #define DEFAULT_RANDOMIZATION TRUE /* should the choice which sols to take be randomized? */
52 #define DEFAULT_DONTWAITATROOT FALSE /* should the nwaitingnodes parameter be ignored at the root node? */
53 #define DEFAULT_USELPROWS FALSE /* should subproblem be created out of the rows in the LP rows,
54  * otherwise, the copy constructors of the constraints handlers are used */
55 #define DEFAULT_COPYCUTS TRUE /* if DEFAULT_USELPROWS is FALSE, then should all active cuts from the
56  * cutpool of the original scip be copied to constraints of the subscip
57  */
58 #define DEFAULT_PERMUTE FALSE /* should the subproblem be permuted to increase diversification? */
59 #define HASHSIZE_SOLS 11113 /* size of hash table for solution tuples in crossover heuristic */
60 
61 /* event handler properties */
62 #define EVENTHDLR_NAME "Crossover"
63 #define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
64 
65 /*
66  * Data structures
67  */
68 
69 typedef struct SolTuple SOLTUPLE;
70 
71 /** primal heuristic data */
72 struct SCIP_HeurData
73 {
74  SCIP_SOL* prevlastsol; /**< worst solution taken into account during the previous run */
75  SCIP_SOL* prevbestsol; /**< best solution during the previous run */
76  int prevnsols; /**< number of all solutions during the previous run */
77 
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 crossover in earlier calls */
82  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
83 
84  int nusedsols; /**< number of solutions that will be taken into account */
85  SCIP_Longint nwaitingnodes; /**< number of nodes without incumbent change heuristic should wait */
86  unsigned int nfailures; /**< number of failures since last successful call */
87  SCIP_Longint nextnodenumber; /**< number of nodes at which crossover should be called the next time */
88  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
89  SCIP_Real minimprove; /**< factor by which Crossover should at least improve the incumbent */
90  SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
91  SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
92  SCIP_Bool randomization; /**< should the choice which sols to take be randomized? */
93  SCIP_Bool dontwaitatroot; /**< should the nwaitingnodes parameter be ignored at the root node? */
94  unsigned int randseed; /**< seed value for random number generator */
95  SCIP_HASHTABLE* hashtable; /**< hashtable used to store the solution tuples already used */
96  SOLTUPLE* lasttuple; /**< last tuple of solutions created by crossover */
97  SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
98  SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
99  * to constraints in subproblem? */
100  SCIP_Bool permute; /**< should the subproblem be permuted to increase diversification? */
101 };
102 
103 /** n-tuple of solutions and their hashkey */
104 struct SolTuple
105 {
106  int* indices; /**< sorted array of solution indices */
107  int size; /**< size of the array (should be heurdata->nusedsols) */
108  unsigned int key; /**< hashkey of the tuple */
109  SOLTUPLE* prev; /**< previous solution tuple created */
110 };
111 
112 
113 /*
114  * Local methods
115  */
116 
117 
118 /** gets the hash key of a solution tuple */
119 static
120 SCIP_DECL_HASHGETKEY(hashGetKeySols)
121 { /*lint --e{715}*/
122  return elem;
123 }
124 
125 
126 /** returns TRUE iff both solution tuples are identical */
127 static
128 SCIP_DECL_HASHKEYEQ(hashKeyEqSols)
129 { /*lint --e{715}*/
130  int i;
131  int size;
132 
133  int* indices1;
134  int* indices2;
135 
136  indices1 = ((SOLTUPLE*)key1)->indices;
137  indices2 = ((SOLTUPLE*)key2)->indices;
138 
139  /* there should be two nonempty arrays of the same size */
140  assert(indices1 != NULL);
141  assert(indices2 != NULL);
142  assert(((SOLTUPLE*)key1)->size == ((SOLTUPLE*)key2)->size);
143 
144  size = ((SOLTUPLE*)key1)->size;
145 
146  /* compare arrays by components, return TRUE, iff equal */
147  for( i = 0; i < size; i++ )
148  {
149  if( indices1[i] != indices2[i] )
150  return FALSE;
151  }
152 
153  return TRUE;
154 }
155 
156 
157 /** returns hashkey of a solution tuple */
158 static
159 SCIP_DECL_HASHKEYVAL(hashKeyValSols)
160 { /*lint --e{715}*/
161  return ((SOLTUPLE*)key)->key;
162 }
163 
164 
165 /** calculates a hash key for a given tuple of solution indices */
166 static
167 unsigned int calculateHashKey(
168  int* indices, /**< indices of solutions */
169  int size /**< number of solutions */
170  )
171 {
172  int i;
173  unsigned int hashkey;
174 
175  /* hashkey should be (x1+1) * (x2+1) * ... * (xn+1) + x1 + x2 + ... + xn */
176  hashkey = 1;
177  for( i = 0; i < size; i++ )
178  hashkey *= indices[i] + 1;
179  for( i = 0; i < size; i++ )
180  hashkey += indices[i];
181 
182  return hashkey;
183 }
184 
185 
186 /** insertion sort for a small int array */
187 static void sortArray(
188  int* a, /**< array to be sorted */
189  int size /**< size of array */
190  )
191 {
192  int i;
193  int j;
194  int tmp;
195 
196  /* simple insertion sort algorithm */
197  for( i = 1; i < size; i++ )
198  {
199  tmp = a[i];
200  j = i-1;
201  while( j >= 0 && a[j] > tmp )
202  {
203  a[j+1] = a[j]; /*lint !e679*/
204  j = j-1;
205  }
206  a[j+1] = tmp; /*lint !e679*/
207  }
208 }
209 
210 
211 /** creates a new tuple of solutions */
212 static
214  SCIP* scip, /**< original SCIP data structure */
215  SOLTUPLE** elem, /**< tuple of solutions which should be created */
216  int* indices, /**< indices of solutions */
217  int size, /**< number of solutions */
218  SCIP_HEURDATA* heurdata /**< primal heuristic data */
219  )
220 {
221  /* memory allocation */
222  SCIP_CALL( SCIPallocBlockMemory(scip, elem) );
223  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*elem)->indices, size) );
224  BMScopyMemoryArray((*elem)->indices, indices, size);
225 
226  /* data input */
227  sortArray(indices,size);
228  (*elem)->size = size;
229  (*elem)->key = calculateHashKey((*elem)->indices, (*elem)->size);
230  (*elem)->prev = heurdata->lasttuple;
231 
232  /* update heurdata */
233  heurdata->lasttuple = *elem;
234  return SCIP_OKAY;
235 }
236 
237 
238 /** checks whether the new solution was found at the same node by the same heuristic as an already selected one */
239 static
241  SCIP_SOL** sols, /**< feasible SCIP solutions */
242  int* selection, /**< pool of solutions crossover uses */
243  int selectionsize, /**< size of solution pool */
244  int newsol /**< candidate solution */
245  )
246 {
247  int i;
248 
249  for( i = 0; i < selectionsize; i++ )
250  {
251  if( SCIPsolGetHeur(sols[selection[i]]) == SCIPsolGetHeur(sols[newsol])
252  && SCIPsolGetNodenum(sols[selection[i]]) == SCIPsolGetNodenum(sols[newsol]) )
253  return FALSE;
254  }
255 
256  return TRUE;
257 }
258 
259 /** randomly selects the solutions crossover will use from the pool of all solutions found so far */
260 static
262  SCIP* scip, /**< original SCIP data structure */
263  int* selection, /**< pool of solutions crossover uses */
264  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
265  SCIP_Bool* success /**< pointer to store whether the process was successful */
266  )
267 {
268  int i;
269  int j;
270  int lastsol; /* the worst solution possible to choose */
271  int nusedsols; /* number of solutions which will be chosen */
272 
273  SOLTUPLE* elem;
274  SCIP_SOL** sols;
275 
276  assert( success != NULL );
277 
278  /* initialization */
279  nusedsols = heurdata->nusedsols;
280  lastsol = SCIPgetNSols(scip);
281  sols = SCIPgetSols(scip);
282  assert(nusedsols < lastsol);
283 
284  i = 0;
285  *success = FALSE;
286 
287  /* perform at maximum 10 restarts and stop as soon as a new set of solutions is found */
288  while( !*success && i < 10 )
289  {
290  SCIP_Bool validtuple;
291 
292  validtuple = TRUE;
293  for( j = 0; j < nusedsols && validtuple; j++ )
294  {
295  int k;
296  k = SCIPgetRandomInt(nusedsols-j-1, lastsol-1, &heurdata->randseed);
297 
298  /* ensure that the solution does not have a similar source as the others */
299  while( k >= nusedsols-j-1 && !solHasNewSource(sols, selection, j, k) )
300  k--;
301 
302  validtuple = (k >= nusedsols-j-1);
303  selection[j] = k;
304  lastsol = k;
305  }
306 
307  if( validtuple )
308  {
309  /* creates an object ready to be inserted into the hashtable */
310  SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
311 
312  /* check whether the randomized set is already in the hashtable, if not, insert it */
313  if( !SCIPhashtableExists(heurdata->hashtable, elem) )
314  {
315  SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
316  *success = TRUE;
317  }
318  }
319  i++;
320  }
321 
322  return SCIP_OKAY;
323 }
324 
325 
326 /** creates the all variables of the subproblem */
328  SCIP* scip, /**< original SCIP data structure */
329  SCIP* subscip, /**< SCIP data structure for the subproblemd */
330  SCIP_VAR** subvars, /**< the variables of the subproblem */
331  int* selection, /**< pool of solutions crossover will use */
332  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
333  SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
334  )
335 {
336  SCIP_VAR** vars; /* original scip variables */
337  SCIP_SOL** sols; /* pool of solutions */
338  SCIP_Real fixingrate; /* percentage of variables that are fixed */
339 
340  int nvars;
341  int nbinvars;
342  int nintvars;
343 
344  int i;
345  int j;
346  int fixingcounter = 0;
347 
348  sols = SCIPgetSols(scip);
349  assert(sols != NULL);
350 
351  /* get required data of the original problem */
352  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
353 
354  /* create the binary and general integer variables of the subproblem */
355  for( i = 0; i < nbinvars + nintvars; i++ )
356  {
357  SCIP_Real solval;
358  SCIP_Bool fixable;
359 
360  fixable = TRUE;
361  solval = SCIPgetSolVal(scip, sols[selection[0]], vars[i]);
362 
363  /* check, whether variable's value is identical for each selected solution */
364  for( j = 1; j < heurdata->nusedsols; j++ )
365  {
366  SCIP_Real varsolval;
367  varsolval = SCIPgetSolVal(scip, sols[selection[j]], vars[i]);
368  if( REALABS(solval - varsolval) > 0.5 )
369  {
370  fixable = FALSE;
371  break;
372  }
373  }
374 
375  /* original solval can be outside transformed global bounds */
376  fixable = fixable && SCIPvarGetLbGlobal(vars[i]) <= solval && solval <= SCIPvarGetUbGlobal(vars[i]);
377 
378  /* if solutions' values are equal, variable is fixed in the subproblem */
379  if( fixable )
380  {
381  SCIP_CALL( SCIPchgVarLbGlobal(subscip, subvars[i], solval) );
382  SCIP_CALL( SCIPchgVarUbGlobal(subscip, subvars[i], solval) );
383  fixingcounter++;
384  }
385  }
386 
387  fixingrate = (SCIP_Real)fixingcounter / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
388 
389  /* if all variables were fixed or amount of fixed variables is insufficient, skip residual part of
390  * subproblem creation and abort immediately */
391  *success = fixingcounter < nbinvars + nintvars && fixingrate >= heurdata->minfixingrate;
392 
393  return SCIP_OKAY;
394 }
395 
396 /** creates the rows of the subproblem */
397 static
399  SCIP* scip, /**< original SCIP data structure */
400  SCIP* subscip, /**< SCIP data structure for the subproblem */
401  SCIP_VAR** subvars /**< the variables of the subproblem */
402  )
403 {
404  SCIP_ROW** rows; /* original scip rows */
405  SCIP_CONS* cons; /* new constraint */
406  SCIP_VAR** consvars; /* new constraint's variables */
407  SCIP_COL** cols; /* original row's columns */
408 
409  SCIP_Real constant; /* constant added to the row */
410  SCIP_Real lhs; /* left hand side of the row */
411  SCIP_Real rhs; /* left right side of the row */
412  SCIP_Real* vals; /* variables' coefficient values of the row */
413 
414  int nrows;
415  int nnonz;
416  int i;
417  int j;
418 
419  /* get the rows and their number */
420  SCIP_CALL( SCIPgetLPRowsData(scip, &rows, &nrows) );
421 
422  /* copy all rows to linear constraints */
423  for( i = 0; i < nrows; i++ )
424  {
425  /* ignore rows that are only locally valid */
426  if( SCIProwIsLocal(rows[i]) )
427  continue;
428 
429  /* get the row's data */
430  constant = SCIProwGetConstant(rows[i]);
431  lhs = SCIProwGetLhs(rows[i]) - constant;
432  rhs = SCIProwGetRhs(rows[i]) - constant;
433  vals = SCIProwGetVals(rows[i]);
434  nnonz = SCIProwGetNNonz(rows[i]);
435  cols = SCIProwGetCols(rows[i]);
436 
437  assert(lhs <= rhs);
438 
439  /* allocate memory array to be filled with the corresponding subproblem variables */
440  SCIP_CALL( SCIPallocBufferArray(scip, &consvars, nnonz) );
441  for( j = 0; j < nnonz; j++ )
442  consvars[j] = subvars[SCIPvarGetProbindex(SCIPcolGetVar(cols[j]))];
443 
444  /* create a new linear constraint and add it to the subproblem */
445  SCIP_CALL( SCIPcreateConsLinear(subscip, &cons, SCIProwGetName(rows[i]), nnonz, consvars, vals, lhs, rhs,
446  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE) );
447  SCIP_CALL( SCIPaddCons(subscip, cons) );
448  SCIP_CALL( SCIPreleaseCons(subscip, &cons) );
449 
450  /* free temporary memory */
451  SCIPfreeBufferArray(scip, &consvars);
452  }
453 
454  return SCIP_OKAY;
455 }
456 
457 /** creates a subproblem for subscip by fixing a number of variables */
458 static
460  SCIP* scip, /**< original SCIP data structure */
461  SCIP* subscip, /**< SCIP data structure for the subproblem */
462  SCIP_VAR** subvars, /**< the variables of the subproblem */
463  int* selection, /**< pool of solutions crossover will use */
464  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
465  SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
466  )
467 {
468  SCIP_SOL** sols; /* array of all solutions found so far */
469  int nsols; /* number of all solutions found so far */
470  int nusedsols; /* number of solutions to use in crossover */
471  int i;
472 
473  /* get solutions' data */
474  nsols = SCIPgetNSols(scip);
475  sols = SCIPgetSols(scip);
476  nusedsols = heurdata->nusedsols;
477 
478  assert(nusedsols > 1);
479  assert(nsols >= nusedsols);
480 
481  /* use nusedsols best solutions if randomization is deactivated or there are only nusedsols solutions at hand
482  * or a good new solution was found since last call */
483  if( !heurdata->randomization || nsols == nusedsols || heurdata->prevlastsol != sols[nusedsols-1] )
484  {
485  SOLTUPLE* elem;
486  SCIP_HEUR* solheur;
487  SCIP_Longint solnodenum;
488  SCIP_Bool allsame;
489 
490  for( i = 0; i < nusedsols; i++ )
491  selection[i] = i;
492  SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
493 
494  solheur = SCIPsolGetHeur(sols[0]);
495  solnodenum = SCIPsolGetNodenum(sols[0]);
496  allsame = TRUE;
497 
498  /* check, whether all solutions have been found by the same heuristic at the same node; in this case we do not run
499  * crossover, since it would probably just optimize over the same space as the other heuristic
500  */
501  for( i = 1; i < nusedsols; i++ )
502  {
503  if( SCIPsolGetHeur(sols[i]) != solheur || SCIPsolGetNodenum(sols[i]) != solnodenum )
504  allsame = FALSE;
505  }
506  *success = !allsame && !SCIPhashtableExists(heurdata->hashtable, elem);
507 
508  /* check, whether solution tuple has already been tried */
509  if( !SCIPhashtableExists(heurdata->hashtable, elem) )
510  {
511  SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
512  }
513 
514  /* if solution tuple has already been tried, randomization is allowed and enough solutions are at hand, try
515  * to randomize another tuple. E.g., this can happen if the last crossover solution was among the best ones */
516  if( !(*success) && heurdata->randomization && nsols > nusedsols )
517  {
518  SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
519  }
520 
521  }
522  /* otherwise randomize the set of solutions */
523  else
524  {
525  SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
526  }
527 
528  /* no acceptable solution tuple could be created */
529  if( !(*success) )
530  return SCIP_OKAY;
531 
532  /* set up the variables of the subproblem */
533  SCIP_CALL( fixVariables(scip, subscip, subvars, selection, heurdata, success) );
534 
535  /* we copy the rows of the LP, if the enough variables could be fixed and we work on the MIP
536  relaxation of the problem */
537  if( *success && heurdata->uselprows )
538  {
539  SCIP_CALL( createRows(scip, subscip, subvars) );
540  }
541 
542  return SCIP_OKAY;
543 }
544 
545 
546 /** creates a new solution for the original problem by copying the solution of the subproblem */
547 static
549  SCIP* scip, /**< original SCIP data structure */
550  SCIP* subscip, /**< SCIP structure of the subproblem */
551  SCIP_VAR** subvars, /**< the variables of the subproblem */
552  SCIP_HEUR* heur, /**< crossover heuristic structure */
553  SCIP_SOL* subsol, /**< solution of the subproblem */
554  int* solindex, /**< index of the solution */
555  SCIP_Bool* success /**< used to store whether new solution was found or not */
556  )
557 {
558  SCIP_VAR** vars; /* the original problem's variables */
559  int nvars;
560  SCIP_SOL* newsol; /* solution to be created for the original problem */
561  SCIP_Real* subsolvals; /* solution values of the subproblem */
562 
563  assert(scip != NULL);
564  assert(subscip != NULL);
565  assert(subvars != NULL);
566  assert(subsol != NULL);
567 
568  /* get variables' data */
569  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
570  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
571  * since constraint copying may have required the copy of variables that are fixed in the main SCIP */
572  assert(nvars <= SCIPgetNOrigVars(subscip));
573 
574  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
575 
576  /* copy the solution */
577  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
578 
579  /* create new solution for the original problem */
580  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
581  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
582  *solindex = SCIPsolGetIndex(newsol);
583 
584  /* try to add new solution to scip and free it immediately */
585  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, TRUE, TRUE, TRUE, success) );
586 
587  SCIPfreeBufferArray(scip, &subsolvals);
588 
589  return SCIP_OKAY;
590 }
591 
592 /** updates heurdata after a run of crossover */
593 static
595  SCIP* scip, /**< original SCIP data structure */
596  SCIP_HEURDATA* heurdata /**< primal heuristic data */
597  )
598 {
599  /* increase number of failures, calculate next node at which crossover should be called and update actual solutions */
600  heurdata->nfailures++;
601  heurdata->nextnodenumber = (heurdata->nfailures <= 25
602  ? SCIPgetNNodes(scip) + 100*(2LL << heurdata->nfailures) /*lint !e703*/
603  : SCIP_LONGINT_MAX);
604 }
605 
606 /* ---------------- Callback methods of event handler ---------------- */
607 
608 /* exec the event handler
609  *
610  * we interrupt the solution process
611  */
612 static
613 SCIP_DECL_EVENTEXEC(eventExecCrossover)
614 {
615  SCIP_HEURDATA* heurdata;
616 
617  assert(eventhdlr != NULL);
618  assert(eventdata != NULL);
619  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
620  assert(event != NULL);
621  assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_LPSOLVED);
622 
623  heurdata = (SCIP_HEURDATA*)eventdata;
624  assert(heurdata != NULL);
625 
626  /* interrupt solution process of sub-SCIP */
627  if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
628  {
629  SCIPdebugMessage("interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
631  }
632 
633  return SCIP_OKAY;
634 }
635 
636 /*
637  * Callback methods of primal heuristic
638  */
639 
640 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
641 static
642 SCIP_DECL_HEURCOPY(heurCopyCrossover)
643 { /*lint --e{715}*/
644  assert(scip != NULL);
645  assert(heur != NULL);
646  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
647 
648  /* call inclusion method of primal heuristic */
650 
651  return SCIP_OKAY;
652 }
653 
654 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
655 static
656 SCIP_DECL_HEURFREE(heurFreeCrossover)
657 { /*lint --e{715}*/
658  SCIP_HEURDATA* heurdata;
659 
660  assert(heur != NULL);
661  assert(scip != NULL);
662 
663  /* get heuristic data */
664  heurdata = SCIPheurGetData(heur);
665  assert(heurdata != NULL);
666 
667  /* free heuristic data */
668  SCIPfreeMemory(scip, &heurdata);
669  SCIPheurSetData(heur, NULL);
670 
671  return SCIP_OKAY;
672 }
673 
674 /** initialization method of primal heuristic (called after problem was transformed) */
675 static
676 SCIP_DECL_HEURINIT(heurInitCrossover)
677 { /*lint --e{715}*/
678  SCIP_HEURDATA* heurdata;
679 
680  assert(heur != NULL);
681  assert(scip != NULL);
682 
683  /* get heuristic's data */
684  heurdata = SCIPheurGetData(heur);
685  assert(heurdata != NULL);
686 
687  /* initialize data */
688  heurdata->usednodes = 0;
689  heurdata->prevlastsol = NULL;
690  heurdata->prevbestsol = NULL;
691  heurdata->randseed = 0;
692  heurdata->lasttuple = NULL;
693  heurdata->nfailures = 0;
694  heurdata->prevnsols = 0;
695  heurdata->nextnodenumber = 0;
696 
697  /* initialize hash table */
698  SCIP_CALL( SCIPhashtableCreate(&heurdata->hashtable, SCIPblkmem(scip), HASHSIZE_SOLS,
699  hashGetKeySols, hashKeyEqSols, hashKeyValSols, NULL) );
700  assert(heurdata->hashtable != NULL);
701 
702  return SCIP_OKAY;
703 }
704 
705 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
706 static
707 SCIP_DECL_HEUREXIT(heurExitCrossover)
708 { /*lint --e{715}*/
709  SCIP_HEURDATA* heurdata;
710  SOLTUPLE* soltuple;
711 
712  assert(heur != NULL);
713  assert(scip != NULL);
714 
715  /* get heuristic data */
716  heurdata = SCIPheurGetData(heur);
717  assert(heurdata != NULL);
718  soltuple = heurdata->lasttuple;
719 
720  /* free all soltuples iteratively */
721  while( soltuple != NULL )
722  {
723  SOLTUPLE* tmp;
724  tmp = soltuple->prev;
725  SCIPfreeBlockMemoryArray(scip, &soltuple->indices, soltuple->size);
726  SCIPfreeBlockMemory(scip, &soltuple);
727  soltuple = tmp;
728  }
729 
730  /* free hash table */
731  assert(heurdata->hashtable != NULL);
732  SCIPhashtableFree(&heurdata->hashtable);
733 
734  return SCIP_OKAY;
735 }
736 
737 
738 /** execution method of primal heuristic */
739 static
740 SCIP_DECL_HEUREXEC(heurExecCrossover)
741 { /*lint --e{715}*/
742  SCIP_HEURDATA* heurdata; /* primal heuristic data */
743  SCIP* subscip; /* the subproblem created by crossover */
744  SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
745  SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
746 
747  SCIP_VAR** vars; /* original problem's variables */
748  SCIP_VAR** subvars; /* subproblem's variables */
749  SCIP_SOL** sols;
750 
751  SCIP_Real memorylimit; /* memory limit for the subproblem */
752  SCIP_Real timelimit; /* time limit for the subproblem */
753  SCIP_Real cutoff; /* objective cutoff for the subproblem */
754  SCIP_Real upperbound;
755  SCIP_Bool success;
756 
757  SCIP_Longint nstallnodes; /* node limit for the subproblem */
758 
759  int* selection; /* pool of solutions crossover uses */
760  int nvars; /* number of original problem's variables */
761  int nbinvars;
762  int nintvars;
763  int nusedsols;
764  int i;
765 
766  SCIP_RETCODE retcode;
767 
768  assert(heur != NULL);
769  assert(scip != NULL);
770  assert(result != NULL);
771 
772  /* get heuristic's data */
773  heurdata = SCIPheurGetData(heur);
774  assert(heurdata != NULL);
775  nusedsols = heurdata->nusedsols;
776 
777  *result = SCIP_DELAYED;
778 
779  /* only call heuristic, if enough solutions are at hand */
780  if( SCIPgetNSols(scip) < nusedsols )
781  return SCIP_OKAY;
782 
783  sols = SCIPgetSols(scip);
784  assert(sols != NULL);
785 
786  /* if one good solution was found, heuristic should not be delayed any longer */
787  if( sols[nusedsols-1] != heurdata->prevlastsol )
788  {
789  heurdata->nextnodenumber = SCIPgetNNodes(scip);
790  if( sols[0] != heurdata->prevbestsol )
791  heurdata->nfailures = 0;
792  }
793  /* in nonrandomized mode: only recall heuristic, if at least one new good solution was found in the meantime */
794  else if( !heurdata->randomization )
795  return SCIP_OKAY;
796 
797  /* if heuristic should be delayed, wait until certain number of nodes is reached */
798  if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
799  return SCIP_OKAY;
800 
801  /* only call heuristic, if enough nodes were processed since last incumbent */
802  if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip, SCIPgetBestSol(scip)) < heurdata->nwaitingnodes
803  && (SCIPgetDepth(scip) > 0 || !heurdata->dontwaitatroot) )
804  return SCIP_OKAY;
805 
806  *result = SCIP_DIDNOTRUN;
807 
808  /* calculate the maximal number of branching nodes until heuristic is aborted */
809  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
810 
811  /* reward Crossover if it succeeded often */
812  nstallnodes = (SCIP_Longint)
813  (nstallnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
814 
815  /* count the setup costs for the sub-MIP as 100 nodes */
816  nstallnodes -= 100 * SCIPheurGetNCalls(heur);
817  nstallnodes += heurdata->nodesofs;
818 
819  /* determine the node limit for the current process */
820  nstallnodes -= heurdata->usednodes;
821  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
822 
823  /* check whether we have enough nodes left to call subproblem solving */
824  if( nstallnodes < heurdata->minnodes )
825  return SCIP_OKAY;
826 
827  if( SCIPisStopped(scip) )
828  return SCIP_OKAY;
829 
830  *result = SCIP_DIDNOTFIND;
831 
832  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
833  assert(nvars > 0);
834 
835  /* check whether discrete variables are available */
836  if( nbinvars == 0 && nintvars == 0 )
837  return SCIP_OKAY;
838 
839  /* initializing the subproblem */
840  SCIP_CALL( SCIPcreate(&subscip) );
841 
842  /* create the variable mapping hash map */
843  SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), SCIPcalcHashtableSize(5 * nvars)) );
844  success = FALSE;
845 
846  eventhdlr = NULL;
847 
848  if( heurdata->uselprows )
849  {
850  char probname[SCIP_MAXSTRLEN];
851 
852  /* copy all plugins */
854 
855  /* get name of the original problem and add the string "_crossoversub" */
856  (void) SCIPsnprintf(probname, SCIP_MAXSTRLEN, "%s_crossoversub", SCIPgetProbName(scip));
857 
858  /* create the subproblem */
859  SCIP_CALL( SCIPcreateProb(subscip, probname, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
860 
861  /* copy all variables */
862  SCIP_CALL( SCIPcopyVars(scip, subscip, varmapfw, NULL, TRUE) );
863  }
864  else
865  {
866  SCIP_CALL( SCIPcopy(scip, subscip, varmapfw, NULL, "crossover", TRUE, FALSE, TRUE, &success) );
867 
868  if( heurdata->copycuts )
869  {
870  /* copies all active cuts from cutpool of sourcescip to linear constraints in targetscip */
871  SCIP_CALL( SCIPcopyCuts(scip, subscip, varmapfw, NULL, TRUE, NULL) );
872  }
873 
874  /* create event handler for LP events */
875  SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecCrossover, NULL) );
876  if( eventhdlr == NULL )
877  {
878  SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
879  return SCIP_PLUGINNOTFOUND;
880  }
881  }
882 
883  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
884  SCIP_CALL( SCIPallocBufferArray(scip, &selection, nusedsols) );
885 
886  for( i = 0; i < nvars; i++ )
887  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
888 
889  /* free hash map */
890  SCIPhashmapFree(&varmapfw);
891 
892  success = FALSE;
893 
894  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
895  /* create a new problem, which fixes variables with same value in a certain set of solutions */
896  SCIP_CALL( setupSubproblem(scip, subscip, subvars, selection, heurdata, &success) );
897 
898  heurdata->prevbestsol = SCIPgetBestSol(scip);
899  heurdata->prevlastsol = sols[heurdata->nusedsols-1];
900 
901  /* if creation of sub-SCIP was aborted (e.g. due to number of fixings), free sub-SCIP and abort */
902  if( !success )
903  {
904  *result = SCIP_DIDNOTRUN;
905 
906  /* this run will be counted as a failure since no new solution tuple could be generated or the neighborhood of the
907  * solution was not fruitful in the sense that it was too big
908  */
909  updateFailureStatistic(scip, heurdata);
910 
911  goto TERMINATE;
912  }
913 
914  /* do not abort subproblem on CTRL-C */
915  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
916 
917  /* disable output to console */
918 
919 #ifdef SCIP_DEBUG
920  /* for debugging crossover, enable MIP output */
921  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
922  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1) );
923 #endif
924 
925  /* check whether there is enough time and memory left */
926  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &timelimit) );
927  if( !SCIPisInfinity(scip, timelimit) )
928  timelimit -= SCIPgetSolvingTime(scip);
929  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &memorylimit) );
930 
931  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
932  if( !SCIPisInfinity(scip, memorylimit) )
933  {
934  memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
935  memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
936  }
937 
938  /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
939  if( timelimit <= 0.0 || memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
940  goto TERMINATE;
941 
942  /* disable statistic timing inside sub SCIP */
943  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
944 
945  /* set limits for the subproblem */
946  heurdata->nodelimit = nstallnodes;
947  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nstallnodes) );
948  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", timelimit) );
949  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", memorylimit) );
950 
951  /* forbid recursive call of heuristics and separators solving subMIPs */
952  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
953 
954  /* disable cutting plane separation */
956 
957  /* disable expensive presolving */
959 
960  /* use best estimate node selection */
961  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
962  {
963  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
964  }
965 
966  /* use inference branching */
967  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
968  {
969  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
970  }
971 
972  /* disable conflict analysis */
973  if( !SCIPisParamFixed(subscip, "conflict/useprop") )
974  {
975  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useprop", FALSE) );
976  }
977  if( !SCIPisParamFixed(subscip, "conflict/useinflp") )
978  {
979  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useinflp", FALSE) );
980  }
981  if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
982  {
983  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/useboundlp", FALSE) );
984  }
985  if( !SCIPisParamFixed(subscip, "conflict/usesb") )
986  {
987  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usesb", FALSE) );
988  }
989  if( !SCIPisParamFixed(subscip, "conflict/usepseudo") )
990  {
991  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/usepseudo", FALSE) );
992  }
993 
994  /* employ a limit on the number of enforcement rounds in the quadratic constraint handler; this fixes the issue that
995  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
996  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
997  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no deductions shall be
998  * made for the original SCIP
999  */
1000  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
1001  {
1002  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 500) );
1003  }
1004 
1005  /* add an objective cutoff */
1006  cutoff = SCIPinfinity(scip);
1008 
1009  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
1011  {
1012  cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
1013  }
1014  else
1015  {
1016  if( SCIPgetUpperbound ( scip ) >= 0 )
1017  cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
1018  else
1019  cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
1020  }
1021  cutoff = MIN(upperbound, cutoff );
1022  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
1023 
1024  /* permute the subproblem to increase diversification */
1025  if( heurdata->permute )
1026  {
1027  SCIP_CALL( SCIPpermuteProb(subscip, (unsigned int) SCIPheurGetNCalls(heur), TRUE, TRUE, TRUE, TRUE, TRUE) );
1028  }
1029 
1030  /* catch LP events of sub-SCIP */
1031  if( !heurdata->uselprows )
1032  {
1033  assert(eventhdlr != NULL);
1034 
1035  SCIP_CALL( SCIPtransformProb(subscip) );
1036  SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
1037  }
1038 
1039  /* solve the subproblem */
1040  SCIPdebugMessage("Solve Crossover subMIP\n");
1041  retcode = SCIPsolve(subscip);
1042 
1043  /* drop LP events of sub-SCIP */
1044  if( !heurdata->uselprows )
1045  {
1046  assert(eventhdlr != NULL);
1047 
1048  SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
1049  }
1050 
1051  /* Errors in solving the subproblem should not kill the overall solving process.
1052  * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
1053  if( retcode != SCIP_OKAY )
1054  {
1055 #ifndef NDEBUG
1056  SCIP_CALL( retcode );
1057 #endif
1058  SCIPwarningMessage(scip, "Error while solving subproblem in Crossover heuristic; sub-SCIP terminated with code <%d>\n", retcode);
1059  }
1060 
1061  /* print solving statistics of subproblem if we are in SCIP's debug mode */
1062  SCIPdebug( SCIP_CALL( SCIPprintStatistics(subscip, NULL) ) );
1063 
1064  heurdata->usednodes += SCIPgetNNodes(subscip);
1065 
1066  /* merge histories of the subscip-variables to the SCIP variables. */
1067  SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
1068  SCIPdebugMessage("Transferring variable histories complete\n");
1069 
1070  /* check, whether a solution was found */
1071  if( SCIPgetNSols(subscip) > 0 )
1072  {
1073  SCIP_SOL** subsols;
1074  int nsubsols;
1075  int solindex; /* index of the solution created by crossover */
1076 
1077  /* check, whether a solution was found;
1078  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */
1079  nsubsols = SCIPgetNSols(subscip);
1080  subsols = SCIPgetSols(subscip);
1081  success = FALSE;
1082  solindex = -1;
1083  for( i = 0; i < nsubsols && !success; ++i )
1084  {
1085  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &solindex, &success) );
1086  }
1087 
1088  if( success )
1089  {
1090  int tmp;
1091 
1092  assert(solindex != -1);
1093 
1094  *result = SCIP_FOUNDSOL;
1095 
1096  /* insert all crossings of the new solution and (nusedsols-1) of its parents into the hashtable
1097  * in order to avoid incest ;)
1098  */
1099  for( i = 0; i < nusedsols; i++ )
1100  {
1101  SOLTUPLE* elem;
1102  tmp = selection[i];
1103  selection[i] = solindex;
1104 
1105  SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
1106  SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
1107  selection[i] = tmp;
1108  }
1109 
1110  /* if solution was among the best ones, crossover should not be called until another good solution was found */
1111  if( !heurdata->randomization )
1112  {
1113  heurdata->prevbestsol = SCIPgetBestSol(scip);
1114  heurdata->prevlastsol = SCIPgetSols(scip)[heurdata->nusedsols-1];
1115  }
1116  }
1117 
1118  /* if solution is not better than incumbent or could not be added to problem => run is counted as a failure */
1119  if( !success || solindex != SCIPsolGetIndex(SCIPgetBestSol(scip)) )
1120  updateFailureStatistic(scip, heurdata);
1121  }
1122  else
1123  {
1124  /* if no new solution was found, run was a failure */
1125  updateFailureStatistic(scip, heurdata);
1126  }
1127 
1128  TERMINATE:
1129  /* free subproblem */
1130  SCIPfreeBufferArray(scip, &selection);
1131  SCIPfreeBufferArray(scip, &subvars);
1132  SCIP_CALL( SCIPfree(&subscip) );
1133 
1134  return SCIP_OKAY;
1135 }
1136 
1137 
1138 /*
1139  * primal heuristic specific interface methods
1140  */
1141 
1142 /** creates the crossover primal heuristic and includes it in SCIP */
1144  SCIP* scip /**< SCIP data structure */
1145  )
1146 {
1147  SCIP_HEURDATA* heurdata;
1148  SCIP_HEUR* heur;
1149 
1150  /* create Crossover primal heuristic data */
1151  SCIP_CALL( SCIPallocMemory(scip, &heurdata) );
1152 
1153  /* include primal heuristic */
1154  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1156  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecCrossover, heurdata) );
1157 
1158  assert(heur != NULL);
1159 
1160  /* set non-NULL pointers to callback methods */
1161  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyCrossover) );
1162  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeCrossover) );
1163  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitCrossover) );
1164  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitCrossover) );
1165 
1166  /* add crossover primal heuristic parameters */
1167 
1168  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1169  "number of nodes added to the contingent of the total nodes",
1170  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1171 
1172  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1173  "maximum number of nodes to regard in the subproblem",
1174  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1175 
1176  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1177  "minimum number of nodes required to start the subproblem",
1178  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1179 
1180  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nusedsols",
1181  "number of solutions to be taken into account",
1182  &heurdata->nusedsols, FALSE, DEFAULT_NUSEDSOLS, 2, INT_MAX, NULL, NULL) );
1183 
1184  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
1185  "number of nodes without incumbent change that heuristic should wait",
1186  &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1187 
1188  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1189  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1190  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1191 
1192  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1193  "minimum percentage of integer variables that have to be fixed",
1194  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1195 
1196  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1197  "factor by which Crossover should at least improve the incumbent",
1198  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1199 
1200  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
1201  "factor by which the limit on the number of LP depends on the node limit",
1202  &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
1203 
1204  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/randomization",
1205  "should the choice which sols to take be randomized?",
1206  &heurdata->randomization, TRUE, DEFAULT_RANDOMIZATION, NULL, NULL) );
1207 
1208  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/dontwaitatroot",
1209  "should the nwaitingnodes parameter be ignored at the root node?",
1210  &heurdata->dontwaitatroot, TRUE, DEFAULT_DONTWAITATROOT, NULL, NULL) );
1211 
1212  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
1213  "should subproblem be created out of the rows in the LP rows?",
1214  &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
1215 
1216  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1217  "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
1218  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1219 
1220  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/permute",
1221  "should the subproblem be permuted to increase diversification?",
1222  &heurdata->permute, TRUE, DEFAULT_PERMUTE, NULL, NULL) );
1223 
1224  return SCIP_OKAY;
1225 }
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:40329
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:5878
#define SCIPallocMemory(scip, ptr)
Definition: scip.h:20526
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:78
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2252
static SCIP_DECL_HASHKEYEQ(hashKeyEqSols)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:41648
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1147
#define HEUR_TIMING
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1567
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20573
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1273
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:7297
void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
Definition: scip.c:1248
#define SCIP_MAXSTRLEN
Definition: def.h:201
#define NULL
Definition: lpi_spx.cpp:130
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1125
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
Definition: lp.c:18915
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
Definition: lp.c:18861
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
static SCIP_DECL_HEURCOPY(heurCopyCrossover)
#define DEFAULT_NODESOFS
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, unsigned int timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:7252
SCIP_RETCODE SCIPpermuteProb(SCIP *scip, unsigned int randseed, SCIP_Bool permuteconss, SCIP_Bool permutebinvars, SCIP_Bool permuteintvars, SCIP_Bool permuteimplvars, SCIP_Bool permutecontvars)
Definition: scip.c:9660
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, int *solindex, SCIP_Bool *success)
#define FALSE
Definition: def.h:56
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:41009
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2057
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4046
#define DEFAULT_RANDOMIZATION
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:7778
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
#define DEFAULT_NUSEDSOLS
#define TRUE
Definition: def.h:55
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define SCIP_CALL(x)
Definition: def.h:266
static unsigned int calculateHashKey(int *indices, int size)
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:36299
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4109
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:20556
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3601
#define HEUR_FREQOFS
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:34983
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2116
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
Definition: lp.c:18881
#define DEFAULT_MAXNODES
#define SCIP_LONGINT_MAX
Definition: def.h:113
static SCIP_DECL_HASHGETKEY(hashGetKeySols)
static SCIP_DECL_EVENTEXEC(eventExecCrossover)
SCIP_RETCODE SCIPincludeHeurCrossover(SCIP *scip)
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:24949
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:20554
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:38393
static SCIP_DECL_HEURFREE(heurFreeCrossover)
SCIP_RETCODE SCIPhashtableCreate(SCIP_HASHTABLE **hashtable, BMS_BLKMEM *blkmem, int tablesize, SCIP_DECL_HASHGETKEY((*hashgetkey)), SCIP_DECL_HASHKEYEQ((*hashkeyeq)), SCIP_DECL_HASHKEYVAL((*hashkeyval)), void *userptr)
Definition: misc.c:1480
SCIP_RETCODE SCIPcopyCuts(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global, int *ncutsadded)
Definition: scip.c:2883
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:35668
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3547
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3573
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:11138
#define HEUR_NAME
static SCIP_DECL_HEUREXEC(heurExecCrossover)
#define SCIPfreeMemory(scip, ptr)
Definition: scip.h:20542
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:15442
SCIP_RETCODE SCIPcopy(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, const char *suffix, SCIP_Bool global, SCIP_Bool enablepricing, SCIP_Bool passmessagehdlr, SCIP_Bool *valid)
Definition: scip.c:3254
LNS heuristic that tries to combine several feasible solutions.
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:20049
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
Definition: lp.c:18925
#define DEFAULT_NODESQUOT
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition: scip.c:2260
#define DEFAULT_COPYCUTS
int SCIPcalcHashtableSize(int minsize)
Definition: misc.c:1157
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:34002
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:41353
SCIP_Bool SCIProwIsLocal(SCIP_ROW *row)
Definition: lp.c:19024
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2075
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4457
SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
Definition: scip.c:9019
SCIP_RETCODE SCIPgetLPRowsData(SCIP *scip, SCIP_ROW ***rows, int *nrows)
Definition: scip.c:26750
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:35020
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:41637
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:766
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:35717
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:37435
const char * SCIProwGetName(SCIP_ROW *row)
Definition: lp.c:18974
static SCIP_DECL_HEUREXIT(heurExitCrossover)
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip.c:12623
static SCIP_RETCODE createSolTuple(SCIP *scip, SOLTUPLE **elem, int *indices, int size, SCIP_HEURDATA *heurdata)
#define EVENTHDLR_DESC
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1068
#define HEUR_DISPCHAR
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:38534
public data structures and miscellaneous methods
static SCIP_RETCODE selectSolsRandomized(SCIP *scip, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
#define SCIP_Bool
Definition: def.h:53
SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:35279
#define HEUR_FREQ
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4001
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:3709
#define HASHSIZE_SOLS
#define DEFAULT_DONTWAITATROOT
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2232
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:4382
SCIP_RETCODE SCIPcopyVars(SCIP *sourcescip, SCIP *targetscip, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global)
Definition: scip.c:2179
struct SolTuple SOLTUPLE
#define MAX(x, y)
Definition: tclique_def.h:75
#define HEUR_MAXDEPTH
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:41396
static SCIP_DECL_HEURINIT(heurInitCrossover)
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
#define DEFAULT_LPLIMFAC
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:4431
Constraint handler for linear constraints in their most general form, .
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:2283
static SCIP_DECL_HASHKEYVAL(hashKeyValSols)
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:7345
int SCIPgetRandomInt(int minrandval, int maxrandval, unsigned int *seedp)
Definition: misc.c:7700
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:1510
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:7329
#define SCIP_REAL_MAX
Definition: def.h:128
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:11477
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:14503
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1293
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:20585
#define DEFAULT_USELPROWS
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:692
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:36588
#define HEUR_PRIORITY
#define HEUR_USESSUBSCIP
#define REALABS(x)
Definition: def.h:151
#define DEFAULT_PERMUTE
#define HEUR_DESC
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
#define DEFAULT_MINNODES
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
Definition: lp.c:18871
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:7313
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:8436
#define SCIP_Real
Definition: def.h:127
#define MIN(x, y)
Definition: memory.c:67
#define DEFAULT_NWAITINGNODES
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:19972
static SCIP_Bool solHasNewSource(SCIP_SOL **sols, int *selection, int selectionsize, int newsol)
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:10194
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:9941
#define EVENTHDLR_NAME
#define SCIP_Longint
Definition: def.h:112
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:917
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:20571
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:34885
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:1692
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:3938
#define DEFAULT_MINIMPROVE
int SCIProwGetNNonz(SCIP_ROW *row)
Definition: lp.c:18836
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1058
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:10572
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:20597
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:3797
#define SCIPdebug(x)
Definition: pub_message.h:74
static void sortArray(int *a, int size)
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8124
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
Definition: lp.c:18685
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:35767
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:3629
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:41132
static SCIP_RETCODE createRows(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars)
#define DEFAULT_MINFIXINGRATE
default SCIP plugins
static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:37372
SCIP callable library.
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:36554
static SCIP_RETCODE setupSubproblem(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:41409