Scippy

    SCIP

    Solving Constraint Integer Programs

    expr_trig.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_trig.c
    26 * @ingroup DEFPLUGINS_EXPR
    27 * @brief handler for sine and cosine expressions
    28 * @author Fabian Wegscheider
    29 *
    30 * The estimator/separator code always computes underestimators for sin(x).
    31 * For overestimators of cos(x), we first reduce to underestimators of sin(x).
    32 *
    33 * Overestimator for sin(x):
    34 * Assume that a*y+b <= sin(y) for y in [-ub,-lb].
    35 * Then we have a*(-y)-b >= -sin(y) = sin(-y) for y in [-ub,-lb].
    36 * Thus, a*x-b >= sin(x) for x in [lb,ub].
    37 *
    38 * Underestimator for cos(x):
    39 * Assume that a*y+b <= sin(y) for y in [lb+pi/2,ub+pi/2].
    40 * Then we have a*(x+pi/2) + b <= sin(x+pi/2) = cos(x) for x in [lb,ub].
    41 * Thus, a*x + (b+a*pi/2) <= cos(x) for x in [lb,ub].
    42 *
    43 * Overestimator for cos(x):
    44 * Assume that a*z+b <= sin(z) for z in [-(ub+pi/2),-(lb+pi/2)].
    45 * Then, a*y-b >= sin(y) for y in [lb+pi/2,ub+pi/2].
    46 * Then, a*x-b+a*pi/2 >= cos(x) for x in [lb,ub].
    47 */
    48
    49/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    50
    51#define _USE_MATH_DEFINES /* to get M_PI on Windows */ /*lint !750 */
    52
    53#include <string.h>
    54#include <math.h>
    55#include "scip/expr_trig.h"
    56#include "scip/expr_value.h"
    57
    58/* fundamental expression handler properties */
    59#define SINEXPRHDLR_NAME "sin"
    60#define SINEXPRHDLR_DESC "sine expression"
    61#define SINEXPRHDLR_PRECEDENCE 91000
    62#define SINEXPRHDLR_HASHKEY SCIPcalcFibHash(82457.0)
    63
    64#define COSEXPRHDLR_NAME "cos"
    65#define COSEXPRHDLR_DESC "cosine expression"
    66#define COSEXPRHDLR_PRECEDENCE 92000
    67#define COSEXPRHDLR_HASHKEY SCIPcalcFibHash(82463.0)
    68
    69#define MAXCHILDABSVAL 1e+6 /**< maximum absolute value that is accepted for propagation */
    70#define NEWTON_NITERATIONS 100
    71#define NEWTON_PRECISION 1e-12
    72
    73/*
    74 * Local methods
    75 */
    76
    77/** evaluates the function a*x + b - sin(x) for some coefficient a and constant b at a given point p
    78 *
    79 * the constants a and b are expected to be stored in that order in params
    80 */
    81static
    83{ /*lint --e{715}*/
    84 assert(params != NULL);
    85 assert(nparams == 2);
    86
    87 return params[0]*point + params[1] - sin(point);
    88}
    89
    90/** evaluates the derivative of a*x + b - sin(x) for some coefficient a and constant b at a given point p
    91 *
    92 * the constants a and b are expected to be stored in that order in params
    93 */
    94static
    96{ /*lint --e{715}*/
    97 assert(params != NULL);
    98 assert(nparams == 2);
    99
    100 return params[0] - cos(point);
    101}
    102
    103/** evaluates the function sin(x) + (alpha - x)*cos(x) - sin(alpha) for some constant alpha at a given point p
    104 *
    105 * the constant alpha is expected to be stored in params
    106 */
    107static
    109{ /*lint --e{715}*/
    110 assert(params != NULL);
    111 assert(nparams == 1);
    112
    113 return sin(point) + (params[0] - point) * cos(point) - sin(params[0]);
    114}
    115
    116/** evaluates the derivative of sin(x) + (alpha - x)*cos(x) - sin(alpha) for some constant alpha at a given point p
    117 *
    118 * the constant alpha is expected to be stored in params
    119 */
    120static
    122{ /*lint --e{715}*/
    123 assert(params != NULL);
    124 assert(nparams == 1);
    125
    126 return (point - params[0]) * sin(point);
    127}
    128
    129/** helper function to compute the secant if it is a valid underestimator
    130 *
    131 * returns true if the estimator was computed successfully
    132 */
    133static
    135 SCIP* scip, /**< SCIP data structure */
    136 SCIP_Real* lincoef, /**< buffer to store linear coefficient of secant */
    137 SCIP_Real* linconst, /**< buffer to store linear constant of secant */
    138 SCIP_Real lb, /**< lower bound of argument variable */
    139 SCIP_Real ub /**< upper bound of argument variable */
    140 )
    141{
    142 assert(scip != NULL);
    143 assert(lincoef != NULL);
    144 assert(linconst != NULL);
    145 assert(lb < ub);
    146
    147 /* if range is too big, secant is not underestimating */
    148 if( ub - lb >= M_PI )
    149 return FALSE;
    150
    151 /* if bounds are not within positive bay, secant is not underestimating */
    152 if( sin(lb) < 0.0 || sin(ub) < 0.0 || (sin(lb) == 0.0 && cos(lb) < 0.0) )
    153 return FALSE;
    154
    155 *lincoef = (sin(ub) - sin(lb)) / (ub - lb);
    156 *linconst = sin(ub) - (*lincoef) * ub;
    157
    158 return TRUE;
    159}
    160
    161/** helper function to compute the tangent at lower bound if it is underestimating
    162 *
    163 * returns true if the underestimator was computed successfully
    164 */
    165static
    167 SCIP* scip, /**< SCIP data structure */
    168 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    169 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    170 SCIP_Real lb /**< lower bound of argument variable */
    171 )
    172{
    173 assert(scip != NULL);
    174 assert(lincoef != NULL);
    175 assert(linconst != NULL);
    176
    177 if( SCIPisInfinity(scip, -lb) )
    178 return FALSE;
    179
    180 /* left tangent is only underestimating in [pi, 1.5*pi) *2kpi */
    181 if( sin(lb) > 0.0 || cos(lb) >= 0.0 )
    182 return FALSE;
    183
    184 *lincoef = cos(lb);
    185 *linconst = sin(lb) - (*lincoef) * lb;
    186
    187 return TRUE;
    188}
    189
    190/* TODO: fix this, more cases can be considered, see at unit test
    191 * the underestimating of the tangents depends not only on the ub but also on the lower bound.
    192 * right now, this function is only checking whether the tangent underestimates independently of the lower bound!
    193 */
    194/** helper function to compute the tangent at upper bound if it is an underestimator
    195 *
    196 * returns true if the underestimator was computed successfully
    197 */
    198static
    200 SCIP* scip, /**< SCIP data structure */
    201 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    202 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    203 SCIP_Real ub /**< upper bound of argument variable */
    204 )
    205{
    206 assert(scip != NULL);
    207 assert(lincoef != NULL);
    208 assert(linconst != NULL);
    209
    210 if( SCIPisInfinity(scip, ub) )
    211 return FALSE;
    212
    213 /* right tangent is only underestimating in (1.5*pi, 2*pi] *2kpi */
    214 if( sin(ub) > 0.0 || cos(ub) <= 0.0 )
    215 return FALSE;
    216
    217 *lincoef = cos(ub);
    218 *linconst = sin(ub) - (*lincoef) * ub;
    219
    220 return TRUE;
    221}
    222
    223/** helper function to compute the tangent at solution point if it is an underestimator
    224 *
    225 * returns true if the underestimator was computed successfully
    226 */
    227static
    229 SCIP* scip, /**< SCIP data structure */
    230 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    231 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    232 SCIP_Real lb, /**< lower bound of argument variable */
    233 SCIP_Real ub, /**< upper bound of argument variable */
    234 SCIP_Real solpoint /**< solution point to be separated */
    235 )
    236{
    237 SCIP_Real params[2];
    238 SCIP_Real startingpoints[3];
    239 SCIP_Real solpointmodpi;
    240 SCIP_Real intersection;
    241 int i;
    242
    243 assert(scip != NULL);
    244 assert(lincoef != NULL);
    245 assert(linconst != NULL);
    246
    247 /* tangent is only underestimating in negative bay */
    248 if( sin(solpoint) > 0.0 )
    249 return FALSE;
    250
    251 /* compute solution point mod pi */
    252 solpointmodpi = fmod(solpoint, M_PI);
    253 if( solpoint < 0.0 )
    254 solpointmodpi += M_PI;
    255
    256 /* if the point is too far away from the bounds or is at a multiple of pi, then tangent is not underestimating */
    257 if( SCIPisGE(scip, solpoint - lb, 2*M_PI) || SCIPisGE(scip, ub - solpoint, 2*M_PI)
    258 || SCIPisZero(scip, solpointmodpi) )
    259 return FALSE;
    260
    261 params[0] = cos(solpoint);
    262 params[1] = sin(solpoint) - params[0] * solpoint;
    263
    264 /* choose starting points for Newton procedure */
    265 if( SCIPisGT(scip, solpointmodpi, M_PI_2) )
    266 {
    267 startingpoints[0] = solpoint + (M_PI - solpointmodpi) + M_PI_2;
    268 startingpoints[1] = startingpoints[0] + M_PI_2;
    269 startingpoints[2] = startingpoints[1] + M_PI_2;
    270 }
    271 else
    272 {
    273 startingpoints[0] = solpoint - solpointmodpi - M_PI_2;
    274 startingpoints[1] = startingpoints[0] - M_PI_2;
    275 startingpoints[2] = startingpoints[1] - M_PI_2;
    276 }
    277
    278 /* use Newton procedure to test if cut is valid */
    279 for( i = 0; i < 3; ++i )
    280 {
    281 intersection = SCIPcalcRootNewton(function1, derivative1, params, 2, startingpoints[i], NEWTON_PRECISION,
    283
    284 if( intersection != SCIP_INVALID && !SCIPisEQ(scip, intersection, solpoint) ) /*lint !e777*/
    285 break;
    286 }
    287
    288 /* if Newton failed or intersection point lies within bounds, underestimator is not valid */
    289 if( intersection == SCIP_INVALID || (intersection >= lb && intersection <= ub) ) /*lint !e777*/
    290 return FALSE;
    291
    292 *lincoef = params[0];
    293 *linconst = params[1];
    294
    295 return TRUE;
    296}
    297
    298/** helper function to compute the secant between lower bound and some point of the graph such that it underestimates
    299 *
    300 * returns true if the underestimator was computed successfully
    301 */
    302static
    304 SCIP* scip, /**< SCIP data structure */
    305 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    306 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    307 SCIP_Real lb, /**< lower bound of argument variable */
    308 SCIP_Real ub /**< upper bound of argument variable */
    309 )
    310{
    311 SCIP_Real lbmodpi;
    312 SCIP_Real tangentpoint;
    313 SCIP_Real startingpoint;
    314
    315 assert(scip != NULL);
    316 assert(lincoef != NULL);
    317 assert(linconst != NULL);
    318 assert(lb < ub);
    319
    320 if( SCIPisInfinity(scip, -lb) )
    321 return FALSE;
    322
    323 /* compute shifted bounds for case evaluation */
    324 lbmodpi = fmod(lb, M_PI);
    325 if( lb < 0.0 )
    326 lbmodpi += M_PI;
    327
    328 /* choose starting point for Newton procedure */
    329 if( cos(lb) < 0.0 )
    330 {
    331 /* in [pi/2,pi] underestimating doesn't work; otherwise, take the midpoint of possible area */
    332 if( SCIPisLE(scip, sin(lb), 0.0) )
    333 return FALSE;
    334 else
    335 startingpoint = lb + 1.25*M_PI - lbmodpi;
    336 }
    337 else
    338 {
    339 /* in ascending area, take the midpoint of the possible area in descending part */
    340 /* for lb < 0 but close to zero, we may have sin(lb) = 0 but lbmodpi = pi, which gives a starting point too close to lb
    341 * but for sin(lb) around 0 we know that the tangent point needs to be in [lb+pi,lb+pi+pi/2]
    342 */
    343 if( SCIPisZero(scip, sin(lb)) )
    344 startingpoint = lb + 1.25*M_PI;
    345 else if( sin(lb) < 0.0 )
    346 startingpoint = lb + 2.25*M_PI - lbmodpi;
    347 else
    348 startingpoint = lb + 1.25*M_PI - lbmodpi;
    349 }
    350
    351 /* use Newton procedure to find the point where the tangent intersects sine at lower bound */
    352 tangentpoint = SCIPcalcRootNewton(function2, derivative2, &lb, 1, startingpoint, NEWTON_PRECISION,
    354
    355 /* if Newton procedure failed, no cut is added */
    356 if( tangentpoint == SCIP_INVALID ) /*lint !e777*/
    357 return FALSE;
    358
    359 /* if the computed point lies outside the bounds, it is shifted to upper bound */
    360 if( SCIPisGE(scip, tangentpoint, ub) )
    361 {
    362 tangentpoint = ub;
    363
    364 /* check whether affine function is still underestimating */
    365 if( SCIPisLE(scip, sin(0.5 * (ub + lb)), sin(lb) + 0.5*(sin(ub) - sin(lb))) )
    366 return FALSE;
    367 }
    368
    369 if( SCIPisEQ(scip, tangentpoint, lb) ) /*lint !e777 */
    370 return FALSE;
    371
    372 /* compute secant between lower bound and connection point */
    373 *lincoef = (sin(tangentpoint) - sin(lb)) / (tangentpoint - lb);
    374 *linconst = sin(lb) - (*lincoef) * lb;
    375
    376 /* if the bounds are too close to each other, it's possible that the underestimator is not valid */
    377 if( *lincoef >= cos(lb) )
    378 return FALSE;
    379
    380 SCIPdebugMsg(scip, "left secant: %g + %g*x <= sin(x) on [%g,%g]\n", *linconst, *lincoef, lb, ub);
    381
    382 return TRUE;
    383}
    384
    385/** helper function to compute the secant between upper bound and some point of the graph such that it underestimates
    386 *
    387 * returns true if the underestimator was computed successfully
    388 */
    389static
    391 SCIP* scip, /**< SCIP data structure */
    392 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    393 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    394 SCIP_Real lb, /**< lower bound of argument variable */
    395 SCIP_Real ub /**< upper bound of argument variable */
    396 )
    397{
    398 SCIP_Real ubmodpi;
    399 SCIP_Real tangentpoint;
    400 SCIP_Real startingpoint;
    401
    402 assert(scip != NULL);
    403 assert(lincoef != NULL);
    404 assert(linconst != NULL);
    405 assert(lb < ub);
    406
    407 if( SCIPisInfinity(scip, ub) )
    408 return FALSE;
    409
    410 /* compute shifted bounds for case evaluation */
    411 ubmodpi = fmod(ub, M_PI);
    412 if( ub < 0.0 )
    413 ubmodpi += M_PI;
    414
    415 /* choose starting point for Newton procedure */
    416 if( cos(ub) > 0.0 )
    417 {
    418 /* in [3*pi/2,2*pi] underestimating doesn't work; otherwise, take the midpoint of possible area */
    419 if( SCIPisLE(scip, sin(ub), 0.0) )
    420 return FALSE;
    421 else
    422 startingpoint = ub - M_PI_4 - ubmodpi;
    423 }
    424 else
    425 {
    426 /* in descending area, take the midpoint of the possible area in ascending part */
    427 /* for ub < 0 but close to zero, we may have sin(ub) = 0 but ubmodpi = pi, which gives a starting point too close to ub
    428 * but for sin(ub) around 0 we know that the tangent point needs to be in [ub-(pi+pi/2),ub-pi]
    429 */
    430 if( SCIPisZero(scip, sin(ub)) )
    431 startingpoint = ub - 1.25*M_PI;
    432 else if( sin(ub) < 0.0 )
    433 startingpoint = ub - 1.25*M_PI - ubmodpi;
    434 else
    435 startingpoint = ub - M_PI_4 - ubmodpi;
    436 }
    437
    438 /* use Newton procedure to find the point where the tangent intersects sine at lower bound */
    439 tangentpoint = SCIPcalcRootNewton(function2, derivative2, &ub, 1, startingpoint, NEWTON_PRECISION,
    441
    442 /* if Newton procedure failed, no underestimator is found */
    443 if( tangentpoint == SCIP_INVALID ) /*lint !e777*/
    444 return FALSE;
    445
    446 /* if the computed point lies outside the bounds, it is shifted to upper bound */
    447 if( SCIPisLE(scip, tangentpoint, lb) )
    448 {
    449 tangentpoint = lb;
    450
    451 /* check whether affine function is still underestimating */
    452 if( SCIPisLE(scip, sin(0.5 * (ub + lb)), sin(lb) + 0.5*(sin(ub) - sin(lb))) )
    453 return FALSE;
    454 }
    455
    456 if( SCIPisEQ(scip, tangentpoint, ub) ) /*lint !e777 */
    457 return FALSE;
    458
    459 /* compute secant between lower bound and connection point */
    460 *lincoef = (sin(tangentpoint) - sin(ub)) / (tangentpoint - ub);
    461 *linconst = sin(ub) - (*lincoef) * ub;
    462
    463 /* if the bounds are to close to each other, it's possible that the underestimator is not valid */
    464 if( *lincoef <= cos(lb) )
    465 return FALSE;
    466
    467 return TRUE;
    468}
    469
    470/** helper function to compute the new interval for child in reverse propagation */
    471static
    473 SCIP* scip, /**< SCIP data structure */
    474 SCIP_INTERVAL parentbounds, /**< bounds for sine expression */
    475 SCIP_INTERVAL childbounds, /**< bounds for child expression */
    476 SCIP_INTERVAL* newbounds /**< buffer to store new child bounds */
    477 )
    478{
    479 SCIP_Real newinf = childbounds.inf;
    480 SCIP_Real newsup = childbounds.sup;
    481
    482 /* if the absolute values of the bounds are too large, skip reverse propagation
    483 * TODO: if bounds are close but too large, shift them to [0,2pi] and do the computation there
    484 */
    485 if( ABS(newinf) > MAXCHILDABSVAL || ABS(newsup) > MAXCHILDABSVAL )
    486 {
    487 SCIPintervalSetBounds(newbounds, newinf, newsup);
    488 return SCIP_OKAY;
    489 }
    490
    491 if( !SCIPisInfinity(scip, -newinf) )
    492 {
    493 /* l(x) and u(x) are lower/upper bound of child, l(s) and u(s) are lower/upper bound of sin expr
    494 *
    495 * if sin(l(x)) < l(s), we are looking for k minimal s.t. a + 2k*pi > l(x) where a = asin(l(s))
    496 * then the new lower bound is a + 2k*pi
    497 */
    498 if( SCIPisLT(scip, sin(newinf), parentbounds.inf) )
    499 {
    500 SCIP_Real a = asin(parentbounds.inf);
    501 int k = (int) ceil((newinf - a) / (2.0*M_PI));
    502 newinf = a + 2.0*M_PI * k;
    503 }
    504
    505 /* if sin(l(x)) > u(s), we are looking for k minimal s.t. pi - a + 2k*pi > l(x) where a = asin(u(s))
    506 * then the new lower bound is pi - a + 2k*pi
    507 */
    508 else if( SCIPisGT(scip, sin(newinf), parentbounds.sup) )
    509 {
    510 SCIP_Real a = asin(parentbounds.sup);
    511 int k = (int) ceil((newinf + a) / (2.0*M_PI) - 0.5);
    512 newinf = M_PI * (2.0*k + 1.0) - a;
    513 }
    514
    515 assert(newinf >= childbounds.inf);
    516 assert(SCIPisFeasGE(scip, sin(newinf), parentbounds.inf));
    517 assert(SCIPisFeasLE(scip, sin(newinf), parentbounds.sup));
    518 }
    519
    520 if( !SCIPisInfinity(scip, newsup) )
    521 {
    522 /* if sin(u(x)) > u(s), we are looking for k minimal s.t. a + 2k*pi > u(x) - 2*pi where a = asin(u(s))
    523 * then the new upper bound is a + 2k*pi
    524 */
    525 if ( SCIPisGT(scip, sin(newsup), parentbounds.sup) )
    526 {
    527 SCIP_Real a = asin(parentbounds.sup);
    528 int k = (int) ceil((newsup - a ) / (2.0*M_PI)) - 1;
    529 newsup = a + 2.0*M_PI * k;
    530 }
    531
    532 /* if sin(u(x)) < l(s), we are looking for k minimal s.t. pi - a + 2k*pi > l(x) - 2*pi where a = asin(l(s))
    533 * then the new upper bound is pi - a + 2k*pi
    534 */
    535 if( SCIPisLT(scip, sin(newsup), parentbounds.inf) )
    536 {
    537 SCIP_Real a = asin(parentbounds.inf);
    538 int k = (int) ceil((newsup + a) / (2.0*M_PI) - 0.5) - 1;
    539 newsup = M_PI * (2.0*k + 1.0) - a;
    540 }
    541
    542 assert(newsup <= childbounds.sup);
    543 assert(SCIPisFeasGE(scip, sin(newsup), parentbounds.inf));
    544 assert(SCIPisFeasLE(scip, sin(newsup), parentbounds.sup));
    545 }
    546
    547 /* if the new interval is invalid, the old one was already invalid */
    548 if( newinf <= newsup )
    549 SCIPintervalSetBounds(newbounds, newinf, newsup);
    550 else
    551 SCIPintervalSetEmpty(newbounds);
    552
    553 return SCIP_OKAY;
    554}
    555
    556/** helper function to compute coefficients and constant term of a linear estimator at a given point
    557 *
    558 * The function will try to compute the following estimators in that order:
    559 * - soltangent: tangent at specified refpoint
    560 * - secant: secant between the points (lb,sin(lb)) and (ub,sin(ub))
    561 * - left secant: secant between lower bound and some point of the graph
    562 * - right secant: secant between upper bound and some point of the graph
    563 *
    564 * They are ordered such that a successful computation for one of them cannot be improved by following ones in terms
    565 * of value at the reference point.
    566 */
    567static
    569 SCIP* scip, /**< SCIP data structure */
    570 SCIP_EXPR* expr, /**< sin or cos expression */
    571 SCIP_Real* lincoef, /**< buffer to store the linear coefficient */
    572 SCIP_Real* linconst, /**< buffer to store the constant term */
    573 SCIP_Real refpoint, /**< point at which to underestimate (can be SCIP_INVALID) */
    574 SCIP_Real childlb, /**< lower bound of child variable */
    575 SCIP_Real childub, /**< upper bound of child variable */
    576 SCIP_Bool underestimate /**< whether the estimator should be underestimating */
    577 )
    578{
    579 SCIP_Bool success;
    580 SCIP_Bool iscos;
    581
    582 assert(scip != NULL);
    583 assert(expr != NULL);
    584 assert(SCIPexprGetNChildren(expr) == 1);
    585 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "sin") == 0
    586 || strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0);
    587 assert(SCIPisLE(scip, childlb, childub));
    588
    589 /* if child is essentially constant, then there should be no point in estimation */
    590 if( SCIPisEQ(scip, childlb, childub) ) /* @todo maybe return a constant estimator? */
    591 return FALSE;
    592
    593 iscos = strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0;
    594
    595 /* for cos expressions, the bounds have to be shifted before and after computation */
    596 if( iscos )
    597 {
    598 childlb += M_PI_2;
    599 childub += M_PI_2;
    600 refpoint += M_PI_2;
    601 }
    602
    603 if( !underestimate )
    604 {
    605 SCIP_Real tmp = childlb;
    606 childlb = -childub;
    607 childub = -tmp;
    608 refpoint *= -1;
    609 }
    610
    611 /* try out tangent at solution point */
    612 success = computeSolTangentSin(scip, lincoef, linconst, childlb, childub, refpoint);
    613
    614 /* otherwise, try out secant */
    615 if( !success )
    616 success = computeSecantSin(scip, lincoef, linconst, childlb, childub);
    617
    618 /* otherwise, try left secant */
    619 if( !success )
    620 success = computeLeftSecantSin(scip, lincoef, linconst, childlb, childub);
    621
    622 /* otherwise, try right secant */
    623 if( !success )
    624 success = computeRightSecantSin(scip, lincoef, linconst, childlb, childub);
    625
    626 if( !success )
    627 return FALSE;
    628
    629 /* for overestimators, mirror back */
    630 if( !underestimate )
    631 (*linconst) *= -1.0;
    632
    633 /* for cos expressions, shift back */
    634 if( iscos )
    635 (*linconst) += (*lincoef) * M_PI_2;
    636
    637 return TRUE;
    638}
    639
    640/** helper function to create initial cuts for sine and cosine separation
    641 *
    642 * The following 5 cuts can be generated:
    643 * - secant: secant between the bounds (lb,sin(lb)) and (ub,sin(ub))
    644 * - left/right secant: secant between lower/upper bound and some point of the graph
    645 * - left/right tangent: tangents at the lower/upper bounds
    646 */
    647static
    649 SCIP* scip, /**< SCIP data structure */
    650 SCIP_EXPR* expr, /**< sin or cos expression */
    651 SCIP_Real childlb, /**< lower bound of child variable */
    652 SCIP_Real childub, /**< upper bound of child variable */
    653 SCIP_Bool underestimate, /**< whether the cuts should be underestimating */
    654 SCIP_Real** coefs, /**< buffer to store coefficients of computed estimators */
    655 SCIP_Real* constant, /**< buffer to store constant of computed estimators */
    656 int* nreturned /**< buffer to store number of estimators that have been computed */
    657 )
    658{
    659 SCIP_Bool iscos;
    660 int i;
    661
    662 assert(scip != NULL);
    663 assert(expr != NULL);
    664 assert(SCIPexprGetNChildren(expr) == 1);
    665 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "sin") == 0 || strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0);
    666 assert(SCIPisLE(scip, childlb, childub));
    667
    668 /* caller must ensure that variable is not already fixed */
    669 assert(!SCIPisEQ(scip, childlb, childub));
    670
    671 *nreturned = 0;
    672
    673 /* for cos expressions, the bounds have to be shifted before and after computation */
    674 iscos = strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0;
    675 if( iscos )
    676 {
    677 childlb += M_PI_2;
    678 childub += M_PI_2;
    679 }
    680
    681 /*
    682 * Compute all initial cuts
    683 * For each linear equation z = a*x + b with bounds [lb,ub] the parameters can be computed by:
    684 *
    685 * a = cos(x^) and b = sin(x^) - a * x^ where x^ is any known point in [lb,ub]
    686 *
    687 * and the resulting cut is a*x + b <=/>= z depending on over-/underestimation
    688 */
    689
    690 if( ! underestimate )
    691 {
    692 SCIP_Real aux;
    693 aux = childlb;
    694 childlb = -childub;
    695 childub = -aux;
    696 }
    697
    698 /* if we can generate a secant between the bounds, then we have convex (concave) hull */
    699 if( computeSecantSin(scip, coefs[*nreturned], &constant[*nreturned], childlb, childub) )
    700 (*nreturned)++;
    701 else
    702 {
    703 /* try generating a secant between lb (ub) and some point < ub (> lb); otherwise try with tangent at lb (ub)*/
    704 if( computeLeftSecantSin(scip, coefs[*nreturned], &constant[*nreturned], childlb, childub) )
    705 (*nreturned)++;
    706 else if( computeLeftTangentSin(scip, coefs[*nreturned], &constant[*nreturned], childlb) )
    707 (*nreturned)++;
    708
    709 /* try generating a secant between ub (lb) and some point > lb (< ub); otherwise try with tangent at ub (lb)*/
    710 if( computeRightSecantSin(scip, coefs[*nreturned], &constant[*nreturned], childlb, childub) )
    711 (*nreturned)++;
    712 else if( computeRightTangentSin(scip, coefs[*nreturned], &constant[*nreturned], childub) )
    713 (*nreturned)++;
    714 }
    715
    716 /* for cos expressions, the estimator needs to be shifted back to match original bounds */
    717 for( i = 0; i < *nreturned; ++i )
    718 {
    719 if( ! underestimate )
    720 constant[i] *= -1.0;
    721
    722 if( iscos)
    723 {
    724 constant[i] += coefs[i][0] * M_PI_2;
    725 }
    726 }
    727
    728 return SCIP_OKAY;
    729}
    730
    731/* helper function that computes the curvature of a sine expression for given bounds and curvature of child */
    732static
    734 SCIP_EXPRCURV childcurvature, /**< curvature of child */
    735 SCIP_Real lb, /**< lower bound of child */
    736 SCIP_Real ub /**< upper bound of child */
    737 )
    738{
    739 SCIP_Real lbsin = sin(lb);
    740 SCIP_Real ubsin = sin(ub);
    741 SCIP_Real lbcos = cos(lb);
    742 SCIP_Real ubcos = cos(ub);
    743
    744 /* curvature can only be determined if bounds lie within one bay*/
    745 if( (ub - lb <= M_PI) && (lbsin * ubsin >= 0.0) )
    746 {
    747 /* special case that both sin(ub) and sin(lb) are 0 (i.e. ub - lb = pi) */
    748 if( lbsin == 0.0 && ubsin == 0.0 )
    749 {
    750 if( childcurvature == SCIP_EXPRCURV_LINEAR )
    751 return (fmod(lb, 2.0*M_PI) == 0.0) ? SCIP_EXPRCURV_CONCAVE : SCIP_EXPRCURV_CONVEX;
    752 }
    753
    754 /* if sine is monotone on the interval, the curvature depends on the child curvature and on the segment */
    755 else if( lbcos * ubcos >= 0.0 )
    756 {
    757 /* on [0, pi/2], sine is concave iff child is concave */
    758 if( lbsin >= 0.0 && lbcos >= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONCAVE) != 0))
    760
    761 /* on [pi/2, pi], sine is concave iff child is convex */
    762 if( lbsin >= 0.0 && lbcos <= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONVEX) != 0))
    764
    765 /* on [pi, 3pi/2], sine is convex iff child is concave */
    766 if( lbsin <= 0.0 && lbcos <= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONCAVE) != 0))
    768
    769 /* on [3pi/2, 2pi], sine is convex iff child is convex */
    770 if( lbsin <= 0.0 && lbcos >= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONVEX) != 0))
    772 }
    773
    774 /* otherwise, we can only say something if the child is linear */
    775 else if( childcurvature == SCIP_EXPRCURV_LINEAR )
    776 return (lbsin >= 0.0 && ubsin >= 0.0) ? SCIP_EXPRCURV_CONCAVE : SCIP_EXPRCURV_CONVEX;
    777 }
    778
    780}
    781
    782/*
    783 * Callback methods of expression handler
    784 */
    785
    786/** expression handler copy callback */
    787static
    789{ /*lint --e{715}*/
    791
    792 return SCIP_OKAY;
    793}
    794
    795/** simplifies a sine expression
    796 *
    797 * Evaluates the sine value function when its child is a value expression.
    798 *
    799 * TODO: add further simplifications
    800 */
    801static
    803{ /*lint --e{715}*/
    804 SCIP_EXPR* child;
    805
    806 assert(scip != NULL);
    807 assert(expr != NULL);
    808 assert(simplifiedexpr != NULL);
    809 assert(SCIPexprGetNChildren(expr) == 1);
    810
    811 child = SCIPexprGetChildren(expr)[0];
    812 assert(child != NULL);
    813
    814 /* check for value expression */
    815 if( SCIPisExprValue(scip, child) )
    816 {
    817 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, sin(SCIPgetValueExprValue(child)), ownercreate,
    818 ownercreatedata) );
    819 }
    820 else
    821 {
    822 *simplifiedexpr = expr;
    823
    824 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    825 SCIPcaptureExpr(*simplifiedexpr);
    826 }
    827
    828 return SCIP_OKAY;
    829}
    830
    831/** expression parse callback */
    832static
    834{ /*lint --e{715}*/
    835 SCIP_EXPR* childexpr;
    836
    837 assert(expr != NULL);
    838
    839 /* parse child expression from remaining string */
    840 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
    841 assert(childexpr != NULL);
    842
    843 /* create sine expression */
    844 SCIP_CALL( SCIPcreateExprSin(scip, expr, childexpr, ownercreate, ownercreatedata) );
    845 assert(*expr != NULL);
    846
    847 /* release child expression since it has been captured by the sine expression */
    848 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
    849
    850 *success = TRUE;
    851
    852 return SCIP_OKAY;
    853}
    854
    855/** expression (point-) evaluation callback */
    856static
    858{ /*lint --e{715}*/
    859 assert(expr != NULL);
    860 assert(SCIPexprGetNChildren(expr) == 1);
    861 assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]) != SCIP_INVALID); /*lint !e777*/
    862
    863 *val = sin(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]));
    864
    865 return SCIP_OKAY;
    866}
    867
    868/** expression derivative evaluation callback */
    869static
    871{ /*lint --e{715}*/
    872 SCIP_EXPR* child;
    873
    874 assert(expr != NULL);
    875 assert(childidx == 0);
    876 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    877
    878 child = SCIPexprGetChildren(expr)[0];
    879 assert(child != NULL);
    880 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    881
    882 *val = cos(SCIPexprGetEvalValue(child));
    883
    884 return SCIP_OKAY;
    885}
    886
    887/** derivative evaluation callback
    888 *
    889 * Computes <gradient, children.dot>, that is, cos(child) dot(child).
    890 */
    891static
    893{ /*lint --e{715}*/
    894 SCIP_EXPR* child;
    895
    896 assert(expr != NULL);
    897 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    898
    899 child = SCIPexprGetChildren(expr)[0];
    900 assert(child != NULL);
    901 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    902 assert(SCIPexprGetDot(child) != SCIP_INVALID); /*lint !e777*/
    903
    904 *dot = cos(SCIPexprGetEvalValue(child)) * SCIPexprGetDot(child);
    905
    906 return SCIP_OKAY;
    907}
    908
    909/** expression backward forward derivative evaluation callback
    910 *
    911 * Computes partial/partial child ( <gradient, children.dot> ), that is, -sin(child) dot(child).
    912 */
    913static
    915{ /*lint --e{715}*/
    916 SCIP_EXPR* child;
    917
    918 assert(expr != NULL);
    919 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    920 assert(childidx == 0);
    921
    922 child = SCIPexprGetChildren(expr)[0];
    923 assert(child != NULL);
    924 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    925 assert(SCIPexprGetDot(child) != SCIP_INVALID); /*lint !e777*/
    926
    927 *bardot = -sin(SCIPexprGetEvalValue(child)) * SCIPexprGetDot(child);
    928
    929 return SCIP_OKAY;
    930}
    931
    932/** expression interval evaluation callback */
    933static
    935{ /*lint --e{715}*/
    936 SCIP_INTERVAL childinterval;
    937
    938 assert(expr != NULL);
    939 assert(SCIPexprGetNChildren(expr) == 1);
    940
    941 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    942
    943 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    944 SCIPintervalSetEmpty(interval);
    945 else
    946 SCIPintervalSin(SCIP_INTERVAL_INFINITY, interval, childinterval);
    947
    948 return SCIP_OKAY;
    949}
    950
    951/** separation initialization callback */
    952static
    954{ /*lint --e{715}*/
    955 SCIP_Real childlb;
    956 SCIP_Real childub;
    957
    958 childlb = bounds[0].inf;
    959 childub = bounds[0].sup;
    960
    961 /* no need for cut if child is fixed */
    962 if( SCIPisRelEQ(scip, childlb, childub) )
    963 return SCIP_OKAY;
    964
    965 /* compute cuts */
    966 SCIP_CALL( computeInitialCutsTrig(scip, expr, childlb, childub, ! overestimate, coefs, constant, nreturned) );
    967
    968 return SCIP_OKAY;
    969}
    970
    971/** expression estimator callback */
    972static
    974{ /*lint --e{715}*/
    975 assert(scip != NULL);
    976 assert(expr != NULL);
    977 assert(SCIPexprGetNChildren(expr) == 1);
    978 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), SINEXPRHDLR_NAME) == 0);
    979 assert(coefs != NULL);
    980 assert(constant != NULL);
    981 assert(islocal != NULL);
    982 assert(branchcand != NULL);
    983 assert(*branchcand == TRUE);
    984 assert(success != NULL);
    985
    986 *success = computeEstimatorsTrig(scip, expr, coefs, constant, refpoint[0], localbounds[0].inf,
    987 localbounds[0].sup, ! overestimate);
    988 *islocal = TRUE; /* TODO there are cases where cuts would be globally valid */
    989
    990 return SCIP_OKAY;
    991}
    992
    993/** expression reverse propagation callback */
    994static
    996{ /*lint --e{715}*/
    997 assert(scip != NULL);
    998 assert(expr != NULL);
    999 assert(SCIPexprGetNChildren(expr) == 1);
    1000 assert(SCIPintervalGetInf(bounds) >= -1.0);
    1001 assert(SCIPintervalGetSup(bounds) <= 1.0);
    1002
    1003 /* compute the new child interval */
    1004 SCIP_CALL( computeRevPropIntervalSin(scip, bounds, childrenbounds[0], childrenbounds) );
    1005
    1006 return SCIP_OKAY;
    1007}
    1008
    1009/** sine hash callback */
    1010static
    1012{ /*lint --e{715}*/
    1013 assert(scip != NULL);
    1014 assert(expr != NULL);
    1015 assert(SCIPexprGetNChildren(expr) == 1);
    1016 assert(hashkey != NULL);
    1017 assert(childrenhashes != NULL);
    1018
    1019 *hashkey = SINEXPRHDLR_HASHKEY;
    1020 *hashkey ^= childrenhashes[0];
    1021
    1022 return SCIP_OKAY;
    1023}
    1024
    1025/** expression curvature detection callback */
    1026static
    1028{ /*lint --e{715}*/
    1029 SCIP_EXPR* child;
    1030 SCIP_INTERVAL childinterval;
    1031
    1032 assert(scip != NULL);
    1033 assert(expr != NULL);
    1034 assert(childcurv != NULL);
    1035 assert(success != NULL);
    1036 assert(SCIPexprGetNChildren(expr) == 1);
    1037
    1038 child = SCIPexprGetChildren(expr)[0];
    1039 assert(child != NULL);
    1041 childinterval = SCIPexprGetActivity(child);
    1042
    1043 /* TODO rewrite SCIPcomputeCurvatureSin so it provides the reverse operation */
    1044 *success = TRUE;
    1045 if( computeCurvatureSin(SCIP_EXPRCURV_CONVEX, childinterval.inf, childinterval.sup) == exprcurvature )
    1046 *childcurv = SCIP_EXPRCURV_CONVEX;
    1047 else if( computeCurvatureSin(SCIP_EXPRCURV_CONCAVE, childinterval.inf, childinterval.sup) == exprcurvature )
    1048 *childcurv = SCIP_EXPRCURV_CONCAVE;
    1049 if( computeCurvatureSin(SCIP_EXPRCURV_LINEAR, childinterval.inf, childinterval.sup) == exprcurvature )
    1050 *childcurv = SCIP_EXPRCURV_LINEAR;
    1051 else
    1052 *success = FALSE;
    1053
    1054 return SCIP_OKAY;
    1055}
    1056
    1057/** expression monotonicity detection callback */
    1058static
    1060{ /*lint --e{715}*/
    1061 SCIP_INTERVAL interval;
    1062 SCIP_Real inf;
    1063 SCIP_Real sup;
    1064 int k;
    1065
    1066 assert(scip != NULL);
    1067 assert(expr != NULL);
    1068 assert(result != NULL);
    1069 assert(childidx == 0);
    1070
    1071 assert(SCIPexprGetChildren(expr)[0] != NULL);
    1073 interval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    1074
    1075 *result = SCIP_MONOTONE_UNKNOWN;
    1076 inf = SCIPintervalGetInf(interval);
    1077 sup = SCIPintervalGetSup(interval);
    1078
    1079 /* expression is not monotone because the interval is too large */
    1080 if( SCIPisGT(scip, sup - inf, M_PI) )
    1081 return SCIP_OKAY;
    1082
    1083 /* compute k s.t. PI * (2k+1) / 2 <= interval.inf <= PI * (2k+3) / 2 */
    1084 k = (int)floor(inf/M_PI - 0.5);
    1085 assert(SCIPisLE(scip, M_PI * (2.0*k + 1.0) / 2.0, inf));
    1086 assert(SCIPisGE(scip, M_PI * (2.0*k + 3.0) / 2.0, inf));
    1087
    1088 /* check whether [inf,sup] are contained in an interval for which the sine function is monotone */
    1089 if( SCIPisLE(scip, sup, M_PI * (2.0*k + 3.0) / 2.0) )
    1090 *result = ((k % 2 + 2) % 2) == 1 ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
    1091
    1092 return SCIP_OKAY;
    1093}
    1094
    1095
    1096/** expression handler copy callback */
    1097static
    1099{ /*lint --e{715}*/
    1101
    1102 return SCIP_OKAY;
    1103}
    1104
    1105/** simplifies a cosine expression
    1106 *
    1107 * Evaluates the cosine value function when its child is a value expression.
    1108 *
    1109 * TODO: add further simplifications
    1110 */
    1111static
    1113{ /*lint --e{715}*/
    1114 SCIP_EXPR* child;
    1115
    1116 assert(scip != NULL);
    1117 assert(expr != NULL);
    1118 assert(simplifiedexpr != NULL);
    1119 assert(SCIPexprGetNChildren(expr) == 1);
    1120
    1121 child = SCIPexprGetChildren(expr)[0];
    1122 assert(child != NULL);
    1123
    1124 /* check for value expression */
    1125 if( SCIPisExprValue(scip, child) )
    1126 {
    1127 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, cos(SCIPgetValueExprValue(child)), ownercreate,
    1128 ownercreatedata) );
    1129 }
    1130 else
    1131 {
    1132 *simplifiedexpr = expr;
    1133
    1134 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    1135 SCIPcaptureExpr(*simplifiedexpr);
    1136 }
    1137
    1138 return SCIP_OKAY;
    1139}
    1140
    1141/** expression parse callback */
    1142static
    1144{ /*lint --e{715}*/
    1145 SCIP_EXPR* childexpr;
    1146
    1147 assert(expr != NULL);
    1148
    1149 /* parse child expression from remaining string */
    1150 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
    1151 assert(childexpr != NULL);
    1152
    1153 /* create cosine expression */
    1154 SCIP_CALL( SCIPcreateExprCos(scip, expr, childexpr, ownercreate, ownercreatedata) );
    1155 assert(*expr != NULL);
    1156
    1157 /* release child expression since it has been captured by the cosine expression */
    1158 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
    1159
    1160 *success = TRUE;
    1161
    1162 return SCIP_OKAY;
    1163}
    1164
    1165/** expression (point-) evaluation callback */
    1166static
    1168{ /*lint --e{715}*/
    1169 assert(expr != NULL);
    1170 assert(SCIPexprGetNChildren(expr) == 1);
    1171 assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]) != SCIP_INVALID); /*lint !e777*/
    1172
    1173 *val = cos(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]));
    1174
    1175 return SCIP_OKAY;
    1176}
    1177
    1178/** expression derivative evaluation callback */
    1179static
    1181{ /*lint --e{715}*/
    1182 SCIP_EXPR* child;
    1183
    1184 assert(expr != NULL);
    1185 assert(childidx == 0);
    1186 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    1187
    1188 child = SCIPexprGetChildren(expr)[0];
    1189 assert(child != NULL);
    1190 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    1191
    1192 *val = -sin(SCIPexprGetEvalValue(child));
    1193
    1194 return SCIP_OKAY;
    1195}
    1196
    1197/** expression interval evaluation callback */
    1198static
    1200{ /*lint --e{715}*/
    1201 SCIP_INTERVAL childinterval;
    1202
    1203 assert(expr != NULL);
    1204 assert(SCIPexprGetNChildren(expr) == 1);
    1205
    1206 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    1207
    1208 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    1209 SCIPintervalSetEmpty(interval);
    1210 else
    1211 SCIPintervalCos(SCIP_INTERVAL_INFINITY, interval, childinterval);
    1212
    1213 return SCIP_OKAY;
    1214}
    1215
    1216/** separation initialization callback */
    1217static
    1219{
    1220 SCIP_Real childlb;
    1221 SCIP_Real childub;
    1222
    1223 childlb = bounds[0].inf;
    1224 childub = bounds[0].sup;
    1225
    1226 /* no need for cut if child is fixed */
    1227 if( SCIPisRelEQ(scip, childlb, childub) )
    1228 return SCIP_OKAY;
    1229
    1230 /* compute cuts */
    1231 SCIP_CALL( computeInitialCutsTrig(scip, expr, childlb, childub, ! overestimate, coefs, constant, nreturned) );
    1232
    1233 return SCIP_OKAY;
    1234}
    1235
    1236/** expression estimator callback */
    1237static
    1239{ /*lint --e{715}*/
    1240 assert(scip != NULL);
    1241 assert(expr != NULL);
    1242 assert(SCIPexprGetNChildren(expr) == 1);
    1243 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), COSEXPRHDLR_NAME) == 0);
    1244 assert(coefs != NULL);
    1245 assert(constant != NULL);
    1246 assert(islocal != NULL);
    1247 assert(branchcand != NULL);
    1248 assert(*branchcand == TRUE);
    1249 assert(success != NULL);
    1250
    1251 *success = computeEstimatorsTrig(scip, expr, coefs, constant, refpoint[0], localbounds[0].inf,
    1252 localbounds[0].sup, ! overestimate);
    1253 *islocal = TRUE; /* TODO there are cases where cuts would be globally valid */
    1254
    1255 return SCIP_OKAY;
    1256}
    1257
    1258/** expression reverse propagation callback */
    1259static
    1261{ /*lint --e{715}*/
    1262 SCIP_INTERVAL newbounds;
    1263
    1264 assert(scip != NULL);
    1265 assert(expr != NULL);
    1266 assert(SCIPexprGetNChildren(expr) == 1);
    1267 /* bounds should have been intersected with activity, which is within [-1,1] */
    1268 assert(SCIPintervalGetInf(bounds) >= -1.0);
    1269 assert(SCIPintervalGetSup(bounds) <= 1.0);
    1270
    1271 /* get the child interval */
    1272 newbounds = childrenbounds[0];
    1273
    1274 /* shift child interval to match sine */
    1275 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &newbounds, newbounds, M_PI_2); /* TODO use bounds on Pi/2 instead of approximation of Pi/2 */
    1276
    1277 /* compute the new child interval */
    1278 SCIP_CALL( computeRevPropIntervalSin(scip, bounds, newbounds, &newbounds) );
    1279
    1281 {
    1282 *infeasible = TRUE;
    1283 return SCIP_OKAY;
    1284 }
    1285
    1286 /* shift the new interval back */
    1287 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &childrenbounds[0], newbounds, -M_PI_2); /* TODO use bounds on Pi/2 instead of approximation of Pi/2 */
    1288
    1289 return SCIP_OKAY;
    1290}
    1291
    1292/** cosine hash callback */
    1293static
    1295{ /*lint --e{715}*/
    1296 assert(scip != NULL);
    1297 assert(expr != NULL);
    1298 assert(SCIPexprGetNChildren(expr) == 1);
    1299 assert(hashkey != NULL);
    1300 assert(childrenhashes != NULL);
    1301
    1302 *hashkey = COSEXPRHDLR_HASHKEY;
    1303 *hashkey ^= childrenhashes[0];
    1304
    1305 return SCIP_OKAY;
    1306}
    1307
    1308/** expression curvature detection callback */
    1309static
    1311{ /*lint --e{715}*/
    1312 SCIP_EXPR* child;
    1313 SCIP_INTERVAL childinterval;
    1314
    1315 assert(scip != NULL);
    1316 assert(expr != NULL);
    1317 assert(exprcurvature != SCIP_EXPRCURV_UNKNOWN);
    1318 assert(childcurv != NULL);
    1319 assert(success != NULL);
    1320 assert(SCIPexprGetNChildren(expr) == 1);
    1321
    1322 child = SCIPexprGetChildren(expr)[0];
    1323 assert(child != NULL);
    1325 childinterval = SCIPexprGetActivity(child);
    1326
    1327 /* TODO rewrite SCIPcomputeCurvatureSin so it provides the reverse operation */
    1328 *success = TRUE;
    1329 if( computeCurvatureSin(SCIP_EXPRCURV_CONCAVE, childinterval.inf + M_PI_2, childinterval.sup + M_PI_2) == exprcurvature )
    1330 *childcurv = SCIP_EXPRCURV_CONCAVE;
    1331 else if( computeCurvatureSin(SCIP_EXPRCURV_CONVEX, childinterval.inf + M_PI_2, childinterval.sup + M_PI_2) == exprcurvature )
    1332 *childcurv = SCIP_EXPRCURV_CONVEX;
    1333 else if( computeCurvatureSin(SCIP_EXPRCURV_LINEAR, childinterval.inf + M_PI_2, childinterval.sup + M_PI_2) == exprcurvature )
    1334 *childcurv = SCIP_EXPRCURV_LINEAR;
    1335 else
    1336 *success = FALSE;
    1337
    1338 return SCIP_OKAY;
    1339}
    1340
    1341/** expression monotonicity detection callback */
    1342static
    1344{ /*lint --e{715}*/
    1345 SCIP_INTERVAL interval;
    1346 SCIP_Real inf;
    1347 SCIP_Real sup;
    1348 int k;
    1349
    1350 assert(scip != NULL);
    1351 assert(expr != NULL);
    1352 assert(result != NULL);
    1353 assert(childidx == 0);
    1354
    1355 assert(SCIPexprGetChildren(expr)[0] != NULL);
    1357 interval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    1358
    1359 *result = SCIP_MONOTONE_UNKNOWN;
    1360 inf = SCIPintervalGetInf(interval);
    1361 sup = SCIPintervalGetSup(interval);
    1362
    1363 /* expression is not monotone because the interval is too large */
    1364 if( SCIPisGT(scip, sup - inf, M_PI) )
    1365 return SCIP_OKAY;
    1366
    1367 /* compute k s.t. PI * k <= interval.inf <= PI * (k+1) */
    1368 k = (int)floor(inf/M_PI);
    1369 assert(SCIPisLE(scip, M_PI * k, inf));
    1370 assert(SCIPisGE(scip, M_PI * (k+1), inf));
    1371
    1372 /* check whether [inf,sup] are contained in an interval for which the cosine function is monotone */
    1373 if( SCIPisLE(scip, sup, M_PI * (k+1)) )
    1374 *result = ((k % 2 + 2) % 2) == 0 ? SCIP_MONOTONE_DEC : SCIP_MONOTONE_INC;
    1375
    1376 return SCIP_OKAY;
    1377}
    1378
    1379/** creates the handler for sin expressions and includes it into SCIP */
    1381 SCIP* scip /**< SCIP data structure */
    1382 )
    1383{
    1384 SCIP_EXPRHDLR* exprhdlr;
    1385
    1386 /* include expression handler */
    1388 assert(exprhdlr != NULL);
    1389
    1390 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrSin, NULL);
    1391 SCIPexprhdlrSetSimplify(exprhdlr, simplifySin);
    1392 SCIPexprhdlrSetParse(exprhdlr, parseSin);
    1393 SCIPexprhdlrSetIntEval(exprhdlr, intevalSin);
    1394 SCIPexprhdlrSetEstimate(exprhdlr, initEstimatesSin, estimateSin);
    1395 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropSin);
    1396 SCIPexprhdlrSetHash(exprhdlr, hashSin);
    1397 SCIPexprhdlrSetDiff(exprhdlr, bwdiffSin, fwdiffSin, bwfwdiffSin);
    1398 SCIPexprhdlrSetCurvature(exprhdlr, curvatureSin);
    1399 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicitySin);
    1400
    1401 return SCIP_OKAY;
    1402}
    1403
    1404/** creates the handler for cos expressions and includes it SCIP */
    1406 SCIP* scip /**< SCIP data structure */
    1407 )
    1408{
    1409 SCIP_EXPRHDLR* exprhdlr;
    1410
    1411 /* include expression handler */
    1413 assert(exprhdlr != NULL);
    1414
    1415 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrCos, NULL);
    1416 SCIPexprhdlrSetSimplify(exprhdlr, simplifyCos);
    1417 SCIPexprhdlrSetParse(exprhdlr, parseCos);
    1418 SCIPexprhdlrSetIntEval(exprhdlr, intevalCos);
    1419 SCIPexprhdlrSetEstimate(exprhdlr, initEstimatesCos, estimateCos);
    1420 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropCos);
    1421 SCIPexprhdlrSetHash(exprhdlr, hashCos);
    1422 SCIPexprhdlrSetDiff(exprhdlr, bwdiffCos, NULL, NULL);
    1423 SCIPexprhdlrSetCurvature(exprhdlr, curvatureCos);
    1424 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityCos);
    1425
    1426 return SCIP_OKAY;
    1427}
    1428
    1429/** creates a sin expression */
    1431 SCIP* scip, /**< SCIP data structure */
    1432 SCIP_EXPR** expr, /**< pointer where to store expression */
    1433 SCIP_EXPR* child, /**< single child */
    1434 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1435 void* ownercreatedata /**< data to pass to ownercreate */
    1436 )
    1437{
    1438 assert(expr != NULL);
    1439 assert(child != NULL);
    1441
    1442 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPfindExprhdlr(scip, SINEXPRHDLR_NAME), NULL, 1, &child, ownercreate,
    1443 ownercreatedata) );
    1444
    1445 return SCIP_OKAY;
    1446}
    1447
    1448
    1449/** creates a cos expression */
    1451 SCIP* scip, /**< SCIP data structure */
    1452 SCIP_EXPR** expr, /**< pointer where to store expression */
    1453 SCIP_EXPR* child, /**< single child */
    1454 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1455 void* ownercreatedata /**< data to pass to ownercreate */
    1456 )
    1457{
    1458 assert(expr != NULL);
    1459 assert(child != NULL);
    1461
    1462 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPfindExprhdlr(scip, COSEXPRHDLR_NAME), NULL, 1, &child, ownercreate,
    1463 ownercreatedata) );
    1464
    1465 return SCIP_OKAY;
    1466}
    1467
    1468/** indicates whether expression is of sine-type */ /*lint -e{715}*/
    1470 SCIP* scip, /**< SCIP data structure */
    1471 SCIP_EXPR* expr /**< expression */
    1472 )
    1473{ /*lint --e{715}*/
    1474 assert(expr != NULL);
    1475
    1476 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), SINEXPRHDLR_NAME) == 0;
    1477}
    1478
    1479/** indicates whether expression is of cosine-type */ /*lint -e{715}*/
    1481 SCIP* scip, /**< SCIP data structure */
    1482 SCIP_EXPR* expr /**< expression */
    1483 )
    1484{ /*lint --e{715}*/
    1485 assert(expr != NULL);
    1486
    1487 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), COSEXPRHDLR_NAME) == 0;
    1488}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    #define NULL
    Definition: def.h:248
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:180
    #define SCIP_Bool
    Definition: def.h:91
    #define SCIP_Real
    Definition: def.h:156
    #define ABS(x)
    Definition: def.h:216
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define SCIP_CALL(x)
    Definition: def.h:355
    static SCIP_Bool computeEstimatorsTrig(SCIP *scip, SCIP_EXPR *expr, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real refpoint, SCIP_Real childlb, SCIP_Real childub, SCIP_Bool underestimate)
    Definition: expr_trig.c:568
    #define COSEXPRHDLR_NAME
    Definition: expr_trig.c:64
    static SCIP_DECL_EXPRINITESTIMATES(initEstimatesSin)
    Definition: expr_trig.c:953
    static SCIP_Bool computeRightSecantSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:390
    #define SINEXPRHDLR_PRECEDENCE
    Definition: expr_trig.c:61
    static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffSin)
    Definition: expr_trig.c:914
    static SCIP_RETCODE computeRevPropIntervalSin(SCIP *scip, SCIP_INTERVAL parentbounds, SCIP_INTERVAL childbounds, SCIP_INTERVAL *newbounds)
    Definition: expr_trig.c:472
    #define SINEXPRHDLR_HASHKEY
    Definition: expr_trig.c:62
    static SCIP_DECL_EXPRBWDIFF(bwdiffSin)
    Definition: expr_trig.c:870
    static SCIP_EXPRCURV computeCurvatureSin(SCIP_EXPRCURV childcurvature, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:733
    #define COSEXPRHDLR_HASHKEY
    Definition: expr_trig.c:67
    static SCIP_DECL_EXPRHASH(hashSin)
    Definition: expr_trig.c:1011
    #define SINEXPRHDLR_DESC
    Definition: expr_trig.c:60
    static SCIP_DECL_EXPREVAL(evalSin)
    Definition: expr_trig.c:857
    static SCIP_DECL_EXPRESTIMATE(estimateSin)
    Definition: expr_trig.c:973
    #define COSEXPRHDLR_DESC
    Definition: expr_trig.c:65
    static SCIP_DECL_EXPRCOPYHDLR(copyhdlrSin)
    Definition: expr_trig.c:788
    static SCIP_DECL_NEWTONEVAL(function1)
    Definition: expr_trig.c:82
    #define NEWTON_NITERATIONS
    Definition: expr_trig.c:70
    static SCIP_DECL_EXPRSIMPLIFY(simplifySin)
    Definition: expr_trig.c:802
    static SCIP_Bool computeLeftSecantSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:303
    static SCIP_DECL_EXPRMONOTONICITY(monotonicitySin)
    Definition: expr_trig.c:1059
    #define MAXCHILDABSVAL
    Definition: expr_trig.c:69
    static SCIP_RETCODE computeInitialCutsTrig(SCIP *scip, SCIP_EXPR *expr, SCIP_Real childlb, SCIP_Real childub, SCIP_Bool underestimate, SCIP_Real **coefs, SCIP_Real *constant, int *nreturned)
    Definition: expr_trig.c:648
    static SCIP_Bool computeSecantSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:134
    #define COSEXPRHDLR_PRECEDENCE
    Definition: expr_trig.c:66
    #define SINEXPRHDLR_NAME
    Definition: expr_trig.c:59
    #define NEWTON_PRECISION
    Definition: expr_trig.c:71
    static SCIP_Bool computeRightTangentSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real ub)
    Definition: expr_trig.c:199
    static SCIP_DECL_EXPRFWDIFF(fwdiffSin)
    Definition: expr_trig.c:892
    static SCIP_Bool computeLeftTangentSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb)
    Definition: expr_trig.c:166
    static SCIP_DECL_EXPRPARSE(parseSin)
    Definition: expr_trig.c:833
    static SCIP_DECL_EXPRREVERSEPROP(reversepropSin)
    Definition: expr_trig.c:995
    static SCIP_DECL_EXPRCURVATURE(curvatureSin)
    Definition: expr_trig.c:1027
    static SCIP_DECL_EXPRINTEVAL(intevalSin)
    Definition: expr_trig.c:934
    static SCIP_Bool computeSolTangentSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub, SCIP_Real solpoint)
    Definition: expr_trig.c:228
    handler for sin expressions
    constant value expression handler
    SCIP_RETCODE SCIPcreateExprSin(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_trig.c:1430
    SCIP_RETCODE SCIPcreateExprCos(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_trig.c:1450
    SCIP_Bool SCIPisExprCos(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_trig.c:1480
    SCIP_Bool SCIPisExprSin(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_trig.c:1469
    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 SCIPincludeExprhdlrCos(SCIP *scip)
    Definition: expr_trig.c:1405
    SCIP_RETCODE SCIPincludeExprhdlrSin(SCIP *scip)
    Definition: expr_trig.c:1380
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    SCIP_Real SCIPcalcRootNewton(SCIP_DECL_NEWTONEVAL((*function)), SCIP_DECL_NEWTONEVAL((*derivative)), SCIP_Real *params, int nparams, SCIP_Real x, SCIP_Real eps, int k)
    Definition: misc.c:10082
    const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:545
    void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
    Definition: expr.c:451
    void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)), SCIP_DECL_EXPRFREEHDLR((*freehdlr)))
    Definition: expr.c:370
    void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)), SCIP_DECL_EXPRBWFWDIFF((*bwfwdiff)))
    Definition: expr.c:473
    void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRREVERSEPROP((*reverseprop)))
    Definition: expr.c:510
    void SCIPexprhdlrSetParse(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRPARSE((*parse)))
    Definition: expr.c:407
    void SCIPexprhdlrSetEstimate(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINITESTIMATES((*initestimates)), SCIP_DECL_EXPRESTIMATE((*estimate)))
    Definition: expr.c:532
    void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRMONOTONICITY((*monotonicity)))
    Definition: expr.c:429
    void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEVAL((*inteval)))
    Definition: expr.c:488
    void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCURVATURE((*curvature)))
    Definition: expr.c:418
    SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
    Definition: scip_expr.c:847
    SCIP_EXPRHDLR * SCIPfindExprhdlr(SCIP *scip, const char *name)
    Definition: scip_expr.c:894
    void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRSIMPLIFY((*simplify)))
    Definition: expr.c:499
    SCIP_RETCODE SCIPcreateExpr(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPRHDLR *exprhdlr, SCIP_EXPRDATA *exprdata, int nchildren, SCIP_EXPR **children, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1000
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1468
    SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
    Definition: scip_expr.c:1443
    SCIP_Real SCIPexprGetDot(SCIP_EXPR *expr)
    Definition: expr.c:3986
    SCIP_RETCODE SCIPparseExpr(SCIP *scip, SCIP_EXPR **expr, const char *exprstr, const char **finalpos, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1406
    SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
    Definition: expr_value.c:298
    SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
    Definition: expr.c:3946
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
    Definition: expr.c:4028
    void SCIPcaptureExpr(SCIP_EXPR *expr)
    Definition: scip_expr.c:1435
    SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1742
    SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
    Definition: expr.c:3895
    SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
    void SCIPintervalCos(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
    SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalSin(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
    void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
    void SCIPintervalAddScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
    SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
    void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
    SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    #define M_PI
    Definition: pricer_rpa.c:97
    SCIP_Real sup
    Definition: intervalarith.h:57
    SCIP_Real inf
    Definition: intervalarith.h:56
    #define SCIP_DECL_EXPR_OWNERCREATE(x)
    Definition: type_expr.h:143
    SCIP_EXPRCURV
    Definition: type_expr.h:61
    @ SCIP_EXPRCURV_CONVEX
    Definition: type_expr.h:63
    @ SCIP_EXPRCURV_LINEAR
    Definition: type_expr.h:65
    @ SCIP_EXPRCURV_UNKNOWN
    Definition: type_expr.h:62
    @ SCIP_EXPRCURV_CONCAVE
    Definition: type_expr.h:64
    @ SCIP_MONOTONE_UNKNOWN
    Definition: type_expr.h:71
    @ SCIP_MONOTONE_INC
    Definition: type_expr.h:72
    @ SCIP_MONOTONE_DEC
    Definition: type_expr.h:73
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63