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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_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 500 /* size of hash table for solution tuples in crossover heuristic */
60 #define DEFAULT_BESTSOLLIMIT -1 /* limit on number of improving incumbent solutions in sub-CIP */
61 #define DEFAULT_USEUCT FALSE /* should uct node selection be used at the beginning of the search? */
62 #define DEFAULT_RANDSEED 7 /* initial random seed */
63 
64 /* event handler properties */
65 #define EVENTHDLR_NAME "Crossover"
66 #define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
67 
68 /*
69  * Data structures
70  */
71 
72 typedef struct SolTuple SOLTUPLE;
73 
74 /** primal heuristic data */
75 struct SCIP_HeurData
76 {
77  SCIP_SOL* prevlastsol; /**< worst solution taken into account during the previous run */
78  SCIP_SOL* prevbestsol; /**< best solution during the previous run */
79  int prevnsols; /**< number of all solutions during the previous run */
80 
81  SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
82  SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
83  SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
84  SCIP_Longint usednodes; /**< nodes already used by crossover in earlier calls */
85  SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
86 
87  int nusedsols; /**< number of solutions that will be taken into account */
88  SCIP_Longint nwaitingnodes; /**< number of nodes without incumbent change heuristic should wait */
89  unsigned int nfailures; /**< number of failures since last successful call */
90  SCIP_Longint nextnodenumber; /**< number of nodes at which crossover should be called the next time */
91  SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
92  SCIP_Real minimprove; /**< factor by which Crossover should at least improve the incumbent */
93  SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
94  SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
95  SCIP_Bool randomization; /**< should the choice which sols to take be randomized? */
96  SCIP_Bool dontwaitatroot; /**< should the nwaitingnodes parameter be ignored at the root node? */
97  SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
98  SCIP_HASHTABLE* hashtable; /**< hashtable used to store the solution tuples already used */
99  SOLTUPLE* lasttuple; /**< last tuple of solutions created by crossover */
100  SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
101  SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
102  * to constraints in subproblem? */
103  SCIP_Bool permute; /**< should the subproblem be permuted to increase diversification? */
104  int bestsollimit; /**< limit on number of improving incumbent solutions in sub-CIP */
105  SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
106 };
107 
108 /** n-tuple of solutions and their hashkey */
109 struct SolTuple
110 {
111  int* indices; /**< sorted array of solution indices */
112  int size; /**< size of the array (should be heurdata->nusedsols) */
113  unsigned int key; /**< hashkey of the tuple */
114  SOLTUPLE* prev; /**< previous solution tuple created */
115 };
116 
117 
118 /*
119  * Local methods
120  */
121 
122 
123 /** gets the hash key of a solution tuple */
124 static
125 SCIP_DECL_HASHGETKEY(hashGetKeySols)
126 { /*lint --e{715}*/
127  return elem;
128 }
129 
130 
131 /** returns TRUE iff both solution tuples are identical */
132 static
133 SCIP_DECL_HASHKEYEQ(hashKeyEqSols)
134 { /*lint --e{715}*/
135  int i;
136  int size;
137 
138  int* indices1;
139  int* indices2;
140 
141  indices1 = ((SOLTUPLE*)key1)->indices;
142  indices2 = ((SOLTUPLE*)key2)->indices;
143 
144  /* there should be two nonempty arrays of the same size */
145  assert(indices1 != NULL);
146  assert(indices2 != NULL);
147  assert(((SOLTUPLE*)key1)->size == ((SOLTUPLE*)key2)->size);
148 
149  size = ((SOLTUPLE*)key1)->size;
150 
151  /* compare arrays by components, return TRUE, iff equal */
152  for( i = 0; i < size; i++ )
153  {
154  if( indices1[i] != indices2[i] )
155  return FALSE;
156  }
157 
158  return TRUE;
159 }
160 
161 
162 /** returns hashkey of a solution tuple */
163 static
164 SCIP_DECL_HASHKEYVAL(hashKeyValSols)
165 { /*lint --e{715}*/
166  return ((SOLTUPLE*)key)->key;
167 }
168 
169 
170 /** calculates a hash key for a given tuple of solution indices */
171 static
172 unsigned int calculateHashKey(
173  int* indices, /**< indices of solutions */
174  int size /**< number of solutions */
175  )
176 {
177  int i;
178  unsigned int hashkey;
179 
180  /* hashkey should be (x1+1) * (x2+1) * ... * (xn+1) + x1 + x2 + ... + xn */
181  hashkey = 1;
182  for( i = 0; i < size; i++ )
183  hashkey *= indices[i] + 1;
184  for( i = 0; i < size; i++ )
185  hashkey += indices[i];
186 
187  return hashkey;
188 }
189 
190 
191 /** insertion sort for a small int array */
192 static void sortArray(
193  int* a, /**< array to be sorted */
194  int size /**< size of array */
195  )
196 {
197  int i;
198  int j;
199  int tmp;
200 
201  /* simple insertion sort algorithm */
202  for( i = 1; i < size; i++ )
203  {
204  tmp = a[i];
205  j = i-1;
206  while( j >= 0 && a[j] > tmp )
207  {
208  a[j+1] = a[j]; /*lint !e679*/
209  j = j-1;
210  }
211  a[j+1] = tmp; /*lint !e679*/
212  }
213 }
214 
215 
216 /** creates a new tuple of solutions */
217 static
219  SCIP* scip, /**< original SCIP data structure */
220  SOLTUPLE** elem, /**< tuple of solutions which should be created */
221  int* indices, /**< indices of solutions */
222  int size, /**< number of solutions */
223  SCIP_HEURDATA* heurdata /**< primal heuristic data */
224  )
225 {
226  /* memory allocation */
227  SCIP_CALL( SCIPallocBlockMemory(scip, elem) );
228  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*elem)->indices, size) );
229  BMScopyMemoryArray((*elem)->indices, indices, size);
230 
231  /* data input */
232  sortArray(indices,size);
233  (*elem)->size = size;
234  (*elem)->key = calculateHashKey((*elem)->indices, (*elem)->size);
235  (*elem)->prev = heurdata->lasttuple;
236 
237  /* update heurdata */
238  heurdata->lasttuple = *elem;
239  return SCIP_OKAY;
240 }
241 
242 
243 /** checks whether the new solution was found at the same node by the same heuristic as an already selected one */
244 static
246  SCIP_SOL** sols, /**< feasible SCIP solutions */
247  int* selection, /**< pool of solutions crossover uses */
248  int selectionsize, /**< size of solution pool */
249  int newsol /**< candidate solution */
250  )
251 {
252  int i;
253 
254  for( i = 0; i < selectionsize; i++ )
255  {
256  if( SCIPsolGetHeur(sols[selection[i]]) == SCIPsolGetHeur(sols[newsol])
257  && SCIPsolGetNodenum(sols[selection[i]]) == SCIPsolGetNodenum(sols[newsol]) )
258  return FALSE;
259  }
260 
261  return TRUE;
262 }
263 
264 /** randomly selects the solutions crossover will use from the pool of all solutions found so far */
265 static
267  SCIP* scip, /**< original SCIP data structure */
268  int* selection, /**< pool of solutions crossover uses */
269  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
270  SCIP_Bool* success /**< pointer to store whether the process was successful */
271  )
272 {
273  int i;
274  int j;
275  int lastsol; /* the worst solution possible to choose */
276  int nusedsols; /* number of solutions which will be chosen */
277 
278  SOLTUPLE* elem;
279  SCIP_SOL** sols;
280 
281  assert( success != NULL );
282 
283  /* initialization */
284  nusedsols = heurdata->nusedsols;
285  lastsol = SCIPgetNSols(scip);
286  sols = SCIPgetSols(scip);
287  assert(nusedsols < lastsol);
288 
289  i = 0;
290  *success = FALSE;
291 
292  /* perform at maximum 10 restarts and stop as soon as a new set of solutions is found */
293  while( !*success && i < 10 )
294  {
295  SCIP_Bool validtuple;
296 
297  validtuple = TRUE;
298  for( j = 0; j < nusedsols && validtuple; j++ )
299  {
300  int k;
301  k = SCIPrandomGetInt(heurdata->randnumgen, nusedsols-j-1, lastsol-1);
302 
303  /* ensure that the solution does not have a similar source as the others */
304  while( k >= nusedsols-j-1 && !solHasNewSource(sols, selection, j, k) )
305  k--;
306 
307  validtuple = (k >= nusedsols-j-1);
308  selection[j] = k;
309  lastsol = k;
310  }
311 
312  if( validtuple )
313  {
314  /* creates an object ready to be inserted into the hashtable */
315  SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
316 
317  /* check whether the randomized set is already in the hashtable, if not, insert it */
318  if( !SCIPhashtableExists(heurdata->hashtable, elem) )
319  {
320  SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
321  *success = TRUE;
322  }
323  }
324  i++;
325  }
326 
327  return SCIP_OKAY;
328 }
329 
330 
331 /** determines the fixings for the CROSSOVER subproblem and checks whether enough fixings were found */
332 static
334  SCIP* scip, /**< original SCIP data structure */
335  SCIP_VAR** fixedvars, /**< array to store source SCIP variables whose copies should be fixed in the sub-SCIP */
336  SCIP_Real* fixedvals, /**< array to store solution values for variable fixing */
337  int* nfixedvars, /**< pointer to store the number of fixed variables */
338  int fixedvarssize, /**< size of the arrays to store fixing variables */
339  int* selection, /**< pool of solutions crossover will use */
340  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
341  SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
342  )
343 {
344  SCIP_VAR** vars; /* original scip variables */
345  SCIP_SOL** sols; /* pool of solutions */
346  SCIP_Real fixingrate; /* percentage of variables that are fixed */
347 
348  int nvars;
349  int nbinvars;
350  int nintvars;
351 
352  int i;
353  int j;
354 
355  sols = SCIPgetSols(scip);
356  assert(sols != NULL);
357  assert(fixedvars != NULL);
358  assert(fixedvals != NULL);
359 
360  /* get required data of the original problem */
361  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
362  assert(fixedvarssize >= nbinvars + nintvars);
363 
364  *nfixedvars = 0;
365 
366  /* go through discrete variables and collect potential fixings */
367  for( i = 0; i < nbinvars + nintvars; i++ )
368  {
369  SCIP_Real solval;
370  SCIP_Bool fixable;
371 
372  fixable = TRUE;
373  solval = SCIPgetSolVal(scip, sols[selection[0]], vars[i]);
374 
375  /* check, whether variable's value is identical for each selected solution */
376  for( j = 1; j < heurdata->nusedsols; j++ )
377  {
378  SCIP_Real varsolval;
379  varsolval = SCIPgetSolVal(scip, sols[selection[j]], vars[i]);
380  if( REALABS(solval - varsolval) > 0.5 )
381  {
382  fixable = FALSE;
383  break;
384  }
385  }
386 
387  /* original solval can be outside transformed global bounds */
388  fixable = fixable && SCIPvarGetLbGlobal(vars[i]) <= solval && solval <= SCIPvarGetUbGlobal(vars[i]);
389 
390  /* if solutions' values are equal, variable should be fixed in the subproblem */
391  if( fixable )
392  {
393  fixedvars[(*nfixedvars)] = vars[i];
394  fixedvals[(*nfixedvars)] = solval;
395  (*nfixedvars)++;
396  }
397  }
398 
399  fixingrate = (SCIP_Real)(*nfixedvars) / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
400 
401  /* if all variables would be fixed or amount of fixed variables is insufficient,
402  * skip subproblem creation and abort immediately
403  */
404  *success = (*nfixedvars) < nbinvars + nintvars && fixingrate >= heurdata->minfixingrate;
405 
406  return SCIP_OKAY;
407 }
408 
409 /** creates a subproblem for subscip by fixing a number of variables */
410 static
412  SCIP* scip, /**< original SCIP data structure */
413  SCIP_VAR** fixedvars, /**< array to store source SCIP variables whose copies should be fixed in the sub-SCIP */
414  SCIP_Real* fixedvals, /**< array to store solution values for variable fixing */
415  int* nfixedvars, /**< pointer to store the number of fixed variables */
416  int fixedvarssize, /**< size of the arrays to store fixing variables */
417  int* selection, /**< pool of solutions crossover will use */
418  SCIP_HEURDATA* heurdata, /**< primal heuristic data */
419  SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
420  )
421 {
422  SCIP_SOL** sols; /* array of all solutions found so far */
423  int nsols; /* number of all solutions found so far */
424  int nusedsols; /* number of solutions to use in crossover */
425  int i;
426 
427  /* get solutions' data */
428  nsols = SCIPgetNSols(scip);
429  sols = SCIPgetSols(scip);
430  nusedsols = heurdata->nusedsols;
431 
432  assert(nusedsols > 1);
433  assert(nsols >= nusedsols);
434 
435  /* use nusedsols best solutions if randomization is deactivated or there are only nusedsols solutions at hand
436  * or a good new solution was found since last call */
437  if( !heurdata->randomization || nsols == nusedsols || heurdata->prevlastsol != sols[nusedsols-1] )
438  {
439  SOLTUPLE* elem;
440  SCIP_HEUR* solheur;
441  SCIP_Longint solnodenum;
442  SCIP_Bool allsame;
443 
444  for( i = 0; i < nusedsols; i++ )
445  selection[i] = i;
446  SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
447 
448  solheur = SCIPsolGetHeur(sols[0]);
449  solnodenum = SCIPsolGetNodenum(sols[0]);
450  allsame = TRUE;
451 
452  /* check, whether all solutions have been found by the same heuristic at the same node; in this case we do not run
453  * crossover, since it would probably just optimize over the same space as the other heuristic
454  */
455  for( i = 1; i < nusedsols; i++ )
456  {
457  if( SCIPsolGetHeur(sols[i]) != solheur || SCIPsolGetNodenum(sols[i]) != solnodenum )
458  allsame = FALSE;
459  }
460  *success = !allsame && !SCIPhashtableExists(heurdata->hashtable, elem);
461 
462  /* check, whether solution tuple has already been tried */
463  if( !SCIPhashtableExists(heurdata->hashtable, elem) )
464  {
465  SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
466  }
467 
468  /* if solution tuple has already been tried, randomization is allowed and enough solutions are at hand, try
469  * to randomize another tuple. E.g., this can happen if the last crossover solution was among the best ones */
470  if( !(*success) && heurdata->randomization && nsols > nusedsols )
471  {
472  SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
473  }
474 
475  }
476  /* otherwise randomize the set of solutions */
477  else
478  {
479  SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
480  }
481 
482  /* no acceptable solution tuple could be created */
483  if( !(*success) )
484  return SCIP_OKAY;
485 
486  /* set up the variables of the subproblem */
487  SCIP_CALL( fixVariables(scip, fixedvars, fixedvals, nfixedvars, fixedvarssize, selection, heurdata, success) );
488 
489  return SCIP_OKAY;
490 }
491 
492 
493 /** creates a new solution for the original problem by copying the solution of the subproblem */
494 static
496  SCIP* scip, /**< original SCIP data structure */
497  SCIP* subscip, /**< SCIP structure of the subproblem */
498  SCIP_VAR** subvars, /**< the variables of the subproblem */
499  SCIP_HEUR* heur, /**< crossover heuristic structure */
500  SCIP_SOL* subsol, /**< solution of the subproblem */
501  int* solindex, /**< index of the solution */
502  SCIP_Bool* success /**< used to store whether new solution was found or not */
503  )
504 {
505  SCIP_VAR** vars; /* the original problem's variables */
506  int nvars;
507  SCIP_SOL* newsol; /* solution to be created for the original problem */
508  SCIP_Real* subsolvals; /* solution values of the subproblem */
509 
510  assert(scip != NULL);
511  assert(subscip != NULL);
512  assert(subvars != NULL);
513  assert(subsol != NULL);
514 
515  /* get variables' data */
516  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
517  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
518  * since constraint copying may have required the copy of variables that are fixed in the main SCIP */
519  assert(nvars <= SCIPgetNOrigVars(subscip));
520 
521  SCIP_CALL( SCIPallocBufferArray(scip, &subsolvals, nvars) );
522 
523  /* copy the solution */
524  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
525 
526  /* create new solution for the original problem */
527  SCIP_CALL( SCIPcreateSol(scip, &newsol, heur) );
528  SCIP_CALL( SCIPsetSolVals(scip, newsol, nvars, vars, subsolvals) );
529  *solindex = SCIPsolGetIndex(newsol);
530 
531  /* try to add new solution to scip and free it immediately */
532  SCIP_CALL( SCIPtrySolFree(scip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, success) );
533 
534  SCIPfreeBufferArray(scip, &subsolvals);
535 
536  return SCIP_OKAY;
537 }
538 
539 /** updates heurdata after a run of crossover */
540 static
542  SCIP* scip, /**< original SCIP data structure */
543  SCIP_HEURDATA* heurdata /**< primal heuristic data */
544  )
545 {
546  /* increase number of failures, calculate next node at which crossover should be called and update actual solutions */
547  heurdata->nfailures++;
548  heurdata->nextnodenumber = (heurdata->nfailures <= 25
549  ? SCIPgetNNodes(scip) + 100*(2LL << heurdata->nfailures) /*lint !e703*/
550  : SCIP_LONGINT_MAX);
551 }
552 
553 /* ---------------- Callback methods of event handler ---------------- */
554 
555 /* exec the event handler
556  *
557  * we interrupt the solution process
558  */
559 static
560 SCIP_DECL_EVENTEXEC(eventExecCrossover)
561 {
562  SCIP_HEURDATA* heurdata;
563 
564  assert(eventhdlr != NULL);
565  assert(eventdata != NULL);
566  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
567  assert(event != NULL);
568  assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_LPSOLVED);
569 
570  heurdata = (SCIP_HEURDATA*)eventdata;
571  assert(heurdata != NULL);
572 
573  /* interrupt solution process of sub-SCIP */
574  if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
575  {
576  SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
578  }
579 
580  return SCIP_OKAY;
581 }
582 
583 /*
584  * Callback methods of primal heuristic
585  */
586 
587 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
588 static
589 SCIP_DECL_HEURCOPY(heurCopyCrossover)
590 { /*lint --e{715}*/
591  assert(scip != NULL);
592  assert(heur != NULL);
593  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
594 
595  /* call inclusion method of primal heuristic */
597 
598  return SCIP_OKAY;
599 }
600 
601 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
602 static
603 SCIP_DECL_HEURFREE(heurFreeCrossover)
604 { /*lint --e{715}*/
605  SCIP_HEURDATA* heurdata;
606 
607  assert(heur != NULL);
608  assert(scip != NULL);
609 
610  /* get heuristic data */
611  heurdata = SCIPheurGetData(heur);
612  assert(heurdata != NULL);
613 
614  /* free heuristic data */
615  SCIPfreeBlockMemory(scip, &heurdata);
616  SCIPheurSetData(heur, NULL);
617 
618  return SCIP_OKAY;
619 }
620 
621 /** initialization method of primal heuristic (called after problem was transformed) */
622 static
623 SCIP_DECL_HEURINIT(heurInitCrossover)
624 { /*lint --e{715}*/
625  SCIP_HEURDATA* heurdata;
626 
627  assert(heur != NULL);
628  assert(scip != NULL);
629 
630  /* get heuristic's data */
631  heurdata = SCIPheurGetData(heur);
632  assert(heurdata != NULL);
633 
634  /* initialize data */
635  heurdata->usednodes = 0;
636  heurdata->prevlastsol = NULL;
637  heurdata->prevbestsol = NULL;
638  heurdata->lasttuple = NULL;
639  heurdata->nfailures = 0;
640  heurdata->prevnsols = 0;
641  heurdata->nextnodenumber = 0;
642 
643  /* create random number generator */
644  SCIP_CALL( SCIPrandomCreate(&heurdata->randnumgen, SCIPblkmem(scip),
646 
647  /* initialize hash table */
648  SCIP_CALL( SCIPhashtableCreate(&heurdata->hashtable, SCIPblkmem(scip), HASHSIZE_SOLS,
649  hashGetKeySols, hashKeyEqSols, hashKeyValSols, NULL) );
650  assert(heurdata->hashtable != NULL);
651 
652  return SCIP_OKAY;
653 }
654 
655 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
656 static
657 SCIP_DECL_HEUREXIT(heurExitCrossover)
658 { /*lint --e{715}*/
659  SCIP_HEURDATA* heurdata;
660  SOLTUPLE* soltuple;
661 
662  assert(heur != NULL);
663  assert(scip != NULL);
664 
665  /* get heuristic data */
666  heurdata = SCIPheurGetData(heur);
667  assert(heurdata != NULL);
668  soltuple = heurdata->lasttuple;
669 
670  /* free all soltuples iteratively */
671  while( soltuple != NULL )
672  {
673  SOLTUPLE* tmp;
674  tmp = soltuple->prev;
675  SCIPfreeBlockMemoryArray(scip, &soltuple->indices, soltuple->size);
676  SCIPfreeBlockMemory(scip, &soltuple);
677  soltuple = tmp;
678  }
679 
680  /* free random number generator */
681  SCIPrandomFree(&heurdata->randnumgen);
682 
683  /* free hash table */
684  assert(heurdata->hashtable != NULL);
685  SCIPhashtableFree(&heurdata->hashtable);
686 
687  return SCIP_OKAY;
688 }
689 
690 
691 /** execution method of primal heuristic */
692 static
693 SCIP_DECL_HEUREXEC(heurExecCrossover)
694 { /*lint --e{715}*/
695  SCIP_HEURDATA* heurdata; /* primal heuristic data */
696  SCIP* subscip; /* the subproblem created by crossover */
697  SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
698  SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
699 
700  SCIP_VAR** vars; /* original problem's variables */
701  SCIP_VAR** subvars; /* subproblem's variables */
702  SCIP_SOL** sols;
703 
704  SCIP_Real cutoff; /* objective cutoff for the subproblem */
705  SCIP_Real upperbound;
706  SCIP_Bool success;
707 
708  SCIP_Longint nstallnodes; /* node limit for the subproblem */
709 
710  int* selection; /* pool of solutions crossover uses */
711  int nvars; /* number of original problem's variables */
712  int nbinvars;
713  int nintvars;
714  int nusedsols;
715  int i;
716  SCIP_VAR** fixedvars;
717  SCIP_Real* fixedvals;
718  int nfixedvars;
719 
720  assert(heur != NULL);
721  assert(scip != NULL);
722  assert(result != NULL);
723 
724  /* get heuristic's data */
725  heurdata = SCIPheurGetData(heur);
726  assert(heurdata != NULL);
727  nusedsols = heurdata->nusedsols;
728 
729  *result = SCIP_DELAYED;
730 
731  /* only call heuristic, if enough solutions are at hand */
732  if( SCIPgetNSols(scip) < nusedsols )
733  return SCIP_OKAY;
734 
735  sols = SCIPgetSols(scip);
736  assert(sols != NULL);
737 
738  /* if one good solution was found, heuristic should not be delayed any longer */
739  if( sols[nusedsols-1] != heurdata->prevlastsol )
740  {
741  heurdata->nextnodenumber = SCIPgetNNodes(scip);
742  if( sols[0] != heurdata->prevbestsol )
743  heurdata->nfailures = 0;
744  }
745  /* in nonrandomized mode: only recall heuristic, if at least one new good solution was found in the meantime */
746  else if( !heurdata->randomization )
747  return SCIP_OKAY;
748 
749  /* if heuristic should be delayed, wait until certain number of nodes is reached */
750  if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
751  return SCIP_OKAY;
752 
753  /* only call heuristic, if enough nodes were processed since last incumbent */
754  if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip, SCIPgetBestSol(scip)) < heurdata->nwaitingnodes
755  && (SCIPgetDepth(scip) > 0 || !heurdata->dontwaitatroot) )
756  return SCIP_OKAY;
757 
758  *result = SCIP_DIDNOTRUN;
759 
760  /* calculate the maximal number of branching nodes until heuristic is aborted */
761  nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
762 
763  /* reward Crossover if it succeeded often */
764  nstallnodes = (SCIP_Longint)
765  (nstallnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
766 
767  /* count the setup costs for the sub-MIP as 100 nodes */
768  nstallnodes -= 100 * SCIPheurGetNCalls(heur);
769  nstallnodes += heurdata->nodesofs;
770 
771  /* determine the node limit for the current process */
772  nstallnodes -= heurdata->usednodes;
773  nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
774 
775  /* check whether we have enough nodes left to call subproblem solving */
776  if( nstallnodes < heurdata->minnodes )
777  return SCIP_OKAY;
778 
779  /* consider time and memory limits of the main SCIP */
780  SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
781 
782  if( !success )
783  return SCIP_OKAY;
784 
785  if( SCIPisStopped(scip) )
786  return SCIP_OKAY;
787 
788  /* get variable information */
789  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
790  assert(nvars > 0);
791 
792  /* check whether discrete variables are available */
793  if( nbinvars == 0 && nintvars == 0 )
794  return SCIP_OKAY;
795 
796  /* allocate necessary buffer storage for selection of variable fixings */
797  SCIP_CALL( SCIPallocBufferArray(scip, &selection, nusedsols) );
798  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
799  SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
800 
801  success = FALSE;
802  nfixedvars = 0;
803  /* determine fixings of variables with same value in a certain set of solutions */
804  SCIP_CALL( determineVariableFixings(scip, fixedvars, fixedvals, &nfixedvars, nbinvars + nintvars, selection, heurdata, &success) );
805 
806  heurdata->prevbestsol = SCIPgetBestSol(scip);
807  heurdata->prevlastsol = sols[heurdata->nusedsols-1];
808 
809  /* if creation of sub-SCIP was aborted (e.g. due to number of fixings), free sub-SCIP and abort */
810  if( !success )
811  {
812  /* this run will be counted as a failure since no new solution tuple could be generated or the neighborhood of the
813  * solution was not fruitful in the sense that it was too big
814  */
815  updateFailureStatistic(scip, heurdata);
816 
817  goto TERMINATE;
818  }
819 
820  *result = SCIP_DIDNOTFIND;
821  /* initializing the subproblem */
822  SCIP_CALL( SCIPcreate(&subscip) );
823 
824  /* create the variable mapping hash map */
825  SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
826  success = FALSE;
827 
828  /* create a copy of the transformed problem to be used by the heuristic */
829  SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "crossover", fixedvars, fixedvals, nfixedvars,
830  heurdata->uselprows, heurdata->copycuts, &success, NULL) );
831 
832  eventhdlr = NULL;
833  /* create event handler for LP events */
834  SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecCrossover, NULL) );
835  if( eventhdlr == NULL )
836  {
837  SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
838  return SCIP_PLUGINNOTFOUND;
839  }
840 
841  /* store copied variables in the order in which they appear in the main SCIP */
842  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
843  for( i = 0; i < nvars; i++ )
844  subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
845 
846  /* free hash map */
847  SCIPhashmapFree(&varmapfw);
848 
849  /* do not abort subproblem on CTRL-C */
850  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
851 
852 #ifdef SCIP_DEBUG
853  /* for debugging, enable full output */
854  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
855  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
856 #else
857  /* disable statistic timing inside sub SCIP and output to console */
858  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
859  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
860 #endif
861 
862  /* check whether there is enough time and memory left */
863  SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsollimit) );
864 
865  /* set limits for the subproblem */
866  SCIP_CALL( SCIPcopyLimits(scip, subscip) );
867  heurdata->nodelimit = nstallnodes;
868  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nstallnodes) );
869 
870  /* forbid recursive call of heuristics and separators solving subMIPs */
871  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
872 
873  /* disable cutting plane separation */
875 
876  /* disable expensive presolving */
878 
879  /* use best estimate node selection */
880  if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
881  {
882  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
883  }
884 
885  /* activate uct node selection at the top of the tree */
886  if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
887  {
888  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
889  }
890 
891  /* use inference branching */
892  if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
893  {
894  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
895  }
896 
897  /* enable conflict analysis and restrict conflict pool */
898  if( !SCIPisParamFixed(subscip, "conflict/enable") )
899  {
900  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
901  }
902  if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
903  {
904  SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
905  }
906 
907  /* speed up sub-SCIP by not checking dual LP feasibility */
908  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
909 
910  /* employ a limit on the number of enforcement rounds in the quadratic constraint handler; this fixes the issue that
911  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
912  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
913  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no deductions shall be
914  * made for the original SCIP
915  */
916  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && !SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
917  {
918  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 500) );
919  }
920 
921  /* add an objective cutoff */
923 
924  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
926  {
927  cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
928  }
929  else
930  {
931  if( SCIPgetUpperbound ( scip ) >= 0 )
932  cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
933  else
934  cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
935  }
936  cutoff = MIN(upperbound, cutoff );
937  SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
938 
939  /* permute the subproblem to increase diversification */
940  if( heurdata->permute )
941  {
943  }
944 
945  /* catch LP events of sub-SCIP */
946  SCIP_CALL( SCIPtransformProb(subscip) );
947  SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
948 
949  /* this code can be enabled whenever the subproblem should be written out */
950 #ifdef SCIP_DISABLED_CODE
951  SCIPdebug( SCIP_CALL( SCIPwriteOrigProblem(subscip, "crossoverprob.cip", "cip", FALSE) ) );
952 #endif
953  /* solve the subproblem */
954  SCIPdebugMsg(scip, "Solve Crossover subMIP\n");
955 
956  /* Errors in solving the subproblem should not kill the overall solving process.
957  * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
958  SCIP_CALL_ABORT( SCIPsolve(subscip) );
959 
960  /* drop LP events of sub-SCIP */
961  SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
962 
963  /* print solving statistics of subproblem if we are in SCIP's debug mode */
965 
966  heurdata->usednodes += SCIPgetNNodes(subscip);
967 
968  /* merge histories of the subscip-variables to the SCIP variables. */
969  SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
970  SCIPdebugMsg(scip, "Transferring variable histories complete\n");
971 
972  /* check, whether a solution was found */
973  if( SCIPgetNSols(subscip) > 0 )
974  {
975  SCIP_SOL** subsols;
976  int nsubsols;
977  int solindex; /* index of the solution created by crossover */
978 
979  /* check, whether a solution was found;
980  * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */
981  nsubsols = SCIPgetNSols(subscip);
982  subsols = SCIPgetSols(subscip);
983  success = FALSE;
984  solindex = -1;
985  for( i = 0; i < nsubsols && !success; ++i )
986  {
987  SCIP_CALL( createNewSol(scip, subscip, subvars, heur, subsols[i], &solindex, &success) );
988  }
989 
990  if( success )
991  {
992  int tmp;
993 
994  assert(solindex != -1);
995 
996  *result = SCIP_FOUNDSOL;
997 
998  /* insert all crossings of the new solution and (nusedsols-1) of its parents into the hashtable
999  * in order to avoid incest ;)
1000  */
1001  for( i = 0; i < nusedsols; i++ )
1002  {
1003  SOLTUPLE* elem;
1004  tmp = selection[i];
1005  selection[i] = solindex;
1006 
1007  SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
1008  SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
1009  selection[i] = tmp;
1010  }
1011 
1012  /* if solution was among the best ones, crossover should not be called until another good solution was found */
1013  if( !heurdata->randomization )
1014  {
1015  heurdata->prevbestsol = SCIPgetBestSol(scip);
1016  heurdata->prevlastsol = SCIPgetSols(scip)[heurdata->nusedsols-1];
1017  }
1018  }
1019 
1020  /* if solution is not better than incumbent or could not be added to problem => run is counted as a failure */
1021  if( !success || solindex != SCIPsolGetIndex(SCIPgetBestSol(scip)) )
1022  updateFailureStatistic(scip, heurdata);
1023  }
1024  else
1025  {
1026  /* if no new solution was found, run was a failure */
1027  updateFailureStatistic(scip, heurdata);
1028  }
1029 
1030  /* free subproblem */
1031  SCIPfreeBufferArray(scip, &subvars);
1032  SCIP_CALL( SCIPfree(&subscip) );
1033 TERMINATE:
1034  /* free buffer storage for variable fixings */
1035  SCIPfreeBufferArray(scip, &fixedvals);
1036  SCIPfreeBufferArray(scip, &fixedvars);
1037  SCIPfreeBufferArray(scip, &selection);
1038 
1039  return SCIP_OKAY;
1040 }
1041 
1042 
1043 /*
1044  * primal heuristic specific interface methods
1045  */
1046 
1047 /** creates the crossover primal heuristic and includes it in SCIP */
1049  SCIP* scip /**< SCIP data structure */
1050  )
1051 {
1052  SCIP_HEURDATA* heurdata;
1053  SCIP_HEUR* heur;
1054 
1055  /* create Crossover primal heuristic data */
1056  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1057 
1058  /* include primal heuristic */
1059  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
1061  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecCrossover, heurdata) );
1062 
1063  assert(heur != NULL);
1064 
1065  /* set non-NULL pointers to callback methods */
1066  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyCrossover) );
1067  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeCrossover) );
1068  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitCrossover) );
1069  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitCrossover) );
1070 
1071  /* add crossover primal heuristic parameters */
1072 
1073  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1074  "number of nodes added to the contingent of the total nodes",
1075  &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1076 
1077  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1078  "maximum number of nodes to regard in the subproblem",
1079  &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1080 
1081  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1082  "minimum number of nodes required to start the subproblem",
1083  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1084 
1085  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nusedsols",
1086  "number of solutions to be taken into account",
1087  &heurdata->nusedsols, FALSE, DEFAULT_NUSEDSOLS, 2, INT_MAX, NULL, NULL) );
1088 
1089  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
1090  "number of nodes without incumbent change that heuristic should wait",
1091  &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1092 
1093  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1094  "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1095  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1096 
1097  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1098  "minimum percentage of integer variables that have to be fixed",
1099  &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1100 
1101  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1102  "factor by which Crossover should at least improve the incumbent",
1103  &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1104 
1105  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
1106  "factor by which the limit on the number of LP depends on the node limit",
1107  &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
1108 
1109  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/randomization",
1110  "should the choice which sols to take be randomized?",
1111  &heurdata->randomization, TRUE, DEFAULT_RANDOMIZATION, NULL, NULL) );
1112 
1113  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/dontwaitatroot",
1114  "should the nwaitingnodes parameter be ignored at the root node?",
1115  &heurdata->dontwaitatroot, TRUE, DEFAULT_DONTWAITATROOT, NULL, NULL) );
1116 
1117  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
1118  "should subproblem be created out of the rows in the LP rows?",
1119  &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
1120 
1121  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1122  "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
1123  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1124 
1125  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/permute",
1126  "should the subproblem be permuted to increase diversification?",
1127  &heurdata->permute, TRUE, DEFAULT_PERMUTE, NULL, NULL) );
1128 
1129  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/bestsollimit",
1130  "limit on number of improving incumbent solutions in sub-CIP",
1131  &heurdata->bestsollimit, FALSE, DEFAULT_BESTSOLLIMIT, -1, INT_MAX, NULL, NULL) );
1132 
1133  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
1134  "should uct node selection be used at the beginning of the search?",
1135  &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
1136  return SCIP_OKAY;
1137 }
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21909
SCIP_RETCODE SCIPrandomCreate(SCIP_RANDNUMGEN **randnumgen, BMS_BLKMEM *blkmem, unsigned int initialseed)
Definition: misc.c:8693
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:84
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5095
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:21892
static SCIP_DECL_HASHKEYEQ(hashKeyEqSols)
#define HEUR_TIMING
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2254
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6541
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1327
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:8092
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12071
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8526
static SCIP_DECL_HEURCOPY(heurCopyCrossover)
#define DEFAULT_NODESOFS
static SCIP_RETCODE createNewSol(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SCIP_HEUR *heur, SCIP_SOL *subsol, int *solindex, SCIP_Bool *success)
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11505
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:38881
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2765
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4230
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip.c:4126
#define DEFAULT_RANDOMIZATION
#define DEFAULT_NUSEDSOLS
#define TRUE
Definition: def.h:63
#define SCIPdebug(x)
Definition: pub_message.h:74
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
Definition: scip.c:10268
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5069
static unsigned int calculateHashKey(int *indices, int size)
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9184
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:21907
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:7999
#define HEUR_FREQOFS
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:8723
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2903
#define DEFAULT_MAXNODES
#define SCIP_LONGINT_MAX
Definition: def.h:121
static SCIP_DECL_HASHGETKEY(hashGetKeySols)
static SCIP_DECL_EVENTEXEC(eventExecCrossover)
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:21937
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:696
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1102
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:21890
#define SCIPdebugMsg
Definition: scip.h:451
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4202
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:44425
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:2015
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
#define HEUR_NAME
static SCIP_DECL_HEUREXEC(heurExecCrossover)
void SCIPrandomFree(SCIP_RANDNUMGEN **randnumgen)
Definition: misc.c:8710
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:15777
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1181
LNS heuristic that tries to combine several feasible solutions.
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4338
#define DEFAULT_NODESQUOT
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8060
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38044
#define DEFAULT_USEUCT
#define DEFAULT_COPYCUTS
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4567
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:45519
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2798
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition: scip.c:2419
#define NULL
Definition: lpi_spx1.cpp:137
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:2382
#define REALABS(x)
Definition: def.h:159
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:42323
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1307
static SCIP_DECL_HEUREXIT(heurExitCrossover)
static SCIP_RETCODE createSolTuple(SCIP *scip, SOLTUPLE **elem, int *indices, int size, SCIP_HEURDATA *heurdata)
#define EVENTHDLR_DESC
#define HEUR_DISPCHAR
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:21925
public data structures and miscellaneous methods
static SCIP_RETCODE selectSolsRandomized(SCIP *scip, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
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:10438
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:40207
#define HEUR_FREQ
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2362
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11078
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42094
#define HASHSIZE_SOLS
#define DEFAULT_DONTWAITATROOT
#define DEFAULT_BESTSOLLIMIT
struct SolTuple SOLTUPLE
#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:39843
#define HEUR_MAXDEPTH
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4625
unsigned int SCIPinitializeRandomSeed(SCIP *scip, int initialseedvalue)
Definition: scip.c:25467
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip.c:40241
static SCIP_DECL_HEURINIT(heurInitCrossover)
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:38832
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_RETCODE SCIPincludeHeurCrossover(SCIP *scip)
#define DEFAULT_LPLIMFAC
static SCIP_RETCODE fixVariables(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, int fixedvarssize, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
Constraint handler for linear constraints in their most general form, .
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:45827
static SCIP_DECL_HASHKEYVAL(hashKeyValSols)
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2065
#define SCIP_REAL_MAX
Definition: def.h:136
#define DEFAULT_USELPROWS
#define HEUR_PRIORITY
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:38931
#define HEUR_USESSUBSCIP
#define DEFAULT_PERMUTE
#define HEUR_DESC
#define DEFAULT_MINNODES
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:8076
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8872
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:899
#define SCIP_Real
Definition: def.h:135
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1138
#define MIN(x, y)
Definition: memory.c:75
#define DEFAULT_NWAITINGNODES
static SCIP_Bool solHasNewSource(SCIP_SOL **sols, int *selection, int selectionsize, int newsol)
#define EVENTHDLR_NAME
#define SCIP_Longint
Definition: def.h:120
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip.c:4090
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2366
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:37909
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip.c:13668
#define DEFAULT_MINIMPROVE
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8044
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:45260
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:16942
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:42472
static void sortArray(int *a, int size)
#define SCIP_CALL_ABORT(x)
Definition: def.h:285
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1092
#define DEFAULT_RANDSEED
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:41182
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:41363
#define DEFAULT_MINFIXINGRATE
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38007
default SCIP plugins
static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:2413
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4258
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5020
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4683
SCIP callable library.
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4176
static SCIP_RETCODE determineVariableFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, int fixedvarssize, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:774
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37005
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:38303