SCIP

    Solving Constraint Integer Programs

    expr_entropy.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 expr_entropy.c
    26 * @ingroup DEFPLUGINS_EXPR
    27 * @brief handler for -x*log(x) expressions
    28 * @author Benjamin Mueller
    29 * @author Fabian Wegscheider
    30 * @author Ksenia Bestuzheva
    31 *
    32 * @todo replace exp(-1.0) by 1.0/M_E
    33 */
    34
    35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    36
    37#include "scip/expr_entropy.h"
    38#include "scip/expr_value.h"
    39#include "scip/expr.h"
    40
    41
    42/* fundamental expression handler properties */
    43#define EXPRHDLR_NAME "entropy"
    44#define EXPRHDLR_DESC "entropy expression (-x*log(x))"
    45#define EXPRHDLR_PRECEDENCE 81000
    46#define EXPRHDLR_HASHKEY SCIPcalcFibHash(7477.0)
    47
    48/*
    49 * Data structures
    50 */
    51
    52/*
    53 * Local methods
    54 */
    55
    56/** helper function for reverseProp() which returns an x* in [xmin,xmax] s.t. the distance -x*log(x) and a given target
    57 * value is minimized; the function assumes that -x*log(x) is monotone on [xmin,xmax];
    58 */
    59static
    61 SCIP* scip, /**< SCIP data structure */
    62 SCIP_Real xmin, /**< smallest possible x */
    63 SCIP_Real xmax, /**< largest possible x */
    64 SCIP_Bool increasing, /**< -x*log(x) is increasing or decreasing on [xmin,xmax] */
    65 SCIP_Real targetval /**< target value */
    66 )
    67{
    68 SCIP_Real xminval = (xmin == 0.0) ? 0.0 : -xmin * log(xmin);
    69 SCIP_Real xmaxval = (xmax == 0.0) ? 0.0 : -xmax * log(xmax);
    70 int i;
    71
    72 assert(xmin <= xmax);
    73 assert(increasing ? xminval <= xmaxval : xminval >= xmaxval);
    74
    75 /* function can not achieve -x*log(x) -> return xmin or xmax */
    76 if( SCIPisGE(scip, xminval, targetval) && SCIPisGE(scip, xmaxval, targetval) )
    77 return increasing ? xmin : xmax;
    78 else if( SCIPisLE(scip, xminval, targetval) && SCIPisLE(scip, xmaxval, targetval) )
    79 return increasing ? xmax : xmin;
    80
    81 /* binary search */
    82 for( i = 0; i < 1000; ++i )
    83 {
    84 SCIP_Real x = (xmin + xmax) / 2.0;
    85 SCIP_Real xval = (x == 0.0) ? 0.0 : -x * log(x);
    86
    87 /* found the corresponding point -> skip */
    88 if( SCIPisEQ(scip, xval, targetval) )
    89 return x;
    90 else if( SCIPisLT(scip, xval, targetval) )
    91 {
    92 if( increasing )
    93 xmin = x;
    94 else
    95 xmax = x;
    96 }
    97 else
    98 {
    99 if( increasing )
    100 xmax = x;
    101 else
    102 xmin = x;
    103 }
    104 }
    105
    106 return SCIP_INVALID;
    107}
    108
    109/** helper function for reverse propagation; needed for proper unittest */
    110static
    112 SCIP* scip, /**< SCIP data structure */
    113 SCIP_INTERVAL exprinterval, /**< bounds on the expression */
    114 SCIP_INTERVAL childinterval, /**< bounds on the interval of the child */
    115 SCIP_INTERVAL* interval /**< resulting interval */
    116 )
    117{
    118 SCIP_INTERVAL childentropy;
    119 SCIP_INTERVAL intersection;
    120 SCIP_INTERVAL tmp;
    121 SCIP_Real childinf;
    122 SCIP_Real childsup;
    123 SCIP_Real extremum;
    124 SCIP_Real boundinf;
    125 SCIP_Real boundsup;
    126
    127 assert(scip != NULL);
    128 assert(interval != NULL);
    129
    130 /* check whether domain is empty, i.e., bounds on -x*log(x) > 1/e */
    131 if( SCIPisGT(scip, SCIPintervalGetInf(exprinterval), exp(-1.0))
    133 {
    134 SCIPintervalSetEmpty(interval);
    135 return SCIP_OKAY;
    136 }
    137
    138 /* compute the intersection between entropy([childinf,childsup]) and [expr.inf, expr.sup] */
    139 SCIPintervalEntropy(SCIP_INTERVAL_INFINITY, &childentropy, childinterval);
    140 SCIPintervalIntersect(&intersection, childentropy, exprinterval);
    141
    142 /* intersection empty -> infeasible */
    144 {
    145 SCIPintervalSetEmpty(interval);
    146 return SCIP_OKAY;
    147 }
    148
    149 /* intersection = childentropy -> nothing can be learned */
    150 if( SCIPintervalIsSubsetEQ(SCIP_INTERVAL_INFINITY, childentropy, intersection) )
    151 {
    153 SCIPintervalIntersect(interval, *interval, childinterval);
    154 return SCIP_OKAY;
    155 }
    156
    157 childinf = MAX(0.0, SCIPintervalGetInf(childinterval)); /*lint !e666*/
    158 childsup = SCIPintervalGetSup(childinterval);
    159 extremum = exp(-1.0);
    160 boundinf = SCIP_INVALID;
    161 boundsup = SCIP_INVALID;
    162
    163 /*
    164 * check whether lower bound of child can be improved
    165 */
    166 SCIPintervalSet(&tmp, childinf);
    168
    169 /* entropy(childinf) < intersection.inf -> consider [childinf, MIN(childsup, extremum)] */
    170 if( SCIPintervalGetInf(intersection) > -SCIP_INTERVAL_INFINITY && SCIPintervalGetSup(tmp) - SCIPintervalGetInf(intersection) < -SCIPepsilon(scip) )
    171 {
    172 boundinf = reversePropBinarySearch(scip, childinf, MIN(extremum, childsup), TRUE,
    173 SCIPintervalGetInf(intersection));
    174 }
    175 /* entropy(childinf) > intersection.sup -> consider [MAX(childinf,extremum), childsup] */
    176 else if( SCIPintervalGetSup(intersection) < SCIP_INTERVAL_INFINITY && SCIPintervalGetInf(tmp) - SCIPintervalGetSup(intersection) > SCIPepsilon(scip) )
    177 {
    178 boundinf = reversePropBinarySearch(scip, MAX(childinf, extremum), childsup, FALSE,
    179 SCIPintervalGetSup(intersection));
    180 }
    181 /* using a strict greater-than here because we expect a tightening because we saw an at-least-epsilon-potential above */
    182 assert(boundinf == SCIP_INVALID || boundinf > childinf); /*lint !e777*/
    183
    184 /*
    185 * check whether upper bound of child can be improved
    186 */
    187 if( childsup < SCIP_INTERVAL_INFINITY )
    188 {
    189 SCIPintervalSet(&tmp, childsup);
    191 }
    192 else
    193 SCIPintervalSetBounds(&tmp, -SCIP_INTERVAL_INFINITY, -SCIP_INTERVAL_INFINITY); /* entropy(inf) = -inf */
    194
    195 /* entropy(childsup) < intersection.inf -> consider [MAX(childinf,extremum), childsup] */
    196 if( SCIPintervalGetInf(intersection) > -SCIP_INTERVAL_INFINITY && SCIPintervalGetSup(tmp) - SCIPintervalGetInf(intersection) < -SCIPepsilon(scip) )
    197 {
    198 boundsup = reversePropBinarySearch(scip, MAX(childinf, extremum), childsup, FALSE,
    199 SCIPintervalGetInf(intersection));
    200 }
    201 /* entropy(childsup) > intersection.sup -> consider [childinf, MIN(childsup,extremum)] */
    202 else if( SCIPintervalGetSup(intersection) < SCIP_INTERVAL_INFINITY && SCIPintervalGetInf(tmp) - SCIPintervalGetSup(intersection) > SCIPepsilon(scip) )
    203 {
    204 boundsup = reversePropBinarySearch(scip, childinf, MIN(childsup, extremum), TRUE,
    205 SCIPintervalGetSup(intersection));
    206 }
    207 /* using a strict smaller-than here because we expect a tightening because we saw an at-least-epsilon-potential above */
    208 assert(boundsup == SCIP_INVALID || boundsup < childsup); /*lint !e777*/
    209
    210 if( boundinf != SCIP_INVALID ) /*lint !e777*/
    211 {
    212 childinf = MAX(childinf, boundinf);
    213 }
    214 if( boundsup != SCIP_INVALID ) /*lint !e777*/
    215 {
    216 childsup = boundsup;
    217 }
    218 assert(childinf <= childsup); /* infeasible case has been handled already */
    219
    220 /* set the resulting bounds */
    221 SCIPintervalSetBounds(interval, childinf, childsup);
    222
    223 return SCIP_OKAY;
    224}
    225
    226/*
    227 * Callback methods of expression handler
    228 */
    229
    230/** expression handler copy callback */
    231static
    233{ /*lint --e{715}*/
    235
    236 return SCIP_OKAY;
    237}
    238
    239/** simplifies an entropy expression */
    240static
    242{ /*lint --e{715}*/
    243 SCIP_EXPR* child;
    244
    245 assert(scip != NULL);
    246 assert(expr != NULL);
    247 assert(simplifiedexpr != NULL);
    248 assert(SCIPexprGetNChildren(expr) == 1);
    249
    250 child = SCIPexprGetChildren(expr)[0];
    251 assert(child != NULL);
    252
    253 /* check for value expression */
    254 if( SCIPisExprValue(scip, child) )
    255 {
    256 SCIP_Real childvalue = SCIPgetValueExprValue(child);
    257
    258 /* TODO how to handle a negative value? */
    259 assert(childvalue >= 0.0);
    260
    261 if( childvalue == 0.0 || childvalue == 1.0 )
    262 {
    263 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, 0.0, ownercreate, ownercreatedata) );
    264 }
    265 else
    266 {
    267 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, -childvalue * log(childvalue), ownercreate,
    268 ownercreatedata) );
    269 }
    270 }
    271 else
    272 {
    273 *simplifiedexpr = expr;
    274
    275 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    276 SCIPcaptureExpr(*simplifiedexpr);
    277 }
    278
    279 /* TODO handle -x*log(x) = 0 if x in {0,1} */
    280
    281 return SCIP_OKAY;
    282}
    283
    284/** expression data copy callback */
    285static
    287{ /*lint --e{715}*/
    288 assert(targetexprdata != NULL);
    289 assert(sourceexpr != NULL);
    290 assert(SCIPexprGetData(sourceexpr) == NULL);
    291
    292 *targetexprdata = NULL;
    293 return SCIP_OKAY;
    294}
    295
    296/** expression data free callback */
    297static
    299{ /*lint --e{715}*/
    300 assert(expr != NULL);
    301
    302 SCIPexprSetData(expr, NULL);
    303 return SCIP_OKAY;
    304}
    305
    306/** expression parse callback */
    307static
    309{ /*lint --e{715}*/
    310 SCIP_EXPR* childexpr;
    311
    312 assert(expr != NULL);
    313
    314 /* parse child expression from remaining string */
    315 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
    316 assert(childexpr != NULL);
    317
    318 /* create entropy expression */
    319 SCIP_CALL( SCIPcreateExprEntropy(scip, expr, childexpr, ownercreate, ownercreatedata) );
    320 assert(*expr != NULL);
    321
    322 /* release child expression since it has been captured by the entropy expression */
    323 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
    324
    325 *success = TRUE;
    326
    327 return SCIP_OKAY;
    328}
    329
    330
    331/** expression (point-) evaluation callback */
    332static
    334{ /*lint --e{715}*/
    335 SCIP_Real childvalue;
    336
    337 assert(expr != NULL);
    338 assert(SCIPexprGetData(expr) == NULL);
    339 assert(SCIPexprGetNChildren(expr) == 1);
    340 assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]) != SCIP_INVALID); /*lint !e777*/
    341
    342 childvalue = SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]);
    343
    344 if( childvalue < 0.0 )
    345 {
    346 SCIPdebugMsg(scip, "invalid evaluation of entropy expression\n");
    347 *val = SCIP_INVALID;
    348 }
    349 else if( childvalue == 0.0 || childvalue == 1.0 )
    350 {
    351 /* -x*log(x) = 0 iff x in {0,1} */
    352 *val = 0.0;
    353 }
    354 else
    355 {
    356 *val = -childvalue * log(childvalue);
    357 }
    358
    359 return SCIP_OKAY;
    360}
    361
    362/** expression derivative evaluation callback */
    363static
    365{ /*lint --e{715}*/
    366 SCIP_EXPR* child;
    367 SCIP_Real childvalue;
    368
    369 assert(expr != NULL);
    370 assert(childidx == 0);
    371 assert(SCIPexprGetNChildren(expr) == 1);
    372 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    373
    374 child = SCIPexprGetChildren(expr)[0];
    375 assert(child != NULL);
    376 assert(!SCIPisExprValue(scip, child));
    377
    378 childvalue = SCIPexprGetEvalValue(child);
    379
    380 /* derivative is not defined for x = 0 */
    381 if( childvalue <= 0.0 )
    382 *val = SCIP_INVALID;
    383 else
    384 *val = -1.0 - log(childvalue);
    385
    386 return SCIP_OKAY;
    387}
    388
    389/** expression interval evaluation callback */
    390static
    392{ /*lint --e{715}*/
    393 SCIP_INTERVAL childinterval;
    394
    395 assert(expr != NULL);
    396 assert(SCIPexprGetData(expr) == NULL);
    397 assert(SCIPexprGetNChildren(expr) == 1);
    398
    399 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    400
    401 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    402 SCIPintervalSetEmpty(interval);
    403 else
    404 SCIPintervalEntropy(SCIP_INTERVAL_INFINITY, interval, childinterval);
    405
    406 return SCIP_OKAY;
    407}
    408
    409/** expression estimator callback */
    410static
    412{ /*lint --e{715}*/
    413 assert(scip != NULL);
    414 assert(expr != NULL);
    415 assert(localbounds != NULL);
    416 assert(globalbounds != NULL);
    417 assert(refpoint != NULL);
    418 assert(coefs != NULL);
    419 assert(constant != NULL);
    420 assert(islocal != NULL);
    421 assert(branchcand != NULL);
    422 assert(*branchcand == TRUE);
    423 assert(success != NULL);
    424
    426
    427 *success = FALSE;
    428
    429 /* use secant for underestimate (locally valid) */
    430 if( !overestimate )
    431 {
    432 SCIP_Real lb;
    433 SCIP_Real ub;
    434 SCIP_Real vallb;
    435 SCIP_Real valub;
    436
    437 lb = localbounds[0].inf;
    438 ub = localbounds[0].sup;
    439
    440 if( lb < 0.0 || SCIPisInfinity(scip, ub) || SCIPisEQ(scip, lb, ub) )
    441 return SCIP_OKAY;
    442
    443 assert(lb >= 0.0 && ub >= 0.0);
    444 assert(ub - lb != 0.0);
    445
    446 vallb = (lb == 0.0) ? 0.0 : -lb * log(lb);
    447 valub = (ub == 0.0) ? 0.0 : -ub * log(ub);
    448
    449 coefs[0] = (valub - vallb) / (ub - lb);
    450 *constant = valub - coefs[0] * ub;
    451 assert(SCIPisEQ(scip, *constant, vallb - coefs[0] * lb));
    452
    453 *islocal = TRUE;
    454 }
    455 /* use gradient cut for overestimate (globally valid) */
    456 else
    457 {
    458 if( !SCIPisPositive(scip, refpoint[0]) )
    459 {
    460 /* if refpoint is 0 (then lb=0 probably) or negative, then slope is infinite (or not defined), then try to move away from 0 */
    461 if( SCIPisZero(scip, localbounds[0].sup) )
    462 return SCIP_OKAY;
    463
    464 refpoint[0] = SCIPepsilon(scip);
    465 }
    466
    467 /* -x*(1+log(x*)) + x* <= -x*log(x) */
    468 coefs[0] = -(1.0 + log(refpoint[0]));
    469 *constant = refpoint[0];
    470
    471 *islocal = FALSE;
    472 *branchcand = FALSE;
    473 }
    474
    475 /* give up if the constant or coefficient is too large */
    476 if( SCIPisInfinity(scip, REALABS(*constant)) || SCIPisInfinity(scip, REALABS(coefs[0])) )
    477 return SCIP_OKAY;
    478
    479 *success = TRUE;
    480
    481 return SCIP_OKAY;
    482}
    483
    484/** initial estimates callback */
    485static
    486SCIP_DECL_EXPRINITESTIMATES(initestimatesEntropy)
    487{ /*lint --e{715}*/
    488 SCIP_Real refpointsover[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
    489 SCIP_Bool overest[4] = {TRUE, TRUE, TRUE, FALSE};
    490 SCIP_Real lb;
    491 SCIP_Real ub;
    492 int i;
    493
    494 assert(scip != NULL);
    495 assert(expr != NULL);
    496 assert(SCIPexprGetNChildren(expr) == 1);
    497
    499
    500 lb = bounds[0].inf;
    501 ub = bounds[0].sup;
    502
    503 if( SCIPisEQ(scip, lb, ub) )
    504 return SCIP_OKAY;
    505
    506 if( overestimate )
    507 {
    508 /* adjust lb */
    509 lb = MAX(lb, SCIPepsilon(scip)); /*lint !e666*/
    510
    511 refpointsover[0] = lb;
    512 refpointsover[1] = SCIPisInfinity(scip, ub) ? lb + 2.0 : (lb + ub) / 2;
    513 refpointsover[2] = SCIPisInfinity(scip, ub) ? lb + 20.0 : ub;
    514 }
    515
    516 *nreturned = 0;
    517
    518 for( i = 0; i < 4; ++i )
    519 {
    520 if( (overest[i] && !overestimate) || (!overest[i] && (overestimate || SCIPisInfinity(scip, ub))) )
    521 continue;
    522
    523 assert(!overest[i] || (SCIPisLE(scip, refpointsover[i], ub) && SCIPisGE(scip, refpointsover[i], lb))); /*lint !e661*/
    524
    525 if( overest[i] )
    526 { /*lint !e661*/
    527 /* -x*(1+log(x*)) + x* <= -x*log(x) */
    528 assert(i < 3);
    529 /* coverity[overrun] */
    530 coefs[*nreturned][0] = -(1.0 + log(refpointsover[i]));
    531 /* coverity[overrun] */
    532 constant[*nreturned] = refpointsover[i];
    533 }
    534 else
    535 {
    536 assert(lb > 0.0 && ub >= 0.0);
    537 assert(ub - lb != 0.0);
    538
    539 coefs[*nreturned][0] = (-ub * log(ub) + lb * log(lb)) / (ub - lb);
    540 constant[*nreturned] = -ub * log(ub) - coefs[*nreturned][0] * ub;
    541 assert(SCIPisEQ(scip, constant[*nreturned], -lb * log(lb) - coefs[*nreturned][0] * lb)); /* cppcheck-suppress assertWithSideEffect */
    542 }
    543
    544 ++(*nreturned);
    545 }
    546
    547 return SCIP_OKAY;
    548}
    549
    550/** expression reverse propagation callback */
    551static
    552SCIP_DECL_EXPRREVERSEPROP(reversepropEntropy)
    553{ /*lint --e{715}*/
    554 SCIP_INTERVAL newinterval;
    555
    556 assert(scip != NULL);
    557 assert(expr != NULL);
    558 assert(SCIPexprGetNChildren(expr) == 1);
    559 assert(childrenbounds != NULL);
    560 assert(infeasible != NULL);
    561
    562 /* compute resulting intervals (reverseProp handles childinterval being empty) */
    563 SCIP_CALL( reverseProp(scip, bounds, childrenbounds[0], &newinterval) );
    564 assert(SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, newinterval) || newinterval.inf >= 0.0);
    565
    566 childrenbounds[0] = newinterval;
    567
    568 return SCIP_OKAY;
    569}
    570
    571/** entropy hash callback */
    572static
    574{ /*lint --e{715}*/
    575 assert(expr != NULL);
    576 assert(SCIPexprGetNChildren(expr) == 1);
    577 assert(hashkey != NULL);
    578 assert(childrenhashes != NULL);
    579
    580 *hashkey = EXPRHDLR_HASHKEY;
    581 *hashkey ^= childrenhashes[0];
    582
    583 return SCIP_OKAY;
    584}
    585
    586/** expression curvature detection callback */
    587static
    588SCIP_DECL_EXPRCURVATURE(curvatureEntropy)
    589{ /*lint --e{715}*/
    590 assert(scip != NULL);
    591 assert(expr != NULL);
    592 assert(childcurv != NULL);
    593 assert(success != NULL);
    594 assert(SCIPexprGetNChildren(expr) == 1);
    595
    596 /* to be concave, the child needs to be concave, too; we cannot be convex or linear */
    597 if( exprcurvature == SCIP_EXPRCURV_CONCAVE )
    598 {
    599 *childcurv = SCIP_EXPRCURV_CONCAVE;
    600 *success = TRUE;
    601 }
    602 else
    603 *success = FALSE;
    604
    605 return SCIP_OKAY;
    606}
    607
    608/** expression monotonicity detection callback */
    609static
    610SCIP_DECL_EXPRMONOTONICITY(monotonicityEntropy)
    611{ /*lint --e{715}*/
    612 SCIP_EXPR* child;
    613 SCIP_INTERVAL childbounds;
    614 SCIP_Real brpoint = exp(-1.0);
    615
    616 assert(scip != NULL);
    617 assert(expr != NULL);
    618 assert(result != NULL);
    619 assert(childidx == 0);
    620
    621 child = SCIPexprGetChildren(expr)[0];
    622 assert(child != NULL);
    623
    625 childbounds = SCIPexprGetActivity(child);
    626
    627 if( childbounds.sup <= brpoint )
    628 *result = SCIP_MONOTONE_INC;
    629 else if( childbounds.inf >= brpoint )
    630 *result = SCIP_MONOTONE_DEC;
    631 else
    632 *result = SCIP_MONOTONE_UNKNOWN;
    633
    634 return SCIP_OKAY;
    635}
    636
    637/** expression integrality detection callback */
    638static
    639SCIP_DECL_EXPRINTEGRALITY(integralityEntropy)
    640{ /*lint --e{715}*/
    641 assert(scip != NULL);
    642 assert(expr != NULL);
    643 assert(integrality != NULL);
    644
    645 /* TODO it is possible to check for the special case that the child is integral and its bounds are [0,1]; in
    646 * this case the entropy expression can only achieve 0 and is thus integral
    647 */
    648 *integrality = SCIP_IMPLINTTYPE_NONE;
    649
    650 return SCIP_OKAY;
    651}
    652
    653/** creates the handler for entropy expressions and includes it into SCIP */
    655 SCIP* scip /**< SCIP data structure */
    656 )
    657{
    658 SCIP_EXPRHDLRDATA* exprhdlrdata;
    659 SCIP_EXPRHDLR* exprhdlr;
    660
    661 /* create expression handler data */
    662 exprhdlrdata = NULL;
    663
    664 /* include expression handler */
    666 evalEntropy, exprhdlrdata) );
    667 assert(exprhdlr != NULL);
    668
    669 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrEntropy, NULL);
    670 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataEntropy, freedataEntropy);
    671 SCIPexprhdlrSetSimplify(exprhdlr, simplifyEntropy);
    672 SCIPexprhdlrSetParse(exprhdlr, parseEntropy);
    673 SCIPexprhdlrSetIntEval(exprhdlr, intevalEntropy);
    674 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesEntropy, estimateEntropy);
    675 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropEntropy);
    676 SCIPexprhdlrSetHash(exprhdlr, hashEntropy);
    677 SCIPexprhdlrSetDiff(exprhdlr, bwdiffEntropy, NULL ,NULL);
    678 SCIPexprhdlrSetCurvature(exprhdlr, curvatureEntropy);
    679 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityEntropy);
    680 SCIPexprhdlrSetIntegrality(exprhdlr, integralityEntropy);
    681
    682 return SCIP_OKAY;
    683}
    684
    685/** creates an entropy expression */
    687 SCIP* scip, /**< SCIP data structure */
    688 SCIP_EXPR** expr, /**< pointer where to store expression */
    689 SCIP_EXPR* child, /**< child expression */
    690 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    691 void* ownercreatedata /**< data to pass to ownercreate */
    692 )
    693{
    694 SCIP_EXPRHDLR* exprhdlr;
    695 SCIP_EXPRDATA* exprdata;
    696
    697 assert(expr != NULL);
    698 assert(child != NULL);
    699
    701 assert(exprhdlr != NULL);
    702
    703 /* create expression data */
    704 exprdata = NULL;
    705
    706 /* create expression */
    707 SCIP_CALL( SCIPcreateExpr(scip, expr, exprhdlr, exprdata, 1, &child, ownercreate, ownercreatedata) );
    708
    709 return SCIP_OKAY;
    710}
    711
    712/** indicates whether expression is of entropy-type */ /*lint -e{715}*/
    714 SCIP* scip, /**< SCIP data structure */
    715 SCIP_EXPR* expr /**< expression */
    716 )
    717{ /*lint --e{715}*/
    718 assert(expr != NULL);
    719
    720 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0;
    721}
    SCIP_VAR ** x
    Definition: circlepacking.c:63
    #define NULL
    Definition: def.h:257
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:189
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define REALABS(x)
    Definition: def.h:191
    #define SCIP_CALL(x)
    Definition: def.h:364
    private functions to work with algebraic expressions
    static SCIP_DECL_EXPRFREEDATA(freedataEntropy)
    Definition: expr_entropy.c:298
    static SCIP_DECL_EXPRBWDIFF(bwdiffEntropy)
    Definition: expr_entropy.c:364
    static SCIP_DECL_EXPRSIMPLIFY(simplifyEntropy)
    Definition: expr_entropy.c:241
    static SCIP_DECL_EXPRREVERSEPROP(reversepropEntropy)
    Definition: expr_entropy.c:552
    #define EXPRHDLR_HASHKEY
    Definition: expr_entropy.c:46
    static SCIP_DECL_EXPRESTIMATE(estimateEntropy)
    Definition: expr_entropy.c:411
    static SCIP_DECL_EXPRCOPYHDLR(copyhdlrEntropy)
    Definition: expr_entropy.c:232
    static SCIP_DECL_EXPRHASH(hashEntropy)
    Definition: expr_entropy.c:573
    static SCIP_DECL_EXPRINITESTIMATES(initestimatesEntropy)
    Definition: expr_entropy.c:486
    #define EXPRHDLR_NAME
    Definition: expr_entropy.c:43
    static SCIP_DECL_EXPRINTEVAL(intevalEntropy)
    Definition: expr_entropy.c:391
    static SCIP_DECL_EXPRCOPYDATA(copydataEntropy)
    Definition: expr_entropy.c:286
    static SCIP_DECL_EXPRCURVATURE(curvatureEntropy)
    Definition: expr_entropy.c:588
    static SCIP_RETCODE reverseProp(SCIP *scip, SCIP_INTERVAL exprinterval, SCIP_INTERVAL childinterval, SCIP_INTERVAL *interval)
    Definition: expr_entropy.c:111
    static SCIP_DECL_EXPRMONOTONICITY(monotonicityEntropy)
    Definition: expr_entropy.c:610
    static SCIP_DECL_EXPRINTEGRALITY(integralityEntropy)
    Definition: expr_entropy.c:639
    static SCIP_Real reversePropBinarySearch(SCIP *scip, SCIP_Real xmin, SCIP_Real xmax, SCIP_Bool increasing, SCIP_Real targetval)
    Definition: expr_entropy.c:60
    #define EXPRHDLR_DESC
    Definition: expr_entropy.c:44
    #define EXPRHDLR_PRECEDENCE
    Definition: expr_entropy.c:45
    static SCIP_DECL_EXPREVAL(evalEntropy)
    Definition: expr_entropy.c:333
    static SCIP_DECL_EXPRPARSE(parseEntropy)
    Definition: expr_entropy.c:308
    handler for -x*log(x) expressions
    constant value expression handler
    SCIP_Bool SCIPisExprEntropy(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_entropy.c:713
    SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_value.c:274
    SCIP_RETCODE SCIPcreateExprEntropy(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_entropy.c:686
    SCIP_RETCODE SCIPincludeExprhdlrEntropy(SCIP *scip)
    Definition: expr_entropy.c:654
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:545
    void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEGRALITY((*integrality)))
    Definition: expr.c:440
    void SCIPexprhdlrSetCopyFreeData(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYDATA((*copydata)), SCIP_DECL_EXPRFREEDATA((*freedata)))
    Definition: expr.c:383
    void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
    Definition: expr.c:451
    void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)), SCIP_DECL_EXPRFREEHDLR((*freehdlr)))
    Definition: expr.c:370
    void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)), SCIP_DECL_EXPRBWFWDIFF((*bwfwdiff)))
    Definition: expr.c:473
    void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRREVERSEPROP((*reverseprop)))
    Definition: expr.c:510
    void SCIPexprhdlrSetParse(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRPARSE((*parse)))
    Definition: expr.c:407
    void SCIPexprhdlrSetEstimate(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINITESTIMATES((*initestimates)), SCIP_DECL_EXPRESTIMATE((*estimate)))
    Definition: expr.c:532
    void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRMONOTONICITY((*monotonicity)))
    Definition: expr.c:429
    void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEVAL((*inteval)))
    Definition: expr.c:488
    void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCURVATURE((*curvature)))
    Definition: expr.c:418
    SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
    Definition: scip_expr.c:847
    SCIP_EXPRHDLR * SCIPfindExprhdlr(SCIP *scip, const char *name)
    Definition: scip_expr.c:894
    void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRSIMPLIFY((*simplify)))
    Definition: expr.c:499
    SCIP_RETCODE SCIPcreateExpr(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPRHDLR *exprhdlr, SCIP_EXPRDATA *exprdata, int nchildren, SCIP_EXPR **children, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1000
    void SCIPexprSetData(SCIP_EXPR *expr, SCIP_EXPRDATA *exprdata)
    Definition: expr.c:3920
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1468
    SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
    Definition: scip_expr.c:1443
    SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
    Definition: expr.c:3905
    SCIP_RETCODE SCIPparseExpr(SCIP *scip, SCIP_EXPR **expr, const char *exprstr, const char **finalpos, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1406
    SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
    Definition: expr_value.c:298
    SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
    Definition: expr.c:3946
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
    Definition: expr.c:4028
    void SCIPcaptureExpr(SCIP_EXPR *expr)
    Definition: scip_expr.c:1435
    SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1742
    SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
    Definition: expr.c:3895
    SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
    void SCIPintervalIntersect(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
    SCIP_Bool SCIPintervalIsSubsetEQ(SCIP_Real infinity, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
    void SCIPintervalEntropy(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
    SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
    void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPepsilon(SCIP *scip)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real sup
    Definition: intervalarith.h:57
    SCIP_Real inf
    Definition: intervalarith.h:56
    #define SCIP_DECL_EXPR_OWNERCREATE(x)
    Definition: type_expr.h:143
    struct SCIP_ExprhdlrData SCIP_EXPRHDLRDATA
    Definition: type_expr.h:195
    struct SCIP_ExprData SCIP_EXPRDATA
    Definition: type_expr.h:54
    @ SCIP_EXPRCURV_CONCAVE
    Definition: type_expr.h:64
    @ SCIP_MONOTONE_UNKNOWN
    Definition: type_expr.h:71
    @ SCIP_MONOTONE_INC
    Definition: type_expr.h:72
    @ SCIP_MONOTONE_DEC
    Definition: type_expr.h:73
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_IMPLINTTYPE_NONE
    Definition: type_var.h:90