Scippy

    SCIP

    Solving Constraint Integer Programs

    branch_distribution.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2025 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file branch_distribution.c
    26 * @ingroup DEFPLUGINS_BRANCH
    27 * @ingroup BRANCHINGRULES
    28 * @brief probability based branching rule based on an article by J. Pryor and J.W. Chinneck
    29 * @author Gregor Hendel
    30 *
    31 * The distribution branching rule selects a variable based on its impact on row activity distributions. More formally,
    32 * let \f$ a(x) = a_1 x_1 + \dots + a_n x_n \leq b \f$ be a row of the LP. Let further \f$ l_i, u_i \in R\f$ denote the
    33 * (finite) lower and upper bound, respectively, of the \f$ i \f$-th variable \f$x_i\f$.
    34 * Viewing every variable \f$x_i \f$ as (continuously) uniformly distributed within its bounds, we can approximately
    35 * understand the row activity \f$a(x)\f$ as a Gaussian random variate with mean value \f$ \mu = E[a(x)] = \sum_i a_i\frac{l_i + u_i}{2}\f$
    36 * and variance \f$ \sigma^2 = \sum_i a_i^2 \sigma_i^2 \f$, with \f$ \sigma_i^2 = \frac{(u_i - l_i)^2}{12}\f$ for
    37 * continuous and \f$ \sigma_i^2 = \frac{(u_i - l_i + 1)^2 - 1}{12}\f$ for discrete variables.
    38 * With these two parameters, we can calculate the probability to satisfy the row in terms of the cumulative distribution
    39 * of the standard normal distribution: \f$ P(a(x) \leq b) = \Phi(\frac{b - \mu}{\sigma})\f$.
    40 *
    41 * The impact of a variable on the probability to satisfy a constraint after branching can be estimated by altering
    42 * the variable contribution to the sums described above. In order to keep the tree size small,
    43 * variables are preferred which decrease the probability
    44 * to satisfy a row because it is more likely to create infeasible subproblems.
    45 *
    46 * The selection of the branching variable is subject to the parameter @p scoreparam. For both branching directions,
    47 * an individual score is calculated. Available options for scoring methods are:
    48 * - @b d: select a branching variable with largest difference in satisfaction probability after branching
    49 * - @b l: lowest cumulative probability amongst all variables on all rows (after branching).
    50 * - @b h: highest cumulative probability amongst all variables on all rows (after branching).
    51 * - @b v: highest number of votes for lowering row probability for all rows a variable appears in.
    52 * - @b w: highest number of votes for increasing row probability for all rows a variable appears in.
    53 *
    54 * If the parameter @p usescipscore is set to @a TRUE, a single branching score is calculated from the respective
    55 * up and down scores as defined by the SCIP branching score function (see advanced branching parameter @p scorefunc),
    56 * otherwise, the variable with the single highest score is selected, and the maximizing direction is assigned
    57 * higher branching priority.
    58 *
    59 * The original idea of probability based branching schemes appeared in:
    60 *
    61 * J. Pryor and J.W. Chinneck:@n
    62 * Faster Integer-Feasibility in Mixed-Integer Linear Programs by Branching to Force Change@n
    63 * Computers and Operations Research, vol. 38, 2011, p. 1143–1152@n
    64 * (Paper: <a href="http://www.sce.carleton.ca/faculty/chinneck/docs/PryorChinneck.pdf">PDF</a>).
    65 */
    66
    67/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    68
    69#define _USE_MATH_DEFINES /* to get M_SQRT2 on Windows */ /*lint !750 */
    70
    72#include "scip/pub_branch.h"
    73#include "scip/pub_event.h"
    74#include "scip/pub_lp.h"
    75#include "scip/pub_message.h"
    76#include "scip/pub_misc.h"
    77#include "scip/pub_var.h"
    78#include "scip/scip_branch.h"
    79#include "scip/scip_event.h"
    80#include "scip/scip_general.h"
    81#include "scip/scip_lp.h"
    82#include "scip/scip_message.h"
    83#include "scip/scip_mem.h"
    84#include "scip/scip_numerics.h"
    85#include "scip/scip_param.h"
    86#include "scip/scip_pricer.h"
    87#include "scip/scip_prob.h"
    88#include "scip/scip_probing.h"
    89#include <string.h>
    90#include <math.h>
    91
    92
    93#define BRANCHRULE_NAME "distribution"
    94#define BRANCHRULE_DESC "branching rule based on variable influence on cumulative normal distribution of row activities"
    95#define BRANCHRULE_PRIORITY 0
    96#define BRANCHRULE_MAXDEPTH -1
    97#define BRANCHRULE_MAXBOUNDDIST 1.0
    98
    99#define SCOREPARAM_VALUES "dhlvw"
    100#define DEFAULT_SCOREPARAM 'v'
    101#define DEFAULT_PRIORITY 2.0
    102#define DEFAULT_ONLYACTIVEROWS FALSE /**< should only rows which are active at the current node be considered? */
    103#define DEFAULT_USEWEIGHTEDSCORE FALSE /**< should the branching score weigh up- and down-scores of a variable */
    104
    105/* branching rule event handler to catch variable bound changes */
    106#define EVENTHDLR_NAME "eventhdlr_distribution" /**< event handler name */
    107#define EVENT_DISTRIBUTION SCIP_EVENTTYPE_BOUNDCHANGED /**< the event tyoe to be handled by this event handler */
    108
    109/*
    110 * Data structures
    111 */
    112
    113/** branching rule data */
    114struct SCIP_BranchruleData
    115{
    116 SCIP_EVENTHDLR* eventhdlr; /**< event handler pointer */
    117 SCIP_VAR** updatedvars; /**< variables to process bound change events for */
    118 SCIP_Real* rowmeans; /**< row activity mean values for all rows */
    119 SCIP_Real* rowvariances; /**< row activity variances for all rows */
    120 SCIP_Real* currentubs; /**< variable upper bounds as currently saved in the row activities */
    121 SCIP_Real* currentlbs; /**< variable lower bounds as currently saved in the row activities */
    122 int* rowinfinitiesdown; /**< count the number of variables with infinite bounds which allow for always
    123 * repairing the constraint right hand side */
    124 int* rowinfinitiesup; /**< count the number of variables with infinite bounds which allow for always
    125 * repairing the constraint left hand side */
    126 int* varposs; /**< array of variable positions in the updated variables array */
    127 int* varfilterposs; /**< array of event filter positions for variable events */
    128 int nupdatedvars; /**< the current number of variables with pending bound changes */
    129 int memsize; /**< memory size of current arrays, needed for dynamic reallocation */
    130 int varpossmemsize; /**< memory size of updated vars and varposs array */
    131 char scoreparam; /**< parameter how the branch score is calculated */
    132 SCIP_Bool onlyactiverows; /**< should only rows which are active at the current node be considered? */
    133 SCIP_Bool usescipscore; /**< should the branching use SCIP's branching score function */
    134};
    135
    136struct SCIP_EventhdlrData
    137{
    138 SCIP_BRANCHRULEDATA* branchruledata; /**< the branching rule data to access distribution arrays */
    139};
    140
    141/*
    142 * Local methods
    143 */
    144
    145/** ensure that maxindex + 1 rows can be represented in data arrays; memory gets reallocated with 10% extra space
    146 * to save some time for future allocations */
    147static
    149 SCIP* scip, /**< SCIP data structure */
    150 SCIP_BRANCHRULEDATA* branchruledata, /**< branchruledata */
    151 int maxindex /**< row index at hand (size must be at least this large) */
    152 )
    153{
    154 int newsize;
    155 int r;
    156
    157 /* maxindex fits in current array -> nothing to do */
    158 if( maxindex < branchruledata->memsize )
    159 return SCIP_OKAY;
    160
    161 /* new memory size is the max index + 1 plus 10% additional space */
    162 newsize = (int)SCIPfeasCeil(scip, (maxindex + 1) * 1.1);
    163 assert(newsize > branchruledata->memsize);
    164 assert(branchruledata->memsize >= 0);
    165
    166 /* alloc memory arrays for row information */
    167 if( branchruledata->memsize == 0 )
    168 {
    169 SCIP_VAR** vars;
    170 int v;
    171 int nvars;
    172
    173 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesdown, newsize) );
    174 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesup, newsize) );
    175 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowmeans, newsize) );
    176 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->rowvariances, newsize) );
    177
    179
    180 vars = SCIPgetVars(scip);
    181 nvars = SCIPgetNVars(scip);
    182
    183 assert(nvars > 0);
    184
    185 /* allocate variable update event processing array storage */
    186 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->varfilterposs, nvars) );
    187 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->varposs, nvars) );
    188 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->updatedvars, nvars) );
    189 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->currentubs, nvars) );
    190 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &branchruledata->currentlbs, nvars) );
    191
    192 branchruledata->varpossmemsize = nvars;
    193 branchruledata->nupdatedvars = 0;
    194
    195 /* init variable event processing data */
    196 for( v = 0; v < nvars; ++v )
    197 {
    198 assert(SCIPvarIsActive(vars[v]));
    199 assert(SCIPvarGetProbindex(vars[v]) == v);
    200
    201 /* set up variable events to catch bound changes */
    202 SCIP_CALL( SCIPcatchVarEvent(scip, vars[v], EVENT_DISTRIBUTION, branchruledata->eventhdlr, NULL, &(branchruledata->varfilterposs[v])) );
    203 assert(branchruledata->varfilterposs[v] >= 0);
    204
    205 branchruledata->varposs[v] = -1;
    206 branchruledata->updatedvars[v] = NULL;
    207 branchruledata->currentlbs[v] = SCIP_INVALID;
    208 branchruledata->currentubs[v] = SCIP_INVALID;
    209 }
    210 }
    211 else
    212 {
    213 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesdown, branchruledata->memsize, newsize) );
    214 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowinfinitiesup, branchruledata->memsize, newsize) );
    215 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowmeans, branchruledata->memsize, newsize) );
    216 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &branchruledata->rowvariances, branchruledata->memsize, newsize) );
    217 }
    218
    219 /* loop over extended arrays and invalidate data to trigger initialization of this row when necessary */
    220 for( r = branchruledata->memsize; r < newsize; ++r )
    221 {
    222 branchruledata->rowmeans[r] = SCIP_INVALID;
    223 branchruledata->rowvariances[r] = SCIP_INVALID;
    224 branchruledata->rowinfinitiesdown[r] = 0;
    225 branchruledata->rowinfinitiesup[r] = 0;
    226 }
    227
    228 /* adjust memsize */
    229 branchruledata->memsize = newsize;
    230
    231 return SCIP_OKAY;
    232}
    233
    234/* update the variables current lower and upper bound */
    235static
    237 SCIP* scip, /**< SCIP data structure */
    238 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
    239 SCIP_VAR* var /**< the variable to update current bounds */
    240 )
    241{
    242 int varindex;
    243 SCIP_Real lblocal;
    244 SCIP_Real ublocal;
    245
    246 assert(var != NULL);
    247
    248 varindex = SCIPvarGetProbindex(var);
    249 assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
    250 lblocal = SCIPvarGetLbLocal(var);
    251 ublocal = SCIPvarGetUbLocal(var);
    252
    253 assert(SCIPisFeasLE(scip, lblocal, ublocal));
    254
    255 branchruledata->currentlbs[varindex] = lblocal;
    256 branchruledata->currentubs[varindex] = ublocal;
    257}
    258
    259/** calculate the variable's distribution parameters (mean and variance) for the bounds specified in the arguments.
    260 * special treatment of infinite bounds necessary */
    262 SCIP* scip, /**< SCIP data structure */
    263 SCIP_Real varlb, /**< variable lower bound */
    264 SCIP_Real varub, /**< variable upper bound */
    265 SCIP_VARTYPE vartype, /**< type of the variable */
    266 SCIP_IMPLINTTYPE impltype, /**< implied integral type of the variable */
    267 SCIP_Real* mean, /**< pointer to store mean value */
    268 SCIP_Real* variance /**< pointer to store the variance of the variable uniform distribution */
    269 )
    270{
    271 assert(mean != NULL);
    272 assert(variance != NULL);
    273
    274 /* calculate mean and variance of variable uniform distribution before and after branching */
    275 if( SCIPisInfinity(scip, varub) || SCIPisInfinity(scip, -varlb) )
    276 {
    277 /* variables with infinite bounds are not kept in the row activity variance */
    278 *variance = 0.0;
    279
    280 if( !SCIPisInfinity(scip, varub) )
    281 *mean = varub;
    282 else if( !SCIPisInfinity(scip, -varlb) )
    283 *mean = varlb;
    284 else
    285 *mean = 0.0;
    286 }
    287 else
    288 {
    289 /* if the variable is continuous, we assume a continuous uniform distribution, otherwise a discrete one */
    290 if( vartype == SCIP_VARTYPE_CONTINUOUS && impltype == SCIP_IMPLINTTYPE_NONE )
    291 *variance = SQR(varub - varlb);
    292 else
    293 *variance = SQR(varub - varlb + 1.0) - 1.0;
    294 *variance /= 12.0;
    295 *mean = (varub + varlb) * .5;
    296 }
    297
    298 assert(!SCIPisNegative(scip, *variance));
    299}
    300
    301/** calculates the cumulative distribution P(-infinity <= x <= value) that a normally distributed
    302 * random variable x takes a value between -infinity and parameter \p value.
    303 *
    304 * The distribution is given by the respective mean and deviation. This implementation
    305 * uses the error function SCIPerf().
    306 */
    308 SCIP* scip, /**< current SCIP */
    309 SCIP_Real mean, /**< the mean value of the distribution */
    310 SCIP_Real variance, /**< the square of the deviation of the distribution */
    311 SCIP_Real value /**< the upper limit of the calculated distribution integral */
    312 )
    313{
    314 SCIP_Real normvalue;
    316
    317 /* we need to calculate the standard deviation from the variance */
    318 assert(!SCIPisNegative(scip, variance));
    319 if( SCIPisFeasZero(scip, variance) )
    320 std = 0.0;
    321 else
    322 std = sqrt(variance);
    323
    324 /* special treatment for zero variance */
    325 if( SCIPisFeasZero(scip, std) )
    326 {
    327 if( SCIPisFeasLE(scip, value, mean) )
    328 return 1.0;
    329 else
    330 return 0.0;
    331 }
    332 assert( std != 0.0 ); /* for lint */
    333
    334 /* scale and translate to standard normal distribution. Factor sqrt(2) is needed for SCIPerf() function */
    335 normvalue = (value - mean)/(std * M_SQRT2);
    336
    337 SCIPdebugMsg(scip, " Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean, std);
    338
    339 /* calculate the cumulative distribution function for normvalue. For negative normvalues, we negate
    340 * the normvalue and use the oddness of the SCIPerf()-function; special treatment for values close to zero.
    341 */
    342 if( SCIPisFeasZero(scip, normvalue) )
    343 return .5;
    344 else if( normvalue > 0 )
    345 {
    346 SCIP_Real erfresult;
    347
    348 erfresult = SCIPerf(normvalue);
    349 return erfresult / 2.0 + 0.5;
    350 }
    351 else
    352 {
    353 SCIP_Real erfresult;
    354
    355 erfresult = SCIPerf(-normvalue);
    356
    357 return 0.5 - erfresult / 2.0;
    358 }
    359}
    360
    361/** calculates the probability of satisfying an LP-row under the assumption
    362 * of uniformly distributed variable values.
    363 *
    364 * For inequalities, we use the cumulative distribution function of the standard normal
    365 * distribution PHI(rhs - mu/sqrt(sigma2)) to calculate the probability
    366 * for a right hand side row with mean activity mu and variance sigma2 to be satisfied.
    367 * Similarly, 1 - PHI(lhs - mu/sqrt(sigma2)) is the probability to satisfy a left hand side row.
    368 * For equations (lhs==rhs), we use the centeredness measure p = min(PHI(lhs'), 1-PHI(lhs'))/max(PHI(lhs'), 1 - PHI(lhs')),
    369 * where lhs' = lhs - mu / sqrt(sigma2).
    370 */
    372 SCIP* scip, /**< current scip */
    373 SCIP_ROW* row, /**< the row */
    374 SCIP_Real mu, /**< the mean value of the row distribution */
    375 SCIP_Real sigma2, /**< the variance of the row distribution */
    376 int rowinfinitiesdown, /**< the number of variables with infinite bounds to DECREASE activity */
    377 int rowinfinitiesup /**< the number of variables with infinite bounds to INCREASE activity */
    378 )
    379{
    380 SCIP_Real rowprobability;
    381 SCIP_Real lhs;
    382 SCIP_Real rhs;
    383 SCIP_Real lhsprob;
    384 SCIP_Real rhsprob;
    385
    386 lhs = SCIProwGetLhs(row);
    387 rhs = SCIProwGetRhs(row);
    388
    389 lhsprob = 1.0;
    390 rhsprob = 1.0;
    391
    392 /* use the cumulative distribution if the row contains no variable to repair every infeasibility */
    393 if( !SCIPisInfinity(scip, rhs) && rowinfinitiesdown == 0 )
    394 rhsprob = SCIPcalcCumulativeDistribution(scip, mu, sigma2, rhs);
    395
    396 /* use the cumulative distribution if the row contains no variable to repair every infeasibility
    397 * otherwise the row can always be made feasible by increasing activity far enough
    398 */
    399 if( !SCIPisInfinity(scip, -lhs) && rowinfinitiesup == 0 )
    400 lhsprob = 1.0 - SCIPcalcCumulativeDistribution(scip, mu, sigma2, lhs);
    401
    402 assert(SCIPisFeasLE(scip, lhsprob, 1.0) && SCIPisFeasGE(scip, lhsprob, 0.0));
    403 assert(SCIPisFeasLE(scip, rhsprob, 1.0) && SCIPisFeasGE(scip, rhsprob, 0.0));
    404
    405 /* use centeredness measure for equations; for inequalities, the minimum of the two probabilities is the
    406 * probability to satisfy the row */
    407 if( SCIPisFeasEQ(scip, lhs, rhs) )
    408 {
    409 SCIP_Real minprobability;
    410 SCIP_Real maxprobability;
    411
    412 minprobability = MIN(rhsprob, lhsprob);
    413 maxprobability = MAX(lhsprob, rhsprob);
    414 rowprobability = minprobability / maxprobability;
    415 }
    416 else
    417 rowprobability = MIN(rhsprob, lhsprob);
    418
    420 SCIPdebugMsg(scip, " Row %s, mean %g, sigma2 %g, LHS %g, RHS %g has probability %g to be satisfied\n",
    421 SCIProwGetName(row), mu, sigma2, lhs, rhs, rowprobability);
    422
    423 assert(SCIPisFeasGE(scip, rowprobability, 0.0) && SCIPisFeasLE(scip, rowprobability, 1.0));
    424
    425 return rowprobability;
    426}
    427
    428/** calculates the initial mean and variance of the row activity normal distribution.
    429 *
    430 * The mean value \f$ \mu \f$ is given by \f$ \mu = \sum_i=1^n c_i * (lb_i +ub_i) / 2 \f$ where
    431 * \f$n \f$ is the number of variables, and \f$ c_i, lb_i, ub_i \f$ are the variable coefficient and
    432 * bounds, respectively. With the same notation, the variance \f$ \sigma^2 \f$ is given by
    433 * \f$ \sigma^2 = \sum_i=1^n c_i^2 * \sigma^2_i \f$, with the variance being
    434 * \f$ \sigma^2_i = ((ub_i - lb_i + 1)^2 - 1) / 12 \f$ for integer variables and
    435 * \f$ \sigma^2_i = (ub_i - lb_i)^2 / 12 \f$ for continuous variables.
    436 */
    437static
    439 SCIP* scip, /**< SCIP data structure */
    440 SCIP_BRANCHRULEDATA* branchruledata, /**< the branching rule data */
    441 SCIP_ROW* row, /**< the row for which the gaussian normal distribution has to be calculated */
    442 SCIP_Real* mu, /**< pointer to store the mean value of the gaussian normal distribution */
    443 SCIP_Real* sigma2, /**< pointer to store the variance value of the gaussian normal distribution */
    444 int* rowinfinitiesdown, /**< pointer to store the number of variables with infinite bounds to DECREASE activity */
    445 int* rowinfinitiesup /**< pointer to store the number of variables with infinite bounds to INCREASE activity */
    446 )
    447{
    448 SCIP_COL** rowcols;
    449 SCIP_Real* rowvals;
    450 int nrowvals;
    451 int c;
    452
    453 assert(scip != NULL);
    454 assert(row != NULL);
    455 assert(mu != NULL);
    456 assert(sigma2 != NULL);
    457 assert(rowinfinitiesup != NULL);
    458 assert(rowinfinitiesdown != NULL);
    459
    460 rowcols = SCIProwGetCols(row);
    461 rowvals = SCIProwGetVals(row);
    462 nrowvals = SCIProwGetNNonz(row);
    463
    464 assert(nrowvals == 0 || rowcols != NULL);
    465 assert(nrowvals == 0 || rowvals != NULL);
    466
    467 *mu = SCIProwGetConstant(row);
    468 *sigma2 = 0.0;
    469 *rowinfinitiesdown = 0;
    470 *rowinfinitiesup = 0;
    471
    472 /* loop over nonzero row coefficients and sum up the variable contributions to mu and sigma2 */
    473 for( c = 0; c < nrowvals; ++c )
    474 {
    475 SCIP_VAR* colvar;
    476 SCIP_Real colval;
    477 SCIP_Real colvarlb;
    478 SCIP_Real colvarub;
    479 SCIP_Real squarecoeff;
    480 SCIP_Real varvariance;
    481 SCIP_Real varmean;
    482 int varindex;
    483
    484 assert(rowcols[c] != NULL);
    485 colvar = SCIPcolGetVar(rowcols[c]);
    486 assert(colvar != NULL);
    487
    488 colval = rowvals[c];
    489 colvarlb = SCIPvarGetLbLocal(colvar);
    490 colvarub = SCIPvarGetUbLocal(colvar);
    491
    492 varmean = 0.0;
    493 varvariance = 0.0;
    494 varindex = SCIPvarGetProbindex(colvar);
    495 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID) == (branchruledata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777*/
    496
    497 /* variable bounds need to be watched from now on */
    498 if( branchruledata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777*/
    499 branchruledataUpdateCurrentBounds(scip, branchruledata, colvar);
    500
    501 assert(!SCIPisInfinity(scip, colvarlb));
    502 assert(!SCIPisInfinity(scip, -colvarub));
    503 assert(SCIPisFeasLE(scip, colvarlb, colvarub));
    504
    505 /* variables with infinite bounds are skipped for the calculation of the variance; they need to
    506 * be accounted for by the counters for infinite row activity decrease and increase and they
    507 * are used to shift the row activity mean in case they have one nonzero, but finite bound */
    508 if( SCIPisInfinity(scip, -colvarlb) || SCIPisInfinity(scip, colvarub) )
    509 {
    510 if( SCIPisInfinity(scip, colvarub) )
    511 {
    512 /* an infinite upper bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
    513 * positive or negative, resp.
    514 */
    515 if( colval < 0.0 )
    516 ++(*rowinfinitiesdown);
    517 else
    518 ++(*rowinfinitiesup);
    519 }
    520
    521 /* an infinite lower bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
    522 * negative or positive, resp.
    523 */
    524 if( SCIPisInfinity(scip, -colvarlb) )
    525 {
    526 if( colval > 0.0 )
    527 ++(*rowinfinitiesdown);
    528 else
    529 ++(*rowinfinitiesup);
    530 }
    531 }
    532 SCIPvarCalcDistributionParameters(scip, colvarlb, colvarub, SCIPvarGetType(colvar), SCIPvarGetImplType(colvar),
    533 &varmean, &varvariance);
    534
    535 /* actual values are updated; the contribution of the variable to mu is the arithmetic mean of its bounds */
    536 *mu += colval * varmean;
    537
    538 /* the variance contribution of a variable is c^2 * (u - l)^2 / 12.0 for continuous and c^2 * ((u - l + 1)^2 - 1) / 12.0 for integer */
    539 squarecoeff = SQR(colval);
    540 *sigma2 += squarecoeff * varvariance;
    541
    542 assert(!SCIPisFeasNegative(scip, *sigma2));
    543 }
    544
    546 SCIPdebugMsg(scip, " Row %s has a mean value of %g at a sigma2 of %g \n", SCIProwGetName(row), *mu, *sigma2);
    547}
    548
    549/** update the up- and downscore of a single variable after calculating the impact of branching on a
    550 * particular row, depending on the chosen score parameter
    551 */
    553 SCIP* scip, /**< current SCIP pointer */
    554 SCIP_Real currentprob, /**< the current probability */
    555 SCIP_Real newprobup, /**< the new probability if branched upwards */
    556 SCIP_Real newprobdown, /**< the new probability if branched downwards */
    557 SCIP_Real* upscore, /**< pointer to store the new score for branching up */
    558 SCIP_Real* downscore, /**< pointer to store the new score for branching down */
    559 char scoreparam /**< parameter to determine the way the score is calculated */
    560 )
    561{
    562 assert(scip != NULL);
    563 assert(SCIPisFeasGE(scip, currentprob, 0.0) && SCIPisFeasLE(scip, currentprob, 1.0));
    564 assert(SCIPisFeasGE(scip, newprobup, 0.0) && SCIPisFeasLE(scip, newprobup, 1.0));
    565 assert(SCIPisFeasGE(scip, newprobdown, 0.0) && SCIPisFeasLE(scip, newprobdown, 1.0));
    566 assert(upscore != NULL);
    567 assert(downscore != NULL);
    568
    569 /* update up and downscore depending on score parameter */
    570 switch( scoreparam )
    571 {
    572 case 'l' :
    573 /* 'l'owest cumulative probability */
    574 if( SCIPisGT(scip, 1.0 - newprobup, *upscore) )
    575 *upscore = 1.0 - newprobup;
    576 if( SCIPisGT(scip, 1.0 - newprobdown, *downscore) )
    577 *downscore = 1.0 - newprobdown;
    578 break;
    579
    580 case 'd' :
    581 /* biggest 'd'ifference currentprob - newprob */
    582 if( SCIPisGT(scip, currentprob - newprobup, *upscore) )
    583 *upscore = currentprob - newprobup;
    584 if( SCIPisGT(scip, currentprob - newprobdown, *downscore) )
    585 *downscore = currentprob - newprobdown;
    586 break;
    587
    588 case 'h' :
    589 /* 'h'ighest cumulative probability */
    590 if( SCIPisGT(scip, newprobup, *upscore) )
    591 *upscore = newprobup;
    592 if( SCIPisGT(scip, newprobdown, *downscore) )
    593 *downscore = newprobdown;
    594 break;
    595
    596 case 'v' :
    597 /* 'v'otes lowest cumulative probability */
    598 if( SCIPisLT(scip, newprobup, newprobdown) )
    599 *upscore += 1.0;
    600 else if( SCIPisGT(scip, newprobup, newprobdown) )
    601 *downscore += 1.0;
    602 break;
    603
    604 case 'w' :
    605 /* votes highest cumulative probability */
    606 if( SCIPisGT(scip, newprobup, newprobdown) )
    607 *upscore += 1.0;
    608 else if( SCIPisLT(scip, newprobup, newprobdown) )
    609 *downscore += 1.0;
    610 break;
    611
    612 default :
    613 SCIPerrorMessage(" ERROR! No branching scheme selected! Exiting method.\n");
    614 return SCIP_INVALIDCALL;
    615 }
    616
    617 return SCIP_OKAY;
    618}
    619
    620/** calculate the branching score of a variable, depending on the chosen score parameter */
    621static
    623 SCIP* scip, /**< current SCIP */
    624 SCIP_BRANCHRULEDATA* branchruledata, /**< branch rule data */
    625 SCIP_VAR* var, /**< candidate variable */
    626 SCIP_Real lpsolval, /**< current fractional LP-relaxation solution value */
    627 SCIP_Real* upscore, /**< pointer to store the variable score when branching on it in upward direction */
    628 SCIP_Real* downscore, /**< pointer to store the variable score when branching on it in downward direction */
    629 char scoreparam /**< the score parameter of this branching rule */
    630 )
    631{
    632 SCIP_COL* varcol;
    633 SCIP_ROW** colrows;
    634 SCIP_Real* rowvals;
    635 SCIP_Real varlb;
    636 SCIP_Real varub;
    637 SCIP_Real squaredbounddiff; /* current squared difference of variable bounds (ub - lb)^2 */
    638 SCIP_Real newub; /* new upper bound if branching downwards */
    639 SCIP_Real newlb; /* new lower bound if branching upwards */
    640 SCIP_Real squaredbounddiffup; /* squared difference after branching upwards (ub - lb')^2 */
    641 SCIP_Real squaredbounddiffdown; /* squared difference after branching downwards (ub' - lb)^2 */
    642 SCIP_Real currentmean; /* current mean value of variable uniform distribution */
    643 SCIP_Real meanup; /* mean value of variable uniform distribution after branching up */
    644 SCIP_Real meandown; /* mean value of variable uniform distribution after branching down*/
    645 SCIP_VARTYPE vartype;
    646 SCIP_IMPLINTTYPE impltype;
    647 int ncolrows;
    648 int i;
    649
    650 SCIP_Bool onlyactiverows; /* should only rows which are active at the current node be considered? */
    651
    652 assert(scip != NULL);
    653 assert(var != NULL);
    654 assert(upscore != NULL);
    655 assert(downscore != NULL);
    656 assert(!SCIPisIntegral(scip, lpsolval));
    658
    659 varcol = SCIPvarGetCol(var);
    660 assert(varcol != NULL);
    661
    662 colrows = SCIPcolGetRows(varcol);
    663 rowvals = SCIPcolGetVals(varcol);
    664 ncolrows = SCIPcolGetNNonz(varcol);
    665 varlb = SCIPvarGetLbLocal(var);
    666 varub = SCIPvarGetUbLocal(var);
    667 assert(SCIPisFeasLT(scip, varlb, varub));
    668 vartype = SCIPvarGetType(var);
    669 impltype = SCIPvarGetImplType(var);
    670
    671 /* calculate mean and variance of variable uniform distribution before and after branching */
    672 currentmean = 0.0;
    673 squaredbounddiff = 0.0;
    674 SCIPvarCalcDistributionParameters(scip, varlb, varub, vartype, impltype, &currentmean, &squaredbounddiff);
    675
    676 newlb = SCIPfeasCeil(scip, lpsolval);
    677 newub = SCIPfeasFloor(scip, lpsolval);
    678
    679 /* calculate the variable's uniform distribution after branching up and down, respectively. */
    680 squaredbounddiffup = 0.0;
    681 meanup = 0.0;
    682 SCIPvarCalcDistributionParameters(scip, newlb, varub, vartype, impltype, &meanup, &squaredbounddiffup);
    683
    684 /* calculate the distribution mean and variance for a variable with finite lower bound */
    685 squaredbounddiffdown = 0.0;
    686 meandown = 0.0;
    687 SCIPvarCalcDistributionParameters(scip, varlb, newub, vartype, impltype, &meandown, &squaredbounddiffdown);
    688
    689 /* initialize the variable's up and down score */
    690 *upscore = 0.0;
    691 *downscore = 0.0;
    692
    693 onlyactiverows = branchruledata->onlyactiverows;
    694
    695 /* loop over the variable rows and calculate the up and down score */
    696 for( i = 0; i < ncolrows; ++i )
    697 {
    698 SCIP_ROW* row;
    699 SCIP_Real changedrowmean;
    700 SCIP_Real rowmean;
    701 SCIP_Real rowvariance;
    702 SCIP_Real changedrowvariance;
    703 SCIP_Real currentrowprob;
    704 SCIP_Real newrowprobup;
    705 SCIP_Real newrowprobdown;
    706 SCIP_Real squaredcoeff;
    707 SCIP_Real rowval;
    708 int rowinfinitiesdown;
    709 int rowinfinitiesup;
    710 int rowpos;
    711
    712 row = colrows[i];
    713 rowval = rowvals[i];
    714 assert(row != NULL);
    715
    716 /* we access the rows by their index */
    717 rowpos = SCIProwGetIndex(row);
    718
    719 /* skip non-active rows if the user parameter was set this way */
    720 if( onlyactiverows && SCIPisSumPositive(scip, SCIPgetRowLPFeasibility(scip, row)) )
    721 continue;
    722
    723 /* call method to ensure sufficient data capacity */
    724 SCIP_CALL( branchruledataEnsureArraySize(scip, branchruledata, rowpos) );
    725
    726 /* calculate row activity distribution if this is the first candidate to appear in this row */
    727 if( branchruledata->rowmeans[rowpos] == SCIP_INVALID ) /*lint !e777*/
    728 {
    729 rowCalculateGauss(scip, branchruledata, row, &branchruledata->rowmeans[rowpos], &branchruledata->rowvariances[rowpos],
    730 &branchruledata->rowinfinitiesdown[rowpos], &branchruledata->rowinfinitiesup[rowpos]);
    731 }
    732
    733 /* retrieve the row distribution parameters from the branch rule data */
    734 rowmean = branchruledata->rowmeans[rowpos];
    735 rowvariance = branchruledata->rowvariances[rowpos];
    736 rowinfinitiesdown = branchruledata->rowinfinitiesdown[rowpos];
    737 rowinfinitiesup = branchruledata->rowinfinitiesdown[rowpos];
    738 assert(!SCIPisNegative(scip, rowvariance));
    739
    740 currentrowprob = SCIProwCalcProbability(scip, row, rowmean, rowvariance,
    741 rowinfinitiesdown, rowinfinitiesup);
    742
    743 /* get variable's current expected contribution to row activity */
    744 squaredcoeff = SQR(rowval);
    745
    746 /* first, get the probability change for the row if the variable is branched on upwards. The probability
    747 * can only be affected if the variable upper bound is finite
    748 */
    749 if( !SCIPisInfinity(scip, varub) )
    750 {
    751 int rowinftiesdownafterbranch;
    752 int rowinftiesupafterbranch;
    753
    754 /* calculate how branching would affect the row parameters */
    755 changedrowmean = rowmean + rowval * (meanup - currentmean);
    756 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffup - squaredbounddiff);
    757 changedrowvariance = MAX(0.0, changedrowvariance);
    758
    759 rowinftiesdownafterbranch = rowinfinitiesdown;
    760 rowinftiesupafterbranch = rowinfinitiesup;
    761
    762 /* account for changes of the row's infinite bound contributions */
    763 if( SCIPisInfinity(scip, -varlb) && rowval < 0.0 )
    764 rowinftiesupafterbranch--;
    765 if( SCIPisInfinity(scip, -varlb) && rowval > 0.0 )
    766 rowinftiesdownafterbranch--;
    767
    768 assert(rowinftiesupafterbranch >= 0);
    769 assert(rowinftiesdownafterbranch >= 0);
    770 newrowprobup = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
    771 rowinftiesupafterbranch);
    772 }
    773 else
    774 newrowprobup = currentrowprob;
    775
    776 /* do the same for the other branching direction */
    777 if( !SCIPisInfinity(scip, varlb) )
    778 {
    779 int rowinftiesdownafterbranch;
    780 int rowinftiesupafterbranch;
    781
    782 changedrowmean = rowmean + rowval * (meandown - currentmean);
    783 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffdown - squaredbounddiff);
    784 changedrowvariance = MAX(0.0, changedrowvariance);
    785
    786 rowinftiesdownafterbranch = rowinfinitiesdown;
    787 rowinftiesupafterbranch = rowinfinitiesup;
    788
    789 /* account for changes of the row's infinite bound contributions */
    790 if( SCIPisInfinity(scip, varub) && rowval > 0.0 )
    791 rowinftiesupafterbranch -= 1;
    792 if( SCIPisInfinity(scip, varub) && rowval < 0.0 )
    793 rowinftiesdownafterbranch -= 1;
    794
    795 assert(rowinftiesdownafterbranch >= 0);
    796 assert(rowinftiesupafterbranch >= 0);
    797 newrowprobdown = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
    798 rowinftiesupafterbranch);
    799 }
    800 else
    801 newrowprobdown = currentrowprob;
    802
    803 /* update the up and down score depending on the chosen scoring parameter */
    804 SCIP_CALL( SCIPupdateDistributionScore(scip, currentrowprob, newrowprobup, newrowprobdown, upscore, downscore, scoreparam) );
    805
    806 SCIPdebugMsg(scip, " Variable %s changes probability of row %s from %g to %g (branch up) or %g;\n",
    807 SCIPvarGetName(var), SCIProwGetName(row), currentrowprob, newrowprobup, newrowprobdown);
    808 SCIPdebugMsg(scip, " --> new variable score: %g (for branching up), %g (for branching down)\n",
    809 *upscore, *downscore);
    810 }
    811
    812 return SCIP_OKAY;
    813}
    814
    815/** free branchrule data */
    816static
    818 SCIP* scip, /**< SCIP data structure */
    819 SCIP_BRANCHRULEDATA* branchruledata /**< branching rule data */
    820 )
    821{
    822 assert(branchruledata->memsize == 0 || branchruledata->rowmeans != NULL);
    823 assert(branchruledata->memsize >= 0);
    824
    825 if( branchruledata->memsize > 0 )
    826 {
    827 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowmeans, branchruledata->memsize);
    828 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowvariances, branchruledata->memsize);
    829 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowinfinitiesup, branchruledata->memsize);
    830 SCIPfreeBlockMemoryArray(scip, &branchruledata->rowinfinitiesdown, branchruledata->memsize);
    831
    832 SCIPfreeBlockMemoryArray(scip, &branchruledata->varfilterposs, branchruledata->varpossmemsize);
    833 SCIPfreeBlockMemoryArray(scip, &branchruledata->varposs, branchruledata->varpossmemsize);
    834 SCIPfreeBlockMemoryArray(scip, &branchruledata->updatedvars, branchruledata->varpossmemsize);
    835 SCIPfreeBlockMemoryArray(scip, &branchruledata->currentubs, branchruledata->varpossmemsize);
    836 SCIPfreeBlockMemoryArray(scip, &branchruledata->currentlbs, branchruledata->varpossmemsize);
    837
    838 branchruledata->memsize = 0;
    839 }
    840}
    841
    842/** add variable to the bound change event queue; skipped if variable is already in there, or if variable has
    843 * no row currently watched
    844 */
    845static
    847 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
    848 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
    849 )
    850{
    851 int varindex;
    852 int varpos;
    853
    854 assert(var != NULL);
    855
    856 varindex = SCIPvarGetProbindex(var);
    857 assert(-1 <= varindex && varindex < branchruledata->varpossmemsize);
    858
    859 /* if variable is not active, it should not be watched */
    860 if( varindex == -1 )
    861 return;
    862 varpos = branchruledata->varposs[varindex];
    863 assert(varpos < branchruledata->nupdatedvars);
    864
    865 /* nothing to do if variable is already in the queue */
    866 if( varpos >= 0 )
    867 {
    868 assert(branchruledata->updatedvars[varpos] == var);
    869
    870 return;
    871 }
    872
    873 /* if none of the variables rows was calculated yet, variable needs not to be watched */
    874 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID) == (branchruledata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777*/
    875 if( branchruledata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777*/
    876 return;
    877
    878 /* add the variable to the branch rule data of variables to process updates for */
    879 assert(branchruledata->varpossmemsize > branchruledata->nupdatedvars);
    880 varpos = branchruledata->nupdatedvars;
    881 branchruledata->updatedvars[varpos] = var;
    882 branchruledata->varposs[varindex] = varpos;
    883 ++branchruledata->nupdatedvars;
    884}
    885
    886/** returns the next unprocessed variable (last in, first out) with pending bound changes, or NULL */
    887static
    889 SCIP_BRANCHRULEDATA* branchruledata /**< branchrule data */
    890 )
    891{
    892 SCIP_VAR* var;
    893 int varpos;
    894 int varindex;
    895
    896 assert(branchruledata->nupdatedvars >= 0);
    897
    898 /* return if no variable is currently pending */
    899 if( branchruledata->nupdatedvars == 0 )
    900 return NULL;
    901
    902 varpos = branchruledata->nupdatedvars - 1;
    903 var = branchruledata->updatedvars[varpos];
    904 assert(var != NULL);
    905 varindex = SCIPvarGetProbindex(var);
    906 assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
    907 assert(varpos == branchruledata->varposs[varindex]);
    908
    909 branchruledata->varposs[varindex] = -1;
    910 branchruledata->nupdatedvars--;
    911
    912 return var;
    913}
    914
    915/** process a variable from the queue of changed variables */
    916static
    918 SCIP* scip, /**< SCIP data structure */
    919 SCIP_BRANCHRULEDATA* branchruledata, /**< branchrule data */
    920 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
    921 )
    922{
    923 SCIP_ROW** colrows;
    924 SCIP_COL* varcol;
    925 SCIP_Real* colvals;
    926 SCIP_Real oldmean;
    927 SCIP_Real newmean;
    928 SCIP_Real oldvariance;
    929 SCIP_Real newvariance;
    930 SCIP_Real oldlb;
    931 SCIP_Real newlb;
    932 SCIP_Real oldub;
    933 SCIP_Real newub;
    934 SCIP_VARTYPE vartype;
    935 SCIP_IMPLINTTYPE impltype;
    936 int ncolrows;
    937 int r;
    938 int varindex;
    939
    940 /* skip event execution if SCIP is in Probing mode because these bound changes will be undone anyway before branching
    941 * rule is called again
    942 */
    943 assert(!SCIPinProbing(scip));
    944
    945 assert(var != NULL);
    946 varcol = SCIPvarGetCol(var);
    947 assert(varcol != NULL);
    948 colrows = SCIPcolGetRows(varcol);
    949 colvals = SCIPcolGetVals(varcol);
    950 ncolrows = SCIPcolGetNNonz(varcol);
    951
    952 varindex = SCIPvarGetProbindex(var);
    953
    954 oldlb = branchruledata->currentlbs[varindex];
    955 oldub = branchruledata->currentubs[varindex];
    956
    957 /* skip update if the variable has never been subject of previously calculated row activities */
    958 assert((oldlb == SCIP_INVALID) == (oldub == SCIP_INVALID)); /*lint !e777*/
    959 if( oldlb == SCIP_INVALID ) /*lint !e777*/
    960 return SCIP_OKAY;
    961
    962 newlb = SCIPvarGetLbLocal(var);
    963 newub = SCIPvarGetUbLocal(var);
    964
    965 /* skip update if the bound change events have cancelled out */
    966 if( SCIPisFeasEQ(scip, oldlb, newlb) && SCIPisFeasEQ(scip, oldub, newub) )
    967 return SCIP_OKAY;
    968
    969 /* calculate old and new variable distribution mean and variance */
    970 oldvariance = 0.0;
    971 newvariance = 0.0;
    972 oldmean = 0.0;
    973 newmean = 0.0;
    974 vartype = SCIPvarGetType(var);
    975 impltype = SCIPvarGetImplType(var);
    976 SCIPvarCalcDistributionParameters(scip, oldlb, oldub, vartype, impltype, &oldmean, &oldvariance);
    977 SCIPvarCalcDistributionParameters(scip, newlb, newub, vartype, impltype, &newmean, &newvariance);
    978
    979 /* loop over all rows of this variable and update activity distribution */
    980 for( r = 0; r < ncolrows; ++r )
    981 {
    982 int rowpos;
    983
    984 assert(colrows[r] != NULL);
    985 rowpos = SCIProwGetIndex(colrows[r]);
    986 assert(rowpos >= 0);
    987
    988 SCIP_CALL( branchruledataEnsureArraySize(scip, branchruledata, rowpos) );
    989
    990 /* only consider rows for which activity distribution was already calculated */
    991 if( branchruledata->rowmeans[rowpos] != SCIP_INVALID ) /*lint !e777*/
    992 {
    993 SCIP_Real coeff;
    994 SCIP_Real coeffsquared;
    995 /*lint -e777*/
    996 assert(branchruledata->rowvariances[rowpos] != SCIP_INVALID
    997 && SCIPisFeasGE(scip, branchruledata->rowvariances[rowpos], 0.0));
    998
    999 coeff = colvals[r];
    1000 coeffsquared = SQR(coeff);
    1001
    1002 /* update variable contribution to row activity distribution */
    1003 branchruledata->rowmeans[rowpos] += coeff * (newmean - oldmean);
    1004 branchruledata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
    1005 branchruledata->rowvariances[rowpos] = MAX(0.0, branchruledata->rowvariances[rowpos]);
    1006
    1007 /* account for changes of the infinite contributions to row activities */
    1008 if( coeff > 0.0 )
    1009 {
    1010 /* if the coefficient is positive, upper bounds affect activity up */
    1011 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
    1012 ++branchruledata->rowinfinitiesup[rowpos];
    1013 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
    1014 --branchruledata->rowinfinitiesup[rowpos];
    1015
    1016 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
    1017 ++branchruledata->rowinfinitiesdown[rowpos];
    1018 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
    1019 --branchruledata->rowinfinitiesdown[rowpos];
    1020 }
    1021 else if( coeff < 0.0 )
    1022 {
    1023 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
    1024 ++branchruledata->rowinfinitiesdown[rowpos];
    1025 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
    1026 --branchruledata->rowinfinitiesdown[rowpos];
    1027
    1028 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
    1029 ++branchruledata->rowinfinitiesup[rowpos];
    1030 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
    1031 --branchruledata->rowinfinitiesup[rowpos];
    1032 }
    1033 assert(branchruledata->rowinfinitiesdown[rowpos] >= 0);
    1034 assert(branchruledata->rowinfinitiesup[rowpos] >= 0);
    1035 }
    1036 }
    1037
    1038 /* store the new local bounds in the data */
    1039 branchruledataUpdateCurrentBounds(scip, branchruledata, var);
    1040
    1041 return SCIP_OKAY;
    1042}
    1043
    1044/** destructor of event handler to free user data (called when SCIP is exiting) */
    1045static
    1046SCIP_DECL_EVENTFREE(eventFreeDistribution)
    1047{
    1048 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1049
    1050 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1051 assert(eventhdlrdata != NULL);
    1052
    1053 SCIPfreeBlockMemory(scip, &eventhdlrdata);
    1054 SCIPeventhdlrSetData(eventhdlr, NULL);
    1055
    1056 return SCIP_OKAY;
    1057}
    1058
    1059/*
    1060 * Callback methods of branching rule
    1061 */
    1062
    1063/** copy method for branchrule plugins (called when SCIP copies plugins) */
    1064static
    1065SCIP_DECL_BRANCHCOPY(branchCopyDistribution)
    1066{ /*lint --e{715}*/
    1067 assert(scip != NULL);
    1068
    1070
    1071 return SCIP_OKAY;
    1072}
    1073
    1074/** solving process deinitialization method of branching rule (called before branch and bound process data is freed) */
    1075static
    1076SCIP_DECL_BRANCHEXITSOL(branchExitsolDistribution)
    1077{
    1078 SCIP_BRANCHRULEDATA* branchruledata;
    1079
    1080 assert(branchrule != NULL);
    1081 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
    1082
    1083 branchruledata = SCIPbranchruleGetData(branchrule);
    1084 assert(branchruledata != NULL);
    1085
    1086 /* drop variable events at the end of branch and bound process (cannot be used after restarts, anyway) */
    1087 if( branchruledata->varfilterposs != NULL)
    1088 {
    1089 SCIP_VAR** vars;
    1090 int nvars;
    1091 int v;
    1092
    1093 vars = SCIPgetVars(scip);
    1094 nvars = SCIPgetNVars(scip);
    1095
    1096 assert(nvars > 0);
    1097 for( v = 0; v < nvars; ++v )
    1098 {
    1099 SCIP_CALL( SCIPdropVarEvent(scip, vars[v], EVENT_DISTRIBUTION, branchruledata->eventhdlr, NULL, branchruledata->varfilterposs[v]) );
    1100 }
    1101 }
    1102
    1103 /* free row arrays when branch-and-bound data is freed */
    1104 branchruledataFreeArrays(scip, branchruledata);
    1105
    1106 return SCIP_OKAY;
    1107}
    1108
    1109/** destructor of branching rule to free user data (called when SCIP is exiting) */
    1110static
    1111SCIP_DECL_BRANCHFREE(branchFreeDistribution)
    1112{
    1113 SCIP_BRANCHRULEDATA* branchruledata;
    1114
    1115 assert(branchrule != NULL);
    1116 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
    1117
    1118 branchruledata = SCIPbranchruleGetData(branchrule);
    1119 assert(branchruledata != NULL);
    1120
    1121 /* free internal arrays first */
    1122 branchruledataFreeArrays(scip, branchruledata);
    1123 SCIPfreeBlockMemory(scip, &branchruledata);
    1124 SCIPbranchruleSetData(branchrule, NULL);
    1125
    1126 return SCIP_OKAY;
    1127}
    1128
    1129/** branching execution method for fractional LP solutions */
    1130static
    1131SCIP_DECL_BRANCHEXECLP(branchExeclpDistribution)
    1132{ /*lint --e{715}*/
    1133 SCIP_BRANCHRULEDATA* branchruledata;
    1134 SCIP_VAR** lpcands;
    1135 SCIP_VAR* bestcand;
    1136 SCIP_NODE* downchild;
    1137 SCIP_NODE* upchild;
    1138
    1139 SCIP_Real* lpcandssol;
    1140
    1141 SCIP_Real bestscore;
    1142 SCIP_BRANCHDIR bestbranchdir;
    1143 int nlpcands;
    1144 int c;
    1145
    1146 assert(branchrule != NULL);
    1147 assert(strcmp(SCIPbranchruleGetName(branchrule), BRANCHRULE_NAME) == 0);
    1148 assert(scip != NULL);
    1149 assert(result != NULL);
    1150
    1151 *result = SCIP_DIDNOTRUN;
    1152
    1153 SCIP_CALL( SCIPgetLPBranchCands(scip, &lpcands, &lpcandssol, NULL, NULL, &nlpcands, NULL) );
    1154
    1155 if( nlpcands == 0 )
    1156 return SCIP_OKAY;
    1157
    1158 if( SCIPgetNActivePricers(scip) > 0 )
    1159 return SCIP_OKAY;
    1160
    1161 branchruledata = SCIPbranchruleGetData(branchrule);
    1162
    1163 /* if branching rule data arrays were not initialized before (usually the first call of the branching execution),
    1164 * allocate arrays with an initial capacity of the number of LP rows */
    1165 if( branchruledata->memsize == 0 )
    1166 {
    1167 int nlprows;
    1168
    1169 /* get LP rows data */
    1170 nlprows = SCIPgetNLPRows(scip);
    1171
    1172 /* initialize arrays only if there are actual LP rows to operate on */
    1173 if( nlprows > 0 )
    1174 {
    1175 SCIP_CALL( branchruledataEnsureArraySize(scip, branchruledata, nlprows) );
    1176 }
    1177 else /* if there are no LP rows, branching rule cannot be used */
    1178 return SCIP_OKAY;
    1179 }
    1180
    1181 /* process pending bound change events */
    1182 while( branchruledata->nupdatedvars > 0 )
    1183 {
    1184 SCIP_VAR* nextvar;
    1185
    1186 /* pop the next variable from the queue and process its bound changes */
    1187 nextvar = branchruledataPopBoundChangeVar(branchruledata);
    1188 assert(nextvar != NULL);
    1189 SCIP_CALL( varProcessBoundChanges(scip, branchruledata, nextvar) );
    1190 }
    1191
    1192 bestscore = -1;
    1193 bestbranchdir = SCIP_BRANCHDIR_AUTO;
    1194 bestcand = NULL;
    1195
    1196 /* invalidate the current row distribution data which is initialized on the fly when looping over the candidates */
    1197
    1198 /* loop over candidate variables and calculate their score in changing the cumulative
    1199 * probability of fulfilling each of their constraints */
    1200 for( c = 0; c < nlpcands; ++c )
    1201 {
    1202 SCIP_Real upscore;
    1203 SCIP_Real downscore;
    1204 SCIP_VAR* lpcand;
    1205 int varindex;
    1206
    1207 lpcand = lpcands[c];
    1208 assert(lpcand != NULL);
    1209
    1210 varindex = SCIPvarGetProbindex(lpcand);
    1211
    1212 /* in debug mode, ensure that all bound process events which occurred in the mean time have been captured
    1213 * by the branching rule event system
    1214 */
    1215 assert(SCIPisFeasLE(scip, SCIPvarGetLbLocal(lpcand), SCIPvarGetUbLocal(lpcand)));
    1216 assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
    1217
    1218 /*lint -e777*/
    1219 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID) == (branchruledata->currentubs[varindex] == SCIP_INVALID));
    1220 assert((branchruledata->currentlbs[varindex] == SCIP_INVALID)
    1221 || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(lpcand), branchruledata->currentlbs[varindex]));
    1222 assert((branchruledata->currentubs[varindex] == SCIP_INVALID)
    1223 || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(lpcand), branchruledata->currentubs[varindex]));
    1224
    1225 /* if the branching rule has not captured the variable bounds yet, this can be done now */
    1226 if( branchruledata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777*/
    1227 {
    1228 branchruledataUpdateCurrentBounds(scip, branchruledata, lpcand);
    1229 }
    1230
    1231 upscore = 0.0;
    1232 downscore = 0.0;
    1233
    1234 /* loop over candidate rows and determine the candidate up- and down- branching score w.r.t. the score parameter */
    1235 SCIP_CALL( calcBranchScore(scip, branchruledata, lpcand, lpcandssol[c],
    1236 &upscore, &downscore, branchruledata->scoreparam) );
    1237
    1238 /* if weighted scoring is enabled, use the branching score method of SCIP to weigh up and down score */
    1239 if( branchruledata->usescipscore )
    1240 {
    1241 SCIP_Real score;
    1242
    1243 score = SCIPgetBranchScore(scip, lpcand, downscore, upscore);
    1244
    1245 /* select the candidate with the highest branching score */
    1246 if( score > bestscore )
    1247 {
    1248 bestscore = score;
    1249 bestcand = lpcand;
    1250 /* prioritize branching direction with the higher score */
    1251 if( upscore > downscore )
    1252 bestbranchdir = SCIP_BRANCHDIR_UPWARDS;
    1253 else
    1254 bestbranchdir = SCIP_BRANCHDIR_DOWNWARDS;
    1255 }
    1256 }
    1257 else
    1258 {
    1259 /* no weighted score; keep candidate which has the single highest score in one direction */
    1260 if( upscore > bestscore && upscore > downscore )
    1261 {
    1262 bestscore = upscore;
    1263 bestbranchdir = SCIP_BRANCHDIR_UPWARDS;
    1264 bestcand = lpcand;
    1265 }
    1266 else if( downscore > bestscore )
    1267 {
    1268 bestscore = downscore;
    1269 bestbranchdir = SCIP_BRANCHDIR_DOWNWARDS;
    1270 bestcand = lpcand;
    1271 }
    1272 }
    1273
    1274 SCIPdebugMsg(scip, " Candidate %s has score down %g and up %g \n", SCIPvarGetName(lpcand), downscore, upscore);
    1275 SCIPdebugMsg(scip, " Best candidate: %s, score %g, direction %d\n", SCIPvarGetName(bestcand), bestscore, bestbranchdir);
    1276 }
    1277 assert(!SCIPisFeasIntegral(scip, SCIPvarGetSol(bestcand, TRUE)));
    1278 assert(bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS || bestbranchdir == SCIP_BRANCHDIR_UPWARDS);
    1279 assert(bestcand != NULL);
    1280
    1281 SCIPdebugMsg(scip, " Branching on variable %s with bounds [%g, %g] and solution value <%g>\n", SCIPvarGetName(bestcand),
    1282 SCIPvarGetLbLocal(bestcand), SCIPvarGetUbLocal(bestcand), SCIPvarGetLPSol(bestcand));
    1283
    1284 /* branch on the best candidate variable */
    1285 SCIP_CALL( SCIPbranchVar(scip, bestcand, &downchild, NULL, &upchild) );
    1286
    1287 assert(downchild != NULL);
    1288 assert(upchild != NULL);
    1289
    1290 if( bestbranchdir == SCIP_BRANCHDIR_UPWARDS )
    1291 {
    1293 SCIPdebugMsg(scip, " Changing node priority of up-child.\n");
    1294 }
    1295 else
    1296 {
    1297 assert(bestbranchdir == SCIP_BRANCHDIR_DOWNWARDS);
    1299 SCIPdebugMsg(scip, " Changing node priority of down-child.\n");
    1300 }
    1301
    1302 *result = SCIP_BRANCHED;
    1303
    1304 return SCIP_OKAY;
    1305}
    1306
    1307/** event execution method of distribution branching which handles bound change events of variables */
    1308static
    1309SCIP_DECL_EVENTEXEC(eventExecDistribution)
    1310{ /*lint --e{715}*/
    1311 SCIP_BRANCHRULEDATA* branchruledata;
    1312 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1313 SCIP_VAR* var;
    1314
    1315 assert(eventhdlr != NULL);
    1316 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1317 assert(eventhdlrdata != NULL);
    1318
    1319 branchruledata = eventhdlrdata->branchruledata;
    1320 var = SCIPeventGetVar(event);
    1321
    1322 /* add the variable to the queue of unprocessed variables; method itself ensures that every variable is added at most once */
    1323 branchruledataAddBoundChangeVar(branchruledata, var);
    1324
    1325 return SCIP_OKAY;
    1326}
    1327
    1328
    1329/*
    1330 * branching rule specific interface methods
    1331 */
    1332
    1333/** creates the distribution branching rule and includes it in SCIP */
    1335 SCIP* scip /**< SCIP data structure */
    1336 )
    1337{
    1338 SCIP_BRANCHRULE* branchrule = NULL;
    1339 SCIP_BRANCHRULEDATA* branchruledata;
    1340 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1341
    1342 /* create distribution branching rule data */
    1343 branchruledata = NULL;
    1344 SCIP_CALL( SCIPallocBlockMemory(scip, &branchruledata) );
    1345
    1346 branchruledata->memsize = 0;
    1347 branchruledata->rowmeans = NULL;
    1348 branchruledata->rowvariances = NULL;
    1349 branchruledata->rowinfinitiesdown = NULL;
    1350 branchruledata->rowinfinitiesup = NULL;
    1351 branchruledata->varfilterposs = NULL;
    1352 branchruledata->currentlbs = NULL;
    1353 branchruledata->currentubs = NULL;
    1354
    1355 /* create event handler first to finish branch rule data */
    1356 eventhdlrdata = NULL;
    1357 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
    1358 eventhdlrdata->branchruledata = branchruledata;
    1359
    1360 branchruledata->eventhdlr = NULL;
    1361 SCIP_CALL( SCIPincludeEventhdlrBasic(scip, &branchruledata->eventhdlr, EVENTHDLR_NAME,
    1362 "event handler for dynamic acitivity distribution updating",
    1363 eventExecDistribution, eventhdlrdata) );
    1364 assert( branchruledata->eventhdlr != NULL);
    1365 SCIP_CALL( SCIPsetEventhdlrFree(scip, branchruledata->eventhdlr, eventFreeDistribution) );
    1366
    1367 /* include branching rule */
    1369 BRANCHRULE_MAXBOUNDDIST, branchruledata) );
    1370
    1371 assert(branchrule != NULL);
    1372 SCIP_CALL( SCIPsetBranchruleCopy(scip, branchrule, branchCopyDistribution) );
    1373 SCIP_CALL( SCIPsetBranchruleFree(scip, branchrule, branchFreeDistribution) );
    1374 SCIP_CALL( SCIPsetBranchruleExitsol(scip, branchrule, branchExitsolDistribution) );
    1375 SCIP_CALL( SCIPsetBranchruleExecLp(scip, branchrule, branchExeclpDistribution) );
    1376
    1377 /* add distribution branching rule parameters */
    1378 SCIP_CALL( SCIPaddCharParam(scip, "branching/" BRANCHRULE_NAME "/scoreparam",
    1379 "the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p., 'v'otes lowest c.p., votes highest c.p.('w') ",
    1380 &branchruledata->scoreparam, TRUE, DEFAULT_SCOREPARAM, SCOREPARAM_VALUES, NULL, NULL) );
    1381
    1382 SCIP_CALL( SCIPaddBoolParam(scip, "branching/" BRANCHRULE_NAME "/onlyactiverows",
    1383 "should only rows which are active at the current node be considered?",
    1384 &branchruledata->onlyactiverows, TRUE, DEFAULT_ONLYACTIVEROWS, NULL, NULL) );
    1385
    1386 SCIP_CALL( SCIPaddBoolParam(scip, "branching/" BRANCHRULE_NAME "/weightedscore",
    1387 "should the branching score weigh up- and down-scores of a variable",
    1388 &branchruledata->usescipscore, TRUE, DEFAULT_USEWEIGHTEDSCORE, NULL, NULL) );
    1389
    1390 return SCIP_OKAY;
    1391}
    #define BRANCHRULE_DESC
    #define DEFAULT_PRIORITY
    #define DEFAULT_SCOREPARAM
    #define BRANCHRULE_PRIORITY
    #define EVENT_DISTRIBUTION
    static SCIP_DECL_BRANCHCOPY(branchCopyDistribution)
    static SCIP_DECL_BRANCHEXECLP(branchExeclpDistribution)
    static SCIP_RETCODE calcBranchScore(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var, SCIP_Real lpsolval, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
    #define SCOREPARAM_VALUES
    static SCIP_DECL_EVENTEXEC(eventExecDistribution)
    static SCIP_DECL_BRANCHFREE(branchFreeDistribution)
    #define BRANCHRULE_NAME
    static void rowCalculateGauss(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_ROW *row, SCIP_Real *mu, SCIP_Real *sigma2, int *rowinfinitiesdown, int *rowinfinitiesup)
    static SCIP_VAR * branchruledataPopBoundChangeVar(SCIP_BRANCHRULEDATA *branchruledata)
    static SCIP_RETCODE branchruledataEnsureArraySize(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, int maxindex)
    static void branchruledataFreeArrays(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata)
    static SCIP_DECL_EVENTFREE(eventFreeDistribution)
    static SCIP_RETCODE varProcessBoundChanges(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
    static SCIP_DECL_BRANCHEXITSOL(branchExitsolDistribution)
    static void branchruledataUpdateCurrentBounds(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
    #define DEFAULT_ONLYACTIVEROWS
    static void branchruledataAddBoundChangeVar(SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
    #define EVENTHDLR_NAME
    #define BRANCHRULE_MAXDEPTH
    #define BRANCHRULE_MAXBOUNDDIST
    #define DEFAULT_USEWEIGHTEDSCORE
    probability based branching rule based on an article by J. Pryor and J.W. Chinneck
    SCIP_Real * r
    Definition: circlepacking.c:59
    #define NULL
    Definition: def.h:248
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIP_CALL(x)
    Definition: def.h:355
    SCIP_RETCODE SCIPupdateDistributionScore(SCIP *scip, SCIP_Real currentprob, SCIP_Real newprobup, SCIP_Real newprobdown, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
    SCIP_Real SCIProwCalcProbability(SCIP *scip, SCIP_ROW *row, SCIP_Real mu, SCIP_Real sigma2, int rowinfinitiesdown, int rowinfinitiesup)
    void SCIPvarCalcDistributionParameters(SCIP *scip, SCIP_Real varlb, SCIP_Real varub, SCIP_VARTYPE vartype, SCIP_IMPLINTTYPE impltype, SCIP_Real *mean, SCIP_Real *variance)
    SCIP_Real SCIPcalcCumulativeDistribution(SCIP *scip, SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
    SCIP_RETCODE SCIPincludeBranchruleDistribution(SCIP *scip)
    SCIP_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    SCIP_RETCODE SCIPchgChildPrio(SCIP *scip, SCIP_NODE *child, SCIP_Real priority)
    Definition: scip_prob.c:4388
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    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 SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_RETCODE 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
    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 SCIPsetBranchruleExitsol(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXITSOL((*branchexitsol)))
    Definition: scip_branch.c:240
    void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
    Definition: branch.c:1896
    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
    SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
    Definition: lp.c:17425
    int SCIPcolGetNNonz(SCIP_COL *col)
    Definition: lp.c:17520
    SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
    Definition: lp.c:17555
    SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
    Definition: lp.c:17545
    SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: scip_event.c:111
    SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
    Definition: event.c:406
    void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
    Definition: event.c:416
    SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
    Definition: scip_event.c:157
    SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
    Definition: scip_event.c:367
    SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
    Definition: scip_event.c:413
    SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
    Definition: event.c:1217
    int SCIPgetNLPRows(SCIP *scip)
    Definition: scip_lp.c:632
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
    Definition: scip_mem.h:99
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    int SCIPgetNActivePricers(SCIP *scip)
    Definition: scip_pricer.c:348
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
    Definition: lp.c:17686
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
    Definition: lp.c:17696
    SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
    Definition: scip_lp.c:2176
    const char * SCIProwGetName(SCIP_ROW *row)
    Definition: lp.c:17745
    int SCIProwGetIndex(SCIP_ROW *row)
    Definition: lp.c:17755
    SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
    Definition: scip_lp.c:1974
    SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_Bool SCIPisSumPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23683
    SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
    Definition: var.c:19007
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
    Definition: var.c:23386
    SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
    Definition: var.c:24268
    SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
    Definition: var.c:23453
    int SCIPvarGetProbindex(SCIP_VAR *var)
    Definition: var.c:23662
    const char * SCIPvarGetName(SCIP_VAR *var)
    Definition: var.c:23267
    SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
    Definition: var.c:24664
    SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
    Definition: var.c:23463
    SCIP_Real SCIPerf(SCIP_Real x)
    Definition: misc.c:160
    #define M_SQRT2
    Definition: misc_rowprep.c:59
    Definition: pqueue.h:38
    public methods for branching rules
    public methods for managing events
    public methods for LP management
    public methods for message output
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public data structures and miscellaneous methods
    public methods for problem variables
    public methods for branching rule plugins and branching
    public methods for event handler plugins and event handlers
    general public methods
    public methods for the LP relaxation, rows and columns
    public methods for memory management
    public methods for message handling
    public methods for numerical tolerances
    public methods for SCIP parameter handling
    public methods for variable pricer plugins
    public methods for global and local (sub)problems
    public methods for the probing mode
    struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
    Definition: type_branch.h:57
    struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
    Definition: type_event.h:160
    @ SCIP_BRANCHDIR_DOWNWARDS
    Definition: type_history.h:43
    @ SCIP_BRANCHDIR_AUTO
    Definition: type_history.h:46
    @ SCIP_BRANCHDIR_UPWARDS
    Definition: type_history.h:44
    enum SCIP_BranchDir SCIP_BRANCHDIR
    Definition: type_history.h:48
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ 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_STAGE_SOLVING
    Definition: type_set.h:53
    enum SCIP_ImplintType SCIP_IMPLINTTYPE
    Definition: type_var.h:117
    @ SCIP_IMPLINTTYPE_NONE
    Definition: type_var.h:90
    @ SCIP_VARTYPE_CONTINUOUS
    Definition: type_var.h:71
    @ SCIP_VARSTATUS_COLUMN
    Definition: type_var.h:53
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73