Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_scheduler.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 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#include <string.h>
    74
    75
    76#define HEUR_NAME "scheduler"
    77#define HEUR_DESC "Adaptive heuristic to schedule LNS and diving heuristics"
    78#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_LNS
    79#define HEUR_PRIORITY -30000
    80#define HEUR_FREQ -1
    81#define HEUR_FREQOFS 0
    82#define HEUR_MAXDEPTH -1
    83#define HEUR_TIMING SCIP_HEURTIMING_AFTERNODE
    84#define HEUR_USESSUBSCIP TRUE /**< does the heuristic use a secondary SCIP instance? */
    85
    86#define NNEIGHBORHOODS 9
    87#define DIVINGHEURS_INITIALSIZE 10
    88
    89/*
    90 * limit parameters for sub-SCIPs
    91 */
    92#define DEFAULT_NODESQUOT 0.1
    93#define DEFAULT_NODESQUOTMIN 0.0
    94#define DEFAULT_NODESOFFSET 500LL
    95#define DEFAULT_NSOLSLIM 3
    96#define DEFAULT_MINNODES 50LL
    97#define DEFAULT_MAXNODES 500LL
    98#define DEFAULT_WAITINGNODES 0LL /**< number of nodes since last incumbent solution that the heuristic should wait */
    99#define DEFAULT_INITLNSNODELIMIT 50
    100#define DEFAULT_INITDIVINGNODELIMIT 500LL
    101#define DEFAULT_TARGETNODEFACTOR 1.05
    102#define LRATEMIN 0.01 /**< lower bound for learning rate for target nodes and minimum improvement */
    103#define LPLIMFAC 4.0
    104#define DEFAULT_INITDURINGROOT FALSE
    105#define DEFAULT_MAXCALLSSAMESOL -1 /**< number of allowed executions of the heuristic on the same incumbent solution */
    106
    107/*
    108 * bandit algorithm parameters
    109 */
    110#define DEFAULT_BESTSOLWEIGHT 1
    111#define DEFAULT_BANDITALGO 'i' /**< the default bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy, exp.3-(i)x */
    112#define DEFAULT_RESETWEIGHTS FALSE/**< should the bandit algorithms be reset when a new problem is read? */
    113#define DEFAULT_SUBSCIPRANDSEEDS FALSE /**< should random seeds of sub-SCIPs be altered to increase diversification? */
    114#define DEFAULT_FIXTOL 0.1 /**< tolerance by which the fixing rate may be missed without generic fixing */
    115#define DEFAULT_UNFIXTOL 0.1 /**< tolerance by which the fixing rate may be exceeded without generic unfixing */
    116#define DEFAULT_BETA 0.0 /**< default reward offset between 0 and 1 at every observation for exp3 */
    117#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) */
    118
    119/*
    120 * parameters to control variable fixing
    121 */
    122#define DEFAULT_USEREDCOST TRUE /**< should reduced cost scores be used for variable priorization? */
    123#define DEFAULT_USEPSCOST TRUE /**< should pseudo cost scores be used for variable priorization? */
    124#define DEFAULT_USEDISTANCES TRUE /**< should distances from fixed variables be used for variable priorization */
    125#define DEFAULT_USELOCALREDCOST FALSE /**< should local reduced costs be used for generic (un)fixing? */
    126
    127/*
    128 * parameters for reward computation
    129 */
    130#define DEFAULT_EFFORTREWARDWEIGHT 0.2
    131#define DEFAULT_SOLREWARDWEIGHT 0.3
    132#define DEFAULT_QUALREWARDWEIGHT 0.3
    133#define DEFAULT_CONFLICTREWARDWEIGHT 0.2
    134
    135/*
    136 * the following 3 parameters have been tuned by a simulation experiment
    137 * as described in the paper.
    138 */
    139#define DEFAULT_EPS 0.4685844 /**< increase exploration in epsilon-greedy bandit algorithm */
    140#define DEFAULT_ALPHA 0.0016 /**< parameter to increase the confidence width in UCB */
    141#define DEFAULT_GAMMA 0.07041455 /**< default weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3 */
    142
    143/*
    144 * parameters to control solve frequency for diving heuristics
    145 */
    146#define SOLVEFREQ_DECAY 0.75 /**< geometric decay for solving freq adjustments */
    147#define SOLVEFREQ_STARTINC 0.2 /**< initial increment value for solving frequency */
    148#define MAXSOLVEFREQ 0.3 /**< maximal solving frequency */
    149#define MINSOLVEFREQ 0.05 /**< minimal solving frequency */
    150
    151/*
    152 * parameters to control variable fixing
    153 */
    154#define FIXINGRATE_DECAY 0.75 /**< geometric decay for fixing rate adjustments */
    155#define FIXINGRATE_STARTINC 0.2 /**< initial increment value for fixing rate */
    156#define DEFAULT_USESUBSCIPHEURS FALSE /**< should the heuristic activate other sub-SCIP heuristics during its search? */
    157#define DEFAULT_COPYCUTS FALSE /**< should cutting planes be copied to the sub-SCIP? */
    158
    159/* individual random seeds */
    160#define DEFAULT_SEED 113
    161#define MUTATIONSEED 121
    162#define CROSSOVERSEED 321
    163
    164/* individual neighborhood parameters */
    165#define DEFAULT_MINFIXINGRATE_RENS 0.3
    166#define DEFAULT_MAXFIXINGRATE_RENS 0.9
    167#define DEFAULT_ACTIVE_RENS TRUE
    168//#define DEFAULT_PRIORITY_RENS 1.0
    169#define DEFAULT_PRIORITY_RENS -1100000
    170
    171#define DEFAULT_MINFIXINGRATE_RINS 0.3
    172#define DEFAULT_MAXFIXINGRATE_RINS 0.9
    173#define DEFAULT_ACTIVE_RINS TRUE
    174//#define DEFAULT_PRIORITY_RINS 1.0
    175#define DEFAULT_PRIORITY_RINS -1101000
    176
    177#define DEFAULT_MINFIXINGRATE_MUTATION 0.3
    178#define DEFAULT_MAXFIXINGRATE_MUTATION 0.9
    179#define DEFAULT_ACTIVE_MUTATION TRUE
    180//#define DEFAULT_PRIORITY_MUTATION 1.0
    181#define DEFAULT_PRIORITY_MUTATION -1103010
    182
    183#define DEFAULT_MINFIXINGRATE_LOCALBRANCHING 0.3
    184#define DEFAULT_MAXFIXINGRATE_LOCALBRANCHING 0.9
    185#define DEFAULT_ACTIVE_LOCALBRANCHING TRUE
    186//#define DEFAULT_PRIORITY_LOCALBRANCHING 1.0
    187#define DEFAULT_PRIORITY_LOCALBRANCHING -1102000
    188
    189#define DEFAULT_MINFIXINGRATE_PROXIMITY 0.3
    190#define DEFAULT_MAXFIXINGRATE_PROXIMITY 0.9
    191#define DEFAULT_ACTIVE_PROXIMITY TRUE
    192//#define DEFAULT_PRIORITY_PROXIMITY 1.0
    193#define DEFAULT_PRIORITY_PROXIMITY -2000000
    194
    195#define DEFAULT_MINFIXINGRATE_CROSSOVER 0.3
    196#define DEFAULT_MAXFIXINGRATE_CROSSOVER 0.9
    197#define DEFAULT_ACTIVE_CROSSOVER TRUE
    198//#define DEFAULT_PRIORITY_CROSSOVER 1.0
    199#define DEFAULT_PRIORITY_CROSSOVER -1104000
    200
    201#define DEFAULT_MINFIXINGRATE_ZEROOBJECTIVE 0.3
    202#define DEFAULT_MAXFIXINGRATE_ZEROOBJECTIVE 0.9
    203#define DEFAULT_ACTIVE_ZEROOBJECTIVE TRUE
    204//#define DEFAULT_PRIORITY_ZEROOBJECTIVE 1.0
    205#define DEFAULT_PRIORITY_ZEROOBJECTIVE 100
    206
    207#define DEFAULT_MINFIXINGRATE_DINS 0.3
    208#define DEFAULT_MAXFIXINGRATE_DINS 0.9
    209#define DEFAULT_ACTIVE_DINS TRUE
    210//#define DEFAULT_PRIORITY_DINS 1.0
    211#define DEFAULT_PRIORITY_DINS -1105000
    212
    213#define DEFAULT_MINFIXINGRATE_TRUSTREGION 0.3
    214#define DEFAULT_MAXFIXINGRATE_TRUSTREGION 0.9
    215#define DEFAULT_ACTIVE_TRUSTREGION FALSE
    216//#define DEFAULT_PRIORITY_TRUSTREGION 1.0
    217#define DEFAULT_PRIORITY_TRUSTREGION -1102010
    218
    219
    220#define DEFAULT_NSOLS_CROSSOVER 2 /**< parameter for the number of solutions that crossover should combine */
    221#define DEFAULT_NPOOLSOLS_DINS 5 /**< number of pool solutions where binary solution values must agree */
    222#define DEFAULT_VIOLPENALTY_TRUSTREGION 100.0 /**< the penalty for violating the trust region */
    223
    224/* event handler properties */
    225#define EVENTHDLR_NAME "Scheduler"
    226#define EVENTHDLR_DESC "LP event handler for " HEUR_NAME " heuristic"
    227#define SCIP_EVENTTYPE_SCHEDULER (SCIP_EVENTTYPE_LPSOLVED | SCIP_EVENTTYPE_SOLFOUND | SCIP_EVENTTYPE_BESTSOLFOUND)
    228
    229/* properties of the scheduler neighborhood statistics table */
    230#define TABLE_NAME_NEIGHBORHOOD "scheduler"
    231#define TABLE_DESC_NEIGHBORHOOD "scheduler heuristics statistics"
    232#define TABLE_POSITION_NEIGHBORHOOD 12500 /**< the position of the statistics table */
    233#define TABLE_EARLIEST_STAGE_NEIGHBORHOOD SCIP_STAGE_TRANSFORMED /**< output of the statistics table is only printed from this stage onwards */
    234
    235/*
    236 * additional neighborhood data structures
    237 */
    238
    239
    240typedef struct data_crossover DATA_CROSSOVER; /**< crossover neighborhood data structure */
    241
    242typedef struct data_mutation DATA_MUTATION; /**< mutation neighborhood data structure */
    243
    244typedef struct data_dins DATA_DINS; /**< dins neighborhood data structure */
    245
    246typedef struct data_trustregion DATA_TRUSTREGION; /**< trustregion neighborhood data structure */
    247
    248typedef struct NH_FixingRate NH_FIXINGRATE; /** fixing rate data structure */
    249
    250typedef struct SolveFreq SOLVEFREQ; /** diving heuristic solving frequency data structure */
    251
    252typedef struct Heur_Stats HEUR_STATS; /**< heuristic statistics data structure */
    253
    254typedef struct Nh NH; /**< neighborhood data structure */
    255
    256typedef struct Diving_Heur DIVING_HEUR; /**< diving heuristic data structure */
    257
    258/*
    259 * variable priorization data structure for sorting
    260 */
    261typedef struct VarPrio VARPRIO;
    262
    263/** callback to collect variable fixings of neighborhood */
    264 #define DECL_VARFIXINGS(x) SCIP_RETCODE x ( \
    265 SCIP* scip, /**< SCIP data structure */ \
    266 NH* neighborhood, /**< neighborhood data structure */ \
    267 SCIP_VAR** varbuf, /**< buffer array to collect variables to fix */\
    268 SCIP_Real* valbuf, /**< buffer array to collect fixing values */ \
    269 int* nfixings, /**< pointer to store the number of fixings */ \
    270 SCIP_RESULT* result /**< result pointer */ \
    271 )
    272
    273/** callback for subproblem changes other than variable fixings
    274 *
    275 * this callback can be used to further modify the subproblem by changes other than variable fixings.
    276 * Typical modifications include restrictions of variable domains, the formulation of additional constraints,
    277 * or changed objective coefficients.
    278 *
    279 * The callback should set the \p success pointer to indicate whether it was successful with its modifications or not.
    280 */
    281#define DECL_CHANGESUBSCIP(x) SCIP_RETCODE x ( \
    282 SCIP* sourcescip, /**< source SCIP data structure */\
    283 SCIP* targetscip, /**< target SCIP data structure */\
    284 NH* neighborhood, /**< neighborhood data structure */\
    285 SCIP_VAR** subvars, /**< array of targetscip variables in the same order as the source SCIP variables */\
    286 int* ndomchgs, /**< pointer to store the number of performed domain changes */\
    287 int* nchgobjs, /**< pointer to store the number of changed objective coefficients */ \
    288 int* naddedconss, /**< pointer to store the number of additional constraints */\
    289 SCIP_Bool* success /**< pointer to store if the sub-MIP was successfully adjusted */\
    290 )
    291
    292/** optional initialization callback for neighborhoods when a new problem is read */
    293#define DECL_NHINIT(x) SCIP_RETCODE x ( \
    294 SCIP* scip, /**< SCIP data structure */ \
    295 NH* neighborhood /**< neighborhood data structure */ \
    296 )
    297
    298/** deinitialization callback for neighborhoods when exiting a problem */
    299#define DECL_NHEXIT(x) SCIP_RETCODE x ( \
    300 SCIP* scip, /**< SCIP data structure */ \
    301 NH* neighborhood /**< neighborhood data structure */ \
    302 )
    303
    304/** deinitialization callback for neighborhoods before SCIP is freed */
    305#define DECL_NHFREE(x) SCIP_RETCODE x ( \
    306 SCIP* scip, /**< SCIP data structure */ \
    307 NH* neighborhood /**< neighborhood data structure */ \
    308 )
    309
    310/** callback function to return a feasible reference solution for further fixings
    311 *
    312 * The reference solution should be stored in the \p solptr.
    313 * The \p result pointer can be used to indicate either
    314 *
    315 * - SCIP_SUCCESS or
    316 * - SCIP_DIDNOTFIND
    317 */
    318#define DECL_NHREFSOL(x) SCIP_RETCODE x ( \
    319 SCIP* scip, /**< SCIP data structure */ \
    320 NH* neighborhood, /**< neighborhood data structure */ \
    321 SCIP_SOL** solptr, /**< pointer to store the reference solution */ \
    322 SCIP_RESULT* result /**< pointer to indicate the callback success whether a reference solution is available */ \
    323 )
    324
    325/** callback function to deactivate neighborhoods on problems where they are irrelevant */
    326#define DECL_NHDEACTIVATE(x) SCIP_RETCODE x (\
    327 SCIP* scip, /**< SCIP data structure */ \
    328 SCIP_Bool* deactivate /**< pointer to store whether the neighborhood should be deactivated (TRUE) for an instance */ \
    329 )
    330
    331/** sub-SCIP status code enumerator */
    333{
    334 HIDX_OPT = 0, /**< sub-SCIP was solved to optimality */
    335 HIDX_USR = 1, /**< sub-SCIP was user interrupted */
    336 HIDX_NODELIM = 2, /**< sub-SCIP reached the node limit */
    337 HIDX_STALLNODE = 3, /**< sub-SCIP reached the stall node limit */
    338 HIDX_INFEAS = 4, /**< sub-SCIP was infeasible */
    339 HIDX_SOLLIM = 5, /**< sub-SCIP reached the solution limit */
    340 HIDX_OTHER = 6 /**< sub-SCIP reached none of the above codes */
    342typedef enum HistIndex HISTINDEX;
    343#define NHISTENTRIES 7
    344
    345
    346/** statistics for heuristics */
    348{
    349 SCIP_Real oldupperbound; /**< upper bound before the heuristic started */
    350 SCIP_Real newupperbound; /**< new upper bound for allrewards mode to work correctly */
    351 int nruns; /**< number of runs of a heuristic */
    352 int nrunsbestsol; /**< number of runs that produced a new incumbent */
    353 SCIP_Longint nsolsfound; /**< the total number of solutions found */
    354 SCIP_Longint nbestsolsfound; /**< the total number of improving solutions found */
    355 SCIP_CLOCK* setupclock; /**< clock for setup time */
    356 SCIP_CLOCK* execclock; /**< clock for the heuristic execution */
    357 /* for diving */
    358 SCIP_Longint nbacktracks; /**< total number of used backtracks */
    359 SCIP_Longint nconflicts; /**< total number of conflict constraints generated */
    360 SCIP_Longint nprobnodes; /**< total number of probing nodes used */
    361 int divingdepth; /**< depth of last dive */
    362 /* for LNS */
    363 SCIP_Longint usednodes; /**< total number of used nodes */
    364 int nfixings; /**< the number of fixings in one run */
    365 int statushist[NHISTENTRIES]; /**< array to count sub-SCIP statuses */
    366};
    367
    368
    369/** fixing rate data structure to control the amount of target fixings of a neighborhood */
    370struct NH_FixingRate
    371{
    372 SCIP_Real minfixingrate; /**< the minimum fixing rate */
    373 SCIP_Real targetfixingrate; /**< the current target fixing rate */
    374 SCIP_Real increment; /**< the current increment by which the target fixing rate is in-/decreased */
    375 SCIP_Real maxfixingrate; /**< the maximum fixing rate */
    376};
    377
    378/** solve frequency for diving heuristics */
    380{
    381 SCIP_Real minsolvefreq; /**< the minimum solve frequency */
    382 SCIP_Real currentsolvefreq; /**< the current solve frequency */
    383 SCIP_Real increment; /**< the current increment by which the solve frequency is in-/decreased */
    384 SCIP_Real maxsolvefreq; /**< the maximum solve frequency */
    385};
    386
    387/** neighborhood data structure with callbacks, statistics, fixing rate */
    388struct Nh
    389{
    390 char* name; /**< the name of this neighborhood */
    391 NH_FIXINGRATE fixingrate; /**< fixing rate for this neighborhood */
    392 HEUR_STATS stats; /**< statistics for this neighborhood */
    393 int nodelimit; /**< nodelimit for next execution */
    394 DECL_VARFIXINGS ((*varfixings)); /**< variable fixings callback for this neighborhood */
    395 DECL_CHANGESUBSCIP ((*changesubscip)); /**< callback for subproblem changes other than variable fixings */
    396 DECL_NHINIT ((*nhinit)); /**< initialization callback when a new problem is read */
    397 DECL_NHEXIT ((*nhexit)); /**< deinitialization callback when exiting a problem */
    398 DECL_NHFREE ((*nhfree)); /**< deinitialization callback before SCIP is freed */
    399 DECL_NHREFSOL ((*nhrefsol)); /**< callback function to return a reference solution for further fixings, or NULL */
    400 DECL_NHDEACTIVATE ((*nhdeactivate)); /**< callback function to deactivate neighborhoods on problems where they are irrelevant, or NULL if it is always active */
    401 SCIP_Bool active; /**< is this neighborhood active or not? */
    402 SCIP_Real priority; /**< positive call priority to initialize bandit algorithms */
    403 int rootnodepriority; /**< heuristic's priority for call at rootnode */
    404 union
    405 {
    406 DATA_MUTATION* mutation; /**< mutation data */
    407 DATA_CROSSOVER* crossover; /**< crossover data */
    408 DATA_DINS* dins; /**< dins data */
    409 DATA_TRUSTREGION* trustregion; /**< trustregion data */
    410 } data; /**< data object for neighborhood specific data */
    411};
    412
    413/** diving heuristic data structure with statistics and diveset */
    415{
    416 SCIP_DIVESET* diveset; /**< publicly available divesets from diving heuristics */
    417 HEUR_STATS* stats; /**< statistics for this diveset */
    418 SCIP_Longint nodelimit; /**< node limit of diving heuristics for next execution */
    419 SOLVEFREQ* solvefreqdata; /**< solve frequency data */
    420 SCIP_Real priority; /**< positive call priority to initialize bandit algorithms */
    421 int rootnodepriority; /**< heuristic's priority for call at rootnode */
    422};
    423
    424/** mutation neighborhood data structure */
    425struct data_mutation
    426{
    427 SCIP_RANDNUMGEN* rng; /**< random number generator */
    428};
    429
    430/** crossover neighborhood data structure */
    431struct data_crossover
    432{
    433 int nsols; /**< the number of solutions that crossover should combine */
    434 SCIP_RANDNUMGEN* rng; /**< random number generator to draw from the solution pool */
    435 SCIP_SOL* selsol; /**< best selected solution by crossover as reference point */
    436};
    437
    438/** dins neighborhood data structure */
    439struct data_dins
    440{
    441 int npoolsols; /**< number of pool solutions where binary solution values must agree */
    442};
    443
    444struct data_trustregion
    445{
    446 SCIP_Real violpenalty; /**< the penalty for violating the trust region */
    447};
    448
    449/** primal heuristic data */
    450struct SCIP_HeurData
    451{
    452 SCIP_BANDIT* bandit; /**< bandit algorithm */
    453 int* sortedindices; /**< array of indices of heuristics sorted w.r.t. heuristic priorities */
    454 int counter; /**< counter to count how often the scheduler selected a heuristic in the rootnode */
    455 SCIP_SOL* lastcallsol; /**< incumbent when the heuristic was last called */
    456 SCIP_Longint waitingnodes; /**< number of nodes since last incumbent solution that the heuristic should wait */
    457 SCIP_Longint firstcallthissol; /**< counter for the number of calls on this incumbent */
    458 char banditalgo; /**< the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy */
    459 int maxcallssamesol; /**< number of allowed executions of the heuristic on the same incumbent solution
    460 * (-1: no limit, 0: number of active neighborhoods) */
    461 int nselections; /**< number of heuristics picked by the scheduler in one call
    462 * (-1: number of controlled heuristics, 0: until new incumbent is found) */
    463 int nskippedcalls; /**< number of calls to heuristic we need to skip since last execution */
    464 int nfailedcalls; /**< number of failed calls to heursitic since last successful one */
    465 SCIP_Bool resetweights; /**< should the bandit algorithms be reset when a new problem is read? */
    466 SCIP_Bool initduringroot; /**< should the heuristic be executed multiple times during the root node? */
    467 int maxnconflicts; /**< maximum number of conflicts detected by diving heur so far */
    468 SCIP_Bool defaultroot; /**< should the default priorities be used at the root node */
    469 /* bandit algorithm parameters */
    470 SCIP_Real exp3_gamma; /**< weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3 */
    471 SCIP_Real exp3_beta; /**< reward offset between 0 and 1 at every observation for exp3 */
    472 SCIP_Real epsgreedy_eps; /**< increase exploration in epsilon-greedy bandit algorithm */
    473 SCIP_Bool epsgreedy_usemod; /**< TRUE if modified version of the epsilon-greedy bandit algorithm should be used */
    474 SCIP_Real ucb_alpha; /**< parameter to increase the confidence width in UCB */
    475 /* reward function parameters (reward is a function between 0 and 1 and thus always upper bounded by 1, even if
    476 * sum of weights do not add up to 1.0) */
    477 SCIP_Real solrewardweight; /**< weight by how much finding a new incumbent is rewarded in reward function */
    478 SCIP_Real effortrewardweight; /**< weight by how much effort is rewarded in reward function */
    479 SCIP_Real qualrewardweight; /**< weight by how much quality of a new incumbent is rewarded in reward function */
    480 SCIP_Real conflictrewardweight;/**< weight by how much number of conflicts found by diving is rewarded in reward function */
    481 /* diving data */
    482 SCIP_SOL* sol; /**< working solution */
    483 DIVING_HEUR** divingheurs; /**< array of diving heuristics */
    484 int divingheurssize; /**< array size for diving heurs array */
    485 int ndiving; /**< number of diving heuristics used by scheduler */
    486 SCIP_Longint initdivingnodelimit;/**< initial node limit for diving heuristics */
    487 SCIP_Longint maxdivingnodelimit; /**< maximum of node limits among all diving heurisitics */
    488 /* LNS data */
    489 NH** neighborhoods; /**< array of neighborhoods */
    490 SCIP_Longint nodesoffset; /**< offset added to the nodes budget */
    491 SCIP_Longint maxnodes; /**< maximum number of nodes in a single sub-SCIP */
    492 SCIP_Longint targetnodes; /**< targeted number of nodes to start a sub-SCIP */
    493 SCIP_Longint minnodes; /**< minimum number of nodes required to start a sub-SCIP */
    494 SCIP_Longint usednodes; /**< total number of nodes already spent in sub-SCIPs */
    495 SCIP_Real nodesquot; /**< fraction of nodes compared to the main SCIP for budget computation */
    496 SCIP_Real nodesquotmin; /**< lower bound on fraction of nodes compared to the main SCIP for budget computation */
    497 SCIP_Real lplimfac; /**< limit fraction of LPs per node to interrupt sub-SCIP */
    498 SCIP_Real targetnodefactor; /**< factor by which target node number is eventually increased */
    499 SCIP_Real fixtol; /**< tolerance by which the fixing rate may be missed without generic fixing */
    500 SCIP_Real unfixtol; /**< tolerance by which the fixing rate may be exceeded without generic unfixing */
    501 int nneighborhoods; /**< number of neighborhoods */
    502 int nactiveneighborhoods;/**< number of active neighborhoods */
    503 int ninitneighborhoods; /**< neighborhoods that were used at least one time */
    504 int nsolslim; /**< limit on the number of improving solutions in a sub-SCIP call */
    505 int seed; /**< initial random seed for bandit algorithms and random decisions by neighborhoods */
    506 int currneighborhood; /**< index of currently selected neighborhood */
    507 int ndelayedcalls; /**< the number of delayed calls */
    508 SCIP_Bool usesubscipheurs; /**< should the heuristic activate other sub-SCIP heuristics during its search? */
    509 SCIP_Bool subsciprandseeds; /**< should random seeds of sub-SCIPs be altered to increase diversification? */
    510 SCIP_Bool copycuts; /**< should cutting planes be copied to the sub-SCIP? */
    511 int initlnsnodelimit; /**< initial node limit for LNS heuristics */
    512 int maxlnsnodelimit; /**< maximum of nodelimits among all LNS heuristics */
    513 SCIP_Bool useredcost; /**< should reduced cost scores be used for variable prioritization? */
    514 SCIP_Bool usedistances; /**< should distances from fixed variables be used for variable prioritization */
    515 SCIP_Bool usepscost; /**< should pseudo cost scores be used for variable prioritization? */
    516 SCIP_Bool uselocalredcost; /**< should local reduced costs be used for generic (un)fixing? */
    517};
    518
    519/** event handler data */
    520struct SCIP_EventData
    521{
    522 SCIP_VAR** subvars; /**< the variables of the subproblem */
    523 SCIP* sourcescip; /**< original SCIP data structure */
    524 SCIP_HEUR* heur; /**< scheduler heuristic structure */
    525 SCIP_Longint nodelimit; /**< node limit of the run */
    526 SCIP_Real lplimfac; /**< limit fraction of LPs per node to interrupt sub-SCIP */
    527 HEUR_STATS* runstats; /**< run statistics for the current neighborhood */
    528};
    529
    530/** represents limits for the sub-SCIP solving process */
    531struct SolveLimits
    532{
    533 SCIP_Longint nodelimit; /**< maximum number of solving nodes for the sub-SCIP */
    534 SCIP_Real memorylimit; /**< memory limit for the sub-SCIP */
    535 SCIP_Real timelimit; /**< time limit for the sub-SCIP */
    536 SCIP_Longint stallnodes; /**< maximum number of nodes without (primal) stalling */
    537};
    538
    540
    541/** data structure that can be used for variable prioritization for additional fixings */
    542struct VarPrio
    543{
    544 SCIP* scip; /**< SCIP data structure */
    545 SCIP_Real* randscores; /**< random scores for prioritization */
    546 int* distances; /**< breadth-first distances from already fixed variables */
    547 SCIP_Real* redcostscores; /**< reduced cost scores for fixing a variable to a reference value */
    548 SCIP_Real* pscostscores; /**< pseudocost scores for fixing a variable to a reference value */
    549 unsigned int useredcost:1; /**< should reduced cost scores be used for variable prioritization? */
    550 unsigned int usedistances:1; /**< should distances from fixed variables be used for variable prioritization */
    551 unsigned int usepscost:1; /**< should pseudo cost scores be used for variable prioritization? */
    552};
    553
    554/*
    555 * Local methods
    556 */
    557
    558/** Reset target fixing rate */
    559static
    561 SCIP* scip, /**< SCIP data structure */
    562 NH_FIXINGRATE* fixingrate /**< heuristic fixing rate */
    563 )
    564{
    565 assert(scip != NULL);
    566 assert(fixingrate != NULL);
    567 fixingrate->increment = FIXINGRATE_STARTINC;
    568
    569 /* always start with the most conservative value */
    570 fixingrate->targetfixingrate = fixingrate->maxfixingrate;
    571
    572 return SCIP_OKAY;
    573}
    574
    575/** update increment for fixing rate */
    576static
    578 NH_FIXINGRATE* fx /**< fixing rate */
    579 )
    580{
    582 fx->increment = MAX(fx->increment, LRATEMIN);
    583}
    584
    585/** increase fixing rate
    586 *
    587 * decrease also the rate by which the target fixing rate is adjusted
    588 */
    589static
    591 NH_FIXINGRATE* fx /**< fixing rate */
    592 )
    593{
    594 fx->targetfixingrate += fx->increment;
    596}
    597
    598/** decrease fixing rate
    599 *
    600 * decrease also the rate by which the target fixing rate is adjusted
    601 */
    602static
    604 NH_FIXINGRATE* fx /**< fixing rate */
    605 )
    606{
    607 fx->targetfixingrate -= fx->increment;
    609}
    610
    611/** update fixing rate based on the results of the current run */
    612static
    614 NH* neighborhood, /**< neighborhood */
    615 SCIP_STATUS subscipstatus, /**< status of the sub-SCIP run */
    616 HEUR_STATS* runstats /**< run statistics for this run */
    617 )
    618{
    619 NH_FIXINGRATE* fx;
    620
    621 fx = &neighborhood->fixingrate;
    622
    623 switch (subscipstatus)
    624 {
    630 /* decrease the fixing rate (make subproblem harder) */
    632 break;
    637 /* increase the fixing rate (make the subproblem easier) only if no solution was found */
    638 if( runstats->nbestsolsfound <= 0 )
    640 break;
    650 default:
    651 break;
    652 }
    653
    655}
    656
    657/** reset the currently active neighborhood */
    658static
    660 SCIP_HEURDATA* heurdata
    661 )
    662{
    663 assert(heurdata != NULL);
    664 heurdata->currneighborhood = -1;
    665 heurdata->ndelayedcalls = 0;
    666}
    667
    668/** reset target node limit */
    669static
    671 SCIP_HEURDATA* heurdata /**< heuristic data */
    672 )
    673{
    674 heurdata->targetnodes = heurdata->minnodes;
    675}
    676
    677/** Reset neighborhood statistics */
    678static
    680 SCIP* scip, /**< SCIP data structure */
    681 HEUR_STATS* stats, /**< heuristic statistics */
    682 SCIP_Bool usediving /**< TRUE if the statistics belong to a diving heuristic */
    683 )
    684{
    685 assert(scip != NULL);
    686 assert(stats != NULL);
    687
    688 stats->nbestsolsfound = 0;
    689 stats->nruns = 0;
    690 stats->nrunsbestsol = 0;
    691 stats->nsolsfound = 0;
    692 stats->usednodes = 0L;
    693 stats->nfixings = 0L;
    694 stats->nbacktracks = 0L;
    695 stats->nconflicts = 0L;
    696 stats->nprobnodes = 0L;
    697 stats->divingdepth = 0;
    698
    701
    702 /* if we use diving, these stats are not used (and memory not allocated) */
    703 if( ! usediving )
    704 {
    706 }
    707
    708 return SCIP_OKAY;
    709}
    710
    711/** create a neighborhood of the specified name and include it into the scheduler heuristic */
    712static
    714 SCIP* scip, /**< SCIP data structure */
    715 SCIP_HEURDATA* heurdata, /**< heuristic data of the scheduler heuristic */
    716 NH** neighborhood, /**< pointer to store the neighborhood */
    717 const char* name, /**< name for this neighborhood */
    718 SCIP_Real minfixingrate, /**< default value for minfixingrate parameter of this neighborhood */
    719 SCIP_Real maxfixingrate, /**< default value for maxfixingrate parameter of this neighborhood */
    720 SCIP_Bool active, /**< default value for active parameter of this neighborhood */
    721 int priority, /**< priority for heuristic in rootnode */
    722 DECL_VARFIXINGS ((*varfixings)), /**< variable fixing callback for this neighborhood, or NULL */
    723 DECL_CHANGESUBSCIP ((*changesubscip)), /**< subscip changes callback for this neighborhood, or NULL */
    724 DECL_NHINIT ((*nhinit)), /**< initialization callback for neighborhood, or NULL */
    725 DECL_NHEXIT ((*nhexit)), /**< deinitialization callback for neighborhood, or NULL */
    726 DECL_NHFREE ((*nhfree)), /**< deinitialization callback before SCIP is freed, or NULL */
    727 DECL_NHREFSOL ((*nhrefsol)), /**< callback function to return a reference solution for further fixings, or NULL */
    728 DECL_NHDEACTIVATE ((*nhdeactivate)) /**< callback function to deactivate neighborhoods on problems where they are irrelevant, or NULL if neighborhood is always active */
    729 )
    730{
    732
    733 assert(scip != NULL);
    734 assert(heurdata != NULL);
    735 assert(neighborhood != NULL);
    736 assert(name != NULL);
    737
    738 SCIP_CALL( SCIPallocBlockMemory(scip, neighborhood) );
    739 assert(*neighborhood != NULL);
    740
    741 SCIP_ALLOC( BMSduplicateMemoryArray(&(*neighborhood)->name, name, strlen(name)+1) );
    742
    743 SCIP_CALL( SCIPcreateClock(scip, &(*neighborhood)->stats.setupclock) );
    744 SCIP_CALL( SCIPcreateClock(scip, &(*neighborhood)->stats.execclock) );
    745
    746 (*neighborhood)->changesubscip = changesubscip;
    747 (*neighborhood)->varfixings = varfixings;
    748 (*neighborhood)->nhinit = nhinit;
    749 (*neighborhood)->nhexit = nhexit;
    750 (*neighborhood)->nhfree = nhfree;
    751 (*neighborhood)->nhrefsol = nhrefsol;
    752 (*neighborhood)->nhdeactivate = nhdeactivate;
    753
    754 (*neighborhood)->rootnodepriority = priority;
    755
    756 /* add parameters for this neighborhood */
    757 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/scheduler/%s/minfixingrate", name);
    758 SCIP_CALL( SCIPaddRealParam(scip, paramname, "minimum fixing rate for this neighborhood",
    759 &(*neighborhood)->fixingrate.minfixingrate, TRUE, minfixingrate, 0.0, 1.0, NULL, NULL) );
    760 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/scheduler/%s/maxfixingrate", name);
    761 SCIP_CALL( SCIPaddRealParam(scip, paramname, "maximum fixing rate for this neighborhood",
    762 &(*neighborhood)->fixingrate.maxfixingrate, TRUE, maxfixingrate, 0.0, 1.0, NULL, NULL) );
    763 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/scheduler/%s/active", name);
    764 SCIP_CALL( SCIPaddBoolParam(scip, paramname, "is this neighborhood active?",
    765 &(*neighborhood)->active, TRUE, active, NULL, NULL) );
    766 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "heuristics/scheduler/%s/priority", name);
    767 SCIP_CALL( SCIPaddRealParam(scip, paramname, "positive call priority to initialize bandit algorithms",
    768 &(*neighborhood)->priority, TRUE, 1.0, 1e-2, 1.0, NULL, NULL) );
    769
    770 /* add the neighborhood to heuristic */
    771 heurdata->neighborhoods[heurdata->nneighborhoods++] = (*neighborhood);
    772
    773 return SCIP_OKAY;
    774}
    775
    776/** release all data and free neighborhood */
    777static
    779 SCIP* scip, /**< SCIP data structure */
    780 NH** neighborhood /**< pointer to neighborhood that should be freed */
    781 )
    782{
    783 NH* nhptr;
    784 assert(scip != NULL);
    785 assert(neighborhood != NULL);
    786
    787 nhptr = *neighborhood;
    788 assert(nhptr != NULL);
    789
    790 BMSfreeMemoryArray(&nhptr->name);
    791
    792 /* release further, neighborhood specific data structures */
    793 if( nhptr->nhfree != NULL )
    794 {
    795 SCIP_CALL( nhptr->nhfree(scip, nhptr) );
    796 }
    797
    799 SCIP_CALL( SCIPfreeClock(scip, &nhptr->stats.execclock) );
    800
    801 SCIPfreeBlockMemory(scip, neighborhood);
    802 *neighborhood = NULL;
    803
    804 return SCIP_OKAY;
    805}
    806
    807/** initialize neighborhood specific data */
    808static
    810 SCIP* scip, /**< SCIP data structure */
    811 NH* neighborhood /**< neighborhood to initialize */
    812 )
    813{
    814 assert(scip != NULL);
    815 assert(neighborhood != NULL);
    816
    817 /* call the init callback of the neighborhood */
    818 if( neighborhood->nhinit != NULL )
    819 {
    820 SCIP_CALL( neighborhood->nhinit(scip, neighborhood) );
    821 }
    822
    823 return SCIP_OKAY;
    824}
    825
    826/** deinitialize neighborhood specific data */
    827static
    829 SCIP* scip, /**< SCIP data structure */
    830 NH* neighborhood /**< neighborhood to initialize */
    831 )
    832{
    833 assert(scip != NULL);
    834 assert(neighborhood != NULL);
    835
    836 if( neighborhood->nhexit != NULL )
    837 {
    838 SCIP_CALL( neighborhood->nhexit(scip, neighborhood) );
    839 }
    840
    841 return SCIP_OKAY;
    842}
    843
    844/** creates a new solution for the original problem by copying the solution of the subproblem */
    845static
    847 SCIP* subscip, /**< SCIP data structure of the subproblem */
    848 SCIP_EVENTDATA* eventdata /**< event handler data */
    849 )
    850{
    851 SCIP* sourcescip; /* original SCIP data structure */
    852 SCIP_VAR** subvars; /* the variables of the subproblem */
    853 SCIP_HEUR* heur; /* scheduler heuristic structure */
    854 SCIP_SOL* subsol; /* solution of the subproblem */
    855 SCIP_SOL* newsol; /* solution to be created for the original problem */
    856 SCIP_Bool success;
    857 HEUR_STATS* runstats;
    858 SCIP_SOL* oldbestsol;
    859
    860 assert(subscip != NULL);
    861
    862 subsol = SCIPgetBestSol(subscip);
    863 assert(subsol != NULL);
    864
    865 sourcescip = eventdata->sourcescip;
    866 subvars = eventdata->subvars;
    867 heur = eventdata->heur;
    868 runstats = eventdata->runstats;
    869 assert(sourcescip != NULL);
    870 assert(sourcescip != subscip);
    871 assert(heur != NULL);
    872 assert(subvars != NULL);
    873 assert(runstats != NULL);
    874
    875 SCIP_CALL( SCIPtranslateSubSol(sourcescip, subscip, subsol, heur, subvars, &newsol) );
    876
    877 oldbestsol = SCIPgetBestSol(sourcescip);
    878
    879 /* try to add new solution to scip and free it immediately */
    880 SCIP_CALL( SCIPtrySolFree(sourcescip, &newsol, FALSE, FALSE, TRUE, TRUE, TRUE, &success) );
    881
    882 if( success )
    883 {
    884 runstats->nsolsfound++;
    885 if( SCIPgetBestSol(sourcescip) != oldbestsol )
    886 runstats->nbestsolsfound++;
    887 }
    888
    889 /* update new upper bound for reward later */
    890 runstats->newupperbound = SCIPgetUpperbound(sourcescip);
    891
    892 return SCIP_OKAY;
    893}
    894
    895/** release all data and free diving heuristic */
    896static
    898 SCIP* scip, /**< SCIP data structure */
    899 DIVING_HEUR** divingheur /**< pointer to diving heuristic that should be freed */
    900 )
    901{
    902 DIVING_HEUR* divingheurptr;
    903 assert(scip != NULL);
    904 assert(divingheur != NULL);
    905
    906 divingheurptr = *divingheur;
    907 assert(divingheurptr != NULL);
    908
    909 SCIP_CALL( SCIPfreeClock(scip, &divingheurptr->stats->setupclock) );
    910 SCIP_CALL( SCIPfreeClock(scip, &divingheurptr->stats->execclock) );
    911
    912 SCIPfreeBlockMemory(scip, &divingheurptr->solvefreqdata);
    913 SCIPfreeBlockMemory(scip, &divingheurptr->stats);
    914 SCIPfreeBlockMemory(scip, divingheur);
    915
    916 return SCIP_OKAY;
    917}
    918
    919/* ---------------- Callback methods of event handler ---------------- */
    920
    921/** execution callback of the event handler
    922 *
    923 * transfer new solutions or interrupt the solving process manually
    924 */
    925static
    926SCIP_DECL_EVENTEXEC(eventExecScheduler)
    927{
    928 assert(eventhdlr != NULL);
    929 assert(eventdata != NULL);
    930 assert(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    931 assert(event != NULL);
    933 assert(eventdata != NULL);
    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 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1798
    1799 /* call inclusion method of primal heuristic */
    1801
    1802 return SCIP_OKAY;
    1803}
    1804
    1805/** query neighborhood for a reference solution for further fixings */
    1806static
    1808 SCIP* scip, /**< SCIP data structure */
    1809 NH* neighborhood, /**< neighborhood data structure */
    1810 SCIP_SOL** solptr /**< solution pointer */
    1811 )
    1812{
    1813 assert(solptr != NULL);
    1814 assert(scip != NULL);
    1815 assert(neighborhood != NULL);
    1816
    1817 *solptr = NULL;
    1818 if( neighborhood->nhrefsol != NULL )
    1819 {
    1820 SCIP_RESULT result;
    1821 SCIP_CALL( neighborhood->nhrefsol(scip, neighborhood, solptr, &result) );
    1822
    1823 if( result == SCIP_DIDNOTFIND )
    1824 *solptr = NULL;
    1825 else
    1826 assert(*solptr != NULL);
    1827 }
    1828
    1829 return SCIP_OKAY;
    1830}
    1831
    1832/** unfix some of the variables because there are too many fixed
    1833 *
    1834 * a variable is ideally unfixed if it is close to other unfixed variables
    1835 * and fixing it has a high reduced cost impact
    1836 */
    1837static
    1839 SCIP* scip, /**< SCIP data structure */
    1840 SCIP_HEURDATA* heurdata, /**< heuristic data of neighborhood */
    1841 SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
    1842 SCIP_Real* valbuf, /**< buffer array to store fixing values */
    1843 int* nfixings, /**< pointer to store the number of fixings */
    1844 int ntargetfixings, /**< number of required target fixings */
    1845 SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
    1846 )
    1847{
    1848 VARPRIO varprio;
    1849 SCIP_Real* redcostscores;
    1850 SCIP_Real* pscostscores;
    1851 SCIP_Real* randscores;
    1852 SCIP_VAR** unfixedvars;
    1853 SCIP_VAR** varbufcpy;
    1854 SCIP_Real* valbufcpy;
    1855 SCIP_Bool* isfixedvar;
    1856 SCIP_VAR** vars;
    1857 SCIP_RANDNUMGEN* rng;
    1858 int* distances;
    1859 int* fixeddistances;
    1860 int* perm;
    1861 int nvars;
    1862 int i;
    1863 int nbinintvars;
    1864 int nunfixed;
    1865
    1866 *success = FALSE;
    1867
    1868 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    1869 if( nbinintvars == 0 )
    1870 return SCIP_OKAY;
    1871
    1872 assert(*nfixings > 0);
    1873
    1874 nvars = SCIPgetNVars(scip);
    1875 SCIP_CALL( SCIPallocBufferArray(scip, &isfixedvar, nvars) );
    1876 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
    1877 SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
    1878 SCIP_CALL( SCIPallocBufferArray(scip, &fixeddistances, *nfixings) );
    1879 SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, *nfixings) );
    1880 SCIP_CALL( SCIPallocBufferArray(scip, &randscores, *nfixings) );
    1881 SCIP_CALL( SCIPallocBufferArray(scip, &perm, *nfixings) );
    1882 SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, *nfixings) );
    1883
    1884 SCIP_CALL( SCIPduplicateBufferArray(scip, &varbufcpy, varbuf, *nfixings) );
    1885 SCIP_CALL( SCIPduplicateBufferArray(scip, &valbufcpy, valbuf, *nfixings) );
    1886
    1887 /*
    1888 * collect the unfixed binary and integer variables
    1889 */
    1890 BMSclearMemoryArray(isfixedvar, nvars);
    1891 /* loop over fixed variables and mark their respective positions as fixed */
    1892 for( i = 0; i < *nfixings; ++i )
    1893 {
    1894 int probindex = SCIPvarGetProbindex(varbuf[i]);
    1895
    1896 assert(probindex >= 0);
    1897
    1898 isfixedvar[probindex] = TRUE;
    1899 }
    1900
    1901 nunfixed = 0;
    1902 vars = SCIPgetVars(scip);
    1903 /* collect unfixed binary and integer variables */
    1904 for( i = 0; i < nbinintvars; ++i )
    1905 {
    1906 if( ! isfixedvar[i] )
    1907 unfixedvars[nunfixed++] = vars[i];
    1908 }
    1909
    1910 varprio.usedistances = heurdata->usedistances && nunfixed > 0;
    1911
    1912 /* collect distances of all fixed variables from those that are not fixed */
    1913 if( varprio.usedistances )
    1914 {
    1915 SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, unfixedvars, nunfixed, distances, INT_MAX, INT_MAX, INT_MAX) );
    1916
    1917 for( i = 0; i < *nfixings; ++i )
    1918 {
    1919 int probindex = SCIPvarGetProbindex(varbuf[i]);
    1920 if( probindex >= 0 )
    1921 fixeddistances[i] = distances[probindex];
    1922 }
    1923 }
    1924 else
    1925 {
    1926 BMSclearMemoryArray(fixeddistances, *nfixings);
    1927 }
    1928
    1929 /* collect reduced cost scores of the fixings and assign random scores */
    1930 rng = SCIPbanditGetRandnumgen(heurdata->bandit);
    1931 for( i = 0; i < *nfixings; ++i )
    1932 {
    1933 SCIP_VAR* fixedvar = varbuf[i];
    1934 SCIP_Real fixval = valbuf[i];
    1935
    1936 /* use negative reduced cost and pseudo cost scores to prefer variable fixings with small score */
    1937 redcostscores[i] = - getVariableRedcostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
    1938 pscostscores[i] = - getVariablePscostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
    1939 randscores[i] = SCIPrandomGetReal(rng, 0.0, 1.0);
    1940 perm[i] = i;
    1941
    1942 //SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
    1943 // SCIPvarGetName(fixedvar), fixeddistances[i], redcostscores[i], pscostscores[i], randscores[i]);
    1944 }
    1945
    1946 varprio.distances = fixeddistances;
    1947 varprio.randscores = randscores;
    1948 varprio.redcostscores = redcostscores;
    1949 varprio.pscostscores = pscostscores;
    1950 varprio.useredcost = heurdata->useredcost;
    1951 varprio.usepscost = heurdata->usepscost;
    1952 varprio.scip = scip;
    1953
    1954 /* scores are assigned in such a way that variables with a smaller score should be fixed last */
    1955 SCIPselectDownInd(perm, sortIndCompScheduler, &varprio, ntargetfixings, *nfixings);
    1956
    1957 /* bring the desired variables to the front of the array */
    1958 for( i = 0; i < ntargetfixings; ++i )
    1959 {
    1960 valbuf[i] = valbufcpy[perm[i]];
    1961 varbuf[i] = varbufcpy[perm[i]];
    1962 }
    1963
    1964 *nfixings = ntargetfixings;
    1965
    1966 /* free the buffer arrays in reverse order of allocation */
    1967 SCIPfreeBufferArray(scip, &valbufcpy);
    1968 SCIPfreeBufferArray(scip, &varbufcpy);
    1969 SCIPfreeBufferArray(scip, &pscostscores);
    1970 SCIPfreeBufferArray(scip, &perm);
    1971 SCIPfreeBufferArray(scip, &randscores);
    1972 SCIPfreeBufferArray(scip, &redcostscores);
    1973 SCIPfreeBufferArray(scip, &fixeddistances);
    1974 SCIPfreeBufferArray(scip, &distances);
    1975 SCIPfreeBufferArray(scip, &unfixedvars);
    1976 SCIPfreeBufferArray(scip, &isfixedvar);
    1977
    1978 *success = TRUE;
    1979
    1980 return SCIP_OKAY;
    1981}
    1982
    1983/** call variable fixing callback for this neighborhood and orchestrate additional variable fixings, if necessary */
    1984static
    1986 SCIP* scip, /**< SCIP data structure */
    1987 SCIP_HEURDATA* heurdata, /**< heuristic data of the scheduler neighborhood */
    1988 NH* neighborhood, /**< neighborhood data structure */
    1989 SCIP_VAR** varbuf, /**< buffer array to keep variables that should be fixed */
    1990 SCIP_Real* valbuf, /**< buffer array to keep fixing values */
    1991 int* nfixings, /**< pointer to store the number of variable fixings */
    1992 SCIP_RESULT* result /**< pointer to store the result of the fixing operation */
    1993 )
    1994{
    1995 int ntargetfixings;
    1996 int nmaxfixings;
    1997 int nminfixings;
    1998 int nbinintvars;
    1999
    2000 assert(scip != NULL);
    2001 assert(neighborhood != NULL);
    2002 assert(varbuf != NULL);
    2003 assert(valbuf != NULL);
    2004 assert(nfixings != NULL);
    2005 assert(result != NULL);
    2006
    2007 *nfixings = 0;
    2008
    2009 *result = SCIP_DIDNOTRUN;
    2010 ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)));
    2011
    2012 if( neighborhood->varfixings != NULL )
    2013 {
    2014 SCIP_CALL( neighborhood->varfixings(scip, neighborhood, varbuf, valbuf, nfixings, result) );
    2015
    2016 if( *result != SCIP_SUCCESS )
    2017 return SCIP_OKAY;
    2018 }
    2019 else if( ntargetfixings == 0 )
    2020 {
    2021 *result = SCIP_SUCCESS;
    2022 return SCIP_OKAY;
    2023 }
    2024
    2025 /* compute upper and lower target fixing limits using tolerance parameters */
    2026 assert(neighborhood->varfixings == NULL || *result != SCIP_DIDNOTRUN);
    2027 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    2028 ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * nbinintvars);
    2029 nminfixings = (int)((neighborhood->fixingrate.targetfixingrate - heurdata->fixtol) * nbinintvars);
    2030 nminfixings = MAX(nminfixings, 0);
    2031 nmaxfixings = (int)((neighborhood->fixingrate.targetfixingrate + heurdata->unfixtol) * nbinintvars);
    2032 nmaxfixings = MIN(nmaxfixings, nbinintvars);
    2033
    2034 SCIPdebugMsg(scip, "Neighborhood Fixings/Target: %d / %d <= %d <= %d\n",*nfixings, nminfixings, ntargetfixings, nmaxfixings);
    2035
    2036 /* if too few fixings, use a strategy to select more variable fixings: randomized, LP graph, ReducedCost based, mix */
    2037 if( (*result == SCIP_SUCCESS || *result == SCIP_DIDNOTRUN) && (*nfixings < nminfixings) )
    2038 {
    2039 SCIP_Bool success;
    2040 SCIP_SOL* refsol;
    2041
    2042 /* get reference solution from neighborhood */
    2043 SCIP_CALL( neighborhoodGetRefsol(scip, neighborhood, &refsol) );
    2044
    2045 /* try to fix more variables based on the reference solution */
    2046 if( refsol != NULL )
    2047 {
    2048 SCIP_CALL( LNSFixMoreVariables(scip, heurdata, refsol, varbuf, valbuf, nfixings, ntargetfixings, &success) );
    2049 }
    2050 else
    2051 success = FALSE;
    2052
    2053 if( success )
    2054 *result = SCIP_SUCCESS;
    2055 else if( *result == SCIP_SUCCESS )
    2056 *result = SCIP_DIDNOTFIND;
    2057 else
    2058 *result = SCIP_DIDNOTRUN;
    2059
    2060 SCIPdebugMsg(scip, "After additional fixings: %d / %d\n",*nfixings, ntargetfixings);
    2061 }
    2062 else if( (SCIP_Real)(*nfixings) > nmaxfixings )
    2063 {
    2064 SCIP_Bool success;
    2065
    2066 SCIP_CALL( LNSUnfixVariables(scip, heurdata, varbuf, valbuf, nfixings, ntargetfixings, &success) );
    2067
    2068 assert(success);
    2069 *result = SCIP_SUCCESS;
    2070 SCIPdebugMsg(scip, "Unfixed variables, fixed variables remaining: %d\n", ntargetfixings);
    2071 }
    2072 else
    2073 {
    2074 SCIPdebugMsg(scip, "No additional fixings performed\n");
    2075 }
    2076
    2077 return SCIP_OKAY;
    2078}
    2079
    2080/** change the sub-SCIP by restricting variable domains, changing objective coefficients, or adding constraints */
    2081static
    2083 SCIP* sourcescip, /**< source SCIP data structure */
    2084 SCIP* targetscip, /**< target SCIP data structure */
    2085 NH* neighborhood, /**< neighborhood */
    2086 SCIP_VAR** targetvars, /**< array of target SCIP variables aligned with source SCIP variables */
    2087 int* ndomchgs, /**< pointer to store the number of variable domain changes */
    2088 int* nchgobjs, /**< pointer to store the number of changed objective coefficients */
    2089 int* naddedconss, /**< pointer to store the number of added constraints */
    2090 SCIP_Bool* success /**< pointer to store whether the sub-SCIP has been successfully modified */
    2091 )
    2092{
    2093 assert(sourcescip != NULL);
    2094 assert(targetscip != NULL);
    2095 assert(neighborhood != NULL);
    2096 assert(targetvars != NULL);
    2097 assert(ndomchgs != NULL);
    2098 assert(nchgobjs != NULL);
    2099 assert(naddedconss != NULL);
    2100 assert(success != NULL);
    2101
    2102 *success = FALSE;
    2103 *ndomchgs = 0;
    2104 *nchgobjs = 0;
    2105 *naddedconss = 0;
    2106
    2107 /* call the change sub-SCIP callback of the neighborhood */
    2108 if( neighborhood->changesubscip != NULL )
    2109 {
    2110 SCIP_CALL( neighborhood->changesubscip(sourcescip, targetscip, neighborhood, targetvars, ndomchgs, nchgobjs, naddedconss, success) );
    2111 }
    2112 else
    2113 {
    2114 *success = TRUE;
    2115 }
    2116
    2117 return SCIP_OKAY;
    2118}
    2119
    2120/** set sub-SCIP solving limits */
    2121static
    2123 SCIP* subscip, /**< SCIP data structure */
    2124 SOLVELIMITS* solvelimits /**< pointer to solving limits data structure */
    2125 )
    2126{
    2127 assert(subscip != NULL);
    2128 assert(solvelimits != NULL);
    2129
    2130 assert(solvelimits->nodelimit >= solvelimits->stallnodes);
    2131
    2132 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", solvelimits->nodelimit) );
    2133 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", solvelimits->stallnodes) );
    2134 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", solvelimits->timelimit) );
    2135 SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", solvelimits->memorylimit) );
    2136
    2137 return SCIP_OKAY;
    2138}
    2139
    2140/** determine limits for a sub-SCIP */
    2141static
    2143 SCIP* scip, /**< SCIP data structure */
    2144 SCIP_HEUR* heur, /**< this heuristic */
    2145 int selection, /**< index of selected neighborhood */
    2146 SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
    2147 SCIP_Bool* runagain /**< can we solve another sub-SCIP with these limits */
    2148 )
    2149{
    2150 SCIP_HEURDATA* heurdata;
    2151 SCIP_Bool avoidmemout;
    2152
    2153 assert(scip != NULL);
    2154 assert(heur != NULL);
    2155 assert(solvelimits != NULL);
    2156 assert(runagain != NULL);
    2157
    2158 heurdata = SCIPheurGetData(heur);
    2159
    2160 /* check whether there is enough time and memory left */
    2161 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &solvelimits->timelimit) );
    2162 if( ! SCIPisInfinity(scip, solvelimits->timelimit) )
    2163 solvelimits->timelimit -= SCIPgetSolvingTime(scip);
    2164 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &solvelimits->memorylimit) );
    2165 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
    2166
    2167 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
    2168 if( ! SCIPisInfinity(scip, solvelimits->memorylimit) )
    2169 {
    2170 solvelimits->memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
    2171 solvelimits->memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
    2172 }
    2173
    2174 /* abort if no time is left or not enough memory (we don't abort in this case if misc_avoidmemout == FALSE)
    2175 * to create a copy of SCIP, including external memory usage */
    2176 if( solvelimits->timelimit <= 0.0 || (avoidmemout && solvelimits->memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0) )
    2177 {
    2178 SCIPdebugMsg(scip, "Aborting LNS heuristic call: Not enough memory or time left.\n");
    2179 *runagain = FALSE;
    2180 return SCIP_OKAY;
    2181 }
    2182
    2183 /* TODO: set stalling limit */
    2184 solvelimits->stallnodes = -1;
    2185 solvelimits->nodelimit = (SCIP_Longint) heurdata->neighborhoods[selection]->nodelimit;
    2186
    2187 return SCIP_OKAY;
    2188}
    2189
    2190/** Calculate reward based on the selected reward measure */
    2191static
    2193 SCIP* scip, /**< SCIP data structure */
    2194 SCIP_HEURDATA* heurdata, /**< heuristic data of the scheduler neighborhood */
    2195 int selection, /**< index of selected heuristic */
    2196 HEUR_STATS* runstats /**< run statistics */
    2197 )
    2198{
    2199 SCIP_Real totalreward;
    2200 SCIP_Real effortsaved;
    2201 SCIP_Real bestsolreward;
    2202 SCIP_Real closedgapreward;
    2203 SCIP_Real conflictreward;
    2204
    2205 /* compute the effort it took to execute selected heuristic */
    2206 if( selection < heurdata->ndiving )
    2207 effortsaved = (SCIP_Real) runstats->divingdepth / (SCIP_Real)heurdata->maxdivingnodelimit;
    2208 else
    2209 effortsaved = MIN(1.0, (SCIP_Real) runstats->usednodes / (SCIP_Real)heurdata->maxlnsnodelimit);
    2210 effortsaved = (1.0 - effortsaved);
    2211 assert(effortsaved >= 0.0 && effortsaved <= 1.0);
    2212 assert(heurdata->maxlnsnodelimit > 0);
    2213 assert(heurdata->maxdivingnodelimit > 0);
    2214
    2215 /* compute reward for number of conflicts generated */
    2216 if( selection < heurdata->ndiving )
    2217 {
    2218 if( runstats->nconflicts == 0 )
    2219 conflictreward = 0.0;
    2220 else if( heurdata->maxnconflicts > 0 )
    2221 conflictreward = (SCIP_Real) runstats->nconflicts / (SCIP_Real) heurdata->maxnconflicts;
    2222 else
    2223 conflictreward = 1.0;
    2224 }
    2225 else
    2226 conflictreward = 0.0; /* LNS heuristics don't add conflict constraints */
    2227 assert(conflictreward >= 0.0 && conflictreward <= 1.0);
    2228
    2229 /* a positive reward is only assigned if a new incumbent solution was found */
    2230 if( runstats->nbestsolsfound > 0 )
    2231 {
    2232 SCIP_Real lb;
    2233 SCIP_Real ub;
    2234
    2235 /* the indicator function is simply 1.0 */
    2236 bestsolreward = 1.0;
    2237
    2238 ub = runstats->newupperbound;
    2239 lb = SCIPgetLowerbound(scip);
    2240
    2241 /* compute the closed gap reward */
    2242 if( SCIPisEQ(scip, ub, lb) || SCIPisInfinity(scip, runstats->oldupperbound) ) // gap is closed or first primal solution was found
    2243 closedgapreward = 1.0;
    2244 else
    2245 closedgapreward = (runstats->oldupperbound - ub) / (runstats->oldupperbound - lb);
    2246 }
    2247 else
    2248 {
    2249 bestsolreward = 0.0;
    2250 closedgapreward = 0.0;
    2251 }
    2252
    2253 /* compute total reward */
    2254 totalreward = heurdata->effortrewardweight * effortsaved + heurdata->solrewardweight * bestsolreward
    2255 + heurdata->qualrewardweight * closedgapreward + heurdata->conflictrewardweight * conflictreward;
    2256 totalreward = MIN( totalreward, 1.0);
    2257 assert(totalreward >= 0.0 && totalreward <= 1.0);
    2258
    2259 return totalreward;
    2260}
    2261
    2262/** set up the sub-SCIP parameters, objective cutoff, and solution limits */
    2263static
    2265 SCIP* scip, /**< SCIP data structure */
    2266 SCIP* subscip, /**< sub-SCIP data structure */
    2267 SCIP_VAR** subvars, /**< array of sub-SCIP variables in the order of the main SCIP */
    2268 SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
    2269 SCIP_HEUR* heur, /**< this heuristic */
    2270 SCIP_Bool objchgd /**< did the objective change between the source and the target SCIP? */
    2271 )
    2272{
    2273 SCIP_HEURDATA* heurdata;
    2274 SCIP_Real cutoff;
    2275
    2276 heurdata = SCIPheurGetData(heur);
    2277
    2278 /* do not abort subproblem on CTRL-C */
    2279 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    2280
    2281 /* disable output to console unless we are in debug mode */
    2282 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    2283
    2284 /* disable statistic timing inside sub SCIP */
    2285 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    2286
    2287#ifdef SCHEDULER_SUBSCIPOUTPUT
    2288 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    2289 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1) );
    2290 /* enable statistic timing inside sub SCIP */
    2291 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", TRUE) );
    2292#endif
    2293
    2294 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->nsolslim) );
    2295
    2296 /* forbid recursive call of heuristics and separators solving subMIPs */
    2297 if( ! heurdata->usesubscipheurs )
    2298 {
    2299 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    2300 }
    2301
    2302 /* disable cutting plane separation */
    2304
    2305 /* disable expensive presolving */
    2307
    2308 /* use best estimate node selection */
    2309 if( SCIPfindNodesel(subscip, "estimate") != NULL && ! SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
    2310 {
    2311 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
    2312 }
    2313
    2314 /* use inference branching */
    2315 if( SCIPfindBranchrule(subscip, "inference") != NULL && ! SCIPisParamFixed(subscip, "branching/inference/priority") )
    2316 {
    2317 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    2318 }
    2319
    2320 /* enable conflict analysis and restrict conflict pool */
    2321 if( ! SCIPisParamFixed(subscip, "conflict/enable") )
    2322 {
    2323 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
    2324 }
    2325
    2326 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
    2327 {
    2328 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
    2329 }
    2330
    2331 if( ! SCIPisParamFixed(subscip, "conflict/maxstoresize") )
    2332 {
    2333 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
    2334 }
    2335
    2336 /* speed up sub-SCIP by not checking dual LP feasibility */
    2337 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    2338
    2339 /* add an objective cutoff */
    2341 {
    2343
    2344 /* if the objective changed between the source and the target SCIP, encode the cutoff as a constraint */
    2345 if( ! objchgd )
    2346 {
    2347 SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
    2348 }
    2349 else
    2350 {
    2351 SCIP_CONS* objcons;
    2352 int nvars;
    2353 SCIP_VAR** vars;
    2354 int i;
    2355
    2356 vars = SCIPgetVars(scip);
    2357 nvars = SCIPgetNVars(scip);
    2358
    2359 SCIP_CALL( SCIPcreateConsLinear(subscip, &objcons, "objbound_of_origscip", 0, NULL, NULL, -SCIPinfinity(subscip), cutoff,
    2361 for( i = 0; i < nvars; ++i)
    2362 {
    2363 if( ! SCIPisFeasZero(subscip, SCIPvarGetObj(vars[i])) )
    2364 {
    2365 assert(subvars[i] != NULL);
    2366 SCIP_CALL( SCIPaddCoefLinear(subscip, objcons, subvars[i], SCIPvarGetObj(vars[i])) );
    2367 }
    2368 }
    2369 SCIP_CALL( SCIPaddCons(subscip, objcons) );
    2370 SCIP_CALL( SCIPreleaseCons(subscip, &objcons) );
    2371 }
    2372 }
    2373
    2374 /* set solve limits for sub-SCIP */
    2375 SCIP_CALL( setLimits(subscip, solvelimits) );
    2376
    2377 /* change random seed of sub-SCIP */
    2378 if( heurdata->subsciprandseeds )
    2379 {
    2380 SCIP_CALL( SCIPsetIntParam(subscip, "randomization/randomseedshift", (int)SCIPheurGetNCalls(heur)) );
    2381 }
    2382
    2383 return SCIP_OKAY;
    2384}
    2385
    2386/** initialize solving frequency */
    2387static
    2389 SOLVEFREQ* solvefreqdata /**< diving heuristic solving freq data */
    2390 )
    2391{
    2392 assert(solvefreqdata != NULL);
    2393
    2394 /* initialize solve frequency data */
    2395 solvefreqdata->increment = SOLVEFREQ_STARTINC;
    2396 solvefreqdata->maxsolvefreq = MAXSOLVEFREQ;
    2397 solvefreqdata->minsolvefreq = MINSOLVEFREQ;
    2398
    2399 /* always start with the most conservative value */
    2400 solvefreqdata->currentsolvefreq = solvefreqdata->minsolvefreq;
    2401}
    2402
    2403/** update increment for solving frequency */
    2404static
    2406 SOLVEFREQ* solvefreqdata /**< diving heuristic solving freq data */
    2407 )
    2408{
    2409 solvefreqdata->increment *= SOLVEFREQ_DECAY;
    2410 solvefreqdata->increment = MAX(solvefreqdata->increment, LRATEMIN);
    2411}
    2412
    2413/** increase solving frequency
    2414 *
    2415 * decrease also the rate by which the solving frequency is adjusted
    2416 */
    2417static
    2419 SOLVEFREQ* solvefreqdata /**< diving heuristic solving freq data */
    2420 )
    2421{
    2422 solvefreqdata->currentsolvefreq += solvefreqdata->increment;
    2423 solvefreqdata->currentsolvefreq = MIN(solvefreqdata->currentsolvefreq, solvefreqdata->maxsolvefreq);
    2424}
    2425
    2426/** decrease solving frequency
    2427 *
    2428 * decrease also the rate by which the solving frequency is adjusted
    2429 */
    2430static
    2432 SOLVEFREQ* solvefreqdata /**< diving heuristic solving freq data */
    2433 )
    2434{
    2435 solvefreqdata->currentsolvefreq -= solvefreqdata->increment;
    2436 solvefreqdata->currentsolvefreq = MAX(solvefreqdata->currentsolvefreq, solvefreqdata->minsolvefreq);
    2437}
    2438
    2439/** update solve frequency for diving heuristics */
    2440static
    2442 DIVING_HEUR* divingheur, /**< diving heuristic */
    2443 HEUR_STATS* stats /**< run statistics for this run */
    2444 )
    2445{
    2446 /* find out why diving heuristic terminated and adapt resolve frequency accordingly */
    2447 if( (int) stats->nprobnodes == divingheur->nodelimit )
    2448 increaseSolveFreq(divingheur->solvefreqdata);
    2449 else if( stats->nsolsfound == 0 )
    2450 decreaseSolveFreq(divingheur->solvefreqdata);
    2451
    2453}
    2454
    2455/** find publicly available divesets and store them */
    2456static
    2458 SCIP* scip, /**< SCIP data structure */
    2459 SCIP_HEUR* heur, /**< the heuristic */
    2460 SCIP_HEURDATA* heurdata /**< heuristic data */
    2461 )
    2462{
    2463 int h;
    2464 SCIP_HEUR** heurs;
    2465
    2466 assert(scip != NULL);
    2467 assert(heur != NULL);
    2468 assert(heurdata != NULL);
    2469
    2470 heurs = SCIPgetHeurs(scip);
    2471
    2472 heurdata->divingheurssize = DIVINGHEURS_INITIALSIZE;
    2473 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->divingheurs, heurdata->divingheurssize) );
    2474 heurdata->ndiving = 0;
    2475
    2476 for( h = 0; h < SCIPgetNHeurs(scip); ++h )
    2477 {
    2478 int d;
    2479 assert(heurs[h] != NULL);
    2480
    2481 /* loop over divesets of this heuristic and check whether they are public */
    2482 for( d = 0; d < SCIPheurGetNDivesets(heurs[h]); ++d )
    2483 {
    2484 SCIP_DIVESET* diveset = SCIPheurGetDivesets(heurs[h])[d];
    2485
    2486 if( SCIPdivesetIsPublic(diveset) )
    2487 {
    2488 DIVING_HEUR* divingheur;
    2489
    2490 SCIPdebugMsg(scip, "Found publicly available diveset %s\n", SCIPdivesetGetName(diveset));
    2491
    2492 /* allocate memory for the diving heuristic */
    2493 SCIP_CALL( SCIPallocBlockMemory(scip, &divingheur) );
    2494 SCIP_CALL( SCIPallocBlockMemory(scip, &(divingheur->stats)) );
    2496
    2497 /* fill struct with diving heuristic specific information */
    2498 divingheur->diveset = diveset;
    2499 divingheur->nodelimit = heurdata->initdivingnodelimit;
    2500 divingheur->rootnodepriority = SCIPheurGetPriority(heurs[h]);
    2501 divingheur->priority = 1.0;
    2502
    2503 initSolveFreq(divingheur->solvefreqdata);
    2504 SCIP_CALL( SCIPcreateClock(scip, &(divingheur->stats->setupclock)) );
    2505 SCIP_CALL( SCIPcreateClock(scip, &(divingheur->stats->execclock)) );
    2506 SCIP_CALL( heurStatsReset(scip, divingheur->stats, TRUE) );
    2507
    2508 if( heurdata->ndiving == heurdata->divingheurssize )
    2509 {
    2510 int newsize = 2 * heurdata->divingheurssize;
    2511 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &heurdata->divingheurs, heurdata->divingheurssize, newsize) );
    2512 heurdata->divingheurssize = newsize;
    2513 }
    2514 assert( heurdata->ndiving < heurdata->divingheurssize );
    2515
    2516 heurdata->divingheurs[heurdata->ndiving] = divingheur;
    2517 heurdata->ndiving++;
    2518 }
    2519 else
    2520 {
    2521 SCIPdebugMsg(scip, "Skipping private diveset %s\n", SCIPdivesetGetName(diveset));
    2522 }
    2523 }
    2524 }
    2525 return SCIP_OKAY;
    2526}
    2527
    2528/** select a heuristic depending on the selected bandit algorithm */
    2529static
    2531 SCIP* scip, /**< SCIP data structure */
    2532 SCIP_HEURDATA* heurdata, /**< heuristic data of the scheduler heuristic */
    2533 int* selection /**< pointer to store the selected heuristic index */
    2534 )
    2535{
    2536 SCIP_BANDIT* bandit;
    2537 int nactions;
    2538
    2539 assert(scip != NULL);
    2540 assert(heurdata != NULL);
    2541 assert(selection != NULL);
    2542
    2543 *selection = -1;
    2544 bandit = heurdata->bandit;
    2545 nactions = heurdata->ndiving + heurdata->nactiveneighborhoods;
    2546
    2547 /* if we use default priorities for executing heuristics for the first time, we don't have to call
    2548 * the bandit to select next action */
    2549 if( heurdata->defaultroot && heurdata->counter < nactions )
    2550 {
    2551 *selection = heurdata->sortedindices[heurdata->counter];
    2552 heurdata->counter++;
    2553 }
    2554 else
    2555 {
    2556 SCIP_CALL( SCIPbanditSelect(bandit, selection) );
    2557 }
    2558 assert(*selection >= 0);
    2559 assert(*selection < heurdata->nactiveneighborhoods + heurdata->ndiving);
    2560
    2561 return SCIP_OKAY;
    2562}
    2563
    2564/** update selection strategy with observed reward for future draws */
    2565static
    2567 SCIP* scip, /**< SCIP data structure */
    2568 SCIP_HEURDATA* heurdata, /**< heuristic data of the scheduler heuristic */
    2569 SCIP_Real reward, /**< measured reward */
    2570 int selection /**< the heuristic index that was chosen */
    2571 )
    2572{
    2573 SCIP_BANDIT* bandit;
    2574
    2575 assert(scip != NULL);
    2576 assert(heurdata != NULL);
    2577 assert(selection >= 0);
    2578 assert(selection < heurdata->nneighborhoods + heurdata->ndiving);
    2579
    2580 bandit = heurdata->bandit;
    2581
    2582 SCIPdebugMsg(scip, "Rewarding bandit algorithm action %d with reward %.2f\n", selection, reward);
    2583 SCIP_CALL( SCIPbanditUpdate(bandit, selection, reward) );
    2584
    2585 return SCIP_OKAY;
    2586}
    2587
    2588/** execute diving heuristic */
    2589static
    2591 SCIP* scip, /**< SCIP data structure */
    2592 SCIP_HEUR* heur, /**< scheduler heuristic */
    2593 int selection, /**< the heuristic index that was chosen */
    2594 HEUR_STATS* runstats, /**< statistics of the call to selection */
    2595 SCIP_RESULT* result /**< pointer to store the result of the heuristic call */
    2596 )
    2597{
    2598 SCIP_HEURDATA* heurdata;
    2599 DIVING_HEUR** divingheurs;
    2600 SCIP_DIVESET* diveset;
    2601
    2602 heurdata = SCIPheurGetData(heur);
    2603 assert(heurdata != NULL);
    2604
    2605 divingheurs = heurdata->divingheurs;
    2606 assert(divingheurs != NULL);
    2607 assert(heurdata->ndiving > 0);
    2608 assert(selection < heurdata->ndiving);
    2609 assert(divingheurs[selection] != NULL);
    2610
    2611 diveset = divingheurs[selection]->diveset;
    2612 assert(diveset != NULL);
    2613
    2614 SCIPdebugMsg(scip, "Selected diving heuristic %s (idx: %d)\n", SCIPdivesetGetName(diveset), selection);
    2615
    2616 /* store some data beforehand to track all improvemnts */
    2623
    2624 if( strcmp(SCIPdivesetGetName(diveset), "guideddiving") != 0 || (strcmp(SCIPdivesetGetName(diveset), "guideddiving") == 0
    2626 {
    2627 SCIP_CALL( SCIPstartClock(scip, divingheurs[selection]->stats->execclock) );
    2628
    2629 /* perform dive */
    2630 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, divingheurs[selection]->diveset, heurdata->sol, heur,
    2631 result, FALSE, -1LL, (int) divingheurs[selection]->nodelimit,
    2632 divingheurs[selection]->solvefreqdata->currentsolvefreq, SCIP_DIVECONTEXT_SCHEDULER) );
    2633
    2634 SCIP_CALL( SCIPstopClock(scip, divingheurs[selection]->stats->execclock) );
    2635 }
    2636
    2637 /* store improvements (if solution was found, what solution was found, nconflict constraints, etc.) */
    2641 runstats->nsolsfound = SCIPdivesetGetNSols(diveset, SCIP_DIVECONTEXT_SCHEDULER) - runstats->nsolsfound;
    2644
    2645 /* update maximum number of conflicts found */
    2646 heurdata->maxnconflicts = MAX(heurdata->maxnconflicts, (int) runstats->nconflicts);
    2647
    2648 SCIPdebugMsg(scip, "Finished executing diving heuristic %s (idx: %d) with %lld sols (%lld best sols), %lld conflicts, %lld backtracks and %lld probing nodes \n",
    2649 SCIPdivesetGetName(diveset), selection, runstats->nsolsfound, runstats->nbestsolsfound,
    2650 runstats->nconflicts, runstats->nbacktracks, runstats->nprobnodes);
    2651
    2652 if( runstats->nbestsolsfound > 0 )
    2653 SCIPdebugMsg(scip, "Upperbound changed: %g -> %g\n", runstats->oldupperbound, runstats->newupperbound);
    2654
    2655 assert( runstats->nbestsolsfound == 0 || runstats->oldupperbound > runstats->newupperbound );
    2656
    2657 return SCIP_OKAY;
    2658}
    2659
    2660/** execute LNS heuristic */
    2661static
    2663 SCIP* scip, /**< SCIP data structure */
    2664 SCIP_HEUR* heur, /**< scheduler heuristic */
    2665 int selection, /**< the heuristic index that was chosen */
    2666 HEUR_STATS* runstats, /**< statistics of the call to selection */
    2667 SCIP_STATUS* subscipstatus, /**< pointer to store status of the sub-SCIP solve */
    2668 SCIP_RESULT* result /**< pointer to store the result of the heuristic call */
    2669 )
    2670{
    2671 SCIP_HEURDATA* heurdata;
    2672 SCIP_VAR** varbuf;
    2673 SCIP_Real* valbuf;
    2674 SCIP_VAR** vars;
    2675 SCIP_VAR** subvars;
    2676 SCIP* subscip = NULL;
    2677
    2678 int nfixings;
    2679 int nvars;
    2680 NH* neighborhood;
    2681 SOLVELIMITS solvelimits;
    2682 SCIP_Bool success;
    2683 SCIP_Bool run;
    2684
    2685 SCIP_HASHMAP* varmapf;
    2686 SCIP_EVENTHDLR* eventhdlr;
    2687 SCIP_EVENTDATA eventdata;
    2688 char probnamesuffix[SCIP_MAXSTRLEN];
    2689 int ndomchgs;
    2690 int nchgobjs;
    2691 int naddedconss;
    2692 int v;
    2693 SCIP_RETCODE retcode;
    2694 SCIP_RESULT fixresult;
    2695
    2696 heurdata = SCIPheurGetData(heur);
    2697 assert(heurdata != NULL);
    2698
    2699 *result = SCIP_DIDNOTRUN;
    2700 *subscipstatus = SCIP_STATUS_UNKNOWN;
    2701 run = TRUE;
    2702
    2703 SCIPdebugMsg(scip, "Selected LNS heuristic %s (idx: %d)\n", heurdata->neighborhoods[selection]->name, selection + heurdata->ndiving);
    2704
    2705 /* check if budget allows a run of the next selected neighborhood */
    2706 SCIP_CALL( determineLimits(scip, heur, selection, &solvelimits, &run) );
    2707
    2708 if( ! run )
    2709 return SCIP_OKAY;
    2710
    2711 /* allocate memory for variable fixings buffer */
    2712 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    2713 SCIP_CALL( SCIPallocBufferArray(scip, &varbuf, nvars) );
    2714 SCIP_CALL( SCIPallocBufferArray(scip, &valbuf, nvars) );
    2715 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    2716
    2717 neighborhood = heurdata->neighborhoods[selection];
    2718 SCIPdebugMsg(scip, "Running '%s' neighborhood %d\n", neighborhood->name, selection);
    2719
    2720 SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.setupclock) );
    2721
    2722 /* determine variable fixings and objective coefficients of this neighborhood */
    2723 SCIP_CALL( neighborhoodFixVariables(scip, heurdata, neighborhood, varbuf, valbuf, &nfixings, &fixresult) );
    2724
    2725 SCIPdebugMsg(scip, "Fix %d/%d variables, result code %d\n", nfixings, nvars, fixresult);
    2726
    2727 /* Fixing was not successful, either because the fixing rate was not reached (and no additional variable
    2728 * prioritization was used), or the neighborhood requested a delay, e.g., because no LP relaxation solution exists
    2729 * at the current node
    2730 *
    2731 * The scheduler heuristic keeps a delayed neighborhood active and delays itself.
    2732 * TODO: handle delays
    2733 */
    2734 if( fixresult != SCIP_SUCCESS )
    2735 {
    2736 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
    2737
    2738 SCIPdebugMsg(scip, "Aborting LNS heuristic call: Not enough variables fixed.\n");
    2739
    2740 *result = fixresult;
    2741 goto CLEANUP;
    2742 }
    2743
    2744 *result = SCIP_DIDNOTFIND;
    2745
    2746 neighborhood->stats.nfixings += nfixings;
    2747 runstats->nfixings = nfixings;
    2748
    2749 SCIP_CALL( SCIPcreate(&subscip) );
    2750 SCIP_CALL( SCIPhashmapCreate(&varmapf, SCIPblkmem(scip), nvars) );
    2751 (void) SCIPsnprintf(probnamesuffix, SCIP_MAXSTRLEN, "scheduler_%s", neighborhood->name);
    2752
    2753 /* todo later: run global propagation for this set of fixings */
    2754 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapf, probnamesuffix, varbuf, valbuf, nfixings, FALSE, heurdata->copycuts, &success, NULL) );
    2755
    2756 /* store sub-SCIP variables in array for faster access */
    2757 for( v = 0; v < nvars; ++v )
    2758 {
    2759 subvars[v] = (SCIP_VAR*)SCIPhashmapGetImage(varmapf, (void *)vars[v]);
    2760 }
    2761
    2762 SCIPhashmapFree(&varmapf);
    2763
    2764 /* let the neighborhood add additional constraints, or restrict domains */
    2765 SCIP_CALL( neighborhoodChangeSubscip(scip, subscip, neighborhood, subvars, &ndomchgs, &nchgobjs, &naddedconss, &success) );
    2766
    2767 if( ! success )
    2768 {
    2769 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
    2770 SCIPdebugMsg(scip, "Aborting LNS heuristic call: Problems with creating subproblem.\n");
    2771 goto CLEANUP;
    2772 }
    2773
    2774 /* set up sub-SCIP parameters */
    2775 SCIP_CALL( setupSubScip(scip, subscip, subvars, &solvelimits, heur, nchgobjs > 0) );
    2776
    2777 /* copy the necessary data into the event data to create new solutions */
    2778 eventdata.nodelimit = solvelimits.nodelimit; /*lint !e644*/
    2779 eventdata.lplimfac = heurdata->lplimfac;
    2780 eventdata.heur = heur;
    2781 eventdata.sourcescip = scip;
    2782 eventdata.subvars = subvars;
    2783 eventdata.runstats = runstats;
    2784
    2785 /* include an event handler to transfer solutions into the main SCIP */
    2786 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecScheduler, NULL) );
    2787
    2788 /* transform the problem before catching the events */
    2789 SCIP_CALL( SCIPtransformProb(subscip) );
    2790 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_SCHEDULER, eventhdlr, &eventdata, NULL) );
    2791
    2792 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
    2793
    2794 SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.execclock) );
    2795
    2796 /* set up sub-SCIP and run presolving */
    2797 retcode = SCIPpresolve(subscip);
    2798 if( retcode != SCIP_OKAY )
    2799 {
    2800 SCIPwarningMessage(scip, "Error while presolving subproblem in Scheduler heuristic; sub-SCIP terminated with code <%d>\n", retcode);
    2801 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.execclock) );
    2802
    2803 SCIPABORT(); /*lint --e{527}*/
    2804 goto CLEANUP;
    2805 }
    2806
    2807 /* run sub-SCIP for the given budget, and collect statistics */
    2808 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    2809
    2810#ifdef SCHEDULER_SUBSCIPOUTPUT
    2811 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2812#endif
    2813
    2814 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.execclock) );
    2815
    2816 /* update statistics based on the sub-SCIP run results */
    2817 updateRunStats(runstats, subscip);
    2818 *subscipstatus = SCIPgetStatus(subscip);
    2819 SCIPdebugMsg(scip, "Status of sub-SCIP run: %d\n", *subscipstatus);
    2820
    2821CLEANUP:
    2822 if( subscip != NULL )
    2823 {
    2824 SCIP_CALL( SCIPfree(&subscip) );
    2825 }
    2826
    2827 SCIPfreeBufferArray(scip, &subvars);
    2828 SCIPfreeBufferArray(scip, &valbuf);
    2829 SCIPfreeBufferArray(scip, &varbuf);
    2830
    2831 if( *result != SCIP_DELAYED && *result != SCIP_DIDNOTRUN )
    2832 {
    2833 /* decrease the number of neighborhoods that have not been initialized */
    2834 if( neighborhood->stats.nruns == 0 )
    2835 --heurdata->ninitneighborhoods;
    2836
    2837 heurdata->usednodes += runstats->usednodes;
    2838
    2839 SCIPdebugMsg(scip, "Finished executing LNS heuristic %s (idx: %d) with %lld sols (%lld best sols) and %lld nodes used.\n",
    2840 neighborhood->name, selection + heurdata->ndiving, runstats->nsolsfound, runstats->nbestsolsfound, runstats->usednodes);
    2841
    2842 if( runstats->nbestsolsfound > 0 )
    2843 SCIPdebugMsg(scip, "Upperbound changed: %g -> %g\n", runstats->oldupperbound, SCIPgetUpperbound(scip));
    2844
    2845 resetCurrentNeighborhood(heurdata);
    2846 }
    2847
    2848 return SCIP_OKAY;
    2849}
    2850
    2851/** execute selected heuristic */
    2852static
    2854 SCIP* scip, /**< SCIP data structure */
    2855 SCIP_HEUR* heur, /**< scheduler heuristic */
    2856 int selection, /**< the heuristic index that was chosen */
    2857 HEUR_STATS* runstats, /**< statistics of call to selection */
    2858 SCIP_STATUS* subscipstatus, /**< pointer to store status of the sub-SCIP solve or NULL if diving was used */
    2859 SCIP_RESULT* result /**< pointer to store the result of the heuristic call */
    2860 )
    2861{
    2862 SCIP_HEURDATA* heurdata;
    2863
    2864 heurdata = SCIPheurGetData(heur);
    2865 assert(heurdata != NULL);
    2866 assert(scip != NULL);
    2867 assert(selection >= 0);
    2868 assert(selection < heurdata->nneighborhoods + heurdata->ndiving);
    2869
    2870 /* check if a diving or LNS heuristic was selected */
    2871 if( selection < heurdata->ndiving )
    2872 {
    2873 SCIP_CALL( executeDivingHeuristic(scip, heur, selection, runstats, result) );
    2874 }
    2875 else
    2876 {
    2877 SCIP_CALL( executeLNSHeuristic(scip, heur, selection - heurdata->ndiving, runstats, subscipstatus, result) );
    2878 }
    2879
    2880 return SCIP_OKAY;
    2881}
    2882
    2883/** reinitialize bandit algorithm since the number of actions has changed */
    2884static
    2886 SCIP* scip, /**< SCIP data structure */
    2887 SCIP_HEURDATA* heurdata, /**< heuristic data */
    2888 int nactions /**< new number of actions */
    2889 )
    2890{
    2891 SCIP_Real* priorities;
    2892 int i;
    2893 unsigned int initseed;
    2894
    2895 /* allocate memory for the priorities */
    2896 SCIP_CALL( SCIPallocBufferArray(scip, &priorities, nactions) );
    2897
    2898 /* get the priorities */
    2899 for( i = 0; i < heurdata->ndiving; ++i )
    2900 priorities[i] = heurdata->divingheurs[i]->priority;
    2901 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
    2902 priorities[i + heurdata->ndiving] = heurdata->neighborhoods[i]->priority;
    2903
    2904 /* free bandit if necessary */
    2905 if( heurdata->bandit != NULL )
    2906 {
    2907 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
    2908 heurdata->bandit = NULL;
    2909 }
    2910
    2911 /* create bandit again */
    2912 initseed = (unsigned int)(heurdata->seed + SCIPgetNVars(scip));
    2913 SCIP_CALL( createBandit(scip, heurdata, priorities, initseed) );
    2914 resetTargetNodeLimit(heurdata);
    2915
    2916 /* free memory */
    2917 SCIPfreeBufferArray(scip, &priorities);
    2918
    2919 return SCIP_OKAY;
    2920}
    2921
    2922/** initializes everything that was missing because diving heuristics were not proccessed by SCIP yet. In particular,
    2923 * the function adds diving heuristics to heurdata, heurdata->maxdivingnodelimit,
    2924 * heurdata->maxlnsnodelimit and heurdata->sortedindices if heurdata->defaultroot is set to TRUE
    2925 */
    2926static
    2928 SCIP* scip, /**< SCIP data structure */
    2929 SCIP_HEUR* heur /**< scheduler heuristic */
    2930 )
    2931{
    2932 SCIP_HEURDATA* heurdata;
    2933 SCIP_Real* priorities;
    2934 int nheurs;
    2935 int i;
    2936
    2937 /* get heuristic data */
    2938 heurdata = SCIPheurGetData(heur);
    2939
    2940 /* include the diving heuristics */
    2941 SCIP_CALL( includeDivingHeurs(scip, heur, heurdata) );
    2942
    2943 /* get number of active heuristics we can choose from */
    2944 nheurs = heurdata->ndiving + heurdata->nactiveneighborhoods;
    2945
    2946 /* we need to initialize the bandit method again since the number of actions has changed */
    2947 SCIP_CALL( reinitBandit(scip, heurdata, nheurs) );
    2948
    2949 /* set maximum of all node and diving depth limit */
    2950 heurdata->maxdivingnodelimit = heurdata->initdivingnodelimit;
    2951 heurdata->maxlnsnodelimit = heurdata->initlnsnodelimit;
    2952
    2953 /* initialize nodelimit for all LNS heursitics */
    2954 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
    2955 heurdata->neighborhoods[i]->nodelimit = heurdata->initlnsnodelimit;
    2956
    2957 /* initialize indices array and sort according to heuristic's priorities if we want to execute heuristics in default order
    2958 * at the root node*/
    2959 if( heurdata->defaultroot )
    2960 {
    2961 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->sortedindices, heurdata->ndiving + heurdata->nneighborhoods) );
    2962 SCIP_CALL( SCIPallocBufferArray(scip, &priorities, nheurs) );
    2963 heurdata->counter = 0;
    2964
    2965 for( i = 0; i < nheurs; ++i )
    2966 {
    2967 heurdata->sortedindices[i] = i;
    2968
    2969 if( i < heurdata->ndiving )
    2970 priorities[i] = (SCIP_Real)-heurdata->divingheurs[i]->rootnodepriority;
    2971 else
    2972 priorities[i] = (SCIP_Real)-heurdata->neighborhoods[i - heurdata->ndiving]->rootnodepriority;
    2973 }
    2974
    2975 /* sort indices */
    2976 SCIPsortRealInt(priorities, heurdata->sortedindices, nheurs);
    2977
    2978 SCIPfreeBufferArray(scip, &priorities);
    2979 }
    2980
    2981 return SCIP_OKAY;
    2982}
    2983
    2984/** execution method of primal heuristic */
    2985static
    2986SCIP_DECL_HEUREXEC(heurExecScheduler)
    2987{ /*lint --e{715}*/
    2988 SCIP_HEURDATA* heurdata;
    2989 SCIP_Bool success;
    2990
    2991 assert(heur != NULL);
    2992 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    2993 assert(scip != NULL);
    2994 assert(result != NULL);
    2995
    2996 /* get heuristic data */
    2997 heurdata = SCIPheurGetData(heur);
    2998
    2999 SCIPdebugMsg(scip, "Calling heurExecScheduler: depth %d sols %d inf %u node %lld \n",
    3000 SCIPgetDepth(scip), SCIPgetNSols(scip), nodeinfeasible, SCIPgetNNodes(scip));
    3001
    3002 /* store diving heuristics if not done already and reset stats */
    3003 if( heurdata->divingheurs == NULL )
    3004 {
    3005 SCIP_CALL( initRest(scip, heur) );
    3006 }
    3007 assert( heurdata->divingheurs != NULL );
    3008
    3009 *result = SCIP_DELAYED;
    3010
    3011 /* do not call heuristic in node that was already detected to be infeasible */
    3012 if( nodeinfeasible )
    3013 return SCIP_OKAY;
    3014
    3015 /* only call heuristic, if an optimal LP solution is at hand */
    3017 return SCIP_OKAY;
    3018
    3019 /* only call heuristic, if the LP objective value is smaller than the cutoff bound */
    3021 return SCIP_OKAY;
    3022
    3023 /* only call heuristic, if the LP solution is basic (which allows fast resolve in diving) */
    3024 if( !SCIPisLPSolBasic(scip) )
    3025 return SCIP_OKAY;
    3026
    3027 /* update internal incumbent solution */
    3028 if( SCIPgetBestSol(scip) != heurdata->lastcallsol )
    3029 {
    3030 heurdata->lastcallsol = SCIPgetBestSol(scip);
    3031 heurdata->firstcallthissol = SCIPheurGetNCalls(heur);
    3032 }
    3033
    3034 /* do not run more than a user-defined number of times on each incumbent (-1: no limit) */
    3035 if( heurdata->maxcallssamesol != -1 )
    3036 {
    3037 SCIP_Longint samesollimit;
    3038
    3039 /* either it is the user-defined limit or the number of heuristics controlled by the scheduler */
    3040 samesollimit = (heurdata->maxcallssamesol > 0) ? heurdata->maxcallssamesol : (SCIP_Longint) heurdata->nneighborhoods + heurdata->ndiving;
    3041
    3042 if( SCIPheurGetNCalls(heur) - heurdata->firstcallthissol >= samesollimit )
    3043 {
    3044 SCIPdebugMsg(scip, "Heuristic already called %" SCIP_LONGINT_FORMAT " times on current incumbent\n", SCIPheurGetNCalls(heur) - heurdata->firstcallthissol);
    3045 return SCIP_OKAY;
    3046 }
    3047 }
    3048
    3049 /* wait for a sufficient number of nodes since last incumbent solution */
    3050 if( SCIPgetDepth(scip) > 0 && SCIPgetBestSol(scip) != NULL
    3051 && (SCIPgetNNodes(scip) - SCIPsolGetNodenum(SCIPgetBestSol(scip))) < heurdata->waitingnodes )
    3052 {
    3053 SCIPdebugMsg(scip, "Waiting nodes not satisfied\n");
    3054 return SCIP_OKAY;
    3055 }
    3056
    3057 /* skip this call if scheduler was too unsuccessful in the past few calls */
    3058 if( heurdata->nskippedcalls > 0 )
    3059 {
    3060 /* reduce counter because we need to skip one call less now */
    3061 heurdata->nskippedcalls--;
    3062
    3063 return SCIP_OKAY;
    3064 }
    3065 else
    3066 {
    3067 /* check if we need to skip calls in the future */
    3068 heurdata->nskippedcalls = (int) floor(exp(0.1 * (SCIP_Real) heurdata->nfailedcalls)) - 1;
    3069 }
    3070
    3071 *result = SCIP_DIDNOTRUN;
    3072 success = FALSE;
    3073 {
    3074 int selection;
    3075 SCIP_Real reward;
    3076 HEUR_STATS* stats;
    3077 SCIP_STATUS subscipstatus;
    3078
    3079 subscipstatus = SCIP_STATUS_UNKNOWN;
    3080
    3081 /* allocate memory for statistics and initialize it */
    3082 SCIP_CALL( SCIPallocBuffer(scip, &stats) );
    3083 initRunStats(scip, stats);
    3084
    3085 /* select the heuristic based on previous success. The heuristics are sorted such that
    3086 * diving comes before LNS */
    3087 SCIP_CALL( selectHeuristic(scip, heurdata, &selection) );
    3088
    3089 /* execute selected heuristic */
    3090 SCIP_CALL( executeHeuristic(scip, heur, selection, stats, &subscipstatus, result) );
    3091
    3092 /* update global statistics */
    3093 if( selection < heurdata->ndiving ) /* diving was selected */
    3094 updateHeurStatsDiving(stats, heurdata->divingheurs[selection]);
    3095 else /* LNS was selected */
    3096 updateHeurStatsLNS(stats, heurdata->neighborhoods[selection - heurdata->ndiving], &subscipstatus);
    3097
    3098 /* observe reward */
    3099 reward = getReward(scip, heurdata, selection, stats);
    3100
    3101 /* call was successfull if solution was found */
    3102 if( stats->nbestsolsfound > 0 )
    3103 success = TRUE;
    3104
    3105 /* update either LP resolve freq or target fixing rate, depending on which heuristic was chosen */
    3106 if( selection < heurdata->ndiving )
    3107 {
    3108 /* update resolve freq */
    3109 updateSolveFreq(heurdata->divingheurs[selection], stats);
    3110 }
    3111 else
    3112 {
    3113 /* update target fixing rate */
    3114 SCIPdebugMsg(scip, "Update fixing rate: %.2f\n", heurdata->neighborhoods[selection - heurdata->ndiving]->fixingrate.targetfixingrate);
    3115 updateFixingRate(heurdata->neighborhoods[selection - heurdata->ndiving], subscipstatus, stats);
    3116 SCIPdebugMsg(scip, "New fixing rate: %.2f\n", heurdata->neighborhoods[selection - heurdata->ndiving]->fixingrate.targetfixingrate);
    3117 }
    3118
    3119 /* update selection strategy */
    3120 SCIP_CALL( updateSelectionStrategy(scip, heurdata, reward, selection) );
    3121
    3122 /* free statistics data struct */
    3123 SCIPfreeBuffer(scip, &stats);
    3124 }
    3125
    3126 /* count how many consecutive failed calls we had */
    3127 if( success )
    3128 heurdata->nfailedcalls = 0;
    3129 else
    3130 heurdata->nfailedcalls++;
    3131
    3132 return SCIP_OKAY;
    3133}
    3134
    3135/** callback to collect variable fixings of RENS */
    3136static
    3137DECL_VARFIXINGS(varFixingsRens)
    3138{ /*lint --e{715}*/
    3139 int nbinvars;
    3140 int nintvars;
    3141 SCIP_VAR** vars;
    3142 int i;
    3143 int *fracidx = NULL;
    3144 SCIP_Real* frac = NULL;
    3145 int nfracs;
    3146
    3147 assert(scip != NULL);
    3148 assert(varbuf != NULL);
    3149 assert(nfixings != NULL);
    3150 assert(valbuf != NULL);
    3151
    3152 *result = SCIP_DELAYED;
    3153
    3154 if( ! SCIPhasCurrentNodeLP(scip) )
    3155 return SCIP_OKAY;
    3157 return SCIP_OKAY;
    3158
    3159 *result = SCIP_DIDNOTRUN;
    3160
    3161 /* get variable information */
    3162 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3163
    3164 /* return if no binary or integer variables are present */
    3165 if( nbinvars + nintvars == 0 )
    3166 return SCIP_OKAY;
    3167
    3168 SCIP_CALL( SCIPallocBufferArray(scip, &fracidx, nbinvars + nintvars) );
    3169 SCIP_CALL( SCIPallocBufferArray(scip, &frac, nbinvars + nintvars) );
    3170
    3171 /* loop over binary and integer variables; determine those that should be fixed in the sub-SCIP */
    3172 for( nfracs = 0, i = 0; i < nbinvars + nintvars; ++i )
    3173 {
    3174 SCIP_VAR* var = vars[i];
    3175 SCIP_Real lpsolval = SCIPvarGetLPSol(var);
    3176 assert((i < nbinvars && SCIPvarIsBinary(var)) || (i >= nbinvars && SCIPvarIsIntegral(var)));
    3177
    3178 /* fix all binary and integer variables with integer LP solution value */
    3179 if( SCIPisFeasIntegral(scip, lpsolval) )
    3180 {
    3181 tryAdd2variableBuffer(scip, var, lpsolval, varbuf, valbuf, nfixings, TRUE);
    3182 }
    3183 else
    3184 {
    3185 frac[nfracs] = SCIPfrac(scip, lpsolval);
    3186 frac[nfracs] = MIN(frac[nfracs], 1.0 - frac[nfracs]);
    3187 fracidx[nfracs++] = i;
    3188 }
    3189 }
    3190
    3191 /* do some additional fixing */
    3192 if( *nfixings < neighborhood->fixingrate.targetfixingrate * (nbinvars + nintvars) && nfracs > 0 )
    3193 {
    3194 SCIPsortDownRealInt(frac, fracidx, nfracs);
    3195
    3196 /* prefer variables that are almost integer */
    3197 for( i = 0; i < nfracs && *nfixings < neighborhood->fixingrate.targetfixingrate * (nbinvars + nintvars); i++ )
    3198 {
    3199 tryAdd2variableBuffer(scip, vars[fracidx[i]], SCIPround(scip, SCIPvarGetLPSol(vars[fracidx[i]])), varbuf, valbuf, nfixings, TRUE);
    3200 }
    3201 }
    3202
    3203 SCIPfreeBufferArray(scip, &frac);
    3204 SCIPfreeBufferArray(scip, &fracidx);
    3205
    3206 *result = SCIP_SUCCESS;
    3207
    3208 return SCIP_OKAY;
    3209}
    3210
    3211/** callback for RENS subproblem changes */
    3212static
    3213DECL_CHANGESUBSCIP(changeSubscipRens)
    3214{ /*lint --e{715}*/
    3215 SCIP_VAR** vars;
    3216 int nintvars;
    3217 int nbinvars;
    3218 int i;
    3219
    3220 assert(SCIPhasCurrentNodeLP(sourcescip));
    3221 assert(SCIPgetLPSolstat(sourcescip) == SCIP_LPSOLSTAT_OPTIMAL);
    3222
    3223 /* get variable information */
    3224 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3225
    3226 /* restrict bounds of integer variables with fractional solution value */
    3227 for( i = nbinvars; i < nbinvars + nintvars; ++i )
    3228 {
    3229 SCIP_VAR* var = vars[i];
    3230 SCIP_Real lpsolval = SCIPgetSolVal(sourcescip, NULL, var);
    3231
    3232 if( subvars[i] == NULL )
    3233 continue;
    3234
    3235 if( ! SCIPisFeasIntegral(sourcescip, lpsolval) )
    3236 {
    3237 SCIP_Real newlb = SCIPfloor(sourcescip, lpsolval);
    3238 SCIP_Real newub = newlb + 1.0;
    3239
    3240 /* only count this as a domain change if the new lower and upper bound are a further restriction */
    3241 if( newlb > SCIPvarGetLbGlobal(subvars[i]) + 0.5 || newub < SCIPvarGetUbGlobal(subvars[i]) - 0.5 )
    3242 {
    3243 SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[i], newlb) );
    3244 SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[i], newub) );
    3245 (*ndomchgs)++;
    3246 }
    3247 }
    3248 }
    3249
    3250 *success = TRUE;
    3251
    3252 return SCIP_OKAY;
    3253}
    3254
    3255/** collect fixings by matching solution values in a collection of solutions for all binary and integer variables,
    3256 * or for a custom set of variables
    3257 */
    3258static
    3260 SCIP* scip, /**< SCIP data structure */
    3261 SCIP_SOL** sols, /**< array of 2 or more solutions. It is okay for the array to contain one element
    3262 * equal to NULL to represent the current LP solution */
    3263 int nsols, /**< number of solutions in the array */
    3264 SCIP_VAR** vars, /**< variable array for which solution values must agree */
    3265 int nvars, /**< number of variables, or -1 for all binary and integer variables */
    3266 SCIP_VAR** varbuf, /**< buffer storage for variable fixings */
    3267 SCIP_Real* valbuf, /**< buffer storage for fixing values */
    3268 int* nfixings /**< pointer to store the number of fixings */
    3269 )
    3270{
    3271 int v;
    3272 int nbinintvars;
    3273 SCIP_SOL* firstsol;
    3274
    3275 assert(scip != NULL);
    3276 assert(sols != NULL);
    3277 assert(nsols >= 2);
    3278 assert(varbuf != NULL);
    3279 assert(valbuf != NULL);
    3280 assert(nfixings != NULL);
    3281 assert(*nfixings == 0);
    3282
    3283 if( nvars == -1 || vars == NULL )
    3284 {
    3285 int nbinvars;
    3286 int nintvars;
    3287 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3288 nbinintvars = nbinvars + nintvars;
    3289 nvars = nbinintvars;
    3290 }
    3291 firstsol = sols[0];
    3292 assert(nvars > 0);
    3293
    3294 /* loop over integer and binary variables and check if their solution values match in all solutions */
    3295 for( v = 0; v < nvars; ++v )
    3296 {
    3297 SCIP_Real solval;
    3298 SCIP_VAR* var;
    3299 int s;
    3300
    3301 var = vars[v];
    3302 assert((v < SCIPgetNBinVars(scip) && SCIPvarIsBinary(var)) || (v >= SCIPgetNBinVars(scip) && SCIPvarIsIntegral(var)));
    3303 solval = SCIPgetSolVal(scip, firstsol, var);
    3304
    3305 /* determine if solution values match in all given solutions */
    3306 for( s = 1; s < nsols; ++s )
    3307 {
    3308 SCIP_Real solval2 = SCIPgetSolVal(scip, sols[s], var);
    3309 if( ! SCIPisEQ(scip, solval, solval2) )
    3310 break;
    3311 }
    3312
    3313 /* if we did not break early, all solutions agree on the solution value of this variable */
    3314 if( s == nsols )
    3315 {
    3316 tryAdd2variableBuffer(scip, var, solval, varbuf, valbuf, nfixings, TRUE);
    3317 }
    3318 }
    3319
    3320 return SCIP_OKAY;
    3321}
    3322
    3323/** callback to collect variable fixings of RINS */
    3324static
    3325DECL_VARFIXINGS(varFixingsRins)
    3326{
    3327 /*lint --e{715}*/
    3328 int nbinvars;
    3329 int nintvars;
    3330 SCIP_VAR** vars;
    3331 SCIP_SOL* incumbent;
    3332 SCIP_SOL* sols[2];
    3333 assert(scip != NULL);
    3334 assert(varbuf != NULL);
    3335 assert(nfixings != NULL);
    3336 assert(valbuf != NULL);
    3337
    3338 *result = SCIP_DELAYED;
    3339
    3340 if( ! SCIPhasCurrentNodeLP(scip) )
    3341 return SCIP_OKAY;
    3343 return SCIP_OKAY;
    3344
    3345 *result = SCIP_DIDNOTRUN;
    3346
    3347 incumbent = SCIPgetBestSol(scip);
    3348 if( incumbent == NULL )
    3349 return SCIP_OKAY;
    3350
    3351 if( SCIPsolGetOrigin(incumbent) == SCIP_SOLORIGIN_ORIGINAL )
    3352 return SCIP_OKAY;
    3353
    3354 /* get variable information */
    3355 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3356
    3357 /* return if no binary or integer variables are present */
    3358 if( nbinvars + nintvars == 0 )
    3359 return SCIP_OKAY;
    3360
    3361 sols[0] = NULL;
    3362 sols[1] = incumbent;
    3363
    3364 SCIP_CALL( fixMatchingSolutionValues(scip, sols, 2, vars, nbinvars + nintvars, varbuf, valbuf, nfixings) );
    3365
    3366 *result = SCIP_SUCCESS;
    3367
    3368 return SCIP_OKAY;
    3369}
    3370
    3371/** initialization callback for crossover when a new problem is read */
    3372static
    3373DECL_NHINIT(nhInitCrossover)
    3374{ /*lint --e{715}*/
    3375 DATA_CROSSOVER* data;
    3376
    3377 data = neighborhood->data.crossover;
    3378 assert(data != NULL);
    3379
    3380 if( data->rng != NULL )
    3381 SCIPfreeRandom(scip, &data->rng);
    3382
    3383 data->selsol = NULL;
    3384
    3385 SCIP_CALL( SCIPcreateRandom(scip, &data->rng, CROSSOVERSEED + (unsigned int)SCIPgetNVars(scip), TRUE) );
    3386
    3387 return SCIP_OKAY;
    3388}
    3389
    3390/** deinitialization callback for crossover when exiting a problem */
    3391static
    3392DECL_NHEXIT(nhExitCrossover)
    3393{ /*lint --e{715}*/
    3394 DATA_CROSSOVER* data;
    3395 data = neighborhood->data.crossover;
    3396
    3397 assert(neighborhood != NULL);
    3398 assert(data->rng != NULL);
    3399
    3400 SCIPfreeRandom(scip, &data->rng);
    3401
    3402 return SCIP_OKAY;
    3403}
    3404
    3405/** deinitialization callback for crossover before SCIP is freed */
    3406static
    3407DECL_NHFREE(nhFreeCrossover)
    3408{ /*lint --e{715}*/
    3409 assert(neighborhood->data.crossover != NULL);
    3410 SCIPfreeBlockMemory(scip, &neighborhood->data.crossover);
    3411
    3412 return SCIP_OKAY;
    3413}
    3414
    3415/** callback to collect variable fixings of crossover */
    3416static
    3417DECL_VARFIXINGS(varFixingsCrossover)
    3418{ /*lint --e{715}*/
    3419 DATA_CROSSOVER* data;
    3420 SCIP_RANDNUMGEN* rng;
    3421 SCIP_SOL** sols;
    3422 SCIP_SOL** scipsols;
    3423 int nsols;
    3424 int lastdraw;
    3425 assert(scip != NULL);
    3426 assert(varbuf != NULL);
    3427 assert(nfixings != NULL);
    3428 assert(valbuf != NULL);
    3429
    3430 data = neighborhood->data.crossover;
    3431
    3432 assert(data != NULL);
    3433 nsols = data->nsols;
    3434 data->selsol = NULL;
    3435
    3436 *result = SCIP_DIDNOTRUN;
    3437
    3438 /* return if the pool has not enough solutions */
    3439 if( nsols > SCIPgetNSols(scip) )
    3440 return SCIP_OKAY;
    3441
    3442 /* return if no binary or integer variables are present */
    3444 return SCIP_OKAY;
    3445
    3446 rng = data->rng;
    3447 lastdraw = SCIPgetNSols(scip);
    3448 SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
    3449 scipsols = SCIPgetSols(scip);
    3450
    3451 /* draw as many solutions from the pool as required by crossover, biased towards
    3452 * better solutions; therefore, the sorting of the solutions by objective is implicitly used
    3453 */
    3454 while( nsols > 0 )
    3455 {
    3456 /* no need for randomization anymore, exactly nsols many solutions remain for the selection */
    3457 if( lastdraw == nsols )
    3458 {
    3459 int s;
    3460
    3461 /* fill the remaining slots 0,...,nsols - 1 by the solutions at the same places */
    3462 for( s = 0; s < nsols; ++s )
    3463 sols[s] = scipsols[s];
    3464
    3465 nsols = 0;
    3466 }
    3467 else
    3468 {
    3469 int nextdraw;
    3470
    3471 assert(nsols < lastdraw);
    3472
    3473 /* draw from the lastdraw - nsols many solutions nsols - 1, ... lastdraw - 1 such that nsols many solution */
    3474 nextdraw = SCIPrandomGetInt(rng, nsols - 1, lastdraw - 1);
    3475 assert(nextdraw >= 0);
    3476
    3477 sols[nsols - 1] = scipsols[nextdraw];
    3478 nsols--;
    3479 lastdraw = nextdraw;
    3480 }
    3481 }
    3482
    3483 SCIP_CALL( fixMatchingSolutionValues(scip, sols, data->nsols, NULL, -1, varbuf, valbuf, nfixings) );
    3484
    3485 /* store best selected solution as reference solution */
    3486 data->selsol = sols[0];
    3487 assert(data->selsol != NULL);
    3488
    3489 *result = SCIP_SUCCESS;
    3490
    3491 SCIPfreeBufferArray(scip, &sols);
    3492
    3493 return SCIP_OKAY;
    3494}
    3495
    3496/** callback for crossover reference solution */
    3497static
    3498DECL_NHREFSOL(nhRefsolCrossover)
    3499{ /*lint --e{715}*/
    3500 DATA_CROSSOVER* data;
    3501
    3502 data = neighborhood->data.crossover;
    3503
    3504 if( data->selsol != NULL )
    3505 {
    3506 *solptr = data->selsol;
    3507 *result = SCIP_SUCCESS;
    3508 }
    3509 else
    3510 {
    3511 *result = SCIP_DIDNOTFIND;
    3512 }
    3513
    3514 return SCIP_OKAY;
    3515}
    3516
    3517/** initialization callback for mutation when a new problem is read */
    3518static
    3519DECL_NHINIT(nhInitMutation)
    3520{ /*lint --e{715}*/
    3521 DATA_MUTATION* data;
    3522 assert(scip != NULL);
    3523 assert(neighborhood != NULL);
    3524
    3525 SCIP_CALL( SCIPallocBlockMemory(scip, &neighborhood->data.mutation) );
    3526
    3527 data = neighborhood->data.mutation;
    3528 assert(data != NULL);
    3529
    3530 SCIP_CALL( SCIPcreateRandom(scip, &data->rng, MUTATIONSEED + (unsigned int)SCIPgetNVars(scip), TRUE) );
    3531
    3532 return SCIP_OKAY;
    3533}
    3534
    3535/** deinitialization callback for mutation when exiting a problem */
    3536static
    3537DECL_NHEXIT(nhExitMutation)
    3538{ /*lint --e{715}*/
    3539 DATA_MUTATION* data;
    3540 assert(scip != NULL);
    3541 assert(neighborhood != NULL);
    3542 data = neighborhood->data.mutation;
    3543 assert(data != NULL);
    3544
    3545 SCIPfreeRandom(scip, &data->rng);
    3546
    3547 SCIPfreeBlockMemory(scip, &neighborhood->data.mutation);
    3548
    3549 return SCIP_OKAY;
    3550}
    3551
    3552/** callback to collect variable fixings of mutation */
    3553static
    3554DECL_VARFIXINGS(varFixingsMutation)
    3555{ /*lint --e{715}*/
    3556 SCIP_RANDNUMGEN* rng;
    3557
    3558 SCIP_VAR** vars;
    3559 SCIP_VAR** varscpy;
    3560 int i;
    3561 int nvars;
    3562 int nbinvars;
    3563 int nintvars;
    3564 int nbinintvars;
    3565 int ntargetfixings;
    3566 SCIP_SOL* incumbentsol;
    3567 SCIP_Real targetfixingrate;
    3568
    3569 assert(scip != NULL);
    3570 assert(neighborhood != NULL);
    3571 assert(neighborhood->data.mutation != NULL);
    3572 assert(neighborhood->data.mutation->rng != NULL);
    3573 rng = neighborhood->data.mutation->rng;
    3574
    3575 *result = SCIP_DIDNOTRUN;
    3576
    3577 /* get the problem variables */
    3578 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    3579
    3580 nbinintvars = nbinvars + nintvars;
    3581 if( nbinintvars == 0 )
    3582 return SCIP_OKAY;
    3583
    3584 incumbentsol = SCIPgetBestSol(scip);
    3585 if( incumbentsol == NULL )
    3586 return SCIP_OKAY;
    3587
    3588 targetfixingrate = neighborhood->fixingrate.targetfixingrate;
    3589 ntargetfixings = (int)(targetfixingrate * nbinintvars) + 1;
    3590
    3591 /* don't continue if number of discrete variables is too small to reach target fixing rate */
    3592 if( nbinintvars <= ntargetfixings )
    3593 return SCIP_OKAY;
    3594
    3595 *result = SCIP_DIDNOTFIND;
    3596
    3597 /* copy variables into a buffer array */
    3598 SCIP_CALL( SCIPduplicateBufferArray(scip, &varscpy, vars, nbinintvars) );
    3599
    3600 /* partially perturb the array until the number of target fixings is reached */
    3601 for( i = 0; *nfixings < ntargetfixings && i < nbinintvars; ++i )
    3602 {
    3603 int randint = SCIPrandomGetInt(rng, i, nbinintvars - 1);
    3604 assert(randint < nbinintvars);
    3605
    3606 if( randint > i )
    3607 {
    3608 SCIPswapPointers((void**)&varscpy[i], (void**)&varscpy[randint]);
    3609 }
    3610 /* copy the selected variables and their solution values into the buffer */
    3611 tryAdd2variableBuffer(scip, varscpy[i], SCIPgetSolVal(scip, incumbentsol, varscpy[i]), varbuf, valbuf, nfixings, TRUE);
    3612 }
    3613
    3614 assert(i == nbinintvars || *nfixings == ntargetfixings);
    3615
    3616 /* Not reaching the number of target fixings means that there is a significant fraction (at least 1 - targetfixingrate)
    3617 * of variables for which the incumbent solution value does not lie within the global bounds anymore. This is a nonsuccess
    3618 * for the neighborhood (additional fixings are not possible), which is okay because the incumbent solution is
    3619 * significantly outdated
    3620 */
    3621 if( *nfixings == ntargetfixings )
    3622 *result = SCIP_SUCCESS;
    3623
    3624 /* free the buffer array */
    3625 SCIPfreeBufferArray(scip, &varscpy);
    3626
    3627 return SCIP_OKAY;
    3628}
    3629
    3630/** add local branching constraint */
    3631static
    3633 SCIP* sourcescip, /**< source SCIP data structure */
    3634 SCIP* targetscip, /**< target SCIP data structure */
    3635 SCIP_VAR** subvars, /**< array of sub SCIP variables in same order as source SCIP variables */
    3636 int distance, /**< right hand side of the local branching constraint */
    3637 SCIP_Bool* success, /**< pointer to store of a local branching constraint has been successfully added */
    3638 int* naddedconss /**< pointer to increase the number of added constraints */
    3639 )
    3640{
    3641 int nbinvars;
    3642 int i;
    3643 SCIP_SOL* referencesol;
    3644 SCIP_CONS* localbranchcons;
    3645 SCIP_VAR** vars;
    3646 SCIP_Real* consvals;
    3647 SCIP_Real rhs;
    3648
    3649 assert(sourcescip != NULL);
    3650 assert(*success == FALSE);
    3651
    3652 nbinvars = SCIPgetNBinVars(sourcescip);
    3653 vars = SCIPgetVars(sourcescip);
    3654
    3655 if( nbinvars <= 3 )
    3656 return SCIP_OKAY;
    3657
    3658 referencesol = SCIPgetBestSol(sourcescip);
    3659 if( referencesol == NULL )
    3660 return SCIP_OKAY;
    3661
    3662 rhs = (SCIP_Real)distance;
    3663 rhs = MAX(rhs, 2.0);
    3664
    3665 SCIP_CALL( SCIPallocBufferArray(sourcescip, &consvals, nbinvars) );
    3666
    3667 /* loop over binary variables and fill the local branching constraint */
    3668 for( i = 0; i < nbinvars; ++i )
    3669 {
    3670 /* skip variables that are not present in sub-SCIP */
    3671 if( subvars[i] == NULL )
    3672 continue;
    3673
    3674 if( SCIPisEQ(sourcescip, SCIPgetSolVal(sourcescip, referencesol, vars[i]), 0.0) )
    3675 consvals[i] = 1.0;
    3676 else
    3677 {
    3678 consvals[i] = -1.0;
    3679 rhs -= 1.0;
    3680 }
    3681 }
    3682
    3683 /* create the local branching constraint in the target scip */
    3684 SCIP_CALL( SCIPcreateConsBasicLinear(targetscip, &localbranchcons, "localbranch", nbinvars, subvars, consvals, -SCIPinfinity(sourcescip), rhs) );
    3685 SCIP_CALL( SCIPaddCons(targetscip, localbranchcons) );
    3686 SCIP_CALL( SCIPreleaseCons(targetscip, &localbranchcons) );
    3687
    3688 *naddedconss = 1;
    3689 *success = TRUE;
    3690
    3691 SCIPfreeBufferArray(sourcescip, &consvals);
    3692
    3693 return SCIP_OKAY;
    3694}
    3695
    3696/** callback for local branching subproblem changes */
    3697static
    3698DECL_CHANGESUBSCIP(changeSubscipLocalbranching)
    3699{ /*lint --e{715}*/
    3700
    3701 SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.2 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
    3702
    3703 return SCIP_OKAY;
    3704}
    3705
    3706/** callback for proximity subproblem changes */
    3707static
    3708DECL_CHANGESUBSCIP(changeSubscipProximity)
    3709{ /*lint --e{715}*/
    3710 SCIP_SOL* referencesol;
    3711 SCIP_VAR** vars;
    3712 int nbinvars;
    3713 int nintvars;
    3714 int nvars;
    3715 int i;
    3716
    3717 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    3718
    3719 if( nbinvars == 0 )
    3720 return SCIP_OKAY;
    3721
    3722 referencesol = SCIPgetBestSol(sourcescip);
    3723 if( referencesol == NULL )
    3724 return SCIP_OKAY;
    3725
    3726 /* loop over binary variables, set objective coefficients based on reference solution in a local branching fashion */
    3727 for( i = 0; i < nbinvars; ++i )
    3728 {
    3729 SCIP_Real newobj;
    3730
    3731 /* skip variables not present in sub-SCIP */
    3732 if( subvars[i] == NULL )
    3733 continue;
    3734
    3735 if( SCIPgetSolVal(sourcescip, referencesol, vars[i]) < 0.5 )
    3736 newobj = -1.0;
    3737 else
    3738 newobj = 1.0;
    3739 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], newobj) );
    3740 }
    3741
    3742 /* loop over the remaining variables and change their objective coefficients to 0 */
    3743 for( ; i < nvars; ++i )
    3744 {
    3745 /* skip variables not present in sub-SCIP */
    3746 if( subvars[i] == NULL )
    3747 continue;
    3748
    3749 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
    3750 }
    3751
    3752 *nchgobjs = nvars;
    3753 *success = TRUE;
    3754
    3755 return SCIP_OKAY;
    3756}
    3757
    3758/** callback for zeroobjective subproblem changes */
    3759static
    3760DECL_CHANGESUBSCIP(changeSubscipZeroobjective)
    3761{ /*lint --e{715}*/
    3762 SCIP_CONSHDLR* conshdlrnl;
    3763 SCIP_VAR** vars;
    3764 int nvars;
    3765 int i;
    3766
    3767 assert(*success == FALSE);
    3768
    3769 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    3770
    3771 /* do not run if no objective variables are present */
    3772 if( SCIPgetNObjVars(sourcescip) == 0 )
    3773 return SCIP_OKAY;
    3774
    3775 /* zeroobj may trigger fixing objvar in nonlinear constraint to infinity,
    3776 * which expr_var.c:simplify cannot handle at the moment; also #3273
    3777 */
    3778 conshdlrnl = SCIPfindConshdlr(sourcescip, "nonlinear");
    3779 if( conshdlrnl != NULL && SCIPconshdlrGetNActiveConss(conshdlrnl) > 0 )
    3780 return SCIP_OKAY;
    3781
    3782 /* loop over the variables and change their objective coefficients to 0 */
    3783 for( i = 0; i < nvars; ++i )
    3784 {
    3785 /* skip variables not present in sub-SCIP */
    3786 if( subvars[i] == NULL )
    3787 continue;
    3788
    3789 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
    3790 }
    3791
    3792 *nchgobjs = nvars;
    3793 *success = TRUE;
    3794
    3795 return SCIP_OKAY;
    3796}
    3797
    3798/** compute tightened bounds for integer variables depending on how much the LP and the incumbent solution values differ */
    3799static
    3801 SCIP* scip, /**< SCIP data structure of the original problem */
    3802 SCIP_VAR* var, /**< the variable for which bounds should be computed */
    3803 SCIP_Real* lbptr, /**< pointer to store the lower bound in the DINS sub-SCIP */
    3804 SCIP_Real* ubptr /**< pointer to store the upper bound in the DINS sub-SCIP */
    3805 )
    3806{
    3807 SCIP_Real mipsol;
    3808 SCIP_Real lpsol;
    3809
    3810 SCIP_Real lbglobal;
    3811 SCIP_Real ubglobal;
    3812 SCIP_SOL* bestsol;
    3813
    3814 /* get the bounds for each variable */
    3815 lbglobal = SCIPvarGetLbGlobal(var);
    3816 ubglobal = SCIPvarGetUbGlobal(var);
    3817
    3819 /* get the current LP solution for each variable */
    3820 lpsol = SCIPvarGetLPSol(var);
    3821
    3822 /* get the current MIP solution for each variable */
    3823 bestsol = SCIPgetBestSol(scip);
    3824 mipsol = SCIPgetSolVal(scip, bestsol, var);
    3825
    3826 /* if the solution values differ by 0.5 or more, the variable is rebounded, otherwise it is just copied */
    3827 if( REALABS(lpsol - mipsol) >= 0.5 )
    3828 {
    3829 SCIP_Real range;
    3830
    3831 *lbptr = lbglobal;
    3832 *ubptr = ubglobal;
    3833
    3834 /* create an equally sized range around lpsol for general integers: bounds are lpsol +- (mipsol-lpsol) */
    3835 range = 2 * lpsol - mipsol;
    3836
    3837 if( mipsol >= lpsol )
    3838 {
    3839 range = SCIPfeasCeil(scip, range);
    3840 *lbptr = MAX(*lbptr, range);
    3841
    3842 /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
    3843 if( SCIPisFeasEQ(scip, mipsol, *lbptr) )
    3844 *ubptr = *lbptr;
    3845 else
    3846 *ubptr = mipsol;
    3847 }
    3848 else
    3849 {
    3850 range = SCIPfeasFloor(scip, range);
    3851 *ubptr = MIN(*ubptr, range);
    3852
    3853 /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
    3854 if( SCIPisFeasEQ(scip, mipsol, *ubptr) )
    3855 *lbptr = *ubptr;
    3856 else
    3857 *lbptr = mipsol;
    3858 }
    3859
    3860 /* the global domain of variables might have been reduced since incumbent was found: adjust lb and ub accordingly */
    3861 *lbptr = MAX(*lbptr, lbglobal);
    3862 *ubptr = MIN(*ubptr, ubglobal);
    3863 }
    3864 else
    3865 {
    3866 /* the global domain of variables might have been reduced since incumbent was found: adjust it accordingly */
    3867 *lbptr = MAX(mipsol, lbglobal);
    3868 *ubptr = MIN(mipsol, ubglobal);
    3869 }
    3870}
    3871
    3872/** callback to collect variable fixings of DINS */
    3873static
    3874DECL_VARFIXINGS(varFixingsDins)
    3875{
    3876 DATA_DINS* data;
    3877 SCIP_SOL* rootlpsol;
    3878 SCIP_SOL** sols;
    3879 int nsols;
    3880 int nmipsols;
    3881 int nbinvars;
    3882 int nintvars;
    3883 SCIP_VAR** vars;
    3884 int v;
    3885
    3886 data = neighborhood->data.dins;
    3887 assert(data != NULL);
    3888 nmipsols = SCIPgetNSols(scip);
    3889 nmipsols = MIN(nmipsols, data->npoolsols);
    3890
    3891 *result = SCIP_DELAYED;
    3892
    3894 return SCIP_OKAY;
    3895
    3896 *result = SCIP_DIDNOTRUN;
    3897
    3898 if( nmipsols == 0 )
    3899 return SCIP_OKAY;
    3900
    3901 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3902
    3903 if( nbinvars + nintvars == 0 )
    3904 return SCIP_OKAY;
    3905
    3906 SCIP_CALL( SCIPcreateSol(scip, &rootlpsol, NULL) );
    3907
    3908 /* save root solution LP values in solution */
    3909 for( v = 0; v < nbinvars + nintvars; ++v )
    3910 {
    3911 SCIP_CALL( SCIPsetSolVal(scip, rootlpsol, vars[v], SCIPvarGetRootSol(vars[v])) );
    3912 }
    3913
    3914 /* add the node and the root LP solution */
    3915 nsols = nmipsols + 2;
    3916
    3917 SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
    3918 sols[0] = NULL; /* node LP solution */
    3919 sols[1] = rootlpsol;
    3920
    3921 /* copy the remaining MIP solutions after the LP solutions */
    3922 BMScopyMemoryArray(&sols[2], SCIPgetSols(scip), nmipsols); /*lint !e866*/
    3923
    3924 /* 1. Binary variables are fixed if their values agree in all the solutions */
    3925 if( nbinvars > 0 )
    3926 {
    3927 SCIP_CALL( fixMatchingSolutionValues(scip, sols, nsols, vars, nbinvars, varbuf, valbuf, nfixings) );
    3928 }
    3929
    3930 /* 2. Integer variables are fixed if they have a very low distance between the incumbent and the root LP solution */
    3931 for( v = nbinvars; v < nintvars; ++v )
    3932 {
    3933 SCIP_Real lb;
    3934 SCIP_Real ub;
    3935 computeIntegerVariableBoundsDins(scip, vars[v], &lb, &ub);
    3936
    3937 if( ub - lb < 0.5 )
    3938 {
    3939 assert(SCIPisFeasIntegral(scip, lb));
    3940 tryAdd2variableBuffer(scip, vars[v], lb, varbuf, valbuf, nfixings, TRUE);
    3941 }
    3942 }
    3943
    3944 *result = SCIP_SUCCESS;
    3945
    3946 SCIPfreeBufferArray(scip, &sols);
    3947
    3948 SCIP_CALL( SCIPfreeSol(scip, &rootlpsol) );
    3949
    3950 return SCIP_OKAY;
    3951}
    3952
    3953/** callback for DINS subproblem changes */
    3954static
    3955DECL_CHANGESUBSCIP(changeSubscipDins)
    3956{ /*lint --e{715}*/
    3957 SCIP_VAR** vars;
    3958 int nintvars;
    3959 int nbinvars;
    3960 int v;
    3961
    3962 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3963
    3964 /* 1. loop over integer variables and tighten the bounds */
    3965 for( v = nbinvars; v < nintvars; ++v )
    3966 {
    3967 SCIP_Real lb;
    3968 SCIP_Real ub;
    3969
    3970 /* skip variables not present in sub-SCIP */
    3971 if( subvars[v] == NULL )
    3972 continue;
    3973
    3974 computeIntegerVariableBoundsDins(sourcescip, vars[v], &lb, &ub);
    3975
    3976 SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[v], lb) );
    3977 SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[v], ub) );
    3978 ++(*ndomchgs);
    3979 }
    3980
    3981 /* 2. add local branching constraint for binary variables */
    3982 SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.1 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
    3983
    3984 *success = TRUE;
    3985
    3986 return SCIP_OKAY;
    3987}
    3988
    3989/** deinitialization callback for DINS before SCIP is freed */
    3990static
    3991DECL_NHFREE(nhFreeDins)
    3992{
    3993 assert(neighborhood->data.dins != NULL);
    3994
    3995 SCIPfreeBlockMemory(scip, &neighborhood->data.dins);
    3996
    3997 return SCIP_OKAY;
    3998}
    3999
    4000/** deinitialization callback for trustregion before SCIP is freed */
    4001static
    4002DECL_NHFREE(nhFreeTrustregion)
    4003{
    4004 assert(neighborhood->data.trustregion != NULL);
    4005
    4006 SCIPfreeBlockMemory(scip, &neighborhood->data.trustregion);
    4007
    4008 return SCIP_OKAY;
    4009}
    4010
    4011/** add trust region neighborhood constraint and auxiliary objective variable */
    4012static
    4013DECL_CHANGESUBSCIP(changeSubscipTrustregion)
    4014{ /*lint --e{715}*/
    4015 DATA_TRUSTREGION* data;
    4016
    4017 data = neighborhood->data.trustregion;
    4018
    4019 /* adding the neighborhood constraint for the trust region heuristic */
    4020 SCIP_CALL( SCIPaddTrustregionNeighborhoodConstraint(sourcescip, targetscip, subvars, data->violpenalty) );
    4021
    4022 /* incrementing the change in objective since an additional variable is added to the objective to penalize the
    4023 * violation of the trust region.
    4024 */
    4025 ++(*nchgobjs);
    4026
    4027 return SCIP_OKAY;
    4028}
    4029
    4030/** callback that returns the incumbent solution as a reference point */
    4031static
    4032DECL_NHREFSOL(nhRefsolIncumbent)
    4033{ /*lint --e{715}*/
    4034 assert(scip != NULL);
    4035
    4036 if( SCIPgetBestSol(scip) != NULL )
    4037 {
    4038 *result = SCIP_SUCCESS;
    4039 *solptr = SCIPgetBestSol(scip);
    4040 }
    4041 else
    4042 {
    4043 *result = SCIP_DIDNOTFIND;
    4044 }
    4045
    4046 return SCIP_OKAY;
    4047}
    4048
    4049
    4050/** callback function that deactivates a neighborhood on problems with no discrete variables */
    4051static
    4052DECL_NHDEACTIVATE(nhDeactivateDiscreteVars)
    4053{ /*lint --e{715}*/
    4054 assert(scip != NULL);
    4055 assert(deactivate != NULL);
    4056
    4057 /* deactivate if no discrete variables are present */
    4058 *deactivate = (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0);
    4059
    4060 return SCIP_OKAY;
    4061}
    4062
    4063/** callback function that deactivates a neighborhood on problems with no binary variables */
    4064static
    4065DECL_NHDEACTIVATE(nhDeactivateBinVars)
    4066{ /*lint --e{715}*/
    4067 assert(scip != NULL);
    4068 assert(deactivate != NULL);
    4069
    4070 /* deactivate if no discrete variables are present */
    4071 *deactivate = (SCIPgetNBinVars(scip) == 0);
    4072
    4073 return SCIP_OKAY;
    4074}
    4075
    4076/** callback function that deactivates a neighborhood on problems with no objective variables */
    4077static
    4078DECL_NHDEACTIVATE(nhDeactivateObjVars)
    4079{ /*lint --e{715}*/
    4080 assert(scip != NULL);
    4081 assert(deactivate != NULL);
    4082
    4083 /* deactivate if no discrete variables are present */
    4084 *deactivate = (SCIPgetNObjVars(scip) == 0);
    4085
    4086 return SCIP_OKAY;
    4087}
    4088
    4089
    4090/** include all neighborhoods */
    4091static
    4093 SCIP* scip, /**< SCIP data structure */
    4094 SCIP_HEURDATA* heurdata /**< heuristic data of the scheduler heuristic */
    4095 )
    4096{
    4097 NH* rens;
    4098 NH* rins;
    4099 NH* mutation;
    4100 NH* localbranching;
    4101 NH* crossover;
    4102 NH* proximity;
    4103 NH* zeroobjective;
    4104 NH* dins;
    4105 NH* trustregion;
    4106
    4107 heurdata->nneighborhoods = 0;
    4108
    4109 /* include the RENS neighborhood */
    4110 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &rens, "rens",
    4112 varFixingsRens, changeSubscipRens, NULL, NULL, NULL, NULL, nhDeactivateDiscreteVars) );
    4113
    4114 /* include the RINS neighborhood */
    4115 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &rins, "rins",
    4117 varFixingsRins, NULL, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
    4118
    4119 /* include the mutation neighborhood */
    4120 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &mutation, "mutation",
    4122 varFixingsMutation, NULL, nhInitMutation, nhExitMutation, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
    4123
    4124 /* include the local branching neighborhood */
    4125 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &localbranching, "localbranching",
    4127 NULL, changeSubscipLocalbranching, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
    4128
    4129 /* include the crossover neighborhood */
    4130 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &crossover, "crossover",
    4132 varFixingsCrossover, NULL,
    4133 nhInitCrossover, nhExitCrossover, nhFreeCrossover, nhRefsolCrossover, nhDeactivateDiscreteVars) );
    4134
    4135 /* allocate data for crossover to include the parameter */
    4137 crossover->data.crossover->rng = NULL;
    4138
    4139 /* add crossover neighborhood parameters */
    4140 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/scheduler/crossover/nsols", "the number of solutions that crossover should combine",
    4141 &crossover->data.crossover->nsols, TRUE, DEFAULT_NSOLS_CROSSOVER, 2, 10, NULL, NULL) );
    4142
    4143 /* include the Proximity neighborhood */
    4144 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &proximity, "proximity",
    4146 NULL, changeSubscipProximity, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
    4147
    4148 /* include the Zeroobjective neighborhood */
    4149 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &zeroobjective, "zeroobjective",
    4151 NULL, changeSubscipZeroobjective, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateObjVars) );
    4152
    4153 /* include the DINS neighborhood */
    4154 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &dins, "dins",
    4156 varFixingsDins, changeSubscipDins, NULL, NULL, nhFreeDins, nhRefsolIncumbent, nhDeactivateBinVars) );
    4157
    4158 /* allocate data for DINS to include the parameter */
    4160
    4161 /* add DINS neighborhood parameters */
    4162 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/scheduler/dins/npoolsols",
    4163 "number of pool solutions where binary solution values must agree",
    4164 &dins->data.dins->npoolsols, TRUE, DEFAULT_NPOOLSOLS_DINS, 1, 100, NULL, NULL) );
    4165
    4166 /* include the trustregion neighborhood */
    4167 SCIP_CALL( schedulerIncludeNeighborhood(scip, heurdata, &trustregion, "trustregion",
    4169 NULL, changeSubscipTrustregion, NULL, NULL, nhFreeTrustregion, nhRefsolIncumbent, nhDeactivateBinVars) );
    4170
    4171 /* allocate data for trustregion to include the parameter */
    4173
    4174 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/trustregion/violpenalty",
    4175 "the penalty for each change in the binary variables from the candidate solution",
    4177
    4178 return SCIP_OKAY;
    4179}
    4180
    4181/** initialization method of primal heuristic (called after problem was transformed) */
    4182static
    4183SCIP_DECL_HEURINIT(heurInitScheduler)
    4184{ /*lint --e{715}*/
    4185 SCIP_HEURDATA* heurdata;
    4186 int i;
    4187
    4188 assert(scip != NULL);
    4189 assert(heur != NULL);
    4190
    4191 heurdata = SCIPheurGetData(heur);
    4192 assert(heurdata != NULL);
    4193
    4194 /* reactivate all neighborhoods if a new problem is read in */
    4195 heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
    4196
    4197 /* initialize neighborhoods for new problem */
    4198 for( i = 0; i < heurdata->nneighborhoods; ++i )
    4199 {
    4200 NH* neighborhood = heurdata->neighborhoods[i];
    4201
    4202 SCIP_CALL( neighborhoodInit(scip, neighborhood) );
    4203
    4204 SCIP_CALL( resetFixingRate(scip, &neighborhood->fixingrate) );
    4205
    4206 SCIP_CALL( heurStatsReset(scip, &neighborhood->stats, FALSE) );
    4207 }
    4208
    4209 /* we clear the list of collected diving heuristics to ensure reproducability and consistent state across multiple runs
    4210 * within the same SCIP data structure */
    4211 /* note: diving heuristics data will be initialized when executing scheduler */
    4212 if( heurdata->divingheurs != NULL )
    4213 {
    4214 int j;
    4215
    4216 for( j = 0; j < heurdata->ndiving; ++j )
    4217 {
    4218 SCIP_CALL( schedulerFreeDivingHeur(scip, &(heurdata->divingheurs[j])) );
    4219 }
    4220
    4221 SCIPfreeBlockMemoryArray(scip, &heurdata->divingheurs, heurdata->divingheurssize);
    4222
    4223 if( heurdata->defaultroot )
    4224 SCIPfreeBlockMemoryArray(scip, &heurdata->sortedindices, heurdata->ndiving + heurdata->nneighborhoods);
    4225 }
    4226
    4227 /* create working solution */
    4228 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    4229
    4230 return SCIP_OKAY;
    4231}
    4232
    4233
    4234/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    4235static
    4236SCIP_DECL_HEURINITSOL(heurInitsolScheduler)
    4237{ /*lint --e{715}*/
    4238 SCIP_HEURDATA* heurdata;
    4239 int i;
    4240 SCIP_Real* priorities;
    4241 unsigned int initseed;
    4242
    4243 assert(scip != NULL);
    4244 assert(heur != NULL);
    4245
    4246 heurdata = SCIPheurGetData(heur);
    4247 assert(heurdata != NULL);
    4248 heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
    4249
    4250 SCIP_CALL( SCIPallocBufferArray(scip, &priorities, heurdata->ndiving + heurdata->nactiveneighborhoods) );
    4251
    4252 /* init neighborhoods for new problem by resetting their statistics and fixing rate */
    4253 for( i = heurdata->nneighborhoods - 1; i >= 0; --i )
    4254 {
    4255 NH* neighborhood = heurdata->neighborhoods[i];
    4256 SCIP_Bool deactivate;
    4257
    4258 SCIP_CALL( neighborhood->nhdeactivate(scip, &deactivate) );
    4259
    4260 /* disable inactive neighborhoods */
    4261 if( deactivate || ! neighborhood->active )
    4262 {
    4263 if( heurdata->nactiveneighborhoods - 1 > i )
    4264 {
    4265 assert(heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]->active);
    4266 SCIPswapPointers((void **)&heurdata->neighborhoods[i], (void **)&heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]);
    4267 }
    4268 heurdata->nactiveneighborhoods--;
    4269 }
    4270 }
    4271
    4272 /* if diving is already initialized (only happens after all diving heuristics are initialized),
    4273 * take the proper priorities. Otherwise, set all priorities to 1.0 */
    4274 if( heurdata->divingheurs != NULL )
    4275 {
    4276 /* collect diving heuristic priorities */
    4277 for( i = 0; i < heurdata->ndiving; ++i )
    4278 priorities[i] = heurdata->divingheurs[i]->priority;
    4279
    4280 /* collect neighborhood priorities */
    4281 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
    4282 priorities[i + heurdata->ndiving] = heurdata->neighborhoods[i]->priority;
    4283 }
    4284 else
    4285 {
    4286 for( i = 0; i < heurdata->ndiving + heurdata->nactiveneighborhoods; ++i )
    4287 priorities[i] = 1.0;
    4288 }
    4289
    4290 initseed = (unsigned int)(heurdata->seed + SCIPgetNVars(scip));
    4291
    4292 /* active neighborhoods might change between init calls, reset functionality must take this into account */
    4293 if( heurdata->bandit != NULL && SCIPbanditGetNActions(heurdata->bandit) != heurdata->ndiving + heurdata->nactiveneighborhoods )
    4294 {
    4295 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
    4296 heurdata->bandit = NULL;
    4297
    4298 /* since the number of active heursitics has changed, we have to update
    4299 * how heuristics are sorted by priority, if we already initialized the data */
    4300 if( heurdata->divingheurs != NULL )
    4301 {
    4302 SCIP_Real* initpriorities;
    4303 int nheurs;
    4304
    4305 nheurs = heurdata->nactiveneighborhoods + heurdata->ndiving;
    4306 SCIP_CALL( SCIPallocBufferArray(scip, &initpriorities, nheurs) );
    4307 heurdata->counter = 0;
    4308
    4309 for( i = 0; i < nheurs; ++i )
    4310 {
    4311 heurdata->sortedindices[i] = i;
    4312
    4313 if( i < heurdata->ndiving )
    4314 initpriorities[i] = (SCIP_Real)-heurdata->divingheurs[i]->rootnodepriority;
    4315 else
    4316 initpriorities[i] = (SCIP_Real)-heurdata->neighborhoods[i - heurdata->ndiving]->rootnodepriority;
    4317 }
    4318
    4319 SCIPsortRealInt(initpriorities, heurdata->sortedindices, nheurs);
    4320
    4321 SCIPfreeBufferArray(scip, &initpriorities);
    4322 }
    4323 }
    4324
    4325 if( heurdata->nactiveneighborhoods + heurdata->ndiving > 0 )
    4326 { /* create or reset bandit algorithm */
    4327 if( heurdata->bandit == NULL )
    4328 {
    4329 SCIP_CALL( createBandit(scip, heurdata, priorities, initseed) );
    4330 resetTargetNodeLimit(heurdata);
    4331 }
    4332 else if( heurdata->resetweights )
    4333 {
    4334 SCIP_CALL( SCIPresetBandit(scip, heurdata->bandit, priorities, initseed) );
    4335 resetTargetNodeLimit(heurdata);
    4336 }
    4337 }
    4338
    4339 /* TODO: maybe do something for diving as well here? */
    4340 heurdata->usednodes = 0;
    4341 heurdata->ninitneighborhoods = heurdata->nactiveneighborhoods;
    4342
    4343 heurdata->lastcallsol = NULL;
    4344 heurdata->firstcallthissol = 0;
    4345
    4346 resetCurrentNeighborhood(heurdata);
    4347
    4348 SCIPfreeBufferArray(scip, &priorities);
    4349
    4350 return SCIP_OKAY;
    4351}
    4352
    4353
    4354/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    4355static
    4356SCIP_DECL_HEUREXIT(heurExitScheduler)
    4357{ /*lint --e{715}*/
    4358 SCIP_HEURDATA* heurdata;
    4359 int i;
    4360
    4361 assert(scip != NULL);
    4362 assert(heur != NULL);
    4363
    4364 heurdata = SCIPheurGetData(heur);
    4365 assert(heurdata != NULL);
    4366
    4367 /* free neighborhood specific data */
    4368 for( i = 0; i < heurdata->nneighborhoods; ++i )
    4369 {
    4370 NH* neighborhood = heurdata->neighborhoods[i];
    4371
    4372 SCIP_CALL( neighborhoodExit(scip, neighborhood) );
    4373 }
    4374
    4375 /* free working solution */
    4376 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    4377
    4378 return SCIP_OKAY;
    4379}
    4380
    4381/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    4382static
    4383SCIP_DECL_HEURFREE(heurFreeScheduler)
    4384{ /*lint --e{715}*/
    4385 SCIP_HEURDATA* heurdata;
    4386 int i;
    4387
    4388 assert(scip != NULL);
    4389 assert(heur != NULL);
    4390
    4391 heurdata = SCIPheurGetData(heur);
    4392 assert(heurdata != NULL);
    4393
    4394 /* bandits are only initialized if a problem has been read */
    4395 if( heurdata->bandit != NULL )
    4396 {
    4397 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
    4398 }
    4399
    4400 /* free diving heuristics */
    4401 if( heurdata->divingheurs != NULL )
    4402 {
    4403 int j;
    4404
    4405 for( j = 0; j < heurdata->ndiving; ++j )
    4406 {
    4407 SCIP_CALL( schedulerFreeDivingHeur(scip, &(heurdata->divingheurs[j])) );
    4408 }
    4409
    4410 SCIPfreeBlockMemoryArray(scip, &heurdata->divingheurs, heurdata->divingheurssize);
    4411
    4412 if( heurdata->defaultroot )
    4413 SCIPfreeBlockMemoryArray(scip, &heurdata->sortedindices, heurdata->ndiving + heurdata->nneighborhoods);
    4414 }
    4415
    4416 /* free neighborhoods */
    4417 for( i = 0; i < heurdata->nneighborhoods; ++i )
    4418 {
    4419 SCIP_CALL( schedulerFreeNeighborhood(scip, &(heurdata->neighborhoods[i])) );
    4420 }
    4421
    4422 SCIPfreeBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS);
    4423
    4424 SCIPfreeBlockMemory(scip, &heurdata);
    4425
    4426 return SCIP_OKAY;
    4427}
    4428
    4429/** output method of statistics table to output file stream 'file' */
    4430static
    4431SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
    4432{ /*lint --e{715}*/
    4433 SCIP_HEURDATA* heurdata;
    4434
    4435 assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
    4437 assert(heurdata != NULL);
    4438
    4439 /* print neighborhood statistics */
    4440 printNeighborhoodStatistics(scip, heurdata, file);
    4441
    4442 /* print only diving statistics if scheduler got executed at least once (because we only then
    4443 * initialize the diving heuristics)
    4444 * Note: More Diving statistics will be printed in scip_solvingstats.c with all other stats about
    4445 * diving since adaptive diving and the scheduler use the same diving context
    4446 */
    4447 if( heurdata->divingheurs != NULL )
    4448 printDivingHeurStatistics(scip, heurdata, file);
    4449
    4450 return SCIP_OKAY;
    4451}
    4452
    4453static
    4454SCIP_DECL_TABLECOLLECT(tableCollectNeighborhood)
    4455{
    4456 assert(table != NULL);
    4457
    4458 SCIP_HEURDATA* heurdata;
    4459
    4460 assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
    4462 assert(heurdata != NULL);
    4463
    4464 /* print neighborhood statistics */
    4465 SCIP_CALL( collectNeighborhoodStatistics(scip, heurdata, datatree) );
    4466
    4467 if( heurdata->divingheurs != NULL )
    4468 {
    4469 SCIP_CALL( collectDivingHeurStatistics(scip, heurdata, datatree) );
    4470 }
    4471
    4472 return SCIP_OKAY;
    4473}
    4474
    4475/*
    4476 * primal heuristic specific interface methods
    4477 */
    4478
    4479/** creates the scheduler primal heuristic and includes it in SCIP */
    4481 SCIP* scip /**< SCIP data structure */
    4482 )
    4483{
    4484 SCIP_HEURDATA* heurdata;
    4485 SCIP_HEUR* heur;
    4486
    4487 /* create primal heuristic data */
    4488 heurdata = NULL;
    4489 heur = NULL;
    4490
    4491 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    4492 BMSclearMemory(heurdata);
    4493
    4494 /* TODO make this a user parameter? */
    4495 heurdata->lplimfac = LPLIMFAC;
    4496
    4497 heurdata->nskippedcalls = 0;
    4498 heurdata->nfailedcalls = 0;
    4499 heurdata->maxnconflicts = 0;
    4500
    4501 /* allocate memory for LNS heuristics */
    4502 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS) );
    4503
    4504 /* include primal heuristic */
    4507 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecScheduler, heurdata) );
    4508
    4509 assert(heur != NULL);
    4510
    4511 /* primal heuristic is safe to use in exact solving mode */
    4512 SCIPheurMarkExact(heur);
    4513
    4514 /* include all neighborhoods */
    4515 /* note: diving heuristics will be included when executing the scheduler heuristic for
    4516 * the first time, because it relies on all heuristics being already added to SCIP
    4517 */
    4518 SCIP_CALL( includeNeighborhoods(scip, heurdata) );
    4519
    4520 /* set non fundamental callbacks via setter functions */
    4521 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyScheduler) );
    4522 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeScheduler) );
    4523 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitScheduler) );
    4524 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolScheduler) );
    4525 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitScheduler) );
    4526
    4527 /* add scheduler primal heuristic parameters */
    4528 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    4529 "maximum number of nodes to regard in the subproblem",
    4530 &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4531
    4532 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    4533 "offset added to the nodes budget",
    4534 &heurdata->nodesoffset, FALSE, DEFAULT_NODESOFFSET, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4535
    4536 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    4537 "minimum number of nodes required to start a sub-SCIP",
    4538 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4539
    4540 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/waitingnodes",
    4541 "number of nodes since last incumbent solution that the heuristic should wait",
    4542 &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4543
    4544 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/initlnsnodelimit",
    4545 "initial node limit for LNS heuristics",
    4546 &heurdata->initlnsnodelimit, TRUE, DEFAULT_INITLNSNODELIMIT, 0, INT_MAX, NULL, NULL) );
    4547
    4548 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/initdivingnodelimit",
    4549 "initial node limit for diving heuristics",
    4550 &heurdata->initdivingnodelimit, TRUE, DEFAULT_INITDIVINGNODELIMIT, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4551
    4552 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    4553 "fraction of nodes compared to the main SCIP for budget computation",
    4554 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    4555
    4556 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquotmin",
    4557 "lower bound fraction of nodes compared to the main SCIP for budget computation",
    4558 &heurdata->nodesquotmin, FALSE, DEFAULT_NODESQUOTMIN, 0.0, 1.0, NULL, NULL) );
    4559
    4560 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nsolslim",
    4561 "limit on the number of improving solutions in a sub-SCIP call",
    4562 &heurdata->nsolslim, FALSE, DEFAULT_NSOLSLIM, -1, INT_MAX, NULL, NULL) );
    4563
    4564 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/banditalgo",
    4565 "the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy, exp.3-(i)x",
    4566 &heurdata->banditalgo, TRUE, DEFAULT_BANDITALGO, "uegi", NULL, NULL) );
    4567
    4568 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gamma",
    4569 "weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3",
    4570 &heurdata->exp3_gamma, TRUE, DEFAULT_GAMMA, 0.0, 1.0, NULL, NULL) );
    4571
    4572 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/beta",
    4573 "reward offset between 0 and 1 at every observation for Exp.3",
    4574 &heurdata->exp3_beta, TRUE, DEFAULT_BETA, 0.0, 1.0, NULL, NULL) );
    4575
    4576 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/alpha",
    4577 "parameter to increase the confidence width in UCB",
    4578 &heurdata->ucb_alpha, TRUE, DEFAULT_ALPHA, 0.0, 100.0, NULL, NULL) );
    4579
    4580 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usedistances",
    4581 "distances from fixed variables be used for variable prioritization",
    4582 &heurdata->usedistances, TRUE, DEFAULT_USEDISTANCES, NULL, NULL) );
    4583
    4584 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useredcost",
    4585 "should reduced cost scores be used for variable prioritization?",
    4586 &heurdata->useredcost, TRUE, DEFAULT_USEREDCOST, NULL, NULL) );
    4587
    4588 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usepscost",
    4589 "should pseudo cost scores be used for variable priorization?",
    4590 &heurdata->usepscost, TRUE, DEFAULT_USEPSCOST, NULL, NULL) );
    4591
    4592 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselocalredcost",
    4593 "should local reduced costs be used for generic (un)fixing?",
    4594 &heurdata->uselocalredcost, TRUE, DEFAULT_USELOCALREDCOST, NULL, NULL) );
    4595
    4596 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usesubscipheurs",
    4597 "should the heuristic activate other sub-SCIP heuristics during its search?",
    4598 &heurdata->usesubscipheurs, TRUE, DEFAULT_USESUBSCIPHEURS, NULL, NULL) );
    4599
    4600 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/targetnodefactor",
    4601 "factor by which target node number is eventually increased",
    4602 &heurdata->targetnodefactor, TRUE, DEFAULT_TARGETNODEFACTOR, 1.0, 1e+5, NULL, NULL) );
    4603
    4604 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/seed",
    4605 "initial random seed for bandit algorithms and random decisions by neighborhoods",
    4606 &heurdata->seed, FALSE, DEFAULT_SEED, 0, INT_MAX, NULL, NULL) );
    4607
    4608 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxcallssamesol",
    4609 "number of allowed executions of the heuristic on the same incumbent solution (-1: no limit, 0: number of active neighborhoods)",
    4610 &heurdata->maxcallssamesol, TRUE, DEFAULT_MAXCALLSSAMESOL, -1, 100, NULL, NULL) );
    4611
    4612 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/eps",
    4613 "increase exploration in epsilon-greedy bandit algorithm",
    4614 &heurdata->epsgreedy_eps, TRUE, DEFAULT_EPS, 0.0, 1.0, NULL, NULL) );
    4615
    4616 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/epsgreedy_usemod",
    4617 "TRUE if modified version of the epsilon-greedy bandit algorithm should be used",
    4618 &heurdata->epsgreedy_usemod, TRUE, TRUE, NULL, NULL) );
    4619
    4620 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/solrewardweight",
    4621 "weight by how much finding a new incumbent is rewarded in reward function",
    4622 &heurdata->solrewardweight, TRUE, DEFAULT_SOLREWARDWEIGHT, 0.0, 1.0, NULL, NULL) );
    4623
    4624 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/effortrewardweight",
    4625 "weight by how much effort is rewarded in reward function",
    4626 &heurdata->effortrewardweight, TRUE, DEFAULT_EFFORTREWARDWEIGHT, 0.0, 1.0, NULL, NULL) );
    4627
    4628 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/qualrewardweight",
    4629 "weight by how much quality of a new incumbent is rewarded in reward function",
    4630 &heurdata->qualrewardweight, TRUE, DEFAULT_QUALREWARDWEIGHT, 0.0, 1.0, NULL, NULL) );
    4631
    4632 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/conflictrewardweight",
    4633 "weight by how much number of conflicts found by diving is rewarded in reward function",
    4634 &heurdata->conflictrewardweight, TRUE, DEFAULT_CONFLICTREWARDWEIGHT, 0.0, 1.0, NULL, NULL) );
    4635
    4636 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/resetweights",
    4637 "should the bandit algorithms be reset when a new problem is read?",
    4638 &heurdata->resetweights, TRUE, DEFAULT_RESETWEIGHTS, NULL, NULL) );
    4639
    4640 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/subsciprandseeds",
    4641 "should random seeds of sub-SCIPs be altered to increase diversification?",
    4642 &heurdata->subsciprandseeds, TRUE, DEFAULT_SUBSCIPRANDSEEDS, NULL, NULL) );
    4643
    4644 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    4645 "should cutting planes be copied to the sub-SCIP?",
    4646 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    4647
    4648 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/fixtol",
    4649 "tolerance by which the fixing rate may be missed without generic fixing",
    4650 &heurdata->fixtol, TRUE, DEFAULT_FIXTOL, 0.0, 1.0, NULL, NULL) );
    4651
    4652 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/unfixtol",
    4653 "tolerance by which the fixing rate may be exceeded without generic unfixing",
    4654 &heurdata->unfixtol, TRUE, DEFAULT_UNFIXTOL, 0.0, 1.0, NULL, NULL) );
    4655
    4656 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/initduringroot",
    4657 "should the heuristic be executed multiple times during the root node?",
    4658 &heurdata->initduringroot, TRUE, DEFAULT_INITDURINGROOT, NULL, NULL) );
    4659
    4660 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/defaultroot",
    4661 "should the default priorities be used at the root node?",
    4662 &heurdata->defaultroot, TRUE, TRUE, NULL, NULL) );
    4663
    4664 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nselections",
    4665 "number of heuristics picked by the scheduler in one call (-1: number of controlled heuristics, 0: until new incumbent is found)",
    4666 &heurdata->nselections, TRUE, DEFAULT_NSELECTIONS, -1, 100, NULL, NULL) );
    4667
    4670 NULL, NULL, NULL, NULL, NULL, NULL, tableOutputNeighborhood, tableCollectNeighborhood,
    4672
    4673 return SCIP_OKAY;
    4674}
    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:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_CALL(x)
    Definition: def.h:355
    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:1397
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:647
    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:4812
    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:2981
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
    Definition: sol.c:4130
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
    Definition: sol.c:4239
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_Bool SCIPsolIsOriginal(SCIP_SOL *sol)
    Definition: sol.c:4140
    SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_sol.c:1846
    SCIP_SOL ** SCIPgetSols(SCIP *scip)
    Definition: scip_sol.c:2931
    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:4109
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPpresolve(SCIP *scip)
    Definition: scip_solve.c:2449
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3548
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    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:23478
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
    Definition: var.c:19480
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19115
    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:23490
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    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:24120
    SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
    Definition: var.c:19547
    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 (weighted) 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
    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