Scippy

    SCIP

    Solving Constraint Integer Programs

    expr_product.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_product.c
    26 * @ingroup DEFPLUGINS_EXPR
    27 * @brief product expression handler
    28 * @author Stefan Vigerske
    29 * @author Benjamin Mueller
    30 * @author Felipe Serrano
    31 * @author Ksenia Bestuzheva
    32 */
    33
    34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
    35
    36#include <string.h>
    37
    38#include "scip/pub_expr.h"
    39#include "scip/expr_product.h"
    40#include "scip/expr_sum.h"
    41#include "scip/expr_pow.h"
    42#include "scip/expr_value.h"
    43#include "scip/expr_exp.h"
    44#include "scip/expr_abs.h"
    45#include "scip/expr_entropy.h"
    46#include "scip/cons_nonlinear.h"
    47#include "scip/pub_misc.h"
    50
    51#define EXPRHDLR_NAME "prod"
    52#define EXPRHDLR_DESC "product expression"
    53#define EXPRHDLR_PRECEDENCE 50000
    54#define EXPRHDLR_HASHKEY SCIPcalcFibHash(54949.0)
    55
    56/** macro to activate/deactivate debugging information of simplify method */
    57/*lint -emacro(681,debugSimplify) */
    58/*lint -emacro(506,debugSimplify) */
    59/*lint -emacro(774,debugSimplify) */
    60#ifdef SIMPLIFY_DEBUG
    61#define debugSimplify printf
    62#else
    63#define debugSimplify while( FALSE ) printf
    64#endif
    65
    66
    67/*lint -e777*/
    68
    69/*
    70 * Data structures
    71 */
    72
    73/** expression data */
    74struct SCIP_ExprData
    75{
    76 SCIP_Real coefficient; /**< coefficient */
    77};
    78
    79struct SCIP_ExprhdlrData
    80{
    81 SCIP_CONSHDLR* conshdlr; /**< nonlinear constraint handler (to compute estimates for > 2-dim products) */
    82
    83 SCIP_Bool expandalways; /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    84};
    85
    86/** node for linked list of expressions */
    88{
    89 SCIP_EXPR* expr; /**< expression in node */
    90 struct exprnode* next; /**< next node */
    91};
    92
    93typedef struct exprnode EXPRNODE;
    94
    95/*
    96 * Local methods
    97 */
    98
    99/** evaluation callback for (vertex-polyhedral) functions used as input for facet computation of its envelopes */
    100static
    102{
    103 /* funcdata is a pointer to the double holding the coefficient */
    104 SCIP_Real ret = *(SCIP_Real*)funcdata;
    105 int i;
    106
    107 for( i = 0; i < nargs; ++i )
    108 ret *= args[i];
    109
    110 return ret;
    111}
    112
    113static
    115 SCIP* scip, /**< SCIP data structure */
    116 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    117 EXPRNODE** simplifiedfactors, /**< factors of simplified product */
    118 SCIP_Bool expandalways, /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    119 SCIP_Bool changed, /**< indicates whether some of the simplified factors was changed */
    120 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    121 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    122 void* ownercreatedata /**< data to pass to ownercreate */
    123 );
    124
    125/* methods for handling linked list of expressions */
    126
    127/** inserts newnode at beginning of list */
    128static
    130 EXPRNODE* newnode, /**< node to insert */
    131 EXPRNODE** list /**< list */
    132 )
    133{
    134 assert(list != NULL);
    135 assert(newnode != NULL);
    136
    137 newnode->next = *list;
    138 *list = newnode;
    139}
    140
    141/** removes first element of list and returns it */
    142static
    144 EXPRNODE** list /**< list */
    145 )
    146{
    147 EXPRNODE* first;
    148
    149 assert(list != NULL);
    150
    151 if( *list == NULL )
    152 return NULL;
    153
    154 first = *list;
    155 *list = (*list)->next;
    156 first->next = NULL;
    157
    158 return first;
    159}
    160
    161/** returns length of list */
    162static
    164 EXPRNODE* list /**< list */
    165 )
    166{
    167 int length;
    168
    169 if( list == NULL )
    170 return 0;
    171
    172 length = 1;
    173 while( (list=list->next) != NULL )
    174 ++length;
    175
    176 return length;
    177}
    178
    179/** creates expression node and captures expression */
    180static
    182 SCIP* scip, /**< SCIP data structure */
    183 SCIP_EXPR* expr, /**< expression stored at node */
    184 EXPRNODE** newnode /**< pointer to store node */
    185 )
    186{
    188
    189 (*newnode)->expr = expr;
    190 (*newnode)->next = NULL;
    192
    193 return SCIP_OKAY;
    194}
    195
    196/** creates expression list from expressions */
    197static
    199 SCIP* scip, /**< SCIP data structure */
    200 SCIP_EXPR** exprs, /**< expressions stored in list */
    201 int nexprs, /**< number of expressions */
    202 EXPRNODE** list /**< pointer to store list */
    203 )
    204{
    205 int i;
    206
    207 assert(*list == NULL);
    208 assert(nexprs > 0);
    209
    210 debugSimplify("building expr list from %d expressions\n", nexprs);
    211 for( i = nexprs - 1; i >= 0; --i )
    212 {
    213 EXPRNODE* newnode;
    214
    215 SCIP_CALL( createExprNode(scip, exprs[i], &newnode) );
    216 insertFirstList(newnode, list);
    217 }
    218 assert(nexprs > 1 || (*list)->next == NULL);
    219
    220 return SCIP_OKAY;
    221}
    222
    223/** frees expression node and releases expressions */
    224static
    226 SCIP* scip, /**< SCIP data structure */
    227 EXPRNODE** node /**< node to be freed */
    228 )
    229{
    230 assert(node != NULL && *node != NULL);
    231
    232 SCIP_CALL( SCIPreleaseExpr(scip, &(*node)->expr) );
    234
    235 return SCIP_OKAY;
    236}
    237
    238/** frees an expression list */
    239static
    241 SCIP* scip, /**< SCIP data structure */
    242 EXPRNODE** exprlist /**< list */
    243 )
    244{
    245 EXPRNODE* current;
    246
    247 if( *exprlist == NULL )
    248 return SCIP_OKAY;
    249
    250 current = *exprlist;
    251 while( current != NULL )
    252 {
    253 EXPRNODE* tofree;
    254
    255 tofree = current;
    256 current = current->next;
    257 SCIP_CALL( freeExprNode(scip, &tofree) );
    258 }
    259 assert(current == NULL);
    260 *exprlist = NULL;
    261
    262 return SCIP_OKAY;
    263}
    264
    265/* helper functions for simplifying expressions */
    266
    267/** creates a product expression with the elements of exprlist as its children */
    268static
    270 SCIP* scip, /**< SCIP data structure */
    271 EXPRNODE* exprlist, /**< list containing the children of expr */
    272 SCIP_Real coef, /**< coef of expr */
    273 SCIP_EXPR** expr, /**< pointer to store the product expression */
    274 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    275 void* ownercreatedata /**< data to pass to ownercreate */
    276 )
    277{
    278 int i;
    279 int nchildren;
    280 SCIP_EXPR** children;
    281
    282 /* asserts SP8 */
    283 assert(coef == 1.0);
    284 nchildren = listLength(exprlist);
    285
    286 SCIP_CALL( SCIPallocBufferArray(scip, &children, nchildren) );
    287
    288 for( i = 0; i < nchildren; ++i )
    289 {
    290 children[i] = exprlist->expr;
    291 exprlist = exprlist->next;
    292 }
    293
    294 assert(exprlist == NULL);
    295
    296 SCIP_CALL( SCIPcreateExprProduct(scip, expr, nchildren, children, coef, ownercreate, ownercreatedata) );
    297
    298 SCIPfreeBufferArray(scip, &children);
    299
    300 return SCIP_OKAY;
    301}
    302
    303/** simplifies a factor of a product expression: base, so that it is a valid children of a simplified product expr
    304 *
    305 * @note In contrast to other simplify methods, this does *not* return a simplified expression.
    306 * Instead, the method is intended to be called only when simplifying a product expression.
    307 * Since in general, base is not a simplified child of a product expression, this method returns
    308 * a list of expressions L, such that (prod L) = baset *and* each expression in L
    309 * is a valid child of a simplified product expression.
    310 */
    311static
    313 SCIP* scip, /**< SCIP data structure */
    314 SCIP_EXPR* factor, /**< expression to be simplified */
    315 SCIP_Real* simplifiedcoef, /**< coefficient of parent product expression */
    316 EXPRNODE** simplifiedfactor, /**< pointer to store the resulting expression node/list of nodes */
    317 SCIP_Bool* changed /**< pointer to store if some term actually got simplified */
    318 )
    319{
    320 assert(simplifiedfactor != NULL);
    321 assert(*simplifiedfactor == NULL);
    322 assert(factor != NULL);
    323 assert(changed != NULL);
    324
    325 /* enforces SP7 */
    326 if( SCIPisExprValue(scip, factor) )
    327 {
    328 *changed = TRUE;
    329 *simplifiedcoef *= SCIPgetValueExprValue(factor);
    330 return SCIP_OKAY;
    331 }
    332
    333 /* enforces SP2 */
    334 if( SCIPisExprProduct(scip, factor) )
    335 {
    336 *changed = TRUE;
    337
    338 /* assert SP8 */
    339 assert(SCIPgetCoefExprProduct(factor) == 1.0);
    340 debugSimplify("[simplifyFactor] seeing a product: include its children\n");
    341
    342 SCIP_CALL( createExprlistFromExprs(scip, SCIPexprGetChildren(factor), SCIPexprGetNChildren(factor), simplifiedfactor) );
    343
    344 return SCIP_OKAY;
    345 }
    346
    347 /* enforces SP13: a sum with a unique child and no constant -> take the coefficient and use its child as factor */
    348 if( SCIPisExprSum(scip, factor) && SCIPexprGetNChildren(factor) == 1 && SCIPgetConstantExprSum(factor) == 0.0 )
    349 {
    350 *changed = TRUE;
    351
    352 /* assert SS8 and SS7 */
    353 assert(SCIPgetCoefsExprSum(factor)[0] != 0.0 && SCIPgetCoefsExprSum(factor)[0] != 1.0);
    354 debugSimplify("[simplifyFactor] seeing a sum of the form coef * child : take coef and child apart\n");
    355
    357 {
    358 /* if child is a product, then add its children to exprlist */
    360 *simplifiedcoef *= SCIPgetCoefExprProduct(SCIPexprGetChildren(factor)[0]);
    361 }
    362 else
    363 {
    364 SCIP_CALL( createExprlistFromExprs(scip, SCIPexprGetChildren(factor), 1, simplifiedfactor) );
    365 }
    366 *simplifiedcoef *= SCIPgetCoefsExprSum(factor)[0];
    367
    368 return SCIP_OKAY;
    369 }
    370
    371 /* the given (simplified) expression `factor`, can be a child of a simplified product */
    372 assert(!SCIPisExprProduct(scip, factor));
    373 assert(!SCIPisExprValue(scip, factor));
    374
    375 SCIP_CALL( createExprNode(scip, factor, simplifiedfactor) );
    376
    377 return SCIP_OKAY;
    378}
    379
    380/** merges tomerge into finalchildren
    381 *
    382 * Both, tomerge and finalchildren contain expressions that could be the children of a simplified product
    383 * (except for SP8 and SP10 which are enforced later).
    384 * However, the concatenation of both lists will not in general yield a simplified product expression,
    385 * because SP4, SP5 and SP14 could be violated. So the purpose of this method is to enforce SP4, SP5 and SP14.
    386 * In the process of enforcing SP4, it could happen that SP2 is violated. Since enforcing SP2
    387 * could generate further violations, we remove the affected children from finalchildren
    388 * and include them in unsimplifiedchildren for further processing.
    389 * @note if tomerge has more than one element, then they are the children of a simplified product expression
    390 */
    391static
    393 SCIP* scip, /**< SCIP data structure */
    394 EXPRNODE* tomerge, /**< list to merge */
    395 EXPRNODE** finalchildren, /**< pointer to store the result of merge between tomerge and *finalchildren */
    396 EXPRNODE** unsimplifiedchildren,/**< the list of children that should go to the product expression;
    397 * they are unsimplified when seen as children of a simplified product */
    398 SCIP_Bool* changed, /**< pointer to store if some term actually got simplified */
    399 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    400 void* ownercreatedata /**< data to pass to ownercreate */
    401 )
    402{
    403 EXPRNODE* tomergenode;
    404 EXPRNODE* current;
    405 EXPRNODE* previous;
    406
    407 if( tomerge == NULL )
    408 return SCIP_OKAY;
    409
    410 if( *finalchildren == NULL )
    411 {
    412 *finalchildren = tomerge;
    413 return SCIP_OKAY;
    414 }
    415
    416 tomergenode = tomerge;
    417 current = *finalchildren;
    418 previous = NULL;
    419
    420 while( tomergenode != NULL && current != NULL )
    421 {
    422 int compareres;
    423 EXPRNODE* aux;
    424 SCIP_EXPR* base1;
    425 SCIP_EXPR* base2;
    426 SCIP_Real expo1;
    427 SCIP_Real expo2;
    428 SCIP_Bool issignpower1;
    429 SCIP_Bool issignpower2;
    430
    431 /* assert invariants */
    432 assert(!SCIPisExprValue(scip, tomergenode->expr));
    433 assert(!SCIPisExprValue(scip, current->expr));
    434 assert(previous == NULL || previous->next == current);
    435
    436 /* we are going to multiply the two exprs: current and tomergenode
    437 * we first check if they are both exponentials
    438 * if so, we multiply them
    439 * otherwise, we interpret them as base^exponent
    440 * the base of an expr is the expr itself
    441 * if type(expr) != pow, otherwise it is the child of pow
    442 */
    443
    444 /* if both are exponentials, create a new exponential with the sum of their children */
    445 if( SCIPisExprExp(scip, current->expr) && SCIPisExprExp(scip, tomergenode->expr) )
    446 {
    447 SCIP_EXPR* sum;
    448 SCIP_EXPR* simplifiedsum;
    449 SCIP_EXPR* expexpr;
    450 SCIP_EXPR* simplifiedexp;
    451
    452 /* inform that expressions changed */
    453 *changed = TRUE;
    454
    455 /* create sum */
    456 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, SCIPexprGetChildren(current->expr), NULL, 0.0, ownercreate, ownercreatedata) );
    457 SCIP_CALL( SCIPappendExprSumExpr(scip, sum, SCIPexprGetChildren(tomergenode->expr)[0], 1.0) );
    458
    459 /* simplify sum */
    460 SCIP_CALL( SCIPcallExprSimplify(scip, sum, &simplifiedsum, ownercreate, ownercreatedata) );
    462
    463 /* create exponential */
    464 SCIP_CALL( SCIPcreateExprExp(scip, &expexpr, simplifiedsum, ownercreate, ownercreatedata) );
    465 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedsum) );
    466
    467 /* simplify exponential */
    468 SCIP_CALL( SCIPcallExprSimplify(scip, expexpr, &simplifiedexp, ownercreate, ownercreatedata) );
    469 SCIP_CALL( SCIPreleaseExpr(scip, &expexpr) );
    470
    471 /* note that simplified exponential might be a product exp(x) * exp(-x + log(y*z)) -> y*z and so it is not a
    472 * valid child of a simplified product; therefore we add it to the unsimplifiedchildren's list
    473 */
    474
    475 /* replace tomergenode's expression with simplifiedexp */
    476 /* TODO: this code repeats below; add new function to avoid duplication */
    477 SCIP_CALL( SCIPreleaseExpr(scip, &tomergenode->expr) );
    478 tomergenode->expr = simplifiedexp;
    479
    480 /* move tomergenode to unsimplifiedchildren */
    481 aux = tomergenode;
    482 tomergenode = tomergenode->next;
    483 insertFirstList(aux, unsimplifiedchildren);
    484
    485 /* remove current */
    486 if( current == *finalchildren )
    487 {
    488 assert(previous == NULL);
    489 aux = listPopFirst(finalchildren);
    490 assert(aux == current);
    491 current = *finalchildren;
    492 }
    493 else
    494 {
    495 assert(previous != NULL);
    496 aux = current;
    497 current = current->next;
    498 previous->next = current;
    499 }
    500 SCIP_CALL( freeExprNode(scip, &aux) );
    501
    502 continue;
    503 }
    504
    505 /* they were not exponentials, so collect bases and exponents */
    506 if( SCIPisExprPower(scip, current->expr) )
    507 {
    508 base1 = SCIPexprGetChildren(current->expr)[0];
    509 expo1 = SCIPgetExponentExprPow(current->expr);
    510 issignpower1 = FALSE;
    511 }
    512 else if( SCIPisExprSignpower(scip, current->expr) )
    513 {
    514 base1 = SCIPexprGetChildren(current->expr)[0];
    515 expo1 = SCIPgetExponentExprPow(current->expr);
    516 issignpower1 = TRUE;
    517 }
    518 else
    519 {
    520 base1 = current->expr;
    521 expo1 = 1.0;
    522 issignpower1 = FALSE;
    523 }
    524 if( SCIPisExprPower(scip, tomergenode->expr) )
    525 {
    526 base2 = SCIPexprGetChildren(tomergenode->expr)[0];
    527 expo2 = SCIPgetExponentExprPow(tomergenode->expr);
    528 issignpower2 = FALSE;
    529 }
    530 else if( SCIPisExprSignpower(scip, tomergenode->expr) )
    531 {
    532 base2 = SCIPexprGetChildren(tomergenode->expr)[0];
    533 expo2 = SCIPgetExponentExprPow(tomergenode->expr);
    534 issignpower2 = TRUE;
    535 }
    536 else
    537 {
    538 base2 = tomergenode->expr;
    539 expo2 = 1.0;
    540 issignpower2 = FALSE;
    541 }
    542
    543 if( SCIPcompareExpr(scip, base1, base2) == 0 )
    544 {
    545 /* the bases are the same, so we should try to merge the multiplication of the powers */
    546 SCIP_EXPR* power = NULL;
    547
    548 if( !issignpower1 && !issignpower2 )
    549 {
    550 /* and both are normal power, then add to unsimplifiedchildren the resulting expr of simplify(base^(expo1 + expo2)) */
    551#ifdef SCIP_DISABLED_CODE
    552 /* TODO we should not loose the implicit base >= 0 constraint, if there is one, but then we should look at bounds on base; simplify currently doesn't */
    553 /*
    554 * unless expo1 or expo2 are fractional but expo1+expo2 is not fractional, then we better keep the original
    555 * the reason for that is that x^fractional implies a constraint x >= 0
    556 */
    557 if( (EPSISINT(expo1, 0.0) && EPSISINT(expo2, 0.0)) || !EPSISINT(expo1+expo2, 0.0) ) /*lint !e835*/
    558#endif
    559 {
    560 SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    561 }
    562 }
    563 else if( issignpower1 ^ issignpower2 )
    564 {
    565 /* exactly one is signpower: sign(x) |x|^expo1 x^expo2 = sign(x)^(1+expo2) |x|^(expo1+expo2), with x = base */
    566 if( EPSISINT(expo2, 0.0) ) /*lint !e835*/
    567 {
    568 if( (int)expo2 % 2 == 0 )
    569 {
    570 /* if expo2 is even, then sign(x)^(1+expo2) = sign(x), so we have signpower: sign(x) |x|^(expo1+expo2)
    571 * TODO: we can remove this case distinction once the simplification of power expressions tranform
    572 * |expr|^even -> expr^even, since the call to SCIPcallExprSimplify(scip, conshdlr, power,
    573 * &simplifiedpower) below will take care of this.
    574 */
    575 SCIP_CALL( SCIPcreateExprSignpower(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    576 }
    577 else
    578 {
    579 /* if expo2 is odd, then sign(x)^(1+expo2) = 1, so we have |x|^(expo1+expo2) */
    580 SCIP_EXPR* absbase;
    581
    582 SCIP_CALL( SCIPcreateExprAbs(scip, &absbase, base1, ownercreate, ownercreatedata) );
    583 SCIP_CALL( SCIPcreateExprPow(scip, &power, absbase, expo1 + expo2, ownercreate, ownercreatedata) );
    584 SCIP_CALL( SCIPreleaseExpr(scip, &absbase) );
    585 }
    586 }
    587 else if( !EPSISINT(expo1+expo2, 0.0) ) /*lint !e835*/
    588 {
    589 /* if expo2 is fractional and expo1+expo2 is fractional, then we need x >= 0, so we can use x^(expo1+expo2) */
    590 SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    591 }
    592 /* else: expo2 is fractional but expo1+expo2 is integral, then we better do not do anything for now
    593 * (leave power at NULL)
    594 */
    595 }
    596 else
    597 {
    598 /* if both are signpower, then we have |base|^(expo1+expo2)
    599 * if expo1+expo2 is even, then we can change this to base^(expo1+expo2)
    600 */
    601 if( EPSISINT(expo1+expo2, 0.0) && (int)(expo1+expo2)%2 == 0 ) /*lint !e835*/
    602 {
    603 SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    604 }
    605 else
    606 {
    607 SCIP_EXPR* absbase;
    608
    609 SCIP_CALL( SCIPcreateExprAbs(scip, &absbase, base1, ownercreate, ownercreatedata) );
    610 SCIP_CALL( SCIPcreateExprPow(scip, &power, absbase, expo1 + expo2, ownercreate, ownercreatedata) );
    611 SCIP_CALL( SCIPreleaseExpr(scip, &absbase) );
    612 }
    613 }
    614
    615 if( power != NULL )
    616 {
    617 /* we have created a new power: simplify again and continue */
    618 SCIP_EXPR* simplifiedpower;
    619
    620 /* call simplifyPow or simplifySignpower */
    621 SCIP_CALL( SCIPcallExprSimplify(scip, power, &simplifiedpower, ownercreate, ownercreatedata) );
    622 SCIP_CALL( SCIPreleaseExpr(scip, &power) );
    623
    624 /* replace tomergenode's expression with simplifiedpower */
    625 SCIP_CALL( SCIPreleaseExpr(scip, &tomergenode->expr) );
    626 tomergenode->expr = simplifiedpower;
    627
    628 *changed = TRUE;
    629
    630 /* move tomergenode to unsimplifiedchildren */
    631 aux = tomergenode;
    632 tomergenode = tomergenode->next;
    633 insertFirstList(aux, unsimplifiedchildren);
    634
    635 /* remove current */
    636 if( current == *finalchildren )
    637 {
    638 assert(previous == NULL);
    639 aux = listPopFirst(finalchildren);
    640 assert(aux == current);
    641 current = *finalchildren;
    642 }
    643 else
    644 {
    645 assert(previous != NULL);
    646 aux = current;
    647 current = current->next;
    648 previous->next = current;
    649 }
    650 SCIP_CALL( freeExprNode(scip, &aux) );
    651
    652 continue;
    653 }
    654 }
    655
    656 /* bases are not the same, or we do not want to merge them
    657 * then expressions cannot be the same
    658 * therefore we need to insert tomergenode in finalchildren
    659 * for this, we need to take care of the order
    660 */
    661 compareres = SCIPcompareExpr(scip, current->expr, tomergenode->expr);
    662 if( compareres == -1 )
    663 {
    664 /* current < tomergenode => move current */
    665 previous = current;
    666 current = current->next;
    667 }
    668 else
    669 {
    670 *changed = TRUE;
    671 assert(compareres == 1);
    672
    673 /* insert: if current is the first node, then insert at beginning; otherwise, insert between previous and current */
    674 if( current == *finalchildren )
    675 {
    676 assert(previous == NULL);
    677 aux = tomergenode;
    678 tomergenode = tomergenode->next;
    679 insertFirstList(aux, finalchildren);
    680 previous = *finalchildren;
    681 }
    682 else
    683 {
    684 assert(previous != NULL);
    685 /* extract */
    686 aux = tomergenode;
    687 tomergenode = tomergenode->next;
    688 /* insert */
    689 previous->next = aux;
    690 aux->next = current;
    691 previous = aux;
    692 }
    693 }
    694 }
    695
    696 /* if all nodes of tomerge were merged, we are done */
    697 if( tomergenode == NULL )
    698 return SCIP_OKAY;
    699
    700 assert(current == NULL);
    701
    702 /* if all nodes of finalchildren were cancelled by nodes of tomerge (i.e., transfered to unsimplifiedchildren),
    703 * then the rest of tomerge is finalchildren
    704 */
    705 if( *finalchildren == NULL )
    706 {
    707 assert(previous == NULL);
    708 *finalchildren = tomergenode;
    709 return SCIP_OKAY;
    710 }
    711
    712 /* there are still nodes of tomerge unmerged; these nodes are larger than finalchildren, so append at end */
    713 assert(previous != NULL && previous->next == NULL);
    714 previous->next = tomergenode;
    715
    716 return SCIP_OKAY;
    717}
    718
    719/** simplifies the given (simplified) exprs so that they can be factors of a simplified product
    720 *
    721 * in particular, it will sort and multiply factors whose product leads to new expressions
    722 */
    723static
    725 SCIP* scip, /**< SCIP data structure */
    726 SCIP_EXPR** exprs, /**< factors to be simplified */
    727 int nexprs, /**< number of factors */
    728 SCIP_Real* simplifiedcoef, /**< buffer to store coefficient of PI exprs; needs to be initialized */
    729 EXPRNODE** finalchildren, /**< expr node list to store the simplified factors */
    730 SCIP_Bool* changed, /**< buffer to store whether some factor changed */
    731 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    732 void* ownercreatedata /**< data to pass to ownercreate */
    733 )
    734{
    735 EXPRNODE* unsimplifiedchildren;
    736
    737 /* set up list of current children (when looking at each of them individually, they are simplified, but as
    738 * children of a product expression they might be unsimplified)
    739 */
    740 unsimplifiedchildren = NULL;
    741 SCIP_CALL( createExprlistFromExprs(scip, exprs, nexprs, &unsimplifiedchildren) );
    742
    743 *changed = FALSE;
    744
    745 /* while there are still children to process */
    746 *finalchildren = NULL;
    747 while( unsimplifiedchildren != NULL )
    748 {
    749 EXPRNODE* tomerge;
    750 EXPRNODE* first;
    751
    752 first = listPopFirst(&unsimplifiedchildren);
    753 assert(first != NULL);
    754
    755#ifdef SIMPLIFY_DEBUG
    756 debugSimplify("simplifying factor:\n");
    757 SCIP_CALL( SCIPprintExpr(scip, first->expr, NULL) );
    758 SCIPinfoMessage(scip, NULL, "\n");
    759#endif
    760
    761 /* enforces SP2, SP7 and SP13 */
    762 tomerge = NULL;
    763 SCIP_CALL( simplifyFactor(scip, first->expr, simplifiedcoef, &tomerge, changed) );
    764
    765 /* enforces SP4 and SP5 note: merge frees (or uses) the nodes of the tomerge list */
    766 SCIP_CALL( mergeProductExprlist(scip, tomerge, finalchildren, &unsimplifiedchildren, changed, ownercreate, ownercreatedata) );
    767
    768 /* free first */
    769 SCIP_CALL( freeExprlist(scip, &first) );
    770
    771 /* if the simplified coefficient is 0, we can return value 0 */
    772 if( *simplifiedcoef == 0.0 )
    773 {
    774 *changed = TRUE;
    775 SCIP_CALL( freeExprlist(scip, finalchildren) );
    776 SCIP_CALL( freeExprlist(scip, &unsimplifiedchildren) );
    777 assert(*finalchildren == NULL);
    778 break;
    779 }
    780 }
    781 return SCIP_OKAY;
    782}
    783
    784/* make sure product has at least two children
    785 * - if it is empty; return value
    786 * - if it has one child and coef = 1; return child
    787 * - if it has one child and coef != 1; return (sum 0 coef expr)
    788 */
    789static
    791 SCIP* scip, /**< SCIP data structure */
    792 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    793 EXPRNODE* finalchildren, /**< factors of simplified product */
    794 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    795 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    796 void* ownercreatedata /**< data to pass to ownercreate */
    797 )
    798{
    799 /* empty list --> return value */
    800 if( finalchildren == NULL )
    801 {
    802 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, simplifiedcoef, ownercreate, ownercreatedata) );
    803 return SCIP_OKAY;
    804 }
    805
    806 /* one child and coef equal to 1 --> return child */
    807 if( finalchildren->next == NULL && simplifiedcoef == 1.0 )
    808 {
    809 *simplifiedexpr = finalchildren->expr;
    810 SCIPcaptureExpr(*simplifiedexpr);
    811 return SCIP_OKAY;
    812 }
    813
    814 /* one child and coef different from 1 --> return (sum 0 coef child) */
    815 if( finalchildren->next == NULL )
    816 {
    817 SCIP_EXPR* sum;
    818
    819 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, &(finalchildren->expr), &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
    820
    821 /* simplifying here is necessary, the product could have sums as children e.g., (prod 2 (sum 1 <x>))
    822 * -> (sum 0 2 (sum 1 <x>)) and that needs to be simplified to (sum 0 2 <x>)
    823 */
    824 SCIP_CALL( SCIPcallExprSimplify(scip, sum, simplifiedexpr, ownercreate, ownercreatedata) );
    826 return SCIP_OKAY;
    827 }
    828
    829 return SCIP_OKAY;
    830}
    831
    832/** checks if it is entropy expression */
    833static
    835 SCIP* scip, /**< SCIP data structure */
    836 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    837 EXPRNODE* finalchildren, /**< factors of simplified product */
    838 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    839 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    840 void* ownercreatedata /**< data to pass to ownercreate */
    841 )
    842{
    843 SCIP_EXPR* entropicchild = NULL;
    844
    845 if( !(finalchildren != NULL && finalchildren->next != NULL && finalchildren->next->next == NULL) )
    846 return SCIP_OKAY;
    847
    848 /* could be log(expr) * expr, e.g., log(sin(x)) * sin(x) (OR11) */
    849 if( strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(finalchildren->expr)), "log") == 0 )
    850 {
    851 assert(SCIPexprGetNChildren(finalchildren->expr) == 1);
    852 if( 0 == SCIPcompareExpr(scip, SCIPexprGetChildren(finalchildren->expr)[0], finalchildren->next->expr) )
    853 entropicchild = finalchildren->next->expr;
    854 }
    855 /* could be expr * log(expr), e.g., (1 + abs(x)) log(1 + abs(x)) (OR11) */
    856 else if( strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(finalchildren->next->expr)), "log") == 0 )
    857 {
    858 assert(SCIPexprGetNChildren(finalchildren->next->expr) == 1);
    859 if( 0 == SCIPcompareExpr(scip, SCIPexprGetChildren(finalchildren->next->expr)[0], finalchildren->expr) )
    860 entropicchild = finalchildren->expr;
    861 }
    862
    863 /* success --> replace finalchildren by entropy expression */
    864 if( entropicchild != NULL )
    865 {
    866 SCIP_EXPR* entropy;
    867
    868 simplifiedcoef *= -1.0;
    869
    870 SCIP_CALL( SCIPcreateExprEntropy(scip, &entropy, entropicchild, ownercreate, ownercreatedata) );
    871
    872 /* enforces SP8: if simplifiedcoef != 1.0, transform it into a sum with the (simplified) entropy as child */
    873 if( simplifiedcoef != 1.0 )
    874 {
    875 SCIP_CALL( SCIPcreateExprSum(scip, simplifiedexpr, 1, &entropy, &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
    876 SCIP_CALL( SCIPreleaseExpr(scip, &entropy) );
    877 }
    878 else
    879 *simplifiedexpr = entropy;
    880 }
    881
    882 return SCIP_OKAY;
    883}
    884
    885/* expands product of two sums or one sum and another expression
    886 * -) two sums: (prod (sum c1 s1 ... sn) (sum c2 t1 ... tm)
    887 * Builds a sum representing the expansion, where all of its children are simplified, and then simplify the sum
    888 * - constant != 0 --> c1 ti or c2 * sj is simplified (ti, sj are not sums, because they are children of a simplified sum)
    889 * - sj * ti may be not be simplified, so put them in a product list and simplify them from there
    890 * -) one sum: (prod factor (sum c s1 ... sn))
    891 * - c != 0 --> c * factor is simplified (i.e. factor is not sum!)
    892 * - factor * si may be not be simplified, so put them in a product list and simplify them from there
    893 */
    894static
    896 SCIP* scip, /**< SCIP data structure */
    897 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    898 EXPRNODE* finalchildren, /**< factors of simplified product */
    899 SCIP_Bool expandalways, /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    900 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    901 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    902 void* ownercreatedata /**< data to pass to ownercreate */
    903 )
    904{
    905 /* we need only two children */
    906 if( ! (finalchildren != NULL && finalchildren->next != NULL && finalchildren->next->next == NULL) )
    907 return SCIP_OKAY;
    908
    909 /* handle both sums case */
    910 if( SCIPisExprSum(scip, finalchildren->expr) && SCIPisExprSum(scip, finalchildren->next->expr) )
    911 {
    912 SCIP_EXPR* expanded = NULL;
    913 SCIP_Real c1 = SCIPgetConstantExprSum(finalchildren->expr);
    914 SCIP_Real c2 = SCIPgetConstantExprSum(finalchildren->next->expr);
    915 int nchildren1 = SCIPexprGetNChildren(finalchildren->expr);
    916 int nchildren2 = SCIPexprGetNChildren(finalchildren->next->expr);
    917 int j;
    918 int k;
    919
    920#ifdef SIMPLIFY_DEBUG
    921 debugSimplify("Multiplying sum1 * sum2\n");
    922 debugSimplify("sum1: \n");
    923 SCIP_CALL( SCIPprintExpr(scip, finalchildren->expr, NULL) );
    924 SCIPinfoMessage(scip, NULL, "\n");
    925 debugSimplify("sum2: \n");
    926 SCIP_CALL( SCIPprintExpr(scip, finalchildren->next->expr, NULL) );
    927 SCIPinfoMessage(scip, NULL, "\n");
    928#endif
    929 SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 0, NULL, NULL, c1 * c2 * simplifiedcoef, ownercreate, ownercreatedata) );
    930
    931 /* multiply c1 * sum2 */
    932 if( c1 != 0.0 )
    933 {
    934 int i;
    935
    936 for( i = 0; i < nchildren2; ++i )
    937 {
    938 SCIP_EXPR* term;
    939
    940 term = SCIPexprGetChildren(finalchildren->next->expr)[i];
    941 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, SCIPgetCoefsExprSum(finalchildren->next->expr)[i] * c1 * simplifiedcoef) );
    942 /* we are just re-using a child here, so do not release term! */
    943#ifdef SIMPLIFY_DEBUG
    944 debugSimplify("Multiplying %f * summand2_i\n", c1);
    945 debugSimplify("summand2_i: \n");
    946 SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
    947 SCIPinfoMessage(scip, NULL, "\n");
    948#endif
    949 }
    950 }
    951 /* multiply c2 * sum1 */
    952 if( c2 != 0.0 )
    953 {
    954 int i;
    955
    956 for( i = 0; i < nchildren1; ++i )
    957 {
    958 SCIP_EXPR* term;
    959
    960 term = SCIPexprGetChildren(finalchildren->expr)[i];
    961 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, SCIPgetCoefsExprSum(finalchildren->expr)[i] * c2 * simplifiedcoef) );
    962 /* we are just re-using a child here, so do not release term! */
    963#ifdef SIMPLIFY_DEBUG
    964 debugSimplify("Multiplying summand1_i * %f\n", c2);
    965 debugSimplify("summand1_i: \n");
    966 SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
    967 SCIPinfoMessage(scip, NULL, "\n");
    968#endif
    969 }
    970 }
    971 /* multiply sum1 * sum2 without constants */
    972 for( j = 0; j < nchildren1; ++j )
    973 {
    974 SCIP_EXPR* factors[2];
    975 SCIP_Real coef1;
    976
    977 coef1 = SCIPgetCoefsExprSum(finalchildren->expr)[j];
    978 factors[0] = SCIPexprGetChildren(finalchildren->expr)[j];
    979 for( k = 0; k < nchildren2; ++k )
    980 {
    981 EXPRNODE* finalfactors;
    982 SCIP_Real factorscoef;
    983 SCIP_Real coef2;
    984 SCIP_EXPR* term = NULL;
    985 SCIP_Bool dummy;
    986
    987 coef2 = SCIPgetCoefsExprSum(finalchildren->next->expr)[k];
    988 factors[1] = SCIPexprGetChildren(finalchildren->next->expr)[k];
    989
    990#ifdef SIMPLIFY_DEBUG
    991 debugSimplify("multiplying %g expr1 * %g expr2\n", coef1, coef2);
    992 debugSimplify("expr1:\n");
    993 SCIP_CALL( SCIPprintExpr(scip, factors[0], NULL) );
    994 SCIPinfoMessage(scip, NULL, "\n");
    995 debugSimplify("expr2\n");
    996 SCIP_CALL( SCIPprintExpr(scip, factors[1], NULL) );
    997 SCIPinfoMessage(scip, NULL, "\n");
    998#endif
    999
    1000 factorscoef = coef1 * coef2;
    1001 SCIP_CALL( simplifyMultiplyChildren(scip, factors, 2, &factorscoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1002 assert(factorscoef != 0.0);
    1003
    1004#ifdef SIMPLIFY_DEBUG
    1005 {
    1006 EXPRNODE* node;
    1007 int i;
    1008
    1009 debugSimplify("Building product from simplified factors\n");
    1010 node = finalfactors;
    1011 i = 0;
    1012 while( node != NULL )
    1013 {
    1014 debugSimplify("factor %d (nuses %d):\n", i, SCIPexprGetNUses(node->expr));
    1015 SCIP_CALL( SCIPprintExpr(scip, node->expr, NULL) );
    1016 SCIPinfoMessage(scip, NULL, "\n");
    1017 node = node->next;
    1018 i++;
    1019 }
    1020 }
    1021#endif
    1022
    1023 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, expandalways, TRUE, &term, ownercreate, ownercreatedata) );
    1024 assert(finalfactors == NULL);
    1025 assert(term != NULL);
    1026
    1027#ifdef SIMPLIFY_DEBUG
    1028 debugSimplify("%g expr1 * %g expr2 = %g * product\n", coef1, coef2, coef1 * coef2);
    1029 debugSimplify("product: (nused %d)\n", SCIPexprGetNUses(term));
    1030 SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
    1031 SCIPinfoMessage(scip, NULL, "\n");
    1032#endif
    1033
    1034 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, factorscoef * simplifiedcoef) );
    1035
    1036 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1037 }
    1038 }
    1039
    1040 /* simplify the sum */
    1041 SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
    1042 SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
    1043
    1044 return SCIP_OKAY;
    1045 }
    1046
    1047 /* handle one sum case */
    1048 if( SCIPisExprSum(scip, finalchildren->expr) || SCIPisExprSum(scip, finalchildren->next->expr) )
    1049 {
    1050 SCIP_EXPR* expanded = NULL;
    1051 SCIP_EXPR* factors[2];
    1052 SCIP_EXPR* sum = NULL;
    1053 SCIP_Real constant;
    1054 int nchildren;
    1055 int j;
    1056
    1057 if( SCIPisExprSum(scip, finalchildren->expr) )
    1058 {
    1059 assert(!SCIPisExprSum(scip, finalchildren->next->expr));
    1060 sum = finalchildren->expr;
    1061 factors[0] = finalchildren->next->expr;
    1062 }
    1063 else
    1064 {
    1065 assert(!SCIPisExprSum(scip, finalchildren->expr));
    1066 sum = finalchildren->next->expr;
    1067 factors[0] = finalchildren->expr;
    1068 }
    1069 constant = simplifiedcoef * SCIPgetConstantExprSum(sum);
    1070 nchildren = SCIPexprGetNChildren(sum);
    1071
    1072 SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 1, &factors[0], &constant, 0.0, ownercreate, ownercreatedata) );
    1073 /* we are just re-using a child here, so do not release factor! */
    1074
    1075 for( j = 0; j < nchildren; ++j )
    1076 {
    1077 SCIP_Real coef;
    1078 SCIP_Real termcoef;
    1079 SCIP_Bool dummy;
    1080 EXPRNODE* finalfactors;
    1081 SCIP_EXPR* term = NULL;
    1082
    1083 coef = SCIPgetCoefsExprSum(sum)[j];
    1084 factors[1] = SCIPexprGetChildren(sum)[j];
    1085
    1086 termcoef = coef;
    1087 SCIP_CALL( simplifyMultiplyChildren(scip, factors, 2, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1088 assert(termcoef != 0.0);
    1089
    1090 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, expandalways, TRUE, &term, ownercreate, ownercreatedata) );
    1091 assert(finalfactors == NULL);
    1092 assert(term != NULL);
    1093
    1094 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef) );
    1095 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1096 }
    1097
    1098 /* simplify the sum */
    1099 SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
    1100 SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
    1101 }
    1102
    1103 return SCIP_OKAY;
    1104}
    1105
    1106/* expands product of one sum and other expressions
    1107 * -) (prod factor ... factor (sum c s1 ... sn) factor ... factor )
    1108 * - c != 0 --> c * factor is simplified (i.e. factor is not sum!)
    1109 * - factor ... factor * si may be not be simplified, so put them in a product list and simplify them from there
    1110 */
    1111static
    1113 SCIP* scip, /**< SCIP data structure */
    1114 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * prod simplifiedfactors */
    1115 EXPRNODE* finalchildren, /**< factors of simplified product */
    1116 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    1117 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1118 void* ownercreatedata /**< data to pass to ownercreate */
    1119 )
    1120{
    1121 EXPRNODE* sum_node = NULL;
    1122 EXPRNODE* n;
    1123 int nfactors = 0;
    1124 SCIP_EXPR** factors;
    1125 int nchildren;
    1126 SCIP_EXPR* expanded;
    1127 int j;
    1128
    1129 /* check whether there is exactly one sum, calc number of factors */
    1130 for( n = finalchildren; n != NULL; n = n->next )
    1131 {
    1132 if( SCIPisExprSum(scip, n->expr) )
    1133 {
    1134 if( sum_node == NULL )
    1135 sum_node = n;
    1136 else
    1137 return SCIP_OKAY; /* more than one sum */
    1138 }
    1139 else
    1140 {
    1141 ++nfactors;
    1142 }
    1143 }
    1144 if( sum_node == NULL || nfactors == 0 ) /* no sum or no other factors */
    1145 return SCIP_OKAY;
    1146
    1147 /* collect exprs of all factors other than the sum */
    1148 SCIP_CALL( SCIPallocBufferArray(scip, &factors, nfactors + 1) );
    1149 for( n = finalchildren, j = 0; n != NULL; n = n->next )
    1150 if( n != sum_node )
    1151 factors[j++] = n->expr;
    1152
    1153 /* build new sum expression */
    1154 nchildren = SCIPexprGetNChildren(sum_node->expr);
    1155 SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 0, NULL, NULL, 0.0, ownercreate, ownercreatedata) );
    1156
    1157 /* handle constant-from-sum * factors */
    1158 if( SCIPgetConstantExprSum(sum_node->expr) != 0.0 )
    1159 {
    1160 if( nfactors == 1 )
    1161 {
    1162 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, factors[0], simplifiedcoef * SCIPgetConstantExprSum(sum_node->expr)) );
    1163 }
    1164 else
    1165 {
    1166 SCIP_Real termcoef = 1.0;
    1167 SCIP_Bool dummy;
    1168 EXPRNODE* finalfactors;
    1169 SCIP_EXPR* term = NULL;
    1170
    1171 SCIP_CALL( simplifyMultiplyChildren(scip, factors, nfactors, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1172 assert(termcoef != 0.0);
    1173
    1174 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, TRUE, TRUE, &term, ownercreate, ownercreatedata) );
    1175 assert(finalfactors == NULL);
    1176 assert(term != NULL);
    1177
    1178 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef * SCIPgetConstantExprSum(sum_node->expr)) );
    1179 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1180 }
    1181 }
    1182
    1183 for( j = 0; j < nchildren; ++j )
    1184 {
    1185 SCIP_Real coef;
    1186 SCIP_Real termcoef;
    1187 SCIP_Bool dummy;
    1188 EXPRNODE* finalfactors;
    1189 SCIP_EXPR* term = NULL;
    1190
    1191 coef = SCIPgetCoefsExprSum(sum_node->expr)[j];
    1192 factors[nfactors] = SCIPexprGetChildren(sum_node->expr)[j];
    1193
    1194 termcoef = coef;
    1195 SCIP_CALL( simplifyMultiplyChildren(scip, factors, nfactors + 1, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1196 assert(termcoef != 0.0);
    1197
    1198 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, TRUE, TRUE, &term, ownercreate, ownercreatedata) );
    1199 assert(finalfactors == NULL);
    1200 assert(term != NULL);
    1201
    1202 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef) );
    1203 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1204 }
    1205
    1206 /* simplify the sum */
    1207 SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
    1208 SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
    1209
    1210 SCIPfreeBufferArray(scip, &factors);
    1211
    1212 return SCIP_OKAY;
    1213}
    1214
    1215/** builds a simplified product from simplifiedfactors
    1216 *
    1217 * @note this function also releases simplifiedfactors
    1218 */
    1219static
    1221 SCIP* scip, /**< SCIP data structure */
    1222 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    1223 EXPRNODE** simplifiedfactors, /**< factors of simplified product */
    1224 SCIP_Bool expandalways, /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    1225 SCIP_Bool changed, /**< indicates whether some of the simplified factors was changed */
    1226 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    1227 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1228 void* ownercreatedata /**< data to pass to ownercreate */
    1229 )
    1230{
    1231 EXPRNODE* finalchildren = *simplifiedfactors;
    1232
    1233 /* build product expression from finalchildren and post-simplify */
    1234 debugSimplify("[simplifyProduct] finalchildren has length %d\n", listLength(finalchildren));
    1235
    1236 *simplifiedexpr = NULL;
    1237
    1238 SCIP_CALL( enforceSP11(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
    1239 if( *simplifiedexpr != NULL )
    1240 goto CLEANUP;
    1241
    1242 SCIP_CALL( enforceSP12(scip, simplifiedcoef, *simplifiedfactors, expandalways, simplifiedexpr, ownercreate, ownercreatedata) );
    1243 if( *simplifiedexpr != NULL )
    1244 goto CLEANUP;
    1245
    1246 if( expandalways )
    1247 {
    1248 SCIP_CALL( enforceSP12b(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
    1249 if( *simplifiedexpr != NULL )
    1250 goto CLEANUP;
    1251 }
    1252
    1253 SCIP_CALL( enforceSP10(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
    1254 if( *simplifiedexpr != NULL )
    1255 goto CLEANUP;
    1256
    1257 /* enforces SP8: if simplifiedcoef != 1.0, transform it into a sum with the (simplified) product as child */
    1258 if( simplifiedcoef != 1.0 )
    1259 {
    1260 SCIP_EXPR* aux;
    1261 SCIP_EXPR* sum;
    1262
    1263 /* create sum */
    1264 SCIP_CALL( createExprProductFromExprlist(scip, finalchildren, 1.0, &aux, ownercreate, ownercreatedata) );
    1265 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, &aux, &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
    1266 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1267
    1268 /* simplify sum */
    1269 SCIP_CALL( SCIPcallExprSimplify(scip, sum, simplifiedexpr, ownercreate, ownercreatedata) );
    1270 SCIP_CALL( SCIPreleaseExpr(scip, &sum) );
    1271
    1272 goto CLEANUP;
    1273 }
    1274
    1275 /* build product expression from list */
    1276 if( changed )
    1277 {
    1278 SCIP_CALL( createExprProductFromExprlist(scip, finalchildren, simplifiedcoef, simplifiedexpr, ownercreate, ownercreatedata) );
    1279 goto CLEANUP;
    1280 }
    1281
    1282CLEANUP:
    1283
    1284 SCIP_CALL( freeExprlist(scip, simplifiedfactors) );
    1285 return SCIP_OKAY;
    1286}
    1287
    1288/** computes an estimator for a product as a vertex polyhedral function
    1289 *
    1290 * Since the product is multilinear, its convex and concave envelopes are piecewise linear.
    1291 */
    1292static
    1294 SCIP* scip, /**< SCIP data structure */
    1295 SCIP_CONSHDLR* conshdlr, /**< nonlinear constraint handler */
    1296 int nfactors, /**< number of factors */
    1297 SCIP_INTERVAL* bounds, /**< bound for each factor */
    1298 SCIP_Real constantfactor, /**< another constant factor */
    1299 SCIP_Real* refpoint, /**< reference point where to estimate, or NULL if called from initestimates */
    1300 SCIP_Bool overestimate, /**< should estimator overestimate expr (TRUE) or underestimate (FALSE) */
    1301 SCIP_Real targetvalue, /**< no need to compute facet if value in xstar would be worse than target value */
    1302 SCIP_Real* coefs, /**< array to store cut coefficients */
    1303 SCIP_Real* constant, /**< pointer to store cut constant */
    1304 SCIP_Bool* success /**< pointer to store whether estimation was successful */
    1305 )
    1306{
    1307 SCIP_Real* box;
    1308 SCIP_Real* xstar;
    1309 int nfixed;
    1310 int i;
    1311
    1312 assert(conshdlr != NULL);
    1313 assert(nfactors > 0);
    1314 assert(bounds != NULL);
    1315 assert(constantfactor != 0.0);
    1316 assert(coefs != NULL);
    1317 assert(constant != NULL);
    1318 assert(success != NULL);
    1319
    1320 *success = FALSE;
    1321
    1322 /* assemble box, check for unbounded variables, assemble xstar */
    1323 SCIP_CALL( SCIPallocBufferArray(scip, &box, 2*nfactors) );
    1324 SCIP_CALL( SCIPallocBufferArray(scip, &xstar, nfactors) );
    1325 for( i = 0, nfixed = 0; i < nfactors; ++i )
    1326 {
    1327 assert(!SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, bounds[i]));
    1328
    1329 if( SCIPisInfinity(scip, -bounds[i].inf) || SCIPisInfinity(scip, bounds[i].sup) )
    1330 {
    1331 SCIPdebugMsg(scip, "a factor is unbounded, no cut is possible\n");
    1332 goto CLEANUP;
    1333 }
    1334
    1335 box[2*i] = bounds[i].inf;
    1336 box[2*i+1] = bounds[i].sup;
    1337
    1338 xstar[i] = refpoint != NULL ? refpoint[i] : 0.5 * (box[2*i] + box[2*i+1]);
    1339
    1340 if( SCIPisRelEQ(scip, box[2*i], box[2*i+1]) )
    1341 ++nfixed;
    1342 }
    1343
    1344 if( nfixed < nfactors && nfactors - nfixed <= SCIP_MAXVERTEXPOLYDIM )
    1345 {
    1347 overestimate, prodfunction, &constantfactor, xstar, box, nfactors, targetvalue, success, coefs, constant) );
    1348 }
    1349
    1350CLEANUP:
    1351 SCIPfreeBufferArray(scip, &xstar);
    1353
    1354 return SCIP_OKAY;
    1355}
    1356
    1357/*
    1358 * Callback methods of expression handler
    1359 */
    1360
    1361/** simplifies a product expression
    1362 *
    1363 * Summary: we first build a list of expressions (called finalchildren) which will be the children of the simplified product
    1364 * and then we process this list in order to enforce SP8 and SP10.
    1365 *
    1366 * Description: In order to build finalchildren, we first build a list of unsimplified children (called unsimplifiedchildren)
    1367 * with the children of the product. Each node of the list is manipulated (see simplifyFactor) in order to satisfy
    1368 * SP2 and SP7 as follows:
    1369 * - SP7: if the node's expression is a value, multiply the value to the products's coef
    1370 * - SP2: if the node's expression is a product, then build a list with the child's children
    1371 *
    1372 * Then, we merge the built list (or the simplified node) into finalchildren. While merging, nodes from finalchildren
    1373 * can go back to unsimplifiedchildren for further processing (see mergeProductExprlist() for more details).
    1374 * After building finalchildren, we create the simplified product out of it, taking care that SP8 and SP10 are satisfied
    1375 */
    1376static
    1378{ /*lint --e{715}*/
    1379 EXPRNODE* finalchildren;
    1380 SCIP_Real simplifiedcoef;
    1381 SCIP_Bool changed;
    1382
    1383 assert(expr != NULL);
    1384 assert(simplifiedexpr != NULL);
    1385
    1386 simplifiedcoef = SCIPgetCoefExprProduct(expr);
    1387
    1388#ifdef SIMPLIFY_DEBUG
    1389 debugSimplify("Simplifying expr:\n");
    1391 SCIPinfoMessage(scip, NULL, "\n");
    1392 debugSimplify("First multiplying children\n");
    1393#endif
    1394
    1395 /* simplify and multiply factors */
    1397 &finalchildren, &changed, ownercreate, ownercreatedata) );
    1398
    1399#ifdef SIMPLIFY_DEBUG
    1400 {
    1401 EXPRNODE* node;
    1402 int i;
    1403
    1404 debugSimplify("Building product from simplified factors\n");
    1405 node = finalchildren;
    1406 i = 0;
    1407 while( node != NULL )
    1408 {
    1409 debugSimplify("factor %d:\n", i);
    1410 SCIP_CALL( SCIPprintExpr(scip, node->expr, NULL) );
    1411 SCIPinfoMessage(scip, NULL, "\n");
    1412 node = node->next;
    1413 i++;
    1414 }
    1415 }
    1416#endif
    1417
    1418 /* get simplified product from simplified factors in finalchildren */
    1419 SCIP_CALL( buildSimplifiedProduct(scip, simplifiedcoef, &finalchildren, SCIPexprhdlrGetData(SCIPexprGetHdlr(expr))->expandalways, changed, simplifiedexpr, ownercreate,
    1420 ownercreatedata) );
    1421 assert(finalchildren == NULL);
    1422
    1423 if( *simplifiedexpr == NULL )
    1424 {
    1425 *simplifiedexpr = expr;
    1426
    1427 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    1428 SCIPcaptureExpr(*simplifiedexpr);
    1429 }
    1430 assert(*simplifiedexpr != NULL);
    1431
    1432 return SCIP_OKAY;
    1433}
    1434
    1435/** compare two product expressions
    1436 *
    1437 * The order of two product expressions, u and v, is a lexicographical order on the factors.
    1438 *
    1439 * Starting from the *last*, we find the first child where they differ, say, the i-th.
    1440 * Then u < v <=> u_i < v_i.
    1441 * If there is no such children and they have different number of children, then u < v <=> nchildren(u) < nchildren(v).
    1442 * If all children are the same and they have the same number of children, then u < v <=> coeff(u) < coeff(v).
    1443 * Otherwise, they are the same.
    1444 *
    1445 * Note: we are assuming expression are simplified, so within u, we have u_1 < u_2, etc.
    1446 *
    1447 * Example: y * z < x * y * z
    1448 */
    1449static
    1451{ /*lint --e{715}*/
    1452 int compareresult;
    1453 int i;
    1454 int j;
    1455 int nchildren1;
    1456 int nchildren2;
    1457 SCIP_EXPR** children1;
    1458 SCIP_EXPR** children2;
    1459
    1460 nchildren1 = SCIPexprGetNChildren(expr1);
    1461 nchildren2 = SCIPexprGetNChildren(expr2);
    1462 children1 = SCIPexprGetChildren(expr1);
    1463 children2 = SCIPexprGetChildren(expr2);
    1464
    1465 for( i = nchildren1 - 1, j = nchildren2 - 1; i >= 0 && j >= 0; --i, --j )
    1466 {
    1467 compareresult = SCIPcompareExpr(scip, children1[i], children2[j]);
    1468 if( compareresult != 0 )
    1469 return compareresult;
    1470 /* expressions are equal, continue */
    1471 }
    1472
    1473 /* all children of one expression are children of the other expression, use number of children as a tie-breaker */
    1474 if( i < j )
    1475 {
    1476 assert(i == -1);
    1477 /* expr1 has less elements, hence expr1 < expr2 */
    1478 return -1;
    1479 }
    1480 if( i > j )
    1481 {
    1482 assert(j == -1);
    1483 /* expr1 has more elements, hence expr1 > expr2 */
    1484 return 1;
    1485 }
    1486
    1487 /* everything is equal, use coefficient as tie-breaker */
    1488 assert(i == -1 && j == -1);
    1490 return -1;
    1492 return 1;
    1493
    1494 /* they are equal */
    1495 return 0;
    1496}
    1497
    1498/** expression handler copy callback */
    1499static
    1501{ /*lint --e{715}*/
    1503
    1504 return SCIP_OKAY;
    1505}
    1506
    1507/** expression handler free callback */
    1508static
    1510{ /*lint --e{715}*/
    1511 assert(scip != NULL);
    1512 assert(exprhdlr != NULL);
    1513 assert(exprhdlrdata != NULL);
    1514 assert(*exprhdlrdata != NULL);
    1515
    1516 SCIPfreeBlockMemory(scip, exprhdlrdata);
    1517 assert(*exprhdlrdata == NULL);
    1518
    1519 return SCIP_OKAY;
    1520}
    1521
    1522/** expression data copy callback */
    1523static
    1525{ /*lint --e{715}*/
    1526 SCIP_EXPRDATA* sourceexprdata;
    1527
    1528 assert(targetexprdata != NULL);
    1529 assert(sourceexpr != NULL);
    1530
    1531 sourceexprdata = SCIPexprGetData(sourceexpr);
    1532 assert(sourceexprdata != NULL);
    1533
    1534 SCIP_CALL( SCIPduplicateBlockMemory(targetscip, targetexprdata, sourceexprdata) );
    1535
    1536 return SCIP_OKAY;
    1537}
    1538
    1539/** expression data free callback */
    1540static
    1542{ /*lint --e{715}*/
    1543 SCIP_EXPRDATA* exprdata;
    1544
    1545 assert(expr != NULL);
    1546
    1547 exprdata = SCIPexprGetData(expr);
    1548 assert(exprdata != NULL);
    1549
    1550 SCIPfreeBlockMemory(scip, &exprdata);
    1551
    1553
    1554 return SCIP_OKAY;
    1555}
    1556
    1557/** expression print callback */
    1558static
    1560{ /*lint --e{715}*/
    1561 SCIP_EXPRDATA* exprdata;
    1562
    1563 assert(expr != NULL);
    1564
    1565 exprdata = SCIPexprGetData(expr);
    1566 assert(exprdata != NULL);
    1567
    1568 switch( stage )
    1569 {
    1571 {
    1572 /* print opening parenthesis, if necessary */
    1573 if( EXPRHDLR_PRECEDENCE <= parentprecedence )
    1574 {
    1575 SCIPinfoMessage(scip, file, "(");
    1576 }
    1577
    1578 /* print coefficient, if not one */
    1579 if( exprdata->coefficient != 1.0 )
    1580 {
    1581 if( exprdata->coefficient < 0.0 && EXPRHDLR_PRECEDENCE > parentprecedence )
    1582 {
    1583 SCIPinfoMessage(scip, file, "(%.15g)", exprdata->coefficient);
    1584 }
    1585 else
    1586 {
    1587 SCIPinfoMessage(scip, file, "%.15g", exprdata->coefficient);
    1588 }
    1589 }
    1590 break;
    1591 }
    1592
    1594 {
    1595 /* print multiplication sign, if not first factor */
    1596 if( exprdata->coefficient != 1.0 || currentchild > 0 )
    1597 {
    1598 SCIPinfoMessage(scip, file, "*");
    1599 }
    1600 break;
    1601 }
    1602
    1604 {
    1605 break;
    1606 }
    1607
    1609 {
    1610 /* print closing parenthesis, if necessary */
    1611 if( EXPRHDLR_PRECEDENCE <= parentprecedence )
    1612 {
    1613 SCIPinfoMessage(scip, file, ")");
    1614 }
    1615 break;
    1616 }
    1617
    1618 default:
    1619 /* all stages should have been covered above */
    1620 SCIPABORT();
    1621 }
    1622
    1623 return SCIP_OKAY;
    1624}
    1625
    1626/** product hash callback */
    1627static
    1629{ /*lint --e{715}*/
    1630 SCIP_EXPRDATA* exprdata;
    1631 int c;
    1632
    1633 assert(scip != NULL);
    1634 assert(expr != NULL);
    1635 assert(hashkey != NULL);
    1636 assert(childrenhashes != NULL);
    1637
    1638 exprdata = SCIPexprGetData(expr);
    1639 assert(exprdata != NULL);
    1640
    1641 *hashkey = EXPRHDLR_HASHKEY;
    1642 *hashkey ^= SCIPcalcFibHash(exprdata->coefficient);
    1643
    1644 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1645 *hashkey ^= childrenhashes[c];
    1646
    1647 return SCIP_OKAY;
    1648}
    1649
    1650/** expression point evaluation callback */
    1651static
    1653{ /*lint --e{715}*/
    1654 SCIP_EXPRDATA* exprdata;
    1655 SCIP_Real childval;
    1656 int c;
    1657
    1658 assert(expr != NULL);
    1659
    1660 exprdata = SCIPexprGetData(expr);
    1661 assert(exprdata != NULL);
    1662
    1663 *val = exprdata->coefficient;
    1664 for( c = 0; c < SCIPexprGetNChildren(expr) && (*val != 0.0); ++c )
    1665 {
    1667 assert(childval != SCIP_INVALID);
    1668
    1669 *val *= childval;
    1670 }
    1671
    1672 return SCIP_OKAY;
    1673}
    1674
    1675/** derivative evaluation callback computing <gradient, children.dot>
    1676 *
    1677 * If expr is \f$\prod_i x_i\f$, then computes \f$\sum_j \prod_{i\neq j} x_i x^{\text{dot}}_j\f$.
    1678 */
    1679static
    1681{ /*lint --e{715}*/
    1682 int c;
    1683
    1684 assert(expr != NULL);
    1685 assert(dot != NULL);
    1686
    1687 assert(SCIPexprGetData(expr) != NULL);
    1688
    1689 /* TODO add special handling for nchildren == 2 */
    1690
    1691 /**! [SnippetExprFwdiffProduct] */
    1692 *dot = 0.0;
    1693 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1694 {
    1695 SCIP_EXPR* child;
    1696
    1697 child = SCIPexprGetChildren(expr)[c];
    1698
    1699 assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
    1700 assert(SCIPexprGetDot(child) != SCIP_INVALID);
    1701
    1702 if( SCIPexprGetDot(child) == 0.0 )
    1703 continue;
    1704
    1705 if( SCIPexprGetEvalValue(child) != 0.0 )
    1707 else
    1708 {
    1709 SCIP_Real partial;
    1710 int i;
    1711
    1712 partial = SCIPexprGetData(expr)->coefficient;
    1713 for( i = 0; i < SCIPexprGetNChildren(expr) && (partial != 0.0); ++i )
    1714 {
    1715 if( i == c )
    1716 continue;
    1717
    1719 }
    1720 *dot += partial * SCIPexprGetDot(child);
    1721 }
    1722 }
    1723 /**! [SnippetExprFwdiffProduct] */
    1724
    1725 return SCIP_OKAY;
    1726}
    1727
    1728/** expression backward forward derivative evaluation callback
    1729 *
    1730 * Computes \f$\frac{\partial}{\partial \text{childidx}} ( \langle \text{gradient}, \text{children.dot}\rangle )\f$.
    1731 *
    1732 * If expr is \f$\prod_i x_i\f$, and childidx is \f$k\f$ then computes
    1733 * \f$\partial_k \sum_j \prod_{i \neq j} x_i x^{\text{dot}}_j
    1734 * = \sum_{j \neq k} \prod_{i \neq j, k} x_i x^{\text{dot}}_j\f$
    1735 */
    1736static
    1738{ /*lint --e{715}*/
    1739 SCIP_EXPR* partialchild;
    1740 int c;
    1741
    1742 assert(expr != NULL);
    1743 assert(bardot != NULL);
    1744 assert(SCIPexprGetData(expr) != NULL);
    1745 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
    1746
    1747 partialchild = SCIPexprGetChildren(expr)[childidx];
    1748 assert(partialchild != NULL);
    1749 assert(!SCIPisExprValue(scip, partialchild));
    1750 assert(SCIPexprGetEvalValue(partialchild) != SCIP_INVALID);
    1751
    1752 /* TODO add special handling for nchildren == 2 */
    1753
    1754 /**! [SnippetExprBwfwdiffProduct] */
    1755 *bardot = 0.0;
    1756 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1757 {
    1758 SCIP_EXPR* child;
    1759
    1760 if( c == childidx )
    1761 continue;
    1762
    1763 child = SCIPexprGetChildren(expr)[c];
    1764
    1765 assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
    1766 assert(SCIPexprGetDot(child) != SCIP_INVALID);
    1767
    1768 if( SCIPexprGetDot(child) == 0.0 )
    1769 continue;
    1770
    1771 if( SCIPexprGetEvalValue(child) != 0.0 && SCIPexprGetEvalValue(partialchild) != 0.0 )
    1772 *bardot += SCIPexprGetEvalValue(expr) / (SCIPexprGetEvalValue(child) * SCIPexprGetEvalValue(partialchild)) * SCIPexprGetDot(child);
    1773 else
    1774 {
    1775 SCIP_Real partial;
    1776 int i;
    1777
    1778 partial = SCIPexprGetData(expr)->coefficient;
    1779 for( i = 0; i < SCIPexprGetNChildren(expr) && (partial != 0.0); ++i )
    1780 {
    1781 if( i == c || i == childidx )
    1782 continue;
    1783
    1785 }
    1786 *bardot += partial * SCIPexprGetDot(child);
    1787 }
    1788 }
    1789 /**! [SnippetExprBwfwdiffProduct] */
    1790
    1791 return SCIP_OKAY;
    1792}
    1793
    1794/** expression derivative evaluation callback */
    1795static
    1797{ /*lint --e{715}*/
    1798 SCIP_EXPR* child;
    1799
    1800 assert(expr != NULL);
    1801 assert(SCIPexprGetData(expr) != NULL);
    1802 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
    1803
    1804 child = SCIPexprGetChildren(expr)[childidx];
    1805 assert(child != NULL);
    1806 assert(!SCIPisExprValue(scip, child));
    1807 assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
    1808
    1809 /* TODO add special handling for nchildren == 2 */
    1810
    1811 /**! [SnippetExprBwdiffProduct] */
    1812 if( !SCIPisZero(scip, SCIPexprGetEvalValue(child)) )
    1813 {
    1815 }
    1816 else
    1817 {
    1818 int i;
    1819
    1820 *val = SCIPexprGetData(expr)->coefficient;
    1821 for( i = 0; i < SCIPexprGetNChildren(expr) && (*val != 0.0); ++i )
    1822 {
    1823 if( i == childidx )
    1824 continue;
    1825
    1827 }
    1828 }
    1829 /**! [SnippetExprBwdiffProduct] */
    1830
    1831 return SCIP_OKAY;
    1832}
    1833
    1834/** expression interval evaluation callback */
    1835static
    1837{ /*lint --e{715}*/
    1838 SCIP_EXPRDATA* exprdata;
    1839 int c;
    1840
    1841 assert(expr != NULL);
    1842
    1843 exprdata = SCIPexprGetData(expr);
    1844 assert(exprdata != NULL);
    1845
    1846 /**! [SnippetExprIntevalProduct] */
    1847 SCIPintervalSet(interval, exprdata->coefficient);
    1848
    1849 SCIPdebugMsg(scip, "inteval %p with %d children: %.20g", (void*)expr, SCIPexprGetNChildren(expr), exprdata->coefficient);
    1850
    1851 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1852 {
    1853 SCIP_INTERVAL childinterval;
    1854
    1855 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[c]);
    1856 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    1857 {
    1858 SCIPintervalSetEmpty(interval);
    1859 break;
    1860 }
    1861
    1862 /* multiply childinterval with the so far computed interval */
    1863 SCIPintervalMul(SCIP_INTERVAL_INFINITY, interval, *interval, childinterval);
    1864
    1865 SCIPdebugMsgPrint(scip, " *[%.20g,%.20g]", childinterval.inf, childinterval.sup);
    1866 }
    1867 SCIPdebugMsgPrint(scip, " = [%.20g,%.20g]\n", interval->inf, interval->sup);
    1868 /**! [SnippetExprIntevalProduct] */
    1869
    1870 return SCIP_OKAY;
    1871}
    1872
    1873/** estimates a multilinear function of the form \f$ f(x) := a \prod_{i = 1}^n x_i \f$
    1874 *
    1875 * \f$ x_i \f$ are the auxiliary variables of the children.
    1876 * If !overestimate, then we look for an affine underestimator of \f$ f(x) \f$ which has a value above targetvalue at \f$ x^* \f$,
    1877 * i.e., \f$ g(x) := \alpha^T x + \beta \le f(x)\f$ for all \f$ x \f$ in the domain, such that \f$ \alpha x^* + \beta > \text{targetvalue}\f$.
    1878 *
    1879 * Since \f$ f(x) \f$ is componentwise linear, its convex envelope is piecewise linear and its value can be computed by
    1880 * finding the largest affine underestimator.
    1881 * This is done either explicitly (if n=2) or by solving an LP, see SCIPcomputeFacetVertexPolyhedralNonlinear().
    1882 */
    1883static
    1885{ /*lint --e{715}*/
    1886 SCIP_EXPRDATA* exprdata;
    1887 int nchildren;
    1888
    1889 assert(scip != NULL);
    1890 assert(expr != NULL);
    1891 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
    1892 assert(refpoint != NULL);
    1893 assert(coefs != NULL);
    1894 assert(constant != NULL);
    1895 assert(islocal != NULL);
    1896 assert(branchcand != NULL);
    1897 assert(*branchcand == TRUE);
    1898 assert(success != NULL);
    1899
    1900 exprdata = SCIPexprGetData(expr);
    1901 assert(exprdata != NULL);
    1902
    1903 *success = FALSE;
    1904 *islocal = TRUE;
    1905
    1906 nchildren = SCIPexprGetNChildren(expr);
    1907
    1908 /* debug output: prints expression we are trying to estimate, bounds of variables and point */
    1909#ifdef SCIP_DEBUG
    1910 {
    1911 int c;
    1912
    1913 SCIPdebugMsg(scip, "%sestimating product with %d variables\n", overestimate ? "over": "under", SCIPexprGetNChildren(expr));
    1914 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1915 {
    1916 SCIPdebugMsg(scip, "child %d = %g in [%g, %g]\n", c, refpoint[c], localbounds[c].inf, localbounds[c].sup);
    1917
    1918 if( SCIPisInfinity(scip, localbounds[c].sup) || SCIPisInfinity(scip, -localbounds[c].inf) )
    1919 {
    1920 SCIPdebugMsg(scip, "unbounded factor related to\n");
    1922 }
    1923 }
    1924 }
    1925#endif
    1926
    1927 /* bilinear term */
    1928 if( nchildren == 2 )
    1929 {
    1930 SCIP_Real refpointx;
    1931 SCIP_Real refpointy;
    1932 SCIP_INTERVAL bndx;
    1933 SCIP_INTERVAL bndy;
    1934
    1935 /* collect first variable */
    1936 refpointx = refpoint[0];
    1937 bndx = localbounds[0];
    1939
    1940 /* collect second variable */
    1941 refpointy = refpoint[1];
    1942 bndy = localbounds[1];
    1944
    1945 /* adjust the reference points */
    1946 refpointx = MIN(MAX(refpointx, bndx.inf), bndx.sup);
    1947 refpointy = MIN(MAX(refpointy, bndy.inf), bndy.sup);
    1948
    1949 coefs[0] = 0.0;
    1950 coefs[1] = 0.0;
    1951 *constant = 0.0;
    1952 *success = TRUE;
    1953
    1954 SCIPaddBilinMcCormick(scip, exprdata->coefficient, bndx.inf, bndx.sup, refpointx,
    1955 bndy.inf, bndy.sup, refpointy, overestimate, &coefs[0], &coefs[1], constant,
    1956 success);
    1957 }
    1958 else
    1959 {
    1960 SCIP_EXPRHDLRDATA* exprhdlrdata;
    1961
    1962 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
    1963 assert(exprhdlrdata != NULL);
    1964
    1965 if( exprhdlrdata->conshdlr != NULL )
    1966 {
    1967 SCIP_CALL( estimateVertexPolyhedralProduct(scip, exprhdlrdata->conshdlr, nchildren, localbounds, exprdata->coefficient, refpoint, overestimate,
    1968 targetvalue, coefs, constant, success) );
    1969 }
    1970 else
    1971 {
    1972 SCIPdebugMsg(scip, "no cons_nonlinear included in SCIP, cannot estimate vertex-polyhedral product function\n");
    1973 }
    1974 }
    1975
    1976 return SCIP_OKAY;
    1977}
    1978
    1979/** initial estimators callback */
    1980static
    1981SCIP_DECL_EXPRINITESTIMATES(initestimatesProduct)
    1982{
    1983 SCIP_EXPRDATA* exprdata;
    1984 SCIP_Bool success = TRUE;
    1985 int nchildren;
    1986
    1987 assert(scip != NULL);
    1988 assert(expr != NULL);
    1989 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
    1990 assert(nreturned != NULL);
    1991
    1992 nchildren = SCIPexprGetNChildren(expr);
    1993
    1994 exprdata = SCIPexprGetData(expr);
    1995 assert(exprdata != NULL);
    1996
    1997 if( nchildren == 2 )
    1998 {
    1999 SCIP_INTERVAL bndx = bounds[0];
    2000 SCIP_INTERVAL bndy = bounds[1];
    2001
    2002 constant[0] = 0.0;
    2003 coefs[0][0] = 0.0;
    2004 coefs[0][1] = 0.0;
    2005
    2006 /* build estimator */
    2007 SCIPaddBilinMcCormick(scip, exprdata->coefficient, bndx.inf, bndx.sup, (bndx.inf + bndx.sup) / 2.0,
    2008 bndy.inf, bndy.sup, (bndy.inf + bndy.sup ) / 2.0, overestimate, &coefs[0][0], &coefs[0][1],
    2009 constant, &success);
    2010 }
    2011 else
    2012 {
    2013 SCIP_EXPRHDLRDATA* exprhdlrdata;
    2014
    2015 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
    2016 assert(exprhdlrdata != NULL);
    2017
    2018 if( exprhdlrdata->conshdlr != NULL )
    2019 {
    2020 SCIP_CALL( estimateVertexPolyhedralProduct(scip, exprhdlrdata->conshdlr, nchildren, bounds, exprdata->coefficient, NULL, overestimate,
    2021 overestimate ? SCIPinfinity(scip) : -SCIPinfinity(scip), coefs[0], constant, &success) );
    2022 }
    2023 else
    2024 {
    2025 SCIPdebugMsg(scip, "no cons_nonlinear included in SCIP, cannot estimate vertex-polyhedral product function\n");
    2026 }
    2027 }
    2028
    2029 if( success )
    2030 *nreturned = 1;
    2031
    2032 return SCIP_OKAY;
    2033}
    2034
    2035/** expression reverse propagation callback */
    2036static
    2037SCIP_DECL_EXPRREVERSEPROP(reversepropProduct)
    2038{ /*lint --e{715}*/
    2039 SCIP_EXPRDATA* exprdata;
    2040 SCIP_INTERVAL childbounds;
    2041 SCIP_INTERVAL otherfactor;
    2042 SCIP_INTERVAL zero;
    2043 int i;
    2044 int j;
    2045
    2046 assert(scip != NULL);
    2047 assert(expr != NULL);
    2048 assert(SCIPexprGetNChildren(expr) > 0);
    2049 assert(infeasible != NULL);
    2050 assert(childrenbounds != NULL);
    2051
    2052 *infeasible = FALSE;
    2053
    2054 /* too expensive (runtime here is quadratic in number of children)
    2055 * TODO implement something faster for larger numbers of factors, e.g., split product into smaller products
    2056 */
    2057 if( SCIPexprGetNChildren(expr) > 10 )
    2058 return SCIP_OKAY;
    2059
    2060 /* not possible to learn bounds on children if expression bounds are unbounded in both directions */
    2062 return SCIP_OKAY;
    2063
    2064 exprdata = SCIPexprGetData(expr);
    2065 assert(exprdata != NULL);
    2066
    2067 /**! [SnippetExprReversepropProduct] */
    2068 SCIPintervalSet(&zero, 0.0);
    2069
    2070 /* f = const * prod_k c_k => c_i solves c_i * (const * prod_{j:j!=i} c_j) = f */
    2071 for( i = 0; i < SCIPexprGetNChildren(expr) && !(*infeasible); ++i )
    2072 {
    2073 SCIPintervalSet(&otherfactor, exprdata->coefficient);
    2074
    2075 /* compute prod_{j:j!=i} c_j */
    2076 for( j = 0; j < SCIPexprGetNChildren(expr); ++j )
    2077 {
    2078 if( i == j )
    2079 continue;
    2080
    2081 /* TODO we should compute these only one time instead of repeating this for almost every i */
    2082 childbounds = childrenbounds[j];
    2084 {
    2085 *infeasible = TRUE;
    2086 return SCIP_OKAY;
    2087 }
    2088
    2089 SCIPintervalMul(SCIP_INTERVAL_INFINITY, &otherfactor, otherfactor, childbounds);
    2090 }
    2091
    2092 childbounds = childrenbounds[i];
    2094 {
    2095 *infeasible = TRUE;
    2096 return SCIP_OKAY;
    2097 }
    2098
    2099 /* solve x*otherfactor = f for x in c_i */
    2100 SCIPintervalSolveUnivariateQuadExpression(SCIP_INTERVAL_INFINITY, &childbounds, zero, otherfactor, bounds, childbounds);
    2101
    2102 SCIPdebugMsg(scip, "child %d: solved [%g,%g]*x = [%g,%g] with x in [%g,%g] -> x = [%g,%g]\n", i, otherfactor.inf, otherfactor.sup,
    2103 bounds.inf, bounds.sup,
    2104 childrenbounds[i].inf, childrenbounds[i].sup,
    2105 childbounds.inf, childbounds.sup);
    2106
    2107 /* store computed bounds of the expression */
    2108 SCIPintervalIntersect(&childrenbounds[i], childrenbounds[i], childbounds);
    2109 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childrenbounds[i]) )
    2110 {
    2111 *infeasible = TRUE;
    2112 return SCIP_OKAY;
    2113 }
    2114 }
    2115 /**! [SnippetExprReversepropProduct] */
    2116
    2117 return SCIP_OKAY;
    2118}
    2119
    2120/** expression curvature detection callback */
    2121static
    2123{ /*lint --e{715}*/
    2124 assert(scip != NULL);
    2125 assert(expr != NULL);
    2126 assert(success != NULL);
    2127 assert(SCIPexprGetNChildren(expr) > 0);
    2128
    2129 if( SCIPexprGetNChildren(expr) == 1 )
    2130 {
    2131 *childcurv = SCIPexprcurvMultiply(SCIPgetCoefExprProduct(expr), exprcurvature);
    2132 *success = TRUE;
    2133 }
    2134 else
    2135 {
    2136 *success = FALSE;
    2137 }
    2138
    2139 return SCIP_OKAY;
    2140}
    2141
    2142/** expression monotonicity detection callback */
    2143static
    2144SCIP_DECL_EXPRMONOTONICITY(monotonicityProduct)
    2145{ /*lint --e{715}*/
    2146 SCIP_Real coef;
    2147 int i;
    2148 int nneg;
    2149
    2150 assert(scip != NULL);
    2151 assert(expr != NULL);
    2152 assert(result != NULL);
    2153 assert(SCIPexprGetNChildren(expr) >= 1);
    2154 assert(childidx >= 0);
    2155 assert(childidx < SCIPexprGetNChildren(expr));
    2156
    2158
    2159 /* count the number of negative children (except for childidx); if some children changes sign
    2160 * -> monotonicity unknown
    2161 */
    2162 nneg = 0;
    2163 for( i = 0; i < SCIPexprGetNChildren(expr); ++i )
    2164 {
    2165 SCIP_INTERVAL interval;
    2166
    2167 if( i == childidx )
    2168 continue;
    2169
    2170 assert(SCIPexprGetChildren(expr)[i] != NULL);
    2173
    2174 if( SCIPintervalGetSup(interval) <= 0.0 )
    2175 nneg++;
    2176 else if( SCIPintervalGetInf(interval) < 0.0 )
    2177 {
    2178 *result = SCIP_MONOTONE_UNKNOWN;
    2179 return SCIP_OKAY;
    2180 }
    2181 }
    2182
    2183 /* note that the monotonicity depends on the sign of the coefficient */
    2184 if( nneg % 2 == 0 )
    2185 *result = (coef >= 0.0) ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
    2186 else
    2187 *result = (coef >= 0.0) ? SCIP_MONOTONE_DEC : SCIP_MONOTONE_INC;
    2188
    2189 return SCIP_OKAY;
    2190}
    2191
    2192/** expression integrality detection callback */
    2193static
    2194SCIP_DECL_EXPRINTEGRALITY(integralityProduct)
    2195{ /*lint --e{715}*/
    2196 SCIP_EXPRDATA* exprdata;
    2197 int i;
    2198
    2199 assert(scip != NULL);
    2200 assert(expr != NULL);
    2201 assert(integrality != NULL);
    2202
    2203 exprdata = SCIPexprGetData(expr);
    2204 assert(exprdata != NULL);
    2205
    2206 *integrality = EPSISINT(exprdata->coefficient, 0.0) ? SCIP_IMPLINTTYPE_STRONG : SCIP_IMPLINTTYPE_NONE; /*lint !e835*/
    2207
    2208 for( i = 0; i < SCIPexprGetNChildren(expr) && *integrality != SCIP_IMPLINTTYPE_NONE; ++i )
    2209 {
    2210 SCIP_EXPR* child = SCIPexprGetChildren(expr)[i];
    2211 assert(child != NULL);
    2212
    2213 *integrality = MIN(*integrality, SCIPexprGetIntegrality(child)); /*lint !e666*/
    2214 }
    2215
    2216 return SCIP_OKAY;
    2217}
    2218
    2219/** expression callback to get information for symmetry detection */
    2220static
    2222{ /*lint --e{715}*/
    2223 assert(scip != NULL);
    2224 assert(expr != NULL);
    2225 assert(symdata != NULL);
    2226
    2227 SCIP_CALL( SCIPallocBlockMemory(scip, symdata) );
    2228
    2229 (*symdata)->nconstants = 1;
    2230 (*symdata)->ncoefficients = 0;
    2231 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*symdata)->constants, 1) );
    2232 (*symdata)->constants[0] = SCIPgetCoefExprProduct(expr);
    2233
    2234 return SCIP_OKAY;
    2235}
    2236
    2237/** creates the handler for product expressions and includes it into SCIP */
    2239 SCIP* scip /**< SCIP data structure */
    2240 )
    2241{
    2242 SCIP_EXPRHDLRDATA* exprhdlrdata;
    2243 SCIP_EXPRHDLR* exprhdlr;
    2244
    2245 /* allocate expression handler data */
    2246 SCIP_CALL( SCIPallocClearBlockMemory(scip, &exprhdlrdata) );
    2247 exprhdlrdata->conshdlr = SCIPfindConshdlr(scip, "nonlinear");
    2248
    2250 exprhdlrdata) );
    2251 assert(exprhdlr != NULL);
    2252
    2253 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrProduct, freehdlrProduct);
    2254 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataProduct, freedataProduct);
    2255 SCIPexprhdlrSetSimplify(exprhdlr, simplifyProduct);
    2256 SCIPexprhdlrSetCompare(exprhdlr, compareProduct);
    2257 SCIPexprhdlrSetPrint(exprhdlr, printProduct);
    2258 SCIPexprhdlrSetIntEval(exprhdlr, intevalProduct);
    2259 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesProduct, estimateProduct);
    2260 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropProduct);
    2261 SCIPexprhdlrSetHash(exprhdlr, hashProduct);
    2262 SCIPexprhdlrSetDiff(exprhdlr, bwdiffProduct, fwdiffProduct, bwfwdiffProduct);
    2263 SCIPexprhdlrSetCurvature(exprhdlr, curvatureProduct);
    2264 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityProduct);
    2265 SCIPexprhdlrSetIntegrality(exprhdlr, integralityProduct);
    2266 SCIPexprhdlrSetGetSymdata(exprhdlr, getSymDataProduct);
    2267
    2268 SCIP_CALL( SCIPaddBoolParam(scip, "expr/" EXPRHDLR_NAME "/expandalways",
    2269 "whether to expand products of a sum and several factors in simplify",
    2270 &exprhdlrdata->expandalways, FALSE, FALSE, NULL, NULL) );
    2271
    2272 return SCIP_OKAY;
    2273}
    2274
    2275/** creates a product expression */
    2277 SCIP* scip, /**< SCIP data structure */
    2278 SCIP_EXPR** expr, /**< pointer where to store expression */
    2279 int nchildren, /**< number of children */
    2280 SCIP_EXPR** children, /**< children */
    2281 SCIP_Real coefficient, /**< constant coefficient of product */
    2282 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    2283 void* ownercreatedata /**< data to pass to ownercreate */
    2284 )
    2285{
    2286 SCIP_EXPRDATA* exprdata;
    2287
    2288 /**! [SnippetCreateExprProduct] */
    2289 SCIP_CALL( SCIPallocBlockMemory(scip, &exprdata) );
    2290 exprdata->coefficient = coefficient;
    2291
    2292 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPgetExprhdlrProduct(scip), exprdata, nchildren, children, ownercreate, ownercreatedata) );
    2293 /**! [SnippetCreateExprProduct] */
    2294
    2295 return SCIP_OKAY;
    2296}
    2297
    2298/* from pub_expr.h */
    2299
    2300/** gets the constant coefficient of a product expression */
    2302 SCIP_EXPR* expr /**< product expression */
    2303 )
    2304{
    2305 SCIP_EXPRDATA* exprdata;
    2306
    2307 assert(expr != NULL);
    2308
    2309 exprdata = SCIPexprGetData(expr);
    2310 assert(exprdata != NULL);
    2311
    2312 return exprdata->coefficient;
    2313}
    constraint handler for nonlinear constraints specified by algebraic expressions
    #define NULL
    Definition: def.h:248
    #define EPSISINT(x, eps)
    Definition: def.h:195
    #define SCIP_INVALID
    Definition: def.h:178
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:180
    #define SCIP_Bool
    Definition: def.h:91
    #define MIN(x, y)
    Definition: def.h:224
    #define SCIP_Real
    Definition: def.h:156
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    #define MAX(x, y)
    Definition: def.h:220
    #define SCIPABORT()
    Definition: def.h:327
    #define SCIP_CALL(x)
    Definition: def.h:355
    absolute expression handler
    handler for -x*log(x) expressions
    exponential expression handler
    power and signed power expression handlers
    static SCIP_DECL_EXPRHASH(hashProduct)
    static SCIP_RETCODE buildSimplifiedProduct(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE **simplifiedfactors, SCIP_Bool expandalways, SCIP_Bool changed, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    static int listLength(EXPRNODE *list)
    Definition: expr_product.c:163
    static SCIP_DECL_EXPRCURVATURE(curvatureProduct)
    static SCIP_DECL_EXPRESTIMATE(estimateProduct)
    #define debugSimplify
    Definition: expr_product.c:63
    static SCIP_RETCODE enforceSP11(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_product.c:834
    #define EXPRHDLR_HASHKEY
    Definition: expr_product.c:54
    static SCIP_DECL_EXPRSIMPLIFY(simplifyProduct)
    static SCIP_DECL_EXPRINTEVAL(intevalProduct)
    static SCIP_RETCODE enforceSP12(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_Bool expandalways, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_product.c:895
    static SCIP_RETCODE enforceSP10(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_product.c:790
    static SCIP_DECL_EXPRFREEDATA(freedataProduct)
    #define EXPRHDLR_NAME
    Definition: expr_product.c:51
    static SCIP_DECL_EXPRPRINT(printProduct)
    static SCIP_DECL_EXPRFREEHDLR(freehdlrProduct)
    static SCIP_RETCODE simplifyFactor(SCIP *scip, SCIP_EXPR *factor, SCIP_Real *simplifiedcoef, EXPRNODE **simplifiedfactor, SCIP_Bool *changed)
    Definition: expr_product.c:312
    static SCIP_DECL_EXPRGETSYMDATA(getSymDataProduct)
    static SCIP_RETCODE createExprProductFromExprlist(SCIP *scip, EXPRNODE *exprlist, SCIP_Real coef, SCIP_EXPR **expr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_product.c:269
    static SCIP_DECL_EXPRINITESTIMATES(initestimatesProduct)
    static SCIP_RETCODE createExprNode(SCIP *scip, SCIP_EXPR *expr, EXPRNODE **newnode)
    Definition: expr_product.c:181
    static EXPRNODE * listPopFirst(EXPRNODE **list)
    Definition: expr_product.c:143
    static SCIP_DECL_EXPRCOPYDATA(copydataProduct)
    static void insertFirstList(EXPRNODE *newnode, EXPRNODE **list)
    Definition: expr_product.c:129
    static SCIP_RETCODE simplifyMultiplyChildren(SCIP *scip, SCIP_EXPR **exprs, int nexprs, SCIP_Real *simplifiedcoef, EXPRNODE **finalchildren, SCIP_Bool *changed, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_product.c:724
    static SCIP_RETCODE enforceSP12b(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    static SCIP_RETCODE freeExprlist(SCIP *scip, EXPRNODE **exprlist)
    Definition: expr_product.c:240
    static SCIP_RETCODE freeExprNode(SCIP *scip, EXPRNODE **node)
    Definition: expr_product.c:225
    static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffProduct)
    static SCIP_DECL_EXPRINTEGRALITY(integralityProduct)
    #define EXPRHDLR_DESC
    Definition: expr_product.c:52
    static SCIP_DECL_EXPRCOMPARE(compareProduct)
    #define EXPRHDLR_PRECEDENCE
    Definition: expr_product.c:53
    static SCIP_DECL_VERTEXPOLYFUN(prodfunction)
    Definition: expr_product.c:101
    static SCIP_RETCODE createExprlistFromExprs(SCIP *scip, SCIP_EXPR **exprs, int nexprs, EXPRNODE **list)
    Definition: expr_product.c:198
    static SCIP_DECL_EXPREVAL(evalProduct)
    static SCIP_DECL_EXPRFWDIFF(fwdiffProduct)
    static SCIP_DECL_EXPRMONOTONICITY(monotonicityProduct)
    static SCIP_RETCODE mergeProductExprlist(SCIP *scip, EXPRNODE *tomerge, EXPRNODE **finalchildren, EXPRNODE **unsimplifiedchildren, SCIP_Bool *changed, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_product.c:392
    static SCIP_DECL_EXPRCOPYHDLR(copyhdlrProduct)
    static SCIP_DECL_EXPRREVERSEPROP(reversepropProduct)
    static SCIP_RETCODE estimateVertexPolyhedralProduct(SCIP *scip, SCIP_CONSHDLR *conshdlr, int nfactors, SCIP_INTERVAL *bounds, SCIP_Real constantfactor, SCIP_Real *refpoint, SCIP_Bool overestimate, SCIP_Real targetvalue, SCIP_Real *coefs, SCIP_Real *constant, SCIP_Bool *success)
    static SCIP_DECL_EXPRBWDIFF(bwdiffProduct)
    product expression handler
    sum expression handler
    constant value expression handler
    SCIP_RETCODE SCIPcomputeFacetVertexPolyhedralNonlinear(SCIP *scip, SCIP_CONSHDLR *conshdlr, SCIP_Bool overestimate, SCIP_DECL_VERTEXPOLYFUN((*function)), void *fundata, SCIP_Real *xstar, SCIP_Real *box, int nallvars, SCIP_Real targetvalue, SCIP_Bool *success, SCIP_Real *facetcoefs, SCIP_Real *facetconstant)
    #define SCIP_MAXVERTEXPOLYDIM
    SCIP_RETCODE SCIPcreateExprProduct(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real coefficient, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    SCIP_RETCODE SCIPcreateExprAbs(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_abs.c:528
    SCIP_RETCODE SCIPappendExprSumExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child, SCIP_Real childcoef)
    Definition: expr_sum.c:1154
    SCIP_RETCODE SCIPcreateExprSignpower(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_pow.c:3209
    SCIP_Bool SCIPisExprExp(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_exp.c:528
    SCIP_RETCODE SCIPcreateExprExp(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_exp.c:510
    SCIP_Bool SCIPisExprSignpower(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_pow.c:3234
    SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_sum.c:1117
    SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_value.c:274
    SCIP_RETCODE SCIPcreateExprEntropy(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_entropy.c:685
    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 SCIPincludeExprhdlrProduct(SCIP *scip)
    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
    void SCIPaddBilinMcCormick(SCIP *scip, SCIP_Real bilincoef, SCIP_Real lbx, SCIP_Real ubx, SCIP_Real refpointx, SCIP_Real lby, SCIP_Real uby, SCIP_Real refpointy, SCIP_Bool overestimate, SCIP_Real *lincoefx, SCIP_Real *lincoefy, SCIP_Real *linconstant, SCIP_Bool *success)
    unsigned int SCIPcalcFibHash(SCIP_Real v)
    Definition: misc.c:10462
    SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
    Definition: scip_param.c:57
    SCIP_CONSHDLR * SCIPfindConshdlr(SCIP *scip, const char *name)
    Definition: scip_cons.c:940
    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
    SCIP_EXPRHDLR * SCIPgetExprhdlrProduct(SCIP *scip)
    Definition: scip_expr.c:939
    void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
    Definition: expr.c:451
    SCIP_EXPRHDLRDATA * SCIPexprhdlrGetData(SCIP_EXPRHDLR *exprhdlr)
    Definition: expr.c:575
    void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)), SCIP_DECL_EXPRFREEHDLR((*freehdlr)))
    Definition: expr.c:370
    void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)), SCIP_DECL_EXPRBWFWDIFF((*bwfwdiff)))
    Definition: expr.c:473
    void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRREVERSEPROP((*reverseprop)))
    Definition: expr.c:510
    void SCIPexprhdlrSetEstimate(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINITESTIMATES((*initestimates)), SCIP_DECL_EXPRESTIMATE((*estimate)))
    Definition: expr.c:532
    void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRMONOTONICITY((*monotonicity)))
    Definition: expr.c:429
    void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEVAL((*inteval)))
    Definition: expr.c:488
    void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCURVATURE((*curvature)))
    Definition: expr.c:418
    SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
    Definition: scip_expr.c:847
    void SCIPexprhdlrSetCompare(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOMPARE((*compare)))
    Definition: expr.c:462
    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
    void SCIPexprSetData(SCIP_EXPR *expr, SCIP_EXPRDATA *exprdata)
    Definition: expr.c:3920
    int SCIPexprGetNChildren(SCIP_EXPR *expr)
    Definition: expr.c:3872
    SCIP_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
    Definition: expr_pow.c:3448
    SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1490
    SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1479
    SCIP_Real * SCIPgetCoefsExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1554
    SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1468
    SCIP_Real SCIPgetCoefExprProduct(SCIP_EXPR *expr)
    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_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1501
    SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
    Definition: expr.c:3946
    SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
    Definition: expr.c:3882
    SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
    Definition: expr_sum.c:1569
    SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
    Definition: expr.c:4028
    void SCIPcaptureExpr(SCIP_EXPR *expr)
    Definition: scip_expr.c:1435
    int SCIPexprGetNUses(SCIP_EXPR *expr)
    Definition: expr.c:3862
    SCIP_RETCODE SCIPdismantleExpr(SCIP *scip, FILE *file, SCIP_EXPR *expr)
    Definition: scip_expr.c:1634
    SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
    Definition: scip_expr.c:1742
    SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
    Definition: expr.c:3895
    SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
    SCIP_Bool SCIPintervalIsEntire(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalSolveUnivariateQuadExpression(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL sqrcoeff, SCIP_INTERVAL lincoeff, SCIP_INTERVAL rhs, SCIP_INTERVAL xbnds)
    void SCIPintervalIntersect(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
    SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
    void SCIPintervalMul(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
    SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
    void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
    #define SCIPallocClearBlockMemory(scip, ptr)
    Definition: scip_mem.h:91
    #define SCIPduplicateBlockMemory(scip, ptr, source)
    Definition: scip_mem.h:103
    #define SCIPallocBufferArray(scip, ptr, num)
    Definition: scip_mem.h:124
    #define SCIPfreeBufferArray(scip, ptr)
    Definition: scip_mem.h:136
    #define SCIPallocBlockMemoryArray(scip, ptr, num)
    Definition: scip_mem.h:93
    #define SCIPfreeBlockMemory(scip, ptr)
    Definition: scip_mem.h:108
    #define SCIPallocBlockMemory(scip, ptr)
    Definition: scip_mem.h:89
    SCIP_Bool SCIPisRelEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
    SCIP_Real SCIPinfinity(SCIP *scip)
    SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
    SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
    bilinear nonlinear handler
    public functions to work with algebraic expressions
    public data structures and miscellaneous methods
    SCIP_Real sup
    Definition: intervalarith.h:57
    SCIP_Real inf
    Definition: intervalarith.h:56
    structs for symmetry computations
    struct exprnode * next
    Definition: expr_product.c:90
    SCIP_EXPR * expr
    Definition: expr_product.c:89
    #define SCIP_DECL_EXPR_OWNERCREATE(x)
    Definition: type_expr.h:143
    struct SCIP_ExprhdlrData SCIP_EXPRHDLRDATA
    Definition: type_expr.h:195
    struct SCIP_ExprData SCIP_EXPRDATA
    Definition: type_expr.h:54
    #define SCIP_EXPRITER_VISITINGCHILD
    Definition: type_expr.h:695
    @ SCIP_MONOTONE_UNKNOWN
    Definition: type_expr.h:71
    @ SCIP_MONOTONE_INC
    Definition: type_expr.h:72
    @ SCIP_MONOTONE_DEC
    Definition: type_expr.h:73
    #define SCIP_EXPRITER_VISITEDCHILD
    Definition: type_expr.h:696
    #define SCIP_EXPRITER_LEAVEEXPR
    Definition: type_expr.h:697
    #define SCIP_EXPRITER_ENTEREXPR
    Definition: type_expr.h:694
    @ SCIP_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