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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file expr_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 <math.h>
    54#include "scip/expr_trig.h"
    55#include "scip/expr_value.h"
    56
    57/* fundamental expression handler properties */
    58#define SINEXPRHDLR_NAME "sin"
    59#define SINEXPRHDLR_DESC "sine expression"
    60#define SINEXPRHDLR_PRECEDENCE 91000
    61#define SINEXPRHDLR_HASHKEY SCIPcalcFibHash(82457.0)
    62
    63#define COSEXPRHDLR_NAME "cos"
    64#define COSEXPRHDLR_DESC "cosine expression"
    65#define COSEXPRHDLR_PRECEDENCE 92000
    66#define COSEXPRHDLR_HASHKEY SCIPcalcFibHash(82463.0)
    67
    68#define MAXCHILDABSVAL 1e+6 /**< maximum absolute value that is accepted for propagation */
    69#define NEWTON_NITERATIONS 100
    70#define NEWTON_PRECISION 1e-12
    71
    72/*
    73 * Local methods
    74 */
    75
    76/** evaluates the function a*x + b - sin(x) for some coefficient a and constant b at a given point p
    77 *
    78 * the constants a and b are expected to be stored in that order in params
    79 */
    80static
    82{ /*lint --e{715}*/
    83 assert(params != NULL);
    84 assert(nparams == 2);
    85
    86 return params[0]*point + params[1] - sin(point);
    87}
    88
    89/** evaluates the derivative of a*x + b - sin(x) for some coefficient a and constant b at a given point p
    90 *
    91 * the constants a and b are expected to be stored in that order in params
    92 */
    93static
    95{ /*lint --e{715}*/
    96 assert(params != NULL);
    97 assert(nparams == 2);
    98
    99 return params[0] - cos(point);
    100}
    101
    102/** evaluates the function sin(x) + (alpha - x)*cos(x) - sin(alpha) for some constant alpha at a given point p
    103 *
    104 * the constant alpha is expected to be stored in params
    105 */
    106static
    108{ /*lint --e{715}*/
    109 assert(params != NULL);
    110 assert(nparams == 1);
    111
    112 return sin(point) + (params[0] - point) * cos(point) - sin(params[0]);
    113}
    114
    115/** evaluates the derivative of sin(x) + (alpha - x)*cos(x) - sin(alpha) for some constant alpha at a given point p
    116 *
    117 * the constant alpha is expected to be stored in params
    118 */
    119static
    121{ /*lint --e{715}*/
    122 assert(params != NULL);
    123 assert(nparams == 1);
    124
    125 return (point - params[0]) * sin(point);
    126}
    127
    128/** helper function to compute the secant if it is a valid underestimator
    129 *
    130 * returns true if the estimator was computed successfully
    131 */
    132static
    134 SCIP* scip, /**< SCIP data structure */
    135 SCIP_Real* lincoef, /**< buffer to store linear coefficient of secant */
    136 SCIP_Real* linconst, /**< buffer to store linear constant of secant */
    137 SCIP_Real lb, /**< lower bound of argument variable */
    138 SCIP_Real ub /**< upper bound of argument variable */
    139 )
    140{
    141 assert(scip != NULL);
    142 assert(lincoef != NULL);
    143 assert(linconst != NULL);
    144 assert(lb < ub);
    145
    146 /* if range is too big, secant is not underestimating */
    147 if( ub - lb >= M_PI )
    148 return FALSE;
    149
    150 /* if bounds are not within positive bay, secant is not underestimating */
    151 if( sin(lb) < 0.0 || sin(ub) < 0.0 || (sin(lb) == 0.0 && cos(lb) < 0.0) )
    152 return FALSE;
    153
    154 *lincoef = (sin(ub) - sin(lb)) / (ub - lb);
    155 *linconst = sin(ub) - (*lincoef) * ub;
    156
    157 return TRUE;
    158}
    159
    160/** helper function to compute the tangent at lower bound if it is underestimating
    161 *
    162 * returns true if the underestimator was computed successfully
    163 */
    164static
    166 SCIP* scip, /**< SCIP data structure */
    167 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    168 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    169 SCIP_Real lb /**< lower bound of argument variable */
    170 )
    171{
    172 assert(scip != NULL);
    173 assert(lincoef != NULL);
    174 assert(linconst != NULL);
    175
    176 if( SCIPisInfinity(scip, -lb) )
    177 return FALSE;
    178
    179 /* left tangent is only underestimating in [pi, 1.5*pi) *2kpi */
    180 if( sin(lb) > 0.0 || cos(lb) >= 0.0 )
    181 return FALSE;
    182
    183 *lincoef = cos(lb);
    184 *linconst = sin(lb) - (*lincoef) * lb;
    185
    186 return TRUE;
    187}
    188
    189/* TODO: fix this, more cases can be considered, see at unit test
    190 * the underestimating of the tangents depends not only on the ub but also on the lower bound.
    191 * right now, this function is only checking whether the tangent underestimates independently of the lower bound!
    192 */
    193/** helper function to compute the tangent at upper bound if it is an underestimator
    194 *
    195 * returns true if the underestimator was computed successfully
    196 */
    197static
    199 SCIP* scip, /**< SCIP data structure */
    200 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    201 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    202 SCIP_Real ub /**< upper bound of argument variable */
    203 )
    204{
    205 assert(scip != NULL);
    206 assert(lincoef != NULL);
    207 assert(linconst != NULL);
    208
    209 if( SCIPisInfinity(scip, ub) )
    210 return FALSE;
    211
    212 /* right tangent is only underestimating in (1.5*pi, 2*pi] *2kpi */
    213 if( sin(ub) > 0.0 || cos(ub) <= 0.0 )
    214 return FALSE;
    215
    216 *lincoef = cos(ub);
    217 *linconst = sin(ub) - (*lincoef) * ub;
    218
    219 return TRUE;
    220}
    221
    222/** helper function to compute the tangent at solution point if it is an underestimator
    223 *
    224 * returns true if the underestimator was computed successfully
    225 */
    226static
    228 SCIP* scip, /**< SCIP data structure */
    229 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    230 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    231 SCIP_Real lb, /**< lower bound of argument variable */
    232 SCIP_Real ub, /**< upper bound of argument variable */
    233 SCIP_Real solpoint /**< solution point to be separated */
    234 )
    235{
    236 SCIP_Real params[2];
    237 SCIP_Real startingpoints[3];
    238 SCIP_Real solpointmodpi;
    239 SCIP_Real intersection;
    240 int i;
    241
    242 assert(scip != NULL);
    243 assert(lincoef != NULL);
    244 assert(linconst != NULL);
    245
    246 /* tangent is only underestimating in negative bay */
    247 if( sin(solpoint) > 0.0 )
    248 return FALSE;
    249
    250 /* compute solution point mod pi */
    251 solpointmodpi = fmod(solpoint, M_PI);
    252 if( solpoint < 0.0 )
    253 solpointmodpi += M_PI;
    254
    255 /* if the point is too far away from the bounds or is at a multiple of pi, then tangent is not underestimating */
    256 if( SCIPisGE(scip, solpoint - lb, 2*M_PI) || SCIPisGE(scip, ub - solpoint, 2*M_PI)
    257 || SCIPisZero(scip, solpointmodpi) )
    258 return FALSE;
    259
    260 params[0] = cos(solpoint);
    261 params[1] = sin(solpoint) - params[0] * solpoint;
    262
    263 /* choose starting points for Newton procedure */
    264 if( SCIPisGT(scip, solpointmodpi, M_PI_2) )
    265 {
    266 startingpoints[0] = solpoint + (M_PI - solpointmodpi) + M_PI_2;
    267 startingpoints[1] = startingpoints[0] + M_PI_2;
    268 startingpoints[2] = startingpoints[1] + M_PI_2;
    269 }
    270 else
    271 {
    272 startingpoints[0] = solpoint - solpointmodpi - M_PI_2;
    273 startingpoints[1] = startingpoints[0] - M_PI_2;
    274 startingpoints[2] = startingpoints[1] - M_PI_2;
    275 }
    276
    277 /* use Newton procedure to test if cut is valid */
    278 for( i = 0; i < 3; ++i )
    279 {
    280 intersection = SCIPcalcRootNewton(function1, derivative1, params, 2, startingpoints[i], NEWTON_PRECISION,
    282
    283 if( intersection != SCIP_INVALID && !SCIPisEQ(scip, intersection, solpoint) ) /*lint !e777*/
    284 break;
    285 }
    286
    287 /* if Newton failed or intersection point lies within bounds, underestimator is not valid */
    288 if( intersection == SCIP_INVALID || (intersection >= lb && intersection <= ub) ) /*lint !e777*/
    289 return FALSE;
    290
    291 *lincoef = params[0];
    292 *linconst = params[1];
    293
    294 return TRUE;
    295}
    296
    297/** helper function to compute the secant between lower bound and some point of the graph such that it underestimates
    298 *
    299 * returns true if the underestimator was computed successfully
    300 */
    301static
    303 SCIP* scip, /**< SCIP data structure */
    304 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    305 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    306 SCIP_Real lb, /**< lower bound of argument variable */
    307 SCIP_Real ub /**< upper bound of argument variable */
    308 )
    309{
    310 SCIP_Real lbmodpi;
    311 SCIP_Real tangentpoint;
    312 SCIP_Real startingpoint;
    313
    314 assert(scip != NULL);
    315 assert(lincoef != NULL);
    316 assert(linconst != NULL);
    317 assert(lb < ub);
    318
    319 if( SCIPisInfinity(scip, -lb) )
    320 return FALSE;
    321
    322 /* compute shifted bounds for case evaluation */
    323 lbmodpi = fmod(lb, M_PI);
    324 if( lb < 0.0 )
    325 lbmodpi += M_PI;
    326
    327 /* choose starting point for Newton procedure */
    328 if( cos(lb) < 0.0 )
    329 {
    330 /* in [pi/2,pi] underestimating doesn't work; otherwise, take the midpoint of possible area */
    331 if( SCIPisLE(scip, sin(lb), 0.0) )
    332 return FALSE;
    333 else
    334 startingpoint = lb + 1.25*M_PI - lbmodpi;
    335 }
    336 else
    337 {
    338 /* in ascending area, take the midpoint of the possible area in descending part */
    339 /* 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
    340 * but for sin(lb) around 0 we know that the tangent point needs to be in [lb+pi,lb+pi+pi/2]
    341 */
    342 if( SCIPisZero(scip, sin(lb)) )
    343 startingpoint = lb + 1.25*M_PI;
    344 else if( sin(lb) < 0.0 )
    345 startingpoint = lb + 2.25*M_PI - lbmodpi;
    346 else
    347 startingpoint = lb + 1.25*M_PI - lbmodpi;
    348 }
    349
    350 /* use Newton procedure to find the point where the tangent intersects sine at lower bound */
    351 tangentpoint = SCIPcalcRootNewton(function2, derivative2, &lb, 1, startingpoint, NEWTON_PRECISION,
    353
    354 /* if Newton procedure failed, no cut is added */
    355 if( tangentpoint == SCIP_INVALID ) /*lint !e777*/
    356 return FALSE;
    357
    358 /* if the computed point lies outside the bounds, it is shifted to upper bound */
    359 if( SCIPisGE(scip, tangentpoint, ub) )
    360 {
    361 tangentpoint = ub;
    362
    363 /* check whether affine function is still underestimating */
    364 if( SCIPisLE(scip, sin(0.5 * (ub + lb)), sin(lb) + 0.5*(sin(ub) - sin(lb))) )
    365 return FALSE;
    366 }
    367
    368 if( SCIPisEQ(scip, tangentpoint, lb) ) /*lint !e777 */
    369 return FALSE;
    370
    371 /* compute secant between lower bound and connection point */
    372 *lincoef = (sin(tangentpoint) - sin(lb)) / (tangentpoint - lb);
    373 *linconst = sin(lb) - (*lincoef) * lb;
    374
    375 /* if the bounds are too close to each other, it's possible that the underestimator is not valid */
    376 if( *lincoef >= cos(lb) )
    377 return FALSE;
    378
    379 SCIPdebugMsg(scip, "left secant: %g + %g*x <= sin(x) on [%g,%g]\n", *linconst, *lincoef, lb, ub);
    380
    381 return TRUE;
    382}
    383
    384/** helper function to compute the secant between upper bound and some point of the graph such that it underestimates
    385 *
    386 * returns true if the underestimator was computed successfully
    387 */
    388static
    390 SCIP* scip, /**< SCIP data structure */
    391 SCIP_Real* lincoef, /**< buffer to store linear coefficient of tangent */
    392 SCIP_Real* linconst, /**< buffer to store linear constant of tangent */
    393 SCIP_Real lb, /**< lower bound of argument variable */
    394 SCIP_Real ub /**< upper bound of argument variable */
    395 )
    396{
    397 SCIP_Real ubmodpi;
    398 SCIP_Real tangentpoint;
    399 SCIP_Real startingpoint;
    400
    401 assert(scip != NULL);
    402 assert(lincoef != NULL);
    403 assert(linconst != NULL);
    404 assert(lb < ub);
    405
    406 if( SCIPisInfinity(scip, ub) )
    407 return FALSE;
    408
    409 /* compute shifted bounds for case evaluation */
    410 ubmodpi = fmod(ub, M_PI);
    411 if( ub < 0.0 )
    412 ubmodpi += M_PI;
    413
    414 /* choose starting point for Newton procedure */
    415 if( cos(ub) > 0.0 )
    416 {
    417 /* in [3*pi/2,2*pi] underestimating doesn't work; otherwise, take the midpoint of possible area */
    418 if( SCIPisLE(scip, sin(ub), 0.0) )
    419 return FALSE;
    420 else
    421 startingpoint = ub - M_PI_4 - ubmodpi;
    422 }
    423 else
    424 {
    425 /* in descending area, take the midpoint of the possible area in ascending part */
    426 /* 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
    427 * but for sin(ub) around 0 we know that the tangent point needs to be in [ub-(pi+pi/2),ub-pi]
    428 */
    429 if( SCIPisZero(scip, sin(ub)) )
    430 startingpoint = ub - 1.25*M_PI;
    431 else if( sin(ub) < 0.0 )
    432 startingpoint = ub - 1.25*M_PI - ubmodpi;
    433 else
    434 startingpoint = ub - M_PI_4 - ubmodpi;
    435 }
    436
    437 /* use Newton procedure to find the point where the tangent intersects sine at lower bound */
    438 tangentpoint = SCIPcalcRootNewton(function2, derivative2, &ub, 1, startingpoint, NEWTON_PRECISION,
    440
    441 /* if Newton procedure failed, no underestimator is found */
    442 if( tangentpoint == SCIP_INVALID ) /*lint !e777*/
    443 return FALSE;
    444
    445 /* if the computed point lies outside the bounds, it is shifted to upper bound */
    446 if( SCIPisLE(scip, tangentpoint, lb) )
    447 {
    448 tangentpoint = lb;
    449
    450 /* check whether affine function is still underestimating */
    451 if( SCIPisLE(scip, sin(0.5 * (ub + lb)), sin(lb) + 0.5*(sin(ub) - sin(lb))) )
    452 return FALSE;
    453 }
    454
    455 if( SCIPisEQ(scip, tangentpoint, ub) ) /*lint !e777 */
    456 return FALSE;
    457
    458 /* compute secant between lower bound and connection point */
    459 *lincoef = (sin(tangentpoint) - sin(ub)) / (tangentpoint - ub);
    460 *linconst = sin(ub) - (*lincoef) * ub;
    461
    462 /* if the bounds are to close to each other, it's possible that the underestimator is not valid */
    463 if( *lincoef <= cos(lb) )
    464 return FALSE;
    465
    466 return TRUE;
    467}
    468
    469/** helper function to compute the new interval for child in reverse propagation */
    470static
    472 SCIP* scip, /**< SCIP data structure */
    473 SCIP_INTERVAL parentbounds, /**< bounds for sine expression */
    474 SCIP_INTERVAL childbounds, /**< bounds for child expression */
    475 SCIP_INTERVAL* newbounds /**< buffer to store new child bounds */
    476 )
    477{
    478 SCIP_Real newinf = childbounds.inf;
    479 SCIP_Real newsup = childbounds.sup;
    480
    481 /* if the absolute values of the bounds are too large, skip reverse propagation
    482 * TODO: if bounds are close but too large, shift them to [0,2pi] and do the computation there
    483 */
    484 if( ABS(newinf) > MAXCHILDABSVAL || ABS(newsup) > MAXCHILDABSVAL )
    485 {
    486 SCIPintervalSetBounds(newbounds, newinf, newsup);
    487 return SCIP_OKAY;
    488 }
    489
    490 if( !SCIPisInfinity(scip, -newinf) )
    491 {
    492 /* l(x) and u(x) are lower/upper bound of child, l(s) and u(s) are lower/upper bound of sin expr
    493 *
    494 * if sin(l(x)) < l(s), we are looking for k minimal s.t. a + 2k*pi > l(x) where a = asin(l(s))
    495 * then the new lower bound is a + 2k*pi
    496 */
    497 if( SCIPisLT(scip, sin(newinf), parentbounds.inf) )
    498 {
    499 SCIP_Real a = asin(parentbounds.inf);
    500 int k = (int) ceil((newinf - a) / (2.0*M_PI));
    501 newinf = a + 2.0*M_PI * k;
    502 }
    503
    504 /* 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))
    505 * then the new lower bound is pi - a + 2k*pi
    506 */
    507 else if( SCIPisGT(scip, sin(newinf), parentbounds.sup) )
    508 {
    509 SCIP_Real a = asin(parentbounds.sup);
    510 int k = (int) ceil((newinf + a) / (2.0*M_PI) - 0.5);
    511 newinf = M_PI * (2.0*k + 1.0) - a;
    512 }
    513
    514 assert(newinf >= childbounds.inf);
    515 assert(SCIPisFeasGE(scip, sin(newinf), parentbounds.inf));
    516 assert(SCIPisFeasLE(scip, sin(newinf), parentbounds.sup));
    517 }
    518
    519 if( !SCIPisInfinity(scip, newsup) )
    520 {
    521 /* 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))
    522 * then the new upper bound is a + 2k*pi
    523 */
    524 if ( SCIPisGT(scip, sin(newsup), parentbounds.sup) )
    525 {
    526 SCIP_Real a = asin(parentbounds.sup);
    527 int k = (int) ceil((newsup - a ) / (2.0*M_PI)) - 1;
    528 newsup = a + 2.0*M_PI * k;
    529 }
    530
    531 /* 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))
    532 * then the new upper bound is pi - a + 2k*pi
    533 */
    534 if( SCIPisLT(scip, sin(newsup), parentbounds.inf) )
    535 {
    536 SCIP_Real a = asin(parentbounds.inf);
    537 int k = (int) ceil((newsup + a) / (2.0*M_PI) - 0.5) - 1;
    538 newsup = M_PI * (2.0*k + 1.0) - a;
    539 }
    540
    541 assert(newsup <= childbounds.sup);
    542 assert(SCIPisFeasGE(scip, sin(newsup), parentbounds.inf));
    543 assert(SCIPisFeasLE(scip, sin(newsup), parentbounds.sup));
    544 }
    545
    546 /* if the new interval is invalid, the old one was already invalid */
    547 if( newinf <= newsup )
    548 SCIPintervalSetBounds(newbounds, newinf, newsup);
    549 else
    550 SCIPintervalSetEmpty(newbounds);
    551
    552 return SCIP_OKAY;
    553}
    554
    555/** helper function to compute coefficients and constant term of a linear estimator at a given point
    556 *
    557 * The function will try to compute the following estimators in that order:
    558 * - soltangent: tangent at specified refpoint
    559 * - secant: secant between the points (lb,sin(lb)) and (ub,sin(ub))
    560 * - left secant: secant between lower bound and some point of the graph
    561 * - right secant: secant between upper bound and some point of the graph
    562 *
    563 * They are ordered such that a successful computation for one of them cannot be improved by following ones in terms
    564 * of value at the reference point.
    565 */
    566static
    568 SCIP* scip, /**< SCIP data structure */
    569 SCIP_EXPR* expr, /**< sin or cos expression */
    570 SCIP_Real* lincoef, /**< buffer to store the linear coefficient */
    571 SCIP_Real* linconst, /**< buffer to store the constant term */
    572 SCIP_Real refpoint, /**< point at which to underestimate (can be SCIP_INVALID) */
    573 SCIP_Real childlb, /**< lower bound of child variable */
    574 SCIP_Real childub, /**< upper bound of child variable */
    575 SCIP_Bool underestimate /**< whether the estimator should be underestimating */
    576 )
    577{
    578 SCIP_Bool success;
    579 SCIP_Bool iscos;
    580
    581 assert(scip != NULL);
    582 assert(expr != NULL);
    583 assert(SCIPexprGetNChildren(expr) == 1);
    584 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "sin") == 0
    585 || strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0);
    586 assert(SCIPisLE(scip, childlb, childub));
    587
    588 /* if child is essentially constant, then there should be no point in estimation */
    589 if( SCIPisEQ(scip, childlb, childub) ) /* @todo maybe return a constant estimator? */
    590 return FALSE;
    591
    592 iscos = strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0;
    593
    594 /* for cos expressions, the bounds have to be shifted before and after computation */
    595 if( iscos )
    596 {
    597 childlb += M_PI_2;
    598 childub += M_PI_2;
    599 refpoint += M_PI_2;
    600 }
    601
    602 if( !underestimate )
    603 {
    604 SCIP_Real tmp = childlb;
    605 childlb = -childub;
    606 childub = -tmp;
    607 refpoint *= -1;
    608 }
    609
    610 /* try out tangent at solution point */
    611 success = computeSolTangentSin(scip, lincoef, linconst, childlb, childub, refpoint);
    612
    613 /* otherwise, try out secant */
    614 if( !success )
    615 success = computeSecantSin(scip, lincoef, linconst, childlb, childub);
    616
    617 /* otherwise, try left secant */
    618 if( !success )
    619 success = computeLeftSecantSin(scip, lincoef, linconst, childlb, childub);
    620
    621 /* otherwise, try right secant */
    622 if( !success )
    623 success = computeRightSecantSin(scip, lincoef, linconst, childlb, childub);
    624
    625 if( !success )
    626 return FALSE;
    627
    628 /* for overestimators, mirror back */
    629 if( !underestimate )
    630 (*linconst) *= -1.0;
    631
    632 /* for cos expressions, shift back */
    633 if( iscos )
    634 (*linconst) += (*lincoef) * M_PI_2;
    635
    636 return TRUE;
    637}
    638
    639/** helper function to create initial cuts for sine and cosine separation
    640 *
    641 * The following 5 cuts can be generated:
    642 * - secant: secant between the bounds (lb,sin(lb)) and (ub,sin(ub))
    643 * - left/right secant: secant between lower/upper bound and some point of the graph
    644 * - left/right tangent: tangents at the lower/upper bounds
    645 */
    646static
    648 SCIP* scip, /**< SCIP data structure */
    649 SCIP_EXPR* expr, /**< sin or cos expression */
    650 SCIP_Real childlb, /**< lower bound of child variable */
    651 SCIP_Real childub, /**< upper bound of child variable */
    652 SCIP_Bool underestimate, /**< whether the cuts should be underestimating */
    653 SCIP_Real** coefs, /**< buffer to store coefficients of computed estimators */
    654 SCIP_Real* constant, /**< buffer to store constant of computed estimators */
    655 int* nreturned /**< buffer to store number of estimators that have been computed */
    656 )
    657{
    658 SCIP_Bool iscos;
    659 int i;
    660
    661 assert(scip != NULL);
    662 assert(expr != NULL);
    663 assert(SCIPexprGetNChildren(expr) == 1);
    664 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "sin") == 0 || strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0);
    665 assert(SCIPisLE(scip, childlb, childub));
    666
    667 /* caller must ensure that variable is not already fixed */
    668 assert(!SCIPisEQ(scip, childlb, childub));
    669
    670 *nreturned = 0;
    671
    672 /* for cos expressions, the bounds have to be shifted before and after computation */
    673 iscos = strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), "cos") == 0;
    674 if( iscos )
    675 {
    676 childlb += M_PI_2;
    677 childub += M_PI_2;
    678 }
    679
    680 /*
    681 * Compute all initial cuts
    682 * For each linear equation z = a*x + b with bounds [lb,ub] the parameters can be computed by:
    683 *
    684 * a = cos(x^) and b = sin(x^) - a * x^ where x^ is any known point in [lb,ub]
    685 *
    686 * and the resulting cut is a*x + b <=/>= z depending on over-/underestimation
    687 */
    688
    689 if( ! underestimate )
    690 {
    691 SCIP_Real aux;
    692 aux = childlb;
    693 childlb = -childub;
    694 childub = -aux;
    695 }
    696
    697 /* if we can generate a secant between the bounds, then we have convex (concave) hull */
    698 if( computeSecantSin(scip, coefs[*nreturned], &constant[*nreturned], childlb, childub) )
    699 (*nreturned)++;
    700 else
    701 {
    702 /* try generating a secant between lb (ub) and some point < ub (> lb); otherwise try with tangent at lb (ub)*/
    703 if( computeLeftSecantSin(scip, coefs[*nreturned], &constant[*nreturned], childlb, childub) )
    704 (*nreturned)++;
    705 else if( computeLeftTangentSin(scip, coefs[*nreturned], &constant[*nreturned], childlb) )
    706 (*nreturned)++;
    707
    708 /* try generating a secant between ub (lb) and some point > lb (< ub); otherwise try with tangent at ub (lb)*/
    709 if( computeRightSecantSin(scip, coefs[*nreturned], &constant[*nreturned], childlb, childub) )
    710 (*nreturned)++;
    711 else if( computeRightTangentSin(scip, coefs[*nreturned], &constant[*nreturned], childub) )
    712 (*nreturned)++;
    713 }
    714
    715 /* for cos expressions, the estimator needs to be shifted back to match original bounds */
    716 for( i = 0; i < *nreturned; ++i )
    717 {
    718 if( ! underestimate )
    719 constant[i] *= -1.0;
    720
    721 if( iscos)
    722 {
    723 constant[i] += coefs[i][0] * M_PI_2;
    724 }
    725 }
    726
    727 return SCIP_OKAY;
    728}
    729
    730/* helper function that computes the curvature of a sine expression for given bounds and curvature of child */
    731static
    733 SCIP_EXPRCURV childcurvature, /**< curvature of child */
    734 SCIP_Real lb, /**< lower bound of child */
    735 SCIP_Real ub /**< upper bound of child */
    736 )
    737{
    738 SCIP_Real lbsin = sin(lb);
    739 SCIP_Real ubsin = sin(ub);
    740 SCIP_Real lbcos = cos(lb);
    741 SCIP_Real ubcos = cos(ub);
    742
    743 /* curvature can only be determined if bounds lie within one bay*/
    744 if( (ub - lb <= M_PI) && (lbsin * ubsin >= 0.0) )
    745 {
    746 /* special case that both sin(ub) and sin(lb) are 0 (i.e. ub - lb = pi) */
    747 if( lbsin == 0.0 && ubsin == 0.0 )
    748 {
    749 if( childcurvature == SCIP_EXPRCURV_LINEAR )
    750 return (fmod(lb, 2.0*M_PI) == 0.0) ? SCIP_EXPRCURV_CONCAVE : SCIP_EXPRCURV_CONVEX;
    751 }
    752
    753 /* if sine is monotone on the interval, the curvature depends on the child curvature and on the segment */
    754 else if( lbcos * ubcos >= 0.0 )
    755 {
    756 /* on [0, pi/2], sine is concave iff child is concave */
    757 if( lbsin >= 0.0 && lbcos >= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONCAVE) != 0))
    759
    760 /* on [pi/2, pi], sine is concave iff child is convex */
    761 if( lbsin >= 0.0 && lbcos <= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONVEX) != 0))
    763
    764 /* on [pi, 3pi/2], sine is convex iff child is concave */
    765 if( lbsin <= 0.0 && lbcos <= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONCAVE) != 0))
    767
    768 /* on [3pi/2, 2pi], sine is convex iff child is convex */
    769 if( lbsin <= 0.0 && lbcos >= 0.0 && ((int)(childcurvature & SCIP_EXPRCURV_CONVEX) != 0))
    771 }
    772
    773 /* otherwise, we can only say something if the child is linear */
    774 else if( childcurvature == SCIP_EXPRCURV_LINEAR )
    775 return (lbsin >= 0.0 && ubsin >= 0.0) ? SCIP_EXPRCURV_CONCAVE : SCIP_EXPRCURV_CONVEX;
    776 }
    777
    779}
    780
    781/*
    782 * Callback methods of expression handler
    783 */
    784
    785/** expression handler copy callback */
    786static
    788{ /*lint --e{715}*/
    790
    791 return SCIP_OKAY;
    792}
    793
    794/** simplifies a sine expression
    795 *
    796 * Evaluates the sine value function when its child is a value expression.
    797 *
    798 * TODO: add further simplifications
    799 */
    800static
    802{ /*lint --e{715}*/
    803 SCIP_EXPR* child;
    804
    805 assert(scip != NULL);
    806 assert(expr != NULL);
    807 assert(simplifiedexpr != NULL);
    808 assert(SCIPexprGetNChildren(expr) == 1);
    809
    810 child = SCIPexprGetChildren(expr)[0];
    811 assert(child != NULL);
    812
    813 /* check for value expression */
    814 if( SCIPisExprValue(scip, child) )
    815 {
    816 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, sin(SCIPgetValueExprValue(child)), ownercreate,
    817 ownercreatedata) );
    818 }
    819 else
    820 {
    821 *simplifiedexpr = expr;
    822
    823 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    824 SCIPcaptureExpr(*simplifiedexpr);
    825 }
    826
    827 return SCIP_OKAY;
    828}
    829
    830/** expression parse callback */
    831static
    833{ /*lint --e{715}*/
    834 SCIP_EXPR* childexpr;
    835
    836 assert(expr != NULL);
    837
    838 /* parse child expression from remaining string */
    839 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
    840 assert(childexpr != NULL);
    841
    842 /* create sine expression */
    843 SCIP_CALL( SCIPcreateExprSin(scip, expr, childexpr, ownercreate, ownercreatedata) );
    844 assert(*expr != NULL);
    845
    846 /* release child expression since it has been captured by the sine expression */
    847 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
    848
    849 *success = TRUE;
    850
    851 return SCIP_OKAY;
    852}
    853
    854/** expression (point-) evaluation callback */
    855static
    857{ /*lint --e{715}*/
    858 assert(expr != NULL);
    859 assert(SCIPexprGetNChildren(expr) == 1);
    860 assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]) != SCIP_INVALID); /*lint !e777*/
    861
    862 *val = sin(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]));
    863
    864 return SCIP_OKAY;
    865}
    866
    867/** expression derivative evaluation callback */
    868static
    870{ /*lint --e{715}*/
    871 SCIP_EXPR* child;
    872
    873 assert(expr != NULL);
    874 assert(childidx == 0);
    875 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    876
    877 child = SCIPexprGetChildren(expr)[0];
    878 assert(child != NULL);
    879 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    880
    881 *val = cos(SCIPexprGetEvalValue(child));
    882
    883 return SCIP_OKAY;
    884}
    885
    886/** derivative evaluation callback
    887 *
    888 * Computes <gradient, children.dot>, that is, cos(child) dot(child).
    889 */
    890static
    892{ /*lint --e{715}*/
    893 SCIP_EXPR* child;
    894
    895 assert(expr != NULL);
    896 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    897
    898 child = SCIPexprGetChildren(expr)[0];
    899 assert(child != NULL);
    900 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    901 assert(SCIPexprGetDot(child) != SCIP_INVALID); /*lint !e777*/
    902
    903 *dot = cos(SCIPexprGetEvalValue(child)) * SCIPexprGetDot(child);
    904
    905 return SCIP_OKAY;
    906}
    907
    908/** expression backward forward derivative evaluation callback
    909 *
    910 * Computes partial/partial child ( <gradient, children.dot> ), that is, -sin(child) dot(child).
    911 */
    912static
    914{ /*lint --e{715}*/
    915 SCIP_EXPR* child;
    916
    917 assert(expr != NULL);
    918 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
    919 assert(childidx == 0);
    920
    921 child = SCIPexprGetChildren(expr)[0];
    922 assert(child != NULL);
    923 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
    924 assert(SCIPexprGetDot(child) != SCIP_INVALID); /*lint !e777*/
    925
    926 *bardot = -sin(SCIPexprGetEvalValue(child)) * SCIPexprGetDot(child);
    927
    928 return SCIP_OKAY;
    929}
    930
    931/** expression interval evaluation callback */
    932static
    934{ /*lint --e{715}*/
    935 SCIP_INTERVAL childinterval;
    936
    937 assert(expr != NULL);
    938 assert(SCIPexprGetNChildren(expr) == 1);
    939
    940 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    941
    942 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    943 SCIPintervalSetEmpty(interval);
    944 else
    945 SCIPintervalSin(SCIP_INTERVAL_INFINITY, interval, childinterval);
    946
    947 return SCIP_OKAY;
    948}
    949
    950/** separation initialization callback */
    951static
    953{ /*lint --e{715}*/
    954 SCIP_Real childlb;
    955 SCIP_Real childub;
    956
    957 childlb = bounds[0].inf;
    958 childub = bounds[0].sup;
    959
    960 /* no need for cut if child is fixed */
    961 if( SCIPisRelEQ(scip, childlb, childub) )
    962 return SCIP_OKAY;
    963
    964 /* compute cuts */
    965 SCIP_CALL( computeInitialCutsTrig(scip, expr, childlb, childub, ! overestimate, coefs, constant, nreturned) );
    966
    967 return SCIP_OKAY;
    968}
    969
    970/** expression estimator callback */
    971static
    973{ /*lint --e{715}*/
    974 assert(scip != NULL);
    975 assert(expr != NULL);
    976 assert(SCIPexprGetNChildren(expr) == 1);
    977 assert(coefs != NULL);
    978 assert(constant != NULL);
    979 assert(islocal != NULL);
    980 assert(branchcand != NULL);
    981 assert(*branchcand == TRUE);
    982 assert(success != NULL);
    983
    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(coefs != NULL);
    1244 assert(constant != NULL);
    1245 assert(islocal != NULL);
    1246 assert(branchcand != NULL);
    1247 assert(*branchcand == TRUE);
    1248 assert(success != NULL);
    1249
    1251
    1252 *success = computeEstimatorsTrig(scip, expr, coefs, constant, refpoint[0], localbounds[0].inf,
    1253 localbounds[0].sup, ! overestimate);
    1254 *islocal = TRUE; /* TODO there are cases where cuts would be globally valid */
    1255
    1256 return SCIP_OKAY;
    1257}
    1258
    1259/** expression reverse propagation callback */
    1260static
    1262{ /*lint --e{715}*/
    1263 SCIP_INTERVAL newbounds;
    1264
    1265 assert(scip != NULL);
    1266 assert(expr != NULL);
    1267 assert(SCIPexprGetNChildren(expr) == 1);
    1268 /* bounds should have been intersected with activity, which is within [-1,1] */
    1269 assert(SCIPintervalGetInf(bounds) >= -1.0);
    1270 assert(SCIPintervalGetSup(bounds) <= 1.0);
    1271
    1272 /* get the child interval */
    1273 newbounds = childrenbounds[0];
    1274
    1275 /* shift child interval to match sine */
    1276 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &newbounds, newbounds, M_PI_2); /* TODO use bounds on Pi/2 instead of approximation of Pi/2 */
    1277
    1278 /* compute the new child interval */
    1279 SCIP_CALL( computeRevPropIntervalSin(scip, bounds, newbounds, &newbounds) );
    1280
    1282 {
    1283 *infeasible = TRUE;
    1284 return SCIP_OKAY;
    1285 }
    1286
    1287 /* shift the new interval back */
    1288 SCIPintervalAddScalar(SCIP_INTERVAL_INFINITY, &childrenbounds[0], newbounds, -M_PI_2); /* TODO use bounds on Pi/2 instead of approximation of Pi/2 */
    1289
    1290 return SCIP_OKAY;
    1291}
    1292
    1293/** cosine hash callback */
    1294static
    1296{ /*lint --e{715}*/
    1297 assert(scip != NULL);
    1298 assert(expr != NULL);
    1299 assert(SCIPexprGetNChildren(expr) == 1);
    1300 assert(hashkey != NULL);
    1301 assert(childrenhashes != NULL);
    1302
    1303 *hashkey = COSEXPRHDLR_HASHKEY;
    1304 *hashkey ^= childrenhashes[0];
    1305
    1306 return SCIP_OKAY;
    1307}
    1308
    1309/** expression curvature detection callback */
    1310static
    1312{ /*lint --e{715}*/
    1313 SCIP_EXPR* child;
    1314 SCIP_INTERVAL childinterval;
    1315
    1316 assert(scip != NULL);
    1317 assert(expr != NULL);
    1318 assert(exprcurvature != SCIP_EXPRCURV_UNKNOWN);
    1319 assert(childcurv != NULL);
    1320 assert(success != NULL);
    1321 assert(SCIPexprGetNChildren(expr) == 1);
    1322
    1323 child = SCIPexprGetChildren(expr)[0];
    1324 assert(child != NULL);
    1326 childinterval = SCIPexprGetActivity(child);
    1327
    1328 /* TODO rewrite SCIPcomputeCurvatureSin so it provides the reverse operation */
    1329 *success = TRUE;
    1330 if( computeCurvatureSin(SCIP_EXPRCURV_CONCAVE, childinterval.inf + M_PI_2, childinterval.sup + M_PI_2) == exprcurvature )
    1331 *childcurv = SCIP_EXPRCURV_CONCAVE;
    1332 else if( computeCurvatureSin(SCIP_EXPRCURV_CONVEX, childinterval.inf + M_PI_2, childinterval.sup + M_PI_2) == exprcurvature )
    1333 *childcurv = SCIP_EXPRCURV_CONVEX;
    1334 else if( computeCurvatureSin(SCIP_EXPRCURV_LINEAR, childinterval.inf + M_PI_2, childinterval.sup + M_PI_2) == exprcurvature )
    1335 *childcurv = SCIP_EXPRCURV_LINEAR;
    1336 else
    1337 *success = FALSE;
    1338
    1339 return SCIP_OKAY;
    1340}
    1341
    1342/** expression monotonicity detection callback */
    1343static
    1345{ /*lint --e{715}*/
    1346 SCIP_INTERVAL interval;
    1347 SCIP_Real inf;
    1348 SCIP_Real sup;
    1349 int k;
    1350
    1351 assert(scip != NULL);
    1352 assert(expr != NULL);
    1353 assert(result != NULL);
    1354 assert(childidx == 0);
    1355
    1356 assert(SCIPexprGetChildren(expr)[0] != NULL);
    1358 interval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
    1359
    1360 *result = SCIP_MONOTONE_UNKNOWN;
    1361 inf = SCIPintervalGetInf(interval);
    1362 sup = SCIPintervalGetSup(interval);
    1363
    1364 /* expression is not monotone because the interval is too large */
    1365 if( SCIPisGT(scip, sup - inf, M_PI) )
    1366 return SCIP_OKAY;
    1367
    1368 /* compute k s.t. PI * k <= interval.inf <= PI * (k+1) */
    1369 k = (int)floor(inf/M_PI);
    1370 assert(SCIPisLE(scip, M_PI * k, inf));
    1371 assert(SCIPisGE(scip, M_PI * (k+1), inf));
    1372
    1373 /* check whether [inf,sup] are contained in an interval for which the cosine function is monotone */
    1374 if( SCIPisLE(scip, sup, M_PI * (k+1)) )
    1375 *result = ((k % 2 + 2) % 2) == 0 ? SCIP_MONOTONE_DEC : SCIP_MONOTONE_INC;
    1376
    1377 return SCIP_OKAY;
    1378}
    1379
    1380/** creates the handler for sin expressions and includes it into SCIP */
    1382 SCIP* scip /**< SCIP data structure */
    1383 )
    1384{
    1385 SCIP_EXPRHDLR* exprhdlr;
    1386
    1387 /* include expression handler */
    1389 assert(exprhdlr != NULL);
    1390
    1391 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrSin, NULL);
    1392 SCIPexprhdlrSetSimplify(exprhdlr, simplifySin);
    1393 SCIPexprhdlrSetParse(exprhdlr, parseSin);
    1394 SCIPexprhdlrSetIntEval(exprhdlr, intevalSin);
    1395 SCIPexprhdlrSetEstimate(exprhdlr, initEstimatesSin, estimateSin);
    1396 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropSin);
    1397 SCIPexprhdlrSetHash(exprhdlr, hashSin);
    1398 SCIPexprhdlrSetDiff(exprhdlr, bwdiffSin, fwdiffSin, bwfwdiffSin);
    1399 SCIPexprhdlrSetCurvature(exprhdlr, curvatureSin);
    1400 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicitySin);
    1401
    1402 return SCIP_OKAY;
    1403}
    1404
    1405/** creates the handler for cos expressions and includes it SCIP */
    1407 SCIP* scip /**< SCIP data structure */
    1408 )
    1409{
    1410 SCIP_EXPRHDLR* exprhdlr;
    1411
    1412 /* include expression handler */
    1414 assert(exprhdlr != NULL);
    1415
    1416 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrCos, NULL);
    1417 SCIPexprhdlrSetSimplify(exprhdlr, simplifyCos);
    1418 SCIPexprhdlrSetParse(exprhdlr, parseCos);
    1419 SCIPexprhdlrSetIntEval(exprhdlr, intevalCos);
    1420 SCIPexprhdlrSetEstimate(exprhdlr, initEstimatesCos, estimateCos);
    1421 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropCos);
    1422 SCIPexprhdlrSetHash(exprhdlr, hashCos);
    1423 SCIPexprhdlrSetDiff(exprhdlr, bwdiffCos, NULL, NULL);
    1424 SCIPexprhdlrSetCurvature(exprhdlr, curvatureCos);
    1425 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityCos);
    1426
    1427 return SCIP_OKAY;
    1428}
    1429
    1430/** creates a sin expression */
    1432 SCIP* scip, /**< SCIP data structure */
    1433 SCIP_EXPR** expr, /**< pointer where to store expression */
    1434 SCIP_EXPR* child, /**< single child */
    1435 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1436 void* ownercreatedata /**< data to pass to ownercreate */
    1437 )
    1438{
    1439 assert(expr != NULL);
    1440 assert(child != NULL);
    1442
    1443 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPfindExprhdlr(scip, SINEXPRHDLR_NAME), NULL, 1, &child, ownercreate,
    1444 ownercreatedata) );
    1445
    1446 return SCIP_OKAY;
    1447}
    1448
    1449
    1450/** creates a cos expression */
    1452 SCIP* scip, /**< SCIP data structure */
    1453 SCIP_EXPR** expr, /**< pointer where to store expression */
    1454 SCIP_EXPR* child, /**< single child */
    1455 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1456 void* ownercreatedata /**< data to pass to ownercreate */
    1457 )
    1458{
    1459 assert(expr != NULL);
    1460 assert(child != NULL);
    1462
    1463 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPfindExprhdlr(scip, COSEXPRHDLR_NAME), NULL, 1, &child, ownercreate,
    1464 ownercreatedata) );
    1465
    1466 return SCIP_OKAY;
    1467}
    1468
    1469/** indicates whether expression is of sine-type */ /*lint -e{715}*/
    1471 SCIP* scip, /**< SCIP data structure */
    1472 SCIP_EXPR* expr /**< expression */
    1473 )
    1474{ /*lint --e{715}*/
    1475 assert(expr != NULL);
    1476
    1477 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), SINEXPRHDLR_NAME) == 0;
    1478}
    1479
    1480/** indicates whether expression is of cosine-type */ /*lint -e{715}*/
    1482 SCIP* scip, /**< SCIP data structure */
    1483 SCIP_EXPR* expr /**< expression */
    1484 )
    1485{ /*lint --e{715}*/
    1486 assert(expr != NULL);
    1487
    1488 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), COSEXPRHDLR_NAME) == 0;
    1489}
    SCIP_VAR * a
    Definition: circlepacking.c:66
    #define NULL
    Definition: def.h:257
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:189
    #define SCIP_Bool
    Definition: def.h:100
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define ABS(x)
    Definition: def.h:225
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define SCIP_CALL(x)
    Definition: def.h:364
    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:567
    #define COSEXPRHDLR_NAME
    Definition: expr_trig.c:63
    static SCIP_DECL_EXPRINITESTIMATES(initEstimatesSin)
    Definition: expr_trig.c:952
    static SCIP_Bool computeRightSecantSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:389
    #define SINEXPRHDLR_PRECEDENCE
    Definition: expr_trig.c:60
    static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffSin)
    Definition: expr_trig.c:913
    static SCIP_RETCODE computeRevPropIntervalSin(SCIP *scip, SCIP_INTERVAL parentbounds, SCIP_INTERVAL childbounds, SCIP_INTERVAL *newbounds)
    Definition: expr_trig.c:471
    #define SINEXPRHDLR_HASHKEY
    Definition: expr_trig.c:61
    static SCIP_DECL_EXPRBWDIFF(bwdiffSin)
    Definition: expr_trig.c:869
    static SCIP_EXPRCURV computeCurvatureSin(SCIP_EXPRCURV childcurvature, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:732
    #define COSEXPRHDLR_HASHKEY
    Definition: expr_trig.c:66
    static SCIP_DECL_EXPRHASH(hashSin)
    Definition: expr_trig.c:1011
    #define SINEXPRHDLR_DESC
    Definition: expr_trig.c:59
    static SCIP_DECL_EXPREVAL(evalSin)
    Definition: expr_trig.c:856
    static SCIP_DECL_EXPRESTIMATE(estimateSin)
    Definition: expr_trig.c:972
    #define COSEXPRHDLR_DESC
    Definition: expr_trig.c:64
    static SCIP_DECL_EXPRCOPYHDLR(copyhdlrSin)
    Definition: expr_trig.c:787
    static SCIP_DECL_NEWTONEVAL(function1)
    Definition: expr_trig.c:81
    #define NEWTON_NITERATIONS
    Definition: expr_trig.c:69
    static SCIP_DECL_EXPRSIMPLIFY(simplifySin)
    Definition: expr_trig.c:801
    static SCIP_Bool computeLeftSecantSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:302
    static SCIP_DECL_EXPRMONOTONICITY(monotonicitySin)
    Definition: expr_trig.c:1059
    #define MAXCHILDABSVAL
    Definition: expr_trig.c:68
    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:647
    static SCIP_Bool computeSecantSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb, SCIP_Real ub)
    Definition: expr_trig.c:133
    #define COSEXPRHDLR_PRECEDENCE
    Definition: expr_trig.c:65
    #define SINEXPRHDLR_NAME
    Definition: expr_trig.c:58
    #define NEWTON_PRECISION
    Definition: expr_trig.c:70
    static SCIP_Bool computeRightTangentSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real ub)
    Definition: expr_trig.c:198
    static SCIP_DECL_EXPRFWDIFF(fwdiffSin)
    Definition: expr_trig.c:891
    static SCIP_Bool computeLeftTangentSin(SCIP *scip, SCIP_Real *lincoef, SCIP_Real *linconst, SCIP_Real lb)
    Definition: expr_trig.c:165
    static SCIP_DECL_EXPRPARSE(parseSin)
    Definition: expr_trig.c:832
    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:933
    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:227
    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:1431
    SCIP_RETCODE SCIPcreateExprCos(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_trig.c:1451
    SCIP_Bool SCIPisExprCos(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_trig.c:1481
    SCIP_Bool SCIPisExprSin(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_trig.c:1470
    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:1406
    SCIP_RETCODE SCIPincludeExprhdlrSin(SCIP *scip)
    Definition: expr_trig.c:1381
    #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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63