Scippy

SCIP

Solving Constraint Integer Programs

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