Scippy

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