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