Scippy

SCIP

Solving Constraint Integer Programs

heur_alns.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2018 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file heur_alns.c
17  * @brief Adaptive large neighborhood search heuristic that orchestrates popular LNS heuristics
18  * @author Gregor Hendel
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include <assert.h>
24 #include <string.h>
25 #if defined(_WIN32) || defined(_WIN64)
26 #else
27 #include <strings.h> /*lint --e{766}*/
28 #endif
29 #include "scip/heur_alns.h"
30 #include "scipdefplugins.h"
31 
32 #define HEUR_NAME "alns"
33 #define HEUR_DESC "Large neighborhood search heuristic that orchestrates the popular neighborhoods Local Branching, RINS, RENS, DINS etc."
34 #define HEUR_DISPCHAR 'L'
35 #define HEUR_PRIORITY -1100500
36 #define HEUR_FREQ 20
37 #define HEUR_FREQOFS 0
38 #define HEUR_MAXDEPTH -1
39 #define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
40 #define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
41 
42 #define NNEIGHBORHOODS 8
43 
44 /*
45  * limit parameters for sub-SCIPs
46  */
47 #define DEFAULT_NODESQUOT 0.1
48 #define DEFAULT_NODESOFFSET 500LL
49 #define DEFAULT_NSOLSLIM 3
50 #define DEFAULT_MINNODES 50LL
51 #define DEFAULT_MAXNODES 5000LL
52 #define DEFAULT_WAITINGNODES 25LL /**< number of nodes since last incumbent solution that the heuristic should wait */
53 #define DEFAULT_TARGETNODEFACTOR 1.5
54 #define DEFAULT_STALLNODEFACTOR 0.25
55 #define LPLIMFAC 4.0
56 
57 /*
58  * parameters for the minimum improvement
59  */
60 #define DEFAULT_MINIMPROVELOW 0.0001
61 #define DEFAULT_MINIMPROVEHIGH 0.1
62 #define MINIMPROVEFAC 1.5
63 #define DEFAULT_STARTMINIMPROVE 0.05
64 #define DEFAULT_ADJUSTMINIMPROVE TRUE
65 
66 /*
67  * bandit algorithm parameters
68  */
69 #define DEFAULT_BESTSOLWEIGHT 1
70 #define DEFAULT_BANDITALGO 'u' /**< the default bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy */
71 #define DEFAULT_GAMMA 0.2 /**< default weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3 */
72 #define DEFAULT_BETA 0.0 /**< default reward offset between 0 and 1 at every observation for exp3 */
73 #define DEFAULT_REWARDCONTROL 0.8 /**< reward control to increase the weight of the simple solution indicator and decrease the weight of the closed gap reward */
74 #define DEFAULT_SCALEBYEFFORT TRUE /**< should the reward be scaled by the effort? */
75 #define DEFAULT_EPS 0.5 /**< increase exploration in epsilon-greedy bandit algorithm */
76 #define DEFAULT_RESETWEIGHTS TRUE /**< should the bandit algorithms be reset when a new problem is read? */
77 #define DEFAULT_SUBSCIPRANDSEEDS FALSE /**< should random seeds of sub-SCIPs be altered to increase diversification? */
78 #define DEFAULT_ALPHA 0.2 /**< parameter to increase the confidence width in UCB */
79 #define DEFAULT_REWARDBASELINE 0.5 /**< the reward baseline to separate successful and failed calls */
80 #define DEFAULT_FIXTOL 0.1 /**< tolerance by which the fixing rate may be missed/exceeded without generic (unfixing) */
81 #define DEFAULT_USELOCALREDCOST FALSE /**< should local reduced costs be used for generic (un)fixing? */
82 
83 /*
84  * parameters to control variable fixing
85  */
86 #define DEFAULT_USEREDCOST TRUE /**< should reduced cost scores be used for variable priorization? */
87 #define DEFAULT_USEPSCOST TRUE /**< should pseudo cost scores be used for variable priorization? */
88 #define DEFAULT_USEDISTANCES TRUE /**< should distances from fixed variables be used for variable priorization */
89 #define DEFAULT_DOMOREFIXINGS TRUE /**< should the ALNS heuristic do more fixings by itself based on variable prioritization
90  * until the target fixing rate is reached? */
91 #define DEFAULT_ADJUSTFIXINGRATE TRUE /**< should the heuristic adjust the target fixing rate based on the success? */
92 #define FIXINGRATE_DECAY 0.75 /**< geometric decay for fixing rate adjustments */
93 #define FIXINGRATE_STARTINC 0.2 /**< initial increment value for fixing rate */
94 #define DEFAULT_USESUBSCIPHEURS FALSE /**< should the heuristic activate other sub-SCIP heuristics during its search? */
95 #define DEFAULT_COPYCUTS FALSE /**< should cutting planes be copied to the sub-SCIP? */
96 #define DEFAULT_REWARDFILENAME "-" /**< file name to store all rewards and the selection of the bandit */
97 
98 /* individual random seeds */
99 #define DEFAULT_SEED 113
100 #define MUTATIONSEED 121
101 #define CROSSOVERSEED 321
103 /* individual neighborhood parameters */
104 #define DEFAULT_MINFIXINGRATE_RENS 0.3
105 #define DEFAULT_MAXFIXINGRATE_RENS 0.7
106 #define DEFAULT_ACTIVE_RENS TRUE
107 #define DEFAULT_PRIORITY_RENS 1.0
109 #define DEFAULT_MINFIXINGRATE_RINS 0.2
110 #define DEFAULT_MAXFIXINGRATE_RINS 0.6
111 #define DEFAULT_ACTIVE_RINS TRUE
112 #define DEFAULT_PRIORITY_RINS 1.0
114 #define DEFAULT_MINFIXINGRATE_MUTATION 0.4
115 #define DEFAULT_MAXFIXINGRATE_MUTATION 0.9
116 #define DEFAULT_ACTIVE_MUTATION TRUE
117 #define DEFAULT_PRIORITY_MUTATION 1.0
119 #define DEFAULT_MINFIXINGRATE_LOCALBRANCHING 0.0
120 #define DEFAULT_MAXFIXINGRATE_LOCALBRANCHING 0.9
121 #define DEFAULT_ACTIVE_LOCALBRANCHING TRUE
122 #define DEFAULT_PRIORITY_LOCALBRANCHING 1.0
124 #define DEFAULT_MINFIXINGRATE_PROXIMITY 0.0
125 #define DEFAULT_MAXFIXINGRATE_PROXIMITY 0.9
126 #define DEFAULT_ACTIVE_PROXIMITY TRUE
127 #define DEFAULT_PRIORITY_PROXIMITY 1.0
129 #define DEFAULT_MINFIXINGRATE_CROSSOVER 0.4
130 #define DEFAULT_MAXFIXINGRATE_CROSSOVER 0.9
131 #define DEFAULT_ACTIVE_CROSSOVER TRUE
132 #define DEFAULT_PRIORITY_CROSSOVER 1.0
134 #define DEFAULT_MINFIXINGRATE_ZEROOBJECTIVE 0.0
135 #define DEFAULT_MAXFIXINGRATE_ZEROOBJECTIVE 0.9
136 #define DEFAULT_ACTIVE_ZEROOBJECTIVE TRUE
137 #define DEFAULT_PRIORITY_ZEROOBJECTIVE 1.0
139 #define DEFAULT_MINFIXINGRATE_DINS 0.1
140 #define DEFAULT_MAXFIXINGRATE_DINS 0.5
141 #define DEFAULT_ACTIVE_DINS TRUE
142 #define DEFAULT_PRIORITY_DINS 1.0
144 #define DEFAULT_NSOLS_CROSSOVER 2 /**< parameter for the number of solutions that crossover should combine */
145 #define DEFAULT_NPOOLSOLS_DINS 5 /**< number of pool solutions where binary solution values must agree */
147 /* event handler properties */
148 #define EVENTHDLR_NAME "Alns"
149 #define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
150 #define SCIP_EVENTTYPE_ALNS (SCIP_EVENTTYPE_LPSOLVED | SCIP_EVENTTYPE_SOLFOUND | SCIP_EVENTTYPE_BESTSOLFOUND)
152 /* properties of the ALNS neighborhood statistics table */
153 #define TABLE_NAME_NEIGHBORHOOD "neighborhood"
154 #define TABLE_DESC_NEIGHBORHOOD "ALNS neighborhood statistics"
155 #define TABLE_POSITION_NEIGHBORHOOD 12500 /**< the position of the statistics table */
156 #define TABLE_EARLIEST_STAGE_NEIGHBORHOOD SCIP_STAGE_TRANSFORMED /**< output of the statistics table is only printed from this stage onwards */
158 /*
159  * Data structures
160  */
161 
162 /*
163  * additional neighborhood data structures
164  */
165 
166 
167 typedef struct data_crossover DATA_CROSSOVER; /**< crossover neighborhood data structure */
169 typedef struct data_mutation DATA_MUTATION; /**< mutation neighborhood data structure */
171 typedef struct data_dins DATA_DINS; /**< dins neighborhood data structure */
173 typedef struct NH_FixingRate NH_FIXINGRATE; /** fixing rate data structure */
175 typedef struct NH_Stats NH_STATS; /**< neighborhood statistics data structure */
177 typedef struct Nh NH; /**< neighborhood data structure */
179 
180 /*
181  * variable priorization data structure for sorting
182  */
183 typedef struct VarPrio VARPRIO;
185 /** callback to collect variable fixings of neighborhood */
186  #define DECL_VARFIXINGS(x) SCIP_RETCODE x ( \
187  SCIP* scip, /**< SCIP data structure */ \
188  NH* neighborhood, /**< ALNS neighborhood data structure */ \
189  SCIP_VAR** varbuf, /**< buffer array to collect variables to fix */\
190  SCIP_Real* valbuf, /**< buffer array to collect fixing values */ \
191  int* nfixings, /**< pointer to store the number of fixings */ \
192  SCIP_RESULT* result /**< result pointer */ \
193  )
194 
195 /** callback for subproblem changes other than variable fixings
196  *
197  * this callback can be used to further modify the subproblem by changes other than variable fixings.
198  * Typical modifications include restrictions of variable domains, the formulation of additional constraints,
199  * or changed objective coefficients.
200  *
201  * The callback should set the \p success pointer to indicate whether it was successful with its modifications or not.
202  */
203 #define DECL_CHANGESUBSCIP(x) SCIP_RETCODE x ( \
204  SCIP* sourcescip, /**< source SCIP data structure */\
205  SCIP* targetscip, /**< target SCIP data structure */\
206  SCIP_VAR** subvars, /**< array of targetscip variables in the same order as the source SCIP variables */\
207  int* ndomchgs, /**< pointer to store the number of performed domain changes */\
208  int* nchgobjs, /**< pointer to store the number of changed objective coefficients */ \
209  int* naddedconss, /**< pointer to store the number of additional constraints */\
210  SCIP_Bool* success /**< pointer to store if the sub-MIP was successfully adjusted */\
211  )
212 
213 /** optional initialization callback for neighborhoods when a new problem is read */
214 #define DECL_NHINIT(x) SCIP_RETCODE x ( \
215  SCIP* scip, /**< SCIP data structure */ \
216  NH* neighborhood /**< neighborhood data structure */ \
217  )
218 
219 /** deinitialization callback for neighborhoods when exiting a problem */
220 #define DECL_NHEXIT(x) SCIP_RETCODE x ( \
221  SCIP* scip, /**< SCIP data structure */ \
222  NH* neighborhood /**< neighborhood data structure */ \
223  )
224 
225 /** deinitialization callback for neighborhoods before SCIP is freed */
226 #define DECL_NHFREE(x) SCIP_RETCODE x ( \
227  SCIP* scip, /**< SCIP data structure */ \
228  NH* neighborhood /**< neighborhood data structure */ \
229  )
230 
231 /** callback function to return a feasible reference solution for further fixings
232  *
233  * The reference solution should be stored in the \p solptr.
234  * The \p result pointer can be used to indicate either
235  *
236  * - SCIP_SUCCESS or
237  * - SCIP_DIDNOTFIND
238  */
239 #define DECL_NHREFSOL(x) SCIP_RETCODE x ( \
240  SCIP* scip, /**< SCIP data structure */ \
241  NH* neighborhood, /**< neighborhood data structure */ \
242  SCIP_SOL** solptr, /**< pointer to store the reference solution */ \
243  SCIP_RESULT* result /**< pointer to indicate the callback success whether a reference solution is available */ \
244  )
245 
246 /** callback function to deactivate neighborhoods on problems where they are irrelevant */
247 #define DECL_NHDEACTIVATE(x) SCIP_RETCODE x (\
248  SCIP* scip, /**< SCIP data structure */ \
249  SCIP_Bool* deactivate /**< pointer to store whether the neighborhood should be deactivated (TRUE) for an instance */ \
250  )
251 
252 /** sub-SCIP status code enumerator */
253 enum HistIndex
254 {
255  HIDX_OPT = 0, /**< sub-SCIP was solved to optimality */
256  HIDX_USR = 1, /**< sub-SCIP was user interrupted */
257  HIDX_NODELIM = 2, /**< sub-SCIP reached the node limit */
258  HIDX_STALLNODE = 3, /**< sub-SCIP reached the stall node limit */
259  HIDX_INFEAS = 4, /**< sub-SCIP was infeasible */
260  HIDX_SOLLIM = 5, /**< sub-SCIP reached the solution limit */
261  HIDX_OTHER = 6 /**< sub-SCIP reached none of the above codes */
262 };
263 typedef enum HistIndex HISTINDEX;
264 #define NHISTENTRIES 7
266 
267 /** statistics for a neighborhood */
268 struct NH_Stats
269 {
270  SCIP_CLOCK* setupclock; /**< clock for sub-SCIP setup time */
271  SCIP_CLOCK* submipclock; /**< clock for the sub-SCIP solve */
272  SCIP_Longint usednodes; /**< total number of used nodes */
273  SCIP_Real oldupperbound; /**< upper bound before the sub-SCIP started */
274  int nruns; /**< number of runs of a neighborhood */
275  int nrunsbestsol; /**< number of runs that produced a new incumbent */
276  SCIP_Longint nsolsfound; /**< the total number of solutions found */
277  SCIP_Longint nbestsolsfound; /**< the total number of improving solutions found */
278  int nfixings; /**< the number of fixings in one run */
279  int statushist[NHISTENTRIES]; /**< array to count sub-SCIP statuses */
280 };
281 
282 
283 /** fixing rate data structure to control the amount of target fixings of a neighborhood */
284 struct NH_FixingRate
285 {
286  SCIP_Real minfixingrate; /**< the minimum fixing rate */
287  SCIP_Real targetfixingrate; /**< the current target fixing rate */
288  SCIP_Real increment; /**< the current increment by which the target fixing rate is in-/decreased */
289  SCIP_Real maxfixingrate; /**< the maximum fixing rate */
290 };
291 
292 /** neighborhood data structure with callbacks, statistics, fixing rate */
293 struct Nh
294 {
295  char* name; /**< the name of this neighborhood */
296  NH_FIXINGRATE fixingrate; /**< fixing rate for this neighborhood */
297  NH_STATS stats; /**< statistics for this neighborhood */
298  DECL_VARFIXINGS ((*varfixings)); /**< variable fixings callback for this neighborhood */
299  DECL_CHANGESUBSCIP ((*changesubscip)); /**< callback for subproblem changes other than variable fixings */
300  DECL_NHINIT ((*nhinit)); /**< initialization callback when a new problem is read */
301  DECL_NHEXIT ((*nhexit)); /**< deinitialization callback when exiting a problem */
302  DECL_NHFREE ((*nhfree)); /**< deinitialization callback before SCIP is freed */
303  DECL_NHREFSOL ((*nhrefsol)); /**< callback function to return a reference solution for further fixings, or NULL */
304  DECL_NHDEACTIVATE ((*nhdeactivate)); /**< callback function to deactivate neighborhoods on problems where they are irrelevant, or NULL if it is always active */
305  SCIP_Bool active; /**< is this neighborhood active or not? */
306  SCIP_Real priority; /**< positive call priority to initialize bandit algorithms */
307  union
308  {
309  DATA_MUTATION* mutation; /**< mutation data */
310  DATA_CROSSOVER* crossover; /**< crossover data */
311  DATA_DINS* dins; /**< dins data */
312  } data; /**< data object for neighborhood specific data */
313 };
314 
315 /** mutation neighborhood data structure */
316 struct data_mutation
317 {
318  SCIP_RANDNUMGEN* rng; /**< random number generator */
319 };
320 
321 /** crossover neighborhood data structure */
322 struct data_crossover
323 {
324  int nsols; /**< the number of solutions that crossover should combine */
325  SCIP_RANDNUMGEN* rng; /**< random number generator to draw from the solution pool */
326  SCIP_SOL* selsol; /**< best selected solution by crossover as reference point */
327 };
328 
329 /** dins neighborhood data structure */
330 struct data_dins
331 {
332  int npoolsols; /**< number of pool solutions where binary solution values must agree */
333 };
334 
335 /** primal heuristic data */
336 struct SCIP_HeurData
337 {
338  NH** neighborhoods; /**< array of neighborhoods */
339  SCIP_BANDIT* bandit; /**< bandit algorithm */
340  char* rewardfilename; /**< file name to store all rewards and the selection of the bandit */
341  FILE* rewardfile; /**< reward file pointer, or NULL */
342  SCIP_Longint nodesoffset; /**< offset added to the nodes budget */
343  SCIP_Longint maxnodes; /**< maximum number of nodes in a single sub-SCIP */
344  SCIP_Longint targetnodes; /**< targeted number of nodes to start a sub-SCIP */
345  SCIP_Longint minnodes; /**< minimum number of nodes required to start a sub-SCIP */
346  SCIP_Longint usednodes; /**< total number of nodes already spent in sub-SCIPs */
347  SCIP_Longint waitingnodes; /**< number of nodes since last incumbent solution that the heuristic should wait */
348  SCIP_Real nodesquot; /**< fraction of nodes compared to the main SCIP for budget computation */
349  SCIP_Real startminimprove; /**< initial factor by which ALNS should at least improve the incumbent */
350  SCIP_Real minimprovelow; /**< lower threshold for the minimal improvement over the incumbent */
351  SCIP_Real minimprovehigh; /**< upper bound for the minimal improvement over the incumbent */
352  SCIP_Real minimprove; /**< factor by which ALNS should at least improve the incumbent */
353  SCIP_Real lplimfac; /**< limit fraction of LPs per node to interrupt sub-SCIP */
354  SCIP_Real exp3_gamma; /**< weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3 */
355  SCIP_Real exp3_beta; /**< reward offset between 0 and 1 at every observation for exp3 */
356  SCIP_Real epsgreedy_eps; /**< increase exploration in epsilon-greedy bandit algorithm */
357  SCIP_Real ucb_alpha; /**< parameter to increase the confidence width in UCB */
358  SCIP_Real rewardcontrol; /**< reward control to increase the weight of the simple solution indicator
359  * and decrease the weight of the closed gap reward */
360  SCIP_Real targetnodefactor; /**< factor by which target node number is increased/decreased at every adjustment */
361  SCIP_Real stallnodefactor; /**< stall node limit as a fraction of total node limit */
362  SCIP_Real rewardbaseline; /**< the reward baseline to separate successful and failed calls */
363  SCIP_Real fixtol; /**< tolerance by which the fixing rate may be missed/exceeded without generic (unfixing) */
364  int nneighborhoods; /**< number of neighborhoods */
365  int nactiveneighborhoods;/**< number of active neighborhoods */
366  int ninitneighborhoods; /**< neighborhoods that were used at least one time */
367  int nsolslim; /**< limit on the number of improving solutions in a sub-SCIP call */
368  int seed; /**< initial random seed for bandit algorithms and random decisions by neighborhoods */
369  int currneighborhood; /**< index of currently selected neighborhood */
370  int ndelayedcalls; /**< the number of delayed calls */
371  char banditalgo; /**< the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy */
372  SCIP_Bool useredcost; /**< should reduced cost scores be used for variable prioritization? */
373  SCIP_Bool usedistances; /**< should distances from fixed variables be used for variable prioritization */
374  SCIP_Bool usepscost; /**< should pseudo cost scores be used for variable prioritization? */
375  SCIP_Bool domorefixings; /**< should the ALNS heuristic do more fixings by itself based on variable prioritization
376  * until the target fixing rate is reached? */
377  SCIP_Bool adjustfixingrate; /**< should the heuristic adjust the target fixing rate based on the success? */
378  SCIP_Bool usesubscipheurs; /**< should the heuristic activate other sub-SCIP heuristics during its search? */
379  SCIP_Bool adjustminimprove; /**< should the factor by which the minimum improvement is bound be dynamically updated? */
380  SCIP_Bool resetweights; /**< should the bandit algorithms be reset when a new problem is read? */
381  SCIP_Bool subsciprandseeds; /**< should random seeds of sub-SCIPs be altered to increase diversification? */
382  SCIP_Bool scalebyeffort; /**< should the reward be scaled by the effort? */
383  SCIP_Bool copycuts; /**< should cutting planes be copied to the sub-SCIP? */
384  SCIP_Bool uselocalredcost; /**< should local reduced costs be used for generic (un)fixing? */
385 };
386 
387 /** event handler data */
388 struct SCIP_EventData
389 {
390  SCIP_VAR** subvars; /**< the variables of the subproblem */
391  SCIP* sourcescip; /**< original SCIP data structure */
392  SCIP_HEUR* heur; /**< alns heuristic structure */
393  SCIP_Longint nodelimit; /**< node limit of the run */
394  SCIP_Real lplimfac; /**< limit fraction of LPs per node to interrupt sub-SCIP */
395  NH_STATS* runstats; /**< run statistics for the current neighborhood */
396  SCIP_Bool allrewardsmode; /**< true if solutions should only be checked for reward comparisons */
397 };
398 
399 /** represents limits for the sub-SCIP solving process */
400 struct SolveLimits
401 {
402  SCIP_Longint nodelimit; /**< maximum number of solving nodes for the sub-SCIP */
403  SCIP_Real memorylimit; /**< memory limit for the sub-SCIP */
404  SCIP_Real timelimit; /**< time limit for the sub-SCIP */
405  SCIP_Longint stallnodes; /**< maximum number of nodes without (primal) stalling */
406 };
407 
408 typedef struct SolveLimits SOLVELIMITS;
410 /** data structure that can be used for variable prioritization for additional fixings */
411 struct VarPrio
412 {
413  SCIP* scip; /**< SCIP data structure */
414  SCIP_Real* randscores; /**< random scores for prioritization */
415  int* distances; /**< breadth-first distances from already fixed variables */
416  SCIP_Real* redcostscores; /**< reduced cost scores for fixing a variable to a reference value */
417  SCIP_Real* pscostscores; /**< pseudocost scores for fixing a variable to a reference value */
418  unsigned int useredcost:1; /**< should reduced cost scores be used for variable prioritization? */
419  unsigned int usedistances:1; /**< should distances from fixed variables be used for variable prioritization */
420  unsigned int usepscost:1; /**< should pseudo cost scores be used for variable prioritization? */
421 };
422 
423 /*
424  * Local methods
425  */
426 
427 /** Reset target fixing rate */
428 static
430  SCIP* scip, /**< SCIP data structure */
431  NH_FIXINGRATE* fixingrate /**< heuristic fixing rate */
432  )
433 {
434  assert(scip != NULL);
435  assert(fixingrate != NULL);
436  fixingrate->increment = FIXINGRATE_STARTINC;
437 
438  /* use the middle between the minimum and the maximum fixing rate */
439  fixingrate->targetfixingrate = 0.5 * (fixingrate->minfixingrate + fixingrate->maxfixingrate);
440 
441  return SCIP_OKAY;
442 }
443 
444 /** reset the currently active neighborhood */
445 static
447  SCIP_HEURDATA* heurdata
448  )
449 {
450  assert(heurdata != NULL);
451  heurdata->currneighborhood = -1;
452  heurdata->ndelayedcalls = 0;
453 }
454 
455 /** update increment for fixing rate */
456 static
458  NH_FIXINGRATE* fx /**< fixing rate */
459  )
460 {
462  fx->increment = MAX(fx->increment, 0.01);
463 }
464 
465 
466 /** increase fixing rate
467  *
468  * decrease also the rate by which the target fixing rate is adjusted
469  */
470 static
471 void increaseFixingRate(
472  NH_FIXINGRATE* fx /**< fixing rate */
473  )
474 {
475  fx->targetfixingrate += fx->increment;
476  fx->targetfixingrate = MIN(fx->targetfixingrate, fx->maxfixingrate);
478 }
479 
480 /** decrease fixing rate
481  *
482  * decrease also the rate by which the target fixing rate is adjusted
483  */
484 static
485 void decreaseFixingRate(
486  NH_FIXINGRATE* fx /**< fixing rate */
487  )
488 {
489  fx->targetfixingrate -= fx->increment;
492 }
493 
494 /** update fixing rate based on the results of the current run */
495 static
496 void updateFixingRate(
497  SCIP* scip, /**< SCIP data structure */
498  NH* neighborhood, /**< neighborhood */
499  SCIP_STATUS subscipstatus, /**< status of the sub-SCIP run */
500  NH_STATS* runstats /**< run statistics for this run */
501  )
502 {
503  NH_FIXINGRATE* fx;
504 
505  fx = &neighborhood->fixingrate;
506 
507  switch (subscipstatus) {
508  case SCIP_STATUS_OPTIMAL:
512  /* decrease the fixing rate (make subproblem harder) */
513  decreaseFixingRate(fx);
514  break;
518  /* increase the fixing rate (make the subproblem easier) only if no solution was found */
519  if( runstats->nbestsolsfound <= 0 )
520  increaseFixingRate(fx);
521  break;
522  /* fall through cases to please lint */
523  case SCIP_STATUS_UNKNOWN:
531  default:
532  break;
533  }
534 }
535 
536 /** increase target node limit */
537 static
539  SCIP_HEURDATA* heurdata /**< heuristic data */
540  )
541 {
542  heurdata->targetnodes = (SCIP_Longint)(heurdata->targetnodes * heurdata->targetnodefactor);
543  heurdata->targetnodes = MIN(heurdata->targetnodes, heurdata->maxnodes);
544 }
545 
546 /** decrease target node limit */
547 static
549  SCIP_HEURDATA* heurdata /**< heuristic data */
550  )
551 {
552  heurdata->targetnodes = (SCIP_Longint)(heurdata->targetnodes / heurdata->targetnodefactor);
553  heurdata->targetnodes = MAX(heurdata->targetnodes, heurdata->minnodes);
554 }
555 
556 /** reset target node limit */
557 static
559  SCIP_HEURDATA* heurdata /**< heuristic data */
560  )
561 {
562  heurdata->targetnodes = heurdata->minnodes;
563 }
564 
565 /** update target node limit based on the current run results */
566 static
568  SCIP_HEURDATA* heurdata, /**< heuristic data */
569  NH_STATS* runstats, /**< statistics of the run */
570  SCIP_STATUS subscipstatus /**< status of the sub-SCIP run */
571  )
572 {
573  switch (subscipstatus) {
574  case SCIP_STATUS_OPTIMAL:
579  /* the subproblem was easy enough -> use smaller limit to speed up SCIP */
580  decreaseTargetNodeLimit(heurdata);
581  break;
584  /* the subproblem could be explored more */
585  if( runstats->nbestsolsfound == 0 )
586  increaseTargetNodeLimit(heurdata);
587  break;
589  case SCIP_STATUS_UNKNOWN:
596  break;
597  default:
598  break;
599  }
600 }
601 
602 /** reset the minimum improvement for the sub-SCIPs */
603 static
605  SCIP_HEURDATA* heurdata /**< heuristic data */
606  )
607 {
608  assert(heurdata != NULL);
609  heurdata->minimprove = heurdata->startminimprove;
610 }
611 
612 /** increase minimum improvement for the sub-SCIPs */
613 static
615  SCIP_HEURDATA* heurdata /**< heuristic data */
616  )
617 {
618  assert(heurdata != NULL);
619 
620  heurdata->minimprove *= MINIMPROVEFAC;
621  heurdata->minimprove = MIN(heurdata->minimprove, heurdata->minimprovehigh);
622 }
623 
624 /** decrease the minimum improvement for the sub-SCIPs */
625 static
627  SCIP_HEURDATA* heurdata /**< heuristic data */
628  )
629 {
630  assert(heurdata != NULL);
631 
632  heurdata->minimprove /= MINIMPROVEFAC;
633  SCIPdebugMessage("%.4f", heurdata->minimprovelow);
634  heurdata->minimprove = MAX(heurdata->minimprove, heurdata->minimprovelow);
635 }
636 
637 /** update the minimum improvement based on the status of the sub-SCIP */
638 static
640  SCIP_HEURDATA* heurdata, /**< heuristic data */
641  SCIP_STATUS subscipstatus, /**< status of the sub-SCIP run */
642  NH_STATS* runstats /**< run statistics for this run */
643  )
644 {
645  assert(heurdata != NULL);
646 
647  /* if the sub-SCIP status was infeasible, we rather want to make the sub-SCIP easier
648  * with a smaller minimum improvement.
649  *
650  * If a solution limit was reached, we may, set it higher.
651  */
652  switch (subscipstatus) {
655  /* subproblem was infeasible, probably due to the minimum improvement -> decrease minimum improvement */
656  decreaseMinimumImprovement(heurdata);
657 
658  break;
661  case SCIP_STATUS_OPTIMAL:
662  /* subproblem could be optimally solved -> try higher minimum improvement */
663  increaseMinimumImprovement(heurdata);
664  break;
668  /* subproblem was too hard, decrease minimum improvement */
669  if( runstats->nbestsolsfound <= 0 )
670  decreaseMinimumImprovement(heurdata);
671  break;
672  case SCIP_STATUS_UNKNOWN:
679  default:
680  break;
681  }
682 }
683 
684 /** Reset neighborhood statistics */
685 static
687  SCIP* scip, /**< SCIP data structure */
688  NH_STATS* stats /**< neighborhood statistics */
689  )
690 {
691  assert(scip != NULL);
692  assert(stats != NULL);
693 
694  stats->nbestsolsfound = 0;
695  stats->nruns = 0;
696  stats->nrunsbestsol = 0;
697  stats->nsolsfound = 0;
698  stats->usednodes = 0L;
699  stats->nfixings = 0L;
700 
702 
703  SCIP_CALL( SCIPresetClock(scip, stats->setupclock) );
704  SCIP_CALL( SCIPresetClock(scip, stats->submipclock) );
705 
706  return SCIP_OKAY;
707 }
708 
709 /** create a neighborhood of the specified name and include it into the ALNS heuristic */
710 static
712  SCIP* scip, /**< SCIP data structure */
713  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS heuristic */
714  NH** neighborhood, /**< pointer to store the neighborhood */
715  const char* name, /**< name for this neighborhood */
716  SCIP_Real minfixingrate, /**< default value for minfixingrate parameter of this neighborhood */
717  SCIP_Real maxfixingrate, /**< default value for maxfixingrate parameter of this neighborhood */
718  SCIP_Bool active, /**< default value for active parameter of this neighborhood */
719  SCIP_Real priority, /**< positive call priority to initialize bandit algorithms */
720  DECL_VARFIXINGS ((*varfixings)), /**< variable fixing callback for this neighborhood, or NULL */
721  DECL_CHANGESUBSCIP ((*changesubscip)), /**< subscip changes callback for this neighborhood, or NULL */
722  DECL_NHINIT ((*nhinit)), /**< initialization callback for neighborhood, or NULL */
723  DECL_NHEXIT ((*nhexit)), /**< deinitialization callback for neighborhood, or NULL */
724  DECL_NHFREE ((*nhfree)), /**< deinitialization callback before SCIP is freed, or NULL */
725  DECL_NHREFSOL ((*nhrefsol)), /**< callback function to return a reference solution for further fixings, or NULL */
726  DECL_NHDEACTIVATE ((*nhdeactivate)) /**< callback function to deactivate neighborhoods on problems where they are irrelevant, or NULL if neighborhood is always active */
727  )
728 {
729  char paramname[SCIP_MAXSTRLEN];
730 
731  assert(scip != NULL);
732  assert(heurdata != NULL);
733  assert(neighborhood != NULL);
734  assert(name != NULL);
735 
736  SCIP_CALL( SCIPallocBlockMemory(scip, neighborhood) );
737  assert(*neighborhood != NULL);
738 
739  SCIP_ALLOC( BMSduplicateMemoryArray(&(*neighborhood)->name, name, strlen(name)+1) );
740 
741  SCIP_CALL( SCIPcreateClock(scip, &(*neighborhood)->stats.setupclock) );
742  SCIP_CALL( SCIPcreateClock(scip, &(*neighborhood)->stats.submipclock) );
743 
744  (*neighborhood)->changesubscip = changesubscip;
745  (*neighborhood)->varfixings = varfixings;
746  (*neighborhood)->nhinit = nhinit;
747  (*neighborhood)->nhexit = nhexit;
748  (*neighborhood)->nhfree = nhfree;
749  (*neighborhood)->nhrefsol = nhrefsol;
750  (*neighborhood)->nhdeactivate = nhdeactivate;
751 
752  /* add parameters for this neighborhood */
753  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/minfixingrate", name);
754  SCIP_CALL( SCIPaddRealParam(scip, paramname, "minimum fixing rate for this neighborhood",
755  &(*neighborhood)->fixingrate.minfixingrate, TRUE, minfixingrate, 0.0, 1.0, NULL, NULL) );
756  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/maxfixingrate", name);
757  SCIP_CALL( SCIPaddRealParam(scip, paramname, "maximum fixing rate for this neighborhood",
758  &(*neighborhood)->fixingrate.maxfixingrate, TRUE, maxfixingrate, 0.0, 1.0, NULL, NULL) );
759  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/active", name);
760  SCIP_CALL( SCIPaddBoolParam(scip, paramname, "is this neighborhood active?",
761  &(*neighborhood)->active, TRUE, active, NULL, NULL) );
762  (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/alns/%s/priority", name);
763  SCIP_CALL( SCIPaddRealParam(scip, paramname, "positive call priority to initialize bandit algorithms",
764  &(*neighborhood)->priority, TRUE, priority, 1e-2, 1.0, NULL, NULL) );
765 
766  /* add the neighborhood to the ALNS heuristic */
767  heurdata->neighborhoods[heurdata->nneighborhoods++] = (*neighborhood);
768 
769  return SCIP_OKAY;
770 }
771 
772 /** release all data and free neighborhood */
773 static
775  SCIP* scip, /**< SCIP data structure */
776  NH** neighborhood /**< pointer to neighborhood that should be freed */
777  )
778 {
779  NH* nhptr;
780  assert(scip != NULL);
781  assert(neighborhood != NULL);
782 
783  nhptr = *neighborhood;
784  assert(nhptr != NULL);
785 
786  BMSfreeMemoryArray(&nhptr->name);
787 
788  /* release further, neighborhood specific data structures */
789  if( nhptr->nhfree != NULL )
790  {
791  SCIP_CALL( nhptr->nhfree(scip, nhptr) );
792  }
793 
794  SCIP_CALL( SCIPfreeClock(scip, &nhptr->stats.setupclock) );
795  SCIP_CALL( SCIPfreeClock(scip, &nhptr->stats.submipclock) );
796 
797  SCIPfreeBlockMemory(scip, neighborhood);
798  *neighborhood = NULL;
799 
800  return SCIP_OKAY;
801 }
802 
803 /** initialize neighborhood specific data */
804 static
806  SCIP* scip, /**< SCIP data structure */
807  NH* neighborhood /**< neighborhood to initialize */
808  )
809 {
810  assert(scip != NULL);
811  assert(neighborhood != NULL);
812 
813  /* call the init callback of the neighborhood */
814  if( neighborhood->nhinit != NULL )
815  {
816  SCIP_CALL( neighborhood->nhinit(scip, neighborhood) );
817  }
818 
819  return SCIP_OKAY;
820 }
821 
822 /** deinitialize neighborhood specific data */
823 static
825  SCIP* scip, /**< SCIP data structure */
826  NH* neighborhood /**< neighborhood to initialize */
827  )
828 {
829  assert(scip != NULL);
830  assert(neighborhood != NULL);
831 
832  if( neighborhood->nhexit != NULL )
833  {
834  SCIP_CALL( neighborhood->nhexit(scip, neighborhood) );
835  }
836 
837  return SCIP_OKAY;
838 }
839 
840 /** creates a new solution for the original problem by copying the solution of the subproblem */
841 static
843  SCIP* subscip, /**< SCIP data structure of the subproblem */
844  SCIP_EVENTDATA* eventdata /**< event handler data */
845  )
846 {
847  SCIP* sourcescip; /* original SCIP data structure */
848  SCIP_VAR** subvars; /* the variables of the subproblem */
849  SCIP_HEUR* heur; /* alns heuristic structure */
850  SCIP_SOL* subsol; /* solution of the subproblem */
851  SCIP_VAR** vars; /* the original problem's variables */
852  int nvars;
853  SCIP_SOL* newsol; /* solution to be created for the original problem */
854  SCIP_Real* subsolvals; /* solution values of the subproblem */
855  SCIP_Bool success;
856  NH_STATS* runstats;
857  SCIP_SOL* oldbestsol;
858 
859  assert(subscip != NULL);
860 
861  subsol = SCIPgetBestSol(subscip);
862  assert(subsol != NULL);
863 
864  sourcescip = eventdata->sourcescip;
865  subvars = eventdata->subvars;
866  heur = eventdata->heur;
867  runstats = eventdata->runstats;
868  assert(sourcescip != NULL);
869  assert(sourcescip != subscip);
870  assert(heur != NULL);
871  assert(subvars != NULL);
872  assert(runstats != NULL);
873 
874  /* get variables' data */
875  SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, NULL, NULL, NULL, NULL) );
876 
877  /* sub-SCIP may have more variables than the number of active (transformed) variables in the main SCIP
878  * since constraint copying may have required the copy of variables that are fixed in the main SCIP */
879  assert(nvars <= SCIPgetNOrigVars(subscip));
880 
881  SCIP_CALL( SCIPallocBufferArray(sourcescip, &subsolvals, nvars) );
882 
883  /* copy the solution */
884  SCIP_CALL( SCIPgetSolVals(subscip, subsol, nvars, subvars, subsolvals) );
885 
886  /* create new solution for the original problem */
887  SCIP_CALL( SCIPcreateSol(sourcescip, &newsol, heur) );
888  SCIP_CALL( SCIPsetSolVals(sourcescip, newsol, nvars, vars, subsolvals) );
889 
890  oldbestsol = SCIPgetBestSol(sourcescip);
891 
892  /* in the special, experimental all rewards mode, the solution is only checked for feasibility
893  * but not stored
894  */
895  if( eventdata->allrewardsmode )
896  {
897  SCIP_CALL( SCIPcheckSol(sourcescip, newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
898 
899  if( success )
900  {
901  runstats->nsolsfound++;
902  if( SCIPgetSolTransObj(sourcescip, newsol) < SCIPgetCutoffbound(sourcescip) )
903  runstats->nbestsolsfound++;
904  }
905 
906  SCIP_CALL( SCIPfreeSol(sourcescip, &newsol) );
907  }
908  else
909  {
910  /* try to add new solution to scip and free it immediately */
911  SCIP_CALL( SCIPtrySolFree(sourcescip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
912 
913  if( success )
914  {
915  runstats->nsolsfound++;
916  if( SCIPgetBestSol(sourcescip) != oldbestsol )
917  runstats->nbestsolsfound++;
918  }
919  }
920 
921  SCIPfreeBufferArray(sourcescip, &subsolvals);
922 
923  return SCIP_OKAY;
924 }
925 
926 
927 /* ---------------- Callback methods of event handler ---------------- */
928 
929 /** execution callback of the event handler
930  *
931  * transfer new solutions or interrupt the solving process manually
932  */
933 static
934 SCIP_DECL_EVENTEXEC(eventExecAlns)
935 {
936  assert(eventhdlr != NULL);
937  assert(eventdata != NULL);
938  assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
939  assert(event != NULL);
940  assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_ALNS);
941  assert(eventdata != NULL);
942 
943  /* treat the different atomic events */
944  switch( SCIPeventGetType(event) )
945  {
948  /* try to transfer the solution to the original SCIP */
949  SCIP_CALL( transferSolution(scip, eventdata) );
950  break;
952  /* interrupt solution process of sub-SCIP */
953  if( SCIPgetNLPs(scip) > eventdata->lplimfac * eventdata->nodelimit )
954  {
955  SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
956  SCIP_CALL( SCIPinterruptSolve(scip) );
957  }
958  break;
959  default:
960  break;
961  }
962 
963  return SCIP_OKAY;
964 }
965 
966 /** initialize neighborhood statistics before the next run */
967 static
968 void initRunStats(
969  SCIP* scip, /**< SCIP data structure */
970  NH_STATS* stats /**< run statistics */
971  )
972 {
973  stats->nbestsolsfound = 0;
974  stats->nsolsfound = 0;
975  stats->usednodes = 0L;
976  stats->nfixings = 0;
977  stats->oldupperbound = SCIPgetUpperbound(scip);
978 }
979 
980 /** update run stats after the sub SCIP was solved */
981 static
982 void updateRunStats(
983  SCIP* scip, /**< SCIP data structure */
984  NH_STATS* stats, /**< run statistics */
985  SCIP* subscip /**< sub-SCIP instance, or NULL */
986  )
987 {
988  /* treat an untransformed subscip as if none was created */
989  if( subscip != NULL && ! SCIPisTransformed(subscip) )
990  subscip = NULL;
991 
992  stats->usednodes = subscip != NULL ? SCIPgetNNodes(subscip) : 0L;
993 }
994 
995 /** get the histogram index for this status */
996 static
997 int getHistIndex(
998  SCIP_STATUS subscipstatus /**< sub-SCIP status */
999  )
1000 {
1001  switch (subscipstatus)
1002  {
1003  case SCIP_STATUS_OPTIMAL:
1004  return (int)HIDX_OPT;
1006  return (int)HIDX_INFEAS;
1007  case SCIP_STATUS_NODELIMIT:
1008  return (int)HIDX_NODELIM;
1010  return (int)HIDX_STALLNODE;
1011  case SCIP_STATUS_SOLLIMIT:
1012  return (int)HIDX_SOLLIM;
1014  return (int)HIDX_USR;
1015  default:
1016  return (int)HIDX_OTHER;
1017  } /*lint !e788*/
1018 }
1019 
1020 /** print neighborhood statistics */
1021 static
1023  SCIP* scip, /**< SCIP data structure */
1024  SCIP_HEURDATA* heurdata, /**< heuristic data */
1025  FILE* file /**< file handle, or NULL for standard out */
1026  )
1027 {
1028  int i;
1029  int j;
1031 
1032  SCIPinfoMessage(scip, file, "Neighborhoods : %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %4s %4s %4s %4s %4s %4s %4s %4s\n",
1033  "Calls", "SetupTime", "SolveTime", "SolveNodes", "Sols", "Best", "Exp3", "EpsGreedy", "UCB", "TgtFixRate",
1034  "Opt", "Inf", "Node", "Stal", "Sol", "Usr", "Othr", "Actv");
1035 
1036 
1037  /* loop over neighborhoods and fill in statistics */
1038  for( i = 0; i < heurdata->nneighborhoods; ++i )
1039  {
1040  NH* neighborhood;
1041  SCIP_Real proba;
1042  SCIP_Real ucb;
1043  SCIP_Real epsgreedyweight;
1044  neighborhood = heurdata->neighborhoods[i];
1045  SCIPinfoMessage(scip, file, " %-17s:", neighborhood->name);
1046  SCIPinfoMessage(scip, file, " %10d", neighborhood->stats.nruns);
1047  SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, neighborhood->stats.setupclock) );
1048  SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, neighborhood->stats.submipclock) );
1049  SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.usednodes );
1050  SCIPinfoMessage(scip, file, " %10d", neighborhood->stats.nsolsfound);
1051  SCIPinfoMessage(scip, file, " %10d", neighborhood->stats.nbestsolsfound);
1052 
1053  proba = 0.0;
1054  ucb = 1.0;
1055  epsgreedyweight = -1.0;
1056 
1057  if( heurdata->bandit != NULL && i < heurdata->nactiveneighborhoods )
1058  {
1059  switch (heurdata->banditalgo) {
1060  case 'u':
1061  ucb = SCIPgetConfidenceBoundUcb(heurdata->bandit, i);
1062  break;
1063  case 'g':
1064  epsgreedyweight = SCIPgetWeightsEpsgreedy(heurdata->bandit)[i];
1065  break;
1066  case 'e':
1067  proba = SCIPgetProbabilityExp3(heurdata->bandit, i);
1068  break;
1069  default:
1070  break;
1071  }
1072  }
1073 
1074  SCIPinfoMessage(scip, file, " %10.5f", proba);
1075  SCIPinfoMessage(scip, file, " %10.5f", epsgreedyweight);
1076  SCIPinfoMessage(scip, file, " %10.5f", ucb);
1077  SCIPinfoMessage(scip, file, " %10.3f", neighborhood->fixingrate.targetfixingrate);
1078 
1079  /* loop over status histogram */
1080  for( j = 0; j < NHISTENTRIES; ++j )
1081  SCIPinfoMessage(scip, file, " %4d", neighborhood->stats.statushist[statusses[j]]);
1082 
1083  SCIPinfoMessage(scip, file, " %4d", i < heurdata->nactiveneighborhoods ? 1 : 0);
1084  SCIPinfoMessage(scip, file, "\n");
1085  }
1086 }
1087 
1088 /** update the statistics of the neighborhood based on the sub-SCIP run */
1089 static
1091  SCIP* scip, /**< SCIP data structure */
1092  NH_STATS* runstats, /**< run statistics */
1093  NH* neighborhood, /**< the selected neighborhood */
1094  SCIP_STATUS subscipstatus /**< status of the sub-SCIP solve */
1095  )
1096 { /*lint --e{715}*/
1097  NH_STATS* stats;
1098  stats = &neighborhood->stats;
1099 
1100  /* copy run statistics into neighborhood statistics */
1101  stats->nbestsolsfound += runstats->nbestsolsfound;
1102  stats->nsolsfound += runstats->nsolsfound;
1103  stats->usednodes += runstats->usednodes;
1104  stats->nruns += 1;
1105 
1106  if( runstats->nbestsolsfound > 0 )
1108  else if( runstats->nsolsfound > 0 )
1109  stats->nrunsbestsol++;
1110 
1111  /* update the counter for the subscip status */
1112  ++stats->statushist[getHistIndex(subscipstatus)];
1113 }
1114 
1115 /** sort callback for variable pointers using the ALNS variable prioritization
1116  *
1117  * the variable prioritization works hierarchically as follows. A variable
1118  * a has the higher priority over b iff
1119  *
1120  * - variable distances should be used and a has a smaller distance than b
1121  * - variable reduced costs should be used and a has a smaller score than b
1122  * - variable pseudo costs should be used and a has a smaller score than b
1123  * - based on previously assigned random scores
1124  *
1125  * @note: distances are context-based. For fixing more variables,
1126  * distances are initialized from the already fixed variables.
1127  * For unfixing variables, distances are initialized starting
1128  * from the unfixed variables
1129  */
1130 static
1131 SCIP_DECL_SORTINDCOMP(sortIndCompAlns)
1132 { /*lint --e{715}*/
1133  VARPRIO* varprio;
1134  SCIP* scip;
1135 
1136  varprio = (VARPRIO*)dataptr;
1137  assert(varprio != NULL);
1138  assert(varprio->randscores != NULL);
1139 
1140  scip = varprio->scip;
1141  assert(scip != NULL);
1142 
1143  if( ind1 == ind2 )
1144  return 0;
1145 
1146  /* priority is on distances, if enabled. The variable which is closer in a breadth-first search sense to
1147  * the already fixed variables has precedence */
1148  if( varprio->usedistances )
1149  {
1150  int dist1;
1151  int dist2;
1152 
1153  dist1 = varprio->distances[ind1];
1154  dist2 = varprio->distances[ind2];
1155 
1156  if( dist1 < 0 )
1157  dist1 = INT_MAX;
1158 
1159  if( dist2 < 0 )
1160  dist2 = INT_MAX;
1161 
1162  assert(varprio->distances != NULL);
1163  if( dist1 < dist2 )
1164  return -1;
1165  else if( dist1 > dist2 )
1166  return 1;
1167  }
1168 
1169  assert(! varprio->usedistances || varprio->distances[ind1] == varprio->distances[ind2]);
1170 
1171  /* if the indices tie considering reduced costs or distances are disabled -> use reduced cost information instead */
1172  if( varprio->useredcost )
1173  {
1174  assert(varprio->redcostscores != NULL);
1175 
1176  if( SCIPisLT(scip, varprio->redcostscores[ind1], varprio->redcostscores[ind2]) )
1177  return -1;
1178  else if( SCIPisGT(scip, varprio->redcostscores[ind1], varprio->redcostscores[ind2]) )
1179  return 1;
1180  }
1181 
1182  assert(! varprio->useredcost || SCIPisEQ(scip, varprio->redcostscores[ind1], varprio->redcostscores[ind2]));
1183 
1184  /* use pseudo cost scores if reduced costs are disabled or a tie was found */
1185  if( varprio->usepscost )
1186  {
1187  assert(varprio->pscostscores != NULL);
1188 
1189  /* prefer the variable with smaller pseudocost score */
1190  if( SCIPisLT(scip, varprio->pscostscores[ind1], varprio->pscostscores[ind2]) )
1191  return -1;
1192  else if( SCIPisGT(scip, varprio->pscostscores[ind1], varprio->pscostscores[ind2]) )
1193  return 1;
1194  }
1195 
1196 
1197  if( varprio->randscores[ind1] < varprio->randscores[ind2] )
1198  return -1;
1199  else if( varprio->randscores[ind1] > varprio->randscores[ind2] )
1200  return 1;
1201 
1202  return ind1 - ind2;
1203 }
1204 
1205 /** Compute the reduced cost score for this variable in the reference solution */
1206 static
1208  SCIP* scip, /**< SCIP data structure */
1209  SCIP_VAR* var, /**< the variable for which the score should be computed */
1210  SCIP_Real refsolval, /**< solution value in reference solution */
1211  SCIP_Bool uselocalredcost /**< should local reduced costs be used for generic (un)fixing? */
1212  )
1213 {
1214  SCIP_Real bestbound;
1215  SCIP_Real redcost;
1216  SCIP_Real score;
1217  assert(scip != NULL);
1218  assert(var != NULL);
1219 
1220  /* prefer column variables */
1222  return SCIPinfinity(scip);
1223 
1224  if( ! uselocalredcost )
1225  {
1226  redcost = SCIPvarGetBestRootRedcost(var);
1227 
1228  bestbound = SCIPvarGetBestRootSol(var);
1229 
1230  /* using global reduced costs, the two factors yield a nonnegative score within tolerances */
1231  assert(SCIPisDualfeasZero(scip, redcost)
1232  || (SCIPisDualfeasNegative(scip, redcost) && ! SCIPisFeasPositive(scip, refsolval - bestbound))
1233  || (SCIPisDualfeasPositive(scip, redcost) && ! SCIPisFeasNegative(scip, refsolval - bestbound)));
1234 
1235  }
1236  else
1237  {
1238  /* this can be safely asserted here, since the heuristic would not reach this point, otherwise */
1239  assert(SCIPhasCurrentNodeLP(scip));
1240  assert(SCIPgetLPSolstat(scip) == SCIP_LPSOLSTAT_OPTIMAL);
1241 
1242  redcost = SCIPgetVarRedcost(scip, var);
1243 
1244  bestbound = SCIPvarGetLPSol(var);
1245  }
1246 
1247  assert(! SCIPisInfinity(scip, REALABS(bestbound)));
1248  assert(SCIPisDualfeasZero(scip, redcost) || SCIPisFeasIntegral(scip, bestbound));
1249 
1250  score = redcost * (refsolval - bestbound);
1251 
1252  /* max out numerical inaccuracies from global scores */
1253  if( ! uselocalredcost )
1254  score = MAX(score, 0.0);
1255 
1256  return score;
1257 }
1258 
1259 /** get the pseudo cost score of this variable with respect to the reference solution */
1260 static
1262  SCIP* scip, /**< SCIP data structure */
1263  SCIP_VAR* var, /**< the variable for which the score should be computed */
1264  SCIP_Real refsolval /**< solution value in reference solution */
1265  )
1266 {
1267  SCIP_Real rootsolval;
1268  assert(scip != NULL);
1269  assert(var != NULL);
1270 
1271  /* variables that aren't LP columns have no pseudocost score */
1273  return 0.0;
1274 
1275  rootsolval = SCIPvarGetRootSol(var);
1276 
1277  /* the score is 0.0 if the values are equal */
1278  if( SCIPisEQ(scip, rootsolval, refsolval) )
1279  return 0.0;
1280  else
1281  return SCIPgetVarPseudocostVal(scip, var, refsolval - rootsolval);
1282 }
1283 
1284 /** add variable and solution value to buffer data structure for variable fixings. The method checks if
1285  * the value still lies within the variable bounds. The value stays unfixed otherwise.
1286  */
1287 static
1289  SCIP* scip, /**< SCIP data structure */
1290  SCIP_VAR* var, /**< (source) SCIP variable that should be added to the buffer */
1291  SCIP_Real val, /**< fixing value for this variable */
1292  SCIP_VAR** varbuf, /**< variable buffer to store variables that should be fixed */
1293  SCIP_Real* valbuf, /**< value buffer to store fixing values */
1294  int* nfixings, /**< pointer to number of fixed buffer variables, will be increased by 1 */
1295  SCIP_Bool integer /**< is this an integer variable? */
1296  )
1297 {
1298  assert(SCIPisFeasIntegral(scip, val) || ! SCIPvarIsIntegral(var));
1299  assert(*nfixings < SCIPgetNVars(scip));
1300 
1301  /* round the value to its nearest integer */
1302  if( integer )
1303  val = SCIPfloor(scip, val + 0.5);
1304 
1305  /* only add fixing if it is still valid within the global variable bounds. Invalidity
1306  * of this solution value may come from a dual reduction that was performed after the solution from which
1307  * this value originated was found
1308  */
1309  if( SCIPvarGetLbGlobal(var) <= val && val <= SCIPvarGetUbGlobal(var) )
1310  {
1311  varbuf[*nfixings] = var;
1312  valbuf[*nfixings] = val;
1313  ++(*nfixings);
1314  }
1315 }
1316 
1317 /** query neighborhood for a reference solution for further fixings */
1318 static
1320  SCIP* scip, /**< SCIP data structure */
1321  NH* neighborhood, /**< ALNS neighborhood data structure */
1322  SCIP_SOL** solptr /**< solution pointer */
1323  )
1324 {
1325  assert(solptr != NULL);
1326  assert(scip != NULL);
1327  assert(neighborhood != NULL);
1328 
1329  *solptr = NULL;
1330  if( neighborhood->nhrefsol != NULL )
1331  {
1332  SCIP_RESULT result;
1333  SCIP_CALL( neighborhood->nhrefsol(scip, neighborhood, solptr, &result) );
1334 
1335  if( result == SCIP_DIDNOTFIND )
1336  *solptr = NULL;
1337  else
1338  assert(*solptr != NULL);
1339  }
1340 
1341  return SCIP_OKAY;
1342 }
1343 
1344 /** fix additional variables found in feasible reference solution if the ones that the neighborhood found were not enough
1345  *
1346  * use not always the best solution for the values, but a reference solution provided by the neighborhood itself
1347  *
1348  * @note it may happen that the target fixing rate is not completely reached. This is the case if intermediate,
1349  * dual reductions render the solution values of the reference solution infeasible for
1350  * the current, global variable bounds.
1351  */
1352 static
1354  SCIP* scip, /**< SCIP data structure */
1355  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1356  SCIP_SOL* refsol, /**< feasible reference solution for more variable fixings */
1357  SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
1358  SCIP_Real* valbuf, /**< buffer array to store fixing values */
1359  int* nfixings, /**< pointer to store the number of fixings */
1360  int ntargetfixings, /**< number of required target fixings */
1361  SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
1362  )
1363 {
1364  VARPRIO varprio;
1365  SCIP_VAR** vars;
1366  SCIP_Real* redcostscores;
1367  SCIP_Real* pscostscores;
1368  SCIP_Real* solvals;
1369  SCIP_RANDNUMGEN* rng;
1370  SCIP_VAR** unfixedvars;
1371  SCIP_Bool* isfixed;
1372  int* distances;
1373  int* perm;
1374  SCIP_Real* randscores;
1375  int nbinvars;
1376  int nintvars;
1377  int nbinintvars;
1378  int nvars;
1379  int b;
1380  int nvarstoadd;
1381  int nunfixedvars;
1382 
1383  assert(scip != NULL);
1384  assert(varbuf != NULL);
1385  assert(nfixings != NULL);
1386  assert(success != NULL);
1387  assert(heurdata != NULL);
1388  assert(refsol != NULL);
1389 
1390  *success = FALSE;
1391 
1392  /* if the user parameter forbids more fixings, return immediately */
1393  if( ! heurdata->domorefixings )
1394  return SCIP_OKAY;
1395 
1396  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
1397 
1398  nbinintvars = nbinvars + nintvars;
1399 
1400  if( ntargetfixings >= nbinintvars )
1401  return SCIP_OKAY;
1402 
1403  /* determine the number of required additional fixings */
1404  nvarstoadd = ntargetfixings - *nfixings;
1405  if( nvarstoadd == 0 )
1406  return SCIP_OKAY;
1407 
1408  varprio.usedistances = heurdata->usedistances && (*nfixings >= 1);
1409  varprio.useredcost = heurdata->useredcost;
1410  varprio.usepscost = heurdata->usepscost;
1411  varprio.scip = scip;
1412  rng = SCIPbanditGetRandnumgen(heurdata->bandit);
1413  assert(rng != NULL);
1414 
1415  SCIP_CALL( SCIPallocBufferArray(scip, &randscores, nbinintvars) );
1416  SCIP_CALL( SCIPallocBufferArray(scip, &perm, nbinintvars) );
1417  SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
1418  SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, nbinintvars) );
1419  SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nbinintvars) );
1420  SCIP_CALL( SCIPallocBufferArray(scip, &isfixed, nbinintvars) );
1421  SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
1422  SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, nbinintvars) );
1423 
1424  /* initialize variable graph distances from already fixed variables */
1425  if( varprio.usedistances )
1426  {
1427  SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, varbuf, *nfixings, distances, INT_MAX, INT_MAX, ntargetfixings) );
1428  }
1429  else
1430  {
1431  /* initialize all equal distances to make them irrelevant */
1432  BMSclearMemoryArray(distances, nbinintvars);
1433  }
1434 
1435  BMSclearMemoryArray(isfixed, nbinintvars);
1436 
1437  /* mark binary and integer variables if they are fixed */
1438  for( b = 0; b < *nfixings; ++b )
1439  {
1440  int probindex;
1441 
1442  assert(varbuf[b] != NULL);
1443  probindex = SCIPvarGetProbindex(varbuf[b]);
1444  assert(probindex >= 0);
1445 
1446  if( probindex < nbinintvars )
1447  isfixed[probindex] = TRUE;
1448  }
1449 
1450 
1451  SCIP_CALL( SCIPgetSolVals(scip, refsol, nbinintvars, vars, solvals) );
1452 
1453  /* assign scores to unfixed every discrete variable of the problem */
1454  nunfixedvars = 0;
1455  for( b = 0; b < nbinintvars; ++b )
1456  {
1457  SCIP_VAR* var = vars[b];
1458 
1459  /* filter fixed variables */
1460  if( isfixed[b] )
1461  continue;
1462 
1463  /* filter variables with a solution value outside its global bounds */
1464  if( solvals[b] < SCIPvarGetLbGlobal(var) - 0.5 || solvals[b] > SCIPvarGetUbGlobal(var) + 0.5 )
1465  continue;
1466 
1467  redcostscores[nunfixedvars] = getVariableRedcostScore(scip, var, solvals[b], heurdata->uselocalredcost);
1468  pscostscores[nunfixedvars] = getVariablePscostScore(scip, var, solvals[b]);
1469 
1470  unfixedvars[nunfixedvars] = var;
1471  perm[nunfixedvars] = nunfixedvars;
1472  randscores[nunfixedvars] = SCIPrandomGetReal(rng, 0.0, 1.0);
1473 
1474 
1475  /* these assignments are based on the fact that nunfixedvars <= b */
1476  solvals[nunfixedvars] = solvals[b];
1477  distances[nunfixedvars] = distances[b];
1478 
1479  SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
1480  SCIPvarGetName(var), distances[nunfixedvars], redcostscores[nunfixedvars],
1481  pscostscores[nunfixedvars], randscores[nunfixedvars]);
1482 
1483  nunfixedvars++;
1484  }
1485 
1486  /* use selection algorithm (order of the variables does not matter) for quickly completing the fixing */
1487  varprio.randscores = randscores;
1488  varprio.distances = distances;
1489  varprio.redcostscores = redcostscores;
1490  varprio.pscostscores = pscostscores;
1491 
1492  nvarstoadd = MIN(nunfixedvars, nvarstoadd);
1493 
1494  /* select the first nvarstoadd many variables according to the score */
1495  if( nvarstoadd < nunfixedvars )
1496  SCIPselectInd(perm, sortIndCompAlns, &varprio, nvarstoadd, nunfixedvars);
1497 
1498  /* loop over the first elements of the selection defined in permutation. They represent the best variables */
1499  for( b = 0; b < nvarstoadd; ++b )
1500  {
1501  int permindex = perm[b];
1502  assert(permindex >= 0);
1503  assert(permindex < nunfixedvars);
1504 
1505  tryAdd2variableBuffer(scip, unfixedvars[permindex], solvals[permindex], varbuf, valbuf, nfixings, TRUE);
1506  }
1507 
1508  *success = TRUE;
1509 
1510  /* free buffer arrays */
1511  SCIPfreeBufferArray(scip, &pscostscores);
1512  SCIPfreeBufferArray(scip, &unfixedvars);
1513  SCIPfreeBufferArray(scip, &isfixed);
1514  SCIPfreeBufferArray(scip, &solvals);
1515  SCIPfreeBufferArray(scip, &redcostscores);
1516  SCIPfreeBufferArray(scip, &distances);
1517  SCIPfreeBufferArray(scip, &perm);
1518  SCIPfreeBufferArray(scip, &randscores);
1519 
1520  return SCIP_OKAY;
1521 }
1522 
1523 /** create the bandit algorithm for the heuristic depending on the user parameter */
1524 static
1526  SCIP* scip, /**< SCIP data structure */
1527  SCIP_HEURDATA* heurdata, /**< heuristic data structure */
1528  SCIP_Real* priorities, /**< call priorities for active neighborhoods */
1529  unsigned int initseed /**< initial random seed */
1530  )
1531 {
1532 
1533  switch (heurdata->banditalgo) {
1534  case 'u':
1535  SCIP_CALL( SCIPcreateBanditUcb(scip, &heurdata->bandit, priorities,
1536  heurdata->ucb_alpha, heurdata->nactiveneighborhoods, initseed) );
1537  break;
1538 
1539  case 'e':
1540  SCIP_CALL( SCIPcreateBanditExp3(scip, &heurdata->bandit, priorities,
1541  heurdata->exp3_gamma, heurdata->exp3_beta, heurdata->nactiveneighborhoods, initseed) );
1542  break;
1543 
1544  case 'g':
1545  SCIP_CALL( SCIPcreateBanditEpsgreedy(scip, &heurdata->bandit, priorities,
1546  heurdata->epsgreedy_eps, heurdata->nactiveneighborhoods, initseed) );
1547  break;
1548 
1549  default:
1550  SCIPerrorMessage("Unknown bandit parameter %c\n", heurdata->banditalgo);
1551  return SCIP_INVALIDDATA;
1552  }
1553 
1554  return SCIP_OKAY;
1555 }
1556 
1557 /*
1558  * Callback methods of primal heuristic
1559  */
1560 
1561 /** copy method for primal heuristic plugins (called when SCIP copies plugins) */
1562 static
1563 SCIP_DECL_HEURCOPY(heurCopyAlns)
1564 { /*lint --e{715}*/
1565  assert(scip != NULL);
1566  assert(heur != NULL);
1567  assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
1568 
1569  /* call inclusion method of primal heuristic */
1570  SCIP_CALL( SCIPincludeHeurAlns(scip) );
1571 
1572  return SCIP_OKAY;
1573 }
1574 
1575 /** unfix some of the variables because there are too many fixed
1576  *
1577  * a variable is ideally unfixed if it is close to other unfixed variables
1578  * and fixing it has a high reduced cost impact
1579  */
1580 static
1582  SCIP* scip, /**< SCIP data structure */
1583  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1584  SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
1585  SCIP_Real* valbuf, /**< buffer array to store fixing values */
1586  int* nfixings, /**< pointer to store the number of fixings */
1587  int ntargetfixings, /**< number of required target fixings */
1588  SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
1589  )
1590 {
1591  VARPRIO varprio;
1592  SCIP_Real* redcostscores;
1593  SCIP_Real* pscostscores;
1594  SCIP_Real* randscores;
1595  SCIP_VAR** unfixedvars;
1596  SCIP_VAR** varbufcpy;
1597  SCIP_Real* valbufcpy;
1598  SCIP_Bool* isfixedvar;
1599  SCIP_VAR** vars;
1600  SCIP_RANDNUMGEN* rng;
1601  int* distances;
1602  int* fixeddistances;
1603  int* perm;
1604  int nvars;
1605  int i;
1606  int nbinintvars;
1607  int nunfixed;
1608 
1609  *success = FALSE;
1610 
1611  nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
1612  if( nbinintvars == 0 )
1613  return SCIP_OKAY;
1614 
1615  assert(*nfixings > 0);
1616 
1617  nvars = SCIPgetNVars(scip);
1618  SCIP_CALL( SCIPallocBufferArray(scip, &isfixedvar, nvars) );
1619  SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
1620  SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
1621  SCIP_CALL( SCIPallocBufferArray(scip, &fixeddistances, *nfixings) );
1622  SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, *nfixings) );
1623  SCIP_CALL( SCIPallocBufferArray(scip, &randscores, *nfixings) );
1624  SCIP_CALL( SCIPallocBufferArray(scip, &perm, *nfixings) );
1625  SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, *nfixings) );
1626 
1627  SCIP_CALL( SCIPduplicateBufferArray(scip, &varbufcpy, varbuf, *nfixings) );
1628  SCIP_CALL( SCIPduplicateBufferArray(scip, &valbufcpy, valbuf, *nfixings) );
1629 
1630  /*
1631  * collect the unfixed binary and integer variables
1632  */
1633  BMSclearMemoryArray(isfixedvar, nvars);
1634  /* loop over fixed variables and mark their respective positions as fixed */
1635  for( i = 0; i < *nfixings; ++i )
1636  {
1637  int probindex = SCIPvarGetProbindex(varbuf[i]);
1638 
1639  assert(probindex >= 0);
1640 
1641  isfixedvar[probindex] = TRUE;
1642  }
1643 
1644  nunfixed = 0;
1645  vars = SCIPgetVars(scip);
1646  /* collect unfixed binary and integer variables */
1647  for( i = 0; i < nbinintvars; ++i )
1648  {
1649  if( ! isfixedvar[i] )
1650  unfixedvars[nunfixed++] = vars[i];
1651  }
1652 
1653  varprio.usedistances = heurdata->usedistances && nunfixed > 0;
1654 
1655  /* collect distances of all fixed variables from those that are not fixed */
1656  if( varprio.usedistances )
1657  {
1658  SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, unfixedvars, nunfixed, distances, INT_MAX, INT_MAX, INT_MAX) );
1659 
1660  for( i = 0; i < *nfixings; ++i )
1661  {
1662  int probindex = SCIPvarGetProbindex(varbuf[i]);
1663  if( probindex >= 0 )
1664  fixeddistances[i] = distances[probindex];
1665  }
1666  }
1667  else
1668  {
1669  BMSclearMemoryArray(fixeddistances, *nfixings);
1670  }
1671 
1672  /* collect reduced cost scores of the fixings and assign random scores */
1673  rng = SCIPbanditGetRandnumgen(heurdata->bandit);
1674  for( i = 0; i < *nfixings; ++i )
1675  {
1676  SCIP_VAR* fixedvar = varbuf[i];
1677  SCIP_Real fixval = valbuf[i];
1678 
1679  /* use negative reduced cost and pseudo cost scores to prefer variable fixings with small score */
1680  redcostscores[i] = - getVariableRedcostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
1681  pscostscores[i] = - getVariablePscostScore(scip, fixedvar, fixval);
1682  randscores[i] = SCIPrandomGetReal(rng, 0.0, 1.0);
1683  perm[i] = i;
1684 
1685  SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
1686  SCIPvarGetName(fixedvar), fixeddistances[i], redcostscores[i], pscostscores[i], randscores[i]);
1687  }
1688 
1689  varprio.distances = fixeddistances;
1690  varprio.randscores = randscores;
1691  varprio.redcostscores = redcostscores;
1692  varprio.pscostscores = pscostscores;
1693  varprio.useredcost = heurdata->useredcost;
1694  varprio.usepscost = heurdata->usepscost;
1695  varprio.scip = scip;
1696 
1697  /* scores are assigned in such a way that variables with a smaller score should be fixed last */
1698  SCIPselectDownInd(perm, sortIndCompAlns, &varprio, ntargetfixings, *nfixings);
1699 
1700  /* bring the desired variables to the front of the array */
1701  for( i = 0; i < ntargetfixings; ++i )
1702  {
1703  valbuf[i] = valbufcpy[perm[i]];
1704  varbuf[i] = varbufcpy[perm[i]];
1705  }
1706 
1707  *nfixings = ntargetfixings;
1708 
1709  /* free the buffer arrays in reverse order of allocation */
1710  SCIPfreeBufferArray(scip, &valbufcpy);
1711  SCIPfreeBufferArray(scip, &varbufcpy);
1712  SCIPfreeBufferArray(scip, &pscostscores);
1713  SCIPfreeBufferArray(scip, &perm);
1714  SCIPfreeBufferArray(scip, &randscores);
1715  SCIPfreeBufferArray(scip, &redcostscores);
1716  SCIPfreeBufferArray(scip, &fixeddistances);
1717  SCIPfreeBufferArray(scip, &distances);
1718  SCIPfreeBufferArray(scip, &unfixedvars);
1719  SCIPfreeBufferArray(scip, &isfixedvar);
1720 
1721  *success = TRUE;
1722 
1723  return SCIP_OKAY;
1724 }
1725 
1726 /** call variable fixing callback for this neighborhood and orchestrate additional variable fixings, if necessary */
1727 static
1729  SCIP* scip, /**< SCIP data structure */
1730  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1731  NH* neighborhood, /**< neighborhood data structure */
1732  SCIP_VAR** varbuf, /**< buffer array to keep variables that should be fixed */
1733  SCIP_Real* valbuf, /**< buffer array to keep fixing values */
1734  int* nfixings, /**< pointer to store the number of variable fixings */
1735  SCIP_RESULT* result /**< pointer to store the result of the fixing operation */
1736  )
1737 {
1738  int ntargetfixings;
1739 
1740  assert(scip != NULL);
1741  assert(neighborhood != NULL);
1742  assert(varbuf != NULL);
1743  assert(valbuf != NULL);
1744  assert(nfixings != NULL);
1745  assert(result != NULL);
1746 
1747  *nfixings = 0;
1748 
1749  *result = SCIP_DIDNOTRUN;
1750 
1751  if( neighborhood->varfixings != NULL )
1752  {
1753  SCIP_CALL( neighborhood->varfixings(scip, neighborhood, varbuf, valbuf, nfixings, result) );
1754 
1755  if( *result != SCIP_SUCCESS )
1756  return SCIP_OKAY;
1757  }
1758 
1759  assert(neighborhood->varfixings == NULL || *result != SCIP_DIDNOTRUN);
1760 
1761  ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)));
1762  SCIPdebugMsg(scip, "Neighborhood Fixings/Target: %d / %d\n",*nfixings, ntargetfixings);
1763 
1764  /* if too few fixings, use a strategy to select more variable fixings: randomized, LP graph, ReducedCost based, mix */
1765  if( (*result == SCIP_SUCCESS || *result == SCIP_DIDNOTRUN) && (*nfixings <= (1.0 - heurdata->fixtol) * ntargetfixings) )
1766  {
1767  SCIP_Bool success;
1768  SCIP_SOL* refsol;
1769 
1770  /* get reference solution from neighborhood */
1771  SCIP_CALL( neighborhoodGetRefsol(scip, neighborhood, &refsol) );
1772 
1773  /* try to fix more variables based on the reference solution */
1774  if( refsol != NULL )
1775  {
1776  SCIP_CALL( alnsFixMoreVariables(scip, heurdata, refsol, varbuf, valbuf, nfixings, ntargetfixings, &success) );
1777  }
1778  else
1779  success = FALSE;
1780 
1781  if( success )
1782  *result = SCIP_SUCCESS;
1783  else if( *result == SCIP_SUCCESS )
1784  *result = SCIP_DIDNOTFIND;
1785  else
1786  *result = SCIP_DIDNOTRUN;
1787 
1788  SCIPdebugMsg(scip, "After additional fixings: %d / %d\n",*nfixings, ntargetfixings);
1789  }
1790  else if( (SCIP_Real)(*nfixings) > (1.0 + heurdata->fixtol) * ntargetfixings)
1791  {
1792  SCIP_Bool success;
1793 
1794  SCIP_CALL( alnsUnfixVariables(scip, heurdata, varbuf, valbuf, nfixings, ntargetfixings, &success) );
1795 
1796  assert(success);
1797  *result = SCIP_SUCCESS;
1798  SCIPdebugMsg(scip, "Unfixed variables, fixed variables remaining: %d\n", ntargetfixings);
1799  }
1800  else
1801  {
1802  SCIPdebugMsg(scip, "No additional fixings performed\n");
1803  }
1804 
1805  return SCIP_OKAY;
1806 }
1807 
1808 /** change the sub-SCIP by restricting variable domains, changing objective coefficients, or adding constraints */
1809 static
1811  SCIP* sourcescip, /**< source SCIP data structure */
1812  SCIP* targetscip, /**< target SCIP data structure */
1813  NH* neighborhood, /**< neighborhood */
1814  SCIP_VAR** targetvars, /**< array of target SCIP variables aligned with source SCIP variables */
1815  int* ndomchgs, /**< pointer to store the number of variable domain changes */
1816  int* nchgobjs, /**< pointer to store the number of changed objective coefficients */
1817  int* naddedconss, /**< pointer to store the number of added constraints */
1818  SCIP_Bool* success /**< pointer to store whether the sub-SCIP has been successfully modified */
1819  )
1820 {
1821  assert(sourcescip != NULL);
1822  assert(targetscip != NULL);
1823  assert(neighborhood != NULL);
1824  assert(targetvars != NULL);
1825  assert(ndomchgs != NULL);
1826  assert(nchgobjs != NULL);
1827  assert(naddedconss != NULL);
1828  assert(success != NULL);
1829 
1830  *success = FALSE;
1831  *ndomchgs = 0;
1832  *nchgobjs = 0;
1833  *naddedconss = 0;
1834 
1835  /* call the change sub-SCIP callback of the neighborhood */
1836  if( neighborhood->changesubscip != NULL )
1837  {
1838  SCIP_CALL( neighborhood->changesubscip(sourcescip, targetscip, targetvars, ndomchgs, nchgobjs, naddedconss, success) );
1839  }
1840  else
1841  {
1842  *success = TRUE;
1843  }
1844 
1845  return SCIP_OKAY;
1846 }
1847 
1848 /** set sub-SCIP solving limits */
1849 static
1851  SCIP* subscip, /**< SCIP data structure */
1852  SOLVELIMITS* solvelimits /**< pointer to solving limits data structure */
1853  )
1854 {
1855  assert(subscip != NULL);
1856  assert(solvelimits != NULL);
1857 
1858  assert(solvelimits->nodelimit >= solvelimits->stallnodes);
1859 
1860  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", solvelimits->nodelimit) );
1861  SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", solvelimits->stallnodes));
1862  SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", solvelimits->timelimit) );
1863  SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", solvelimits->memorylimit) );
1864 
1865  return SCIP_OKAY;
1866 }
1867 
1868 /** determine limits for a sub-SCIP */
1869 static
1871  SCIP* scip, /**< SCIP data structure */
1872  SCIP_HEUR* heur, /**< this heuristic */
1873  SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
1874  SCIP_Bool* runagain /**< can we solve another sub-SCIP with these limits */
1875  )
1876 {
1877  SCIP_HEURDATA* heurdata;
1878  SCIP_Real initfactor;
1879  SCIP_Real nodesquot;
1880 
1881  assert(scip != NULL);
1882  assert(heur != NULL);
1883  assert(solvelimits != NULL);
1884  assert(runagain != NULL);
1885 
1886  heurdata = SCIPheurGetData(heur);
1887 
1888  /* check whether there is enough time and memory left */
1889  SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &solvelimits->timelimit) );
1890  if( ! SCIPisInfinity(scip, solvelimits->timelimit) )
1891  solvelimits->timelimit -= SCIPgetSolvingTime(scip);
1892  SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &solvelimits->memorylimit) );
1893 
1894  /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
1895  if( ! SCIPisInfinity(scip, solvelimits->memorylimit) )
1896  {
1897  solvelimits->memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
1898  solvelimits->memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
1899  }
1900 
1901  /* abort if no time is left or not enough memory to create a copy of SCIP, including external memory usage */
1902  if( solvelimits->timelimit <= 0.0 || solvelimits->memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0 )
1903  *runagain = FALSE;
1904 
1905  nodesquot = heurdata->nodesquot;
1906  nodesquot *= (SCIPheurGetNBestSolsFound(heur) + 1.0)/(SCIPheurGetNCalls(heur) + 1.0);
1907 
1908  /* calculate the search node limit of the heuristic */
1909  solvelimits->nodelimit = (SCIP_Longint)(nodesquot * SCIPgetNNodes(scip));
1910  solvelimits->nodelimit += heurdata->nodesoffset;
1911  solvelimits->nodelimit -= heurdata->usednodes;
1912  solvelimits->nodelimit -= 100 * SCIPheurGetNCalls(heur);
1913  solvelimits->nodelimit = MIN(heurdata->maxnodes, solvelimits->nodelimit);
1914 
1915  /* use a smaller budget if not all neighborhoods have been initialized yet */
1916  assert(heurdata->ninitneighborhoods >= 0);
1917  initfactor = (heurdata->nactiveneighborhoods - heurdata->ninitneighborhoods + 1.0) / (heurdata->nactiveneighborhoods + 1.0);
1918  solvelimits->nodelimit = (SCIP_Longint)(solvelimits->nodelimit * initfactor);
1919  solvelimits->stallnodes = (SCIP_Longint)(solvelimits->nodelimit * heurdata->stallnodefactor);
1920 
1921  /* check whether we have enough nodes left to call subproblem solving */
1922  if( solvelimits->nodelimit < heurdata->targetnodes )
1923  *runagain = FALSE;
1924 
1925  return SCIP_OKAY;
1926 }
1927 
1928 /** return the bandit algorithm that should be used */
1929 static
1931  SCIP_HEURDATA* heurdata /**< heuristic data of the ALNS neighborhood */
1932  )
1933 {
1934  assert(heurdata != NULL);
1935  return heurdata->bandit;
1936 }
1937 
1938 /** select a neighborhood depending on the selected bandit algorithm */
1939 static
1941  SCIP* scip, /**< SCIP data structure */
1942  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1943  int* neighborhoodidx /**< pointer to store the selected neighborhood index */
1944  )
1945 {
1946  SCIP_BANDIT* bandit;
1947  assert(scip != NULL);
1948  assert(heurdata != NULL);
1949  assert(neighborhoodidx != NULL);
1950 
1951  *neighborhoodidx = -1;
1952 
1953  bandit = getBandit(heurdata);
1954 
1955  SCIP_CALL( SCIPbanditSelect(bandit, neighborhoodidx) );
1956  assert(*neighborhoodidx >= 0);
1957 
1958  return SCIP_OKAY;
1959 }
1960 
1961 /** Calculate reward based on the selected reward measure */
1962 static
1964  SCIP* scip, /**< SCIP data structure */
1965  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
1966  NH_STATS* runstats, /**< run statistics */
1967  SCIP_Real* rewardptr /**< pointer to store the computed reward */
1968  )
1969 {
1970  SCIP_Real reward = 0.0;
1971  SCIP_Real effort;
1972 
1973  assert(runstats->usednodes >= 0);
1974  assert(runstats->nfixings >= 0);
1975 
1976  /* just add one node to avoid division by zero */
1977  effort = runstats->usednodes / (SCIP_Real)(heurdata->targetnodes + 1.0);
1978 
1979  /* assume that every fixed variable linearly reduces the subproblem complexity */
1980  effort = (1.0 - (runstats->nfixings / ((SCIP_Real)SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)))) * effort;
1981  assert(rewardptr != NULL);
1982 
1983  /* a positive reward is only assigned if a new incumbent solution was found */
1984  if( runstats->nbestsolsfound > 0 )
1985  {
1986  SCIP_Real bestsolreward;
1987  SCIP_Real closedgapreward;
1988  SCIP_Real rewardcontrol = heurdata->rewardcontrol;
1989 
1990  SCIP_Real lb;
1991  SCIP_Real ub;
1992 
1993  /* the indicator function is simply 1.0 */
1994  bestsolreward = 1.0;
1995 
1996  ub = SCIPgetUpperbound(scip);
1997  lb = SCIPgetLowerbound(scip);
1998 
1999  /* compute the closed gap reward */
2000  if( SCIPisEQ(scip, ub, lb) )
2001  closedgapreward = 1.0;
2002  else if( SCIPisInfinity(scip, runstats->oldupperbound) )
2003  closedgapreward = 1.0;
2004  else
2005  {
2006  closedgapreward = (runstats->oldupperbound - ub) / (runstats->oldupperbound - lb);
2007  }
2008 
2009  /* the reward is a convex combination of the best solution reward and the reward for the closed gap */
2010  reward = rewardcontrol * bestsolreward + (1.0 - rewardcontrol) * closedgapreward;
2011 
2012  /* optionally, scale the reward by the involved effort */
2013  if( heurdata->scalebyeffort )
2014  {
2015  /* reward can be larger than 1.0 if a best solution was found within 0 nodes */
2016  reward /= (effort + 1.0);
2017  }
2018 
2019  /* add the baseline and rescale the reward into the interval [baseline, 1.0] */
2020  reward = heurdata->rewardbaseline + (1.0 - heurdata->rewardbaseline) * reward;
2021  }
2022  else
2023  {
2024  /* linearly decrease the reward based on the number of nodes spent */
2025  SCIP_Real maxeffort = heurdata->targetnodes * heurdata->stallnodefactor;
2026  SCIP_Real usednodes = runstats->usednodes;
2027 
2028  usednodes *= (1.0 - (runstats->nfixings / ((SCIP_Real)SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip))));
2029 
2030  reward = heurdata->rewardbaseline - (usednodes) * heurdata->rewardbaseline / maxeffort;
2031 
2032 
2033  reward = MAX(0.0, reward);
2034  }
2035 
2036  *rewardptr = reward;
2037  return SCIP_OKAY;
2038 }
2039 
2040 /** update internal bandit algorithm statistics for future draws */
2041 static
2043  SCIP* scip, /**< SCIP data structure */
2044  SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
2045  SCIP_Real reward, /**< measured reward */
2046  int neighborhoodidx /**< the neighborhood that was chosen */
2047  )
2048 {
2049  SCIP_BANDIT* bandit;
2050  assert(scip != NULL);
2051  assert(heurdata != NULL);
2052  assert(neighborhoodidx >= 0);
2053  assert(neighborhoodidx < heurdata->nactiveneighborhoods);
2054 
2055  bandit = getBandit(heurdata);
2056 
2057  SCIPdebugMsg(scip, "Rewarding bandit algorithm action %d with reward %.2f\n", neighborhoodidx, reward);
2058  SCIP_CALL( SCIPbanditUpdate(bandit, neighborhoodidx, reward) );
2059 
2060  return SCIP_OKAY;
2061 }
2062 
2063 /** set up the sub-SCIP parameters, objective cutoff, and solution limits */
2064 static
2066  SCIP* scip, /**< SCIP data structure */
2067  SCIP* subscip, /**< sub-SCIP data structure */
2068  SCIP_VAR** subvars, /**< array of sub-SCIP variables in the order of the main SCIP */
2069  SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
2070  SCIP_HEUR* heur, /**< this heuristic */
2071  SCIP_Bool objchgd /**< did the objective change between the source and the target SCIP? */
2072  )
2073 {
2074  SCIP_HEURDATA* heurdata;
2075  SCIP_Real cutoff;
2076  SCIP_Real upperbound;
2077 
2078  heurdata = SCIPheurGetData(heur);
2079 
2080  /* do not abort subproblem on CTRL-C */
2081  SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
2082 
2083  /* disable output to console unless we are in debug mode */
2084  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
2085 
2086  /* disable statistic timing inside sub SCIP */
2087  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
2088 
2089 #ifdef ALNS_SUBSCIPOUTPUT
2090  SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
2091  SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1) );
2092  /* enable statistic timing inside sub SCIP */
2093  SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", TRUE) );
2094 #endif
2095 
2096  SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->nsolslim) );
2097 
2098  /* forbid recursive call of heuristics and separators solving subMIPs */
2099  if( ! heurdata->usesubscipheurs )
2100  {
2101  SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
2102  }
2103 
2104  /* disable cutting plane separation */
2106 
2107  /* disable expensive presolving */
2109 
2110  /* use best estimate node selection */
2111  if( SCIPfindNodesel(subscip, "estimate") != NULL && ! SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
2112  {
2113  SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
2114  }
2115 
2116  /* use inference branching */
2117  if( SCIPfindBranchrule(subscip, "inference") != NULL && ! SCIPisParamFixed(subscip, "branching/inference/priority") )
2118  {
2119  SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
2120  }
2121 
2122  /* enable conflict analysis and restrict conflict pool */
2123  if( ! SCIPisParamFixed(subscip, "conflict/enable") )
2124  {
2125  SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
2126  }
2127  if( ! SCIPisParamFixed(subscip, "conflict/maxstoresize") )
2128  {
2129  SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
2130  }
2131 
2132  /* speed up sub-SCIP by not checking dual LP feasibility */
2133  SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
2134 
2135  /* employ a limit on the number of enforcement rounds in the quadratic constraint handlers; this fixes the issue that
2136  * sometimes the quadratic constraint handler needs hundreds or thousands of enforcement rounds to determine the
2137  * feasibility status of a single node without fractional branching candidates by separation (namely for uflquad
2138  * instances); however, the solution status of the sub-SCIP might get corrupted by this; hence no decutions shall be
2139  * made for the original SCIP
2140  */
2141  if( SCIPfindConshdlr(subscip, "quadratic") != NULL && ! SCIPisParamFixed(subscip, "constraints/quadratic/enfolplimit") )
2142  {
2143  SCIP_CALL( SCIPsetIntParam(subscip, "constraints/quadratic/enfolplimit", 10) );
2144  }
2145 
2146  /* add an objective cutoff */
2147  if( ! SCIPisInfinity(scip, SCIPgetUpperbound(scip)) )
2148  {
2149  upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
2150  if( ! SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
2151  {
2152  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip)
2153  + heurdata->minimprove * SCIPgetLowerbound(scip);
2154  }
2155  else
2156  {
2157  if( SCIPgetUpperbound(scip) >= 0 )
2158  cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
2159  else
2160  cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
2161  }
2162  cutoff = MIN(upperbound, cutoff);
2163 
2164  if( SCIPisObjIntegral(scip) )
2165  cutoff = SCIPfloor(scip, cutoff);
2166 
2167  SCIPdebugMsg(scip, "Sub-SCIP cutoff: %15.9" SCIP_REAL_FORMAT " (%15.9" SCIP_REAL_FORMAT " in original space)\n",
2168  cutoff, SCIPretransformObj(scip, cutoff));
2169 
2170  /* if the objective changed between the source and the target SCIP, encode the cutoff as a constraint */
2171  if( ! objchgd )
2172  {
2173  SCIP_CALL(SCIPsetObjlimit(subscip, cutoff));
2174 
2175  SCIPdebugMsg(scip, "Cutoff added as Objective Limit\n");
2176  }
2177  else
2178  {
2179  SCIP_CONS* objcons;
2180  int nvars;
2181  SCIP_VAR** vars;
2182  int i;
2183 
2184  vars = SCIPgetVars(scip);
2185  nvars = SCIPgetNVars(scip);
2186 
2187  SCIP_CALL( SCIPcreateConsLinear(subscip, &objcons, "objbound_of_origscip", 0, NULL, NULL, -SCIPinfinity(subscip), cutoff,
2188  TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE) );
2189  for( i = 0; i < nvars; ++i)
2190  {
2191  if( ! SCIPisFeasZero(subscip, SCIPvarGetObj(vars[i])) )
2192  {
2193  SCIP_CALL( SCIPaddCoefLinear(subscip, objcons, subvars[i], SCIPvarGetObj(vars[i])) );
2194  }
2195  }
2196  SCIP_CALL( SCIPaddCons(subscip, objcons) );
2197  SCIP_CALL( SCIPreleaseCons(subscip, &objcons) );
2198 
2199  SCIPdebugMsg(scip, "Cutoff added as constraint\n");
2200  }
2201  }
2202 
2203  /* set solve limits for sub-SCIP */
2204  SCIP_CALL( setLimits(subscip, solvelimits) );
2205 
2206  /* change random seed of sub-SCIP */
2207  if( heurdata->subsciprandseeds )
2208  {
2209  SCIP_CALL( SCIPsetIntParam(subscip, "randomization/randomseedshift", (int)SCIPheurGetNCalls(heur)) );
2210  }
2211 
2212  SCIPdebugMsg(scip, "Solve Limits: %lld (%lld) nodes (stall nodes), %.1f sec., %d sols\n",
2213  solvelimits->nodelimit, solvelimits->stallnodes, solvelimits->timelimit, heurdata->nsolslim);
2214 
2215  return SCIP_OKAY;
2216 }
2217 
2218 /** execution method of primal heuristic */
2219 static
2220 SCIP_DECL_HEUREXEC(heurExecAlns)
2221 { /*lint --e{715}*/
2222  SCIP_HEURDATA* heurdata;
2223  SCIP_VAR** varbuf;
2224  SCIP_Real* valbuf;
2225  SCIP_VAR** vars;
2226  SCIP_VAR** subvars;
2227  NH_STATS runstats[NNEIGHBORHOODS];
2228  SCIP_STATUS subscipstatus[NNEIGHBORHOODS];
2229  SCIP* subscip = NULL;
2230 
2231  int nfixings;
2232  int nvars;
2233  int neighborhoodidx;
2234  int ntries;
2235  SCIP_Bool tryagain;
2236  NH* neighborhood;
2237  SOLVELIMITS solvelimits;
2238  SCIP_Bool success;
2239  SCIP_Bool run;
2240  SCIP_Bool allrewardsmode;
2241  SCIP_Real rewards[NNEIGHBORHOODS];
2242  int banditidx;
2243  int i;
2244 
2245  heurdata = SCIPheurGetData(heur);
2246  assert(heurdata != NULL);
2247 
2248  *result = SCIP_DIDNOTRUN;
2249 
2250  if( heurdata->nactiveneighborhoods == 0 )
2251  return SCIP_OKAY;
2252 
2253  /* wait for a sufficient number of nodes since last incumbent solution */
2254  if( SCIPgetDepth(scip) > 0 && SCIPgetBestSol(scip) != NULL
2255  && (SCIPgetNNodes(scip) - SCIPsolGetNodenum(SCIPgetBestSol(scip))) < heurdata->waitingnodes )
2256  {
2257  SCIPdebugMsg(scip, "Waiting nodes not satisfied\n");
2258  return SCIP_OKAY;
2259  }
2260 
2261  run = TRUE;
2262  /* check if budget allows a run of the next selected neighborhood */
2263  SCIP_CALL( determineLimits(scip, heur, &solvelimits, &run) );
2264  SCIPdebugMsg(scip, "Budget check: %" SCIP_LONGINT_FORMAT " (%" SCIP_LONGINT_FORMAT ") %s\n", solvelimits.nodelimit, heurdata->targetnodes, run ? "passed" : "must wait");
2265 
2266  if( ! run )
2267  return SCIP_OKAY;
2268 
2269  /* delay the heuristic if local reduced costs should be used for generic variable unfixing */
2270  if( heurdata->uselocalredcost && (nodeinfeasible || ! SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL) )
2271  {
2272  *result = SCIP_DELAYED;
2273 
2274  return SCIP_OKAY;
2275  }
2276 
2277 
2278 
2279  allrewardsmode = heurdata->rewardfile != NULL;
2280 
2281  /* apply some other rules for a fair all rewards mode; in normal execution mode, neighborhoods are iterated through */
2282  if( allrewardsmode )
2283  {
2284  /* most neighborhoods require an incumbent solution */
2285  if( SCIPgetNSols(scip) < 2 )
2286  {
2287  SCIPdebugMsg(scip, "Not enough solutions for all rewards mode\n");
2288  return SCIP_OKAY;
2289  }
2290 
2291  /* if the node is infeasible, or has no LP solution, which is required by some neighborhoods
2292  * if we are not in all rewards mode, the neighborhoods delay themselves individually
2293  */
2294  if( nodeinfeasible || ! SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
2295  {
2296  SCIPdebugMsg(scip, "Delay ALNS heuristic until a feasible node with optimally solved LP relaxation\n");
2297  *result = SCIP_DELAYED;
2298  return SCIP_OKAY;
2299  }
2300  }
2301 
2302  /* use the neighborhood that requested a delay or select the next neighborhood to run based on the selected bandit algorithm */
2303  if( heurdata->currneighborhood >= 0 )
2304  {
2305  assert(! allrewardsmode);
2306  banditidx = heurdata->currneighborhood;
2307  SCIPdebugMsg(scip, "Select delayed neighborhood %d (was delayed %d times)\n", banditidx, heurdata->ndelayedcalls);
2308  }
2309  else
2310  {
2311  SCIP_CALL( selectNeighborhood(scip, heurdata, &banditidx) );
2312  SCIPdebugMsg(scip, "Selected neighborhood %d with bandit algorithm\n", banditidx);
2313  }
2314 
2315  /* in all rewards mode, we simply loop over all heuristics */
2316  if( ! allrewardsmode )
2317  neighborhoodidx = banditidx;
2318  else
2319  neighborhoodidx = 0;
2320 
2321  assert(neighborhoodidx >= 0);
2322  assert(heurdata->nactiveneighborhoods > neighborhoodidx);
2323 
2324  /* allocate memory for variable fixings buffer */
2325  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
2326  SCIP_CALL( SCIPallocBufferArray(scip, &varbuf, nvars) );
2327  SCIP_CALL( SCIPallocBufferArray(scip, &valbuf, nvars) );
2328  SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
2329 
2330  /* initialize neighborhood statistics for a run */
2331  ntries = 1;
2332  do
2333  {
2334  SCIP_HASHMAP* varmapf;
2335  SCIP_EVENTHDLR* eventhdlr;
2336  SCIP_EVENTDATA eventdata;
2337  int ndomchgs;
2338  int nchgobjs;
2339  int naddedconss;
2340  int v;
2341  SCIP_RESULT fixresult;
2342  tryagain = FALSE;
2343  neighborhood = heurdata->neighborhoods[neighborhoodidx];
2344  SCIPdebugMsg(scip, "Running '%s' neighborhood %d\n", neighborhood->name, neighborhoodidx);
2345 
2346  initRunStats(scip, &runstats[neighborhoodidx]);
2347  rewards[neighborhoodidx] = 0.0;
2348 
2349  subscipstatus[neighborhoodidx] = SCIP_STATUS_UNKNOWN;
2350  SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.setupclock) );
2351 
2352  /* determine variable fixings and objective coefficients of this neighborhood */
2353  SCIP_CALL( neighborhoodFixVariables(scip, heurdata, neighborhood, varbuf, valbuf, &nfixings, &fixresult) );
2354 
2355  SCIPdebugMsg(scip, "Fix %d/%d variables\n", nfixings, nvars);
2356 
2357  /* Fixing was not successful, either because the fixing rate was not reached (and no additional variable
2358  * prioritization was used), or the neighborhood requested a delay, e.g., because no LP relaxation solution exists
2359  * at the current node
2360  *
2361  * The ALNS heuristic keeps a delayed neighborhood active and delays itself.
2362  */
2363  if( fixresult != SCIP_SUCCESS )
2364  {
2365  SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
2366 
2367  /* to determine all rewards, we cannot delay neighborhoods */
2368  if( allrewardsmode )
2369  {
2370  if( ntries == heurdata->nactiveneighborhoods )
2371  break;
2372 
2373  neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
2374  ntries++;
2375  tryagain = TRUE;
2376 
2377  continue;
2378  }
2379 
2380 
2381  /* delay the heuristic along with the selected neighborhood
2382  *
2383  * if the neighborhood has been delayed for too many consecutive calls, the delay is treated as a failure */
2384  if( fixresult == SCIP_DELAYED )
2385  {
2386 
2387  if( heurdata->ndelayedcalls > (SCIPheurGetFreq(heur) / 4 + 1) )
2388  {
2389  resetCurrentNeighborhood(heurdata);
2390 
2391  /* use SCIP_DIDNOTFIND to penalize the neighborhood with a bad reward */
2392  fixresult = SCIP_DIDNOTFIND;
2393  }
2394  else if( heurdata->currneighborhood == -1 )
2395  {
2396  heurdata->currneighborhood = neighborhoodidx;
2397  heurdata->ndelayedcalls = 1;
2398  }
2399  else
2400  {
2401  heurdata->ndelayedcalls++;
2402  }
2403  }
2404 
2405  if( fixresult == SCIP_DIDNOTRUN )
2406  {
2407  if( ntries < heurdata->nactiveneighborhoods )
2408  {
2409  SCIP_CALL( updateBanditAlgorithms(scip, heurdata, 0.0, neighborhoodidx) );
2410  SCIP_CALL( selectNeighborhood(scip, heurdata, &neighborhoodidx) );
2411  ntries++;
2412  tryagain = TRUE;
2413 
2414  SCIPdebugMsg(scip, "Neighborhood cannot run -> try next neighborhood %d\n", neighborhoodidx);
2415  continue;
2416  }
2417  else
2418  break;
2419  }
2420 
2421  assert(fixresult == SCIP_DIDNOTFIND || fixresult == SCIP_DELAYED);
2422  *result = fixresult;
2423  break;
2424  }
2425 
2426  *result = SCIP_DIDNOTFIND;
2427 
2428  neighborhood->stats.nfixings += nfixings;
2429  runstats[neighborhoodidx].nfixings = nfixings;
2430 
2431  SCIP_CALL( SCIPcreate(&subscip) );
2432  SCIP_CALL( SCIPhashmapCreate(&varmapf, SCIPblkmem(scip), nvars) );
2433 
2434  /* todo later: run global propagation for this set of fixings */
2435  SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapf, neighborhood->name, varbuf, valbuf, nfixings, FALSE, heurdata->copycuts, &success, NULL) );
2436 
2437  /* store sub-SCIP variables in array for faster access */
2438  for( v = 0; v < nvars; ++v )
2439  {
2440  subvars[v] = (SCIP_VAR*)SCIPhashmapGetImage(varmapf, (void *)vars[v]);
2441  assert(subvars[v] != NULL);
2442  }
2443 
2444  SCIPhashmapFree(&varmapf);
2445 
2446  /* let the neighborhood add additional constraints, or restrict domains */
2447  SCIP_CALL( neighborhoodChangeSubscip(scip, subscip, neighborhood, subvars, &ndomchgs, &nchgobjs, &naddedconss, &success) );
2448 
2449  if( ! success )
2450  {
2451  SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
2452 
2453  if( ! allrewardsmode || ntries == heurdata->nactiveneighborhoods )
2454  break;
2455 
2456  neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
2457  ntries++;
2458  tryagain = TRUE;
2459 
2460  SCIP_CALL( SCIPfree(&subscip) );
2461 
2462  continue;
2463  }
2464 
2465  /* set up sub-SCIP parameters */
2466  SCIP_CALL( setupSubScip(scip, subscip, subvars, &solvelimits, heur, nchgobjs > 0) );
2467 
2468  /* copy the necessary data into the event data to create new solutions */
2469  eventdata.nodelimit = solvelimits.nodelimit;
2470  eventdata.lplimfac = heurdata->lplimfac;
2471  eventdata.heur = heur;
2472  eventdata.sourcescip = scip;
2473  eventdata.subvars = subvars;
2474  eventdata.runstats = &runstats[neighborhoodidx];
2475  eventdata.allrewardsmode = allrewardsmode;
2476 
2477  /* include an event handler to transfer solutions into the main SCIP */
2478  SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecAlns, NULL) );
2479 
2480  /* transform the problem before catching the events */
2481  SCIP_CALL( SCIPtransformProb(subscip) );
2482  SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_ALNS, eventhdlr, &eventdata, NULL) );
2483 
2484  SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
2485 
2486  /* todo alternatively: set up sub-SCIP and run presolving */
2487  /* todo was presolving successful enough regarding fixings? otherwise terminate */
2488 
2489  SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.submipclock) );
2490  /* run sub-SCIP for the given budget, and collect statistics */
2491  SCIP_CALL_ABORT( SCIPsolve(subscip) );
2492 
2493 #ifdef ALNS_SUBSCIPOUTPUT
2494  SCIP_CALL( SCIPprintStatistics(scip, NULL) );
2495 #endif
2496 
2497  SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.submipclock) );
2498 
2499  /* update statistics based on the sub-SCIP run results */
2500  updateRunStats(scip, &runstats[neighborhoodidx], subscip);
2501  subscipstatus[neighborhoodidx] = SCIPgetStatus(subscip);
2502 
2503  SCIP_CALL( getReward(scip, heurdata, &runstats[neighborhoodidx], &rewards[neighborhoodidx]) );
2504 
2505  /* in all rewards mode, continue with the next neighborhood */
2506  if( allrewardsmode && ntries < heurdata->nactiveneighborhoods )
2507  {
2508  neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
2509  ntries++;
2510  tryagain = TRUE;
2511 
2512  SCIP_CALL( SCIPfree(&subscip) );
2513  }
2514  }
2515  while( tryagain && ! SCIPisStopped(scip) );
2516 
2517  if( subscip != NULL )
2518  {
2519  SCIP_CALL( SCIPfree(&subscip) );
2520  }
2521 
2522  SCIPfreeBufferArray(scip, &subvars);
2523  SCIPfreeBufferArray(scip, &valbuf);
2524  SCIPfreeBufferArray(scip, &varbuf);
2525 
2526  /* update bandit index that may have changed unless we are in all rewards mode */
2527  if( ! allrewardsmode )
2528  banditidx = neighborhoodidx;
2529 
2530  if( *result != SCIP_DELAYED )
2531  {
2532  /* decrease the number of neighborhoods that have not been initialized */
2533  if( neighborhood->stats.nruns == 0 )
2534  --heurdata->ninitneighborhoods;
2535 
2536  heurdata->usednodes += runstats[banditidx].usednodes;
2537 
2538  /* determine the success of this neighborhood, and update the target fixing rate for the next time */
2539  updateNeighborhoodStats(scip, &runstats[banditidx], heurdata->neighborhoods[banditidx], subscipstatus[banditidx]);
2540 
2541  SCIPdebugMsg(scip, "Status of sub-SCIP run: %d\n", subscipstatus[banditidx]);
2542 
2543  /* adjust the fixing rate for this neighborhood
2544  * make no adjustments in all rewards mode, because this only affects 1 of 8 heuristics
2545  */
2546  if( heurdata->adjustfixingrate && ! allrewardsmode )
2547  {
2548  SCIPdebugMsg(scip, "Update fixing rate: %.2f\n", heurdata->neighborhoods[banditidx]->fixingrate.targetfixingrate);
2549  updateFixingRate(scip, heurdata->neighborhoods[banditidx], subscipstatus[banditidx], &runstats[banditidx]);
2550  SCIPdebugMsg(scip, "New fixing rate: %.2f\n", heurdata->neighborhoods[banditidx]->fixingrate.targetfixingrate);
2551  }
2552  /* similarly, update the minimum improvement for the ALNS heuristic
2553  * make no adjustments in all rewards mode
2554  */
2555  if( heurdata->adjustminimprove && ! allrewardsmode )
2556  {
2557  SCIPdebugMsg(scip, "Update Minimum Improvement: %.4f\n", heurdata->minimprove);
2558  updateMinimumImprovement(heurdata, subscipstatus[banditidx], &runstats[banditidx]);
2559  SCIPdebugMsg(scip, "--> %.4f\n", heurdata->minimprove);
2560  }
2561 
2562  /* update the target node limit based on the status of the selected algorithm */
2563  updateTargetNodeLimit(heurdata, &runstats[banditidx], subscipstatus[banditidx]);
2564 
2565  /* update the bandit algorithms by the measured reward */
2566  SCIP_CALL( updateBanditAlgorithms(scip, heurdata, rewards[banditidx], banditidx) );
2567 
2568  resetCurrentNeighborhood(heurdata);
2569  }
2570 
2571  /* write single, measured rewards and the bandit index to the reward file */
2572  if( allrewardsmode )
2573  {
2574  for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
2575  {
2576  fprintf(heurdata->rewardfile, "%.4f,", rewards[i]);
2577  }
2578  fprintf(heurdata->rewardfile, "%d\n", banditidx);
2579  }
2580 
2581  return SCIP_OKAY;
2582 }
2583 
2584 /** callback to collect variable fixings of RENS */
2585 static
2586 DECL_VARFIXINGS(varFixingsRens)
2587 { /*lint --e{715}*/
2588  int nbinvars;
2589  int nintvars;
2590  SCIP_VAR** vars;
2591  int i;
2592  assert(scip != NULL);
2593  assert(varbuf != NULL);
2594  assert(nfixings != NULL);
2595  assert(valbuf != NULL);
2596 
2597  *result = SCIP_DELAYED;
2598 
2599  if( ! SCIPhasCurrentNodeLP(scip) )
2600  return SCIP_OKAY;
2602  return SCIP_OKAY;
2603 
2604  *result = SCIP_DIDNOTRUN;
2605 
2606  /* get variable information */
2607  SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2608 
2609  /* return if no binary or integer variables are present */
2610  if( nbinvars + nintvars == 0 )
2611  return SCIP_OKAY;
2612 
2613  /* loop over binary and integer variables; determine those that should be fixed in the sub-SCIP */
2614  for( i = 0; i < nbinvars + nintvars; ++i )
2615  {
2616  SCIP_VAR* var = vars[i];
2617  SCIP_Real lpsolval = SCIPgetSolVal(scip, NULL, var);
2618  assert((i < nbinvars && SCIPvarIsBinary(var)) || (i >= nbinvars && SCIPvarIsIntegral(var)));
2619 
2620  /* fix all binary and integer variables with integer LP solution value */
2621  if( SCIPisFeasIntegral(scip, lpsolval) )
2622  tryAdd2variableBuffer(scip, var, lpsolval, varbuf, valbuf, nfixings, TRUE);
2623  }
2624 
2625  *result = SCIP_SUCCESS;
2626 
2627  return SCIP_OKAY;
2628 }
2629 
2630 /** callback for RENS subproblem changes */
2631 static
2632 DECL_CHANGESUBSCIP(changeSubscipRens)
2633 { /*lint --e{715}*/
2634  SCIP_VAR** vars;
2635  int nintvars;
2636  int nbinvars;
2637  int i;
2638 
2639  assert(SCIPhasCurrentNodeLP(sourcescip));
2640  assert(SCIPgetLPSolstat(sourcescip) == SCIP_LPSOLSTAT_OPTIMAL);
2641 
2642  /* get variable information */
2643  SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2644 
2645  /* restrict bounds of integer variables with fractional solution value */
2646  for( i = nbinvars; i < nbinvars + nintvars; ++i )
2647  {
2648  SCIP_VAR* var = vars[i];
2649  SCIP_Real lpsolval = SCIPgetSolVal(sourcescip, NULL, var);
2650 
2651  if( ! SCIPisFeasIntegral(sourcescip, lpsolval) )
2652  {
2653  SCIP_Real newlb = SCIPfloor(sourcescip, lpsolval);
2654  SCIP_Real newub = newlb + 1.0;
2655 
2656  /* only count this as a domain change if the new lower and upper bound are a further restriction */
2657  if( newlb > SCIPvarGetLbGlobal(subvars[i]) + 0.5 || newub < SCIPvarGetUbGlobal(subvars[i]) - 0.5 )
2658  {
2659  SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[i], newlb) );
2660  SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[i], newub) );
2661  (*ndomchgs)++;
2662  }
2663  }
2664  }
2665 
2666  *success = TRUE;
2667 
2668  return SCIP_OKAY;
2669 }
2670 
2671 /** collect fixings by matching solution values in a collection of solutions for all binary and integer variables,
2672  * or for a custom set of variables
2673  */
2674 static
2676  SCIP* scip, /**< SCIP data structure */
2677  SCIP_SOL** sols, /**< array of 2 or more solutions. It is okay for the array to contain one element
2678  * equal to NULL to represent the current LP solution */
2679  int nsols, /**< number of solutions in the array */
2680  SCIP_VAR** vars, /**< variable array for which solution values must agree */
2681  int nvars, /**< number of variables, or -1 for all binary and integer variables */
2682  SCIP_VAR** varbuf, /**< buffer storage for variable fixings */
2683  SCIP_Real* valbuf, /**< buffer storage for fixing values */
2684  int* nfixings /**< pointer to store the number of fixings */
2685  )
2686 {
2687  int v;
2688  int nbinintvars;
2689  SCIP_SOL* firstsol;
2690 
2691  assert(scip != NULL);
2692  assert(sols != NULL);
2693  assert(nsols >= 2);
2694  assert(varbuf != NULL);
2695  assert(valbuf != NULL);
2696  assert(nfixings != NULL);
2697  assert(*nfixings == 0);
2698 
2699  if( nvars == -1 || vars == NULL )
2700  {
2701  int nbinvars;
2702  int nintvars;
2703  SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2704  nbinintvars = nbinvars + nintvars;
2705  nvars = nbinintvars;
2706  }
2707  firstsol = sols[0];
2708  assert(nvars > 0);
2709 
2710  /* loop over integer and binary variables and check if their solution values match in all solutions */
2711  for( v = 0; v < nvars; ++v )
2712  {
2713  SCIP_Real solval;
2714  SCIP_VAR* var;
2715  int s;
2716 
2717  var = vars[v];
2718  assert((v < SCIPgetNBinVars(scip) && SCIPvarIsBinary(var)) || (v >= SCIPgetNBinVars(scip) && SCIPvarIsIntegral(var)));
2719  solval = SCIPgetSolVal(scip, firstsol, var);
2720 
2721  /* determine if solution values match in all given solutions */
2722  for( s = 1; s < nsols; ++s )
2723  {
2724  SCIP_Real solval2 = SCIPgetSolVal(scip, sols[s], var);
2725  if( ! SCIPisEQ(scip, solval, solval2) )
2726  break;
2727  }
2728 
2729  /* if we did not break early, all solutions agree on the solution value of this variable */
2730  if( s == nsols )
2731  {
2732  tryAdd2variableBuffer(scip, var, solval, varbuf, valbuf, nfixings, TRUE);
2733  }
2734  }
2735 
2736  return SCIP_OKAY;
2737 }
2738 
2739 /** callback to collect variable fixings of RINS */
2740 static
2741 DECL_VARFIXINGS(varFixingsRins)
2743  /*lint --e{715}*/
2744  int nbinvars;
2745  int nintvars;
2746  SCIP_VAR** vars;
2747  SCIP_SOL* incumbent;
2748  SCIP_SOL* sols[2];
2749  assert(scip != NULL);
2750  assert(varbuf != NULL);
2751  assert(nfixings != NULL);
2752  assert(valbuf != NULL);
2753 
2754  *result = SCIP_DELAYED;
2755 
2756  if( ! SCIPhasCurrentNodeLP(scip) )
2757  return SCIP_OKAY;
2759  return SCIP_OKAY;
2760 
2761  *result = SCIP_DIDNOTRUN;
2762 
2763  incumbent = SCIPgetBestSol(scip);
2764  if( incumbent == NULL )
2765  return SCIP_OKAY;
2766 
2767  if( SCIPsolGetOrigin(incumbent) == SCIP_SOLORIGIN_ORIGINAL )
2768  return SCIP_OKAY;
2769 
2770  /* get variable information */
2771  SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
2772 
2773  /* return if no binary or integer variables are present */
2774  if( nbinvars + nintvars == 0 )
2775  return SCIP_OKAY;
2776 
2777  sols[0] = NULL;
2778  sols[1] = incumbent;
2779 
2780  SCIP_CALL( fixMatchingSolutionValues(scip, sols, 2, vars, nbinvars + nintvars, varbuf, valbuf, nfixings) );
2781 
2782  *result = SCIP_SUCCESS;
2783 
2784  return SCIP_OKAY;
2785 }
2786 
2787 /** initialization callback for crossover when a new problem is read */
2788 static
2789 DECL_NHINIT(nhInitCrossover)
2790 { /*lint --e{715}*/
2791  DATA_CROSSOVER* data;
2792 
2793  data = neighborhood->data.crossover;
2794  assert(data != NULL);
2795 
2796  if( data->rng != NULL )
2797  SCIPfreeRandom(scip, &data->rng);
2798 
2799  data->selsol = NULL;
2800 
2801  SCIP_CALL( SCIPcreateRandom(scip, &data->rng, CROSSOVERSEED + (unsigned int)SCIPgetNVars(scip)) );
2802 
2803  return SCIP_OKAY;
2804 }
2805 
2806 /** deinitialization callback for crossover when exiting a problem */
2807 static
2808 DECL_NHEXIT(nhExitCrossover)
2809 { /*lint --e{715}*/
2810  DATA_CROSSOVER* data;
2811  data = neighborhood->data.crossover;
2812 
2813  assert(neighborhood != NULL);
2814  assert(data->rng != NULL);
2815 
2816  SCIPfreeRandom(scip, &data->rng);
2817 
2818  return SCIP_OKAY;
2819 }
2820 
2821 /** deinitialization callback for crossover before SCIP is freed */
2822 static
2823 DECL_NHFREE(nhFreeCrossover)
2824 { /*lint --e{715}*/
2825  assert(neighborhood->data.crossover != NULL);
2826  SCIPfreeBlockMemory(scip, &neighborhood->data.crossover);
2827 
2828  return SCIP_OKAY;
2829 }
2830 
2831 /** callback to collect variable fixings of crossover */
2832 static
2833 DECL_VARFIXINGS(varFixingsCrossover)
2834 { /*lint --e{715}*/
2835  DATA_CROSSOVER* data;
2836  SCIP_RANDNUMGEN* rng;
2837  SCIP_SOL** sols;
2838  SCIP_SOL** scipsols;
2839  int nsols;
2840  int lastdraw;
2841  assert(scip != NULL);
2842  assert(varbuf != NULL);
2843  assert(nfixings != NULL);
2844  assert(valbuf != NULL);
2845 
2846  data = neighborhood->data.crossover;
2847 
2848  assert(data != NULL);
2849  nsols = data->nsols;
2850  data->selsol = NULL;
2851 
2852  *result = SCIP_DIDNOTRUN;
2853 
2854  /* return if the pool has not enough solutions */
2855  if( nsols > SCIPgetNSols(scip) )
2856  return SCIP_OKAY;
2857 
2858  /* return if no binary or integer variables are present */
2859  if( SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0 )
2860  return SCIP_OKAY;
2861 
2862  rng = data->rng;
2863  lastdraw = SCIPgetNSols(scip);
2864  SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
2865  scipsols = SCIPgetSols(scip);
2866 
2867  /* draw as many solutions from the pool as required by crossover, biased towards
2868  * better solutions; therefore, the sorting of the solutions by objective is implicitly used
2869  */
2870  while( nsols > 0 )
2871  {
2872  /* no need for randomization anymore, exactly nsols many solutions remain for the selection */
2873  if( lastdraw == nsols )
2874  {
2875  int s;
2876 
2877  /* fill the remaining slots 0,...,nsols - 1 by the solutions at the same places */
2878  for( s = 0; s < nsols; ++s )
2879  sols[s] = scipsols[s];
2880 
2881  nsols = 0;
2882  }
2883  else
2884  {
2885  int nextdraw;
2886 
2887  assert(nsols < lastdraw);
2888 
2889  /* draw from the lastdraw - nsols many solutions nsols - 1, ... lastdraw - 1 such that nsols many solution */
2890  nextdraw = SCIPrandomGetInt(rng, nsols - 1, lastdraw - 1);
2891  assert(nextdraw >= 0);
2892 
2893  sols[nsols - 1] = scipsols[nextdraw];
2894  nsols--;
2895  lastdraw = nextdraw;
2896  }
2897  }
2898 
2899  SCIP_CALL( fixMatchingSolutionValues(scip, sols, data->nsols, NULL, -1, varbuf, valbuf, nfixings) );
2900 
2901  /* store best selected solution as reference solution */
2902  data->selsol = sols[0];
2903  assert(data->selsol != NULL);
2904 
2905  *result = SCIP_SUCCESS;
2906 
2907  SCIPfreeBufferArray(scip, &sols);
2908 
2909  return SCIP_OKAY;
2910 }
2911 
2912 /** callback for crossover reference solution */
2913 static
2914 DECL_NHREFSOL(nhRefsolCrossover)
2915 { /*lint --e{715}*/
2916  DATA_CROSSOVER* data;
2917 
2918  data = neighborhood->data.crossover;
2919 
2920  if( data->selsol != NULL )
2921  {
2922  *solptr = data->selsol;
2923  *result = SCIP_SUCCESS;
2924  }
2925  else
2926  {
2927  *result = SCIP_DIDNOTFIND;
2928  }
2929 
2930  return SCIP_OKAY;
2931 }
2932 
2933 /** initialization callback for mutation when a new problem is read */
2934 static
2935 DECL_NHINIT(nhInitMutation)
2936 { /*lint --e{715}*/
2937  DATA_MUTATION* data;
2938  assert(scip != NULL);
2939  assert(neighborhood != NULL);
2940 
2941  SCIP_CALL( SCIPallocBlockMemory(scip, &neighborhood->data.mutation) );
2942 
2943  data = neighborhood->data.mutation;
2944  assert(data != NULL);
2945 
2946  SCIP_CALL( SCIPcreateRandom(scip, &data->rng, MUTATIONSEED + (unsigned int)SCIPgetNVars(scip)) );
2947 
2948  return SCIP_OKAY;
2949 }
2950 
2951 /** deinitialization callback for mutation when exiting a problem */
2952 static
2953 DECL_NHEXIT(nhExitMutation)
2954 { /*lint --e{715}*/
2955  DATA_MUTATION* data;
2956  assert(scip != NULL);
2957  assert(neighborhood != NULL);
2958  data = neighborhood->data.mutation;
2959  assert(data != NULL);
2960 
2961  SCIPfreeRandom(scip, &data->rng);
2962 
2963  SCIPfreeBlockMemory(scip, &neighborhood->data.mutation);
2964 
2965  return SCIP_OKAY;
2966 }
2967 
2968 /** callback to collect variable fixings of mutation */
2969 static
2970 DECL_VARFIXINGS(varFixingsMutation)
2971 { /*lint --e{715}*/
2972  SCIP_RANDNUMGEN* rng;
2973 
2974  SCIP_VAR** vars;
2975  SCIP_VAR** varscpy;
2976  int i;
2977  int nvars;
2978  int nbinvars;
2979  int nintvars;
2980  int nbinintvars;
2981  int ntargetfixings;
2982  SCIP_SOL* incumbentsol;
2983  SCIP_Real targetfixingrate;
2984 
2985  assert(scip != NULL);
2986  assert(neighborhood != NULL);
2987  assert(neighborhood->data.mutation != NULL);
2988  assert(neighborhood->data.mutation->rng != NULL);
2989  rng = neighborhood->data.mutation->rng;
2990 
2991  *result = SCIP_DIDNOTRUN;
2992 
2993  /* get the problem variables */
2994  SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
2995 
2996  nbinintvars = nbinvars + nintvars;
2997  if( nbinintvars == 0 )
2998  return SCIP_OKAY;
2999 
3000  incumbentsol = SCIPgetBestSol(scip);
3001  if( incumbentsol == NULL )
3002  return SCIP_OKAY;
3003 
3004  targetfixingrate = neighborhood->fixingrate.targetfixingrate;
3005  ntargetfixings = (int)(targetfixingrate * nbinintvars) + 1;
3006 
3007  /* don't continue if number of discrete variables is too small to reach target fixing rate */
3008  if( nbinintvars <= ntargetfixings )
3009  return SCIP_OKAY;
3010 
3011  *result = SCIP_DIDNOTFIND;
3012 
3013  /* copy variables into a buffer array */
3014  SCIP_CALL( SCIPduplicateBufferArray(scip, &varscpy, vars, nbinintvars) );
3015 
3016  /* partially perturb the array until the number of target fixings is reached */
3017  for( i = 0; *nfixings < ntargetfixings && i < nbinintvars; ++i )
3018  {
3019  int randint = SCIPrandomGetInt(rng, i, nbinintvars - 1);
3020  assert(randint < nbinintvars);
3021 
3022  if( randint > i )
3023  {
3024  SCIPswapPointers((void**)&varscpy[i], (void**)&varscpy[randint]);
3025  }
3026  /* copy the selected variables and their solution values into the buffer */
3027  tryAdd2variableBuffer(scip, varscpy[i], SCIPgetSolVal(scip, incumbentsol, varscpy[i]), varbuf, valbuf, nfixings, TRUE);
3028  }
3029 
3030  assert(i == nbinintvars || *nfixings == ntargetfixings);
3031 
3032  /* Not reaching the number of target fixings means that there is a significant fraction (at least 1 - targetfixingrate)
3033  * of variables for which the incumbent solution value does not lie within the global bounds anymore. This is a nonsuccess
3034  * for the neighborhood (additional fixings are not possible), which is okay because the incumbent solution is
3035  * significantly outdated
3036  */
3037  if( *nfixings == ntargetfixings )
3038  *result = SCIP_SUCCESS;
3039 
3040  /* free the buffer array */
3041  SCIPfreeBufferArray(scip, &varscpy);
3042 
3043  return SCIP_OKAY;
3044 }
3045 
3046 /** add local branching constraint */
3047 static
3049  SCIP* sourcescip, /**< source SCIP data structure */
3050  SCIP* targetscip, /**< target SCIP data structure */
3051  SCIP_VAR** subvars, /**< array of sub SCIP variables in same order as source SCIP variables */
3052  int distance, /**< right hand side of the local branching constraint */
3053  SCIP_Bool* success, /**< pointer to store of a local branching constraint has been successfully added */
3054  int* naddedconss /**< pointer to increase the number of added constraints */
3055  )
3056 {
3057  int nbinvars;
3058  int i;
3059  SCIP_SOL* referencesol;
3060  SCIP_CONS* localbranchcons;
3061  SCIP_VAR** vars;
3062  SCIP_Real* consvals;
3063  SCIP_Real rhs;
3064 
3065  assert(sourcescip != NULL);
3066  assert(*success == FALSE);
3067 
3068  nbinvars = SCIPgetNBinVars(sourcescip);
3069  vars = SCIPgetVars(sourcescip);
3070 
3071 
3072  if( nbinvars <= 3 )
3073  return SCIP_OKAY;
3074 
3075  referencesol = SCIPgetBestSol(sourcescip);
3076  if( referencesol == NULL )
3077  return SCIP_OKAY;
3078 
3079  rhs = (SCIP_Real)distance;
3080  rhs = MAX(rhs, 2.0);
3081 
3082 
3083  SCIP_CALL( SCIPallocBufferArray(sourcescip, &consvals, nbinvars) );
3084 
3085  /* loop over binary variables and fill the local branching constraint */
3086  for( i = 0; i < nbinvars; ++i )
3087  {
3088  if( SCIPisEQ(sourcescip, SCIPgetSolVal(sourcescip, referencesol, vars[i]), 0.0) )
3089  consvals[i] = 1.0;
3090  else
3091  {
3092  consvals[i] = -1.0;
3093  rhs -= 1.0;
3094  }
3095  }
3096 
3097  /* create the local branching constraint in the target scip */
3098  SCIP_CALL( SCIPcreateConsBasicLinear(targetscip, &localbranchcons, "localbranch", nbinvars, subvars, consvals, -SCIPinfinity(sourcescip), rhs) );
3099  SCIP_CALL( SCIPaddCons(targetscip, localbranchcons) );
3100  SCIP_CALL( SCIPreleaseCons(targetscip, &localbranchcons) );
3101 
3102  *naddedconss = 1;
3103  *success = TRUE;
3104 
3105  SCIPfreeBufferArray(sourcescip, &consvals);
3106 
3107  return SCIP_OKAY;
3108 }
3109 
3110 /** callback for local branching subproblem changes */
3111 static
3112 DECL_CHANGESUBSCIP(changeSubscipLocalbranching)
3113 { /*lint --e{715}*/
3114 
3115  SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.2 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
3116 
3117  return SCIP_OKAY;
3118 }
3119 
3120 /** callback for proximity subproblem changes */
3121 static
3122 DECL_CHANGESUBSCIP(changeSubscipProximity)
3123 { /*lint --e{715}*/
3124  SCIP_SOL* referencesol;
3125  SCIP_VAR** vars;
3126  int nbinvars;
3127  int nintvars;
3128  int nvars;
3129  int i;
3130 
3131  SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
3132 
3133  if( nbinvars == 0 )
3134  return SCIP_OKAY;
3135 
3136  referencesol = SCIPgetBestSol(sourcescip);
3137  if( referencesol == NULL )
3138  return SCIP_OKAY;
3139 
3140  /* loop over binary variables, set objective coefficients based on reference solution in a local branching fashion */
3141  for( i = 0; i < nbinvars; ++i )
3142  {
3143  SCIP_Real newobj;
3144  if( SCIPgetSolVal(sourcescip, referencesol, vars[i]) < 0.5 )
3145  newobj = -1.0;
3146  else
3147  newobj = 1.0;
3148  SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], newobj) );
3149  }
3150 
3151  /* loop over the remaining variables and change their objective coefficients to 0 */
3152  for( ; i < nvars; ++i )
3153  {
3154  SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
3155  }
3156 
3157  *nchgobjs = nvars;
3158  *success = TRUE;
3159 
3160  return SCIP_OKAY;
3161 }
3162 
3163 /** callback for zeroobjective subproblem changes */
3164 static
3165 DECL_CHANGESUBSCIP(changeSubscipZeroobjective)
3166 { /*lint --e{715}*/
3167  SCIP_VAR** vars;
3168  int nvars;
3169  int i;
3170 
3171  assert(*success == FALSE);
3172 
3173  SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, NULL, NULL, NULL, NULL) );
3174 
3175  /* do not run if no objective variables are present */
3176  if( SCIPgetNObjVars(sourcescip) == 0 )
3177  return SCIP_OKAY;
3178 
3179  /* loop over the variables and change their objective coefficients to 0 */
3180  for( i = 0; i < nvars; ++i )
3181  {
3182  SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
3183  }
3184 
3185  *nchgobjs = nvars;
3186  *success = TRUE;
3187 
3188  return SCIP_OKAY;
3189 }
3190 
3191 /** compute tightened bounds for integer variables depending on how much the LP and the incumbent solution values differ */
3192 static
3194  SCIP* scip, /**< SCIP data structure of the original problem */
3195  SCIP_VAR* var, /**< the variable for which bounds should be computed */
3196  SCIP_Real* lbptr, /**< pointer to store the lower bound in the DINS sub-SCIP */
3197  SCIP_Real* ubptr /**< pointer to store the upper bound in the DINS sub-SCIP */
3198  )
3199 {
3200  SCIP_Real mipsol;
3201  SCIP_Real lpsol;
3202 
3203  SCIP_Real lbglobal;
3204  SCIP_Real ubglobal;
3205  SCIP_SOL* bestsol;
3206 
3207  /* get the bounds for each variable */
3208  lbglobal = SCIPvarGetLbGlobal(var);
3209  ubglobal = SCIPvarGetUbGlobal(var);
3210 
3211  assert(SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER);
3212  /* get the current LP solution for each variable */
3213  lpsol = SCIPvarGetLPSol(var);
3214 
3215  /* get the current MIP solution for each variable */
3216  bestsol = SCIPgetBestSol(scip);
3217  mipsol = SCIPgetSolVal(scip, bestsol, var);
3218 
3219 
3220  /* if the solution values differ by 0.5 or more, the variable is rebounded, otherwise it is just copied */
3221  if( REALABS(lpsol - mipsol) >= 0.5 )
3222  {
3223  SCIP_Real range;
3224 
3225  *lbptr = lbglobal;
3226  *ubptr = ubglobal;
3227 
3228  /* create an equally sized range around lpsol for general integers: bounds are lpsol +- (mipsol-lpsol) */
3229  range = 2 * lpsol - mipsol;
3230 
3231  if( mipsol >= lpsol )
3232  {
3233  range = SCIPfeasCeil(scip, range);
3234  *lbptr = MAX(*lbptr, range);
3235 
3236  /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
3237  if( SCIPisFeasEQ(scip, mipsol, *lbptr) )
3238  *ubptr = *lbptr;
3239  else
3240  *ubptr = mipsol;
3241  }
3242  else
3243  {
3244  range = SCIPfeasFloor(scip, range);
3245  *ubptr = MIN(*ubptr, range);
3246 
3247  /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
3248  if( SCIPisFeasEQ(scip, mipsol, *ubptr) )
3249  *lbptr = *ubptr;
3250  else
3251  *lbptr = mipsol;
3252  }
3253 
3254  /* the global domain of variables might have been reduced since incumbent was found: adjust lb and ub accordingly */
3255  *lbptr = MAX(*lbptr, lbglobal);
3256  *ubptr = MIN(*ubptr, ubglobal);
3257  }
3258  else
3259  {
3260  /* the global domain of variables might have been reduced since incumbent was found: adjust it accordingly */
3261  *lbptr = MAX(mipsol, lbglobal);
3262  *ubptr = MIN(mipsol, ubglobal);
3263  }
3264 }
3265 
3266 /** callback to collect variable fixings of DINS */
3267 static
3268 DECL_VARFIXINGS(varFixingsDins)
3270  DATA_DINS* data;
3271  SCIP_SOL* rootlpsol;
3272  SCIP_SOL** sols;
3273  int nsols;
3274  int nmipsols;
3275  int nbinvars;
3276  int nintvars;
3277  SCIP_VAR** vars;
3278  int v;
3279 
3280  data = neighborhood->data.dins;
3281  assert(data != NULL);
3282  nmipsols = SCIPgetNSols(scip);
3283  nmipsols = MIN(nmipsols, data->npoolsols);
3284 
3285  *result = SCIP_DELAYED;
3286 
3288  return SCIP_OKAY;
3289 
3290  *result = SCIP_DIDNOTRUN;
3291 
3292  if( nmipsols == 0 )
3293  return SCIP_OKAY;
3294 
3295  SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
3296 
3297  if( nbinvars + nintvars == 0 )
3298  return SCIP_OKAY;
3299 
3300  SCIP_CALL( SCIPcreateSol(scip, &rootlpsol, NULL) );
3301 
3302  /* save root solution LP values in solution */
3303  for( v = 0; v < nbinvars + nintvars; ++v )
3304  {
3305  SCIP_CALL( SCIPsetSolVal(scip, rootlpsol, vars[v], SCIPvarGetRootSol(vars[v])) );
3306  }
3307 
3308  /* add the node and the root LP solution */
3309  nsols = nmipsols + 2;
3310 
3311  SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
3312  sols[0] = NULL; /* node LP solution */
3313  sols[1] = rootlpsol;
3314 
3315  /* copy the remaining MIP solutions after the LP solutions */
3316  BMScopyMemoryArray(&sols[2], SCIPgetSols(scip), nmipsols); /*lint !e866*/
3317 
3318  /* 1. Binary variables are fixed if their values agree in all the solutions */
3319  if( nbinvars > 0 )
3320  {
3321  SCIP_CALL( fixMatchingSolutionValues(scip, sols, nsols, vars, nbinvars, varbuf, valbuf, nfixings) );
3322  }
3323 
3324  /* 2. Integer variables are fixed if they have a very low distance between the incumbent and the root LP solution */
3325  for( v = nbinvars; v < nintvars; ++v )
3326  {
3327  SCIP_Real lb;
3328  SCIP_Real ub;
3329  computeIntegerVariableBoundsDins(scip, vars[v], &lb, &ub);
3330 
3331  if( ub - lb < 0.5 )
3332  {
3333  assert(SCIPisFeasIntegral(scip, lb));
3334  tryAdd2variableBuffer(scip, vars[v], lb, varbuf, valbuf, nfixings, TRUE);
3335  }
3336  }
3337 
3338  *result = SCIP_SUCCESS;
3339 
3340  SCIPfreeBufferArray(scip, &sols);
3341 
3342  SCIP_CALL( SCIPfreeSol(scip, &rootlpsol) );
3343 
3344  return SCIP_OKAY;
3345 }
3346 
3347 /** callback for DINS subproblem changes */
3348 static
3349 DECL_CHANGESUBSCIP(changeSubscipDins)
3350 { /*lint --e{715}*/
3351  SCIP_VAR** vars;
3352  int nintvars;
3353  int nbinvars;
3354  int v;
3355 
3356  SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
3357 
3358  /* 1. loop over integer variables and tighten the bounds */
3359  for( v = nbinvars; v < nintvars; ++v )
3360  {
3361  SCIP_Real lb;
3362  SCIP_Real ub;
3363 
3364  computeIntegerVariableBoundsDins(sourcescip, vars[v], &lb, &ub);
3365 
3366  SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[v], lb) );
3367  SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[v], ub) );
3368  ++(*ndomchgs);
3369  }
3370 
3371  /* 2. add local branching constraint for binary variables */
3372  SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.1 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
3373 
3374  *success = TRUE;
3375 
3376  return SCIP_OKAY;
3377 }
3378 
3379 /** deinitialization callback for DINS before SCIP is freed */
3380 static
3381 DECL_NHFREE(nhFreeDins)
3383  assert(neighborhood->data.dins != NULL);
3384 
3385  SCIPfreeBlockMemory(scip, &neighborhood->data.dins);
3386 
3387  return SCIP_OKAY;
3388 }
3389 
3390 /** callback that returns the incumbent solution as a reference point */
3391 static
3392 DECL_NHREFSOL(nhRefsolIncumbent)
3393 { /*lint --e{715}*/
3394  assert(scip != NULL);
3395 
3396  if( SCIPgetBestSol(scip) != NULL )
3397  {
3398  *result = SCIP_SUCCESS;
3399  *solptr = SCIPgetBestSol(scip);
3400  }
3401  else
3402  {
3403  *result = SCIP_DIDNOTFIND;
3404  }
3405 
3406  return SCIP_OKAY;
3407 }
3408 
3409 
3410 /** callback function that deactivates a neighborhood on problems with no discrete variables */
3411 static
3412 DECL_NHDEACTIVATE(nhDeactivateDiscreteVars)
3413 { /*lint --e{715}*/
3414  assert(scip != NULL);
3415  assert(deactivate != NULL);
3416 
3417  /* deactivate if no discrete variables are present */
3418  *deactivate = (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0);
3419 
3420  return SCIP_OKAY;
3421 }
3422 
3423 /** callback function that deactivates a neighborhood on problems with no binary variables */
3424 static
3425 DECL_NHDEACTIVATE(nhDeactivateBinVars)
3426 { /*lint --e{715}*/
3427  assert(scip != NULL);
3428  assert(deactivate != NULL);
3429 
3430  /* deactivate if no discrete variables are present */
3431  *deactivate = (SCIPgetNBinVars(scip) == 0);
3432 
3433  return SCIP_OKAY;
3434 }
3435 
3436 /** callback function that deactivates a neighborhood on problems with no objective variables */
3437 static
3438 DECL_NHDEACTIVATE(nhDeactivateObjVars)
3439 { /*lint --e{715}*/
3440  assert(scip != NULL);
3441  assert(deactivate != NULL);
3442 
3443  /* deactivate if no discrete variables are present */
3444  *deactivate = (SCIPgetNObjVars(scip) == 0);
3445 
3446  return SCIP_OKAY;
3447 }
3448 
3449 
3450 /** include all neighborhoods */
3451 static
3453  SCIP* scip, /**< SCIP data structure */
3454  SCIP_HEURDATA* heurdata /**< heuristic data of the ALNS heuristic */
3455  )
3456 {
3457  NH* rens;
3458  NH* rins;
3459  NH* mutation;
3460  NH* localbranching;
3461  NH* crossover;
3462  NH* proximity;
3463  NH* zeroobjective;
3464  NH* dins;
3465 
3466  heurdata->nneighborhoods = 0;
3467 
3468  /* include the RENS neighborhood */
3469  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &rens, "rens",
3471  varFixingsRens, changeSubscipRens, NULL, NULL, NULL, NULL, nhDeactivateDiscreteVars) );
3472 
3473  /* include the RINS neighborhood */
3474  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &rins, "rins",
3476  varFixingsRins, NULL, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
3477 
3478  /* include the mutation neighborhood */
3479  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &mutation, "mutation",
3481  varFixingsMutation, NULL, nhInitMutation, nhExitMutation, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
3482 
3483  /* include the local branching neighborhood */
3484  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &localbranching, "localbranching",
3486  NULL, changeSubscipLocalbranching, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
3487 
3488  /* include the crossover neighborhood */
3489  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &crossover, "crossover",
3491  varFixingsCrossover, NULL,
3492  nhInitCrossover, nhExitCrossover, nhFreeCrossover, nhRefsolCrossover, nhDeactivateDiscreteVars) );
3493 
3494  /* allocate data for crossover to include the parameter */
3495  SCIP_CALL( SCIPallocBlockMemory(scip, &crossover->data.crossover) );
3496  crossover->data.crossover->rng = NULL;
3497 
3498  /* add crossover neighborhood parameters */
3499  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/alns/crossover/nsols", "the number of solutions that crossover should combine",
3500  &crossover->data.crossover->nsols, TRUE, DEFAULT_NSOLS_CROSSOVER, 2, 10, NULL, NULL) );
3501 
3502  /* include the Proximity neighborhood */
3503  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &proximity, "proximity",
3505  NULL, changeSubscipProximity, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
3506 
3507  /* include the Zeroobjective neighborhood */
3508  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &zeroobjective, "zeroobjective",
3510  NULL, changeSubscipZeroobjective, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateObjVars) );
3511 
3512  /* include the DINS neighborhood */
3513  SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &dins, "dins",
3515  varFixingsDins, changeSubscipDins, NULL, NULL, nhFreeDins, nhRefsolIncumbent, nhDeactivateBinVars) );
3516 
3517  /* allocate data for DINS to include the parameter */
3518  SCIP_CALL( SCIPallocBlockMemory(scip, &dins->data.dins) );
3519 
3520  /* add DINS neighborhood parameters */
3521  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/alns/dins/npoolsols",
3522  "number of pool solutions where binary solution values must agree",
3523  &dins->data.dins->npoolsols, TRUE, DEFAULT_NPOOLSOLS_DINS, 1, 100, NULL, NULL) );
3524 
3525  return SCIP_OKAY;
3526 }
3527 
3528 /** initialization method of primal heuristic (called after problem was transformed) */
3529 static
3530 SCIP_DECL_HEURINIT(heurInitAlns)
3531 { /*lint --e{715}*/
3532  SCIP_HEURDATA* heurdata;
3533  int i;
3534 
3535  assert(scip != NULL);
3536  assert(heur != NULL);
3537 
3538  heurdata = SCIPheurGetData(heur);
3539  assert(heurdata != NULL);
3540 
3541  /* reactivate all neighborhoods if a new problem is read in */
3542  heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
3543 
3544  /* todo initialize neighborhoods for new problem */
3545  for( i = 0; i < heurdata->nneighborhoods; ++i )
3546  {
3547  NH* neighborhood = heurdata->neighborhoods[i];
3548 
3549  SCIP_CALL( neighborhoodInit(scip, neighborhood) );
3550 
3551  SCIP_CALL( resetFixingRate(scip, &neighborhood->fixingrate) );
3552 
3553  SCIP_CALL( neighborhoodStatsReset(scip, &neighborhood->stats) );
3554  }
3555 
3556  /* open reward file for reading */
3557  if( strncasecmp(heurdata->rewardfilename, DEFAULT_REWARDFILENAME, strlen(DEFAULT_REWARDFILENAME)) != 0 )
3558  {
3559  heurdata->rewardfile = fopen(heurdata->rewardfilename, "w");
3560 
3561  if( heurdata->rewardfile == NULL )
3562  {
3563  SCIPerrorMessage("Error: Could not open reward file <%s>\n", heurdata->rewardfilename);
3564  return SCIP_FILECREATEERROR;
3565  }
3566 
3567  SCIPdebugMsg(scip, "Writing reward information to <%s>\n", heurdata->rewardfilename);
3568  }
3569  else
3570  heurdata->rewardfile = NULL;
3571 
3572  return SCIP_OKAY;
3573 }
3574 
3575 
3576 /** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
3577 static
3578 SCIP_DECL_HEURINITSOL(heurInitsolAlns)
3579 { /*lint --e{715}*/
3580  SCIP_HEURDATA* heurdata;
3581  int i;
3582  SCIP_Real* priorities;
3583  unsigned int initseed;
3584 
3585  assert(scip != NULL);
3586  assert(heur != NULL);
3587 
3588  heurdata = SCIPheurGetData(heur);
3589  assert(heurdata != NULL);
3590  heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
3591 
3592  SCIP_CALL( SCIPallocBufferArray(scip, &priorities, heurdata->nactiveneighborhoods) );
3593 
3594  /* init neighborhoods for new problem by resetting their statistics and fixing rate */
3595  for( i = heurdata->nneighborhoods - 1; i >= 0; --i )
3596  {
3597  NH* neighborhood = heurdata->neighborhoods[i];
3598  SCIP_Bool deactivate;
3599 
3600  SCIP_CALL( neighborhood->nhdeactivate(scip, &deactivate) );
3601 
3602  /* disable inactive neighborhoods */
3603  if( deactivate || ! neighborhood->active )
3604  {
3605  if( heurdata->nactiveneighborhoods - 1 > i )
3606  {
3607  assert(heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]->active);
3608  SCIPswapPointers((void **)&heurdata->neighborhoods[i], (void **)&heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]);
3609  }
3610  heurdata->nactiveneighborhoods--;
3611  }
3612  }
3613 
3614  /* collect neighborhood priorities */
3615  for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
3616  priorities[i] = heurdata->neighborhoods[i]->priority;
3617 
3618  initseed = (unsigned int)heurdata->seed + SCIPgetNVars(scip);
3619 
3620  /* active neighborhoods might change between init calls, reset functionality must take this into account */
3621  if( heurdata->bandit != NULL && SCIPbanditGetNActions(heurdata->bandit) != heurdata->nactiveneighborhoods )
3622  {
3623  SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
3624 
3625  heurdata->bandit = NULL;
3626  }
3627 
3628  if( heurdata->nactiveneighborhoods > 0 )
3629  { /* create or reset bandit algorithm */
3630  if( heurdata->bandit == NULL )
3631  {
3632  SCIP_CALL( createBandit(scip, heurdata, priorities, initseed) );
3633 
3634  resetMinimumImprovement(heurdata);
3635  resetTargetNodeLimit(heurdata);
3636  }
3637  else if( heurdata->resetweights )
3638  {
3639  SCIP_CALL( SCIPresetBandit(scip, heurdata->bandit, priorities, initseed) );
3640 
3641  resetMinimumImprovement(heurdata);
3642  resetTargetNodeLimit(heurdata);
3643  }
3644  }
3645 
3646  heurdata->usednodes = 0;
3647  heurdata->ninitneighborhoods = heurdata->nactiveneighborhoods;
3648  resetCurrentNeighborhood(heurdata);
3649 
3650  SCIPfreeBufferArray(scip, &priorities);
3651 
3652  return SCIP_OKAY;
3653 }
3654 
3655 
3656 /** deinitialization method of primal heuristic (called before transformed problem is freed) */
3657 static
3658 SCIP_DECL_HEUREXIT(heurExitAlns)
3659 { /*lint --e{715}*/
3660 
3661  SCIP_HEURDATA* heurdata;
3662  int i;
3663 
3664  assert(scip != NULL);
3665  assert(heur != NULL);
3666 
3667  heurdata = SCIPheurGetData(heur);
3668  assert(heurdata != NULL);
3669 
3670  /* free neighborhood specific data */
3671  for( i = 0; i < heurdata->nneighborhoods; ++i )
3672  {
3673  NH* neighborhood = heurdata->neighborhoods[i];
3674 
3675  SCIP_CALL( neighborhoodExit(scip, neighborhood) );
3676  }
3677 
3678  if( heurdata->rewardfile != NULL )
3679  {
3680  fclose(heurdata->rewardfile);
3681  heurdata->rewardfile = NULL;
3682  }
3683 
3684  return SCIP_OKAY;
3685 }
3686 
3687 /** destructor of primal heuristic to free user data (called when SCIP is exiting) */
3688 static
3689 SCIP_DECL_HEURFREE(heurFreeAlns)
3690 { /*lint --e{715}*/
3691  SCIP_HEURDATA* heurdata;
3692  int i;
3693 
3694  assert(scip != NULL);
3695  assert(heur != NULL);
3696 
3697  heurdata = SCIPheurGetData(heur);
3698  assert(heurdata != NULL);
3699 
3700  /* bandits are only initialized if a problem has been read */
3701  if( heurdata->bandit != NULL )
3702  {
3703  SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
3704  }
3705 
3706  /* free neighborhoods */
3707  for( i = 0; i < heurdata->nneighborhoods; ++i )
3708  {
3709  SCIP_CALL( alnsFreeNeighborhood(scip, &(heurdata->neighborhoods[i])) );
3710  }
3711 
3712  SCIPfreeBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS);
3713 
3714  SCIPfreeBlockMemory(scip, &heurdata);
3715 
3716  return SCIP_OKAY;
3717 }
3718 
3719 /** output method of statistics table to output file stream 'file' */
3720 static
3721 SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
3722 { /*lint --e{715}*/
3723  SCIP_HEURDATA* heurdata;
3724 
3725  assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
3726  heurdata = SCIPheurGetData(SCIPfindHeur(scip, HEUR_NAME));
3727  assert(heurdata != NULL);
3728 
3729  printNeighborhoodStatistics(scip, heurdata, file);
3730 
3731  return SCIP_OKAY;
3732 }
3733 
3734 /*
3735  * primal heuristic specific interface methods
3736  */
3737 
3738 /** creates the alns primal heuristic and includes it in SCIP */
3740  SCIP* scip /**< SCIP data structure */
3741  )
3742 {
3743  SCIP_HEURDATA* heurdata;
3744  SCIP_HEUR* heur;
3745 
3746  /* create alns primal heuristic data */
3747  heurdata = NULL;
3748  heur = NULL;
3749 
3750  SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
3751  BMSclearMemory(heurdata);
3752 
3753  /* TODO make this a user parameter? */
3754  heurdata->lplimfac = LPLIMFAC;
3755 
3756  SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS) );
3757 
3758  /* include primal heuristic */
3759  SCIP_CALL( SCIPincludeHeurBasic(scip, &heur,
3761  HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecAlns, heurdata) );
3762 
3763  assert(heur != NULL);
3764 
3765  /* include all neighborhoods */
3766  SCIP_CALL( includeNeighborhoods(scip, heurdata) );
3767 
3768  /* set non fundamental callbacks via setter functions */
3769  SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyAlns) );
3770  SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeAlns) );
3771  SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitAlns) );
3772  SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolAlns) );
3773  SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitAlns) );
3774 
3775  /* add alns primal heuristic parameters */
3776  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
3777  "maximum number of nodes to regard in the subproblem",
3778  &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3779 
3780  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
3781  "offset added to the nodes budget",
3782  &heurdata->nodesoffset, FALSE, DEFAULT_NODESOFFSET, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3783 
3784  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
3785  "minimum number of nodes required to start a sub-SCIP",
3786  &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3787 
3788  SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/waitingnodes",
3789  "number of nodes since last incumbent solution that the heuristic should wait",
3790  &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
3791 
3792  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
3793  "fraction of nodes compared to the main SCIP for budget computation",
3794  &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
3795 
3796  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/startminimprove",
3797  "initial factor by which ALNS should at least improve the incumbent",
3798  &heurdata->startminimprove, TRUE, DEFAULT_STARTMINIMPROVE, 0.0, 1.0, NULL, NULL) );
3799 
3800  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprovelow",
3801  "lower threshold for the minimal improvement over the incumbent",
3802  &heurdata->minimprovelow, TRUE, DEFAULT_MINIMPROVELOW, 0.0, 1.0, NULL, NULL) );
3803 
3804  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprovehigh",
3805  "upper bound for the minimal improvement over the incumbent",
3806  &heurdata->minimprovehigh, TRUE, DEFAULT_MINIMPROVEHIGH, 0.0, 1.0, NULL, NULL) );
3807 
3808  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nsolslim",
3809  "limit on the number of improving solutions in a sub-SCIP call",
3810  &heurdata->nsolslim, FALSE, DEFAULT_NSOLSLIM, -1, INT_MAX, NULL, NULL) );
3811 
3812  SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/banditalgo",
3813  "the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy",
3814  &heurdata->banditalgo, TRUE, DEFAULT_BANDITALGO, "ueg", NULL, NULL) );
3815 
3816  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gamma",
3817  "weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3",
3818  &heurdata->exp3_gamma, TRUE, DEFAULT_GAMMA, 0.0, 1.0, NULL, NULL) );
3819 
3820  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/beta",
3821  "reward offset between 0 and 1 at every observation for Exp.3",
3822  &heurdata->exp3_beta, TRUE, DEFAULT_BETA, 0.0, 1.0, NULL, NULL) );
3823 
3824  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/alpha",
3825  "parameter to increase the confidence width in UCB",
3826  &heurdata->ucb_alpha, TRUE, DEFAULT_ALPHA, 0.0, 100.0, NULL, NULL) );
3827 
3828  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usedistances",
3829  "distances from fixed variables be used for variable prioritization",
3830  &heurdata->usedistances, TRUE, DEFAULT_USEDISTANCES, NULL, NULL) );
3831 
3832  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useredcost",
3833  "should reduced cost scores be used for variable prioritization?",
3834  &heurdata->useredcost, TRUE, DEFAULT_USEREDCOST, NULL, NULL) );
3835 
3836  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/domorefixings",
3837  "should the ALNS heuristic do more fixings by itself based on variable prioritization"
3838  "until the target fixing rate is reached?",
3839  &heurdata->domorefixings, TRUE, DEFAULT_DOMOREFIXINGS, NULL, NULL) );
3840 
3841  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjustfixingrate",
3842  "should the heuristic adjust the target fixing rate based on the success?",
3843  &heurdata->adjustfixingrate, TRUE, DEFAULT_ADJUSTFIXINGRATE, NULL, NULL) );
3844 
3845  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usesubscipheurs",
3846  "should the heuristic activate other sub-SCIP heuristics during its search?",
3847  &heurdata->usesubscipheurs, TRUE, DEFAULT_USESUBSCIPHEURS, NULL, NULL) );
3848 
3849  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rewardcontrol",
3850  "reward control to increase the weight of the simple solution indicator and decrease the weight of the closed gap reward",
3851  &heurdata->rewardcontrol, TRUE, DEFAULT_REWARDCONTROL, 0.0, 1.0, NULL, NULL) );
3852 
3853  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/targetnodefactor",
3854  "factor by which target node number is increased/decreased at every adjustment",
3855  &heurdata->targetnodefactor, TRUE, DEFAULT_TARGETNODEFACTOR, 1.0, 1e+5, NULL, NULL) );
3856 
3857  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/stallnodefactor",
3858  "stall node limit as a fraction of total node limit",
3859  &heurdata->stallnodefactor, TRUE, DEFAULT_STALLNODEFACTOR, 0.0, 1.0, NULL, NULL) );
3860 
3861  SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/seed",
3862  "initial random seed for bandit algorithms and random decisions by neighborhoods",
3863  &heurdata->seed, FALSE, DEFAULT_SEED, 0, INT_MAX, NULL, NULL) );
3864 
3865  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjustminimprove",
3866  "should the factor by which the minimum improvement is bound be dynamically updated?",
3867  &heurdata->adjustminimprove, TRUE, DEFAULT_ADJUSTMINIMPROVE, NULL, NULL) );
3868 
3869  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/eps",
3870  "increase exploration in epsilon-greedy bandit algorithm",
3871  &heurdata->epsgreedy_eps, TRUE, DEFAULT_EPS, 0.0, 1.0, NULL, NULL) );
3872 
3873  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rewardbaseline",
3874  "the reward baseline to separate successful and failed calls",
3875  &heurdata->rewardbaseline, TRUE, DEFAULT_REWARDBASELINE, 0.0, 0.99, NULL, NULL) );
3876 
3877  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/resetweights",
3878  "should the bandit algorithms be reset when a new problem is read?",
3879  &heurdata->resetweights, TRUE, DEFAULT_RESETWEIGHTS, NULL, NULL) );
3880 
3881  SCIP_CALL( SCIPaddStringParam(scip, "heuristics/" HEUR_NAME "/rewardfilename", "file name to store all rewards and the selection of the bandit",
3882  &heurdata->rewardfilename, TRUE, DEFAULT_REWARDFILENAME, NULL, NULL) );
3883 
3884  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/subsciprandseeds",
3885  "should random seeds of sub-SCIPs be altered to increase diversification?",
3886  &heurdata->subsciprandseeds, TRUE, DEFAULT_SUBSCIPRANDSEEDS, NULL, NULL) );
3887 
3888  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/scalebyeffort",
3889  "should the reward be scaled by the effort?",
3890  &heurdata->scalebyeffort, TRUE, DEFAULT_SCALEBYEFFORT, NULL, NULL) );
3891 
3892  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
3893  "should cutting planes be copied to the sub-SCIP?",
3894  &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
3895 
3896  SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/fixtol",
3897  "tolerance by which the fixing rate may be missed/exceeded without generic (unfixing)",
3898  &heurdata->fixtol, TRUE, DEFAULT_FIXTOL, 0.0, 1.0, NULL, NULL) );
3899 
3900  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselocalredcost",
3901  "should local reduced costs be used for generic (un)fixing?",
3902  &heurdata->uselocalredcost, TRUE, DEFAULT_USELOCALREDCOST, NULL, NULL) );
3903 
3904  SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usepscost",
3905  "should pseudo cost scores be used for variable priorization?",
3906  &heurdata->usepscost, TRUE, DEFAULT_USEPSCOST, NULL, NULL) );
3907 
3908  assert(SCIPfindTable(scip, TABLE_NAME_NEIGHBORHOOD) == NULL);
3910  NULL, NULL, NULL, NULL, NULL, NULL, tableOutputNeighborhood,
3912 
3913  return SCIP_OKAY;
3914 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
#define DEFAULT_BANDITALGO
Definition: heur_alns.c:70
SCIP_Real targetfixingrate
Definition: heur_alns.c:288
void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
Definition: scip.c:48626
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22604
int SCIPgetNIntVars(SCIP *scip)
Definition: scip.c:11902
#define DEFAULT_GAMMA
Definition: heur_alns.c:71
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47363
NH_STATS stats
Definition: heur_alns.c:298
#define DEFAULT_USESUBSCIPHEURS
Definition: heur_alns.c:95
#define DEFAULT_RESETWEIGHTS
Definition: heur_alns.c:76
static SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
Definition: heur_alns.c:3722
static SCIP_RETCODE addLocalBranchingConstraint(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **subvars, int distance, SCIP_Bool *success, int *naddedconss)
Definition: heur_alns.c:3049
SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22282
int nfixings
Definition: heur_alns.c:279
SCIP_Real SCIPgetSolvingTime(SCIP *scip)
Definition: scip.c:46306
static void decreaseTargetNodeLimit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:549
#define SCIP_EVENTTYPE_LPSOLVED
Definition: type_event.h:84
SCIP_RETCODE SCIPsetSeparating(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5158
SCIP_Real oldupperbound
Definition: heur_alns.c:274
int nruns
Definition: heur_alns.c:275
#define DEFAULT_STARTMINIMPROVE
Definition: heur_alns.c:63
#define SCIPallocBlockMemoryArray(scip, ptr, num)
Definition: scip.h:22587
static SCIP_RETCODE createBandit(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real *priorities, unsigned int initseed)
Definition: heur_alns.c:1526
SCIP_RETCODE SCIPincludeTable(SCIP *scip, const char *name, const char *desc, SCIP_Bool active, SCIP_DECL_TABLECOPY((*tablecopy)), SCIP_DECL_TABLEFREE((*tablefree)), SCIP_DECL_TABLEINIT((*tableinit)), SCIP_DECL_TABLEEXIT((*tableexit)), SCIP_DECL_TABLEINITSOL((*tableinitsol)), SCIP_DECL_TABLEEXITSOL((*tableexitsol)), SCIP_DECL_TABLEOUTPUT((*tableoutput)), SCIP_TABLEDATA *tabledata, int position, SCIP_STAGE earlieststage)
Definition: scip.c:9452
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47298
HistIndex
Definition: heur_alns.c:254
SCIP_RETCODE SCIPcreateBanditExp3(SCIP *scip, SCIP_BANDIT **exp3, SCIP_Real *priorities, SCIP_Real gammaparam, SCIP_Real beta, int nactions, unsigned int initseed)
Definition: bandit_exp3.c:299
#define HEUR_DISPCHAR
Definition: heur_alns.c:34
#define DEFAULT_REWARDBASELINE
Definition: heur_alns.c:79
SCIP_Real * pscostscores
Definition: heur_alns.c:418
SCIP_RETCODE SCIPcreateBanditUcb(SCIP *scip, SCIP_BANDIT **ucb, SCIP_Real *priorities, SCIP_Real alpha, int nactions, unsigned int initseed)
Definition: bandit_ucb.c:325
SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
SCIP_RETCODE SCIPincludeHeurAlns(SCIP *scip)
Definition: heur_alns.c:3740
SCIP_SOL * selsol
Definition: heur_alns.c:327
#define DEFAULT_MAXFIXINGRATE_LOCALBRANCHING
Definition: heur_alns.c:121
static void updateMinimumImprovement(SCIP_HEURDATA *heurdata, SCIP_STATUS subscipstatus, NH_STATS *runstats)
Definition: heur_alns.c:640
enum HistIndex HISTINDEX
Definition: heur_alns.c:264
static SCIP_RETCODE alnsUnfixVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, int ntargetfixings, SCIP_Bool *success)
Definition: heur_alns.c:1582
static void decreaseMinimumImprovement(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:627
SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
Definition: scip.c:6604
SCIP_Real SCIPgetCutoffbound(SCIP *scip)
Definition: scip.c:43453
DATA_DINS * dins
Definition: heur_alns.c:312
static void resetMinimumImprovement(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:605
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
#define DECL_NHINIT(x)
Definition: heur_alns.c:215
#define HEUR_FREQ
Definition: heur_alns.c:36
SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
Definition: scip.c:4489
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
Definition: scip.c:26031
#define DEFAULT_NSOLSLIM
Definition: heur_alns.c:49
static SCIP_DECL_HEURINIT(heurInitAlns)
Definition: heur_alns.c:3531
SCIP_Longint SCIPheurGetNBestSolsFound(SCIP_HEUR *heur)
Definition: heur.c:1344
#define DEFAULT_ACTIVE_CROSSOVER
Definition: heur_alns.c:132
#define DEFAULT_PRIORITY_PROXIMITY
Definition: heur_alns.c:128
SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed)
Definition: scip.c:48608
#define HEUR_TIMING
Definition: heur_alns.c:39
SCIP_RETCODE SCIPbanditSelect(SCIP_BANDIT *bandit, int *action)
Definition: bandit.c:143
SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
Definition: scip.c:8177
SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
Definition: scip.c:19381
static SCIP_RETCODE alnsIncludeNeighborhood(SCIP *scip, SCIP_HEURDATA *heurdata, NH **neighborhood, const char *name, SCIP_Real minfixingrate, SCIP_Real maxfixingrate, SCIP_Bool active, SCIP_Real priority, DECL_VARFIXINGS((*varfixings)), DECL_CHANGESUBSCIP((*changesubscip)), DECL_NHINIT((*nhinit)), DECL_NHEXIT((*nhexit)), DECL_NHFREE((*nhfree)), DECL_NHREFSOL((*nhrefsol)), DECL_NHDEACTIVATE((*nhdeactivate)))
Definition: heur_alns.c:712
#define DEFAULT_PRIORITY_DINS
Definition: heur_alns.c:143
int SCIPgetNOrigVars(SCIP *scip)
Definition: scip.c:12252
#define DEFAULT_USEREDCOST
Definition: heur_alns.c:86
SCIP * scip
Definition: heur_alns.c:414
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
Definition: scip.c:8611
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16842
#define DECL_VARFIXINGS(x)
Definition: heur_alns.c:187
SCIP_TABLE * SCIPfindTable(SCIP *scip, const char *name)
Definition: scip.c:9490
SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:46115
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47387
#define DEFAULT_ACTIVE_RINS
Definition: heur_alns.c:112
#define NNEIGHBORHOODS
Definition: heur_alns.c:42
DATA_CROSSOVER * crossover
Definition: heur_alns.c:311
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12758
#define TABLE_DESC_NEIGHBORHOOD
Definition: heur_alns.c:155
#define DECL_NHREFSOL(x)
Definition: heur_alns.c:240
void SCIPswapPointers(void **pointer1, void **pointer2)
Definition: misc.c:9639
SCIP_RETCODE SCIPgetVarsData(SCIP *scip, SCIP_VAR ***vars, int *nvars, int *nbinvars, int *nintvars, int *nimplvars, int *ncontvars)
Definition: scip.c:11686
#define LPLIMFAC
Definition: heur_alns.c:55
SCIP_SOL ** SCIPgetSols(SCIP *scip)
Definition: scip.c:39832
#define FALSE
Definition: def.h:64
SCIP_RETCODE SCIPhashmapCreate(SCIP_HASHMAP **hashmap, BMS_BLKMEM *blkmem, int mapsize)
Definition: misc.c:2793
#define DEFAULT_ACTIVE_LOCALBRANCHING
Definition: heur_alns.c:122
const char * SCIPeventhdlrGetName(SCIP_EVENTHDLR *eventhdlr)
Definition: event.c:278
SCIP_RETCODE SCIPaddLongintParam(SCIP *scip, const char *name, const char *desc, SCIP_Longint *valueptr, SCIP_Bool isadvanced, SCIP_Longint defaultvalue, SCIP_Longint minvalue, SCIP_Longint maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4293
#define DEFAULT_NODESOFFSET
Definition: heur_alns.c:48
SCIP_Real SCIPinfinity(SCIP *scip)
Definition: scip.c:47028
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
#define TRUE
Definition: def.h:63
SCIP_Longint stallnodes
Definition: heur_alns.c:406
#define DEFAULT_PRIORITY_RINS
Definition: heur_alns.c:113
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
#define DEFAULT_ACTIVE_PROXIMITY
Definition: heur_alns.c:127
#define DEFAULT_MINFIXINGRATE_PROXIMITY
Definition: heur_alns.c:125
SCIP_RETCODE SCIPsetPresolving(SCIP *scip, SCIP_PARAMSETTING paramsetting, SCIP_Bool quiet)
Definition: scip.c:5132
#define DEFAULT_WAITINGNODES
Definition: heur_alns.c:52
SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
Definition: scip.c:9269
NH_FIXINGRATE fixingrate
Definition: heur_alns.c:297
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
#define DEFAULT_NODESQUOT
Definition: heur_alns.c:47
SCIP_Bool SCIPisDualfeasZero(SCIP *scip, SCIP_Real val)
Definition: scip.c:47536
#define DEFAULT_MINIMPROVELOW
Definition: heur_alns.c:60
#define DECL_NHFREE(x)
Definition: heur_alns.c:227
struct SCIP_HeurData SCIP_HEURDATA
Definition: type_heur.h:51
static GRAPHNODE ** active
void SCIPselectInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int k, int len)
static SCIP_RETCODE neighborhoodFixVariables(SCIP *scip, SCIP_HEURDATA *heurdata, NH *neighborhood, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, SCIP_RESULT *result)
Definition: heur_alns.c:1729
static SCIP_DECL_HEUREXIT(heurExitAlns)
Definition: heur_alns.c:3659
#define SCIPfreeBlockMemory(scip, ptr)
Definition: scip.h:22602
SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
Definition: scip.c:8084
SCIP_RETCODE SCIPaddStringParam(SCIP *scip, const char *name, const char *desc, char **valueptr, SCIP_Bool isadvanced, const char *defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4376
#define DEFAULT_REWARDFILENAME
Definition: heur_alns.c:97
#define DEFAULT_MAXFIXINGRATE_DINS
Definition: heur_alns.c:141
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_Real timelimit
Definition: heur_alns.c:405
int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
Definition: misc.c:9366
#define HEUR_NAME
Definition: heur_alns.c:32
#define DEFAULT_MINFIXINGRATE_RENS
Definition: heur_alns.c:105
static SCIP_RETCODE alnsFixMoreVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL *refsol, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, int ntargetfixings, SCIP_Bool *success)
Definition: heur_alns.c:1354
#define SCIPduplicateBufferArray(scip, ptr, source, num)
Definition: scip.h:22628
SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:46064
void * SCIPhashmapGetImage(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2931
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46963
#define SCIP_LONGINT_MAX
Definition: def.h:135
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip.h:22632
SCIP_RETCODE SCIPcreate(SCIP **scip)
Definition: scip.c:748
#define SCIPallocBlockMemory(scip, ptr)
Definition: scip.h:22585
SCIP_Bool SCIPisTransformed(SCIP *scip)
Definition: scip.c:1017
SCIP_RETCODE SCIPsetRealParam(SCIP *scip, const char *name, SCIP_Real value)
Definition: scip.c:4804
Definition: heur_alns.c:294
#define SCIP_EVENTTYPE_ALNS
Definition: heur_alns.c:151
SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
Definition: scip.c:22369
#define SCIPdebugMsg
Definition: scip.h:455
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4265
SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
Definition: scip.c:45651
SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
Definition: scip.c:1343
#define DEFAULT_PRIORITY_ZEROOBJECTIVE
Definition: heur_alns.c:138
#define DEFAULT_ADJUSTFIXINGRATE
Definition: heur_alns.c:92
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
Definition: scip.c:47435
static SCIP_RETCODE alnsFreeNeighborhood(SCIP *scip, NH **neighborhood)
Definition: heur_alns.c:775
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47423
static void updateTargetNodeLimit(SCIP_HEURDATA *heurdata, NH_STATS *runstats, SCIP_STATUS subscipstatus)
Definition: heur_alns.c:568
#define HEUR_USESSUBSCIP
Definition: heur_alns.c:40
#define SCIP_REAL_FORMAT
Definition: def.h:152
static void updateNeighborhoodStats(SCIP *scip, NH_STATS *runstats, NH *neighborhood, SCIP_STATUS subscipstatus)
Definition: heur_alns.c:1091
#define DEFAULT_ACTIVE_RENS
Definition: heur_alns.c:107
static void increaseTargetNodeLimit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:539
#define DEFAULT_USEDISTANCES
Definition: heur_alns.c:88
#define DEFAULT_MINIMPROVEHIGH
Definition: heur_alns.c:61
SCIP_Real increment
Definition: heur_alns.c:289
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
#define DEFAULT_PRIORITY_LOCALBRANCHING
Definition: heur_alns.c:123
#define TABLE_POSITION_NEIGHBORHOOD
Definition: heur_alns.c:156
#define DEFAULT_MINFIXINGRATE_RINS
Definition: heur_alns.c:110
static void resetCurrentNeighborhood(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:447
#define SCIP_EVENTTYPE_SOLFOUND
Definition: type_event.h:127
SCIP_Real memorylimit
Definition: heur_alns.c:404
static SCIP_RETCODE neighborhoodStatsReset(SCIP *scip, NH_STATS *stats)
Definition: heur_alns.c:687
static void increaseFixingRate(NH_FIXINGRATE *fx)
Definition: heur_alns.c:472
SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
Definition: scip.c:8193
SCIP_RETCODE SCIPsolve(SCIP *scip)
Definition: scip.c:16115
const char * SCIPheurGetName(SCIP_HEUR *heur)
Definition: heur.c:1198
SCIP_RETCODE SCIPcreateClock(SCIP *scip, SCIP_CLOCK **clck)
Definition: scip.c:46013
SCIP_HEUR * SCIPfindHeur(SCIP *scip, const char *name)
Definition: scip.c:8225
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:129
#define SCIPerrorMessage
Definition: pub_message.h:45
DATA_MUTATION * mutation
Definition: heur_alns.c:310
SCIP_Bool SCIPisParamFixed(SCIP *scip, const char *name)
Definition: scip.c:4401
SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
Definition: scip.c:12591
static SCIP_DECL_HEURCOPY(heurCopyAlns)
Definition: heur_alns.c:1564
#define DECL_NHDEACTIVATE(x)
Definition: heur_alns.c:248
SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
Definition: scip.c:8145
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:46976
#define DEFAULT_MINFIXINGRATE_DINS
Definition: heur_alns.c:140
SCIP_Real * redcostscores
Definition: heur_alns.c:417
SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38948
char * name
Definition: heur_alns.c:296
static SCIP_DECL_HEURFREE(heurFreeAlns)
Definition: heur_alns.c:3690
union Nh::@4 data
SCIP_RETCODE SCIPsetBoolParam(SCIP *scip, const char *name, SCIP_Bool value)
Definition: scip.c:4630
SCIP_STATUS SCIPgetStatus(SCIP *scip)
Definition: scip.c:928
BMS_BLKMEM * SCIPblkmem(SCIP *scip)
Definition: scip.c:46731
#define DEFAULT_MINNODES
Definition: heur_alns.c:50
SCIP_CLOCK * submipclock
Definition: heur_alns.c:272
void SCIPselectDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int k, int len)
#define FIXINGRATE_DECAY
Definition: heur_alns.c:93
#define DEFAULT_ACTIVE_ZEROOBJECTIVE
Definition: heur_alns.c:137
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
static SCIP_DECL_SORTINDCOMP(sortIndCompAlns)
Definition: heur_alns.c:1132
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
void SCIPhashmapFree(SCIP_HASHMAP **hashmap)
Definition: misc.c:2826
static void updateFixingRate(SCIP *scip, NH *neighborhood, SCIP_STATUS subscipstatus, NH_STATS *runstats)
Definition: heur_alns.c:497
#define DEFAULT_ALPHA
Definition: heur_alns.c:78
static SCIP_DECL_HEURINITSOL(heurInitsolAlns)
Definition: heur_alns.c:3579
SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
Definition: scip.c:39041
#define DEFAULT_MAXFIXINGRATE_RENS
Definition: heur_alns.c:106
SCIP_RANDNUMGEN * rng
Definition: heur_alns.c:326
#define EVENTHDLR_DESC
Definition: heur_alns.c:150
#define REALABS(x)
Definition: def.h:173
int SCIPheurGetFreq(SCIP_HEUR *heur)
Definition: heur.c:1283
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17650
#define HEUR_FREQOFS
Definition: heur_alns.c:37
Adaptive large neighborhood search heuristic that orchestrates popular LNS heuristics.
static SCIP_RETCODE neighborhoodInit(SCIP *scip, NH *neighborhood)
Definition: heur_alns.c:806
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Real SCIPgetLowerbound(SCIP *scip)
Definition: scip.c:43277
#define DEFAULT_SUBSCIPRANDSEEDS
Definition: heur_alns.c:77
SCIP_Longint nodelimit
Definition: heur_alns.c:403
unsigned int useredcost
Definition: heur_alns.c:419
SCIP_Longint nbestsolsfound
Definition: heur_alns.c:278
#define DEFAULT_PRIORITY_MUTATION
Definition: heur_alns.c:118
static SCIP_Real getVariableRedcostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real refsolval, SCIP_Bool uselocalredcost)
Definition: heur_alns.c:1208
SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
Definition: heur.c:1324
#define DEFAULT_MAXNODES
Definition: heur_alns.c:51
static void updateFixingRateIncrement(NH_FIXINGRATE *fx)
Definition: heur_alns.c:458
SCIP_CLOCK * setupclock
Definition: heur_alns.c:271
SCIP_Bool SCIPisDualfeasNegative(SCIP *scip, SCIP_Real val)
Definition: scip.c:47560
#define BMSduplicateMemoryArray(ptr, source, num)
Definition: memory.h:125
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip.c:29208
SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
Definition: scip.c:21853
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip.h:22620
#define DEFAULT_USEPSCOST
Definition: heur_alns.c:87
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip.c:38771
#define DEFAULT_BESTSOLWEIGHT
Definition: heur_alns.c:69
#define DECL_NHEXIT(x)
Definition: heur_alns.c:221
SCIP_RETCODE SCIPcheckSol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *feasible)
Definition: scip.c:40980
SCIP_Real SCIPgetProbabilityExp3(SCIP_BANDIT *exp3, int action)
Definition: bandit_exp3.c:351
#define SCIP_Bool
Definition: def.h:61
SCIP_RETCODE SCIPcatchEvent(SCIP *scip, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: scip.c:41158
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip.c:29293
SCIP_EVENTTYPE SCIPeventGetType(SCIP_EVENT *event)
Definition: event.c:959
SCIP_Longint usednodes
Definition: heur_alns.c:273
static SCIP_RETCODE fixMatchingSolutionValues(SCIP *scip, SCIP_SOL **sols, int nsols, SCIP_VAR **vars, int nvars, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings)
Definition: heur_alns.c:2676
SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
Definition: sol.c:2528
SCIP_RETCODE SCIPvariablegraphBreadthFirst(SCIP *scip, SCIP_VGRAPH *vargraph, SCIP_VAR **startvars, int nstartvars, int *distances, int maxdistance, int maxvars, int maxbinintvars)
Definition: heur.c:1435
enum SCIP_Status SCIP_STATUS
Definition: type_stat.h:57
#define DEFAULT_MAXFIXINGRATE_ZEROOBJECTIVE
Definition: heur_alns.c:136
SCIP_RETCODE SCIPsetObjlimit(SCIP *scip, SCIP_Real objlimit)
Definition: scip.c:11246
SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:46247
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
static SCIP_Real getVariablePscostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real refsolval)
Definition: heur_alns.c:1262
static SCIP_RETCODE transferSolution(SCIP *subscip, SCIP_EVENTDATA *eventdata)
Definition: heur_alns.c:843
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip.c:40794
SCIP_RETCODE SCIPcreateBanditEpsgreedy(SCIP *scip, SCIP_BANDIT **epsgreedy, SCIP_Real *priorities, SCIP_Real eps, int nactions, unsigned int initseed)
static void initRunStats(SCIP *scip, NH_STATS *stats)
Definition: heur_alns.c:969
SCIP_Bool active
Definition: heur_alns.c:306
#define DECL_CHANGESUBSCIP(x)
Definition: heur_alns.c:204
SCIP_RETCODE SCIPsetIntParam(SCIP *scip, const char *name, int value)
Definition: scip.c:4688
#define DEFAULT_MAXFIXINGRATE_PROXIMITY
Definition: heur_alns.c:126
static void tryAdd2variableBuffer(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, SCIP_Bool integer)
Definition: heur_alns.c:1289
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip.c:38535
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13188
#define DEFAULT_MINFIXINGRATE_CROSSOVER
Definition: heur_alns.c:130
int SCIPgetNSols(SCIP *scip)
Definition: scip.c:39783
#define DEFAULT_ADJUSTMINIMPROVE
Definition: heur_alns.c:64
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
static void decreaseFixingRate(NH_FIXINGRATE *fx)
Definition: heur_alns.c:486
static SCIP_RETCODE neighborhoodExit(SCIP *scip, NH *neighborhood)
Definition: heur_alns.c:825
#define DEFAULT_SCALEBYEFFORT
Definition: heur_alns.c:74
static SCIP_DECL_HEUREXEC(heurExecAlns)
Definition: heur_alns.c:2221
#define DEFAULT_EPS
Definition: heur_alns.c:75
#define DEFAULT_MINFIXINGRATE_ZEROOBJECTIVE
Definition: heur_alns.c:135
#define HEUR_DESC
Definition: heur_alns.c:33
#define DEFAULT_MINFIXINGRATE_LOCALBRANCHING
Definition: heur_alns.c:120
int SCIPgetNObjVars(SCIP *scip)
Definition: scip.c:12040
static SCIP_RETCODE neighborhoodGetRefsol(SCIP *scip, NH *neighborhood, SCIP_SOL **solptr)
Definition: heur_alns.c:1320
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
Definition: scip.c:47039
int npoolsols
Definition: heur_alns.c:333
#define BMSclearMemory(ptr)
Definition: memory.h:111
SCIP_Longint nsolsfound
Definition: heur_alns.c:277
static SCIP_RETCODE determineLimits(SCIP *scip, SCIP_HEUR *heur, SOLVELIMITS *solvelimits, SCIP_Bool *runagain)
Definition: heur_alns.c:1871
static SCIP_RETCODE updateBanditAlgorithms(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real reward, int neighborhoodidx)
Definition: heur_alns.c:2043
int SCIPgetNBinVars(SCIP *scip)
Definition: scip.c:11857
#define DEFAULT_DOMOREFIXINGS
Definition: heur_alns.c:89
unsigned int usedistances
Definition: heur_alns.c:420
SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
Definition: misc.c:9388
static SCIP_BANDIT * getBandit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:1931
int nrunsbestsol
Definition: heur_alns.c:276
int SCIPgetNVars(SCIP *scip)
Definition: scip.c:11812
SCIP_RETCODE SCIPbanditUpdate(SCIP_BANDIT *bandit, int action, SCIP_Real score)
Definition: bandit.c:164
SCIP_RETCODE SCIPfreeBandit(SCIP *scip, SCIP_BANDIT **bandit)
Definition: scip_bandit.c:91
#define EVENTHDLR_NAME
Definition: heur_alns.c:149
#define HEUR_MAXDEPTH
Definition: heur_alns.c:38
static SCIP_RETCODE resetFixingRate(SCIP *scip, NH_FIXINGRATE *fixingrate)
Definition: heur_alns.c:430
static SCIP_DECL_EVENTEXEC(eventExecAlns)
Definition: heur_alns.c:935
SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
SCIP_Bool SCIPisDualfeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47548
SCIP_RETCODE SCIPresetBandit(SCIP *scip, SCIP_BANDIT *bandit, SCIP_Real *priorities, unsigned int seed)
Definition: scip_bandit.c:75
SCIP_Bool SCIPisObjIntegral(SCIP *scip)
Definition: scip.c:11386
#define DEFAULT_PRIORITY_RENS
Definition: heur_alns.c:108
#define DEFAULT_MINFIXINGRATE_MUTATION
Definition: heur_alns.c:115
#define SCIP_EVENTTYPE_BESTSOLFOUND
Definition: type_event.h:88
#define DEFAULT_MAXFIXINGRATE_MUTATION
Definition: heur_alns.c:116
SCIP_SOL * SCIPgetBestSol(SCIP *scip)
Definition: scip.c:39882
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
Definition: scip.c:47002
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4349
static void printNeighborhoodStatistics(SCIP *scip, SCIP_HEURDATA *heurdata, FILE *file)
Definition: heur_alns.c:1023
static SCIP_RETCODE selectNeighborhood(SCIP *scip, SCIP_HEURDATA *heurdata, int *neighborhoodidx)
Definition: heur_alns.c:1941
SCIP_Longint SCIPgetMemUsed(SCIP *scip)
Definition: scip.c:46774
SCIP_Real maxfixingrate
Definition: heur_alns.c:290
#define DEFAULT_NPOOLSOLS_DINS
Definition: heur_alns.c:146
SCIP_RETCODE SCIPresetClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:46081
#define DEFAULT_COPYCUTS
Definition: heur_alns.c:96
SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
Definition: scip.c:27761
#define DEFAULT_FIXTOL
Definition: heur_alns.c:80
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13122
static SCIP_RETCODE getReward(SCIP *scip, SCIP_HEURDATA *heurdata, NH_STATS *runstats, SCIP_Real *rewardptr)
Definition: heur_alns.c:1964
#define CROSSOVERSEED
Definition: heur_alns.c:102
static SCIP_RETCODE setLimits(SCIP *subscip, SOLVELIMITS *solvelimits)
Definition: heur_alns.c:1851
SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
Definition: sol.c:2455
#define DEFAULT_NSOLS_CROSSOVER
Definition: heur_alns.c:145
SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
Definition: scip.c:8161
SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
Definition: scip.c:39126
SCIP_Bool SCIPisFeasPositive(SCIP *scip, SCIP_Real val)
Definition: scip.c:47375
SCIP_Longint SCIPgetMemExternEstim(SCIP *scip)
Definition: scip.c:46800
SCIP_NODESEL * SCIPfindNodesel(SCIP *scip, const char *name)
Definition: scip.c:8957
SCIP_RETCODE SCIPcopyLargeNeighborhoodSearch(SCIP *sourcescip, SCIP *subscip, SCIP_HASHMAP *varmap, const char *suffix, SCIP_VAR **fixedvars, SCIP_Real *fixedvals, int nfixedvars, SCIP_Bool uselprows, SCIP_Bool copycuts, SCIP_Bool *success, SCIP_Bool *valid)
Definition: heuristics.c:903
SCIP_VAR ** SCIPgetVars(SCIP *scip)
Definition: scip.c:11767
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16781
int statushist[NHISTENTRIES]
Definition: heur_alns.c:280
#define SCIP_Real
Definition: def.h:149
SCIP_Real * SCIPgetWeightsEpsgreedy(SCIP_BANDIT *epsgreedy)
SCIP_Bool SCIPisStopped(SCIP *scip)
Definition: scip.c:1145
#define DEFAULT_SEED
Definition: heur_alns.c:100
static int getHistIndex(SCIP_STATUS subscipstatus)
Definition: heur_alns.c:998
int SCIPbanditGetNActions(SCIP_BANDIT *bandit)
Definition: bandit.c:265
#define SCIP_Longint
Definition: def.h:134
static void updateRunStats(SCIP *scip, NH_STATS *stats, SCIP *subscip)
Definition: heur_alns.c:983
SCIP_Real minfixingrate
Definition: heur_alns.c:287
SCIP_RANDNUMGEN * rng
Definition: heur_alns.c:319
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
SCIP_RANDNUMGEN * SCIPbanditGetRandnumgen(SCIP_BANDIT *bandit)
Definition: bandit.c:255
SCIP_RETCODE SCIPsetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
Definition: scip.c:38813
SCIP_RETCODE SCIPtransformProb(SCIP *scip)
Definition: scip.c:13935
#define DEFAULT_PRIORITY_CROSSOVER
Definition: heur_alns.c:133
#define DEFAULT_MAXFIXINGRATE_RINS
Definition: heur_alns.c:111
#define DEFAULT_ACTIVE_DINS
Definition: heur_alns.c:142
SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
Definition: scip.c:8129
SCIP_Real * randscores
Definition: heur_alns.c:415
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
Definition: scip.c:47399
#define DEFAULT_MAXFIXINGRATE_CROSSOVER
Definition: heur_alns.c:131
SCIP_Real SCIPsumepsilon(SCIP *scip)
Definition: scip.c:46429
#define NHISTENTRIES
Definition: heur_alns.c:265
SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
Definition: scip.c:17324
SCIP_Real SCIPgetUpperbound(SCIP *scip)
Definition: scip.c:43426
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:112
#define DEFAULT_USELOCALREDCOST
Definition: heur_alns.c:81
#define MINIMPROVEFAC
Definition: heur_alns.c:62
#define DEFAULT_TARGETNODEFACTOR
Definition: heur_alns.c:53
unsigned int usepscost
Definition: heur_alns.c:421
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
Definition: heur.c:1109
static void computeIntegerVariableBoundsDins(SCIP *scip, SCIP_VAR *var, SCIP_Real *lbptr, SCIP_Real *ubptr)
Definition: heur_alns.c:3194
#define MUTATIONSEED
Definition: heur_alns.c:101
#define DEFAULT_BETA
Definition: heur_alns.c:72
#define TABLE_NAME_NEIGHBORHOOD
Definition: heur_alns.c:154
#define SCIP_ALLOC(x)
Definition: def.h:361
SCIP_Longint SCIPgetNNodes(SCIP *scip)
Definition: scip.c:42133
SCIP_Longint SCIPgetNLPs(SCIP *scip)
Definition: scip.c:42314
SCIP_Real SCIPgetConfidenceBoundUcb(SCIP_BANDIT *ucb, int action)
Definition: bandit_ucb.c:250
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
static SCIP_RETCODE neighborhoodChangeSubscip(SCIP *sourcescip, SCIP *targetscip, NH *neighborhood, SCIP_VAR **targetvars, int *ndomchgs, int *nchgobjs, int *naddedconss, SCIP_Bool *success)
Definition: heur_alns.c:1811
#define TABLE_EARLIEST_STAGE_NEIGHBORHOOD
Definition: heur_alns.c:157
SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
Definition: scip.c:46098
static SCIP_RETCODE setupSubScip(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SOLVELIMITS *solvelimits, SCIP_HEUR *heur, SCIP_Bool objchgd)
Definition: heur_alns.c:2066
#define DEFAULT_REWARDCONTROL
Definition: heur_alns.c:73
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip.c:38911
default SCIP plugins
#define DEFAULT_STALLNODEFACTOR
Definition: heur_alns.c:54
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4321
SCIP_RETCODE SCIPsetSubscipsOff(SCIP *scip, SCIP_Bool quiet)
Definition: scip.c:5083
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
Definition: scip.c:47149
static void increaseMinimumImprovement(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:615
#define FIXINGRATE_STARTINC
Definition: heur_alns.c:94
SCIP_RETCODE SCIPsetLongintParam(SCIP *scip, const char *name, SCIP_Longint value)
Definition: scip.c:4746
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition: scip.c:4239
int * distances
Definition: heur_alns.c:416
static void resetTargetNodeLimit(SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:559
SCIP_RETCODE SCIPfree(SCIP **scip)
Definition: scip.c:780
#define DEFAULT_ACTIVE_MUTATION
Definition: heur_alns.c:117
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip.c:37878
#define HEUR_PRIORITY
Definition: heur_alns.c:35
static SCIP_RETCODE includeNeighborhoods(SCIP *scip, SCIP_HEURDATA *heurdata)
Definition: heur_alns.c:3453