Scippy

SCIP

Solving Constraint Integer Programs

expr_erf.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-2022 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file expr_erf.c
17  * @brief handler for Gaussian error function expressions
18  * @author Benjamin Mueller
19  */
20 
21 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
22 
23 #include "scip/expr_erf.h"
24 #include "scip/expr_value.h"
25 
26 /* fundamental expression handler properties */
27 #define EXPRHDLR_NAME "erf"
28 #define EXPRHDLR_DESC "Gaussian error function"
29 #define EXPRHDLR_PRECEDENCE 79000
30 #define EXPRHDLR_HASHKEY SCIPcalcFibHash(131071.0)
31 
32 /*
33  * Data structures
34  */
35 
36 /*
37  * Local methods
38  */
39 
40 /** evaluates the Gaussian error function at a given point */
41 static
43  SCIP_Real x /**< point to evaluate */
44  )
45 {
46  SCIP_Real a1 = +0.254829592;
47  SCIP_Real a2 = -0.284496736;
48  SCIP_Real a3 = +1.421413741;
49  SCIP_Real a4 = -1.453152027;
50  SCIP_Real a5 = +1.061405429;
51  SCIP_Real p = +0.3275911;
52  int sign = (x >= 0.0) ? 1 : -1;
53  SCIP_Real t = 1.0 / (1.0 + p * REALABS(x));
54  SCIP_Real y = 1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x*x);
55 
56  return sign*y;
57 }
58 
59 /*
60  * Callback methods of expression handler
61  */
62 
63 /** expression handler copy callback */
64 static
66 { /*lint --e{715}*/
68 
69  return SCIP_OKAY;
70 }
71 
72 /** simplifies an erf expression */
73 static
75 { /*lint --e{715}*/
76  SCIP_EXPR* child;
77 
78  assert(scip != NULL);
79  assert(expr != NULL);
80  assert(simplifiedexpr != NULL);
81  assert(SCIPexprGetNChildren(expr) == 1);
82 
83  child = SCIPexprGetChildren(expr)[0];
84  assert(child != NULL);
85 
86  /* check for value expression */
87  if( SCIPisExprValue(scip, child) )
88  {
89  SCIP_CALL( SCIPcreateExprValue(scip, simplifiedexpr, errorf(SCIPgetValueExprValue(child)), ownercreate, ownercreatedata) );
90  }
91  else
92  {
93  *simplifiedexpr = expr;
94 
95  /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
96  SCIPcaptureExpr(*simplifiedexpr);
97  }
98 
99  return SCIP_OKAY;
100 }
101 
102 /** expression parse callback */
103 static
105 { /*lint --e{715}*/
106  SCIP_EXPR* childexpr;
107 
108  assert(expr != NULL);
109 
110  /* parse child expression from remaining string */
111  SCIP_CALL( SCIPparseExpr(scip, &childexpr, string, endstring, ownercreate, ownercreatedata) );
112  assert(childexpr != NULL);
113 
114  /* create gaussian error function expression */
115  SCIP_CALL( SCIPcreateExprErf(scip, expr, childexpr, ownercreate, ownercreatedata) );
116  assert(*expr != NULL);
117 
118  /* release child expression since it has been captured by the gaussian error function expression */
119  SCIP_CALL( SCIPreleaseExpr(scip, &childexpr) );
120 
121  *success = TRUE;
122 
123  return SCIP_OKAY;
124 }
125 
126 /** expression (point-) evaluation callback */
127 static
129 { /*lint --e{715}*/
130  assert(expr != NULL);
131  assert(SCIPexprGetData(expr) == NULL);
132  assert(SCIPexprGetNChildren(expr) == 1);
133  assert(SCIPexprGetEvalValue(SCIPexprGetChildren(expr)[0]) != SCIP_INVALID); /*lint !e777*/
134 
136 
137  return SCIP_OKAY;
138 }
139 
140 /** expression derivative evaluation callback */
141 static
143 { /*lint --e{715}*/
144  assert(expr != NULL);
145 
146  SCIPerrorMessage("method of erf expression handler not implemented yet\n");
147  SCIPABORT(); /*lint --e{527}*/
148 
149  return SCIP_OKAY;
150 }
151 
152 /** expression interval evaluation callback */
153 static
155 { /*lint --e{715}*/
156  SCIP_INTERVAL childinterval;
157 
158  assert(expr != NULL);
159  assert(SCIPexprGetData(expr) == NULL);
160  assert(SCIPexprGetNChildren(expr) == 1);
161 
162  childinterval = SCIPexprGetActivity(SCIPexprGetChildren(expr)[0]);
163 
164  if( SCIPintervalIsEmpty(SCIP_INTERVAL_INFINITY, childinterval) )
165  SCIPintervalSetEmpty(interval);
166  else
167  {
168  SCIP_Real childinf = SCIPintervalGetInf(childinterval);
169  SCIP_Real childsup = SCIPintervalGetSup(childinterval);
170  SCIP_Real inf = childinf <= -SCIP_INTERVAL_INFINITY ? -1.0 : errorf(childinf);
171  SCIP_Real sup = childsup >= +SCIP_INTERVAL_INFINITY ? +1.0 : errorf(childsup);
172  assert(inf <= sup);
173  SCIPintervalSetBounds(interval, inf, sup);
174  }
175 
176  return SCIP_OKAY;
177 }
178 
179 /** erf hash callback */
180 static
182 { /*lint --e{715}*/
183  assert(scip != NULL);
184  assert(expr != NULL);
185  assert(SCIPexprGetNChildren(expr) == 1);
186  assert(hashkey != NULL);
187  assert(childrenhashes != NULL);
188 
189  *hashkey = EXPRHDLR_HASHKEY;
190  *hashkey ^= childrenhashes[0];
191 
192  return SCIP_OKAY;
193 }
194 
195 /** expression curvature detection callback */
196 static
198 { /*lint --e{715}*/
199  assert(scip != NULL);
200  assert(expr != NULL);
201 
202  /* expression is
203  * - convex if child is convex and child <= 0
204  * - concave if child is concave and child >= 0
205  */
206  if( exprcurvature == SCIP_EXPRCURV_CONVEX )
207  {
208  *success = TRUE;
209  *childcurv = SCIP_EXPRCURV_CONVEX;
210  }
211  else
212  *success = FALSE;
213 
214  return SCIP_OKAY;
215 }
216 
217 /** expression monotonicity detection callback */
218 static
220 { /*lint --e{715}*/
221  assert(scip != NULL);
222  assert(expr != NULL);
223  assert(result != NULL);
224 
225  *result = SCIP_MONOTONE_INC;
226 
227  return SCIP_OKAY;
228 }
229 
230 /** expression integrality detection callback */
231 static
233 { /*lint --e{715}*/
234  assert(scip != NULL);
235  assert(expr != NULL);
236  assert(isintegral != NULL);
237 
238  *isintegral = FALSE;
239 
240  return SCIP_OKAY;
241 }
242 
243 /** creates an erf expression
244  *
245  * @attention The implementation of `erf` expressions is incomplete.
246  * They are not usable for most use cases so far.
247  */
249  SCIP* scip, /**< SCIP data structure */
250  SCIP_EXPR** expr, /**< pointer where to store expression */
251  SCIP_EXPR* child, /**< child expression */
252  SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
253  void* ownercreatedata /**< data to pass to ownercreate */
254  )
255 {
256  SCIP_EXPRHDLR* exprhdlr;
257 
258  assert(expr != NULL);
259  assert(child != NULL);
260 
261  exprhdlr = SCIPfindExprhdlr(scip, EXPRHDLR_NAME);
262  if( exprhdlr == NULL )
263  {
264  SCIPerrorMessage("could not find %s expression handler -> abort\n", EXPRHDLR_NAME);
265  SCIPABORT();
266  return SCIP_PLUGINNOTFOUND;
267  }
268 
269  /* create expression */
270  SCIP_CALL( SCIPcreateExpr(scip, expr, exprhdlr, NULL, 1, &child, ownercreate, ownercreatedata) );
271 
272  return SCIP_OKAY;
273 }
274 
275 /** indicates whether expression is of erf-type */ /*lint -e{715}*/
277  SCIP* scip, /**< SCIP data structure */
278  SCIP_EXPR* expr /**< expression */
279  )
280 { /*lint --e{715}*/
281  assert(expr != NULL);
282 
283  return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0;
284 }
285 
286 /** creates the handler for erf expressions and includes it into SCIP
287  *
288  * @attention The implementation of this expression handler is incomplete.
289  * It is not usable for most use cases so far.
290  */
292  SCIP* scip /**< SCIP data structure */
293  )
294 {
295  SCIP_EXPRHDLR* exprhdlr;
296 
297  /* include expression handler */
299  assert(exprhdlr != NULL);
300 
301  SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrErf, NULL);
302  SCIPexprhdlrSetSimplify(exprhdlr, simplifyErf);
303  SCIPexprhdlrSetParse(exprhdlr, parseErf);
304  SCIPexprhdlrSetIntEval(exprhdlr, intevalErf);
305  SCIPexprhdlrSetHash(exprhdlr, hashErf);
306  SCIPexprhdlrSetDiff(exprhdlr, bwdiffErf, NULL, NULL);
307  SCIPexprhdlrSetCurvature(exprhdlr, curvatureErf);
308  SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityErf);
309  SCIPexprhdlrSetIntegrality(exprhdlr, integralityErf);
310 
311  return SCIP_OKAY;
312 }
static SCIP_DECL_EXPRCOPYHDLR(copyhdlrErf)
Definition: expr_erf.c:65
int SCIPexprGetNChildren(SCIP_EXPR *expr)
Definition: expr.c:3798
#define EXPRHDLR_HASHKEY
Definition: expr_erf.c:30
void SCIPexprhdlrSetDiff(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRBWDIFF((*bwdiff)), SCIP_DECL_EXPRFWDIFF((*fwdiff)), SCIP_DECL_EXPRBWFWDIFF((*bwfwdiff)))
Definition: expr.c:464
const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
Definition: expr.c:525
#define EXPRHDLR_DESC
Definition: expr_erf.c:28
static SCIP_DECL_EXPRBWDIFF(bwdiffErf)
Definition: expr_erf.c:142
void SCIPexprhdlrSetParse(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRPARSE((*parse)))
Definition: expr.c:398
#define FALSE
Definition: def.h:87
#define TRUE
Definition: def.h:86
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
void SCIPexprhdlrSetHash(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRHASH((*hash)))
Definition: expr.c:442
SCIP_INTERVAL SCIPexprGetActivity(SCIP_EXPR *expr)
Definition: expr.c:3954
void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEGRALITY((*integrality)))
Definition: expr.c:431
void SCIPcaptureExpr(SCIP_EXPR *expr)
Definition: scip_expr.c:1399
SCIP_EXPRHDLR * SCIPfindExprhdlr(SCIP *scip, const char *name)
Definition: scip_expr.c:859
SCIP_VAR ** x
Definition: circlepacking.c:54
SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
Definition: expr.c:3831
SCIP_EXPR ** SCIPexprGetChildren(SCIP_EXPR *expr)
Definition: expr.c:3808
SCIP_Real SCIPexprGetEvalValue(SCIP_EXPR *expr)
Definition: expr.c:3872
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:964
#define SCIPerrorMessage
Definition: pub_message.h:55
SCIP_Bool SCIPintervalIsEmpty(SCIP_Real infinity, SCIP_INTERVAL operand)
void SCIPintervalSetEmpty(SCIP_INTERVAL *resultant)
SCIP_Bool SCIPisExprValue(SCIP *scip, SCIP_EXPR *expr)
Definition: scip_expr.c:1432
SCIP_Real SCIPintervalGetInf(SCIP_INTERVAL interval)
#define NULL
Definition: lpi_spx1.cpp:155
SCIP_Real SCIPintervalGetSup(SCIP_INTERVAL interval)
#define REALABS(x)
Definition: def.h:201
#define SCIP_CALL(x)
Definition: def.h:384
static SCIP_Real errorf(SCIP_Real x)
Definition: expr_erf.c:42
static SCIP_DECL_EXPRPARSE(parseErf)
Definition: expr_erf.c:104
SCIP_RETCODE SCIPcreateExprValue(SCIP *scip, SCIP_EXPR **expr, SCIP_Real value, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_value.c:261
void SCIPexprhdlrSetCopyFreeHdlr(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYHDLR((*copyhdlr)), SCIP_DECL_EXPRFREEHDLR((*freehdlr)))
Definition: expr.c:359
#define SCIP_INTERVAL_INFINITY
Definition: def.h:199
#define EXPRHDLR_NAME
Definition: expr_erf.c:27
SCIP_RETCODE SCIPcreateExprErf(SCIP *scip, SCIP_EXPR **expr, SCIP_EXPR *child, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition: expr_erf.c:248
#define SCIP_Bool
Definition: def.h:84
SCIP_Bool SCIPisExprErf(SCIP *scip, SCIP_EXPR *expr)
Definition: expr_erf.c:276
#define SCIP_DECL_EXPR_OWNERCREATE(x)
Definition: type_expr.h:131
void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRMONOTONICITY((*monotonicity)))
Definition: expr.c:420
SCIP_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition: scip_expr.c:1407
SCIP_RETCODE SCIPincludeExprhdlrErf(SCIP *scip)
Definition: expr_erf.c:291
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:1370
static SCIP_DECL_EXPRSIMPLIFY(simplifyErf)
Definition: expr_erf.c:74
SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
Definition: expr.c:3821
static SCIP_DECL_EXPRCURVATURE(curvatureErf)
Definition: expr_erf.c:197
constant value expression handler
static SCIP_DECL_EXPRMONOTONICITY(monotonicityErf)
Definition: expr_erf.c:219
void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCURVATURE((*curvature)))
Definition: expr.c:409
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
#define SCIP_Real
Definition: def.h:177
handler for Gaussian error function expressions
static SCIP_DECL_EXPREVAL(evalErf)
Definition: expr_erf.c:128
SCIP_VAR ** y
Definition: circlepacking.c:55
static SCIP_DECL_EXPRHASH(hashErf)
Definition: expr_erf.c:181
#define SCIP_INVALID
Definition: def.h:197
SCIP_Real SCIPgetValueExprValue(SCIP_EXPR *expr)
Definition: expr_value.c:285
#define EXPRHDLR_PRECEDENCE
Definition: expr_erf.c:29
static SCIP_DECL_EXPRINTEGRALITY(integralityErf)
Definition: expr_erf.c:232
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:814
static SCIP_DECL_EXPRINTEVAL(intevalErf)
Definition: expr_erf.c:154
#define SCIPABORT()
Definition: def.h:356
void SCIPexprhdlrSetSimplify(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRSIMPLIFY((*simplify)))
Definition: expr.c:490
void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRINTEVAL((*inteval)))
Definition: expr.c:479