SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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-2026 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
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 {
502 }
503 }
504 /* otherwise randomize the set of solutions */
505 else
506 {
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{
544
545 assert(eventhdlr != NULL);
546 assert(eventdata != NULL);
547 assert(event != NULL);
549
551
552 heurdata = (SCIP_HEURDATA*)eventdata;
553 assert(heurdata != NULL);
554
555 /* interrupt solution process of sub-SCIP */
556 if( SCIPgetNLPs(scip) > heurdata->lplimfac * heurdata->nodelimit )
557 {
558 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
560 }
561
562 return SCIP_OKAY;
563}
564
565/*
566 * Callback methods of primal heuristic
567 */
569/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
570static
571SCIP_DECL_HEURCOPY(heurCopyCrossover)
572{ /*lint --e{715}*/
573 assert(scip != NULL);
574 assert(heur != NULL);
575
577
578 /* call inclusion method of primal heuristic */
580
581 return SCIP_OKAY;
582}
584/** setup and solve the subproblem and catch the return code */
585static
587 SCIP* scip, /**< SCIP data structure */
588 SCIP* subscip, /**< sub-SCIP data structure */
589 SCIP_HEUR* heur, /**< mutation heuristic */
590 SCIP_HEURDATA* heurdata, /**< heuristics data */
591 SCIP_VAR** vars, /**< SCIP variables */
592 SCIP_VAR** fixedvars, /**< array to store the variables that should be fixed in the subproblem */
593 SCIP_Real* fixedvals, /**< array to store the fixing values to fix variables in the subproblem */
594 SCIP_Longint nstallnodes, /**< node limit for the subproblem */
595 SCIP_RESULT* result, /**< pointer to store the result */
596 int* selection, /**< pool of solutions crossover uses */
597 int nvars, /**< number of original problem's variables */
598 int nfixedvars, /**< the number of variables that should be fixed */
599 int nusedsols /**< number of solutions which will be chosen */
600 )
601{
602 SCIP_EVENTHDLR* eventhdlr; /* event handler for LP events */
603 SCIP_HASHMAP* varmapfw; /* mapping of SCIP variables to sub-SCIP variables */
604 SCIP_VAR** subvars; /* subproblem's variables */
605 SCIP_Real cutoff; /* objective cutoff for the subproblem */
606 SCIP_Real upperbound;
607 SCIP_Bool success;
608 int i;
609
610 assert(scip != NULL);
611 assert(subscip != NULL);
612 assert(heur != NULL);
613 assert(heurdata != NULL);
614
615 /* create the variable mapping hash map */
616 SCIP_CALL( SCIPhashmapCreate(&varmapfw, SCIPblkmem(subscip), nvars) );
617 success = FALSE;
618
619 /* create a copy of the transformed problem to be used by the heuristic */
620 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapfw, "crossover", fixedvars, fixedvals, nfixedvars,
621 heurdata->uselprows, heurdata->copycuts, &success, NULL) );
622
623 eventhdlr = NULL;
624 /* create event handler for LP events */
625 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecCrossover, NULL) );
626 if( eventhdlr == NULL )
627 {
628 SCIPerrorMessage("event handler for " HEUR_NAME " heuristic not found.\n");
629 return SCIP_PLUGINNOTFOUND;
630 }
631
632 /* store copied variables in the order in which they appear in the main SCIP */
634 for( i = 0; i < nvars; i++ )
635 subvars[i] = (SCIP_VAR*) SCIPhashmapGetImage(varmapfw, vars[i]);
636
637 /* free hash map */
638 SCIPhashmapFree(&varmapfw);
639
640 /* do not abort subproblem on CTRL-C */
641 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
642
643#ifdef SCIP_DEBUG
644 /* for debugging, enable full output */
645 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
646 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 100000000) );
647#else
648 /* disable statistic timing inside sub SCIP and output to console */
649 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
650 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
651#endif
652
653 /* check whether there is enough time and memory left */
654 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->bestsollimit) );
655
656 /* set limits for the subproblem */
657 SCIP_CALL( SCIPcopyLimits(scip, subscip) );
658 heurdata->nodelimit = nstallnodes;
659 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", nstallnodes) );
660
661 /* forbid recursive call of heuristics and separators solving subMIPs */
662 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
663
664 /* disable cutting plane separation */
666
667 /* disable expensive presolving */
669
670 /* use best estimate node selection */
671 if( SCIPfindNodesel(subscip, "estimate") != NULL && !SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
672 {
673 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
674 }
675
676 /* activate uct node selection at the top of the tree */
677 if( heurdata->useuct && SCIPfindNodesel(subscip, "uct") != NULL && !SCIPisParamFixed(subscip, "nodeselection/uct/stdpriority") )
678 {
679 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/uct/stdpriority", INT_MAX/2) );
680 }
681
682 /* use inference branching */
683 if( SCIPfindBranchrule(subscip, "inference") != NULL && !SCIPisParamFixed(subscip, "branching/inference/priority") )
684 {
685 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
686 }
687
688 /* enable conflict analysis, disable analysis of boundexceeding LPs, and restrict conflict pool */
689 if( !SCIPisParamFixed(subscip, "conflict/enable") )
690 {
691 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
692 }
693 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
694 {
695 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
696 }
697 if( !SCIPisParamFixed(subscip, "conflict/maxstoresize") )
698 {
699 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
700 }
701
702 /* speed up sub-SCIP by not checking dual LP feasibility */
703 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
704
705 /* add an objective cutoff */
707
708 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
710 {
711 cutoff = (1-heurdata->minimprove)*SCIPgetUpperbound(scip) + heurdata->minimprove*SCIPgetLowerbound(scip);
712 }
713 else
714 {
715 if( SCIPgetUpperbound ( scip ) >= 0 )
716 cutoff = ( 1 - heurdata->minimprove ) * SCIPgetUpperbound ( scip );
717 else
718 cutoff = ( 1 + heurdata->minimprove ) * SCIPgetUpperbound ( scip );
719 }
720 cutoff = MIN(upperbound, cutoff );
721 SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
722
723 /* permute the subproblem to increase diversification */
724 if( heurdata->permute )
725 {
727 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) );
728 }
729
730 /* catch LP events of sub-SCIP */
731 SCIP_CALL( SCIPtransformProb(subscip) );
733
734 /* this code can be enabled whenever the subproblem should be written out */
735#ifdef SCIP_DISABLED_CODE
736 SCIPdebug( SCIP_CALL( SCIPwriteOrigProblem(subscip, "crossoverprob.cip", "cip", FALSE) ) );
737#endif
738 /* solve the subproblem */
739 SCIPdebugMsg(scip, "Solve Crossover subMIP\n");
740
741 /* Errors in solving the subproblem should not kill the overall solving process.
742 * Hence, the return code is caught and a warning is printed, only in debug mode, SCIP will stop. */
743 SCIP_CALL_ABORT( SCIPsolve(subscip) );
744
745 /* drop LP events of sub-SCIP */
747
748 /* print solving statistics of subproblem if we are in SCIP's debug mode */
750
751 heurdata->usednodes += SCIPgetNNodes(subscip);
752
753 /* merge histories of the subscip-variables to the SCIP variables. */
754 SCIP_CALL( SCIPmergeVariableStatistics(subscip, scip, subvars, vars, nvars) );
755 SCIPdebugMsg(scip, "Transferring variable histories complete\n");
756
757 /* check, whether a solution was found */
758 if( SCIPgetNSols(subscip) > 0 )
759 {
760 int solindex; /* index of the solution created by crossover */
761
762 /* check, whether a solution was found;
763 * due to numerics, it might happen that not all solutions are feasible -> try all solutions until one was accepted */
764 success = FALSE;
765 solindex = -1;
766 SCIP_CALL( SCIPtranslateSubSols(scip, subscip, heur, subvars, &success, &solindex) );
767
768 if( success )
769 {
770 int tmp;
771
772 assert(solindex != -1);
773
775
776 /* insert all crossings of the new solution and (nusedsols-1) of its parents into the hashtable
777 * in order to avoid incest ;)
778 */
779 for( i = 0; i < nusedsols; i++ )
780 {
781 SOLTUPLE* elem;
782 tmp = selection[i];
783 selection[i] = solindex;
784
785 SCIP_CALL( createSolTuple(scip, &elem, selection, nusedsols, heurdata) );
786 SCIP_CALL( SCIPhashtableInsert(heurdata->hashtable, elem) );
787 selection[i] = tmp;
788 }
789
790 /* if solution was among the best ones, crossover should not be called until another good solution was found */
791 if( !heurdata->randomization )
792 {
793 heurdata->prevbestsol = SCIPgetBestSol(scip);
794 heurdata->prevlastsol = SCIPgetSols(scip)[heurdata->nusedsols-1];
795 }
796 }
797
798 /* if solution is not better than incumbent or could not be added to problem => run is counted as a failure */
799 if( !success || solindex != SCIPsolGetIndex(SCIPgetBestSol(scip)) )
801 }
802 else
803 {
804 /* if no new solution was found, run was a failure */
806 }
807
808 SCIPfreeBufferArray(scip, &subvars);
809
810 return SCIP_OKAY;
811}
813/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
814static
815SCIP_DECL_HEURFREE(heurFreeCrossover)
816{ /*lint --e{715}*/
818
819 assert(heur != NULL);
820 assert(scip != NULL);
821
822 /* get heuristic data */
824 assert(heurdata != NULL);
825
826 /* free heuristic data */
828 SCIPheurSetData(heur, NULL);
829
830 return SCIP_OKAY;
831}
833/** initialization method of primal heuristic (called after problem was transformed) */
834static
835SCIP_DECL_HEURINIT(heurInitCrossover)
836{ /*lint --e{715}*/
838
839 assert(heur != NULL);
840 assert(scip != NULL);
841
842 /* get heuristic's data */
844 assert(heurdata != NULL);
845
846 /* initialize data */
847 heurdata->usednodes = 0;
848 heurdata->prevlastsol = NULL;
849 heurdata->prevbestsol = NULL;
850 heurdata->lasttuple = NULL;
851 heurdata->nfailures = 0;
852 heurdata->prevnsols = 0;
853 heurdata->nextnodenumber = 0;
854
855 /* create random number generator */
857
858 /* initialize hash table */
860 hashGetKeySols, hashKeyEqSols, hashKeyValSols, NULL) );
861 assert(heurdata->hashtable != NULL);
862
863 return SCIP_OKAY;
864}
866/** deinitialization method of primal heuristic (called before transformed problem is freed) */
867static
868SCIP_DECL_HEUREXIT(heurExitCrossover)
869{ /*lint --e{715}*/
871 SOLTUPLE* soltuple;
872
873 assert(heur != NULL);
874 assert(scip != NULL);
875
876 /* get heuristic data */
878 assert(heurdata != NULL);
879 soltuple = heurdata->lasttuple;
880
881 /* free all soltuples iteratively */
882 while( soltuple != NULL )
883 {
884 SOLTUPLE* tmp;
885 tmp = soltuple->prev;
886 SCIPfreeBlockMemoryArray(scip, &soltuple->indices, soltuple->size);
887 SCIPfreeBlockMemory(scip, &soltuple);
888 soltuple = tmp;
889 }
890
891 /* free random number generator */
892 SCIPfreeRandom(scip, &heurdata->randnumgen);
893
894 /* free hash table */
895 assert(heurdata->hashtable != NULL);
896 SCIPhashtableFree(&heurdata->hashtable);
897
898 return SCIP_OKAY;
899}
901/** execution method of primal heuristic */
902static
903SCIP_DECL_HEUREXEC(heurExecCrossover)
904{ /*lint --e{715}*/
905 SCIP* subscip; /* the subproblem created by crossover */
906 SCIP_HEURDATA* heurdata; /* primal heuristic data */
907 SCIP_VAR** vars; /* original problem's variables */
908 SCIP_VAR** fixedvars;
909 SCIP_SOL** sols;
910 SCIP_RETCODE retcode;
911 SCIP_Longint nstallnodes; /* node limit for the subproblem */
912 SCIP_Bool success;
913 SCIP_Real* fixedvals;
914 int* selection; /* pool of solutions crossover uses */
915 int nvars; /* number of original problem's variables */
916 int nbinvars;
917 int nintvars;
918 int nusedsols;
919 int nfixedvars;
920
921 assert(heur != NULL);
922 assert(scip != NULL);
923 assert(result != NULL);
924
925 /* get heuristic's data */
927 assert(heurdata != NULL);
928 nusedsols = heurdata->nusedsols;
929
931
932 /* only call heuristic, if enough solutions are at hand */
933 if( SCIPgetNSols(scip) < nusedsols )
934 return SCIP_OKAY;
935
936 sols = SCIPgetSols(scip);
937 assert(sols != NULL);
938
939 /* if one good solution was found, heuristic should not be delayed any longer */
940 if( sols[nusedsols-1] != heurdata->prevlastsol )
941 {
942 heurdata->nextnodenumber = SCIPgetNNodes(scip);
943 if( sols[0] != heurdata->prevbestsol )
944 heurdata->nfailures = 0;
945 }
946 /* in nonrandomized mode: only recall heuristic, if at least one new good solution was found in the meantime */
947 else if( !heurdata->randomization )
948 return SCIP_OKAY;
949
950 /* if heuristic should be delayed, wait until certain number of nodes is reached */
951 if( SCIPgetNNodes(scip) < heurdata->nextnodenumber )
952 return SCIP_OKAY;
953
954 /* only call heuristic, if enough nodes were processed since last incumbent */
956 && (SCIPgetDepth(scip) > 0 || !heurdata->dontwaitatroot) )
957 return SCIP_OKAY;
958
960
961 /* calculate the maximal number of branching nodes until heuristic is aborted */
962 nstallnodes = (SCIP_Longint)(heurdata->nodesquot * SCIPgetNNodes(scip));
963
964 /* reward Crossover if it succeeded often */
965 nstallnodes = (SCIP_Longint)
966 (nstallnodes * (1.0 + 2.0*(SCIPheurGetNBestSolsFound(heur)+1.0)/(SCIPheurGetNCalls(heur)+1.0)));
967
968 /* count the setup costs for the sub-MIP as 100 nodes */
969 nstallnodes -= 100 * SCIPheurGetNCalls(heur);
970 nstallnodes += heurdata->nodesofs;
971
972 /* determine the node limit for the current process */
973 nstallnodes -= heurdata->usednodes;
974 nstallnodes = MIN(nstallnodes, heurdata->maxnodes);
975
976 /* check whether we have enough nodes left to call subproblem solving */
977 if( nstallnodes < heurdata->minnodes )
978 return SCIP_OKAY;
979
980 /* consider time and memory limits of the main SCIP */
981 SCIP_CALL( SCIPcheckCopyLimits(scip, &success) );
982
983 if( !success )
984 return SCIP_OKAY;
985
986 if( SCIPisStopped(scip) )
987 return SCIP_OKAY;
988
989 /* get variable information */
990 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
991 assert(nvars > 0);
992
993 /* check whether discrete variables are available */
994 if( nbinvars == 0 && nintvars == 0 )
995 return SCIP_OKAY;
996
997 /* allocate necessary buffer storage for selection of variable fixings */
999 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvars, nbinvars + nintvars) );
1000 SCIP_CALL( SCIPallocBufferArray(scip, &fixedvals, nbinvars + nintvars) );
1001
1002 success = FALSE;
1003 nfixedvars = 0;
1004 /* determine fixings of variables with same value in a certain set of solutions */
1005 SCIP_CALL( determineVariableFixings(scip, fixedvars, fixedvals, &nfixedvars, nbinvars + nintvars, selection, heurdata, &success) );
1006
1007 heurdata->prevbestsol = SCIPgetBestSol(scip);
1008 heurdata->prevlastsol = sols[heurdata->nusedsols-1];
1009
1010 /* if creation of sub-SCIP was aborted (e.g. due to number of fixings), free sub-SCIP and abort */
1011 if( !success )
1012 {
1013 /* this run will be counted as a failure since no new solution tuple could be generated or the neighborhood of the
1014 * solution was not fruitful in the sense that it was too big
1015 */
1017
1018 goto TERMINATE;
1019 }
1020
1022 /* initializing the subproblem */
1023 SCIP_CALL( SCIPcreate(&subscip) );
1024
1025 /* setup and solve the subproblem and catch the return code */
1026 retcode = setupAndSolveSubscipCrossover(scip, subscip, heur, heurdata, vars,
1027 fixedvars, fixedvals, nstallnodes, result, selection, nvars, nfixedvars, nusedsols);
1028
1029 /* free the subscip in any case */
1030 SCIP_CALL( SCIPfree(&subscip) );
1031 SCIP_CALL( retcode );
1032
1033TERMINATE:
1034 /* free buffer storage for variable fixings */
1035 SCIPfreeBufferArray(scip, &fixedvals);
1036 SCIPfreeBufferArray(scip, &fixedvars);
1038
1039 return SCIP_OKAY;
1040}
1041
1042/*
1043 * primal heuristic specific interface methods
1045
1046/** creates the crossover primal heuristic and includes it in SCIP */
1048 SCIP* scip /**< SCIP data structure */
1049 )
1050{
1052 SCIP_HEUR* heur;
1053
1054 /* create Crossover primal heuristic data */
1056
1057 /* include primal heuristic */
1060 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecCrossover, heurdata) );
1061
1062 assert(heur != NULL);
1063
1064 /* primal heuristic is safe to use in exact solving mode */
1065 SCIPheurMarkExact(heur);
1066
1067 /* set non-NULL pointers to callback methods */
1068 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyCrossover) );
1069 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeCrossover) );
1070 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitCrossover) );
1071 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitCrossover) );
1072
1073 /* add crossover primal heuristic parameters */
1074
1075 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
1076 "number of nodes added to the contingent of the total nodes",
1077 &heurdata->nodesofs, FALSE, DEFAULT_NODESOFS, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1078
1079 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
1080 "maximum number of nodes to regard in the subproblem",
1081 &heurdata->maxnodes, TRUE, DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1082
1083 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
1084 "minimum number of nodes required to start the subproblem",
1085 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1086
1087 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nusedsols",
1088 "number of solutions to be taken into account",
1089 &heurdata->nusedsols, FALSE, DEFAULT_NUSEDSOLS, 2, INT_MAX, NULL, NULL) );
1090
1091 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nwaitingnodes",
1092 "number of nodes without incumbent change that heuristic should wait",
1093 &heurdata->nwaitingnodes, TRUE, DEFAULT_NWAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
1094
1095 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
1096 "contingent of sub problem nodes in relation to the number of nodes of the original problem",
1097 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
1098
1099 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minfixingrate",
1100 "minimum percentage of integer variables that have to be fixed",
1101 &heurdata->minfixingrate, FALSE, DEFAULT_MINFIXINGRATE, 0.0, 1.0, NULL, NULL) );
1102
1103 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprove",
1104 "factor by which Crossover should at least improve the incumbent",
1105 &heurdata->minimprove, TRUE, DEFAULT_MINIMPROVE, 0.0, 1.0, NULL, NULL) );
1106
1107 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/lplimfac",
1108 "factor by which the limit on the number of LP depends on the node limit",
1109 &heurdata->lplimfac, TRUE, DEFAULT_LPLIMFAC, 1.0, SCIP_REAL_MAX, NULL, NULL) );
1110
1111 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/randomization",
1112 "should the choice which sols to take be randomized?",
1113 &heurdata->randomization, TRUE, DEFAULT_RANDOMIZATION, NULL, NULL) );
1114
1115 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/dontwaitatroot",
1116 "should the nwaitingnodes parameter be ignored at the root node?",
1117 &heurdata->dontwaitatroot, TRUE, DEFAULT_DONTWAITATROOT, NULL, NULL) );
1118
1119 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselprows",
1120 "should subproblem be created out of the rows in the LP rows?",
1121 &heurdata->uselprows, TRUE, DEFAULT_USELPROWS, NULL, NULL) );
1122
1123 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
1124 "if uselprows == FALSE, should all active cuts from cutpool be copied to constraints in subproblem?",
1125 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
1126
1127 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/permute",
1128 "should the subproblem be permuted to increase diversification?",
1129 &heurdata->permute, TRUE, DEFAULT_PERMUTE, NULL, NULL) );
1130
1131 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/bestsollimit",
1132 "limit on number of improving incumbent solutions in sub-CIP",
1133 &heurdata->bestsollimit, FALSE, DEFAULT_BESTSOLLIMIT, -1, INT_MAX, NULL, NULL) );
1134
1135 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useuct",
1136 "should uct node selection be used at the beginning of the search?",
1137 &heurdata->useuct, TRUE, DEFAULT_USEUCT, NULL, NULL) );
1138 return SCIP_OKAY;
1139}
#define EVENTHDLR_NAME
SCIP_VAR * a
#define EVENTHDLR_DESC
#define DEFAULT_MAXNODES
#define DEFAULT_MINIMPROVE
#define DEFAULT_RANDSEED
#define NULL
Definition def.h:257
#define SCIP_Longint
Definition def.h:150
#define SCIP_REAL_MAX
Definition def.h:167
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define SCIP_CALL_ABORT(x)
Definition def.h:343
#define SCIP_LONGINT_FORMAT
Definition def.h:157
#define REALABS(x)
Definition def.h:191
#define SCIP_LONGINT_MAX
Definition def.h:151
#define SCIP_CALL(x)
Definition def.h:364
#define DEFAULT_MINNODES
SCIP_RETCODE SCIPtranslateSubSols(SCIP *scip, SCIP *subscip, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_Bool *success, int *solindex)
Definition scip_copy.c:1438
SCIP_RETCODE SCIPcheckCopyLimits(SCIP *sourcescip, SCIP_Bool *success)
Definition scip_copy.c:3250
SCIP_RETCODE SCIPmergeVariableStatistics(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **sourcevars, SCIP_VAR **targetvars, int nvars)
Definition scip_copy.c:1255
SCIP_RETCODE SCIPcopyLimits(SCIP *sourcescip, SCIP *targetscip)
Definition scip_copy.c:3293
SCIP_Bool SCIPisStopped(SCIP *scip)
SCIP_RETCODE SCIPfree(SCIP **scip)
SCIP_RETCODE SCIPcreate(SCIP **scip)
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
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)
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 SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:183
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_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition heur.c:1613
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:167
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition heur.c:1593
void SCIPheurMarkExact(SCIP_HEUR *heur)
Definition heur.c:1457
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur,)
Definition scip_heur.c:215
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur,)
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)
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition scip_sol.c:2986
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition sol.c:4254
int SCIPgetNSols(SCIP *scip)
Definition scip_sol.c:2887
SCIP_HEUR * SCIPsolGetHeur(SCIP_SOL *sol)
Definition sol.c:4274
int SCIPsolGetIndex(SCIP_SOL *sol)
Definition sol.c:4305
SCIP_Longint SCIPgetSolNodenum(SCIP *scip, SCIP_SOL *sol)
Definition scip_sol.c:2221
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition scip_sol.c:2936
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition scip_solve.c:232
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
SCIP_RETCODE SCIPsolve(SCIP *scip)
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:24174
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition var.c:24152
unsigned int SCIPinitializeRandomSeed(SCIP *scip, unsigned int initialseedvalue)
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition misc.c:10223
#define HEUR_TIMING
return SCIP_OKAY
#define HEUR_FREQOFS
#define HEUR_DESC
#define HEUR_DISPCHAR
#define HEUR_MAXDEPTH
#define HEUR_PRIORITY
#define HEUR_NAME
#define HEUR_FREQ
#define HEUR_USESSUBSCIP
SCIPfreeRandom(scip, &heurdata->randnumgen)
int selection
#define DEFAULT_NODESQUOT
Definition heur_alns.c:90
#define DEFAULT_COPYCUTS
Definition heur_alns.c:147
#define DEFAULT_NODESOFS
Definition heur_clique.c:94
#define DEFAULT_LPLIMFAC
#define DEFAULT_NWAITINGNODES
#define DEFAULT_NUSEDSOLS
struct SolTuple SOLTUPLE
#define DEFAULT_DONTWAITATROOT
#define HASHSIZE_SOLS
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 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)
#define DEFAULT_BESTSOLLIMIT
static void updateFailureStatistic(SCIP *scip, SCIP_HEURDATA *heurdata)
LNS heuristic that tries to combine several feasible solutions.
SCIP_Bool cutoff
SCIPcreateRandom(scip, &heurdata->randnumgen, DEFAULT_RANDSEED, TRUE))
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
heurdata usednodes
Definition heur_locks.c:163
static SCIP_VAR ** vars
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_Eventhdlr SCIP_EVENTHDLR
Definition type_event.h:159
struct SCIP_EventData SCIP_EVENTDATA
Definition type_event.h:179
#define SCIP_DECL_EVENTEXEC(x)
Definition type_event.h:259
#define SCIP_EVENTTYPE_LPSOLVED
Definition type_event.h:102
#define SCIP_DECL_HEURCOPY(x)
Definition type_heur.h:97
struct SCIP_HeurData SCIP_HEURDATA
Definition type_heur.h:77
struct SCIP_Heur SCIP_HEUR
Definition type_heur.h:76
#define SCIP_DECL_HEURINIT(x)
Definition type_heur.h:113
#define SCIP_DECL_HEUREXIT(x)
Definition type_heur.h:121
#define SCIP_DECL_HEURFREE(x)
Definition type_heur.h:105
#define SCIP_DECL_HEUREXEC(x)
Definition type_heur.h:163
struct SCIP_HashMap SCIP_HASHMAP
Definition type_misc.h:106
#define SCIP_DECL_HASHKEYEQ(x)
Definition type_misc.h:195
struct SCIP_RandNumGen SCIP_RANDNUMGEN
Definition type_misc.h:127
#define SCIP_DECL_HASHGETKEY(x)
Definition type_misc.h:192
#define SCIP_DECL_HASHKEYVAL(x)
Definition type_misc.h:198
struct SCIP_HashTable SCIP_HASHTABLE
Definition type_misc.h:88
@ SCIP_PARAMSETTING_OFF
@ SCIP_PARAMSETTING_FAST
@ 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
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Sol SCIP_SOL
Definition type_sol.h:57
struct SCIP_Var SCIP_VAR
Definition type_var.h:166