SCIP

    Solving Constraint Integer Programs

    branch_pscost.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_pscost.c
    26 * @ingroup DEFPLUGINS_BRANCH
    27 * @brief pseudo costs branching rule
    28 * @author Tobias Achterberg
    29 * @author Stefan Vigerske
    30 * @author Krunal Patel
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    36#include "scip/branch_pscost.h"
    37#include "scip/pub_branch.h"
    38#include "scip/pub_message.h"
    39#include "scip/pub_misc.h"
    40#include "scip/pub_misc_sort.h"
    41#include "scip/pub_tree.h"
    42#include "scip/pub_var.h"
    43#include "scip/scip_branch.h"
    44#include "scip/scip_mem.h"
    45#include "scip/scip_message.h"
    46#include "scip/scip_numerics.h"
    47#include "scip/scip_param.h"
    49#include "scip/scip_sol.h"
    50#include "scip/scip_tree.h"
    51#include "scip/scip_var.h"
    52
    53
    54#define BRANCHRULE_NAME "pscost"
    55#define BRANCHRULE_DESC "branching on pseudo cost values"
    56#define BRANCHRULE_PRIORITY 2000
    57#define BRANCHRULE_MAXDEPTH -1
    58#define BRANCHRULE_MAXBOUNDDIST 1.0
    59
    60#define BRANCHRULE_STRATEGIES "dsuv" /**< possible pseudo cost multiplication strategies for branching on external candidates */
    61#define BRANCHRULE_STRATEGY_DEFAULT 'u' /**< default pseudo cost multiplication strategy */
    62#define BRANCHRULE_SCOREMINWEIGHT_DEFAULT 0.8 /**< default weight for minimum of scores of a branching candidate */
    63#define BRANCHRULE_SCOREMAXWEIGHT_DEFAULT 1.3 /**< default weight for maximum of scores of a branching candidate */
    64#define BRANCHRULE_SCORESUMWEIGHT_DEFAULT 0.1 /**< default weight for sum of scores of a branching candidate */
    65#define BRANCHRULE_NCHILDREN_DEFAULT 2 /**< default number of children in n-ary branching */
    66#define BRANCHRULE_NARYMAXDEPTH_DEFAULT -1 /**< default maximal depth where to do n-ary branching */
    67#define BRANCHRULE_NARYMINWIDTH_DEFAULT 0.001 /**< default minimal domain width in children when doing n-ary branching */
    68#define BRANCHRULE_NARYWIDTHFAC_DEFAULT 2.0 /**< default factor of domain width in n-ary branching */
    69#define BRANCHRULE_RANDSEED_DEFAULT 47 /**< initial random seed */
    70#define BRANCHRULE_DISCOUNTFACTOR 0.2 /**< default discount factor for discounted pseudo costs */
    71
    72
    73#define WEIGHTEDSCORING(data, min, max, sum) \
    74 ((data)->scoreminweight * (min) + (data)->scoremaxweight * (max) + (data)->scoresumweight * (sum))
    75
    76/** branching rule data */
    77struct SCIP_BranchruleData
    78{
    79 SCIP_RANDNUMGEN* randnumgen; /**< random number generator */
    80
    81 char strategy; /**< strategy for computing score of external candidates */
    82 SCIP_Real scoreminweight; /**< weight for minimum of scores of a branching candidate */
    83 SCIP_Real scoremaxweight; /**< weight for maximum of scores of a branching candidate */
    84 SCIP_Real scoresumweight; /**< weight for sum of scores of a branching candidate */
    85
    86 char updatestrategy; /**< strategy used to update pseudo costs of continuous variables */
    87
    88 int nchildren; /**< targeted number of children in n-ary branching */
    89 int narymaxdepth; /**< maximal depth where to do n-ary branching, -1 to turn off */
    90 SCIP_Real naryminwidth; /**< minimal domain width in children when doing n-ary branching, relative to global bounds */
    91 SCIP_Real narywidthfactor; /**< factor of domain width in n-ary branching */
    92 SCIP_Real discountfactor; /**< discount factor for discounted pseudo costs.*/
    93};
    94
    95/*
    96 * Local methods
    97 */
    98
    99/** checks if a given branching candidate is better than a previous one and updates the best branching candidate accordingly */
    100static
    102 SCIP* scip, /**< SCIP data structure */
    103 SCIP_BRANCHRULEDATA* branchruledata, /**< branching rule data */
    104 SCIP_VAR** bestvar, /**< best branching candidate */
    105 SCIP_Real* bestbrpoint, /**< branching point for best branching candidate */
    106 SCIP_Real* bestscore, /**< score of best branching candidate */
    107 SCIP_Real* bestrndscore, /**< random score of the best branching candidate */
    108 SCIP_VAR* cand, /**< branching candidate to consider */
    109 SCIP_Real candscoremin, /**< minimal score of branching candidate */
    110 SCIP_Real candscoremax, /**< maximal score of branching candidate */
    111 SCIP_Real candscoresum, /**< sum of scores of branching candidate */
    112 SCIP_Real candrndscore, /**< random score of branching candidate */
    113 SCIP_Real candsol /**< proposed branching point of branching candidate */
    114 )
    115{
    116 SCIP_Real candbrpoint;
    117 SCIP_Real branchscore;
    118
    119 SCIP_Real deltaminus;
    120 SCIP_Real deltaplus;
    121
    122 SCIP_Real pscostdown;
    123 SCIP_Real pscostup;
    124
    125 SCIP_VARTYPE besttype;
    126 SCIP_VARTYPE candtype;
    127
    128 char strategy;
    129
    130 assert(scip != NULL);
    131 assert(branchruledata != NULL);
    132 assert(bestvar != NULL);
    133 assert(bestbrpoint != NULL);
    134 assert(bestscore != NULL);
    135 assert(cand != NULL);
    136
    137 /* a branching variable candidate should either be an active problem variable or a multi-aggregated variable */
    138 assert(SCIPvarIsActive(SCIPvarGetProbvar(cand)) ||
    140
    142 {
    143 /* for a multi-aggregated variable, we call updateBestCandidate function recursively with all variables in the multi-aggregation */
    144 SCIP_VAR** multvars;
    145 int nmultvars;
    146 int i;
    147 SCIP_Bool success;
    148 SCIP_Real multvarlb;
    149 SCIP_Real multvarub;
    150
    151 cand = SCIPvarGetProbvar(cand);
    152 multvars = SCIPvarGetMultaggrVars(cand);
    153 nmultvars = SCIPvarGetMultaggrNVars(cand);
    154
    155 /* if we have a candidate branching point, then first register only aggregation variables
    156 * for which we can compute a corresponding branching point too (see also comments below)
    157 * if this fails, then register all (unfixed) aggregation variables, thereby forgetting about candsol
    158 */
    159 success = FALSE;
    160 if( candsol != SCIP_INVALID ) /*lint !e777*/
    161 {
    162 SCIP_Real* multscalars;
    163 SCIP_Real minact;
    164 SCIP_Real maxact;
    165 SCIP_Real aggrvarsol;
    166 SCIP_Real aggrvarsol1;
    167 SCIP_Real aggrvarsol2;
    168
    169 multscalars = SCIPvarGetMultaggrScalars(cand);
    170
    171 /* for computing the branching point, we need the current bounds of the multi-aggregated variable */
    172 minact = SCIPcomputeVarLbLocal(scip, cand);
    173 maxact = SCIPcomputeVarUbLocal(scip, cand);
    174
    175 for( i = 0; i < nmultvars; ++i )
    176 {
    177 /* skip fixed variables */
    178 multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
    179 multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
    180 if( SCIPisEQ(scip, multvarlb, multvarub) )
    181 continue;
    182
    183 assert(multscalars != NULL);
    184 assert(multscalars[i] != 0.0);
    185
    186 /* we cannot ensure that both the upper bound in the left node and the lower bound in the right node
    187 * will be candsol by a clever choice for the branching point of multvars[i],
    188 * but we can try to ensure that at least one of them will be at candsol
    189 */
    190 if( multscalars[i] > 0.0 )
    191 {
    192 /* cand >= candsol
    193 * if multvars[i] >= (candsol - (maxact - multscalars[i] * ub(multvars[i]))) / multscalars[i]
    194 * = (candsol - maxact) / multscalars[i] + ub(multvars[i])
    195 */
    196 aggrvarsol1 = (candsol - maxact) / multscalars[i] + multvarub;
    197
    198 /* cand <= candsol
    199 * if multvars[i] <= (candsol - (minact - multscalar[i] * lb(multvars[i]))) / multscalars[i]
    200 * = (candsol - minact) / multscalars[i] + lb(multvars[i])
    201 */
    202 aggrvarsol2 = (candsol - minact) / multscalars[i] + multvarlb;
    203 }
    204 else
    205 {
    206 /* cand >= candsol
    207 * if multvars[i] <= (candsol - (maxact - multscalars[i] * lb(multvars[i]))) / multscalars[i]
    208 * = (candsol - maxact) / multscalars[i] + lb(multvars[i])
    209 */
    210 aggrvarsol2 = (candsol - maxact) / multscalars[i] + multvarlb;
    211
    212 /* cand <= candsol
    213 * if multvars[i] >= (candsol - (minact - multscalar[i] * ub(multvars[i]))) / multscalars[i]
    214 * = (candsol - minact) / multscalars[i] + ub(multvars[i])
    215 */
    216 aggrvarsol1 = (candsol - minact) / multscalars[i] + multvarub;
    217 }
    218
    219 /* by the above choice, aggrvarsol1 <= ub(multvars[i]) and aggrvarsol2 >= lb(multvars[i])
    220 * if aggrvarsol1 <= lb(multvars[i]) or aggrvarsol2 >= ub(multvars[i]), then choose the other one
    221 * if both are out of bounds, then give up
    222 * if both are inside bounds, then choose the one closer to 0.0 (someone has better idea???)
    223 */
    224 if( SCIPisFeasLE(scip, aggrvarsol1, multvarlb) )
    225 {
    226 if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
    227 continue;
    228 else
    229 aggrvarsol = aggrvarsol2;
    230 }
    231 else
    232 {
    233 if( SCIPisFeasGE(scip, aggrvarsol2, multvarub) )
    234 aggrvarsol = aggrvarsol1;
    235 else
    236 aggrvarsol = REALABS(aggrvarsol1) < REALABS(aggrvarsol2) ? aggrvarsol1 : aggrvarsol2;
    237 }
    238 success = TRUE;
    239
    240 SCIP_CALL( updateBestCandidate(scip, branchruledata, bestvar, bestbrpoint, bestscore, bestrndscore,
    241 multvars[i], candscoremin, candscoremax, candscoresum, candrndscore, aggrvarsol) );
    242 }
    243 }
    244
    245 if( !success )
    246 for( i = 0; i < nmultvars; ++i )
    247 {
    248 /* skip fixed variables */
    249 multvarlb = SCIPcomputeVarLbLocal(scip, multvars[i]);
    250 multvarub = SCIPcomputeVarUbLocal(scip, multvars[i]);
    251 if( SCIPisEQ(scip, multvarlb, multvarub) )
    252 continue;
    253
    254 SCIP_CALL( updateBestCandidate(scip, branchruledata, bestvar, bestbrpoint, bestscore, bestrndscore,
    255 multvars[i], candscoremin, candscoremax, candscoresum, candrndscore, SCIP_INVALID) );
    256 }
    257
    258 assert(*bestvar != NULL); /* if all variables were fixed, something is strange */
    259
    260 return SCIP_OKAY;
    261 }
    262
    263 /* select branching point for this variable */
    264 candbrpoint = SCIPgetBranchingPoint(scip, cand, candsol);
    265 assert(candbrpoint >= SCIPvarGetLbLocal(cand));
    266 assert(candbrpoint <= SCIPvarGetUbLocal(cand));
    267
    268 /* we cannot branch on a huge value for a discrete variable, because we simply cannot enumerate such huge integer values in floating point
    269 * arithmetics
    270 */
    271 if( SCIPvarIsIntegral(cand) && (SCIPisHugeValue(scip, candbrpoint) || SCIPisHugeValue(scip, -candbrpoint)) )
    272 return SCIP_OKAY;
    273
    274 assert(!SCIPvarIsIntegral(cand) || !SCIPisIntegral(scip, candbrpoint));
    275
    276 if( !SCIPvarIsIntegral(cand) )
    277 strategy = (branchruledata->strategy == 'u' ? branchruledata->updatestrategy : branchruledata->strategy);
    278 else
    279 strategy = (branchruledata->strategy == 'u' ? 'l' : branchruledata->strategy);
    280
    281 switch( strategy )
    282 {
    283 case 'l':
    284 if( SCIPisInfinity(scip, SCIPgetSolVal(scip, NULL, cand)) || SCIPgetSolVal(scip, NULL, cand) <= SCIPadjustedVarUb(scip, cand, candbrpoint) )
    285 deltaminus = 0.0;
    286 else
    287 deltaminus = SCIPgetSolVal(scip, NULL, cand) - SCIPadjustedVarUb(scip, cand, candbrpoint);
    288 if( SCIPisInfinity(scip, -SCIPgetSolVal(scip, NULL, cand)) || SCIPgetSolVal(scip, NULL, cand) >= SCIPadjustedVarLb(scip, cand, candbrpoint) )
    289 deltaplus = 0.0;
    290 else
    291 deltaplus = SCIPadjustedVarLb(scip, cand, candbrpoint) - SCIPgetSolVal(scip, NULL, cand);
    292 break;
    293
    294 case 'd':
    296 deltaminus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
    297 else
    298 deltaminus = SCIPadjustedVarUb(scip, cand, candbrpoint) - SCIPvarGetLbLocal(cand);
    299
    301 deltaplus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
    302 else
    303 deltaplus = SCIPvarGetUbLocal(cand) - SCIPadjustedVarLb(scip, cand, candbrpoint);
    304 break;
    305
    306 case 's':
    308 deltaplus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
    309 else
    310 deltaplus = SCIPadjustedVarUb(scip, cand, candbrpoint) - SCIPvarGetLbLocal(cand);
    311
    313 deltaminus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
    314 else
    315 deltaminus = SCIPvarGetUbLocal(cand) - SCIPadjustedVarLb(scip, cand, candbrpoint);
    316 break;
    317
    318 case 'v':
    319 deltaplus = SCIPisInfinity(scip, candscoremax) ? SCIPinfinity(scip) : WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum);
    320 deltaminus = deltaplus;
    321 break;
    322
    323 default :
    324 SCIPerrorMessage("branching strategy %c unknown\n", strategy);
    325 SCIPABORT();
    326 return SCIP_INVALIDDATA; /*lint !e527*/
    327 }
    328
    329 if( SCIPisInfinity(scip, deltaminus) || SCIPisInfinity(scip, deltaplus) )
    330 {
    331 branchscore = SCIPinfinity(scip);
    332 }
    333 else
    334 {
    335 pscostdown = SCIPgetVarPseudocostVal(scip, cand, -deltaminus);
    336 pscostup = SCIPgetVarPseudocostVal(scip, cand, deltaplus);
    337 branchscore = SCIPgetBranchScore(scip, cand, pscostdown, pscostup);
    338 assert(!SCIPisNegative(scip, branchscore));
    339 }
    340 SCIPdebugMsg(scip, "branching score variable <%s>[%g,%g] = %g; wscore = %g; type=%d bestbrscore=%g\n",
    341 SCIPvarGetName(cand), SCIPvarGetLbLocal(cand), SCIPvarGetUbLocal(cand), branchscore, WEIGHTEDSCORING(branchruledata, candscoremin, candscoremax, candscoresum),
    342 SCIPvarGetType(cand), *bestscore);
    343
    344 if( SCIPisInfinity(scip, branchscore) )
    345 branchscore = 0.9*SCIPinfinity(scip);
    346
    347 if( SCIPisSumGT(scip, branchscore, *bestscore) )
    348 {
    349 (*bestscore) = branchscore;
    350 (*bestrndscore) = candrndscore;
    351 (*bestvar) = cand;
    352 (*bestbrpoint) = candbrpoint;
    353 return SCIP_OKAY;
    354 }
    355
    356 /* if score of candidate is worse than bestscore, stay with best candidate */
    357 if( !SCIPisSumEQ(scip, branchscore, *bestscore) )
    358 return SCIP_OKAY;
    359
    361 {
    362 /* best candidate is unbounded -> we prefer to branch on it */
    364 SCIPrandomGetReal(branchruledata->randnumgen, 0.0, 1.0) <= 0.5
    365 )
    366 {
    367 /* but if the new candidate is also unbounded (thus as good as best candidate),
    368 * then switch to the candidate with 50% probability to reduce performance variability
    369 */
    370 (*bestscore) = branchscore;
    371 (*bestrndscore) = candrndscore;
    372 (*bestvar) = cand;
    373 (*bestbrpoint) = candbrpoint;
    374 }
    375
    376 return SCIP_OKAY;
    377 }
    378
    379 /* best candidate has a finite lower or upper bound -> consider taking the other candidate */
    380
    383 {
    384 /* both candidates are unbounded, but one side may be finite (for bestcand we know there is one)
    385 * take the candidate with the larger bound on the bounded side (hope that this avoids branching on always the same variable)
    386 * this will also prefer unbounded variables over bounded ones
    387 */
    388 if( SCIPvarGetUbLocal(cand) > SCIPvarGetUbLocal(*bestvar) || SCIPvarGetLbLocal(cand) < SCIPvarGetLbLocal(*bestvar) )
    389 {
    390 /* cand is better than bestvar */
    391 (*bestscore) = branchscore;
    392 (*bestrndscore) = candrndscore;
    393 (*bestvar) = cand;
    394 (*bestbrpoint) = candbrpoint;
    395 return SCIP_OKAY;
    396 }
    397
    398 if( SCIPvarGetUbLocal(*bestvar) > SCIPvarGetUbLocal(cand) || SCIPvarGetLbLocal(*bestvar) < SCIPvarGetLbLocal(cand) )
    399 {
    400 /* bestvar is better than cand */
    401 return SCIP_OKAY;
    402 }
    403
    404 /* both are equally good */
    405 }
    406
    407 /* @TODO: handle implied integrality like in relpscost */
    410
    411 if( besttype == candtype )
    412 {
    413 /* if both have the same type, take the one with larger relative diameter */
    415 {
    416 /* cand has larger diameter than bestvar*/
    417 (*bestscore) = branchscore;
    418 (*bestrndscore) = candrndscore;
    419 (*bestvar) = cand;
    420 (*bestbrpoint) = candbrpoint;
    421 return SCIP_OKAY;
    422 }
    423
    425 {
    426 /* bestvar has larger diameter than cand */
    427 return SCIP_OKAY;
    428 }
    429 }
    430
    431 /* take the one with better type ("more discrete") */
    432 if( besttype > candtype )
    433 {
    434 /* cand is more discrete than bestvar */
    435 (*bestscore) = branchscore;
    436 (*bestrndscore) = candrndscore;
    437 (*bestvar) = cand;
    438 (*bestbrpoint) = candbrpoint;
    439 return SCIP_OKAY;
    440 }
    441 if( besttype < candtype )
    442 {
    443 /* bestvar is more discrete than cand */
    444 return SCIP_OKAY;
    445 }
    446
    447 /* cand seems to be as good as the currently best one (bestvar); use the random score as a final tie-breaker */
    448 if( candrndscore >= (*bestrndscore) )
    449 {
    450 (*bestscore) = branchscore;
    451 (*bestrndscore) = candrndscore;
    452 (*bestvar) = cand;
    453 (*bestbrpoint) = candbrpoint;
    454 }
    455
    456 return SCIP_OKAY;
    457}
    458
    459/** selects the branching variable from given candidate array */
    460static
    462 SCIP* scip, /**< SCIP data structure */
    463 SCIP_BRANCHRULE* branchrule, /**< branching rule */
    464 SCIP_VAR** cands, /**< array of branching candidates */
    465 SCIP_Real* candssol, /**< array of candidate solution values */
    466 SCIP_Real* candsscore, /**< array of candidate scores */
    467 int ncands, /**< the number of candidates */
    468 SCIP_VAR** brvar, /**< pointer to store the selected branching candidate or NULL if none */
    469 SCIP_Real* brpoint /**< pointer to store branching point of selected branching variable */
    470 )
    471{ /*lint --e{850}*/
    472 SCIP_BRANCHRULEDATA* branchruledata;
    473
    474 SCIP_VAR* cand;
    475 SCIP_Real candsol;
    476
    477 SCIP_Real bestbranchscore;
    478 SCIP_Real bestrndscore;
    479
    480 SCIP_Real scoremin;
    481 SCIP_Real scoresum;
    482 SCIP_Real scoremax;
    483
    484 SCIP_VAR** candssorted;
    485 int* candsorigidx;
    486
    487 int i;
    488 int j;
    489
    490 assert(brvar != NULL);
    491 assert(brpoint != NULL);
    492
    493 (*brvar) = NULL;
    494 (*brpoint) = SCIP_INVALID;
    495
    496 if( ncands == 0 )
    497 return SCIP_OKAY;
    498
    499 branchruledata = SCIPbranchruleGetData(branchrule);
    500 assert(branchruledata != NULL);
    501
    502 /* sort branching candidates (in a copy), such that same variables are on consecutive positions */
    503 SCIP_CALL( SCIPduplicateBufferArray(scip, &candssorted, cands, ncands) );
    504 SCIP_CALL( SCIPallocBufferArray(scip, &candsorigidx, ncands) );
    505 for( i = 0; i < ncands; ++i )
    506 candsorigidx[i] = i;
    507
    508 SCIPsortPtrInt((void**)candssorted, candsorigidx, SCIPvarComp, ncands);
    509
    510 bestbranchscore = -1.0;
    511 bestrndscore = -1.0;
    512
    513 for( i = 0; i < ncands; ++i )
    514 {
    515 cand = candssorted[i];
    516
    517 /* there should be no fixed branching candidates */
    518 assert(!SCIPisEQ(scip, SCIPvarGetLbLocal(cand), SCIPvarGetUbLocal(cand)));
    519
    520 /* compute min, sum, and max of all registered scores for this variables
    521 * set candsol to a valid value, if someone registered one */
    522 scoremin = candsscore[candsorigidx[i]];
    523 scoresum = scoremin;
    524 scoremax = scoremin;
    525 candsol = candssol[candsorigidx[i]];
    526 for( j = i+1 ; j < ncands && SCIPvarCompare(candssorted[j], cand) == 0; ++j )
    527 {
    528 assert(candsscore[candsorigidx[j]] >= 0.0);
    529 scoresum += candsscore[candsorigidx[j]];
    530 if( candsscore[candsorigidx[j]] < scoremin )
    531 scoremin = candsscore[candsorigidx[j]];
    532 else if( candsscore[candsorigidx[j]] > scoremax )
    533 scoremax = candsscore[candsorigidx[j]];
    534
    535 /* @todo if there are two valid externcandssol available for the same variable, should we take the one closer to the middle of the domain? */
    536 if( SCIPisInfinity(scip, REALABS(candsol)) )
    537 candsol = candssol[candsorigidx[j]];
    538 }
    539 /* set i to last occurrence of cand in candssorted (instead of first one as before), so in next round we look at another variable */
    540 i = j-1;
    541 assert(candssorted[i] == cand);
    542
    543 /* check if new candidate is better than previous candidate (if any) */
    544 SCIP_CALL( updateBestCandidate(scip, branchruledata, brvar, brpoint, &bestbranchscore, &bestrndscore, cand,
    545 scoremin, scoremax, scoresum, SCIPrandomGetReal(branchruledata->randnumgen, 0.0, 1.0), candsol) );
    546 }
    547
    548 /* there were candidates, but no variable was selected; this can only happen if the branching points are huge values
    549 * for all non-continuous variables on which we cannot branch
    550 * @todo delay the node?
    551 */
    552 if( (*brvar) == NULL )
    553 {
    554 SCIPerrorMessage("no branching could be created: all external candidates have huge bounds\n");
    555 return SCIP_BRANCHERROR; /*lint !e527*/
    556 }
    557
    558 /* free buffer arrays */
    559 SCIPfreeBufferArray(scip, &candsorigidx);
    560 SCIPfreeBufferArray(scip, &candssorted);
    561
    562 return SCIP_OKAY;
    563}
    564
    565/*
    566 * Callback methods
    567 */
    568
    569/** copy method for branchrule plugins (called when SCIP copies plugins) */
    570static
    571SCIP_DECL_BRANCHCOPY(branchCopyPscost)
    572{ /*lint --e{715}*/
    573 assert(scip != NULL);
    574 assert(branchrule != NULL);
    575
    577
    578 /* call inclusion method of branchrule */
    580
    581 return SCIP_OKAY;
    582}
    583
    584/** destructor of branching rule to free user data (called when SCIP is exiting) */
    585static
    586SCIP_DECL_BRANCHFREE(branchFreePscost)
    587{ /*lint --e{715}*/
    588 SCIP_BRANCHRULEDATA* branchruledata;
    589
    590 /* get branching rule data */
    591 branchruledata = SCIPbranchruleGetData(branchrule);
    592 assert(branchruledata != NULL);
    593
    594 /* free random number generator */
    595 SCIPfreeRandom(scip, &branchruledata->randnumgen);
    596
    597 /* free branching rule data */
    598 SCIPfreeBlockMemory(scip, &branchruledata);
    599 SCIPbranchruleSetData(branchrule, NULL);
    600
    601 return SCIP_OKAY;
    602}
    603
    604/** initialization method of branching rule (called after problem was transformed) */
    605static
    606SCIP_DECL_BRANCHINIT(branchInitPscost)
    607{ /*lint --e{715}*/
    608 SCIP_BRANCHRULEDATA* branchruledata;
    609
    610 /* initialize branching rule data */
    611 branchruledata = SCIPbranchruleGetData(branchrule);
    612 assert(branchruledata != NULL);
    613
    614 SCIPsetRandomSeed(scip, branchruledata->randnumgen, BRANCHRULE_RANDSEED_DEFAULT);
    615
    616 return SCIP_OKAY;
    617}
    618
    619/** branching execution method for fractional LP solutions */
    620static
    621SCIP_DECL_BRANCHEXECLP(branchExeclpPscost)
    622{ /*lint --e{715}*/
    623 SCIP_BRANCHRULEDATA* branchruledata;
    624 SCIP_VAR** lpcands;
    625 SCIP_Real* lpcandssol;
    626 SCIP_Real bestscore;
    627 SCIP_Real bestrootdiff;
    628 int nlpcands;
    629 int bestcand;
    630 int c;
    631
    632 assert(branchrule != NULL);
    633 assert(scip != NULL);
    634 assert(result != NULL);
    635
    637
    638 branchruledata = SCIPbranchruleGetData(branchrule);
    639 assert(branchruledata != NULL);
    640
    641 SCIPdebugMsg(scip, "Execlp method of pscost branching\n");
    642
    643 /* get branching candidates */
    644 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, NULL, &nlpcands, NULL) );
    645 assert(nlpcands > 0);
    646
    647 bestcand = -1;
    648 bestscore = -SCIPinfinity(scip);
    649 bestrootdiff = 0.0;
    650 for( c = 0; c < nlpcands; ++c )
    651 {
    652 SCIP_Real score;
    653 SCIP_Real rootsolval;
    654 SCIP_Real rootdiff;
    655
    656 score = SCIPgetVarDPseudocostScore(scip, lpcands[c], lpcandssol[c], branchruledata->discountfactor);
    657 rootsolval = SCIPvarGetRootSol(lpcands[c]);
    658 rootdiff = REALABS(lpcandssol[c] - rootsolval);
    659 if( SCIPisSumGT(scip, score, bestscore) || (SCIPisSumEQ(scip, score, bestscore) && rootdiff > bestrootdiff) )
    660 {
    661 bestcand = c;
    662 bestscore = score;
    663 bestrootdiff = rootdiff;
    664 }
    665 }
    666 assert(0 <= bestcand && bestcand < nlpcands);
    667 assert(!SCIPisFeasIntegral(scip, lpcandssol[bestcand]));
    668 assert(!SCIPisFeasIntegral(scip, SCIPvarGetSol(lpcands[bestcand], TRUE)));
    669
    670 /* perform the branching */
    671 SCIPdebugMsg(scip, " -> %d cands, selected cand %d: variable <%s> (solval=%g, score=%g)\n",
    672 nlpcands, bestcand, SCIPvarGetName(lpcands[bestcand]), lpcandssol[bestcand], bestscore);
    673
    674 /* perform the branching */
    675 SCIP_CALL( SCIPbranchVar(scip, lpcands[bestcand], NULL, NULL, NULL) );
    676 *result = SCIP_BRANCHED;
    677
    678 return SCIP_OKAY;
    679}
    680
    681
    682/** branching execution method for external candidates
    683 *
    684 * @todo extend discounted pseudocosts for non-linear problems
    685 */
    686static
    687SCIP_DECL_BRANCHEXECEXT(branchExecextPscost)
    688{ /*lint --e{715}*/
    689 SCIP_BRANCHRULEDATA* branchruledata;
    690 SCIP_VAR** externcands;
    691 SCIP_Real* externcandssol;
    692 SCIP_Real* externcandsscore;
    693 int nprioexterncands;
    694 SCIP_VAR* brvar;
    695 SCIP_Real brpoint;
    696 int nchildren;
    697
    698 assert(branchrule != NULL);
    699 assert(scip != NULL);
    700 assert(result != NULL);
    701
    703
    704 branchruledata = SCIPbranchruleGetData(branchrule);
    705 assert(branchruledata != NULL);
    706
    707 SCIPdebugMsg(scip, "Execext method of pscost branching\n");
    708
    709 /* get branching candidates */
    710 SCIP_CALL( SCIPgetExternBranchCands(scip, &externcands, &externcandssol, &externcandsscore, NULL, &nprioexterncands, NULL, NULL, NULL) );
    711 assert(nprioexterncands > 0);
    712
    713 /* get current update strategy for pseudo costs, if our multiplier rule is 'u' */
    714 if( branchruledata->strategy == 'u' )
    715 {
    716 SCIP_CALL( SCIPgetCharParam(scip, "branching/lpgainnormalize", &branchruledata->updatestrategy) );
    717 }
    718
    719 /* select branching variable */
    720 SCIP_CALL( selectBranchVar(scip, branchrule, externcands, externcandssol, externcandsscore, nprioexterncands, &brvar, &brpoint) );
    721
    722 if( brvar == NULL )
    723 {
    724 /* can happen if all candidates were non-continous variables with huge bounds */
    725 *result = SCIP_DIDNOTFIND;
    726 return SCIP_OKAY;
    727 }
    728
    729 assert(SCIPvarIsActive(SCIPvarGetProbvar(brvar)));
    730
    731 SCIPdebugMsg(scip, "branching on variable <%s>: new intervals: [%g, %g] and [%g, %g]\n",
    732 SCIPvarGetName(brvar), SCIPvarGetLbLocal(brvar), SCIPadjustedVarUb(scip, brvar, brpoint), SCIPadjustedVarLb(scip, brvar, brpoint), SCIPvarGetUbLocal(brvar));
    733
    734 if( branchruledata->nchildren > 2 && SCIPnodeGetDepth(SCIPgetCurrentNode(scip)) <= branchruledata->narymaxdepth )
    735 {
    736 /* do n-ary branching */
    737 SCIP_Real minwidth;
    738
    739 minwidth = 0.0;
    741 minwidth = branchruledata->naryminwidth * (SCIPvarGetUbGlobal(brvar) - SCIPvarGetLbGlobal(brvar));
    742
    743 SCIP_CALL( SCIPbranchVarValNary(scip, brvar, brpoint, branchruledata->nchildren, minwidth, branchruledata->narywidthfactor, &nchildren) );
    744 }
    745 else
    746 {
    747 /* do binary branching */
    748 SCIP_CALL( SCIPbranchVarValNary(scip, brvar, brpoint, 2, 0.0, 1.0, &nchildren) );
    749 }
    750
    751 if( nchildren > 1 )
    752 {
    753 *result = SCIP_BRANCHED;
    754 }
    755 else
    756 {
    757 /* if there are no children, then variable should have been fixed by SCIPbranchVarVal */
    758 assert(SCIPisEQ(scip, SCIPvarGetLbLocal(brvar), SCIPvarGetUbLocal(brvar)));
    759 *result = SCIP_REDUCEDDOM;
    760 }
    761
    762 return SCIP_OKAY;
    763}
    764
    765
    766/*
    767 * branching specific interface methods
    768 */
    769
    770/** creates the pseudo cost branching rule and includes it in SCIP */
    772 SCIP* scip /**< SCIP data structure */
    773 )
    774{
    775 SCIP_BRANCHRULEDATA* branchruledata;
    776 SCIP_BRANCHRULE* branchrule;
    777
    778 /* create pscost branching rule data */
    779 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
    780
    781 /* include allfullstrong branching rule */
    784
    785 assert(branchrule != NULL);
    786 /* create a random number generator */
    787 SCIP_CALL( SCIPcreateRandom(scip, &branchruledata->randnumgen,
    789
    790 /* set non-fundamental callbacks via specific setter functions*/
    791 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyPscost) );
    792 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreePscost) );
    793 SCIP_CALL( SCIPsetBranchruleInit(scip, branchrule, branchInitPscost) );
    794 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpPscost) );
    795 SCIP_CALL( SCIPsetBranchruleExecExt(scip, branchrule, branchExecextPscost) );
    796
    797 SCIP_CALL( SCIPaddCharParam(scip, "branching/" BRANCHRULE_NAME "/strategy",
    798 "strategy for utilizing pseudo-costs of external branching candidates (multiply as in pseudo costs 'u'pdate rule, or by 'd'omain reduction, or by domain reduction of 's'ibling, or by 'v'ariable score)",
    799 &branchruledata->strategy, FALSE, BRANCHRULE_STRATEGY_DEFAULT, BRANCHRULE_STRATEGIES, NULL, NULL) );
    800
    801 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/minscoreweight",
    802 "weight for minimum of scores of a branching candidate when building weighted sum of min/max/sum of scores",
    803 &branchruledata->scoreminweight, TRUE, BRANCHRULE_SCOREMINWEIGHT_DEFAULT, -SCIPinfinity(scip), SCIPinfinity(scip), NULL, NULL) );
    804
    805 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/maxscoreweight",
    806 "weight for maximum of scores of a branching candidate when building weighted sum of min/max/sum of scores",
    807 &branchruledata->scoremaxweight, TRUE, BRANCHRULE_SCOREMAXWEIGHT_DEFAULT, -SCIPinfinity(scip), SCIPinfinity(scip), NULL, NULL) );
    808
    809 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/sumscoreweight",
    810 "weight for sum of scores of a branching candidate when building weighted sum of min/max/sum of scores",
    811 &branchruledata->scoresumweight, TRUE, BRANCHRULE_SCORESUMWEIGHT_DEFAULT, -SCIPinfinity(scip), SCIPinfinity(scip), NULL, NULL) );
    812
    813 SCIP_CALL( SCIPaddIntParam(scip, "branching/" BRANCHRULE_NAME "/nchildren",
    814 "number of children to create in n-ary branching",
    815 &branchruledata->nchildren, FALSE, BRANCHRULE_NCHILDREN_DEFAULT, 2, INT_MAX, NULL, NULL) );
    816
    817 SCIP_CALL( SCIPaddIntParam(scip, "branching/" BRANCHRULE_NAME "/narymaxdepth",
    818 "maximal depth where to do n-ary branching, -1 to turn off",
    819 &branchruledata->narymaxdepth, FALSE, BRANCHRULE_NARYMAXDEPTH_DEFAULT, -1, INT_MAX, NULL, NULL) );
    820
    821 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/naryminwidth",
    822 "minimal domain width in children when doing n-ary branching, relative to global bounds",
    823 &branchruledata->naryminwidth, FALSE, BRANCHRULE_NARYMINWIDTH_DEFAULT, 0.0, 1.0, NULL, NULL) );
    824
    825 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/narywidthfactor",
    826 "factor of domain width in n-ary branching when creating nodes with increasing distance from branching value",
    827 &branchruledata->narywidthfactor, FALSE, BRANCHRULE_NARYWIDTHFAC_DEFAULT, 1.0, SCIP_REAL_MAX, NULL, NULL) );
    828
    829 SCIP_CALL( SCIPaddRealParam(scip, "branching/" BRANCHRULE_NAME "/discountfactor",
    830 "discount factor for ancestral pseudo costs (0.0: disable discounted pseudo costs)",
    831 &branchruledata->discountfactor, FALSE, BRANCHRULE_DISCOUNTFACTOR, 0.0, 1.0, NULL, NULL) );
    832
    833 return SCIP_OKAY;
    834}
    835
    836/** selects a branching variable, due to pseudo cost, from the given candidate array and returns this variable together
    837 * with a branching point */
    839 SCIP* scip, /**< SCIP data structure */
    840 SCIP_VAR** branchcands, /**< branching candidates */
    841 SCIP_Real* branchcandssol, /**< solution value for the branching candidates */
    842 SCIP_Real* branchcandsscore, /**< array of candidate scores */
    843 int nbranchcands, /**< number of branching candidates */
    844 SCIP_VAR** var, /**< pointer to store the variable to branch on, or NULL if none */
    845 SCIP_Real* brpoint /**< pointer to store the branching point for the branching variable, will be fractional for a discrete variable */
    846 )
    847{
    848 SCIP_BRANCHRULE* branchrule;
    849
    850 assert(scip != NULL);
    851
    852 /* find branching rule */
    854 assert(branchrule != NULL);
    855
    856 /* select branching variable */
    857 SCIP_CALL( selectBranchVar(scip, branchrule, branchcands, branchcandssol, branchcandsscore, nbranchcands, var, brpoint) );
    858
    859 return SCIP_OKAY;
    860}
    #define BRANCHRULE_DESC
    Definition: branch_pscost.c:55
    static SCIP_DECL_BRANCHFREE(branchFreePscost)
    static SCIP_DECL_BRANCHEXECLP(branchExeclpPscost)
    #define BRANCHRULE_NCHILDREN_DEFAULT
    Definition: branch_pscost.c:65
    #define BRANCHRULE_PRIORITY
    Definition: branch_pscost.c:56
    #define BRANCHRULE_DISCOUNTFACTOR
    Definition: branch_pscost.c:70
    static SCIP_DECL_BRANCHEXECEXT(branchExecextPscost)
    #define BRANCHRULE_NARYMAXDEPTH_DEFAULT
    Definition: branch_pscost.c:66
    static SCIP_RETCODE selectBranchVar(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_VAR **cands, SCIP_Real *candssol, SCIP_Real *candsscore, int ncands, SCIP_VAR **brvar, SCIP_Real *brpoint)
    static SCIP_DECL_BRANCHINIT(branchInitPscost)
    #define BRANCHRULE_NAME
    Definition: branch_pscost.c:54
    #define BRANCHRULE_SCOREMAXWEIGHT_DEFAULT
    Definition: branch_pscost.c:63
    static SCIP_RETCODE updateBestCandidate(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR **bestvar, SCIP_Real *bestbrpoint, SCIP_Real *bestscore, SCIP_Real *bestrndscore, SCIP_VAR *cand, SCIP_Real candscoremin, SCIP_Real candscoremax, SCIP_Real candscoresum, SCIP_Real candrndscore, SCIP_Real candsol)
    #define BRANCHRULE_RANDSEED_DEFAULT
    Definition: branch_pscost.c:69
    #define BRANCHRULE_NARYMINWIDTH_DEFAULT
    Definition: branch_pscost.c:67
    #define WEIGHTEDSCORING(data, min, max, sum)
    Definition: branch_pscost.c:73
    #define BRANCHRULE_NARYWIDTHFAC_DEFAULT
    Definition: branch_pscost.c:68
    #define BRANCHRULE_SCOREMINWEIGHT_DEFAULT
    Definition: branch_pscost.c:62
    #define BRANCHRULE_SCORESUMWEIGHT_DEFAULT
    Definition: branch_pscost.c:64
    static SCIP_DECL_BRANCHCOPY(branchCopyPscost)
    #define BRANCHRULE_STRATEGY_DEFAULT
    Definition: branch_pscost.c:61
    #define BRANCHRULE_STRATEGIES
    Definition: branch_pscost.c:60
    #define BRANCHRULE_MAXDEPTH
    Definition: branch_pscost.c:57
    #define BRANCHRULE_MAXBOUNDDIST
    Definition: branch_pscost.c:58
    pseudo costs branching rule
    #define NULL
    Definition: def.h:257
    #define SCIP_REAL_MAX
    Definition: def.h:167
    #define SCIP_INVALID
    Definition: def.h:187
    #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 TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIPABORT()
    Definition: def.h:336
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_RETCODE SCIPselectBranchVarPscost(SCIP *scip, SCIP_VAR **branchcands, SCIP_Real *branchcandssol, SCIP_Real *branchcandsscore, int nbranchcands, SCIP_VAR **var, SCIP_Real *brpoint)
    SCIP_RETCODE SCIPincludeBranchrulePscost(SCIP *scip)
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_Real SCIPrelDiff(SCIP_Real val1, SCIP_Real val2)
    Definition: misc.c:11162
    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 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 SCIPgetCharParam(SCIP *scip, const char *name, char *value)
    Definition: scip_param.c:326
    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_BRANCHRULE * SCIPfindBranchrule(SCIP *scip, const char *name)
    Definition: scip_branch.c:304
    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
    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 SCIPbranchVarValNary(SCIP *scip, SCIP_VAR *var, SCIP_Real val, int n, SCIP_Real minwidth, SCIP_Real widthfactor, int *nchildren)
    Definition: scip_branch.c:1196
    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_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
    Definition: scip_branch.c:857
    #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 SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPnodeGetDepth(SCIP_NODE *node)
    Definition: tree.c:8523
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1763
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisHugeValue(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisSumEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisSumGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_NODE * SCIPgetCurrentNode(SCIP *scip)
    Definition: scip_tree.c:91
    SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
    Definition: var.c:19036
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23674
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23418
    SCIP_Bool SCIPvarIsImpliedIntegral(SCIP_VAR *var)
    Definition: var.c:23530
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24300
    SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
    Definition: var.c:17595
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23485
    SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
    Definition: var.c:24174
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23299
    SCIP_Real SCIPgetVarDPseudocostScore(SCIP *scip, SCIP_VAR *var, SCIP_Real solval, SCIP_Real discountfac)
    Definition: scip_var.c:11570
    SCIP_Real SCIPadjustedVarUb(SCIP *scip, SCIP_VAR *var, SCIP_Real ub)
    Definition: scip_var.c:5634
    SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
    Definition: var.c:19144
    SCIP_Real SCIPgetVarPseudocostVal(SCIP *scip, SCIP_VAR *var, SCIP_Real solvaldelta)
    Definition: scip_var.c:11188
    SCIP_Real SCIPadjustedVarLb(SCIP *scip, SCIP_VAR *var, SCIP_Real lb)
    Definition: scip_var.c:5570
    SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
    Definition: var.c:23522
    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
    SCIP_Real SCIPcomputeVarLbLocal(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:8417
    SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
    Definition: var.c:24152
    int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
    Definition: var.c:17319
    SCIP_Real SCIPcomputeVarUbLocal(SCIP *scip, SCIP_VAR *var)
    Definition: scip_var.c:8462
    SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
    Definition: var.c:23850
    void SCIPfreeRandom(SCIP *scip, SCIP_RANDNUMGEN **randnumgen)
    void SCIPsetRandomSeed(SCIP *scip, SCIP_RANDNUMGEN *randnumgen, unsigned int seed)
    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)
    void SCIPsortPtrInt(void **ptrarray, int *intarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
    memory allocation routines
    public methods for branching rules
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    public data structures and miscellaneous methods
    methods for sorting joint arrays of various types
    public methods for branch and bound tree
    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 solutions
    public methods for the branch-and-bound tree
    public methods for SCIP variables
    struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
    Definition: type_branch.h:57
    @ SCIP_REDUCEDDOM
    Definition: type_result.h:51
    @ SCIP_DIDNOTFIND
    Definition: type_result.h:44
    @ SCIP_BRANCHED
    Definition: type_result.h:54
    @ SCIP_BRANCHERROR
    Definition: type_retcode.h:60
    @ SCIP_INVALIDDATA
    Definition: type_retcode.h:52
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    #define SCIP_DEPRECATED_VARTYPE_IMPLINT
    Definition: type_var.h:79
    @ SCIP_VARSTATUS_MULTAGGR
    Definition: type_var.h:56
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73