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-2026 Zuse Institute Berlin (ZIB) */
    7/* */
    8/* Licensed under the Apache License, Version 2.0 (the "License"); */
    9/* you may not use this file except in compliance with the License. */
    10/* You may obtain a copy of the License at */
    11/* */
    12/* http://www.apache.org/licenses/LICENSE-2.0 */
    13/* */
    14/* Unless required by applicable law or agreed to in writing, software */
    15/* distributed under the License is distributed on an "AS IS" BASIS, */
    16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
    17/* See the License for the specific language governing permissions and */
    18/* limitations under the License. */
    19/* */
    20/* You should have received a copy of the Apache-2.0 license */
    21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
    22/* */
    23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    24
    25/**@file expr_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 "scip/pub_expr.h"
    37#include "scip/expr_product.h"
    38#include "scip/expr_sum.h"
    39#include "scip/expr_pow.h"
    40#include "scip/expr_value.h"
    41#include "scip/expr_exp.h"
    42#include "scip/expr_abs.h"
    43#include "scip/expr_entropy.h"
    44#include "scip/cons_nonlinear.h"
    45#include "scip/pub_misc.h"
    48
    49#define EXPRHDLR_NAME "prod"
    50#define EXPRHDLR_DESC "product expression"
    51#define EXPRHDLR_PRECEDENCE 50000
    52#define EXPRHDLR_HASHKEY SCIPcalcFibHash(54949.0)
    53
    54/** macro to activate/deactivate debugging information of simplify method */
    55/*lint -emacro(681,debugSimplify) */
    56/*lint -emacro(506,debugSimplify) */
    57/*lint -emacro(774,debugSimplify) */
    58#ifdef SIMPLIFY_DEBUG
    59#define debugSimplify printf
    60#else
    61#define debugSimplify while( FALSE ) printf
    62#endif
    63
    64
    65/*lint -e777*/
    66
    67/*
    68 * Data structures
    69 */
    70
    71/** expression data */
    72struct SCIP_ExprData
    73{
    74 SCIP_Real coefficient; /**< coefficient */
    75};
    76
    77struct SCIP_ExprhdlrData
    78{
    79 SCIP_CONSHDLR* conshdlr; /**< nonlinear constraint handler (to compute estimates for > 2-dim products) */
    80
    81 SCIP_Bool expandalways; /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    82};
    83
    84/** node for linked list of expressions */
    86{
    87 SCIP_EXPR* expr; /**< expression in node */
    88 struct exprnode* next; /**< next node */
    89};
    90
    91typedef struct exprnode EXPRNODE;
    92
    93/*
    94 * Local methods
    95 */
    96
    97/** evaluation callback for (vertex-polyhedral) functions used as input for facet computation of its envelopes */
    98static
    100{
    101 /* funcdata is a pointer to the double holding the coefficient */
    102 SCIP_Real ret = *(SCIP_Real*)funcdata;
    103 int i;
    104
    105 for( i = 0; i < nargs; ++i )
    106 ret *= args[i];
    107
    108 return ret;
    109}
    110
    111static
    113 SCIP* scip, /**< SCIP data structure */
    114 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    115 EXPRNODE** simplifiedfactors, /**< factors of simplified product */
    116 SCIP_Bool expandalways, /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    117 SCIP_Bool changed, /**< indicates whether some of the simplified factors was changed */
    118 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    119 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    120 void* ownercreatedata /**< data to pass to ownercreate */
    121 );
    122
    123/* methods for handling linked list of expressions */
    124
    125/** inserts newnode at beginning of list */
    126static
    128 EXPRNODE* newnode, /**< node to insert */
    129 EXPRNODE** list /**< list */
    130 )
    131{
    132 assert(list != NULL);
    133 assert(newnode != NULL);
    134
    135 newnode->next = *list;
    136 *list = newnode;
    137}
    138
    139/** removes first element of list and returns it */
    140static
    142 EXPRNODE** list /**< list */
    143 )
    144{
    145 EXPRNODE* first;
    146
    147 assert(list != NULL);
    148
    149 if( *list == NULL )
    150 return NULL;
    151
    152 first = *list;
    153 *list = (*list)->next;
    154 first->next = NULL;
    155
    156 return first;
    157}
    158
    159/** returns length of list */
    160static
    162 EXPRNODE* list /**< list */
    163 )
    164{
    165 int length;
    166
    167 if( list == NULL )
    168 return 0;
    169
    170 length = 1;
    171 while( (list=list->next) != NULL )
    172 ++length;
    173
    174 return length;
    175}
    176
    177/** creates expression node and captures expression */
    178static
    180 SCIP* scip, /**< SCIP data structure */
    181 SCIP_EXPR* expr, /**< expression stored at node */
    182 EXPRNODE** newnode /**< pointer to store node */
    183 )
    184{
    186
    187 (*newnode)->expr = expr;
    188 (*newnode)->next = NULL;
    190
    191 return SCIP_OKAY;
    192}
    193
    194/** creates expression list from expressions */
    195static
    197 SCIP* scip, /**< SCIP data structure */
    198 SCIP_EXPR** exprs, /**< expressions stored in list */
    199 int nexprs, /**< number of expressions */
    200 EXPRNODE** list /**< pointer to store list */
    201 )
    202{
    203 int i;
    204
    205 assert(*list == NULL);
    206 assert(nexprs > 0);
    207
    208 debugSimplify("building expr list from %d expressions\n", nexprs);
    209 for( i = nexprs - 1; i >= 0; --i )
    210 {
    211 EXPRNODE* newnode;
    212
    213 SCIP_CALL( createExprNode(scip, exprs[i], &newnode) );
    214 insertFirstList(newnode, list);
    215 }
    216 assert(nexprs > 1 || (*list)->next == NULL);
    217
    218 return SCIP_OKAY;
    219}
    220
    221/** frees expression node and releases expressions */
    222static
    224 SCIP* scip, /**< SCIP data structure */
    225 EXPRNODE** node /**< node to be freed */
    226 )
    227{
    228 assert(node != NULL && *node != NULL);
    229
    230 SCIP_CALL( SCIPreleaseExpr(scip, &(*node)->expr) );
    232
    233 return SCIP_OKAY;
    234}
    235
    236/** frees an expression list */
    237static
    239 SCIP* scip, /**< SCIP data structure */
    240 EXPRNODE** exprlist /**< list */
    241 )
    242{
    243 EXPRNODE* current;
    244
    245 if( *exprlist == NULL )
    246 return SCIP_OKAY;
    247
    248 current = *exprlist;
    249 while( current != NULL )
    250 {
    251 EXPRNODE* tofree;
    252
    253 tofree = current;
    254 current = current->next;
    255 SCIP_CALL( freeExprNode(scip, &tofree) );
    256 }
    257 assert(current == NULL);
    258 *exprlist = NULL;
    259
    260 return SCIP_OKAY;
    261}
    262
    263/* helper functions for simplifying expressions */
    264
    265/** creates a product expression with the elements of exprlist as its children */
    266static
    268 SCIP* scip, /**< SCIP data structure */
    269 EXPRNODE* exprlist, /**< list containing the children of expr */
    270 SCIP_Real coef, /**< coef of expr */
    271 SCIP_EXPR** expr, /**< pointer to store the product expression */
    272 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    273 void* ownercreatedata /**< data to pass to ownercreate */
    274 )
    275{
    276 int i;
    277 int nchildren;
    278 SCIP_EXPR** children;
    279
    280 /* asserts SP8 */
    281 assert(coef == 1.0);
    282 nchildren = listLength(exprlist);
    283
    284 SCIP_CALL( SCIPallocBufferArray(scip, &children, nchildren) );
    285
    286 for( i = 0; i < nchildren; ++i )
    287 {
    288 children[i] = exprlist->expr;
    289 exprlist = exprlist->next;
    290 }
    291
    292 assert(exprlist == NULL);
    293
    294 SCIP_CALL( SCIPcreateExprProduct(scip, expr, nchildren, children, coef, ownercreate, ownercreatedata) );
    295
    296 SCIPfreeBufferArray(scip, &children);
    297
    298 return SCIP_OKAY;
    299}
    300
    301/** simplifies a factor of a product expression: base, so that it is a valid children of a simplified product expr
    302 *
    303 * @note In contrast to other simplify methods, this does *not* return a simplified expression.
    304 * Instead, the method is intended to be called only when simplifying a product expression.
    305 * Since in general, base is not a simplified child of a product expression, this method returns
    306 * a list of expressions L, such that (prod L) = baset *and* each expression in L
    307 * is a valid child of a simplified product expression.
    308 */
    309static
    311 SCIP* scip, /**< SCIP data structure */
    312 SCIP_EXPR* factor, /**< expression to be simplified */
    313 SCIP_Real* simplifiedcoef, /**< coefficient of parent product expression */
    314 EXPRNODE** simplifiedfactor, /**< pointer to store the resulting expression node/list of nodes */
    315 SCIP_Bool* changed /**< pointer to store if some term actually got simplified */
    316 )
    317{
    318 assert(simplifiedfactor != NULL);
    319 assert(*simplifiedfactor == NULL);
    320 assert(factor != NULL);
    321 assert(changed != NULL);
    322
    323 /* enforces SP7 */
    324 if( SCIPisExprValue(scip, factor) )
    325 {
    326 *changed = TRUE;
    327 *simplifiedcoef *= SCIPgetValueExprValue(factor);
    328 return SCIP_OKAY;
    329 }
    330
    331 /* enforces SP2 */
    332 if( SCIPisExprProduct(scip, factor) )
    333 {
    334 *changed = TRUE;
    335
    336 /* assert SP8 */
    337 assert(SCIPgetCoefExprProduct(factor) == 1.0);
    338 debugSimplify("[simplifyFactor] seeing a product: include its children\n");
    339
    340 SCIP_CALL( createExprlistFromExprs(scip, SCIPexprGetChildren(factor), SCIPexprGetNChildren(factor), simplifiedfactor) );
    341
    342 return SCIP_OKAY;
    343 }
    344
    345 /* enforces SP13: a sum with a unique child and no constant -> take the coefficient and use its child as factor */
    346 if( SCIPisExprSum(scip, factor) && SCIPexprGetNChildren(factor) == 1 && SCIPgetConstantExprSum(factor) == 0.0 )
    347 {
    348 *changed = TRUE;
    349
    350 /* assert SS8 and SS7 */
    351 assert(SCIPgetCoefsExprSum(factor)[0] != 0.0 && SCIPgetCoefsExprSum(factor)[0] != 1.0);
    352 debugSimplify("[simplifyFactor] seeing a sum of the form coef * child : take coef and child apart\n");
    353
    355 {
    356 /* if child is a product, then add its children to exprlist */
    358 *simplifiedcoef *= SCIPgetCoefExprProduct(SCIPexprGetChildren(factor)[0]);
    359 }
    360 else
    361 {
    362 SCIP_CALL( createExprlistFromExprs(scip, SCIPexprGetChildren(factor), 1, simplifiedfactor) );
    363 }
    364 *simplifiedcoef *= SCIPgetCoefsExprSum(factor)[0];
    365
    366 return SCIP_OKAY;
    367 }
    368
    369 /* the given (simplified) expression `factor`, can be a child of a simplified product */
    370 assert(!SCIPisExprProduct(scip, factor));
    371 assert(!SCIPisExprValue(scip, factor));
    372
    373 SCIP_CALL( createExprNode(scip, factor, simplifiedfactor) );
    374
    375 return SCIP_OKAY;
    376}
    377
    378/** merges tomerge into finalchildren
    379 *
    380 * Both, tomerge and finalchildren contain expressions that could be the children of a simplified product
    381 * (except for SP8 and SP10 which are enforced later).
    382 * However, the concatenation of both lists will not in general yield a simplified product expression,
    383 * because SP4, SP5 and SP14 could be violated. So the purpose of this method is to enforce SP4, SP5 and SP14.
    384 * In the process of enforcing SP4, it could happen that SP2 is violated. Since enforcing SP2
    385 * could generate further violations, we remove the affected children from finalchildren
    386 * and include them in unsimplifiedchildren for further processing.
    387 * @note if tomerge has more than one element, then they are the children of a simplified product expression
    388 */
    389static
    391 SCIP* scip, /**< SCIP data structure */
    392 EXPRNODE* tomerge, /**< list to merge */
    393 EXPRNODE** finalchildren, /**< pointer to store the result of merge between tomerge and *finalchildren */
    394 EXPRNODE** unsimplifiedchildren,/**< the list of children that should go to the product expression;
    395 * they are unsimplified when seen as children of a simplified product */
    396 SCIP_Bool* changed, /**< pointer to store if some term actually got simplified */
    397 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    398 void* ownercreatedata /**< data to pass to ownercreate */
    399 )
    400{
    401 EXPRNODE* tomergenode;
    402 EXPRNODE* current;
    403 EXPRNODE* previous;
    404
    405 if( tomerge == NULL )
    406 return SCIP_OKAY;
    407
    408 if( *finalchildren == NULL )
    409 {
    410 *finalchildren = tomerge;
    411 return SCIP_OKAY;
    412 }
    413
    414 tomergenode = tomerge;
    415 current = *finalchildren;
    416 previous = NULL;
    417
    418 while( tomergenode != NULL && current != NULL )
    419 {
    420 int compareres;
    421 EXPRNODE* aux;
    422 SCIP_EXPR* base1;
    423 SCIP_EXPR* base2;
    424 SCIP_Real expo1;
    425 SCIP_Real expo2;
    426 SCIP_Bool issignpower1;
    427 SCIP_Bool issignpower2;
    428
    429 /* assert invariants */
    430 assert(!SCIPisExprValue(scip, tomergenode->expr));
    431 assert(!SCIPisExprValue(scip, current->expr));
    432 assert(previous == NULL || previous->next == current);
    433
    434 /* we are going to multiply the two exprs: current and tomergenode
    435 * we first check if they are both exponentials
    436 * if so, we multiply them
    437 * otherwise, we interpret them as base^exponent
    438 * the base of an expr is the expr itself
    439 * if type(expr) != pow, otherwise it is the child of pow
    440 */
    441
    442 /* if both are exponentials, create a new exponential with the sum of their children */
    443 if( SCIPisExprExp(scip, current->expr) && SCIPisExprExp(scip, tomergenode->expr) )
    444 {
    445 SCIP_EXPR* sum;
    446 SCIP_EXPR* simplifiedsum;
    447 SCIP_EXPR* expexpr;
    448 SCIP_EXPR* simplifiedexp;
    449
    450 /* inform that expressions changed */
    451 *changed = TRUE;
    452
    453 /* create sum */
    454 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, SCIPexprGetChildren(current->expr), NULL, 0.0, ownercreate, ownercreatedata) );
    455 SCIP_CALL( SCIPappendExprSumExpr(scip, sum, SCIPexprGetChildren(tomergenode->expr)[0], 1.0) );
    456
    457 /* simplify sum */
    458 SCIP_CALL( SCIPcallExprSimplify(scip, sum, &simplifiedsum, ownercreate, ownercreatedata) );
    460
    461 /* create exponential */
    462 SCIP_CALL( SCIPcreateExprExp(scip, &expexpr, simplifiedsum, ownercreate, ownercreatedata) );
    463 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedsum) );
    464
    465 /* simplify exponential */
    466 SCIP_CALL( SCIPcallExprSimplify(scip, expexpr, &simplifiedexp, ownercreate, ownercreatedata) );
    467 SCIP_CALL( SCIPreleaseExpr(scip, &expexpr) );
    468
    469 /* note that simplified exponential might be a product exp(x) * exp(-x + log(y*z)) -> y*z and so it is not a
    470 * valid child of a simplified product; therefore we add it to the unsimplifiedchildren's list
    471 */
    472
    473 /* replace tomergenode's expression with simplifiedexp */
    474 /* TODO: this code repeats below; add new function to avoid duplication */
    475 SCIP_CALL( SCIPreleaseExpr(scip, &tomergenode->expr) );
    476 tomergenode->expr = simplifiedexp;
    477
    478 /* move tomergenode to unsimplifiedchildren */
    479 aux = tomergenode;
    480 tomergenode = tomergenode->next;
    481 insertFirstList(aux, unsimplifiedchildren);
    482
    483 /* remove current */
    484 if( current == *finalchildren )
    485 {
    486 assert(previous == NULL);
    487 aux = listPopFirst(finalchildren);
    488 assert(aux == current);
    489 current = *finalchildren;
    490 }
    491 else
    492 {
    493 assert(previous != NULL);
    494 aux = current;
    495 current = current->next;
    496 previous->next = current;
    497 }
    498 SCIP_CALL( freeExprNode(scip, &aux) );
    499
    500 continue;
    501 }
    502
    503 /* they were not exponentials, so collect bases and exponents */
    504 if( SCIPisExprPower(scip, current->expr) )
    505 {
    506 base1 = SCIPexprGetChildren(current->expr)[0];
    507 expo1 = SCIPgetExponentExprPow(current->expr);
    508 issignpower1 = FALSE;
    509 }
    510 else if( SCIPisExprSignpower(scip, current->expr) )
    511 {
    512 base1 = SCIPexprGetChildren(current->expr)[0];
    513 expo1 = SCIPgetExponentExprPow(current->expr);
    514 issignpower1 = TRUE;
    515 }
    516 else
    517 {
    518 base1 = current->expr;
    519 expo1 = 1.0;
    520 issignpower1 = FALSE;
    521 }
    522 if( SCIPisExprPower(scip, tomergenode->expr) )
    523 {
    524 base2 = SCIPexprGetChildren(tomergenode->expr)[0];
    525 expo2 = SCIPgetExponentExprPow(tomergenode->expr);
    526 issignpower2 = FALSE;
    527 }
    528 else if( SCIPisExprSignpower(scip, tomergenode->expr) )
    529 {
    530 base2 = SCIPexprGetChildren(tomergenode->expr)[0];
    531 expo2 = SCIPgetExponentExprPow(tomergenode->expr);
    532 issignpower2 = TRUE;
    533 }
    534 else
    535 {
    536 base2 = tomergenode->expr;
    537 expo2 = 1.0;
    538 issignpower2 = FALSE;
    539 }
    540
    541 if( SCIPcompareExpr(scip, base1, base2) == 0 )
    542 {
    543 /* the bases are the same, so we should try to merge the multiplication of the powers */
    544 SCIP_EXPR* power = NULL;
    545
    546 if( !issignpower1 && !issignpower2 )
    547 {
    548 /* and both are normal power, then add to unsimplifiedchildren the resulting expr of simplify(base^(expo1 + expo2)) */
    549#ifdef SCIP_DISABLED_CODE
    550 /* 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 */
    551 /*
    552 * unless expo1 or expo2 are fractional but expo1+expo2 is not fractional, then we better keep the original
    553 * the reason for that is that x^fractional implies a constraint x >= 0
    554 */
    555 if( (EPSISINT(expo1, 0.0) && EPSISINT(expo2, 0.0)) || !EPSISINT(expo1+expo2, 0.0) ) /*lint !e835*/
    556#endif
    557 {
    558 SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    559 }
    560 }
    561 else if( issignpower1 ^ issignpower2 )
    562 {
    563 /* exactly one is signpower: sign(x) |x|^expo1 x^expo2 = sign(x)^(1+expo2) |x|^(expo1+expo2), with x = base */
    564 if( EPSISINT(expo2, 0.0) ) /*lint !e835*/
    565 {
    566 if( (int)expo2 % 2 == 0 )
    567 {
    568 /* if expo2 is even, then sign(x)^(1+expo2) = sign(x), so we have signpower: sign(x) |x|^(expo1+expo2)
    569 * TODO: we can remove this case distinction once the simplification of power expressions tranform
    570 * |expr|^even -> expr^even, since the call to SCIPcallExprSimplify(scip, conshdlr, power,
    571 * &simplifiedpower) below will take care of this.
    572 */
    573 SCIP_CALL( SCIPcreateExprSignpower(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    574 }
    575 else
    576 {
    577 /* if expo2 is odd, then sign(x)^(1+expo2) = 1, so we have |x|^(expo1+expo2) */
    578 SCIP_EXPR* absbase;
    579
    580 SCIP_CALL( SCIPcreateExprAbs(scip, &absbase, base1, ownercreate, ownercreatedata) );
    581 SCIP_CALL( SCIPcreateExprPow(scip, &power, absbase, expo1 + expo2, ownercreate, ownercreatedata) );
    582 SCIP_CALL( SCIPreleaseExpr(scip, &absbase) );
    583 }
    584 }
    585 else if( !EPSISINT(expo1+expo2, 0.0) ) /*lint !e835*/
    586 {
    587 /* if expo2 is fractional and expo1+expo2 is fractional, then we need x >= 0, so we can use x^(expo1+expo2) */
    588 SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    589 }
    590 /* else: expo2 is fractional but expo1+expo2 is integral, then we better do not do anything for now
    591 * (leave power at NULL)
    592 */
    593 }
    594 else
    595 {
    596 /* if both are signpower, then we have |base|^(expo1+expo2)
    597 * if expo1+expo2 is even, then we can change this to base^(expo1+expo2)
    598 */
    599 if( EPSISINT(expo1+expo2, 0.0) && (int)(expo1+expo2)%2 == 0 ) /*lint !e835*/
    600 {
    601 SCIP_CALL( SCIPcreateExprPow(scip, &power, base1, expo1 + expo2, ownercreate, ownercreatedata) );
    602 }
    603 else
    604 {
    605 SCIP_EXPR* absbase;
    606
    607 SCIP_CALL( SCIPcreateExprAbs(scip, &absbase, base1, ownercreate, ownercreatedata) );
    608 SCIP_CALL( SCIPcreateExprPow(scip, &power, absbase, expo1 + expo2, ownercreate, ownercreatedata) );
    609 SCIP_CALL( SCIPreleaseExpr(scip, &absbase) );
    610 }
    611 }
    612
    613 if( power != NULL )
    614 {
    615 /* we have created a new power: simplify again and continue */
    616 SCIP_EXPR* simplifiedpower;
    617
    618 /* call simplifyPow or simplifySignpower */
    619 SCIP_CALL( SCIPcallExprSimplify(scip, power, &simplifiedpower, ownercreate, ownercreatedata) );
    620 SCIP_CALL( SCIPreleaseExpr(scip, &power) );
    621
    622 /* replace tomergenode's expression with simplifiedpower */
    623 SCIP_CALL( SCIPreleaseExpr(scip, &tomergenode->expr) );
    624 tomergenode->expr = simplifiedpower;
    625
    626 *changed = TRUE;
    627
    628 /* move tomergenode to unsimplifiedchildren */
    629 aux = tomergenode;
    630 tomergenode = tomergenode->next;
    631 insertFirstList(aux, unsimplifiedchildren);
    632
    633 /* remove current */
    634 if( current == *finalchildren )
    635 {
    636 assert(previous == NULL);
    637 aux = listPopFirst(finalchildren);
    638 assert(aux == current);
    639 current = *finalchildren;
    640 }
    641 else
    642 {
    643 assert(previous != NULL);
    644 aux = current;
    645 current = current->next;
    646 previous->next = current;
    647 }
    648 SCIP_CALL( freeExprNode(scip, &aux) );
    649
    650 continue;
    651 }
    652 }
    653
    654 /* bases are not the same, or we do not want to merge them
    655 * then expressions cannot be the same
    656 * therefore we need to insert tomergenode in finalchildren
    657 * for this, we need to take care of the order
    658 */
    659 compareres = SCIPcompareExpr(scip, current->expr, tomergenode->expr);
    660 if( compareres == -1 )
    661 {
    662 /* current < tomergenode => move current */
    663 previous = current;
    664 current = current->next;
    665 }
    666 else
    667 {
    668 *changed = TRUE;
    669 assert(compareres == 1);
    670
    671 /* insert: if current is the first node, then insert at beginning; otherwise, insert between previous and current */
    672 if( current == *finalchildren )
    673 {
    674 assert(previous == NULL);
    675 aux = tomergenode;
    676 tomergenode = tomergenode->next;
    677 insertFirstList(aux, finalchildren);
    678 previous = *finalchildren;
    679 }
    680 else
    681 {
    682 assert(previous != NULL);
    683 /* extract */
    684 aux = tomergenode;
    685 tomergenode = tomergenode->next;
    686 /* insert */
    687 previous->next = aux;
    688 aux->next = current;
    689 previous = aux;
    690 }
    691 }
    692 }
    693
    694 /* if all nodes of tomerge were merged, we are done */
    695 if( tomergenode == NULL )
    696 return SCIP_OKAY;
    697
    698 assert(current == NULL);
    699
    700 /* if all nodes of finalchildren were cancelled by nodes of tomerge (i.e., transfered to unsimplifiedchildren),
    701 * then the rest of tomerge is finalchildren
    702 */
    703 if( *finalchildren == NULL )
    704 {
    705 assert(previous == NULL);
    706 *finalchildren = tomergenode;
    707 return SCIP_OKAY;
    708 }
    709
    710 /* there are still nodes of tomerge unmerged; these nodes are larger than finalchildren, so append at end */
    711 assert(previous != NULL && previous->next == NULL);
    712 previous->next = tomergenode;
    713
    714 return SCIP_OKAY;
    715}
    716
    717/** simplifies the given (simplified) exprs so that they can be factors of a simplified product
    718 *
    719 * in particular, it will sort and multiply factors whose product leads to new expressions
    720 */
    721static
    723 SCIP* scip, /**< SCIP data structure */
    724 SCIP_EXPR** exprs, /**< factors to be simplified */
    725 int nexprs, /**< number of factors */
    726 SCIP_Real* simplifiedcoef, /**< buffer to store coefficient of PI exprs; needs to be initialized */
    727 EXPRNODE** finalchildren, /**< expr node list to store the simplified factors */
    728 SCIP_Bool* changed, /**< buffer to store whether some factor changed */
    729 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    730 void* ownercreatedata /**< data to pass to ownercreate */
    731 )
    732{
    733 EXPRNODE* unsimplifiedchildren;
    734
    735 /* set up list of current children (when looking at each of them individually, they are simplified, but as
    736 * children of a product expression they might be unsimplified)
    737 */
    738 unsimplifiedchildren = NULL;
    739 SCIP_CALL( createExprlistFromExprs(scip, exprs, nexprs, &unsimplifiedchildren) );
    740
    741 *changed = FALSE;
    742
    743 /* while there are still children to process */
    744 *finalchildren = NULL;
    745 while( unsimplifiedchildren != NULL )
    746 {
    747 EXPRNODE* tomerge;
    748 EXPRNODE* first;
    749
    750 first = listPopFirst(&unsimplifiedchildren);
    751 assert(first != NULL);
    752
    753#ifdef SIMPLIFY_DEBUG
    754 debugSimplify("simplifying factor:\n");
    755 SCIP_CALL( SCIPprintExpr(scip, first->expr, NULL) );
    756 SCIPinfoMessage(scip, NULL, "\n");
    757#endif
    758
    759 /* enforces SP2, SP7 and SP13 */
    760 tomerge = NULL;
    761 SCIP_CALL( simplifyFactor(scip, first->expr, simplifiedcoef, &tomerge, changed) );
    762
    763 /* enforces SP4 and SP5 note: merge frees (or uses) the nodes of the tomerge list */
    764 SCIP_CALL( mergeProductExprlist(scip, tomerge, finalchildren, &unsimplifiedchildren, changed, ownercreate, ownercreatedata) );
    765
    766 /* free first */
    767 SCIP_CALL( freeExprlist(scip, &first) );
    768
    769 /* if the simplified coefficient is 0, we can return value 0 */
    770 if( *simplifiedcoef == 0.0 )
    771 {
    772 *changed = TRUE;
    773 SCIP_CALL( freeExprlist(scip, finalchildren) );
    774 SCIP_CALL( freeExprlist(scip, &unsimplifiedchildren) );
    775 assert(*finalchildren == NULL);
    776 break;
    777 }
    778 }
    779 return SCIP_OKAY;
    780}
    781
    782/* make sure product has at least two children
    783 * - if it is empty; return value
    784 * - if it has one child and coef = 1; return child
    785 * - if it has one child and coef != 1; return (sum 0 coef expr)
    786 */
    787static
    789 SCIP* scip, /**< SCIP data structure */
    790 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    791 EXPRNODE* finalchildren, /**< factors of simplified product */
    792 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    793 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    794 void* ownercreatedata /**< data to pass to ownercreate */
    795 )
    796{
    797 /* empty list --> return value */
    798 if( finalchildren == NULL )
    799 {
    800 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, simplifiedcoef, ownercreate, ownercreatedata) );
    801 return SCIP_OKAY;
    802 }
    803
    804 /* one child and coef equal to 1 --> return child */
    805 if( finalchildren->next == NULL && simplifiedcoef == 1.0 )
    806 {
    807 *simplifiedexpr = finalchildren->expr;
    808 SCIPcaptureExpr(*simplifiedexpr);
    809 return SCIP_OKAY;
    810 }
    811
    812 /* one child and coef different from 1 --> return (sum 0 coef child) */
    813 if( finalchildren->next == NULL )
    814 {
    815 SCIP_EXPR* sum;
    816
    817 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, &(finalchildren->expr), &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
    818
    819 /* simplifying here is necessary, the product could have sums as children e.g., (prod 2 (sum 1 <x>))
    820 * -> (sum 0 2 (sum 1 <x>)) and that needs to be simplified to (sum 0 2 <x>)
    821 */
    822 SCIP_CALL( SCIPcallExprSimplify(scip, sum, simplifiedexpr, ownercreate, ownercreatedata) );
    824 return SCIP_OKAY;
    825 }
    826
    827 return SCIP_OKAY;
    828}
    829
    830/** checks if it is entropy expression */
    831static
    833 SCIP* scip, /**< SCIP data structure */
    834 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    835 EXPRNODE* finalchildren, /**< factors of simplified product */
    836 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    837 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    838 void* ownercreatedata /**< data to pass to ownercreate */
    839 )
    840{
    841 SCIP_EXPR* entropicchild = NULL;
    842
    843 if( !(finalchildren != NULL && finalchildren->next != NULL && finalchildren->next->next == NULL) )
    844 return SCIP_OKAY;
    845
    846 /* could be log(expr) * expr, e.g., log(sin(x)) * sin(x) (OR11) */
    847 if( strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(finalchildren->expr)), "log") == 0 )
    848 {
    849 assert(SCIPexprGetNChildren(finalchildren->expr) == 1);
    850 if( 0 == SCIPcompareExpr(scip, SCIPexprGetChildren(finalchildren->expr)[0], finalchildren->next->expr) )
    851 entropicchild = finalchildren->next->expr;
    852 }
    853 /* could be expr * log(expr), e.g., (1 + abs(x)) log(1 + abs(x)) (OR11) */
    854 else if( strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(finalchildren->next->expr)), "log") == 0 )
    855 {
    856 assert(SCIPexprGetNChildren(finalchildren->next->expr) == 1);
    857 if( 0 == SCIPcompareExpr(scip, SCIPexprGetChildren(finalchildren->next->expr)[0], finalchildren->expr) )
    858 entropicchild = finalchildren->expr;
    859 }
    860
    861 /* success --> replace finalchildren by entropy expression */
    862 if( entropicchild != NULL )
    863 {
    864 SCIP_EXPR* entropy;
    865
    866 simplifiedcoef *= -1.0;
    867
    868 SCIP_CALL( SCIPcreateExprEntropy(scip, &entropy, entropicchild, ownercreate, ownercreatedata) );
    869
    870 /* enforces SP8: if simplifiedcoef != 1.0, transform it into a sum with the (simplified) entropy as child */
    871 if( simplifiedcoef != 1.0 )
    872 {
    873 SCIP_CALL( SCIPcreateExprSum(scip, simplifiedexpr, 1, &entropy, &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
    874 SCIP_CALL( SCIPreleaseExpr(scip, &entropy) );
    875 }
    876 else
    877 *simplifiedexpr = entropy;
    878 }
    879
    880 return SCIP_OKAY;
    881}
    882
    883/* expands product of two sums or one sum and another expression
    884 * -) two sums: (prod (sum c1 s1 ... sn) (sum c2 t1 ... tm)
    885 * Builds a sum representing the expansion, where all of its children are simplified, and then simplify the sum
    886 * - constant != 0 --> c1 ti or c2 * sj is simplified (ti, sj are not sums, because they are children of a simplified sum)
    887 * - sj * ti may be not be simplified, so put them in a product list and simplify them from there
    888 * -) one sum: (prod factor (sum c s1 ... sn))
    889 * - c != 0 --> c * factor is simplified (i.e. factor is not sum!)
    890 * - factor * si may be not be simplified, so put them in a product list and simplify them from there
    891 */
    892static
    894 SCIP* scip, /**< SCIP data structure */
    895 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    896 EXPRNODE* finalchildren, /**< factors of simplified product */
    897 SCIP_Bool expandalways, /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    898 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    899 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    900 void* ownercreatedata /**< data to pass to ownercreate */
    901 )
    902{
    903 /* we need only two children */
    904 if( ! (finalchildren != NULL && finalchildren->next != NULL && finalchildren->next->next == NULL) )
    905 return SCIP_OKAY;
    906
    907 /* handle both sums case */
    908 if( SCIPisExprSum(scip, finalchildren->expr) && SCIPisExprSum(scip, finalchildren->next->expr) )
    909 {
    910 SCIP_EXPR* expanded = NULL;
    911 SCIP_Real c1 = SCIPgetConstantExprSum(finalchildren->expr);
    912 SCIP_Real c2 = SCIPgetConstantExprSum(finalchildren->next->expr);
    913 int nchildren1 = SCIPexprGetNChildren(finalchildren->expr);
    914 int nchildren2 = SCIPexprGetNChildren(finalchildren->next->expr);
    915 int j;
    916 int k;
    917
    918#ifdef SIMPLIFY_DEBUG
    919 debugSimplify("Multiplying sum1 * sum2\n");
    920 debugSimplify("sum1: \n");
    921 SCIP_CALL( SCIPprintExpr(scip, finalchildren->expr, NULL) );
    922 SCIPinfoMessage(scip, NULL, "\n");
    923 debugSimplify("sum2: \n");
    924 SCIP_CALL( SCIPprintExpr(scip, finalchildren->next->expr, NULL) );
    925 SCIPinfoMessage(scip, NULL, "\n");
    926#endif
    927 SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 0, NULL, NULL, c1 * c2 * simplifiedcoef, ownercreate, ownercreatedata) );
    928
    929 /* multiply c1 * sum2 */
    930 if( c1 != 0.0 )
    931 {
    932 int i;
    933
    934 for( i = 0; i < nchildren2; ++i )
    935 {
    936 SCIP_EXPR* term;
    937
    938 term = SCIPexprGetChildren(finalchildren->next->expr)[i];
    939 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, SCIPgetCoefsExprSum(finalchildren->next->expr)[i] * c1 * simplifiedcoef) );
    940 /* we are just re-using a child here, so do not release term! */
    941#ifdef SIMPLIFY_DEBUG
    942 debugSimplify("Multiplying %f * summand2_i\n", c1);
    943 debugSimplify("summand2_i: \n");
    944 SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
    945 SCIPinfoMessage(scip, NULL, "\n");
    946#endif
    947 }
    948 }
    949 /* multiply c2 * sum1 */
    950 if( c2 != 0.0 )
    951 {
    952 int i;
    953
    954 for( i = 0; i < nchildren1; ++i )
    955 {
    956 SCIP_EXPR* term;
    957
    958 term = SCIPexprGetChildren(finalchildren->expr)[i];
    959 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, SCIPgetCoefsExprSum(finalchildren->expr)[i] * c2 * simplifiedcoef) );
    960 /* we are just re-using a child here, so do not release term! */
    961#ifdef SIMPLIFY_DEBUG
    962 debugSimplify("Multiplying summand1_i * %f\n", c2);
    963 debugSimplify("summand1_i: \n");
    964 SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
    965 SCIPinfoMessage(scip, NULL, "\n");
    966#endif
    967 }
    968 }
    969 /* multiply sum1 * sum2 without constants */
    970 for( j = 0; j < nchildren1; ++j )
    971 {
    972 SCIP_EXPR* factors[2];
    973 SCIP_Real coef1;
    974
    975 coef1 = SCIPgetCoefsExprSum(finalchildren->expr)[j];
    976 factors[0] = SCIPexprGetChildren(finalchildren->expr)[j];
    977 for( k = 0; k < nchildren2; ++k )
    978 {
    979 EXPRNODE* finalfactors;
    980 SCIP_Real factorscoef;
    981 SCIP_Real coef2;
    982 SCIP_EXPR* term = NULL;
    983 SCIP_Bool dummy;
    984
    985 coef2 = SCIPgetCoefsExprSum(finalchildren->next->expr)[k];
    986 factors[1] = SCIPexprGetChildren(finalchildren->next->expr)[k];
    987
    988#ifdef SIMPLIFY_DEBUG
    989 debugSimplify("multiplying %g expr1 * %g expr2\n", coef1, coef2);
    990 debugSimplify("expr1:\n");
    991 SCIP_CALL( SCIPprintExpr(scip, factors[0], NULL) );
    992 SCIPinfoMessage(scip, NULL, "\n");
    993 debugSimplify("expr2\n");
    994 SCIP_CALL( SCIPprintExpr(scip, factors[1], NULL) );
    995 SCIPinfoMessage(scip, NULL, "\n");
    996#endif
    997
    998 factorscoef = coef1 * coef2;
    999 SCIP_CALL( simplifyMultiplyChildren(scip, factors, 2, &factorscoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1000 assert(factorscoef != 0.0);
    1001
    1002#ifdef SIMPLIFY_DEBUG
    1003 {
    1004 EXPRNODE* node;
    1005 int i;
    1006
    1007 debugSimplify("Building product from simplified factors\n");
    1008 node = finalfactors;
    1009 i = 0;
    1010 while( node != NULL )
    1011 {
    1012 debugSimplify("factor %d (nuses %d):\n", i, SCIPexprGetNUses(node->expr));
    1013 SCIP_CALL( SCIPprintExpr(scip, node->expr, NULL) );
    1014 SCIPinfoMessage(scip, NULL, "\n");
    1015 node = node->next;
    1016 i++;
    1017 }
    1018 }
    1019#endif
    1020
    1021 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, expandalways, TRUE, &term, ownercreate, ownercreatedata) );
    1022 assert(finalfactors == NULL);
    1023 assert(term != NULL);
    1024
    1025#ifdef SIMPLIFY_DEBUG
    1026 debugSimplify("%g expr1 * %g expr2 = %g * product\n", coef1, coef2, coef1 * coef2);
    1027 debugSimplify("product: (nused %d)\n", SCIPexprGetNUses(term));
    1028 SCIP_CALL( SCIPprintExpr(scip, term, NULL) );
    1029 SCIPinfoMessage(scip, NULL, "\n");
    1030#endif
    1031
    1032 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, factorscoef * simplifiedcoef) );
    1033
    1034 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1035 }
    1036 }
    1037
    1038 /* simplify the sum */
    1039 SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
    1040 SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
    1041
    1042 return SCIP_OKAY;
    1043 }
    1044
    1045 /* handle one sum case */
    1046 if( SCIPisExprSum(scip, finalchildren->expr) || SCIPisExprSum(scip, finalchildren->next->expr) )
    1047 {
    1048 SCIP_EXPR* expanded = NULL;
    1049 SCIP_EXPR* factors[2];
    1050 SCIP_EXPR* sum = NULL;
    1051 SCIP_Real constant;
    1052 int nchildren;
    1053 int j;
    1054
    1055 if( SCIPisExprSum(scip, finalchildren->expr) )
    1056 {
    1057 assert(!SCIPisExprSum(scip, finalchildren->next->expr));
    1058 sum = finalchildren->expr;
    1059 factors[0] = finalchildren->next->expr;
    1060 }
    1061 else
    1062 {
    1063 assert(!SCIPisExprSum(scip, finalchildren->expr));
    1064 sum = finalchildren->next->expr;
    1065 factors[0] = finalchildren->expr;
    1066 }
    1067 constant = simplifiedcoef * SCIPgetConstantExprSum(sum);
    1068 nchildren = SCIPexprGetNChildren(sum);
    1069
    1070 SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 1, &factors[0], &constant, 0.0, ownercreate, ownercreatedata) );
    1071 /* we are just re-using a child here, so do not release factor! */
    1072
    1073 for( j = 0; j < nchildren; ++j )
    1074 {
    1075 SCIP_Real coef;
    1076 SCIP_Real termcoef;
    1077 SCIP_Bool dummy;
    1078 EXPRNODE* finalfactors;
    1079 SCIP_EXPR* term = NULL;
    1080
    1081 coef = SCIPgetCoefsExprSum(sum)[j];
    1082 factors[1] = SCIPexprGetChildren(sum)[j];
    1083
    1084 termcoef = coef;
    1085 SCIP_CALL( simplifyMultiplyChildren(scip, factors, 2, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1086 assert(termcoef != 0.0);
    1087
    1088 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, expandalways, TRUE, &term, ownercreate, ownercreatedata) );
    1089 assert(finalfactors == NULL);
    1090 assert(term != NULL);
    1091
    1092 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef) );
    1093 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1094 }
    1095
    1096 /* simplify the sum */
    1097 SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
    1098 SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
    1099 }
    1100
    1101 return SCIP_OKAY;
    1102}
    1103
    1104/* expands product of one sum and other expressions
    1105 * -) (prod factor ... factor (sum c s1 ... sn) factor ... factor )
    1106 * - c != 0 --> c * factor is simplified (i.e. factor is not sum!)
    1107 * - factor ... factor * si may be not be simplified, so put them in a product list and simplify them from there
    1108 */
    1109static
    1111 SCIP* scip, /**< SCIP data structure */
    1112 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * prod simplifiedfactors */
    1113 EXPRNODE* finalchildren, /**< factors of simplified product */
    1114 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    1115 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1116 void* ownercreatedata /**< data to pass to ownercreate */
    1117 )
    1118{
    1119 EXPRNODE* sum_node = NULL;
    1120 EXPRNODE* n;
    1121 int nfactors = 0;
    1122 SCIP_EXPR** factors;
    1123 int nchildren;
    1124 SCIP_EXPR* expanded;
    1125 int j;
    1126
    1127 /* check whether there is exactly one sum, calc number of factors */
    1128 for( n = finalchildren; n != NULL; n = n->next )
    1129 {
    1130 if( SCIPisExprSum(scip, n->expr) )
    1131 {
    1132 if( sum_node == NULL )
    1133 sum_node = n;
    1134 else
    1135 return SCIP_OKAY; /* more than one sum */
    1136 }
    1137 else
    1138 {
    1139 ++nfactors;
    1140 }
    1141 }
    1142 if( sum_node == NULL || nfactors == 0 ) /* no sum or no other factors */
    1143 return SCIP_OKAY;
    1144
    1145 /* collect exprs of all factors other than the sum */
    1146 SCIP_CALL( SCIPallocBufferArray(scip, &factors, nfactors + 1) );
    1147 for( n = finalchildren, j = 0; n != NULL; n = n->next )
    1148 if( n != sum_node )
    1149 factors[j++] = n->expr;
    1150
    1151 /* build new sum expression */
    1152 nchildren = SCIPexprGetNChildren(sum_node->expr);
    1153 SCIP_CALL( SCIPcreateExprSum(scip, &expanded, 0, NULL, NULL, 0.0, ownercreate, ownercreatedata) );
    1154
    1155 /* handle constant-from-sum * factors */
    1156 if( SCIPgetConstantExprSum(sum_node->expr) != 0.0 )
    1157 {
    1158 if( nfactors == 1 )
    1159 {
    1160 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, factors[0], simplifiedcoef * SCIPgetConstantExprSum(sum_node->expr)) );
    1161 }
    1162 else
    1163 {
    1164 SCIP_Real termcoef = 1.0;
    1165 SCIP_Bool dummy;
    1166 EXPRNODE* finalfactors;
    1167 SCIP_EXPR* term = NULL;
    1168
    1169 SCIP_CALL( simplifyMultiplyChildren(scip, factors, nfactors, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1170 assert(termcoef != 0.0);
    1171
    1172 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, TRUE, TRUE, &term, ownercreate, ownercreatedata) );
    1173 assert(finalfactors == NULL);
    1174 assert(term != NULL);
    1175
    1176 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef * SCIPgetConstantExprSum(sum_node->expr)) );
    1177 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1178 }
    1179 }
    1180
    1181 for( j = 0; j < nchildren; ++j )
    1182 {
    1183 SCIP_Real coef;
    1184 SCIP_Real termcoef;
    1185 SCIP_Bool dummy;
    1186 EXPRNODE* finalfactors;
    1187 SCIP_EXPR* term = NULL;
    1188
    1189 coef = SCIPgetCoefsExprSum(sum_node->expr)[j];
    1190 factors[nfactors] = SCIPexprGetChildren(sum_node->expr)[j];
    1191
    1192 termcoef = coef;
    1193 SCIP_CALL( simplifyMultiplyChildren(scip, factors, nfactors + 1, &termcoef, &finalfactors, &dummy, ownercreate, ownercreatedata) );
    1194 assert(termcoef != 0.0);
    1195
    1196 SCIP_CALL( buildSimplifiedProduct(scip, 1.0, &finalfactors, TRUE, TRUE, &term, ownercreate, ownercreatedata) );
    1197 assert(finalfactors == NULL);
    1198 assert(term != NULL);
    1199
    1200 SCIP_CALL( SCIPappendExprSumExpr(scip, expanded, term, termcoef * simplifiedcoef) );
    1201 SCIP_CALL( SCIPreleaseExpr(scip, &term) );
    1202 }
    1203
    1204 /* simplify the sum */
    1205 SCIP_CALL( SCIPcallExprSimplify(scip, expanded, simplifiedexpr, ownercreate, ownercreatedata) );
    1206 SCIP_CALL( SCIPreleaseExpr(scip, &expanded) );
    1207
    1208 SCIPfreeBufferArray(scip, &factors);
    1209
    1210 return SCIP_OKAY;
    1211}
    1212
    1213/** builds a simplified product from simplifiedfactors
    1214 *
    1215 * @note this function also releases simplifiedfactors
    1216 */
    1217static
    1219 SCIP* scip, /**< SCIP data structure */
    1220 SCIP_Real simplifiedcoef, /**< simplified product should be simplifiedcoef * PI simplifiedfactors */
    1221 EXPRNODE** simplifiedfactors, /**< factors of simplified product */
    1222 SCIP_Bool expandalways, /**< whether to expand products of a sum and several factors in simplify (SP12b) */
    1223 SCIP_Bool changed, /**< indicates whether some of the simplified factors was changed */
    1224 SCIP_EXPR** simplifiedexpr, /**< buffer to store the simplified expression */
    1225 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
    1226 void* ownercreatedata /**< data to pass to ownercreate */
    1227 )
    1228{
    1229 EXPRNODE* finalchildren = *simplifiedfactors;
    1230
    1231 /* build product expression from finalchildren and post-simplify */
    1232 debugSimplify("[simplifyProduct] finalchildren has length %d\n", listLength(finalchildren));
    1233
    1234 *simplifiedexpr = NULL;
    1235
    1236 SCIP_CALL( enforceSP11(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
    1237 if( *simplifiedexpr != NULL )
    1238 goto CLEANUP;
    1239
    1240 SCIP_CALL( enforceSP12(scip, simplifiedcoef, *simplifiedfactors, expandalways, simplifiedexpr, ownercreate, ownercreatedata) );
    1241 if( *simplifiedexpr != NULL )
    1242 goto CLEANUP;
    1243
    1244 if( expandalways )
    1245 {
    1246 SCIP_CALL( enforceSP12b(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
    1247 if( *simplifiedexpr != NULL )
    1248 goto CLEANUP;
    1249 }
    1250
    1251 SCIP_CALL( enforceSP10(scip, simplifiedcoef, *simplifiedfactors, simplifiedexpr, ownercreate, ownercreatedata) );
    1252 if( *simplifiedexpr != NULL )
    1253 goto CLEANUP;
    1254
    1255 /* enforces SP8: if simplifiedcoef != 1.0, transform it into a sum with the (simplified) product as child */
    1256 if( simplifiedcoef != 1.0 )
    1257 {
    1258 SCIP_EXPR* aux;
    1259 SCIP_EXPR* sum;
    1260
    1261 /* create sum */
    1262 SCIP_CALL( createExprProductFromExprlist(scip, finalchildren, 1.0, &aux, ownercreate, ownercreatedata) );
    1263 SCIP_CALL( SCIPcreateExprSum(scip, &sum, 1, &aux, &simplifiedcoef, 0.0, ownercreate, ownercreatedata) );
    1264 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
    1265
    1266 /* simplify sum */
    1267 SCIP_CALL( SCIPcallExprSimplify(scip, sum, simplifiedexpr, ownercreate, ownercreatedata) );
    1268 SCIP_CALL( SCIPreleaseExpr(scip, &sum) );
    1269
    1270 goto CLEANUP;
    1271 }
    1272
    1273 /* build product expression from list */
    1274 if( changed )
    1275 {
    1276 SCIP_CALL( createExprProductFromExprlist(scip, finalchildren, simplifiedcoef, simplifiedexpr, ownercreate, ownercreatedata) );
    1277 goto CLEANUP;
    1278 }
    1279
    1280CLEANUP:
    1281
    1282 SCIP_CALL( freeExprlist(scip, simplifiedfactors) );
    1283 return SCIP_OKAY;
    1284}
    1285
    1286/** computes an estimator for a product as a vertex polyhedral function
    1287 *
    1288 * Since the product is multilinear, its convex and concave envelopes are piecewise linear.
    1289 */
    1290static
    1292 SCIP* scip, /**< SCIP data structure */
    1293 SCIP_CONSHDLR* conshdlr, /**< nonlinear constraint handler */
    1294 int nfactors, /**< number of factors */
    1295 SCIP_INTERVAL* bounds, /**< bound for each factor */
    1296 SCIP_Real constantfactor, /**< another constant factor */
    1297 SCIP_Real* refpoint, /**< reference point where to estimate, or NULL if called from initestimates */
    1298 SCIP_Bool overestimate, /**< should estimator overestimate expr (TRUE) or underestimate (FALSE) */
    1299 SCIP_Real targetvalue, /**< no need to compute facet if value in xstar would be worse than target value */
    1300 SCIP_Real* coefs, /**< array to store cut coefficients */
    1301 SCIP_Real* constant, /**< pointer to store cut constant */
    1302 SCIP_Bool* success /**< pointer to store whether estimation was successful */
    1303 )
    1304{
    1305 SCIP_Real* box;
    1306 SCIP_Real* xstar;
    1307 int nfixed;
    1308 int i;
    1309
    1310 assert(conshdlr != NULL);
    1311 assert(nfactors > 0);
    1312 assert(bounds != NULL);
    1313 assert(constantfactor != 0.0);
    1314 assert(coefs != NULL);
    1315 assert(constant != NULL);
    1316 assert(success != NULL);
    1317
    1318 *success = FALSE;
    1319
    1320 /* assemble box, check for unbounded variables, assemble xstar */
    1321 SCIP_CALL( SCIPallocBufferArray(scip, &box, 2*nfactors) );
    1322 SCIP_CALL( SCIPallocBufferArray(scip, &xstar, nfactors) );
    1323 for( i = 0, nfixed = 0; i < nfactors; ++i )
    1324 {
    1325 assert(!SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, bounds[i]));
    1326
    1327 if( SCIPisInfinity(scip, -bounds[i].inf) || SCIPisInfinity(scip, bounds[i].sup) )
    1328 {
    1329 SCIPdebugMsg(scip, "a factor is unbounded, no cut is possible\n");
    1330 goto CLEANUP;
    1331 }
    1332
    1333 box[2*i] = bounds[i].inf;
    1334 box[2*i+1] = bounds[i].sup;
    1335
    1336 xstar[i] = refpoint != NULL ? refpoint[i] : 0.5 * (box[2*i] + box[2*i+1]);
    1337
    1338 if( SCIPisRelEQ(scip, box[2*i], box[2*i+1]) )
    1339 ++nfixed;
    1340 }
    1341
    1342 if( nfixed < nfactors && nfactors - nfixed <= SCIP_MAXVERTEXPOLYDIM )
    1343 {
    1345 overestimate, prodfunction, &constantfactor, xstar, box, nfactors, targetvalue, success, coefs, constant) );
    1346 }
    1347
    1348CLEANUP:
    1349 SCIPfreeBufferArray(scip, &xstar);
    1351
    1352 return SCIP_OKAY;
    1353}
    1354
    1355/*
    1356 * Callback methods of expression handler
    1357 */
    1358
    1359/** simplifies a product expression
    1360 *
    1361 * Summary: we first build a list of expressions (called finalchildren) which will be the children of the simplified product
    1362 * and then we process this list in order to enforce SP8 and SP10.
    1363 *
    1364 * Description: In order to build finalchildren, we first build a list of unsimplified children (called unsimplifiedchildren)
    1365 * with the children of the product. Each node of the list is manipulated (see simplifyFactor) in order to satisfy
    1366 * SP2 and SP7 as follows:
    1367 * - SP7: if the node's expression is a value, multiply the value to the products's coef
    1368 * - SP2: if the node's expression is a product, then build a list with the child's children
    1369 *
    1370 * Then, we merge the built list (or the simplified node) into finalchildren. While merging, nodes from finalchildren
    1371 * can go back to unsimplifiedchildren for further processing (see mergeProductExprlist() for more details).
    1372 * After building finalchildren, we create the simplified product out of it, taking care that SP8 and SP10 are satisfied
    1373 */
    1374static
    1376{ /*lint --e{715}*/
    1377 EXPRNODE* finalchildren;
    1378 SCIP_Real simplifiedcoef;
    1379 SCIP_Bool changed;
    1380
    1381 assert(expr != NULL);
    1382 assert(simplifiedexpr != NULL);
    1383
    1384 simplifiedcoef = SCIPgetCoefExprProduct(expr);
    1385
    1386#ifdef SIMPLIFY_DEBUG
    1387 debugSimplify("Simplifying expr:\n");
    1389 SCIPinfoMessage(scip, NULL, "\n");
    1390 debugSimplify("First multiplying children\n");
    1391#endif
    1392
    1393 /* simplify and multiply factors */
    1395 &finalchildren, &changed, ownercreate, ownercreatedata) );
    1396
    1397#ifdef SIMPLIFY_DEBUG
    1398 {
    1399 EXPRNODE* node;
    1400 int i;
    1401
    1402 debugSimplify("Building product from simplified factors\n");
    1403 node = finalchildren;
    1404 i = 0;
    1405 while( node != NULL )
    1406 {
    1407 debugSimplify("factor %d:\n", i);
    1408 SCIP_CALL( SCIPprintExpr(scip, node->expr, NULL) );
    1409 SCIPinfoMessage(scip, NULL, "\n");
    1410 node = node->next;
    1411 i++;
    1412 }
    1413 }
    1414#endif
    1415
    1416 /* get simplified product from simplified factors in finalchildren */
    1417 SCIP_CALL( buildSimplifiedProduct(scip, simplifiedcoef, &finalchildren, SCIPexprhdlrGetData(SCIPexprGetHdlr(expr))->expandalways, changed, simplifiedexpr, ownercreate,
    1418 ownercreatedata) );
    1419 assert(finalchildren == NULL);
    1420
    1421 if( *simplifiedexpr == NULL )
    1422 {
    1423 *simplifiedexpr = expr;
    1424
    1425 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
    1426 SCIPcaptureExpr(*simplifiedexpr);
    1427 }
    1428 assert(*simplifiedexpr != NULL);
    1429
    1430 return SCIP_OKAY;
    1431}
    1432
    1433/** compare two product expressions
    1434 *
    1435 * The order of two product expressions, u and v, is a lexicographical order on the factors.
    1436 *
    1437 * Starting from the *last*, we find the first child where they differ, say, the i-th.
    1438 * Then u < v <=> u_i < v_i.
    1439 * If there is no such children and they have different number of children, then u < v <=> nchildren(u) < nchildren(v).
    1440 * If all children are the same and they have the same number of children, then u < v <=> coeff(u) < coeff(v).
    1441 * Otherwise, they are the same.
    1442 *
    1443 * Note: we are assuming expression are simplified, so within u, we have u_1 < u_2, etc.
    1444 *
    1445 * Example: y * z < x * y * z
    1446 */
    1447static
    1449{ /*lint --e{715}*/
    1450 int compareresult;
    1451 int i;
    1452 int j;
    1453 int nchildren1;
    1454 int nchildren2;
    1455 SCIP_EXPR** children1;
    1456 SCIP_EXPR** children2;
    1457
    1458 nchildren1 = SCIPexprGetNChildren(expr1);
    1459 nchildren2 = SCIPexprGetNChildren(expr2);
    1460 children1 = SCIPexprGetChildren(expr1);
    1461 children2 = SCIPexprGetChildren(expr2);
    1462
    1463 for( i = nchildren1 - 1, j = nchildren2 - 1; i >= 0 && j >= 0; --i, --j )
    1464 {
    1465 compareresult = SCIPcompareExpr(scip, children1[i], children2[j]);
    1466 if( compareresult != 0 )
    1467 return compareresult;
    1468 /* expressions are equal, continue */
    1469 }
    1470
    1471 /* all children of one expression are children of the other expression, use number of children as a tie-breaker */
    1472 if( i < j )
    1473 {
    1474 assert(i == -1);
    1475 /* expr1 has less elements, hence expr1 < expr2 */
    1476 return -1;
    1477 }
    1478 if( i > j )
    1479 {
    1480 assert(j == -1);
    1481 /* expr1 has more elements, hence expr1 > expr2 */
    1482 return 1;
    1483 }
    1484
    1485 /* everything is equal, use coefficient as tie-breaker */
    1486 assert(i == -1 && j == -1);
    1488 return -1;
    1490 return 1;
    1491
    1492 /* they are equal */
    1493 return 0;
    1494}
    1495
    1496/** expression handler copy callback */
    1497static
    1499{ /*lint --e{715}*/
    1501
    1502 return SCIP_OKAY;
    1503}
    1504
    1505/** expression handler free callback */
    1506static
    1508{ /*lint --e{715}*/
    1509 assert(scip != NULL);
    1510 assert(exprhdlr != NULL);
    1511 assert(exprhdlrdata != NULL);
    1512 assert(*exprhdlrdata != NULL);
    1513
    1514 SCIPfreeBlockMemory(scip, exprhdlrdata);
    1515 assert(*exprhdlrdata == NULL);
    1516
    1517 return SCIP_OKAY;
    1518}
    1519
    1520/** expression data copy callback */
    1521static
    1523{ /*lint --e{715}*/
    1524 SCIP_EXPRDATA* sourceexprdata;
    1525
    1526 assert(targetexprdata != NULL);
    1527 assert(sourceexpr != NULL);
    1528
    1529 sourceexprdata = SCIPexprGetData(sourceexpr);
    1530 assert(sourceexprdata != NULL);
    1531
    1532 SCIP_CALL( SCIPduplicateBlockMemory(targetscip, targetexprdata, sourceexprdata) );
    1533
    1534 return SCIP_OKAY;
    1535}
    1536
    1537/** expression data free callback */
    1538static
    1540{ /*lint --e{715}*/
    1541 SCIP_EXPRDATA* exprdata;
    1542
    1543 assert(expr != NULL);
    1544
    1545 exprdata = SCIPexprGetData(expr);
    1546 assert(exprdata != NULL);
    1547
    1548 SCIPfreeBlockMemory(scip, &exprdata);
    1549
    1551
    1552 return SCIP_OKAY;
    1553}
    1554
    1555/** expression print callback */
    1556static
    1558{ /*lint --e{715}*/
    1559 SCIP_EXPRDATA* exprdata;
    1560
    1561 assert(expr != NULL);
    1562
    1563 exprdata = SCIPexprGetData(expr);
    1564 assert(exprdata != NULL);
    1565
    1566 switch( stage )
    1567 {
    1569 {
    1570 /* print opening parenthesis, if necessary */
    1571 if( EXPRHDLR_PRECEDENCE <= parentprecedence )
    1572 {
    1573 SCIPinfoMessage(scip, file, "(");
    1574 }
    1575
    1576 /* print coefficient, if not one */
    1577 if( exprdata->coefficient != 1.0 )
    1578 {
    1579 if( exprdata->coefficient < 0.0 && EXPRHDLR_PRECEDENCE > parentprecedence )
    1580 {
    1581 SCIPinfoMessage(scip, file, "(%.15g)", exprdata->coefficient);
    1582 }
    1583 else
    1584 {
    1585 SCIPinfoMessage(scip, file, "%.15g", exprdata->coefficient);
    1586 }
    1587 }
    1588 break;
    1589 }
    1590
    1592 {
    1593 /* print multiplication sign, if not first factor */
    1594 if( exprdata->coefficient != 1.0 || currentchild > 0 )
    1595 {
    1596 SCIPinfoMessage(scip, file, "*");
    1597 }
    1598 break;
    1599 }
    1600
    1602 {
    1603 break;
    1604 }
    1605
    1607 {
    1608 /* print closing parenthesis, if necessary */
    1609 if( EXPRHDLR_PRECEDENCE <= parentprecedence )
    1610 {
    1611 SCIPinfoMessage(scip, file, ")");
    1612 }
    1613 break;
    1614 }
    1615
    1616 default:
    1617 /* all stages should have been covered above */
    1618 SCIPABORT();
    1619 }
    1620
    1621 return SCIP_OKAY;
    1622}
    1623
    1624/** product hash callback */
    1625static
    1627{ /*lint --e{715}*/
    1628 SCIP_EXPRDATA* exprdata;
    1629 int c;
    1630
    1631 assert(scip != NULL);
    1632 assert(expr != NULL);
    1633 assert(hashkey != NULL);
    1634 assert(childrenhashes != NULL);
    1635
    1636 exprdata = SCIPexprGetData(expr);
    1637 assert(exprdata != NULL);
    1638
    1639 *hashkey = EXPRHDLR_HASHKEY;
    1640 *hashkey ^= SCIPcalcFibHash(exprdata->coefficient);
    1641
    1642 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1643 *hashkey ^= childrenhashes[c];
    1644
    1645 return SCIP_OKAY;
    1646}
    1647
    1648/** expression point evaluation callback */
    1649static
    1651{ /*lint --e{715}*/
    1652 SCIP_EXPRDATA* exprdata;
    1653 SCIP_Real childval;
    1654 int c;
    1655
    1656 assert(expr != NULL);
    1657
    1658 exprdata = SCIPexprGetData(expr);
    1659 assert(exprdata != NULL);
    1660
    1661 *val = exprdata->coefficient;
    1662 for( c = 0; c < SCIPexprGetNChildren(expr) && (*val != 0.0); ++c )
    1663 {
    1665 assert(childval != SCIP_INVALID);
    1666
    1667 *val *= childval;
    1668 }
    1669
    1670 return SCIP_OKAY;
    1671}
    1672
    1673/** derivative evaluation callback computing <gradient, children.dot>
    1674 *
    1675 * 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$.
    1676 */
    1677static
    1679{ /*lint --e{715}*/
    1680 int c;
    1681
    1682 assert(expr != NULL);
    1683 assert(dot != NULL);
    1684
    1685 assert(SCIPexprGetData(expr) != NULL);
    1686
    1687 /* TODO add special handling for nchildren == 2 */
    1688
    1689 /**! [SnippetExprFwdiffProduct] */
    1690 *dot = 0.0;
    1691 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1692 {
    1693 SCIP_EXPR* child;
    1694
    1695 child = SCIPexprGetChildren(expr)[c];
    1696
    1697 assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
    1698 assert(SCIPexprGetDot(child) != SCIP_INVALID);
    1699
    1700 if( SCIPexprGetDot(child) == 0.0 )
    1701 continue;
    1702
    1703 if( SCIPexprGetEvalValue(child) != 0.0 )
    1705 else
    1706 {
    1707 SCIP_Real partial;
    1708 int i;
    1709
    1710 partial = SCIPexprGetData(expr)->coefficient;
    1711 for( i = 0; i < SCIPexprGetNChildren(expr) && (partial != 0.0); ++i )
    1712 {
    1713 if( i == c )
    1714 continue;
    1715
    1717 }
    1718 *dot += partial * SCIPexprGetDot(child);
    1719 }
    1720 }
    1721 /**! [SnippetExprFwdiffProduct] */
    1722
    1723 return SCIP_OKAY;
    1724}
    1725
    1726/** expression backward forward derivative evaluation callback
    1727 *
    1728 * Computes \f$\frac{\partial}{\partial \text{childidx}} ( \langle \text{gradient}, \text{children.dot}\rangle )\f$.
    1729 *
    1730 * If expr is \f$\prod_i x_i\f$, and childidx is \f$k\f$ then computes
    1731 * \f$\partial_k \sum_j \prod_{i \neq j} x_i x^{\text{dot}}_j
    1732 * = \sum_{j \neq k} \prod_{i \neq j, k} x_i x^{\text{dot}}_j\f$
    1733 */
    1734static
    1736{ /*lint --e{715}*/
    1737 SCIP_EXPR* partialchild;
    1738 int c;
    1739
    1740 assert(expr != NULL);
    1741 assert(bardot != NULL);
    1742 assert(SCIPexprGetData(expr) != NULL);
    1743 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
    1744
    1745 partialchild = SCIPexprGetChildren(expr)[childidx];
    1746 assert(partialchild != NULL);
    1747 assert(!SCIPisExprValue(scip, partialchild));
    1748 assert(SCIPexprGetEvalValue(partialchild) != SCIP_INVALID);
    1749
    1750 /* TODO add special handling for nchildren == 2 */
    1751
    1752 /**! [SnippetExprBwfwdiffProduct] */
    1753 *bardot = 0.0;
    1754 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1755 {
    1756 SCIP_EXPR* child;
    1757
    1758 if( c == childidx )
    1759 continue;
    1760
    1761 child = SCIPexprGetChildren(expr)[c];
    1762
    1763 assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
    1764 assert(SCIPexprGetDot(child) != SCIP_INVALID);
    1765
    1766 if( SCIPexprGetDot(child) == 0.0 )
    1767 continue;
    1768
    1769 if( SCIPexprGetEvalValue(child) != 0.0 && SCIPexprGetEvalValue(partialchild) != 0.0 )
    1770 *bardot += SCIPexprGetEvalValue(expr) / (SCIPexprGetEvalValue(child) * SCIPexprGetEvalValue(partialchild)) * SCIPexprGetDot(child);
    1771 else
    1772 {
    1773 SCIP_Real partial;
    1774 int i;
    1775
    1776 partial = SCIPexprGetData(expr)->coefficient;
    1777 for( i = 0; i < SCIPexprGetNChildren(expr) && (partial != 0.0); ++i )
    1778 {
    1779 if( i == c || i == childidx )
    1780 continue;
    1781
    1783 }
    1784 *bardot += partial * SCIPexprGetDot(child);
    1785 }
    1786 }
    1787 /**! [SnippetExprBwfwdiffProduct] */
    1788
    1789 return SCIP_OKAY;
    1790}
    1791
    1792/** expression derivative evaluation callback */
    1793static
    1795{ /*lint --e{715}*/
    1796 SCIP_EXPR* child;
    1797
    1798 assert(expr != NULL);
    1799 assert(SCIPexprGetData(expr) != NULL);
    1800 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
    1801
    1802 child = SCIPexprGetChildren(expr)[childidx];
    1803 assert(child != NULL);
    1804 assert(!SCIPisExprValue(scip, child));
    1805 assert(SCIPexprGetEvalValue(child) != SCIP_INVALID);
    1806
    1807 /* TODO add special handling for nchildren == 2 */
    1808
    1809 /**! [SnippetExprBwdiffProduct] */
    1810 if( !SCIPisZero(scip, SCIPexprGetEvalValue(child)) )
    1811 {
    1813 }
    1814 else
    1815 {
    1816 int i;
    1817
    1818 *val = SCIPexprGetData(expr)->coefficient;
    1819 for( i = 0; i < SCIPexprGetNChildren(expr) && (*val != 0.0); ++i )
    1820 {
    1821 if( i == childidx )
    1822 continue;
    1823
    1825 }
    1826 }
    1827 /**! [SnippetExprBwdiffProduct] */
    1828
    1829 return SCIP_OKAY;
    1830}
    1831
    1832/** expression interval evaluation callback */
    1833static
    1835{ /*lint --e{715}*/
    1836 SCIP_EXPRDATA* exprdata;
    1837 int c;
    1838
    1839 assert(expr != NULL);
    1840
    1841 exprdata = SCIPexprGetData(expr);
    1842 assert(exprdata != NULL);
    1843
    1844 /**! [SnippetExprIntevalProduct] */
    1845 SCIPintervalSet(interval, exprdata->coefficient);
    1846
    1847 SCIPdebugMsg(scip, "inteval %p with %d children: %.20g", (void*)expr, SCIPexprGetNChildren(expr), exprdata->coefficient);
    1848
    1849 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1850 {
    1851 SCIP_INTERVAL childinterval;
    1852
    1853 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[c]);
    1854 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
    1855 {
    1856 SCIPintervalSetEmpty(interval);
    1857 break;
    1858 }
    1859
    1860 /* multiply childinterval with the so far computed interval */
    1861 SCIPintervalMul(SCIP_INTERVAL_INFINITY, interval, *interval, childinterval);
    1862
    1863 SCIPdebugMsgPrint(scip, " *[%.20g,%.20g]", childinterval.inf, childinterval.sup);
    1864 }
    1865 SCIPdebugMsgPrint(scip, " = [%.20g,%.20g]\n", interval->inf, interval->sup);
    1866 /**! [SnippetExprIntevalProduct] */
    1867
    1868 return SCIP_OKAY;
    1869}
    1870
    1871/** estimates a multilinear function of the form \f$ f(x) := a \prod_{i = 1}^n x_i \f$
    1872 *
    1873 * \f$ x_i \f$ are the auxiliary variables of the children.
    1874 * If !overestimate, then we look for an affine underestimator of \f$ f(x) \f$ which has a value above targetvalue at \f$ x^* \f$,
    1875 * 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$.
    1876 *
    1877 * Since \f$ f(x) \f$ is componentwise linear, its convex envelope is piecewise linear and its value can be computed by
    1878 * finding the largest affine underestimator.
    1879 * This is done either explicitly (if n=2) or by solving an LP, see SCIPcomputeFacetVertexPolyhedralNonlinear().
    1880 */
    1881static
    1883{ /*lint --e{715}*/
    1884 SCIP_EXPRDATA* exprdata;
    1885 int nchildren;
    1886
    1887 assert(scip != NULL);
    1888 assert(expr != NULL);
    1889 assert(refpoint != NULL);
    1890 assert(coefs != NULL);
    1891 assert(constant != NULL);
    1892 assert(islocal != NULL);
    1893 assert(branchcand != NULL);
    1894 assert(*branchcand == TRUE);
    1895 assert(success != NULL);
    1896
    1898
    1899 exprdata = SCIPexprGetData(expr);
    1900 assert(exprdata != NULL);
    1901
    1902 *success = FALSE;
    1903 *islocal = TRUE;
    1904
    1905 nchildren = SCIPexprGetNChildren(expr);
    1906
    1907 /* debug output: prints expression we are trying to estimate, bounds of variables and point */
    1908#ifdef SCIP_DEBUG
    1909 {
    1910 int c;
    1911
    1912 SCIPdebugMsg(scip, "%sestimating product with %d variables\n", overestimate ? "over": "under", SCIPexprGetNChildren(expr));
    1913 for( c = 0; c < SCIPexprGetNChildren(expr); ++c )
    1914 {
    1915 SCIPdebugMsg(scip, "child %d = %g in [%g, %g]\n", c, refpoint[c], localbounds[c].inf, localbounds[c].sup);
    1916
    1917 if( SCIPisInfinity(scip, localbounds[c].sup) || SCIPisInfinity(scip, -localbounds[c].inf) )
    1918 {
    1919 SCIPdebugMsg(scip, "unbounded factor related to\n");
    1921 }
    1922 }
    1923 }
    1924#endif
    1925
    1926 /* bilinear term */
    1927 if( nchildren == 2 )
    1928 {
    1929 SCIP_Real refpointx;
    1930 SCIP_Real refpointy;
    1931 SCIP_INTERVAL bndx;
    1932 SCIP_INTERVAL bndy;
    1933
    1934 /* collect first variable */
    1935 refpointx = refpoint[0];
    1936 bndx = localbounds[0];
    1938
    1939 /* collect second variable */
    1940 refpointy = refpoint[1];
    1941 bndy = localbounds[1];
    1943
    1944 /* adjust the reference points */
    1945 refpointx = MIN(MAX(refpointx, bndx.inf), bndx.sup);
    1946 refpointy = MIN(MAX(refpointy, bndy.inf), bndy.sup);
    1947
    1948 coefs[0] = 0.0;
    1949 coefs[1] = 0.0;
    1950 *constant = 0.0;
    1951 *success = TRUE;
    1952
    1953 SCIPaddBilinMcCormick(scip, exprdata->coefficient, bndx.inf, bndx.sup, refpointx,
    1954 bndy.inf, bndy.sup, refpointy, overestimate, &coefs[0], &coefs[1], constant,
    1955 success);
    1956 }
    1957 else
    1958 {
    1959 SCIP_EXPRHDLRDATA* exprhdlrdata;
    1960
    1961 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
    1962 assert(exprhdlrdata != NULL);
    1963
    1964 if( exprhdlrdata->conshdlr != NULL )
    1965 {
    1966 SCIP_CALL( estimateVertexPolyhedralProduct(scip, exprhdlrdata->conshdlr, nchildren, localbounds, exprdata->coefficient, refpoint, overestimate,
    1967 targetvalue, coefs, constant, success) );
    1968 }
    1969 else
    1970 {
    1971 SCIPdebugMsg(scip, "no cons_nonlinear included in SCIP, cannot estimate vertex-polyhedral product function\n");
    1972 }
    1973 }
    1974
    1975 return SCIP_OKAY;
    1976}
    1977
    1978/** initial estimators callback */
    1979static
    1980SCIP_DECL_EXPRINITESTIMATES(initestimatesProduct)
    1981{
    1982 SCIP_EXPRDATA* exprdata;
    1983 SCIP_Bool success = TRUE;
    1984 int nchildren;
    1985
    1986 assert(scip != NULL);
    1987 assert(expr != NULL);
    1988 assert(nreturned != NULL);
    1989
    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:257
    #define EPSISINT(x, eps)
    Definition: def.h:204
    #define SCIP_INVALID
    Definition: def.h:187
    #define SCIP_INTERVAL_INFINITY
    Definition: def.h:189
    #define SCIP_Bool
    Definition: def.h:100
    #define MIN(x, y)
    Definition: def.h:233
    #define SCIP_STRINGEQ(name, reference, retcode)
    Definition: def.h:454
    #define SCIP_Real
    Definition: def.h:165
    #define TRUE
    Definition: def.h:102
    #define FALSE
    Definition: def.h:103
    #define MAX(x, y)
    Definition: def.h:229
    #define SCIPABORT()
    Definition: def.h:336
    #define SCIP_CALL(x)
    Definition: def.h:364
    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:161
    static SCIP_DECL_EXPRCURVATURE(curvatureProduct)
    static SCIP_DECL_EXPRESTIMATE(estimateProduct)
    #define debugSimplify
    Definition: expr_product.c:61
    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:832
    #define EXPRHDLR_HASHKEY
    Definition: expr_product.c:52
    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:893
    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:788
    static SCIP_DECL_EXPRFREEDATA(freedataProduct)
    #define EXPRHDLR_NAME
    Definition: expr_product.c:49
    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:310
    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:267
    static SCIP_DECL_EXPRINITESTIMATES(initestimatesProduct)
    static SCIP_RETCODE createExprNode(SCIP *scip, SCIP_EXPR *expr, EXPRNODE **newnode)
    Definition: expr_product.c:179
    static EXPRNODE * listPopFirst(EXPRNODE **list)
    Definition: expr_product.c:141
    static SCIP_DECL_EXPRCOPYDATA(copydataProduct)
    static void insertFirstList(EXPRNODE *newnode, EXPRNODE **list)
    Definition: expr_product.c:127
    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:722
    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:238
    static SCIP_RETCODE freeExprNode(SCIP *scip, EXPRNODE **node)
    Definition: expr_product.c:223
    static SCIP_DECL_EXPRBWFWDIFF(bwfwdiffProduct)
    static SCIP_DECL_EXPRINTEGRALITY(integralityProduct)
    #define EXPRHDLR_DESC
    Definition: expr_product.c:50
    static SCIP_DECL_EXPRCOMPARE(compareProduct)
    #define EXPRHDLR_PRECEDENCE
    Definition: expr_product.c:51
    static SCIP_DECL_VERTEXPOLYFUN(prodfunction)
    Definition: expr_product.c:99
    static SCIP_RETCODE createExprlistFromExprs(SCIP *scip, SCIP_EXPR **exprs, int nexprs, EXPRNODE **list)
    Definition: expr_product.c:196
    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:390
    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:3210
    SCIP_Bool SCIPisExprExp(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_exp.c:529
    SCIP_RETCODE SCIPcreateExprExp(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
    Definition: expr_exp.c:511
    SCIP_Bool SCIPisExprSignpower(SCIP *scip, SCIP_EXPR *expr)
    Definition: expr_pow.c:3235
    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:686
    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:3186
    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:3449
    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:88
    SCIP_EXPR * expr
    Definition: expr_product.c:87
    #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
    @ SCIP_INVALIDCALL
    Definition: type_retcode.h:51
    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