SCIP

    Solving Constraint Integer Programs

    history.c
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the program and library */
    4/* SCIP --- Solving Constraint Integer Programs */
    5/* */
    6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file history.c
    26 * @ingroup OTHER_CFILES
    27 * @brief methods for branching and inference history
    28 * @author Tobias Achterberg
    29 */
    30
    31/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    32
    33#include <assert.h>
    34
    35#include "scip/def.h"
    36#include "scip/set.h"
    37#include "scip/history.h"
    38#include "scip/pub_misc.h"
    39#include "scip/pub_history.h"
    40#include "scip/pub_message.h"
    41
    42#ifndef NDEBUG
    43#include "scip/struct_history.h"
    44#endif
    45
    46/*
    47 * methods for branching and inference history
    48 */
    49
    50/** creates an empty history entry */
    52 SCIP_HISTORY** history, /**< pointer to store branching and inference history */
    53 BMS_BLKMEM* blkmem /**< block memory */
    54 )
    55{
    56 assert(history != NULL);
    57
    58 SCIP_ALLOC( BMSallocBlockMemory(blkmem, history) );
    59
    60 SCIPhistoryReset(*history);
    61
    62 return SCIP_OKAY;
    63}
    64
    65/** frees a history entry */
    67 SCIP_HISTORY** history, /**< pointer to branching and inference history */
    68 BMS_BLKMEM* blkmem /**< block memory */
    69 )
    70{
    71 assert(history != NULL);
    72 assert(*history != NULL);
    73
    74 BMSfreeBlockMemory(blkmem, history);
    75}
    76
    77/** resets history entry to zero */
    79 SCIP_HISTORY* history /**< branching and inference history */
    80 )
    81{
    82 assert(history != NULL);
    83
    84 history->pscostcount[0] = 0.0;
    85 history->pscostcount[1] = 0.0;
    86 history->pscostweightedmean[0] = 0.0;
    87 history->pscostweightedmean[1] = 0.0;
    88 history->pscostvariance[0] = 0.0;
    89 history->pscostvariance[1] = 0.0;
    90 history->ancpscostcount[0] = 0.0;
    91 history->ancpscostcount[1] = 0.0;
    92 history->ancpscostweightedmean[0] = 0.0;
    93 history->ancpscostweightedmean[1] = 0.0;
    94 history->vsids[0] = 0.0;
    95 history->vsids[1] = 0.0;
    96 history->conflengthsum[0] = 0.0;
    97 history->conflengthsum[1] = 0.0;
    98 history->inferencesum[0] = 0.0;
    99 history->inferencesum[1] = 0.0;
    100 history->cutoffsum[0] = 0.0;
    101 history->cutoffsum[1] = 0.0;
    102 history->ratio = 0.0;
    103 history->ratiovalid = FALSE;
    104 history->balance = 0.0;
    105 history->ngmi = 0;
    106 history->gmieff = 0.0;
    107 history->gmieffsum = 0.0;
    108 history->nactiveconflicts[0] = 0;
    109 history->nactiveconflicts[1] = 0;
    110 history->nbranchings[0] = 0;
    111 history->nbranchings[1] = 0;
    112 history->branchdepthsum[0] = 0;
    113 history->branchdepthsum[1] = 0;
    114}
    115
    116/** unites two history entries by adding the values of the second one to the first one */
    118 SCIP_HISTORY* history, /**< branching and inference history */
    119 SCIP_HISTORY* addhistory, /**< history values to add to history */
    120 SCIP_Bool switcheddirs /**< should the history entries be united with switched directories */
    121 )
    122{
    123 int i;
    124
    125 assert(history != NULL);
    126 assert(addhistory != NULL);
    127
    128 /* loop over both directions and combine the statistics */
    129 for( i = 0; i <= 1; ++i )
    130 {
    131 int d;
    132 d = (switcheddirs ? 1 - i : i);
    133
    134 history->pscostcount[i] += addhistory->pscostcount[d];
    135 history->ancpscostcount[i] += addhistory->ancpscostcount[d];
    136
    137 /* if both histories a count of zero, there is nothing to do */
    138 if( history->pscostcount[i] > 0.0 )
    139 {
    140 SCIP_Real oldmean;
    141
    142 oldmean = history->pscostweightedmean[i];
    143
    144 /* we update the mean as if the history was one observation with a large weight */
    145 history->pscostweightedmean[i] += addhistory->pscostcount[d] * (addhistory->pscostweightedmean[d] - history->pscostweightedmean[i]) / history->pscostcount[i];
    146
    147 /* we update the variance of two sets A and B as S_A+B = S_A + (mu_A)^2 * count_A ...*/
    148 /* @todo is there a numerically more stable variant for this merge? */
    149 history->pscostvariance[i] = history->pscostvariance[i] + oldmean * oldmean * (history->pscostcount[i] - addhistory->pscostcount[d]) + \
    150 /* S_B + (mu_B)^2 * count_B */
    151 addhistory->pscostvariance[d] + addhistory->pscostcount[d] * addhistory->pscostweightedmean[d] * addhistory->pscostweightedmean[d] - \
    152 /* - count_A+B * mu_A+B^ 2 */
    153 history->pscostcount[i] * history->pscostweightedmean[i] * history->pscostweightedmean[i];
    154
    155 /* slight violations of nonnegativity are numerically possible */
    156 history->pscostvariance[i] = MAX(history->pscostvariance[i], 0.0);
    157 }
    158#ifndef NDEBUG
    159 else
    160 {
    161 assert(history->pscostweightedmean[i] == 0.0);
    162 assert(history->pscostvariance[i] == 0.0);
    163 }
    164#endif
    165 /* if both histories a discounted count of zero, there is nothing to do */
    166 if( history->ancpscostcount[i] > 0.0 )
    167 {
    168 /* we update the mean as if the history was one observation with a large weight */
    169 history->ancpscostweightedmean[i] += addhistory->ancpscostcount[d] * (addhistory->ancpscostweightedmean[d] - history->ancpscostweightedmean[i]) / history->ancpscostcount[i];
    170 }
    171#ifndef NDEBUG
    172 else
    173 {
    174 assert(history->ancpscostweightedmean[i] == 0.0);
    175 }
    176#endif
    177
    178 history->vsids[i] += addhistory->vsids[d];
    179 history->conflengthsum[i] += addhistory->conflengthsum[d];
    180 history->inferencesum[i] += addhistory->inferencesum[d];
    181 history->cutoffsum[i] += addhistory->cutoffsum[d];
    182 history->nactiveconflicts[i] += addhistory->nactiveconflicts[d];
    183 history->nbranchings[i] += addhistory->nbranchings[d];
    184 history->branchdepthsum[i] += addhistory->branchdepthsum[d];
    185 }
    186}
    187
    188/** updates the pseudo costs for a change of "solvaldelta" in the variable's LP solution value and a change of "objdelta"
    189 * in the LP's objective value
    190 */
    192 SCIP_HISTORY* history, /**< branching and inference history */
    193 SCIP_SET* set, /**< global SCIP settings */
    194 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
    195 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
    196 SCIP_Real weight /**< weight of this update in pseudo cost sum (added to pscostcount) */
    197 )
    198{
    199 SCIP_Real distance;
    201 SCIP_Real sumcontribution;
    202 SCIP_Real olddelta;
    203 int dir;
    204
    205 assert(history != NULL);
    206 assert(set != NULL);
    207 assert(!SCIPsetIsInfinity(set, REALABS(solvaldelta)));
    208 assert(!SCIPsetIsInfinity(set, objdelta));
    209 assert(!SCIPsetIsNegative(set, objdelta));
    210 assert(0.0 < weight && weight <= 1.0);
    211
    212 if( SCIPsetIsPositive(set, solvaldelta) )
    213 {
    214 /* variable's solution value moved upwards */
    215 dir = 1;
    216 distance = solvaldelta;
    217 }
    218 else if( SCIPsetIsNegative(set, solvaldelta) )
    219 {
    220 /* variable's solution value moved downwards */
    221 dir = 0;
    222 distance = -solvaldelta;
    223 }
    224 else
    225 {
    226 /* the variable's solution value didn't change, and the pseudo costs cannot be updated */
    227 return;
    228 }
    229 assert(dir == 0 || dir == 1);
    230 assert(SCIPsetIsPositive(set, distance));
    231
    232 /* apply a lower limit on the distance to avoid numerical instabilities due to very large summands */
    234 distance = MAX(distance, eps);
    235
    236 /* slightly increase objective delta, s.t. pseudo cost values are not zero, and fractionalities are
    237 * always used at least a bit
    238 */
    239 objdelta += SCIPsetPseudocostdelta(set);
    240
    241 sumcontribution = objdelta/distance;
    242 /* update the pseudo cost values */
    243 olddelta = sumcontribution - history->pscostweightedmean[dir];
    244 history->pscostcount[dir] += weight;
    245 history->pscostweightedmean[dir] += weight * olddelta / history->pscostcount[dir];
    246 history->pscostvariance[dir] = history->pscostvariance[dir] + weight * olddelta * (sumcontribution - history->pscostweightedmean[dir]);
    247
    248 SCIPsetDebugMsg(set, "updated pseudo costs of history %p: dir=%d, distance=%g, objdelta=%g, weight=%g -> %g/%g\n",
    249 (void*)history, dir, distance, objdelta, weight, history->pscostcount[dir], history->pscostweightedmean[dir]);
    250}
    251
    252/** updates the ancestral pseudo costs for a change of "solvaldelta" in the variable's LP solution value and a change of "objdelta"
    253 * in the LP's objective value
    254 */
    256 SCIP_HISTORY* history, /**< branching and inference history */
    257 SCIP_SET* set, /**< global SCIP settings */
    258 SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
    259 SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
    260 SCIP_Real weight /**< weight of this update in discounted pseudo cost sum (added to pscostcount) */
    261 )
    262{
    263 SCIP_Real distance;
    265 SCIP_Real sumcontribution;
    266 SCIP_Real olddelta;
    267 int dir;
    268
    269 assert(history != NULL);
    270 assert(set != NULL);
    271 assert(!SCIPsetIsInfinity(set, REALABS(solvaldelta)));
    272 assert(!SCIPsetIsInfinity(set, objdelta));
    273 assert(!SCIPsetIsNegative(set, objdelta));
    274 assert(0.0 < weight && weight <= 1.0);
    275
    276 if( SCIPsetIsPositive(set, solvaldelta) )
    277 {
    278 /* variable's solution value moved upwards */
    279 dir = 1;
    280 distance = solvaldelta;
    281 }
    282 else if( SCIPsetIsNegative(set, solvaldelta) )
    283 {
    284 /* variable's solution value moved downwards */
    285 dir = 0;
    286 distance = -solvaldelta;
    287 }
    288 else
    289 {
    290 /* the variable's solution value didn't change, and the pseudo costs cannot be updated */
    291 return;
    292 }
    293 assert(dir == 0 || dir == 1);
    294 assert(SCIPsetIsPositive(set, distance));
    295
    296 /* apply a lower limit on the distance to avoid numerical instabilities due to very large summands */
    298 distance = MAX(distance, eps);
    299
    300 /* slightly increase objective delta, s.t. discounted pseudo cost values are not zero, and fractionalities are
    301 * always used at least a bit
    302 */
    303 objdelta += SCIPsetPseudocostdelta(set);
    304
    305 sumcontribution = objdelta/distance;
    306 /* update the pseudo cost values */
    307 olddelta = sumcontribution - history->ancpscostweightedmean[dir];
    308 history->ancpscostcount[dir] += weight;
    309 history->ancpscostweightedmean[dir] += weight * olddelta / history->ancpscostcount[dir];
    310
    311 SCIPsetDebugMsg(set, "updated ancestor pseudo costs of history %p: dir=%d, distance=%g, objdelta=%g, weight=%g -> %g/%g\n",
    312 (void*)history, dir, distance, objdelta, weight, history->ancpscostcount[dir], history->ancpscostweightedmean[dir]);
    313}
    314
    315/**@name Value based history
    316 *
    317 * Value based history methods
    318 *
    319 * @{
    320 */
    321
    322/** creates an empty value history */
    324 SCIP_VALUEHISTORY** valuehistory, /**< pointer to store the value based branching and inference histories */
    325 BMS_BLKMEM* blkmem /**< block memory */
    326 )
    327{
    328 assert(valuehistory != NULL);
    329
    330 SCIP_ALLOC( BMSallocBlockMemory(blkmem, valuehistory) );
    331
    332 (*valuehistory)->nvalues = 0;
    333 (*valuehistory)->sizevalues = 5;
    334
    335 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*valuehistory)->histories, (*valuehistory)->sizevalues) );
    336 SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*valuehistory)->values, (*valuehistory)->sizevalues) );
    337
    338 return SCIP_OKAY;
    339}
    340
    341/** frees a value history */
    343 SCIP_VALUEHISTORY** valuehistory, /**< pointer to value based history */
    344 BMS_BLKMEM* blkmem /**< block memory */
    345 )
    346{
    347 assert(valuehistory != NULL);
    348
    349 if( *valuehistory != NULL )
    350 {
    351 int i;
    352
    353 for( i = (*valuehistory)->nvalues-1; i >= 0; --i )
    354 SCIPhistoryFree(&(*valuehistory)->histories[i], blkmem);
    355
    356 BMSfreeBlockMemoryArray(blkmem, &(*valuehistory)->histories, (*valuehistory)->sizevalues);
    357 BMSfreeBlockMemoryArray(blkmem, &(*valuehistory)->values, (*valuehistory)->sizevalues);
    358
    359 BMSfreeBlockMemory(blkmem, valuehistory);
    360 }
    361}
    362
    363/** finds for the given domain value the history if it does not exist yet it will be created */
    365 SCIP_VALUEHISTORY* valuehistory, /**< value based history */
    366 BMS_BLKMEM* blkmem, /**< block memory */
    367 SCIP_SET* set, /**< global SCIP settings */
    368 SCIP_Real value, /**< domain value of interest */
    369 SCIP_HISTORY** history /**< pointer to store the history for the given domain value */
    370 )
    371{
    372 int pos;
    373
    374 assert(valuehistory != NULL);
    375 assert(blkmem != NULL);
    376 assert(set != NULL);
    377 assert(history != NULL);
    378
    379 *history = NULL;
    380
    381 if( valuehistory->nvalues == 0 || !SCIPsortedvecFindReal(valuehistory->values, value, valuehistory->nvalues, &pos) )
    382 {
    383 /* check if we need to resize the history array */
    384 if( valuehistory->nvalues == valuehistory->sizevalues )
    385 {
    386 int newsize;
    387
    388 newsize = SCIPsetCalcMemGrowSize(set, valuehistory->sizevalues + 1);
    389 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &valuehistory->histories, valuehistory->nvalues, newsize) );
    390 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &valuehistory->values, valuehistory->nvalues, newsize) );
    391 valuehistory->sizevalues = newsize;
    392 }
    393
    394 /* create new empty history entry */
    395 SCIP_CALL( SCIPhistoryCreate(history, blkmem) );
    396
    397 /* insert new history into the value based history array */
    398 SCIPsortedvecInsertRealPtr(valuehistory->values, (void**)valuehistory->histories, value, (void*)(*history), &valuehistory->nvalues, NULL);
    399 }
    400 else
    401 (*history) = valuehistory->histories[pos]; /*lint !e530*/
    402
    403 assert(*history != NULL);
    404
    405 return SCIP_OKAY;
    406}
    407
    408/** scales the conflict score values with the given scalar for each value history entry */
    410 SCIP_VALUEHISTORY* valuehistory, /**< value based history */
    411 SCIP_Real scalar /**< scalar to multiply the conflict scores with */
    412 )
    413{
    414 if( valuehistory != NULL )
    415 {
    416 int i;
    417
    418 for( i = valuehistory->nvalues-1; i >= 0; --i )
    419 {
    420 SCIPhistoryScaleVSIDS(valuehistory->histories[i], scalar);
    421 }
    422 }
    423}
    424
    425
    426/*
    427 * simple functions implemented as defines
    428 */
    429
    430#ifdef NDEBUG
    431
    432/* In debug mode, the following methods are implemented as function calls to ensure
    433 * type validity.
    434 * In optimized mode, the methods are implemented as defines to improve performance.
    435 * However, we want to have them in the library anyways, so we have to undef the defines.
    436 */
    437
    438#undef SCIPvaluehistoryGetNValues
    439#undef SCIPvaluehistoryGetHistories
    440#undef SCIPvaluehistoryGetValues
    441
    442#endif
    443
    444/** return the number of (domain) values for which a history exists */
    446 SCIP_VALUEHISTORY* valuehistory /**< value based history */
    447 )
    448{
    449 assert(valuehistory != NULL);
    450
    451 return valuehistory->nvalues;
    452}
    453
    454/** return the array containing the histories for the individual (domain) values */
    456 SCIP_VALUEHISTORY* valuehistory /**< value based history */
    457 )
    458{
    459 assert(valuehistory != NULL);
    460
    461 return valuehistory->histories;
    462}
    463
    464/** return the array containing the (domain) values for which a history exists */
    466 SCIP_VALUEHISTORY* valuehistory /**< value based history */
    467 )
    468{
    469 assert(valuehistory != NULL);
    470
    471 return valuehistory->values;
    472}
    473
    474/**@} */
    475
    476/*
    477 * simple functions implemented as defines
    478 */
    479
    480#ifdef NDEBUG
    481
    482/* In debug mode, the following methods are implemented as function calls to ensure
    483 * type validity.
    484 * In optimized mode, the methods are implemented as defines to improve performance.
    485 * However, we want to have them in the library anyways, so we have to undef the defines.
    486 */
    487
    488#undef SCIPbranchdirOpposite
    489#undef SCIPhistoryGetPseudocost
    490#undef SCIPhistoryGetPseudocostCount
    491#undef SCIPhistoryIsPseudocostEmpty
    492#undef SCIPhistoryGetAncPseudocost
    493#undef SCIPhistoryGetAncPseudocostCount
    494#undef SCIPhistoryIsAncPseudocostEmpty
    495#undef SCIPhistoryIncVSIDS
    496#undef SCIPhistoryScaleVSIDS
    497#undef SCIPhistoryGetVSIDS
    498#undef SCIPhistoryIncNActiveConflicts
    499#undef SCIPhistoryGetNActiveConflicts
    500#undef SCIPhistoryGetAvgConflictlength
    501#undef SCIPhistoryIncNBranchings
    502#undef SCIPhistoryIncInferenceSum
    503#undef SCIPhistoryIncCutoffSum
    504#undef SCIPhistoryGetNBranchings
    505#undef SCIPhistoryGetInferenceSum
    506#undef SCIPhistoryGetAvgInferences
    507#undef SCIPhistoryGetCutoffSum
    508#undef SCIPhistoryGetAvgCutoffs
    509#undef SCIPhistoryGetAvgBranchdepth
    510#undef SCIPhistoryIsRatioValid
    511#undef SCIPhistoryGetLastRatio
    512#undef SCIPhistorySetRatioHistory
    513#undef SCIPhistoryGetLastBalance
    514#undef SCIPhistorySetLastGMIeff
    515#undef SCIPhistoryGetLastGMIeff
    516#undef SCIPhistoryIncGMIeffSum
    517#undef SCIPhistoryGetAvgGMIeff
    518#undef SCIPhistoryGetPseudocostVariance
    519
    520#endif
    521
    522/** returns the opposite direction of the given branching direction */
    524 SCIP_BRANCHDIR dir /**< branching direction */
    525 )
    526{
    529}
    530
    531/** returns the expected dual gain for moving the corresponding variable by "solvaldelta" */
    533 SCIP_HISTORY* history, /**< branching and inference history */
    534 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
    535 )
    536{
    537 assert(history != NULL);
    538
    539 if( solvaldelta >= 0.0 )
    540 return solvaldelta * (history->pscostcount[1] > 0.0 ? history->pscostweightedmean[1] : 1.0);
    541 else
    542 return -solvaldelta * (history->pscostcount[0] > 0.0 ? history->pscostweightedmean[0] : 1.0);
    543}
    544
    545/** returns the expected ancestral dual gain for moving the corresponding variable by "solvaldelta" */
    547 SCIP_HISTORY* history, /**< branching and inference history */
    548 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
    549 )
    550{
    551 assert(history != NULL);
    552
    553 if( solvaldelta >= 0.0 )
    554 return solvaldelta * (history->ancpscostcount[1] > 0.0 ? history->ancpscostweightedmean[1] : 1.0);
    555 else
    556 return -solvaldelta * (history->ancpscostcount[0] > 0.0 ? history->ancpscostweightedmean[0] : 1.0);
    557}
    558
    559/** returns the variance of pseudo costs about the mean. */
    561 SCIP_HISTORY* history, /**< branching and inference history */
    562 SCIP_BRANCHDIR direction /**< direction of variable: 1 for upwards history, 0 for downwards history */
    563 )
    564{
    565 int dir;
    566 SCIP_Real correctionfactor;
    567
    568 assert(history != NULL);
    569 assert(direction == SCIP_BRANCHDIR_UPWARDS || direction == SCIP_BRANCHDIR_DOWNWARDS);
    570
    571 dir = (direction == SCIP_BRANCHDIR_UPWARDS ? 1 : 0);
    572 correctionfactor = history->pscostcount[dir] - 1.0;
    573
    574 /** @todo for an unbiased estimate of the weighted sample variance, we need a correction factor that uses the sum of squared weights */
    575 if( correctionfactor > 0.9 )
    576 return history->pscostvariance[dir] / correctionfactor;
    577 else
    578 return 0.0;
    579}
    580
    581/** returns the (possible fractional) number of (partial) pseudo cost updates performed on this pseudo cost entry in
    582 * the given branching direction
    583 */
    585 SCIP_HISTORY* history, /**< branching and inference history */
    586 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    587 )
    588{
    589 assert(history != NULL);
    590 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    591 assert((int)dir == 0 || (int)dir == 1);
    592
    593 return history->pscostcount[dir];
    594}
    595
    596/** returns the (possible fractional) number of (partial) ancestral pseudo cost updates performed on this pseudo cost entry in
    597 * the given branching direction
    598 */
    600 SCIP_HISTORY* history, /**< branching and inference history */
    601 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    602 )
    603{
    604 assert(history != NULL);
    605 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    606 assert((int)dir == 0 || (int)dir == 1);
    607
    608 return history->ancpscostcount[dir];
    609}
    610
    611/** returns whether the pseudo cost entry is empty in the given branching direction (whether no value was added yet) */
    613 SCIP_HISTORY* history, /**< branching and inference history */
    614 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    615 )
    616{
    617 assert(history != NULL);
    618 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    619 assert((int)dir == 0 || (int)dir == 1);
    620
    621 return (history->pscostcount[dir] == 0.0);
    622}
    623
    624/** returns whether the ancestral pseudo cost entry is empty in the given branching direction (whether no value was added yet) */
    626 SCIP_HISTORY* history, /**< branching and inference history */
    627 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    628 )
    629{
    630 assert(history != NULL);
    631 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    632 assert((int)dir == 0 || (int)dir == 1);
    633
    634 return (history->ancpscostcount[dir] == 0.0);
    635}
    636
    637/** increases the conflict score of the history entry by the given weight */
    639 SCIP_HISTORY* history, /**< branching and inference history */
    640 SCIP_BRANCHDIR dir, /**< branching direction */
    641 SCIP_Real weight /**< weight of this update in conflict score */
    642 )
    643{
    644 assert(history != NULL);
    645 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    646 assert((int)dir == 0 || (int)dir == 1);
    647
    648 history->vsids[dir] += weight;
    649}
    650
    651/** scales the conflict score values with the given scalar */
    653 SCIP_HISTORY* history, /**< branching and inference history */
    654 SCIP_Real scalar /**< scalar to multiply the conflict scores with */
    655 )
    656{
    657 assert(history != NULL);
    658
    659 history->vsids[0] *= scalar;
    660 history->vsids[1] *= scalar;
    661}
    662
    663/** gets the conflict score of the history entry */
    665 SCIP_HISTORY* history, /**< branching and inference history */
    666 SCIP_BRANCHDIR dir /**< branching direction */
    667 )
    668{
    669 assert(history != NULL);
    670 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    671 assert((int)dir == 0 || (int)dir == 1);
    672
    673 return history->vsids[dir];
    674}
    675
    676/** increases the number of active conflicts by one and the overall length of the history entry by the given weight */
    678 SCIP_HISTORY* history, /**< branching and inference history */
    679 SCIP_BRANCHDIR dir, /**< branching direction */
    680 SCIP_Real length /**< length of the conflict */
    681 )
    682{
    683 assert(history != NULL);
    684 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    685 assert((int)dir == 0 || (int)dir == 1);
    686 assert(length >= 0.0);
    687
    688 history->nactiveconflicts[dir]++;
    689 history->conflengthsum[dir] += length;
    690}
    691
    692/** gets the number of active conflicts of the history entry */
    694 SCIP_HISTORY* history, /**< branching and inference history */
    695 SCIP_BRANCHDIR dir /**< branching direction */
    696 )
    697{
    698 assert(history != NULL);
    699 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    700 assert((int)dir == 0 || (int)dir == 1);
    701
    702 return history->nactiveconflicts[dir];
    703}
    704
    705/** gets the average conflict length of the history entry */
    707 SCIP_HISTORY* history, /**< branching and inference history */
    708 SCIP_BRANCHDIR dir /**< branching direction */
    709 )
    710{
    711 assert(history != NULL);
    712 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    713 assert((int)dir == 0 || (int)dir == 1);
    714
    715 return history->conflengthsum[dir] > 0.0 ? (SCIP_Real)history->nactiveconflicts[dir]/(SCIP_Real)history->conflengthsum[dir] : 0.0;
    716}
    717
    718/** increases the number of branchings counter */
    720 SCIP_HISTORY* history, /**< branching and inference history */
    721 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
    722 int depth /**< depth at which the bound change took place */
    723 )
    724{
    725 assert(history != NULL);
    726 assert(depth >= 1);
    727 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    728 assert((int)dir == 0 || (int)dir == 1);
    729
    730 history->nbranchings[dir]++;
    731 history->branchdepthsum[dir] += depth;
    732}
    733
    734/** increases the number of inferences counter by a certain value */
    736 SCIP_HISTORY* history, /**< branching and inference history */
    737 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
    738 SCIP_Real weight /**< weight of this update in inference score */
    739 )
    740{
    741 assert(history != NULL);
    742 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    743 assert((int)dir == 0 || (int)dir == 1);
    744 assert(history->nbranchings[dir] >= 1);
    745 assert(weight >= 0.0);
    746
    747 history->inferencesum[dir] += weight;
    748}
    749
    750/** increases the number of cutoffs counter */
    752 SCIP_HISTORY* history, /**< branching and inference history */
    753 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
    754 SCIP_Real weight /**< weight of this update in cutoff score */
    755 )
    756{
    757 assert(history != NULL);
    758 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    759 assert((int)dir == 0 || (int)dir == 1);
    760 assert(history->nbranchings[dir] >= 1);
    761 assert(weight >= 0.0);
    762
    763 history->cutoffsum[dir] += weight;
    764}
    765
    766/** get number of branchings counter */
    768 SCIP_HISTORY* history, /**< branching and inference history */
    769 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    770 )
    771{
    772 assert(history != NULL);
    773 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    774 assert((int)dir == 0 || (int)dir == 1);
    775
    776 return history->nbranchings[dir];
    777}
    778
    779/** get number of inferences counter */
    781 SCIP_HISTORY* history, /**< branching and inference history */
    782 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    783 )
    784{
    785 assert(history != NULL);
    786 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    787 assert((int)dir == 0 || (int)dir == 1);
    788
    789 return history->inferencesum[dir];
    790}
    791
    792/** returns the average number of inferences per branching */
    794 SCIP_HISTORY* history, /**< branching and inference history */
    795 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    796 )
    797{
    798 assert(history != NULL);
    799 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    800 assert((int)dir == 0 || (int)dir == 1);
    801
    802 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->inferencesum[dir]/(SCIP_Real)history->nbranchings[dir] : 0.0;
    803}
    804
    805/** get number of cutoffs counter */
    807 SCIP_HISTORY* history, /**< branching and inference history */
    808 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    809 )
    810{
    811 assert(history != NULL);
    812 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    813 assert((int)dir == 0 || (int)dir == 1);
    814
    815 return history->cutoffsum[dir];
    816}
    817
    818/** returns the average number of cutoffs per branching */
    820 SCIP_HISTORY* history, /**< branching and inference history */
    821 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    822 )
    823{
    824 assert(history != NULL);
    825 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    826 assert((int)dir == 0 || (int)dir == 1);
    827
    828 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->cutoffsum[dir]/(SCIP_Real)history->nbranchings[dir] : 0.0;
    829}
    830
    831/** returns the average depth of bound changes due to branching */
    833 SCIP_HISTORY* history, /**< branching and inference history */
    834 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    835 )
    836{
    837 assert(history != NULL);
    838 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    839 assert((int)dir == 0 || (int)dir == 1);
    840
    841 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->branchdepthsum[dir]/(SCIP_Real)history->nbranchings[dir] : 1.0;
    842}
    843
    844/** returns true if the given history contains a valid ratio */
    846 SCIP_HISTORY* history /**< branching and inference history */
    847 )
    848{
    849 assert(history != NULL);
    850
    851 return history->ratiovalid;
    852}
    853
    854/** returns the most recent ratio computed given the variable history */
    856 SCIP_HISTORY* history /**< branching and inference history */
    857 )
    858{
    859 assert(history != NULL);
    860 assert(history->ratiovalid);
    861
    862 return history->ratio;
    863}
    864
    865/** returns the most recent value of r/l used to compute this variable's ratio */
    867 SCIP_HISTORY* history /**< branching and inference history */
    868 )
    869{
    870 assert(history != NULL);
    871 assert(history->ratiovalid);
    872
    873 return history->balance;
    874}
    875
    876/** returns the average efficacy value for the GMI cut produced by this variable */
    878 SCIP_HISTORY* history /**< branching and inference history */
    879 )
    880{
    881 assert(history != NULL);
    882
    883 return history->ngmi > 0 ? history->gmieffsum / history->ngmi : 0.0;
    884}
    885
    886/** increases the average efficacy value for the GMI cut produced by this variable */
    888 SCIP_HISTORY* history, /**< branching and inference history */
    889 SCIP_Real gmieff /**< normalized efficacy value of a cut which will increase gmieff */
    890 )
    891{
    892 assert(history != NULL);
    893 assert(gmieff >= 0.0);
    894
    895 history->gmieffsum += gmieff;
    896 history->ngmi += 1;
    897}
    898
    899/** returns the most recent efficacy value for the GMI cut produced by this variable */
    901 SCIP_HISTORY* history /**< branching and inference history */
    902 )
    903{
    904 assert(history != NULL);
    905
    906 return history->gmieff;
    907}
    908
    909/** sets the new most recent efficacy value for the GMI cut produced by this variable */
    911 SCIP_HISTORY* history, /**< branching and inference history */
    912 SCIP_Real gmieff /**< Efficacy of GMI cut produced from simplex tableau row of this var */
    913 )
    914{
    915 assert(history != NULL);
    916
    917 history->gmieff = gmieff;
    918}
    919
    920/** sets the ratio history for a particular variable */
    922 SCIP_HISTORY* history, /**< branching and inference history */
    923 SCIP_Bool valid, /**< True iff the ratio computed is valid */
    924 SCIP_Real ratio, /**< Ratio of the characteristic polynomial with gains (1, rightgain/leftgain) */
    925 SCIP_Real balance /**< The value of rightgain/leftgain */
    926 )
    927{
    928 assert(history != NULL);
    929
    930 history->ratiovalid = valid;
    931 history->ratio = ratio;
    932 history->balance = balance;
    933}
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:257
    #define SCIP_Longint
    Definition: def.h:150
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_ALLOC(x)
    Definition: def.h:375
    #define SCIP_Real
    Definition: def.h:165
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    SCIP_Bool SCIPsortedvecFindReal(SCIP_Real *realarray, SCIP_Real val, int len, int *pos)
    void SCIPsortedvecInsertRealPtr(SCIP_Real *realarray, void **ptrarray, SCIP_Real keyval, void *field1val, int *len, int *pos)
    int SCIPvaluehistoryGetNValues(SCIP_VALUEHISTORY *valuehistory)
    Definition: history.c:445
    SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
    Definition: history.c:323
    SCIP_HISTORY ** SCIPvaluehistoryGetHistories(SCIP_VALUEHISTORY *valuehistory)
    Definition: history.c:455
    SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
    Definition: history.c:364
    SCIP_Real * SCIPvaluehistoryGetValues(SCIP_VALUEHISTORY *valuehistory)
    Definition: history.c:465
    void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
    Definition: history.c:342
    void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
    Definition: history.c:409
    void SCIPhistoryReset(SCIP_HISTORY *history)
    Definition: history.c:78
    SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
    Definition: history.c:532
    SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:793
    void SCIPhistorySetRatioHistory(SCIP_HISTORY *history, SCIP_Bool valid, SCIP_Real ratio, SCIP_Real balance)
    Definition: history.c:921
    SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:693
    SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:767
    SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:706
    SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:819
    SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
    Definition: history.c:51
    SCIP_Real SCIPhistoryGetAncPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:599
    void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
    Definition: history.c:910
    void SCIPhistoryUpdateAncPseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
    Definition: history.c:255
    SCIP_Real SCIPhistoryGetLastRatio(SCIP_HISTORY *history)
    Definition: history.c:855
    void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:735
    SCIP_Real SCIPhistoryGetAncPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
    Definition: history.c:546
    SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:806
    SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:584
    SCIP_Bool SCIPhistoryIsPseudocostEmpty(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:612
    SCIP_Bool SCIPhistoryIsAncPseudocostEmpty(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:625
    SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
    Definition: history.c:560
    void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
    Definition: history.c:677
    void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
    Definition: history.c:652
    void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:751
    void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
    Definition: history.c:719
    void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
    Definition: history.c:191
    SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:664
    SCIP_Bool SCIPhistoryIsRatioValid(SCIP_HISTORY *history)
    Definition: history.c:845
    SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:832
    SCIP_Real SCIPhistoryGetLastBalance(SCIP_HISTORY *history)
    Definition: history.c:866
    SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
    Definition: history.c:900
    SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
    Definition: history.c:877
    SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:780
    void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
    Definition: history.c:66
    void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
    Definition: history.c:117
    void SCIPhistoryIncGMIeffSum(SCIP_HISTORY *history, SCIP_Real gmieff)
    Definition: history.c:887
    SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
    Definition: history.c:523
    void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:638
    internal methods for branching and inference history
    #define BMSfreeBlockMemory(mem, ptr)
    Definition: memory.h:465
    #define BMSallocBlockMemory(mem, ptr)
    Definition: memory.h:451
    #define BMSallocBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:454
    #define BMSfreeBlockMemoryArray(mem, ptr, num)
    Definition: memory.h:467
    #define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
    Definition: memory.h:458
    struct BMS_BlkMem BMS_BLKMEM
    Definition: memory.h:437
    real eps
    public methods for branching and inference history structure
    public methods for message output
    public data structures and miscellaneous methods
    SCIP_Real SCIPsetPseudocosteps(SCIP_SET *set)
    Definition: set.c:6466
    SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6654
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6521
    SCIP_Real SCIPsetPseudocostdelta(SCIP_SET *set)
    Definition: set.c:6476
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6086
    SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6665
    internal methods for global SCIP settings
    #define SCIPsetDebugMsg
    Definition: set.h:1811
    SCIP_Real ancpscostcount[2]
    SCIP_Longint nbranchings[2]
    SCIP_Real pscostweightedmean[2]
    SCIP_Longint nactiveconflicts[2]
    SCIP_Bool ratiovalid
    SCIP_Real pscostvariance[2]
    SCIP_Real vsids[2]
    SCIP_Real pscostcount[2]
    SCIP_Real ratio
    SCIP_Real cutoffsum[2]
    SCIP_Real ngmi
    SCIP_Real inferencesum[2]
    SCIP_Real balance
    SCIP_Real gmieff
    SCIP_Real conflengthsum[2]
    SCIP_Real ancpscostweightedmean[2]
    SCIP_Real gmieffsum
    SCIP_Longint branchdepthsum[2]
    SCIP_Real * values
    SCIP_HISTORY ** histories
    datastructures for branching and inference history
    Definition: heur_padm.c:132
    @ 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_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63