SCIP Doxygen Documentation
Loading...
Searching...
No Matches
expr_pow.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_pow.c
26 * @ingroup DEFPLUGINS_EXPR
27 * @brief power expression handler
28 * @author Benjamin Mueller
29 * @author Ksenia Bestuzheva
30 *
31 * @todo signpower for exponent < 1 ?
32 */
33
34/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
36/*lint --e{835}*/
37/*lint -e777*/
38
39#include "scip/expr_pow.h"
40#include "scip/pub_expr.h"
41#include "scip/expr_value.h"
42#include "scip/expr_product.h"
43#include "scip/expr_sum.h"
44#include "scip/expr_exp.h"
45#include "scip/expr_abs.h"
47
48#define POWEXPRHDLR_NAME "pow"
49#define POWEXPRHDLR_DESC "power expression"
50#define POWEXPRHDLR_PRECEDENCE 55000
51#define POWEXPRHDLR_HASHKEY SCIPcalcFibHash(21163.0)
52
53#define SIGNPOWEXPRHDLR_NAME "signpower"
54#define SIGNPOWEXPRHDLR_DESC "signed power expression"
55#define SIGNPOWEXPRHDLR_PRECEDENCE 56000
56#define SIGNPOWEXPRHDLR_HASHKEY SCIPcalcFibHash(21163.1)
57
58#define INITLPMAXPOWVAL 1e+06 /**< maximal allowed absolute value of power expression at bound,
59 * used for adjusting bounds in the convex case in initestimates */
60
61/*
62 * Data structures
63 */
64
65/** sign of a value (-1 or +1)
66 *
67 * 0.0 has sign +1 here (shouldn't matter, though)
68 */
69#define SIGN(x) ((x) >= 0.0 ? 1.0 : -1.0)
70
71#define SIGNPOW_ROOTS_KNOWN 10 /**< up to which (integer) exponents precomputed roots have been stored */
72
73/** The positive root of the polynomial (n-1) y^n + n y^(n-1) - 1 is needed in separation.
74 * Here we store these roots for small integer values of n.
75 */
76static
78 -1.0, /* no root for n=0 */
79 -1.0, /* no root for n=1 */
80 0.41421356237309504880, /* root for n=2 (-1+sqrt(2)) */
81 0.5, /* root for n=3 */
82 0.56042566045031785945, /* root for n=4 */
83 0.60582958618826802099, /* root for n=5 */
84 0.64146546982884663257, /* root for n=6 */
85 0.67033204760309682774, /* root for n=7 */
86 0.69428385661425826738, /* root for n=8 */
87 0.71453772716733489700, /* root for n=9 */
88 0.73192937842370733350 /* root for n=10 */
89};
90
91/** expression handler data */
92struct SCIP_ExprhdlrData
93{
94 SCIP_Real minzerodistance; /**< minimal distance from zero to enforce for child in bound tightening */
95 int expandmaxexponent; /**< maximal exponent when to expand power of sum in simplify */
96 SCIP_Bool distribfracexponent;/**< whether a fractional exponent is distributed onto factors on power of product */
97
98 SCIP_Bool warnedonpole; /**< whether we warned on enforcing a minimal distance from zero for child */
99};
100
101/** expression data */
102struct SCIP_ExprData
103{
104 SCIP_Real exponent; /**< exponent */
105 SCIP_Real root; /**< positive root of (n-1) y^n + n y^(n-1) - 1, or
106 SCIP_INVALID if not computed yet */
107};
108
109/*
110 * Local methods
111 */
112
113/** computes positive root of the polynomial (n-1) y^n + n y^(n-1) - 1 for n > 1 */
114static
116 SCIP* scip, /**< SCIP data structure */
117 SCIP_Real* root, /**< buffer where to store computed root */
118 SCIP_Real exponent /**< exponent n */
119 )
120{
121 SCIP_Real polyval;
122 SCIP_Real gradval;
123 int iter;
124
125 assert(scip != NULL);
126 assert(exponent > 1.0);
127 assert(root != NULL);
128
129 /* lookup for popular integer exponent */
130 if( SCIPisIntegral(scip, exponent) && exponent-0.5 < SIGNPOW_ROOTS_KNOWN )
131 {
132 *root = signpow_roots[(int)SCIPfloor(scip, exponent+0.5)];
133 return SCIP_OKAY;
134 }
135
136 /* lookup for weymouth exponent */
137 if( SCIPisEQ(scip, exponent, 1.852) )
138 {
139 *root = 0.39821689389382575186;
140 return SCIP_OKAY;
141 }
142
143 /* search for a positive root of (n-1) y^n + n y^(n-1) - 1
144 * use the closest precomputed root as starting value
145 */
146 if( exponent >= SIGNPOW_ROOTS_KNOWN )
148 else if( exponent <= 2.0 )
149 *root = signpow_roots[2];
150 else
151 *root = signpow_roots[(int)SCIPfloor(scip, exponent)];
152
153 for( iter = 0; iter < 1000; ++iter )
154 {
155 polyval = (exponent - 1.0) * pow(*root, exponent) + exponent * pow(*root, exponent - 1.0) - 1.0;
156 if( fabs(polyval) < 1e-12 && SCIPisZero(scip, polyval) )
157 break;
158
159 /* gradient of (n-1) y^n + n y^(n-1) - 1 is n(n-1)y^(n-1) + n(n-1)y^(n-2) */
160 gradval = (exponent - 1.0) * exponent * (pow(*root, exponent - 1.0) + pow(*root, exponent - 2.0));
161 if( SCIPisZero(scip, gradval) )
162 break;
163
164 /* update root by adding -polyval/gradval (Newton's method) */
165 *root -= polyval / gradval;
166 if( *root < 0.0 )
167 *root = 0.0;
168 }
169
170 if( !SCIPisZero(scip, polyval) )
171 {
172 SCIPerrorMessage("failed to compute root for exponent %g\n", exponent);
173 return SCIP_ERROR;
174 }
175 SCIPdebugMsg(scip, "root for %g is %.20g, certainty = %g\n", exponent, *root, polyval);
176 /* @todo cache root value for other expressions (an exponent seldom comes alone)?? (they are actually really fast to compute...) */
177
178 return SCIP_OKAY;
179}
180
181/** computes negative root of the polynomial (n-1) y^n - n y^(n-1) + 1 for n < -1 */
182static
184 SCIP* scip, /**< SCIP data structure */
185 SCIP_Real* root, /**< buffer where to store computed root */
186 SCIP_Real exponent /**< exponent n */
187 )
188{
189 SCIP_Real polyval;
190 SCIP_Real gradval;
191 int iter;
192
193 assert(scip != NULL);
194 assert(exponent < -1.0);
195 assert(root != NULL);
196
197 *root = -2.0; /* that's the solution for n=-2 */
198
199 for( iter = 0; iter < 1000; ++iter )
200 {
201 polyval = (exponent - 1.0) * pow(*root, exponent) - exponent * pow(*root, exponent - 1.0) + 1.0;
202 if( fabs(polyval) < 1e-12 && SCIPisZero(scip, polyval) )
203 break;
204
205 /* gradient of (n-1) y^n - n y^(n-1) + 1 is n(n-1)y^(n-1) - n(n-1)y^(n-2) */
206 gradval = (exponent - 1.0) * exponent * (pow(*root, exponent - 1.0) - pow(*root, exponent - 2.0));
207 if( SCIPisZero(scip, gradval) )
208 break;
209
210 /* update root by adding -polyval/gradval (Newton's method) */
211 *root -= polyval / gradval;
212 if( *root >= 0.0 )
213 *root = -1;
214 }
215
216 if( !SCIPisZero(scip, polyval) )
217 {
218 SCIPerrorMessage("failed to compute root for exponent %g\n", exponent);
219 return SCIP_ERROR;
220 }
221 SCIPdebugMsg(scip, "root for %g is %.20g, certainty = %g\n", exponent, *root, polyval);
222 /* @todo cache root value for other expressions (an exponent seldom comes alone)?? (they are actually really fast to compute...) */
223
224 return SCIP_OKAY;
225}
226
227/** creates expression data */
228static
230 SCIP* scip, /**< SCIP data structure */
231 SCIP_EXPRDATA** exprdata, /**< pointer where to store expression data */
232 SCIP_Real exponent /**< exponent of the power expression */
233 )
234{
235 assert(exprdata != NULL);
236
237 SCIP_CALL( SCIPallocBlockMemory(scip, exprdata) );
238
239 (*exprdata)->exponent = exponent;
240 (*exprdata)->root = SCIP_INVALID;
241
242 return SCIP_OKAY;
243}
244
245/** computes a tangent at a reference point by linearization
246 *
247 * for a normal power, linearization in xref is xref^exponent + exponent * xref^(exponent-1) (x - xref)
248 * = (1-exponent) * xref^exponent + exponent * xref^(exponent-1) * x
249 *
250 * for a signpower, linearization is the same if xref is positive
251 * for xref negative it is -(-xref)^exponent + exponent * (-xref)^(exponent-1) (x-xref)
252 * = (1-exponent) * (-xref)^(exponent-1) * xref + exponent * (-xref)^(exponent-1) * x
253 */
254static
256 SCIP* scip, /**< SCIP data structure */
257 SCIP_Bool signpower, /**< are we signpower or normal power */
258 SCIP_Real exponent, /**< exponent */
259 SCIP_Real xref, /**< reference point where to linearize */
260 SCIP_Real* constant, /**< buffer to store constant term of secant */
261 SCIP_Real* slope, /**< buffer to store slope of secant */
262 SCIP_Bool* success /**< buffer to store whether secant could be computed */
263 )
264{
265 SCIP_Real xrefpow;
266
267 assert(scip != NULL);
268 assert(constant != NULL);
269 assert(slope != NULL);
270 assert(success != NULL);
271 assert(xref != 0.0 || exponent > 0.0);
272 /* non-integral exponent -> reference point must be >= 0 or we do signpower */
273 assert(EPSISINT(exponent, 0.0) || signpower || !SCIPisNegative(scip, xref));
274
275 /* TODO power is not differentiable at 0.0 for exponent < 0
276 * should we forbid here that xref > 0, do something smart here, or just return success=FALSE?
277 */
278 /* assert(exponent >= 1.0 || xref > 0.0); */
279
280 if( !EPSISINT(exponent, 0.0) && !signpower && xref < 0.0 )
281 xref = 0.0;
282
283 xrefpow = pow(signpower ? REALABS(xref) : xref, exponent - 1.0);
284
285 /* if huge xref and/or exponent too large, then pow may overflow */
286 if( !SCIPisFinite(xrefpow) )
287 {
288 *success = FALSE;
289 return;
290 }
291
292 *constant = (1.0 - exponent) * xrefpow * xref;
293 *slope = exponent * xrefpow;
294 *success = TRUE;
295}
296
297/** computes a secant between lower and upper bound
298 *
299 * secant is xlb^exponent + (xub^exponent - xlb^exponent) / (xub - xlb) * (x - xlb)
300 * = xlb^exponent - slope * xlb + slope * x with slope = (xub^exponent - xlb^exponent) / (xub - xlb)
301 * same if signpower
302 */
303static
305 SCIP* scip, /**< SCIP data structure */
306 SCIP_Bool signpower, /**< are we signpower or normal power */
307 SCIP_Real exponent, /**< exponent */
308 SCIP_Real xlb, /**< lower bound on x */
309 SCIP_Real xub, /**< upper bound on x */
310 SCIP_Real* constant, /**< buffer to store constant term of secant */
311 SCIP_Real* slope, /**< buffer to store slope of secant */
312 SCIP_Bool* success /**< buffer to store whether secant could be computed */
313 )
314{
315 assert(scip != NULL);
316 assert(constant != NULL);
317 assert(slope != NULL);
318 assert(success != NULL);
319 assert(xlb >= 0.0 || EPSISINT(exponent, 0.0) || signpower);
320 assert(xub >= 0.0 || EPSISINT(exponent, 0.0) || signpower);
321 assert(exponent != 1.0);
322
323 *success = FALSE;
324
325 /* infinite bounds will not work */
326 if( SCIPisInfinity(scip, -xlb) || SCIPisInfinity(scip, xub) )
327 return;
328
329 /* first handle some special cases */
330 if( xlb == xub )
331 {
332 /* usually taken care of in separatePointPow already, but we might be called with different bounds here,
333 * e.g., when handling odd or signed power
334 */
335 *slope = 0.0;
336 *constant = pow(xlb, exponent);
337 }
338 else if( EPSISINT(exponent / 2.0, 0.0) && !signpower && xub > 0.1 && SCIPisFeasEQ(scip, xlb, -xub) )
339 {
340 /* for normal power with even exponents with xlb ~ -xub the slope would be very close to 0
341 * since xub^n - xlb^n is prone to cancellation here, we omit computing this secant (it's probably useless)
342 * unless the bounds are close to 0 as well (xub <= 0.1 in the "if" above)
343 * or we have exactly xlb=-xub, where we can return a clean 0.0 (though it's probably useless)
344 */
345 if( xlb == -xub )
346 {
347 *slope = 0.0;
348 *constant = pow(xlb, exponent);
349 }
350 else
351 {
352 return;
353 }
354 }
355 else if( xlb == 0.0 && exponent > 0.0 )
356 {
357 assert(xub >= 0.0);
358 *slope = pow(xub, exponent-1.0);
359 *constant = 0.0;
360 }
361 else if( xub == 0.0 && exponent > 0.0 )
362 {
363 /* normal pow: slope = - xlb^exponent / (-xlb) = xlb^(exponent-1)
364 * signpower: slope = (-xlb)^exponent / (-xlb) = (-xlb)^(exponent-1)
365 */
366 assert(xlb <= 0.0); /* so signpower or exponent is integral */
367 if( signpower )
368 *slope = pow(-xlb, exponent-1.0);
369 else
370 *slope = pow(xlb, exponent-1.0);
371 *constant = 0.0;
372 }
373 else if( SCIPisEQ(scip, xlb, xub) && (!signpower || xlb >= 0.0 || xub <= 0.0) )
374 {
375 /* Computing the slope as (xub^n - xlb^n)/(xub-xlb) can lead to cancellation.
376 * To avoid this, we replace xub^n by a Taylor expansion of pow at xlb:
377 * xub^n = xlb^n + n xlb^(n-1) (xub-xlb) + 0.5 n*(n-1) xlb^(n-2) (xub-xlb)^2 + 1/6 n*(n-1)*(n-2) xi^(n-3) (xub-xlb)^3 for some xlb < xi < xub
378 * Dropping the last term, the slope is (with an error of O((xub-xlb)^2) = 1e-18)
379 * n*xlb^(n-1) + 0.5 n*(n-1) xlb^(n-2)*(xub-xlb)
380 * = n*xlb^(n-1) (1 - 0.5*(n-1)) + 0.5 n*(n-1) xlb^(n-2)*xub
381 * = 0.5*n*((3-n)*xlb^(n-1) + (n-1) xlb^(n-2)*xub)
382 *
383 * test n=2: 0.5*2*((3-2)*xlb + (2-1) 1*xub) = xlb + xub ok
384 * n=3: 0.5*3*((3-3)*xlb + (3-1) xlb*xub) = 3*xlb*xub ~ xlb^2 + xlb*xub + xub^2 ok
385 *
386 * The constant is
387 * xlb^n - 0.5*n*((3-n) xlb^(n-1) + (n-1) xlb^(n-2)*xub) * xlb
388 * = xlb^n - 0.5*n*(3-n) xlb^n - 0.5*n*(n-1) xlb^(n-1)*xub
389 * = (1-0.5*n*(3-n)) xlb^n - 0.5 n*(n-1) xlb^(n-1) xub
390 *
391 * test n=2: (1-0.5*2*(3-2)) xlb^2 - 0.5 2*(2-1) xlb xub = -xlb*xub
392 * old formula: xlb^2 - (xlb+xub) * xlb = -xlb*xub ok
393 *
394 * For signpower with xub <= 0, we can negate xlb and xub:
395 * slope: (sign(xub)|xub|^n - sign(xlb)*|xlb|^n) / (xub-xlb) = -((-xub)^n - (-xlb)^n) / (xub - xlb) = ((-xub)^n - (-xlb)^n) / (-xub - (-xlb))
396 * constant: sign(xlb)|xlb|^n + slope * (xub - xlb) = -((-xlb)^n - slope * (xub - xlb)) = -((-xlb)^n + slope * ((-xub) - (-xlb)))
397 */
398 SCIP_Real xlb_n; /* xlb^n */
399 SCIP_Real xlb_n1; /* xlb^(n-1) */
400 SCIP_Real xlb_n2; /* xlb^(n-2) */
401
402 if( signpower && xub <= 0.0 )
403 {
404 xlb *= -1.0;
405 xub *= -1.0;
406 }
407
408 xlb_n = pow(xlb, exponent);
409 xlb_n1 = pow(xlb, exponent - 1.0);
410 xlb_n2 = pow(xlb, exponent - 2.0);
411
412 *slope = 0.5*exponent * ((3.0-exponent) * xlb_n1 + (exponent-1.0) * xlb_n2 * xub);
413 *constant = (1.0 - 0.5*exponent*(3.0-exponent)) * xlb_n - 0.5*exponent*(exponent-1.0) * xlb_n1 * xub;
414
415 if( signpower && xub <= 0.0 )
416 *constant *= -1.0;
417 }
418 else
419 {
420 SCIP_Real lbval;
421 SCIP_Real ubval;
422
423 if( signpower )
424 lbval = SIGN(xlb) * pow(REALABS(xlb), exponent);
425 else
426 lbval = pow(xlb, exponent);
427 if( !SCIPisFinite(lbval) )
428 return;
429
430 if( signpower )
431 ubval = SIGN(xub) * pow(REALABS(xub), exponent);
432 else
433 ubval = pow(xub, exponent);
434 if( !SCIPisFinite(ubval) )
435 return;
436
437 /* we still can have bad numerics when xlb^exponent and xub^exponent are very close, but xlb and xub are not
438 * for now, only check that things did not cancel out completely
439 */
440 if( lbval == ubval )
441 return;
442
443 *slope = (ubval - lbval) / (xub - xlb);
444 *constant = lbval - *slope * xlb;
445 }
446
447 /* check whether we had overflows */
448 if( !SCIPisFinite(*slope) || !SCIPisFinite(*constant) )
449 return;
450
451 *success = TRUE;
452}
453
454/** Separation for parabola
455 *
456 * - even positive powers: x^2, x^4, x^6 with x arbitrary, or
457 * - positive powers > 1: x^1.5, x^2.5 with x >= 0
458 <pre>
459 100 +--------------------------------------------------------------------+
460 |* + + + *|
461 90 |** x**2 ********|
462 | * * |
463 80 |-+* *+-|
464 | ** ** |
465 70 |-+ * * +-|
466 | ** ** |
467 60 |-+ * * +-|
468 | ** ** |
469 50 |-+ * * +-|
470 | ** ** |
471 40 |-+ * * +-|
472 | ** ** |
473 30 |-+ ** ** +-|
474 | ** ** |
475 20 |-+ ** ** +-|
476 | *** *** |
477 10 |-+ *** *** +-|
478 | + ***** + ***** + |
479 0 +--------------------------------------------------------------------+
480 -10 -5 0 5 10
481 </pre>
482 */
483static
485 SCIP* scip, /**< SCIP data structure */
486 SCIP_Real exponent, /**< exponent */
487 SCIP_Bool overestimate, /**< should the power be overestimated? */
488 SCIP_Real xlb, /**< lower bound on x */
489 SCIP_Real xub, /**< upper bound on x */
490 SCIP_Real xref, /**< reference point (where to linearize) */
491 SCIP_Real* constant, /**< buffer to store constant term of estimator */
492 SCIP_Real* slope, /**< buffer to store slope of estimator */
493 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
494 * it depends on given bounds */
495 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
496 )
497{
498 assert(scip != NULL);
499 assert(constant != NULL);
500 assert(slope != NULL);
501 assert(islocal != NULL);
502 assert(success != NULL);
503 assert((exponent >= 0.0 && EPSISINT(exponent/2.0, 0.0)) || (exponent > 1.0 && xlb >= 0.0));
504
505 if( !overestimate )
506 {
507 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
508 *islocal = FALSE;
509 }
510 else
511 {
512 /* overestimation -> secant */
513 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
514 *islocal = TRUE;
515 }
516}
517
518
519/** Separation for signpower
520 *
521 * - odd positive powers, x^3, x^5, x^7
522 * - sign(x)|x|^n for n > 1
523 * - lower bound on x is negative (otherwise one should use separation for parabola)
524 <pre>
525 100 +--------------------------------------------------------------------+
526 | + + + **|
527 | x*abs(x) ******* |
528 | ** |
529 | ** |
530 50 |-+ *** +-|
531 | *** |
532 | *** |
533 | ***** |
534 | ***** |
535 0 |-+ **************** +-|
536 | ***** |
537 | ***** |
538 | *** |
539 | *** |
540 -50 |-+ *** +-|
541 | ** |
542 | ** |
543 | ** |
544 |** + + + |
545 -100 +--------------------------------------------------------------------+
546 -10 -5 0 5 10
547 </pre>
548 */
549static
551 SCIP* scip, /**< SCIP data structure */
552 SCIP_Real exponent, /**< exponent */
553 SCIP_Real root, /**< positive root of the polynomial (n-1) y^n + n y^(n-1) - 1,
554 * if xubglobal > 0 */
555 SCIP_Bool overestimate, /**< should the power be overestimated? */
556 SCIP_Real xlb, /**< lower bound on x, assumed to be non-positive */
557 SCIP_Real xub, /**< upper bound on x */
558 SCIP_Real xref, /**< reference point (where to linearize) */
559 SCIP_Real xlbglobal, /**< global lower bound on x */
560 SCIP_Real xubglobal, /**< global upper bound on x */
561 SCIP_Real* constant, /**< buffer to store constant term of estimator */
562 SCIP_Real* slope, /**< buffer to store slope of estimator */
563 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
564 * it depends on given bounds */
565 SCIP_Bool* branchcand, /**< buffer to indicate whether estimator would improve by branching
566 * on it */
567 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
568 )
569{
570 assert(scip != NULL);
571 assert(constant != NULL);
572 assert(slope != NULL);
573 assert(islocal != NULL);
574 assert(branchcand != NULL);
575 assert(*branchcand == TRUE); /* the default */
576 assert(success != NULL);
577 assert(exponent >= 1.0);
578 assert(xlb < 0.0); /* otherwise estimateParabola should have been called */
579 assert(xubglobal <= 0.0 || (root > 0.0 && root < 1.0));
580
581 *success = FALSE;
582
583 if( !SCIPisPositive(scip, xub) )
584 {
585 /* easy case */
586 if( !overestimate )
587 {
588 /* underestimator is secant */
589 computeSecant(scip, TRUE, exponent, xlb, xub, constant, slope, success);
590 *islocal = TRUE;
591 }
592 else
593 {
594 /* overestimator is tangent */
595
596 /* we must linearize left of 0 */
597 if( xref > 0.0 )
598 xref = 0.0;
599
600 computeTangent(scip, TRUE, exponent, xref, constant, slope, success);
601
602 /* if global upper bound is > 0, then the tangent is only valid locally if the reference point is right of
603 * -root*xubglobal
604 */
605 *islocal = SCIPisPositive(scip, xubglobal) && xref > -root * xubglobal;
606
607 /* tangent doesn't move after branching */
608 *branchcand = FALSE;
609 }
610 }
611 else
612 {
613 SCIP_Real c;
614
615 if( !overestimate )
616 {
617 /* compute the special point which decides between secant and tangent */
618 c = -xlb * root;
619
620 if( xref < c )
621 {
622 /* underestimator is secant between xlb and c */
623 computeSecant(scip, TRUE, exponent, xlb, c, constant, slope, success);
624 *islocal = TRUE;
625 }
626 else
627 {
628 /* underestimator is tangent */
629 computeTangent(scip, TRUE, exponent, xref, constant, slope, success);
630
631 /* if reference point is left of -root*xlbglobal (c w.r.t. global bounds),
632 * then tangent is not valid w.r.t. global bounds
633 */
634 *islocal = xref < -root * xlbglobal;
635
636 /* tangent doesn't move after branching */
637 *branchcand = FALSE;
638 }
639 }
640 else
641 {
642 /* compute the special point which decides between secant and tangent */
643 c = -xub * root;
644
645 if( xref <= c )
646 {
647 /* overestimator is tangent */
648 computeTangent(scip, TRUE, exponent, xref, constant, slope, success);
649
650 /* if reference point is right of -root*xubglobal (c w.r.t. global bounds),
651 * then tangent is not valid w.r.t. global bounds
652 */
653 *islocal = xref > -root * xubglobal;
654
655 /* tangent doesn't move after branching */
656 *branchcand = FALSE;
657 }
658 else
659 {
660 /* overestimator is secant */
661 computeSecant(scip, TRUE, exponent, c, xub, constant, slope, success);
662 *islocal = TRUE;
663 }
664 }
665 }
666}
667
668/** Separation for positive hyperbola
669 *
670 * - x^-2, x^-4 with x arbitrary
671 * - x^-0.5, x^-1, x^-1.5, x^-3, x^-5 with x >= 0
672 <pre>
673 5 +----------------------------------------------------------------------+
674 | + * +* + |
675 | * * x**(-2) ******* |
676 4 |-+ * * +-|
677 | * * |
678 | * * |
679 | * * |
680 3 |-+ * * +-|
681 | * * |
682 | * * |
683 2 |-+ * * +-|
684 | * * |
685 | * * |
686 1 |-+ * * +-|
687 | * * |
688 | ** ** |
689 | ********** ********** |
690 0 |******************* *******************|
691 | |
692 | + + + |
693 -1 +----------------------------------------------------------------------+
694 -10 -5 0 5 10
695 </pre>
696 */
697static
699 SCIP* scip, /**< SCIP data structure */
700 SCIP_Real exponent, /**< exponent */
701 SCIP_Real root, /**< negative root of the polynomial (n-1) y^n - n y^(n-1) + 1,
702 * if x has mixed sign (w.r.t. global bounds?) and underestimating */
703 SCIP_Bool overestimate, /**< should the power be overestimated? */
704 SCIP_Real xlb, /**< lower bound on x */
705 SCIP_Real xub, /**< upper bound on x */
706 SCIP_Real xref, /**< reference point (where to linearize) */
707 SCIP_Real xlbglobal, /**< global lower bound on x */
708 SCIP_Real xubglobal, /**< global upper bound on x */
709 SCIP_Real* constant, /**< buffer to store constant term of estimator */
710 SCIP_Real* slope, /**< buffer to store slope of estimator */
711 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
712 * it depends on given bounds */
713 SCIP_Bool* branchcand, /**< buffer to indicate whether estimator would improve by branching
714 * on it */
715 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
716 )
717{
718 assert(scip != NULL);
719 assert(constant != NULL);
720 assert(slope != NULL);
721 assert(islocal != NULL);
722 assert(branchcand != NULL);
723 assert(*branchcand == TRUE); /* the default */
724 assert(success != NULL);
725 assert(exponent < 0.0);
726 assert(EPSISINT(exponent/2.0, 0.0) || xlb >= 0.0);
727
728 *success = FALSE;
729
730 if( !overestimate )
731 {
732 if( xlb >= 0.0 || xub <= 0.0 )
733 {
734 /* underestimate and fixed sign -> tangent */
735
736 /* make sure xref has the same sign as xlb,xub */
737 if( xref < 0.0 && xlb >= 0.0 )
738 xref = xlb;
739 else if( xref > 0.0 && xub <= 0.0 )
740 xref = xub;
741
742 if( SCIPisZero(scip, xref) )
743 {
744 /* estimator would need to have an (essentially) infinite scope
745 * first try to make up a better refpoint
746 */
747 if( xub > 0.0 )
748 {
749 /* thus xlb >= 0.0; stay close to xlb (probably = 0) */
750 if( !SCIPisInfinity(scip, xub) )
751 xref = 0.9 * xlb + 0.1 * xub;
752 else
753 xref = 0.1;
754 }
755 else
756 {
757 /* xub <= 0.0; stay close to xub (probably = 0) */
758 if( !SCIPisInfinity(scip, -xlb) )
759 xref = 0.1 * xlb + 0.9 * xub;
760 else
761 xref = 0.1;
762 }
763
764 /* if still close to 0, then also bounds are close to 0, then just give up */
765 if( SCIPisZero(scip, xref) )
766 return;
767 }
768
769 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
770
771 /* tangent will not change if branching on x (even if only locally valid, see checks below) */
772 *branchcand = FALSE;
773
774 if( EPSISINT(exponent/2.0, 0.0) )
775 {
776 /* for even exponents (as in the picture):
777 * if x has fixed sign globally, then our tangent is also globally valid
778 * however, if x has mixed sign, then it depends on the constellation between reference point and global
779 * bounds, whether the tangent is globally valid (see also the longer discussion for the mixed-sign
780 * underestimator below )
781 */
782 if( xref > 0.0 && xlbglobal < 0.0 )
783 {
784 assert(xubglobal > 0.0); /* since xref > 0.0 */
785 assert(root < 0.0); /* root needs to be given */
786 /* if on right side, then tangent is only locally valid if xref is too much to the left */
787 *islocal = xref < xlbglobal * root;
788 }
789 else if( xref < 0.0 && xubglobal > 0.0 )
790 {
791 assert(xlbglobal < 0.0); /* since xref < 0.0 */
792 assert(root < 0.0); /* root needs to be given */
793 /* if on left side, then tangent is only locally valid if xref is too much to the right */
794 *islocal = xref > xubglobal * root;
795 }
796 else
797 *islocal = FALSE;
798 }
799 else
800 {
801 /* for odd exponents, the tangent is only locally valid if the sign of x is not fixed globally */
802 *islocal = xlbglobal * xubglobal < 0.0;
803 }
804 }
805 else
806 {
807 /* underestimate but mixed sign */
808 if( SCIPisInfinity(scip, -xlb) )
809 {
810 if( SCIPisInfinity(scip, xub) )
811 {
812 /* underestimator is constant 0, but that is globally valid */
813 *constant = 0.0;
814 *slope = 0.0;
815 *islocal = FALSE;
816 *success = TRUE;
817 return;
818 }
819
820 /* switch sign of x (mirror on ordinate) to make left bound finite and use its estimator */
821 estimateHyperbolaPositive(scip, exponent, root, overestimate, -xub, -xlb, -xref, -xubglobal, -xlbglobal,
822 constant, slope, islocal, branchcand, success);
823 if( *success )
824 *slope = -*slope;
825 }
826 else
827 {
828 /* The convex envelope of x^exponent for x in [xlb, infinity] is a line (secant) between xlb and some positive
829 * coordinate xhat, and x^exponent for x > xhat.
830 * Further, on [xlb,xub] with xub < xhat, the convex envelope is the secant between xlb and xub.
831 *
832 * To find xhat, consider the affine-linear function l(x) = xlb^n + c * (x - xlb) where n = exponent
833 * we look for a value of x such that f(x) and l(x) coincide and such that l(x) will be tangent to f(x) on that
834 * point, that is
835 * xhat > 0 such that f(xhat) = l(xhat) and f'(xhat) = l'(xhat)
836 * => xhat^n = xlb^n + c * (xhat - xlb) and n * xhat^(n-1) = c
837 * => xhat^n = xlb^n + n * xhat^n - n * xhat^(n-1) * xlb
838 * => 0 = xlb^n + (n-1) * xhat^n - n * xhat^(n-1) * xlb
839 *
840 * Divide by xlb^n, one gets a polynomial that looks very much like the one for signpower, but a sign is
841 * different (since this is *not signed* power):
842 * 0 = 1 + (n-1) * y^n - n * y^(n-1) where y = xhat/xlb
843 *
844 * The solution y < 0 (because xlb < 0 and we want xhat > 0) is what we expect to be given as "root".
845 */
846 assert(root < 0.0); /* root needs to be given */
847 if( xref <= xlb * root )
848 {
849 /* If the reference point is left of xhat (=xlb*root), then we can take the
850 * secant between xlb and root*xlb (= tangent at root*xlb).
851 * However, if xub < root*xlb, then we can tilt the estimator to be the secant between xlb and xub.
852 */
853 computeSecant(scip, FALSE, exponent, xlb, MIN(xlb * root, xub), constant, slope, success);
854 *islocal = TRUE;
855 }
856 else
857 {
858 /* If reference point is right of xhat, then take the tangent at xref.
859 * This will still be underestimating for x in [xlb,0], too.
860 * The tangent is globally valid, if we had also generated w.r.t. global bounds.
861 */
862 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
863 *islocal = xref < xlbglobal * root;
864 *branchcand = FALSE;
865 }
866 }
867 }
868 }
869 else
870 {
871 /* overestimate and mixed sign -> pole is within domain -> cannot overestimate */
872 if( xlb < 0.0 && xub > 0.0 )
873 return;
874
875 /* overestimate and fixed sign -> secant */
876 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
877 *islocal = TRUE;
878 }
879}
880
881/** Separation for mixed-sign hyperbola
882 *
883 * - x^-1, x^-3, x^-5 without x >= 0 (either x arbitrary or x negative)
884 <pre>
885 +----------------------------------------------------------------------+
886 | + * + |
887 4 |-+ * x**(-1) *******-|
888 | * |
889 | * |
890 | * |
891 2 |-+ * +-|
892 | * |
893 | ** |
894 | ********* |
895 0 |********************* *********************|
896 | ********* |
897 | ** |
898 | * |
899 -2 |-+ * +-|
900 | * |
901 | * |
902 | * |
903 -4 |-+ * +-|
904 | + *+ + |
905 +----------------------------------------------------------------------+
906 -10 -5 0 5 10
907 </pre>
908 */
909static
911 SCIP* scip, /**< SCIP data structure */
912 SCIP_Real exponent, /**< exponent */
913 SCIP_Bool overestimate, /**< should the power be overestimated? */
914 SCIP_Real xlb, /**< lower bound on x */
915 SCIP_Real xub, /**< upper bound on x */
916 SCIP_Real xref, /**< reference point (where to linearize) */
917 SCIP_Real xlbglobal, /**< global lower bound on x */
918 SCIP_Real xubglobal, /**< global upper bound on x */
919 SCIP_Real* constant, /**< buffer to store constant term of estimator */
920 SCIP_Real* slope, /**< buffer to store slope of estimator */
921 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
922 it depends on given bounds */
923 SCIP_Bool* branchcand, /**< buffer to indicate whether estimator would improve by branching
924 on it */
925 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
926 )
927{
928 assert(scip != NULL);
929 assert(constant != NULL);
930 assert(slope != NULL);
931 assert(islocal != NULL);
932 assert(branchcand != NULL);
933 assert(*branchcand == TRUE); /* the default */
934 assert(success != NULL);
935 assert(exponent < 0.0);
936 assert(EPSISINT((exponent-1.0)/2.0, 0.0));
937 assert(xlb < 0.0);
938
939 *success = FALSE;
940
941 if( xub <= 0.0 )
942 {
943 /* x is negative */
944 if( !overestimate )
945 {
946 /* underestimation -> secant */
947 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
948 *islocal = TRUE;
949 }
950 else if( !SCIPisZero(scip, xlb/10.0) )
951 {
952 /* overestimation -> tangent */
953
954 /* need to linearize left of 0 */
955 if( xref > 0.0 )
956 xref = 0.0;
957
958 if( SCIPisZero(scip, xref) )
959 {
960 /* if xref is very close to 0.0, then slope would be infinite
961 * try to move closer to lower bound (if xlb < -10*eps)
962 */
963 if( !SCIPisInfinity(scip, -xlb) )
964 xref = 0.1*xlb + 0.9*xub;
965 else
966 xref = 0.1;
967 }
968
969 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
970
971 /* if x does not have a fixed sign globally, then our tangent is not globally valid
972 * (power is not convex on global domain)
973 */
974 *islocal = xlbglobal * xubglobal < 0.0;
975
976 /* tangent doesn't move by branching */
977 *branchcand = FALSE;
978 }
979 /* else: xlb is very close to zero, xub is <= 0, so slope would be infinite
980 * (for any reference point in [xlb, xub]) -> do not estimate
981 */
982 }
983 /* else: x has mixed sign -> pole is within domain -> cannot estimate */
984}
985
986/** builds an estimator for a power function */
987static
989 SCIP* scip, /**< SCIP data structure */
990 SCIP_EXPRDATA* exprdata, /**< expression data */
991 SCIP_Bool overestimate, /**< is this an overestimator? */
992 SCIP_Real childlb, /**< local lower bound on the child */
993 SCIP_Real childub, /**< local upper bound on the child */
994 SCIP_Real childglb, /**< global lower bound on the child */
995 SCIP_Real childgub, /**< global upper bound on the child */
996 SCIP_Bool childintegral, /**< whether child is integral */
997 SCIP_Real refpoint, /**< reference point */
998 SCIP_Real exponent, /**< esponent */
999 SCIP_Real* coef, /**< pointer to store the coefficient of the estimator */
1000 SCIP_Real* constant, /**< pointer to store the constant of the estimator */
1001 SCIP_Bool* success, /**< pointer to store whether the estimator was built successfully */
1002 SCIP_Bool* islocal, /**< pointer to store whether the estimator is valid w.r.t. local bounds
1003 * only */
1004 SCIP_Bool* branchcand /**< pointer to indicate whether to consider child for branching
1005 * (initialized to TRUE) */
1006 )
1007{
1008 SCIP_Bool isinteger;
1009 SCIP_Bool iseven;
1010
1011 assert(scip != NULL);
1012 assert(exprdata != NULL);
1013 assert(coef != NULL);
1014 assert(constant != NULL);
1015 assert(success != NULL);
1016 assert(islocal != NULL);
1017 assert(branchcand != NULL);
1018
1019 isinteger = EPSISINT(exponent, 0.0);
1020 iseven = isinteger && EPSISINT(exponent / 2.0, 0.0);
1021
1022 if( exponent == 2.0 )
1023 {
1024 /* important special case: quadratic case */
1025 /* initialize, because SCIPaddSquareXyz only adds to existing values */
1026 *success = TRUE;
1027 *coef = 0.0;
1028 *constant = 0.0;
1029
1030 if( overestimate )
1031 {
1032 SCIPaddSquareSecant(scip, 1.0, childlb, childub, coef, constant, success);
1033 *islocal = TRUE; /* secants are only valid locally */
1034 }
1035 else
1036 {
1037 SCIPaddSquareLinearization(scip, 1.0, refpoint, childintegral, coef, constant, success);
1038 *islocal = FALSE; /* linearizations are globally valid */
1039 *branchcand = FALSE; /* there is no improvement due to branching */
1040 }
1041 }
1042 else if( exponent > 0.0 && iseven )
1043 {
1044 estimateParabola(scip, exponent, overestimate, childlb, childub, refpoint, constant, coef, islocal, success);
1045 /* if estimate is locally valid, then we computed a secant and so branching can improve it */
1046 *branchcand = *islocal;
1047 }
1048 else if( exponent > 1.0 && childlb >= 0.0 )
1049 {
1050 /* make sure we linearize in convex region (if we will linearize) */
1051 if( refpoint < 0.0 )
1052 refpoint = 0.0;
1053
1054 estimateParabola(scip, exponent, overestimate, childlb, childub, refpoint, constant, coef, islocal, success);
1055
1056 /* if estimate is locally valid, then we computed a secant and so branching can improve it */
1057 *branchcand = *islocal;
1058
1059 /* if odd power, then check whether tangent on parabola is also globally valid, that is reference point is
1060 * right of -root*global-lower-bound
1061 */
1062 if( !*islocal && !iseven && childglb < 0.0 )
1063 {
1064 if( SCIPisInfinity(scip, -childglb) )
1065 *islocal = TRUE;
1066 else
1067 {
1068 if( exprdata->root == SCIP_INVALID )
1069 {
1070 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
1071 }
1072 *islocal = refpoint < exprdata->root * (-childglb);
1073 }
1074 }
1075 }
1076 else if( exponent > 1.0 ) /* and !iseven && childlb < 0.0 due to previous if */
1077 {
1078 /* compute root if not known yet; only needed if mixed sign (global child ub > 0) */
1079 if( exprdata->root == SCIP_INVALID && childgub > 0.0 )
1080 {
1081 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
1082 }
1083 estimateSignedpower(scip, exponent, exprdata->root, overestimate, childlb, childub, refpoint,
1084 -childglb, childgub, constant, coef, islocal, branchcand, success);
1085 }
1086 else if( exponent < 0.0 && (iseven || childlb >= 0.0) )
1087 {
1088 /* compute root if not known yet; only needed if mixed sign (globally) and iseven */
1089 if( exprdata->root == SCIP_INVALID && iseven )
1090 {
1091 SCIP_CALL( computeHyperbolaRoot(scip, &exprdata->root, exponent) );
1092 }
1093 estimateHyperbolaPositive(scip, exponent, exprdata->root, overestimate, childlb, childub, refpoint,
1094 childglb, childgub, constant, coef, islocal, branchcand, success);
1095 }
1096 else if( exponent < 0.0 )
1097 {
1098 assert(!iseven); /* should hold due to previous if */
1099 assert(childlb < 0.0); /* should hold due to previous if */
1100 assert(isinteger); /* should hold because childlb < 0.0 (same as assert above) */
1101
1102 estimateHyperbolaMixed(scip, exponent, overestimate, childlb, childub, refpoint, childglb, childgub,
1103 constant, coef, islocal, branchcand, success);
1104 }
1105 else
1106 {
1107 assert(exponent < 1.0); /* the only case that should be left */
1108 assert(exponent > 0.0); /* should hold due to previous if */
1109
1110 SCIPestimateRoot(scip, exponent, overestimate, childlb, childub, refpoint, constant, coef, islocal, success);
1111
1112 /* if estimate is locally valid, then we computed a secant, and so branching can improve it */
1113 *branchcand = *islocal;
1114 }
1115
1116 return SCIP_OKAY;
1117}
1118
1119/** fills an array of reference points for estimating on the convex side */
1120static
1122 SCIP* scip, /**< SCIP data structure */
1123 SCIP_Real exponent, /**< exponent of the power expression */
1124 SCIP_Real lb, /**< lower bound on the child variable */
1125 SCIP_Real ub, /**< upper bound on the child variable */
1126 SCIP_Real* refpoints /**< array to store the reference points */
1127 )
1128{
1129 SCIP_Real maxabsbnd;
1130
1131 assert(refpoints != NULL);
1132
1133 maxabsbnd = pow(INITLPMAXPOWVAL, 1 / exponent);
1134
1135 /* make sure the absolute values of bounds are not too large */
1136 if( ub > -maxabsbnd )
1137 lb = MAX(lb, -maxabsbnd);
1138 if( lb < maxabsbnd )
1139 ub = MIN(ub, maxabsbnd);
1140
1141 /* in the case when ub < -maxabsbnd or lb > maxabsbnd, we still want to at least make bounds finite */
1142 if( SCIPisInfinity(scip, -lb) )
1143 lb = MIN(-10.0, ub - 0.1*REALABS(ub)); /*lint !e666 */
1144 if( SCIPisInfinity(scip, ub) )
1145 ub = MAX( 10.0, lb + 0.1*REALABS(lb)); /*lint !e666 */
1146
1147 refpoints[0] = (7.0 * lb + ub) / 8.0;
1148 refpoints[1] = (lb + ub) / 2.0;
1149 refpoints[2] = (lb + 7.0 * ub) / 8.0;
1150}
1151
1152/** fills an array of reference points for sign(x)*abs(x)^n or x^n (n odd), where x has mixed signs
1153 *
1154 * The reference points are: the lower and upper bounds (one for secant and one for tangent);
1155 * and for the second tangent, the point on the convex part of the function between the point
1156 * deciding between tangent and secant, and the corresponding bound
1157 */
1158static
1160 SCIP* scip, /**< SCIP data structure */
1161 SCIP_EXPRDATA* exprdata, /**< expression data */
1162 SCIP_Real lb, /**< lower bound on the child variable */
1163 SCIP_Real ub, /**< upper bound on the child variable */
1164 SCIP_Real exponent, /**< exponent */
1165 SCIP_Bool underestimate, /**< are the refpoints for an underestimator */
1166 SCIP_Real* refpoints /**< array to store the reference points */
1167 )
1168{
1169 assert(refpoints != NULL);
1170
1171 if( (underestimate && SCIPisInfinity(scip, -lb)) || (!underestimate && SCIPisInfinity(scip, ub)) )
1172 return SCIP_OKAY;
1173
1174 if( exprdata->root == SCIP_INVALID )
1175 {
1176 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
1177 }
1178
1179 /* make bounds finite (due to a previous if, only one can be infinite here) */
1180 if( SCIPisInfinity(scip, -lb) )
1181 lb = -ub * exprdata->root - 1.0;
1182 else if( SCIPisInfinity(scip, ub) )
1183 ub = -lb * exprdata->root + 1.0;
1184
1185 if( underestimate )
1186 {
1187 /* secant point */
1188 refpoints[0] = lb;
1189
1190 /* tangent points, depending on the special point */
1191 if( -lb * exprdata->root < ub - 2.0 )
1192 refpoints[2] = ub;
1193 if( -lb * exprdata->root < ub - 4.0 )
1194 refpoints[1] = (-lb * exprdata->root + ub) / 2.0;
1195 }
1196
1197 if( !underestimate )
1198 {
1199 /* secant point */
1200 refpoints[2] = ub;
1201
1202 /* tangent points, depending on the special point */
1203 if( -ub * exprdata->root > lb + 2.0 )
1204 refpoints[0] = lb;
1205 if( -ub * exprdata->root > lb + 4.0 )
1206 refpoints[1] = (lb - ub * exprdata->root) / 2.0;
1207 }
1208
1209 return SCIP_OKAY;
1210}
1211
1212/** choose reference points for adding initestimates cuts for a power expression */
1213static
1215 SCIP* scip, /**< SCIP data structure */
1216 SCIP_EXPRDATA* exprdata, /**< expression data */
1217 SCIP_Real lb, /**< lower bound on the child variable */
1218 SCIP_Real ub, /**< upper bound on the child variable */
1219 SCIP_Real* refpointsunder, /**< array to store reference points for underestimators */
1220 SCIP_Real* refpointsover, /**< array to store reference points for overestimators */
1221 SCIP_Bool underestimate, /**< whether refpoints for underestimation are needed */
1222 SCIP_Bool overestimate /**< whether refpoints for overestimation are needed */
1223 )
1224{
1225 SCIP_Bool convex;
1226 SCIP_Bool concave;
1227 SCIP_Bool mixedsign;
1228 SCIP_Bool even;
1229 SCIP_Real exponent;
1230
1231 assert(scip != NULL);
1232 assert(exprdata != NULL);
1233 assert(refpointsunder != NULL && refpointsover != NULL);
1234
1235 exponent = exprdata->exponent;
1236 even = EPSISINT(exponent, 0.0) && EPSISINT(exponent / 2.0, 0.0);
1237
1238 convex = FALSE;
1239 concave = FALSE;
1240 mixedsign = lb < 0.0 && ub > 0.0;
1241
1242 /* convex case:
1243 * - parabola with an even degree or positive domain
1244 * - hyperbola with a positive domain
1245 * - even hyperbola with a negative domain
1246 */
1247 if( (exponent > 1.0 && (lb >= 0 || even)) || (exponent < 0.0 && lb >= 0) || (exponent < 0.0 && even && ub <= 0.0) )
1248 convex = TRUE;
1249 /* concave case:
1250 * - parabola or hyperbola with a negative domain and (due to previous if) an uneven degree
1251 * - root
1252 */
1253 else if( ub <= 0 || (exponent > 0.0 && exponent < 1.0) )
1254 concave = TRUE;
1255
1256 if( underestimate )
1257 {
1258 if( convex )
1259 addTangentRefpoints(scip, exponent, lb, ub, refpointsunder);
1260 else if( (concave && !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub)) ||
1261 (exponent < 0.0 && even && mixedsign) ) /* concave with finite bounds or mixed even hyperbola */
1262 {
1263 /* for secant, refpoint doesn't matter, but we add it to signal that the corresponding cut should be created */
1264 refpointsunder[0] = (lb + ub) / 2.0;
1265 }
1266 else if( exponent > 1.0 && !even && mixedsign ) /* mixed signpower */
1267 {
1268 SCIP_CALL( addSignpowerRefpoints(scip, exprdata, lb, ub, exponent, TRUE, refpointsunder) );
1269 }
1270 else /* mixed odd hyperbola or an infinite bound */
1271 assert((exponent < 0.0 && !even && mixedsign) || SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub));
1272 }
1273
1274 if( overestimate )
1275 {
1276 if( convex && !SCIPisInfinity(scip, -lb) && !SCIPisInfinity(scip, ub) )
1277 refpointsover[0] = (lb + ub) / 2.0;
1278 else if( concave )
1279 addTangentRefpoints(scip, exponent, lb, ub, refpointsover);
1280 else if( exponent > 1.0 && !even && mixedsign ) /* mixed signpower */
1281 {
1282 SCIP_CALL( addSignpowerRefpoints(scip, exprdata, lb, ub, exponent, FALSE, refpointsover) );
1283 }
1284 else /* mixed hyperbola or an infinite bound */
1285 assert((exponent < 0.0 && mixedsign) || SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub));
1286 }
1287
1288 return SCIP_OKAY;
1289}
1290
1291
1292/*
1293 * Callback methods of expression handler
1294 */
1295
1296/** compares two power expressions
1297 *
1298 * the order of two power (normal or signed) is base_1^expo_1 < base_2^expo_2 if and only if
1299 * base_1 < base2 or, base_1 = base_2 and expo_1 < expo_2
1300 */
1301static
1303{ /*lint --e{715}*/
1304 SCIP_Real expo1;
1305 SCIP_Real expo2;
1306 int compareresult;
1307
1308 /**! [SnippetExprComparePow] */
1309 compareresult = SCIPcompareExpr(scip, SCIPexprGetChildren(expr1)[0], SCIPexprGetChildren(expr2)[0]);
1310 if( compareresult != 0 )
1311 return compareresult;
1312
1313 expo1 = SCIPgetExponentExprPow(expr1);
1314 expo2 = SCIPgetExponentExprPow(expr2);
1315
1316 return expo1 == expo2 ? 0 : expo1 < expo2 ? -1 : 1;
1317 /**! [SnippetExprComparePow] */
1318}
1319
1320/** simplifies a pow expression
1321 *
1322 * Evaluates the power function when its child is a value expression
1323 */
1324static
1326{ /*lint --e{715}*/
1327 SCIP_EXPRHDLR* exprhdlr;
1328 SCIP_EXPRHDLRDATA* exprhdlrdata;
1329 SCIP_EXPR* base;
1330 SCIP_Real exponent;
1331
1332 assert(scip != NULL);
1333 assert(expr != NULL);
1334 assert(simplifiedexpr != NULL);
1335 assert(SCIPexprGetNChildren(expr) == 1);
1336
1337 exprhdlr = SCIPexprGetHdlr(expr);
1338 assert(exprhdlr != NULL);
1339
1340 exprhdlrdata = SCIPexprhdlrGetData(exprhdlr);
1341 assert(exprhdlrdata != NULL);
1342
1343 base = SCIPexprGetChildren(expr)[0];
1344 assert(base != NULL);
1345
1346 exponent = SCIPgetExponentExprPow(expr);
1347
1348 SCIPdebugPrintf("[simplifyPow] simplifying power with expo %g\n", exponent);
1349
1350 /* enforces POW1 */
1351 if( exponent == 0.0 )
1352 {
1353 SCIPdebugPrintf("[simplifyPow] POW1\n");
1354 /* TODO: more checks? */
1355 assert(!SCIPisExprValue(scip, base) || SCIPgetValueExprValue(base) != 0.0);
1356 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, 1.0, ownercreate, ownercreatedata) );
1357 return SCIP_OKAY;
1358 }
1359
1360 /* enforces POW2 */
1361 if( exponent == 1.0 )
1362 {
1363 SCIPdebugPrintf("[simplifyPow] POW2\n");
1364 *simplifiedexpr = base;
1365 SCIPcaptureExpr(*simplifiedexpr);
1366 return SCIP_OKAY;
1367 }
1368
1369 /* enforces POW3 */
1370 if( SCIPisExprValue(scip, base) )
1371 {
1372 SCIP_Real baseval;
1373
1374 SCIPdebugPrintf("[simplifyPow] POW3\n");
1375 baseval = SCIPgetValueExprValue(base);
1376
1377 /* the assert below was failing on st_e35 for baseval=-1e-15 and fractional exponent
1378 * in the subNLP heuristic; I assume that this was because baseval was evaluated after
1379 * variable fixings and that there were just floating-point inaccuracies and 0 was meant,
1380 * so I treat -1e-15 as 0 here
1381 */
1382 if( baseval < 0.0 && fmod(exponent, 1.0) != 0.0 && baseval > -SCIPepsilon(scip) )
1383 baseval = 0.0;
1384
1385 /* TODO check if those are all important asserts */
1386 assert(baseval >= 0.0 || fmod(exponent, 1.0) == 0.0);
1387 assert(baseval != 0.0 || exponent != 0.0);
1388
1389 if( baseval != 0.0 || exponent > 0.0 )
1390 {
1391 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, pow(baseval, exponent), ownercreate, ownercreatedata) );
1392 return SCIP_OKAY;
1393 }
1394 }
1395
1396 /* enforces POW11 (exp(x)^n = exp(n*x)) */
1397 if( SCIPisExprExp(scip, base) )
1398 {
1399 SCIP_EXPR* child;
1400 SCIP_EXPR* prod;
1401 SCIP_EXPR* exponential;
1402 SCIP_EXPR* simplifiedprod;
1403
1404 SCIPdebugPrintf("[simplifyPow] POW11\n");
1405 child = SCIPexprGetChildren(base)[0];
1406
1407 /* multiply child of exponential with exponent */
1408 SCIP_CALL( SCIPcreateExprProduct(scip, &prod, 1, &child, exponent, ownercreate, ownercreatedata) );
1409
1410 /* simplify product */
1411 SCIP_CALL( SCIPcallExprSimplify(scip, prod, &simplifiedprod, ownercreate, ownercreatedata) );
1412 SCIP_CALL( SCIPreleaseExpr(scip, &prod) );
1413
1414 /* create exponential with new child */
1415 SCIP_CALL( SCIPcreateExprExp(scip, &exponential, simplifiedprod, ownercreate, ownercreatedata) );
1416 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedprod) );
1417
1418 /* the final simplified expression is the simplification of the just created exponential */
1419 SCIP_CALL( SCIPcallExprSimplify(scip, exponential, simplifiedexpr, ownercreate, ownercreatedata) );
1420 SCIP_CALL( SCIPreleaseExpr(scip, &exponential) );
1421
1422 return SCIP_OKAY;
1423 }
1424
1425 /* enforces POW10 */
1426 if( SCIPisExprVar(scip, base) )
1427 {
1428 SCIP_VAR* basevar;
1429
1430 SCIPdebugPrintf("[simplifyPow] POW10\n");
1431 basevar = SCIPgetVarExprVar(base);
1432
1433 assert(basevar != NULL);
1434
1435 /* TODO: if exponent is negative, we could fix the binary variable to 1. However, this is a bit tricky because
1436 * variables can not be tighten in EXITPRE, where the simplify is also called
1437 */
1438 if( SCIPvarIsBinary(basevar) && exponent > 0.0 )
1439 {
1440 *simplifiedexpr = base;
1441 SCIPcaptureExpr(*simplifiedexpr);
1442 return SCIP_OKAY;
1443 }
1444 }
1445
1446 if( EPSISINT(exponent, 0.0) )
1447 {
1448 SCIP_EXPR* aux;
1449 SCIP_EXPR* simplifiedaux;
1450
1451 /* enforces POW12 (abs(x)^n = x^n if n is even) */
1452 if( SCIPisExprAbs(scip, base) && (int)exponent % 2 == 0 )
1453 {
1454 SCIP_EXPR* newpow;
1455
1456 SCIPdebugPrintf("[simplifyPow] POWXX\n");
1457
1458 SCIP_CALL( SCIPcreateExprPow(scip, &newpow, SCIPexprGetChildren(base)[0], exponent, ownercreate, ownercreatedata) );
1459 SCIP_CALL( simplifyPow(scip, newpow, simplifiedexpr, ownercreate, ownercreatedata) );
1460 SCIP_CALL( SCIPreleaseExpr(scip, &newpow) );
1461
1462 return SCIP_OKAY;
1463 }
1464
1465 /* enforces POW5
1466 * given (pow n (prod 1.0 expr_1 ... expr_k)) we distribute the exponent:
1467 * -> (prod 1.0 (pow n expr_1) ... (pow n expr_k))
1468 * notes: - since base is simplified and its coefficient is 1.0 (SP8)
1469 * - n is an integer (excluding 1 and 0; see POW1-2 above)
1470 */
1471 if( SCIPisExprProduct(scip, base) )
1472 {
1473 SCIP_EXPR* auxproduct;
1474 int i;
1475
1476 /* create empty product */
1477 SCIP_CALL( SCIPcreateExprProduct(scip, &auxproduct, 0, NULL, 1.0, ownercreate, ownercreatedata) );
1478
1479 for( i = 0; i < SCIPexprGetNChildren(base); ++i )
1480 {
1481 /* create (pow n expr_i) and simplify */
1482 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[i], exponent, ownercreate, ownercreatedata) );
1483 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
1484 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1485
1486 /* append (pow n expr_i) to product */
1487 SCIP_CALL( SCIPappendExprChild(scip, auxproduct, simplifiedaux) );
1488 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
1489 }
1490
1491 /* simplify (prod 1.0 (pow n expr_1) ... (pow n expr_k))
1492 * this calls simplifyProduct directly, since we know its children are simplified */
1493 SCIP_CALL( SCIPcallExprSimplify(scip, auxproduct, simplifiedexpr, ownercreate, ownercreatedata) );
1494 SCIP_CALL( SCIPreleaseExpr(scip, &auxproduct) );
1495 return SCIP_OKAY;
1496 }
1497
1498 /* enforces POW6
1499 * given (pow n (sum 0.0 coef expr)) we can move `pow` inside `sum`:
1500 * (pow n (sum 0.0 coef expr) ) -> (sum 0.0 coef^n (pow n expr))
1501 * notes: - since base is simplified and its constant is 0, then coef != 1.0 (SS7)
1502 * - n is an integer (excluding 1 and 0; see POW1-2 above)
1503 */
1504 if( SCIPisExprSum(scip, base) && SCIPexprGetNChildren(base) == 1 && SCIPgetConstantExprSum(base) == 0.0 )
1505 {
1506 SCIP_Real newcoef;
1507
1508 SCIPdebugPrintf("[simplifyPow] seeing a sum with one term, exponent %g\n", exponent);
1509
1510 /* assert SS7 holds */
1511 assert(SCIPgetCoefsExprSum(base)[0] != 1.0);
1512
1513 /* create (pow n expr) and simplify it
1514 * note: we call simplifyPow directly, since we know that `expr` is simplified */
1515 newcoef = pow(SCIPgetCoefsExprSum(base)[0], exponent);
1516 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[0], exponent, ownercreate, ownercreatedata) );
1517 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
1518 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1519
1520 /* create (sum (pow n expr)) and simplify it
1521 * this calls simplifySum directly, since we know its children are simplified */
1522 SCIP_CALL( SCIPcreateExprSum(scip, &aux, 1, &simplifiedaux, &newcoef, 0.0, ownercreate, ownercreatedata) );
1523 SCIP_CALL( SCIPcallExprSimplify(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
1524 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1525 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
1526 return SCIP_OKAY;
1527 }
1528
1529 /* enforces POW7 for exponent 2
1530 * (const + sum alpha_i expr_i)^2 = sum alpha_i^2 expr_i^2
1531 * + sum_{j < i} 2*alpha_i alpha_j expr_i expr_j
1532 * + sum const alpha_i expr_i
1533 * TODO: put some limits on the number of children of the sum being expanded
1534 */
1535 if( SCIPisExprSum(scip, base) && exponent == 2.0 && exprhdlrdata->expandmaxexponent >= 2 )
1536 {
1537 int i;
1538 int nchildren;
1539 int nexpandedchildren;
1540 SCIP_EXPR* expansion;
1541 SCIP_EXPR** expandedchildren;
1542 SCIP_Real* coefs;
1543 SCIP_Real constant;
1544
1545 SCIPdebugPrintf("[simplifyPow] expanding sum^%g\n", exponent);
1546
1547 nchildren = SCIPexprGetNChildren(base);
1548 nexpandedchildren = nchildren * (nchildren + 1) / 2 + nchildren;
1549 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, nexpandedchildren) );
1550 SCIP_CALL( SCIPallocBufferArray(scip, &expandedchildren, nexpandedchildren) );
1551
1552 for( i = 0; i < nchildren; ++i )
1553 {
1554 int j;
1555 SCIP_EXPR* expansionchild;
1556 SCIP_EXPR* prodchildren[2];
1557 prodchildren[0] = SCIPexprGetChildren(base)[i];
1558
1559 /* create and simplify expr_i * expr_j */
1560 for( j = 0; j < i; ++j )
1561 {
1562 prodchildren[1] = SCIPexprGetChildren(base)[j];
1563 coefs[i*(i+1)/2 + j] = 2 * SCIPgetCoefsExprSum(base)[i] * SCIPgetCoefsExprSum(base)[j];
1564
1565 SCIP_CALL( SCIPcreateExprProduct(scip, &expansionchild, 2, prodchildren, 1.0, ownercreate,
1566 ownercreatedata) );
1567 SCIP_CALL( SCIPcallExprSimplify(scip, expansionchild, &expandedchildren[i*(i+1)/2 + j],
1568 ownercreate, ownercreatedata) ); /* this calls simplifyProduct */
1569 SCIP_CALL( SCIPreleaseExpr(scip, &expansionchild) );
1570 }
1571 /* create and simplify expr_i * expr_i */
1572 prodchildren[1] = SCIPexprGetChildren(base)[i];
1573 coefs[i*(i+1)/2 + i] = SCIPgetCoefsExprSum(base)[i] * SCIPgetCoefsExprSum(base)[i];
1574
1575 SCIP_CALL( SCIPcreateExprProduct(scip, &expansionchild, 2, prodchildren, 1.0, ownercreate,
1576 ownercreatedata) );
1577 SCIP_CALL( SCIPcallExprSimplify(scip, expansionchild, &expandedchildren[i*(i+1)/2 + i], ownercreate,
1578 ownercreatedata) ); /* this calls simplifyProduct */
1579 SCIP_CALL( SCIPreleaseExpr(scip, &expansionchild) );
1580 }
1581 /* create const * alpha_i expr_i */
1582 for( i = 0; i < nchildren; ++i )
1583 {
1584 coefs[i + nexpandedchildren - nchildren] = 2 * SCIPgetConstantExprSum(base) * SCIPgetCoefsExprSum(base)[i];
1585 expandedchildren[i + nexpandedchildren - nchildren] = SCIPexprGetChildren(base)[i];
1586 }
1587
1588 constant = SCIPgetConstantExprSum(base);
1589 constant *= constant;
1590 /* create sum of all the above and simplify it with simplifySum since all of its children are simplified! */
1591 SCIP_CALL( SCIPcreateExprSum(scip, &expansion, nexpandedchildren, expandedchildren, coefs, constant,
1592 ownercreate, ownercreatedata) );
1593 SCIP_CALL( SCIPcallExprSimplify(scip, expansion, simplifiedexpr, ownercreate,
1594 ownercreatedata) ); /* this calls simplifySum */
1595
1596 /* release everything */
1597 SCIP_CALL( SCIPreleaseExpr(scip, &expansion) );
1598 /* release the *created* expanded children */
1599 for( i = 0; i < nexpandedchildren - nchildren; ++i )
1600 {
1601 SCIP_CALL( SCIPreleaseExpr(scip, &expandedchildren[i]) );
1602 }
1603 SCIPfreeBufferArray(scip, &expandedchildren);
1604 SCIPfreeBufferArray(scip, &coefs);
1605
1606 return SCIP_OKAY;
1607 }
1608
1609 /* enforces POW7 for exponent > 2 */
1610 if( SCIPisExprSum(scip, base) && exponent > 2.0 && exponent <= exprhdlrdata->expandmaxexponent )
1611 {
1612 SCIPdebugPrintf("[simplifyPow] expanding sum^%g\n", exponent);
1613
1614 SCIP_CALL( SCIPpowerExprSum(scip, simplifiedexpr, base, (int)exponent, TRUE, ownercreate, ownercreatedata) );
1615
1616 return SCIP_OKAY;
1617 }
1618 }
1619 else
1620 {
1621 /* enforces POW9
1622 *
1623 * FIXME code of POW6 is very similar
1624 */
1625 if( SCIPexprGetNChildren(base) == 1
1626 && SCIPisExprSum(scip, base)
1627 && SCIPgetConstantExprSum(base) == 0.0
1628 && SCIPgetCoefsExprSum(base)[0] >= 0.0 )
1629 {
1630 SCIP_EXPR* simplifiedaux;
1631 SCIP_EXPR* aux;
1632 SCIP_Real newcoef;
1633
1634 SCIPdebugPrintf("[simplifyPow] seeing a sum with one term, exponent %g\n", exponent);
1635 /* assert SS7 holds */
1636 assert(SCIPgetCoefsExprSum(base)[0] != 1.0);
1637
1638 /* create (pow n expr) and simplify it
1639 * note: we call simplifyPow directly, since we know that `expr` is simplified */
1640 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[0], exponent, ownercreate,
1641 ownercreatedata) );
1642 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
1643 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1644
1645 /* create (sum (pow n expr)) and simplify it
1646 * this calls simplifySum directly, since we know its child is simplified! */
1647 newcoef = pow(SCIPgetCoefsExprSum(base)[0], exponent);
1648 SCIP_CALL( SCIPcreateExprSum(scip, &aux, 1, &simplifiedaux, &newcoef, 0.0, ownercreate,
1649 ownercreatedata) );
1650 SCIP_CALL( SCIPcallExprSimplify(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
1651 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1652 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
1653
1654 return SCIP_OKAY;
1655 }
1656
1657 /* enforces POW5a
1658 * given (pow n (prod 1.0 expr_1 ... expr_k)) we distribute the exponent:
1659 * -> (prod 1.0 (pow n expr_1) ... (pow n expr_k))
1660 * notes: - since base is simplified and its coefficient is 1.0 (SP8)
1661 * TODO we can enable this more often by default when simplify makes use of bounds on factors
1662 */
1663 if( exprhdlrdata->distribfracexponent && SCIPisExprProduct(scip, base) )
1664 {
1665 SCIP_EXPR* aux;
1666 SCIP_EXPR* simplifiedaux;
1667 SCIP_EXPR* auxproduct;
1668 int i;
1669
1670 /* create empty product */
1671 SCIP_CALL( SCIPcreateExprProduct(scip, &auxproduct, 0, NULL, 1.0, ownercreate, ownercreatedata) );
1672
1673 for( i = 0; i < SCIPexprGetNChildren(base); ++i )
1674 {
1675 /* create (pow n expr_i) and simplify */
1676 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[i], exponent, ownercreate, ownercreatedata) );
1677 SCIP_CALL( simplifyPow(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
1678 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1679
1680 /* append (pow n expr_i) to product */
1681 SCIP_CALL( SCIPappendExprChild(scip, auxproduct, simplifiedaux) );
1682 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
1683 }
1684
1685 /* simplify (prod 1.0 (pow n expr_1) ... (pow n expr_k))
1686 * this calls simplifyProduct directly, since we know its children are simplified */
1687 SCIP_CALL( SCIPcallExprSimplify(scip, auxproduct, simplifiedexpr, ownercreate, ownercreatedata) );
1688 SCIP_CALL( SCIPreleaseExpr(scip, &auxproduct) );
1689 return SCIP_OKAY;
1690 }
1691 }
1692
1693 /* enforces POW8
1694 * given (pow n (pow expo expr)) we distribute the exponent:
1695 * -> (pow n*expo expr)
1696 * notes: n is not 1 or 0, see POW1-2 above
1697 */
1698 if( SCIPisExprPower(scip, base) )
1699 {
1700 SCIP_Real newexponent;
1701 SCIP_Real baseexponent;
1702
1703 baseexponent = SCIPgetExponentExprPow(base);
1704 newexponent = baseexponent * exponent;
1705
1706 /* some checks (see POW8 definition in scip_expr.h) to make sure we don't loose an
1707 * implicit SCIPexprGetChildren(base)[0] >= 0 constraint
1708 *
1709 * if newexponent is fractional, then we will still need expr >= 0
1710 * if both exponents were integer, then we never required and will not require expr >= 0
1711 * if base exponent was an even integer, then we did not require expr >= 0
1712 * (but may need to use |expr|^newexponent)
1713 */
1714 if( !EPSISINT(newexponent, 0.0) ||
1715 (EPSISINT(baseexponent, 0.0) && EPSISINT(exponent, 0.0)) ||
1716 (EPSISINT(baseexponent, 0.0) && ((int)baseexponent) % 2 == 0) )
1717 {
1718 SCIP_EXPR* aux;
1719
1720 if( EPSISINT(baseexponent, 0.0) && ((int)baseexponent) % 2 == 0 &&
1721 (!EPSISINT(newexponent, 0.0) || ((int)newexponent) % 2 == 1) )
1722 {
1723 /* If base exponent was even integer and new exponent will be fractional,
1724 * then simplify to |expr|^newexponent to allow eval for expr < 0.
1725 * If base exponent was even integer and new exponent will be odd integer,
1726 * then simplify to |expr|^newexponent to preserve value for expr < 0.
1727 */
1728 SCIP_EXPR* simplifiedaux;
1729
1730 SCIP_CALL( SCIPcreateExprAbs(scip, &aux, SCIPexprGetChildren(base)[0], ownercreate, ownercreatedata) );
1731 SCIP_CALL( SCIPcallExprSimplify(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
1732 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1733 SCIP_CALL( SCIPcreateExprPow(scip, &aux, simplifiedaux, newexponent, ownercreate, ownercreatedata) );
1734 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
1735 }
1736 else
1737 {
1738 SCIP_CALL( SCIPcreateExprPow(scip, &aux, SCIPexprGetChildren(base)[0], newexponent, ownercreate,
1739 ownercreatedata) );
1740 }
1741
1742 SCIP_CALL( simplifyPow(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
1743 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
1744
1745 return SCIP_OKAY;
1746 }
1747 }
1748
1749 SCIPdebugPrintf("[simplifyPow] power is simplified\n");
1750 *simplifiedexpr = expr;
1751
1752 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
1753 SCIPcaptureExpr(*simplifiedexpr);
1754
1755 return SCIP_OKAY;
1756}
1757
1758/** expression callback to get information for symmetry detection */
1759static
1761{ /*lint --e{715}*/
1762 SCIP_EXPRDATA* exprdata;
1763
1764 assert(scip != NULL);
1765 assert(expr != NULL);
1766
1767 exprdata = SCIPexprGetData(expr);
1768 assert(exprdata != NULL);
1769
1770 SCIP_CALL( SCIPallocBlockMemory(scip, symdata) );
1771
1772 (*symdata)->nconstants = 1;
1773 (*symdata)->ncoefficients = 0;
1774
1775 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(*symdata)->constants, 1) );
1776 (*symdata)->constants[0] = exprdata->exponent;
1777
1778 return SCIP_OKAY;
1779}
1780
1781/** expression handler copy callback */
1782static
1784{ /*lint --e{715}*/
1786
1787 return SCIP_OKAY;
1788}
1789
1790/** expression handler free callback */
1791static
1793{ /*lint --e{715}*/
1794 assert(exprhdlrdata != NULL);
1795 assert(*exprhdlrdata != NULL);
1796
1797 SCIPfreeBlockMemory(scip, exprhdlrdata);
1798
1799 return SCIP_OKAY;
1800}
1801
1802/** expression data copy callback */
1803static
1805{ /*lint --e{715}*/
1806 SCIP_EXPRDATA* sourceexprdata;
1807
1808 assert(targetexprdata != NULL);
1809 assert(sourceexpr != NULL);
1810
1811 sourceexprdata = SCIPexprGetData(sourceexpr);
1812 assert(sourceexprdata != NULL);
1813
1814 *targetexprdata = NULL;
1815
1816 SCIP_CALL( createData(targetscip, targetexprdata, sourceexprdata->exponent) );
1817
1818 return SCIP_OKAY;
1819}
1820
1821/** expression data free callback */
1822static
1824{ /*lint --e{715}*/
1825 SCIP_EXPRDATA* exprdata;
1826
1827 assert(expr != NULL);
1828
1829 exprdata = SCIPexprGetData(expr);
1830 assert(exprdata != NULL);
1831
1832 SCIPfreeBlockMemory(scip, &exprdata);
1833 SCIPexprSetData(expr, NULL);
1834
1835 return SCIP_OKAY;
1836}
1837
1838/** expression print callback */
1839/** @todo: use precedence for better printing */
1840static
1842{ /*lint --e{715}*/
1843 assert(expr != NULL);
1844
1845 /**! [SnippetExprPrintPow] */
1846 switch( stage )
1847 {
1849 {
1850 /* print function with opening parenthesis */
1851 SCIPinfoMessage(scip, file, "(");
1852 break;
1853 }
1854
1856 {
1857 assert(currentchild == 0);
1858 break;
1859 }
1860
1862 {
1863 SCIP_Real exponent = SCIPgetExponentExprPow(expr);
1864
1865 /* print closing parenthesis */
1866 if( exponent >= 0.0 )
1867 SCIPinfoMessage(scip, file, ")^%.15g", exponent);
1868 else
1869 SCIPinfoMessage(scip, file, ")^(%.15g)", exponent);
1870
1871 break;
1872 }
1873
1875 default:
1876 break;
1877 }
1878 /**! [SnippetExprPrintPow] */
1879
1880 return SCIP_OKAY;
1881}
1882
1883/** expression point evaluation callback */
1884static
1886{ /*lint --e{715}*/
1887 SCIP_Real exponent;
1888 SCIP_Real base;
1889
1890 assert(expr != NULL);
1891 assert(SCIPexprGetNChildren(expr) == 1);
1893
1894 exponent = SCIPgetExponentExprPow(expr);
1896
1897 *val = pow(base, exponent);
1898
1899 /* if there is a domain, pole, or range error, pow() should return some kind of NaN, infinity, or HUGE_VAL
1900 * we could also work with floating point exceptions or errno, but I am not sure this would be thread-safe
1901 */
1902 if( !SCIPisFinite(*val) || *val == HUGE_VAL || *val == -HUGE_VAL )
1903 *val = SCIP_INVALID;
1904
1905 return SCIP_OKAY;
1906}
1907
1908/** derivative evaluation callback
1909 *
1910 * computes <gradient, children.dot>
1911 * if expr is child^p, then computes
1912 * p child^(p-1) dot(child)
1913 */
1914static
1916{ /*lint --e{715}*/
1917 SCIP_EXPR* child;
1918 SCIP_Real exponent;
1919
1920 assert(expr != NULL);
1921 assert(SCIPexprGetData(expr) != NULL);
1923
1924 child = SCIPexprGetChildren(expr)[0];
1925 assert(child != NULL);
1926 assert(!SCIPisExprValue(scip, child));
1928
1929 exponent = SCIPgetExponentExprPow(expr);
1930 assert(exponent != 0.0);
1931
1932 /* x^exponent is not differentiable for x = 0 and exponent in ]0,1[ */
1933 if( exponent > 0.0 && exponent < 1.0 && SCIPexprGetEvalValue(child) == 0.0 )
1934 *dot = SCIP_INVALID;
1935 else
1936 *dot = exponent * pow(SCIPexprGetEvalValue(child), exponent - 1.0) * SCIPexprGetDot(child);
1937
1938 return SCIP_OKAY;
1939}
1940
1941/** expression backward forward derivative evaluation callback
1942 *
1943 * computes partial/partial child ( <gradient, children.dot> )
1944 * if expr is child^n, then computes
1945 * n * (n - 1) child^(n-2) dot(child)
1946 */
1947static
1949{ /*lint --e{715}*/
1950 SCIP_EXPR* child;
1951 SCIP_Real exponent;
1952
1953 assert(expr != NULL);
1954 assert(SCIPexprGetData(expr) != NULL);
1956 assert(childidx == 0);
1957
1958 child = SCIPexprGetChildren(expr)[0];
1959 assert(child != NULL);
1960 assert(!SCIPisExprValue(scip, child));
1962
1963 exponent = SCIPgetExponentExprPow(expr);
1964 assert(exponent != 0.0);
1965
1966 /* x^exponent is not twice differentiable for x = 0 and exponent in ]0,1[ u ]1,2[ */
1967 if( exponent > 0.0 && exponent < 2.0 && SCIPexprGetEvalValue(child) == 0.0 && exponent != 1.0 )
1968 *bardot = SCIP_INVALID;
1969 else
1970 *bardot = exponent * (exponent - 1.0) * pow(SCIPexprGetEvalValue(child), exponent - 2.0) * SCIPexprGetDot(child);
1971
1972 return SCIP_OKAY;
1973}
1974
1975/** expression derivative evaluation callback */
1976static
1978{ /*lint --e{715}*/
1979 SCIP_EXPR* child;
1980 SCIP_Real childval;
1981 SCIP_Real exponent;
1982
1983 assert(expr != NULL);
1984 assert(SCIPexprGetData(expr) != NULL);
1985 assert(childidx == 0);
1986
1987 child = SCIPexprGetChildren(expr)[0];
1988 assert(child != NULL);
1989 assert(!SCIPisExprValue(scip, child));
1990
1991 childval = SCIPexprGetEvalValue(child);
1992 assert(childval != SCIP_INVALID);
1993
1994 exponent = SCIPgetExponentExprPow(expr);
1995 assert(exponent != 0.0);
1996
1997 /* x^exponent is not differentiable for x = 0 and exponent in ]0,1[ */
1998 if( exponent > 0.0 && exponent < 1.0 && childval == 0.0 )
1999 *val = SCIP_INVALID;
2000 else
2001 *val = exponent * pow(childval, exponent - 1.0);
2002
2003 return SCIP_OKAY;
2004}
2005
2006/** expression interval evaluation callback */
2007static
2009{ /*lint --e{715}*/
2010 SCIP_INTERVAL childinterval;
2011 SCIP_Real exponent;
2012
2013 assert(expr != NULL);
2014 assert(SCIPexprGetNChildren(expr) == 1);
2015
2016 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
2017
2018 exponent = SCIPgetExponentExprPow(expr);
2019
2020 if( exponent < 0.0 )
2021 {
2022 SCIP_EXPRHDLRDATA* exprhdlrdata;
2023 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
2024 assert(exprhdlrdata != NULL);
2025
2026 if( exprhdlrdata->minzerodistance > 0.0 )
2027 {
2028 /* avoid small interval around 0 if possible, see also reversepropPow */
2029 if( childinterval.inf > -exprhdlrdata->minzerodistance && childinterval.inf < exprhdlrdata->minzerodistance )
2030 {
2031 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
2032 {
2033 SCIPinfoMessage(scip, NULL, "Changing lower bound for child of pow(.,%g) from %g to %g.\n"
2034 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
2035 exponent, childinterval.inf, exprhdlrdata->minzerodistance);
2036 SCIPinfoMessage(scip, NULL, "Expression: ");
2037 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
2038 SCIPinfoMessage(scip, NULL, "\n");
2039 exprhdlrdata->warnedonpole = TRUE;
2040 }
2041 childinterval.inf = exprhdlrdata->minzerodistance;
2042 }
2043 else if( childinterval.sup < exprhdlrdata->minzerodistance
2044 && childinterval.sup > -exprhdlrdata->minzerodistance )
2045 {
2046 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
2047 {
2048 SCIPinfoMessage(scip, NULL, "Changing upper bound for child of pow(.,%g) from %g to %g.\n"
2049 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
2050 exponent, childinterval.sup, -exprhdlrdata->minzerodistance);
2051 SCIPinfoMessage(scip, NULL, "Expression: ");
2052 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
2053 SCIPinfoMessage(scip, NULL, "\n");
2054 exprhdlrdata->warnedonpole = TRUE;
2055 }
2056 childinterval.sup = -exprhdlrdata->minzerodistance;
2057 }
2058 }
2059 }
2060
2061 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
2062 {
2063 SCIPintervalSetEmpty(interval);
2064 return SCIP_OKAY;
2065 }
2066
2067 SCIPintervalPowerScalar(SCIP_INTERVAL_INFINITY, interval, childinterval, exponent);
2068
2069 /* make sure 0^negative is an empty interval, as some other codes do not handle intervals like [inf,inf] well
2070 * TODO maybe change SCIPintervalPowerScalar?
2071 */
2072 if( exponent < 0.0 && childinterval.inf == 0.0 && childinterval.sup == 0.0 )
2073 SCIPintervalSetEmpty(interval);
2074
2075 return SCIP_OKAY;
2076}
2077
2078/** expression estimator callback */
2079static
2081{ /*lint --e{715}*/
2082 SCIP_EXPRDATA* exprdata;
2083 SCIP_EXPR* child;
2084 SCIP_Real childlb;
2085 SCIP_Real childub;
2086 SCIP_Real exponent;
2087 SCIP_Bool isinteger;
2088
2089 assert(scip != NULL);
2090 assert(expr != NULL);
2091 assert(SCIPexprGetNChildren(expr) == 1);
2092 assert(refpoint != NULL);
2093 assert(coefs != NULL);
2094 assert(constant != NULL);
2095 assert(islocal != NULL);
2096 assert(branchcand != NULL);
2097 assert(*branchcand == TRUE); /* the default */
2098 assert(success != NULL);
2099
2101
2102 *success = FALSE;
2103
2104 /* get aux variables: we over- or underestimate childvar^exponent */
2105 child = SCIPexprGetChildren(expr)[0];
2106 assert(child != NULL);
2107
2108 SCIPdebugMsg(scip, "%sestimation of x^%g at x=%.15g\n",
2109 overestimate ? "over" : "under", SCIPgetExponentExprPow(expr), *refpoint);
2110
2111 /* we can not generate a cut at +/- infinity */
2112 if( SCIPisInfinity(scip, REALABS(*refpoint)) )
2113 return SCIP_OKAY;
2114
2115 childlb = localbounds[0].inf;
2116 childub = localbounds[0].sup;
2117
2118 exprdata = SCIPexprGetData(expr);
2119 exponent = exprdata->exponent;
2120 assert(exponent != 1.0 && exponent != 0.0); /* this should have been simplified */
2121
2122 /* if child is constant, then return a constant estimator
2123 * this can help with small infeasibilities if boundtightening is relaxing bounds too much
2124 */
2125 if( childlb == childub )
2126 {
2127 *coefs = 0.0;
2128 *constant = pow(childlb, exponent);
2129 *success = TRUE;
2130 *islocal = globalbounds[0].inf != globalbounds[0].sup;
2131 *branchcand = FALSE;
2132 return SCIP_OKAY;
2133 }
2134
2135 isinteger = EPSISINT(exponent, 0.0);
2136
2137 /* if exponent is not integral, then child must be non-negative */
2138 if( !isinteger && childlb < 0.0 )
2139 {
2140 /* somewhere we should have tightened the bound on x, but small tightening are not always applied by SCIP
2141 * it is ok to do this tightening here, but let's assert that we were close to 0.0 already
2142 */
2143 assert(SCIPisFeasZero(scip, childlb));
2144 childlb = 0.0;
2145 }
2146 assert(isinteger || childlb >= 0.0);
2147
2148 SCIP_CALL( buildPowEstimator(scip, exprdata, overestimate, childlb, childub, globalbounds[0].inf,
2149 globalbounds[0].sup, SCIPexprIsIntegral(child), MAX(childlb, *refpoint), exponent, coefs,
2150 constant, success, islocal, branchcand) );
2151
2152 return SCIP_OKAY;
2153}
2154
2155/** expression reverse propagaton callback */
2156static
2158{ /*lint --e{715}*/
2159 SCIP_INTERVAL child;
2160 SCIP_INTERVAL interval;
2161 SCIP_Real exponent;
2162
2163 assert(scip != NULL);
2164 assert(expr != NULL);
2165 assert(SCIPexprGetNChildren(expr) == 1);
2166
2167 exponent = SCIPgetExponentExprPow(expr);
2168 child = childrenbounds[0];
2169
2170 SCIPdebugMsg(scip, "reverseprop x^%g in [%.15g,%.15g], x = [%.15g,%.15g]", exponent, bounds.inf, bounds.sup,
2171 child.inf, child.sup);
2172
2174 {
2175 *infeasible = TRUE;
2176 return SCIP_OKAY;
2177 }
2178
2180 {
2181 /* if exponent is not integral, then make sure that child is non-negative */
2182 if( !EPSISINT(exponent, 0.0) && child.inf < 0.0 )
2183 {
2184 SCIPintervalSetBounds(&interval, 0.0, child.sup);
2185 }
2186 else
2187 {
2188 SCIPdebugMsgPrint(scip, "-> no improvement\n");
2189 return SCIP_OKAY;
2190 }
2191 }
2192 else
2193 {
2194 /* f = pow(c0, alpha) -> c0 = pow(f, 1/alpha) */
2195 SCIPintervalPowerScalarInverse(SCIP_INTERVAL_INFINITY, &interval, child, exponent, bounds);
2196 }
2197
2198 if( exponent < 0.0 )
2199 {
2200 SCIP_EXPRHDLRDATA* exprhdlrdata;
2201
2202 exprhdlrdata = SCIPexprhdlrGetData(SCIPexprGetHdlr(expr));
2203 assert(exprhdlrdata != NULL);
2204
2205 if( exprhdlrdata->minzerodistance > 0.0 )
2206 {
2207 /* push lower bound from >= -epsilon to >= epsilon to avoid pole at 0 (domain error)
2208 * push upper bound from <= epsilon to <= -epsilon to avoid pole at 0 (domain error)
2209 * this can lead to a cutoff if domain would otherwise be very close around 0
2210 */
2211 if( interval.inf > -exprhdlrdata->minzerodistance && interval.inf < exprhdlrdata->minzerodistance )
2212 {
2213 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
2214 {
2215 SCIPinfoMessage(scip, NULL, "Changing lower bound for child of pow(.,%g) from %g to %g.\n"
2216 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
2217 exponent, interval.inf, exprhdlrdata->minzerodistance);
2218 SCIPinfoMessage(scip, NULL, "Expression: ");
2219 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
2220 SCIPinfoMessage(scip, NULL, "\n");
2221 exprhdlrdata->warnedonpole = TRUE;
2222 }
2223 interval.inf = exprhdlrdata->minzerodistance;
2224 }
2225 else if( interval.sup < exprhdlrdata->minzerodistance && interval.sup > -exprhdlrdata->minzerodistance )
2226 {
2227 if( !exprhdlrdata->warnedonpole && SCIPgetVerbLevel(scip) > SCIP_VERBLEVEL_NONE )
2228 {
2229 SCIPinfoMessage(scip, NULL, "Changing lower bound for child of pow(.,%g) from %g to %g.\n"
2230 "Check your model formulation or use option expr/" POWEXPRHDLR_NAME "/minzerodistance to avoid this warning.\n",
2231 exponent, interval.sup, -exprhdlrdata->minzerodistance);
2232 SCIPinfoMessage(scip, NULL, "Expression: ");
2233 SCIP_CALL( SCIPprintExpr(scip, expr, NULL) );
2234 SCIPinfoMessage(scip, NULL, "\n");
2235 exprhdlrdata->warnedonpole = TRUE;
2236 }
2237 interval.sup = -exprhdlrdata->minzerodistance;
2238 }
2239 }
2240 }
2241
2242 SCIPdebugMsgPrint(scip, " -> [%.15g,%.15g]\n", interval.inf, interval.sup);
2243
2244 childrenbounds[0] = interval;
2245
2246 return SCIP_OKAY;
2247}
2248
2249/** initial estimates callback for a power expression */
2250static
2252{
2253 SCIP_EXPRDATA* exprdata;
2254 SCIP_EXPR* child;
2255 SCIP_Real childlb;
2256 SCIP_Real childub;
2257 SCIP_Real exponent;
2258 SCIP_Bool isinteger;
2259 SCIP_Bool branchcand;
2260 SCIP_Bool success;
2261 SCIP_Bool islocal;
2262 SCIP_Real refpointsunder[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
2263 SCIP_Real refpointsover[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
2264 SCIP_Bool overest[6] = {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE};
2265 int i;
2266
2267 assert(scip != NULL);
2268 assert(expr != NULL);
2269
2270 child = SCIPexprGetChildren(expr)[0];
2271 assert(child != NULL);
2272
2273 childlb = bounds[0].inf;
2274 childub = bounds[0].sup;
2275
2276 /* if child is essentially constant, then there should be no point in separation */
2277 if( SCIPisEQ(scip, childlb, childub) )
2278 {
2279 SCIPdebugMsg(scip, "skip initestimates as child seems essentially fixed [%.15g,%.15g]\n", childlb, childub);
2280 return SCIP_OKAY;
2281 }
2282
2283 exprdata = SCIPexprGetData(expr);
2284 exponent = exprdata->exponent;
2285 assert(exponent != 1.0 && exponent != 0.0); /* this should have been simplified */
2286
2287 isinteger = EPSISINT(exponent, 0.0);
2288
2289 /* if exponent is not integral, then child must be non-negative */
2290 if( !isinteger && childlb < 0.0 )
2291 {
2292 /* somewhere we should have tightened the bound on x, but small tightening are not always applied by SCIP
2293 * it is ok to do this tightening here, but let's assert that we were close to 0.0 already
2294 */
2295 assert(SCIPisFeasZero(scip, childlb));
2296 childlb = 0.0;
2297 }
2298 assert(isinteger || childlb >= 0.0);
2299
2300 /* TODO simplify to get 3 refpoints for either under- or overestimate */
2301 SCIP_CALL( chooseRefpointsPow(scip, exprdata, childlb, childub, refpointsunder, refpointsover, !overestimate,
2302 overestimate) );
2303
2304 for( i = 0; i < 6 && *nreturned < SCIP_EXPR_MAXINITESTIMATES; ++i )
2305 {
2306 SCIP_Real refpoint;
2307
2308 if( (overest[i] && !overestimate) || (!overest[i] && overestimate) )
2309 continue;
2310
2311 assert(overest[i] || i < 3); /* make sure that no out-of-bounds array access will be attempted */
2312 refpoint = overest[i] ? refpointsover[i % 3] : refpointsunder[i % 3];
2313
2314 if( refpoint == SCIP_INVALID )
2315 continue;
2316
2317 assert(SCIPisLE(scip, refpoint, childub) && SCIPisGE(scip, refpoint, childlb));
2318
2319 branchcand = TRUE;
2320 SCIP_CALL( buildPowEstimator(scip, exprdata, overest[i], childlb, childub, childlb, childub,
2321 SCIPexprIsIntegral(child), refpoint, exponent, coefs[*nreturned], &constant[*nreturned],
2322 &success, &islocal, &branchcand) );
2323
2324 if( success )
2325 {
2326 SCIPdebugMsg(scip, "initestimate x^%g for base in [%g,%g] at ref=%g, over:%u -> %g*x+%g\n", exponent,
2327 childlb, childub, refpoint, overest[i], coefs[*nreturned][0], constant[*nreturned]);
2328 ++*nreturned;
2329 }
2330 }
2331
2332 return SCIP_OKAY;
2333}
2334
2335/** expression hash callback */
2336static
2338{ /*lint --e{715}*/
2339 assert(scip != NULL);
2340 assert(expr != NULL);
2341 assert(SCIPexprGetNChildren(expr) == 1);
2342 assert(hashkey != NULL);
2343 assert(childrenhashes != NULL);
2344
2345 /* TODO include exponent into hashkey */
2346 *hashkey = POWEXPRHDLR_HASHKEY;
2347 *hashkey ^= childrenhashes[0];
2348
2349 return SCIP_OKAY;
2350}
2351
2352/** expression curvature detection callback */
2353static
2355{ /*lint --e{715}*/
2356 SCIP_EXPR* child;
2357 SCIP_INTERVAL childinterval;
2358 SCIP_Real exponent;
2359
2360 assert(scip != NULL);
2361 assert(expr != NULL);
2362 assert(exprcurvature != SCIP_EXPRCURV_UNKNOWN);
2363 assert(childcurv != NULL);
2364 assert(success != NULL);
2365 assert(SCIPexprGetNChildren(expr) == 1);
2366
2367 exponent = SCIPgetExponentExprPow(expr);
2368 child = SCIPexprGetChildren(expr)[0];
2369 assert(child != NULL);
2370
2372 childinterval = SCIPexprGetActivity(child);
2373
2374 *childcurv = SCIPexprcurvPowerInv(childinterval, exponent, exprcurvature);
2375 /* SCIPexprcurvPowerInv return unknown actually means that curv cannot be obtained */
2376 *success = *childcurv != SCIP_EXPRCURV_UNKNOWN;
2377
2378 return SCIP_OKAY;
2379}
2380
2381/** expression monotonicity detection callback */
2382static
2384{ /*lint --e{715}*/
2385 SCIP_INTERVAL interval;
2386 SCIP_Real exponent;
2387 SCIP_Real inf;
2388 SCIP_Real sup;
2389 SCIP_Bool expisint;
2390
2391 assert(scip != NULL);
2392 assert(expr != NULL);
2393 assert(result != NULL);
2394 assert(SCIPexprGetNChildren(expr) == 1);
2395 assert(childidx == 0);
2396
2397 assert(SCIPexprGetChildren(expr)[0] != NULL);
2399 interval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
2400
2402 inf = SCIPintervalGetInf(interval);
2403 sup = SCIPintervalGetSup(interval);
2404 exponent = SCIPgetExponentExprPow(expr);
2405 expisint = EPSISINT(exponent, 0.0); /*lint !e835*/
2406
2407 if( expisint )
2408 {
2409 SCIP_Bool expisodd = ceil(exponent/2) != exponent/2;
2410
2411 if( expisodd )
2412 {
2413 /* x^1, x^3, ... */
2414 if( exponent >= 0.0 )
2416
2417 /* ..., x^-3, x^-1 are decreasing if 0 is not in ]inf,sup[ */
2418 else if( inf >= 0.0 || sup <= 0.0 )
2420 }
2421 /* ..., x^-4, x^-2, x^2, x^4, ... */
2422 else
2423 {
2424 /* function is not monotone if 0 is in ]inf,sup[ */
2425 if( inf >= 0.0 )
2426 *result = exponent >= 0.0 ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
2427 else if( sup <= 0.0 )
2428 *result = exponent >= 0.0 ? SCIP_MONOTONE_DEC : SCIP_MONOTONE_INC;
2429 }
2430 }
2431 else
2432 {
2433 /* note that the expression is not defined for negative input values
2434 *
2435 * - increasing iff exponent >= 0
2436 * - decreasing iff exponent <= 0
2437 */
2438 *result = exponent >= 0.0 ? SCIP_MONOTONE_INC : SCIP_MONOTONE_DEC;
2439 }
2440
2441 return SCIP_OKAY;
2442}
2443
2444/** expression integrality detection callback */
2445static
2447{ /*lint --e{715}*/
2448 SCIP_EXPR* child;
2449 SCIP_Real exponent;
2450 SCIP_Bool expisint;
2451
2452 assert(scip != NULL);
2453 assert(expr != NULL);
2454 assert(integrality != NULL);
2455 assert(SCIPexprGetNChildren(expr) == 1);
2456
2457 child = SCIPexprGetChildren(expr)[0];
2458 assert(child != NULL);
2459
2460 exponent = SCIPgetExponentExprPow(expr);
2461 assert(exponent != 0.0);
2462 expisint = EPSISINT(exponent, 0.0); /*lint !e835*/
2463
2464 /* maintain child integrality if exponent is non-negative and integral */
2465 *integrality = (expisint && exponent >= 0.0) ? SCIPexprGetIntegrality(child) : SCIP_IMPLINTTYPE_NONE;
2466
2467 return SCIP_OKAY;
2468}
2469
2470/** simplifies a signpower expression
2471 */
2472static
2473SCIP_DECL_EXPRSIMPLIFY(simplifySignpower)
2474{ /*lint --e{715}*/
2475 SCIP_EXPR* base;
2476 SCIP_Real exponent;
2477
2478 assert(scip != NULL);
2479 assert(expr != NULL);
2480 assert(simplifiedexpr != NULL);
2481 assert(SCIPexprGetNChildren(expr) == 1);
2482
2483 base = SCIPexprGetChildren(expr)[0];
2484 assert(base != NULL);
2485
2486 exponent = SCIPgetExponentExprPow(expr);
2487 SCIPdebugPrintf("[simplifySignpower] simplifying power with expo %g\n", exponent);
2488 assert(exponent >= 1.0);
2489
2490 /* enforces SPOW2 */
2491 if( exponent == 1.0 )
2492 {
2493 SCIPdebugPrintf("[simplifySignpower] POW2\n");
2494 *simplifiedexpr = base;
2495 SCIPcaptureExpr(*simplifiedexpr);
2496 return SCIP_OKAY;
2497 }
2498
2499 /* enforces SPOW3 */
2500 if( SCIPisExprValue(scip, base) )
2501 {
2502 SCIP_Real baseval;
2503
2504 SCIPdebugPrintf("[simplifySignpower] POW3\n");
2505 baseval = SCIPgetValueExprValue(base);
2506
2507 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, SIGN(baseval) * pow(REALABS(baseval), exponent),
2508 ownercreate, ownercreatedata) );
2509
2510 return SCIP_OKAY;
2511 }
2512
2513 /* enforces SPOW11 (exp(x)^n = exp(n*x))
2514 * since exp() is always nonnegative, we can treat signpower as normal power here
2515 */
2516 if( SCIPisExprExp(scip, base) )
2517 {
2518 SCIP_EXPR* child;
2519 SCIP_EXPR* prod;
2520 SCIP_EXPR* exponential;
2521 SCIP_EXPR* simplifiedprod;
2522
2523 SCIPdebugPrintf("[simplifySignpower] POW11\n");
2524 child = SCIPexprGetChildren(base)[0];
2525
2526 /* multiply child of exponential with exponent */
2527 SCIP_CALL( SCIPcreateExprProduct(scip, &prod, 1, &child, exponent, ownercreate, ownercreatedata) );
2528
2529 /* simplify product */
2530 SCIP_CALL( SCIPcallExprSimplify(scip, prod, &simplifiedprod, ownercreate, ownercreatedata) );
2531 SCIP_CALL( SCIPreleaseExpr(scip, &prod) );
2532
2533 /* create exponential with new child */
2534 SCIP_CALL( SCIPcreateExprExp(scip, &exponential, simplifiedprod, ownercreate, ownercreatedata) );
2535 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedprod) );
2536
2537 /* the final simplified expression is the simplification of the just created exponential */
2538 SCIP_CALL( SCIPcallExprSimplify(scip, exponential, simplifiedexpr, ownercreate, ownercreatedata) );
2539 SCIP_CALL( SCIPreleaseExpr(scip, &exponential) );
2540
2541 return SCIP_OKAY;
2542 }
2543
2544 /* enforces SPOW6 */
2545 if( EPSISINT(exponent, 0.0) && ((int)exponent) % 2 == 1 )
2546 {
2547 SCIP_EXPR* aux;
2548
2549 /* we do not just change the expression data of expression to say it is a normal power, since, at the moment,
2550 * simplify identifies that expressions changed by checking that the pointer of the input expression is
2551 * different from the returned (simplified) expression
2552 */
2553 SCIP_CALL( SCIPcreateExprPow(scip, &aux, base, exponent, ownercreate, ownercreatedata) );
2554
2555 SCIP_CALL( simplifyPow(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
2556 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
2557
2558 return SCIP_OKAY;
2559 }
2560
2561 /* enforces SPOW10 */
2562 if( SCIPisExprVar(scip, base) )
2563 {
2564 SCIP_VAR* basevar;
2565
2566 SCIPdebugPrintf("[simplifySignpower] POW10\n");
2567 basevar = SCIPgetVarExprVar(base);
2568
2569 assert(basevar != NULL);
2570
2571 if( SCIPvarIsBinary(basevar) )
2572 {
2573 *simplifiedexpr = base;
2574 SCIPcaptureExpr(*simplifiedexpr);
2575 return SCIP_OKAY;
2576 }
2577 }
2578
2579 /* TODO if( SCIPisExprSignpower(scip, base) ... */
2580
2581 /* enforces SPOW8
2582 * given (signpow n (pow expo expr)) we distribute the exponent:
2583 * -> (signpow n*expo expr) for even n (i.e., sign(x^n) * |x|^n = 1 * x^n)
2584 * notes: n is an even integer (see SPOW6 above)
2585 * FIXME: doesn't this extend to any exponent?
2586 * If (pow expo expr) can be negative, it should mean that (-1)^expo = -1
2587 * then (signpow n (pow expo expr)) = sign(expr^expo) * |expr^expo|^n
2588 * then sign(expr^expo) = sign(expr) and |expr^expo| = |expr|^expo and so
2589 * (signpow n (pow expo expr)) = sign(expr^expo) * |expr^expo|^n = sign(expr) * |expr|^(expo*n) = signpow n*expo expr
2590 */
2591 if( EPSISINT(exponent, 0.0) && SCIPisExprPower(scip, base) )
2592 {
2593 SCIP_EXPR* aux;
2594 SCIP_Real newexponent;
2595
2596 assert(((int)exponent) % 2 == 0 ); /* odd case should have been handled by SPOW6 */
2597
2598 newexponent = SCIPgetExponentExprPow(base) * exponent;
2599 SCIP_CALL( SCIPcreateExprSignpower(scip, &aux, SCIPexprGetChildren(base)[0], newexponent,
2600 ownercreate, ownercreatedata) );
2601 SCIP_CALL( simplifySignpower(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
2602
2603 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
2604
2605 return SCIP_OKAY;
2606 }
2607
2608 /* enforces SPOW9 */
2609 if( SCIPisExprSum(scip, base)
2610 && SCIPexprGetNChildren(base) == 1
2611 && SCIPgetConstantExprSum(base) == 0.0 )
2612 {
2613 SCIP_EXPR* simplifiedaux;
2614 SCIP_EXPR* aux;
2615 SCIP_Real newcoef;
2616
2617 SCIPdebugPrintf("[simplifySignpower] seeing a sum with one term, exponent %g\n", exponent);
2618 /* assert SS7 holds */
2619 assert(SCIPgetCoefsExprSum(base)[0] != 1.0);
2620
2621 /* create (signpow n expr) and simplify it
2622 * note: we call simplifySignpower directly, since we know that `expr` is simplified */
2623 SCIP_CALL( SCIPcreateExprSignpower(scip, &aux, SCIPexprGetChildren(base)[0], exponent,
2624 ownercreate, ownercreatedata) );
2625 newcoef = SIGN(SCIPgetCoefsExprSum(base)[0]) * pow(REALABS(SCIPgetCoefsExprSum(base)[0]), exponent);
2626 SCIP_CALL( simplifySignpower(scip, aux, &simplifiedaux, ownercreate, ownercreatedata) );
2627 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
2628
2629 /* create (sum (signpow n expr)) and simplify it
2630 * this calls simplifySum directly, since we know its child is simplified */
2631 SCIP_CALL( SCIPcreateExprSum(scip, &aux, 1, &simplifiedaux, &newcoef, 0.0, ownercreate, ownercreatedata) );
2632 SCIP_CALL( SCIPcallExprSimplify(scip, aux, simplifiedexpr, ownercreate, ownercreatedata) );
2633 SCIP_CALL( SCIPreleaseExpr(scip, &aux) );
2634 SCIP_CALL( SCIPreleaseExpr(scip, &simplifiedaux) );
2635 return SCIP_OKAY;
2636 }
2637
2638 SCIPdebugPrintf("[simplifySignpower] signpower is simplified\n");
2639 *simplifiedexpr = expr;
2640
2641 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
2642 SCIPcaptureExpr(*simplifiedexpr);
2643
2644 return SCIP_OKAY;
2645}
2646
2647/** expression handler copy callback */
2648static
2649SCIP_DECL_EXPRCOPYHDLR(copyhdlrSignpower)
2650{ /*lint --e{715}*/
2652
2653 return SCIP_OKAY;
2654}
2655
2656/** expression print callback */
2657static
2658SCIP_DECL_EXPRPRINT(printSignpower)
2659{ /*lint --e{715}*/
2660 assert(expr != NULL);
2661
2662 switch( stage )
2663 {
2665 {
2666 SCIPinfoMessage(scip, file, "signpower(");
2667 break;
2668 }
2669
2671 {
2672 assert(currentchild == 0);
2673 break;
2674 }
2675
2677 {
2678 SCIPinfoMessage(scip, file, ",%.15g)", SCIPgetExponentExprPow(expr));
2679 break;
2680 }
2681
2683 default:
2684 break;
2685 }
2686
2687 return SCIP_OKAY;
2688}
2689
2690/** expression parse callback */
2691static
2692SCIP_DECL_EXPRPARSE(parseSignpower)
2693{ /*lint --e{715}*/
2694 SCIP_EXPR* childexpr;
2695 SCIP_Real exponent;
2696
2697 assert(expr != NULL);
2698
2699 /**! [SnippetExprParseSignpower] */
2700 /* parse child expression string */
2701 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
2702 assert(childexpr != NULL);
2703
2704 string = *endstring;
2705 while( *string == ' ' )
2706 ++string;
2707
2708 if( *string != ',' )
2709 {
2710 SCIPerrorMessage("Expected comma after first argument of signpower().\n");
2711 return SCIP_READERROR;
2712 }
2713 ++string;
2714
2715 if( !SCIPparseReal(scip, string, &exponent, (char**)endstring) )
2716 {
2717 SCIPerrorMessage("Expected numeric exponent for second argument of signpower().\n");
2718 return SCIP_READERROR;
2719 }
2720
2721 if( exponent <= 1.0 || !SCIPisFinite(exponent) || SCIPisInfinity(scip, exponent) )
2722 {
2723 SCIPerrorMessage("Expected finite exponent >= 1.0 for signpower().\n");
2724 return SCIP_READERROR;
2725 }
2726
2727 /* create signpower expression */
2728 SCIP_CALL( SCIPcreateExprSignpower(scip, expr, childexpr, exponent, ownercreate, ownercreatedata) );
2729 assert(*expr != NULL);
2730
2731 /* release child expression since it has been captured by the signpower expression */
2732 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
2733
2734 *success = TRUE;
2735 /**! [SnippetExprParseSignpower] */
2736
2737 return SCIP_OKAY;
2738}
2739
2740/** expression point evaluation callback */
2741static
2743{ /*lint --e{715}*/
2744 SCIP_Real exponent;
2745 SCIP_Real base;
2746
2747 assert(expr != NULL);
2748 assert(SCIPexprGetNChildren(expr) == 1);
2750
2751 exponent = SCIPgetExponentExprPow(expr);
2753
2754 *val = SIGN(base) * pow(REALABS(base), exponent);
2755
2756 /* if there is a range error, pow() should return some kind of infinity, or HUGE_VAL
2757 * we could also work with floating point exceptions or errno, but I am not sure this would be thread-safe
2758 */
2759 if( !SCIPisFinite(*val) || *val == HUGE_VAL || *val == -HUGE_VAL )
2760 *val = SCIP_INVALID;
2761
2762 return SCIP_OKAY;
2763}
2764
2765/** expression derivative evaluation callback */
2766static
2767SCIP_DECL_EXPRBWDIFF(bwdiffSignpower)
2768{ /*lint --e{715}*/
2769 SCIP_EXPR* child;
2770 SCIP_Real childval;
2771 SCIP_Real exponent;
2772
2773 assert(expr != NULL);
2774 assert(SCIPexprGetData(expr) != NULL);
2775 assert(childidx == 0);
2776
2777 child = SCIPexprGetChildren(expr)[0];
2778 assert(child != NULL);
2779 assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(child)), "val") != 0);
2780
2781 childval = SCIPexprGetEvalValue(child);
2782 assert(childval != SCIP_INVALID);
2783
2784 exponent = SCIPgetExponentExprPow(expr);
2785 assert(exponent >= 1.0);
2786
2787 *val = exponent * pow(REALABS(childval), exponent - 1.0);
2788
2789 return SCIP_OKAY;
2790}
2791
2792/** expression interval evaluation callback */
2793static
2794SCIP_DECL_EXPRINTEVAL(intevalSignpower)
2795{ /*lint --e{715}*/
2796 SCIP_INTERVAL childinterval;
2797
2798 assert(expr != NULL);
2799 assert(SCIPexprGetNChildren(expr) == 1);
2800
2801 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
2802 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
2803 {
2804 SCIPintervalSetEmpty(interval);
2805 return SCIP_OKAY;
2806 }
2807
2809
2810 return SCIP_OKAY;
2811}
2812
2813/** expression estimator callback */
2814static
2815SCIP_DECL_EXPRESTIMATE(estimateSignpower)
2816{ /*lint --e{715}*/
2817 SCIP_EXPRDATA* exprdata;
2818 SCIP_Real childlb;
2819 SCIP_Real childub;
2820 SCIP_Real childglb;
2821 SCIP_Real childgub;
2822 SCIP_Real exponent;
2823
2824 assert(scip != NULL);
2825 assert(expr != NULL);
2826 assert(SCIPexprGetNChildren(expr) == 1);
2827 assert(refpoint != NULL);
2828 assert(coefs != NULL);
2829 assert(constant != NULL);
2830 assert(islocal != NULL);
2831 assert(branchcand != NULL);
2832 assert(*branchcand == TRUE); /* the default */
2833 assert(success != NULL);
2834
2836
2837 *success = FALSE;
2838
2839 SCIPdebugMsg(scip, "%sestimation of signed x^%g at x=%g\n", overestimate ? "over" : "under",
2840 SCIPgetExponentExprPow(expr), *refpoint);
2841
2842 /* we can not generate a cut at +/- infinity */
2843 if( SCIPisInfinity(scip, REALABS(*refpoint)) )
2844 return SCIP_OKAY;
2845
2846 childlb = localbounds[0].inf;
2847 childub = localbounds[0].sup;
2848
2849 childglb = globalbounds[0].inf;
2850 childgub = globalbounds[0].sup;
2851
2852 exprdata = SCIPexprGetData(expr);
2853 exponent = exprdata->exponent;
2854 assert(exponent > 1.0); /* exponent == 1 should have been simplified */
2855
2856 /* if child is constant, then return a constant estimator
2857 * this can help with small infeasibilities if boundtightening is relaxing bounds too much
2858 */
2859 if( childlb == childub )
2860 {
2861 *coefs = 0.0;
2862 *constant = SIGN(childlb)*pow(REALABS(childlb), exponent);
2863 *success = TRUE;
2864 *islocal = childglb != childgub;
2865 *branchcand = FALSE;
2866 return SCIP_OKAY;
2867 }
2868
2869 if( childlb >= 0.0 )
2870 {
2871 estimateParabola(scip, exponent, overestimate, childlb, childub, MAX(0.0, *refpoint), constant, coefs,
2872 islocal, success);
2873
2874 *branchcand = *islocal;
2875
2876 /* if odd or signed power, then check whether tangent on parabola is also globally valid, that is
2877 * reference point is right of -root*global-lower-bound
2878 */
2879 if( !*islocal && childglb < 0.0 )
2880 {
2881 if( SCIPisInfinity(scip, -childglb) )
2882 *islocal = TRUE;
2883 else
2884 {
2885 if( exprdata->root == SCIP_INVALID )
2886 {
2887 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
2888 }
2889 *islocal = *refpoint < exprdata->root * (-childglb);
2890 }
2891 }
2892 }
2893 else /* and childlb < 0.0 due to previous if */
2894 {
2895 /* compute root if not known yet; only needed if mixed sign (global child ub > 0) */
2896 if( exprdata->root == SCIP_INVALID && childgub > 0.0 )
2897 {
2898 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
2899 }
2900 estimateSignedpower(scip, exponent, exprdata->root, overestimate, childlb, childub, *refpoint,
2901 childglb, childgub, constant, coefs, islocal, branchcand, success);
2902 }
2903
2904 return SCIP_OKAY;
2905}
2906
2907/** initial estimates callback for a signpower expression */
2908static
2909SCIP_DECL_EXPRINITESTIMATES(initestimatesSignpower)
2910{
2911 SCIP_EXPRDATA* exprdata;
2912 SCIP_Real childlb;
2913 SCIP_Real childub;
2914 SCIP_Real exponent;
2915 SCIP_Bool branchcand;
2916 SCIP_Bool success;
2917 SCIP_Bool islocal;
2918 SCIP_Real refpointsunder[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
2919 SCIP_Real refpointsover[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
2920 SCIP_Bool overest[6] = {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE};
2921 SCIP_Real refpoint;
2922 int i;
2923
2924 assert(scip != NULL);
2925 assert(expr != NULL);
2926 assert(SCIPexprGetNChildren(expr) == 1);
2927
2929
2930 childlb = bounds[0].inf;
2931 childub = bounds[0].sup;
2932
2933 /* if child is essentially constant, then there should be no point in separation */
2934 if( SCIPisEQ(scip, childlb, childub) )
2935 {
2936 SCIPdebugMsg(scip, "skip initestimates as child seems essentially fixed [%.15g,%.15g]\n", childlb, childub);
2937 return SCIP_OKAY;
2938 }
2939
2940 exprdata = SCIPexprGetData(expr);
2941 exponent = exprdata->exponent;
2942 assert(exponent > 1.0); /* this should have been simplified */
2943
2944 if( childlb >= 0.0 )
2945 {
2946 if( !overestimate )
2947 addTangentRefpoints(scip, exponent, childlb, childub, refpointsunder);
2948 if( overestimate && !SCIPisInfinity(scip, childub) )
2949 refpointsover[0] = (childlb + childub) / 2.0;
2950 }
2951 else if( childub <= 0.0 )
2952 {
2953 if( !overestimate && !SCIPisInfinity(scip, -childlb) )
2954 refpointsunder[0] = (childlb + childub) / 2.0;
2955 if( overestimate )
2956 addTangentRefpoints(scip, exponent, childlb, childub, refpointsunder);
2957 }
2958 else
2959 {
2960 SCIP_CALL( addSignpowerRefpoints(scip, exprdata, childlb, childub, exponent, !overestimate, refpointsunder) );
2961 }
2962
2963 /* add cuts for all refpoints */
2964 for( i = 0; i < 6 && *nreturned < SCIP_EXPR_MAXINITESTIMATES; ++i )
2965 {
2966 if( (overest[i] && !overestimate) || (!overest[i] && overestimate) )
2967 continue;
2968
2969 assert(overest[i] || i < 3); /* make sure that no out-of-bounds array access will be attempted */
2970 refpoint = overest[i] ? refpointsover[i % 3] : refpointsunder[i % 3];
2971 if( refpoint == SCIP_INVALID )
2972 continue;
2973 assert(SCIPisLE(scip, refpoint, childub) && SCIPisGE(scip, refpoint, childlb));
2974
2975 if( childlb >= 0 )
2976 {
2977 estimateParabola(scip, exponent, overest[i], childlb, childub, refpoint, &constant[*nreturned], coefs[*nreturned],
2978 &islocal, &success);
2979 }
2980 else
2981 {
2982 /* compute root if not known yet; only needed if mixed sign (global child ub > 0) */
2983 if( exprdata->root == SCIP_INVALID && childub > 0.0 )
2984 {
2985 SCIP_CALL( computeSignpowerRoot(scip, &exprdata->root, exponent) );
2986 }
2987 branchcand = TRUE;
2988 estimateSignedpower(scip, exponent, exprdata->root, overest[i], childlb, childub, refpoint,
2989 childlb, childub, &constant[*nreturned], coefs[*nreturned], &islocal,
2990 &branchcand, &success);
2991 }
2992
2993 if( success )
2994 ++*nreturned;
2995 }
2996
2997 return SCIP_OKAY;
2998}
2999
3000/** expression reverse propagaton callback */
3001static
3002SCIP_DECL_EXPRREVERSEPROP(reversepropSignpower)
3003{ /*lint --e{715}*/
3004 SCIP_INTERVAL interval;
3005 SCIP_INTERVAL exprecip;
3006 SCIP_Real exponent;
3007
3008 assert(scip != NULL);
3009 assert(expr != NULL);
3010 assert(SCIPexprGetNChildren(expr) == 1);
3011
3012 exponent = SCIPgetExponentExprPow(expr);
3013
3014 SCIPdebugMsg(scip, "reverseprop signpow(x,%g) in [%.15g,%.15g]", exponent, bounds.inf, bounds.sup);
3015
3017 {
3018 SCIPdebugMsgPrint(scip, "-> no improvement\n");
3019 return SCIP_OKAY;
3020 }
3021
3022 /* f = pow(c0, alpha) -> c0 = pow(f, 1/alpha) */
3023 SCIPintervalSet(&exprecip, exponent);
3024 SCIPintervalReciprocal(SCIP_INTERVAL_INFINITY, &exprecip, exprecip);
3025 if( exprecip.inf == exprecip.sup )
3026 {
3027 SCIPintervalSignPowerScalar(SCIP_INTERVAL_INFINITY, &interval, bounds, exprecip.inf);
3028 }
3029 else
3030 {
3031 SCIP_INTERVAL interval1, interval2;
3032 SCIPintervalSignPowerScalar(SCIP_INTERVAL_INFINITY, &interval1, bounds, exprecip.inf);
3033 SCIPintervalSignPowerScalar(SCIP_INTERVAL_INFINITY, &interval2, bounds, exprecip.sup);
3034 SCIPintervalUnify(&interval, interval1, interval2);
3035 }
3036
3037 SCIPdebugMsgPrint(scip, " -> [%.15g,%.15g]\n", interval.inf, interval.sup);
3038
3039 childrenbounds[0] = interval;
3040
3041 return SCIP_OKAY;
3042}
3043
3044/** expression hash callback */
3045static
3047{ /*lint --e{715}*/
3048 assert(scip != NULL);
3049 assert(expr != NULL);
3050 assert(SCIPexprGetNChildren(expr) == 1);
3051 assert(hashkey != NULL);
3052 assert(childrenhashes != NULL);
3053
3054 /* TODO include exponent into hashkey */
3055 *hashkey = SIGNPOWEXPRHDLR_HASHKEY;
3056 *hashkey ^= childrenhashes[0];
3057
3058 return SCIP_OKAY;
3059}
3060
3061/** expression curvature detection callback */
3062static
3063SCIP_DECL_EXPRCURVATURE(curvatureSignpower)
3064{ /*lint --e{715}*/
3065 SCIP_EXPR* child;
3066 SCIP_INTERVAL childinterval;
3067
3068 assert(scip != NULL);
3069 assert(expr != NULL);
3070 assert(exprcurvature != SCIP_EXPRCURV_UNKNOWN);
3071 assert(childcurv != NULL);
3072 assert(success != NULL);
3073 assert(SCIPexprGetNChildren(expr) == 1);
3074
3075 child = SCIPexprGetChildren(expr)[0];
3076 assert(child != NULL);
3077
3079 childinterval = SCIPexprGetActivity(child);
3080
3081 if( exprcurvature == SCIP_EXPRCURV_CONVEX )
3082 {
3083 /* signpower is only convex if argument is convex and non-negative */
3084 *childcurv = SCIP_EXPRCURV_CONVEX;
3085 *success = childinterval.inf >= 0.0;
3086 }
3087 else if( exprcurvature == SCIP_EXPRCURV_CONCAVE )
3088 {
3089 /* signpower is only concave if argument is concave and non-positive */
3090 *childcurv = SCIP_EXPRCURV_CONCAVE;
3091 *success = childinterval.sup <= 0.0;
3092 }
3093 else
3094 *success = FALSE;
3095
3096 return SCIP_OKAY;
3097}
3098
3099/** expression monotonicity detection callback */
3100static
3101SCIP_DECL_EXPRMONOTONICITY(monotonicitySignpower)
3102{ /*lint --e{715}*/
3103 assert(scip != NULL);
3104 assert(expr != NULL);
3105 assert(result != NULL);
3106
3108 return SCIP_OKAY;
3109}
3110
3111/** creates the handler for power expression and includes it into SCIP */
3113 SCIP* scip /**< SCIP data structure */
3114 )
3115{
3116 SCIP_EXPRHDLR* exprhdlr;
3117 SCIP_EXPRHDLRDATA* exprhdlrdata;
3118
3119 SCIP_CALL( SCIPallocClearBlockMemory(scip, &exprhdlrdata) );
3120
3122 evalPow, exprhdlrdata) );
3123 assert(exprhdlr != NULL);
3124
3125 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrPow, freehdlrPow);
3126 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataPow, freedataPow);
3127 SCIPexprhdlrSetSimplify(exprhdlr, simplifyPow);
3128 SCIPexprhdlrSetPrint(exprhdlr, printPow);
3129 SCIPexprhdlrSetIntEval(exprhdlr, intevalPow);
3130 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesPow, estimatePow);
3131 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropPow);
3132 SCIPexprhdlrSetHash(exprhdlr, hashPow);
3133 SCIPexprhdlrSetCompare(exprhdlr, comparePow);
3134 SCIPexprhdlrSetDiff(exprhdlr, bwdiffPow, fwdiffPow, bwfwdiffPow);
3135 SCIPexprhdlrSetCurvature(exprhdlr, curvaturePow);
3136 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityPow);
3137 SCIPexprhdlrSetIntegrality(exprhdlr, integralityPow);
3138 SCIPexprhdlrSetGetSymdata(exprhdlr, getSymDataPow);
3139
3140 SCIP_CALL( SCIPaddRealParam(scip, "expr/" POWEXPRHDLR_NAME "/minzerodistance",
3141 "minimal distance from zero to enforce for child in bound tightening",
3142 &exprhdlrdata->minzerodistance, FALSE, SCIPepsilon(scip), 0.0, 1.0, NULL, NULL) );
3143
3144 SCIP_CALL( SCIPaddIntParam(scip, "expr/" POWEXPRHDLR_NAME "/expandmaxexponent",
3145 "maximal exponent when to expand power of sum in simplify",
3146 &exprhdlrdata->expandmaxexponent, FALSE, 2, 1, INT_MAX, NULL, NULL) );
3147
3148 SCIP_CALL( SCIPaddBoolParam(scip, "expr/" POWEXPRHDLR_NAME "/distribfracexponent",
3149 "whether a fractional exponent is distributed onto factors on power of product",
3150 &exprhdlrdata->distribfracexponent, FALSE, FALSE, NULL, NULL) );
3151
3152 return SCIP_OKAY;
3153}
3154
3155/** creates the handler for signed power expression and includes it into SCIP */
3157 SCIP* scip /**< SCIP data structure */
3158 )
3159{
3160 SCIP_EXPRHDLR* exprhdlr;
3161
3163 SIGNPOWEXPRHDLR_PRECEDENCE, evalSignpower, NULL) );
3164 assert(exprhdlr != NULL);
3165
3166 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrSignpower, NULL);
3167 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataPow, freedataPow);
3168 SCIPexprhdlrSetSimplify(exprhdlr, simplifySignpower);
3169 SCIPexprhdlrSetPrint(exprhdlr, printSignpower);
3170 SCIPexprhdlrSetParse(exprhdlr, parseSignpower);
3171 SCIPexprhdlrSetIntEval(exprhdlr, intevalSignpower);
3172 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesSignpower, estimateSignpower);
3173 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropSignpower);
3174 SCIPexprhdlrSetHash(exprhdlr, hashSignpower);
3175 SCIPexprhdlrSetCompare(exprhdlr, comparePow);
3176 SCIPexprhdlrSetDiff(exprhdlr, bwdiffSignpower, NULL, NULL);
3177 SCIPexprhdlrSetCurvature(exprhdlr, curvatureSignpower);
3178 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicitySignpower);
3179 SCIPexprhdlrSetIntegrality(exprhdlr, integralityPow);
3180 SCIPexprhdlrSetGetSymdata(exprhdlr, getSymDataPow);
3181
3182 return SCIP_OKAY;
3183}
3184
3185/** creates a power expression */
3187 SCIP* scip, /**< SCIP data structure */
3188 SCIP_EXPR** expr, /**< pointer where to store expression */
3189 SCIP_EXPR* child, /**< single child */
3190 SCIP_Real exponent, /**< exponent of the power expression */
3191 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
3192 void* ownercreatedata /**< data to pass to ownercreate */
3193 )
3194{
3195 SCIP_EXPRDATA* exprdata;
3196
3197 assert(expr != NULL);
3198 assert(child != NULL);
3199
3200 SCIP_CALL( createData(scip, &exprdata, exponent) );
3201 assert(exprdata != NULL);
3202
3203 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPgetExprhdlrPower(scip), exprdata, 1, &child, ownercreate,
3204 ownercreatedata) );
3205
3206 return SCIP_OKAY;
3207}
3208
3209/** creates a signpower expression */
3211 SCIP* scip, /**< SCIP data structure */
3212 SCIP_EXPR** expr, /**< pointer where to store expression */
3213 SCIP_EXPR* child, /**< single child */
3214 SCIP_Real exponent, /**< exponent of the power expression */
3215 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
3216 void* ownercreatedata /**< data to pass to ownercreate */
3217 )
3218{
3219 SCIP_EXPRDATA* exprdata;
3220
3221 assert(expr != NULL);
3222 assert(child != NULL);
3224
3225 SCIP_CALL( createData(scip, &exprdata, exponent) );
3226 assert(exprdata != NULL);
3227
3229 ownercreate, ownercreatedata) );
3230
3231 return SCIP_OKAY;
3232}
3233
3234/** indicates whether expression is of signpower-type */ /*lint -e{715}*/
3236 SCIP* scip, /**< SCIP data structure */
3237 SCIP_EXPR* expr /**< expression */
3238 )
3239{ /*lint --e{715}*/
3240 assert(expr != NULL);
3241
3242 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), SIGNPOWEXPRHDLR_NAME) == 0;
3243}
3244
3245/** computes coefficients of linearization of a square term in a reference point */
3247 SCIP* scip, /**< SCIP data structure */
3248 SCIP_Real sqrcoef, /**< coefficient of square term */
3249 SCIP_Real refpoint, /**< point where to linearize */
3250 SCIP_Bool isint, /**< whether corresponding variable is a discrete variable, and thus linearization could be moved */
3251 SCIP_Real* lincoef, /**< buffer to add coefficient of linearization */
3252 SCIP_Real* linconstant, /**< buffer to add constant of linearization */
3253 SCIP_Bool* success /**< buffer to set to FALSE if linearization has failed due to large numbers */
3254 )
3255{
3256 assert(scip != NULL);
3257 assert(lincoef != NULL);
3258 assert(linconstant != NULL);
3259 assert(success != NULL);
3260
3261 if( sqrcoef == 0.0 )
3262 return;
3263
3264 if( SCIPisInfinity(scip, REALABS(refpoint)) )
3265 {
3266 *success = FALSE;
3267 return;
3268 }
3269
3270 if( !isint || SCIPisIntegral(scip, refpoint) )
3271 {
3272 SCIP_Real tmp;
3273
3274 /* sqrcoef * x^2 -> tangent in refpoint = sqrcoef * 2 * refpoint * (x - refpoint) */
3275
3276 tmp = sqrcoef * refpoint;
3277
3278 if( SCIPisInfinity(scip, 2.0 * REALABS(tmp)) )
3279 {
3280 *success = FALSE;
3281 return;
3282 }
3283
3284 *lincoef += 2.0 * tmp;
3285 tmp *= refpoint;
3286 *linconstant -= tmp;
3287 }
3288 else
3289 {
3290 /* sqrcoef * x^2 -> secant between f=floor(refpoint) and f+1 = sqrcoef * (f^2 + ((f+1)^2 - f^2) * (x-f))
3291 * = sqrcoef * (-f*(f+1) + (2*f+1)*x)
3292 */
3293 SCIP_Real f;
3294 SCIP_Real coef;
3295 SCIP_Real constant;
3296
3297 f = SCIPfloor(scip, refpoint);
3298
3299 coef = sqrcoef * (2.0 * f + 1.0);
3300 constant = -sqrcoef * f * (f + 1.0);
3301
3302 if( SCIPisInfinity(scip, REALABS(coef)) || SCIPisInfinity(scip, REALABS(constant)) )
3303 {
3304 *success = FALSE;
3305 return;
3306 }
3307
3308 *lincoef += coef;
3309 *linconstant += constant;
3310 }
3311}
3312
3313/** computes coefficients of secant of a square term */
3315 SCIP* scip, /**< SCIP data structure */
3316 SCIP_Real sqrcoef, /**< coefficient of square term */
3317 SCIP_Real lb, /**< lower bound on variable */
3318 SCIP_Real ub, /**< upper bound on variable */
3319 SCIP_Real* lincoef, /**< buffer to add coefficient of secant */
3320 SCIP_Real* linconstant, /**< buffer to add constant of secant */
3321 SCIP_Bool* success /**< buffer to set to FALSE if secant has failed due to large numbers or unboundedness */
3322 )
3323{
3324 SCIP_Real coef;
3325 SCIP_Real constant;
3326
3327 assert(scip != NULL);
3328 assert(!SCIPisInfinity(scip, lb));
3329 assert(!SCIPisInfinity(scip, -ub));
3330 assert(SCIPisLE(scip, lb, ub));
3331 assert(lincoef != NULL);
3332 assert(linconstant != NULL);
3333 assert(success != NULL);
3334
3335 if( sqrcoef == 0.0 )
3336 return;
3337
3338 if( SCIPisInfinity(scip, -lb) || SCIPisInfinity(scip, ub) )
3339 {
3340 /* unboundedness */
3341 *success = FALSE;
3342 return;
3343 }
3344
3345 /* sqrcoef * x^2 -> sqrcoef * (lb * lb + (ub*ub - lb*lb)/(ub-lb) * (x-lb)) = sqrcoef * (lb*lb + (ub+lb)*(x-lb))
3346 * = sqrcoef * ((lb+ub)*x - lb*ub)
3347 */
3348 coef = sqrcoef * (lb + ub);
3349 constant = -sqrcoef * lb * ub;
3350 if( SCIPisInfinity(scip, REALABS(coef)) || SCIPisInfinity(scip, REALABS(constant)) )
3351 {
3352 *success = FALSE;
3353 return;
3354 }
3355
3356 *lincoef += coef;
3357 *linconstant += constant;
3358}
3359
3360/** Separation for roots with exponent in [0,1]
3361 *
3362 * - x^0.5 with x >= 0
3363 <pre>
3364 8 +----------------------------------------------------------------------+
3365 | + + + + |
3366 7 |-+ x**0.5 ********|
3367 | *********|
3368 | ******** |
3369 6 |-+ ******** +-|
3370 | ****** |
3371 5 |-+ ****** +-|
3372 | ****** |
3373 | ***** |
3374 4 |-+ **** +-|
3375 | ***** |
3376 3 |-+ **** +-|
3377 | *** |
3378 | *** |
3379 2 |-+ ** +-|
3380 | ** |
3381 1 |** +-|
3382 |* |
3383 |* + + + + |
3384 0 +----------------------------------------------------------------------+
3385 0 10 20 30 40 50
3386 </pre>
3387 */
3389 SCIP* scip, /**< SCIP data structure */
3390 SCIP_Real exponent, /**< exponent */
3391 SCIP_Bool overestimate, /**< should the power be overestimated? */
3392 SCIP_Real xlb, /**< lower bound on x */
3393 SCIP_Real xub, /**< upper bound on x */
3394 SCIP_Real xref, /**< reference point (where to linearize) */
3395 SCIP_Real* constant, /**< buffer to store constant term of estimator */
3396 SCIP_Real* slope, /**< buffer to store slope of estimator */
3397 SCIP_Bool* islocal, /**< buffer to store whether estimator only locally valid, that is,
3398 it depends on given bounds */
3399 SCIP_Bool* success /**< buffer to store whether estimator could be computed */
3400 )
3401{
3402 assert(scip != NULL);
3403 assert(constant != NULL);
3404 assert(slope != NULL);
3405 assert(islocal != NULL);
3406 assert(success != NULL);
3407 assert(exponent > 0.0);
3408 assert(exponent < 1.0);
3409 assert(xlb >= 0.0);
3410
3411 if( !overestimate )
3412 {
3413 /* underestimate -> secant */
3414 computeSecant(scip, FALSE, exponent, xlb, xub, constant, slope, success);
3415 *islocal = TRUE;
3416 }
3417 else
3418 {
3419 /* overestimate -> tangent */
3420
3421 /* need to linearize right of 0 */
3422 if( xref < 0.0 )
3423 xref = 0.0;
3424
3425 if( SCIPisZero(scip, xref) )
3426 {
3427 if( SCIPisZero(scip, xub) )
3428 {
3429 *success = FALSE;
3430 *islocal = FALSE;
3431 return;
3432 }
3433
3434 /* if xref is 0 (then xlb=0 probably), then slope is infinite, then try to move away from 0 */
3435 if( xub < 0.2 )
3436 xref = 0.5 * xlb + 0.5 * xub;
3437 else
3438 xref = 0.1;
3439 }
3440
3441 computeTangent(scip, FALSE, exponent, xref, constant, slope, success);
3442 *islocal = FALSE;
3443 }
3444}
3445
3446/* from pub_expr.h */
3447
3448/** gets the exponent of a power or signed power expression */ /*lint -e{715}*/
3450 SCIP_EXPR* expr /**< expression */
3451 )
3452{
3453 SCIP_EXPRDATA* exprdata;
3454
3455 assert(expr != NULL);
3456
3457 exprdata = SCIPexprGetData(expr);
3458 assert(exprdata != NULL);
3459
3460 return exprdata->exponent;
3461}
#define NULL
Definition def.h:257
#define EPSISINT(x, eps)
Definition def.h:204
#define SCIP_INVALID
Definition def.h:187
#define SCIP_INTERVAL_INFINITY
Definition def.h:189
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
absolute expression handler
exponential expression handler
#define SIGNPOWEXPRHDLR_PRECEDENCE
Definition expr_pow.c:55
#define POWEXPRHDLR_PRECEDENCE
Definition expr_pow.c:50
void SCIPaddSquareLinearization(SCIP *scip, SCIP_Real sqrcoef, SCIP_Real refpoint, SCIP_Bool isint, SCIP_Real *lincoef, SCIP_Real *linconstant, SCIP_Bool *success)
Definition expr_pow.c:3246
static SCIP_RETCODE chooseRefpointsPow(SCIP *scip, SCIP_EXPRDATA *exprdata, SCIP_Real lb, SCIP_Real ub, SCIP_Real *refpointsunder, SCIP_Real *refpointsover, SCIP_Bool underestimate, SCIP_Bool overestimate)
Definition expr_pow.c:1214
static void estimateSignedpower(SCIP *scip, SCIP_Real exponent, SCIP_Real root, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real xlbglobal, SCIP_Real xubglobal, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *branchcand, SCIP_Bool *success)
Definition expr_pow.c:550
static void computeTangent(SCIP *scip, SCIP_Bool signpower, SCIP_Real exponent, SCIP_Real xref, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *success)
Definition expr_pow.c:255
#define SIGNPOWEXPRHDLR_NAME
Definition expr_pow.c:53
void SCIPestimateRoot(SCIP *scip, SCIP_Real exponent, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *success)
Definition expr_pow.c:3388
#define SIGNPOWEXPRHDLR_HASHKEY
Definition expr_pow.c:56
#define POWEXPRHDLR_NAME
Definition expr_pow.c:48
static SCIP_RETCODE buildPowEstimator(SCIP *scip, SCIP_EXPRDATA *exprdata, SCIP_Bool overestimate, SCIP_Real childlb, SCIP_Real childub, SCIP_Real childglb, SCIP_Real childgub, SCIP_Bool childintegral, SCIP_Real refpoint, SCIP_Real exponent, SCIP_Real *coef, SCIP_Real *constant, SCIP_Bool *success, SCIP_Bool *islocal, SCIP_Bool *branchcand)
Definition expr_pow.c:988
static void estimateParabola(SCIP *scip, SCIP_Real exponent, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *success)
Definition expr_pow.c:484
#define SIGN(x)
Definition expr_pow.c:69
static SCIP_RETCODE createData(SCIP *scip, SCIP_EXPRDATA **exprdata, SCIP_Real exponent)
Definition expr_pow.c:229
void SCIPaddSquareSecant(SCIP *scip, SCIP_Real sqrcoef, SCIP_Real lb, SCIP_Real ub, SCIP_Real *lincoef, SCIP_Real *linconstant, SCIP_Bool *success)
Definition expr_pow.c:3314
static SCIP_RETCODE addSignpowerRefpoints(SCIP *scip, SCIP_EXPRDATA *exprdata, SCIP_Real lb, SCIP_Real ub, SCIP_Real exponent, SCIP_Bool underestimate, SCIP_Real *refpoints)
Definition expr_pow.c:1159
#define SIGNPOW_ROOTS_KNOWN
Definition expr_pow.c:71
static void estimateHyperbolaPositive(SCIP *scip, SCIP_Real exponent, SCIP_Real root, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real xlbglobal, SCIP_Real xubglobal, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *branchcand, SCIP_Bool *success)
Definition expr_pow.c:698
#define POWEXPRHDLR_HASHKEY
Definition expr_pow.c:51
static SCIP_RETCODE computeSignpowerRoot(SCIP *scip, SCIP_Real *root, SCIP_Real exponent)
Definition expr_pow.c:115
static void estimateHyperbolaMixed(SCIP *scip, SCIP_Real exponent, SCIP_Bool overestimate, SCIP_Real xlb, SCIP_Real xub, SCIP_Real xref, SCIP_Real xlbglobal, SCIP_Real xubglobal, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *islocal, SCIP_Bool *branchcand, SCIP_Bool *success)
Definition expr_pow.c:910
#define SIGNPOWEXPRHDLR_DESC
Definition expr_pow.c:54
#define INITLPMAXPOWVAL
Definition expr_pow.c:58
#define POWEXPRHDLR_DESC
Definition expr_pow.c:49
static void addTangentRefpoints(SCIP *scip, SCIP_Real exponent, SCIP_Real lb, SCIP_Real ub, SCIP_Real *refpoints)
Definition expr_pow.c:1121
static SCIP_RETCODE computeHyperbolaRoot(SCIP *scip, SCIP_Real *root, SCIP_Real exponent)
Definition expr_pow.c:183
static SCIP_Real signpow_roots[SIGNPOW_ROOTS_KNOWN+1]
Definition expr_pow.c:77
static void computeSecant(SCIP *scip, SCIP_Bool signpower, SCIP_Real exponent, SCIP_Real xlb, SCIP_Real xub, SCIP_Real *constant, SCIP_Real *slope, SCIP_Bool *success)
Definition expr_pow.c:304
power and signed power expression handlers
product expression handler
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)
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_Bool SCIPisExprAbs(SCIP *scip, SCIP_EXPR *expr)
Definition expr_abs.c:546
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 SCIPcreateExprSignpower(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_Real exponent, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_pow.c:3210
SCIP_Bool SCIPisExprExp(SCIP *scip, SCIP_EXPR *expr)
Definition expr_exp.c:529
SCIP_RETCODE SCIPcreateExprExp(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_exp.c:511
SCIP_Bool SCIPisExprSignpower(SCIP *scip, SCIP_EXPR *expr)
Definition expr_pow.c:3235
SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_sum.c:1117
SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_value.c:274
SCIP_RETCODE 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 SCIPincludeExprhdlrSignpower(SCIP *scip)
Definition expr_pow.c:3156
SCIP_RETCODE SCIPincludeExprhdlrPow(SCIP *scip)
Definition expr_pow.c:3112
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
SCIP_VERBLEVEL SCIPgetVerbLevel(SCIP *scip)
#define SCIPdebugMsgPrint
#define SCIPdebugMsg
SCIP_RETCODE SCIPaddIntParam(SCIP *scip, const char *name, const char *desc, int *valueptr, SCIP_Bool isadvanced, int defaultvalue, int minvalue, int maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:83
SCIP_RETCODE SCIPaddRealParam(SCIP *scip, const char *name, const char *desc, SCIP_Real *valueptr, SCIP_Bool isadvanced, SCIP_Real defaultvalue, SCIP_Real minvalue, SCIP_Real maxvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
Definition scip_param.c:139
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
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 SCIPexprhdlrSetParse(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:407
SCIP_EXPRHDLRDATA * SCIPexprhdlrGetData(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:575
void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:488
void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:429
void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:510
void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:451
void SCIPexprhdlrSetGetSymdata(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:521
SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
Definition scip_expr.c:847
void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:499
void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)),)
Definition expr.c:473
void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)),)
Definition expr.c:370
SCIP_EXPRHDLR * SCIPgetExprhdlrPower(SCIP *scip)
Definition scip_expr.c:950
void SCIPexprhdlrSetPrint(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:396
SCIP_EXPRHDLR * SCIPfindExprhdlr(SCIP *scip, const char *name)
Definition scip_expr.c:894
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_Real SCIPgetExponentExprPow(SCIP_EXPR *expr)
Definition expr_pow.c:3449
SCIP_Bool SCIPisExprProduct(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1490
SCIP_EXPRCURV SCIPexprcurvPowerInv(SCIP_INTERVAL basebounds, SCIP_Real exponent, SCIP_EXPRCURV powercurv)
Definition exprcurv.c:209
SCIP_Bool SCIPisExprSum(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1479
SCIP_Bool SCIPexprIsIntegral(SCIP_EXPR *expr)
Definition expr.c:4101
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_Bool SCIPisExprVar(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1457
SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
Definition expr.c:3905
SCIP_RETCODE SCIPparseExpr(SCIP *scip, SCIP_EXPR **expr, const char *exprstr, const char **finalpos, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition scip_expr.c:1406
SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
Definition scip_expr.c:1512
SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
Definition expr_value.c:298
SCIP_Bool SCIPisExprPower(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1501
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition expr.c:3946
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3882
SCIP_Real SCIPgetConstantExprSum(SCIP_EXPR *expr)
Definition expr_sum.c:1569
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:423
SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
Definition expr.c:4028
void SCIPcaptureExpr(SCIP_EXPR *expr)
Definition scip_expr.c:1435
SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1742
SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
Definition expr.c:3895
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
SCIP_Bool SCIPintervalIsEntire(SCIP_Real infinity, SCIP_INTERVAL operand)
void SCIPintervalSignPowerScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
void SCIPintervalUnify(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 SCIPintervalPowerScalarInverse(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL basedomain, SCIP_Real exponent, SCIP_INTERVAL image)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
struct SCIP_Interval SCIP_INTERVAL
void SCIPintervalReciprocal(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
void SCIPintervalPowerScalar(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_Real operand2)
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
#define SCIPallocClearBlockMemory(scip, ptr)
Definition scip_mem.h:91
#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 SCIPisGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPepsilon(SCIP *scip)
SCIP_Bool SCIPparseReal(SCIP *scip, const char *str, SCIP_Real *value, char **endptr)
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition var.c:23510
return SCIP_OKAY
int c
assert(minobj< SCIPgetCutoffbound(scip))
public functions to work with algebraic expressions
#define SCIPerrorMessage
Definition pub_message.h:64
#define SCIPdebugPrintf
Definition pub_message.h:99
#define SCIPisFinite(x)
Definition pub_misc.h:82
SCIP_Real sup
SCIP_Real inf
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_ExprhdlrData SCIP_EXPRHDLRDATA
Definition type_expr.h:195
struct SCIP_ExprData SCIP_EXPRDATA
Definition type_expr.h:54
#define SCIP_DECL_EXPRFREEDATA(x)
Definition type_expr.h:268
@ SCIP_EXPRCURV_CONVEX
Definition type_expr.h:63
@ SCIP_EXPRCURV_UNKNOWN
Definition type_expr.h:62
@ SCIP_EXPRCURV_CONCAVE
Definition type_expr.h:64
#define SCIP_EXPR_MAXINITESTIMATES
Definition type_expr.h:198
#define SCIP_DECL_EXPRPARSE(x)
Definition type_expr.h:312
#define SCIP_DECL_EXPRBWDIFF(x)
Definition type_expr.h:451
#define SCIP_DECL_EXPRINTEVAL(x)
Definition type_expr.h:541
#define SCIP_DECL_EXPRMONOTONICITY(x)
Definition type_expr.h:358
#define SCIP_EXPRITER_VISITINGCHILD
Definition type_expr.h:695
@ SCIP_MONOTONE_UNKNOWN
Definition type_expr.h:71
@ SCIP_MONOTONE_INC
Definition type_expr.h:72
@ SCIP_MONOTONE_DEC
Definition type_expr.h:73
struct SCIP_Exprhdlr SCIP_EXPRHDLR
Definition type_expr.h:194
#define SCIP_DECL_EXPRCOMPARE(x)
Definition type_expr.h:412
#define SCIP_DECL_EXPRSIMPLIFY(x)
Definition type_expr.h:634
#define SCIP_DECL_EXPREVAL(x)
Definition type_expr.h:428
#define SCIP_DECL_EXPRFWDIFF(x)
Definition type_expr.h:482
#define SCIP_DECL_EXPRHASH(x)
Definition type_expr.h:393
#define SCIP_DECL_EXPRCOPYHDLR(x)
Definition type_expr.h:210
#define SCIP_DECL_EXPRPRINT(x)
Definition type_expr.h:289
#define SCIP_DECL_EXPRFREEHDLR(x)
Definition type_expr.h:224
#define SCIP_DECL_EXPRINTEGRALITY(x)
Definition type_expr.h:377
#define SCIP_EXPRITER_VISITEDCHILD
Definition type_expr.h:696
#define SCIP_DECL_EXPRGETSYMDATA(x)
Definition type_expr.h:674
#define SCIP_DECL_EXPRCOPYDATA(x)
Definition type_expr.h:249
#define SCIP_EXPRITER_LEAVEEXPR
Definition type_expr.h:697
#define SCIP_DECL_EXPRESTIMATE(x)
Definition type_expr.h:577
#define SCIP_EXPRITER_ENTEREXPR
Definition type_expr.h:694
@ SCIP_VERBLEVEL_NONE
@ SCIP_READERROR
@ SCIP_INVALIDCALL
@ SCIP_ERROR
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90