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