Scippy

    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-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 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#ifndef 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/** return the number of (domain) values for which a history exists */
    444 SCIP_VALUEHISTORY* valuehistory /**< value based history */
    445 )
    446{
    447 assert(valuehistory != NULL);
    448
    449 return valuehistory->nvalues;
    450}
    451
    452/** return the array containing the histories for the individual (domain) values */
    454 SCIP_VALUEHISTORY* valuehistory /**< value based history */
    455 )
    456{
    457 assert(valuehistory != NULL);
    458
    459 return valuehistory->histories;
    460}
    461
    462/** return the array containing the (domain) values for which a history exists */
    464 SCIP_VALUEHISTORY* valuehistory /**< value based history */
    465 )
    466{
    467 assert(valuehistory != NULL);
    468
    469 return valuehistory->values;
    470}
    471
    472#endif
    473
    474/**@} */
    475
    476/*
    477 * simple functions implemented as defines
    478 */
    479
    480#ifndef 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
    519/** returns the opposite direction of the given branching direction */
    521 SCIP_BRANCHDIR dir /**< branching direction */
    522 )
    523{
    526}
    527
    528/** returns the expected dual gain for moving the corresponding variable by "solvaldelta" */
    530 SCIP_HISTORY* history, /**< branching and inference history */
    531 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
    532 )
    533{
    534 assert(history != NULL);
    535
    536 if( solvaldelta >= 0.0 )
    537 return solvaldelta * (history->pscostcount[1] > 0.0 ? history->pscostweightedmean[1] : 1.0);
    538 else
    539 return -solvaldelta * (history->pscostcount[0] > 0.0 ? history->pscostweightedmean[0] : 1.0);
    540}
    541
    542/** returns the expected ancestral dual gain for moving the corresponding variable by "solvaldelta" */
    544 SCIP_HISTORY* history, /**< branching and inference history */
    545 SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
    546 )
    547{
    548 assert(history != NULL);
    549
    550 if( solvaldelta >= 0.0 )
    551 return solvaldelta * (history->ancpscostcount[1] > 0.0 ? history->ancpscostweightedmean[1] : 1.0);
    552 else
    553 return -solvaldelta * (history->ancpscostcount[0] > 0.0 ? history->ancpscostweightedmean[0] : 1.0);
    554}
    555
    556/** returns the variance of pseudo costs about the mean. */
    558 SCIP_HISTORY* history, /**< branching and inference history */
    559 SCIP_BRANCHDIR direction /**< direction of variable: 1 for upwards history, 0 for downwards history */
    560 )
    561{
    562 int dir;
    563 SCIP_Real correctionfactor;
    564
    565 assert(history != NULL);
    566 assert(direction == SCIP_BRANCHDIR_UPWARDS || direction == SCIP_BRANCHDIR_DOWNWARDS);
    567
    568 dir = (direction == SCIP_BRANCHDIR_UPWARDS ? 1 : 0);
    569 correctionfactor = history->pscostcount[dir] - 1.0;
    570
    571 /** @todo for an unbiased estimate of the weighted sample variance, we need a correction factor that uses the sum of squared weights */
    572 if( correctionfactor > 0.9 )
    573 return history->pscostvariance[dir] / correctionfactor;
    574 else
    575 return 0.0;
    576}
    577
    578/** returns the (possible fractional) number of (partial) pseudo cost updates performed on this pseudo cost entry in
    579 * the given branching direction
    580 */
    582 SCIP_HISTORY* history, /**< branching and inference history */
    583 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    584 )
    585{
    586 assert(history != NULL);
    587 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    588 assert((int)dir == 0 || (int)dir == 1);
    589
    590 return history->pscostcount[dir];
    591}
    592
    593/** returns the (possible fractional) number of (partial) ancestral pseudo cost updates performed on this pseudo cost entry in
    594 * the given branching direction
    595 */
    597 SCIP_HISTORY* history, /**< branching and inference history */
    598 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    599 )
    600{
    601 assert(history != NULL);
    602 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    603 assert((int)dir == 0 || (int)dir == 1);
    604
    605 return history->ancpscostcount[dir];
    606}
    607
    608/** returns whether the pseudo cost entry is empty in the given branching direction (whether no value was added yet) */
    610 SCIP_HISTORY* history, /**< branching and inference history */
    611 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    612 )
    613{
    614 assert(history != NULL);
    615 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    616 assert((int)dir == 0 || (int)dir == 1);
    617
    618 return (history->pscostcount[dir] == 0.0);
    619}
    620
    621/** returns whether the ancestral pseudo cost entry is empty in the given branching direction (whether no value was added yet) */
    623 SCIP_HISTORY* history, /**< branching and inference history */
    624 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    625 )
    626{
    627 assert(history != NULL);
    628 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    629 assert((int)dir == 0 || (int)dir == 1);
    630
    631 return (history->ancpscostcount[dir] == 0.0);
    632}
    633
    634/** increases the conflict score of the history entry by the given weight */
    636 SCIP_HISTORY* history, /**< branching and inference history */
    637 SCIP_BRANCHDIR dir, /**< branching direction */
    638 SCIP_Real weight /**< weight of this update in conflict score */
    639 )
    640{
    641 assert(history != NULL);
    642 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    643 assert((int)dir == 0 || (int)dir == 1);
    644
    645 history->vsids[dir] += weight;
    646}
    647
    648/** scales the conflict score values with the given scalar */
    650 SCIP_HISTORY* history, /**< branching and inference history */
    651 SCIP_Real scalar /**< scalar to multiply the conflict scores with */
    652 )
    653{
    654 assert(history != NULL);
    655
    656 history->vsids[0] *= scalar;
    657 history->vsids[1] *= scalar;
    658}
    659
    660/** gets the conflict score of the history entry */
    662 SCIP_HISTORY* history, /**< branching and inference history */
    663 SCIP_BRANCHDIR dir /**< branching direction */
    664 )
    665{
    666 assert(history != NULL);
    667 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    668 assert((int)dir == 0 || (int)dir == 1);
    669
    670 return history->vsids[dir];
    671}
    672
    673/** increases the number of active conflicts by one and the overall length of the history entry by the given weight */
    675 SCIP_HISTORY* history, /**< branching and inference history */
    676 SCIP_BRANCHDIR dir, /**< branching direction */
    677 SCIP_Real length /**< length of the conflict */
    678 )
    679{
    680 assert(history != NULL);
    681 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    682 assert((int)dir == 0 || (int)dir == 1);
    683 assert(length >= 0.0);
    684
    685 history->nactiveconflicts[dir]++;
    686 history->conflengthsum[dir] += length;
    687}
    688
    689/** gets the number of active conflicts of the history entry */
    691 SCIP_HISTORY* history, /**< branching and inference history */
    692 SCIP_BRANCHDIR dir /**< branching direction */
    693 )
    694{
    695 assert(history != NULL);
    696 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    697 assert((int)dir == 0 || (int)dir == 1);
    698
    699 return history->nactiveconflicts[dir];
    700}
    701
    702/** gets the average conflict length of the history entry */
    704 SCIP_HISTORY* history, /**< branching and inference history */
    705 SCIP_BRANCHDIR dir /**< branching direction */
    706 )
    707{
    708 assert(history != NULL);
    709 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    710 assert((int)dir == 0 || (int)dir == 1);
    711
    712 return history->conflengthsum[dir] > 0.0 ? (SCIP_Real)history->nactiveconflicts[dir]/(SCIP_Real)history->conflengthsum[dir] : 0.0;
    713}
    714
    715/** increases the number of branchings counter */
    717 SCIP_HISTORY* history, /**< branching and inference history */
    718 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
    719 int depth /**< depth at which the bound change took place */
    720 )
    721{
    722 assert(history != NULL);
    723 assert(depth >= 1);
    724 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    725 assert((int)dir == 0 || (int)dir == 1);
    726
    727 history->nbranchings[dir]++;
    728 history->branchdepthsum[dir] += depth;
    729}
    730
    731/** increases the number of inferences counter by a certain value */
    733 SCIP_HISTORY* history, /**< branching and inference history */
    734 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
    735 SCIP_Real weight /**< weight of this update in inference score */
    736 )
    737{
    738 assert(history != NULL);
    739 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    740 assert((int)dir == 0 || (int)dir == 1);
    741 assert(history->nbranchings[dir] >= 1);
    742 assert(weight >= 0.0);
    743
    744 history->inferencesum[dir] += weight;
    745}
    746
    747/** increases the number of cutoffs counter */
    749 SCIP_HISTORY* history, /**< branching and inference history */
    750 SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
    751 SCIP_Real weight /**< weight of this update in cutoff score */
    752 )
    753{
    754 assert(history != NULL);
    755 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    756 assert((int)dir == 0 || (int)dir == 1);
    757 assert(history->nbranchings[dir] >= 1);
    758 assert(weight >= 0.0);
    759
    760 history->cutoffsum[dir] += weight;
    761}
    762
    763/** get number of branchings counter */
    765 SCIP_HISTORY* history, /**< branching and inference history */
    766 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    767 )
    768{
    769 assert(history != NULL);
    770 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    771 assert((int)dir == 0 || (int)dir == 1);
    772
    773 return history->nbranchings[dir];
    774}
    775
    776/** get number of inferences counter */
    778 SCIP_HISTORY* history, /**< branching and inference history */
    779 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    780 )
    781{
    782 assert(history != NULL);
    783 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    784 assert((int)dir == 0 || (int)dir == 1);
    785
    786 return history->inferencesum[dir];
    787}
    788
    789/** returns the average number of inferences per branching */
    791 SCIP_HISTORY* history, /**< branching and inference history */
    792 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    793 )
    794{
    795 assert(history != NULL);
    796 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    797 assert((int)dir == 0 || (int)dir == 1);
    798
    799 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->inferencesum[dir]/(SCIP_Real)history->nbranchings[dir] : 0.0;
    800}
    801
    802/** get number of cutoffs counter */
    804 SCIP_HISTORY* history, /**< branching and inference history */
    805 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    806 )
    807{
    808 assert(history != NULL);
    809 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    810 assert((int)dir == 0 || (int)dir == 1);
    811
    812 return history->cutoffsum[dir];
    813}
    814
    815/** returns the average number of cutoffs per branching */
    817 SCIP_HISTORY* history, /**< branching and inference history */
    818 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    819 )
    820{
    821 assert(history != NULL);
    822 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    823 assert((int)dir == 0 || (int)dir == 1);
    824
    825 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->cutoffsum[dir]/(SCIP_Real)history->nbranchings[dir] : 0.0;
    826}
    827
    828/** returns the average depth of bound changes due to branching */
    830 SCIP_HISTORY* history, /**< branching and inference history */
    831 SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
    832 )
    833{
    834 assert(history != NULL);
    835 assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
    836 assert((int)dir == 0 || (int)dir == 1);
    837
    838 return history->nbranchings[dir] > 0 ? (SCIP_Real)history->branchdepthsum[dir]/(SCIP_Real)history->nbranchings[dir] : 1.0;
    839}
    840
    841/** returns true if the given history contains a valid ratio */
    843 SCIP_HISTORY* history /**< branching and inference history */
    844 )
    845{
    846 assert(history != NULL);
    847
    848 return history->ratiovalid;
    849}
    850
    851/** returns the most recent ratio computed given the variable history */
    853 SCIP_HISTORY* history /**< branching and inference history */
    854 )
    855{
    856 assert(history != NULL);
    857 assert(history->ratiovalid);
    858
    859 return history->ratio;
    860}
    861
    862/** returns the most recent value of r/l used to compute this variable's ratio */
    864 SCIP_HISTORY* history /**< branching and inference history */
    865 )
    866{
    867 assert(history != NULL);
    868 assert(history->ratiovalid);
    869
    870 return history->balance;
    871}
    872
    873/** returns the average efficacy value for the GMI cut produced by this variable */
    875 SCIP_HISTORY* history /**< branching and inference history */
    876 )
    877{
    878 assert(history != NULL);
    879
    880 return history->ngmi > 0 ? history->gmieffsum / history->ngmi : 0.0;
    881}
    882
    883/** increases the average efficacy value for the GMI cut produced by this variable */
    885 SCIP_HISTORY* history, /**< branching and inference history */
    886 SCIP_Real gmieff /**< normalized efficacy value of a cut which will increase gmieff */
    887 )
    888{
    889 assert(history != NULL);
    890 assert(gmieff >= 0.0);
    891
    892 history->gmieffsum += gmieff;
    893 history->ngmi += 1;
    894}
    895
    896/** returns the most recent efficacy value for the GMI cut produced by this variable */
    898 SCIP_HISTORY* history /**< branching and inference history */
    899 )
    900{
    901 assert(history != NULL);
    902
    903 return history->gmieff;
    904}
    905
    906/** sets the new most recent efficacy value for the GMI cut produced by this variable */
    908 SCIP_HISTORY* history, /**< branching and inference history */
    909 SCIP_Real gmieff /**< Efficacy of GMI cut produced from simplex tableau row of this var */
    910 )
    911{
    912 assert(history != NULL);
    913
    914 history->gmieff = gmieff;
    915}
    916
    917/** sets the ratio history for a particular variable */
    919 SCIP_HISTORY* history, /**< branching and inference history */
    920 SCIP_Bool valid, /**< True iff the ratio computed is valid */
    921 SCIP_Real ratio, /**< Ratio of the characteristic polynomial with gains (1, rightgain/leftgain) */
    922 SCIP_Real balance /**< The value of rightgain/leftgain */
    923 )
    924{
    925 assert(history != NULL);
    926
    927 history->ratiovalid = valid;
    928 history->ratio = ratio;
    929 history->balance = balance;
    930}
    931
    932#endif
    common defines and data types used in all packages of SCIP
    #define NULL
    Definition: def.h:248
    #define SCIP_Longint
    Definition: def.h:141
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_ALLOC(x)
    Definition: def.h:366
    #define SCIP_Real
    Definition: def.h:156
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    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:443
    SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
    Definition: history.c:323
    SCIP_HISTORY ** SCIPvaluehistoryGetHistories(SCIP_VALUEHISTORY *valuehistory)
    Definition: history.c:453
    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:463
    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:529
    SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:790
    void SCIPhistorySetRatioHistory(SCIP_HISTORY *history, SCIP_Bool valid, SCIP_Real ratio, SCIP_Real balance)
    Definition: history.c:918
    SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:690
    SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:764
    SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:703
    SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:816
    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:596
    void SCIPhistorySetLastGMIeff(SCIP_HISTORY *history, SCIP_Real gmieff)
    Definition: history.c:907
    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:852
    void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:732
    SCIP_Real SCIPhistoryGetAncPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
    Definition: history.c:543
    SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:803
    SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:581
    SCIP_Bool SCIPhistoryIsPseudocostEmpty(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:609
    SCIP_Bool SCIPhistoryIsAncPseudocostEmpty(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:622
    SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
    Definition: history.c:557
    void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
    Definition: history.c:674
    void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
    Definition: history.c:649
    void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:748
    void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
    Definition: history.c:716
    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:661
    SCIP_Bool SCIPhistoryIsRatioValid(SCIP_HISTORY *history)
    Definition: history.c:842
    SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:829
    SCIP_Real SCIPhistoryGetLastBalance(SCIP_HISTORY *history)
    Definition: history.c:863
    SCIP_Real SCIPhistoryGetLastGMIeff(SCIP_HISTORY *history)
    Definition: history.c:897
    SCIP_Real SCIPhistoryGetAvgGMIeff(SCIP_HISTORY *history)
    Definition: history.c:874
    SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
    Definition: history.c:777
    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:884
    SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
    Definition: history.c:520
    void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
    Definition: history.c:635
    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:6460
    SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6648
    SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6515
    SCIP_Real SCIPsetPseudocostdelta(SCIP_SET *set)
    Definition: set.c:6470
    int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
    Definition: set.c:6080
    SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
    Definition: set.c:6659
    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:135
    @ 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