Scippy

    SCIP

    Solving Constraint Integer Programs

    heur_distributiondiving.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 heur_distributiondiving.c
    26 * @ingroup DEFPLUGINS_HEUR
    27 * @brief Diving heuristic that chooses fixings w.r.t. changes in the solution density after Pryor and Chinneck.
    28 * @author Gregor Hendel
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    36#include "scip/heuristics.h"
    37#include "scip/pub_event.h"
    38#include "scip/pub_heur.h"
    39#include "scip/pub_lp.h"
    40#include "scip/pub_message.h"
    41#include "scip/pub_var.h"
    42#include "scip/scip_event.h"
    43#include "scip/scip_general.h"
    44#include "scip/scip_heur.h"
    45#include "scip/scip_lp.h"
    46#include "scip/scip_mem.h"
    47#include "scip/scip_message.h"
    48#include "scip/scip_numerics.h"
    49#include "scip/scip_param.h"
    50#include "scip/scip_prob.h"
    51#include "scip/scip_probing.h"
    52#include "scip/scip_sol.h"
    53#include <string.h>
    54
    55#define HEUR_NAME "distributiondiving"
    56#define HEUR_DESC "Diving heuristic that chooses fixings w.r.t. changes in the solution density"
    57#define HEUR_DISPCHAR SCIP_HEURDISPCHAR_DIVING
    58#define HEUR_PRIORITY -1003300
    59#define HEUR_FREQ 10
    60#define HEUR_FREQOFS 3
    61#define HEUR_MAXDEPTH -1
    62#define HEUR_TIMING SCIP_HEURTIMING_AFTERLPPLUNGE
    63#define HEUR_USESSUBSCIP FALSE /**< does the heuristic use a secondary SCIP instance? */
    64#define EVENT_DISTRIBUTION SCIP_EVENTTYPE_BOUNDCHANGED /**< the event type to be handled by this event handler */
    65#define EVENTHDLR_NAME "eventhdlr_distributiondiving"
    66#define DIVESET_DIVETYPES SCIP_DIVETYPE_INTEGRALITY /**< bit mask that represents all supported dive types */
    67#define DIVESET_ISPUBLIC FALSE /**< is this dive set publicly available (ie., can be used by other primal heuristics?) */
    68
    69/*
    70 * Default parameter settings
    71 */
    72
    73#define DEFAULT_MINRELDEPTH 0.0 /**< minimal relative depth to start diving */
    74#define DEFAULT_MAXRELDEPTH 1.0 /**< maximal relative depth to start diving */
    75#define DEFAULT_MAXLPITERQUOT 0.05 /**< maximal fraction of diving LP iterations compared to node LP iterations */
    76#define DEFAULT_MAXLPITEROFS 1000 /**< additional number of allowed LP iterations */
    77#define DEFAULT_MAXDIVEUBQUOT 0.8 /**< maximal quotient (curlowerbound - lowerbound)/(cutoffbound - lowerbound)
    78 * where diving is performed (0.0: no limit) */
    79#define DEFAULT_MAXDIVEAVGQUOT 0.0 /**< maximal quotient (curlowerbound - lowerbound)/(avglowerbound - lowerbound)
    80 * where diving is performed (0.0: no limit) */
    81#define DEFAULT_MAXDIVEUBQUOTNOSOL 0.1 /**< maximal UBQUOT when no solution was found yet (0.0: no limit) */
    82#define DEFAULT_MAXDIVEAVGQUOTNOSOL 0.0 /**< maximal AVGQUOT when no solution was found yet (0.0: no limit) */
    83#define DEFAULT_BACKTRACK TRUE /**< use one level of backtracking if infeasibility is encountered? */
    84#define DEFAULT_LPRESOLVEDOMCHGQUOT 0.15 /**< percentage of immediate domain changes during probing to trigger LP resolve */
    85#define DEFAULT_LPSOLVEFREQ 0 /**< LP solve frequency for diving heuristics */
    86#define DEFAULT_ONLYLPBRANCHCANDS TRUE /**< should only LP branching candidates be considered instead of the slower but
    87 * more general constraint handler diving variable selection? */
    88
    89#define SCOREPARAM_VALUES "lhwvd" /**< the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p.,
    90 * 'v'otes lowest c.p., votes highest c.p.('w'), 'r'evolving */
    91#define SCOREPARAM_VALUESLEN 5
    92#define DEFAULT_SCOREPARAM 'r' /**< default scoring parameter to guide the diving */
    93#define DEFAULT_RANDSEED 117 /**< initial seed for random number generation */
    94
    95/* locally defined heuristic data */
    96struct SCIP_HeurData
    97{
    98 SCIP_SOL* sol; /**< working solution */
    99 SCIP_EVENTHDLR* eventhdlr; /**< event handler pointer */
    100 SCIP_VAR** updatedvars; /**< variables to process bound change events for */
    101 SCIP_Real* rowmeans; /**< row activity mean values for all rows */
    102 SCIP_Real* rowvariances; /**< row activity variances for all rows */
    103 SCIP_Real* currentubs; /**< variable upper bounds as currently saved in the row activities */
    104 SCIP_Real* currentlbs; /**< variable lower bounds as currently saved in the row activities */
    105 int* rowinfinitiesdown; /**< count the number of variables with infinite bounds which allow for always
    106 * repairing the constraint right hand side */
    107 int* rowinfinitiesup; /**< count the number of variables with infinite bounds which allow for always
    108 * repairing the constraint left hand side */
    109 int* varposs; /**< array of variable positions in the updated variables array */
    110 int* varfilterposs; /**< array of event filter positions for variable events */
    111 int nupdatedvars; /**< the current number of variables with pending bound changes */
    112 int memsize; /**< memory size of current arrays, needed for dynamic reallocation */
    113 int varpossmemsize; /**< memory size of updated vars and varposs array */
    114
    115 char scoreparam; /**< score user parameter */
    116 char score; /**< score to be used depending on user parameter to use fixed score or revolve */
    117};
    118
    119struct SCIP_EventhdlrData
    120{
    121 SCIP_HEURDATA* heurdata; /**< the heuristic data to access distribution arrays */
    122};
    123/*
    124 * local methods
    125 */
    126
    127/** ensure that maxindex + 1 rows can be represented in data arrays; memory gets reallocated with 10% extra space
    128 * to save some time for future allocations */
    129static
    131 SCIP* scip, /**< SCIP data structure */
    132 SCIP_HEURDATA* heurdata, /**< heuristic data */
    133 int maxindex /**< row index at hand (size must be at least this large) */
    134 )
    135{
    136 int newsize;
    137 int r;
    138
    139 /* maxindex fits in current array -> nothing to do */
    140 if( maxindex < heurdata->memsize )
    141 return SCIP_OKAY;
    142
    143 /* new memory size is the max index + 1 plus 10% additional space */
    144 newsize = (int)SCIPfeasCeil(scip, (maxindex + 1) * 1.1);
    145 assert(newsize > heurdata->memsize);
    146 assert(heurdata->memsize >= 0);
    147
    148 /* alloc memory arrays for row information */
    149 if( heurdata->memsize == 0 )
    150 {
    151 SCIP_VAR** vars;
    152 int v;
    153 int nvars;
    154
    155 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) );
    156 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) );
    157 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowmeans, newsize) );
    158 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->rowvariances, newsize) );
    159
    161
    162 vars = SCIPgetVars(scip);
    163 nvars = SCIPgetNVars(scip);
    164
    165 assert(nvars > 0);
    166
    167 /* allocate variable update event processing array storage */
    168 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varfilterposs, nvars) );
    169 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->varposs, nvars) );
    170 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->updatedvars, nvars) );
    171 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentubs, nvars) );
    172 SCIP_CALL( SCIPallocBufferArray(scip, &heurdata->currentlbs, nvars) );
    173
    174 heurdata->varpossmemsize = nvars;
    175 heurdata->nupdatedvars = 0;
    176
    177 /* init variable event processing data */
    178 for( v = 0; v < nvars; ++v )
    179 {
    180 assert(SCIPvarIsActive(vars[v]));
    181 assert(SCIPvarGetProbindex(vars[v]) == v);
    182
    183 /* set up variable events to catch bound changes */
    184 SCIP_CALL( SCIPcatchVarEvent(scip, vars[v], EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, &(heurdata->varfilterposs[v])) );
    185 assert(heurdata->varfilterposs[v] >= 0);
    186
    187 heurdata->varposs[v] = -1;
    188 heurdata->updatedvars[v] = NULL;
    189 heurdata->currentlbs[v] = SCIP_INVALID;
    190 heurdata->currentubs[v] = SCIP_INVALID;
    191 }
    192 }
    193 else
    194 {
    195 SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesdown, newsize) );
    196 SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowinfinitiesup, newsize) );
    197 SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowmeans, newsize) );
    198 SCIP_CALL( SCIPreallocBufferArray(scip, &heurdata->rowvariances, newsize) );
    199 }
    200
    201 /* loop over extended arrays and invalidate data to trigger initialization of this row when necessary */
    202 for( r = heurdata->memsize; r < newsize; ++r )
    203 {
    204 heurdata->rowmeans[r] = SCIP_INVALID;
    205 heurdata->rowvariances[r] = SCIP_INVALID;
    206 heurdata->rowinfinitiesdown[r] = 0;
    207 heurdata->rowinfinitiesup[r] = 0;
    208 }
    209
    210 /* adjust memsize */
    211 heurdata->memsize = newsize;
    212
    213 return SCIP_OKAY;
    214}
    215
    216/** update the variables current lower and upper bound */
    217static
    219 SCIP* scip, /**< SCIP data structure */
    220 SCIP_HEURDATA* heurdata, /**< heuristic data */
    221 SCIP_VAR* var /**< the variable to update current bounds */
    222 )
    223{
    224 int varindex;
    225 SCIP_Real lblocal;
    226 SCIP_Real ublocal;
    227
    228 assert(var != NULL);
    229
    230 varindex = SCIPvarGetProbindex(var);
    231 assert(0 <= varindex && varindex < heurdata->varpossmemsize);
    232 lblocal = SCIPvarGetLbLocal(var);
    233 ublocal = SCIPvarGetUbLocal(var);
    234
    235 assert(SCIPisFeasLE(scip, lblocal, ublocal));
    236
    237 heurdata->currentlbs[varindex] = lblocal;
    238 heurdata->currentubs[varindex] = ublocal;
    239}
    240
    241/** calculates the initial mean and variance of the row activity normal distribution.
    242 *
    243 * The mean value \f$ \mu \f$ is given by \f$ \mu = \sum_i=1^n c_i * (lb_i +ub_i) / 2 \f$ where
    244 * \f$n \f$ is the number of variables, and \f$ c_i, lb_i, ub_i \f$ are the variable coefficient and
    245 * bounds, respectively. With the same notation, the variance \f$ \sigma^2 \f$ is given by
    246 * \f$ \sigma^2 = \sum_i=1^n c_i^2 * \sigma^2_i \f$, with the variance being
    247 * \f$ \sigma^2_i = ((ub_i - lb_i + 1)^2 - 1) / 12 \f$ for integer variables and
    248 * \f$ \sigma^2_i = (ub_i - lb_i)^2 / 12 \f$ for continuous variables.
    249 */
    250static
    252 SCIP* scip, /**< SCIP data structure */
    253 SCIP_HEURDATA* heurdata, /**< the heuristic rule data */
    254 SCIP_ROW* row, /**< the row for which the gaussian normal distribution has to be calculated */
    255 SCIP_Real* mu, /**< pointer to store the mean value of the gaussian normal distribution */
    256 SCIP_Real* sigma2, /**< pointer to store the variance value of the gaussian normal distribution */
    257 int* rowinfinitiesdown, /**< pointer to store the number of variables with infinite bounds to DECREASE activity */
    258 int* rowinfinitiesup /**< pointer to store the number of variables with infinite bounds to INCREASE activity */
    259 )
    260{
    261 SCIP_COL** rowcols;
    262 SCIP_Real* rowvals;
    263 int nrowvals;
    264 int c;
    265
    266 assert(scip != NULL);
    267 assert(row != NULL);
    268 assert(mu != NULL);
    269 assert(sigma2 != NULL);
    270 assert(rowinfinitiesup != NULL);
    271 assert(rowinfinitiesdown != NULL);
    272
    273 rowcols = SCIProwGetCols(row);
    274 rowvals = SCIProwGetVals(row);
    275 nrowvals = SCIProwGetNNonz(row);
    276
    277 assert(nrowvals == 0 || rowcols != NULL);
    278 assert(nrowvals == 0 || rowvals != NULL);
    279
    280 *mu = SCIProwGetConstant(row);
    281 *sigma2 = 0.0;
    282 *rowinfinitiesdown = 0;
    283 *rowinfinitiesup = 0;
    284
    285 /* loop over nonzero row coefficients and sum up the variable contributions to mu and sigma2 */
    286 for( c = 0; c < nrowvals; ++c )
    287 {
    288 SCIP_VAR* colvar;
    289 SCIP_Real colval;
    290 SCIP_Real colvarlb;
    291 SCIP_Real colvarub;
    292 SCIP_Real squarecoeff;
    293 SCIP_Real varvariance;
    294 SCIP_Real varmean;
    295 int varindex;
    296
    297 assert(rowcols[c] != NULL);
    298 colvar = SCIPcolGetVar(rowcols[c]);
    299 assert(colvar != NULL);
    300
    301 colval = rowvals[c];
    302 colvarlb = SCIPvarGetLbLocal(colvar);
    303 colvarub = SCIPvarGetUbLocal(colvar);
    304
    305 varmean = 0.0;
    306 varvariance = 0.0;
    307 varindex = SCIPvarGetProbindex(colvar);
    308 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) == (heurdata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
    309
    310 /* variable bounds need to be watched from now on */
    311 if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
    312 heurdataUpdateCurrentBounds(scip, heurdata, colvar);
    313
    314 assert(!SCIPisInfinity(scip, colvarlb));
    315 assert(!SCIPisInfinity(scip, -colvarub));
    316 assert(SCIPisFeasLE(scip, colvarlb, colvarub));
    317
    318 /* variables with infinite bounds are skipped for the calculation of the variance; they need to
    319 * be accounted for by the counters for infinite row activity decrease and increase and they
    320 * are used to shift the row activity mean in case they have one nonzero, but finite bound */
    321 if( SCIPisInfinity(scip, -colvarlb) || SCIPisInfinity(scip, colvarub) )
    322 {
    323 if( SCIPisInfinity(scip, colvarub) )
    324 {
    325 /* an infinite upper bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
    326 * positive or negative, resp.
    327 */
    328 if( colval < 0.0 )
    329 ++(*rowinfinitiesdown);
    330 else
    331 ++(*rowinfinitiesup);
    332 }
    333
    334 /* an infinite lower bound gives the row an infinite maximum activity or minimum activity, if the coefficient is
    335 * negative or positive, resp.
    336 */
    337 if( SCIPisInfinity(scip, -colvarlb) )
    338 {
    339 if( colval > 0.0 )
    340 ++(*rowinfinitiesdown);
    341 else
    342 ++(*rowinfinitiesup);
    343 }
    344 }
    345 SCIPvarCalcDistributionParameters(scip, colvarlb, colvarub, SCIPvarGetType(colvar), SCIPvarGetImplType(colvar),
    346 &varmean, &varvariance);
    347
    348 /* actual values are updated; the contribution of the variable to mu is the arithmetic mean of its bounds */
    349 *mu += colval * varmean;
    350
    351 /* 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 */
    352 squarecoeff = SQR(colval);
    353 *sigma2 += squarecoeff * varvariance;
    354
    355 assert(!SCIPisFeasNegative(scip, *sigma2));
    356 }
    357
    359 SCIPdebugMsg(scip, " Row %s has a mean value of %g at a sigma2 of %g \n", SCIProwGetName(row), *mu, *sigma2);
    360}
    361
    362/** calculate the branching score of a variable, depending on the chosen score parameter */
    363static
    365 SCIP* scip, /**< current SCIP */
    366 SCIP_HEURDATA* heurdata, /**< branch rule data */
    367 SCIP_VAR* var, /**< candidate variable */
    368 SCIP_Real lpsolval, /**< current fractional LP-relaxation solution value */
    369 SCIP_Real* upscore, /**< pointer to store the variable score when branching on it in upward direction */
    370 SCIP_Real* downscore, /**< pointer to store the variable score when branching on it in downward direction */
    371 char scoreparam /**< the score parameter of this heuristic */
    372 )
    373{
    374 SCIP_COL* varcol;
    375 SCIP_ROW** colrows;
    376 SCIP_Real* rowvals;
    377 SCIP_Real varlb;
    378 SCIP_Real varub;
    379 SCIP_Real squaredbounddiff; /* current squared difference of variable bounds (ub - lb)^2 */
    380 SCIP_Real newub; /* new upper bound if branching downwards */
    381 SCIP_Real newlb; /* new lower bound if branching upwards */
    382 SCIP_Real squaredbounddiffup; /* squared difference after branching upwards (ub - lb')^2 */
    383 SCIP_Real squaredbounddiffdown; /* squared difference after branching downwards (ub' - lb)^2 */
    384 SCIP_Real currentmean; /* current mean value of variable uniform distribution */
    385 SCIP_Real meanup; /* mean value of variable uniform distribution after branching up */
    386 SCIP_Real meandown; /* mean value of variable uniform distribution after branching down*/
    387 SCIP_VARTYPE vartype;
    388 SCIP_IMPLINTTYPE impltype;
    389 int ncolrows;
    390 int i;
    391
    392 assert(scip != NULL);
    393 assert(var != NULL);
    394 assert(upscore != NULL);
    395 assert(downscore != NULL);
    396 assert(!SCIPisIntegral(scip, lpsolval) || SCIPvarIsBinary(var));
    398
    399 varcol = SCIPvarGetCol(var);
    400 assert(varcol != NULL);
    401
    402 colrows = SCIPcolGetRows(varcol);
    403 rowvals = SCIPcolGetVals(varcol);
    404 ncolrows = SCIPcolGetNNonz(varcol);
    405 varlb = SCIPvarGetLbLocal(var);
    406 varub = SCIPvarGetUbLocal(var);
    407 assert(varub - varlb > 0.5);
    408 vartype = SCIPvarGetType(var);
    409 impltype = SCIPvarGetImplType(var);
    410
    411 /* calculate mean and variance of variable uniform distribution before and after branching */
    412 currentmean = 0.0;
    413 squaredbounddiff = 0.0;
    414 SCIPvarCalcDistributionParameters(scip, varlb, varub, vartype, impltype, &currentmean, &squaredbounddiff);
    415
    416 /* unfixed binary variables may have an integer solution value in the LP solution, eg, at the presence of indicator constraints */
    417 if( !SCIPvarIsBinary(var) )
    418 {
    419 newlb = SCIPfeasCeil(scip, lpsolval);
    420 newub = SCIPfeasFloor(scip, lpsolval);
    421 }
    422 else
    423 {
    424 newlb = 1.0;
    425 newub = 0.0;
    426 }
    427
    428 /* calculate the variable's uniform distribution after branching up and down, respectively. */
    429 squaredbounddiffup = 0.0;
    430 meanup = 0.0;
    431 SCIPvarCalcDistributionParameters(scip, newlb, varub, vartype, impltype, &meanup, &squaredbounddiffup);
    432
    433 /* calculate the distribution mean and variance for a variable with finite lower bound */
    434 squaredbounddiffdown = 0.0;
    435 meandown = 0.0;
    436 SCIPvarCalcDistributionParameters(scip, varlb, newub, vartype, impltype, &meandown, &squaredbounddiffdown);
    437
    438 /* initialize the variable's up and down score */
    439 *upscore = 0.0;
    440 *downscore = 0.0;
    441
    442 /* loop over the variable rows and calculate the up and down score */
    443 for( i = 0; i < ncolrows; ++i )
    444 {
    445 SCIP_ROW* row;
    446 SCIP_Real changedrowmean;
    447 SCIP_Real rowmean;
    448 SCIP_Real rowvariance;
    449 SCIP_Real changedrowvariance;
    450 SCIP_Real currentrowprob;
    451 SCIP_Real newrowprobup;
    452 SCIP_Real newrowprobdown;
    453 SCIP_Real squaredcoeff;
    454 SCIP_Real rowval;
    455 int rowinfinitiesdown;
    456 int rowinfinitiesup;
    457 int rowpos;
    458
    459 row = colrows[i];
    460 rowval = rowvals[i];
    461 assert(row != NULL);
    462
    463 /* we access the rows by their index */
    464 rowpos = SCIProwGetIndex(row);
    465
    466 /* TODO add possibility to skip non-active rows by setting a user parameter */
    467 /* if( SCIPisSumPositive(scip, SCIPgetRowLPFeasibility(scip, row)) )
    468 continue;
    469 */
    470
    471 /* call method to ensure sufficient data capacity */
    472 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
    473
    474 /* calculate row activity distribution if this is the first candidate to appear in this row */
    475 if( heurdata->rowmeans[rowpos] == SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
    476 {
    477 rowCalculateGauss(scip, heurdata, row, &heurdata->rowmeans[rowpos], &heurdata->rowvariances[rowpos],
    478 &heurdata->rowinfinitiesdown[rowpos], &heurdata->rowinfinitiesup[rowpos]);
    479 }
    480
    481 /* retrieve the row distribution parameters from the branch rule data */
    482 rowmean = heurdata->rowmeans[rowpos];
    483 rowvariance = heurdata->rowvariances[rowpos];
    484 rowinfinitiesdown = heurdata->rowinfinitiesdown[rowpos];
    485 rowinfinitiesup = heurdata->rowinfinitiesup[rowpos];
    486 assert(!SCIPisNegative(scip, rowvariance));
    487
    488 currentrowprob = SCIProwCalcProbability(scip, row, rowmean, rowvariance,
    489 rowinfinitiesdown, rowinfinitiesup);
    490
    491 /* get variable's current expected contribution to row activity */
    492 squaredcoeff = SQR(rowval);
    493
    494 /* first, get the probability change for the row if the variable is branched on upwards. The probability
    495 * can only be affected if the variable upper bound is finite
    496 */
    497 if( !SCIPisInfinity(scip, varub) )
    498 {
    499 int rowinftiesdownafterbranch;
    500 int rowinftiesupafterbranch;
    501
    502 /* calculate how branching would affect the row parameters */
    503 changedrowmean = rowmean + rowval * (meanup - currentmean);
    504 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffup - squaredbounddiff);
    505 changedrowvariance = MAX(0.0, changedrowvariance);
    506
    507 rowinftiesdownafterbranch = rowinfinitiesdown;
    508 rowinftiesupafterbranch = rowinfinitiesup;
    509
    510 /* account for changes of the row's infinite bound contributions */
    511 if( SCIPisInfinity(scip, -varlb) && rowval < 0.0 )
    512 rowinftiesupafterbranch--;
    513 if( SCIPisInfinity(scip, -varlb) && rowval > 0.0 )
    514 rowinftiesdownafterbranch--;
    515
    516 assert(rowinftiesupafterbranch >= 0);
    517 assert(rowinftiesdownafterbranch >= 0);
    518 newrowprobup = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
    519 rowinftiesupafterbranch);
    520 }
    521 else
    522 newrowprobup = currentrowprob;
    523
    524 /* do the same for the other branching direction */
    525 if( !SCIPisInfinity(scip, varlb) )
    526 {
    527 int rowinftiesdownafterbranch;
    528 int rowinftiesupafterbranch;
    529
    530 changedrowmean = rowmean + rowval * (meandown - currentmean);
    531 changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffdown - squaredbounddiff);
    532 changedrowvariance = MAX(0.0, changedrowvariance);
    533
    534 rowinftiesdownafterbranch = rowinfinitiesdown;
    535 rowinftiesupafterbranch = rowinfinitiesup;
    536
    537 /* account for changes of the row's infinite bound contributions */
    538 if( SCIPisInfinity(scip, varub) && rowval > 0.0 )
    539 rowinftiesupafterbranch -= 1;
    540 if( SCIPisInfinity(scip, varub) && rowval < 0.0 )
    541 rowinftiesdownafterbranch -= 1;
    542
    543 assert(rowinftiesdownafterbranch >= 0);
    544 assert(rowinftiesupafterbranch >= 0);
    545 newrowprobdown = SCIProwCalcProbability(scip, row, changedrowmean, changedrowvariance, rowinftiesdownafterbranch,
    546 rowinftiesupafterbranch);
    547 }
    548 else
    549 newrowprobdown = currentrowprob;
    550
    551 /* update the up and down score depending on the chosen scoring parameter */
    552 SCIP_CALL( SCIPupdateDistributionScore(scip, currentrowprob, newrowprobup, newrowprobdown, upscore, downscore, scoreparam) );
    553
    554 SCIPdebugMsg(scip, " Variable %s changes probability of row %s from %g to %g (branch up) or %g;\n",
    555 SCIPvarGetName(var), SCIProwGetName(row), currentrowprob, newrowprobup, newrowprobdown);
    556 SCIPdebugMsg(scip, " --> new variable score: %g (for branching up), %g (for branching down)\n",
    557 *upscore, *downscore);
    558 }
    559
    560 return SCIP_OKAY;
    561}
    562
    563/** free heuristic data */
    564static
    566 SCIP* scip, /**< SCIP data structure */
    567 SCIP_HEURDATA* heurdata /**< heuristic data */
    568 )
    569{
    570 assert(heurdata->memsize == 0 || heurdata->rowmeans != NULL);
    571 assert(heurdata->memsize >= 0);
    572
    573 if( heurdata->varpossmemsize > 0 )
    574 {
    575 SCIP_VAR** vars;
    576 int v;
    577
    578 assert(heurdata->varpossmemsize == SCIPgetNVars(scip));
    579
    580 vars = SCIPgetVars(scip);
    581 for( v = heurdata->varpossmemsize - 1; v >= 0; --v )
    582 {
    583 SCIP_VAR* var;
    584
    585 var = vars[v];
    586
    587 assert(var != NULL);
    588 assert(v == SCIPvarGetProbindex(var));
    589 SCIP_CALL( SCIPdropVarEvent(scip, var, EVENT_DISTRIBUTION, heurdata->eventhdlr, NULL, heurdata->varfilterposs[v]) );
    590 }
    591 SCIPfreeBufferArray(scip, &heurdata->currentlbs);
    592 SCIPfreeBufferArray(scip, &heurdata->currentubs);
    593 SCIPfreeBufferArray(scip, &heurdata->updatedvars);
    594 SCIPfreeBufferArray(scip, &heurdata->varposs);
    595 SCIPfreeBufferArray(scip, &heurdata->varfilterposs);
    596 }
    597
    598 if( heurdata->memsize > 0 )
    599 {
    600 SCIPfreeBufferArray(scip, &heurdata->rowvariances);
    601 SCIPfreeBufferArray(scip, &heurdata->rowmeans);
    602 SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesup);
    603 SCIPfreeBufferArray(scip, &heurdata->rowinfinitiesdown);
    604
    605 heurdata->memsize = 0;
    606 }
    607
    608 heurdata->varpossmemsize = 0;
    609 heurdata->nupdatedvars = 0;
    610
    611 return SCIP_OKAY;
    612}
    613
    614/** add variable to the bound change event queue; skipped if variable is already in there, or if variable has
    615 * no row currently watched
    616 */
    617static
    619 SCIP_HEURDATA* heurdata, /**< heuristic data */
    620 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
    621 )
    622{
    623 int varindex;
    624 int varpos;
    625
    626 assert(var != NULL);
    627
    628 varindex = SCIPvarGetProbindex(var);
    629 assert(-1 <= varindex && varindex < heurdata->varpossmemsize);
    630
    631 /* if variable is not active, it should not be watched */
    632 if( varindex == -1 )
    633 return;
    634 varpos = heurdata->varposs[varindex];
    635 assert(varpos < heurdata->nupdatedvars);
    636
    637 /* nothing to do if variable is already in the queue */
    638 if( varpos >= 0 )
    639 {
    640 assert(heurdata->updatedvars[varpos] == var);
    641
    642 return;
    643 }
    644
    645 /* if none of the variables rows was calculated yet, variable needs not to be watched */
    646 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) == (heurdata->currentubs[varindex] == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
    647
    648 /* we don't need to enqueue the variable if it hasn't been watched so far */
    649 if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 see above */
    650 return;
    651
    652 /* add the variable to the heuristic data of variables to process updates for */
    653 assert(heurdata->varpossmemsize > heurdata->nupdatedvars);
    654 varpos = heurdata->nupdatedvars;
    655 heurdata->updatedvars[varpos] = var;
    656 heurdata->varposs[varindex] = varpos;
    657 ++heurdata->nupdatedvars;
    658}
    659
    660/** returns the next unprocessed variable (last in, first out) with pending bound changes, or NULL */
    661static
    663 SCIP_HEURDATA* heurdata /**< heuristic data */
    664 )
    665{
    666 SCIP_VAR* var;
    667 int varpos;
    668 int varindex;
    669
    670 assert(heurdata->nupdatedvars >= 0);
    671
    672 /* return if no variable is currently pending */
    673 if( heurdata->nupdatedvars == 0 )
    674 return NULL;
    675
    676 varpos = heurdata->nupdatedvars - 1;
    677 var = heurdata->updatedvars[varpos];
    678 assert(var != NULL);
    679 varindex = SCIPvarGetProbindex(var);
    680 assert(0 <= varindex && varindex < heurdata->varpossmemsize);
    681 assert(varpos == heurdata->varposs[varindex]);
    682
    683 heurdata->varposs[varindex] = -1;
    684 heurdata->nupdatedvars--;
    685
    686 return var;
    687}
    688
    689/** process a variable from the queue of changed variables */
    690static
    692 SCIP* scip, /**< SCIP data structure */
    693 SCIP_HEURDATA* heurdata, /**< heuristic data */
    694 SCIP_VAR* var /**< the variable whose bound changes need to be processed */
    695 )
    696{
    697 SCIP_ROW** colrows;
    698 SCIP_COL* varcol;
    699 SCIP_Real* colvals;
    700 SCIP_Real oldmean;
    701 SCIP_Real newmean;
    702 SCIP_Real oldvariance;
    703 SCIP_Real newvariance;
    704 SCIP_Real oldlb;
    705 SCIP_Real newlb;
    706 SCIP_Real oldub;
    707 SCIP_Real newub;
    708 SCIP_VARTYPE vartype;
    709 SCIP_IMPLINTTYPE impltype;
    710 int ncolrows;
    711 int r;
    712 int varindex;
    713
    714 /* ensure that this is a probing bound change */
    715 assert(SCIPinProbing(scip));
    716
    717 assert(var != NULL);
    718 varcol = SCIPvarGetCol(var);
    719 assert(varcol != NULL);
    720 colrows = SCIPcolGetRows(varcol);
    721 colvals = SCIPcolGetVals(varcol);
    722 ncolrows = SCIPcolGetNNonz(varcol);
    723
    724 varindex = SCIPvarGetProbindex(var);
    725
    726 oldlb = heurdata->currentlbs[varindex];
    727 oldub = heurdata->currentubs[varindex];
    728
    729 /* skip update if the variable has never been subject of previously calculated row activities */
    730 assert((oldlb == SCIP_INVALID) == (oldub == SCIP_INVALID)); /*lint !e777 doesn't like comparing floats for equality */
    731 if( oldlb == SCIP_INVALID ) /*lint !e777 */
    732 return SCIP_OKAY;
    733
    734 newlb = SCIPvarGetLbLocal(var);
    735 newub = SCIPvarGetUbLocal(var);
    736
    737 /* skip update if the bound change events have cancelled out */
    738 if( SCIPisFeasEQ(scip, oldlb, newlb) && SCIPisFeasEQ(scip, oldub, newub) )
    739 return SCIP_OKAY;
    740
    741 /* calculate old and new variable distribution mean and variance */
    742 oldvariance = 0.0;
    743 newvariance = 0.0;
    744 oldmean = 0.0;
    745 newmean = 0.0;
    746 vartype = SCIPvarGetType(var);
    747 impltype = SCIPvarGetImplType(var);
    748 SCIPvarCalcDistributionParameters(scip, oldlb, oldub, vartype, impltype, &oldmean, &oldvariance);
    749 SCIPvarCalcDistributionParameters(scip, newlb, newub, vartype, impltype, &newmean, &newvariance);
    750
    751 /* loop over all rows of this variable and update activity distribution */
    752 for( r = 0; r < ncolrows; ++r )
    753 {
    754 int rowpos;
    755
    756 assert(colrows[r] != NULL);
    757 rowpos = SCIProwGetIndex(colrows[r]);
    758 assert(rowpos >= 0);
    759
    760 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, rowpos) );
    761
    762 /* only consider rows for which activity distribution was already calculated */
    763 if( heurdata->rowmeans[rowpos] != SCIP_INVALID ) /*lint !e777 doesn't like comparing floats for equality */
    764 {
    765 SCIP_Real coeff;
    766 SCIP_Real coeffsquared;
    767 assert(heurdata->rowvariances[rowpos] != SCIP_INVALID && SCIPisFeasGE(scip, heurdata->rowvariances[rowpos], 0.0)); /*lint !e777 */
    768
    769 coeff = colvals[r];
    770 coeffsquared = SQR(coeff);
    771
    772 /* update variable contribution to row activity distribution */
    773 heurdata->rowmeans[rowpos] += coeff * (newmean - oldmean);
    774 heurdata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
    775 heurdata->rowvariances[rowpos] = MAX(0.0, heurdata->rowvariances[rowpos]);
    776
    777 /* account for changes of the infinite contributions to row activities */
    778 if( coeff > 0.0 )
    779 {
    780 /* if the coefficient is positive, upper bounds affect activity up */
    781 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
    782 ++heurdata->rowinfinitiesup[rowpos];
    783 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
    784 --heurdata->rowinfinitiesup[rowpos];
    785
    786 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
    787 ++heurdata->rowinfinitiesdown[rowpos];
    788 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
    789 --heurdata->rowinfinitiesdown[rowpos];
    790 }
    791 else if( coeff < 0.0 )
    792 {
    793 if( SCIPisInfinity(scip, newub) && !SCIPisInfinity(scip, oldub) )
    794 ++heurdata->rowinfinitiesdown[rowpos];
    795 else if( !SCIPisInfinity(scip, newub) && SCIPisInfinity(scip, oldub) )
    796 --heurdata->rowinfinitiesdown[rowpos];
    797
    798 if( SCIPisInfinity(scip, newlb) && !SCIPisInfinity(scip, oldlb) )
    799 ++heurdata->rowinfinitiesup[rowpos];
    800 else if( !SCIPisInfinity(scip, newlb) && SCIPisInfinity(scip, oldlb) )
    801 --heurdata->rowinfinitiesup[rowpos];
    802 }
    803 assert(heurdata->rowinfinitiesdown[rowpos] >= 0);
    804 assert(heurdata->rowinfinitiesup[rowpos] >= 0);
    805 }
    806 }
    807
    808 /* store the new local bounds in the data */
    809 heurdataUpdateCurrentBounds(scip, heurdata, var);
    810
    811 return SCIP_OKAY;
    812}
    813
    814/** destructor of event handler to free user data (called when SCIP is exiting) */
    815static
    816SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
    817{
    818 SCIP_EVENTHDLRDATA* eventhdlrdata;
    819
    820 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    821 assert(eventhdlrdata != NULL);
    822
    823 SCIPfreeBlockMemory(scip, &eventhdlrdata);
    824 SCIPeventhdlrSetData(eventhdlr, NULL);
    825
    826 return SCIP_OKAY;
    827}
    828
    829/*
    830 * Callback methods
    831 */
    832
    833/** copy method for primal heuristic plugins (called when SCIP copies plugins) */
    834static
    835SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
    836{ /*lint --e{715}*/
    837 assert(scip != NULL);
    838 assert(heur != NULL);
    839 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    840
    841 /* call inclusion method of primal heuristic */
    843
    844 return SCIP_OKAY;
    845}
    846
    847/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
    848static
    849SCIP_DECL_HEURFREE(heurFreeDistributiondiving) /*lint --e{715}*/
    850{ /*lint --e{715}*/
    851 SCIP_HEURDATA* heurdata;
    852
    853 assert(heur != NULL);
    854 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    855 assert(scip != NULL);
    856
    857 /* free heuristic data */
    858 heurdata = SCIPheurGetData(heur);
    859 assert(heurdata != NULL);
    860 SCIPfreeBlockMemory(scip, &heurdata);
    861 SCIPheurSetData(heur, NULL);
    862
    863 return SCIP_OKAY;
    864}
    865
    866
    867/** initialization method of primal heuristic (called after problem was transformed) */
    868static
    869SCIP_DECL_HEURINIT(heurInitDistributiondiving) /*lint --e{715}*/
    870{ /*lint --e{715}*/
    871 SCIP_HEURDATA* heurdata;
    872
    873 assert(heur != NULL);
    874 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    875
    876 /* get heuristic data */
    877 heurdata = SCIPheurGetData(heur);
    878 assert(heurdata != NULL);
    879
    880 /* create working solution */
    881 SCIP_CALL( SCIPcreateSol(scip, &heurdata->sol, heur) );
    882
    883 return SCIP_OKAY;
    884}
    885
    886
    887/** deinitialization method of primal heuristic (called before transformed problem is freed) */
    888static
    889SCIP_DECL_HEUREXIT(heurExitDistributiondiving) /*lint --e{715}*/
    890{ /*lint --e{715}*/
    891 SCIP_HEURDATA* heurdata;
    892
    893 assert(heur != NULL);
    894 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    895
    896 /* get heuristic data */
    897 heurdata = SCIPheurGetData(heur);
    898 assert(heurdata != NULL);
    899
    900 /* free working solution */
    901 SCIP_CALL( SCIPfreeSol(scip, &heurdata->sol) );
    902
    903 return SCIP_OKAY;
    904}
    905
    906/** scoring callback for distribution diving. best candidate maximizes the distribution score */
    907static
    908SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
    909{ /*lint --e{715}*/
    910 SCIP_HEURDATA* heurdata;
    911 SCIP_Real upscore;
    912 SCIP_Real downscore;
    913 int varindex;
    914
    915 heurdata = SCIPheurGetData(SCIPdivesetGetHeur(diveset));
    916 assert(heurdata != NULL);
    917
    918 /* process pending bound change events */
    919 while( heurdata->nupdatedvars > 0 )
    920 {
    921 SCIP_VAR* nextvar;
    922
    923 /* pop the next variable from the queue and process its bound changes */
    924 nextvar = heurdataPopBoundChangeVar(heurdata);
    925 assert(nextvar != NULL);
    926 SCIP_CALL( varProcessBoundChanges(scip, heurdata, nextvar) );
    927 }
    928
    929 assert(cand != NULL);
    930
    931 varindex = SCIPvarGetProbindex(cand);
    932
    933 /* terminate with a penalty for inactive variables, which the plugin can currently not score
    934 * this should never happen with default settings where only LP branching candidates are iterated, but might occur
    935 * if other constraint handlers try to score an inactive variable that was (multi-)aggregated or negated
    936 */
    937 if( varindex == - 1 )
    938 {
    939 *score = -1.0;
    940 *roundup = FALSE;
    941
    942 return SCIP_OKAY;
    943 }
    944
    945 /* in debug mode, ensure that all bound process events which occurred in the mean time have been captured
    946 * by the heuristic event system
    947 */
    949 assert(0 <= varindex && varindex < heurdata->varpossmemsize);
    950
    951 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) == (heurdata->currentubs[varindex] == SCIP_INVALID));/*lint !e777 doesn't like comparing floats for equality */
    952 assert((heurdata->currentlbs[varindex] == SCIP_INVALID) || SCIPisFeasEQ(scip, SCIPvarGetLbLocal(cand), heurdata->currentlbs[varindex])); /*lint !e777 */
    953 assert((heurdata->currentubs[varindex] == SCIP_INVALID) || SCIPisFeasEQ(scip, SCIPvarGetUbLocal(cand), heurdata->currentubs[varindex])); /*lint !e777 */
    954
    955 /* if the heuristic has not captured the variable bounds yet, this can be done now */
    956 if( heurdata->currentlbs[varindex] == SCIP_INVALID ) /*lint !e777 */
    957 heurdataUpdateCurrentBounds(scip, heurdata, cand);
    958
    959 upscore = 0.0;
    960 downscore = 0.0;
    961
    962 /* loop over candidate rows and determine the candidate up- and down- branching score w.r.t. the score parameter */
    963 SCIP_CALL( calcBranchScore(scip, heurdata, cand, candsol, &upscore, &downscore, heurdata->score) );
    964
    965 /* score is simply the maximum of the two individual scores */
    966 *roundup = (upscore > downscore);
    967 *score = MAX(upscore, downscore);
    968
    969 return SCIP_OKAY;
    970}
    971
    972
    973/** execution method of primal heuristic */
    974static
    975SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
    976{ /*lint --e{715}*/
    977 SCIP_HEURDATA* heurdata;
    978 SCIP_DIVESET* diveset;
    979 int nlprows;
    980
    981 assert(heur != NULL);
    982 assert(strcmp(SCIPheurGetName(heur), HEUR_NAME) == 0);
    983 assert(scip != NULL);
    984 assert(result != NULL);
    985 assert(SCIPhasCurrentNodeLP(scip));
    986
    987 *result = SCIP_DIDNOTRUN;
    988
    989 /* get heuristic's data */
    990 heurdata = SCIPheurGetData(heur);
    991 assert(heurdata != NULL);
    992 nlprows = SCIPgetNLPRows(scip);
    993 if( nlprows == 0 )
    994 return SCIP_OKAY;
    995
    996 /* terminate if there are no integer variables (note that, e.g., SOS1 variables may be present) */
    998 return SCIP_OKAY;
    999
    1000 /* select and store the scoring parameter for this call of the heuristic */
    1001 if( heurdata->scoreparam == 'r' )
    1002 heurdata->score = SCOREPARAM_VALUES[SCIPheurGetNCalls(heur) % SCOREPARAM_VALUESLEN];
    1003 else
    1004 heurdata->score = heurdata->scoreparam;
    1005
    1006 SCIP_CALL( heurdataEnsureArraySize(scip, heurdata, nlprows) );
    1007 assert(SCIPheurGetNDivesets(heur) > 0);
    1008 assert(SCIPheurGetDivesets(heur) != NULL);
    1009 diveset = SCIPheurGetDivesets(heur)[0];
    1010 assert(diveset != NULL);
    1011
    1012 SCIP_CALL( SCIPperformGenericDivingAlgorithm(scip, diveset, heurdata->sol, heur, result, nodeinfeasible, -1L, -1, -1.0, SCIP_DIVECONTEXT_SINGLE) );
    1013
    1014 SCIP_CALL( heurdataFreeArrays(scip, heurdata) );
    1015
    1016 return SCIP_OKAY;
    1017}
    1018
    1019/** event execution method of distribution branching which handles bound change events of variables */
    1020static
    1021SCIP_DECL_EVENTEXEC(eventExecDistribution)
    1022{
    1023 SCIP_HEURDATA* heurdata;
    1024 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1025 SCIP_VAR* var;
    1026
    1027 assert(eventhdlr != NULL);
    1028 eventhdlrdata = SCIPeventhdlrGetData(eventhdlr);
    1029 assert(eventhdlrdata != NULL);
    1030
    1031 heurdata = eventhdlrdata->heurdata;
    1032 var = SCIPeventGetVar(event);
    1033
    1034 /* add the variable to the queue of unprocessed variables; method itself ensures that every variable is added at most once */
    1035 heurdataAddBoundChangeVar(heurdata, var);
    1036
    1037 return SCIP_OKAY;
    1038}
    1039
    1040/*
    1041 * heuristic specific interface methods
    1042 */
    1043
    1044#define divesetAvailableDistributiondiving NULL
    1045
    1046/** creates the distributiondiving heuristic and includes it in SCIP */
    1048 SCIP* scip /**< SCIP data structure */
    1049 )
    1050{
    1051 SCIP_HEURDATA* heurdata;
    1052 SCIP_HEUR* heur;
    1053 SCIP_EVENTHDLRDATA* eventhdlrdata;
    1054
    1055 /* create distributiondiving data */
    1056 heurdata = NULL;
    1057 SCIP_CALL( SCIPallocBlockMemory(scip, &heurdata) );
    1058
    1059 heurdata->memsize = 0;
    1060 heurdata->rowmeans = NULL;
    1061 heurdata->rowvariances = NULL;
    1062 heurdata->rowinfinitiesdown = NULL;
    1063 heurdata->rowinfinitiesup = NULL;
    1064 heurdata->varfilterposs = NULL;
    1065 heurdata->currentlbs = NULL;
    1066 heurdata->currentubs = NULL;
    1067
    1068 /* create event handler first to finish heuristic data */
    1069 eventhdlrdata = NULL;
    1070 SCIP_CALL( SCIPallocBlockMemory(scip, &eventhdlrdata) );
    1071 eventhdlrdata->heurdata = heurdata;
    1072
    1073 heurdata->eventhdlr = NULL;
    1075 "event handler for dynamic acitivity distribution updating",
    1076 eventExecDistribution, eventhdlrdata) );
    1077 assert( heurdata->eventhdlr != NULL);
    1078 SCIP_CALL( SCIPsetEventhdlrFree(scip, heurdata->eventhdlr, eventFreeDistributiondiving) );
    1079
    1080 /* include primal heuristic */
    1083 HEUR_MAXDEPTH, HEUR_TIMING, HEUR_USESSUBSCIP, heurExecDistributiondiving, heurdata) );
    1084
    1085 assert(heur != NULL);
    1086
    1087 /* primal heuristic is safe to use in exact solving mode */
    1088 SCIPheurMarkExact(heur);
    1089
    1090 /* set non-NULL pointers to callback methods */
    1091 SCIP_CALL( SCIPsetHeurCopy(scip, heur, heurCopyDistributiondiving) );
    1092 SCIP_CALL( SCIPsetHeurFree(scip, heur, heurFreeDistributiondiving) );
    1093 SCIP_CALL( SCIPsetHeurInit(scip, heur, heurInitDistributiondiving) );
    1094 SCIP_CALL( SCIPsetHeurExit(scip, heur, heurExitDistributiondiving) );
    1095
    1096 /* add diveset with the defined scoring function */
    1102 divesetGetScoreDistributiondiving, divesetAvailableDistributiondiving) );
    1103
    1104 SCIP_CALL( SCIPaddCharParam(scip, "heuristics/" HEUR_NAME "/scoreparam",
    1105 "the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p., 'v'otes lowest c.p., votes highest c.p.('w'), 'r'evolving",
    1106 &heurdata->scoreparam, TRUE, DEFAULT_SCOREPARAM, "lvdhwr", NULL, NULL) );
    1107
    1108 return SCIP_OKAY;
    1109}
    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_Real
    Definition: def.h:156
    #define SQR(x)
    Definition: def.h:199
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #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_STAGE SCIPgetStage(SCIP *scip)
    Definition: scip_general.c:444
    int SCIPgetNContVars(SCIP *scip)
    Definition: scip_prob.c:2569
    int SCIPgetNVars(SCIP *scip)
    Definition: scip_prob.c:2246
    SCIP_VAR ** SCIPgetVars(SCIP *scip)
    Definition: scip_prob.c:2201
    int SCIPgetNContImplVars(SCIP *scip)
    Definition: scip_prob.c:2522
    #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 SCIPincludeHeurDistributiondiving(SCIP *scip)
    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 SCIPcreateDiveset(SCIP *scip, SCIP_DIVESET **diveset, SCIP_HEUR *heur, const char *name, SCIP_Real minreldepth, SCIP_Real maxreldepth, SCIP_Real maxlpiterquot, SCIP_Real maxdiveubquot, SCIP_Real maxdiveavgquot, SCIP_Real maxdiveubquotnosol, SCIP_Real maxdiveavgquotnosol, SCIP_Real lpresolvedomchgquot, int lpsolvefreq, int maxlpiterofs, unsigned int initialseed, SCIP_Bool backtrack, SCIP_Bool onlylpbranchcands, SCIP_Bool ispublic, SCIP_Bool specificsos1score, SCIP_DECL_DIVESETGETSCORE((*divesetgetscore)), SCIP_DECL_DIVESETAVAILABLE((*divesetavailable)))
    Definition: scip_heur.c:323
    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
    SCIP_RETCODE SCIPsetHeurCopy(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURCOPY((*heurcopy)))
    Definition: scip_heur.c:167
    SCIP_HEURDATA * SCIPheurGetData(SCIP_HEUR *heur)
    Definition: heur.c:1368
    SCIP_RETCODE SCIPincludeHeurBasic(SCIP *scip, SCIP_HEUR **heur, const char *name, const char *desc, char dispchar, int priority, int freq, int freqofs, int maxdepth, SCIP_HEURTIMING timingmask, SCIP_Bool usessubscip, SCIP_DECL_HEUREXEC((*heurexec)), SCIP_HEURDATA *heurdata)
    Definition: scip_heur.c:122
    SCIP_RETCODE SCIPsetHeurFree(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURFREE((*heurfree)))
    Definition: scip_heur.c:183
    SCIP_RETCODE SCIPsetHeurExit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEUREXIT((*heurexit)))
    Definition: scip_heur.c:215
    SCIP_Longint SCIPheurGetNCalls(SCIP_HEUR *heur)
    Definition: heur.c:1593
    int SCIPheurGetNDivesets(SCIP_HEUR *heur)
    Definition: heur.c:1675
    void SCIPheurMarkExact(SCIP_HEUR *heur)
    Definition: heur.c:1457
    SCIP_RETCODE SCIPsetHeurInit(SCIP *scip, SCIP_HEUR *heur, SCIP_DECL_HEURINIT((*heurinit)))
    Definition: scip_heur.c:199
    const char * SCIPheurGetName(SCIP_HEUR *heur)
    Definition: heur.c:1467
    SCIP_DIVESET ** SCIPheurGetDivesets(SCIP_HEUR *heur)
    Definition: heur.c:1665
    void SCIPheurSetData(SCIP_HEUR *heur, SCIP_HEURDATA *heurdata)
    Definition: heur.c:1378
    SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
    Definition: scip_lp.c:87
    int SCIPgetNLPRows(SCIP *scip)
    Definition: scip_lp.c:632
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPreallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:128
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Bool SCIPinProbing(SCIP *scip)
    Definition: scip_probing.c:98
    int SCIProwGetNNonz(SCIP_ROW *row)
    Definition: lp.c:17607
    SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
    Definition: lp.c:17632
    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 SCIProwGetConstant(SCIP_ROW *row)
    Definition: lp.c:17652
    SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
    Definition: lp.c:17642
    SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
    Definition: scip_sol.c:516
    SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
    Definition: scip_sol.c:1252
    SCIP_RETCODE SCIPperformGenericDivingAlgorithm(SCIP *scip, SCIP_DIVESET *diveset, SCIP_SOL *worksol, SCIP_HEUR *heur, SCIP_RESULT *result, SCIP_Bool nodeinfeasible, SCIP_Longint iterlim, int nodelimit, SCIP_Real lpresolvedomchgquot, SCIP_DIVECONTEXT divecontext)
    Definition: heuristics.c:221
    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_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
    Definition: var.c:23683
    SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
    Definition: var.c:23642
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23478
    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 SCIPvarGetLbLocal(SCIP_VAR *var)
    Definition: var.c:24234
    SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
    Definition: var.c:23463
    SCIP_HEUR * SCIPdivesetGetHeur(SCIP_DIVESET *diveset)
    Definition: heur.c:416
    #define DEFAULT_ONLYLPBRANCHCANDS
    #define DEFAULT_MAXDIVEUBQUOT
    #define divesetAvailableDistributiondiving
    #define DEFAULT_SCOREPARAM
    #define DEFAULT_LPRESOLVEDOMCHGQUOT
    static SCIP_DECL_EVENTFREE(eventFreeDistributiondiving)
    #define EVENT_DISTRIBUTION
    #define HEUR_TIMING
    #define SCOREPARAM_VALUES
    static SCIP_DECL_EVENTEXEC(eventExecDistribution)
    #define DEFAULT_MAXLPITERQUOT
    #define HEUR_FREQOFS
    static SCIP_RETCODE calcBranchScore(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var, SCIP_Real lpsolval, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
    static void rowCalculateGauss(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_ROW *row, SCIP_Real *mu, SCIP_Real *sigma2, int *rowinfinitiesdown, int *rowinfinitiesup)
    #define HEUR_DESC
    #define SCOREPARAM_VALUESLEN
    static SCIP_DECL_HEURCOPY(heurCopyDistributiondiving)
    static void heurdataUpdateCurrentBounds(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
    #define DEFAULT_MAXDIVEAVGQUOT
    #define DEFAULT_LPSOLVEFREQ
    static SCIP_RETCODE varProcessBoundChanges(SCIP *scip, SCIP_HEURDATA *heurdata, SCIP_VAR *var)
    static SCIP_VAR * heurdataPopBoundChangeVar(SCIP_HEURDATA *heurdata)
    #define DEFAULT_BACKTRACK
    #define DEFAULT_MAXDIVEUBQUOTNOSOL
    #define HEUR_DISPCHAR
    #define HEUR_MAXDEPTH
    #define HEUR_PRIORITY
    #define DEFAULT_MAXRELDEPTH
    #define DEFAULT_MAXLPITEROFS
    static SCIP_RETCODE heurdataEnsureArraySize(SCIP *scip, SCIP_HEURDATA *heurdata, int maxindex)
    #define DEFAULT_MAXDIVEAVGQUOTNOSOL
    #define HEUR_NAME
    static SCIP_DECL_DIVESETGETSCORE(divesetGetScoreDistributiondiving)
    static SCIP_RETCODE heurdataFreeArrays(SCIP *scip, SCIP_HEURDATA *heurdata)
    static SCIP_DECL_HEURINIT(heurInitDistributiondiving)
    static SCIP_DECL_HEUREXIT(heurExitDistributiondiving)
    #define DEFAULT_RANDSEED
    #define DIVESET_DIVETYPES
    static SCIP_DECL_HEURFREE(heurFreeDistributiondiving)
    static void heurdataAddBoundChangeVar(SCIP_HEURDATA *heurdata, SCIP_VAR *var)
    #define DIVESET_ISPUBLIC
    #define HEUR_FREQ
    #define DEFAULT_MINRELDEPTH
    #define HEUR_USESSUBSCIP
    #define EVENTHDLR_NAME
    static SCIP_DECL_HEUREXEC(heurExecDistributiondiving)
    Diving heuristic that chooses fixings w.r.t. changes in the solution density after Pryor and Chinneck...
    methods commonly used by primal heuristics
    memory allocation routines
    public methods for managing events
    public methods for primal heuristics
    public methods for LP management
    public methods for message output
    #define SCIPdebug(x)
    Definition: pub_message.h:93
    public methods for problem variables
    public methods for event handler plugins and event handlers
    general public methods
    public methods for primal heuristic plugins and divesets
    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 global and local (sub)problems
    public methods for the probing mode
    public methods for solutions
    SCIP_SOL * sol
    Definition: struct_heur.h:71
    struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
    Definition: type_event.h:160
    struct SCIP_HeurData SCIP_HEURDATA
    Definition: type_heur.h:77
    @ SCIP_DIVECONTEXT_SINGLE
    Definition: type_heur.h:69
    @ SCIP_DIDNOTRUN
    Definition: type_result.h:42
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    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_VARSTATUS_COLUMN
    Definition: type_var.h:53
    enum SCIP_Vartype SCIP_VARTYPE
    Definition: type_var.h:73