SCIP

    Solving Constraint Integer Programs

    branch_random.c
    Go to the documentation of this file.
    1
    2/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    3/* */
    4/* This file is part of the program and library */
    5/* SCIP --- Solving Constraint Integer Programs */
    6/* */
    7/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    8/* */
    9/* Licensed under the Apache License, Version 2.0 (the "License"); */
    10/* you may not use this file except in compliance with the License. */
    11/* You may obtain a copy of the License at */
    12/* */
    13/* http://www.apache.org/licenses/LICENSE-2.0 */
    14/* */
    15/* Unless required by applicable law or agreed to in writing, software */
    16/* distributed under the License is distributed on an "AS IS" BASIS, */
    17/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    18/* See the License for the specific language governing permissions and */
    19/* limitations under the License. */
    20/* */
    21/* You should have received a copy of the Apache-2.0 license */
    22/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    23/* */
    24/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    25
    26/**@file branch_random.c
    27 * @ingroup DEFPLUGINS_BRANCH
    28 * @brief random variable branching rule
    29 * @author Tobias Achterberg
    30 * @author Stefan Vigerske
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    35#include "scip/branch_random.h"
    36#include "scip/pub_branch.h"
    37#include "scip/pub_message.h"
    38#include "scip/pub_misc.h"
    39#include "scip/pub_var.h"
    40#include "scip/scip_branch.h"
    41#include "scip/scip_message.h"
    42#include "scip/scip_mem.h"
    43#include "scip/scip_numerics.h"
    44#include "scip/scip_param.h"
    46#include "scip/scip_tree.h"
    47
    48
    49#define BRANCHRULE_NAME "random"
    50#define BRANCHRULE_DESC "random variable branching"
    51#define BRANCHRULE_PRIORITY -100000
    52#define BRANCHRULE_MAXDEPTH -1
    53#define BRANCHRULE_MAXBOUNDDIST 1.0
    54
    55#define DEFAULT_INITSEED 41 /**< initial random seed */
    56
    57/** branching rule data */
    58struct SCIP_BranchruleData
    59{
    60 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    61 int initseed; /**< initial random seed value */
    62};
    63
    64/*
    65 * Local methods
    66 */
    67
    68/** selects a random active variable from a given list of variables */
    69static
    71 SCIP* scip, /**< SCIP data structure */
    72 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
    73 SCIP_VAR** cands, /**< array of branching candidates */
    74 SCIP_Real* candssol, /**< relaxation solution values of branching candidates, or NULL */
    75 int ncands, /**< number of branching candidates */
    76 SCIP_VAR** bestcand, /**< buffer to store pointer to best candidate */
    77 SCIP_Real* bestcandsol /**< buffer to store solution value of best candidate */
    78 )
    79{
    80 int idx;
    81 int firstidx;
    82
    83 assert(scip != NULL);
    84 assert(cands != NULL);
    85 assert(ncands > 0);
    86 assert(bestcand != NULL);
    87 assert(bestcandsol != NULL);
    88
    89 idx = SCIPrandomGetInt(branchruledata->randnumgen, 0, ncands-1);
    90 assert(idx >= 0);
    91
    92 /* handle case where cands[idx] is fixed by selecting next idx with unfixed var
    93 * this may happen if we are inside a multi-aggregation */
    94 firstidx = idx;
    95 while( SCIPisEQ(scip, SCIPvarGetLbLocal(cands[idx]), SCIPvarGetUbLocal(cands[idx])) )
    96 {
    97 ++idx;
    98 if( idx == ncands )
    99 idx = 0;
    100 if( idx == firstidx )
    101 {
    102 /* odd: all variables seem to be fixed */
    103 SCIPdebugMsg(scip, "Warning: all branching candidates seem to be fixed\n");
    104 return;
    105 }
    106 }
    107
    108 /* a branching variable candidate should either be an active problem variable or a multi-aggregated variable */
    109 assert(SCIPvarIsActive(SCIPvarGetProbvar(cands[idx])) ||
    111
    113 {
    114 /* for a multi-aggregated variable, we call the getRandomVariable function recursively with all variables in the multi-aggregation */
    115 SCIP_VAR* cand;
    116
    117 cand = SCIPvarGetProbvar(cands[idx]);
    118
    120 bestcand, bestcandsol);
    121 return;
    122 }
    123
    124 assert(idx >= 0 && idx < ncands);
    125
    126 *bestcand = cands[idx];
    127 assert(*bestcand != NULL);
    128
    129 if( candssol != NULL )
    130 *bestcandsol = candssol[idx];
    131}
    132
    133/*
    134 * Callback methods
    135 */
    136
    137/** copy method for branchrule plugins (called when SCIP copies plugins) */
    138static
    139SCIP_DECL_BRANCHCOPY(branchCopyRandom)
    140{ /*lint --e{715}*/
    141 assert(scip != NULL);
    142 assert(branchrule != NULL);
    143
    145
    146 /* call inclusion method of branchrule */
    148
    149 return SCIP_OKAY;
    150}
    151
    152/** destructor of branching rule to free user data (called when SCIP is exiting) */
    153/**! [SnippetBranchFreeRandom] */
    154static
    155SCIP_DECL_BRANCHFREE(branchFreeRandom)
    156{ /*lint --e{715}*/
    157 SCIP_BRANCHRULEDATA* branchruledata;
    158
    159 /* get branching rule data */
    160 branchruledata = SCIPbranchruleGetData(branchrule);
    161 assert(branchruledata != NULL);
    162
    163 /* free branching rule data */
    164 SCIPfreeBlockMemory(scip, &branchruledata);
    165 SCIPbranchruleSetData(branchrule, NULL);
    166
    167 return SCIP_OKAY;
    168}
    169/**! [SnippetBranchFreeRandom] */
    170
    171
    172/** initialization method of branching rule (called after problem was transformed) */
    173static
    174SCIP_DECL_BRANCHINIT(branchInitRandom)
    175{ /*lint --e{715}*/
    176 SCIP_BRANCHRULEDATA* branchruledata;
    177
    178 branchruledata = SCIPbranchruleGetData(branchrule);
    179 assert(branchruledata != NULL);
    180 assert(branchruledata->initseed >= 0);
    181
    182 /* create a random number generator */
    183 SCIP_CALL( SCIPcreateRandom(scip, &branchruledata->randnumgen,
    184 (unsigned int)branchruledata->initseed, TRUE) );
    185
    186 return SCIP_OKAY;
    187}
    188
    189/** deinitialization method of branching rule */
    190static
    191SCIP_DECL_BRANCHEXIT(branchExitRandom)
    192{ /*lint --e{715}*/
    193 SCIP_BRANCHRULEDATA* branchruledata;
    194
    195 /* get branching rule data */
    196 branchruledata = SCIPbranchruleGetData(branchrule);
    197 assert(branchruledata != NULL);
    198
    199 /* free random number generator */
    200 SCIPfreeRandom(scip, &branchruledata->randnumgen);
    201
    202 return SCIP_OKAY;
    203}
    204
    205/** branching execution method for fractional LP solutions */
    206static
    207SCIP_DECL_BRANCHEXECLP(branchExeclpRandom)
    208{ /*lint --e{715}*/
    209 SCIP_BRANCHRULEDATA* branchruledata;
    210 SCIP_VAR** lpcands;
    211 int nlpcands;
    212 int bestcand;
    213
    214 assert(branchrule != NULL);
    215 assert(scip != NULL);
    216 assert(result != NULL);
    217
    219
    220 SCIPdebugMsg(scip, "Execlp method of random branching in depth %d\n", SCIPgetDepth(scip));
    221
    222 branchruledata = SCIPbranchruleGetData(branchrule);
    223 assert(branchruledata != NULL);
    224
    225 /* get branching candidates */
    226 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, NULL, NULL, NULL, &nlpcands, NULL) );
    227 assert(nlpcands > 0);
    228
    229 /* get random branching candidate */
    230 bestcand = SCIPrandomGetInt(branchruledata->randnumgen, 0, nlpcands-1);
    231 assert(bestcand >= 0);
    232
    233 SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s>\n",
    234 nlpcands, bestcand, SCIPvarGetName(lpcands[bestcand]));
    235
    236 /* perform the branching */
    237 SCIP_CALL( SCIPbranchVar(scip, lpcands[bestcand], NULL, NULL, NULL) );
    238 *result = SCIP_BRANCHED;
    239
    240 return SCIP_OKAY;
    241}
    242
    243
    244/** branching execution method for external candidates */
    245static
    246SCIP_DECL_BRANCHEXECEXT(branchExecextRandom)
    247{ /*lint --e{715}*/
    248 SCIP_BRANCHRULEDATA* branchruledata;
    249 SCIP_VAR** externcands;
    250 SCIP_Real* externcandssol;
    251 int nprioexterncands;
    252 SCIP_VAR* bestcand;
    253 SCIP_Real bestcandsol;
    254 SCIP_Real brpoint;
    255 SCIP_NODE* downchild;
    256 SCIP_NODE* eqchild;
    257 SCIP_NODE* upchild;
    258
    259 assert(branchrule != NULL);
    260 assert(scip != NULL);
    261 assert(result != NULL);
    262
    264
    265 SCIPdebugMsg(scip, "Execrel method of random branching\n");
    266
    267 branchruledata = SCIPbranchruleGetData(branchrule);
    268 assert(branchruledata != NULL);
    269
    270 bestcand = NULL;
    271 bestcandsol = 0.0;
    272
    273 /* get branching candidates */
    274 SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, NULL, NULL, &nprioexterncands, NULL, NULL, NULL) );
    275 assert(nprioexterncands > 0);
    276
    277 /* get random branching candidate
    278 *
    279 * since variables can occur several times in the list of candidates, variables that have been added more often have
    280 * a higher probability to be chosen for branching
    281 */
    282 getRandomVariable(scip, branchruledata, externcands, externcandssol, nprioexterncands, &bestcand, &bestcandsol);
    283
    284 if( bestcand == NULL )
    285 {
    286 SCIPerrorMessage("branchExecrelRandom failed to select a branching variable from %d candidates\n", nprioexterncands);
    287 *result = SCIP_DIDNOTRUN;
    288 return SCIP_OKAY;
    289 }
    290
    291 brpoint = SCIPgetBranchingPoint(scip, bestcand, bestcandsol);
    292
    293 SCIPdebugMsg(scip, " -> %d candidates, selected variable <%s> with solution value %g, branching point=%g\n",
    294 nprioexterncands, SCIPvarGetName(bestcand), bestcandsol, brpoint);
    295
    296 SCIP_CALL( SCIPbranchVarVal(scip, bestcand, brpoint, &downchild, &eqchild, &upchild) );
    297
    298 if( downchild != NULL || eqchild != NULL || upchild != NULL )
    299 {
    300 *result = SCIP_BRANCHED;
    301 }
    302 else
    303 {
    304 /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */
    305 assert(SCIPisEQ(scip, SCIPvarGetLbLocal(bestcand), SCIPvarGetUbLocal(bestcand)));
    306 *result = SCIP_REDUCEDDOM;
    307 }
    308
    309 return SCIP_OKAY;
    310}
    311
    312/** branching execution method for not completely fixed pseudo solutions */
    313static
    314SCIP_DECL_BRANCHEXECPS(branchExecpsRandom)
    315{ /*lint --e{715}*/
    316 SCIP_BRANCHRULEDATA* branchruledata;
    317 SCIP_VAR** pseudocands;
    318 int npseudocands;
    319 int bestcand;
    320
    321 assert(branchrule != NULL);
    322 assert(scip != NULL);
    323 assert(result != NULL);
    324
    326
    327 SCIPdebugMsg(scip, "Execps method of random branching\n");
    328
    329 branchruledata = SCIPbranchruleGetData(branchrule);
    330 assert(branchruledata != NULL);
    331
    332 /* get branching candidates */
    333 SCIP_CALL( SCIPgetPseudoBranchCands(scip, &pseudocands, NULL, &npseudocands) );
    334 assert(npseudocands > 0);
    335
    336 /* get random branching candidate */
    337 bestcand = SCIPrandomGetInt(branchruledata->randnumgen, 0, npseudocands-1);
    338 assert(bestcand >= 0);
    339
    340 SCIPdebugMsg(scip, " -> %d candidates, selected candidate %d: variable <%s>\n",
    341 npseudocands, bestcand, SCIPvarGetName(pseudocands[bestcand]));
    342
    343 /* perform the branching */
    344 SCIP_CALL( SCIPbranchVar(scip, pseudocands[bestcand], NULL, NULL, NULL) );
    345 *result = SCIP_BRANCHED;
    346
    347 return SCIP_OKAY;
    348}
    349
    350
    351/*
    352 * branching specific interface methods
    353 */
    354
    355/** creates the random branching rule and includes it in SCIP */
    357 SCIP* scip /**< SCIP data structure */
    358 )
    359{
    360 SCIP_BRANCHRULEDATA* branchruledata;
    361 SCIP_BRANCHRULE* branchrule;
    362
    363 /* create random branching rule data */
    364 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
    365
    366 /* include allfullstrong branching rule */
    369
    370 assert(branchrule != NULL);
    371
    372 /* set non-fundamental callbacks via specific setter functions*/
    373 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyRandom) );
    374 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeRandom) );
    375 SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitRandom) );
    376 SCIP_CALL( SCIPsetBranchruleExit(scip, branchrule, branchExitRandom) );
    377 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpRandom) );
    378 SCIP_CALL( SCIPsetBranchruleExecExt(scip, branchrule, branchExecextRandom) );
    379 SCIP_CALL( SCIPsetBranchruleExecPs(scip, branchrule, branchExecpsRandom) );
    380
    381 SCIP_CALL( SCIPaddIntParam(scip, "branching/" BRANCHRULE_NAME "/seed", "initial random seed value",
    382 &branchruledata->initseed, FALSE, DEFAULT_INITSEED, 0, INT_MAX, NULL, NULL) );
    383
    384 return SCIP_OKAY;
    385}
    #define BRANCHRULE_DESC
    Definition: branch_random.c:50
    static SCIP_DECL_BRANCHFREE(branchFreeRandom)
    #define BRANCHRULE_PRIORITY
    Definition: branch_random.c:51
    static SCIP_DECL_BRANCHEXECEXT(branchExecextRandom)
    static SCIP_DECL_BRANCHEXECLP(branchExeclpRandom)
    #define BRANCHRULE_NAME
    Definition: branch_random.c:49
    static SCIP_DECL_BRANCHEXECPS(branchExecpsRandom)
    static SCIP_DECL_BRANCHCOPY(branchCopyRandom)
    #define DEFAULT_INITSEED
    Definition: branch_random.c:55
    static void getRandomVariable(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR **cands, SCIP_Real *candssol, int ncands, SCIP_VAR **bestcand, SCIP_Real *bestcandsol)
    Definition: branch_random.c:70
    static SCIP_DECL_BRANCHEXIT(branchExitRandom)
    static SCIP_DECL_BRANCHINIT(branchInitRandom)
    #define BRANCHRULE_MAXDEPTH
    Definition: branch_random.c:52
    #define BRANCHRULE_MAXBOUNDDIST
    Definition: branch_random.c:53
    random variable branching rule
    #define NULL
    Definition: def.h:257
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPincludeBranchruleRandom(SCIP *scip)
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    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 SCIPsetBranchruleExecExt(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECEXT((*branchexecext)))
    Definition: scip_branch.c:272
    SCIP_RETCODE SCIPsetBranchruleExit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXIT((*branchexit)))
    Definition: scip_branch.c:208
    SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
    Definition: scip_branch.c:256
    SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
    Definition: scip_branch.c:160
    SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
    Definition: scip_branch.c:123
    SCIP_RETCODE SCIPsetBranchruleExecPs(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECPS((*branchexecps)))
    Definition: scip_branch.c:288
    const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
    Definition: branch.c:2018
    SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
    Definition: branch.c:1886
    SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
    Definition: scip_branch.c:176
    SCIP_RETCODE SCIPsetBranchruleInit(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHINIT((*branchinit)))
    Definition: scip_branch.c:192
    void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
    Definition: branch.c:1896
    SCIP_RETCODE SCIPgetExternBranchCands(SCIP *scip, SCIP_VAR ***externcands, SCIP_Real **externcandssol, SCIP_Real **externcandsscore, int *nexterncands, int *nprioexterncands, int *nprioexternbins, int *nprioexternints, int *nprioexternimpls)
    Definition: scip_branch.c:519
    SCIP_Real SCIPgetBranchingPoint(SCIP *scip, SCIP_VAR *var, SCIP_Real suggestion)
    Definition: scip_branch.c:905
    SCIP_RETCODE SCIPbranchVarVal(SCIP *scip, SCIP_VAR *var, SCIP_Real val, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
    Definition: scip_branch.c:1134
    SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
    Definition: scip_branch.c:402
    SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
    Definition: scip_branch.c:1058
    SCIP_RETCODE SCIPgetPseudoBranchCands(SCIP *scip, SCIP_VAR ***pseudocands, int *npseudocands, int *npriopseudocands)
    Definition: scip_branch.c:741
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17595
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
    Definition: var.c:23838
    int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
    Definition: var.c:23826
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24266
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    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
    public methods for branching rules
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for random numbers
    public methods for the branch-and-bound tree
    struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
    Definition: type_branch.h:57
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56