SCIP Doxygen Documentation
Loading...
Searching...
No Matches
expr_entropy.c
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2026 Zuse Institute Berlin (ZIB) */
7/* */
8/* Licensed under the Apache License, Version 2.0 (the "License"); */
9/* you may not use this file except in compliance with the License. */
10/* You may obtain a copy of the License at */
11/* */
12/* http://www.apache.org/licenses/LICENSE-2.0 */
13/* */
14/* Unless required by applicable law or agreed to in writing, software */
15/* distributed under the License is distributed on an "AS IS" BASIS, */
16/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17/* See the License for the specific language governing permissions and */
18/* limitations under the License. */
19/* */
20/* You should have received a copy of the Apache-2.0 license */
21/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
22/* */
23/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24
25/**@file expr_entropy.c
26 * @ingroup DEFPLUGINS_EXPR
27 * @brief handler for -x*log(x) expressions
28 * @author Benjamin Mueller
29 * @author Fabian Wegscheider
30 * @author Ksenia Bestuzheva
31 *
32 * @todo replace exp(-1.0) by 1.0/M_E
33 */
34
35/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36
37#include "scip/expr_entropy.h"
38#include "scip/expr_value.h"
39#include "scip/expr.h"
40
41
42/* fundamental expression handler properties */
43#define EXPRHDLR_NAME "entropy"
44#define EXPRHDLR_DESC "entropy expression (-x*log(x))"
45#define EXPRHDLR_PRECEDENCE 81000
46#define EXPRHDLR_HASHKEY SCIPcalcFibHash(7477.0)
47
48/*
49 * Data structures
50 */
51
52/*
53 * Local methods
54 */
55
56/** helper function for reverseProp() which returns an x* in [xmin,xmax] s.t. the distance -x*log(x) and a given target
57 * value is minimized; the function assumes that -x*log(x) is monotone on [xmin,xmax];
58 */
59static
61 SCIP* scip, /**< SCIP data structure */
62 SCIP_Real xmin, /**< smallest possible x */
63 SCIP_Real xmax, /**< largest possible x */
64 SCIP_Bool increasing, /**< -x*log(x) is increasing or decreasing on [xmin,xmax] */
65 SCIP_Real targetval /**< target value */
66 )
67{
68 SCIP_Real xminval = (xmin == 0.0) ? 0.0 : -xmin * log(xmin);
69 SCIP_Real xmaxval = (xmax == 0.0) ? 0.0 : -xmax * log(xmax);
70 int i;
71
72 assert(xmin <= xmax);
73 assert(increasing ? xminval <= xmaxval : xminval >= xmaxval);
74
75 /* function can not achieve -x*log(x) -> return xmin or xmax */
76 if( SCIPisGE(scip, xminval, targetval) && SCIPisGE(scip, xmaxval, targetval) )
77 return increasing ? xmin : xmax;
78 else if( SCIPisLE(scip, xminval, targetval) && SCIPisLE(scip, xmaxval, targetval) )
79 return increasing ? xmax : xmin;
80
81 /* binary search */
82 for( i = 0; i < 1000; ++i )
83 {
84 SCIP_Real x = (xmin + xmax) / 2.0;
85 SCIP_Real xval = (x == 0.0) ? 0.0 : -x * log(x);
86
87 /* found the corresponding point -> skip */
88 if( SCIPisEQ(scip, xval, targetval) )
89 return x;
90 else if( SCIPisLT(scip, xval, targetval) )
91 {
92 if( increasing )
93 xmin = x;
94 else
95 xmax = x;
96 }
97 else
98 {
99 if( increasing )
100 xmax = x;
101 else
102 xmin = x;
103 }
104 }
105
106 return SCIP_INVALID;
107}
108
109/** helper function for reverse propagation; needed for proper unittest */
110static
112 SCIP* scip, /**< SCIP data structure */
113 SCIP_INTERVAL exprinterval, /**< bounds on the expression */
114 SCIP_INTERVAL childinterval, /**< bounds on the interval of the child */
115 SCIP_INTERVAL* interval /**< resulting interval */
116 )
117{
118 SCIP_INTERVAL childentropy;
119 SCIP_INTERVAL intersection;
120 SCIP_INTERVAL tmp;
121 SCIP_Real childinf;
122 SCIP_Real childsup;
123 SCIP_Real extremum;
124 SCIP_Real boundinf;
125 SCIP_Real boundsup;
126
127 assert(scip != NULL);
128 assert(interval != NULL);
129
130 /* check whether domain is empty, i.e., bounds on -x*log(x) > 1/e */
131 if( SCIPisGT(scip, SCIPintervalGetInf(exprinterval), exp(-1.0))
133 {
134 SCIPintervalSetEmpty(interval);
135 return SCIP_OKAY;
136 }
137
138 /* compute the intersection between entropy([childinf,childsup]) and [expr.inf, expr.sup] */
139 SCIPintervalEntropy(SCIP_INTERVAL_INFINITY, &childentropy, childinterval);
140 SCIPintervalIntersect(&intersection, childentropy, exprinterval);
141
142 /* intersection empty -> infeasible */
144 {
145 SCIPintervalSetEmpty(interval);
146 return SCIP_OKAY;
147 }
148
149 /* intersection = childentropy -> nothing can be learned */
150 if( SCIPintervalIsSubsetEQ(SCIP_INTERVAL_INFINITY, childentropy, intersection) )
151 {
153 SCIPintervalIntersect(interval, *interval, childinterval);
154 return SCIP_OKAY;
155 }
156
157 childinf = MAX(0.0, SCIPintervalGetInf(childinterval)); /*lint !e666*/
158 childsup = SCIPintervalGetSup(childinterval);
159 extremum = exp(-1.0);
160 boundinf = SCIP_INVALID;
161 boundsup = SCIP_INVALID;
162
163 /*
164 * check whether lower bound of child can be improved
165 */
166 SCIPintervalSet(&tmp, childinf);
168
169 /* entropy(childinf) < intersection.inf -> consider [childinf, MIN(childsup, extremum)] */
170 if( SCIPintervalGetInf(intersection) > -SCIP_INTERVAL_INFINITY && SCIPintervalGetSup(tmp) - SCIPintervalGetInf(intersection) < -SCIPepsilon(scip) )
171 {
172 boundinf = reversePropBinarySearch(scip, childinf, MIN(extremum, childsup), TRUE,
173 SCIPintervalGetInf(intersection));
174 }
175 /* entropy(childinf) > intersection.sup -> consider [MAX(childinf,extremum), childsup] */
176 else if( SCIPintervalGetSup(intersection) < SCIP_INTERVAL_INFINITY && SCIPintervalGetInf(tmp) - SCIPintervalGetSup(intersection) > SCIPepsilon(scip) )
177 {
178 boundinf = reversePropBinarySearch(scip, MAX(childinf, extremum), childsup, FALSE,
179 SCIPintervalGetSup(intersection));
180 }
181 /* using a strict greater-than here because we expect a tightening because we saw an at-least-epsilon-potential above */
182 assert(boundinf == SCIP_INVALID || boundinf > childinf); /*lint !e777*/
183
184 /*
185 * check whether upper bound of child can be improved
186 */
187 if( childsup < SCIP_INTERVAL_INFINITY )
188 {
189 SCIPintervalSet(&tmp, childsup);
191 }
192 else
193 SCIPintervalSetBounds(&tmp, -SCIP_INTERVAL_INFINITY, -SCIP_INTERVAL_INFINITY); /* entropy(inf) = -inf */
194
195 /* entropy(childsup) < intersection.inf -> consider [MAX(childinf,extremum), childsup] */
196 if( SCIPintervalGetInf(intersection) > -SCIP_INTERVAL_INFINITY && SCIPintervalGetSup(tmp) - SCIPintervalGetInf(intersection) < -SCIPepsilon(scip) )
197 {
198 boundsup = reversePropBinarySearch(scip, MAX(childinf, extremum), childsup, FALSE,
199 SCIPintervalGetInf(intersection));
200 }
201 /* entropy(childsup) > intersection.sup -> consider [childinf, MIN(childsup,extremum)] */
202 else if( SCIPintervalGetSup(intersection) < SCIP_INTERVAL_INFINITY && SCIPintervalGetInf(tmp) - SCIPintervalGetSup(intersection) > SCIPepsilon(scip) )
203 {
204 boundsup = reversePropBinarySearch(scip, childinf, MIN(childsup, extremum), TRUE,
205 SCIPintervalGetSup(intersection));
206 }
207 /* using a strict smaller-than here because we expect a tightening because we saw an at-least-epsilon-potential above */
208 assert(boundsup == SCIP_INVALID || boundsup < childsup); /*lint !e777*/
209
210 if( boundinf != SCIP_INVALID ) /*lint !e777*/
211 {
212 childinf = MAX(childinf, boundinf);
213 }
214 if( boundsup != SCIP_INVALID ) /*lint !e777*/
215 {
216 childsup = boundsup;
217 }
218 assert(childinf <= childsup); /* infeasible case has been handled already */
219
220 /* set the resulting bounds */
221 SCIPintervalSetBounds(interval, childinf, childsup);
222
223 return SCIP_OKAY;
224}
225
226/*
227 * Callback methods of expression handler
228 */
229
230/** expression handler copy callback */
231static
233{ /*lint --e{715}*/
235
236 return SCIP_OKAY;
237}
238
239/** simplifies an entropy expression */
240static
242{ /*lint --e{715}*/
243 SCIP_EXPR* child;
244
245 assert(scip != NULL);
246 assert(expr != NULL);
247 assert(simplifiedexpr != NULL);
248 assert(SCIPexprGetNChildren(expr) == 1);
249
250 child = SCIPexprGetChildren(expr)[0];
251 assert(child != NULL);
252
253 /* check for value expression */
254 if( SCIPisExprValue(scip, child) )
255 {
256 SCIP_Real childvalue = SCIPgetValueExprValue(child);
257
258 /* TODO how to handle a negative value? */
259 assert(childvalue >= 0.0);
260
261 if( childvalue == 0.0 || childvalue == 1.0 )
262 {
263 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, 0.0, ownercreate, ownercreatedata) );
264 }
265 else
266 {
267 SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, -childvalue * log(childvalue), ownercreate,
268 ownercreatedata) );
269 }
270 }
271 else
272 {
273 *simplifiedexpr = expr;
274
275 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
276 SCIPcaptureExpr(*simplifiedexpr);
277 }
278
279 /* TODO handle -x*log(x) = 0 if x in {0,1} */
280
281 return SCIP_OKAY;
282}
283
284/** expression data copy callback */
285static
287{ /*lint --e{715}*/
288 assert(targetexprdata != NULL);
289 assert(sourceexpr != NULL);
290 assert(SCIPexprGetData(sourceexpr) == NULL);
291
292 *targetexprdata = NULL;
293 return SCIP_OKAY;
294}
295
296/** expression data free callback */
297static
299{ /*lint --e{715}*/
300 assert(expr != NULL);
301
302 SCIPexprSetData(expr, NULL);
303 return SCIP_OKAY;
304}
305
306/** expression parse callback */
307static
309{ /*lint --e{715}*/
310 SCIP_EXPR* childexpr;
311
312 assert(expr != NULL);
313
314 /* parse child expression from remaining string */
315 SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
316 assert(childexpr != NULL);
317
318 /* create entropy expression */
319 SCIP_CALL( SCIPcreateExprEntropy(scip, expr, childexpr, ownercreate, ownercreatedata) );
320 assert(*expr != NULL);
321
322 /* release child expression since it has been captured by the entropy expression */
323 SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
324
325 *success = TRUE;
326
327 return SCIP_OKAY;
328}
329
330
331/** expression (point-) evaluation callback */
332static
334{ /*lint --e{715}*/
335 SCIP_Real childvalue;
336
337 assert(expr != NULL);
338 assert(SCIPexprGetData(expr) == NULL);
339 assert(SCIPexprGetNChildren(expr) == 1);
340 assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]) != SCIP_INVALID); /*lint !e777*/
341
342 childvalue = SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]);
343
344 if( childvalue < 0.0 )
345 {
346 SCIPdebugMsg(scip, "invalid evaluation of entropy expression\n");
347 *val = SCIP_INVALID;
348 }
349 else if( childvalue == 0.0 || childvalue == 1.0 )
350 {
351 /* -x*log(x) = 0 iff x in {0,1} */
352 *val = 0.0;
353 }
354 else
355 {
356 *val = -childvalue * log(childvalue);
357 }
358
359 return SCIP_OKAY;
360}
361
362/** expression derivative evaluation callback */
363static
365{ /*lint --e{715}*/
366 SCIP_EXPR* child;
367 SCIP_Real childvalue;
368
369 assert(expr != NULL);
370 assert(childidx == 0);
371 assert(SCIPexprGetNChildren(expr) == 1);
372 assert(SCIPexprGetEvalValue(expr) != SCIP_INVALID); /*lint !e777*/
373
374 child = SCIPexprGetChildren(expr)[0];
375 assert(child != NULL);
376 assert(!SCIPisExprValue(scip, child));
377
378 childvalue = SCIPexprGetEvalValue(child);
379
380 /* derivative is not defined for x = 0 */
381 if( childvalue <= 0.0 )
382 *val = SCIP_INVALID;
383 else
384 *val = -1.0 - log(childvalue);
385
386 return SCIP_OKAY;
387}
388
389/** expression interval evaluation callback */
390static
392{ /*lint --e{715}*/
393 SCIP_INTERVAL childinterval;
394
395 assert(expr != NULL);
396 assert(SCIPexprGetData(expr) == NULL);
397 assert(SCIPexprGetNChildren(expr) == 1);
398
399 childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
400
401 if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
402 SCIPintervalSetEmpty(interval);
403 else
404 SCIPintervalEntropy(SCIP_INTERVAL_INFINITY, interval, childinterval);
405
406 return SCIP_OKAY;
407}
408
409/** expression estimator callback */
410static
412{ /*lint --e{715}*/
413 assert(scip != NULL);
414 assert(expr != NULL);
415 assert(localbounds != NULL);
416 assert(globalbounds != NULL);
417 assert(refpoint != NULL);
418 assert(coefs != NULL);
419 assert(constant != NULL);
420 assert(islocal != NULL);
421 assert(branchcand != NULL);
422 assert(*branchcand == TRUE);
423 assert(success != NULL);
424
426
427 *success = FALSE;
428
429 /* use secant for underestimate (locally valid) */
430 if( !overestimate )
431 {
432 SCIP_Real lb;
433 SCIP_Real ub;
434 SCIP_Real vallb;
435 SCIP_Real valub;
436
437 lb = localbounds[0].inf;
438 ub = localbounds[0].sup;
439
440 if( lb < 0.0 || SCIPisInfinity(scip, ub) || SCIPisEQ(scip, lb, ub) )
441 return SCIP_OKAY;
442
443 assert(lb >= 0.0 && ub >= 0.0);
444 assert(ub - lb != 0.0);
445
446 vallb = (lb == 0.0) ? 0.0 : -lb * log(lb);
447 valub = (ub == 0.0) ? 0.0 : -ub * log(ub);
448
449 coefs[0] = (valub - vallb) / (ub - lb);
450 *constant = valub - coefs[0] * ub;
451 assert(SCIPisEQ(scip, *constant, vallb - coefs[0] * lb));
452
453 *islocal = TRUE;
454 }
455 /* use gradient cut for overestimate (globally valid) */
456 else
457 {
458 if( !SCIPisPositive(scip, refpoint[0]) )
459 {
460 /* if refpoint is 0 (then lb=0 probably) or negative, then slope is infinite (or not defined), then try to move away from 0 */
461 if( SCIPisZero(scip, localbounds[0].sup) )
462 return SCIP_OKAY;
463
464 refpoint[0] = SCIPepsilon(scip);
465 }
466
467 /* -x*(1+log(x*)) + x* <= -x*log(x) */
468 coefs[0] = -(1.0 + log(refpoint[0]));
469 *constant = refpoint[0];
470
471 *islocal = FALSE;
472 *branchcand = FALSE;
473 }
474
475 /* give up if the constant or coefficient is too large */
476 if( SCIPisInfinity(scip, REALABS(*constant)) || SCIPisInfinity(scip, REALABS(coefs[0])) )
477 return SCIP_OKAY;
478
479 *success = TRUE;
480
481 return SCIP_OKAY;
482}
483
484/** initial estimates callback */
485static
486SCIP_DECL_EXPRINITESTIMATES(initestimatesEntropy)
487{ /*lint --e{715}*/
488 SCIP_Real refpointsover[3] = {SCIP_INVALID, SCIP_INVALID, SCIP_INVALID};
489 SCIP_Bool overest[4] = {TRUE, TRUE, TRUE, FALSE};
490 SCIP_Real lb;
491 SCIP_Real ub;
492 int i;
493
494 assert(scip != NULL);
495 assert(expr != NULL);
496 assert(SCIPexprGetNChildren(expr) == 1);
497
499
500 lb = bounds[0].inf;
501 ub = bounds[0].sup;
502
503 if( SCIPisEQ(scip, lb, ub) )
504 return SCIP_OKAY;
505
506 if( overestimate )
507 {
508 /* adjust lb */
509 lb = MAX(lb, SCIPepsilon(scip)); /*lint !e666*/
510
511 refpointsover[0] = lb;
512 refpointsover[1] = SCIPisInfinity(scip, ub) ? lb + 2.0 : (lb + ub) / 2;
513 refpointsover[2] = SCIPisInfinity(scip, ub) ? lb + 20.0 : ub;
514 }
515
516 *nreturned = 0;
517
518 for( i = 0; i < 4; ++i )
519 {
520 if( (overest[i] && !overestimate) || (!overest[i] && (overestimate || SCIPisInfinity(scip, ub))) )
521 continue;
522
523 assert(!overest[i] || (SCIPisLE(scip, refpointsover[i], ub) && SCIPisGE(scip, refpointsover[i], lb))); /*lint !e661*/
524
525 if( overest[i] )
526 { /*lint !e661*/
527 /* -x*(1+log(x*)) + x* <= -x*log(x) */
528 assert(i < 3);
529 /* coverity[overrun] */
530 coefs[*nreturned][0] = -(1.0 + log(refpointsover[i]));
531 /* coverity[overrun] */
532 constant[*nreturned] = refpointsover[i];
533 }
534 else
535 {
536 assert(lb > 0.0 && ub >= 0.0);
537 assert(ub - lb != 0.0);
538
539 coefs[*nreturned][0] = (-ub * log(ub) + lb * log(lb)) / (ub - lb);
540 constant[*nreturned] = -ub * log(ub) - coefs[*nreturned][0] * ub;
541 assert(SCIPisEQ(scip, constant[*nreturned], -lb * log(lb) - coefs[*nreturned][0] * lb)); /* cppcheck-suppress assertWithSideEffect */
542 }
543
544 ++(*nreturned);
545 }
546
547 return SCIP_OKAY;
548}
549
550/** expression reverse propagation callback */
551static
552SCIP_DECL_EXPRREVERSEPROP(reversepropEntropy)
553{ /*lint --e{715}*/
554 SCIP_INTERVAL newinterval;
555
556 assert(scip != NULL);
557 assert(expr != NULL);
558 assert(SCIPexprGetNChildren(expr) == 1);
559 assert(childrenbounds != NULL);
560 assert(infeasible != NULL);
561
562 /* compute resulting intervals (reverseProp handles childinterval being empty) */
563 SCIP_CALL( reverseProp(scip, bounds, childrenbounds[0], &newinterval) );
564 assert(SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, newinterval) || newinterval.inf >= 0.0);
565
566 childrenbounds[0] = newinterval;
567
568 return SCIP_OKAY;
569}
570
571/** entropy hash callback */
572static
574{ /*lint --e{715}*/
575 assert(expr != NULL);
576 assert(SCIPexprGetNChildren(expr) == 1);
577 assert(hashkey != NULL);
578 assert(childrenhashes != NULL);
579
580 *hashkey = EXPRHDLR_HASHKEY;
581 *hashkey ^= childrenhashes[0];
582
583 return SCIP_OKAY;
584}
585
586/** expression curvature detection callback */
587static
588SCIP_DECL_EXPRCURVATURE(curvatureEntropy)
589{ /*lint --e{715}*/
590 assert(scip != NULL);
591 assert(expr != NULL);
592 assert(childcurv != NULL);
593 assert(success != NULL);
594 assert(SCIPexprGetNChildren(expr) == 1);
595
596 /* to be concave, the child needs to be concave, too; we cannot be convex or linear */
597 if( exprcurvature == SCIP_EXPRCURV_CONCAVE )
598 {
599 *childcurv = SCIP_EXPRCURV_CONCAVE;
600 *success = TRUE;
601 }
602 else
603 *success = FALSE;
604
605 return SCIP_OKAY;
606}
607
608/** expression monotonicity detection callback */
609static
610SCIP_DECL_EXPRMONOTONICITY(monotonicityEntropy)
611{ /*lint --e{715}*/
612 SCIP_EXPR* child;
613 SCIP_INTERVAL childbounds;
614 SCIP_Real brpoint = exp(-1.0);
615
616 assert(scip != NULL);
617 assert(expr != NULL);
618 assert(result != NULL);
619 assert(childidx == 0);
620
621 child = SCIPexprGetChildren(expr)[0];
622 assert(child != NULL);
623
625 childbounds = SCIPexprGetActivity(child);
626
627 if( childbounds.sup <= brpoint )
629 else if( childbounds.inf >= brpoint )
631 else
633
634 return SCIP_OKAY;
635}
636
637/** expression integrality detection callback */
638static
639SCIP_DECL_EXPRINTEGRALITY(integralityEntropy)
640{ /*lint --e{715}*/
641 assert(scip != NULL);
642 assert(expr != NULL);
643 assert(integrality != NULL);
644
645 /* TODO it is possible to check for the special case that the child is integral and its bounds are [0,1]; in
646 * this case the entropy expression can only achieve 0 and is thus integral
647 */
648 *integrality = SCIP_IMPLINTTYPE_NONE;
649
650 return SCIP_OKAY;
651}
652
653/** creates the handler for entropy expressions and includes it into SCIP */
655 SCIP* scip /**< SCIP data structure */
656 )
657{
658 SCIP_EXPRHDLRDATA* exprhdlrdata;
659 SCIP_EXPRHDLR* exprhdlr;
660
661 /* create expression handler data */
662 exprhdlrdata = NULL;
663
664 /* include expression handler */
666 evalEntropy, exprhdlrdata) );
667 assert(exprhdlr != NULL);
668
669 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrEntropy, NULL);
670 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataEntropy, freedataEntropy);
671 SCIPexprhdlrSetSimplify(exprhdlr, simplifyEntropy);
672 SCIPexprhdlrSetParse(exprhdlr, parseEntropy);
673 SCIPexprhdlrSetIntEval(exprhdlr, intevalEntropy);
674 SCIPexprhdlrSetEstimate(exprhdlr, initestimatesEntropy, estimateEntropy);
675 SCIPexprhdlrSetReverseProp(exprhdlr, reversepropEntropy);
676 SCIPexprhdlrSetHash(exprhdlr, hashEntropy);
677 SCIPexprhdlrSetDiff(exprhdlr, bwdiffEntropy, NULL ,NULL);
678 SCIPexprhdlrSetCurvature(exprhdlr, curvatureEntropy);
679 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityEntropy);
680 SCIPexprhdlrSetIntegrality(exprhdlr, integralityEntropy);
681
682 return SCIP_OKAY;
683}
684
685/** creates an entropy expression */
687 SCIP* scip, /**< SCIP data structure */
688 SCIP_EXPR** expr, /**< pointer where to store expression */
689 SCIP_EXPR* child, /**< child expression */
690 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
691 void* ownercreatedata /**< data to pass to ownercreate */
692 )
693{
694 SCIP_EXPRHDLR* exprhdlr;
695 SCIP_EXPRDATA* exprdata;
696
697 assert(expr != NULL);
698 assert(child != NULL);
699
701 assert(exprhdlr != NULL);
702
703 /* create expression data */
704 exprdata = NULL;
705
706 /* create expression */
707 SCIP_CALL( SCIPcreateExpr(scip, expr, exprhdlr, exprdata, 1, &child, ownercreate, ownercreatedata) );
708
709 return SCIP_OKAY;
710}
711
712/** indicates whether expression is of entropy-type */ /*lint -e{715}*/
714 SCIP* scip, /**< SCIP data structure */
715 SCIP_EXPR* expr /**< expression */
716 )
717{ /*lint --e{715}*/
718 assert(expr != NULL);
719
720 return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0;
721}
SCIP_VAR ** x
#define NULL
Definition def.h:257
#define SCIP_INVALID
Definition def.h:187
#define SCIP_INTERVAL_INFINITY
Definition def.h:189
#define SCIP_Bool
Definition def.h:100
#define MIN(x, y)
Definition def.h:233
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define FALSE
Definition def.h:103
#define MAX(x, y)
Definition def.h:229
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
private functions to work with algebraic expressions
#define EXPRHDLR_HASHKEY
Definition expr_abs.c:41
#define EXPRHDLR_NAME
Definition expr_abs.c:38
#define EXPRHDLR_DESC
Definition expr_abs.c:39
#define EXPRHDLR_PRECEDENCE
Definition expr_abs.c:40
static SCIP_RETCODE reverseProp(SCIP *scip, SCIP_INTERVAL exprinterval, SCIP_INTERVAL childinterval, SCIP_INTERVAL *interval)
static SCIP_Real reversePropBinarySearch(SCIP *scip, SCIP_Real xmin, SCIP_Real xmax, SCIP_Bool increasing, SCIP_Real targetval)
handler for -x*log(x) expressions
constant value expression handler
SCIP_Bool SCIPisExprEntropy(SCIP *scip, SCIP_EXPR *expr)
SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_value.c:274
SCIP_RETCODE SCIPcreateExprEntropy(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
SCIP_RETCODE SCIPincludeExprhdlrEntropy(SCIP *scip)
#define SCIPdebugMsg
const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:545
void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:440
void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:418
void SCIPexprhdlrSetParse(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:407
void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:488
void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:429
void SCIPexprhdlrSetReverseProp(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:510
void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:451
SCIP_RETCODE SCIPincludeExprhdlr(SCIP *scip, SCIP_EXPRHDLR **exprhdlr, const char *name, const char *desc, unsigned int precedence, SCIP_DECL_EXPREVAL((*eval)), SCIP_EXPRHDLRDATA *data)
Definition scip_expr.c:847
void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:499
void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)),)
Definition expr.c:473
void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)),)
Definition expr.c:370
SCIP_EXPRHDLR * SCIPfindExprhdlr(SCIP *scip, const char *name)
Definition scip_expr.c:894
void SCIPexprhdlrSetCopyFreeData(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYDATA((*copydata)),)
Definition expr.c:383
void SCIPexprhdlrSetEstimate(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINITESTIMATES((*initestimates)),)
Definition expr.c:532
SCIP_RETCODE SCIPcreateExpr(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPRHDLR *exprhdlr, SCIP_EXPRDATA *exprdata, int nchildren, SCIP_EXPR **children, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition scip_expr.c:1000
void SCIPexprSetData(SCIP_EXPR *expr, SCIP_EXPRDATA *exprdata)
Definition expr.c:3920
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition expr.c:3872
SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1468
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition scip_expr.c:1443
SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
Definition expr.c:3905
SCIP_RETCODE SCIPparseExpr(SCIP *scip, SCIP_EXPR **expr, const char *exprstr, const char **finalpos, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition scip_expr.c:1406
SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
Definition expr_value.c:298
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition expr.c:3946
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition expr.c:3882
SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
Definition expr.c:4028
void SCIPcaptureExpr(SCIP_EXPR *expr)
Definition scip_expr.c:1435
SCIP_RETCODE SCIPevalExprActivity(SCIP *scip, SCIP_EXPR *expr)
Definition scip_expr.c:1742
SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
Definition expr.c:3895
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
void SCIPintervalIntersect(SCIP_INTERVAL *resultant, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
void SCIPintervalSet(SCIP_INTERVAL *resultant, SCIP_Real value)
SCIP_Bool SCIPintervalIsSubsetEQ(SCIP_Real infinity, SCIP_INTERVAL operand1, SCIP_INTERVAL operand2)
SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
struct SCIP_Interval SCIP_INTERVAL
void SCIPintervalEntropy(SCIP_Real infinity, SCIP_INTERVAL *resultant, SCIP_INTERVAL operand)
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
SCIP_Bool SCIPisGE(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 SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
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 SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
return SCIP_OKAY
assert(minobj< SCIPgetCutoffbound(scip))
SCIP_Real sup
SCIP_Real inf
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
#define SCIP_DECL_EXPR_OWNERCREATE(x)
Definition type_expr.h:143
#define SCIP_DECL_EXPRREVERSEPROP(x)
Definition type_expr.h:659
#define SCIP_DECL_EXPRINITESTIMATES(x)
Definition type_expr.h:610
#define SCIP_DECL_EXPRCURVATURE(x)
Definition type_expr.h:340
struct SCIP_ExprhdlrData SCIP_EXPRHDLRDATA
Definition type_expr.h:195
struct SCIP_ExprData SCIP_EXPRDATA
Definition type_expr.h:54
#define SCIP_DECL_EXPRFREEDATA(x)
Definition type_expr.h:268
@ SCIP_EXPRCURV_CONCAVE
Definition type_expr.h:64
#define SCIP_DECL_EXPRPARSE(x)
Definition type_expr.h:312
#define SCIP_DECL_EXPRBWDIFF(x)
Definition type_expr.h:451
#define SCIP_DECL_EXPRINTEVAL(x)
Definition type_expr.h:541
#define SCIP_DECL_EXPRMONOTONICITY(x)
Definition type_expr.h:358
@ SCIP_MONOTONE_UNKNOWN
Definition type_expr.h:71
@ SCIP_MONOTONE_INC
Definition type_expr.h:72
@ SCIP_MONOTONE_DEC
Definition type_expr.h:73
struct SCIP_Exprhdlr SCIP_EXPRHDLR
Definition type_expr.h:194
#define SCIP_DECL_EXPRSIMPLIFY(x)
Definition type_expr.h:634
#define SCIP_DECL_EXPREVAL(x)
Definition type_expr.h:428
#define SCIP_DECL_EXPRHASH(x)
Definition type_expr.h:393
#define SCIP_DECL_EXPRCOPYHDLR(x)
Definition type_expr.h:210
#define SCIP_DECL_EXPRINTEGRALITY(x)
Definition type_expr.h:377
#define SCIP_DECL_EXPRCOPYDATA(x)
Definition type_expr.h:249
#define SCIP_DECL_EXPRESTIMATE(x)
Definition type_expr.h:577
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90