SCIP

    Solving Constraint Integer Programs

    expr_pow.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_pow.c
    26 * @ingroup DEFPLUGINS_EXPR
    27 * @brief power expression handler
    28 * @author Benjamin Mueller
    29 * @author Ksenia Bestuzheva
    30 *
    31 * @todo signpower for exponent < 1 ?
    32 */
    33
    34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    35
    36/*lint --e{835}*/
    37/*lint -e777*/
    38
    39#include "scip/expr_pow.h"
    40#include "scip/pub_expr.h"
    41#include "scip/expr_value.h"
    42#include "scip/expr_product.h"
    43#include "scip/expr_sum.h"
    44#include "scip/expr_exp.h"
    45#include "scip/expr_abs.h"
    47
    48#define POWEXPRHDLR_NAME "pow"
    49#define POWEXPRHDLR_DESC "power expression"
    50#define POWEXPRHDLR_PRECEDENCE 55000
    51#define POWEXPRHDLR_HASHKEY SCIPcalcFibHash(21163.0)
    52
    53#define SIGNPOWEXPRHDLR_NAME "signpower"
    54#define SIGNPOWEXPRHDLR_DESC "signed power expression"
    55#define SIGNPOWEXPRHDLR_PRECEDENCE 56000
    56#define SIGNPOWEXPRHDLR_HASHKEY SCIPcalcFibHash(21163.1)
    57
    58#define INITLPMAXPOWVAL 1e+06 /**< maximal allowed absolute value of power expression at bound,
    59 * used for adjusting bounds in the convex case in initestimates */
    60
    61/*
    62 * Data structures
    63 */
    64
    65/** sign of a value (-1 or +1)
    66 *
    67 * 0.0 has sign +1 here (shouldn't matter, though)
    68 */
    69#define SIGN(x) ((x) >= 0.0 ? 1.0 : -1.0)
    70
    71#define SIGNPOW_ROOTS_KNOWN 10 /**< up to which (integer) exponents precomputed roots have been stored */
    72
    73/** The positive root of the polynomial (n-1) y^n + n y^(n-1) - 1 is needed in separation.
    74 * Here we store these roots for small integer values of n.
    75 */
    76static
    78 -1.0, /* no root for n=0 */
    79 -1.0, /* no root for n=1 */
    80 0.41421356237309504880, /* root for n=2 (-1+sqrt(2)) */
    81 0.5, /* root for n=3 */
    82 0.56042566045031785945, /* root for n=4 */
    83 0.60582958618826802099, /* root for n=5 */
    84 0.64146546982884663257, /* root for n=6 */
    85 0.67033204760309682774, /* root for n=7 */
    86 0.69428385661425826738, /* root for n=8 */
    87 0.71453772716733489700, /* root for n=9 */
    88 0.73192937842370733350 /* root for n=10 */
    89};
    90
    91/** expression handler data */
    92struct SCIP_ExprhdlrData
    93{
    94 SCIP_Real minzerodistance; /**< minimal distance from zero to enforce for child in bound tightening */
    95 int expandmaxexponent; /**< maximal exponent when to expand power of sum in simplify */
    96 SCIP_Bool distribfracexponent;/**< whether a fractional exponent is distributed onto factors on power of product */
    97
    98 SCIP_Bool warnedonpole; /**< whether we warned on enforcing a minimal distance from zero for child */
    99};
    100
    101/** expression data */
    102struct SCIP_ExprData
    103{
    104 SCIP_Real exponent; /**< exponent */
    105 SCIP_Real root; /**< positive root of (n-1) y^n + n y^(n-1) - 1, or
    106 SCIP_INVALID if not computed yet */
    107};
    108
    109/*
    110 * Local methods
    111 */
    112
    113/** computes positive root of the polynomial (n-1) y^n + n y^(n-1) - 1 for n > 1 */
    114static
    116 SCIP* scip, /**< SCIP data structure */
    117 SCIP_Real* root, /**< buffer where to store computed root */
    118 SCIP_Real exponent /**< exponent n */
    119 )
    120{
    121 SCIP_Real polyval;
    122 SCIP_Real gradval;
    123 int iter;
    124
    125 assert(scip != NULL);
    126 assert(exponent > 1.0);
    127 assert(root != NULL);
    128
    129 /* lookup for popular integer exponent */
    130 if( SCIPisIntegral(scip, exponent) && exponent-0.5 < SIGNPOW_ROOTS_KNOWN )
    131 {
    132 *root = signpow_roots[(int)SCIPfloor(scip, exponent+0.5)];
    133 return SCIP_OKAY;
    134 }
    135
    136 /* lookup for weymouth exponent */
    137 if( SCIPisEQ(scip, exponent, 1.852) )
    138 {
    139 *root = 0.39821689389382575186;
    140 return SCIP_OKAY;
    141 }
    142
    143 /* search for a positive root of (n-1) y^n + n y^(n-1) - 1
    144 * use the closest precomputed root as starting value
    145 */
    146 if( exponent >= SIGNPOW_ROOTS_KNOWN )
    148 else if( exponent <= 2.0 )
    149 *root = signpow_roots[2];
    150 else
    151 *root = signpow_roots[(int)SCIPfloor(scip, exponent)];
    152
    153 for( iter = 0; iter < 1000; ++iter )
    154 {
    155 polyval = (exponent - 1.0) * pow(*root, exponent) + exponent * pow(*root, exponent - 1.0) - 1.0;
    156 if( fabs(polyval) < 1e-12 && SCIPisZero(scip, polyval) )
    157 break;
    158
    159 /* gradient of (n-1) y^n + n y^(n-1) - 1 is n(n-1)y^(n-1) + n(n-1)y^(n-2) */
    160 gradval = (exponent - 1.0) * exponent * (pow(*root, exponent - 1.0) + pow(*root, exponent - 2.0));
    161 if( SCIPisZero(scip, gradval) )
    162 break;
    163
    164 /* update root by adding -polyval/gradval (Newton's method) */
    165 *root -= polyval / gradval;
    166 if( *root < 0.0 )
    167 *root = 0.0;
    168 }
    169
    170 if( !SCIPisZero(scip, polyval) )
    171 {
    172 SCIPerrorMessage("failed to compute root for exponent %g\n", exponent);
    173 return SCIP_ERROR;
    174 }
    175 SCIPdebugMsg(scip, "root for %g is %.20g, certainty = %g\n", exponent, *root, polyval);
    176 /* @todo cache root value for other expressions (an exponent seldom comes alone)?? (they are actually really fast to compute...) */
    177
    178 return SCIP_OKAY;
    179}
    180
    181/** computes negative root of the polynomial (n-1) y^n - n y^(n-1) + 1 for n < -1 */
    182static
    184 SCIP* scip, /**< SCIP data structure */
    185 SCIP_Real* root, /**< buffer where to store computed root */
    186 SCIP_Real exponent /**< exponent n */
    187 )
    188{
    189 SCIP_Real polyval;
    190 SCIP_Real gradval;
    191 int iter;
    192
    193 assert(scip != NULL);
    194 assert(exponent < -1.0);
    195 assert(root != NULL);
    196
    197 *root = -2.0; /* that's the solution for n=-2 */
    198
    199 for( iter = 0; iter < 1000; ++iter )
    200 {
    201 polyval = (exponent - 1.0) * pow(*root, exponent) - exponent * pow(*root, exponent - 1.0) + 1.0;
    202 if( fabs(polyval) < 1e-12 && SCIPisZero(scip, polyval) )
    203 break;
    204
    205 /* gradient of (n-1) y^n - n y^(n-1) + 1 is n(n-1)y^(n-1) - n(n-1)y^(n-2) */
    206 gradval = (exponent - 1.0) * exponent * (pow(*root, exponent - 1.0) - pow(*root, exponent - 2.0));
    207 if( SCIPisZero(scip, gradval) )
    208 break;
    209
    210 /* update root by adding -polyval/gradval (Newton's method) */
    211 *root -= polyval / gradval;
    212 if( *root >= 0.0 )
    213 *root = -1;
    214 }
    215
    216 if( !SCIPisZero(scip, polyval) )
    217 {
    218 SCIPerrorMessage("failed to compute root for exponent %g\n", exponent);
    219 return SCIP_ERROR;
    220 }
    221 SCIPdebugMsg(scip, "root for %g is %.20g, certainty = %g\n", exponent, *root, polyval);
    222 /* @todo cache root value for other expressions (an exponent seldom comes alone)?? (they are actually really fast to compute...) */
    223
    224 return SCIP_OKAY;
    225}
    226
    227/** creates expression data */
    228static
    230 SCIP* scip, /**< SCIP data structure */
    231 SCIP_EXPRDATA** exprdata, /**< pointer where to store expression data */
    232 SCIP_Real exponent /**< exponent of the power expression */
    233 )
    234{
    235 assert(exprdata != NULL);
    236
    237 SCIP_CALL( SCIPallocBlockMemory(scip, exprdata) );
    238
    239 (*exprdata)->exponent = exponent;
    240 (*exprdata)->root = SCIP_INVALID;
    241
    242 return SCIP_OKAY;
    243}
    244
    245/** computes a tangent at a reference point by linearization
    246 *
    247 * for a normal power, linearization in xref is xref^exponent + exponent * xref^(exponent-1) (x - xref)
    248 * = (1-exponent) * xref^exponent + exponent * xref^(exponent-1) * x
    249 *
    250 * for a signpower, linearization is the same if xref is positive
    251 * for xref negative it is -(-xref)^exponent + exponent * (-xref)^(exponent-1) (x-xref)
    252 * = (1-exponent) * (-xref)^(exponent-1) * xref + exponent * (-xref)^(exponent-1) * x
    253 */
    254static
    256 SCIP* scip, /**< SCIP data structure */
    257 SCIP_Bool signpower, /**< are we signpower or normal power */
    258 SCIP_Real exponent, /**< exponent */
    259 SCIP_Real xref, /**< reference point where to linearize */
    260 SCIP_Real* constant, /**< buffer to store constant term of secant */
    261 SCIP_Real* slope, /**< buffer to store slope of secant */
    262 SCIP_Bool* success /**< buffer to store whether secant could be computed */
    263 )
    264{
    265 SCIP_Real xrefpow;
    266
    267 assert(scip != NULL);
    268 assert(constant != NULL);
    269 assert(slope != NULL);
    270 assert(success != NULL);
    271 assert(xref != 0.0 || exponent > 0.0);
    272 /* non-integral exponent -> reference point must be >= 0 or we do signpower */
    273 assert(EPSISINT(exponent, 0.0) || signpower || !SCIPisNegative(scip, xref));
    274
    275 /* TODO power is not differentiable at 0.0 for exponent < 0
    276 * should we forbid here that xref > 0, do something smart here, or just return success=FALSE?
    277 */
    278 /* assert(exponent >= 1.0 || xref > 0.0); */
    279
    280 if( !EPSISINT(exponent, 0.0) && !signpower && xref < 0.0 )
    281 xref = 0.0;
    282
    283 xrefpow = pow(signpower ? REALABS(xref) : xref, exponent - 1.0);
    284
    285 /* if huge xref and/or exponent too large, then pow may overflow */
    286 if( !SCIPisFinite(xrefpow) )
    287 {
    288 *success = FALSE;
    289 return;
    290 }
    291
    292 *constant = (1.0 - exponent) * xrefpow * xref;
    293 *slope = exponent * xrefpow;
    294 *success = TRUE;
    295}
    296
    297/** computes a secant between lower and upper bound
    298 *
    299 * secant is xlb^exponent + (xub^exponent - xlb^exponent) / (xub - xlb) * (x - xlb)
    300 * = xlb^exponent - slope * xlb + slope * x with slope = (xub^exponent - xlb^exponent) / (xub - xlb)
    301 * same if signpower
    302 */
    303static
    305 SCIP* scip, /**< SCIP data structure */
    306 SCIP_Bool signpower, /**< are we signpower or normal power */
    307 SCIP_Real exponent, /**< exponent */
    308 SCIP_Real xlb, /**< lower bound on x */
    309 SCIP_Real xub, /**< upper bound on x */
    310 SCIP_Real* constant, /**< buffer to store constant term of secant */
    311 SCIP_Real* slope, /**< buffer to store slope of secant */
    312 SCIP_Bool* success /**< buffer to store whether secant could be computed */
    313 )
    314{
    315 assert(scip != NULL);
    316 assert(constant != NULL);
    317 assert(slope != NULL);
    318 assert(success != NULL);
    319 assert(xlb >= 0.0 || EPSISINT(exponent, 0.0) || signpower);
    320 assert(xub >= 0.0 || EPSISINT(exponent, 0.0) || signpower);
    321 assert(exponent != 1.0);
    322
    323 *success = FALSE;
    324
    325 /* infinite bounds will not work */
    326 if( SCIPisInfinity(scip, -xlb) || SCIPisInfinity(scip, xub) )
    327 return;
    328
    329 /* first handle some special cases */
    330 if( xlb == xub )
    331 {
    332 /* usually taken care of in separatePointPow already, but we might be called with different bounds here,
    333 * e.g., when handling odd or signed power
    334 */
    335 *slope = 0.0;
    336 *constant = pow(xlb, exponent);
    337 }
    338 else if( EPSISINT(exponent / 2.0, 0.0) && !signpower && xub > 0.1 && SCIPisFeasEQ(scip, xlb, -xub) )
    339 {
    340 /* for normal power with even exponents with xlb ~ -xub the slope would be very close to 0
    341 * since xub^n - xlb^n is prone to cancellation here, we omit computing this secant (it's probably useless)
    342 * unless the bounds are close to 0 as well (xub <= 0.1 in the "if" above)
    343 * or we have exactly xlb=-xub, where we can return a clean 0.0 (though it's probably useless)
    344 */
    345 if( xlb == -xub )
    346 {
    347 *slope = 0.0;
    348 *constant = pow(xlb, exponent);
    349 }
    350 else
    351 {
    352 return;
    353 }
    354 }
    355 else if( xlb == 0.0 && exponent > 0.0 )
    356 {
    357 assert(xub >= 0.0);
    358 *slope = pow(xub, exponent-1.0);
    359 *constant = 0.0;
    360 }
    361 else if( xub == 0.0 && exponent > 0.0 )
    362 {
    363 /* normal pow: slope = - xlb^exponent / (-xlb) = xlb^(exponent-1)
    364 * signpower: slope = (-xlb)^exponent / (-xlb) = (-xlb)^(exponent-1)
    365 */
    366 assert(xlb <= 0.0); /* so signpower or exponent is integral */
    367 if( signpower )
    368 *slope = pow(-xlb, exponent-1.0);
    369 else
    370 *slope = pow(xlb, exponent-1.0);
    371 *constant = 0.0;
    372 }
    373 else if( SCIPisEQ(scip, xlb, xub) && (!signpower || xlb >= 0.0 || xub <= 0.0) )
    374 {
    375 /* Computing the slope as (xub^n - xlb^n)/(xub-xlb) can lead to cancellation.
    376 * To avoid this, we replace xub^n by a Taylor expansion of pow at xlb:
    377 * xub^n = xlb^n + n xlb^(n-1) (xub-xlb) + 0.5 n*(n-1) xlb^(n-2) (xub-xlb)^2 + 1/6 n*(n-1)*(n-2) xi^(n-3) (xub-xlb)^3 for some xlb < xi < xub
    378 * Dropping the last term, the slope is (with an error of O((xub-xlb)^2) = 1e-18)
    379 * n*xlb^(n-1) + 0.5 n*(n-1) xlb^(n-2)*(xub-xlb)
    380 * = n*xlb^(n-1) (1 - 0.5*(n-1)) + 0.5 n*(n-1) xlb^(n-2)*xub
    381 * = 0.5*n*((3-n)*xlb^(n-1) + (n-1) xlb^(n-2)*xub)
    382 *
    383 * test n=2: 0.5*2*((3-2)*xlb + (2-1) 1*xub) = xlb + xub ok
    384 * n=3: 0.5*3*((3-3)*xlb + (3-1) xlb*xub) = 3*xlb*xub ~ xlb^2 + xlb*xub + xub^2 ok
    385 *
    386 * The constant is
    387 * xlb^n - 0.5*n*((3-n) xlb^(n-1) + (n-1) xlb^(n-2)*xub) * xlb
    388 * = xlb^n - 0.5*n*(3-n) xlb^n - 0.5*n*(n-1) xlb^(n-1)*xub
    389 * = (1-0.5*n*(3-n)) xlb^n - 0.5 n*(n-1) xlb^(n-1) xub
    390 *
    391 * test n=2: (1-0.5*2*(3-2)) xlb^2 - 0.5 2*(2-1) xlb xub = -xlb*xub
    392 * old formula: xlb^2 - (xlb+xub) * xlb = -xlb*xub ok
    393 *
    394 * For signpower with xub <= 0, we can negate xlb and xub:
    395 * slope: (sign(xub)|xub|^n - sign(xlb)*|xlb|^n) / (xub-xlb) = -((-xub)^n - (-xlb)^n) / (xub - xlb) = ((-xub)^n - (-xlb)^n) / (-xub - (-xlb))
    396 * constant: sign(xlb)|xlb|^n + slope * (xub - xlb) = -((-xlb)^n - slope * (xub - xlb)) = -((-xlb)^n + slope * ((-xub) - (-xlb)))
    397 */
    398 SCIP_Real xlb_n; /* xlb^n */
    399 SCIP_Real xlb_n1; /* xlb^(n-1) */
    400 SCIP_Real xlb_n2; /* xlb^(n-2) */
    401
    402 if( signpower && xub <= 0.0 )
    403 {
    404 xlb *= -1.0;
    405 xub *= -1.0;
    406 }
    407
    408 xlb_n = pow(xlb, exponent);
    409 xlb_n1 = pow(xlb, exponent - 1.0);
    410 xlb_n2 = pow(xlb, exponent - 2.0);
    411
    412 *slope = 0.5*exponent * ((3.0-exponent) * xlb_n1 + (exponent-1.0) * xlb_n2 * xub);
    413 *constant = (1.0 - 0.5*exponent*(3.0-exponent)) * xlb_n - 0.5*exponent*(exponent-1.0) * xlb_n1 * xub;
    414
    415 if( signpower && xub <= 0.0 )
    416 *constant *= -1.0;
    417 }
    418 else
    419 {
    420 SCIP_Real lbval;
    421 SCIP_Real ubval;
    422
    423 if( signpower )
    424 lbval = SIGN(xlb) * pow(REALABS(xlb), exponent);
    425 else
    426 lbval = pow(xlb, exponent);
    427 if( !SCIPisFinite(lbval) )
    428 return;
    429
    430 if( signpower )
    431 ubval = SIGN(xub) * pow(REALABS(xub), exponent);
    432 else
    433 ubval = pow(xub, exponent);
    434 if( !SCIPisFinite(ubval) )
    435 return;
    436
    437 /* we still can have bad numerics when xlb^exponent and xub^exponent are very close, but xlb and xub are not
    438 * for now, only check that things did not cancel out completely
    439 */
    440 if( lbval == ubval )
    441 return;
    442
    443 *slope = (ubval - lbval) / (xub - xlb);
    444 *constant = lbval - *slope * xlb;
    445 }
    446
    447 /* check whether we had overflows */
    448 if( !SCIPisFinite(*slope) || !SCIPisFinite(*constant) )
    449 return;
    450
    451 *success = TRUE;
    452}
    453
    454/** Separation for parabola
    455 *
    456 * - even positive powers: x^2, x^4, x^6 with x arbitrary, or
    457 * - positive powers > 1: x^1.5, x^2.5 with x >= 0
    458 <pre>
    459 100 +--------------------------------------------------------------------+
    460 |* + + + *|
    461 90 |** x**2 ********|
    462 | * * |
    463 80 |-+* *+-|
    464 | ** ** |
    465 70 |-+ * * +-|
    466 | ** ** |
    467 60 |-+ * * +-|
    468 | ** ** |
    469 50 |-+ * * +-|
    470 | ** ** |
    471 40 |-+ * * +-|
    472 | ** ** |
    473 30 |-+ ** ** +-|
    474 | ** ** |
    475 20 |-+ ** ** +-|
    476 | *** *** |
    477 10 |-+ *** *** +-|
    478 | + ***** + ***** + |
    479 0 +--------------------------------------------------------------------+
    480 -10 -5 0 5 10
    481 </pre>
    482 */
    483static
    485 SCIP* scip, /**< SCIP data structure */
    486 SCIP_Real exponent, /**< exponent */
    487 SCIP_Bool overestimate, /**< should the power be overestimated? */
    488 SCIP_Real xlb, /**< lower bound on x */
    489 SCIP_Real xub, /**< upper bound on x */
    490 SCIP_Real xref, /**< reference point (where to linearize) */
    491 SCIP_Real* constant, /**< buffer to store constant term of estimator */
    492 SCIP_Real* slope, /**< buffer to store slope of estimator */
    493 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
    494 * it depends on given bounds */
    495 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
    496 )
    497{
    498 assert(scip != NULL);
    499 assert(constant != NULL);
    500 assert(slope != NULL);
    501 assert(islocal != NULL);
    502 assert(success != NULL);
    503 assert((exponent >= 0.0 && EPSISINT(exponent/2.0, 0.0)) || (exponent > 1.0 && xlb >= 0.0));
    504
    505 if( !overestimate )
    506 {
    507 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
    508 *islocal = FALSE;
    509 }
    510 else
    511 {
    512 /* overestimation -> secant */
    513 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
    514 *islocal = TRUE;
    515 }
    516}
    517
    518
    519/** Separation for signpower
    520 *
    521 * - odd positive powers, x^3, x^5, x^7
    522 * - sign(x)|x|^n for n > 1
    523 * - lower bound on x is negative (otherwise one should use separation for parabola)
    524 <pre>
    525 100 +--------------------------------------------------------------------+
    526 | + + + **|
    527 | x*abs(x) ******* |
    528 | ** |
    529 | ** |
    530 50 |-+ *** +-|
    531 | *** |
    532 | *** |
    533 | ***** |
    534 | ***** |
    535 0 |-+ **************** +-|
    536 | ***** |
    537 | ***** |
    538 | *** |
    539 | *** |
    540 -50 |-+ *** +-|
    541 | ** |
    542 | ** |
    543 | ** |
    544 |** + + + |
    545 -100 +--------------------------------------------------------------------+
    546 -10 -5 0 5 10
    547 </pre>
    548 */
    549static
    551 SCIP* scip, /**< SCIP data structure */
    552 SCIP_Real exponent, /**< exponent */
    553 SCIP_Real root, /**< positive root of the polynomial (n-1) y^n + n y^(n-1) - 1,
    554 * if xubglobal > 0 */
    555 SCIP_Bool overestimate, /**< should the power be overestimated? */
    556 SCIP_Real xlb, /**< lower bound on x, assumed to be non-positive */
    557 SCIP_Real xub, /**< upper bound on x */
    558 SCIP_Real xref, /**< reference point (where to linearize) */
    559 SCIP_Real xlbglobal, /**< global lower bound on x */
    560 SCIP_Real xubglobal, /**< global upper bound on x */
    561 SCIP_Real* constant, /**< buffer to store constant term of estimator */
    562 SCIP_Real* slope, /**< buffer to store slope of estimator */
    563 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
    564 * it depends on given bounds */
    565 SCIP_Bool* branchcand, /**< buffer to indicate whether estimator would improve by branching
    566 * on it */
    567 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
    568 )
    569{
    570 assert(scip != NULL);
    571 assert(constant != NULL);
    572 assert(slope != NULL);
    573 assert(islocal != NULL);
    574 assert(branchcand != NULL);
    575 assert(*branchcand == TRUE); /* the default */
    576 assert(success != NULL);
    577 assert(exponent >= 1.0);
    578 assert(xlb < 0.0); /* otherwise estimateParabola should have been called */
    579 assert(xubglobal <= 0.0 || (root > 0.0 && root < 1.0));
    580
    581 *success = FALSE;
    582
    583 if( !SCIPisPositive(scip, xub) )
    584 {
    585 /* easy case */
    586 if( !overestimate )
    587 {
    588 /* underestimator is secant */
    589 computeSecant(scip, TRUE, exponent, xlb, xub, constant, slope, success);
    590 *islocal = TRUE;
    591 }
    592 else
    593 {
    594 /* overestimator is tangent */
    595
    596 /* we must linearize left of 0 */
    597 if( xref > 0.0 )
    598 xref = 0.0;
    599
    600 computeTangent(scip, TRUE, exponent, xref, constant, slope, success);
    601
    602 /* if global upper bound is > 0, then the tangent is only valid locally if the reference point is right of
    603 * -root*xubglobal
    604 */
    605 *islocal = SCIPisPositive(scip, xubglobal) && xref > -root * xubglobal;
    606
    607 /* tangent doesn't move after branching */
    608 *branchcand = FALSE;
    609 }
    610 }
    611 else
    612 {
    613 SCIP_Real c;
    614
    615 if( !overestimate )
    616 {
    617 /* compute the special point which decides between secant and tangent */
    618 c = -xlb * root;
    619
    620 if( xref < c )
    621 {
    622 /* underestimator is secant between xlb and c */
    623 computeSecant(scip, TRUE, exponent, xlb, c, constant, slope, success);
    624 *islocal = TRUE;
    625 }
    626 else
    627 {
    628 /* underestimator is tangent */
    629 computeTangent(scip, TRUE, exponent, xref, constant, slope, success);
    630
    631 /* if reference point is left of -root*xlbglobal (c w.r.t. global bounds),
    632 * then tangent is not valid w.r.t. global bounds
    633 */
    634 *islocal = xref < -root * xlbglobal;
    635
    636 /* tangent doesn't move after branching */
    637 *branchcand = FALSE;
    638 }
    639 }
    640 else
    641 {
    642 /* compute the special point which decides between secant and tangent */
    643 c = -xub * root;
    644
    645 if( xref <= c )
    646 {
    647 /* overestimator is tangent */
    648 computeTangent(scip, TRUE, exponent, xref, constant, slope, success);
    649
    650 /* if reference point is right of -root*xubglobal (c w.r.t. global bounds),
    651 * then tangent is not valid w.r.t. global bounds
    652 */
    653 *islocal = xref > -root * xubglobal;
    654
    655 /* tangent doesn't move after branching */
    656 *branchcand = FALSE;
    657 }
    658 else
    659 {
    660 /* overestimator is secant */
    661 computeSecant(scip, TRUE, exponent, c, xub, constant, slope, success);
    662 *islocal = TRUE;
    663 }
    664 }
    665 }
    666}
    667
    668/** Separation for positive hyperbola
    669 *
    670 * - x^-2, x^-4 with x arbitrary
    671 * - x^-0.5, x^-1, x^-1.5, x^-3, x^-5 with x >= 0
    672 <pre>
    673 5 +----------------------------------------------------------------------+
    674 | + * +* + |
    675 | * * x**(-2) ******* |
    676 4 |-+ * * +-|
    677 | * * |
    678 | * * |
    679 | * * |
    680 3 |-+ * * +-|
    681 | * * |
    682 | * * |
    683 2 |-+ * * +-|
    684 | * * |
    685 | * * |
    686 1 |-+ * * +-|
    687 | * * |
    688 | ** ** |
    689 | ********** ********** |
    690 0 |******************* *******************|
    691 | |
    692 | + + + |
    693 -1 +----------------------------------------------------------------------+
    694 -10 -5 0 5 10
    695 </pre>
    696 */
    697static
    699 SCIP* scip, /**< SCIP data structure */
    700 SCIP_Real exponent, /**< exponent */
    701 SCIP_Real root, /**< negative root of the polynomial (n-1) y^n - n y^(n-1) + 1,
    702 * if x has mixed sign (w.r.t. global bounds?) and underestimating */
    703 SCIP_Bool overestimate, /**< should the power be overestimated? */
    704 SCIP_Real xlb, /**< lower bound on x */
    705 SCIP_Real xub, /**< upper bound on x */
    706 SCIP_Real xref, /**< reference point (where to linearize) */
    707 SCIP_Real xlbglobal, /**< global lower bound on x */
    708 SCIP_Real xubglobal, /**< global upper bound on x */
    709 SCIP_Real* constant, /**< buffer to store constant term of estimator */
    710 SCIP_Real* slope, /**< buffer to store slope of estimator */
    711 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
    712 * it depends on given bounds */
    713 SCIP_Bool* branchcand, /**< buffer to indicate whether estimator would improve by branching
    714 * on it */
    715 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
    716 )
    717{
    718 assert(scip != NULL);
    719 assert(constant != NULL);
    720 assert(slope != NULL);
    721 assert(islocal != NULL);
    722 assert(branchcand != NULL);
    723 assert(*branchcand == TRUE); /* the default */
    724 assert(success != NULL);
    725 assert(exponent < 0.0);
    726 assert(EPSISINT(exponent/2.0, 0.0) || xlb >= 0.0);
    727
    728 *success = FALSE;
    729
    730 if( !overestimate )
    731 {
    732 if( xlb >= 0.0 || xub <= 0.0 )
    733 {
    734 /* underestimate and fixed sign -> tangent */
    735
    736 /* make sure xref has the same sign as xlb,xub */
    737 if( xref < 0.0 && xlb >= 0.0 )
    738 xref = xlb;
    739 else if( xref > 0.0 && xub <= 0.0 )
    740 xref = xub;
    741
    742 if( SCIPisZero(scip, xref) )
    743 {
    744 /* estimator would need to have an (essentially) infinite scope
    745 * first try to make up a better refpoint
    746 */
    747 if( xub > 0.0 )
    748 {
    749 /* thus xlb >= 0.0; stay close to xlb (probably = 0) */
    750 if( !SCIPisInfinity(scip, xub) )
    751 xref = 0.9 * xlb + 0.1 * xub;
    752 else
    753 xref = 0.1;
    754 }
    755 else
    756 {
    757 /* xub <= 0.0; stay close to xub (probably = 0) */
    758 if( !SCIPisInfinity(scip, -xlb) )
    759 xref = 0.1 * xlb + 0.9 * xub;
    760 else
    761 xref = 0.1;
    762 }
    763
    764 /* if still close to 0, then also bounds are close to 0, then just give up */
    765 if( SCIPisZero(scip, xref) )
    766 return;
    767 }
    768
    769 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
    770
    771 /* tangent will not change if branching on x (even if only locally valid, see checks below) */
    772 *branchcand = FALSE;
    773
    774 if( EPSISINT(exponent/2.0, 0.0) )
    775 {
    776 /* for even exponents (as in the picture):
    777 * if x has fixed sign globally, then our tangent is also globally valid
    778 * however, if x has mixed sign, then it depends on the constellation between reference point and global
    779 * bounds, whether the tangent is globally valid (see also the longer discussion for the mixed-sign
    780 * underestimator below )
    781 */
    782 if( xref > 0.0 && xlbglobal < 0.0 )
    783 {
    784 assert(xubglobal > 0.0); /* since xref > 0.0 */
    785 assert(root < 0.0); /* root needs to be given */
    786 /* if on right side, then tangent is only locally valid if xref is too much to the left */
    787 *islocal = xref < xlbglobal * root;
    788 }
    789 else if( xref < 0.0 && xubglobal > 0.0 )
    790 {
    791 assert(xlbglobal < 0.0); /* since xref < 0.0 */
    792 assert(root < 0.0); /* root needs to be given */
    793 /* if on left side, then tangent is only locally valid if xref is too much to the right */
    794 *islocal = xref > xubglobal * root;
    795 }
    796 else
    797 *islocal = FALSE;
    798 }
    799 else
    800 {
    801 /* for odd exponents, the tangent is only locally valid if the sign of x is not fixed globally */
    802 *islocal = xlbglobal * xubglobal < 0.0;
    803 }
    804 }
    805 else
    806 {
    807 /* underestimate but mixed sign */
    808 if( SCIPisInfinity(scip, -xlb) )
    809 {
    810 if( SCIPisInfinity(scip, xub) )
    811 {
    812 /* underestimator is constant 0, but that is globally valid */
    813 *constant = 0.0;
    814 *slope = 0.0;
    815 *islocal = FALSE;
    816 *success = TRUE;
    817 return;
    818 }
    819
    820 /* switch sign of x (mirror on ordinate) to make left bound finite and use its estimator */
    821 estimateHyperbolaPositive(scip, exponent, root, overestimate, -xub, -xlb, -xref, -xubglobal, -xlbglobal,
    822 constant, slope, islocal, branchcand, success);
    823 if( *success )
    824 *slope = -*slope;
    825 }
    826 else
    827 {
    828 /* The convex envelope of x^exponent for x in [xlb, infinity] is a line (secant) between xlb and some positive
    829 * coordinate xhat, and x^exponent for x > xhat.
    830 * Further, on [xlb,xub] with xub < xhat, the convex envelope is the secant between xlb and xub.
    831 *
    832 * To find xhat, consider the affine-linear function l(x) = xlb^n + c * (x - xlb) where n = exponent
    833 * we look for a value of x such that f(x) and l(x) coincide and such that l(x) will be tangent to f(x) on that
    834 * point, that is
    835 * xhat > 0 such that f(xhat) = l(xhat) and f'(xhat) = l'(xhat)
    836 * => xhat^n = xlb^n + c * (xhat - xlb) and n * xhat^(n-1) = c
    837 * => xhat^n = xlb^n + n * xhat^n - n * xhat^(n-1) * xlb
    838 * => 0 = xlb^n + (n-1) * xhat^n - n * xhat^(n-1) * xlb
    839 *
    840 * Divide by xlb^n, one gets a polynomial that looks very much like the one for signpower, but a sign is
    841 * different (since this is *not signed* power):
    842 * 0 = 1 + (n-1) * y^n - n * y^(n-1) where y = xhat/xlb
    843 *
    844 * The solution y < 0 (because xlb < 0 and we want xhat > 0) is what we expect to be given as "root".
    845 */
    846 assert(root < 0.0); /* root needs to be given */
    847 if( xref <= xlb * root )
    848 {
    849 /* If the reference point is left of xhat (=xlb*root), then we can take the
    850 * secant between xlb and root*xlb (= tangent at root*xlb).
    851 * However, if xub < root*xlb, then we can tilt the estimator to be the secant between xlb and xub.
    852 */
    853 computeSecant(scip, FALSE, exponent, xlb, MIN(xlb * root, xub), constant, slope, success);
    854 *islocal = TRUE;
    855 }
    856 else
    857 {
    858 /* If reference point is right of xhat, then take the tangent at xref.
    859 * This will still be underestimating for x in [xlb,0], too.
    860 * The tangent is globally valid, if we had also generated w.r.t. global bounds.
    861 */
    862 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
    863 *islocal = xref < xlbglobal * root;
    864 *branchcand = FALSE;
    865 }
    866 }
    867 }
    868 }
    869 else
    870 {
    871 /* overestimate and mixed sign -> pole is within domain -> cannot overestimate */
    872 if( xlb < 0.0 && xub > 0.0 )
    873 return;
    874
    875 /* overestimate and fixed sign -> secant */
    876 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
    877 *islocal = TRUE;
    878 }
    879}
    880
    881/** Separation for mixed-sign hyperbola
    882 *
    883 * - x^-1, x^-3, x^-5 without x >= 0 (either x arbitrary or x negative)
    884 <pre>
    885 +----------------------------------------------------------------------+
    886 | + * + |
    887 4 |-+ * x**(-1) *******-|
    888 | * |
    889 | * |
    890 | * |
    891 2 |-+ * +-|
    892 | * |
    893 | ** |
    894 | ********* |
    895 0 |********************* *********************|
    896 | ********* |
    897 | ** |
    898 | * |
    899 -2 |-+ * +-|
    900 | * |
    901 | * |
    902 | * |
    903 -4 |-+ * +-|
    904 | + *+ + |
    905 +----------------------------------------------------------------------+
    906 -10 -5 0 5 10
    907 </pre>
    908 */
    909static
    911 SCIP* scip, /**< SCIP data structure */
    912 SCIP_Real exponent, /**< exponent */
    913 SCIP_Bool overestimate, /**< should the power be overestimated? */
    914 SCIP_Real xlb, /**< lower bound on x */
    915 SCIP_Real xub, /**< upper bound on x */
    916 SCIP_Real xref, /**< reference point (where to linearize) */
    917 SCIP_Real xlbglobal, /**< global lower bound on x */
    918 SCIP_Real xubglobal, /**< global upper bound on x */
    919 SCIP_Real* constant, /**< buffer to store constant term of estimator */
    920 SCIP_Real* slope, /**< buffer to store slope of estimator */
    921 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
    922 it depends on given bounds */
    923 SCIP_Bool* branchcand, /**< buffer to indicate whether estimator would improve by branching
    924 on it */
    925 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
    926 )
    927{
    928 assert(scip != NULL);
    929 assert(constant != NULL);
    930 assert(slope != NULL);
    931 assert(islocal != NULL);
    932 assert(branchcand != NULL);
    933 assert(*branchcand == TRUE); /* the default */
    934 assert(success != NULL);
    935 assert(exponent < 0.0);
    936 assert(EPSISINT((exponent-1.0)/2.0, 0.0));
    937 assert(xlb < 0.0);
    938
    939 *success = FALSE;
    940
    941 if( xub <= 0.0 )
    942 {
    943 /* x is negative */
    944 if( !overestimate )
    945 {
    946 /* underestimation -> secant */
    947 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
    948 *islocal = TRUE;
    949 }
    950 else if( !SCIPisZero(scip, xlb/10.0) )
    951 {
    952 /* overestimation -> tangent */
    953
    954 /* need to linearize left of 0 */
    955 if( xref > 0.0 )
    956 xref = 0.0;
    957
    958 if( SCIPisZero(scip, xref) )
    959 {
    960 /* if xref is very close to 0.0, then slope would be infinite
    961 * try to move closer to lower bound (if xlb < -10*eps)
    962 */
    963 if( !SCIPisInfinity(scip, -xlb) )
    964 xref = 0.1*xlb + 0.9*xub;
    965 else
    966 xref = 0.1;
    967 }
    968
    969 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
    970
    971 /* if x does not have a fixed sign globally, then our tangent is not globally valid
    972 * (power is not convex on global domain)
    973 */
    974 *islocal = xlbglobal * xubglobal < 0.0;
    975
    976 /* tangent doesn't move by branching */
    977 *branchcand = FALSE;
    978 }
    979 /* else: xlb is very close to zero, xub is <= 0, so slope would be infinite
    980 * (for any reference point in [xlb, xub]) -> do not estimate
    981 */
    982 }
    983 /* else: x has mixed sign -> pole is within domain -> cannot estimate */
    984}
    985
    986/** builds an estimator for a power function */
    987static
    989 SCIP* scip, /**< SCIP data structure */
    990 SCIP_EXPRDATA* exprdata, /**< expression data */
    991 SCIP_Bool overestimate, /**< is this an overestimator? */
    992 SCIP_Real childlb, /**< local lower bound on the child */
    993 SCIP_Real childub, /**< local upper bound on the child */
    994 SCIP_Real childglb, /**< global lower bound on the child */
    995 SCIP_Real childgub, /**< global upper bound on the child */
    996 SCIP_Bool childintegral, /**< whether child is integral */
    997 SCIP_Real refpoint, /**< reference point */
    998 SCIP_Real exponent, /**< esponent */
    999 SCIP_Real* coef, /**< pointer to store the coefficient of the estimator */
    1000 SCIP_Real* constant, /**< pointer to store the constant of the estimator */
    1001 SCIP_Bool* success, /**< pointer to store whether the estimator was built successfully */
    1002 SCIP_Bool* islocal, /**< pointer to store whether the estimator is valid w.r.t. local bounds
    1003 * only */
    1004 SCIP_Bool* branchcand /**< pointer to indicate whether to consider child for branching
    1005 * (initialized to TRUE) */
    1006 )
    1007{
    1008 SCIP_Bool isinteger;
    1009 SCIP_Bool iseven;
    1010
    1011 assert(scip != NULL);
    1012 assert(exprdata != NULL);
    1013 assert(coef != NULL);
    1014 assert(constant != NULL);
    1015 assert(success != NULL);
    1016 assert(islocal != NULL);
    1017 assert(branchcand != NULL);
    1018
    1019 isinteger = EPSISINT(exponent, 0.0);
    1020 iseven = isinteger && EPSISINT(exponent / 2.0, 0.0);
    1021
    1022 if( exponent == 2.0 )
    1023 {
    1024 /* important special case: quadratic case */
    1025 /* initialize, because SCIPaddSquareXyz only adds to existing values */
    1026 *success = TRUE;
    1027 *coef = 0.0;
    1028 *constant = 0.0;
    1029
    1030 if( overestimate )
    1031 {
    1032 SCIPaddSquareSecant(scip, 1.0, childlb, childub, coef, constant, success);
    1033 *islocal = TRUE; /* secants are only valid locally */
    1034 }
    1035 else
    1036 {
    1037 SCIPaddSquareLinearization(scip, 1.0, refpoint, childintegral, coef, constant, success);
    1038 *islocal = FALSE; /* linearizations are globally valid */
    1039 *branchcand = FALSE; /* there is no improvement due to branching */
    1040 }
    1041 }
    1042 else if( exponent > 0.0 && iseven )
    1043 {
    1044 estimateParabola(scip, exponent, overestimate, childlb, childub, refpoint, constant, coef, islocal, success);
    1045 /* if estimate is locally valid, then we computed a secant and so branching can improve it */
    1046 *branchcand = *islocal;
    1047 }
    1048 else if( exponent > 1.0 && childlb >= 0.0 )
    1049 {
    1050 /* make sure we linearize in convex region (if we will linearize) */
    1051 if( refpoint < 0.0 )
    1052 refpoint = 0.0;
    1053
    1054 estimateParabola(scip, exponent, overestimate, childlb, childub, refpoint, constant, coef, islocal, success);
    1055
    1056 /* if estimate is locally valid, then we computed a secant and so branching can improve it */
    1057 *branchcand = *islocal;
    1058
    1059 /* if odd power, then check whether tangent on parabola is also globally valid, that is reference point is
    1060 * right of -root*global-lower-bound
    1061 */
    1062 if( !*islocal && !iseven && childglb < 0.0 )
    1063 {
    1064 if( SCIPisInfinity(scip, -childglb) )
    1065 *islocal = TRUE;
    1066 else
    1067 {
    1068 if( exprdata->root == SCIP_INVALID )
    1069 {
    1070 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
    1071 }
    1072 *islocal = refpoint < exprdata->root * (-childglb);
    1073 }
    1074 }
    1075 }
    1076 else if( exponent > 1.0 ) /* and !iseven && childlb < 0.0 due to previous if */
    1077 {
    1078 /* compute root if not known yet; only needed if mixed sign (global child ub > 0) */
    1079 if( exprdata->root == SCIP_INVALID && childgub > 0.0 )
    1080 {
    1081 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
    1082 }
    1083 estimateSignedpower(scip, exponent, exprdata->root, overestimate, childlb, childub, refpoint,
    1084 -childglb, childgub, constant, coef, islocal, branchcand, success);
    1085 }
    1086 else if( exponent < 0.0 && (iseven || childlb >= 0.0) )
    1087 {
    1088 /* compute root if not known yet; only needed if mixed sign (globally) and iseven */
    1089 if( exprdata->root == SCIP_INVALID && iseven )
    1090 {
    1091 SCIP_CALL( computeHyperbolaRoot(scip, &exprdata->root, exponent) );
    1092 }
    1093 estimateHyperbolaPositive(scip, exponent, exprdata->root, overestimate, childlb, childub, refpoint,
    1094 childglb, childgub, constant, coef, islocal, branchcand, success);
    1095 }
    1096 else if( exponent < 0.0 )
    1097 {
    1098 assert(!iseven); /* should hold due to previous if */
    1099 assert(childlb < 0.0); /* should hold due to previous if */
    1100 assert(isinteger); /* should hold because childlb < 0.0 (same as assert above) */
    1101
    1102 estimateHyperbolaMixed(scip, exponent, overestimate, childlb, childub, refpoint, childglb, childgub,
    1103 constant, coef, islocal, branchcand, success);
    1104 }
    1105 else
    1106 {
    1107 assert(exponent < 1.0); /* the only case that should be left */
    1108 assert(exponent > 0.0); /* should hold due to previous if */
    1109
    1110 SCIPestimateRoot(scip, exponent, overestimate, childlb, childub, refpoint, constant, coef, islocal, success);
    1111
    1112 /* if estimate is locally valid, then we computed a secant, and so branching can improve it */
    1113 *branchcand = *islocal;
    1114 }
    1115
    1116 return SCIP_OKAY;
    1117}
    1118
    1119/** fills an array of reference points for estimating on the convex side */
    1120static
    1122 SCIP* scip, /**< SCIP data structure */
    1123 SCIP_Real exponent, /**< exponent of the power expression */
    1124 SCIP_Real lb, /**< lower bound on the child variable */
    1125 SCIP_Real ub, /**< upper bound on the child variable */
    1126 SCIP_Real* refpoints /**< array to store the reference points */
    1127 )
    1128{
    1129 SCIP_Real maxabsbnd;
    1130
    1131 assert(refpoints != NULL);
    1132
    1133 maxabsbnd = pow(INITLPMAXPOWVAL, 1 / exponent);
    1134
    1135 /* make sure the absolute values of bounds are not too large */
    1136 if( ub > -maxabsbnd )
    1137 lb = MAX(lb, -maxabsbnd);
    1138 if( lb < maxabsbnd )
    1139 ub = MIN(ub, maxabsbnd);
    1140
    1141 /* in the case when ub < -maxabsbnd or lb > maxabsbnd, we still want to at least make bounds finite */
    1142 if( SCIPisInfinity(scip, -lb) )
    1143 lb = MIN(-10.0, ub - 0.1*REALABS(ub)); /*lint !e666 */
    1144 if( SCIPisInfinity(scip, ub) )
    1145 ub = MAX( 10.0, lb + 0.1*REALABS(lb)); /*lint !e666 */
    1146
    1147 refpoints[0] = (7.0 * lb + ub) / 8.0;
    1148 refpoints[1] = (lb + ub) / 2.0;
    1149 refpoints[2] = (lb + 7.0 * ub) / 8.0;
    1150}
    1151
    1152/** fills an array of reference points for sign(x)*abs(x)^n or x^n (n odd), where x has mixed signs
    1153 *
    1154 * The reference points are: the lower and upper bounds (one for secant and one for tangent);
    1155 * and for the second tangent, the point on the convex part of the function between the point
    1156 * deciding between tangent and secant, and the corresponding bound
    1157 */
    1158static
    1160 SCIP* scip, /**< SCIP data structure */
    1161 SCIP_EXPRDATA* exprdata, /**< expression data */
    1162 SCIP_Real lb, /**< lower bound on the child variable */
    1163 SCIP_Real ub, /**< upper bound on the child variable */
    1164 SCIP_Real exponent, /**< exponent */
    1165 SCIP_Bool underestimate, /**< are the refpoints for an underestimator */
    1166 SCIP_Real* refpoints /**< array to store the reference points */
    1167 )
    1168{
    1169 assert(refpoints != NULL);
    1170
    1171 if( (underestimate && SCIPisInfinity(scip, -lb)) || (!underestimate && SCIPisInfinity(scip, ub)) )
    1172 return SCIP_OKAY;
    1173
    1174 if( exprdata->root == SCIP_INVALID )
    1175 {
    1176 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
    1177 }
    1178
    1179 /* make bounds finite (due to a previous if, only one can be infinite here) */
    1180 if( SCIPisInfinity(scip, -lb) )
    1181 lb = -ub * exprdata->root - 1.0;
    1182 else if( SCIPisInfinity(scip, ub) )
    1183 ub = -lb * exprdata->root + 1.0;
    1184
    1185 if( underestimate )
    1186 {
    1187 /* secant point */
    1188 refpoints[0] = lb;
    1189
    1190 /* tangent points, depending on the special point */
    1191 if( -lb * exprdata->root < ub - 2.0 )
    1192 refpoints[2] = ub;
    1193 if( -lb * exprdata->root < ub - 4.0 )
    1194 refpoints[1] = (-lb * exprdata->root + ub) / 2.0;
    1195 }
    1196
    1197 if( !underestimate )
    1198 {
    1199 /* secant point */
    1200 refpoints[2] = ub;
    1201
    1202 /* tangent points, depending on the special point */
    1203 if( -ub * exprdata->root > lb + 2.0 )
    1204 refpoints[0] = lb;
    1205 if( -ub * exprdata->root > lb + 4.0 )
    1206 refpoints[1] = (lb - ub * exprdata->root) / 2.0;
    1207 }
    1208
    1209 return SCIP_OKAY;
    1210}
    1211
    1212/** choose reference points for adding initestimates cuts for a power expression */
    1213static
    1215 SCIP* scip, /**< SCIP data structure */
    1216 SCIP_EXPRDATA* exprdata, /**< expression data */
    1217 SCIP_Real lb, /**< lower bound on the child variable */
    1218 SCIP_Real ub, /**< upper bound on the child variable */
    1219 SCIP_Real* refpointsunder, /**< array to store reference points for underestimators */
    1220 SCIP_Real* refpointsover, /**< array to store reference points for overestimators */
    1221 SCIP_Bool underestimate, /**< whether refpoints for underestimation are needed */
    1222 SCIP_Bool overestimate /**< whether refpoints for overestimation are needed */
    1223 )
    1224{
    1225 SCIP_Bool convex;
    1226 SCIP_Bool concave;
    1227 SCIP_Bool mixedsign;
    1228 SCIP_Bool even;
    1229 SCIP_Real exponent;
    1230
    1231 assert(scip != NULL);
    1232 assert(exprdata != NULL);
    1233 assert(refpointsunder != NULL && refpointsover != NULL);
    1234
    1235 exponent = exprdata->exponent;
    1236 even = EPSISINT(exponent, 0.0) && EPSISINT(exponent / 2.0, 0.0);
    1237
    1238 convex = FALSE;
    1239 concave = FALSE;
    1240 mixedsign = lb < 0.0 && ub > 0.0;
    1241
    1242 /* convex case:
    1243 * - parabola with an even degree or positive domain
    1244 * - hyperbola with a positive domain
    1245 * - even hyperbola with a negative domain
    1246 */
    1247 if( (exponent > 1.0 && (lb >= 0 || even)) || (exponent < 0.0 && lb >= 0) || (exponent < 0.0 && even && ub <= 0.0) )
    1248 convex = TRUE;
    1249 /* concave case:
    1250 * - parabola or hyperbola with a negative domain and (due to previous if) an uneven degree
    1251 * - root
    1252 */
    1253 else if( ub <= 0 || (exponent > 0.0 && exponent < 1.0) )
    1254 concave = TRUE;
    1255
    1256 if( underestimate )
    1257 {
    1258 if( convex )
    1259 addTangentRefpoints(scip, exponent, lb, ub, refpointsunder);
    1260 else if( (concave && !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub)) ||
    1261 (exponent < 0.0 && even && mixedsign) ) /* concave with finite bounds or mixed even hyperbola */
    1262 {
    1263 /* for secant, refpoint doesn't matter, but we add it to signal that the corresponding cut should be created */
    1264 refpointsunder[0] = (lb + ub) / 2.0;
    1265 }
    1266 else if( exponent > 1.0 && !even && mixedsign ) /* mixed signpower */
    1267 {
    1268 SCIP_CALL( addSignpowerRefpoints(scip, exprdata, lb, ub, exponent, TRUE, refpointsunder) );
    1269 }
    1270 else /* mixed odd hyperbola or an infinite bound */
    1271 assert((exponent < 0.0 && !even && mixedsign) || SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub));
    1272 }
    1273
    1274 if( overestimate )
    1275 {
    1276 if( convex && !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
    1277 refpointsover[0] = (lb + ub) / 2.0;
    1278 else if( concave )
    1279 addTangentRefpoints(scip, exponent, lb, ub, refpointsover);
    1280 else if( exponent > 1.0 && !even && mixedsign ) /* mixed signpower */
    1281 {
    1282 SCIP_CALL( addSignpowerRefpoints(scip, exprdata, lb, ub, exponent, FALSE, refpointsover) );
    1283 }
    1284 else /* mixed hyperbola or an infinite bound */
    1285 assert((exponent < 0.0 && mixedsign) || SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub));
    1286 }
    1287
    1288 return SCIP_OKAY;
    1289}
    1290
    1291
    1292/*
    1293 * Callback methods of expression handler
    1294 */
    1295
    1296/** compares two power expressions
    1297 *
    1298 * the order of two power (normal or signed) is base_1^expo_1 < base_2^expo_2 if and only if
    1299 * base_1 < base2 or, base_1 = base_2 and expo_1 < expo_2
    1300 */
    1301static
    1303{ /*lint --e{715}*/
    1304 SCIP_Real expo1;
    1305 SCIP_Real expo2;
    1306 int compareresult;
    1307
    1308 /**! [SnippetExprComparePow] */
    1309 compareresult = SCIPcompareExpr(scip, SCIPexprGetChildren(expr1)[0], SCIPexprGetChildren(expr2)[0]);
    1310 if( compareresult != 0 )
    1311 return compareresult;
    1312
    1313 expo1 = SCIPgetExponentExprPow(expr1);
    1314 expo2 = SCIPgetExponentExprPow(expr2);
    1315
    1316 return expo1 == expo2 ? 0 : expo1 < expo2 ? -1 : 1;
    1317 /**! [SnippetExprComparePow] */
    1318}
    1319
    1320/** simplifies a pow expression
    1321 *
    1322 * Evaluates the power function when its child is a value expression
    1323 */
    1324static
    1326{ /*lint --e{715}*/
    1327 SCIP_EXPRHDLR* exprhdlr;
    1328 SCIP_EXPRHDLRDATA* exprhdlrdata;
    1329 SCIP_EXPR* base;
    1330 SCIP_Real exponent;
    1331
    1332 assert(scip != NULL);
    1333 assert(expr != NULL);
    1334 assert(simplifiedexpr != NULL);
    1335 assert(SCIPexprGetNChildren(expr) == 1);
    1336
    1337 exprhdlr = SCIPexprGetHdlr(expr);
    1338 assert(exprhdlr != NULL);
    1339
    1340 exprhdlrdata = SCIPexprhdlrGetData(exprhdlr);
    1341 assert(exprhdlrdata != NULL);
    1342
    1343 base = SCIPexprGetChildren(expr)[0];
    1344 assert(base != NULL);
    1345
    1346 exponent = SCIPgetExponentExprPow(expr);
    1347
    1348 SCIPdebugPrintf("[simplifyPow] simplifying power with expo %g\n", exponent);
    1349
    1350 /* enforces POW1 */
    1351 if( exponent == 0.0 )
    1352 {
    1353 SCIPdebugPrintf("[simplifyPow] POW1\n");
    1354 /* TODO: more checks? */
    1355 assert(!SCIPisExprValue(scip, base) || SCIPgetValueExprValue(base) != 0.0);
    1356 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, 1.0, ownercreate, ownercreatedata) );
    1357 return SCIP_OKAY;
    1358 }
    1359
    1360 /* enforces POW2 */
    1361 if( exponent == 1.0 )
    1362 {
    1363 SCIPdebugPrintf("[simplifyPow] POW2\n");
    1364 *simplifiedexpr = base;
    1365 SCIPcaptureExpr(*simplifiedexpr);
    1366 return SCIP_OKAY;
    1367 }
    1368
    1369 /* enforces POW3 */
    1370 if( SCIPisExprValue(scip, base) )
    1371 {
    1372 SCIP_Real baseval;
    1373
    1374 SCIPdebugPrintf("[simplifyPow] POW3\n");
    1375 baseval = SCIPgetValueExprValue(base);
    1376
    1377 /* the assert below was failing on st_e35 for baseval=-1e-15 and fractional exponent
    1378 * in the subNLP heuristic; I assume that this was because baseval was evaluated after
    1379 * variable fixings and that there were just floating-point inaccuracies and 0 was meant,
    1380 * so I treat -1e-15 as 0 here
    1381 */
    1382 if( baseval < 0.0 && fmod(exponent, 1.0) != 0.0 && baseval > -SCIPepsilon(scip) )
    1383 baseval = 0.0;
    1384
    1385 /* TODO check if those are all important asserts */
    1386 assert(baseval >= 0.0 || fmod(exponent, 1.0) == 0.0);
    1387 assert(baseval != 0.0 || exponent != 0.0);
    1388
    1389 if( baseval != 0.0 || exponent > 0.0 )
    1390 {
    1391 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, pow(baseval, exponent), ownercreate, ownercreatedata) );
    1392 return SCIP_OKAY;
    1393 }
    1394 }
    1395
    1396 /* enforces POW11 (exp(x)^n = exp(n*x)) */
    1397 if( SCIPisExprExp(scip, base) )
    1398 {
    1399 SCIP_EXPR* child;
    1400 SCIP_EXPR* prod;
    1401 SCIP_EXPR* exponential;
    1402 SCIP_EXPR* simplifiedprod;
    1403
    1404 SCIPdebugPrintf("[simplifyPow] POW11\n");
    1405 child = SCIPexprGetChildren(base)[0];
    1406
    1407 /* multiply child of exponential with exponent */
    1408 SCIP_CALL( SCIPcreateExprProduct(scip, &prod, 1, &child, exponent, ownercreate, ownercreatedata) );
    1409
    1410 /* simplify product */
    1411 SCIP_CALL( SCIPcallExprSimplify(scip, prod, &simplifiedprod, ownercreate, ownercreatedata) );
    1412 SCIP_CALL( SCIPreleaseExpr(scip, &prod) );
    1413
    1414 /* create exponential with new child */
    1415 SCIP_CALL( SCIPcreateExprExp(scip, &exponential, simplifiedprod, ownercreate, ownercreatedata) );
    1416 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedprod) );
    1417
    1418 /* the final simplified expression is the simplification of the just created exponential */
    1419 SCIP_CALL( SCIPcallExprSimplify(scip, exponential, simplifiedexpr, ownercreate, ownercreatedata) );
    1420 SCIP_CALL( SCIPreleaseExpr(scip, &exponential) );
    1421
    1422 return SCIP_OKAY;
    1423 }
    1424
    1425 /* enforces POW10 */
    1426 if( SCIPisExprVar(scip, base) )
    1427 {
    1428 SCIP_VAR* basevar;
    1429
    1430 SCIPdebugPrintf("[simplifyPow] POW10\n");
    1431 basevar = SCIPgetVarExprVar(base);
    1432
    1433 assert(basevar != NULL);
    1434
    1435 /* TODO: if exponent is negative, we could fix the binary variable to 1. However, this is a bit tricky because
    1436 * variables can not be tighten in EXITPRE, where the simplify is also called
    1437 */
    1438 if( SCIPvarIsBinary(basevar) && exponent > 0.0 )
    1439 {
    1440 *simplifiedexpr = base;
    1441 SCIPcaptureExpr(*simplifiedexpr);
    1442 return SCIP_OKAY;
    1443 }
    1444 }
    1445
    1446 if( EPSISINT(exponent, 0.0) )
    1447 {
    1448 SCIP_EXPR* aux;
    1449 SCIP_EXPR* simplifiedaux;
    1450
    1451 /* enforces POW12 (abs(x)^n = x^n if n is even) */
    1452 if( SCIPisExprAbs(scip, base) && (int)exponent % 2 == 0 )
    1453 {
    1454 SCIP_EXPR* newpow;
    1455
    1456 SCIPdebugPrintf("[simplifyPow] POWXX\n");
    1457
    1458 SCIP_CALL( SCIPcreateExprPow(scip, &newpow, SCIPexprGetChildren(base)[0], exponent, ownercreate, ownercreatedata) );
    1459 SCIP_CALL( simplifyPow(scip, newpow, simplifiedexpr, ownercreate, ownercreatedata) );
    1460 SCIP_CALL( SCIPreleaseExpr(scip, &newpow) );
    1461
    1462 return SCIP_OKAY;
    1463 }
    1464
    1465 /* enforces POW5
    1466 * given (pow n (prod 1.0 expr_1 ... expr_k)) we distribute the exponent:
    1467 * -> (prod 1.0 (pow n expr_1) ... (pow n expr_k))
    1468 * notes: - since base is simplified and its coefficient is 1.0 (SP8)
    1469 * - n is an integer (excluding 1 and 0; see POW1-2 above)
    1470 */
    1471 if( SCIPisExprProduct(scip, base) )
    1472 {
    1473 SCIP_EXPR* auxproduct;
    1474 int i;
    1475
    1476 /* create empty product */
    1477 SCIP_CALL( SCIPcreateExprProduct(scip, &auxproduct, 0, NULL, 1.0, ownercreate, ownercreatedata) );
    1478
    1479 for( i = 0; i < SCIPexprGetNChildren(base); ++i )
    1480 {
    1481 /* create (pow n expr_i) and simplify */
    1482 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[i], exponent, ownercreate, ownercreatedata) );
    1483 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
    1484 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1485
    1486 /* append (pow n expr_i) to product */
    1487 SCIP_CALL( SCIPappendExprChild(scip, auxproduct, simplifiedaux) );
    1488 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
    1489 }
    1490
    1491 /* simplify (prod 1.0 (pow n expr_1) ... (pow n expr_k))
    1492 * this calls simplifyProduct directly, since we know its children are simplified */
    1493 SCIP_CALL( SCIPcallExprSimplify(scip, auxproduct, simplifiedexpr, ownercreate, ownercreatedata) );
    1494 SCIP_CALL( SCIPreleaseExpr(scip, &auxproduct) );
    1495 return SCIP_OKAY;
    1496 }
    1497
    1498 /* enforces POW6
    1499 * given (pow n (sum 0.0 coef expr)) we can move `pow` inside `sum`:
    1500 * (pow n (sum 0.0 coef expr) ) -> (sum 0.0 coef^n (pow n expr))
    1501 * notes: - since base is simplified and its constant is 0, then coef != 1.0 (SS7)
    1502 * - n is an integer (excluding 1 and 0; see POW1-2 above)
    1503 */
    1504 if( SCIPisExprSum(scip, base) && SCIPexprGetNChildren(base) == 1 && SCIPgetConstantExprSum(base) == 0.0 )
    1505 {
    1506 SCIP_Real newcoef;
    1507
    1508 SCIPdebugPrintf("[simplifyPow] seeing a sum with one term, exponent %g\n", exponent);
    1509
    1510 /* assert SS7 holds */
    1511 assert(SCIPgetCoefsExprSum(base)[0] != 1.0);
    1512
    1513 /* create (pow n expr) and simplify it
    1514 * note: we call simplifyPow directly, since we know that `expr` is simplified */
    1515 newcoef = pow(SCIPgetCoefsExprSum(base)[0], exponent);
    1516 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[0], exponent, ownercreate, ownercreatedata) );
    1517 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
    1518 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1519
    1520 /* create (sum (pow n expr)) and simplify it
    1521 * this calls simplifySum directly, since we know its children are simplified */
    1522 SCIP_CALL( SCIPcreateExprSum(scip, &aux, 1, &simplifiedaux, &newcoef, 0.0, ownercreate, ownercreatedata) );
    1523 SCIP_CALL( SCIPcallExprSimplify(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
    1524 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1525 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
    1526 return SCIP_OKAY;
    1527 }
    1528
    1529 /* enforces POW7 for exponent 2
    1530 * (const + sum alpha_i expr_i)^2 = sum alpha_i^2 expr_i^2
    1531 * + sum_{j < i} 2*alpha_i alpha_j expr_i expr_j
    1532 * + sum const alpha_i expr_i
    1533 * TODO: put some limits on the number of children of the sum being expanded
    1534 */
    1535 if( SCIPisExprSum(scip, base) && exponent == 2.0 && exprhdlrdata->expandmaxexponent >= 2 )
    1536 {
    1537 int i;
    1538 int nchildren;
    1539 int nexpandedchildren;
    1540 SCIP_EXPR* expansion;
    1541 SCIP_EXPR** expandedchildren;
    1542 SCIP_Real* coefs;
    1543 SCIP_Real constant;
    1544
    1545 SCIPdebugPrintf("[simplifyPow] expanding sum^%g\n", exponent);
    1546
    1547 nchildren = SCIPexprGetNChildren(base);
    1548 nexpandedchildren = nchildren * (nchildren + 1) / 2 + nchildren;
    1549 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nexpandedchildren) );
    1550 SCIP_CALL( SCIPallocBufferArray(scip, &expandedchildren, nexpandedchildren) );
    1551
    1552 for( i = 0; i < nchildren; ++i )
    1553 {
    1554 int j;
    1555 SCIP_EXPR* expansionchild;
    1556 SCIP_EXPR* prodchildren[2];
    1557 prodchildren[0] = SCIPexprGetChildren(base)[i];
    1558
    1559 /* create and simplify expr_i * expr_j */
    1560 for( j = 0; j < i; ++j )
    1561 {
    1562 prodchildren[1] = SCIPexprGetChildren(base)[j];
    1563 coefs[i*(i+1)/2 + j] = 2 * SCIPgetCoefsExprSum(base)[i] * SCIPgetCoefsExprSum(base)[j];
    1564
    1565 SCIP_CALL( SCIPcreateExprProduct(scip, &expansionchild, 2, prodchildren, 1.0, ownercreate,
    1566 ownercreatedata) );
    1567 SCIP_CALL( SCIPcallExprSimplify(scip, expansionchild, &expandedchildren[i*(i+1)/2 + j],
    1568 ownercreate, ownercreatedata) ); /* this calls simplifyProduct */
    1569 SCIP_CALL( SCIPreleaseExpr(scip, &expansionchild) );
    1570 }
    1571 /* create and simplify expr_i * expr_i */
    1572 prodchildren[1] = SCIPexprGetChildren(base)[i];
    1573 coefs[i*(i+1)/2 + i] = SCIPgetCoefsExprSum(base)[i] * SCIPgetCoefsExprSum(base)[i];
    1574
    1575 SCIP_CALL( SCIPcreateExprProduct(scip, &expansionchild, 2, prodchildren, 1.0, ownercreate,
    1576 ownercreatedata) );
    1577 SCIP_CALL( SCIPcallExprSimplify(scip, expansionchild, &expandedchildren[i*(i+1)/2 + i], ownercreate,
    1578 ownercreatedata) ); /* this calls simplifyProduct */
    1579 SCIP_CALL( SCIPreleaseExpr(scip, &expansionchild) );
    1580 }
    1581 /* create const * alpha_i expr_i */
    1582 for( i = 0; i < nchildren; ++i )
    1583 {
    1584 coefs[i + nexpandedchildren - nchildren] = 2 * SCIPgetConstantExprSum(base) * SCIPgetCoefsExprSum(base)[i];
    1585 expandedchildren[i + nexpandedchildren - nchildren] = SCIPexprGetChildren(base)[i];
    1586 }
    1587
    1588 constant = SCIPgetConstantExprSum(base);
    1589 constant *= constant;
    1590 /* create sum of all the above and simplify it with simplifySum since all of its children are simplified! */
    1591 SCIP_CALL( SCIPcreateExprSum(scip, &expansion, nexpandedchildren, expandedchildren, coefs, constant,
    1592 ownercreate, ownercreatedata) );
    1593 SCIP_CALL( SCIPcallExprSimplify(scip, expansion, simplifiedexpr, ownercreate,
    1594 ownercreatedata) ); /* this calls simplifySum */
    1595
    1596 /* release everything */
    1597 SCIP_CALL( SCIPreleaseExpr(scip, &expansion) );
    1598 /* release the *created* expanded children */
    1599 for( i = 0; i < nexpandedchildren - nchildren; ++i )
    1600 {
    1601 SCIP_CALL( SCIPreleaseExpr(scip, &expandedchildren[i]) );
    1602 }
    1603 SCIPfreeBufferArray(scip, &expandedchildren);
    1604 SCIPfreeBufferArray(scip, &coefs);
    1605
    1606 return SCIP_OKAY;
    1607 }
    1608
    1609 /* enforces POW7 for exponent > 2 */
    1610 if( SCIPisExprSum(scip, base) && exponent > 2.0 && exponent <= exprhdlrdata->expandmaxexponent )
    1611 {
    1612 SCIPdebugPrintf("[simplifyPow] expanding sum^%g\n", exponent);
    1613
    1614 SCIP_CALL( SCIPpowerExprSum(scip, simplifiedexpr, base, (int)exponent, TRUE, ownercreate, ownercreatedata) );
    1615
    1616 return SCIP_OKAY;
    1617 }
    1618 }
    1619 else
    1620 {
    1621 /* enforces POW9
    1622 *
    1623 * FIXME code of POW6 is very similar
    1624 */
    1625 if( SCIPexprGetNChildren(base) == 1
    1626 && SCIPisExprSum(scip, base)
    1627 && SCIPgetConstantExprSum(base) == 0.0
    1628 && SCIPgetCoefsExprSum(base)[0] >= 0.0 )
    1629 {
    1630 SCIP_EXPR* simplifiedaux;
    1631 SCIP_EXPR* aux;
    1632 SCIP_Real newcoef;
    1633
    1634 SCIPdebugPrintf("[simplifyPow] seeing a sum with one term, exponent %g\n", exponent);
    1635 /* assert SS7 holds */
    1636 assert(SCIPgetCoefsExprSum(base)[0] != 1.0);
    1637
    1638 /* create (pow n expr) and simplify it
    1639 * note: we call simplifyPow directly, since we know that `expr` is simplified */
    1640 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[0], exponent, ownercreate,
    1641 ownercreatedata) );
    1642 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
    1643 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1644
    1645 /* create (sum (pow n expr)) and simplify it
    1646 * this calls simplifySum directly, since we know its child is simplified! */
    1647 newcoef = pow(SCIPgetCoefsExprSum(base)[0], exponent);
    1648 SCIP_CALL( SCIPcreateExprSum(scip, &aux, 1, &simplifiedaux, &newcoef, 0.0, ownercreate,
    1649 ownercreatedata) );
    1650 SCIP_CALL( SCIPcallExprSimplify(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
    1651 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1652 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
    1653
    1654 return SCIP_OKAY;
    1655 }
    1656
    1657 /* enforces POW5a
    1658 * given (pow n (prod 1.0 expr_1 ... expr_k)) we distribute the exponent:
    1659 * -> (prod 1.0 (pow n expr_1) ... (pow n expr_k))
    1660 * notes: - since base is simplified and its coefficient is 1.0 (SP8)
    1661 * TODO we can enable this more often by default when simplify makes use of bounds on factors
    1662 */
    1663 if( exprhdlrdata->distribfracexponent && SCIPisExprProduct(scip, base) )
    1664 {
    1665 SCIP_EXPR* aux;
    1666 SCIP_EXPR* simplifiedaux;
    1667 SCIP_EXPR* auxproduct;
    1668 int i;
    1669
    1670 /* create empty product */
    1671 SCIP_CALL( SCIPcreateExprProduct(scip, &auxproduct, 0, NULL, 1.0, ownercreate, ownercreatedata) );
    1672
    1673 for( i = 0; i < SCIPexprGetNChildren(base); ++i )
    1674 {
    1675 /* create (pow n expr_i) and simplify */
    1676 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[i], exponent, ownercreate, ownercreatedata) );
    1677 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
    1678 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1679
    1680 /* append (pow n expr_i) to product */
    1681 SCIP_CALL( SCIPappendExprChild(scip, auxproduct, simplifiedaux) );
    1682 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
    1683 }
    1684
    1685 /* simplify (prod 1.0 (pow n expr_1) ... (pow n expr_k))
    1686 * this calls simplifyProduct directly, since we know its children are simplified */
    1687 SCIP_CALL( SCIPcallExprSimplify(scip, auxproduct, simplifiedexpr, ownercreate, ownercreatedata) );
    1688 SCIP_CALL( SCIPreleaseExpr(scip, &auxproduct) );
    1689 return SCIP_OKAY;
    1690 }
    1691 }
    1692
    1693 /* enforces POW8
    1694 * given (pow n (pow expo expr)) we distribute the exponent:
    1695 * -> (pow n*expo expr)
    1696 * notes: n is not 1 or 0, see POW1-2 above
    1697 */
    1698 if( SCIPisExprPower(scip, base) )
    1699 {
    1700 SCIP_Real newexponent;
    1701 SCIP_Real baseexponent;
    1702
    1703 baseexponent = SCIPgetExponentExprPow(base);
    1704 newexponent = baseexponent * exponent;
    1705
    1706 /* some checks (see POW8 definition in scip_expr.h) to make sure we don't loose an
    1707 * implicit SCIPexprGetChildren(base)[0] >= 0 constraint
    1708 *
    1709 * if newexponent is fractional, then we will still need expr >= 0
    1710 * if both exponents were integer, then we never required and will not require expr >= 0
    1711 * if base exponent was an even integer, then we did not require expr >= 0
    1712 * (but may need to use |expr|^newexponent)
    1713 */
    1714 if( !EPSISINT(newexponent, 0.0) ||
    1715 (EPSISINT(baseexponent, 0.0) && EPSISINT(exponent, 0.0)) ||
    1716 (EPSISINT(baseexponent, 0.0) && ((int)baseexponent) % 2 == 0) )
    1717 {
    1718 SCIP_EXPR* aux;
    1719
    1720 if( EPSISINT(baseexponent, 0.0) && ((int)baseexponent) % 2 == 0 &&
    1721 (!EPSISINT(newexponent, 0.0) || ((int)newexponent) % 2 == 1) )
    1722 {
    1723 /* If base exponent was even integer and new exponent will be fractional,
    1724 * then simplify to |expr|^newexponent to allow eval for expr < 0.
    1725 * If base exponent was even integer and new exponent will be odd integer,
    1726 * then simplify to |expr|^newexponent to preserve value for expr < 0.
    1727 */
    1728 SCIP_EXPR* simplifiedaux;
    1729
    1730 SCIP_CALL( SCIPcreateExprAbs(scip, &aux, SCIPexprGetChildren(base)[0], ownercreate, ownercreatedata) );
    1731 SCIP_CALL( SCIPcallExprSimplify(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
    1732 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1733 SCIP_CALL( SCIPcreateExprPow(scip, &aux, simplifiedaux, newexponent, ownercreate, ownercreatedata) );
    1734 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
    1735 }
    1736 else
    1737 {
    1738 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[0], newexponent, ownercreate,
    1739 ownercreatedata) );
    1740 }
    1741
    1742 SCIP_CALL( simplifyPow(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
    1743 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1744
    1745 return SCIP_OKAY;
    1746 }
    1747 }
    1748
    1749 SCIPdebugPrintf("[simplifyPow] power is simplified\n");
    1750 *simplifiedexpr = expr;
    1751
    1752 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    1753 SCIPcaptureExpr(*simplifiedexpr);
    1754
    1755 return SCIP_OKAY;
    1756}
    1757
    1758/** expression callback to get information for symmetry detection */
    1759static
    1761{ /*lint --e{715}*/
    1762 SCIP_EXPRDATA* exprdata;
    1763
    1764 assert(scip != NULL);
    1765 assert(expr != NULL);
    1766
    1767 exprdata = SCIPexprGetData(expr);
    1768 assert(exprdata != NULL);
    1769
    1770 SCIP_CALL( SCIPallocBlockMemory(scip, symdata) );
    1771
    1772 (*symdata)->nconstants = 1;
    1773 (*symdata)->ncoefficients = 0;
    1774
    1775 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*symdata)->constants, 1) );
    1776 (*symdata)->constants[0] = exprdata->exponent;
    1777
    1778 return SCIP_OKAY;
    1779}
    1780
    1781/** expression handler copy callback */
    1782static
    1784{ /*lint --e{715}*/
    1786
    1787 return SCIP_OKAY;
    1788}
    1789
    1790/** expression handler free callback */
    1791static
    1793{ /*lint --e{715}*/
    1794 assert(exprhdlrdata != NULL);
    1795 assert(*exprhdlrdata != NULL);
    1796
    1797 SCIPfreeBlockMemory(scip, exprhdlrdata);
    1798
    1799 return SCIP_OKAY;
    1800}
    1801
    1802/** expression data copy callback */
    1803static
    1805{ /*lint --e{715}*/
    1806 SCIP_EXPRDATA* sourceexprdata;
    1807
    1808 assert(targetexprdata != NULL);
    1809 assert(sourceexpr != NULL);
    1810
    1811 sourceexprdata = SCIPexprGetData(sourceexpr);
    1812 assert(sourceexprdata != NULL);
    1813
    1814 *targetexprdata = NULL;
    1815
    1816 SCIP_CALL( createData(targetscip, targetexprdata, sourceexprdata->exponent) );
    1817
    1818 return SCIP_OKAY;
    1819}
    1820
    1821/** expression data free callback */
    1822static
    1824{ /*lint --e{715}*/
    1825 SCIP_EXPRDATA* exprdata;
    1826
    1827 assert(expr != NULL);
    1828
    1829 exprdata = SCIPexprGetData(expr);
    1830 assert(exprdata != NULL);
    1831
    1832 SCIPfreeBlockMemory(scip, &exprdata);
    1833 SCIPexprSetData(expr, NULL);
    1834
    1835 return SCIP_OKAY;
    1836}
    1837
    1838/** expression print callback */
    1839/** @todo: use precedence for better printing */
    1840static
    1842{ /*lint --e{715}*/
    1843 assert(expr != NULL);
    1844
    1845 /**! [SnippetExprPrintPow] */
    1846 switch( stage )
    1847 {
    1849 {
    1850 /* print function with opening parenthesis */
    1851 SCIPinfoMessage(scip, file, "(");
    1852 break;
    1853 }
    1854
    1856 {
    1857 assert(currentchild == 0);
    1858 break;
    1859 }
    1860
    1862 {
    1863 SCIP_Real exponent = SCIPgetExponentExprPow(expr);
    1864
    1865 /* print closing parenthesis */
    1866 if( exponent >= 0.0 )
    1867 SCIPinfoMessage(scip, file, ")^%.15g", exponent);
    1868 else
    1869 SCIPinfoMessage(scip, file, ")^(%.15g)", exponent);
    1870
    1871 break;
    1872 }
    1873
    1875 default:
    1876 break;
    1877 }
    1878 /**! [SnippetExprPrintPow] */
    1879
    1880 return SCIP_OKAY;
    1881}
    1882
    1883/** expression point evaluation callback */
    1884static
    1886{ /*lint --e{715}*/
    1887 SCIP_Real exponent;
    1888 SCIP_Real base;
    1889
    1890 assert(expr != NULL);
    1891 assert(SCIPexprGetNChildren(expr) == 1);
    1893
    1894 exponent = SCIPgetExponentExprPow(expr);
    1896
    1897 *val = pow(base, exponent);
    1898
    1899 /* if there is a domain, pole, or range error, pow() should return some kind of NaN, infinity, or HUGE_VAL
    1900 * we could also work with floating point exceptions or errno, but I am not sure this would be thread-safe
    1901 */
    1902 if( !SCIPisFinite(*val) || *val == HUGE_VAL || *val == -HUGE_VAL )
    1903 *val = SCIP_INVALID;
    1904
    1905 return SCIP_OKAY;
    1906}
    1907
    1908/** derivative evaluation callback
    1909 *
    1910 * computes <gradient, children.dot>
    1911 * if expr is child^p, then computes
    1912 * p child^(p-1) dot(child)
    1913 */
    1914static
    1916{ /*lint --e{715}*/
    1917 SCIP_EXPR* child;
    1918 SCIP_Real exponent;
    1919
    1920 assert(expr != NULL);
    1921 assert(SCIPexprGetData(expr) != NULL);
    1922 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID);
    1923
    1924 child = SCIPexprGetChildren(expr)[0];
    1925 assert(child != NULL);
    1926 assert(!SCIPisExprValue(scip, child));
    1927 assert(SCIPexprGetDot(child) != SCIP_INVALID);
    1928
    1929 exponent = SCIPgetExponentExprPow(expr);
    1930 assert(exponent != 0.0);
    1931
    1932 /* x^exponent is not differentiable for x = 0 and exponent in ]0,1[ */
    1933 if( exponent > 0.0 && exponent < 1.0 && SCIPexprGetEvalValue(child) == 0.0 )
    1934 *dot = SCIP_INVALID;
    1935 else
    1936 *dot = exponent * pow(SCIPexprGetEvalValue(child), exponent - 1.0) * SCIPexprGetDot(child);
    1937
    1938 return SCIP_OKAY;
    1939}
    1940
    1941/** expression backward forward derivative evaluation callback
    1942 *
    1943 * computes partial/partial child ( <gradient, children.dot> )
    1944 * if expr is child^n, then computes
    1945 * n * (n - 1) child^(n-2) dot(child)
    1946 */
    1947static
    1949{ /*lint --e{715}*/
    1950 SCIP_EXPR* child;
    1951 SCIP_Real exponent;
    1952
    1953 assert(expr != NULL);
    1954 assert(SCIPexprGetData(expr) != NULL);
    1955 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID);
    1956 assert(childidx == 0);
    1957
    1958 child = SCIPexprGetChildren(expr)[0];
    1959 assert(child != NULL);
    1960 assert(!SCIPisExprValue(scip, child));
    1961 assert(SCIPexprGetDot(child) != SCIP_INVALID);
    1962
    1963 exponent = SCIPgetExponentExprPow(expr);
    1964 assert(exponent != 0.0);
    1965
    1966 /* x^exponent is not twice differentiable for x = 0 and exponent in ]0,1[ u ]1,2[ */
    1967 if( exponent > 0.0 && exponent < 2.0 && SCIPexprGetEvalValue(child) == 0.0 && exponent != 1.0 )
    1968 *bardot = SCIP_INVALID;
    1969 else
    1970 *bardot = exponent * (exponent - 1.0) * pow(SCIPexprGetEvalValue(child), exponent - 2.0) * SCIPexprGetDot(child);
    1971
    1972 return SCIP_OKAY;
    1973}
    1974
    1975/** expression derivative evaluation callback */
    1976static
    1978{ /*lint --e{715}*/
    1979 SCIP_EXPR* child;
    1980 SCIP_Real childval;
    1981 SCIP_Real exponent;
    1982
    1983 assert(expr != NULL);
    1984 assert(SCIPexprGetData(expr) != NULL);
    1985 assert(childidx == 0);
    1986
    1987 child = SCIPexprGetChildren(expr)[0];
    1988 assert(child != NULL);
    1989 assert(!SCIPisExprValue(scip, child));
    1990
    1991 childval = SCIPexprGetEvalValue(child);
    1992 assert(childval != SCIP_INVALID);
    1993
    1994 exponent = SCIPgetExponentExprPow(expr);
    1995 assert(exponent != 0.0);
    1996
    1997 /* x^exponent is not differentiable for x = 0 and exponent in ]0,1[ */
    1998 if( exponent > 0.0 && exponent < 1.0 && childval == 0.0 )
    1999 *val = SCIP_INVALID;
    2000 else
    2001 *val = exponent * pow(childval, exponent - 1.0);
    2002
    2003 return SCIP_OKAY;
    2004}
    2005
    2006/** expression interval evaluation callback */
    2007static
    2009{ /*lint --e{715}*/
    2010 SCIP_INTERVAL childinterval;
    2011 SCIP_Real exponent;
    2012
    2013 assert(expr != NULL);
    2014 assert(SCIPexprGetNChildren(expr) == 1);
    2015
    2016 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    2017
    2018 exponent = SCIPgetExponentExprPow(expr);
    2019
    2020 if( exponent < 0.0 )
    2021 {
    2022 SCIP_EXPRHDLRDATA* exprhdlrdata;
    2023 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
    2024 assert(exprhdlrdata != NULL);
    2025
    2026 if( exprhdlrdata->minzerodistance > 0.0 )
    2027 {
    2028 /* avoid small interval around 0 if possible, see also reversepropPow */
    2029 if( childinterval.inf > -exprhdlrdata->minzerodistance && childinterval.inf < exprhdlrdata->minzerodistance )
    2030 {
    2031 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
    2032 {
    2033 SCIPinfoMessage(scip, NULL, "Changing lower bound for child of pow(.,%g) from %g to %g.\n"
    2034 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
    2035 exponent, childinterval.inf, exprhdlrdata->minzerodistance);
    2036 SCIPinfoMessage(scip, NULL, "Expression: ");
    2037 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
    2038 SCIPinfoMessage(scip, NULL, "\n");
    2039 exprhdlrdata->warnedonpole = TRUE;
    2040 }
    2041 childinterval.inf = exprhdlrdata->minzerodistance;
    2042 }
    2043 else if( childinterval.sup < exprhdlrdata->minzerodistance
    2044 && childinterval.sup > -exprhdlrdata->minzerodistance )
    2045 {
    2046 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
    2047 {
    2048 SCIPinfoMessage(scip, NULL, "Changing upper bound for child of pow(.,%g) from %g to %g.\n"
    2049 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
    2050 exponent, childinterval.sup, -exprhdlrdata->minzerodistance);
    2051 SCIPinfoMessage(scip, NULL, "Expression: ");
    2052 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
    2053 SCIPinfoMessage(scip, NULL, "\n");
    2054 exprhdlrdata->warnedonpole = TRUE;
    2055 }
    2056 childinterval.sup = -exprhdlrdata->minzerodistance;
    2057 }
    2058 }
    2059 }
    2060
    2061 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    2062 {
    2063 SCIPintervalSetEmpty(interval);
    2064 return SCIP_OKAY;
    2065 }
    2066
    2067 SCIPintervalPowerScalar(SCIP_INTERVAL_INFINITY, interval, childinterval, exponent);
    2068
    2069 /* make sure 0^negative is an empty interval, as some other codes do not handle intervals like [inf,inf] well
    2070 * TODO maybe change SCIPintervalPowerScalar?
    2071 */
    2072 if( exponent < 0.0 && childinterval.inf == 0.0 && childinterval.sup == 0.0 )
    2073 SCIPintervalSetEmpty(interval);
    2074
    2075 return SCIP_OKAY;
    2076}
    2077
    2078/** expression estimator callback */
    2079static
    2081{ /*lint --e{715}*/
    2082 SCIP_EXPRDATA* exprdata;
    2083 SCIP_EXPR* child;
    2084 SCIP_Real childlb;
    2085 SCIP_Real childub;
    2086 SCIP_Real exponent;
    2087 SCIP_Bool isinteger;
    2088
    2089 assert(scip != NULL);
    2090 assert(expr != NULL);
    2091 assert(SCIPexprGetNChildren(expr) == 1);
    2092 assert(refpoint != NULL);
    2093 assert(coefs != NULL);
    2094 assert(constant != NULL);
    2095 assert(islocal != NULL);
    2096 assert(branchcand != NULL);
    2097 assert(*branchcand == TRUE); /* the default */
    2098 assert(success != NULL);
    2099
    2101
    2102 *success = FALSE;
    2103
    2104 /* get aux variables: we over- or underestimate childvar^exponent */
    2105 child = SCIPexprGetChildren(expr)[0];
    2106 assert(child != NULL);
    2107
    2108 SCIPdebugMsg(scip, "%sestimation of x^%g at x=%.15g\n",
    2109 overestimate ? "over" : "under", SCIPgetExponentExprPow(expr), *refpoint);
    2110
    2111 /* we can not generate a cut at +/- infinity */
    2112 if( SCIPisInfinity(scip, REALABS(*refpoint)) )
    2113 return SCIP_OKAY;
    2114
    2115 childlb = localbounds[0].inf;
    2116 childub = localbounds[0].sup;
    2117
    2118 exprdata = SCIPexprGetData(expr);
    2119 exponent = exprdata->exponent;
    2120 assert(exponent != 1.0 && exponent != 0.0); /* this should have been simplified */
    2121
    2122 /* if child is constant, then return a constant estimator
    2123 * this can help with small infeasibilities if boundtightening is relaxing bounds too much
    2124 */
    2125 if( childlb == childub )
    2126 {
    2127 *coefs = 0.0;
    2128 *constant = pow(childlb, exponent);
    2129 *success = TRUE;
    2130 *islocal = globalbounds[0].inf != globalbounds[0].sup;
    2131 *branchcand = FALSE;
    2132 return SCIP_OKAY;
    2133 }
    2134
    2135 isinteger = EPSISINT(exponent, 0.0);
    2136
    2137 /* if exponent is not integral, then child must be non-negative */
    2138 if( !isinteger && childlb < 0.0 )
    2139 {
    2140 /* somewhere we should have tightened the bound on x, but small tightening are not always applied by SCIP
    2141 * it is ok to do this tightening here, but let's assert that we were close to 0.0 already
    2142 */
    2143 assert(SCIPisFeasZero(scip, childlb));
    2144 childlb = 0.0;
    2145 }
    2146 assert(isinteger || childlb >= 0.0);
    2147
    2148 SCIP_CALL( buildPowEstimator(scip, exprdata, overestimate, childlb, childub, globalbounds[0].inf,
    2149 globalbounds[0].sup, SCIPexprIsIntegral(child), MAX(childlb, *refpoint), exponent, coefs,
    2150 constant, success, islocal, branchcand) );
    2151
    2152 return SCIP_OKAY;
    2153}
    2154
    2155/** expression reverse propagaton callback */
    2156static
    2158{ /*lint --e{715}*/
    2159 SCIP_INTERVAL child;
    2160 SCIP_INTERVAL interval;
    2161 SCIP_Real exponent;
    2162
    2163 assert(scip != NULL);
    2164 assert(expr != NULL);
    2165 assert(SCIPexprGetNChildren(expr) == 1);
    2166
    2167 exponent = SCIPgetExponentExprPow(expr);
    2168 child = childrenbounds[0];
    2169
    2170 SCIPdebugMsg(scip, "reverseprop x^%g in [%.15g,%.15g], x = [%.15g,%.15g]", exponent, bounds.inf, bounds.sup,
    2171 child.inf, child.sup);
    2172
    2174 {
    2175 *infeasible = TRUE;
    2176 return SCIP_OKAY;
    2177 }
    2178
    2180 {
    2181 /* if exponent is not integral, then make sure that child is non-negative */
    2182 if( !EPSISINT(exponent, 0.0) && child.inf < 0.0 )
    2183 {
    2184 SCIPintervalSetBounds(&interval, 0.0, child.sup);
    2185 }
    2186 else
    2187 {
    2188 SCIPdebugMsgPrint(scip, "-> no improvement\n");
    2189 return SCIP_OKAY;
    2190 }
    2191 }
    2192 else
    2193 {
    2194 /* f = pow(c0, alpha) -> c0 = pow(f, 1/alpha) */
    2195 SCIPintervalPowerScalarInverse(SCIP_INTERVAL_INFINITY, &interval, child, exponent, bounds);
    2196 }
    2197
    2198 if( exponent < 0.0 )
    2199 {
    2200 SCIP_EXPRHDLRDATA* exprhdlrdata;
    2201
    2202 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
    2203 assert(exprhdlrdata != NULL);
    2204
    2205 if( exprhdlrdata->minzerodistance > 0.0 )
    2206 {
    2207 /* push lower bound from >= -epsilon to >= epsilon to avoid pole at 0 (domain error)
    2208 * push upper bound from <= epsilon to <= -epsilon to avoid pole at 0 (domain error)
    2209 * this can lead to a cutoff if domain would otherwise be very close around 0
    2210 */
    2211 if( interval.inf > -exprhdlrdata->minzerodistance && interval.inf < exprhdlrdata->minzerodistance )
    2212 {
    2213 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
    2214 {
    2215 SCIPinfoMessage(scip, NULL, "Changing lower bound for child of pow(.,%g) from %g to %g.\n"
    2216 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
    2217 exponent, interval.inf, exprhdlrdata->minzerodistance);
    2218 SCIPinfoMessage(scip, NULL, "Expression: ");
    2219 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
    2220 SCIPinfoMessage(scip, NULL, "\n");
    2221 exprhdlrdata->warnedonpole = TRUE;
    2222 }
    2223 interval.inf = exprhdlrdata->minzerodistance;
    2224 }
    2225 else if( interval.sup < exprhdlrdata->minzerodistance && interval.sup > -exprhdlrdata->minzerodistance )
    2226 {
    2227 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
    2228 {
    2229 SCIPinfoMessage(scip, NULL, "Changing lower bound for child of pow(.,%g) from %g to %g.\n"
    2230 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
    2231 exponent, interval.sup, -exprhdlrdata->minzerodistance);
    2232 SCIPinfoMessage(scip, NULL, "Expression: ");
    2233 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
    2234 SCIPinfoMessage(scip, NULL, "\n");
    2235 exprhdlrdata->warnedonpole = TRUE;
    2236 }
    2237 interval.sup = -exprhdlrdata->minzerodistance;
    2238 }
    2239 }
    2240 }
    2241
    2242 SCIPdebugMsgPrint(scip, " -> [%.15g,%.15g]\n", interval.inf, interval.sup);
    2243
    2244 childrenbounds[0] = interval;
    2245
    2246 return SCIP_OKAY;
    2247}
    2248
    2249/** initial estimates callback for a power expression */
    2250static
    2252{
    2253 SCIP_EXPRDATA* exprdata;
    2254 SCIP_EXPR* child;
    2255 SCIP_Real childlb;
    2256 SCIP_Real childub;
    2257 SCIP_Real exponent;
    2258 SCIP_Bool isinteger;
    2259 SCIP_Bool branchcand;
    2260 SCIP_Bool success;
    2261 SCIP_Bool islocal;
    2262 SCIP_Real refpointsunder[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
    2263 SCIP_Real refpointsover[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
    2264 SCIP_Bool overest[6] = {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE};
    2265 int i;
    2266
    2267 assert(scip != NULL);
    2268 assert(expr != NULL);
    2269
    2270 child = SCIPexprGetChildren(expr)[0];
    2271 assert(child != NULL);
    2272
    2273 childlb = bounds[0].inf;
    2274 childub = bounds[0].sup;
    2275
    2276 /* if child is essentially constant, then there should be no point in separation */
    2277 if( SCIPisEQ(scip, childlb, childub) )
    2278 {
    2279 SCIPdebugMsg(scip, "skip initestimates as child seems essentially fixed [%.15g,%.15g]\n", childlb, childub);
    2280 return SCIP_OKAY;
    2281 }
    2282
    2283 exprdata = SCIPexprGetData(expr);
    2284 exponent = exprdata->exponent;
    2285 assert(exponent != 1.0 && exponent != 0.0); /* this should have been simplified */
    2286
    2287 isinteger = EPSISINT(exponent, 0.0);
    2288
    2289 /* if exponent is not integral, then child must be non-negative */
    2290 if( !isinteger && childlb < 0.0 )
    2291 {
    2292 /* somewhere we should have tightened the bound on x, but small tightening are not always applied by SCIP
    2293 * it is ok to do this tightening here, but let's assert that we were close to 0.0 already
    2294 */
    2295 assert(SCIPisFeasZero(scip, childlb));
    2296 childlb = 0.0;
    2297 }
    2298 assert(isinteger || childlb >= 0.0);
    2299
    2300 /* TODO simplify to get 3 refpoints for either under- or overestimate */
    2301 SCIP_CALL( chooseRefpointsPow(scip, exprdata, childlb, childub, refpointsunder, refpointsover, !overestimate,
    2302 overestimate) );
    2303
    2304 for( i = 0; i < 6 && *nreturned < SCIP_EXPR_MAXINITESTIMATES; ++i )
    2305 {
    2306 SCIP_Real refpoint;
    2307
    2308 if( (overest[i] && !overestimate) || (!overest[i] && overestimate) )
    2309 continue;
    2310
    2311 assert(overest[i] || i < 3); /* make sure that no out-of-bounds array access will be attempted */
    2312 refpoint = overest[i] ? refpointsover[i % 3] : refpointsunder[i % 3];
    2313
    2314 if( refpoint == SCIP_INVALID )
    2315 continue;
    2316
    2317 assert(SCIPisLE(scip, refpoint, childub) && SCIPisGE(scip, refpoint, childlb));
    2318
    2319 branchcand = TRUE;
    2320 SCIP_CALL( buildPowEstimator(scip, exprdata, overest[i], childlb, childub, childlb, childub,
    2321 SCIPexprIsIntegral(child), refpoint, exponent, coefs[*nreturned], &constant[*nreturned],
    2322 &success, &islocal, &branchcand) );
    2323
    2324 if( success )
    2325 {
    2326 SCIPdebugMsg(scip, "initestimate x^%g for base in [%g,%g] at ref=%g, over:%u -> %g*x+%g\n", exponent,
    2327 childlb, childub, refpoint, overest[i], coefs[*nreturned][0], constant[*nreturned]);
    2328 ++*nreturned;
    2329 }
    2330 }
    2331
    2332 return SCIP_OKAY;
    2333}
    2334
    2335/** expression hash callback */
    2336static
    2338{ /*lint --e{715}*/
    2339 assert(scip != NULL);
    2340 assert(expr != NULL);
    2341 assert(SCIPexprGetNChildren(expr) == 1);
    2342 assert(hashkey != NULL);
    2343 assert(childrenhashes != NULL);
    2344
    2345 /* TODO include exponent into hashkey */
    2346 *hashkey = POWEXPRHDLR_HASHKEY;
    2347 *hashkey ^= childrenhashes[0];
    2348
    2349 return SCIP_OKAY;
    2350}
    2351
    2352/** expression curvature detection callback */
    2353static
    2355{ /*lint --e{715}*/
    2356 SCIP_EXPR* child;
    2357 SCIP_INTERVAL childinterval;
    2358 SCIP_Real exponent;
    2359
    2360 assert(scip != NULL);
    2361 assert(expr != NULL);
    2362 assert(exprcurvature != SCIP_EXPRCURV_UNKNOWN);
    2363 assert(childcurv != NULL);
    2364 assert(success != NULL);
    2365 assert(SCIPexprGetNChildren(expr) == 1);
    2366
    2367 exponent = SCIPgetExponentExprPow(expr);
    2368 child = SCIPexprGetChildren(expr)[0];
    2369 assert(child != NULL);
    2370
    2372 childinterval = SCIPexprGetActivity(child);
    2373
    2374 *childcurv = SCIPexprcurvPowerInv(childinterval, exponent, exprcurvature);
    2375 /* SCIPexprcurvPowerInv return unknown actually means that curv cannot be obtained */
    2376 *success = *childcurv != SCIP_EXPRCURV_UNKNOWN;
    2377
    2378 return SCIP_OKAY;
    2379}
    2380
    2381/** expression monotonicity detection callback */
    2382static
    2384{ /*lint --e{715}*/
    2385 SCIP_INTERVAL interval;
    2386 SCIP_Real exponent;
    2387 SCIP_Real inf;
    2388 SCIP_Real sup;
    2389 SCIP_Bool expisint;
    2390
    2391 assert(scip != NULL);
    2392 assert(expr != NULL);
    2393 assert(result != NULL);
    2394 assert(SCIPexprGetNChildren(expr) == 1);
    2395 assert(childidx == 0);
    2396
    2397 assert(SCIPexprGetChildren(expr)[0] != NULL);
    2399 interval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    2400
    2401 *result = SCIP_MONOTONE_UNKNOWN;
    2402 inf = SCIPintervalGetInf(interval);
    2403 sup = SCIPintervalGetSup(interval);
    2404 exponent = SCIPgetExponentExprPow(expr);
    2405 expisint = EPSISINT(exponent, 0.0); /*lint !e835*/
    2406
    2407 if( expisint )
    2408 {
    2409 SCIP_Bool expisodd = ceil(exponent/2) != exponent/2;
    2410
    2411 if( expisodd )
    2412 {
    2413 /* x^1, x^3, ... */
    2414 if( exponent >= 0.0 )
    2415 *result = SCIP_MONOTONE_INC;
    2416
    2417 /* ..., x^-3, x^-1 are decreasing if 0 is not in ]inf,sup[ */
    2418 else if( inf >= 0.0 || sup <= 0.0 )
    2419 *result = SCIP_MONOTONE_DEC;
    2420 }
    2421 /* ..., x^-4, x^-2, x^2, x^4, ... */
    2422 else
    2423 {
    2424 /* function is not monotone if 0 is in ]inf,sup[ */
    2425 if( inf >= 0.0 )
    2426 *result = exponent >= 0.0 ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
    2427 else if( sup <= 0.0 )
    2428 *result = exponent >= 0.0 ? SCIP_MONOTONE_DEC : SCIP_MONOTONE_INC;
    2429 }
    2430 }
    2431 else
    2432 {
    2433 /* note that the expression is not defined for negative input values
    2434 *
    2435 * - increasing iff exponent >= 0
    2436 * - decreasing iff exponent <= 0
    2437 */
    2438 *result = exponent >= 0.0 ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
    2439 }
    2440
    2441 return SCIP_OKAY;
    2442}
    2443
    2444/** expression integrality detection callback */
    2445static
    2447{ /*lint --e{715}*/
    2448 SCIP_EXPR* child;
    2449 SCIP_Real exponent;
    2450 SCIP_Bool expisint;
    2451
    2452 assert(scip != NULL);
    2453 assert(expr != NULL);
    2454 assert(integrality != NULL);
    2455 assert(SCIPexprGetNChildren(expr) == 1);
    2456
    2457 child = SCIPexprGetChildren(expr)[0];
    2458 assert(child != NULL);
    2459
    2460 exponent = SCIPgetExponentExprPow(expr);
    2461 assert(exponent != 0.0);
    2462 expisint = EPSISINT(exponent, 0.0); /*lint !e835*/
    2463
    2464 /* maintain child integrality if exponent is non-negative and integral */
    2465 *integrality = (expisint && exponent >= 0.0) ? SCIPexprGetIntegrality(child) : SCIP_IMPLINTTYPE_NONE;
    2466
    2467 return SCIP_OKAY;
    2468}
    2469
    2470/** simplifies a signpower expression
    2471 */
    2472static
    2473SCIP_DECL_EXPRSIMPLIFY(simplifySignpower)
    2474{ /*lint --e{715}*/
    2475 SCIP_EXPR* base;
    2476 SCIP_Real exponent;
    2477
    2478 assert(scip != NULL);
    2479 assert(expr != NULL);
    2480 assert(simplifiedexpr != NULL);
    2481 assert(SCIPexprGetNChildren(expr) == 1);
    2482
    2483 base = SCIPexprGetChildren(expr)[0];
    2484 assert(base != NULL);
    2485
    2486 exponent = SCIPgetExponentExprPow(expr);
    2487 SCIPdebugPrintf("[simplifySignpower] simplifying power with expo %g\n", exponent);
    2488 assert(exponent >= 1.0);
    2489
    2490 /* enforces SPOW2 */
    2491 if( exponent == 1.0 )
    2492 {
    2493 SCIPdebugPrintf("[simplifySignpower] POW2\n");
    2494 *simplifiedexpr = base;
    2495 SCIPcaptureExpr(*simplifiedexpr);
    2496 return SCIP_OKAY;
    2497 }
    2498
    2499 /* enforces SPOW3 */
    2500 if( SCIPisExprValue(scip, base) )
    2501 {
    2502 SCIP_Real baseval;
    2503
    2504 SCIPdebugPrintf("[simplifySignpower] POW3\n");
    2505 baseval = SCIPgetValueExprValue(base);
    2506
    2507 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, SIGN(baseval) * pow(REALABS(baseval), exponent),
    2508 ownercreate, ownercreatedata) );
    2509
    2510 return SCIP_OKAY;
    2511 }
    2512
    2513 /* enforces SPOW11 (exp(x)^n = exp(n*x))
    2514 * since exp() is always nonnegative, we can treat signpower as normal power here
    2515 */
    2516 if( SCIPisExprExp(scip, base) )
    2517 {
    2518 SCIP_EXPR* child;
    2519 SCIP_EXPR* prod;
    2520 SCIP_EXPR* exponential;
    2521 SCIP_EXPR* simplifiedprod;
    2522
    2523 SCIPdebugPrintf("[simplifySignpower] POW11\n");
    2524 child = SCIPexprGetChildren(base)[0];
    2525
    2526 /* multiply child of exponential with exponent */
    2527 SCIP_CALL( SCIPcreateExprProduct(scip, &prod, 1, &child, exponent, ownercreate, ownercreatedata) );
    2528
    2529 /* simplify product */
    2530 SCIP_CALL( SCIPcallExprSimplify(scip, prod, &simplifiedprod, ownercreate, ownercreatedata) );
    2531 SCIP_CALL( SCIPreleaseExpr(scip, &prod) );
    2532
    2533 /* create exponential with new child */
    2534 SCIP_CALL( SCIPcreateExprExp(scip, &exponential, simplifiedprod, ownercreate, ownercreatedata) );
    2535 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedprod) );
    2536
    2537 /* the final simplified expression is the simplification of the just created exponential */
    2538 SCIP_CALL( SCIPcallExprSimplify(scip, exponential, simplifiedexpr, ownercreate, ownercreatedata) );
    2539 SCIP_CALL( SCIPreleaseExpr(scip, &exponential) );
    2540
    2541 return SCIP_OKAY;
    2542 }
    2543
    2544 /* enforces SPOW6 */
    2545 if( EPSISINT(exponent, 0.0) && ((int)exponent) % 2 == 1 )
    2546 {
    2547 SCIP_EXPR* aux;
    2548
    2549 /* we do not just change the expression data of expression to say it is a normal power, since, at the moment,
    2550 * simplify identifies that expressions changed by checking that the pointer of the input expression is
    2551 * different from the returned (simplified) expression
    2552 */
    2553 SCIP_CALL( SCIPcreateExprPow(scip, &aux, base, exponent, ownercreate, ownercreatedata) );
    2554
    2555 SCIP_CALL( simplifyPow(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
    2556 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    2557
    2558 return SCIP_OKAY;
    2559 }
    2560
    2561 /* enforces SPOW10 */
    2562 if( SCIPisExprVar(scip, base) )
    2563 {
    2564 SCIP_VAR* basevar;
    2565
    2566 SCIPdebugPrintf("[simplifySignpower] POW10\n");
    2567 basevar = SCIPgetVarExprVar(base);
    2568
    2569 assert(basevar != NULL);
    2570
    2571 if( SCIPvarIsBinary(basevar) )
    2572 {
    2573 *simplifiedexpr = base;
    2574 SCIPcaptureExpr(*simplifiedexpr);
    2575 return SCIP_OKAY;
    2576 }
    2577 }
    2578
    2579 /* TODO if( SCIPisExprSignpower(scip, base) ... */
    2580
    2581 /* enforces SPOW8
    2582 * given (signpow n (pow expo expr)) we distribute the exponent:
    2583 * -> (signpow n*expo expr) for even n (i.e., sign(x^n) * |x|^n = 1 * x^n)
    2584 * notes: n is an even integer (see SPOW6 above)
    2585 * FIXME: doesn't this extend to any exponent?
    2586 * If (pow expo expr) can be negative, it should mean that (-1)^expo = -1
    2587 * then (signpow n (pow expo expr)) = sign(expr^expo) * |expr^expo|^n
    2588 * then sign(expr^expo) = sign(expr) and |expr^expo| = |expr|^expo and so
    2589 * (signpow n (pow expo expr)) = sign(expr^expo) * |expr^expo|^n = sign(expr) * |expr|^(expo*n) = signpow n*expo expr
    2590 */
    2591 if( EPSISINT(exponent, 0.0) && SCIPisExprPower(scip, base) )
    2592 {
    2593 SCIP_EXPR* aux;
    2594 SCIP_Real newexponent;
    2595
    2596 assert(((int)exponent) % 2 == 0 ); /* odd case should have been handled by SPOW6 */
    2597
    2598 newexponent = SCIPgetExponentExprPow(base) * exponent;
    2599 SCIP_CALL( SCIPcreateExprSignpower(scip, &aux, SCIPexprGetChildren(base)[0], newexponent,
    2600 ownercreate, ownercreatedata) );
    2601 SCIP_CALL( simplifySignpower(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
    2602
    2603 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    2604
    2605 return SCIP_OKAY;
    2606 }
    2607
    2608 /* enforces SPOW9 */
    2609 if( SCIPisExprSum(scip, base)
    2610 && SCIPexprGetNChildren(base) == 1
    2611 && SCIPgetConstantExprSum(base) == 0.0 )
    2612 {
    2613 SCIP_EXPR* simplifiedaux;
    2614 SCIP_EXPR* aux;
    2615 SCIP_Real newcoef;
    2616
    2617 SCIPdebugPrintf("[simplifySignpower] seeing a sum with one term, exponent %g\n", exponent);
    2618 /* assert SS7 holds */
    2619 assert(SCIPgetCoefsExprSum(base)[0] != 1.0);
    2620
    2621 /* create (signpow n expr) and simplify it
    2622 * note: we call simplifySignpower directly, since we know that `expr` is simplified */
    2623 SCIP_CALL( SCIPcreateExprSignpower(scip, &aux, SCIPexprGetChildren(base)[0], exponent,
    2624 ownercreate, ownercreatedata) );
    2625 newcoef = SIGN(SCIPgetCoefsExprSum(base)[0]) * pow(REALABS(SCIPgetCoefsExprSum(base)[0]), exponent);
    2626 SCIP_CALL( simplifySignpower(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
    2627 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    2628
    2629 /* create (sum (signpow n expr)) and simplify it
    2630 * this calls simplifySum directly, since we know its child is simplified */
    2631 SCIP_CALL( SCIPcreateExprSum(scip, &aux, 1, &simplifiedaux, &newcoef, 0.0, ownercreate, ownercreatedata) );
    2632 SCIP_CALL( SCIPcallExprSimplify(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
    2633 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    2634 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
    2635 return SCIP_OKAY;
    2636 }
    2637
    2638 SCIPdebugPrintf("[simplifySignpower] signpower is simplified\n");
    2639 *simplifiedexpr = expr;
    2640
    2641 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    2642 SCIPcaptureExpr(*simplifiedexpr);
    2643
    2644 return SCIP_OKAY;
    2645}
    2646
    2647/** expression handler copy callback */
    2648static
    2649SCIP_DECL_EXPRCOPYHDLR(copyhdlrSignpower)
    2650{ /*lint --e{715}*/
    2652
    2653 return SCIP_OKAY;
    2654}
    2655
    2656/** expression print callback */
    2657static
    2658SCIP_DECL_EXPRPRINT(printSignpower)
    2659{ /*lint --e{715}*/
    2660 assert(expr != NULL);
    2661
    2662 switch( stage )
    2663 {
    2665 {
    2666 SCIPinfoMessage(scip, file, "signpower(");
    2667 break;
    2668 }
    2669
    2671 {
    2672 assert(currentchild == 0);
    2673 break;
    2674 }
    2675
    2677 {
    2678 SCIPinfoMessage(scip, file, ",%.15g)", SCIPgetExponentExprPow(expr));
    2679 break;
    2680 }
    2681
    2683 default:
    2684 break;
    2685 }
    2686
    2687 return SCIP_OKAY;
    2688}
    2689
    2690/** expression parse callback */
    2691static
    2692SCIP_DECL_EXPRPARSE(parseSignpower)
    2693{ /*lint --e{715}*/
    2694 SCIP_EXPR* childexpr;
    2695 SCIP_Real exponent;
    2696
    2697 assert(expr != NULL);
    2698
    2699 /**! [SnippetExprParseSignpower] */
    2700 /* parse child expression string */
    2701 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
    2702 assert(childexpr != NULL);
    2703
    2704 string = *endstring;
    2705 while( *string == ' ' )
    2706 ++string;
    2707
    2708 if( *string != ',' )
    2709 {
    2710 SCIPerrorMessage("Expected comma after first argument of signpower().\n");
    2711 return SCIP_READERROR;
    2712 }
    2713 ++string;
    2714
    2715 if( !SCIPparseReal(scip, string, &exponent, (char**)endstring) )
    2716 {
    2717 SCIPerrorMessage("Expected numeric exponent for second argument of signpower().\n");
    2718 return SCIP_READERROR;
    2719 }
    2720
    2721 if( exponent <= 1.0 || !SCIPisFinite(exponent) || SCIPisInfinity(scip, exponent) )
    2722 {
    2723 SCIPerrorMessage("Expected finite exponent >= 1.0 for signpower().\n");
    2724 return SCIP_READERROR;
    2725 }
    2726
    2727 /* create signpower expression */
    2728 SCIP_CALL( SCIPcreateExprSignpower(scip, expr, childexpr, exponent, ownercreate, ownercreatedata) );
    2729 assert(*expr != NULL);
    2730
    2731 /* release child expression since it has been captured by the signpower expression */
    2732 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
    2733
    2734 *success = TRUE;
    2735 /**! [SnippetExprParseSignpower] */
    2736
    2737 return SCIP_OKAY;
    2738}
    2739
    2740/** expression point evaluation callback */
    2741static
    2743{ /*lint --e{715}*/
    2744 SCIP_Real exponent;
    2745 SCIP_Real base;
    2746
    2747 assert(expr != NULL);
    2748 assert(SCIPexprGetNChildren(expr) == 1);
    2750
    2751 exponent = SCIPgetExponentExprPow(expr);
    2753
    2754 *val = SIGN(base) * pow(REALABS(base), exponent);
    2755
    2756 /* if there is a range error, pow() should return some kind of infinity, or HUGE_VAL
    2757 * we could also work with floating point exceptions or errno, but I am not sure this would be thread-safe
    2758 */
    2759 if( !SCIPisFinite(*val) || *val == HUGE_VAL || *val == -HUGE_VAL )
    2760 *val = SCIP_INVALID;
    2761
    2762 return SCIP_OKAY;
    2763}
    2764
    2765/** expression derivative evaluation callback */
    2766static
    2767SCIP_DECL_EXPRBWDIFF(bwdiffSignpower)
    2768{ /*lint --e{715}*/
    2769 SCIP_EXPR* child;
    2770 SCIP_Real childval;
    2771 SCIP_Real exponent;
    2772
    2773 assert(expr != NULL);
    2774 assert(SCIPexprGetData(expr) != NULL);
    2775 assert(childidx == 0);
    2776
    2777 child = SCIPexprGetChildren(expr)[0];
    2778 assert(child != NULL);
    2779 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    2780
    2781 childval = SCIPexprGetEvalValue(child);
    2782 assert(childval != SCIP_INVALID);
    2783
    2784 exponent = SCIPgetExponentExprPow(expr);
    2785 assert(exponent >= 1.0);
    2786
    2787 *val = exponent * pow(REALABS(childval), exponent - 1.0);
    2788
    2789 return SCIP_OKAY;
    2790}
    2791
    2792/** expression interval evaluation callback */
    2793static
    2794SCIP_DECL_EXPRINTEVAL(intevalSignpower)
    2795{ /*lint --e{715}*/
    2796 SCIP_INTERVAL childinterval;
    2797
    2798 assert(expr != NULL);
    2799 assert(SCIPexprGetNChildren(expr) == 1);
    2800
    2801 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    2802 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    2803 {
    2804 SCIPintervalSetEmpty(interval);
    2805 return SCIP_OKAY;
    2806 }
    2807
    2809
    2810 return SCIP_OKAY;
    2811}
    2812
    2813/** expression estimator callback */
    2814static
    2815SCIP_DECL_EXPRESTIMATE(estimateSignpower)
    2816{ /*lint --e{715}*/
    2817 SCIP_EXPRDATA* exprdata;
    2818 SCIP_Real childlb;
    2819 SCIP_Real childub;
    2820 SCIP_Real childglb;
    2821 SCIP_Real childgub;
    2822 SCIP_Real exponent;
    2823
    2824 assert(scip != NULL);
    2825 assert(expr != NULL);
    2826 assert(SCIPexprGetNChildren(expr) == 1);
    2827 assert(refpoint != NULL);
    2828 assert(coefs != NULL);
    2829 assert(constant != NULL);
    2830 assert(islocal != NULL);
    2831 assert(branchcand != NULL);
    2832 assert(*branchcand == TRUE); /* the default */
    2833 assert(success != NULL);
    2834
    2836
    2837 *success = FALSE;
    2838
    2839 SCIPdebugMsg(scip, "%sestimation of signed x^%g at x=%g\n", overestimate ? "over" : "under",
    2840 SCIPgetExponentExprPow(expr), *refpoint);
    2841
    2842 /* we can not generate a cut at +/- infinity */
    2843 if( SCIPisInfinity(scip, REALABS(*refpoint)) )
    2844 return SCIP_OKAY;
    2845
    2846 childlb = localbounds[0].inf;
    2847 childub = localbounds[0].sup;
    2848
    2849 childglb = globalbounds[0].inf;
    2850 childgub = globalbounds[0].sup;
    2851
    2852 exprdata = SCIPexprGetData(expr);
    2853 exponent = exprdata->exponent;
    2854 assert(exponent > 1.0); /* exponent == 1 should have been simplified */
    2855
    2856 /* if child is constant, then return a constant estimator
    2857 * this can help with small infeasibilities if boundtightening is relaxing bounds too much
    2858 */
    2859 if( childlb == childub )
    2860 {
    2861 *coefs = 0.0;
    2862 *constant = SIGN(childlb)*pow(REALABS(childlb), exponent);
    2863 *success = TRUE;
    2864 *islocal = childglb != childgub;
    2865 *branchcand = FALSE;
    2866 return SCIP_OKAY;
    2867 }
    2868
    2869 if( childlb >= 0.0 )
    2870 {
    2871 estimateParabola(scip, exponent, overestimate, childlb, childub, MAX(0.0, *refpoint), constant, coefs,
    2872 islocal, success);
    2873
    2874 *branchcand = *islocal;
    2875
    2876 /* if odd or signed power, then check whether tangent on parabola is also globally valid, that is
    2877 * reference point is right of -root*global-lower-bound
    2878 */
    2879 if( !*islocal && childglb < 0.0 )
    2880 {
    2881 if( SCIPisInfinity(scip, -childglb) )
    2882 *islocal = TRUE;
    2883 else
    2884 {
    2885 if( exprdata->root == SCIP_INVALID )
    2886 {
    2887 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
    2888 }
    2889 *islocal = *refpoint < exprdata->root * (-childglb);
    2890 }
    2891 }
    2892 }
    2893 else /* and childlb < 0.0 due to previous if */
    2894 {
    2895 /* compute root if not known yet; only needed if mixed sign (global child ub > 0) */
    2896 if( exprdata->root == SCIP_INVALID && childgub > 0.0 )
    2897 {
    2898 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
    2899 }
    2900 estimateSignedpower(scip, exponent, exprdata->root, overestimate, childlb, childub, *refpoint,
    2901 childglb, childgub, constant, coefs, islocal, branchcand, success);
    2902 }
    2903
    2904 return SCIP_OKAY;
    2905}
    2906
    2907/** initial estimates callback for a signpower expression */
    2908static
    2909SCIP_DECL_EXPRINITESTIMATES(initestimatesSignpower)
    2910{
    2911 SCIP_EXPRDATA* exprdata;
    2912 SCIP_Real childlb;
    2913 SCIP_Real childub;
    2914 SCIP_Real exponent;
    2915 SCIP_Bool branchcand;
    2916 SCIP_Bool success;
    2917 SCIP_Bool islocal;
    2918 SCIP_Real refpointsunder[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
    2919 SCIP_Real refpointsover[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
    2920 SCIP_Bool overest[6] = {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE};
    2921 SCIP_Real refpoint;
    2922 int i;
    2923
    2924 assert(scip != NULL);
    2925 assert(expr != NULL);
    2926 assert(SCIPexprGetNChildren(expr) == 1);
    2927
    2929
    2930 childlb = bounds[0].inf;
    2931 childub = bounds[0].sup;
    2932
    2933 /* if child is essentially constant, then there should be no point in separation */
    2934 if( SCIPisEQ(scip, childlb, childub) )
    2935 {
    2936 SCIPdebugMsg(scip, "skip initestimates as child seems essentially fixed [%.15g,%.15g]\n", childlb, childub);
    2937 return SCIP_OKAY;
    2938 }
    2939
    2940 exprdata = SCIPexprGetData(expr);
    2941 exponent = exprdata->exponent;
    2942 assert(exponent > 1.0); /* this should have been simplified */
    2943
    2944 if( childlb >= 0.0 )
    2945 {
    2946 if( !overestimate )
    2947 addTangentRefpoints(scip, exponent, childlb, childub, refpointsunder);
    2948 if( overestimate && !SCIPisInfinity(scip, childub) )
    2949 refpointsover[0] = (childlb + childub) / 2.0;
    2950 }
    2951 else if( childub <= 0.0 )
    2952 {
    2953 if( !overestimate && !SCIPisInfinity(scip, -childlb) )
    2954 refpointsunder[0] = (childlb + childub) / 2.0;
    2955 if( overestimate )
    2956 addTangentRefpoints(scip, exponent, childlb, childub, refpointsunder);
    2957 }
    2958 else
    2959 {
    2960 SCIP_CALL( addSignpowerRefpoints(scip, exprdata, childlb, childub, exponent, !overestimate, refpointsunder) );
    2961 }
    2962
    2963 /* add cuts for all refpoints */
    2964 for( i = 0; i < 6 && *nreturned < SCIP_EXPR_MAXINITESTIMATES; ++i )
    2965 {
    2966 if( (overest[i] && !overestimate) || (!overest[i] && overestimate) )
    2967 continue;
    2968
    2969 assert(overest[i] || i < 3); /* make sure that no out-of-bounds array access will be attempted */
    2970 refpoint = overest[i] ? refpointsover[i % 3] : refpointsunder[i % 3];
    2971 if( refpoint == SCIP_INVALID )
    2972 continue;
    2973 assert(SCIPisLE(scip, refpoint, childub) && SCIPisGE(scip, refpoint, childlb));
    2974
    2975 if( childlb >= 0 )
    2976 {
    2977 estimateParabola(scip, exponent, overest[i], childlb, childub, refpoint, &constant[*nreturned], coefs[*nreturned],
    2978 &islocal, &success);
    2979 }
    2980 else
    2981 {
    2982 /* compute root if not known yet; only needed if mixed sign (global child ub > 0) */
    2983 if( exprdata->root == SCIP_INVALID && childub > 0.0 )
    2984 {
    2985 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
    2986 }
    2987 branchcand = TRUE;
    2988 estimateSignedpower(scip, exponent, exprdata->root, overest[i], childlb, childub, refpoint,
    2989 childlb, childub, &constant[*nreturned], coefs[*nreturned], &islocal,
    2990 &branchcand, &success);
    2991 }
    2992
    2993 if( success )
    2994 ++*nreturned;
    2995 }
    2996
    2997 return SCIP_OKAY;
    2998}
    2999
    3000/** expression reverse propagaton callback */
    3001static
    3002SCIP_DECL_EXPRREVERSEPROP(reversepropSignpower)
    3003{ /*lint --e{715}*/
    3004 SCIP_INTERVAL interval;
    3005 SCIP_INTERVAL exprecip;
    3006 SCIP_Real exponent;
    3007
    3008 assert(scip != NULL);
    3009 assert(expr != NULL);
    3010 assert(SCIPexprGetNChildren(expr) == 1);
    3011
    3012 exponent = SCIPgetExponentExprPow(expr);
    3013
    3014 SCIPdebugMsg(scip, "reverseprop signpow(x,%g) in [%.15g,%.15g]", exponent, bounds.inf, bounds.sup);
    3015
    3017 {
    3018 SCIPdebugMsgPrint(scip, "-> no improvement\n");
    3019 return SCIP_OKAY;
    3020 }
    3021
    3022 /* f = pow(c0, alpha) -> c0 = pow(f, 1/alpha) */
    3023 SCIPintervalSet(&exprecip, exponent);
    3024 SCIPintervalReciprocal(SCIP_INTERVAL_INFINITY, &exprecip, exprecip);
    3025 if( exprecip.inf == exprecip.sup )
    3026 {
    3027 SCIPintervalSignPowerScalar(SCIP_INTERVAL_INFINITY, &interval, bounds, exprecip.inf);
    3028 }
    3029 else
    3030 {
    3031 SCIP_INTERVAL interval1, interval2;
    3032 SCIPintervalSignPowerScalar(SCIP_INTERVAL_INFINITY, &interval1, bounds, exprecip.inf);
    3033 SCIPintervalSignPowerScalar(SCIP_INTERVAL_INFINITY, &interval2, bounds, exprecip.sup);
    3034 SCIPintervalUnify(&interval, interval1, interval2);
    3035 }
    3036
    3037 SCIPdebugMsgPrint(scip, " -> [%.15g,%.15g]\n", interval.inf, interval.sup);
    3038
    3039 childrenbounds[0] = interval;
    3040
    3041 return SCIP_OKAY;
    3042}
    3043
    3044/** expression hash callback */
    3045static
    3047{ /*lint --e{715}*/
    3048 assert(scip != NULL);
    3049 assert(expr != NULL);
    3050 assert(SCIPexprGetNChildren(expr) == 1);
    3051 assert(hashkey != NULL);
    3052 assert(childrenhashes != NULL);
    3053
    3054 /* TODO include exponent into hashkey */
    3055 *hashkey = SIGNPOWEXPRHDLR_HASHKEY;
    3056 *hashkey ^= childrenhashes[0];
    3057
    3058 return SCIP_OKAY;
    3059}
    3060
    3061/** expression curvature detection callback */
    3062static
    3063SCIP_DECL_EXPRCURVATURE(curvatureSignpower)
    3064{ /*lint --e{715}*/
    3065 SCIP_EXPR* child;
    3066 SCIP_INTERVAL childinterval;
    3067
    3068 assert(scip != NULL);
    3069 assert(expr != NULL);
    3070 assert(exprcurvature != SCIP_EXPRCURV_UNKNOWN);
    3071 assert(childcurv != NULL);
    3072 assert(success != NULL);
    3073 assert(SCIPexprGetNChildren(expr) == 1);
    3074
    3075 child = SCIPexprGetChildren(expr)[0];
    3076 assert(child != NULL);
    3077
    3079 childinterval = SCIPexprGetActivity(child);
    3080
    3081 if( exprcurvature == SCIP_EXPRCURV_CONVEX )
    3082 {
    3083 /* signpower is only convex if argument is convex and non-negative */
    3084 *childcurv = SCIP_EXPRCURV_CONVEX;
    3085 *success = childinterval.inf >= 0.0;
    3086 }
    3087 else if( exprcurvature == SCIP_EXPRCURV_CONCAVE )
    3088 {
    3089 /* signpower is only concave if argument is concave and non-positive */
    3090 *childcurv = SCIP_EXPRCURV_CONCAVE;
    3091 *success = childinterval.sup <= 0.0;
    3092 }
    3093 else
    3094 *success = FALSE;
    3095
    3096 return SCIP_OKAY;
    3097}
    3098
    3099/** expression monotonicity detection callback */
    3100static
    3101SCIP_DECL_EXPRMONOTONICITY(monotonicitySignpower)
    3102{ /*lint --e{715}*/
    3103 assert(scip != NULL);
    3104 assert(expr != NULL);
    3105 assert(result != NULL);
    3106
    3107 *result = SCIP_MONOTONE_INC;
    3108 return SCIP_OKAY;
    3109}
    3110
    3111/** creates the handler for power expression and includes it into SCIP */
    3113 SCIP* scip /**< SCIP data structure */
    3114 )
    3115{
    3116 SCIP_EXPRHDLR* exprhdlr;
    3117 SCIP_EXPRHDLRDATA* exprhdlrdata;
    3118
    3119 SCIP_CALL( SCIPallocClearBlockMemory(scip, &exprhdlrdata) );
    3120
    3122 evalPow, exprhdlrdata) );
    3123 assert(exprhdlr != NULL);
    3124
    3125 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrPow, freehdlrPow);
    3126 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataPow, freedataPow);
    3127 SCIPexprhdlrSetSimplify(exprhdlr, simplifyPow);
    3128 SCIPexprhdlrSetPrint(exprhdlr, printPow);
    3129 SCIPexprhdlrSetIntEval(exprhdlr, intevalPow);
    3130 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesPow, estimatePow);
    3131 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropPow);
    3132 SCIPexprhdlrSetHash(exprhdlr, hashPow);
    3133 SCIPexprhdlrSetCompare(exprhdlr, comparePow);
    3134 SCIPexprhdlrSetDiff(exprhdlr, bwdiffPow, fwdiffPow, bwfwdiffPow);
    3135 SCIPexprhdlrSetCurvature(exprhdlr, curvaturePow);
    3136 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityPow);
    3137 SCIPexprhdlrSetIntegrality(exprhdlr, integralityPow);
    3138 SCIPexprhdlrSetGetSymdata(exprhdlr, getSymDataPow);
    3139
    3140 SCIP_CALL( SCIPaddRealParam(scip, "expr/" POWEXPRHDLR_NAME "/minzerodistance",
    3141 "minimal distance from zero to enforce for child in bound tightening",
    3142 &exprhdlrdata->minzerodistance, FALSE, SCIPepsilon(scip), 0.0, 1.0, NULL, NULL) );
    3143
    3144 SCIP_CALL( SCIPaddIntParam(scip, "expr/" POWEXPRHDLR_NAME "/expandmaxexponent",
    3145 "maximal exponent when to expand power of sum in simplify",
    3146 &exprhdlrdata->expandmaxexponent, FALSE, 2, 1, INT_MAX, NULL, NULL) );
    3147
    3148 SCIP_CALL( SCIPaddBoolParam(scip, "expr/" POWEXPRHDLR_NAME "/distribfracexponent",
    3149 "whether a fractional exponent is distributed onto factors on power of product",
    3150 &exprhdlrdata->distribfracexponent, FALSE, FALSE, NULL, NULL) );
    3151
    3152 return SCIP_OKAY;
    3153}
    3154
    3155/** creates the handler for signed power expression and includes it into SCIP */
    3157 SCIP* scip /**< SCIP data structure */
    3158 )
    3159{
    3160 SCIP_EXPRHDLR* exprhdlr;
    3161
    3163 SIGNPOWEXPRHDLR_PRECEDENCE, evalSignpower, NULL) );
    3164 assert(exprhdlr != NULL);
    3165
    3166 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrSignpower, NULL);
    3167 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataPow, freedataPow);
    3168 SCIPexprhdlrSetSimplify(exprhdlr, simplifySignpower);
    3169 SCIPexprhdlrSetPrint(exprhdlr, printSignpower);
    3170 SCIPexprhdlrSetParse(exprhdlr, parseSignpower);
    3171 SCIPexprhdlrSetIntEval(exprhdlr, intevalSignpower);
    3172 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesSignpower, estimateSignpower);
    3173 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropSignpower);
    3174 SCIPexprhdlrSetHash(exprhdlr, hashSignpower);
    3175 SCIPexprhdlrSetCompare(exprhdlr, comparePow);
    3176 SCIPexprhdlrSetDiff(exprhdlr, bwdiffSignpower, NULL, NULL);
    3177 SCIPexprhdlrSetCurvature(exprhdlr, curvatureSignpower);
    3178 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicitySignpower);
    3179 SCIPexprhdlrSetIntegrality(exprhdlr, integralityPow);
    3180 SCIPexprhdlrSetGetSymdata(exprhdlr, getSymDataPow);
    3181
    3182 return SCIP_OKAY;
    3183}
    3184
    3185/** creates a power expression */
    3187 SCIP* scip, /**< SCIP data structure */
    3188 SCIP_EXPR** expr, /**< pointer where to store expression */
    3189 SCIP_EXPR* child, /**< single child */
    3190 SCIP_Real exponent, /**< exponent of the power expression */
    3191 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    3192 void* ownercreatedata /**< data to pass to ownercreate */
    3193 )
    3194{
    3195 SCIP_EXPRDATA* exprdata;
    3196
    3197 assert(expr != NULL);
    3198 assert(child != NULL);
    3199
    3200 SCIP_CALL( createData(scip, &exprdata, exponent) );
    3201 assert(exprdata != NULL);
    3202
    3203 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPgetExprhdlrPower(scip), exprdata, 1, &child, ownercreate,
    3204 ownercreatedata) );
    3205
    3206 return SCIP_OKAY;
    3207}
    3208
    3209/** creates a signpower expression */
    3211 SCIP* scip, /**< SCIP data structure */
    3212 SCIP_EXPR** expr, /**< pointer where to store expression */
    3213 SCIP_EXPR* child, /**< single child */
    3214 SCIP_Real exponent, /**< exponent of the power expression */
    3215 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    3216 void* ownercreatedata /**< data to pass to ownercreate */
    3217 )
    3218{
    3219 SCIP_EXPRDATA* exprdata;
    3220
    3221 assert(expr != NULL);
    3222 assert(child != NULL);
    3224
    3225 SCIP_CALL( createData(scip, &exprdata, exponent) );
    3226 assert(exprdata != NULL);
    3227
    3229 ownercreate, ownercreatedata) );
    3230
    3231 return SCIP_OKAY;
    3232}
    3233
    3234/** indicates whether expression is of signpower-type */ /*lint -e{715}*/
    3236 SCIP* scip, /**< SCIP data structure */
    3237 SCIP_EXPR* expr /**< expression */
    3238 )
    3239{ /*lint --e{715}*/
    3240 assert(expr != NULL);
    3241
    3242 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), SIGNPOWEXPRHDLR_NAME) == 0;
    3243}
    3244
    3245/** computes coefficients of linearization of a square term in a reference point */
    3247 SCIP* scip, /**< SCIP data structure */
    3248 SCIP_Real sqrcoef, /**< coefficient of square term */
    3249 SCIP_Real refpoint, /**< point where to linearize */
    3250 SCIP_Bool isint, /**< whether corresponding variable is a discrete variable, and thus linearization could be moved */
    3251 SCIP_Real* lincoef, /**< buffer to add coefficient of linearization */
    3252 SCIP_Real* linconstant, /**< buffer to add constant of linearization */
    3253 SCIP_Bool* success /**< buffer to set to FALSE if linearization has failed due to large numbers */
    3254 )
    3255{
    3256 assert(scip != NULL);
    3257 assert(lincoef != NULL);
    3258 assert(linconstant != NULL);
    3259 assert(success != NULL);
    3260
    3261 if( sqrcoef == 0.0 )
    3262 return;
    3263
    3264 if( SCIPisInfinity(scip, REALABS(refpoint)) )
    3265 {
    3266 *success = FALSE;
    3267 return;
    3268 }
    3269
    3270 if( !isint || SCIPisIntegral(scip, refpoint) )
    3271 {
    3272 SCIP_Real tmp;
    3273
    3274 /* sqrcoef * x^2 -> tangent in refpoint = sqrcoef * 2 * refpoint * (x - refpoint) */
    3275
    3276 tmp = sqrcoef * refpoint;
    3277
    3278 if( SCIPisInfinity(scip, 2.0 * REALABS(tmp)) )
    3279 {
    3280 *success = FALSE;
    3281 return;
    3282 }
    3283
    3284 *lincoef += 2.0 * tmp;
    3285 tmp *= refpoint;
    3286 *linconstant -= tmp;
    3287 }
    3288 else
    3289 {
    3290 /* sqrcoef * x^2 -> secant between f=floor(refpoint) and f+1 = sqrcoef * (f^2 + ((f+1)^2 - f^2) * (x-f))
    3291 * = sqrcoef * (-f*(f+1) + (2*f+1)*x)
    3292 */
    3293 SCIP_Real f;
    3294 SCIP_Real coef;
    3295 SCIP_Real constant;
    3296
    3297 f = SCIPfloor(scip, refpoint);
    3298
    3299 coef = sqrcoef * (2.0 * f + 1.0);
    3300 constant = -sqrcoef * f * (f + 1.0);
    3301
    3302 if( SCIPisInfinity(scip, REALABS(coef)) || SCIPisInfinity(scip, REALABS(constant)) )
    3303 {
    3304 *success = FALSE;
    3305 return;
    3306 }
    3307
    3308 *lincoef += coef;
    3309 *linconstant += constant;
    3310 }
    3311}
    3312
    3313/** computes coefficients of secant of a square term */
    3315 SCIP* scip, /**< SCIP data structure */
    3316 SCIP_Real sqrcoef, /**< coefficient of square term */
    3317 SCIP_Real lb, /**< lower bound on variable */
    3318 SCIP_Real ub, /**< upper bound on variable */
    3319 SCIP_Real* lincoef, /**< buffer to add coefficient of secant */
    3320 SCIP_Real* linconstant, /**< buffer to add constant of secant */
    3321 SCIP_Bool* success /**< buffer to set to FALSE if secant has failed due to large numbers or unboundedness */
    3322 )
    3323{
    3324 SCIP_Real coef;
    3325 SCIP_Real constant;
    3326
    3327 assert(scip != NULL);
    3328 assert(!SCIPisInfinity(scip, lb));
    3329 assert(!SCIPisInfinity(scip, -ub));
    3330 assert(SCIPisLE(scip, lb, ub));
    3331 assert(lincoef != NULL);
    3332 assert(linconstant != NULL);
    3333 assert(success != NULL);
    3334
    3335 if( sqrcoef == 0.0 )
    3336 return;
    3337
    3338 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
    3339 {
    3340 /* unboundedness */
    3341 *success = FALSE;
    3342 return;
    3343 }
    3344
    3345 /* sqrcoef * x^2 -> sqrcoef * (lb * lb + (ub*ub - lb*lb)/(ub-lb) * (x-lb)) = sqrcoef * (lb*lb + (ub+lb)*(x-lb))
    3346 * = sqrcoef * ((lb+ub)*x - lb*ub)
    3347 */
    3348 coef = sqrcoef * (lb + ub);
    3349 constant = -sqrcoef * lb * ub;
    3350 if( SCIPisInfinity(scip, REALABS(coef)) || SCIPisInfinity(scip, REALABS(constant)) )
    3351 {
    3352 *success = FALSE;
    3353 return;
    3354 }
    3355
    3356 *lincoef += coef;
    3357 *linconstant += constant;
    3358}
    3359
    3360/** Separation for roots with exponent in [0,1]
    3361 *
    3362 * - x^0.5 with x >= 0
    3363 <pre>
    3364 8 +----------------------------------------------------------------------+
    3365 | + + + + |
    3366 7 |-+ x**0.5 ********|
    3367 | *********|
    3368 | ******** |
    3369 6 |-+ ******** +-|
    3370 | ****** |
    3371 5 |-+ ****** +-|
    3372 | ****** |
    3373 | ***** |
    3374 4 |-+ **** +-|
    3375 | ***** |
    3376 3 |-+ **** +-|
    3377 | *** |
    3378 | *** |
    3379 2 |-+ ** +-|
    3380 | ** |
    3381 1 |** +-|
    3382 |* |
    3383 |* + + + + |
    3384 0 +----------------------------------------------------------------------+
    3385 0 10 20 30 40 50
    3386 </pre>
    3387 */
    3389 SCIP* scip, /**< SCIP data structure */
    3390 SCIP_Real exponent, /**< exponent */
    3391 SCIP_Bool overestimate, /**< should the power be overestimated? */
    3392 SCIP_Real xlb, /**< lower bound on x */
    3393 SCIP_Real xub, /**< upper bound on x */
    3394 SCIP_Real xref, /**< reference point (where to linearize) */
    3395 SCIP_Real* constant, /**< buffer to store constant term of estimator */
    3396 SCIP_Real* slope, /**< buffer to store slope of estimator */
    3397 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
    3398 it depends on given bounds */
    3399 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
    3400 )
    3401{
    3402 assert(scip != NULL);
    3403 assert(constant != NULL);
    3404 assert(slope != NULL);
    3405 assert(islocal != NULL);
    3406 assert(success != NULL);
    3407 assert(exponent > 0.0);
    3408 assert(exponent < 1.0);
    3409 assert(xlb >= 0.0);
    3410
    3411 if( !overestimate )
    3412 {
    3413 /* underestimate -> secant */
    3414 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
    3415 *islocal = TRUE;
    3416 }
    3417 else
    3418 {
    3419 /* overestimate -> tangent */
    3420
    3421 /* need to linearize right of 0 */
    3422 if( xref < 0.0 )
    3423 xref = 0.0;
    3424
    3425 if( SCIPisZero(scip, xref) )
    3426 {
    3427 if( SCIPisZero(scip, xub) )
    3428 {
    3429 *success = FALSE;
    3430 *islocal = FALSE;
    3431 return;
    3432 }
    3433
    3434 /* if xref is 0 (then xlb=0 probably), then slope is infinite, then try to move away from 0 */
    3435 if( xub < 0.2 )
    3436 xref = 0.5 * xlb + 0.5 * xub;
    3437 else
    3438 xref = 0.1;
    3439 }
    3440
    3441 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
    3442 *islocal = FALSE;
    3443 }
    3444}
    3445
    3446/* from pub_expr.h */
    3447
    3448/** gets the exponent of a power or signed power expression */ /*lint -e{715}*/
    3450 SCIP_EXPR* expr /**< expression */
    3451 )
    3452{
    3453 SCIP_EXPRDATA* exprdata;
    3454
    3455 assert(expr != NULL);
    3456
    3457 exprdata = SCIPexprGetData(expr);
    3458 assert(exprdata != NULL);
    3459
    3460 return exprdata->exponent;
    3461}
    #define NULL
    Definition: def.h:257
    #define EPSISINT(x, eps)
    Definition: def.h:204
    #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
    absolute expression handler
    exponential expression handler
    #define SIGNPOWEXPRHDLR_PRECEDENCE
    Definition: expr_pow.c:55
    static SCIP_DECL_EXPRPRINT(printPow)
    Definition: expr_pow.c:1841
    static SCIP_DECL_EXPRESTIMATE(estimatePow)
    Definition: expr_pow.c:2080
    static SCIP_DECL_EXPRREVERSEPROP(reversepropPow)
    Definition: expr_pow.c:2157
    #define POWEXPRHDLR_PRECEDENCE
    Definition: expr_pow.c:50
    void SCIPaddSquareLinearization(SCIP *scip, SCIP_Real sqrcoef, SCIP_Real refpoint, SCIP_Bool isint, SCIP_Real *lincoef, SCIP_Real *linconstant, SCIP_Bool *success)
    Definition: expr_pow.c:3246
    static SCIP_DECL_EXPRBWDIFF(bwdiffPow)
    Definition: expr_pow.c:1977
    static SCIP_RETCODE chooseRefpointsPow(SCIP *scip, SCIP_EXPRDATA *exprdata, SCIP_Real lb, SCIP_Real ub, SCIP_Real *refpointsunder, SCIP_Real *refpointsover, SCIP_Bool underestimate, SCIP_Bool overestimate)
    Definition: expr_pow.c:1214
    static SCIP_DECL_EXPRPARSE(parseSignpower)
    Definition: expr_pow.c:2692
    static SCIP_DECL_EXPRINITESTIMATES(initestimatesPow)
    Definition: expr_pow.c:2251
    static SCIP_DECL_EXPRFWDIFF(fwdiffPow)
    Definition: expr_pow.c:1915
    static void estimateSignedpower(SCIP *scip, SCIP_Real exponent, SCIP_Real root, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real xlbglobal, SCIP_Real xubglobal, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *branchcand, SCIP_Bool *success)
    Definition: expr_pow.c:550
    static SCIP_DECL_EXPRFREEHDLR(freehdlrPow)
    Definition: expr_pow.c:1792
    static void computeTangent(SCIP *scip, SCIP_Bool signpower, SCIP_Real exponent, SCIP_Real xref, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *success)
    Definition: expr_pow.c:255
    #define SIGNPOWEXPRHDLR_NAME
    Definition: expr_pow.c:53
    static SCIP_DECL_EXPRINTEVAL(intevalPow)
    Definition: expr_pow.c:2008
    void SCIPestimateRoot(SCIP *scip, SCIP_Real exponent, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *success)
    Definition: expr_pow.c:3388
    #define SIGNPOWEXPRHDLR_HASHKEY
    Definition: expr_pow.c:56
    #define POWEXPRHDLR_NAME
    Definition: expr_pow.c:48
    static SCIP_DECL_EXPRCOPYHDLR(copyhdlrPow)
    Definition: expr_pow.c:1783
    static SCIP_RETCODE buildPowEstimator(SCIP *scip, SCIP_EXPRDATA *exprdata, SCIP_Bool overestimate, SCIP_Real childlb, SCIP_Real childub, SCIP_Real childglb, SCIP_Real childgub, SCIP_Bool childintegral, SCIP_Real refpoint, SCIP_Real exponent, SCIP_Real *coef, SCIP_Real *constant, SCIP_Bool *success, SCIP_Bool *islocal, SCIP_Bool *branchcand)
    Definition: expr_pow.c:988
    static void estimateParabola(SCIP *scip, SCIP_Real exponent, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *success)
    Definition: expr_pow.c:484
    static SCIP_DECL_EXPRGETSYMDATA(getSymDataPow)
    Definition: expr_pow.c:1760
    static SCIP_DECL_EXPREVAL(evalPow)
    Definition: expr_pow.c:1885
    #define SIGN(x)
    Definition: expr_pow.c:69
    static SCIP_RETCODE createData(SCIP *scip, SCIP_EXPRDATA **exprdata, SCIP_Real exponent)
    Definition: expr_pow.c:229
    static SCIP_DECL_EXPRMONOTONICITY(monotonicityPow)
    Definition: expr_pow.c:2383
    static SCIP_DECL_EXPRINTEGRALITY(integralityPow)
    Definition: expr_pow.c:2446
    static SCIP_DECL_EXPRCURVATURE(curvaturePow)
    Definition: expr_pow.c:2354
    static SCIP_DECL_EXPRCOMPARE(comparePow)
    Definition: expr_pow.c:1302
    static SCIP_DECL_EXPRFREEDATA(freedataPow)
    Definition: expr_pow.c:1823
    void SCIPaddSquareSecant(SCIP *scip, SCIP_Real sqrcoef, SCIP_Real lb, SCIP_Real ub, SCIP_Real *lincoef, SCIP_Real *linconstant, SCIP_Bool *success)
    Definition: expr_pow.c:3314
    static SCIP_RETCODE addSignpowerRefpoints(SCIP *scip, SCIP_EXPRDATA *exprdata, SCIP_Real lb, SCIP_Real ub, SCIP_Real exponent, SCIP_Bool underestimate, SCIP_Real *refpoints)
    Definition: expr_pow.c:1159
    #define SIGNPOW_ROOTS_KNOWN
    Definition: expr_pow.c:71
    static void estimateHyperbolaPositive(SCIP *scip, SCIP_Real exponent, SCIP_Real root, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real xlbglobal, SCIP_Real xubglobal, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *branchcand, SCIP_Bool *success)
    Definition: expr_pow.c:698
    static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffPow)
    Definition: expr_pow.c:1948
    #define POWEXPRHDLR_HASHKEY
    Definition: expr_pow.c:51
    static SCIP_DECL_EXPRCOPYDATA(copydataPow)
    Definition: expr_pow.c:1804
    static SCIP_RETCODE computeSignpowerRoot(SCIP *scip, SCIP_Real *root, SCIP_Real exponent)
    Definition: expr_pow.c:115
    static SCIP_DECL_EXPRSIMPLIFY(simplifyPow)
    Definition: expr_pow.c:1325
    static void estimateHyperbolaMixed(SCIP *scip, SCIP_Real exponent, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real xlbglobal, SCIP_Real xubglobal, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *branchcand, SCIP_Bool *success)
    Definition: expr_pow.c:910
    #define SIGNPOWEXPRHDLR_DESC
    Definition: expr_pow.c:54
    #define INITLPMAXPOWVAL
    Definition: expr_pow.c:58
    #define POWEXPRHDLR_DESC
    Definition: expr_pow.c:49
    static SCIP_DECL_EXPRHASH(hashPow)
    Definition: expr_pow.c:2337
    static void addTangentRefpoints(SCIP *scip, SCIP_Real exponent, SCIP_Real lb, SCIP_Real ub, SCIP_Real *refpoints)
    Definition: expr_pow.c:1121
    static SCIP_RETCODE computeHyperbolaRoot(SCIP *scip, SCIP_Real *root, SCIP_Real exponent)
    Definition: expr_pow.c:183
    static SCIP_Real signpow_roots[SIGNPOW_ROOTS_KNOWN+1]
    Definition: expr_pow.c:77
    static void computeSecant(SCIP *scip, SCIP_Bool signpower, SCIP_Real exponent, SCIP_Real xlb, SCIP_Real xub, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *success)
    Definition: expr_pow.c:304
    power and signed power expression handlers
    product expression handler
    sum expression handler
    constant value expression handler
    SCIP_RETCODE SCIPcreateExprProduct(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real coefficient, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    SCIP_RETCODE SCIPpowerExprSum(SCIP *scip, SCIP_EXPR **result, SCIP_EXPR *base, int exponent, SCIP_Bool simplify, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:1315
    SCIP_Bool SCIPisExprAbs(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_abs.c:546
    SCIP_RETCODE SCIPcreateExprAbs(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_abs.c:528
    SCIP_RETCODE SCIPcreateExprSignpower(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_pow.c:3210
    SCIP_Bool SCIPisExprExp(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_exp.c:529
    SCIP_RETCODE SCIPcreateExprExp(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_exp.c:511
    SCIP_Bool SCIPisExprSignpower(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_pow.c:3235
    SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:1117
    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 SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_pow.c:3186
    SCIP_RETCODE SCIPincludeExprhdlrSignpower(SCIP *scip)
    Definition: expr_pow.c:3156
    SCIP_RETCODE SCIPincludeExprhdlrPow(SCIP *scip)
    Definition: expr_pow.c:3112
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    SCIP_VERBLEVEL SCIPgetVerbLevel(SCIP *scip)
    Definition: scip_message.c:249
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:83
    SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:139
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    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 SCIPexprhdlrSetPrint(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRPRINT((*print)))
    Definition: expr.c:396
    void SCIPexprhdlrSetGetSymdata(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRGETSYMDATA((*getsymdata)))
    Definition: expr.c:521
    void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
    Definition: expr.c:451
    SCIP_EXPRHDLRDATA * SCIPexprhdlrGetData(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:575
    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
    void SCIPexprhdlrSetCompare(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOMPARE((*compare)))
    Definition: expr.c:462
    SCIP_EXPRHDLR * SCIPgetExprhdlrPower(SCIP *scip)
    Definition: scip_expr.c:950
    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_IMPLINTTYPE SCIPexprGetIntegrality(SCIP_EXPR *expr)
    Definition: expr.c:4091
    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
    SCIP_RETCODE SCIPappendExprChild(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child)
    Definition: scip_expr.c:1256
    void SCIPexprSetData(SCIP_EXPR *expr, SCIP_EXPRDATA *exprdata)
    Definition: expr.c:3920
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
    Definition: expr_pow.c:3449
    SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1490
    SCIP_EXPRCURV SCIPexprcurvPowerInv(SCIP_INTERVAL basebounds, SCIP_Real exponent, SCIP_EXPRCURV powercurv)
    Definition: exprcurv.c:209
    SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1479
    SCIP_Bool SCIPexprIsIntegral(SCIP_EXPR *expr)
    Definition: expr.c:4101
    SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1554
    SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1468
    int SCIPcompareExpr(SCIP *scip, SCIP_EXPR *expr1, SCIP_EXPR *expr2)
    Definition: scip_expr.c:1759
    SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
    Definition: scip_expr.c:1443
    SCIP_Real SCIPexprGetDot(SCIP_EXPR *expr)
    Definition: expr.c:3986
    SCIP_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1457
    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_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
    Definition: scip_expr.c:1512
    SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
    Definition: expr_value.c:298
    SCIP_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1501
    SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
    Definition: expr.c:3946
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1569
    SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
    Definition: expr_var.c:423
    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)
    SCIP_Bool SCIPintervalIsEntire(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalSignPowerScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
    void SCIPintervalUnify(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
    SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalPowerScalarInverse(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL basedomain, SCIP_Real exponent, SCIP_INTERVAL image)
    void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
    void SCIPintervalReciprocal(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
    void SCIPintervalPowerScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
    SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
    void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
    #define SCIPallocClearBlockMemory(scip, ptr)
    Definition: scip_mem.h:91
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
    SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
    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 SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
    SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
    Definition: var.c:23510
    public functions to work with algebraic expressions
    #define SCIPerrorMessage
    Definition: pub_message.h:64
    #define SCIPdebugPrintf
    Definition: pub_message.h:99
    #define SCIPisFinite(x)
    Definition: pub_misc.h:82
    SCIP_Real sup
    Definition: intervalarith.h:57
    SCIP_Real inf
    Definition: intervalarith.h:56
    structs for symmetry computations
    #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_CONVEX
    Definition: type_expr.h:63
    @ SCIP_EXPRCURV_UNKNOWN
    Definition: type_expr.h:62
    @ SCIP_EXPRCURV_CONCAVE
    Definition: type_expr.h:64
    #define SCIP_EXPR_MAXINITESTIMATES
    Definition: type_expr.h:198
    #define SCIP_EXPRITER_VISITINGCHILD
    Definition: type_expr.h:695
    @ SCIP_MONOTONE_UNKNOWN
    Definition: type_expr.h:71
    @ SCIP_MONOTONE_INC
    Definition: type_expr.h:72
    @ SCIP_MONOTONE_DEC
    Definition: type_expr.h:73
    #define SCIP_EXPRITER_VISITEDCHILD
    Definition: type_expr.h:696
    #define SCIP_EXPRITER_LEAVEEXPR
    Definition: type_expr.h:697
    #define SCIP_EXPRITER_ENTEREXPR
    Definition: type_expr.h:694
    @ SCIP_VERBLEVEL_NONE
    Definition: type_message.h:57
    @ SCIP_READERROR
    Definition: type_retcode.h:45
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    @ SCIP_ERROR
    Definition: type_retcode.h:43
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_IMPLINTTYPE_NONE
    Definition: type_var.h:90