Scippy

SCIP

Solving Constraint Integer Programs

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