SCIP

    Solving Constraint Integer Programs

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