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-2025 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file heur_crossover.c
26 * @ingroup DEFPLUGINS_HEUR
27 * @brief crossover primal heuristic
28 * @author Timo Berthold
29 */
30
31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32
34#include "scip/heur_crossover.h"
35#include "scip/heuristics.h"
36#include "scip/pub_event.h"
37#include "scip/pub_heur.h"
38#include "scip/pub_message.h"
39#include "scip/pub_misc.h"
40#include "scip/pub_sol.h"
41#include "scip/pub_var.h"
42#include "scip/scip_branch.h"
43#include "scip/scip_cons.h"
44#include "scip/scip_copy.h"
45#include "scip/scip_event.h"
46#include "scip/scip_general.h"
47#include "scip/scip_heur.h"
48#include "scip/scip_mem.h"
49#include "scip/scip_message.h"
50#include "scip/scip_nodesel.h"
51#include "scip/scip_numerics.h"
52#include "scip/scip_param.h"
53#include "scip/scip_prob.h"
55#include "scip/scip_sol.h"
56#include "scip/scip_solve.h"
58#include "scip/scip_tree.h"
59#include "scip/scip_var.h"
60#include <string.h>
61
62#define HEUR_NAME "crossover"
63#define HEUR_DESC "LNS heuristic that fixes all variables that are identic in a couple of solutions"
64#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
65#define HEUR_PRIORITY -1104000
66#define HEUR_FREQ 15
67#define HEUR_FREQOFS 0
68#define HEUR_MAXDEPTH -1
69#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
70#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
71
72#define DEFAULT_MAXNODES 5000LL /* maximum number of nodes to regard in the subproblem */
73#define DEFAULT_MINIMPROVE 0.01 /* factor by which Crossover should at least improve the incumbent */
74#define DEFAULT_MINNODES 50LL /* minimum number of nodes to regard in the subproblem */
75#define DEFAULT_MINFIXINGRATE 0.666 /* minimum percentage of integer variables that have to be fixed */
76#define DEFAULT_NODESOFS 500LL /* number of nodes added to the contingent of the total nodes */
77#define DEFAULT_NODESQUOT 0.1 /* subproblem nodes in relation to nodes of the original problem */
78#define DEFAULT_LPLIMFAC 2.0 /* factor by which the limit on the number of LP depends on the node limit */
79#define DEFAULT_NUSEDSOLS 3 /* number of solutions that will be taken into account */
80#define DEFAULT_NWAITINGNODES 200LL /* number of nodes without incumbent change heuristic should wait */
81#define DEFAULT_RANDOMIZATION TRUE /* should the choice which sols to take be randomized? */
82#define DEFAULT_DONTWAITATROOT FALSE /* should the nwaitingnodes parameter be ignored at the root node? */
83#define DEFAULT_USELPROWS FALSE /* should subproblem be created out of the rows in the LP rows,
84 * otherwise, the copy constructors of the constraints handlers are used */
85#define DEFAULT_COPYCUTS TRUE /* if DEFAULT_USELPROWS is FALSE, then should all active cuts from the
86 * cutpool of the original scip be copied to constraints of the subscip
87 */
88#define DEFAULT_PERMUTE FALSE /* should the subproblem be permuted to increase diversification? */
89#define HASHSIZE_SOLS 500 /* size of hash table for solution tuples in crossover heuristic */
90#define DEFAULT_BESTSOLLIMIT -1 /* limit on number of improving incumbent solutions in sub-CIP */
91#define DEFAULT_USEUCT FALSE /* should uct node selection be used at the beginning of the search? */
92#define DEFAULT_RANDSEED 7 /* initial random seed */
94/* event handler properties */
95#define EVENTHDLR_NAME "Crossover"
96#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
97
98/*
99 * Data structures
100 */
101
102typedef struct SolTuple SOLTUPLE;
103
104/** primal heuristic data */
105struct SCIP_HeurData
106{
107 SCIP_SOL* prevlastsol; /**< worst solution taken into account during the previous run */
108 SCIP_SOL* prevbestsol; /**< best solution during the previous run */
109 int prevnsols; /**< number of all solutions during the previous run */
110
111 SCIP_Longint maxnodes; /**< maximum number of nodes to regard in the subproblem */
112 SCIP_Longint minnodes; /**< minimum number of nodes to regard in the subproblem */
113 SCIP_Longint nodesofs; /**< number of nodes added to the contingent of the total nodes */
114 SCIP_Longint usednodes; /**< nodes already used by crossover in earlier calls */
115 SCIP_Real nodesquot; /**< subproblem nodes in relation to nodes of the original problem */
116
117 int nusedsols; /**< number of solutions that will be taken into account */
118 SCIP_Longint nwaitingnodes; /**< number of nodes without incumbent change heuristic should wait */
119 unsigned int nfailures; /**< number of failures since last successful call */
120 SCIP_Longint nextnodenumber; /**< number of nodes at which crossover should be called the next time */
121 SCIP_Real minfixingrate; /**< minimum percentage of integer variables that have to be fixed */
122 SCIP_Real minimprove; /**< factor by which Crossover should at least improve the incumbent */
123 SCIP_Real nodelimit; /**< the nodelimit employed in the current sub-SCIP, for the event handler*/
124 SCIP_Real lplimfac; /**< factor by which the limit on the number of LP depends on the node limit */
125 SCIP_Bool randomization; /**< should the choice which sols to take be randomized? */
126 SCIP_Bool dontwaitatroot; /**< should the nwaitingnodes parameter be ignored at the root node? */
127 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
128 SCIP_HASHTABLE* hashtable; /**< hashtable used to store the solution tuples already used */
129 SOLTUPLE* lasttuple; /**< last tuple of solutions created by crossover */
130 SCIP_Bool uselprows; /**< should subproblem be created out of the rows in the LP rows? */
131 SCIP_Bool copycuts; /**< if uselprows == FALSE, should all active cuts from cutpool be copied
132 * to constraints in subproblem? */
133 SCIP_Bool permute; /**< should the subproblem be permuted to increase diversification? */
134 int bestsollimit; /**< limit on number of improving incumbent solutions in sub-CIP */
135 SCIP_Bool useuct; /**< should uct node selection be used at the beginning of the search? */
136};
137
138/** n-tuple of solutions and their hashkey */
139struct SolTuple
140{
141 int* indices; /**< sorted array of solution indices */
142 int size; /**< size of the array (should be heurdata->nusedsols) */
143 unsigned int key; /**< hashkey of the tuple */
144 SOLTUPLE* prev; /**< previous solution tuple created */
145};
146
147
148/*
149 * Local methods
150 */
152/** gets the hash key of a solution tuple */
153static
154SCIP_DECL_HASHGETKEY(hashGetKeySols)
155{ /*lint --e{715}*/
156 return elem;
157}
158
160/** returns TRUE iff both solution tuples are identical */
161static
162SCIP_DECL_HASHKEYEQ(hashKeyEqSols)
163{ /*lint --e{715}*/
164 int i;
165 int size;
166
167 int* indices1;
168 int* indices2;
169
170 indices1 = ((SOLTUPLE*)key1)->indices;
171 indices2 = ((SOLTUPLE*)key2)->indices;
172
173 /* there should be two nonempty arrays of the same size */
174 assert(indices1 != NULL);
175 assert(indices2 != NULL);
176 assert(((SOLTUPLE*)key1)->size == ((SOLTUPLE*)key2)->size);
177
178 size = ((SOLTUPLE*)key1)->size;
179
180 /* compare arrays by components, return TRUE, iff equal */
181 for( i = 0; i < size; i++ )
182 {
183 if( indices1[i] != indices2[i] )
184 return FALSE;
185 }
186
187 return TRUE;
188}
189
191/** returns hashkey of a solution tuple */
192static
193SCIP_DECL_HASHKEYVAL(hashKeyValSols)
194{ /*lint --e{715}*/
195 return ((SOLTUPLE*)key)->key;
196}
197
199/** calculates a hash key for a given tuple of solution indices */
200static
201unsigned int calculateHashKey(
202 int* indices, /**< indices of solutions */
203 int size /**< number of solutions */
204 )
205{
206 int i;
207 unsigned int hashkey;
208
209 /* hashkey should be (x1+1) * (x2+1) * ... * (xn+1) + x1 + x2 + ... + xn */
210 hashkey = 1;
211 for( i = 0; i < size; i++ )
212 hashkey *= (unsigned) indices[i] + 1;
213 for( i = 0; i < size; i++ )
214 hashkey += (unsigned) indices[i];
215
216 return hashkey;
217}
219
220/** insertion sort for a small int array */
221static void sortArray(
222 int* a, /**< array to be sorted */
223 int size /**< size of array */
224 )
225{
226 int i;
227 int j;
228 int tmp;
229
230 /* simple insertion sort algorithm */
231 for( i = 1; i < size; i++ )
232 {
233 tmp = a[i];
234 j = i-1;
235 while( j >= 0 && a[j] > tmp )
236 {
237 a[j+1] = a[j]; /*lint !e679*/
238 j = j-1;
239 }
240 a[j+1] = tmp; /*lint !e679*/
241 }
242}
243
245/** creates a new tuple of solutions */
246static
248 SCIP* scip, /**< original SCIP data structure */
249 SOLTUPLE** elem, /**< tuple of solutions which should be created */
250 int* indices, /**< indices of solutions */
251 int size, /**< number of solutions */
252 SCIP_HEURDATA* heurdata /**< primal heuristic data */
253 )
254{
255 /* memory allocation */
257 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*elem)->indices, size) );
258 BMScopyMemoryArray((*elem)->indices, indices, size);
259
260 /* data input */
261 sortArray(indices,size);
262 (*elem)->size = size;
263 (*elem)->key = calculateHashKey((*elem)->indices, (*elem)->size);
264 (*elem)->prev = heurdata->lasttuple;
265
266 /* update heurdata */
267 heurdata->lasttuple = *elem;
268 return SCIP_OKAY;
269}
270
272/** checks whether the new solution was found at the same node by the same heuristic as an already selected one */
273static
275 SCIP_SOL** sols, /**< feasible SCIP solutions */
276 int* selection, /**< pool of solutions crossover uses */
277 int selectionsize, /**< size of solution pool */
278 int newsol /**< candidate solution */
279 )
280{
281 int i;
282
283 for( i = 0; i < selectionsize; i++ )
284 {
285 if( SCIPsolGetHeur(sols[selection[i]]) == SCIPsolGetHeur(sols[newsol])
286 && SCIPsolGetNodenum(sols[selection[i]]) == SCIPsolGetNodenum(sols[newsol]) )
287 return FALSE;
288 }
289
290 return TRUE;
291}
293/** randomly selects the solutions crossover will use from the pool of all solutions found so far */
294static
296 SCIP* scip, /**< original SCIP data structure */
297 int* selection, /**< pool of solutions crossover uses */
298 SCIP_HEURDATA* heurdata, /**< primal heuristic data */
299 SCIP_Bool* success /**< pointer to store whether the process was successful */
300 )
301{
302 int i;
303 int j;
304 int lastsol; /* the worst solution possible to choose */
305 int nusedsols; /* number of solutions which will be chosen */
306
307 SOLTUPLE* elem;
308 SCIP_SOL** sols;
309
310 assert( success != NULL );
311
312 /* initialization */
313 nusedsols = heurdata->nusedsols;
314 lastsol = SCIPgetNSols(scip);
315 sols = SCIPgetSols(scip);
316 assert(nusedsols < lastsol);
317
318 i = 0;
319 *success = FALSE;
320
321 /* perform at maximum 10 restarts and stop as soon as a new set of solutions is found */
322 while( !*success && i < 10 )
323 {
324 SCIP_Bool validtuple;
325
326 validtuple = TRUE;
327 for( j = 0; j < nusedsols && validtuple; j++ )
328 {
329 int k;
330 k = SCIPrandomGetInt(heurdata->randnumgen, nusedsols-j-1, lastsol-1);
331
332 /* ensure that the solution does not have a similar source as the others */
333 while( k >= nusedsols-j-1 && !solHasNewSource(sols, selection, j, k) )
334 k--;
335
336 validtuple = (k >= nusedsols-j-1);
337 selection[j] = k;
338 lastsol = k;
339 }
340
341 if( validtuple )
342 {
343 /* creates an object ready to be inserted into the hashtable */
344 SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
345
346 /* check whether the randomized set is already in the hashtable, if not, insert it */
347 if( !SCIPhashtableExists(heurdata->hashtable, elem) )
348 {
349 SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
350 *success = TRUE;
351 }
352 }
353 i++;
354 }
355
356 return SCIP_OKAY;
357}
358
360/** determines the fixings for the CROSSOVER subproblem and checks whether enough fixings were found */
361static
363 SCIP* scip, /**< original SCIP data structure */
364 SCIP_VAR** fixedvars, /**< array to store source SCIP variables whose copies should be fixed in the sub-SCIP */
365 SCIP_Real* fixedvals, /**< array to store solution values for variable fixing */
366 int* nfixedvars, /**< pointer to store the number of fixed variables */
367 int fixedvarssize, /**< size of the arrays to store fixing variables */
368 int* selection, /**< pool of solutions crossover will use */
369 SCIP_HEURDATA* heurdata, /**< primal heuristic data */
370 SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
371 )
372{
373 SCIP_VAR** vars; /* original scip variables */
374 SCIP_SOL** sols; /* pool of solutions */
375 SCIP_Real fixingrate; /* percentage of variables that are fixed */
376
377 int nvars;
378 int nbinvars;
379 int nintvars;
380
381 int i;
382 int j;
383
384 sols = SCIPgetSols(scip);
385 assert(sols != NULL);
386 assert(fixedvars != NULL);
387 assert(fixedvals != NULL);
388
389 /* get required data of the original problem */
390 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
391 assert(fixedvarssize >= nbinvars + nintvars);
392
393 *nfixedvars = 0;
394
395 /* go through discrete variables and collect potential fixings */
396 for( i = 0; i < nbinvars + nintvars; i++ )
397 {
398 SCIP_Real solval;
399 SCIP_Bool fixable;
400
401 fixable = TRUE;
402 solval = SCIPgetSolVal(scip, sols[selection[0]], vars[i]);
403
404 /* check, whether variable's value is identical for each selected solution */
405 for( j = 1; j < heurdata->nusedsols; j++ )
406 {
407 SCIP_Real varsolval;
408 varsolval = SCIPgetSolVal(scip, sols[selection[j]], vars[i]);
409 if( REALABS(solval - varsolval) > 0.5 )
410 {
411 fixable = FALSE;
412 break;
413 }
414 }
415
416 /* original solval can be outside transformed global bounds */
417 fixable = fixable && SCIPvarGetLbGlobal(vars[i]) <= solval && solval <= SCIPvarGetUbGlobal(vars[i]);
418
419 /* if solutions' values are equal, variable should be fixed in the subproblem */
420 if( fixable )
421 {
422 fixedvars[(*nfixedvars)] = vars[i];
423 fixedvals[(*nfixedvars)] = solval;
424 (*nfixedvars)++;
425 }
426 }
427
428 fixingrate = (SCIP_Real)(*nfixedvars) / (SCIP_Real)(MAX(nbinvars + nintvars, 1));
429
430 /* if all variables would be fixed or amount of fixed variables is insufficient,
431 * skip subproblem creation and abort immediately
432 */
433 *success = (*nfixedvars) < nbinvars + nintvars && fixingrate >= heurdata->minfixingrate;
434
435 return SCIP_OKAY;
436}
438/** creates a subproblem for subscip by fixing a number of variables */
439static
441 SCIP* scip, /**< original SCIP data structure */
442 SCIP_VAR** fixedvars, /**< array to store source SCIP variables whose copies should be fixed in the sub-SCIP */
443 SCIP_Real* fixedvals, /**< array to store solution values for variable fixing */
444 int* nfixedvars, /**< pointer to store the number of fixed variables */
445 int fixedvarssize, /**< size of the arrays to store fixing variables */
446 int* selection, /**< pool of solutions crossover will use */
447 SCIP_HEURDATA* heurdata, /**< primal heuristic data */
448 SCIP_Bool* success /**< pointer to store whether the problem was created successfully */
449 )
450{
451 SCIP_SOL** sols; /* array of all solutions found so far */
452 int nsols; /* number of all solutions found so far */
453 int nusedsols; /* number of solutions to use in crossover */
454 int i;
455
456 /* get solutions' data */
457 nsols = SCIPgetNSols(scip);
458 sols = SCIPgetSols(scip);
459 nusedsols = heurdata->nusedsols;
460
461 assert(nusedsols > 1);
462 assert(nsols >= nusedsols);
463
464 /* use nusedsols best solutions if randomization is deactivated or there are only nusedsols solutions at hand
465 * or a good new solution was found since last call */
466 if( !heurdata->randomization || nsols == nusedsols || heurdata->prevlastsol != sols[nusedsols-1] )
467 {
468 SOLTUPLE* elem;
469 SCIP_HEUR* solheur;
470 SCIP_Longint solnodenum;
471 SCIP_Bool allsame;
472
473 for( i = 0; i < nusedsols; i++ )
474 selection[i] = i;
475 SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
476
477 solheur = SCIPsolGetHeur(sols[0]);
478 solnodenum = SCIPsolGetNodenum(sols[0]);
479 allsame = TRUE;
480
481 /* check, whether all solutions have been found by the same heuristic at the same node; in this case we do not run
482 * crossover, since it would probably just optimize over the same space as the other heuristic
483 */
484 for( i = 1; i < nusedsols; i++ )
485 {
486 if( SCIPsolGetHeur(sols[i]) != solheur || SCIPsolGetNodenum(sols[i]) != solnodenum )
487 allsame = FALSE;
488 }
489 *success = !allsame && !SCIPhashtableExists(heurdata->hashtable, elem);
490
491 /* check, whether solution tuple has already been tried */
492 if( !SCIPhashtableExists(heurdata->hashtable, elem) )
493 {
494 SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
495 }
496
497 /* if solution tuple has already been tried, randomization is allowed and enough solutions are at hand, try
498 * to randomize another tuple. E.g., this can happen if the last crossover solution was among the best ones */
499 if( !(*success) && heurdata->randomization && nsols > nusedsols )
500 {
501 SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
502 }
503 }
504 /* otherwise randomize the set of solutions */
505 else
506 {
507 SCIP_CALL( selectSolsRandomized(scip, selection, heurdata, success) );
508 }
509
510 /* no acceptable solution tuple could be created */
511 if( !(*success) )
512 return SCIP_OKAY;
513
514 /* set up the variables of the subproblem */
515 SCIP_CALL( fixVariables(scip, fixedvars, fixedvals, nfixedvars, fixedvarssize, selection, heurdata, success) );
516
517 return SCIP_OKAY;
518}
520/** updates heurdata after a run of crossover */
521static
523 SCIP* scip, /**< original SCIP data structure */
524 SCIP_HEURDATA* heurdata /**< primal heuristic data */
525 )
526{
527 /* increase number of failures, calculate next node at which crossover should be called and update actual solutions */
528 heurdata->nfailures++;
529 heurdata->nextnodenumber = (heurdata->nfailures <= 25
530 ? SCIPgetNNodes(scip) + 100*(2LL << heurdata->nfailures) /*lint !e703*/
532}
533
534/* ---------------- Callback methods of event handler ---------------- */
535
536/* exec the event handler
537 *
538 * we interrupt the solution process
539 */
540static
541SCIP_DECL_EVENTEXEC(eventExecCrossover)
542{
543 SCIP_HEURDATA* heurdata;
544
545 assert(eventhdlr != NULL);
546 assert(eventdata != NULL);
547 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
548 assert(event != NULL);
550
551 heurdata = (SCIP_HEURDATA*)eventdata;
552 assert(heurdata != NULL);
553
554 /* interrupt solution process of sub-SCIP */
555 if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
556 {
557 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
559 }
560
561 return SCIP_OKAY;
562}
563
564/*
565 * Callback methods of primal heuristic
566 */
568/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
569static
570SCIP_DECL_HEURCOPY(heurCopyCrossover)
571{ /*lint --e{715}*/
572 assert(scip != NULL);
573 assert(heur != NULL);
574 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
575
576 /* call inclusion method of primal heuristic */
578
579 return SCIP_OKAY;
580}
582/** setup and solve the subproblem and catch the return code */
583static
585 SCIP* scip, /**< SCIP data structure */
586 SCIP* subscip, /**< sub-SCIP data structure */
587 SCIP_HEUR* heur, /**< mutation heuristic */
588 SCIP_HEURDATA* heurdata, /**< heuristics data */
589 SCIP_VAR** vars, /**< SCIP variables */
590 SCIP_VAR** fixedvars, /**< array to store the variables that should be fixed in the subproblem */
591 SCIP_Real* fixedvals, /**< array to store the fixing values to fix variables in the subproblem */
592 SCIP_Longint nstallnodes, /**< node limit for the subproblem */
593 SCIP_RESULT* result, /**< pointer to store the result */
594 int* selection, /**< pool of solutions crossover uses */
595 int nvars, /**< number of original problem's variables */
596 int nfixedvars, /**< the number of variables that should be fixed */
597 int nusedsols /**< number of solutions which will be chosen */
598 )
599{
600 SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
601 SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
602 SCIP_VAR** subvars; /* subproblem's variables */
603 SCIP_Real cutoff; /* objective cutoff for the subproblem */
604 SCIP_Real upperbound;
605 SCIP_Bool success;
606 int i;
607
608 assert(scip != NULL);
609 assert(subscip != NULL);
610 assert(heur != NULL);
611 assert(heurdata != NULL);
612
613 /* create the variable mapping hash map */
614 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
615 success = FALSE;
616
617 /* create a copy of the transformed problem to be used by the heuristic */
618 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "crossover", fixedvars, fixedvals, nfixedvars,
619 heurdata->uselprows, heurdata->copycuts, &success, NULL) );
620
621 eventhdlr = NULL;
622 /* create event handler for LP events */
623 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecCrossover, NULL) );
624 if( eventhdlr == NULL )
625 {
626 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
627 return SCIP_PLUGINNOTFOUND;
628 }
629
630 /* store copied variables in the order in which they appear in the main SCIP */
631 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
632 for( i = 0; i < nvars; i++ )
633 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
634
635 /* free hash map */
636 SCIPhashmapFree(&varmapfw);
637
638 /* do not abort subproblem on CTRL-C */
639 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
640
641#ifdef SCIP_DEBUG
642 /* for debugging, enable full output */
643 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
644 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
645#else
646 /* disable statistic timing inside sub SCIP and output to console */
647 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
648 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
649#endif
650
651 /* check whether there is enough time and memory left */
652 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsollimit) );
653
654 /* set limits for the subproblem */
655 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
656 heurdata->nodelimit = nstallnodes;
657 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nstallnodes) );
658
659 /* forbid recursive call of heuristics and separators solving subMIPs */
660 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
661
662 /* disable cutting plane separation */
664
665 /* disable expensive presolving */
667
668 /* use best estimate node selection */
669 if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
670 {
671 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
672 }
673
674 /* activate uct node selection at the top of the tree */
675 if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
676 {
677 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
678 }
679
680 /* use inference branching */
681 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
682 {
683 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
684 }
685
686 /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
687 if( !SCIPisParamFixed(subscip, "conflict/enable") )
688 {
689 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
690 }
691 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
692 {
693 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
694 }
695 if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
696 {
697 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
698 }
699
700 /* speed up sub-SCIP by not checking dual LP feasibility */
701 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
702
703 /* add an objective cutoff */
705
706 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
708 {
709 cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
710 }
711 else
712 {
713 if( SCIPgetUpperbound ( scip ) >= 0 )
714 cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
715 else
716 cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
717 }
718 cutoff = MIN(upperbound, cutoff );
719 SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
720
721 /* permute the subproblem to increase diversification */
722 if( heurdata->permute )
723 {
725 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) );
726 }
727
728 /* catch LP events of sub-SCIP */
729 SCIP_CALL( SCIPtransformProb(subscip) );
730 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, NULL) );
731
732 /* this code can be enabled whenever the subproblem should be written out */
733#ifdef SCIP_DISABLED_CODE
734 SCIPdebug( SCIP_CALL( SCIPwriteOrigProblem(subscip, "crossoverprob.cip", "cip", FALSE) ) );
735#endif
736 /* solve the subproblem */
737 SCIPdebugMsg(scip, "Solve Crossover subMIP\n");
738
739 /* Errors in solving the subproblem should not kill the overall solving process.
740 * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
741 SCIP_CALL_ABORT( SCIPsolve(subscip) );
742
743 /* drop LP events of sub-SCIP */
744 SCIP_CALL( SCIPdropEvent(subscip, SCIP_EVENTTYPE_LPSOLVED, eventhdlr, (SCIP_EVENTDATA*) heurdata, -1) );
745
746 /* print solving statistics of subproblem if we are in SCIP's debug mode */
748
749 heurdata->usednodes += SCIPgetNNodes(subscip);
750
751 /* merge histories of the subscip-variables to the SCIP variables. */
752 SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
753 SCIPdebugMsg(scip, "Transferring variable histories complete\n");
754
755 /* check, whether a solution was found */
756 if( SCIPgetNSols(subscip) > 0 )
757 {
758 int solindex; /* index of the solution created by crossover */
759
760 /* check, whether a solution was found;
761 * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */
762 success = FALSE;
763 solindex = -1;
764 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, &solindex) );
765
766 if( success )
767 {
768 int tmp;
769
770 assert(solindex != -1);
771
772 *result = SCIP_FOUNDSOL;
773
774 /* insert all crossings of the new solution and (nusedsols-1) of its parents into the hashtable
775 * in order to avoid incest ;)
776 */
777 for( i = 0; i < nusedsols; i++ )
778 {
779 SOLTUPLE* elem;
780 tmp = selection[i];
781 selection[i] = solindex;
782
783 SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
784 SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
785 selection[i] = tmp;
786 }
787
788 /* if solution was among the best ones, crossover should not be called until another good solution was found */
789 if( !heurdata->randomization )
790 {
791 heurdata->prevbestsol = SCIPgetBestSol(scip);
792 heurdata->prevlastsol = SCIPgetSols(scip)[heurdata->nusedsols-1];
793 }
794 }
795
796 /* if solution is not better than incumbent or could not be added to problem => run is counted as a failure */
797 if( !success || solindex != SCIPsolGetIndex(SCIPgetBestSol(scip)) )
798 updateFailureStatistic(scip, heurdata);
799 }
800 else
801 {
802 /* if no new solution was found, run was a failure */
803 updateFailureStatistic(scip, heurdata);
804 }
805
806 SCIPfreeBufferArray(scip, &subvars);
807
808 return SCIP_OKAY;
809}
811/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
812static
813SCIP_DECL_HEURFREE(heurFreeCrossover)
814{ /*lint --e{715}*/
815 SCIP_HEURDATA* heurdata;
816
817 assert(heur != NULL);
818 assert(scip != NULL);
819
820 /* get heuristic data */
821 heurdata = SCIPheurGetData(heur);
822 assert(heurdata != NULL);
823
824 /* free heuristic data */
825 SCIPfreeBlockMemory(scip, &heurdata);
826 SCIPheurSetData(heur, NULL);
827
828 return SCIP_OKAY;
829}
831/** initialization method of primal heuristic (called after problem was transformed) */
832static
833SCIP_DECL_HEURINIT(heurInitCrossover)
834{ /*lint --e{715}*/
835 SCIP_HEURDATA* heurdata;
836
837 assert(heur != NULL);
838 assert(scip != NULL);
839
840 /* get heuristic's data */
841 heurdata = SCIPheurGetData(heur);
842 assert(heurdata != NULL);
843
844 /* initialize data */
845 heurdata->usednodes = 0;
846 heurdata->prevlastsol = NULL;
847 heurdata->prevbestsol = NULL;
848 heurdata->lasttuple = NULL;
849 heurdata->nfailures = 0;
850 heurdata->prevnsols = 0;
851 heurdata->nextnodenumber = 0;
852
853 /* create random number generator */
854 SCIP_CALL( SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE) );
855
856 /* initialize hash table */
858 hashGetKeySols, hashKeyEqSols, hashKeyValSols, NULL) );
859 assert(heurdata->hashtable != NULL);
860
861 return SCIP_OKAY;
862}
864/** deinitialization method of primal heuristic (called before transformed problem is freed) */
865static
866SCIP_DECL_HEUREXIT(heurExitCrossover)
867{ /*lint --e{715}*/
868 SCIP_HEURDATA* heurdata;
869 SOLTUPLE* soltuple;
870
871 assert(heur != NULL);
872 assert(scip != NULL);
873
874 /* get heuristic data */
875 heurdata = SCIPheurGetData(heur);
876 assert(heurdata != NULL);
877 soltuple = heurdata->lasttuple;
878
879 /* free all soltuples iteratively */
880 while( soltuple != NULL )
881 {
882 SOLTUPLE* tmp;
883 tmp = soltuple->prev;
884 SCIPfreeBlockMemoryArray(scip, &soltuple->indices, soltuple->size);
885 SCIPfreeBlockMemory(scip, &soltuple);
886 soltuple = tmp;
887 }
888
889 /* free random number generator */
890 SCIPfreeRandom(scip, &heurdata->randnumgen);
891
892 /* free hash table */
893 assert(heurdata->hashtable != NULL);
894 SCIPhashtableFree(&heurdata->hashtable);
895
896 return SCIP_OKAY;
897}
899/** execution method of primal heuristic */
900static
901SCIP_DECL_HEUREXEC(heurExecCrossover)
902{ /*lint --e{715}*/
903 SCIP* subscip; /* the subproblem created by crossover */
904 SCIP_HEURDATA* heurdata; /* primal heuristic data */
905 SCIP_VAR** vars; /* original problem's variables */
906 SCIP_VAR** fixedvars;
907 SCIP_SOL** sols;
908 SCIP_RETCODE retcode;
909 SCIP_Longint nstallnodes; /* node limit for the subproblem */
910 SCIP_Bool success;
911 SCIP_Real* fixedvals;
912 int* selection; /* pool of solutions crossover uses */
913 int nvars; /* number of original problem's variables */
914 int nbinvars;
915 int nintvars;
916 int nusedsols;
917 int nfixedvars;
918
919 assert(heur != NULL);
920 assert(scip != NULL);
921 assert(result != NULL);
922
923 /* get heuristic's data */
924 heurdata = SCIPheurGetData(heur);
925 assert(heurdata != NULL);
926 nusedsols = heurdata->nusedsols;
927
928 *result = SCIP_DELAYED;
929
930 /* only call heuristic, if enough solutions are at hand */
931 if( SCIPgetNSols(scip) < nusedsols )
932 return SCIP_OKAY;
933
934 sols = SCIPgetSols(scip);
935 assert(sols != NULL);
936
937 /* if one good solution was found, heuristic should not be delayed any longer */
938 if( sols[nusedsols-1] != heurdata->prevlastsol )
939 {
940 heurdata->nextnodenumber = SCIPgetNNodes(scip);
941 if( sols[0] != heurdata->prevbestsol )
942 heurdata->nfailures = 0;
943 }
944 /* in nonrandomized mode: only recall heuristic, if at least one new good solution was found in the meantime */
945 else if( !heurdata->randomization )
946 return SCIP_OKAY;
947
948 /* if heuristic should be delayed, wait until certain number of nodes is reached */
949 if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
950 return SCIP_OKAY;
951
952 /* only call heuristic, if enough nodes were processed since last incumbent */
953 if( SCIPgetNNodes(scip) - SCIPgetSolNodenum(scip, SCIPgetBestSol(scip)) < heurdata->nwaitingnodes
954 && (SCIPgetDepth(scip) > 0 || !heurdata->dontwaitatroot) )
955 return SCIP_OKAY;
956
957 *result = SCIP_DIDNOTRUN;
958
959 /* calculate the maximal number of branching nodes until heuristic is aborted */
960 nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
961
962 /* reward Crossover if it succeeded often */
963 nstallnodes = (SCIP_Longint)
964 (nstallnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
965
966 /* count the setup costs for the sub-MIP as 100 nodes */
967 nstallnodes -= 100 * SCIPheurGetNCalls(heur);
968 nstallnodes += heurdata->nodesofs;
969
970 /* determine the node limit for the current process */
971 nstallnodes -= heurdata->usednodes;
972 nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
973
974 /* check whether we have enough nodes left to call subproblem solving */
975 if( nstallnodes < heurdata->minnodes )
976 return SCIP_OKAY;
977
978 /* consider time and memory limits of the main SCIP */
979 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
980
981 if( !success )
982 return SCIP_OKAY;
983
984 if( SCIPisStopped(scip) )
985 return SCIP_OKAY;
986
987 /* get variable information */
988 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
989 assert(nvars > 0);
990
991 /* check whether discrete variables are available */
992 if( nbinvars == 0 && nintvars == 0 )
993 return SCIP_OKAY;
994
995 /* allocate necessary buffer storage for selection of variable fixings */
996 SCIP_CALL( SCIPallocBufferArray(scip, &selection, nusedsols) );
997 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
998 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
999
1000 success = FALSE;
1001 nfixedvars = 0;
1002 /* determine fixings of variables with same value in a certain set of solutions */
1003 SCIP_CALL( determineVariableFixings(scip, fixedvars, fixedvals, &nfixedvars, nbinvars + nintvars, selection, heurdata, &success) );
1004
1005 heurdata->prevbestsol = SCIPgetBestSol(scip);
1006 heurdata->prevlastsol = sols[heurdata->nusedsols-1];
1007
1008 /* if creation of sub-SCIP was aborted (e.g. due to number of fixings), free sub-SCIP and abort */
1009 if( !success )
1010 {
1011 /* this run will be counted as a failure since no new solution tuple could be generated or the neighborhood of the
1012 * solution was not fruitful in the sense that it was too big
1013 */
1014 updateFailureStatistic(scip, heurdata);
1015
1016 goto TERMINATE;
1017 }
1018
1019 *result = SCIP_DIDNOTFIND;
1020 /* initializing the subproblem */
1021 SCIP_CALL( SCIPcreate(&subscip) );
1022
1023 /* setup and solve the subproblem and catch the return code */
1024 retcode = setupAndSolveSubscipCrossover(scip, subscip, heur, heurdata, vars,
1025 fixedvars, fixedvals, nstallnodes, result, selection, nvars, nfixedvars, nusedsols);
1026
1027 /* free the subscip in any case */
1028 SCIP_CALL( SCIPfree(&subscip) );
1029 SCIP_CALL( retcode );
1030
1031TERMINATE:
1032 /* free buffer storage for variable fixings */
1033 SCIPfreeBufferArray(scip, &fixedvals);
1034 SCIPfreeBufferArray(scip, &fixedvars);
1035 SCIPfreeBufferArray(scip, &selection);
1036
1037 return SCIP_OKAY;
1038}
1039
1040/*
1041 * primal heuristic specific interface methods
1043
1044/** creates the crossover primal heuristic and includes it in SCIP */
1046 SCIP* scip /**< SCIP data structure */
1047 )
1048{
1049 SCIP_HEURDATA* heurdata;
1050 SCIP_HEUR* heur;
1051
1052 /* create Crossover primal heuristic data */
1053 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
1054
1055 /* include primal heuristic */
1058 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecCrossover, heurdata) );
1059
1060 assert(heur != NULL);
1061
1062 /* primal heuristic is safe to use in exact solving mode */
1063 SCIPheurMarkExact(heur);
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}
SCIP_VAR * a
Definition: circlepacking.c:66
#define NULL
Definition: def.h:248
#define SCIP_Longint
Definition: def.h:141
#define SCIP_REAL_MAX
Definition: def.h:158
#define SCIP_Bool
Definition: def.h:91
#define MIN(x, y)
Definition: def.h:224
#define SCIP_Real
Definition: def.h:156
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define MAX(x, y)
Definition: def.h:220
#define SCIP_CALL_ABORT(x)
Definition: def.h:334
#define SCIP_LONGINT_FORMAT
Definition: def.h:148
#define REALABS(x)
Definition: def.h:182
#define SCIP_LONGINT_MAX
Definition: def.h:142
#define SCIP_CALL(x)
Definition: def.h:355
SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
Definition: scip_copy.c:1437
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition: scip_copy.c:3249
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition: scip_copy.c:1254
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition: scip_copy.c:3292
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip_general.c:759
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip_general.c:402
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip_general.c:370
SCIP_RETCODE SCIPpermuteProb(SCIP *scip, unsigned int randseed, SCIP_Bool permuteconss, SCIP_Bool permutebinvars, SCIP_Bool permuteintvars, SCIP_Bool permutebinimplvars, SCIP_Bool permuteintimplvars, SCIP_Bool permutecontimplvars, SCIP_Bool permutecontvars)
Definition: scip_prob.c:922
SCIP_RETCODE SCIPwriteOrigProblem(SCIP *scip, const char *filename, const char *extension, SCIP_Bool genericnames)
Definition: scip_prob.c:742
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip_prob.c:1661
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip_prob.c:2115
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:3095
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3284
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:3061
void SCIPhashtableFree(SCIP_HASHTABLE **hashtable)
Definition: misc.c:2348
SCIP_Bool SCIPhashtableExists(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2647
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:2298
SCIP_RETCODE SCIPhashtableInsert(SCIP_HASHTABLE *hashtable, void *element)
Definition: misc.c:2535
#define SCIPdebugMsg
Definition: scip_message.h:78
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_param.c:111
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip_param.c:219
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_param.c:83
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip_param.c:545
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_param.c:139
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip_param.c:487
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip_param.c:904
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:956
SCIP_RETCODE SCIPsetCharParam(SCIP *scip, const char *name, char value)
Definition: scip_param.c:661
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_param.c:57
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip_param.c:429
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip_param.c:985
SCIP_RETCODE SCIPincludeHeurCrossover(SCIP *scip)
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip_branch.c:304
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip_event.c:111
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:396
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:1194
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip_event.c:293
SCIP_RETCODE SCIPdropEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: scip_event.c:333
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip_heur.c:167
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1368
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_heur.c:122
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip_heur.c:183
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip_heur.c:215
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1613
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1593
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition: heur.c:1457
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip_heur.c:199
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1467
void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
Definition: heur.c:1378
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:110
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip_mem.c:57
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip_mem.h:93
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip_mem.h:108
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip_mem.h:89
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip_nodesel.c:242
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip_sol.c:2981
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:4239
int SCIPgetNSols(SCIP *scip)
Definition: scip_sol.c:2882
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition: sol.c:4259
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition: sol.c:4290
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:2219
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip_sol.c:2931
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1765
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip_solve.c:232
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip_solve.c:3548
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip_solve.c:2635
SCIP_Real SCIPgetUpperbound(SCIP *scip)
SCIP_Longint SCIPgetNNodes(SCIP *scip)
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
SCIP_Real SCIPgetLowerbound(SCIP *scip)
SCIP_Longint SCIPgetNLPs(SCIP *scip)
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:953
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPsumepsilon(SCIP *scip)
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:672
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:24142
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:24120
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
unsigned int SCIPinitializeRandomSeed(SCIP *scip, unsigned int initialseedvalue)
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:10223
#define DEFAULT_NODESQUOT
#define DEFAULT_NWAITINGNODES
static SCIP_DECL_HEURFREE(heurFreeCrossover)
#define DEFAULT_NODESOFS
#define DEFAULT_COPYCUTS
#define DEFAULT_MAXNODES
static SCIP_DECL_HEUREXIT(heurExitCrossover)
#define HEUR_TIMING
#define DEFAULT_MINNODES
#define DEFAULT_NUSEDSOLS
struct SolTuple SOLTUPLE
#define HEUR_FREQOFS
#define DEFAULT_DONTWAITATROOT
#define HEUR_DESC
#define HASHSIZE_SOLS
static SCIP_DECL_HASHKEYVAL(hashKeyValSols)
#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)
static SCIP_RETCODE setupAndSolveSubscipCrossover(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_HEURDATA *heurdata, SCIP_VAR **vars, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, SCIP_Longint nstallnodes, SCIP_RESULT *result, int *selection, int nvars, int nfixedvars, int nusedsols)
#define DEFAULT_MINFIXINGRATE
#define DEFAULT_USEUCT
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
static SCIP_DECL_HASHGETKEY(hashGetKeySols)
#define DEFAULT_MINIMPROVE
#define HEUR_NAME
#define DEFAULT_USELPROWS
#define DEFAULT_PERMUTE
static SCIP_RETCODE createSolTuple(SCIP *scip, SOLTUPLE **elem, int *indices, int size, SCIP_HEURDATA *heurdata)
static void sortArray(int *a, int size)
#define DEFAULT_RANDOMIZATION
static SCIP_RETCODE determineVariableFixings(SCIP *scip, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int *nfixedvars, int fixedvarssize, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
static SCIP_Bool solHasNewSource(SCIP_SOL **sols, int *selection, int selectionsize, int newsol)
static SCIP_RETCODE selectSolsRandomized(SCIP *scip, int *selection, SCIP_HEURDATA *heurdata, SCIP_Bool *success)
static unsigned int calculateHashKey(int *indices, int size)
static SCIP_DECL_HEUREXEC(heurExecCrossover)
#define DEFAULT_BESTSOLLIMIT
#define DEFAULT_RANDSEED
static SCIP_DECL_EVENTEXEC(eventExecCrossover)
#define EVENTHDLR_DESC
static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
static SCIP_DECL_HASHKEYEQ(hashKeyEqSols)
#define HEUR_FREQ
static SCIP_DECL_HEURINIT(heurInitCrossover)
#define HEUR_USESSUBSCIP
static SCIP_DECL_HEURCOPY(heurCopyCrossover)
#define EVENTHDLR_NAME
LNS heuristic that tries to combine several feasible solutions.
methods commonly used by primal heuristics
memory allocation routines
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:134
public methods for managing events
public methods for primal heuristics
public methods for message output
#define SCIPerrorMessage
Definition: pub_message.h:64
#define SCIPdebug(x)
Definition: pub_message.h:93
public data structures and miscellaneous methods
public methods for primal CIP solutions
public methods for problem variables
public methods for branching rule plugins and branching
public methods for constraint handler plugins and constraints
public methods for problem copies
public methods for event handler plugins and event handlers
general public methods
public methods for primal heuristic plugins and divesets
public methods for memory management
public methods for message handling
public methods for node selector plugins
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for global and local (sub)problems
public methods for random numbers
public methods for solutions
public solving methods
public methods for querying solving statistics
public methods for the branch-and-bound tree
public methods for SCIP variables
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:179
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:102
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:77
@ SCIP_PARAMSETTING_OFF
Definition: type_paramset.h:63
@ SCIP_PARAMSETTING_FAST
Definition: type_paramset.h:62
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_DELAYED
Definition: type_result.h:43
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_FOUNDSOL
Definition: type_result.h:56
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:61
@ SCIP_PLUGINNOTFOUND
Definition: type_retcode.h:54
@ SCIP_OKAY
Definition: type_retcode.h:42
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:63