Scippy

    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-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file heur_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#include <string.h>
    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(strcmp(SCIPeventhdlrGetName(eventhdlr), EVENTHDLR_NAME) == 0);
    1010 assert(event != NULL);
    1011 assert(SCIPeventGetType(event) & SCIP_EVENTTYPE_ALNS);
    1012 assert(eventdata != NULL);
    1013
    1014 /* treat the different atomic events */
    1015 switch( SCIPeventGetType(event) )
    1016 {
    1019 /* try to transfer the solution to the original SCIP */
    1020 SCIP_CALL( transferSolution(scip, eventdata) );
    1021 break;
    1023 /* interrupt solution process of sub-SCIP */
    1024 if( SCIPgetNLPs(scip) > eventdata->lplimfac * eventdata->nodelimit )
    1025 {
    1026 SCIPdebugMsg(scip, "interrupt after %" SCIP_LONGINT_FORMAT " LPs\n", SCIPgetNLPs(scip));
    1028 }
    1029 break;
    1030 default:
    1031 break;
    1032 }
    1033
    1034 return SCIP_OKAY;
    1035}
    1036
    1037/** initialize neighborhood statistics before the next run */
    1038static
    1040 SCIP* scip, /**< SCIP data structure */
    1041 NH_STATS* stats /**< run statistics */
    1042 )
    1043{
    1044 stats->nbestsolsfound = 0;
    1045 stats->nsolsfound = 0;
    1046 stats->usednodes = 0L;
    1047 stats->nfixings = 0;
    1050}
    1051
    1052/** update run stats after the sub SCIP was solved */
    1053static
    1055 NH_STATS* stats, /**< run statistics */
    1056 SCIP* subscip /**< sub-SCIP instance, or NULL */
    1057 )
    1058{
    1059 /* treat an untransformed subscip as if none was created */
    1060 if( subscip != NULL && ! SCIPisTransformed(subscip) )
    1061 subscip = NULL;
    1062
    1063 stats->usednodes = subscip != NULL ? SCIPgetNNodes(subscip) : 0L;
    1064}
    1065
    1066/** get the histogram index for this status */
    1067static
    1069 SCIP_STATUS subscipstatus /**< sub-SCIP status */
    1070 )
    1071{
    1072 switch (subscipstatus)
    1073 {
    1075 return (int)HIDX_OPT;
    1077 return (int)HIDX_INFEAS;
    1079 return (int)HIDX_NODELIM;
    1081 return (int)HIDX_STALLNODE;
    1084 return (int)HIDX_SOLLIM;
    1086 return (int)HIDX_USR;
    1087 default:
    1088 return (int)HIDX_OTHER;
    1089 } /*lint !e788*/
    1090}
    1091
    1092/** print neighborhood statistics */
    1093static
    1095 SCIP* scip, /**< SCIP data structure */
    1096 SCIP_HEURDATA* heurdata, /**< heuristic data */
    1097 FILE* file /**< file handle, or NULL for standard out */
    1098 )
    1099{
    1100 int i;
    1101 int j;
    1103
    1104 if( ! heurdata->shownbstats )
    1105 return;
    1106
    1107 SCIPinfoMessage(scip, file, "Neighborhoods : %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %4s %4s %4s %4s %4s %4s %4s %4s\n",
    1108 "Calls", "SetupTime", "SolveTime", "SolveNodes", "Sols", "Best", "Exp3", "Exp3-IX", "EpsGreedy", "UCB", "TgtFixRate",
    1109 "Opt", "Inf", "Node", "Stal", "Sol", "Usr", "Othr", "Actv");
    1110
    1111 /* loop over neighborhoods and fill in statistics */
    1112 for( i = 0; i < heurdata->nneighborhoods; ++i )
    1113 {
    1114 NH* neighborhood;
    1115 SCIP_Real proba;
    1116 SCIP_Real probaix;
    1117 SCIP_Real ucb;
    1118 SCIP_Real epsgreedyweight;
    1119
    1120 neighborhood = heurdata->neighborhoods[i];
    1121 SCIPinfoMessage(scip, file, " %-17s:", neighborhood->name);
    1122 SCIPinfoMessage(scip, file, " %10d", neighborhood->stats.nruns);
    1123 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, neighborhood->stats.setupclock) );
    1124 SCIPinfoMessage(scip, file, " %10.2f", SCIPgetClockTime(scip, neighborhood->stats.submipclock) );
    1125 SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.usednodes );
    1126 SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.nsolsfound);
    1127 SCIPinfoMessage(scip, file, " %10" SCIP_LONGINT_FORMAT, neighborhood->stats.nbestsolsfound);
    1128
    1129 proba = 0.0;
    1130 probaix = 0.0;
    1131 ucb = 1.0;
    1132 epsgreedyweight = -1.0;
    1133
    1134 if( heurdata->bandit != NULL && i < heurdata->nactiveneighborhoods )
    1135 {
    1136 switch (heurdata->banditalgo)
    1137 {
    1138 case 'u':
    1139 ucb = SCIPgetConfidenceBoundUcb(heurdata->bandit, i);
    1140 break;
    1141 case 'g':
    1142 epsgreedyweight = SCIPgetWeightsEpsgreedy(heurdata->bandit)[i];
    1143 break;
    1144 case 'e':
    1145 proba = SCIPgetProbabilityExp3(heurdata->bandit, i);
    1146 break;
    1147 case 'i':
    1148 probaix = SCIPgetProbabilityExp3IX(heurdata->bandit, i);
    1149 break;
    1150 default:
    1151 break;
    1152 }
    1153 }
    1154
    1155 SCIPinfoMessage(scip, file, " %10.5f", proba);
    1156 SCIPinfoMessage(scip, file, " %10.5f", probaix);
    1157 SCIPinfoMessage(scip, file, " %10.5f", epsgreedyweight);
    1158 SCIPinfoMessage(scip, file, " %10.5f", ucb);
    1159 SCIPinfoMessage(scip, file, " %10.3f", neighborhood->fixingrate.targetfixingrate);
    1160
    1161 /* loop over status histogram */
    1162 for( j = 0; j < NHISTENTRIES; ++j )
    1163 SCIPinfoMessage(scip, file, " %4d", neighborhood->stats.statushist[statusses[j]]);
    1164
    1165 SCIPinfoMessage(scip, file, " %4d", i < heurdata->nactiveneighborhoods ? 1 : 0);
    1166 SCIPinfoMessage(scip, file, "\n");
    1167 }
    1168}
    1169
    1170/** update the statistics of the neighborhood based on the sub-SCIP run */
    1171static
    1173 NH_STATS* runstats, /**< run statistics */
    1174 NH* neighborhood, /**< the selected neighborhood */
    1175 SCIP_STATUS subscipstatus /**< status of the sub-SCIP solve */
    1176 )
    1177{ /*lint --e{715}*/
    1178 NH_STATS* stats;
    1179 stats = &neighborhood->stats;
    1180
    1181 /* copy run statistics into neighborhood statistics */
    1182 stats->nbestsolsfound += runstats->nbestsolsfound;
    1183 stats->nsolsfound += runstats->nsolsfound;
    1184 stats->usednodes += runstats->usednodes;
    1185 stats->nruns += 1;
    1186
    1187 if( runstats->nbestsolsfound > 0 )
    1189 else if( runstats->nsolsfound > 0 )
    1190 stats->nrunsbestsol++;
    1191
    1192 /* update the counter for the subscip status */
    1193 ++stats->statushist[getHistIndex(subscipstatus)];
    1194}
    1195
    1196/** sort callback for variable pointers using the ALNS variable prioritization
    1197 *
    1198 * the variable prioritization works hierarchically as follows. A variable
    1199 * a has the higher priority over b iff
    1200 *
    1201 * - variable distances should be used and a has a smaller distance than b
    1202 * - variable reduced costs should be used and a has a smaller score than b
    1203 * - variable pseudo costs should be used and a has a smaller score than b
    1204 * - based on previously assigned random scores
    1205 *
    1206 * @note: distances are context-based. For fixing more variables,
    1207 * distances are initialized from the already fixed variables.
    1208 * For unfixing variables, distances are initialized starting
    1209 * from the unfixed variables
    1210 */
    1211static
    1213{ /*lint --e{715}*/
    1214 VARPRIO* varprio;
    1215
    1216 varprio = (VARPRIO*)dataptr;
    1217 assert(varprio != NULL);
    1218 assert(varprio->randscores != NULL);
    1219
    1220 if( ind1 == ind2 )
    1221 return 0;
    1222
    1223 /* priority is on distances, if enabled. The variable which is closer in a breadth-first search sense to
    1224 * the already fixed variables has precedence */
    1225 if( varprio->usedistances )
    1226 {
    1227 int dist1;
    1228 int dist2;
    1229
    1230 dist1 = varprio->distances[ind1];
    1231 dist2 = varprio->distances[ind2];
    1232
    1233 if( dist1 < 0 )
    1234 dist1 = INT_MAX;
    1235
    1236 if( dist2 < 0 )
    1237 dist2 = INT_MAX;
    1238
    1239 assert(varprio->distances != NULL);
    1240 if( dist1 < dist2 )
    1241 return -1;
    1242 else if( dist1 > dist2 )
    1243 return 1;
    1244 }
    1245
    1246 assert(! varprio->usedistances || varprio->distances[ind1] == varprio->distances[ind2]);
    1247
    1248 /* if the indices tie considering distances or distances are disabled -> use reduced cost information instead */
    1249 if( varprio->useredcost )
    1250 {
    1251 assert(varprio->redcostscores != NULL);
    1252
    1253 if( varprio->redcostscores[ind1] < varprio->redcostscores[ind2] )
    1254 return -1;
    1255 else if( varprio->redcostscores[ind1] > varprio->redcostscores[ind2] )
    1256 return 1;
    1257 }
    1258
    1259 /* use pseudo cost scores if reduced costs are disabled or a tie was found */
    1260 if( varprio->usepscost )
    1261 {
    1262 assert(varprio->pscostscores != NULL);
    1263
    1264 /* prefer the variable with smaller pseudocost score */
    1265 if( varprio->pscostscores[ind1] < varprio->pscostscores[ind2] )
    1266 return -1;
    1267 else if( varprio->pscostscores[ind1] > varprio->pscostscores[ind2] )
    1268 return 1;
    1269 }
    1270
    1271 if( varprio->randscores[ind1] < varprio->randscores[ind2] )
    1272 return -1;
    1273 else if( varprio->randscores[ind1] > varprio->randscores[ind2] )
    1274 return 1;
    1275
    1276 return ind1 - ind2;
    1277}
    1278
    1279/** Compute the reduced cost score for this variable in the reference solution */
    1280static
    1282 SCIP* scip, /**< SCIP data structure */
    1283 SCIP_VAR* var, /**< the variable for which the score should be computed */
    1284 SCIP_Real refsolval, /**< solution value in reference solution */
    1285 SCIP_Bool uselocalredcost /**< should local reduced costs be used for generic (un)fixing? */
    1286 )
    1287{
    1288 SCIP_Real bestbound;
    1289 SCIP_Real redcost;
    1290 SCIP_Real score;
    1291 assert(scip != NULL);
    1292 assert(var != NULL);
    1293
    1294 /* prefer column variables */
    1296 return SCIPinfinity(scip);
    1297
    1298 if( ! uselocalredcost )
    1299 {
    1300 redcost = SCIPvarGetBestRootRedcost(var);
    1301
    1302 bestbound = SCIPvarGetBestRootSol(var);
    1303
    1304 /* using global reduced costs, the two factors yield a nonnegative score within tolerances */
    1305 assert(SCIPisDualfeasZero(scip, redcost)
    1306 || (SCIPisDualfeasNegative(scip, redcost) && ! SCIPisFeasPositive(scip, refsolval - bestbound))
    1307 || (SCIPisDualfeasPositive(scip, redcost) && ! SCIPisFeasNegative(scip, refsolval - bestbound)));
    1308 }
    1309 else
    1310 {
    1311 /* this can be safely asserted here, since the heuristic would not reach this point, otherwise */
    1312 assert(SCIPhasCurrentNodeLP(scip));
    1314
    1315 redcost = SCIPgetVarRedcost(scip, var);
    1316
    1317 bestbound = SCIPvarGetLPSol(var);
    1318 }
    1319
    1320 assert(! SCIPisInfinity(scip, REALABS(bestbound)));
    1321 assert(SCIPisDualfeasZero(scip, redcost) || SCIPisFeasIntegral(scip, bestbound));
    1322
    1323 score = redcost * (refsolval - bestbound);
    1324
    1325 /* max out numerical inaccuracies from global scores */
    1326 if( ! uselocalredcost )
    1327 score = MAX(score, 0.0);
    1328
    1329 return score;
    1330}
    1331
    1332/** get the pseudo cost score of this variable with respect to the reference solution */
    1333static
    1335 SCIP* scip, /**< SCIP data structure */
    1336 SCIP_VAR* var, /**< the variable for which the score should be computed */
    1337 SCIP_Real refsolval, /**< solution value in reference solution */
    1338 SCIP_Bool uselocallpsol /**< should local LP solution be used? */
    1339 )
    1340{
    1341 SCIP_Real soldiff;
    1342
    1343 assert(scip != NULL);
    1344 assert(var != NULL);
    1345
    1346 /* variables that aren't LP columns have no pseudocost score */
    1348 return 0.0;
    1349
    1350 soldiff = refsolval - (uselocallpsol ? SCIPvarGetLPSol(var) : SCIPvarGetRootSol(var));
    1351
    1352 /* the score is 0.0 if the values are equal */
    1353 if( SCIPisFeasZero(scip, soldiff) )
    1354 return 0.0;
    1355 else
    1356 return SCIPgetVarPseudocostVal(scip, var, soldiff);
    1357}
    1358
    1359/** add variable and solution value to buffer data structure for variable fixings. The method checks if
    1360 * the value still lies within the variable bounds. The value stays unfixed otherwise.
    1361 */
    1362static
    1364 SCIP* scip, /**< SCIP data structure */
    1365 SCIP_VAR* var, /**< (source) SCIP variable that should be added to the buffer */
    1366 SCIP_Real val, /**< fixing value for this variable */
    1367 SCIP_VAR** varbuf, /**< variable buffer to store variables that should be fixed */
    1368 SCIP_Real* valbuf, /**< value buffer to store fixing values */
    1369 int* nfixings, /**< pointer to number of fixed buffer variables, will be increased by 1 */
    1370 SCIP_Bool integer /**< is this an integer variable? */
    1371 )
    1372{
    1373 assert(integer == (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY || SCIPvarGetType(var) == SCIP_VARTYPE_INTEGER));
    1374 assert(!integer || SCIPisFeasIntegral(scip, val));
    1375 assert(*nfixings < SCIPgetNVars(scip));
    1376
    1377 /* round the value to its nearest integer */
    1378 if( integer )
    1379 val = SCIPfloor(scip, val + 0.5);
    1380
    1381 /* only add fixing if it is still valid within the global variable bounds. Invalidity
    1382 * of this solution value may come from a dual reduction that was performed after the solution from which
    1383 * this value originated was found
    1384 */
    1385 if( SCIPvarGetLbGlobal(var) <= val && val <= SCIPvarGetUbGlobal(var) )
    1386 {
    1387 varbuf[*nfixings] = var;
    1388 valbuf[*nfixings] = val;
    1389 ++(*nfixings);
    1390 }
    1391}
    1392
    1393/** query neighborhood for a reference solution for further fixings */
    1394static
    1396 SCIP* scip, /**< SCIP data structure */
    1397 NH* neighborhood, /**< ALNS neighborhood data structure */
    1398 SCIP_SOL** solptr /**< solution pointer */
    1399 )
    1400{
    1401 assert(solptr != NULL);
    1402 assert(scip != NULL);
    1403 assert(neighborhood != NULL);
    1404
    1405 *solptr = NULL;
    1406 if( neighborhood->nhrefsol != NULL )
    1407 {
    1408 SCIP_RESULT result;
    1409 SCIP_CALL( neighborhood->nhrefsol(scip, neighborhood, solptr, &result) );
    1410
    1411 if( result == SCIP_DIDNOTFIND )
    1412 *solptr = NULL;
    1413 else
    1414 assert(*solptr != NULL);
    1415 }
    1416
    1417 return SCIP_OKAY;
    1418}
    1419
    1420/** fix additional variables found in feasible reference solution if the ones that the neighborhood found were not enough
    1421 *
    1422 * use not always the best solution for the values, but a reference solution provided by the neighborhood itself
    1423 *
    1424 * @note it may happen that the target fixing rate is not completely reached. This is the case if intermediate,
    1425 * dual reductions render the solution values of the reference solution infeasible for
    1426 * the current, global variable bounds.
    1427 */
    1428static
    1430 SCIP* scip, /**< SCIP data structure */
    1431 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
    1432 SCIP_SOL* refsol, /**< feasible reference solution for more variable fixings */
    1433 SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
    1434 SCIP_Real* valbuf, /**< buffer array to store fixing values */
    1435 int* nfixings, /**< pointer to store the number of fixings */
    1436 int ntargetfixings, /**< number of required target fixings */
    1437 SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
    1438 )
    1439{
    1440 VARPRIO varprio;
    1441 SCIP_VAR** vars;
    1442 SCIP_Real* redcostscores;
    1443 SCIP_Real* pscostscores;
    1444 SCIP_Real* solvals;
    1445 SCIP_RANDNUMGEN* rng;
    1446 SCIP_VAR** unfixedvars;
    1447 SCIP_Bool* isfixed;
    1448 int* distances;
    1449 int* perm;
    1450 SCIP_Real* randscores;
    1451 int nbinvars;
    1452 int nintvars;
    1453 int nbinintvars;
    1454 int nvars;
    1455 int b;
    1456 int nvarstoadd;
    1457 int nunfixedvars;
    1458
    1459 assert(scip != NULL);
    1460 assert(varbuf != NULL);
    1461 assert(nfixings != NULL);
    1462 assert(success != NULL);
    1463 assert(heurdata != NULL);
    1464 assert(refsol != NULL);
    1465
    1466 *success = FALSE;
    1467
    1468 /* if the user parameter forbids more fixings, return immediately */
    1469 if( ! heurdata->domorefixings )
    1470 return SCIP_OKAY;
    1471
    1472 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    1473
    1474 nbinintvars = nbinvars + nintvars;
    1475
    1476 if( ntargetfixings >= nbinintvars )
    1477 return SCIP_OKAY;
    1478
    1479 /* determine the number of required additional fixings */
    1480 nvarstoadd = ntargetfixings - *nfixings;
    1481 if( nvarstoadd == 0 )
    1482 return SCIP_OKAY;
    1483
    1484 varprio.usedistances = heurdata->usedistances && (*nfixings >= 1);
    1485 varprio.useredcost = heurdata->useredcost;
    1486 varprio.usepscost = heurdata->usepscost;
    1487 varprio.scip = scip;
    1488 rng = SCIPbanditGetRandnumgen(heurdata->bandit);
    1489 assert(rng != NULL);
    1490
    1491 SCIP_CALL( SCIPallocBufferArray(scip, &randscores, nbinintvars) );
    1492 SCIP_CALL( SCIPallocBufferArray(scip, &perm, nbinintvars) );
    1493 SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
    1494 SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, nbinintvars) );
    1495 SCIP_CALL( SCIPallocBufferArray(scip, &solvals, nbinintvars) );
    1496 SCIP_CALL( SCIPallocBufferArray(scip, &isfixed, nbinintvars) );
    1497 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
    1498 SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, nbinintvars) );
    1499
    1500 /* initialize variable graph distances from already fixed variables */
    1501 if( varprio.usedistances )
    1502 {
    1503 SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, varbuf, *nfixings, distances, INT_MAX, INT_MAX, ntargetfixings) );
    1504 }
    1505 else
    1506 {
    1507 /* initialize all equal distances to make them irrelevant */
    1508 BMSclearMemoryArray(distances, nbinintvars);
    1509 }
    1510
    1511 BMSclearMemoryArray(isfixed, nbinintvars);
    1512
    1513 /* mark binary and integer variables if they are fixed */
    1514 for( b = 0; b < *nfixings; ++b )
    1515 {
    1516 int probindex;
    1517
    1518 assert(varbuf[b] != NULL);
    1519 probindex = SCIPvarGetProbindex(varbuf[b]);
    1520 assert(probindex >= 0);
    1521
    1522 if( probindex < nbinintvars )
    1523 isfixed[probindex] = TRUE;
    1524 }
    1525
    1526 SCIP_CALL( SCIPgetSolVals(scip, refsol, nbinintvars, vars, solvals) );
    1527
    1528 /* assign scores to unfixed every discrete variable of the problem */
    1529 nunfixedvars = 0;
    1530 for( b = 0; b < nbinintvars; ++b )
    1531 {
    1532 SCIP_VAR* var = vars[b];
    1533
    1534 /* filter fixed variables */
    1535 if( isfixed[b] )
    1536 continue;
    1537
    1538 /* filter variables with a solution value outside its global bounds */
    1539 if( solvals[b] < SCIPvarGetLbGlobal(var) - 0.5 || solvals[b] > SCIPvarGetUbGlobal(var) + 0.5 )
    1540 continue;
    1541
    1542 /* filter variables with a fractional solution value
    1543 * (could be a solution that was found before variables were upgraded to integral type)
    1544 */
    1545 if( !SCIPisFeasIntegral(scip, solvals[b]) )
    1546 continue;
    1547
    1548 redcostscores[nunfixedvars] = getVariableRedcostScore(scip, var, solvals[b], heurdata->uselocalredcost);
    1549 pscostscores[nunfixedvars] = getVariablePscostScore(scip, var, solvals[b], heurdata->uselocalredcost);
    1550
    1551 unfixedvars[nunfixedvars] = var;
    1552 perm[nunfixedvars] = nunfixedvars;
    1553 randscores[nunfixedvars] = SCIPrandomGetReal(rng, 0.0, 1.0);
    1554
    1555 /* these assignments are based on the fact that nunfixedvars <= b */
    1556 solvals[nunfixedvars] = solvals[b];
    1557 distances[nunfixedvars] = distances[b];
    1558
    1559 SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
    1560 SCIPvarGetName(var), distances[nunfixedvars], redcostscores[nunfixedvars],
    1561 pscostscores[nunfixedvars], randscores[nunfixedvars]);
    1562
    1563 nunfixedvars++;
    1564 }
    1565
    1566 /* use selection algorithm (order of the variables does not matter) for quickly completing the fixing */
    1567 varprio.randscores = randscores;
    1568 varprio.distances = distances;
    1569 varprio.redcostscores = redcostscores;
    1570 varprio.pscostscores = pscostscores;
    1571
    1572 /* select the first nvarstoadd many variables according to the score */
    1573 if( nvarstoadd < nunfixedvars )
    1574 SCIPselectInd(perm, sortIndCompAlns, &varprio, nvarstoadd, nunfixedvars);
    1575 else
    1576 nvarstoadd = nunfixedvars;
    1577
    1578 /* loop over the first elements of the selection defined in permutation. They represent the best variables */
    1579 for( b = 0; b < nvarstoadd; ++b )
    1580 {
    1581 int permindex = perm[b];
    1582 assert(permindex >= 0);
    1583 assert(permindex < nunfixedvars);
    1584
    1585 tryAdd2variableBuffer(scip, unfixedvars[permindex], solvals[permindex], varbuf, valbuf, nfixings, TRUE);
    1586 }
    1587
    1588 *success = TRUE;
    1589
    1590 /* free buffer arrays */
    1591 SCIPfreeBufferArray(scip, &pscostscores);
    1592 SCIPfreeBufferArray(scip, &unfixedvars);
    1593 SCIPfreeBufferArray(scip, &isfixed);
    1594 SCIPfreeBufferArray(scip, &solvals);
    1595 SCIPfreeBufferArray(scip, &redcostscores);
    1596 SCIPfreeBufferArray(scip, &distances);
    1597 SCIPfreeBufferArray(scip, &perm);
    1598 SCIPfreeBufferArray(scip, &randscores);
    1599
    1600 return SCIP_OKAY;
    1601}
    1602
    1603/** create the bandit algorithm for the heuristic depending on the user parameter */
    1604static
    1606 SCIP* scip, /**< SCIP data structure */
    1607 SCIP_HEURDATA* heurdata, /**< heuristic data structure */
    1608 SCIP_Real* priorities, /**< call priorities for active neighborhoods */
    1609 unsigned int initseed /**< initial random seed */
    1610 )
    1611{
    1612 switch (heurdata->banditalgo)
    1613 {
    1614 case 'u':
    1615 SCIP_CALL( SCIPcreateBanditUcb(scip, &heurdata->bandit, priorities,
    1616 heurdata->ucb_alpha, heurdata->nactiveneighborhoods, initseed) );
    1617 break;
    1618
    1619 case 'e':
    1620 SCIP_CALL( SCIPcreateBanditExp3(scip, &heurdata->bandit, priorities,
    1621 heurdata->exp3_gamma, heurdata->exp3_beta, heurdata->nactiveneighborhoods, initseed) );
    1622 break;
    1623
    1624 case 'i':
    1625 SCIP_CALL( SCIPcreateBanditExp3IX(scip, &heurdata->bandit, priorities,
    1626 heurdata->nactiveneighborhoods, initseed) );
    1627 break;
    1628
    1629 case 'g':
    1630 SCIP_CALL( SCIPcreateBanditEpsgreedy(scip, &heurdata->bandit, priorities,
    1631 heurdata->epsgreedy_eps, FALSE, FALSE, 0.9, 0, heurdata->nactiveneighborhoods, initseed) );
    1632 break;
    1633
    1634 default:
    1635 SCIPerrorMessage("Unknown bandit parameter %c\n", heurdata->banditalgo);
    1636 return SCIP_INVALIDDATA;
    1637 }
    1638
    1639 return SCIP_OKAY;
    1640}
    1641
    1642/*
    1643 * Callback methods of primal heuristic
    1644 */
    1645
    1646/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    1647static
    1649{ /*lint --e{715}*/
    1650 assert(scip != NULL);
    1651 assert(heur != NULL);
    1652 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    1653
    1654 /* call inclusion method of primal heuristic */
    1656
    1657 return SCIP_OKAY;
    1658}
    1659
    1660/** unfix some of the variables because there are too many fixed
    1661 *
    1662 * a variable is ideally unfixed if it is close to other unfixed variables
    1663 * and fixing it has a high reduced cost impact
    1664 */
    1665static
    1667 SCIP* scip, /**< SCIP data structure */
    1668 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
    1669 SCIP_VAR** varbuf, /**< buffer array to store variables to fix */
    1670 SCIP_Real* valbuf, /**< buffer array to store fixing values */
    1671 int* nfixings, /**< pointer to store the number of fixings */
    1672 int ntargetfixings, /**< number of required target fixings */
    1673 SCIP_Bool* success /**< pointer to store whether the target fixings have been successfully reached */
    1674 )
    1675{
    1676 VARPRIO varprio;
    1677 SCIP_Real* redcostscores;
    1678 SCIP_Real* pscostscores;
    1679 SCIP_Real* randscores;
    1680 SCIP_VAR** unfixedvars;
    1681 SCIP_VAR** varbufcpy;
    1682 SCIP_Real* valbufcpy;
    1683 SCIP_Bool* isfixedvar;
    1684 SCIP_VAR** vars;
    1685 SCIP_RANDNUMGEN* rng;
    1686 int* distances;
    1687 int* fixeddistances;
    1688 int* perm;
    1689 int nvars;
    1690 int i;
    1691 int nbinintvars;
    1692 int nunfixed;
    1693
    1694 *success = FALSE;
    1695
    1696 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    1697 if( nbinintvars == 0 )
    1698 return SCIP_OKAY;
    1699
    1700 assert(*nfixings > 0);
    1701
    1702 nvars = SCIPgetNVars(scip);
    1703 SCIP_CALL( SCIPallocBufferArray(scip, &isfixedvar, nvars) );
    1704 SCIP_CALL( SCIPallocBufferArray(scip, &unfixedvars, nbinintvars) );
    1705 SCIP_CALL( SCIPallocBufferArray(scip, &distances, nvars) );
    1706 SCIP_CALL( SCIPallocBufferArray(scip, &fixeddistances, *nfixings) );
    1707 SCIP_CALL( SCIPallocBufferArray(scip, &redcostscores, *nfixings) );
    1708 SCIP_CALL( SCIPallocBufferArray(scip, &randscores, *nfixings) );
    1709 SCIP_CALL( SCIPallocBufferArray(scip, &perm, *nfixings) );
    1710 SCIP_CALL( SCIPallocBufferArray(scip, &pscostscores, *nfixings) );
    1711
    1712 SCIP_CALL( SCIPduplicateBufferArray(scip, &varbufcpy, varbuf, *nfixings) );
    1713 SCIP_CALL( SCIPduplicateBufferArray(scip, &valbufcpy, valbuf, *nfixings) );
    1714
    1715 /*
    1716 * collect the unfixed binary and integer variables
    1717 */
    1718 BMSclearMemoryArray(isfixedvar, nvars);
    1719 /* loop over fixed variables and mark their respective positions as fixed */
    1720 for( i = 0; i < *nfixings; ++i )
    1721 {
    1722 int probindex = SCIPvarGetProbindex(varbuf[i]);
    1723
    1724 assert(probindex >= 0);
    1725
    1726 isfixedvar[probindex] = TRUE;
    1727 }
    1728
    1729 nunfixed = 0;
    1730 vars = SCIPgetVars(scip);
    1731 /* collect unfixed binary and integer variables */
    1732 for( i = 0; i < nbinintvars; ++i )
    1733 {
    1734 if( ! isfixedvar[i] )
    1735 unfixedvars[nunfixed++] = vars[i];
    1736 }
    1737
    1738 varprio.usedistances = heurdata->usedistances && nunfixed > 0;
    1739
    1740 /* collect distances of all fixed variables from those that are not fixed */
    1741 if( varprio.usedistances )
    1742 {
    1743 SCIP_CALL( SCIPvariablegraphBreadthFirst(scip, NULL, unfixedvars, nunfixed, distances, INT_MAX, INT_MAX, INT_MAX) );
    1744
    1745 for( i = 0; i < *nfixings; ++i )
    1746 {
    1747 int probindex = SCIPvarGetProbindex(varbuf[i]);
    1748 if( probindex >= 0 )
    1749 fixeddistances[i] = distances[probindex];
    1750 }
    1751 }
    1752 else
    1753 {
    1754 BMSclearMemoryArray(fixeddistances, *nfixings);
    1755 }
    1756
    1757 /* collect reduced cost scores of the fixings and assign random scores */
    1758 rng = SCIPbanditGetRandnumgen(heurdata->bandit);
    1759 for( i = 0; i < *nfixings; ++i )
    1760 {
    1761 SCIP_VAR* fixedvar = varbuf[i];
    1762 SCIP_Real fixval = valbuf[i];
    1763
    1764 /* use negative reduced cost and pseudo cost scores to prefer variable fixings with small score */
    1765 redcostscores[i] = - getVariableRedcostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
    1766 pscostscores[i] = - getVariablePscostScore(scip, fixedvar, fixval, heurdata->uselocalredcost);
    1767 randscores[i] = SCIPrandomGetReal(rng, 0.0, 1.0);
    1768 perm[i] = i;
    1769
    1770 SCIPdebugMsg(scip, "Var <%s> scores: dist %3d, red cost %15.9g, pscost %15.9g rand %6.4f\n",
    1771 SCIPvarGetName(fixedvar), fixeddistances[i], redcostscores[i], pscostscores[i], randscores[i]);
    1772 }
    1773
    1774 varprio.distances = fixeddistances;
    1775 varprio.randscores = randscores;
    1776 varprio.redcostscores = redcostscores;
    1777 varprio.pscostscores = pscostscores;
    1778 varprio.useredcost = heurdata->useredcost;
    1779 varprio.usepscost = heurdata->usepscost;
    1780 varprio.scip = scip;
    1781
    1782 /* scores are assigned in such a way that variables with a smaller score should be fixed last */
    1783 SCIPselectDownInd(perm, sortIndCompAlns, &varprio, ntargetfixings, *nfixings);
    1784
    1785 /* bring the desired variables to the front of the array */
    1786 for( i = 0; i < ntargetfixings; ++i )
    1787 {
    1788 valbuf[i] = valbufcpy[perm[i]];
    1789 varbuf[i] = varbufcpy[perm[i]];
    1790 }
    1791
    1792 *nfixings = ntargetfixings;
    1793
    1794 /* free the buffer arrays in reverse order of allocation */
    1795 SCIPfreeBufferArray(scip, &valbufcpy);
    1796 SCIPfreeBufferArray(scip, &varbufcpy);
    1797 SCIPfreeBufferArray(scip, &pscostscores);
    1798 SCIPfreeBufferArray(scip, &perm);
    1799 SCIPfreeBufferArray(scip, &randscores);
    1800 SCIPfreeBufferArray(scip, &redcostscores);
    1801 SCIPfreeBufferArray(scip, &fixeddistances);
    1802 SCIPfreeBufferArray(scip, &distances);
    1803 SCIPfreeBufferArray(scip, &unfixedvars);
    1804 SCIPfreeBufferArray(scip, &isfixedvar);
    1805
    1806 *success = TRUE;
    1807
    1808 return SCIP_OKAY;
    1809}
    1810
    1811/** call variable fixing callback for this neighborhood and orchestrate additional variable fixings, if necessary */
    1812static
    1814 SCIP* scip, /**< SCIP data structure */
    1815 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
    1816 NH* neighborhood, /**< neighborhood data structure */
    1817 SCIP_VAR** varbuf, /**< buffer array to keep variables that should be fixed */
    1818 SCIP_Real* valbuf, /**< buffer array to keep fixing values */
    1819 int* nfixings, /**< pointer to store the number of variable fixings */
    1820 SCIP_RESULT* result /**< pointer to store the result of the fixing operation */
    1821 )
    1822{
    1823 int ntargetfixings;
    1824 int nmaxfixings;
    1825 int nminfixings;
    1826 int nbinintvars;
    1827
    1828 assert(scip != NULL);
    1829 assert(neighborhood != NULL);
    1830 assert(varbuf != NULL);
    1831 assert(valbuf != NULL);
    1832 assert(nfixings != NULL);
    1833 assert(result != NULL);
    1834
    1835 *nfixings = 0;
    1836
    1837 *result = SCIP_DIDNOTRUN;
    1838 ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip)));
    1839
    1840 if( neighborhood->varfixings != NULL )
    1841 {
    1842 SCIP_CALL( neighborhood->varfixings(scip, neighborhood, varbuf, valbuf, nfixings, result) );
    1843
    1844 if( *result != SCIP_SUCCESS )
    1845 return SCIP_OKAY;
    1846 }
    1847 else if( ntargetfixings == 0 )
    1848 {
    1849 *result = SCIP_SUCCESS;
    1850
    1851 return SCIP_OKAY;
    1852 }
    1853
    1854 /* compute upper and lower target fixing limits using tolerance parameters */
    1855 assert(neighborhood->varfixings == NULL || *result != SCIP_DIDNOTRUN);
    1856 nbinintvars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    1857 ntargetfixings = (int)(neighborhood->fixingrate.targetfixingrate * nbinintvars);
    1858 nminfixings = (int)((neighborhood->fixingrate.targetfixingrate - heurdata->fixtol) * nbinintvars);
    1859 nminfixings = MAX(nminfixings, 0);
    1860 nmaxfixings = (int)((neighborhood->fixingrate.targetfixingrate + heurdata->unfixtol) * nbinintvars);
    1861 nmaxfixings = MIN(nmaxfixings, nbinintvars);
    1862
    1863 SCIPdebugMsg(scip, "Neighborhood Fixings/Target: %d / %d <= %d <= %d\n",*nfixings, nminfixings, ntargetfixings, nmaxfixings);
    1864
    1865 /* if too few fixings, use a strategy to select more variable fixings: randomized, LP graph, ReducedCost based, mix */
    1866 if( (*result == SCIP_SUCCESS || *result == SCIP_DIDNOTRUN) && (*nfixings < nminfixings) )
    1867 {
    1868 SCIP_Bool success;
    1869 SCIP_SOL* refsol;
    1870
    1871 /* get reference solution from neighborhood */
    1872 SCIP_CALL( neighborhoodGetRefsol(scip, neighborhood, &refsol) );
    1873
    1874 /* try to fix more variables based on the reference solution */
    1875 if( refsol != NULL )
    1876 {
    1877 SCIP_CALL( alnsFixMoreVariables(scip, heurdata, refsol, varbuf, valbuf, nfixings, ntargetfixings, &success) );
    1878 }
    1879 else
    1880 success = FALSE;
    1881
    1882 if( success )
    1883 *result = SCIP_SUCCESS;
    1884 else if( *result == SCIP_SUCCESS )
    1885 *result = SCIP_DIDNOTFIND;
    1886 else
    1887 *result = SCIP_DIDNOTRUN;
    1888
    1889 SCIPdebugMsg(scip, "After additional fixings: %d / %d\n",*nfixings, ntargetfixings);
    1890 }
    1891 else if( (SCIP_Real)(*nfixings) > nmaxfixings )
    1892 {
    1893 SCIP_Bool success;
    1894
    1895 SCIP_CALL( alnsUnfixVariables(scip, heurdata, varbuf, valbuf, nfixings, ntargetfixings, &success) );
    1896
    1897 assert(success);
    1898 *result = SCIP_SUCCESS;
    1899 SCIPdebugMsg(scip, "Unfixed variables, fixed variables remaining: %d\n", ntargetfixings);
    1900 }
    1901 else
    1902 {
    1903 SCIPdebugMsg(scip, "No additional fixings performed\n");
    1904 }
    1905
    1906 return SCIP_OKAY;
    1907}
    1908
    1909/** change the sub-SCIP by restricting variable domains, changing objective coefficients, or adding constraints */
    1910static
    1912 SCIP* sourcescip, /**< source SCIP data structure */
    1913 SCIP* targetscip, /**< target SCIP data structure */
    1914 NH* neighborhood, /**< neighborhood */
    1915 SCIP_VAR** targetvars, /**< array of target SCIP variables aligned with source SCIP variables */
    1916 int* ndomchgs, /**< pointer to store the number of variable domain changes */
    1917 int* nchgobjs, /**< pointer to store the number of changed objective coefficients */
    1918 int* naddedconss, /**< pointer to store the number of added constraints */
    1919 SCIP_Bool* success /**< pointer to store whether the sub-SCIP has been successfully modified */
    1920 )
    1921{
    1922 assert(sourcescip != NULL);
    1923 assert(targetscip != NULL);
    1924 assert(neighborhood != NULL);
    1925 assert(targetvars != NULL);
    1926 assert(ndomchgs != NULL);
    1927 assert(nchgobjs != NULL);
    1928 assert(naddedconss != NULL);
    1929 assert(success != NULL);
    1930
    1931 *success = FALSE;
    1932 *ndomchgs = 0;
    1933 *nchgobjs = 0;
    1934 *naddedconss = 0;
    1935
    1936 /* call the change sub-SCIP callback of the neighborhood */
    1937 if( neighborhood->changesubscip != NULL )
    1938 {
    1939 SCIP_CALL( neighborhood->changesubscip(sourcescip, targetscip, neighborhood, targetvars, ndomchgs, nchgobjs, naddedconss, success) );
    1940 }
    1941 else
    1942 {
    1943 *success = TRUE;
    1944 }
    1945
    1946 return SCIP_OKAY;
    1947}
    1948
    1949/** set sub-SCIP solving limits */
    1950static
    1952 SCIP* subscip, /**< SCIP data structure */
    1953 SOLVELIMITS* solvelimits /**< pointer to solving limits data structure */
    1954 )
    1955{
    1956 assert(subscip != NULL);
    1957 assert(solvelimits != NULL);
    1958
    1959 assert(solvelimits->nodelimit >= solvelimits->stallnodes);
    1960
    1961 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/nodes", solvelimits->nodelimit) );
    1962 SCIP_CALL( SCIPsetLongintParam(subscip, "limits/stallnodes", solvelimits->stallnodes) );
    1963 SCIP_CALL( SCIPsetRealParam(subscip, "limits/time", solvelimits->timelimit) );
    1964 SCIP_CALL( SCIPsetRealParam(subscip, "limits/memory", solvelimits->memorylimit) );
    1965
    1966 return SCIP_OKAY;
    1967}
    1968
    1969/** determine limits for a sub-SCIP */
    1970static
    1972 SCIP* scip, /**< SCIP data structure */
    1973 SCIP_HEUR* heur, /**< this heuristic */
    1974 SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
    1975 SCIP_Bool* runagain /**< can we solve another sub-SCIP with these limits */
    1976 )
    1977{
    1978 SCIP_HEURDATA* heurdata;
    1979 SCIP_Real initfactor;
    1980 SCIP_Real nodesquot;
    1981 SCIP_Bool avoidmemout;
    1982
    1983 assert(scip != NULL);
    1984 assert(heur != NULL);
    1985 assert(solvelimits != NULL);
    1986 assert(runagain != NULL);
    1987
    1988 heurdata = SCIPheurGetData(heur);
    1989
    1990 /* check whether there is enough time and memory left */
    1991 SCIP_CALL( SCIPgetRealParam(scip, "limits/time", &solvelimits->timelimit) );
    1992 if( ! SCIPisInfinity(scip, solvelimits->timelimit) )
    1993 solvelimits->timelimit -= SCIPgetSolvingTime(scip);
    1994 SCIP_CALL( SCIPgetRealParam(scip, "limits/memory", &solvelimits->memorylimit) );
    1995 SCIP_CALL( SCIPgetBoolParam(scip, "misc/avoidmemout", &avoidmemout) );
    1996
    1997 /* substract the memory already used by the main SCIP and the estimated memory usage of external software */
    1998 if( ! SCIPisInfinity(scip, solvelimits->memorylimit) )
    1999 {
    2000 solvelimits->memorylimit -= SCIPgetMemUsed(scip)/1048576.0;
    2001 solvelimits->memorylimit -= SCIPgetMemExternEstim(scip)/1048576.0;
    2002 }
    2003
    2004 /* abort if no time is left or not enough memory (we don't abort in this case if misc_avoidmemout == FALSE)
    2005 * to create a copy of SCIP, including external memory usage */
    2006 if( solvelimits->timelimit <= 0.0 || (avoidmemout && solvelimits->memorylimit <= 2.0*SCIPgetMemExternEstim(scip)/1048576.0) )
    2007 *runagain = FALSE;
    2008
    2009 nodesquot = heurdata->nodesquot;
    2010
    2011 /* if the heuristic is used to measure all rewards, it will always be penalized here */
    2012 if( heurdata->rewardfile == NULL )
    2013 nodesquot *= (SCIPheurGetNBestSolsFound(heur) + 1.0)/(SCIPheurGetNCalls(heur) + 1.0);
    2014
    2015 nodesquot = MAX(nodesquot, heurdata->nodesquotmin);
    2016
    2017 /* calculate the search node limit of the heuristic */
    2018 solvelimits->stallnodes = (SCIP_Longint)(nodesquot * SCIPgetNNodes(scip));
    2019 solvelimits->stallnodes += heurdata->nodesoffset;
    2020 solvelimits->stallnodes -= heurdata->usednodes;
    2021 solvelimits->stallnodes -= 100 * SCIPheurGetNCalls(heur);
    2022 solvelimits->stallnodes = MIN(heurdata->maxnodes, solvelimits->stallnodes);
    2023
    2024 /* use a smaller budget if not all neighborhoods have been initialized yet */
    2025 assert(heurdata->ninitneighborhoods >= 0);
    2026 initfactor = (heurdata->nactiveneighborhoods - heurdata->ninitneighborhoods + 1.0) / (heurdata->nactiveneighborhoods + 1.0);
    2027 solvelimits->stallnodes = (SCIP_Longint)(solvelimits->stallnodes * initfactor);
    2028 solvelimits->nodelimit = (SCIP_Longint)(heurdata->maxnodes);
    2029
    2030 /* check whether we have enough nodes left to call subproblem solving */
    2031 if( solvelimits->stallnodes < heurdata->targetnodes )
    2032 *runagain = FALSE;
    2033
    2034 return SCIP_OKAY;
    2035}
    2036
    2037/** return the bandit algorithm that should be used */
    2038static
    2040 SCIP_HEURDATA* heurdata /**< heuristic data of the ALNS neighborhood */
    2041 )
    2042{
    2043 assert(heurdata != NULL);
    2044 return heurdata->bandit;
    2045}
    2046
    2047/** select a neighborhood depending on the selected bandit algorithm */
    2048static
    2050 SCIP* scip, /**< SCIP data structure */
    2051 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
    2052 int* neighborhoodidx /**< pointer to store the selected neighborhood index */
    2053 )
    2054{
    2055 SCIP_BANDIT* bandit;
    2056 assert(scip != NULL);
    2057 assert(heurdata != NULL);
    2058 assert(neighborhoodidx != NULL);
    2059
    2060 *neighborhoodidx = -1;
    2061
    2062 bandit = getBandit(heurdata);
    2063
    2064 SCIP_CALL( SCIPbanditSelect(bandit, neighborhoodidx) );
    2065 assert(*neighborhoodidx >= 0);
    2066
    2067 return SCIP_OKAY;
    2068}
    2069
    2070/** Calculate reward based on the selected reward measure */
    2071static
    2073 SCIP* scip, /**< SCIP data structure */
    2074 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
    2075 NH_STATS* runstats, /**< run statistics */
    2076 SCIP_Real* rewardptr /**< array to store the computed rewards, total and individual */
    2077 )
    2078{
    2079 SCIP_Real reward = 0.0;
    2080 SCIP_Real effort;
    2081 int ndiscretevars;
    2082
    2083 memset(rewardptr, 0, sizeof(*rewardptr)*(int)NREWARDTYPES);
    2084
    2085 assert(rewardptr != NULL);
    2086 assert(runstats->usednodes >= 0);
    2087 assert(runstats->nfixings >= 0);
    2088
    2089 effort = runstats->usednodes / 100.0;
    2090
    2091 ndiscretevars = SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip);
    2092 /* assume that every fixed variable linearly reduces the subproblem complexity */
    2093 if( ndiscretevars > 0 )
    2094 {
    2095 effort = (1.0 - (runstats->nfixings / (SCIP_Real)ndiscretevars)) * effort;
    2096 }
    2097 assert(rewardptr != NULL);
    2098
    2099 /* a positive reward is only assigned if a new incumbent solution was found */
    2100 if( runstats->nbestsolsfound > 0 )
    2101 {
    2102 SCIP_Real rewardcontrol = heurdata->rewardcontrol;
    2103
    2104 SCIP_Real lb;
    2105 SCIP_Real ub;
    2106
    2107 /* the indicator function is simply 1.0 */
    2108 rewardptr[REWARDTYPE_BESTSOL] = 1.0;
    2109 rewardptr[REWARDTYPE_NOSOLPENALTY] = 1.0;
    2110
    2111 ub = runstats->newupperbound;
    2112 lb = SCIPgetLowerbound(scip);
    2113
    2114 /* compute the closed gap reward */
    2115 if( SCIPisEQ(scip, ub, lb) || SCIPisInfinity(scip, runstats->oldupperbound) )
    2116 rewardptr[REWARDTYPE_CLOSEDGAP] = 1.0;
    2117 else
    2118 {
    2119 rewardptr[REWARDTYPE_CLOSEDGAP] = (runstats->oldupperbound - ub) / (runstats->oldupperbound - lb);
    2120 }
    2121
    2122 /* the reward is a convex combination of the best solution reward and the reward for the closed gap */
    2123 reward = rewardcontrol * rewardptr[REWARDTYPE_BESTSOL] + (1.0 - rewardcontrol) * rewardptr[REWARDTYPE_CLOSEDGAP];
    2124
    2125 /* optionally, scale the reward by the involved effort */
    2126 if( heurdata->scalebyeffort )
    2127 reward /= (effort + 1.0);
    2128
    2129 /* add the baseline and rescale the reward into the interval [baseline, 1.0] */
    2130 reward = heurdata->rewardbaseline + (1.0 - heurdata->rewardbaseline) * reward;
    2131 }
    2132 else
    2133 {
    2134 /* linearly decrease the reward based on the number of nodes spent */
    2135 SCIP_Real maxeffort = heurdata->targetnodes;
    2136 SCIP_Real usednodes = runstats->usednodes;
    2137
    2138 if( ndiscretevars > 0 )
    2139 usednodes *= (1.0 - (runstats->nfixings / (SCIP_Real)ndiscretevars));
    2140
    2141 rewardptr[REWARDTYPE_NOSOLPENALTY] = 1 - (usednodes / maxeffort);
    2142 rewardptr[REWARDTYPE_NOSOLPENALTY] = MAX(0.0, rewardptr[REWARDTYPE_NOSOLPENALTY]);
    2143 reward = heurdata->rewardbaseline * rewardptr[REWARDTYPE_NOSOLPENALTY];
    2144 }
    2145
    2146 rewardptr[REWARDTYPE_TOTAL] = reward;
    2147
    2148 return SCIP_OKAY;
    2149}
    2150
    2151/** update internal bandit algorithm statistics for future draws */
    2152static
    2154 SCIP* scip, /**< SCIP data structure */
    2155 SCIP_HEURDATA* heurdata, /**< heuristic data of the ALNS neighborhood */
    2156 SCIP_Real reward, /**< measured reward */
    2157 int neighborhoodidx /**< the neighborhood that was chosen */
    2158 )
    2159{
    2160 SCIP_BANDIT* bandit;
    2161 assert(scip != NULL);
    2162 assert(heurdata != NULL);
    2163 assert(neighborhoodidx >= 0);
    2164 assert(neighborhoodidx < heurdata->nactiveneighborhoods);
    2165
    2166 bandit = getBandit(heurdata);
    2167
    2168 SCIPdebugMsg(scip, "Rewarding bandit algorithm action %d with reward %.2f\n", neighborhoodidx, reward);
    2169 SCIP_CALL( SCIPbanditUpdate(bandit, neighborhoodidx, reward) );
    2170
    2171 return SCIP_OKAY;
    2172}
    2173
    2174/** set up the sub-SCIP parameters, objective cutoff, and solution limits */
    2175static
    2177 SCIP* scip, /**< SCIP data structure */
    2178 SCIP* subscip, /**< sub-SCIP data structure */
    2179 SCIP_VAR** subvars, /**< array of sub-SCIP variables in the order of the main SCIP */
    2180 SOLVELIMITS* solvelimits, /**< pointer to solving limits data structure */
    2181 SCIP_HEUR* heur, /**< this heuristic */
    2182 SCIP_Bool objchgd /**< did the objective change between the source and the target SCIP? */
    2183 )
    2184{
    2185 SCIP_HEURDATA* heurdata;
    2186 SCIP_Real cutoff;
    2187 SCIP_Real upperbound;
    2188
    2189 heurdata = SCIPheurGetData(heur);
    2190
    2191 /* do not abort subproblem on CTRL-C */
    2192 SCIP_CALL( SCIPsetBoolParam(subscip, "misc/catchctrlc", FALSE) );
    2193
    2194 /* disable output to console unless we are in debug mode */
    2195 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 0) );
    2196
    2197 /* disable statistic timing inside sub SCIP */
    2198 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", FALSE) );
    2199
    2200#ifdef ALNS_SUBSCIPOUTPUT
    2201 SCIP_CALL( SCIPsetIntParam(subscip, "display/verblevel", 5) );
    2202 SCIP_CALL( SCIPsetIntParam(subscip, "display/freq", 1) );
    2203 /* enable statistic timing inside sub SCIP */
    2204 SCIP_CALL( SCIPsetBoolParam(subscip, "timing/statistictiming", TRUE) );
    2205#endif
    2206
    2207 SCIP_CALL( SCIPsetIntParam(subscip, "limits/bestsol", heurdata->nsolslim) );
    2208
    2209 /* forbid recursive call of heuristics and separators solving subMIPs */
    2210 if( ! heurdata->usesubscipheurs )
    2211 {
    2212 SCIP_CALL( SCIPsetSubscipsOff(subscip, TRUE) );
    2213 }
    2214
    2215 /* disable cutting plane separation */
    2217
    2218 /* disable expensive presolving */
    2220
    2221 /* use best estimate node selection */
    2222 if( SCIPfindNodesel(subscip, "estimate") != NULL && ! SCIPisParamFixed(subscip, "nodeselection/estimate/stdpriority") )
    2223 {
    2224 SCIP_CALL( SCIPsetIntParam(subscip, "nodeselection/estimate/stdpriority", INT_MAX/4) );
    2225 }
    2226
    2227 /* use inference branching */
    2228 if( SCIPfindBranchrule(subscip, "inference") != NULL && ! SCIPisParamFixed(subscip, "branching/inference/priority") )
    2229 {
    2230 SCIP_CALL( SCIPsetIntParam(subscip, "branching/inference/priority", INT_MAX/4) );
    2231 }
    2232
    2233 /* enable conflict analysis and restrict conflict pool */
    2234 if( ! SCIPisParamFixed(subscip, "conflict/enable") )
    2235 {
    2236 SCIP_CALL( SCIPsetBoolParam(subscip, "conflict/enable", TRUE) );
    2237 }
    2238
    2239 if( !SCIPisParamFixed(subscip, "conflict/useboundlp") )
    2240 {
    2241 SCIP_CALL( SCIPsetCharParam(subscip, "conflict/useboundlp", 'o') );
    2242 }
    2243
    2244 if( ! SCIPisParamFixed(subscip, "conflict/maxstoresize") )
    2245 {
    2246 SCIP_CALL( SCIPsetIntParam(subscip, "conflict/maxstoresize", 100) );
    2247 }
    2248
    2249 /* speed up sub-SCIP by not checking dual LP feasibility */
    2250 SCIP_CALL( SCIPsetBoolParam(subscip, "lp/checkdualfeas", FALSE) );
    2251
    2252 /* add an objective cutoff */
    2254 {
    2255 upperbound = SCIPgetUpperbound(scip) - SCIPsumepsilon(scip);
    2256 if( ! SCIPisInfinity(scip, -1.0 * SCIPgetLowerbound(scip)) )
    2257 {
    2258 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip)
    2259 + heurdata->minimprove * SCIPgetLowerbound(scip);
    2260 }
    2261 else
    2262 {
    2263 if( SCIPgetUpperbound(scip) >= 0 )
    2264 cutoff = (1 - heurdata->minimprove) * SCIPgetUpperbound(scip);
    2265 else
    2266 cutoff = (1 + heurdata->minimprove) * SCIPgetUpperbound(scip);
    2267 }
    2268 cutoff = MIN(upperbound, cutoff);
    2269
    2270 if( SCIPisObjIntegral(scip) )
    2271 cutoff = SCIPfloor(scip, cutoff);
    2272
    2273 SCIPdebugMsg(scip, "Sub-SCIP cutoff: %15.9" SCIP_REAL_FORMAT " (%15.9" SCIP_REAL_FORMAT " in original space)\n",
    2274 cutoff, SCIPretransformObj(scip, cutoff));
    2275
    2276 /* if the objective changed between the source and the target SCIP, encode the cutoff as a constraint */
    2277 if( ! objchgd )
    2278 {
    2279 SCIP_CALL( SCIPsetObjlimit(subscip, cutoff) );
    2280
    2281 SCIPdebugMsg(scip, "Cutoff added as Objective Limit\n");
    2282 }
    2283 else
    2284 {
    2285 SCIP_CONS* objcons;
    2286 int nvars;
    2287 SCIP_VAR** vars;
    2288 int i;
    2289
    2290 vars = SCIPgetVars(scip);
    2291 nvars = SCIPgetNVars(scip);
    2292
    2293 SCIP_CALL( SCIPcreateConsLinear(subscip, &objcons, "objbound_of_origscip", 0, NULL, NULL, -SCIPinfinity(subscip), cutoff,
    2295 for( i = 0; i < nvars; ++i)
    2296 {
    2297 if( ! SCIPisFeasZero(subscip, SCIPvarGetObj(vars[i])) )
    2298 {
    2299 assert(subvars[i] != NULL);
    2300 SCIP_CALL( SCIPaddCoefLinear(subscip, objcons, subvars[i], SCIPvarGetObj(vars[i])) );
    2301 }
    2302 }
    2303 SCIP_CALL( SCIPaddCons(subscip, objcons) );
    2304 SCIP_CALL( SCIPreleaseCons(subscip, &objcons) );
    2305
    2306 SCIPdebugMsg(scip, "Cutoff added as constraint\n");
    2307 }
    2308 }
    2309
    2310 /* set solve limits for sub-SCIP */
    2311 SCIP_CALL( setLimits(subscip, solvelimits) );
    2312
    2313 /* change random seed of sub-SCIP */
    2314 if( heurdata->subsciprandseeds )
    2315 {
    2316 SCIP_CALL( SCIPsetIntParam(subscip, "randomization/randomseedshift", (int)SCIPheurGetNCalls(heur)) );
    2317 }
    2318
    2319 SCIPdebugMsg(scip, "Solve Limits: %lld (%lld) nodes (stall nodes), %.1f sec., %d sols\n",
    2320 solvelimits->nodelimit, solvelimits->stallnodes, solvelimits->timelimit, heurdata->nsolslim);
    2321
    2322 return SCIP_OKAY;
    2323}
    2324
    2325/** execution method of primal heuristic */
    2326static
    2328{ /*lint --e{715}*/
    2329 SCIP_HEURDATA* heurdata;
    2330 SCIP_VAR** varbuf;
    2331 SCIP_Real* valbuf;
    2332 SCIP_VAR** vars;
    2333 SCIP_VAR** subvars;
    2334 NH_STATS runstats[NNEIGHBORHOODS];
    2335 SCIP_STATUS subscipstatus[NNEIGHBORHOODS];
    2336 SCIP* subscip = NULL;
    2337
    2338 int nfixings;
    2339 int nvars;
    2340 int neighborhoodidx;
    2341 int ntries;
    2342 SCIP_Bool tryagain;
    2343 NH* neighborhood;
    2344 SOLVELIMITS solvelimits;
    2345 SCIP_Bool success;
    2346 SCIP_Bool run;
    2347 SCIP_Bool allrewardsmode;
    2348 SCIP_Real rewards[NNEIGHBORHOODS][NREWARDTYPES] = {{0}};
    2349 int banditidx;
    2350
    2351 int i;
    2352
    2353 heurdata = SCIPheurGetData(heur);
    2354 assert(heurdata != NULL);
    2355
    2356 *result = SCIP_DIDNOTRUN;
    2357
    2358 if( heurdata->nactiveneighborhoods == 0 )
    2359 return SCIP_OKAY;
    2360
    2361 /* we only allow to run multiple times at a node during the root */
    2362 if( (heurtiming & SCIP_HEURTIMING_DURINGLPLOOP) && (SCIPgetDepth(scip) > 0 || !heurdata->initduringroot) )
    2363 return SCIP_OKAY;
    2364
    2365 /* update internal incumbent solution */
    2366 if( SCIPgetBestSol(scip) != heurdata->lastcallsol )
    2367 {
    2368 heurdata->lastcallsol = SCIPgetBestSol(scip);
    2369 heurdata->firstcallthissol = SCIPheurGetNCalls(heur);
    2370 }
    2371
    2372 /* do not run more than a user-defined number of times on each incumbent (-1: no limit) */
    2373 if( heurdata->maxcallssamesol != -1 )
    2374 {
    2375 SCIP_Longint samesollimit = (heurdata->maxcallssamesol > 0) ?
    2376 heurdata->maxcallssamesol :
    2377 heurdata->nactiveneighborhoods;
    2378
    2379 if( SCIPheurGetNCalls(heur) - heurdata->firstcallthissol >= samesollimit )
    2380 {
    2381 SCIPdebugMsg(scip, "Heuristic already called %" SCIP_LONGINT_FORMAT " times on current incumbent\n", SCIPheurGetNCalls(heur) - heurdata->firstcallthissol);
    2382 return SCIP_OKAY;
    2383 }
    2384 }
    2385
    2386 /* wait for a sufficient number of nodes since last incumbent solution */
    2387 if( SCIPgetDepth(scip) > 0 && SCIPgetBestSol(scip) != NULL
    2388 && (SCIPgetNNodes(scip) - SCIPsolGetNodenum(SCIPgetBestSol(scip))) < heurdata->waitingnodes )
    2389 {
    2390 SCIPdebugMsg(scip, "Waiting nodes not satisfied\n");
    2391 return SCIP_OKAY;
    2392 }
    2393
    2394 run = TRUE;
    2395 /* check if budget allows a run of the next selected neighborhood */
    2396 SCIP_CALL( determineLimits(scip, heur, &solvelimits, &run) );
    2397 SCIPdebugMsg(scip, "Budget check: %" SCIP_LONGINT_FORMAT " (%" SCIP_LONGINT_FORMAT ") %s\n", solvelimits.nodelimit, heurdata->targetnodes, run ? "passed" : "must wait");
    2398
    2399 if( ! run )
    2400 return SCIP_OKAY;
    2401
    2402 /* delay the heuristic if local reduced costs should be used for generic variable unfixing */
    2403 if( heurdata->uselocalredcost && (nodeinfeasible || ! SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL) )
    2404 {
    2405 *result = SCIP_DELAYED;
    2406
    2407 return SCIP_OKAY;
    2408 }
    2409
    2410 allrewardsmode = heurdata->rewardfile != NULL;
    2411
    2412 /* apply some other rules for a fair all rewards mode; in normal execution mode, neighborhoods are iterated through */
    2413 if( allrewardsmode )
    2414 {
    2415 /* most neighborhoods require an incumbent solution */
    2416 if( SCIPgetNSols(scip) < 2 )
    2417 {
    2418 SCIPdebugMsg(scip, "Not enough solutions for all rewards mode\n");
    2419 return SCIP_OKAY;
    2420 }
    2421
    2422 /* if the node is infeasible, or has no LP solution, which is required by some neighborhoods
    2423 * if we are not in all rewards mode, the neighborhoods delay themselves individually
    2424 */
    2425 if( nodeinfeasible || ! SCIPhasCurrentNodeLP(scip) || SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
    2426 {
    2427 SCIPdebugMsg(scip, "Delay ALNS heuristic until a feasible node with optimally solved LP relaxation\n");
    2428 *result = SCIP_DELAYED;
    2429 return SCIP_OKAY;
    2430 }
    2431 }
    2432
    2433 /* use the neighborhood that requested a delay or select the next neighborhood to run based on the selected bandit algorithm */
    2434 if( heurdata->currneighborhood >= 0 )
    2435 {
    2436 assert(! allrewardsmode);
    2437 banditidx = heurdata->currneighborhood;
    2438 SCIPdebugMsg(scip, "Select delayed neighborhood %d (was delayed %d times)\n", banditidx, heurdata->ndelayedcalls);
    2439 }
    2440 else
    2441 {
    2442 SCIP_CALL( selectNeighborhood(scip, heurdata, &banditidx) );
    2443 SCIPdebugMsg(scip, "Selected neighborhood %d with bandit algorithm\n", banditidx);
    2444 }
    2445
    2446 /* in all rewards mode, we simply loop over all heuristics */
    2447 if( ! allrewardsmode )
    2448 neighborhoodidx = banditidx;
    2449 else
    2450 neighborhoodidx = 0;
    2451
    2452 assert(0 <= neighborhoodidx && neighborhoodidx < NNEIGHBORHOODS);
    2453 assert(heurdata->nactiveneighborhoods > neighborhoodidx);
    2454
    2455 /* allocate memory for variable fixings buffer */
    2456 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    2457 SCIP_CALL( SCIPallocBufferArray(scip, &varbuf, nvars) );
    2458 SCIP_CALL( SCIPallocBufferArray(scip, &valbuf, nvars) );
    2459 SCIP_CALL( SCIPallocBufferArray(scip, &subvars, nvars) );
    2460
    2461 /* initialize neighborhood statistics for a run */
    2462 ntries = 1;
    2463 do
    2464 {
    2465 SCIP_HASHMAP* varmapf;
    2466 SCIP_EVENTHDLR* eventhdlr;
    2467 SCIP_EVENTDATA eventdata;
    2468 char probnamesuffix[SCIP_MAXSTRLEN];
    2469 SCIP_Real allfixingrate;
    2470 int ndomchgs;
    2471 int nchgobjs;
    2472 int naddedconss;
    2473 int v;
    2474 SCIP_RETCODE retcode;
    2475 SCIP_RESULT fixresult;
    2476
    2477 tryagain = FALSE;
    2478 neighborhood = heurdata->neighborhoods[neighborhoodidx];
    2479 SCIPdebugMsg(scip, "Running '%s' neighborhood %d\n", neighborhood->name, neighborhoodidx);
    2480
    2481 initRunStats(scip, &runstats[neighborhoodidx]);
    2482 rewards[neighborhoodidx][REWARDTYPE_TOTAL] = 0.0;
    2483
    2484 subscipstatus[neighborhoodidx] = SCIP_STATUS_UNKNOWN;
    2485 SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.setupclock) );
    2486
    2487 /* determine variable fixings and objective coefficients of this neighborhood */
    2488 SCIP_CALL( neighborhoodFixVariables(scip, heurdata, neighborhood, varbuf, valbuf, &nfixings, &fixresult) );
    2489
    2490 SCIPdebugMsg(scip, "Fix %d/%d variables, result code %d\n", nfixings, nvars,fixresult);
    2491
    2492 /* Fixing was not successful, either because the fixing rate was not reached (and no additional variable
    2493 * prioritization was used), or the neighborhood requested a delay, e.g., because no LP relaxation solution exists
    2494 * at the current node
    2495 *
    2496 * The ALNS heuristic keeps a delayed neighborhood active and delays itself.
    2497 */
    2498 if( fixresult != SCIP_SUCCESS )
    2499 {
    2500 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
    2501
    2502 /* to determine all rewards, we cannot delay neighborhoods */
    2503 if( allrewardsmode )
    2504 {
    2505 if( ntries == heurdata->nactiveneighborhoods )
    2506 break;
    2507
    2508 neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
    2509 ntries++;
    2510 tryagain = TRUE;
    2511
    2512 continue;
    2513 }
    2514
    2515 /* delay the heuristic along with the selected neighborhood
    2516 *
    2517 * if the neighborhood has been delayed for too many consecutive calls, the delay is treated as a failure */
    2518 if( fixresult == SCIP_DELAYED )
    2519 {
    2520 if( heurdata->ndelayedcalls > (SCIPheurGetFreq(heur) / 4 + 1) )
    2521 {
    2522 resetCurrentNeighborhood(heurdata);
    2523
    2524 /* use SCIP_DIDNOTFIND to penalize the neighborhood with a bad reward */
    2525 fixresult = SCIP_DIDNOTFIND;
    2526 }
    2527 else if( heurdata->currneighborhood == -1 )
    2528 {
    2529 heurdata->currneighborhood = neighborhoodidx;
    2530 heurdata->ndelayedcalls = 1;
    2531 }
    2532 else
    2533 {
    2534 heurdata->ndelayedcalls++;
    2535 }
    2536 }
    2537
    2538 if( fixresult == SCIP_DIDNOTRUN )
    2539 {
    2540 if( ntries < heurdata->nactiveneighborhoods )
    2541 {
    2542 SCIP_CALL( updateBanditAlgorithm(scip, heurdata, 0.0, neighborhoodidx) );
    2543 SCIP_CALL( selectNeighborhood(scip, heurdata, &neighborhoodidx) );
    2544 ntries++;
    2545 tryagain = TRUE;
    2546
    2547 SCIPdebugMsg(scip, "Neighborhood cannot run -> try next neighborhood %d\n", neighborhoodidx);
    2548 continue;
    2549 }
    2550 else
    2551 break;
    2552 }
    2553
    2554 assert(fixresult == SCIP_DIDNOTFIND || fixresult == SCIP_DELAYED);
    2555 *result = fixresult;
    2556 break;
    2557 }
    2558
    2559 *result = SCIP_DIDNOTFIND;
    2560
    2561 neighborhood->stats.nfixings += nfixings;
    2562 runstats[neighborhoodidx].nfixings = nfixings;
    2563
    2564 SCIP_CALL( SCIPcreate(&subscip) );
    2565 SCIP_CALL( SCIPhashmapCreate(&varmapf, SCIPblkmem(scip), nvars) );
    2566 (void) SCIPsnprintf(probnamesuffix, SCIP_MAXSTRLEN, "alns_%s", neighborhood->name);
    2567
    2568 /* todo later: run global propagation for this set of fixings */
    2569 SCIP_CALL( SCIPcopyLargeNeighborhoodSearch(scip, subscip, varmapf, probnamesuffix, varbuf, valbuf, nfixings, FALSE, heurdata->copycuts, &success, NULL) );
    2570
    2571 /* store sub-SCIP variables in array for faster access */
    2572 for( v = 0; v < nvars; ++v )
    2573 {
    2574 subvars[v] = (SCIP_VAR*)SCIPhashmapGetImage(varmapf, (void *)vars[v]);
    2575 }
    2576
    2577 SCIPhashmapFree(&varmapf);
    2578
    2579 /* let the neighborhood add additional constraints, or restrict domains */
    2580 SCIP_CALL( neighborhoodChangeSubscip(scip, subscip, neighborhood, subvars, &ndomchgs, &nchgobjs, &naddedconss, &success) );
    2581
    2582 if( ! success )
    2583 {
    2584 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
    2585
    2586 if( ! allrewardsmode || ntries == heurdata->nactiveneighborhoods )
    2587 break;
    2588
    2589 neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
    2590 ntries++;
    2591 tryagain = TRUE;
    2592
    2593 SCIP_CALL( SCIPfree(&subscip) );
    2594
    2595 continue;
    2596 }
    2597
    2598 /* set up sub-SCIP parameters */
    2599 SCIP_CALL( setupSubScip(scip, subscip, subvars, &solvelimits, heur, nchgobjs > 0) );
    2600
    2601 /* copy the necessary data into the event data to create new solutions */
    2602 eventdata.nodelimit = solvelimits.nodelimit; /*lint !e644*/
    2603 eventdata.lplimfac = heurdata->lplimfac;
    2604 eventdata.heur = heur;
    2605 eventdata.sourcescip = scip;
    2606 eventdata.subvars = subvars;
    2607 eventdata.runstats = &runstats[neighborhoodidx];
    2608 eventdata.allrewardsmode = allrewardsmode;
    2609
    2610 /* include an event handler to transfer solutions into the main SCIP */
    2611 SCIP_CALL( SCIPincludeEventhdlrBasic(subscip, &eventhdlr, EVENTHDLR_NAME, EVENTHDLR_DESC, eventExecAlns, NULL) );
    2612
    2613 /* transform the problem before catching the events */
    2614 SCIP_CALL( SCIPtransformProb(subscip) );
    2615 SCIP_CALL( SCIPcatchEvent(subscip, SCIP_EVENTTYPE_ALNS, eventhdlr, &eventdata, NULL) );
    2616
    2617 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.setupclock) );
    2618
    2619 SCIP_CALL( SCIPstartClock(scip, neighborhood->stats.submipclock) );
    2620
    2621 /* set up sub-SCIP and run presolving */
    2622 retcode = SCIPpresolve(subscip);
    2623 if( retcode != SCIP_OKAY )
    2624 {
    2625 SCIPwarningMessage(scip, "Error while presolving subproblem in ALNS heuristic; sub-SCIP terminated with code <%d>\n", retcode);
    2626 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.submipclock) );
    2627
    2628 SCIPABORT(); /*lint --e{527}*/
    2629 break;
    2630 }
    2631
    2632 /* was presolving successful enough regarding fixings? otherwise, terminate */
    2633 allfixingrate = (SCIPgetNOrigVars(subscip) - SCIPgetNVars(subscip)) / (SCIP_Real)SCIPgetNOrigVars(subscip);
    2634
    2635 /* additional variables added in presolving may lead to the subSCIP having more variables than the original */
    2636 allfixingrate = MAX(allfixingrate, 0.0);
    2637
    2638 if( allfixingrate >= neighborhood->fixingrate.targetfixingrate / 2.0 )
    2639 {
    2640 /* run sub-SCIP for the given budget, and collect statistics */
    2641 SCIP_CALL_ABORT( SCIPsolve(subscip) );
    2642 }
    2643 else
    2644 {
    2645 SCIPdebugMsg(scip, "Fixed only %.3f of all variables after presolving -> do not solve sub-SCIP\n", allfixingrate);
    2646 }
    2647
    2648#ifdef ALNS_SUBSCIPOUTPUT
    2649 SCIP_CALL( SCIPprintStatistics(subscip, NULL) );
    2650#endif
    2651
    2652 SCIP_CALL( SCIPstopClock(scip, neighborhood->stats.submipclock) );
    2653
    2654 /* update statistics based on the sub-SCIP run results */
    2655 updateRunStats(&runstats[neighborhoodidx], subscip);
    2656 subscipstatus[neighborhoodidx] = SCIPgetStatus(subscip);
    2657 SCIPdebugMsg(scip, "Status of sub-SCIP run: %d\n", subscipstatus[neighborhoodidx]);
    2658
    2659 SCIP_CALL( getReward(scip, heurdata, &runstats[neighborhoodidx], rewards[neighborhoodidx]) );
    2660
    2661 /* in all rewards mode, continue with the next neighborhood */
    2662 if( allrewardsmode && ntries < heurdata->nactiveneighborhoods )
    2663 {
    2664 neighborhoodidx = (neighborhoodidx + 1) % heurdata->nactiveneighborhoods;
    2665 ntries++;
    2666 tryagain = TRUE;
    2667
    2668 SCIP_CALL( SCIPfree(&subscip) );
    2669 }
    2670 }
    2671 while( tryagain && ! SCIPisStopped(scip) );
    2672
    2673 if( subscip != NULL )
    2674 {
    2675 SCIP_CALL( SCIPfree(&subscip) );
    2676 }
    2677
    2678 SCIPfreeBufferArray(scip, &subvars);
    2679 SCIPfreeBufferArray(scip, &valbuf);
    2680 SCIPfreeBufferArray(scip, &varbuf);
    2681
    2682 /* update bandit index that may have changed unless we are in all rewards mode */
    2683 if( ! allrewardsmode )
    2684 banditidx = neighborhoodidx;
    2685
    2686 if( *result != SCIP_DELAYED )
    2687 {
    2688 /* decrease the number of neighborhoods that have not been initialized */
    2689 if( neighborhood->stats.nruns == 0 )
    2690 --heurdata->ninitneighborhoods;
    2691
    2692 heurdata->usednodes += runstats[banditidx].usednodes;
    2693
    2694 /* determine the success of this neighborhood, and update the target fixing rate for the next time */
    2695 updateNeighborhoodStats(&runstats[banditidx], heurdata->neighborhoods[banditidx], subscipstatus[banditidx]);
    2696
    2697 /* adjust the fixing rate for this neighborhood
    2698 * make no adjustments in all rewards mode, because this only affects 1 of 8 heuristics
    2699 */
    2700 if( heurdata->adjustfixingrate && ! allrewardsmode )
    2701 {
    2702 SCIPdebugMsg(scip, "Update fixing rate: %.2f\n", heurdata->neighborhoods[banditidx]->fixingrate.targetfixingrate);
    2703 updateFixingRate(heurdata->neighborhoods[banditidx], subscipstatus[banditidx], &runstats[banditidx]);
    2704 SCIPdebugMsg(scip, "New fixing rate: %.2f\n", heurdata->neighborhoods[banditidx]->fixingrate.targetfixingrate);
    2705 }
    2706 /* similarly, update the minimum improvement for the ALNS heuristic */
    2707 if( heurdata->adjustminimprove )
    2708 {
    2709 SCIPdebugMsg(scip, "Update Minimum Improvement: %.4f\n", heurdata->minimprove);
    2710 updateMinimumImprovement(heurdata, subscipstatus[banditidx], &runstats[banditidx]);
    2711 SCIPdebugMsg(scip, "--> %.4f\n", heurdata->minimprove);
    2712 }
    2713
    2714 /* update the target node limit based on the status of the selected algorithm */
    2715 if( heurdata->adjusttargetnodes && SCIPheurGetNCalls(heur) >= heurdata->nactiveneighborhoods )
    2716 {
    2717 updateTargetNodeLimit(heurdata, &runstats[banditidx], subscipstatus[banditidx]);
    2718 }
    2719
    2720 /* update the bandit algorithm by the measured reward */
    2721 SCIP_CALL( updateBanditAlgorithm(scip, heurdata, rewards[banditidx][REWARDTYPE_TOTAL], banditidx) );
    2722
    2723 resetCurrentNeighborhood(heurdata);
    2724 }
    2725
    2726 /* write single, measured rewards and the bandit index to the reward file */
    2727 if( allrewardsmode )
    2728 {
    2729 int j;
    2730 for( j = 0; j < (int)NREWARDTYPES; j++ )
    2731 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
    2732 fprintf(heurdata->rewardfile, "%.4f,", rewards[i][j]);
    2733
    2734 fprintf(heurdata->rewardfile, "%d\n", banditidx);
    2735 }
    2736
    2737 return SCIP_OKAY;
    2738}
    2739
    2740/** callback to collect variable fixings of RENS */
    2741static
    2742DECL_VARFIXINGS(varFixingsRens)
    2743{ /*lint --e{715}*/
    2744 int nbinvars;
    2745 int nintvars;
    2746 SCIP_VAR** vars;
    2747 int i;
    2748 int *fracidx = NULL;
    2749 SCIP_Real* frac = NULL;
    2750 int nfracs;
    2751
    2752 assert(scip != NULL);
    2753 assert(varbuf != NULL);
    2754 assert(nfixings != NULL);
    2755 assert(valbuf != NULL);
    2756
    2757 *result = SCIP_DELAYED;
    2758
    2759 if( ! SCIPhasCurrentNodeLP(scip) )
    2760 return SCIP_OKAY;
    2762 return SCIP_OKAY;
    2763
    2764 *result = SCIP_DIDNOTRUN;
    2765
    2766 /* get variable information */
    2767 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    2768
    2769 /* return if no binary or integer variables are present */
    2770 if( nbinvars + nintvars == 0 )
    2771 return SCIP_OKAY;
    2772
    2773 SCIP_CALL( SCIPallocBufferArray(scip, &fracidx, nbinvars + nintvars) );
    2774 SCIP_CALL( SCIPallocBufferArray(scip, &frac, nbinvars + nintvars) );
    2775
    2776 /* loop over binary and integer variables; determine those that should be fixed in the sub-SCIP */
    2777 for( nfracs = 0, i = 0; i < nbinvars + nintvars; ++i )
    2778 {
    2779 SCIP_VAR* var;
    2780 SCIP_Real lpsolval;
    2781
    2782 var = vars[i];
    2784 assert((i < nbinvars) == (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY));
    2785 lpsolval = SCIPvarGetLPSol(var);
    2786
    2787 /* fix all binary and integer variables with integer LP solution value */
    2788 if( SCIPisFeasIntegral(scip, lpsolval) )
    2789 {
    2790 tryAdd2variableBuffer(scip, var, lpsolval, varbuf, valbuf, nfixings, TRUE);
    2791 }
    2792 else
    2793 {
    2794 frac[nfracs] = SCIPfrac(scip, lpsolval);
    2795 frac[nfracs] = MIN(frac[nfracs], 1.0 - frac[nfracs]);
    2796 fracidx[nfracs++] = i;
    2797 }
    2798 }
    2799
    2800 /* do some additional fixing */
    2801 if( *nfixings < neighborhood->fixingrate.targetfixingrate * (nbinvars + nintvars) && nfracs > 0 )
    2802 {
    2803 SCIPsortDownRealInt(frac, fracidx, nfracs);
    2804
    2805 /* prefer variables that are almost integer */
    2806 for( i = 0; i < nfracs && *nfixings < neighborhood->fixingrate.targetfixingrate * (nbinvars + nintvars); i++ )
    2807 {
    2808 tryAdd2variableBuffer(scip, vars[fracidx[i]], SCIPround(scip, SCIPvarGetLPSol(vars[fracidx[i]])), varbuf, valbuf, nfixings, TRUE);
    2809 }
    2810 }
    2811
    2812 SCIPfreeBufferArray(scip, &frac);
    2813 SCIPfreeBufferArray(scip, &fracidx);
    2814
    2815 *result = SCIP_SUCCESS;
    2816
    2817 return SCIP_OKAY;
    2818}
    2819
    2820/** callback for RENS subproblem changes */
    2821static
    2822DECL_CHANGESUBSCIP(changeSubscipRens)
    2823{ /*lint --e{715}*/
    2824 SCIP_VAR** vars;
    2825 int nintvars;
    2826 int nbinvars;
    2827 int i;
    2828
    2829 assert(SCIPhasCurrentNodeLP(sourcescip));
    2830 assert(SCIPgetLPSolstat(sourcescip) == SCIP_LPSOLSTAT_OPTIMAL);
    2831
    2832 /* get variable information */
    2833 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    2834
    2835 /* restrict bounds of integer variables with fractional solution value */
    2836 for( i = nbinvars; i < nbinvars + nintvars; ++i )
    2837 {
    2838 SCIP_VAR* var = vars[i];
    2839 SCIP_Real lpsolval = SCIPgetSolVal(sourcescip, NULL, var);
    2840
    2841 if( subvars[i] == NULL )
    2842 continue;
    2843
    2844 if( ! SCIPisFeasIntegral(sourcescip, lpsolval) )
    2845 {
    2846 SCIP_Real newlb = SCIPfloor(sourcescip, lpsolval);
    2847 SCIP_Real newub = newlb + 1.0;
    2848
    2849 /* only count this as a domain change if the new lower and upper bound are a further restriction */
    2850 if( newlb > SCIPvarGetLbGlobal(subvars[i]) + 0.5 || newub < SCIPvarGetUbGlobal(subvars[i]) - 0.5 )
    2851 {
    2852 SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[i], newlb) );
    2853 SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[i], newub) );
    2854 (*ndomchgs)++;
    2855 }
    2856 }
    2857 }
    2858
    2859 *success = TRUE;
    2860
    2861 return SCIP_OKAY;
    2862}
    2863
    2864/** collect fixings by matching solution values in a collection of solutions for all binary and integer variables,
    2865 * or for a custom set of variables
    2866 */
    2867static
    2869 SCIP* scip, /**< SCIP data structure */
    2870 SCIP_SOL** sols, /**< array of 2 or more solutions. It is okay for the array to contain one element
    2871 * equal to NULL to represent the current LP solution */
    2872 int nsols, /**< number of solutions in the array */
    2873 SCIP_VAR** vars, /**< variable array for which solution values must agree */
    2874 int nvars, /**< number of variables, or -1 for all binary and integer variables */
    2875 SCIP_VAR** varbuf, /**< buffer storage for variable fixings */
    2876 SCIP_Real* valbuf, /**< buffer storage for fixing values */
    2877 int* nfixings /**< pointer to store the number of fixings */
    2878 )
    2879{
    2880 int v;
    2881 int nbinintvars;
    2882 SCIP_SOL* firstsol;
    2883
    2884 assert(scip != NULL);
    2885 assert(sols != NULL);
    2886 assert(nsols >= 2);
    2887 assert(varbuf != NULL);
    2888 assert(valbuf != NULL);
    2889 assert(nfixings != NULL);
    2890 assert(*nfixings == 0);
    2891
    2892 if( nvars == -1 || vars == NULL )
    2893 {
    2894 int nbinvars;
    2895 int nintvars;
    2896 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    2897 nbinintvars = nbinvars + nintvars;
    2898 nvars = nbinintvars;
    2899 }
    2900 firstsol = sols[0];
    2901 assert(nvars > 0);
    2902
    2903 /* loop over integer and binary variables and check if their solution values match in all solutions */
    2904 for( v = 0; v < nvars; ++v )
    2905 {
    2906 SCIP_VAR* var;
    2907 SCIP_Real solval;
    2908 int s;
    2909
    2910 var = vars[v];
    2912 assert((v < SCIPgetNBinVars(scip)) == (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY));
    2913 solval = SCIPgetSolVal(scip, firstsol, var);
    2914
    2915 /* determine if solution values match in all given solutions */
    2916 for( s = 1; s < nsols; ++s )
    2917 {
    2918 if( !SCIPisFeasZero(scip, solval - SCIPgetSolVal(scip, sols[s], var)) )
    2919 break;
    2920 }
    2921
    2922 /* if we did not break early, all solutions agree on the solution value of this variable */
    2923 if( s == nsols )
    2924 {
    2925 tryAdd2variableBuffer(scip, var, solval, varbuf, valbuf, nfixings, TRUE);
    2926 }
    2927 }
    2928
    2929 return SCIP_OKAY;
    2930}
    2931
    2932/** callback to collect variable fixings of RINS */
    2933static
    2934DECL_VARFIXINGS(varFixingsRins)
    2935{
    2936 /*lint --e{715}*/
    2937 int nbinvars;
    2938 int nintvars;
    2939 SCIP_VAR** vars;
    2940 SCIP_SOL* incumbent;
    2941 SCIP_SOL* sols[2];
    2942 assert(scip != NULL);
    2943 assert(varbuf != NULL);
    2944 assert(nfixings != NULL);
    2945 assert(valbuf != NULL);
    2946
    2947 *result = SCIP_DELAYED;
    2948
    2949 if( ! SCIPhasCurrentNodeLP(scip) )
    2950 return SCIP_OKAY;
    2952 return SCIP_OKAY;
    2953
    2954 *result = SCIP_DIDNOTRUN;
    2955
    2956 incumbent = SCIPgetBestSol(scip);
    2957 if( incumbent == NULL )
    2958 return SCIP_OKAY;
    2959
    2960 if( SCIPsolGetOrigin(incumbent) == SCIP_SOLORIGIN_ORIGINAL )
    2961 return SCIP_OKAY;
    2962
    2963 /* get variable information */
    2964 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    2965
    2966 /* return if no binary or integer variables are present */
    2967 if( nbinvars + nintvars == 0 )
    2968 return SCIP_OKAY;
    2969
    2970 /* incumbent is reference */
    2971 sols[0] = incumbent;
    2972 sols[1] = NULL;
    2973
    2974 SCIP_CALL( fixMatchingSolutionValues(scip, sols, 2, vars, nbinvars + nintvars, varbuf, valbuf, nfixings) );
    2975
    2976 *result = SCIP_SUCCESS;
    2977
    2978 return SCIP_OKAY;
    2979}
    2980
    2981/** initialization callback for crossover when a new problem is read */
    2982static
    2983DECL_NHINIT(nhInitCrossover)
    2984{ /*lint --e{715}*/
    2985 DATA_CROSSOVER* data;
    2986
    2987 data = neighborhood->data.crossover;
    2988 assert(data != NULL);
    2989
    2990 if( data->rng != NULL )
    2991 SCIPfreeRandom(scip, &data->rng);
    2992
    2993 data->selsol = NULL;
    2994
    2995 SCIP_CALL( SCIPcreateRandom(scip, &data->rng, CROSSOVERSEED + (unsigned int)SCIPgetNVars(scip), TRUE) );
    2996
    2997 return SCIP_OKAY;
    2998}
    2999
    3000/** deinitialization callback for crossover when exiting a problem */
    3001static
    3002DECL_NHEXIT(nhExitCrossover)
    3003{ /*lint --e{715}*/
    3004 DATA_CROSSOVER* data;
    3005 data = neighborhood->data.crossover;
    3006
    3007 assert(neighborhood != NULL);
    3008 assert(data->rng != NULL);
    3009
    3010 SCIPfreeRandom(scip, &data->rng);
    3011
    3012 return SCIP_OKAY;
    3013}
    3014
    3015/** deinitialization callback for crossover before SCIP is freed */
    3016static
    3017DECL_NHFREE(nhFreeCrossover)
    3018{ /*lint --e{715}*/
    3019 assert(neighborhood->data.crossover != NULL);
    3020 SCIPfreeBlockMemory(scip, &neighborhood->data.crossover);
    3021
    3022 return SCIP_OKAY;
    3023}
    3024
    3025/** callback to collect variable fixings of crossover */
    3026static
    3027DECL_VARFIXINGS(varFixingsCrossover)
    3028{ /*lint --e{715}*/
    3029 DATA_CROSSOVER* data;
    3030 SCIP_RANDNUMGEN* rng;
    3031 SCIP_SOL** sols;
    3032 SCIP_SOL** scipsols;
    3033 int nsols;
    3034 int lastdraw;
    3035 assert(scip != NULL);
    3036 assert(varbuf != NULL);
    3037 assert(nfixings != NULL);
    3038 assert(valbuf != NULL);
    3039
    3040 data = neighborhood->data.crossover;
    3041
    3042 assert(data != NULL);
    3043 nsols = data->nsols;
    3044 data->selsol = NULL;
    3045
    3046 *result = SCIP_DIDNOTRUN;
    3047
    3048 /* return if the pool has not enough solutions */
    3049 if( nsols > SCIPgetNSols(scip) )
    3050 return SCIP_OKAY;
    3051
    3052 /* return if no binary or integer variables are present */
    3054 return SCIP_OKAY;
    3055
    3056 rng = data->rng;
    3057 lastdraw = SCIPgetNSols(scip);
    3058 SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
    3059 scipsols = SCIPgetSols(scip);
    3060
    3061 /* draw as many solutions from the pool as required by crossover, biased towards
    3062 * better solutions; therefore, the sorting of the solutions by objective is implicitly used
    3063 */
    3064 while( nsols > 0 )
    3065 {
    3066 /* no need for randomization anymore, exactly nsols many solutions remain for the selection */
    3067 if( lastdraw == nsols )
    3068 {
    3069 int s;
    3070
    3071 /* fill the remaining slots 0,...,nsols - 1 by the solutions at the same places */
    3072 for( s = 0; s < nsols; ++s )
    3073 sols[s] = scipsols[s];
    3074
    3075 nsols = 0;
    3076 }
    3077 else
    3078 {
    3079 int nextdraw;
    3080
    3081 assert(nsols < lastdraw);
    3082
    3083 /* draw from the lastdraw - nsols many solutions nsols - 1, ... lastdraw - 1 such that nsols many solution */
    3084 nextdraw = SCIPrandomGetInt(rng, nsols - 1, lastdraw - 1);
    3085 assert(nextdraw >= 0);
    3086
    3087 sols[nsols - 1] = scipsols[nextdraw];
    3088 nsols--;
    3089 lastdraw = nextdraw;
    3090 }
    3091 }
    3092
    3093 SCIP_CALL( fixMatchingSolutionValues(scip, sols, data->nsols, NULL, -1, varbuf, valbuf, nfixings) );
    3094
    3095 /* store best selected solution as reference solution */
    3096 data->selsol = sols[0];
    3097 assert(data->selsol != NULL);
    3098
    3099 *result = SCIP_SUCCESS;
    3100
    3101 SCIPfreeBufferArray(scip, &sols);
    3102
    3103 return SCIP_OKAY;
    3104}
    3105
    3106/** callback for crossover reference solution */
    3107static
    3108DECL_NHREFSOL(nhRefsolCrossover)
    3109{ /*lint --e{715}*/
    3110 DATA_CROSSOVER* data;
    3111
    3112 data = neighborhood->data.crossover;
    3113
    3114 if( data->selsol != NULL )
    3115 {
    3116 *solptr = data->selsol;
    3117 *result = SCIP_SUCCESS;
    3118 }
    3119 else
    3120 {
    3121 *result = SCIP_DIDNOTFIND;
    3122 }
    3123
    3124 return SCIP_OKAY;
    3125}
    3126
    3127/** initialization callback for mutation when a new problem is read */
    3128static
    3129DECL_NHINIT(nhInitMutation)
    3130{ /*lint --e{715}*/
    3131 DATA_MUTATION* data;
    3132 assert(scip != NULL);
    3133 assert(neighborhood != NULL);
    3134
    3135 SCIP_CALL( SCIPallocBlockMemory(scip, &neighborhood->data.mutation) );
    3136
    3137 data = neighborhood->data.mutation;
    3138 assert(data != NULL);
    3139
    3140 SCIP_CALL( SCIPcreateRandom(scip, &data->rng, MUTATIONSEED + (unsigned int)SCIPgetNVars(scip), TRUE) );
    3141
    3142 return SCIP_OKAY;
    3143}
    3144
    3145/** deinitialization callback for mutation when exiting a problem */
    3146static
    3147DECL_NHEXIT(nhExitMutation)
    3148{ /*lint --e{715}*/
    3149 DATA_MUTATION* data;
    3150 assert(scip != NULL);
    3151 assert(neighborhood != NULL);
    3152 data = neighborhood->data.mutation;
    3153 assert(data != NULL);
    3154
    3155 SCIPfreeRandom(scip, &data->rng);
    3156
    3157 SCIPfreeBlockMemory(scip, &neighborhood->data.mutation);
    3158
    3159 return SCIP_OKAY;
    3160}
    3161
    3162/** callback to collect variable fixings of mutation */
    3163static
    3164DECL_VARFIXINGS(varFixingsMutation)
    3165{ /*lint --e{715}*/
    3166 SCIP_RANDNUMGEN* rng;
    3167
    3168 SCIP_VAR** vars;
    3169 SCIP_VAR** varscpy;
    3170 int i;
    3171 int nvars;
    3172 int nbinvars;
    3173 int nintvars;
    3174 int nbinintvars;
    3175 int ntargetfixings;
    3176 SCIP_SOL* incumbentsol;
    3177 SCIP_Real targetfixingrate;
    3178
    3179 assert(scip != NULL);
    3180 assert(neighborhood != NULL);
    3181 assert(neighborhood->data.mutation != NULL);
    3182 assert(neighborhood->data.mutation->rng != NULL);
    3183 rng = neighborhood->data.mutation->rng;
    3184
    3185 *result = SCIP_DIDNOTRUN;
    3186
    3187 /* get the problem variables */
    3188 SCIP_CALL( SCIPgetVarsData(scip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    3189
    3190 nbinintvars = nbinvars + nintvars;
    3191 if( nbinintvars == 0 )
    3192 return SCIP_OKAY;
    3193
    3194 incumbentsol = SCIPgetBestSol(scip);
    3195 if( incumbentsol == NULL )
    3196 return SCIP_OKAY;
    3197
    3198 targetfixingrate = neighborhood->fixingrate.targetfixingrate;
    3199 ntargetfixings = (int)(targetfixingrate * nbinintvars) + 1;
    3200
    3201 /* don't continue if number of discrete variables is too small to reach target fixing rate */
    3202 if( nbinintvars <= ntargetfixings )
    3203 return SCIP_OKAY;
    3204
    3205 *result = SCIP_DIDNOTFIND;
    3206
    3207 /* copy variables into a buffer array */
    3208 SCIP_CALL( SCIPduplicateBufferArray(scip, &varscpy, vars, nbinintvars) );
    3209
    3210 /* partially perturb the array until the number of target fixings is reached */
    3211 for( i = 0; *nfixings < ntargetfixings && i < nbinintvars; ++i )
    3212 {
    3213 int randint = SCIPrandomGetInt(rng, i, nbinintvars - 1);
    3214 assert(randint < nbinintvars);
    3215
    3216 if( randint > i )
    3217 {
    3218 SCIPswapPointers((void**)&varscpy[i], (void**)&varscpy[randint]);
    3219 }
    3220 /* copy the selected variables and their solution values into the buffer */
    3221 tryAdd2variableBuffer(scip, varscpy[i], SCIPgetSolVal(scip, incumbentsol, varscpy[i]), varbuf, valbuf, nfixings, TRUE);
    3222 }
    3223
    3224 assert(i == nbinintvars || *nfixings == ntargetfixings);
    3225
    3226 /* Not reaching the number of target fixings means that there is a significant fraction (at least 1 - targetfixingrate)
    3227 * of variables for which the incumbent solution value does not lie within the global bounds anymore. This is a nonsuccess
    3228 * for the neighborhood (additional fixings are not possible), which is okay because the incumbent solution is
    3229 * significantly outdated
    3230 */
    3231 if( *nfixings == ntargetfixings )
    3232 *result = SCIP_SUCCESS;
    3233
    3234 /* free the buffer array */
    3235 SCIPfreeBufferArray(scip, &varscpy);
    3236
    3237 return SCIP_OKAY;
    3238}
    3239
    3240/** add local branching constraint */
    3241static
    3243 SCIP* sourcescip, /**< source SCIP data structure */
    3244 SCIP* targetscip, /**< target SCIP data structure */
    3245 SCIP_VAR** subvars, /**< array of sub SCIP variables in same order as source SCIP variables */
    3246 int distance, /**< right hand side of the local branching constraint */
    3247 SCIP_Bool* success, /**< pointer to store of a local branching constraint has been successfully added */
    3248 int* naddedconss /**< pointer to increase the number of added constraints */
    3249 )
    3250{
    3251 int nbinvars;
    3252 int i;
    3253 SCIP_SOL* referencesol;
    3254 SCIP_CONS* localbranchcons;
    3255 SCIP_VAR** vars;
    3256 SCIP_Real* consvals;
    3257 SCIP_Real rhs;
    3258
    3259 assert(sourcescip != NULL);
    3260 assert(*success == FALSE);
    3261
    3262 nbinvars = SCIPgetNBinVars(sourcescip);
    3263 vars = SCIPgetVars(sourcescip);
    3264
    3265 if( nbinvars <= 3 )
    3266 return SCIP_OKAY;
    3267
    3268 referencesol = SCIPgetBestSol(sourcescip);
    3269 if( referencesol == NULL )
    3270 return SCIP_OKAY;
    3271
    3272 rhs = (SCIP_Real)distance;
    3273 rhs = MAX(rhs, 2.0);
    3274
    3275 SCIP_CALL( SCIPallocBufferArray(sourcescip, &consvals, nbinvars) );
    3276
    3277 /* loop over binary variables and fill the local branching constraint */
    3278 for( i = 0; i < nbinvars; ++i )
    3279 {
    3280 /* skip variables that are not present in sub-SCIP */
    3281 if( subvars[i] == NULL )
    3282 continue;
    3283
    3284 if( SCIPisEQ(sourcescip, SCIPgetSolVal(sourcescip, referencesol, vars[i]), 0.0) )
    3285 consvals[i] = 1.0;
    3286 else
    3287 {
    3288 consvals[i] = -1.0;
    3289 rhs -= 1.0;
    3290 }
    3291 }
    3292
    3293 /* create the local branching constraint in the target scip */
    3294 SCIP_CALL( SCIPcreateConsBasicLinear(targetscip, &localbranchcons, "localbranch", nbinvars, subvars, consvals, -SCIPinfinity(sourcescip), rhs) );
    3295 SCIP_CALL( SCIPaddCons(targetscip, localbranchcons) );
    3296 SCIP_CALL( SCIPreleaseCons(targetscip, &localbranchcons) );
    3297
    3298 *naddedconss = 1;
    3299 *success = TRUE;
    3300
    3301 SCIPfreeBufferArray(sourcescip, &consvals);
    3302
    3303 return SCIP_OKAY;
    3304}
    3305
    3306/** callback for local branching subproblem changes */
    3307static
    3308DECL_CHANGESUBSCIP(changeSubscipLocalbranching)
    3309{ /*lint --e{715}*/
    3310
    3311 SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.2 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
    3312
    3313 return SCIP_OKAY;
    3314}
    3315
    3316/** callback for proximity subproblem changes */
    3317static
    3318DECL_CHANGESUBSCIP(changeSubscipProximity)
    3319{ /*lint --e{715}*/
    3320 SCIP_SOL* referencesol;
    3321 SCIP_VAR** vars;
    3322 int nbinvars;
    3323 int nintvars;
    3324 int nvars;
    3325 int i;
    3326
    3327 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, &nbinvars, &nintvars, NULL, NULL) );
    3328
    3329 if( nbinvars == 0 )
    3330 return SCIP_OKAY;
    3331
    3332 referencesol = SCIPgetBestSol(sourcescip);
    3333 if( referencesol == NULL )
    3334 return SCIP_OKAY;
    3335
    3336 /* loop over binary variables, set objective coefficients based on reference solution in a local branching fashion */
    3337 for( i = 0; i < nbinvars; ++i )
    3338 {
    3339 SCIP_Real newobj;
    3340
    3341 /* skip variables not present in sub-SCIP */
    3342 if( subvars[i] == NULL )
    3343 continue;
    3344
    3345 if( SCIPgetSolVal(sourcescip, referencesol, vars[i]) < 0.5 )
    3346 newobj = -1.0;
    3347 else
    3348 newobj = 1.0;
    3349 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], newobj) );
    3350 }
    3351
    3352 /* loop over the remaining variables and change their objective coefficients to 0 */
    3353 for( ; i < nvars; ++i )
    3354 {
    3355 /* skip variables not present in sub-SCIP */
    3356 if( subvars[i] == NULL )
    3357 continue;
    3358
    3359 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
    3360 }
    3361
    3362 *nchgobjs = nvars;
    3363 *success = TRUE;
    3364
    3365 return SCIP_OKAY;
    3366}
    3367
    3368/** callback for zeroobjective subproblem changes */
    3369static
    3370DECL_CHANGESUBSCIP(changeSubscipZeroobjective)
    3371{ /*lint --e{715}*/
    3372 SCIP_VAR** vars;
    3373 int nvars;
    3374 int i;
    3375
    3376 assert(*success == FALSE);
    3377
    3378 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, &nvars, NULL, NULL, NULL, NULL) );
    3379
    3380 /* do not run if no objective variables are present */
    3381 if( SCIPgetNObjVars(sourcescip) == 0 )
    3382 return SCIP_OKAY;
    3383
    3384 /* loop over the variables and change their objective coefficients to 0 */
    3385 for( i = 0; i < nvars; ++i )
    3386 {
    3387 /* skip variables not present in sub-SCIP */
    3388 if( subvars[i] == NULL )
    3389 continue;
    3390
    3391 SCIP_CALL( SCIPchgVarObj(targetscip, subvars[i], 0.0) );
    3392 }
    3393
    3394 *nchgobjs = nvars;
    3395 *success = TRUE;
    3396
    3397 return SCIP_OKAY;
    3398}
    3399
    3400/** compute tightened bounds for integer variables depending on how much the LP and the incumbent solution values differ */
    3401static
    3403 SCIP* scip, /**< SCIP data structure of the original problem */
    3404 SCIP_VAR* var, /**< the variable for which bounds should be computed */
    3405 SCIP_Real* lbptr, /**< pointer to store the lower bound in the DINS sub-SCIP */
    3406 SCIP_Real* ubptr /**< pointer to store the upper bound in the DINS sub-SCIP */
    3407 )
    3408{
    3409 SCIP_Real mipsol;
    3410 SCIP_Real lpsol;
    3411
    3412 SCIP_Real lbglobal;
    3413 SCIP_Real ubglobal;
    3414 SCIP_SOL* bestsol;
    3415
    3416 /* get the bounds for each variable */
    3417 lbglobal = SCIPvarGetLbGlobal(var);
    3418 ubglobal = SCIPvarGetUbGlobal(var);
    3419
    3421 /* get the current LP solution for each variable */
    3422 lpsol = SCIPvarGetLPSol(var);
    3423
    3424 /* get the current MIP solution for each variable */
    3425 bestsol = SCIPgetBestSol(scip);
    3426 mipsol = SCIPgetSolVal(scip, bestsol, var);
    3427
    3428 /* if the solution values differ by 0.5 or more, the variable is rebounded, otherwise it is just copied */
    3429 if( REALABS(lpsol - mipsol) >= 0.5 )
    3430 {
    3431 SCIP_Real range;
    3432
    3433 *lbptr = lbglobal;
    3434 *ubptr = ubglobal;
    3435
    3436 /* create an equally sized range around lpsol for general integers: bounds are lpsol +- (mipsol-lpsol) */
    3437 range = 2 * lpsol - mipsol;
    3438
    3439 if( mipsol >= lpsol )
    3440 {
    3441 range = SCIPfeasCeil(scip, range);
    3442 *lbptr = MAX(*lbptr, range);
    3443
    3444 /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
    3445 if( SCIPisFeasEQ(scip, mipsol, *lbptr) )
    3446 *ubptr = *lbptr;
    3447 else
    3448 *ubptr = mipsol;
    3449 }
    3450 else
    3451 {
    3452 range = SCIPfeasFloor(scip, range);
    3453 *ubptr = MIN(*ubptr, range);
    3454
    3455 /* when the bound new upper bound is equal to the current MIP solution, we set both bounds to the integral bound (without eps) */
    3456 if( SCIPisFeasEQ(scip, mipsol, *ubptr) )
    3457 *lbptr = *ubptr;
    3458 else
    3459 *lbptr = mipsol;
    3460 }
    3461
    3462 /* the global domain of variables might have been reduced since incumbent was found: adjust lb and ub accordingly */
    3463 *lbptr = MAX(*lbptr, lbglobal);
    3464 *ubptr = MIN(*ubptr, ubglobal);
    3465 }
    3466 else
    3467 {
    3468 /* the global domain of variables might have been reduced since incumbent was found: adjust it accordingly */
    3469 *lbptr = MAX(mipsol, lbglobal);
    3470 *ubptr = MIN(mipsol, ubglobal);
    3471 }
    3472}
    3473
    3474/** callback to collect variable fixings of DINS */
    3475static
    3476DECL_VARFIXINGS(varFixingsDins)
    3477{
    3478 DATA_DINS* data;
    3479 SCIP_SOL* rootlpsol;
    3480 SCIP_SOL** sols;
    3481 int nsols;
    3482 int nmipsols;
    3483 int nbinvars;
    3484 int nintvars;
    3485 SCIP_VAR** vars;
    3486 int v;
    3487
    3488 data = neighborhood->data.dins;
    3489 assert(data != NULL);
    3490 nmipsols = SCIPgetNSols(scip);
    3491 nmipsols = MIN(nmipsols, data->npoolsols);
    3492
    3493 *result = SCIP_DELAYED;
    3494
    3496 return SCIP_OKAY;
    3497
    3498 *result = SCIP_DIDNOTRUN;
    3499
    3500 if( nmipsols == 0 )
    3501 return SCIP_OKAY;
    3502
    3503 SCIP_CALL( SCIPgetVarsData(scip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3504
    3505 if( nbinvars + nintvars == 0 )
    3506 return SCIP_OKAY;
    3507
    3508 SCIP_CALL( SCIPcreateSol(scip, &rootlpsol, NULL) );
    3509
    3510 /* save root solution LP values in solution */
    3511 for( v = 0; v < nbinvars + nintvars; ++v )
    3512 {
    3513 SCIP_CALL( SCIPsetSolVal(scip, rootlpsol, vars[v], SCIPvarGetRootSol(vars[v])) );
    3514 }
    3515
    3516 /* add the node and the root LP solution */
    3517 nsols = nmipsols + 2;
    3518
    3519 SCIP_CALL( SCIPallocBufferArray(scip, &sols, nsols) );
    3520
    3521 /* incumbent is reference */
    3522 BMScopyMemoryArray(sols, SCIPgetSols(scip), nmipsols); /*lint !e866*/
    3523 sols[nmipsols] = NULL;
    3524 sols[nmipsols + 1] = rootlpsol;
    3525
    3526 /* 1. Binary variables are fixed if their values agree in all the solutions */
    3527 if( nbinvars > 0 )
    3528 {
    3529 SCIP_CALL( fixMatchingSolutionValues(scip, sols, nsols, vars, nbinvars, varbuf, valbuf, nfixings) );
    3530 }
    3531
    3532 /* 2. Integer variables are fixed if they have a very low distance between the incumbent and the root LP solution */
    3533 for( v = nbinvars; v < nintvars; ++v )
    3534 {
    3535 SCIP_Real lb;
    3536 SCIP_Real ub;
    3537 computeIntegerVariableBoundsDins(scip, vars[v], &lb, &ub);
    3538
    3539 if( ub - lb < 0.5 )
    3540 {
    3541 assert(SCIPisFeasIntegral(scip, lb));
    3542 tryAdd2variableBuffer(scip, vars[v], lb, varbuf, valbuf, nfixings, TRUE);
    3543 }
    3544 }
    3545
    3546 *result = SCIP_SUCCESS;
    3547
    3548 SCIPfreeBufferArray(scip, &sols);
    3549
    3550 SCIP_CALL( SCIPfreeSol(scip, &rootlpsol) );
    3551
    3552 return SCIP_OKAY;
    3553}
    3554
    3555/** callback for DINS subproblem changes */
    3556static
    3557DECL_CHANGESUBSCIP(changeSubscipDins)
    3558{ /*lint --e{715}*/
    3559 SCIP_VAR** vars;
    3560 int nintvars;
    3561 int nbinvars;
    3562 int v;
    3563
    3564 SCIP_CALL( SCIPgetVarsData(sourcescip, &vars, NULL, &nbinvars, &nintvars, NULL, NULL) );
    3565
    3566 /* 1. loop over integer variables and tighten the bounds */
    3567 for( v = nbinvars; v < nintvars; ++v )
    3568 {
    3569 SCIP_Real lb;
    3570 SCIP_Real ub;
    3571
    3572 /* skip variables not present in sub-SCIP */
    3573 if( subvars[v] == NULL )
    3574 continue;
    3575
    3576 computeIntegerVariableBoundsDins(sourcescip, vars[v], &lb, &ub);
    3577
    3578 SCIP_CALL( SCIPchgVarLbGlobal(targetscip, subvars[v], lb) );
    3579 SCIP_CALL( SCIPchgVarUbGlobal(targetscip, subvars[v], ub) );
    3580 ++(*ndomchgs);
    3581 }
    3582
    3583 /* 2. add local branching constraint for binary variables */
    3584 SCIP_CALL( addLocalBranchingConstraint(sourcescip, targetscip, subvars, (int)(0.1 * SCIPgetNBinVars(sourcescip)), success, naddedconss) );
    3585
    3586 *success = TRUE;
    3587
    3588 return SCIP_OKAY;
    3589}
    3590
    3591/** deinitialization callback for DINS before SCIP is freed */
    3592static
    3593DECL_NHFREE(nhFreeDins)
    3594{
    3595 assert(neighborhood->data.dins != NULL);
    3596
    3597 SCIPfreeBlockMemory(scip, &neighborhood->data.dins);
    3598
    3599 return SCIP_OKAY;
    3600}
    3601
    3602/** deinitialization callback for trustregion before SCIP is freed */
    3603static
    3604DECL_NHFREE(nhFreeTrustregion)
    3605{
    3606 assert(neighborhood->data.trustregion != NULL);
    3607
    3608 SCIPfreeBlockMemory(scip, &neighborhood->data.trustregion);
    3609
    3610 return SCIP_OKAY;
    3611}
    3612
    3613/** add trust region neighborhood constraint and auxiliary objective variable */
    3614static
    3615DECL_CHANGESUBSCIP(changeSubscipTrustregion)
    3616{ /*lint --e{715}*/
    3617 DATA_TRUSTREGION* data;
    3618
    3619 assert(success != NULL);
    3620
    3621 if( !SCIPgetBestSol(sourcescip) )
    3622 {
    3623 SCIPdebugMsg(sourcescip, "changeSubscipTrustregion unsuccessful, because it was called without incumbent being present\n");
    3624 *success = FALSE;
    3625
    3626 return SCIP_OKAY;
    3627 }
    3628
    3629 data = neighborhood->data.trustregion;
    3630
    3631 /* adding the neighborhood constraint for the trust region heuristic */
    3632 SCIP_CALL( SCIPaddTrustregionNeighborhoodConstraint(sourcescip, targetscip, subvars, data->violpenalty) );
    3633
    3634 /* incrementing the change in objective since an additional variable is added to the objective to penalize the
    3635 * violation of the trust region.
    3636 */
    3637 ++(*nchgobjs);
    3638
    3639 return SCIP_OKAY;
    3640}
    3641
    3642/** callback that returns the incumbent solution as a reference point */
    3643static
    3644DECL_NHREFSOL(nhRefsolIncumbent)
    3645{ /*lint --e{715}*/
    3646 assert(scip != NULL);
    3647
    3648 if( SCIPgetBestSol(scip) != NULL )
    3649 {
    3650 *result = SCIP_SUCCESS;
    3651 *solptr = SCIPgetBestSol(scip);
    3652 }
    3653 else
    3654 {
    3655 *result = SCIP_DIDNOTFIND;
    3656 }
    3657
    3658 return SCIP_OKAY;
    3659}
    3660
    3661
    3662/** callback function that deactivates a neighborhood on problems with no discrete variables */
    3663static
    3664DECL_NHDEACTIVATE(nhDeactivateDiscreteVars)
    3665{ /*lint --e{715}*/
    3666 assert(scip != NULL);
    3667 assert(deactivate != NULL);
    3668
    3669 /* deactivate if no discrete variables are present */
    3670 *deactivate = (SCIPgetNBinVars(scip) + SCIPgetNIntVars(scip) == 0);
    3671
    3672 return SCIP_OKAY;
    3673}
    3674
    3675/** callback function that deactivates a neighborhood on problems with no binary variables */
    3676static
    3677DECL_NHDEACTIVATE(nhDeactivateBinVars)
    3678{ /*lint --e{715}*/
    3679 assert(scip != NULL);
    3680 assert(deactivate != NULL);
    3681
    3682 /* deactivate if no discrete variables are present */
    3683 *deactivate = (SCIPgetNBinVars(scip) == 0);
    3684
    3685 return SCIP_OKAY;
    3686}
    3687
    3688/** callback function that deactivates a neighborhood on problems with no objective variables */
    3689static
    3690DECL_NHDEACTIVATE(nhDeactivateObjVars)
    3691{ /*lint --e{715}*/
    3692 assert(scip != NULL);
    3693 assert(deactivate != NULL);
    3694
    3695 /* deactivate if no discrete variables are present */
    3696 *deactivate = (SCIPgetNObjVars(scip) == 0);
    3697
    3698 return SCIP_OKAY;
    3699}
    3700
    3701
    3702/** include all neighborhoods */
    3703static
    3705 SCIP* scip, /**< SCIP data structure */
    3706 SCIP_HEURDATA* heurdata /**< heuristic data of the ALNS heuristic */
    3707 )
    3708{
    3709 NH* rens;
    3710 NH* rins;
    3711 NH* mutation;
    3712 NH* localbranching;
    3713 NH* crossover;
    3714 NH* proximity;
    3715 NH* zeroobjective;
    3716 NH* dins;
    3717 NH* trustregion;
    3718
    3719 heurdata->nneighborhoods = 0;
    3720
    3721 /* include the RENS neighborhood */
    3722 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &rens, "rens",
    3724 varFixingsRens, changeSubscipRens, NULL, NULL, NULL, NULL, nhDeactivateDiscreteVars) );
    3725
    3726 /* include the RINS neighborhood */
    3727 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &rins, "rins",
    3729 varFixingsRins, NULL, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
    3730
    3731 /* include the mutation neighborhood */
    3732 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &mutation, "mutation",
    3734 varFixingsMutation, NULL, nhInitMutation, nhExitMutation, NULL, nhRefsolIncumbent, nhDeactivateDiscreteVars) );
    3735
    3736 /* include the local branching neighborhood */
    3737 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &localbranching, "localbranching",
    3739 NULL, changeSubscipLocalbranching, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
    3740
    3741 /* include the crossover neighborhood */
    3742 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &crossover, "crossover",
    3744 varFixingsCrossover, NULL,
    3745 nhInitCrossover, nhExitCrossover, nhFreeCrossover, nhRefsolCrossover, nhDeactivateDiscreteVars) );
    3746
    3747 /* allocate data for crossover to include the parameter */
    3749 crossover->data.crossover->rng = NULL;
    3750
    3751 /* add crossover neighborhood parameters */
    3752 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/alns/crossover/nsols", "the number of solutions that crossover should combine",
    3753 &crossover->data.crossover->nsols, TRUE, DEFAULT_NSOLS_CROSSOVER, 2, 10, NULL, NULL) );
    3754
    3755 /* include the Proximity neighborhood */
    3756 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &proximity, "proximity",
    3758 NULL, changeSubscipProximity, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateBinVars) );
    3759
    3760 /* include the Zeroobjective neighborhood */
    3761 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &zeroobjective, "zeroobjective",
    3763 NULL, changeSubscipZeroobjective, NULL, NULL, NULL, nhRefsolIncumbent, nhDeactivateObjVars) );
    3764
    3765 /* include the DINS neighborhood */
    3766 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &dins, "dins",
    3768 varFixingsDins, changeSubscipDins, NULL, NULL, nhFreeDins, nhRefsolIncumbent, nhDeactivateBinVars) );
    3769
    3770 /* allocate data for DINS to include the parameter */
    3772
    3773 /* add DINS neighborhood parameters */
    3774 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/alns/dins/npoolsols",
    3775 "number of pool solutions where binary solution values must agree",
    3776 &dins->data.dins->npoolsols, TRUE, DEFAULT_NPOOLSOLS_DINS, 1, 100, NULL, NULL) );
    3777
    3778 /* include the trustregion neighborhood */
    3779 SCIP_CALL( alnsIncludeNeighborhood(scip, heurdata, &trustregion, "trustregion",
    3781 NULL, changeSubscipTrustregion, NULL, NULL, nhFreeTrustregion, nhRefsolIncumbent, nhDeactivateBinVars) );
    3782
    3783 /* allocate data for trustregion to include the parameter */
    3785
    3786 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/trustregion/violpenalty",
    3787 "the penalty for each change in the binary variables from the candidate solution",
    3789
    3790 return SCIP_OKAY;
    3791}
    3792
    3793/** initialization method of primal heuristic (called after problem was transformed) */
    3794static
    3796{ /*lint --e{715}*/
    3797 SCIP_HEURDATA* heurdata;
    3798 int i;
    3799
    3800 assert(scip != NULL);
    3801 assert(heur != NULL);
    3802
    3803 heurdata = SCIPheurGetData(heur);
    3804 assert(heurdata != NULL);
    3805
    3806 /* reactivate all neighborhoods if a new problem is read in */
    3807 heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
    3808
    3809 /* initialize neighborhoods for new problem */
    3810 for( i = 0; i < heurdata->nneighborhoods; ++i )
    3811 {
    3812 NH* neighborhood = heurdata->neighborhoods[i];
    3813
    3814 SCIP_CALL( neighborhoodInit(scip, neighborhood) );
    3815
    3816 SCIP_CALL( resetFixingRate(scip, &neighborhood->fixingrate) );
    3817
    3818 SCIP_CALL( neighborhoodStatsReset(scip, &neighborhood->stats) );
    3819 }
    3820
    3821 /* open reward file for reading */
    3822 if( strcmp(heurdata->rewardfilename, DEFAULT_REWARDFILENAME) != 0 )
    3823 {
    3824 heurdata->rewardfile = fopen(heurdata->rewardfilename, "w");
    3825
    3826 if( heurdata->rewardfile == NULL )
    3827 {
    3828 SCIPerrorMessage("Error: Could not open reward file <%s>\n", heurdata->rewardfilename);
    3829 return SCIP_FILECREATEERROR;
    3830 }
    3831
    3832 SCIPdebugMsg(scip, "Writing reward information to <%s>\n", heurdata->rewardfilename);
    3833 }
    3834 else
    3835 heurdata->rewardfile = NULL;
    3836
    3837 return SCIP_OKAY;
    3838}
    3839
    3840
    3841/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin) */
    3842static
    3844{ /*lint --e{715}*/
    3845 SCIP_HEURDATA* heurdata;
    3846 int i;
    3847 SCIP_Real* priorities;
    3848 unsigned int initseed;
    3849
    3850 assert(scip != NULL);
    3851 assert(heur != NULL);
    3852
    3853 heurdata = SCIPheurGetData(heur);
    3854 assert(heurdata != NULL);
    3855 heurdata->nactiveneighborhoods = heurdata->nneighborhoods;
    3856
    3857 SCIP_CALL( SCIPallocBufferArray(scip, &priorities, heurdata->nactiveneighborhoods) );
    3858
    3859 /* init neighborhoods for new problem by resetting their statistics and fixing rate */
    3860 for( i = heurdata->nneighborhoods - 1; i >= 0; --i )
    3861 {
    3862 NH* neighborhood = heurdata->neighborhoods[i];
    3863 SCIP_Bool deactivate;
    3864
    3865 SCIP_CALL( neighborhood->nhdeactivate(scip, &deactivate) );
    3866
    3867 /* disable inactive neighborhoods */
    3868 if( deactivate || ! neighborhood->active )
    3869 {
    3870 if( heurdata->nactiveneighborhoods - 1 > i )
    3871 {
    3872 assert(heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]->active);
    3873 SCIPswapPointers((void **)&heurdata->neighborhoods[i], (void **)&heurdata->neighborhoods[heurdata->nactiveneighborhoods - 1]);
    3874 }
    3875 heurdata->nactiveneighborhoods--;
    3876 }
    3877 }
    3878
    3879 /* collect neighborhood priorities */
    3880 for( i = 0; i < heurdata->nactiveneighborhoods; ++i )
    3881 priorities[i] = heurdata->neighborhoods[i]->priority;
    3882
    3883 initseed = (unsigned int)(heurdata->seed + SCIPgetNVars(scip));
    3884
    3885 /* active neighborhoods might change between init calls, reset functionality must take this into account */
    3886 if( heurdata->bandit != NULL && SCIPbanditGetNActions(heurdata->bandit) != heurdata->nactiveneighborhoods )
    3887 {
    3888 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
    3889
    3890 heurdata->bandit = NULL;
    3891 }
    3892
    3893 if( heurdata->nactiveneighborhoods > 0 )
    3894 { /* create or reset bandit algorithm */
    3895 if( heurdata->bandit == NULL )
    3896 {
    3897 SCIP_CALL( createBandit(scip, heurdata, priorities, initseed) );
    3898
    3899 resetMinimumImprovement(heurdata);
    3900 resetTargetNodeLimit(heurdata);
    3901 }
    3902 else if( heurdata->resetweights )
    3903 {
    3904 SCIP_CALL( SCIPresetBandit(scip, heurdata->bandit, priorities, initseed) );
    3905
    3906 resetMinimumImprovement(heurdata);
    3907 resetTargetNodeLimit(heurdata);
    3908 }
    3909 }
    3910
    3911 heurdata->usednodes = 0;
    3912 heurdata->ninitneighborhoods = heurdata->nactiveneighborhoods;
    3913
    3914 heurdata->lastcallsol = NULL;
    3915 heurdata->firstcallthissol = 0;
    3916
    3917 resetCurrentNeighborhood(heurdata);
    3918
    3919 SCIPfreeBufferArray(scip, &priorities);
    3920
    3921 return SCIP_OKAY;
    3922}
    3923
    3924
    3925/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    3926static
    3928{ /*lint --e{715}*/
    3929 SCIP_HEURDATA* heurdata;
    3930 int i;
    3931
    3932 assert(scip != NULL);
    3933 assert(heur != NULL);
    3934
    3935 heurdata = SCIPheurGetData(heur);
    3936 assert(heurdata != NULL);
    3937
    3938 /* free neighborhood specific data */
    3939 for( i = 0; i < heurdata->nneighborhoods; ++i )
    3940 {
    3941 NH* neighborhood = heurdata->neighborhoods[i];
    3942
    3943 SCIP_CALL( neighborhoodExit(scip, neighborhood) );
    3944 }
    3945
    3946 if( heurdata->rewardfile != NULL )
    3947 {
    3948 fclose(heurdata->rewardfile);
    3949 heurdata->rewardfile = NULL;
    3950 }
    3951
    3952 return SCIP_OKAY;
    3953}
    3954
    3955/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    3956static
    3958{ /*lint --e{715}*/
    3959 SCIP_HEURDATA* heurdata;
    3960 int i;
    3961
    3962 assert(scip != NULL);
    3963 assert(heur != NULL);
    3964
    3965 heurdata = SCIPheurGetData(heur);
    3966 assert(heurdata != NULL);
    3967
    3968 /* bandits are only initialized if a problem has been read */
    3969 if( heurdata->bandit != NULL )
    3970 {
    3971 SCIP_CALL( SCIPfreeBandit(scip, &heurdata->bandit) );
    3972 }
    3973
    3974 /* free neighborhoods */
    3975 for( i = 0; i < heurdata->nneighborhoods; ++i )
    3976 {
    3977 SCIP_CALL( alnsFreeNeighborhood(scip, &(heurdata->neighborhoods[i])) );
    3978 }
    3979
    3980 SCIPfreeBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS);
    3981
    3982 SCIPfreeBlockMemory(scip, &heurdata);
    3983
    3984 return SCIP_OKAY;
    3985}
    3986
    3987/** output method of statistics table to output file stream 'file' */
    3988static
    3989SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
    3990{ /*lint --e{715}*/
    3991 SCIP_HEURDATA* heurdata;
    3992
    3993 assert(SCIPfindHeur(scip, HEUR_NAME) != NULL);
    3995 assert(heurdata != NULL);
    3996
    3997 printNeighborhoodStatistics(scip, heurdata, file);
    3998
    3999 return SCIP_OKAY;
    4000}
    4001
    4002/*
    4003 * primal heuristic specific interface methods
    4004 */
    4005
    4006/** creates the alns primal heuristic and includes it in SCIP */
    4008 SCIP* scip /**< SCIP data structure */
    4009 )
    4010{
    4011 SCIP_HEURDATA* heurdata;
    4012 SCIP_HEUR* heur;
    4013
    4014 /* create alns primal heuristic data */
    4015 heurdata = NULL;
    4016 heur = NULL;
    4017
    4018 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    4019 BMSclearMemory(heurdata);
    4020
    4021 /* TODO make this a user parameter? */
    4022 heurdata->lplimfac = LPLIMFAC;
    4023
    4024 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &heurdata->neighborhoods, NNEIGHBORHOODS) );
    4025
    4026 /* include primal heuristic */
    4029 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecAlns, heurdata) );
    4030
    4031 assert(heur != NULL);
    4032
    4033 /* primal heuristic is safe to use in exact solving mode */
    4034 SCIPheurMarkExact(heur);
    4035
    4036 /* include all neighborhoods */
    4037 SCIP_CALL( includeNeighborhoods(scip, heurdata) );
    4038
    4039 /* set non fundamental callbacks via setter functions */
    4040 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyAlns) );
    4041 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeAlns) );
    4042 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitAlns) );
    4043 SCIP_CALL( SCIPsetHeurInitsol(scip, heur, heurInitsolAlns) );
    4044 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitAlns) );
    4045
    4046 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/shownbstats",
    4047 "show statistics on neighborhoods?",
    4048 &heurdata->shownbstats, TRUE, DEFAULT_SHOWNBSTATS, NULL, NULL) );
    4049
    4050 /* add alns primal heuristic parameters */
    4051 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/maxnodes",
    4052 "maximum number of nodes to regard in the subproblem",
    4053 &heurdata->maxnodes, TRUE,DEFAULT_MAXNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4054
    4055 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/nodesofs",
    4056 "offset added to the nodes budget",
    4057 &heurdata->nodesoffset, FALSE, DEFAULT_NODESOFFSET, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4058
    4059 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/minnodes",
    4060 "minimum number of nodes required to start a sub-SCIP",
    4061 &heurdata->minnodes, TRUE, DEFAULT_MINNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4062
    4063 SCIP_CALL( SCIPaddLongintParam(scip, "heuristics/" HEUR_NAME "/waitingnodes",
    4064 "number of nodes since last incumbent solution that the heuristic should wait",
    4065 &heurdata->waitingnodes, TRUE, DEFAULT_WAITINGNODES, 0LL, SCIP_LONGINT_MAX, NULL, NULL) );
    4066
    4067 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquot",
    4068 "fraction of nodes compared to the main SCIP for budget computation",
    4069 &heurdata->nodesquot, FALSE, DEFAULT_NODESQUOT, 0.0, 1.0, NULL, NULL) );
    4070 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/nodesquotmin",
    4071 "lower bound fraction of nodes compared to the main SCIP for budget computation",
    4072 &heurdata->nodesquotmin, FALSE, DEFAULT_NODESQUOTMIN, 0.0, 1.0, NULL, NULL) );
    4073
    4074 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/startminimprove",
    4075 "initial factor by which ALNS should at least improve the incumbent",
    4076 &heurdata->startminimprove, TRUE, DEFAULT_STARTMINIMPROVE, 0.0, 1.0, NULL, NULL) );
    4077
    4078 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprovelow",
    4079 "lower threshold for the minimal improvement over the incumbent",
    4080 &heurdata->minimprovelow, TRUE, DEFAULT_MINIMPROVELOW, 0.0, 1.0, NULL, NULL) );
    4081
    4082 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/minimprovehigh",
    4083 "upper bound for the minimal improvement over the incumbent",
    4084 &heurdata->minimprovehigh, TRUE, DEFAULT_MINIMPROVEHIGH, 0.0, 1.0, NULL, NULL) );
    4085
    4086 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/nsolslim",
    4087 "limit on the number of improving solutions in a sub-SCIP call",
    4088 &heurdata->nsolslim, FALSE, DEFAULT_NSOLSLIM, -1, INT_MAX, NULL, NULL) );
    4089
    4090 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/banditalgo",
    4091 "the bandit algorithm: (u)pper confidence bounds, (e)xp.3, epsilon (g)reedy, exp.3-(i)x",
    4092 &heurdata->banditalgo, TRUE, DEFAULT_BANDITALGO, "uegi", NULL, NULL) );
    4093
    4094 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/gamma",
    4095 "weight between uniform (gamma ~ 1) and weight driven (gamma ~ 0) probability distribution for exp3",
    4096 &heurdata->exp3_gamma, TRUE, DEFAULT_GAMMA, 0.0, 1.0, NULL, NULL) );
    4097
    4098 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/beta",
    4099 "reward offset between 0 and 1 at every observation for Exp.3",
    4100 &heurdata->exp3_beta, TRUE, DEFAULT_BETA, 0.0, 1.0, NULL, NULL) );
    4101
    4102 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/alpha",
    4103 "parameter to increase the confidence width in UCB",
    4104 &heurdata->ucb_alpha, TRUE, DEFAULT_ALPHA, 0.0, 100.0, NULL, NULL) );
    4105
    4106 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usedistances",
    4107 "distances from fixed variables be used for variable prioritization",
    4108 &heurdata->usedistances, TRUE, DEFAULT_USEDISTANCES, NULL, NULL) );
    4109
    4110 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/useredcost",
    4111 "should reduced cost scores be used for variable prioritization?",
    4112 &heurdata->useredcost, TRUE, DEFAULT_USEREDCOST, NULL, NULL) );
    4113
    4114 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/domorefixings",
    4115 "should the ALNS heuristic do more fixings by itself based on variable prioritization "
    4116 "until the target fixing rate is reached?",
    4117 &heurdata->domorefixings, TRUE, DEFAULT_DOMOREFIXINGS, NULL, NULL) );
    4118
    4119 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjustfixingrate",
    4120 "should the heuristic adjust the target fixing rate based on the success?",
    4121 &heurdata->adjustfixingrate, TRUE, DEFAULT_ADJUSTFIXINGRATE, NULL, NULL) );
    4122
    4123 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usesubscipheurs",
    4124 "should the heuristic activate other sub-SCIP heuristics during its search?",
    4125 &heurdata->usesubscipheurs, TRUE, DEFAULT_USESUBSCIPHEURS, NULL, NULL) );
    4126
    4127 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rewardcontrol",
    4128 "reward control to increase the weight of the simple solution indicator and decrease the weight of the closed gap reward",
    4129 &heurdata->rewardcontrol, TRUE, DEFAULT_REWARDCONTROL, 0.0, 1.0, NULL, NULL) );
    4130
    4131 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/targetnodefactor",
    4132 "factor by which target node number is eventually increased",
    4133 &heurdata->targetnodefactor, TRUE, DEFAULT_TARGETNODEFACTOR, 1.0, 1e+5, NULL, NULL) );
    4134
    4135 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/seed",
    4136 "initial random seed for bandit algorithms and random decisions by neighborhoods",
    4137 &heurdata->seed, FALSE, DEFAULT_SEED, 0, INT_MAX, NULL, NULL) );
    4138 SCIP_CALL( SCIPaddIntParam(scip, "heuristics/" HEUR_NAME "/maxcallssamesol",
    4139 "number of allowed executions of the heuristic on the same incumbent solution (-1: no limit, 0: number of active neighborhoods)",
    4140 &heurdata->maxcallssamesol, TRUE, DEFAULT_MAXCALLSSAMESOL, -1, 100, NULL, NULL) );
    4141
    4142 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjustminimprove",
    4143 "should the factor by which the minimum improvement is bound be dynamically updated?",
    4144 &heurdata->adjustminimprove, TRUE, DEFAULT_ADJUSTMINIMPROVE, NULL, NULL) );
    4145
    4146 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/adjusttargetnodes",
    4147 "should the target nodes be dynamically adjusted?",
    4148 &heurdata->adjusttargetnodes, TRUE, DEFAULT_ADJUSTTARGETNODES, NULL, NULL) );
    4149
    4150 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/eps",
    4151 "increase exploration in epsilon-greedy bandit algorithm",
    4152 &heurdata->epsgreedy_eps, TRUE, DEFAULT_EPS, 0.0, 1.0, NULL, NULL) );
    4153
    4154 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/rewardbaseline",
    4155 "the reward baseline to separate successful and failed calls",
    4156 &heurdata->rewardbaseline, TRUE, DEFAULT_REWARDBASELINE, 0.0, 0.99, NULL, NULL) );
    4157
    4158 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/resetweights",
    4159 "should the bandit algorithms be reset when a new problem is read?",
    4160 &heurdata->resetweights, TRUE, DEFAULT_RESETWEIGHTS, NULL, NULL) );
    4161
    4162 SCIP_CALL( SCIPaddStringParam(scip, "heuristics/" HEUR_NAME "/rewardfilename", "file name to store all rewards and the selection of the bandit",
    4163 &heurdata->rewardfilename, TRUE, DEFAULT_REWARDFILENAME, NULL, NULL) );
    4164
    4165 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/subsciprandseeds",
    4166 "should random seeds of sub-SCIPs be altered to increase diversification?",
    4167 &heurdata->subsciprandseeds, TRUE, DEFAULT_SUBSCIPRANDSEEDS, NULL, NULL) );
    4168
    4169 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/scalebyeffort",
    4170 "should the reward be scaled by the effort?",
    4171 &heurdata->scalebyeffort, TRUE, DEFAULT_SCALEBYEFFORT, NULL, NULL) );
    4172
    4173 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/copycuts",
    4174 "should cutting planes be copied to the sub-SCIP?",
    4175 &heurdata->copycuts, TRUE, DEFAULT_COPYCUTS, NULL, NULL) );
    4176
    4177 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/fixtol",
    4178 "tolerance by which the fixing rate may be missed without generic fixing",
    4179 &heurdata->fixtol, TRUE, DEFAULT_FIXTOL, 0.0, 1.0, NULL, NULL) );
    4180
    4181 SCIP_CALL( SCIPaddRealParam(scip, "heuristics/" HEUR_NAME "/unfixtol",
    4182 "tolerance by which the fixing rate may be exceeded without generic unfixing",
    4183 &heurdata->unfixtol, TRUE, DEFAULT_UNFIXTOL, 0.0, 1.0, NULL, NULL) );
    4184
    4185 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/uselocalredcost",
    4186 "should local reduced costs be used for generic (un)fixing?",
    4187 &heurdata->uselocalredcost, TRUE, DEFAULT_USELOCALREDCOST, NULL, NULL) );
    4188
    4189 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/usepscost",
    4190 "should pseudo cost scores be used for variable priorization?",
    4191 &heurdata->usepscost, TRUE, DEFAULT_USEPSCOST, NULL, NULL) );
    4192
    4193 SCIP_CALL( SCIPaddBoolParam(scip, "heuristics/" HEUR_NAME "/initduringroot",
    4194 "should the heuristic be executed multiple times during the root node?",
    4195 &heurdata->initduringroot, TRUE, DEFAULT_INITDURINGROOT, NULL, NULL) );
    4196
    4199 NULL, NULL, NULL, NULL, NULL, NULL, tableOutputNeighborhood, NULL,
    4201
    4202 return SCIP_OKAY;
    4203}
    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:248
    #define SCIP_MAXSTRLEN
    Definition: def.h:269
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_REAL_MAX
    Definition: def.h:158
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL_ABORT(x)
    Definition: def.h:334
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:148
    #define SCIPABORT()
    Definition: def.h:327
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_LONGINT_MAX
    Definition: def.h:142
    #define SCIP_REAL_FORMAT
    Definition: def.h:161
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs)
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPtranslateSubSol(SCIP *scip, SCIP *subscip, SCIP_SOL *subsol, SCIP_HEUR *heur, SCIP_VAR **subvars, SCIP_SOL **newsol)
    Definition: scip_copy.c:1397
    SCIP_Bool SCIPisTransformed(SCIP *scip)
    Definition: scip_general.c:647
    SCIP_Bool SCIPisStopped(SCIP *scip)
    Definition: scip_general.c:759
    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:4007
    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:2981
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_SOLORIGIN SCIPsolGetOrigin(SCIP_SOL *sol)
    Definition: sol.c:4130
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_Longint SCIPsolGetNodenum(SCIP_SOL *sol)
    Definition: sol.c:4239
    int SCIPgetNSols(SCIP *scip)
    Definition: scip_sol.c:2882
    SCIP_RETCODE SCIPgetSolVals(SCIP *scip, SCIP_SOL *sol, int nvars, SCIP_VAR **vars, SCIP_Real *vals)
    Definition: scip_sol.c:1846
    SCIP_SOL ** SCIPgetSols(SCIP *scip)
    Definition: scip_sol.c:2931
    SCIP_RETCODE 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:4312
    SCIP_RETCODE SCIPtrySolFree(SCIP *scip, SCIP_SOL **sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
    Definition: scip_sol.c:4109
    SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
    Definition: scip_sol.c:1571
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_Real SCIPgetSolTransObj(SCIP *scip, SCIP_SOL *sol)
    Definition: scip_sol.c:2005
    SCIP_Real SCIPretransformObj(SCIP *scip, SCIP_Real obj)
    Definition: scip_sol.c:2132
    SCIP_RETCODE SCIPtransformProb(SCIP *scip)
    Definition: scip_solve.c:232
    SCIP_RETCODE SCIPpresolve(SCIP *scip)
    Definition: scip_solve.c:2449
    SCIP_RETCODE SCIPinterruptSolve(SCIP *scip)
    Definition: scip_solve.c:3548
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_Real SCIPgetUpperbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_RETCODE SCIPprintStatistics(SCIP *scip, FILE *file)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Longint SCIPgetNLPs(SCIP *scip)
    SCIP_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:23386
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23498
    SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
    Definition: var.c:19480
    SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
    Definition: var.c:23900
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24142
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19115
    SCIP_RETCODE SCIPchgVarLbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6141
    SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
    Definition: scip_var.c:11188
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    SCIP_RETCODE SCIPchgVarUbGlobal(SCIP *scip, SCIP_VAR *var, SCIP_Real newbound)
    Definition: scip_var.c:6230
    SCIP_Real SCIPgetVarRedcost(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:2608
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24120
    SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
    Definition: var.c:19547
    SCIP_RETCODE SCIPchgVarObj(SCIP *scip, SCIP_VAR *var, SCIP_Real newobj)
    Definition: scip_var.c:5372
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    SCIP_Real SCIPrandomGetReal(SCIP_RANDNUMGEN *randnumgen, SCIP_Real minrandval, SCIP_Real maxrandval)
    Definition: misc.c:10245
    SCIP_RETCODE SCIPcreateRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen, unsigned int initialseed, SCIP_Bool useglobalseed)
    int SCIPrandomGetInt(SCIP_RANDNUMGEN *randnumgen, int minrandval, int maxrandval)
    Definition: misc.c:10223
    void SCIPselectInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int k, int len)
    void SCIPselectDownInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int k, int len)
    void 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:1363
    static void updateRunStats(NH_STATS *stats, SCIP *subscip)
    Definition: heur_alns.c:1054
    #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:1429
    #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:3795
    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:1172
    #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:1395
    #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:2153
    #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:3843
    #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:3957
    #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:1212
    static void initRunStats(SCIP *scip, NH_STATS *stats)
    Definition: heur_alns.c:1039
    static SCIP_DECL_HEURCOPY(heurCopyAlns)
    Definition: heur_alns.c:1648
    static SCIP_BANDIT * getBandit(SCIP_HEURDATA *heurdata)
    Definition: heur_alns.c:2039
    static SCIP_RETCODE selectNeighborhood(SCIP *scip, SCIP_HEURDATA *heurdata, int *neighborhoodidx)
    Definition: heur_alns.c:2049
    #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:3242
    #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:1971
    #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:1951
    #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:3927
    #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:2868
    #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:1334
    static int getHistIndex(SCIP_STATUS subscipstatus)
    Definition: heur_alns.c:1068
    #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:3402
    #define DEFAULT_MAXFIXINGRATE_RINS
    Definition: heur_alns.c:162
    static SCIP_RETCODE includeNeighborhoods(SCIP *scip, SCIP_HEURDATA *heurdata)
    Definition: heur_alns.c:3704
    #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:2072
    static SCIP_Real getVariableRedcostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real refsolval, SCIP_Bool uselocalredcost)
    Definition: heur_alns.c:1281
    #define HEUR_USESSUBSCIP
    Definition: heur_alns.c:81
    static SCIP_DECL_HEUREXEC(heurExecAlns)
    Definition: heur_alns.c:2327
    #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:1666
    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:1094
    static SCIP_RETCODE setupSubScip(SCIP *scip, SCIP *subscip, SCIP_VAR **subvars, SOLVELIMITS *solvelimits, SCIP_HEUR *heur, SCIP_Bool objchgd)
    Definition: heur_alns.c:2176
    #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:1911
    #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:1605
    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:1813
    #define DEFAULT_GAMMA
    Definition: heur_alns.c:134
    static SCIP_DECL_TABLEOUTPUT(tableOutputNeighborhood)
    Definition: heur_alns.c:3989
    #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 (weighted) k-medians
    public methods for primal CIP solutions
    public methods for problem variables
    public methods for bandit algorithms
    public methods for branching rule plugins and branching
    public methods for constraint handler plugins and constraints
    public methods for problem copies
    public methods for event handler plugins and event handlers
    general public methods
    public methods for primal heuristic plugins and divesets
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for node selector plugins
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for global and local (sub)problems
    public methods for random numbers
    public methods for solutions
    public solving methods
    public methods for querying solving statistics
    public methods for statistics table plugins
    public methods for timing
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    SCIP_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
    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