Scippy

    SCIP

    Solving Constraint Integer Programs

    expr_sum.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_sum.c
    26 * @ingroup DEFPLUGINS_EXPR
    27 * @brief sum expression handler
    28 * @author Stefan Vigerske
    29 * @author Benjamin Mueller
    30 * @author Felipe Serrano
    31 */
    32
    33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    34
    35#include <string.h>
    36#include <stddef.h>
    37
    38#include "scip/expr_sum.h"
    39#include "scip/expr_value.h"
    40#include "scip/expr_product.h"
    41#include "scip/expr_exp.h"
    42#include "scip/expr_pow.h"
    44
    45#define EXPRHDLR_NAME "sum"
    46#define EXPRHDLR_DESC "summation with coefficients and a constant"
    47#define EXPRHDLR_PRECEDENCE 40000
    48#define EXPRHDLR_HASHKEY SCIPcalcFibHash(47161.0)
    49
    50/** macro to activate/deactivate debugging information of simplify method */
    51/*lint -emacro(774,debugSimplify) */
    52#ifdef SIMPLIFY_DEBUG
    53#define debugSimplify printf
    54#else
    55#define debugSimplify while( FALSE ) printf
    56#endif
    57
    58/*
    59 * Data structures
    60 */
    61
    62/** expression data */
    63struct SCIP_ExprData
    64{
    65 SCIP_Real constant; /**< constant coefficient */
    66 SCIP_Real* coefficients; /**< coefficients of children */
    67 int coefssize; /**< size of the coefficients array */
    68};
    69
    70/*
    71 * Local methods
    72 */
    73
    74/** creates expression data */
    75static
    77 SCIP* scip, /**< SCIP data structure */
    78 SCIP_EXPRDATA** exprdata, /**< pointer where to store expression data */
    79 int ncoefficients, /**< number of coefficients (i.e., number of children) */
    80 SCIP_Real* coefficients, /**< array with coefficients for all children (or NULL if all 1.0) */
    81 SCIP_Real constant /**< constant term of sum */
    82 )
    83{
    84 assert(exprdata != NULL);
    85 assert(ncoefficients >= 0);
    86
    88
    89 if( coefficients != NULL )
    90 {
    91 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*exprdata)->coefficients, coefficients, ncoefficients) );
    92 }
    93 else
    94 {
    95 int i;
    96
    97 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*exprdata)->coefficients, ncoefficients) );
    98 for( i = 0; i < ncoefficients; ++i )
    99 (*exprdata)->coefficients[i] = 1.0;
    100 }
    101
    102 (*exprdata)->coefssize = ncoefficients;
    103 (*exprdata)->constant = constant;
    104
    105 return SCIP_OKAY;
    106}
    107
    108/** simplifies the `idx`-th child of the sum expression `duplicate` in order for it to be able to be a child of a simplified sum
    109 *
    110 * for example, this means that the `idx`-th child cannot be itself a sum
    111 * if it is, we have to flatten it, i.e., take all its children and make them children of `duplicate`
    112 */
    113static
    115 SCIP* scip, /**< SCIP data structure */
    116 SCIP_EXPR* duplicate, /**< expression to be simplified */
    117 int idx, /**< idx of children to be simplified */
    118 SCIP_Bool* changed, /**< pointer to store if some term actually got simplified */
    119 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    120 void* ownercreatedata /**< data to pass to ownercreate */
    121 )
    122{
    123 SCIP_EXPR** children;
    124 SCIP_EXPR* expr;
    125 SCIP_Real* coefs;
    126 SCIP_Real constant ;
    127 SCIP_Real coef;
    128
    129 assert(duplicate != NULL);
    130 assert(idx >= 0);
    131 assert(idx < SCIPexprGetNChildren(duplicate));
    132 assert(changed != NULL);
    133
    134 children = SCIPexprGetChildren(duplicate);
    135 coefs = SCIPgetCoefsExprSum(duplicate);
    136 constant = SCIPgetConstantExprSum(duplicate);
    137
    138 coef = coefs[idx];
    139 expr = children[idx];
    140 assert(expr != NULL);
    141
    142 /* enforces SS3 */
    143 if( SCIPisExprValue(scip, expr) )
    144 {
    145 *changed = TRUE;
    146 constant += coef * SCIPgetValueExprValue(expr);
    147 SCIPsetConstantExprSum(duplicate, constant);
    148
    149 /* TODO: remove child? */
    150 coefs[idx] = 0.0;
    151
    152 return SCIP_OKAY;
    153 }
    154
    155 /* enforces SS2 */
    156 if( SCIPisExprSum(scip, expr) )
    157 {
    158 *changed = TRUE;
    159
    160 /* pass constant to parent */
    161 constant += coef * SCIPgetConstantExprSum(expr);
    162 SCIPsetConstantExprSum(duplicate, constant);
    163
    164 /* append all children of expr on parent except the first one */
    165 if( SCIPexprGetNChildren(expr) > 1 )
    166 {
    167 int i;
    168
    169 for( i = 1; i < SCIPexprGetNChildren(expr); ++i )
    170 {
    171 assert(!SCIPisExprSum(scip, SCIPexprGetChildren(expr)[i]));
    173 coef * SCIPgetCoefsExprSum(expr)[i]) );
    174 }
    175 }
    176
    177 /* replace expr with first child; need to get data again since it might be re-allocated */
    178 assert(!SCIPisExprSum(scip, SCIPexprGetChildren(expr)[0]));
    179
    180 coefs = SCIPgetCoefsExprSum(duplicate);
    181
    182 coefs[idx] = coef * SCIPgetCoefsExprSum(expr)[0];
    183 SCIP_CALL( SCIPreplaceExprChild(scip, duplicate, idx, SCIPexprGetChildren(expr)[0]) );
    184
    185 return SCIP_OKAY;
    186 }
    187
    188 /* enforce SS9 */
    189 if( REALABS(coef) != 1.0 && SCIPisExprProduct(scip, expr) )
    190 {
    191 SCIP_EXPR* expchild = NULL;
    192 int i;
    193
    194 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    195 {
    196 SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
    197 assert(child != NULL);
    198
    199 if( SCIPisExprExp(scip, child) )
    200 {
    201 expchild = child;
    202 break;
    203 }
    204 }
    205
    206 /* coef != +- 1, term is product and one factor is an exponential -> enforce SS9 */
    207 if( expchild != NULL )
    208 {
    209 SCIP_EXPR* sum;
    210 SCIP_EXPR* prod;
    211 SCIP_EXPR* simplifiedprod;
    212 SCIP_EXPR* simplifiedsum;
    213 SCIP_EXPR* exponential;
    214 SCIP_EXPR* simplifiedexp;
    215 SCIP_Real expconstant;
    216
    217 /* inform that expression will change */
    218 *changed = TRUE;
    219
    220 /* compute expchild's coefficient as +- 1.0 * exp(log(abs(coef))) */
    221 if( coef > 0.0 )
    222 {
    223 expconstant = log(coef);
    224 coefs[idx] = 1.0;
    225 }
    226 else
    227 {
    228 expconstant = log(-coef);
    229 coefs[idx] = -1.0;
    230 }
    231
    232 /* add constant to exponential's child */
    233 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, SCIPexprGetChildren(expchild), NULL, expconstant, ownercreate,
    234 ownercreatedata) );
    235
    236 /* simplify sum */
    237 SCIP_CALL( SCIPcallExprSimplify(scip, sum, &simplifiedsum, ownercreate, ownercreatedata) );
    239
    240 /* create exponential with new child */
    241 SCIP_CALL( SCIPcreateExprExp(scip, &exponential, simplifiedsum, ownercreate, ownercreatedata) );
    242 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedsum) );
    243
    244 /* simplify exponential */
    245 SCIP_CALL( SCIPcallExprSimplify(scip, exponential, &simplifiedexp, ownercreate, ownercreatedata) );
    246 SCIP_CALL( SCIPreleaseExpr(scip, &exponential) );
    247
    248 /* create product with new child */
    249 SCIP_CALL( SCIPcreateExprProduct(scip, &prod, 0, NULL, 1.0, ownercreate, ownercreatedata) );
    250
    251 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    252 {
    253 if( SCIPexprGetChildren(expr)[i] == expchild )
    254 {
    255 SCIP_CALL( SCIPappendExprChild(scip, prod, simplifiedexp) );
    256 }
    257 else
    258 {
    260 }
    261 }
    262 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexp) );
    263
    264 /* simplify product */
    265 SCIP_CALL( SCIPcallExprSimplify(scip, prod, &simplifiedprod, ownercreate, ownercreatedata) );
    266 SCIP_CALL( SCIPreleaseExpr(scip, &prod) );
    267
    268 /* replace current child with simplified product */
    269 SCIP_CALL( SCIPreplaceExprChild(scip, duplicate, idx, simplifiedprod) );
    270 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedprod) );
    271
    272 /* since the simplified product can be a sum ( exp(-1)*exp(log(x+y)+1) -> x+y ),
    273 * we call the function we are in again
    274 * this is no endless recursion, since the coef is now +- 1
    275 */
    276 SCIP_CALL( simplifyTerm(scip, duplicate, idx, changed, ownercreate, ownercreatedata) );
    277
    278 return SCIP_OKAY;
    279 }
    280 }
    281
    282 /* enforce SS10 */
    283 if( REALABS(coef) != 1.0 && SCIPisExprExp(scip, expr) )
    284 {
    285 /* coef != +- 1, term is exponential -> enforce SS10 by moving |coef| into argument of exponential */
    286
    287 SCIP_EXPR* sum;
    288 SCIP_EXPR* simplifiedsum;
    289 SCIP_EXPR* exponential;
    290 SCIP_EXPR* simplifiedexp;
    291 SCIP_Real expconstant;
    292
    293 /* inform that expression will change */
    294 *changed = TRUE;
    295
    296 /* compute expchild's coefficient as +- 1.0 * exp(log(abs(coef))) */
    297 if( coef > 0.0 )
    298 {
    299 expconstant = log(coef);
    300 coefs[idx] = 1.0;
    301 }
    302 else
    303 {
    304 expconstant = log(-coef);
    305 coefs[idx] = -1.0;
    306 }
    307
    308 /* add constant to exponential's child */
    309 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, SCIPexprGetChildren(expr), NULL, expconstant, ownercreate,
    310 ownercreatedata) ); /* expconstant+expchild */
    311
    312 /* simplify sum */
    313 SCIP_CALL( SCIPcallExprSimplify(scip, sum, &simplifiedsum, ownercreate, ownercreatedata) );
    315
    316 /* create exponential with new child */
    317 SCIP_CALL( SCIPcreateExprExp(scip, &exponential, simplifiedsum, ownercreate, ownercreatedata) );
    318 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedsum) );
    319
    320 /* simplify exponential */
    321 SCIP_CALL( SCIPcallExprSimplify(scip, exponential, &simplifiedexp, ownercreate, ownercreatedata) );
    322 SCIP_CALL( SCIPreleaseExpr(scip, &exponential) );
    323
    324 /* replace current child with simplified exponential */
    325 SCIP_CALL( SCIPreplaceExprChild(scip, duplicate, idx, simplifiedexp) );
    326 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedexp) );
    327
    328 return SCIP_OKAY;
    329 }
    330
    331 /* other types of (simplified) expressions can be a child of a simplified sum */
    332 assert(!SCIPisExprSum(scip, expr));
    333 assert(!SCIPisExprValue(scip, expr));
    334
    335 return SCIP_OKAY;
    336}
    337
    338/** helper struct for expressions sort */
    339typedef struct
    340{
    341 SCIP* scip; /**< SCIP data structure */
    342 SCIP_EXPR** exprs; /**< expressions */
    344
    345static
    347{
    348 SORTEXPRDATA* data = (SORTEXPRDATA*)dataptr;
    349
    350 return SCIPcompareExpr(data->scip, data->exprs[ind1], data->exprs[ind2]);
    351}
    352
    353/*
    354 * Callback methods of expression handler
    355 */
    356
    357/** simplifies a sum expression
    358 *
    359 * goes through each child and simplifies it; then sorts the simplified children; then sum the children that are equal;
    360 * finally creates a sum expression with all the children that do not have a 0 coefficient and post-process so that SS6
    361 * and SS7 are satisfied
    362 */
    363static
    365{ /*lint --e{715}*/
    366 SCIP_EXPR** children;
    367 SCIP_EXPR* duplicate = NULL;
    368 SCIP_EXPR** newchildren = NULL;
    369 SCIP_Real* newcoefs = NULL;
    370 int nnewchildren;
    371 SCIP_Real newconstant;
    372 SCIP_Real* coefs;
    373 int i;
    374 int nchildren;
    375 SCIP_Bool changed;
    376 SORTEXPRDATA sortdata;
    377 int* order = NULL;
    378
    379 assert(expr != NULL);
    380 assert(simplifiedexpr != NULL);
    381 assert(SCIPexprGetHdlr(expr) == SCIPgetExprhdlrSum(scip));
    382
    383 changed = FALSE;
    384
    385 /* TODO: maybe have a flag to know if it is simplified ? */
    386 /* TODO: can we do this with a shallow duplicate + copy of children pointer? currently simplifyTerm may modify children,
    387 * so one would need to be careful
    388 */
    389 SCIP_CALL( SCIPduplicateExpr(scip, expr, &duplicate, NULL, NULL, ownercreate, ownercreatedata) );
    390 assert(duplicate != NULL);
    391
    392 nchildren = SCIPexprGetNChildren(duplicate);
    393 for( i = 0; i < nchildren; i++ )
    394 {
    395 /* enforces SS8 TODO: remove child? */
    396 /* we have to ask for the coefs everytime, since it might get realloced in simpifyTerm */
    397 if( SCIPgetCoefsExprSum(duplicate)[i] == 0.0 )
    398 {
    399 changed = TRUE;
    400 continue;
    401 }
    402
    403 /* enforces SS2, SS3, SS9, and SS10 */
    404 SCIP_CALL( simplifyTerm(scip, duplicate, i, &changed, ownercreate, ownercreatedata) );
    405 }
    406
    407 /* simplifyTerm can add new children to duplicate and realloc them; so get them again */
    408 nchildren = SCIPexprGetNChildren(duplicate);
    409 children = SCIPexprGetChildren(duplicate);
    410 coefs = SCIPgetCoefsExprSum(duplicate);
    411
    412 /* treat zero term case */
    413 if( nchildren == 0 )
    414 {
    415 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, SCIPgetConstantExprSum(duplicate), ownercreate, ownercreatedata) );
    416 goto CLEANUP;
    417 }
    418
    419 /* treat one term case */
    420 if( nchildren == 1 )
    421 {
    422 if( coefs[0] == 0.0 )
    423 {
    424 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, SCIPgetConstantExprSum(duplicate), ownercreate, ownercreatedata) );
    425 goto CLEANUP;
    426 }
    427
    428 if( coefs[0] == 1.0 && SCIPgetConstantExprSum(duplicate) == 0.0 )
    429 *simplifiedexpr = children[0]; /* SS7 */
    430 else
    431 *simplifiedexpr = changed ? duplicate : expr;
    432
    433 SCIPcaptureExpr(*simplifiedexpr);
    434
    435 goto CLEANUP;
    436 }
    437
    438 /* enforces SS5: sort children */
    439 SCIP_CALL( SCIPallocBufferArray(scip, &order, nchildren) );
    440 for( i = 0; i < nchildren; i++ )
    441 order[i] = i;
    442 sortdata.scip = scip;
    443 sortdata.exprs = children;
    444 SCIPsortInd(order, sortExprComp, (void*)&sortdata, nchildren);
    445
    446 /* create sorted variant of children and coefs */
    447 SCIP_CALL( SCIPallocBufferArray(scip, &newchildren, nchildren) );
    448 SCIP_CALL( SCIPallocBufferArray(scip, &newcoefs, nchildren) );
    449 for( i = 0; i < nchildren; ++i )
    450 {
    451 newchildren[i] = children[order[i]];
    452 newcoefs[i] = coefs[order[i]];
    453 if( order[i] != i )
    454 changed = TRUE;
    455 }
    456
    457 /* post-process */
    458
    459 /* enforces SS4 */
    460 nnewchildren = 0;
    461 for( i = 0; i < nchildren; i++ )
    462 {
    463 /* eliminate zero-coefficients */
    464 if( newcoefs[i] == 0.0 )
    465 {
    466 changed = TRUE;
    467 continue;
    468 }
    469
    470 /* sum equal expressions */
    471 if( i < nchildren-1 && SCIPcompareExpr(scip, newchildren[i], newchildren[i+1]) == 0 )
    472 {
    473 changed = TRUE;
    474 /* if we substract two almost equal not-so-small numbers, then set new coefficient to 0.0
    475 * instead of some tiny value that is likely the result of some random round-off error
    476 * E.g., on instance ex1221, we have x1^2 + b3 = 1.25.
    477 * Probing finds an aggregation x1 = 1.11803 - 0.618034 b3.
    478 * Simplify would then produce 1.25 + 1e-16 x1 = 1.25.
    479 */
    480 if( SCIPisEQ(scip, newcoefs[i], -newcoefs[i+1]) && REALABS(newcoefs[i]) >= 1.0 )
    481 newcoefs[i+1] = 0.0;
    482 else
    483 newcoefs[i+1] += newcoefs[i];
    484 continue;
    485 }
    486
    487 /* move i-th child to new position */
    488 newchildren[nnewchildren] = newchildren[i];
    489 newcoefs[nnewchildren] = newcoefs[i];
    490 nnewchildren++;
    491 }
    492
    493 /* build sum expression from finalchildren and post-simplify */
    494 newconstant = SCIPgetConstantExprSum(duplicate);
    495
    496 debugSimplify("what to do? finalchildren has length %d\n", nnewchildren); /*lint !e506 !e681*/
    497
    498 /* enforces SS6: if they are no children, return value */
    499 if( nnewchildren == 0 )
    500 {
    501 debugSimplify("[sum] got empty list, return value %g\n", newconstant); /*lint !e506 !e681*/
    502 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, newconstant, ownercreate, ownercreatedata) );
    503
    504 goto CLEANUP;
    505 }
    506
    507 /* enforces SS7: if list consists of one expr with coef 1.0 and constant is 0, return that expr */
    508 if( nnewchildren == 1 && newcoefs[0] == 1.0 && newconstant == 0.0 )
    509 {
    510 *simplifiedexpr = newchildren[0];
    511 SCIPcaptureExpr(*simplifiedexpr);
    512
    513 goto CLEANUP;
    514 }
    515
    516 /* build sum expression from children */
    517 if( changed )
    518 {
    519 SCIP_CALL( SCIPcreateExprSum(scip, simplifiedexpr, nnewchildren, newchildren, newcoefs, newconstant,
    520 ownercreate, ownercreatedata) );
    521
    522 goto CLEANUP;
    523 }
    524
    525 *simplifiedexpr = expr;
    526
    527 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    528 SCIPcaptureExpr(*simplifiedexpr);
    529
    530 /* free memory */
    531 CLEANUP:
    532 SCIPfreeBufferArrayNull(scip, &newcoefs);
    533 SCIPfreeBufferArrayNull(scip, &newchildren);
    535 SCIP_CALL( SCIPreleaseExpr(scip, &duplicate) );
    536
    537 return SCIP_OKAY;
    538}
    539
    540/** expression callback to get information for symmetry detection */
    541static
    543{ /*lint --e{715}*/
    544 SCIP_EXPRDATA* exprdata;
    545 int i;
    546
    547 assert(scip != NULL);
    548 assert(expr != NULL);
    549
    550 exprdata = SCIPexprGetData(expr);
    551 assert(exprdata != NULL);
    552
    554
    555 (*symdata)->nconstants = 1;
    556 (*symdata)->ncoefficients = exprdata->coefssize;
    557
    558 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*symdata)->constants, 1) );
    559 (*symdata)->constants[0] = exprdata->constant;
    560
    561 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*symdata)->coefficients, exprdata->coefssize) );
    562 for( i = 0; i < exprdata->coefssize; ++i )
    563 (*symdata)->coefficients[i] = exprdata->coefficients[i];
    564
    565 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*symdata)->children, exprdata->coefssize) );
    566 for( i = 0; i < exprdata->coefssize; ++i )
    567 (*symdata)->children[i] = SCIPexprGetChildren(expr)[i];
    568
    569 return SCIP_OKAY;
    570}
    571
    572/** compares two sum expressions
    573 *
    574 * The order of two sum expressions is a lexicographical order on the terms.
    575 *
    576 * Starting from the *last*, we find the first child where they differ, say, the i-th.
    577 * Then u < v <=> u_i < v_i.
    578 * If there are no such children and they have different number of children, then u < v <=> nchildren(u) < nchildren(v).
    579 * If there are no such children and they have the same number of children, then u < v <=> const(u) < const(v).
    580 * Otherwise, they are the same.
    581 *
    582 * Note: we are assuming expression are simplified, so within u, we have u_1 < u_2, etc
    583 *
    584 * Example: y + z < x + y + z, 2*x + 3*y < 3*x + 3*y
    585 */
    586static
    588{ /*lint --e{715}*/
    589 SCIP_Real const1;
    590 SCIP_Real* coefs1;
    591 SCIP_EXPR** children1;
    592 int nchildren1;
    593 SCIP_Real const2;
    594 SCIP_Real* coefs2;
    595 SCIP_EXPR** children2;
    596 int nchildren2;
    597 int compareresult;
    598 int i;
    599 int j;
    600
    601 nchildren1 = SCIPexprGetNChildren(expr1);
    602 nchildren2 = SCIPexprGetNChildren(expr2);
    603 children1 = SCIPexprGetChildren(expr1);
    604 children2 = SCIPexprGetChildren(expr2);
    605 coefs1 = SCIPgetCoefsExprSum(expr1);
    606 coefs2 = SCIPgetCoefsExprSum(expr2);
    607 const1 = SCIPgetConstantExprSum(expr1);
    608 const2 = SCIPgetConstantExprSum(expr2);
    609
    610 for( i = nchildren1 - 1, j = nchildren2 - 1; i >= 0 && j >= 0; --i, --j )
    611 {
    612 compareresult = SCIPcompareExpr(scip, children1[i], children2[j]);
    613 if( compareresult != 0 )
    614 return compareresult;
    615 else
    616 {
    617 /* expressions are equal, compare coefficient */
    618 if( (coefs1 ? coefs1[i] : 1.0) < (coefs2 ? coefs2[j] : 1.0) )
    619 return -1;
    620 if( (coefs1 ? coefs1[i] : 1.0) > (coefs2 ? coefs2[j] : 1.0) )
    621 return 1;
    622
    623 /* coefficients are equal, continue */
    624 }
    625 }
    626
    627 /* all children of one expression are children of the other expression, use number of children as a tie-breaker */
    628 if( i < j )
    629 {
    630 assert(i == -1);
    631 /* expr1 has less elements, hence expr1 < expr2 */
    632 return -1;
    633 }
    634 if( i > j )
    635 {
    636 assert(j == -1);
    637 /* expr1 has more elements, hence expr1 > expr2 */
    638 return 1;
    639 }
    640
    641 /* everything is equal, use constant/coefficient as tie-breaker */
    642 assert(i == -1 && j == -1);
    643 if( const1 < const2 )
    644 return -1;
    645 if( const1 > const2 )
    646 return 1;
    647
    648 /* they are equal */
    649 return 0;
    650}
    651
    652/** expression handler copy callback */
    653static
    655{ /*lint --e{715}*/
    657
    658 return SCIP_OKAY;
    659}
    660
    661/** expression data copy callback */
    662static
    664{ /*lint --e{715}*/
    665 SCIP_EXPRDATA* sourceexprdata;
    666
    667 assert(targetexprdata != NULL);
    668 assert(sourceexpr != NULL);
    669
    670 sourceexprdata = SCIPexprGetData(sourceexpr);
    671 assert(sourceexprdata != NULL);
    672
    673 SCIP_CALL( createData(targetscip, targetexprdata, SCIPexprGetNChildren(sourceexpr),
    674 sourceexprdata->coefficients, sourceexprdata->constant) );
    675
    676 return SCIP_OKAY;
    677}
    678
    679/** expression data free callback */
    680static
    682{ /*lint --e{715}*/
    683 SCIP_EXPRDATA* exprdata;
    684
    685 assert(expr != NULL);
    686
    687 exprdata = SCIPexprGetData(expr);
    688 assert(exprdata != NULL);
    689
    690 SCIPfreeBlockMemoryArray(scip, &(exprdata->coefficients), exprdata->coefssize);
    691 SCIPfreeBlockMemory(scip, &exprdata);
    692
    693 SCIPexprSetData(expr, NULL);
    694
    695 return SCIP_OKAY;
    696}
    697
    698/** expression print callback */
    699static
    701{ /*lint --e{715}*/
    702 SCIP_EXPRDATA* exprdata;
    703
    704 assert(expr != NULL);
    705
    706 exprdata = SCIPexprGetData(expr);
    707 assert(exprdata != NULL);
    708
    709 /**! [SnippetExprPrintSum] */
    710 switch( stage )
    711 {
    713 {
    714 /* print opening parenthesis, if necessary */
    715 if( EXPRHDLR_PRECEDENCE <= parentprecedence )
    716 {
    717 SCIPinfoMessage(scip, file, "(");
    718 }
    719
    720 /* print constant, if nonzero */
    721 if( exprdata->constant != 0.0 )
    722 {
    723 SCIPinfoMessage(scip, file, "%.15g", exprdata->constant);
    724 }
    725 break;
    726 }
    727
    729 {
    730 SCIP_Real coef;
    731
    732 coef = exprdata->coefficients[currentchild];
    733
    734 /* print coefficient, if necessary */
    735 if( coef == 1.0 )
    736 {
    737 /* if coefficient is 1.0, then print only "+" if not the first term */
    738 if( exprdata->constant != 0.0 || currentchild > 0 )
    739 {
    740 SCIPinfoMessage(scip, file, "+");
    741 }
    742 }
    743 else if( coef == -1.0 )
    744 {
    745 /* if coefficient is -1.0, then print only "-" */
    746 SCIPinfoMessage(scip, file, "-");
    747 }
    748 else
    749 {
    750 /* force "+" sign on positive coefficient if not the first term */
    751 SCIPinfoMessage(scip, file, (exprdata->constant != 0.0 || currentchild > 0) ? "%+.15g*" : "%.15g*", coef);
    752 }
    753
    754 break;
    755 }
    756
    758 {
    759 /* print closing parenthesis, if necessary */
    760 if( EXPRHDLR_PRECEDENCE <= parentprecedence )
    761 {
    762 SCIPinfoMessage(scip, file, ")");
    763 }
    764 break;
    765 }
    766
    768 default: ;
    769 }
    770 /**! [SnippetExprPrintSum] */
    771
    772 return SCIP_OKAY;
    773}
    774
    775/** expression point evaluation callback */
    776static
    778{ /*lint --e{715}*/
    779 SCIP_EXPRDATA* exprdata;
    780 int c;
    781
    782 assert(expr != NULL);
    783
    784 exprdata = SCIPexprGetData(expr);
    785 assert(exprdata != NULL);
    786
    787 /**! [SnippetExprEvalSum] */
    788 *val = exprdata->constant;
    789 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    790 {
    791 assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[c]) != SCIP_INVALID); /*lint !e777*/
    792
    793 *val += exprdata->coefficients[c] * SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[c]);
    794 }
    795 /**! [SnippetExprEvalSum] */
    796
    797 return SCIP_OKAY;
    798}
    799
    800/** expression forward derivative evaluation callback */
    801static
    803{ /*lint --e{715}*/
    804 SCIP_EXPRDATA* exprdata;
    805 int c;
    806
    807 assert(expr != NULL);
    808 assert(dot != NULL);
    809
    810 exprdata = SCIPexprGetData(expr);
    811 assert(exprdata != NULL);
    812
    813 *dot = 0.0;
    814 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    815 {
    816 assert(SCIPexprGetDot(SCIPexprGetChildren(expr)[c]) != SCIP_INVALID); /*lint !e777*/
    817
    818 *dot += exprdata->coefficients[c] * SCIPexprGetDot(SCIPexprGetChildren(expr)[c]);
    819 }
    820
    821 return SCIP_OKAY;
    822}
    823
    824/** expression derivative evaluation callback */
    825static
    827{ /*lint --e{715}*/
    828 assert(expr != NULL);
    829 assert(SCIPexprGetData(expr) != NULL);
    830 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
    831 assert(SCIPexprGetChildren(expr)[childidx] != NULL);
    832 assert(!SCIPisExprValue(scip, SCIPexprGetChildren(expr)[childidx]));
    833
    834 *val = SCIPgetCoefsExprSum(expr)[childidx];
    835
    836 return SCIP_OKAY;
    837}
    838
    839/** expression backward forward derivative evaluation callback */
    840static
    842{ /*lint --e{715}*/
    843 assert(bardot != NULL);
    844
    845 *bardot = 0.0;
    846
    847 return SCIP_OKAY;
    848}
    849
    850/** expression interval evaluation callback */
    851static
    853{ /*lint --e{715}*/
    854 SCIP_EXPRDATA* exprdata;
    855 SCIP_INTERVAL suminterval;
    856 int c;
    857
    858 assert(expr != NULL);
    859
    860 exprdata = SCIPexprGetData(expr);
    861 assert(exprdata != NULL);
    862
    863 SCIPintervalSet(interval, exprdata->constant);
    864
    865 SCIPdebugMsg(scip, "inteval %p with %d children: %.20g", (void*)expr, SCIPexprGetNChildren(expr), exprdata->constant);
    866
    867 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    868 {
    869 SCIP_INTERVAL childinterval;
    870
    871 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[c]);
    872 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    873 {
    874 SCIPintervalSetEmpty(interval);
    875 break;
    876 }
    877
    878 /* compute coefficients[c] * childinterval and add the result to the so far computed interval */
    879 if( exprdata->coefficients[c] == 1.0 )
    880 {
    881 SCIPintervalAdd(SCIP_INTERVAL_INFINITY, interval, *interval, childinterval);
    882 }
    883 else
    884 {
    885 SCIPintervalMulScalar(SCIP_INTERVAL_INFINITY, &suminterval, childinterval, exprdata->coefficients[c]);
    886 SCIPintervalAdd(SCIP_INTERVAL_INFINITY, interval, *interval, suminterval);
    887 }
    888
    889 SCIPdebugMsgPrint(scip, " %+.20g*[%.20g,%.20g]", exprdata->coefficients[c], childinterval.inf, childinterval.sup);
    890 }
    891 SCIPdebugMsgPrint(scip, " = [%.20g,%.20g]\n", interval->inf, interval->sup);
    892
    893 return SCIP_OKAY;
    894}
    895
    896/** initial estimators callback */
    897static
    899{ /*lint --e{715}*/
    900 SCIP_EXPRDATA* exprdata;
    901
    902#ifdef SCIP_DEBUG
    903 SCIPinfoMessage(scip, NULL, "initEstimatesSum %d children: ", SCIPexprGetNChildren(expr));
    904 SCIPprintExpr(scip, expr, NULL);
    905 SCIPinfoMessage(scip, NULL, "\n");
    906#endif
    907 assert(scip != NULL);
    908 assert(expr != NULL);
    909 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
    910
    911 assert(coefs[0] != NULL);
    912 assert(constant != NULL);
    913 assert(nreturned != NULL);
    914
    915 exprdata = SCIPexprGetData(expr);
    916 assert(exprdata != NULL);
    917
    918 BMScopyMemoryArray(coefs[0], exprdata->coefficients, SCIPexprGetNChildren(expr));
    919 *constant = exprdata->constant;
    920 *nreturned = 1;
    921
    922 return SCIP_OKAY;
    923}
    924
    925/** expression estimate callback */
    926static
    928{ /*lint --e{715}*/
    929 SCIP_EXPRDATA* exprdata;
    930
    931 assert(scip != NULL);
    932 assert(expr != NULL);
    933 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
    934 assert(islocal != NULL);
    935 assert(success != NULL);
    936 assert(branchcand != NULL);
    937
    938 exprdata = SCIPexprGetData(expr);
    939 assert(exprdata != NULL);
    940
    941 /* NOTE: nlhdlr_default assumes in nlhdlrInitSepaDefault that this estimator can be used for both under- and overestimation */
    942
    943 BMScopyMemoryArray(coefs, exprdata->coefficients, SCIPexprGetNChildren(expr));
    944 *constant = exprdata->constant;
    945 *islocal = FALSE;
    946 *success = TRUE;
    947
    948 /* for none of our children, branching would improve the underestimator, so set branchcand[i]=FALSE everywhere
    949 * if we branch for numerical reasons, then cons-expr-core should figure out what the candidates are
    950 */
    951 BMSclearMemoryArray(branchcand, SCIPexprGetNChildren(expr));
    952
    953 return SCIP_OKAY;
    954}
    955
    956/** expression reverse propagation callback */
    957static
    959{ /*lint --e{715}*/
    960 SCIP_EXPRDATA* exprdata;
    961 SCIP_INTERVAL* newbounds;
    962 int nchildren;
    963 int nreductions;
    964
    965 assert(scip != NULL);
    966 assert(expr != NULL);
    967 assert(infeasible != NULL);
    968
    969 nchildren = SCIPexprGetNChildren(expr);
    970 assert(nchildren > 0);
    971
    972 exprdata = SCIPexprGetData(expr);
    973 assert(exprdata != NULL);
    974
    975 SCIP_CALL( SCIPallocBufferArray(scip, &newbounds, nchildren) );
    976
    977 nreductions = SCIPintervalPropagateWeightedSum(SCIP_INTERVAL_INFINITY, nchildren, childrenbounds,
    978 exprdata->coefficients, exprdata->constant, bounds, newbounds, infeasible);
    979
    980 if( !*infeasible && nreductions > 0 )
    981 BMScopyMemoryArray(childrenbounds, newbounds, nchildren);
    982
    983 SCIPfreeBufferArray(scip, &newbounds);
    984
    985 return SCIP_OKAY;
    986}
    987
    988/** sum hash callback */
    989static
    991{ /*lint --e{715}*/
    992 SCIP_EXPRDATA* exprdata;
    993 int c;
    994
    995 assert(scip != NULL);
    996 assert(expr != NULL);
    997 assert(hashkey != NULL);
    998 assert(childrenhashes != NULL);
    999
    1000 exprdata = SCIPexprGetData(expr);
    1001 assert(exprdata != NULL);
    1002
    1003 /**! [SnippetExprHashSum] */
    1004 *hashkey = EXPRHDLR_HASHKEY;
    1005 *hashkey ^= SCIPcalcFibHash(exprdata->constant);
    1006
    1007 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1008 *hashkey ^= SCIPcalcFibHash(exprdata->coefficients[c]) ^ childrenhashes[c];
    1009 /**! [SnippetExprHashSum] */
    1010
    1011 return SCIP_OKAY;
    1012}
    1013
    1014/** expression curvature detection callback */
    1015static
    1017{ /*lint --e{715}*/
    1018 SCIP_EXPRDATA* exprdata;
    1019 int i;
    1020
    1021 assert(scip != NULL);
    1022 assert(expr != NULL);
    1023 assert(childcurv != NULL);
    1024 assert(success != NULL);
    1025
    1026 exprdata = SCIPexprGetData(expr);
    1027 assert(exprdata != NULL);
    1028
    1029 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    1030 childcurv[i] = SCIPexprcurvMultiply(exprdata->coefficients[i], exprcurvature);
    1031
    1032 *success = TRUE;
    1033
    1034 return SCIP_OKAY;
    1035}
    1036
    1037/** expression monotonicity detection callback */
    1038static
    1040{ /*lint --e{715}*/
    1041 SCIP_EXPRDATA* exprdata;
    1042
    1043 assert(scip != NULL);
    1044 assert(expr != NULL);
    1045 assert(result != NULL);
    1046 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
    1047
    1048 exprdata = SCIPexprGetData(expr);
    1049 assert(exprdata != NULL);
    1050
    1051 *result = exprdata->coefficients[childidx] >= 0.0 ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
    1052
    1053 return SCIP_OKAY;
    1054}
    1055
    1056/** expression integrality detection callback */
    1057static
    1059{ /*lint --e{715}*/
    1060 SCIP_EXPRDATA* exprdata;
    1061 int i;
    1062
    1063 assert(scip != NULL);
    1064 assert(expr != NULL);
    1065 assert(integrality != NULL);
    1066
    1067 exprdata = SCIPexprGetData(expr);
    1068 assert(exprdata != NULL);
    1069
    1070 /**! [SnippetExprIntegralitySum] */
    1071 *integrality = EPSISINT(exprdata->constant, 0.0) ? SCIP_IMPLINTTYPE_STRONG : SCIP_IMPLINTTYPE_NONE; /*lint !e835 */
    1072
    1073 for( i = 0; i < SCIPexprGetNChildren(expr) && *integrality != SCIP_IMPLINTTYPE_NONE; ++i )
    1074 {
    1075 SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
    1076 assert(child != NULL);
    1077
    1078 if( EPSISINT(exprdata->coefficients[i], 0.0) ) /*lint !e835*/
    1079 *integrality = MIN(*integrality, SCIPexprGetIntegrality(child)); /*lint !e666*/
    1080 else
    1081 *integrality = SCIP_IMPLINTTYPE_NONE;
    1082 }
    1083 /**! [SnippetExprIntegralitySum] */
    1084
    1085 return SCIP_OKAY;
    1086}
    1087
    1088/** creates the handler for sum expressions and includes it into SCIP */
    1090 SCIP* scip /**< SCIP data structure */
    1091 )
    1092{
    1093 SCIP_EXPRHDLR* exprhdlr;
    1094
    1096 assert(exprhdlr != NULL);
    1097
    1098 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrSum, NULL);
    1099 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataSum, freedataSum);
    1100 SCIPexprhdlrSetSimplify(exprhdlr, simplifySum);
    1101 SCIPexprhdlrSetCompare(exprhdlr, compareSum);
    1102 SCIPexprhdlrSetPrint(exprhdlr, printSum);
    1103 SCIPexprhdlrSetIntEval(exprhdlr, intevalSum);
    1104 SCIPexprhdlrSetEstimate(exprhdlr, initEstimatesSum, estimateSum);
    1105 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropSum);
    1106 SCIPexprhdlrSetHash(exprhdlr, hashSum);
    1107 SCIPexprhdlrSetDiff(exprhdlr, bwdiffSum, fwdiffSum, bwfwdiffSum);
    1108 SCIPexprhdlrSetCurvature(exprhdlr, curvatureSum);
    1109 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicitySum);
    1110 SCIPexprhdlrSetIntegrality(exprhdlr, integralitySum);
    1111 SCIPexprhdlrSetGetSymdata(exprhdlr, getSymDataSum);
    1112
    1113 return SCIP_OKAY;
    1114}
    1115
    1116/** creates a sum expression */
    1118 SCIP* scip, /**< SCIP data structure */
    1119 SCIP_EXPR** expr, /**< pointer where to store expression */
    1120 int nchildren, /**< number of children */
    1121 SCIP_EXPR** children, /**< children */
    1122 SCIP_Real* coefficients, /**< array with coefficients for all children (or NULL if all 1.0) */
    1123 SCIP_Real constant, /**< constant term of sum */
    1124 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1125 void* ownercreatedata /**< data to pass to ownercreate */
    1126 )
    1127{
    1128 SCIP_EXPRDATA* exprdata;
    1129
    1130 SCIP_CALL( createData(scip, &exprdata, nchildren, coefficients, constant) );
    1131
    1132 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPgetExprhdlrSum(scip), exprdata, nchildren, children, ownercreate, ownercreatedata) );
    1133
    1134 return SCIP_OKAY;
    1135}
    1136
    1137/** sets the constant of a summation expression */
    1139 SCIP_EXPR* expr, /**< sum expression */
    1140 SCIP_Real constant /**< constant */
    1141 )
    1142{
    1143 SCIP_EXPRDATA* exprdata;
    1144
    1145 assert(expr != NULL);
    1146
    1147 exprdata = SCIPexprGetData(expr);
    1148 assert(exprdata != NULL);
    1149
    1150 exprdata->constant = constant;
    1151}
    1152
    1153/** appends an expression to a sum expression */
    1155 SCIP* scip, /**< SCIP data structure */
    1156 SCIP_EXPR* expr, /**< sum expression */
    1157 SCIP_EXPR* child, /**< expression to be appended */
    1158 SCIP_Real childcoef /**< child's coefficient */
    1159 )
    1160{
    1161 SCIP_EXPRDATA* exprdata;
    1162 int nchildren;
    1163
    1164 assert(expr != NULL);
    1165 assert(SCIPisExprSum(scip, expr));
    1166
    1167 exprdata = SCIPexprGetData(expr);
    1168 assert(exprdata != NULL);
    1169
    1170 nchildren = SCIPexprGetNChildren(expr);
    1171
    1172 SCIP_CALL( SCIPensureBlockMemoryArray(scip, &exprdata->coefficients, &exprdata->coefssize, nchildren + 1) );
    1173
    1174 assert(exprdata->coefssize > nchildren);
    1175 exprdata->coefficients[nchildren] = childcoef;
    1176
    1177 SCIP_CALL( SCIPappendExprChild(scip, expr, child) );
    1178
    1179 return SCIP_OKAY;
    1180}
    1181
    1182/** multiplies given sum expression by a constant */
    1184 SCIP_EXPR* expr, /**< sum expression */
    1185 SCIP_Real constant /**< constant that multiplies sum expression */
    1186 )
    1187{
    1188 int i;
    1189 SCIP_EXPRDATA* exprdata;
    1190
    1191 assert(expr != NULL);
    1192
    1193 exprdata = SCIPexprGetData(expr);
    1194 assert(exprdata != NULL);
    1195
    1196 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    1197 exprdata->coefficients[i] *= constant;
    1198 exprdata->constant *= constant;
    1199}
    1200
    1201/** constructs the expanded product of two sum expressions */
    1203 SCIP* scip, /**< SCIP data structure */
    1204 SCIP_EXPR** product, /**< buffer where to store multiplied sums (expanded as sum) */
    1205 SCIP_EXPR* factor1, /**< first sum */
    1206 SCIP_EXPR* factor2, /**< second sum */
    1207 SCIP_Bool simplify, /**< whether to simplify created terms and sum */
    1208 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1209 void* ownercreatedata /**< data to pass to ownercreate */
    1210 )
    1211{
    1212 SCIP_Real constant1;
    1213 SCIP_Real constant2;
    1214 int nchildren1;
    1215 int nchildren2;
    1216 int i1;
    1217 int i2;
    1218
    1219 assert(scip != NULL);
    1220 assert(product != NULL);
    1221 assert(factor1 != NULL);
    1222 assert(SCIPisExprSum(scip, factor1));
    1223 assert(factor2 != NULL);
    1224 assert(SCIPisExprSum(scip, factor2));
    1225
    1226 constant1 = SCIPgetConstantExprSum(factor1);
    1227 constant2 = SCIPgetConstantExprSum(factor2);
    1228 nchildren1 = SCIPexprGetNChildren(factor1);
    1229 nchildren2 = SCIPexprGetNChildren(factor2);
    1230
    1231 /* TODO might be nice to integrate more with simplify and construct a simplified sum right away */
    1232
    1233 SCIP_CALL( SCIPcreateExprSum(scip, product, 0, NULL, NULL, constant1 * constant2, ownercreate, ownercreatedata) );
    1234
    1235 /* first add constant1 * factor2
    1236 * constant * constant2 already added above
    1237 */
    1238 if( constant1 != 0.0 )
    1239 {
    1240 for( i2 = 0; i2 < nchildren2; ++i2 )
    1241 {
    1242 SCIP_CALL( SCIPappendExprSumExpr(scip, *product, SCIPexprGetChildren(factor2)[i2], constant1 * SCIPgetCoefsExprSum(factor2)[i2]) );
    1243 }
    1244 }
    1245
    1246 for( i1 = 0; i1 < nchildren1; ++i1 )
    1247 {
    1248 SCIP_EXPR* child1;
    1249 SCIP_EXPR* child2;
    1250 SCIP_Real coef1;
    1251 SCIP_Real coef2;
    1252
    1253 coef1 = SCIPgetCoefsExprSum(factor1)[i1];
    1254 child1 = SCIPexprGetChildren(factor1)[i1];
    1255
    1256 if( constant2 != 0.0 )
    1257 {
    1258 /* add coef1 * child1 * constant2 */
    1259 SCIP_CALL( SCIPappendExprSumExpr(scip, *product, child1, coef1 * constant2) );
    1260 }
    1261
    1262 for( i2 = 0; i2 < nchildren2; ++i2 )
    1263 {
    1264 /* add coef1 * child1 * coef2 * child2 */
    1265 SCIP_EXPR* termprod;
    1266 SCIP_EXPR* termprodsimplified;
    1267 SCIP_EXPR* termfactors[2];
    1268
    1269 coef2 = SCIPgetCoefsExprSum(factor2)[i2];
    1270 child2 = SCIPexprGetChildren(factor2)[i2];
    1271
    1272 /* create child1 * child2 expr */
    1273 termfactors[0] = child1;
    1274 termfactors[1] = child2;
    1275 SCIP_CALL( SCIPcreateExprProduct(scip, &termprod, 2, termfactors, 1.0, NULL, NULL) );
    1276
    1277 if( simplify )
    1278 {
    1279 SCIP_Bool changed;
    1280 SCIP_Bool infeasible;
    1281
    1282 /* simplify child1*child2 */
    1283 SCIP_CALL( SCIPsimplifyExpr(scip, termprod, &termprodsimplified, &changed, &infeasible, ownercreate, ownercreatedata) );
    1284 assert(!infeasible); /* simplify of products should never be infeasible */
    1285 SCIP_CALL( SCIPreleaseExpr(scip, &termprod) );
    1286 }
    1287 else
    1288 termprodsimplified = termprod;
    1289
    1290 /* append to product */
    1291 SCIP_CALL( SCIPappendExprSumExpr(scip, *product, termprodsimplified, coef1 * coef2) );
    1292 SCIP_CALL( SCIPreleaseExpr(scip, &termprodsimplified) );
    1293 }
    1294 }
    1295
    1296 if( simplify )
    1297 {
    1298 SCIP_EXPR* prodsimplified;
    1299 SCIP_Bool changed;
    1300 SCIP_Bool infeasible;
    1301
    1302 SCIP_CALL( SCIPsimplifyExpr(scip, *product, &prodsimplified, &changed, &infeasible, ownercreate, ownercreatedata) );
    1303 assert(!infeasible);
    1304 SCIP_CALL( SCIPreleaseExpr(scip, product) );
    1305 *product = prodsimplified;
    1306 }
    1307
    1308 return SCIP_OKAY;
    1309}
    1310
    1311/** constructs the expanded power of a sum expression
    1312 *
    1313 * @attention The number of terms in the expansion grows exponential with the exponent. Be aware of what you wish for.
    1314 */
    1316 SCIP* scip, /**< SCIP data structure */
    1317 SCIP_EXPR** result, /**< buffer where to store expanded power of sum */
    1318 SCIP_EXPR* base, /**< sum */
    1319 int exponent, /**< exponent > 1 */
    1320 SCIP_Bool simplify, /**< whether to simplify created terms and sum */
    1321 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1322 void* ownercreatedata /**< data to pass to ownercreate */
    1323 )
    1324{
    1325 /* for sum_i alpha_i expr_i and exponent p, this constructs
    1326 * sum_{beta} (p over beta) prod_i (alpha_i expr_i)^beta_i over all multiindex beta such that sum_i beta_i = p
    1327 * See also https://en.wikipedia.org/wiki/Multinomial_theorem
    1328 * Calculation of multinomials adapted from https://github.com/m-j-w/MultinomialSeries.jl
    1329 *
    1330 * TODO might be nice to integrate more with simplify and construct a simplified sum right away
    1331 */
    1332
    1333 SCIP_EXPR** children;
    1334 SCIP_EXPR*** childrenpower;
    1335 SCIP_Real* coefs;
    1336 SCIP_Real constant;
    1337 SCIP_Bool haveconst;
    1338 int nchildren;
    1339 int nterms;
    1340 int* factorials;
    1341 int* beta;
    1342 int betapos;
    1343 int restsum;
    1344 int multinomialcoef;
    1345 int i;
    1346
    1347 SCIP_EXPR* newterm;
    1348 SCIP_Real newtermcoef;
    1349
    1350 assert(scip != NULL);
    1351 assert(result != NULL);
    1352 assert(base != NULL);
    1353 assert(exponent > 1);
    1354 assert(SCIPisExprSum(scip, base));
    1355 assert(exponent > 1.0);
    1356
    1357 children = SCIPexprGetChildren(base);
    1358 nchildren = SCIPexprGetNChildren(base);
    1359 coefs = SCIPgetCoefsExprSum(base);
    1360 constant = SCIPgetConstantExprSum(base);
    1361 haveconst = constant != 0.0;
    1362 nterms = nchildren + (haveconst ? 1 : 0);
    1363
    1364#ifdef SCIP_DEBUG
    1365 SCIPinfoMessage(scip, NULL, "expanding (");
    1366 SCIPprintExpr(scip, base, NULL);
    1367 SCIPinfoMessage(scip, NULL, ")^%d\n", exponent);
    1368#endif
    1369
    1370 SCIP_CALL( SCIPcreateExprSum(scip, result, 0, NULL, NULL, 0.0, ownercreate, ownercreatedata) );
    1371
    1373 SCIP_CALL( SCIPallocBufferArray(scip, &factorials, exponent+1) );
    1374
    1375 /* precompute factorials k!, k = 0...exponent */
    1376 factorials[0] = 1;
    1377 for( i = 1; i <= exponent; ++i )
    1378 factorials[i] = factorials[i-1] * i;
    1379
    1380 /* precompute children^k, k=1..exponent */
    1381 SCIP_CALL( SCIPallocBufferArray(scip, &childrenpower, nchildren) );
    1382 for( i = 0; i < nchildren; ++i )
    1383 {
    1384 int k;
    1385 SCIP_CALL( SCIPallocBufferArray(scip, &childrenpower[i], exponent+1) );
    1386 childrenpower[i][1] = children[i];
    1387 for( k = 2; k <= exponent; ++k )
    1388 {
    1389 SCIP_CALL( SCIPcreateExprPow(scip, &childrenpower[i][k], children[i], (SCIP_Real)k, NULL, NULL) );
    1390 if( simplify )
    1391 {
    1392 SCIP_Bool changed;
    1393 SCIP_Bool infeasible;
    1394 SCIP_EXPR* simplified;
    1395
    1396 SCIP_CALL( SCIPsimplifyExpr(scip, childrenpower[i][k], &simplified, &changed, &infeasible, ownercreate, ownercreatedata) );
    1397 assert(!infeasible);
    1398 SCIP_CALL( SCIPreleaseExpr(scip, &childrenpower[i][k]) );
    1399 childrenpower[i][k] = simplified;
    1400 }
    1401 }
    1402 }
    1403
    1404 /* first multinomial is (exponent,0,0,...) */
    1405 beta[0] = exponent;
    1406 betapos = 0;
    1407 do
    1408 {
    1409 /* compute multinomial coef exponent! / (beta[0]! * ... * beta[nterms-1]!) */
    1410 multinomialcoef = factorials[exponent];
    1411 for( i = 0; i < nterms; ++i )
    1412 {
    1413 assert(beta[i] >= 0);
    1414 assert(beta[i] <= exponent);
    1415 multinomialcoef /= factorials[beta[i]];
    1416 }
    1417
    1418 SCIPdebugMsg(scip, "multinomial (");
    1419 for( i = 0; i < nterms; ++i )
    1420 SCIPdebugPrintf("%d ", beta[i]);
    1421 SCIPdebugPrintf(") with coef %d\n", multinomialcoef);
    1422
    1423 /* construct new term for expanded sum */
    1424 SCIP_CALL( SCIPcreateExprProduct(scip, &newterm, 0, NULL, 1.0, ownercreate, ownercreatedata) );
    1425 newtermcoef = multinomialcoef;
    1426 for( i = 0; i < nterms; ++i )
    1427 {
    1428 if( beta[i] == 0 )
    1429 continue;
    1430
    1431 if( i == nterms-1 && haveconst )
    1432 {
    1433 /* if constant term, then update newtermcoef */
    1434 newtermcoef *= pow(constant, (double)beta[i]);
    1435 continue;
    1436 }
    1437
    1438 /* alpha_i^beta_i */
    1439 newtermcoef *= pow(coefs[i], (double)beta[i]);
    1440
    1441 /* expr_i^beta_i*/
    1442 SCIP_CALL( SCIPappendExprChild(scip, newterm, childrenpower[i][beta[i]]) );
    1443 }
    1444
    1445 /* append newterm to sum */
    1446 switch( SCIPexprGetNChildren(newterm) )
    1447 {
    1448 case 0:
    1449 {
    1450 /* no factor in product, so it is a constant -> update constant in sum */
    1451 SCIPsetConstantExprSum(*result, SCIPgetConstantExprSum(*result) + newtermcoef);
    1452 break;
    1453 }
    1454
    1455 case 1:
    1456 {
    1457 /* only one factor in product -> add this factor itself to sum */
    1458 SCIP_CALL( SCIPappendExprSumExpr(scip, *result, SCIPexprGetChildren(newterm)[0], newtermcoef) );
    1459 break;
    1460 }
    1461
    1462 default:
    1463 {
    1464 if( simplify )
    1465 {
    1466 /* simplify product */
    1467 SCIP_Bool changed;
    1468 SCIP_Bool infeasible;
    1469 SCIP_EXPR* simplified;
    1470
    1471 SCIP_CALL( SCIPsimplifyExpr(scip, newterm, &simplified, &changed, &infeasible, ownercreate, ownercreatedata) );
    1472 assert(!infeasible);
    1473 SCIP_CALL( SCIPreleaseExpr(scip, &newterm) );
    1474 newterm = simplified;
    1475 }
    1476
    1477 /* append new term to sum */
    1478 SCIP_CALL( SCIPappendExprSumExpr(scip, *result, newterm, newtermcoef) );
    1479 break;
    1480 }
    1481 }
    1482 SCIP_CALL( SCIPreleaseExpr(scip, &newterm) );
    1483
    1484 /* determine next beta */
    1485 while( beta[betapos] == 0 )
    1486 --betapos;
    1487
    1488 if( betapos == nterms-1 )
    1489 {
    1490 do
    1491 {
    1492 if( betapos == 0 )
    1493 goto TERMINATE;
    1494 --betapos;
    1495 }
    1496 while( beta[betapos] == 0 );
    1497
    1498 restsum = 0;
    1499 for( i = betapos+1; i < nterms; ++i )
    1500 {
    1501 restsum += beta[i];
    1502 beta[i] = 0;
    1503 }
    1504 beta[betapos+1] = restsum;
    1505 }
    1506
    1507 if( beta[betapos] > 0 )
    1508 {
    1509 --beta[betapos];
    1510 ++beta[++betapos];
    1511 }
    1512 }
    1513 while( TRUE ); /*lint !e506*/
    1514
    1515 TERMINATE:
    1516
    1517 if( simplify )
    1518 {
    1519 SCIP_Bool changed;
    1520 SCIP_Bool infeasible;
    1521 SCIP_EXPR* simplified;
    1522
    1523 SCIP_CALL( SCIPsimplifyExpr(scip, *result, &simplified, &changed, &infeasible, ownercreate, ownercreatedata) );
    1524 assert(!infeasible);
    1525 SCIP_CALL( SCIPreleaseExpr(scip, result) );
    1526 *result = simplified;
    1527 }
    1528
    1529 for( i = nchildren-1; i >= 0; --i )
    1530 {
    1531 int k;
    1532 for( k = exponent; k >= 2; --k )
    1533 {
    1534 SCIP_CALL( SCIPreleaseExpr(scip, &childrenpower[i][k]) );
    1535 }
    1536 SCIPfreeBufferArray(scip, &childrenpower[i]);
    1537 }
    1538 SCIPfreeBufferArray(scip, &childrenpower);
    1539 SCIPfreeBufferArray(scip, &factorials);
    1540 SCIPfreeBufferArray(scip, &beta);
    1541
    1542#ifdef SCIP_DEBUG
    1543 SCIPinfoMessage(scip, NULL, "-> ");
    1544 SCIPprintExpr(scip, *result, NULL);
    1545 SCIPinfoMessage(scip, NULL, "\n");
    1546#endif
    1547
    1548 return SCIP_OKAY;
    1549}
    1550
    1551/* from pub_expr.h */
    1552
    1553/** gets the coefficients of a summation expression */
    1555 SCIP_EXPR* expr /**< sum expression */
    1556 )
    1557{
    1558 SCIP_EXPRDATA* exprdata;
    1559
    1560 assert(expr != NULL);
    1561
    1562 exprdata = SCIPexprGetData(expr);
    1563 assert(exprdata != NULL);
    1564
    1565 return exprdata->coefficients;
    1566}
    1567
    1568/** gets the constant of a summation expression */
    1570 SCIP_EXPR* expr /**< sum expression */
    1571 )
    1572{
    1573 SCIP_EXPRDATA* exprdata;
    1574
    1575 assert(expr != NULL);
    1576
    1577 exprdata = SCIPexprGetData(expr);
    1578 assert(exprdata != NULL);
    1579
    1580 return exprdata->constant;
    1581}
    #define NULL
    Definition: def.h:248
    #define EPSISINT(x, eps)
    Definition: def.h:195
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:180
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define REALABS(x)
    Definition: def.h:182
    #define SCIP_CALL(x)
    Definition: def.h:355
    exponential expression handler
    power and signed power expression handlers
    product expression handler
    #define debugSimplify
    Definition: expr_sum.c:55
    #define EXPRHDLR_HASHKEY
    Definition: expr_sum.c:48
    static SCIP_DECL_EXPRPRINT(printSum)
    Definition: expr_sum.c:700
    static SCIP_DECL_EXPRCOPYHDLR(copyhdlrSum)
    Definition: expr_sum.c:654
    static SCIP_DECL_EXPRBWDIFF(bwdiffSum)
    Definition: expr_sum.c:826
    static SCIP_DECL_EXPREVAL(evalSum)
    Definition: expr_sum.c:777
    static SCIP_DECL_SORTINDCOMP(sortExprComp)
    Definition: expr_sum.c:346
    static SCIP_DECL_EXPRFREEDATA(freedataSum)
    Definition: expr_sum.c:681
    #define EXPRHDLR_NAME
    Definition: expr_sum.c:45
    static SCIP_DECL_EXPRCOMPARE(compareSum)
    Definition: expr_sum.c:587
    static SCIP_DECL_EXPRINTEGRALITY(integralitySum)
    Definition: expr_sum.c:1058
    static SCIP_DECL_EXPRINTEVAL(intevalSum)
    Definition: expr_sum.c:852
    static SCIP_RETCODE createData(SCIP *scip, SCIP_EXPRDATA **exprdata, int ncoefficients, SCIP_Real *coefficients, SCIP_Real constant)
    Definition: expr_sum.c:76
    static SCIP_DECL_EXPRREVERSEPROP(reversepropSum)
    Definition: expr_sum.c:958
    static SCIP_DECL_EXPRESTIMATE(estimateSum)
    Definition: expr_sum.c:927
    static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffSum)
    Definition: expr_sum.c:841
    static SCIP_DECL_EXPRHASH(hashSum)
    Definition: expr_sum.c:990
    static SCIP_DECL_EXPRCURVATURE(curvatureSum)
    Definition: expr_sum.c:1016
    static SCIP_DECL_EXPRGETSYMDATA(getSymDataSum)
    Definition: expr_sum.c:542
    static SCIP_RETCODE simplifyTerm(SCIP *scip, SCIP_EXPR *duplicate, int idx, SCIP_Bool *changed, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:114
    static SCIP_DECL_EXPRINITESTIMATES(initEstimatesSum)
    Definition: expr_sum.c:898
    static SCIP_DECL_EXPRSIMPLIFY(simplifySum)
    Definition: expr_sum.c:364
    #define EXPRHDLR_DESC
    Definition: expr_sum.c:46
    #define EXPRHDLR_PRECEDENCE
    Definition: expr_sum.c:47
    static SCIP_DECL_EXPRMONOTONICITY(monotonicitySum)
    Definition: expr_sum.c:1039
    static SCIP_DECL_EXPRFWDIFF(fwdiffSum)
    Definition: expr_sum.c:802
    static SCIP_DECL_EXPRCOPYDATA(copydataSum)
    Definition: expr_sum.c:663
    sum expression handler
    constant value expression handler
    SCIP_RETCODE SCIPcreateExprProduct(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real coefficient, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    void SCIPsetConstantExprSum(SCIP_EXPR *expr, SCIP_Real constant)
    Definition: expr_sum.c:1138
    void SCIPmultiplyByConstantExprSum(SCIP_EXPR *expr, SCIP_Real constant)
    Definition: expr_sum.c:1183
    SCIP_RETCODE SCIPpowerExprSum(SCIP *scip, SCIP_EXPR **result, SCIP_EXPR *base, int exponent, SCIP_Bool simplify, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:1315
    SCIP_RETCODE SCIPappendExprSumExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child, SCIP_Real childcoef)
    Definition: expr_sum.c:1154
    SCIP_Bool SCIPisExprExp(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_exp.c:528
    SCIP_RETCODE SCIPcreateExprExp(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_exp.c:510
    SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:1117
    SCIP_RETCODE SCIPmultiplyBySumExprSum(SCIP *scip, SCIP_EXPR **product, SCIP_EXPR *factor1, SCIP_EXPR *factor2, SCIP_Bool simplify, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:1202
    SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_value.c:274
    SCIP_RETCODE SCIPcreateExprPow(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_pow.c:3185
    SCIP_RETCODE SCIPincludeExprhdlrSum(SCIP *scip)
    Definition: expr_sum.c:1089
    void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
    Definition: scip_message.c:208
    #define SCIPdebugMsgPrint
    Definition: scip_message.h:79
    #define SCIPdebugMsg
    Definition: scip_message.h:78
    unsigned int SCIPcalcFibHash(SCIP_Real v)
    Definition: misc.c:10462
    const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:545
    void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEGRALITY((*integrality)))
    Definition: expr.c:440
    void SCIPexprhdlrSetCopyFreeData(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYDATA((*copydata)), SCIP_DECL_EXPRFREEDATA((*freedata)))
    Definition: expr.c:383
    void SCIPexprhdlrSetPrint(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRPRINT((*print)))
    Definition: expr.c:396
    void SCIPexprhdlrSetGetSymdata(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRGETSYMDATA((*getsymdata)))
    Definition: expr.c:521
    void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
    Definition: expr.c:451
    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 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
    SCIP_EXPRHDLR * SCIPgetExprhdlrSum(SCIP *scip)
    Definition: scip_expr.c:928
    void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEVAL((*inteval)))
    Definition: expr.c:488
    void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCURVATURE((*curvature)))
    Definition: expr.c:418
    SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
    Definition: scip_expr.c:847
    void SCIPexprhdlrSetCompare(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOMPARE((*compare)))
    Definition: expr.c:462
    void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRSIMPLIFY((*simplify)))
    Definition: expr.c:499
    SCIP_IMPLINTTYPE SCIPexprGetIntegrality(SCIP_EXPR *expr)
    Definition: expr.c:4091
    SCIP_RETCODE SCIPcreateExpr(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPRHDLR *exprhdlr, SCIP_EXPRDATA *exprdata, int nchildren, SCIP_EXPR **children, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1000
    SCIP_RETCODE SCIPappendExprChild(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child)
    Definition: scip_expr.c:1256
    void SCIPexprSetData(SCIP_EXPR *expr, SCIP_EXPRDATA *exprdata)
    Definition: expr.c:3920
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1490
    SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1479
    SCIP_RETCODE SCIPreplaceExprChild(SCIP *scip, SCIP_EXPR *expr, int childidx, SCIP_EXPR *newchild)
    Definition: scip_expr.c:1274
    SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1554
    SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1468
    int SCIPcompareExpr(SCIP *scip, SCIP_EXPR *expr1, SCIP_EXPR *expr2)
    Definition: scip_expr.c:1759
    SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
    Definition: scip_expr.c:1443
    SCIP_Real SCIPexprGetDot(SCIP_EXPR *expr)
    Definition: expr.c:3986
    SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
    Definition: expr.c:3905
    SCIP_EXPRCURV SCIPexprcurvMultiply(SCIP_Real factor, SCIP_EXPRCURV curvature)
    Definition: exprcurv.c:88
    SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
    Definition: scip_expr.c:1512
    SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
    Definition: expr_value.c:298
    SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
    Definition: expr.c:3946
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1569
    SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
    Definition: expr.c:4028
    SCIP_RETCODE SCIPduplicateExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR **copyexpr, SCIP_DECL_EXPR_MAPEXPR((*mapexpr)), void *mapexprdata, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1307
    void SCIPcaptureExpr(SCIP_EXPR *expr)
    Definition: scip_expr.c:1435
    SCIP_RETCODE SCIPsimplifyExpr(SCIP *scip, SCIP_EXPR *rootexpr, SCIP_EXPR **simplified, SCIP_Bool *changed, SCIP_Bool *infeasible, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: scip_expr.c:1798
    SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
    Definition: expr.c:3895
    void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
    SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalMulScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
    int SCIPintervalPropagateWeightedSum(SCIP_Real infinity, int noperands, SCIP_INTERVAL *operands, SCIP_Real *weights, SCIP_Real constant, SCIP_INTERVAL rhs, SCIP_INTERVAL *resultants, SCIP_Bool *infeasible)
    void SCIPintervalAdd(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
    #define SCIPfreeBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:110
    #define SCIPensureBlockMemoryArray(scip, ptr, arraysizeptr, minsize)
    Definition: scip_mem.h:107
    #define SCIPallocClearBufferArray(scip, ptr, num)
    Definition: scip_mem.h:126
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPfreeBufferArrayNull(scip, ptr)
    Definition: scip_mem.h:137
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    #define SCIPduplicateBlockMemoryArray(scip, ptr, source, num)
    Definition: scip_mem.h:105
    SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    void SCIPsortInd(int *indarray, SCIP_DECL_SORTINDCOMP((*indcomp)), void *dataptr, int len)
    static volatile int nterms
    Definition: interrupt.c:47
    #define BMScopyMemoryArray(ptr, source, num)
    Definition: memory.h:134
    #define BMSclearMemoryArray(ptr, num)
    Definition: memory.h:130
    #define SCIPdebugPrintf
    Definition: pub_message.h:99
    SCIP_Real sup
    Definition: intervalarith.h:57
    SCIP_Real inf
    Definition: intervalarith.h:56
    SCIP_EXPR ** exprs
    Definition: expr_sum.c:342
    SCIP * scip
    Definition: expr_sum.c:341
    structs for symmetry computations
    #define SCIP_DECL_EXPR_OWNERCREATE(x)
    Definition: type_expr.h:143
    struct SCIP_ExprData SCIP_EXPRDATA
    Definition: type_expr.h:54
    #define SCIP_EXPRITER_VISITINGCHILD
    Definition: type_expr.h:695
    @ SCIP_MONOTONE_INC
    Definition: type_expr.h:72
    @ SCIP_MONOTONE_DEC
    Definition: type_expr.h:73
    #define SCIP_EXPRITER_VISITEDCHILD
    Definition: type_expr.h:696
    #define SCIP_EXPRITER_LEAVEEXPR
    Definition: type_expr.h:697
    #define SCIP_EXPRITER_ENTEREXPR
    Definition: type_expr.h:694
    @ SCIP_OKAY
    Definition: type_retcode.h:42
    enum SCIP_Retcode SCIP_RETCODE
    Definition: type_retcode.h:63
    @ SCIP_IMPLINTTYPE_NONE
    Definition: type_var.h:90
    @ SCIP_IMPLINTTYPE_STRONG
    Definition: type_var.h:106