SCIP

    Solving Constraint Integer Programs

    branch_nodereopt.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file branch_nodereopt.c
    26 * @ingroup DEFPLUGINS_BRANCH
    27 * @brief branching rule to reconstruct the search tree
    28 * @author Jakob Witzig
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    35#include "scip/scip.h"
    36#include "scip/tree.h"
    37#include "scip/pub_reopt.h"
    38
    39#define BRANCHRULE_NAME "nodereopt"
    40#define BRANCHRULE_DESC "branching rule for node reoptimization"
    41#define BRANCHRULE_PRIORITY -9000000
    42#define BRANCHRULE_MAXDEPTH -1
    43#define BRANCHRULE_MAXBOUNDDIST 1.0
    44
    45/*
    46 * Data structures
    47 */
    48
    49
    50/** execute the branching of nodes with additional constraints */
    51static
    53 SCIP* scip, /**< SCIP data structure */
    54 SCIP_RESULT* result /**< pointer to store the result */
    55 )
    56{
    57 SCIP_REOPTNODE* reoptnode;
    58 SCIP_NODE* curnode;
    59 SCIP_REOPTTYPE reopttype;
    60 SCIP_Bool localrestart;
    61 unsigned int* childids;
    62 unsigned int curid;
    63 int naddedconss;
    64 int nchilds;
    65 int childnodessize;
    66 int ncreatednodes;
    67 int c;
    68
    69 assert(scip != NULL );
    70 assert(SCIPisReoptEnabled(scip));
    71
    72 curnode = SCIPgetCurrentNode(scip);
    73 assert(curnode != NULL);
    74
    75 curid = SCIPnodeGetReoptID(curnode);
    76 assert(curid >= 1 || SCIPgetRootNode(scip) == curnode);
    77
    78 /* calculate local similarity and delete the induced subtree if the similarity is to low */
    79 localrestart = FALSE;
    80 SCIP_CALL( SCIPcheckReoptRestart(scip, curnode, &localrestart) );
    81
    82 ncreatednodes = 0;
    83
    84 if( localrestart )
    85 {
    86 *result = SCIP_DIDNOTRUN;
    87 goto TERMINATE;
    88 }
    89
    90 SCIPdebugMsg(scip, "current node is %lld, ID %u:\n", SCIPnodeGetNumber(curnode), curid);
    91
    92 /* get the corresponding node of the reoptimization tree */
    93 reoptnode = SCIPgetReoptnode(scip, curid);
    94 assert(reoptnode != NULL);
    95 reopttype = (SCIP_REOPTTYPE)SCIPreoptnodeGetType(reoptnode);
    96
    97 /* The current node is equal to the root and dual reductions were performed. Since the root has a special role
    98 * within the reoptimiziation we have to split the root node into several nodes and move all stored child nodes to
    99 * the one representing the root node including all dual reductions as before.
    100 *
    101 * @note If the type is infsubtree, there cannot exist a child node and the method SCIPapplyReopt adds a global valid
    102 * constraint only.
    103 */
    104 if( curid == 0 )
    105 {
    106 if( reopttype == SCIP_REOPTTYPE_STRBRANCHED || reopttype == SCIP_REOPTTYPE_INFSUBTREE )
    107 {
    108 int ncreatedchilds;
    109
    110 /* apply the reoptimization at the root node */
    111 SCIP_CALL( SCIPsplitReoptRoot(scip, &ncreatedchilds, &naddedconss) );
    112
    113 if( reopttype == SCIP_REOPTTYPE_INFSUBTREE )
    114 {
    115 assert(ncreatedchilds == 0);
    116 assert(naddedconss == 1);
    117
    118 /* there is nothing to do */
    119 *result = SCIP_DIDNOTRUN;
    120
    121 goto TERMINATE;
    122 }
    123
    124 assert(reopttype == SCIP_REOPTTYPE_STRBRANCHED);
    125 assert(ncreatedchilds >= 2);
    126
    127 ncreatednodes += ncreatedchilds;
    128
    129 /* We decrease the counter by one because after splitting the root node and moving all children to the node
    130 * representing the original root with all fixings (caused by dual reductions), we continue reactivating the
    131 * original children nodes of the root. Thus, the node containing all the fixings can be replaced by the children
    132 * nodes
    133 */
    134 --ncreatednodes;
    135 }
    136
    137 goto REVIVE;
    138 }
    139
    140 /* if we reach this part of the code the current has to be different to the root node */
    141 assert(curid >= 1);
    142
    143 REVIVE:
    144
    145 /* get the IDs of all child nodes */
    146 childnodessize = SCIPreoptnodeGetNChildren(reoptnode);
    147 SCIP_CALL( SCIPallocBufferArray(scip, &childids, childnodessize) );
    148 SCIP_CALL( SCIPgetReoptChildIDs(scip, curnode, childids, childnodessize, &nchilds) );
    149
    150 if( childnodessize < nchilds )
    151 {
    152 childnodessize = SCIPreoptnodeGetNChildren(reoptnode);
    153 SCIP_CALL( SCIPreallocBufferArray(scip, &childids, childnodessize) );
    154 SCIP_CALL( SCIPgetReoptChildIDs(scip, curnode, childids, childnodessize, &nchilds) );
    155 }
    156 assert(nchilds <= childnodessize);
    157
    158 naddedconss = 0;
    159
    160 for(c = 0; c < nchilds; c++)
    161 {
    162 SCIP_NODE** childnodes;
    163 SCIP_Bool success;
    164 unsigned int childid;
    165 int ncreatedchilds;
    166
    167 childid = childids[c];
    168 assert(childid >= 1);
    169
    170 SCIPdebugMsg(scip, "process child at ID %u\n", childid);
    171
    172 reoptnode = SCIPgetReoptnode(scip, childid);
    173 assert(reoptnode != NULL);
    174
    175 reopttype = (SCIP_REOPTTYPE)SCIPreoptnodeGetType(reoptnode);
    176 ncreatedchilds = 0;
    177
    178 /* check whether node need to be split */
    179 if( reopttype == SCIP_REOPTTYPE_STRBRANCHED || reopttype == SCIP_REOPTTYPE_INFSUBTREE )
    180 {
    181 /* by default we assume the node get split into two node (because using a constraint to split the node is
    182 * the default case */
    183 childnodessize = 2;
    184 }
    185 else
    186 {
    187 /* we only need to reconstruct the node */
    188 childnodessize = 1;
    189 }
    190
    191 /* allocate buffer */
    192 SCIP_CALL( SCIPallocBufferArray(scip, &childnodes, childnodessize) );
    193
    194 /* apply the reoptimization */
    195 SCIP_CALL( SCIPapplyReopt(scip, reoptnode, childid, SCIPnodeGetEstimate(curnode), childnodes, &ncreatedchilds,
    196 &naddedconss, childnodessize, &success) );
    197
    198 if( !success )
    199 {
    200 assert(ncreatedchilds > childnodessize);
    201
    202 /* reallocate buffer memory */
    203 childnodessize = ncreatedchilds+1;
    204 SCIP_CALL( SCIPreallocBufferArray(scip, &childnodes, childnodessize) );
    205
    206 /* apply the reoptimization */
    207 SCIP_CALL( SCIPapplyReopt(scip, reoptnode, childid, SCIPnodeGetEstimate(curnode), childnodes, &ncreatedchilds,
    208 &naddedconss, childnodessize, &success) );
    209 }
    210
    211 assert(success);
    212
    213 /* free buffer memory */
    214 SCIPfreeBufferArray(scip, &childnodes);
    215
    216 ncreatednodes += ncreatedchilds;
    217 }
    218
    219 if( ncreatednodes == 0 )
    220 *result = SCIP_DIDNOTRUN;
    221 else
    222 *result = SCIP_BRANCHED;
    223
    224 /* free the buffer memory */
    225 SCIPfreeBufferArray(scip, &childids);
    226
    227 TERMINATE:
    228
    229 SCIPdebugMsg(scip, "**** finish reoptimizing %d child nodes of node %lld ****\n", ncreatednodes, SCIPnodeGetNumber(curnode));
    230
    231 return SCIP_OKAY;
    232}
    233
    234/*
    235 * Callback methods of branching rule
    236 */
    237
    238/** copy method for branchrule plugins (called when SCIP copies plugins) */
    239static
    240SCIP_DECL_BRANCHCOPY(branchCopyNodereopt)
    241{ /*lint --e{715}*/
    242 assert(scip != NULL);
    243 assert(branchrule != NULL);
    244
    246
    247 /* call inclusion method of branchrule */
    249
    250 return SCIP_OKAY;
    251}
    252
    253/** branching execution method for fractional LP solutions */
    254static
    255SCIP_DECL_BRANCHEXECLP(branchExeclpNodereopt)
    256{/*lint --e{715}*/
    257 assert(branchrule != NULL );
    258 assert(*result != SCIP_BRANCHED);
    259
    260 *result = SCIP_DIDNOTRUN;
    261
    263 {
    264 SCIP_VAR** branchcands;
    265 SCIP_Real* branchcandssol;
    266 SCIP_Real* branchcandsfrac;
    267 SCIP_Real objsimrootlp;
    268 SCIP_Bool sbinit;
    269 int nbranchcands;
    270
    271 assert(SCIPgetNReoptRuns(scip) > 1);
    272
    273 SCIP_CALL( SCIPgetBoolParam(scip, "reoptimization/strongbranchinginit", &sbinit) );
    274 SCIP_CALL( SCIPgetRealParam(scip, "reoptimization/objsimrootLP", &objsimrootlp) );
    275
    277 && SCIPgetReoptSimilarity(scip, SCIPgetNReoptRuns(scip)-1, SCIPgetNReoptRuns(scip)) <= objsimrootlp ) /* check objsimrootlp */
    278 {
    279 /* get branching candidates */
    280 SCIP_CALL( SCIPgetLPBranchCands(scip, &branchcands, &branchcandssol, &branchcandsfrac, NULL, &nbranchcands, NULL) );
    281
    282 /* run strong branching initialization */
    283 if( nbranchcands > 0 )
    284 {
    285 SCIP_CALL( SCIPexecRelpscostBranching(scip, branchcands, branchcandssol, branchcandsfrac, nbranchcands, FALSE, result) );
    286 assert(*result == SCIP_DIDNOTRUN || *result == SCIP_CUTOFF || *result == SCIP_REDUCEDDOM || *result == SCIP_CONSADDED);
    287 }
    288 }
    289
    290 if( *result != SCIP_CUTOFF && *result != SCIP_REDUCEDDOM && *result != SCIP_CONSADDED )
    291 {
    294
    295 SCIP_CALL( Exec(scip, result) );
    296 }
    297 }
    298
    299 return SCIP_OKAY;
    300}
    301
    302/** branching execution method for external candidates */
    303static SCIP_DECL_BRANCHEXECEXT(branchExecextNodereopt)
    304{/*lint --e{715}*/
    305 assert(branchrule != NULL );
    306 assert(*result != SCIP_BRANCHED);
    307
    308 *result = SCIP_DIDNOTRUN;
    309
    311 {
    314
    315 SCIP_CALL( Exec(scip, result) );
    316 }
    317
    318 return SCIP_OKAY;
    319}
    320
    321/** branching execution method for not completely fixed pseudo solutions */
    322static SCIP_DECL_BRANCHEXECPS(branchExecpsNodereopt)
    323{/*lint --e{715}*/
    324 assert(branchrule != NULL );
    325 assert(*result != SCIP_BRANCHED);
    326
    327 *result = SCIP_DIDNOTRUN;
    328
    330 {
    333
    334 SCIP_CALL( Exec(scip, result) );
    335 }
    336
    337 return SCIP_OKAY;
    338}
    339
    340/*
    341 * branching rule specific interface methods
    342 */
    343
    344/** creates the nodereopt branching rule and includes it in SCIP */
    346 SCIP* scip /**< SCIP data structure */
    347 )
    348{
    349 SCIP_BRANCHRULE* branchrule;
    350
    351 assert(scip != NULL );
    352
    353 /* include nodereopt branching rule */
    356
    357 assert(branchrule != NULL );
    358
    359 /* set non fundamental callbacks via setter functions */
    360 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyNodereopt) );
    361 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpNodereopt) );
    362 SCIP_CALL( SCIPsetBranchruleExecExt(scip, branchrule, branchExecextNodereopt) );
    363 SCIP_CALL( SCIPsetBranchruleExecPs(scip, branchrule, branchExecpsNodereopt) );
    364
    365 return SCIP_OKAY;
    366}
    #define BRANCHRULE_DESC
    static SCIP_DECL_BRANCHEXECEXT(branchExecextNodereopt)
    #define BRANCHRULE_PRIORITY
    static SCIP_DECL_BRANCHEXECLP(branchExeclpNodereopt)
    static SCIP_DECL_BRANCHEXECPS(branchExecpsNodereopt)
    #define BRANCHRULE_NAME
    static SCIP_DECL_BRANCHCOPY(branchCopyNodereopt)
    static SCIP_RETCODE Exec(SCIP *scip, SCIP_RESULT *result)
    #define BRANCHRULE_MAXDEPTH
    #define BRANCHRULE_MAXBOUNDDIST
    nodereopt branching rule
    reliable pseudo costs branching rule
    #define NULL
    Definition: def.h:257
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define FALSE
    Definition: def.h:103
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPexecRelpscostBranching(SCIP *scip, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsfrac, int nbranchcands, SCIP_Bool executebranching, SCIP_RESULT *result)
    SCIP_RETCODE SCIPincludeBranchruleNodereopt(SCIP *scip)
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPgetBoolParam(SCIP *scip, const char *name, SCIP_Bool *value)
    Definition: scip_param.c:250
    SCIP_RETCODE SCIPgetRealParam(SCIP *scip, const char *name, SCIP_Real *value)
    Definition: scip_param.c:307
    SCIP_RETCODE SCIPsetBranchruleExecExt(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECEXT((*branchexecext)))
    Definition: scip_branch.c:272
    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_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
    Definition: scip_branch.c:402
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
    Definition: tree.c:8513
    SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
    Definition: tree.c:8553
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8523
    unsigned int SCIPnodeGetReoptID(SCIP_NODE *node)
    Definition: tree.c:8594
    SCIP_REOPTNODE * SCIPgetReoptnode(SCIP *scip, unsigned int id)
    Definition: scip_reopt.c:154
    SCIP_Bool SCIPreoptimizeNode(SCIP *scip, SCIP_NODE *node)
    Definition: scip_reopt.c:424
    SCIP_RETCODE SCIPcheckReoptRestart(SCIP *scip, SCIP_NODE *node, SCIP_Bool *restart)
    Definition: scip_solve.c:3689
    SCIP_RETCODE SCIPgetReoptChildIDs(SCIP *scip, SCIP_NODE *node, unsigned int *ids, int idssize, int *nids)
    Definition: scip_reopt.c:69
    SCIP_Bool SCIPisReoptEnabled(SCIP *scip)
    Definition: scip_solve.c:3629
    SCIP_RETCODE SCIPapplyReopt(SCIP *scip, SCIP_REOPTNODE *reoptnode, unsigned int id, SCIP_Real estimate, SCIP_NODE **childnodes, int *ncreatedchilds, int *naddedconss, int childnodessize, SCIP_Bool *success)
    Definition: scip_reopt.c:382
    SCIP_Real SCIPgetReoptSimilarity(SCIP *scip, int run1, int run2)
    Definition: scip_reopt.c:407
    SCIP_RETCODE SCIPsplitReoptRoot(SCIP *scip, int *ncreatedchilds, int *naddedconss)
    Definition: scip_reopt.c:489
    int SCIPgetNReoptRuns(SCIP *scip)
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_NODE * SCIPgetRootNode(SCIP *scip)
    Definition: scip_tree.c:110
    public methods for reoptimization
    SCIP_REOPTTYPE SCIPreoptnodeGetType(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5838
    int SCIPreoptnodeGetNChildren(SCIP_REOPTNODE *reoptnode)
    Definition: reopt.c:5818
    SCIP callable library.
    internal methods for branch and bound tree
    @ SCIP_REOPTTYPE_INFSUBTREE
    Definition: type_reopt.h:60
    @ SCIP_REOPTTYPE_STRBRANCHED
    Definition: type_reopt.h:61
    enum SCIP_ReoptType SCIP_REOPTTYPE
    Definition: type_reopt.h:67
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_CUTOFF
    Definition: type_result.h:48
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_CONSADDED
    Definition: type_result.h:52
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    enum SCIP_Result SCIP_RESULT
    Definition: type_result.h:61
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63