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