SCIP

    Solving Constraint Integer Programs

    nodesel_estimate.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 nodesel_estimate.c
    26 * @ingroup DEFPLUGINS_NODESEL
    27 * @brief node selector for best estimate search
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    34#include "scip/pub_message.h"
    35#include "scip/pub_nodesel.h"
    36#include "scip/pub_tree.h"
    37#include "scip/scip_mem.h"
    38#include "scip/scip_message.h"
    39#include "scip/scip_nodesel.h"
    40#include "scip/scip_numerics.h"
    41#include "scip/scip_param.h"
    43#include "scip/scip_tree.h"
    44
    45
    46#define NODESEL_NAME "estimate"
    47#define NODESEL_DESC "best estimate search"
    48#define NODESEL_STDPRIORITY 200000
    49#define NODESEL_MEMSAVEPRIORITY 100
    50
    51
    52/*
    53 * Default parameter settings
    54 */
    55
    56#define DEFAULT_MINPLUNGEDEPTH -1 /**< minimal plunging depth, before new best node may be selected (-1 for dynamic setting) */
    57#define DEFAULT_MAXPLUNGEDEPTH -1 /**< maximal plunging depth, before new best node is forced to be selected (-1 for dynamic setting) */
    58#define DEFAULT_MAXPLUNGEQUOT 0.25 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
    59 * where plunging is performed */
    60#define DEFAULT_BESTNODEFREQ 10 /**< frequency at which the best node instead of the best estimate is selected (0: never) */
    61#define DEFAULT_BREADTHFIRSTDEPTH -1 /**< depth until breadth-first search is applied (-1: never) */
    62#define DEFAULT_PLUNGEOFFSET 0 /**< number of nodes before doing plunging the first time */
    63
    64
    65/** node selector data for best estimate search node selection */
    66struct SCIP_NodeselData
    67{
    68 SCIP_Real maxplungequot; /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
    69 * where plunging is performed */
    70 int minplungedepth; /**< minimal plunging depth, before new best node may be selected
    71 * (-1 for dynamic setting) */
    72 int maxplungedepth; /**< maximal plunging depth, before new best node is forced to be selected
    73 * (-1 for dynamic setting) */
    74 int bestnodefreq; /**< frequency at which the best node instead of the best estimate is selected
    75 * (0: never) */
    76 int breadthfirstdepth; /**< depth until breadth-fisrt search is applied */
    77 int plungeoffset; /**< number of nodes before doing plunging the first time */
    78};
    79
    80
    81/*
    82 * Callback methods
    83 */
    84
    85/** copy method for node selector plugins (called when SCIP copies plugins) */
    86static
    87SCIP_DECL_NODESELCOPY(nodeselCopyEstimate)
    88{ /*lint --e{715}*/
    89 assert(scip != NULL);
    90 assert(nodesel != NULL);
    91
    93
    94 /* call inclusion method of node selector */
    96
    97 return SCIP_OKAY;
    98}
    99
    100/** destructor of node selector to free user data (called when SCIP is exiting) */
    101static
    102SCIP_DECL_NODESELFREE(nodeselFreeEstimate)
    103{ /*lint --e{715}*/
    104 SCIP_NODESELDATA* nodeseldata;
    105
    106 assert(nodesel != NULL);
    107 assert(scip != NULL);
    108
    110
    111 /* free user data of node selector */
    112 nodeseldata = SCIPnodeselGetData(nodesel);
    113 assert(nodeseldata != NULL);
    114 SCIPfreeBlockMemory(scip, &nodeseldata);
    115 SCIPnodeselSetData(nodesel, nodeseldata);
    116
    117 return SCIP_OKAY;
    118}
    119
    120
    121/** node selection method of node selector */
    122static
    123SCIP_DECL_NODESELSELECT(nodeselSelectEstimate)
    124{ /*lint --e{715}*/
    125 SCIP_NODESELDATA* nodeseldata;
    126 int minplungedepth;
    127 int maxplungedepth;
    128 int plungedepth;
    129 int bestnodefreq;
    130 SCIP_Real maxplungequot;
    131
    132 assert(nodesel != NULL);
    133 assert(scip != NULL);
    134 assert(selnode != NULL);
    135
    137
    138 *selnode = NULL;
    139
    140 /* get node selector user data */
    141 nodeseldata = SCIPnodeselGetData(nodesel);
    142 assert(nodeseldata != NULL);
    143
    144 /* check if the breadth-first search should be applied */
    145 if( SCIPgetDepth(scip) <= nodeseldata->breadthfirstdepth )
    146 {
    147 SCIP_NODE* node;
    148
    149 SCIPdebugMsg(scip, "perform breadth-first search at depth <%d>\n", SCIPgetDepth(scip));
    150
    151 node = SCIPgetPrioSibling(scip);
    152 if( node != NULL )
    153 {
    154 *selnode = node;
    155 SCIPdebugMsg(scip, " -> selected prio sibling: estimate=%g\n", SCIPnodeGetEstimate(*selnode));
    156 return SCIP_OKAY;
    157 }
    158
    159 node = SCIPgetPrioChild(scip);
    160 if( node != NULL )
    161 {
    162 *selnode = node;
    163 SCIPdebugMsg(scip, " -> selected prio child: estimate=%g\n", SCIPnodeGetEstimate(*selnode));
    164 return SCIP_OKAY;
    165 }
    166 }
    167
    168 bestnodefreq = (nodeseldata->bestnodefreq == 0 ? INT_MAX : nodeseldata->bestnodefreq);
    169
    170 /* check if we don't want to do plunging yet */
    171 if( SCIPgetNNodes(scip) < nodeseldata->plungeoffset )
    172 {
    173 /* we don't want to plunge yet: select best node from the tree */
    174 SCIPdebugMsg(scip, "nnodes=%" SCIP_LONGINT_FORMAT " < %d=plungeoffset -> don't start plunging\n", SCIPgetNNodes(scip),
    175 nodeseldata->plungeoffset);
    176
    177 if( SCIPgetNNodes(scip) % bestnodefreq == 0 )
    178 *selnode = SCIPgetBestboundNode(scip);
    179 else
    180 *selnode = SCIPgetBestNode(scip);
    181 SCIPdebugMsg(scip, " -> best node : lower=%g\n",
    182 *selnode != NULL ? SCIPnodeGetLowerbound(*selnode) : SCIPinfinity(scip));
    183 return SCIP_OKAY;
    184 }
    185
    186 /* calculate minimal and maximal plunging depth */
    187 minplungedepth = nodeseldata->minplungedepth;
    188 maxplungedepth = nodeseldata->maxplungedepth;
    189 maxplungequot = nodeseldata->maxplungequot;
    190 if( minplungedepth == -1 )
    191 {
    192 minplungedepth = SCIPgetMaxDepth(scip)/10;
    194 minplungedepth += 10;
    195 if( maxplungedepth >= 0 )
    196 minplungedepth = MIN(minplungedepth, maxplungedepth);
    197 }
    198 if( maxplungedepth == -1 )
    199 maxplungedepth = SCIPgetMaxDepth(scip)/2;
    200 maxplungedepth = MAX(maxplungedepth, minplungedepth);
    201
    202 /* check, if we exceeded the maximal plunging depth */
    203 plungedepth = SCIPgetPlungeDepth(scip);
    204 if( plungedepth > maxplungedepth )
    205 {
    206 /* we don't want to plunge again: select best node from the tree */
    207 SCIPdebugMsg(scip, "plungedepth: [%d,%d], cur: %d -> abort plunging\n", minplungedepth, maxplungedepth, plungedepth);
    208 if( SCIPgetNNodes(scip) % bestnodefreq == 0 )
    209 *selnode = SCIPgetBestboundNode(scip);
    210 else
    211 *selnode = SCIPgetBestNode(scip);
    212 SCIPdebugMsg(scip, " -> best node : lower=%g\n",
    213 *selnode != NULL ? SCIPnodeGetLowerbound(*selnode) : SCIPinfinity(scip));
    214 }
    215 else
    216 {
    217 SCIP_NODE* node;
    218 SCIP_Real lowerbound;
    219 SCIP_Real cutoffbound;
    220 SCIP_Real maxbound;
    221
    222 /* get global lower and cutoff bound */
    223 lowerbound = SCIPgetLowerbound(scip);
    224 cutoffbound = SCIPgetCutoffbound(scip);
    225
    226 /* if we didn't find a solution yet, the cutoff bound is usually very bad:
    227 * use only 20% of the gap as cutoff bound
    228 */
    229 if( SCIPgetNSolsFound(scip) == 0 )
    230 cutoffbound = lowerbound + 0.2 * (cutoffbound - lowerbound);
    231
    232 /* check, if plunging is forced at the current depth */
    233 if( plungedepth < minplungedepth )
    234 maxbound = SCIPinfinity(scip);
    235 else
    236 {
    237 /* calculate maximal plunging bound */
    238 maxbound = lowerbound + maxplungequot * (cutoffbound - lowerbound);
    239 }
    240
    241 SCIPdebugMsg(scip, "plungedepth: [%d,%d], cur: %d, bounds: [%g,%g], maxbound: %g\n",
    242 minplungedepth, maxplungedepth, plungedepth, lowerbound, cutoffbound, maxbound);
    243
    244 /* we want to plunge again: prefer children over siblings, and siblings over leaves,
    245 * but only select a child or sibling, if its estimate is small enough;
    246 * prefer using nodes with higher node selection priority assigned by the branching rule
    247 */
    248 node = SCIPgetPrioChild(scip);
    249 if( node != NULL && SCIPnodeGetEstimate(node) < maxbound )
    250 {
    251 *selnode = node;
    252 SCIPdebugMsg(scip, " -> selected prio child: estimate=%g\n", SCIPnodeGetEstimate(*selnode));
    253 }
    254 else
    255 {
    256 node = SCIPgetBestChild(scip);
    257 if( node != NULL && SCIPnodeGetEstimate(node) < maxbound )
    258 {
    259 *selnode = node;
    260 SCIPdebugMsg(scip, " -> selected best child: estimate=%g\n", SCIPnodeGetEstimate(*selnode));
    261 }
    262 else
    263 {
    264 node = SCIPgetPrioSibling(scip);
    265 if( node != NULL && SCIPnodeGetEstimate(node) < maxbound )
    266 {
    267 *selnode = node;
    268 SCIPdebugMsg(scip, " -> selected prio sibling: estimate=%g\n", SCIPnodeGetEstimate(*selnode));
    269 }
    270 else
    271 {
    272 node = SCIPgetBestSibling(scip);
    273 if( node != NULL && SCIPnodeGetEstimate(node) < maxbound )
    274 {
    275 *selnode = node;
    276 SCIPdebugMsg(scip, " -> selected best sibling: estimate=%g\n", SCIPnodeGetEstimate(*selnode));
    277 }
    278 else
    279 {
    280 if( SCIPgetNNodes(scip) % bestnodefreq == 0 )
    281 *selnode = SCIPgetBestboundNode(scip);
    282 else
    283 *selnode = SCIPgetBestNode(scip);
    284 SCIPdebugMsg(scip, " -> selected best leaf: estimate=%g\n",
    285 *selnode != NULL ? SCIPnodeGetEstimate(*selnode) : SCIPinfinity(scip));
    286 }
    287 }
    288 }
    289 }
    290 }
    291
    292 return SCIP_OKAY;
    293}
    294
    295
    296/** node comparison method of node selector */
    297static
    298SCIP_DECL_NODESELCOMP(nodeselCompEstimate)
    299{ /*lint --e{715}*/
    300 SCIP_Real estimate1;
    301 SCIP_Real estimate2;
    302
    303 assert(nodesel != NULL);
    304 assert(scip != NULL);
    305
    306 estimate1 = SCIPnodeGetEstimate(node1);
    307 estimate2 = SCIPnodeGetEstimate(node2);
    308 if( (SCIPisInfinity(scip, estimate1) && SCIPisInfinity(scip, estimate2)) ||
    309 (SCIPisInfinity(scip, -estimate1) && SCIPisInfinity(scip, -estimate2)) ||
    310 SCIPisEQ(scip, estimate1, estimate2) )
    311 {
    312 SCIP_Real lowerbound1;
    313 SCIP_Real lowerbound2;
    314
    315 lowerbound1 = SCIPnodeGetLowerbound(node1);
    316 lowerbound2 = SCIPnodeGetLowerbound(node2);
    317 if( SCIPisLT(scip, lowerbound1, lowerbound2) )
    318 return -1;
    319 else if( SCIPisGT(scip, lowerbound1, lowerbound2) )
    320 return +1;
    321 else
    322 {
    323 SCIP_NODETYPE nodetype1;
    324 SCIP_NODETYPE nodetype2;
    325
    326 nodetype1 = SCIPnodeGetType(node1);
    327 nodetype2 = SCIPnodeGetType(node2);
    328 if( nodetype1 == SCIP_NODETYPE_CHILD && nodetype2 != SCIP_NODETYPE_CHILD )
    329 return -1;
    330 else if( nodetype1 != SCIP_NODETYPE_CHILD && nodetype2 == SCIP_NODETYPE_CHILD )
    331 return +1;
    332 else if( nodetype1 == SCIP_NODETYPE_SIBLING && nodetype2 != SCIP_NODETYPE_SIBLING )
    333 return -1;
    334 else if( nodetype1 != SCIP_NODETYPE_SIBLING && nodetype2 == SCIP_NODETYPE_SIBLING )
    335 return +1;
    336 else
    337 {
    338 int depth1;
    339 int depth2;
    340
    341 depth1 = SCIPnodeGetDepth(node1);
    342 depth2 = SCIPnodeGetDepth(node2);
    343 if( depth1 < depth2 )
    344 return -1;
    345 else if( depth1 > depth2 )
    346 return +1;
    347 else
    348 return 0;
    349 }
    350 }
    351 }
    352
    353 if( SCIPisLT(scip, estimate1, estimate2) )
    354 return -1;
    355
    356 assert(SCIPisGT(scip, estimate1, estimate2));
    357 return +1;
    358}
    359
    360
    361/*
    362 * estimate specific interface methods
    363 */
    364
    365/** creates the node selector for best estimate search and includes it in SCIP */
    367 SCIP* scip /**< SCIP data structure */
    368 )
    369{
    370 SCIP_NODESELDATA* nodeseldata;
    371 SCIP_NODESEL* nodesel;
    372
    373 /* allocate and initialize node selector data; this has to be freed in the destructor */
    374 SCIP_CALL( SCIPallocBlockMemory(scip, &nodeseldata) );
    375
    376 /* include node selector */
    378 nodeselSelectEstimate, nodeselCompEstimate, nodeseldata) );
    379
    380 assert(nodesel != NULL);
    381
    382 SCIP_CALL( SCIPsetNodeselCopy(scip, nodesel, nodeselCopyEstimate) );
    383 SCIP_CALL( SCIPsetNodeselFree(scip, nodesel, nodeselFreeEstimate) );
    384
    385 /* add node selector parameters */
    387 "nodeselection/estimate/minplungedepth",
    388 "minimal plunging depth, before new best node may be selected (-1 for dynamic setting)",
    389 &nodeseldata->minplungedepth, TRUE, DEFAULT_MINPLUNGEDEPTH, -1, INT_MAX, NULL, NULL) );
    391 "nodeselection/estimate/maxplungedepth",
    392 "maximal plunging depth, before new best node is forced to be selected (-1 for dynamic setting)",
    393 &nodeseldata->maxplungedepth, TRUE, DEFAULT_MAXPLUNGEDEPTH, -1, INT_MAX, NULL, NULL) );
    395 "nodeselection/estimate/maxplungequot",
    396 "maximal quotient (estimate - lowerbound)/(cutoffbound - lowerbound) where plunging is performed",
    397 &nodeseldata->maxplungequot, TRUE, DEFAULT_MAXPLUNGEQUOT, 0.0, SCIP_REAL_MAX, NULL, NULL) );
    399 "nodeselection/estimate/bestnodefreq",
    400 "frequency at which the best node instead of the best estimate is selected (0: never)",
    401 &nodeseldata->bestnodefreq, FALSE, DEFAULT_BESTNODEFREQ, 0, INT_MAX, NULL, NULL) );
    403 "nodeselection/estimate/breadthfirstdepth",
    404 "depth until breadth-first search is applied",
    405 &nodeseldata->breadthfirstdepth, FALSE, DEFAULT_BREADTHFIRSTDEPTH, -1, INT_MAX, NULL, NULL) );
    407 "nodeselection/estimate/plungeoffset",
    408 "number of nodes before doing plunging the first time",
    409 &nodeseldata->plungeoffset, FALSE, DEFAULT_PLUNGEOFFSET, 0, INT_MAX, NULL, NULL) );
    410
    411 return SCIP_OKAY;
    412}
    413
    #define NULL
    Definition: def.h:257
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIP_LONGINT_FORMAT
    Definition: def.h:157
    #define SCIP_CALL(x)
    Definition: def.h:364
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPincludeNodeselEstimate(SCIP *scip)
    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 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
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_NODETYPE SCIPnodeGetType(SCIP_NODE *node)
    Definition: tree.c:8503
    SCIP_Real SCIPnodeGetLowerbound(SCIP_NODE *node)
    Definition: tree.c:8533
    SCIP_Real SCIPnodeGetEstimate(SCIP_NODE *node)
    Definition: tree.c:8553
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8523
    SCIP_RETCODE SCIPincludeNodeselBasic(SCIP *scip, SCIP_NODESEL **nodesel, const char *name, const char *desc, int stdpriority, int memsavepriority, SCIP_DECL_NODESELSELECT((*nodeselselect)), SCIP_DECL_NODESELCOMP((*nodeselcomp)), SCIP_NODESELDATA *nodeseldata)
    Definition: scip_nodesel.c:111
    void SCIPnodeselSetData(SCIP_NODESEL *nodesel, SCIP_NODESELDATA *nodeseldata)
    Definition: nodesel.c:1273
    SCIP_RETCODE SCIPsetNodeselFree(SCIP *scip, SCIP_NODESEL *nodesel, SCIP_DECL_NODESELFREE((*nodeselfree)))
    Definition: scip_nodesel.c:162
    SCIP_NODESELDATA * SCIPnodeselGetData(SCIP_NODESEL *nodesel)
    Definition: nodesel.c:1263
    SCIP_RETCODE SCIPsetNodeselCopy(SCIP *scip, SCIP_NODESEL *nodesel, SCIP_DECL_NODESELCOPY((*nodeselcopy)))
    Definition: scip_nodesel.c:146
    const char * SCIPnodeselGetName(SCIP_NODESEL *nodesel)
    Definition: nodesel.c:1195
    SCIP_Longint SCIPgetNSolsFound(SCIP *scip)
    int SCIPgetMaxDepth(SCIP *scip)
    SCIP_Longint SCIPgetNNodes(SCIP *scip)
    SCIP_Longint SCIPgetNStrongbranchLPIterations(SCIP *scip)
    SCIP_Real SCIPgetLowerbound(SCIP *scip)
    SCIP_Longint SCIPgetNNodeLPIterations(SCIP *scip)
    SCIP_Real SCIPgetCutoffbound(SCIP *scip)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_NODE * SCIPgetBestSibling(SCIP *scip)
    Definition: scip_tree.c:336
    SCIP_NODE * SCIPgetBestChild(SCIP *scip)
    Definition: scip_tree.c:320
    SCIP_NODE * SCIPgetPrioSibling(SCIP *scip)
    Definition: scip_tree.c:304
    int SCIPgetDepth(SCIP *scip)
    Definition: scip_tree.c:672
    SCIP_NODE * SCIPgetBestNode(SCIP *scip)
    Definition: scip_tree.c:368
    int SCIPgetPlungeDepth(SCIP *scip)
    Definition: scip_tree.c:715
    SCIP_NODE * SCIPgetBestboundNode(SCIP *scip)
    Definition: scip_tree.c:384
    SCIP_NODE * SCIPgetPrioChild(SCIP *scip)
    Definition: scip_tree.c:288
    static SCIP_DECL_NODESELFREE(nodeselFreeEstimate)
    #define DEFAULT_MAXPLUNGEDEPTH
    #define NODESEL_NAME
    static SCIP_DECL_NODESELCOMP(nodeselCompEstimate)
    #define NODESEL_MEMSAVEPRIORITY
    #define NODESEL_STDPRIORITY
    #define NODESEL_DESC
    #define DEFAULT_BESTNODEFREQ
    static SCIP_DECL_NODESELCOPY(nodeselCopyEstimate)
    static SCIP_DECL_NODESELSELECT(nodeselSelectEstimate)
    #define DEFAULT_PLUNGEOFFSET
    #define DEFAULT_BREADTHFIRSTDEPTH
    #define DEFAULT_MINPLUNGEDEPTH
    #define DEFAULT_MAXPLUNGEQUOT
    node selector for best estimate search
    public methods for message output
    public methods for node selectors
    public methods for branch and bound tree
    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 querying solving statistics
    public methods for the branch-and-bound tree
    struct SCIP_NodeselData SCIP_NODESELDATA
    Definition: type_nodesel.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    enum SCIP_NodeType SCIP_NODETYPE
    Definition: type_tree.h:53
    @ SCIP_NODETYPE_CHILD
    Definition: type_tree.h:44
    @ SCIP_NODETYPE_SIBLING
    Definition: type_tree.h:43