Scippy

SCIP

Solving Constraint Integer Programs

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