SCIP Doxygen Documentation
Loading...
Searching...
No Matches
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 {
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
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
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);
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
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);
1800 assert(childidx >= 0 && childidx < SCIPexprGetNChildren(expr));
1801
1802 child = SCIPexprGetChildren(expr)[childidx];
1803 assert(child != NULL);
1804 assert(!SCIPisExprValue(scip, child));
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);
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);
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);
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
2173
2174 if( SCIPintervalGetSup(interval) <= 0.0 )
2175 nneg++;
2176 else if( SCIPintervalGetInf(interval) < 0.0 )
2177 {
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 {
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
#define EXPRHDLR_HASHKEY
Definition expr_abs.c:41
#define EXPRHDLR_NAME
Definition expr_abs.c:38
#define EXPRHDLR_DESC
Definition expr_abs.c:39
#define EXPRHDLR_PRECEDENCE
Definition expr_abs.c:40
absolute expression handler
handler for -x*log(x) expressions
exponential expression handler
power and signed power expression handlers
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)
#define debugSimplify
static SCIP_RETCODE enforceSP11(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
static SCIP_RETCODE enforceSP12(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_Bool expandalways, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
static SCIP_RETCODE enforceSP10(SCIP *scip, SCIP_Real simplifiedcoef, EXPRNODE *finalchildren, SCIP_EXPR **simplifiedexpr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
static SCIP_RETCODE simplifyFactor(SCIP *scip, SCIP_EXPR *factor, SCIP_Real *simplifiedcoef, EXPRNODE **simplifiedfactor, SCIP_Bool *changed)
static SCIP_RETCODE createExprProductFromExprlist(SCIP *scip, EXPRNODE *exprlist, SCIP_Real coef, SCIP_EXPR **expr, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
static SCIP_RETCODE createExprNode(SCIP *scip, SCIP_EXPR *expr, EXPRNODE **newnode)
static EXPRNODE * listPopFirst(EXPRNODE **list)
static void insertFirstList(EXPRNODE *newnode, EXPRNODE **list)
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)
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)
static SCIP_RETCODE freeExprNode(SCIP *scip, EXPRNODE **node)
static SCIP_RETCODE createExprlistFromExprs(SCIP *scip, SCIP_EXPR **exprs, int nexprs, EXPRNODE **list)
static SCIP_RETCODE mergeProductExprlist(SCIP *scip, EXPRNODE *tomerge, EXPRNODE **finalchildren, EXPRNODE **unsimplifiedchildren, SCIP_Bool *changed, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
struct exprnode EXPRNODE
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)
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_DECL_VERTEXPOLYFUN(f)
#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)
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,...)
#define SCIPdebugMsgPrint
#define SCIPdebugMsg
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 SCIPexprhdlrSetCompare(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:462
void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:440
void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:418
SCIP_EXPRHDLR * SCIPgetExprhdlrProduct(SCIP *scip)
Definition scip_expr.c:939
SCIP_EXPRHDLRDATA * SCIPexprhdlrGetData(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:575
void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:488
void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:429
void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:510
void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:451
void SCIPexprhdlrSetGetSymdata(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:521
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 SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:499
void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)),)
Definition expr.c:473
void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)),)
Definition expr.c:370
void SCIPexprhdlrSetPrint(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:396
void SCIPexprhdlrSetCopyFreeData(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYDATA((*copydata)),)
Definition expr.c:383
void SCIPexprhdlrSetEstimate(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINITESTIMATES((*initestimates)),)
Definition expr.c:532
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)
struct SCIP_Interval SCIP_INTERVAL
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)
return SCIP_OKAY
int c
assert(minobj< SCIPgetCutoffbound(scip))
bilinear nonlinear handler
public functions to work with algebraic expressions
public data structures and miscellaneous methods
SCIP_Real sup
SCIP_Real inf
structs for symmetry computations
struct exprnode * next
SCIP_EXPR * expr
struct SCIP_Conshdlr SCIP_CONSHDLR
Definition type_cons.h:62
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
#define SCIP_DECL_EXPR_OWNERCREATE(x)
Definition type_expr.h:143
#define SCIP_DECL_EXPRREVERSEPROP(x)
Definition type_expr.h:659
#define SCIP_DECL_EXPRINITESTIMATES(x)
Definition type_expr.h:610
#define SCIP_DECL_EXPRBWFWDIFF(x)
Definition type_expr.h:522
#define SCIP_DECL_EXPRCURVATURE(x)
Definition type_expr.h:340
struct SCIP_ExprhdlrData SCIP_EXPRHDLRDATA
Definition type_expr.h:195
struct SCIP_ExprData SCIP_EXPRDATA
Definition type_expr.h:54
#define SCIP_DECL_EXPRFREEDATA(x)
Definition type_expr.h:268
#define SCIP_DECL_EXPRBWDIFF(x)
Definition type_expr.h:451
#define SCIP_DECL_EXPRINTEVAL(x)
Definition type_expr.h:541
#define SCIP_DECL_EXPRMONOTONICITY(x)
Definition type_expr.h:358
#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
struct SCIP_Exprhdlr SCIP_EXPRHDLR
Definition type_expr.h:194
#define SCIP_DECL_EXPRCOMPARE(x)
Definition type_expr.h:412
#define SCIP_DECL_EXPRSIMPLIFY(x)
Definition type_expr.h:634
#define SCIP_DECL_EXPREVAL(x)
Definition type_expr.h:428
#define SCIP_DECL_EXPRFWDIFF(x)
Definition type_expr.h:482
#define SCIP_DECL_EXPRHASH(x)
Definition type_expr.h:393
#define SCIP_DECL_EXPRCOPYHDLR(x)
Definition type_expr.h:210
#define SCIP_DECL_EXPRPRINT(x)
Definition type_expr.h:289
#define SCIP_DECL_EXPRFREEHDLR(x)
Definition type_expr.h:224
#define SCIP_DECL_EXPRINTEGRALITY(x)
Definition type_expr.h:377
#define SCIP_EXPRITER_VISITEDCHILD
Definition type_expr.h:696
#define SCIP_DECL_EXPRGETSYMDATA(x)
Definition type_expr.h:674
#define SCIP_DECL_EXPRCOPYDATA(x)
Definition type_expr.h:249
#define SCIP_EXPRITER_LEAVEEXPR
Definition type_expr.h:697
#define SCIP_DECL_EXPRESTIMATE(x)
Definition type_expr.h:577
#define SCIP_EXPRITER_ENTEREXPR
Definition type_expr.h:694
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106