SCIP

    Solving Constraint Integer Programs

    heur_scheduler.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-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 */
    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
    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
    659 SCIP_HEURDATA* heurdata
    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 */
    1485 assert(SCIPisDualfeasZero(scip, redcost)
    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 */
    1492 assert(SCIPhasCurrentNodeLP(scip));
    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{
    1553 assert(SCIPisFeasIntegral(scip, val) || ! SCIPvarIsIntegral(var));
    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
    1639 SCIP_CALL( SCIPallocBufferArray(scip, &randscores, nbinintvars) );
    1640 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nbinintvars) );
    1641 SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
    1642 SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, nbinintvars) );
    1643 SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nbinintvars) );
    1644 SCIP_CALL( SCIPallocBufferArray(scip, &isfixed, nbinintvars) );
    1645 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, 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
    1659 BMSclearMemoryArray(isfixed, nbinintvars);
    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 {
    1821 SCIP_RESULT result;
    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
    1869 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    1870 if( nbinintvars == 0 )
    1871 return SCIP_OKAY;
    1872
    1873 assert(*nfixings > 0);
    1874
    1875 nvars = SCIPgetNVars(scip);
    1876 SCIP_CALL( SCIPallocBufferArray(scip, &isfixedvar, nvars) );
    1877 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
    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;
    1903 vars = SCIPgetVars(scip);
    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
    2010 *result = SCIP_DIDNOTRUN;
    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 {
    2022 *result = SCIP_SUCCESS;
    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);
    2028 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    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 )
    2055 *result = SCIP_SUCCESS;
    2056 else if( *result == SCIP_SUCCESS )
    2057 *result = SCIP_DIDNOTFIND;
    2058 else
    2059 *result = SCIP_DIDNOTRUN;
    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);
    2070 *result = SCIP_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{
    2151 SCIP_HEURDATA* heurdata;
    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{
    2274 SCIP_HEURDATA* heurdata;
    2275 SCIP_Real cutoff;
    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
    2357 vars = SCIPgetVars(scip);
    2358 nvars = SCIPgetNVars(scip);
    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 {
    2485 SCIP_DIVESET* diveset = SCIPheurGetDivesets(heurs[h])[d];
    2486
    2487 if( SCIPdivesetIsPublic(diveset) )
    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 {
    2557 SCIP_CALL( SCIPbanditSelect(bandit, selection) );
    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{
    2599 SCIP_HEURDATA* heurdata;
    2600 DIVING_HEUR** divingheurs;
    2601 SCIP_DIVESET* diveset;
    2602
    2603 heurdata = SCIPheurGetData(heur);
    2604 assert(heurdata != NULL);
    2605
    2606 divingheurs = heurdata->divingheurs;
    2607 assert(divingheurs != NULL);
    2608 assert(heurdata->ndiving > 0);
    2609 assert(selection < heurdata->ndiving);
    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 */
    2631 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, divingheurs[selection]->diveset, heurdata->sol, heur,
    2632 result, FALSE, -1LL, (int) divingheurs[selection]->nodelimit,
    2633 divingheurs[selection]->solvefreqdata->currentsolvefreq, SCIP_DIVECONTEXT_SCHEDULER) );
    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.) */
    2642 runstats->nsolsfound = SCIPdivesetGetNSols(diveset, SCIP_DIVECONTEXT_SCHEDULER) - runstats->nsolsfound;
    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",
    2650 SCIPdivesetGetName(diveset), selection, runstats->nsolsfound, runstats->nbestsolsfound,
    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{
    2672 SCIP_HEURDATA* heurdata;
    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
    2700 *result = SCIP_DIDNOTRUN;
    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 */
    2713 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    2714 SCIP_CALL( SCIPallocBufferArray(scip, &varbuf, nvars) );
    2715 SCIP_CALL( SCIPallocBufferArray(scip, &valbuf, nvars) );
    2716 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    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
    2745 *result = SCIP_DIDNOTFIND;
    2746
    2747 neighborhood->stats.nfixings += nfixings;
    2748 runstats->nfixings = nfixings;
    2749
    2750 SCIP_CALL( SCIPcreate(&subscip) );
    2751 SCIP_CALL( SCIPhashmapCreate(&varmapf, SCIPblkmem(scip), nvars) );
    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
    2846 resetCurrentNeighborhood(heurdata);
    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{
    2863 SCIP_HEURDATA* heurdata;
    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 {
    2874 SCIP_CALL( executeDivingHeuristic(scip, heur, selection, runstats, result) );
    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) );
    2915 resetTargetNodeLimit(heurdata);
    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{
    2933 SCIP_HEURDATA* heurdata;
    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 */
    2942 SCIP_CALL( includeDivingHeurs(scip, heur, heurdata) );
    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}*/
    2989 SCIP_HEURDATA* heurdata;
    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
    3011 *result = SCIP_DELAYED;
    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
    3053 && (SCIPgetNNodes(scip) - SCIPsolGetNodenum(SCIPgetBestSol(scip))) < heurdata->waitingnodes )
    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
    3073 *result = SCIP_DIDNOTRUN;
    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 */
    3089 SCIP_CALL( selectHeuristic(scip, heurdata, &selection) );
    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 */
    3122 SCIP_CALL( updateSelectionStrategy(scip, heurdata, reward, selection) );
    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
    3154 *result = SCIP_DELAYED;
    3155
    3156 if( ! SCIPhasCurrentNodeLP(scip) )
    3157 return SCIP_OKAY;
    3159 return SCIP_OKAY;
    3160
    3161 *result = SCIP_DIDNOTRUN;
    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
    3205 SCIPfreeBufferArray(scip, &frac);
    3206 SCIPfreeBufferArray(scip, &fracidx);
    3207
    3208 *result = SCIP_SUCCESS;
    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));
    3223 assert(SCIPgetLPSolstat(sourcescip) == SCIP_LPSOLSTAT_OPTIMAL);
    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;
    3291 nvars = nbinintvars;
    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];
    3304 assert((v < SCIPgetNBinVars(scip) && SCIPvarIsBinary(var)) || (v >= SCIPgetNBinVars(scip) && SCIPvarIsIntegral(var)));
    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
    3340 *result = SCIP_DELAYED;
    3341
    3342 if( ! SCIPhasCurrentNodeLP(scip) )
    3343 return SCIP_OKAY;
    3345 return SCIP_OKAY;
    3346
    3347 *result = SCIP_DIDNOTRUN;
    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
    3368 *result = SCIP_SUCCESS;
    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
    3438 *result = SCIP_DIDNOTRUN;
    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
    3491 *result = SCIP_SUCCESS;
    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;
    3509 *result = SCIP_SUCCESS;
    3510 }
    3511 else
    3512 {
    3513 *result = SCIP_DIDNOTFIND;
    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
    3577 *result = SCIP_DIDNOTRUN;
    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
    3597 *result = SCIP_DIDNOTFIND;
    3598
    3599 /* copy variables into a buffer array */
    3600 SCIP_CALL( SCIPduplicateBufferArray(scip, &varscpy, vars, nbinintvars) );
    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 )
    3624 *result = SCIP_SUCCESS;
    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 {
    3731 SCIP_Real newobj;
    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
    3893 *result = SCIP_DELAYED;
    3894
    3896 return SCIP_OKAY;
    3897
    3898 *result = SCIP_DIDNOTRUN;
    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;
    3937 computeIntegerVariableBoundsDins(scip, vars[v], &lb, &ub);
    3938
    3939 if( ub - lb < 0.5 )
    3940 {
    3941 assert(SCIPisFeasIntegral(scip, lb));
    3942 tryAdd2variableBuffer(scip, vars[v], lb, varbuf, valbuf, nfixings, TRUE);
    3943 }
    3944 }
    3945
    3946 *result = SCIP_SUCCESS;
    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 {
    4040 *result = SCIP_SUCCESS;
    4041 *solptr = SCIPgetBestSol(scip);
    4042 }
    4043 else
    4044 {
    4045 *result = SCIP_DIDNOTFIND;
    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 */
    4112 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &rens, "rens",
    4114 varFixingsRens, changeSubscipRens, NULL, NULL, NULL, NULL, nhDeactivateDiscreteVars) );
    4115
    4116 /* include the RINS neighborhood */
    4117 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &rins, "rins",
    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 */
    4156 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &dins, "dins",
    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}*/
    4187 SCIP_HEURDATA* heurdata;
    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}*/
    4240 SCIP_HEURDATA* heurdata;
    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) );
    4332 resetTargetNodeLimit(heurdata);
    4333 }
    4334 else if( heurdata->resetweights )
    4335 {
    4336 SCIP_CALL( SCIPresetBandit(scip, heurdata->bandit, priorities, initseed) );
    4337 resetTargetNodeLimit(heurdata);
    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
    4348 resetCurrentNeighborhood(heurdata);
    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}*/
    4360 SCIP_HEURDATA* heurdata;
    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 */
    4378 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    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}*/
    4387 SCIP_HEURDATA* heurdata;
    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
    4424 SCIPfreeBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS);
    4425
    4426 SCIPfreeBlockMemory(scip, &heurdata);
    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}*/
    4435 SCIP_HEURDATA* heurdata;
    4436
    4437 assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
    4439 assert(heurdata != NULL);
    4440
    4441 /* print neighborhood statistics */
    4442 printNeighborhoodStatistics(scip, heurdata, file);
    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 )
    4450 printDivingHeurStatistics(scip, heurdata, file);
    4451
    4452 return SCIP_OKAY;
    4453}
    4454
    4455static
    4456SCIP_DECL_TABLECOLLECT(tableCollectNeighborhood)
    4457{
    4458 assert(table != NULL);
    4459
    4460 SCIP_HEURDATA* heurdata;
    4461
    4462 assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
    4464 assert(heurdata != NULL);
    4465
    4466 /* print neighborhood statistics */
    4467 SCIP_CALL( collectNeighborhoodStatistics(scip, heurdata, datatree) );
    4468
    4469 if( heurdata->divingheurs != NULL )
    4470 {
    4471 SCIP_CALL( collectDivingHeurStatistics(scip, heurdata, datatree) );
    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{
    4486 SCIP_HEURDATA* heurdata;
    4487 SCIP_HEUR* heur;
    4488
    4489 /* create primal heuristic data */
    4490 heurdata = NULL;
    4491 heur = NULL;
    4492
    4493 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    4494 BMSclearMemory(heurdata);
    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 */
    4504 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS) );
    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 */
    4520 SCIP_CALL( includeNeighborhoods(scip, heurdata) );
    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
    SCIP_VAR * h
    Definition: circlepacking.c:68
    SCIP_VAR ** b
    Definition: circlepacking.c:65
    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
    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)
    Definition: scip_general.c:655
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_STATUS SCIPgetStatus(SCIP *scip)
    Definition: scip_general.c:562
    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,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    void SCIPwarningMessage(SCIP *scip, const char *formatstr,...)
    Definition: scip_message.c:120
    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)
    Definition: bandit_exp3.c:311
    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)
    Definition: scip_bandit.c:107
    SCIP_Real SCIPgetProbabilityExp3(SCIP_BANDIT *exp3, int action)
    Definition: bandit_exp3.c:363
    SCIP_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
    Definition: scip_branch.c:304
    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)
    Definition: scip_datatree.c:61
    SCIP_RETCODE SCIPinsertDatatreeBool(SCIP *scip, SCIP_DATATREE *datatree, const char *name, SCIP_Bool value)
    Definition: scip_datatree.c:82
    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 SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    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
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    int SCIPheurGetPriority(SCIP_HEUR *heur)
    Definition: heur.c:1528
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    int SCIPgetNHeurs(SCIP *scip)
    Definition: scip_heur.c:287
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    SCIP_RETCODE SCIPsetHeurInitsol(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINITSOL((*heurinitsol)))
    Definition: scip_heur.c:231
    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 SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    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)
    Definition: scip_nodesel.c:242
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2986
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:514
    SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
    Definition: sol.c:4145
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1250
    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)
    Definition: scip_solve.c:2425
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3561
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2611
    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 SCIPperformGenericDivingAlgorithm(SCIP *scip, SCIP_DIVESET *diveset, SCIP_SOL *worksol, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Bool nodeinfeasible, SCIP_Longint iterlim, int nodelimit, SCIP_Real lpresolvedomchgquot, SCIP_DIVECONTEXT divecontext)
    Definition: heuristics.c:221
    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)
    Definition: heuristics.c:1042
    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)
    Definition: scip_timing.c:144
    SCIP_RETCODE SCIPstopClock(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:178
    SCIP_Real SCIPgetSolvingTime(SCIP *scip)
    Definition: scip_timing.c:378
    SCIP_RETCODE SCIPfreeClock(SCIP *scip, SCIP_CLOCK **clck)
    Definition: scip_timing.c:127
    SCIP_Real SCIPgetClockTime(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:319
    SCIP_RETCODE SCIPstartClock(SCIP *scip, SCIP_CLOCK *clck)
    Definition: scip_timing.c:161
    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
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    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
    enum HistIndex HISTINDEX
    Definition: heur_alns.c:335
    HistIndex
    Definition: heur_alns.c:326
    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)
    #define DEFAULT_ACTIVE_MUTATION
    #define DEFAULT_MINFIXINGRATE_ZEROOBJECTIVE
    static void printDivingHeurStatistics(SCIP *scip, SCIP_HEURDATA *heurdata, FILE *file)
    enum HistIndex HISTINDEX
    static SCIP_RETCODE initRest(SCIP *scip, SCIP_HEUR *heur)
    static SCIP_DECL_HEURFREE(heurFreeScheduler)
    #define DECL_NHEXIT(x)
    #define TABLE_POSITION_NEIGHBORHOOD
    #define DEFAULT_NODESQUOT
    static void increaseFixingRate(NH_FIXINGRATE *fx)
    #define DEFAULT_MAXCALLSSAMESOL
    #define NNEIGHBORHOODS
    static SCIP_DECL_SORTINDCOMP(sortIndCompScheduler)
    static SCIP_RETCODE updateSelectionStrategy(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_Real reward, int selection)
    #define DEFAULT_NSOLSLIM
    #define DECL_NHDEACTIVATE(x)
    static SCIP_DECL_HEURINIT(heurInitScheduler)
    #define DEFAULT_PRIORITY_RENS
    #define DEFAULT_ACTIVE_PROXIMITY
    #define DEFAULT_NODESQUOTMIN
    #define DEFAULT_MINFIXINGRATE_DINS
    #define DEFAULT_SEED
    #define DEFAULT_ACTIVE_RINS
    #define TABLE_NAME_NEIGHBORHOOD
    static void initRunStats(SCIP *scip, HEUR_STATS *stats)
    #define DEFAULT_COPYCUTS
    #define DEFAULT_MAXNODES
    static SCIP_RETCODE neighborhoodGetRefsol(SCIP *scip, NH *neighborhood, SCIP_SOL **solptr)
    #define DEFAULT_USEREDCOST
    #define SOLVEFREQ_DECAY
    #define HEUR_TIMING
    #define DEFAULT_MINNODES
    static void decreaseFixingRate(NH_FIXINGRATE *fx)
    #define DECL_NHINIT(x)
    #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)
    #define DEFAULT_FIXTOL
    static void updateFixingRate(NH *neighborhood, SCIP_STATUS subscipstatus, HEUR_STATS *runstats)
    #define SCIP_EVENTTYPE_SCHEDULER
    #define DEFAULT_SOLREWARDWEIGHT
    #define HEUR_FREQOFS
    static void updateRunStats(HEUR_STATS *stats, SCIP *subscip)
    #define FIXINGRATE_STARTINC
    #define HEUR_DESC
    #define DEFAULT_MAXFIXINGRATE_RENS
    #define DEFAULT_PRIORITY_PROXIMITY
    static void resetTargetNodeLimit(SCIP_HEURDATA *heurdata)
    #define SOLVEFREQ_STARTINC
    static SCIP_RETCODE neighborhoodInit(SCIP *scip, NH *neighborhood)
    #define DEFAULT_ACTIVE_TRUSTREGION
    #define DEFAULT_MINFIXINGRATE_RENS
    #define DEFAULT_MAXFIXINGRATE_DINS
    static SCIP_DECL_TABLECOLLECT(tableCollectNeighborhood)
    static SCIP_DECL_HEURINITSOL(heurInitsolScheduler)
    #define FIXINGRATE_DECAY
    #define DEFAULT_MINFIXINGRATE_RINS
    static SCIP_Real getReward(SCIP *scip, SCIP_HEURDATA *heurdata, int selection, HEUR_STATS *runstats)
    #define DEFAULT_PRIORITY_ZEROOBJECTIVE
    #define DEFAULT_INITLNSNODELIMIT
    #define DEFAULT_WAITINGNODES
    #define DEFAULT_NODESOFFSET
    #define TABLE_DESC_NEIGHBORHOOD
    #define DECL_CHANGESUBSCIP(x)
    #define DEFAULT_EFFORTREWARDWEIGHT
    #define DEFAULT_RESETWEIGHTS
    static SCIP_RETCODE selectHeuristic(SCIP *scip, SCIP_HEURDATA *heurdata, int *selection)
    #define HEUR_DISPCHAR
    #define DEFAULT_QUALREWARDWEIGHT
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_MAXFIXINGRATE_MUTATION
    #define TABLE_EARLIEST_STAGE_NEIGHBORHOOD
    static SCIP_DECL_HEURCOPY(heurCopyScheduler)
    #define DECL_NHREFSOL(x)
    static void increaseSolveFreq(SOLVEFREQ *solvefreqdata)
    #define DEFAULT_USELOCALREDCOST
    #define DEFAULT_CONFLICTREWARDWEIGHT
    #define DEFAULT_MAXFIXINGRATE_TRUSTREGION
    static SCIP_RETCODE schedulerIncludeNeighborhood(SCIP *scip, SCIP_HEURDATA *heurdata, NH **neighborhood, const char *name, SCIP_Real minfixingrate, SCIP_Real maxfixingrate, SCIP_Bool active, int priority, DECL_VARFIXINGS((*varfixings)), DECL_CHANGESUBSCIP((*changesubscip)), DECL_NHINIT((*nhinit)), DECL_NHEXIT((*nhexit)), DECL_NHFREE((*nhfree)), DECL_NHREFSOL((*nhrefsol)), DECL_NHDEACTIVATE((*nhdeactivate)))
    #define DIVINGHEURS_INITIALSIZE
    #define DEFAULT_MAXFIXINGRATE_ZEROOBJECTIVE
    #define HEUR_NAME
    #define DEFAULT_ACTIVE_RENS
    #define NHISTENTRIES
    static void initSolveFreq(SOLVEFREQ *solvefreqdata)
    static void updateFixingRateIncrement(NH_FIXINGRATE *fx)
    #define DEFAULT_INITDIVINGNODELIMIT
    #define DEFAULT_MINFIXINGRATE_CROSSOVER
    static SCIP_RETCODE addLocalBranchingConstraint(SCIP *sourcescip, SCIP *targetscip, SCIP_VAR **subvars, int distance, SCIP_Bool *success, int *naddedconss)
    #define DEFAULT_ACTIVE_ZEROOBJECTIVE
    #define DEFAULT_MINFIXINGRATE_LOCALBRANCHING
    #define MINSOLVEFREQ
    @ HIDX_STALLNODE
    @ HIDX_OTHER
    @ HIDX_SOLLIM
    @ HIDX_USR
    @ HIDX_OPT
    @ HIDX_INFEAS
    @ HIDX_NODELIM
    #define DEFAULT_PRIORITY_CROSSOVER
    #define DEFAULT_NSELECTIONS
    static SCIP_RETCODE collectNeighborhoodStatistics(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_DATATREE *datatree)
    static SCIP_RETCODE setLimits(SCIP *subscip, SOLVELIMITS *solvelimits)
    #define DEFAULT_INITDURINGROOT
    static SCIP_RETCODE executeHeuristic(SCIP *scip, SCIP_HEUR *heur, int selection, HEUR_STATS *runstats, SCIP_STATUS *subscipstatus, SCIP_RESULT *result)
    static SCIP_DECL_HEUREXEC(heurExecScheduler)
    #define DEFAULT_VIOLPENALTY_TRUSTREGION
    #define DEFAULT_UNFIXTOL
    static SCIP_RETCODE resetFixingRate(SCIP *scip, NH_FIXINGRATE *fixingrate)
    #define DEFAULT_ALPHA
    #define MUTATIONSEED
    #define DEFAULT_ACTIVE_LOCALBRANCHING
    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)
    #define DEFAULT_PRIORITY_MUTATION
    #define DEFAULT_PRIORITY_RINS
    static SCIP_Real getVariablePscostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real refsolval, SCIP_Bool uselocallpsol)
    #define MAXSOLVEFREQ
    static int getHistIndex(SCIP_STATUS subscipstatus)
    #define DEFAULT_ACTIVE_DINS
    #define EVENTHDLR_DESC
    #define DEFAULT_PRIORITY_TRUSTREGION
    static SCIP_DECL_HEUREXIT(heurExitScheduler)
    static void updateSolveFreqIncrement(SOLVEFREQ *solvefreqdata)
    #define LPLIMFAC
    #define CROSSOVERSEED
    #define DEFAULT_MAXFIXINGRATE_LOCALBRANCHING
    #define HEUR_FREQ
    #define DEFAULT_SUBSCIPRANDSEEDS
    #define DEFAULT_NPOOLSOLS_DINS
    static void computeIntegerVariableBoundsDins(SCIP *scip, SCIP_VAR *var, SCIP_Real *lbptr, SCIP_Real *ubptr)
    #define DEFAULT_MAXFIXINGRATE_RINS
    static SCIP_RETCODE includeNeighborhoods(SCIP *scip, SCIP_HEURDATA *heurdata)
    #define DEFAULT_MINFIXINGRATE_MUTATION
    #define DEFAULT_EPS
    static SCIP_RETCODE LNSUnfixVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, int ntargetfixings, SCIP_Bool *success)
    #define DEFAULT_TARGETNODEFACTOR
    #define DEFAULT_MAXFIXINGRATE_CROSSOVER
    #define DEFAULT_NSOLS_CROSSOVER
    #define DEFAULT_USEDISTANCES
    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_DECL_EVENTEXEC(eventExecScheduler)
    #define HEUR_USESSUBSCIP
    #define DEFAULT_BETA
    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)
    #define DEFAULT_ACTIVE_CROSSOVER
    static SCIP_RETCODE executeDivingHeuristic(SCIP *scip, SCIP_HEUR *heur, int selection, HEUR_STATS *runstats, SCIP_RESULT *result)
    #define DEFAULT_USESUBSCIPHEURS
    #define DEFAULT_PRIORITY_DINS
    #define EVENTHDLR_NAME
    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)
    #define DEFAULT_MAXFIXINGRATE_PROXIMITY
    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)
    #define DEFAULT_PRIORITY_LOCALBRANCHING
    static SCIP_RETCODE heurStatsReset(SCIP *scip, HEUR_STATS *stats, SCIP_Bool usediving)
    #define DEFAULT_MINFIXINGRATE_TRUSTREGION
    #define DEFAULT_BESTSOLWEIGHT
    #define DEFAULT_BANDITALGO
    static SCIP_RETCODE LNSFixMoreVariables(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_SOL *refsol, SCIP_VAR **varbuf, SCIP_Real *valbuf, int *nfixings, int ntargetfixings, SCIP_Bool *success)
    #define DEFAULT_MINFIXINGRATE_PROXIMITY
    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)
    #define DEFAULT_GAMMA
    static SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
    #define LRATEMIN
    #define DEFAULT_USEPSCOST
    static SCIP_RETCODE transferSolution(SCIP *subscip, SCIP_EVENTDATA *eventdata)
    Adaptive heuristic to schedule LNS and diving heuristics.
    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
    Definition: heur_alns.c:367
    HEUR_STATS stats
    NH_FIXINGRATE fixingrate
    Definition: heur_alns.c:369
    DECL_NHINIT((*nhinit))
    DATA_MUTATION * mutation
    Definition: heur_alns.c:382
    int nodelimit
    union Nh::@7 data
    DECL_CHANGESUBSCIP((*changesubscip))
    SCIP_Bool active
    Definition: heur_alns.c:378
    NH_STATS stats
    Definition: heur_alns.c:370
    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_SOL * sol
    Definition: struct_heur.h:71
    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_EventData SCIP_EVENTDATA
    Definition: type_event.h:179
    #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
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIVECONTEXT_SCHEDULER
    Definition: type_heur.h:71
    @ SCIP_LPSOLSTAT_OPTIMAL
    Definition: type_lp.h:44
    @ SCIP_PARAMSETTING_OFF
    Definition: type_paramset.h:63
    @ SCIP_PARAMSETTING_FAST
    Definition: type_paramset.h:62
    @ 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
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ 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
    @ SCIP_VARTYPE_INTEGER
    Definition: type_var.h:65
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53