SCIP Doxygen Documentation
Loading...
Searching...
No Matches
expr_var.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_var.c
26 * @ingroup DEFPLUGINS_EXPR
27 * @brief variable expression handler
28 * @author Stefan Vigerske
29 * @author Benjamin Mueller
30 * @author Felipe Serrano
31 */
32
33/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
34
35#include "scip/expr_var.h"
36#include "scip/expr_sum.h"
37
38#ifdef NDEBUG
39#undef SCIPgetVarExprVar
40#endif
41
42#define EXPRHDLR_NAME "var"
43#define EXPRHDLR_DESC "SCIP variable expression"
44#define EXPRHDLR_PRECEDENCE 0
45#define EXPRHDLR_HASHKEY SCIPcalcFibHash(22153.0)
46
47/** translate from one value of infinity to another
48 *
49 * if val is >= infty1, then give infty2, else give val
50 */
51#define infty2infty(infty1, infty2, val) ((val) >= (infty1) ? (infty2) : (val))
52
53
54/** simplifies a variable expression
55 *
56 * We replace the variable when fixed by its value.
57 * If a variable is fixed, (multi)aggregated or more generally, inactive, we replace it with its active counterpart
58 *
59 * Implementation note:
60 * - we follow the general approach of the simplify, where we replace the var expression for its
61 * simplified expression only in the current parent. So if we see that there is any performance issue in the simplify
62 * we might have to revisit this decision.
63 * - we build the sum expression by appending variable expressions one at a time. This may be
64 * speed-up if we allocate memory for all the variable expressions and build the sum directly.
65 */
66static
68{ /*lint --e{715}*/
70 SCIP_VAR** vars;
71 SCIP_Real* coefs;
72 SCIP_Real constant;
73 int nvars;
74 int varssize;
75 int i;
76 SCIP_EXPR* sumexpr;
77
78 assert(expr != NULL);
79 assert(simplifiedexpr != NULL);
80
81 var = SCIPgetVarExprVar(expr);
82 assert(var != NULL);
83
84 /* if var is active then there is nothing to simplify */
85 if( SCIPvarIsActive(var) )
86 {
87 *simplifiedexpr = expr;
88 /* we have to capture it, since it must simulate a "normal" simplified call in which a new expression is created */
89 SCIPcaptureExpr(*simplifiedexpr);
90 return SCIP_OKAY;
91 }
92
93 /* var is not active; obtain active representation var = constant + sum coefs_i vars_i */
94 varssize = 5;
96 SCIP_CALL( SCIPallocBufferArray(scip, &coefs, varssize) );
97
98 vars[0] = var;
99 coefs[0] = 1.0;
100 constant = 0.0;
101 nvars = 1;
102 if( !SCIPvarIsOriginal(var) )
103 {
104 int requsize;
105
106 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, coefs, &nvars, varssize, &constant, &requsize) );
107
108 if( requsize > varssize )
109 {
111 SCIP_CALL( SCIPreallocBufferArray(scip, &coefs, requsize) );
112 varssize = requsize;
113 SCIP_CALL( SCIPgetProbvarLinearSum(scip, vars, coefs, &nvars, varssize, &constant, &requsize) );
114 assert(requsize <= varssize);
115 }
116 assert(requsize == nvars);
117 }
118
119 /* create expression for constant + sum coefs_i vars_i */
120 SCIP_CALL( SCIPcreateExprSum(scip, &sumexpr, 0, NULL, NULL, constant, ownercreate, ownercreatedata) );
121
122 for( i = 0; i < nvars; ++i )
123 {
124 SCIP_EXPR* child;
125
126 SCIP_CALL( SCIPcreateExprVar(scip, &child, vars[i], ownercreate, ownercreatedata) );
127 SCIP_CALL( SCIPappendExprSumExpr(scip, sumexpr, child, coefs[i]) );
128 SCIP_CALL( SCIPreleaseExpr(scip, &child) );
129 }
130
131 /* simplify since it might not really be a sum */
132 SCIP_CALL( SCIPcallExprSimplify(scip, sumexpr, simplifiedexpr, ownercreate, ownercreatedata) );
133
134#ifdef SCIP_DEBUG
135 SCIPinfoMessage(scip, NULL, "expr_var simplify: <%s> := ", SCIPvarGetName(var));
136 SCIPprintExpr(scip, *simplifiedexpr, NULL);
137 SCIPinfoMessage(scip, NULL, "\n");
138#endif
139
140 /* we cannot handle fixings to infinity at the moment (TODO we should) */
141 assert(!SCIPisInfinity(scip, REALABS(constant)));
142
143 /* release no longer used sumexpr */
144 SCIP_CALL( SCIPreleaseExpr(scip, &sumexpr) );
145
146 /* free memory */
147 SCIPfreeBufferArray(scip, &coefs);
149
150 return SCIP_OKAY;
151}
152
153/** the order of two variable is given by their indices
154 *
155 * @note this is affected by permutations in the problem
156 */
157static
159{ /*lint --e{715}*/
160 int index1;
161 int index2;
162
163 index1 = SCIPvarGetIndex(SCIPgetVarExprVar(expr1));
164 index2 = SCIPvarGetIndex(SCIPgetVarExprVar(expr2));
165
166 return index1 < index2 ? -1 : index1 == index2 ? 0 : 1;
167}
168
169/** expression handler copy callback */
170static
172{ /*lint --e{715}*/
174
175 return SCIP_OKAY;
176}
177
178/** expression data copy callback */
179static
181{ /*lint --e{715}*/
182 SCIP_VAR* var;
183
184 assert(targetexprdata != NULL);
185 assert(sourceexpr != NULL);
186
187 /* copying into a different SCIP should be handled on the SCIPexprCopy() level (via mapexpr) */
188 assert(targetscip == sourcescip);
189
190 var = SCIPgetVarExprVar(sourceexpr);
191 assert(var != NULL);
192
193 *targetexprdata = (SCIP_EXPRDATA*)var;
194
195 SCIP_CALL( SCIPcaptureVar(targetscip, var) );
196
197 return SCIP_OKAY;
198}
199
200/** expression data free callback */
201static
203{ /*lint --e{715}*/
204 SCIP_EXPRDATA* exprdata;
205
206 assert(expr != NULL);
207
208 exprdata = SCIPexprGetData(expr);
209 assert(exprdata != NULL);
210
211 SCIP_CALL( SCIPreleaseVar(scip, (SCIP_VAR**)&exprdata) );
212
213 SCIPexprSetData(expr, NULL);
214
215 return SCIP_OKAY;
216}
217
218/** expression print callback */
219static
221{ /*lint --e{715}*/
222 assert(expr != NULL);
223 assert(SCIPgetVarExprVar(expr) != NULL);
224
225 if( stage == SCIP_EXPRITER_ENTEREXPR )
226 {
228 }
229
230 return SCIP_OKAY;
231}
232
233/** expression point evaluation callback */
234static
236{ /*lint --e{715}*/
237 assert(expr != NULL);
238 assert(SCIPgetVarExprVar(expr) != NULL);
239
240 *val = SCIPgetSolVal(scip, sol, SCIPgetVarExprVar(expr));
241
242 return SCIP_OKAY;
243}
244
245/** expression backward derivative evaluation callback */
246static
248{ /*lint --e{715}*/
249 /* this should never happen because variable expressions do not have children */
250 return SCIP_INVALIDCALL;
251}
252
253/** expression forward derivative evaluation callback */
254static
256{ /*lint --e{715}*/
257 assert(expr != NULL);
258 assert(SCIPgetVarExprVar(expr) != NULL);
259
260 *dot = SCIPgetSolVal(scip, direction, SCIPgetVarExprVar(expr));
261
262 return SCIP_OKAY;
263}
264
265/** expression derivative evaluation callback */
266static
268{ /*lint --e{715}*/
269 /* this should never happen because variable expressions do not have children */
270 return SCIP_INVALIDCALL;
271}
272
273/** expression interval evaluation callback */
274static
276{ /*lint --e{715}*/
277 SCIP_VAR* var;
278
279 assert(expr != NULL);
280
281 var = SCIPgetVarExprVar(expr);
282 assert(var != NULL);
283
284 if( intevalvar != NULL )
285 *interval = intevalvar(scip, var, intevalvardata);
286 else
287 {
288 SCIP_Real lb;
289 SCIP_Real ub;
290
293
294 SCIPintervalSetBounds(interval, /*lint !e666*/
295 -infty2infty(SCIPinfinity(scip), SCIP_INTERVAL_INFINITY, -lb), /*lint !e666*/
297 }
298
299 return SCIP_OKAY;
300}
301
302/** variable hash callback */
303static
305{ /*lint --e{715}*/
306 SCIP_VAR* var;
307
308 assert(scip != NULL);
309 assert(expr != NULL);
310 assert(SCIPexprGetNChildren(expr) == 0);
311 assert(hashkey != NULL);
312
313 var = SCIPgetVarExprVar(expr);
314 assert(var != NULL);
315
316 *hashkey = EXPRHDLR_HASHKEY;
318
319 return SCIP_OKAY;
320}
321
322/** expression curvature detection callback */
323static
325{ /*lint --e{715}*/
326 assert(scip != NULL);
327 assert(expr != NULL);
328 assert(success != NULL);
329 assert(SCIPexprGetNChildren(expr) == 0);
330
331 /* x -> x is linear, convex, and concave */
332 *success = TRUE;
333
334 return SCIP_OKAY;
335}
336
337/** expression monotonicity detection callback */
338static
340{ /*lint --e{715}*/
341 assert(scip != NULL);
342 assert(expr != NULL);
343 assert(result != NULL);
344 assert(SCIPexprGetNChildren(expr) == 0);
345
347
348 return SCIP_OKAY;
349}
350
351/** expression integrality detection callback */
352static
354{ /*lint --e{715}*/
355 assert(scip != NULL);
356 assert(expr != NULL);
357 assert(integrality != NULL);
358
360
361 if( !SCIPvarIsIntegral(var) )
362 *integrality = SCIP_IMPLINTTYPE_NONE;
364 *integrality = SCIP_IMPLINTTYPE_WEAK;
365 else
366 *integrality = SCIP_IMPLINTTYPE_STRONG;
367
368 return SCIP_OKAY;
369}
370
371/** creates the handler for variable expression and includes it into SCIP */
373 SCIP* scip /**< SCIP data structure */
374 )
375{
376 SCIP_EXPRHDLR* exprhdlr;
377
379 assert(exprhdlr != NULL);
380
381 SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrVar, NULL);
382 SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataVar, freedataVar);
383 SCIPexprhdlrSetSimplify(exprhdlr, simplifyVar);
384 SCIPexprhdlrSetCompare(exprhdlr, compareVar);
385 SCIPexprhdlrSetPrint(exprhdlr, printVar);
386 SCIPexprhdlrSetIntEval(exprhdlr, intevalVar);
387 SCIPexprhdlrSetHash(exprhdlr, hashVar);
388 SCIPexprhdlrSetDiff(exprhdlr, bwdiffVar, fwdiffVar, bwfwdiffVar);
389 SCIPexprhdlrSetCurvature(exprhdlr, curvatureVar);
390 SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityVar);
391 SCIPexprhdlrSetIntegrality(exprhdlr, integralityVar);
392
393 return SCIP_OKAY;
394}
395
396/** creates a variable expression */
398 SCIP* scip, /**< SCIP data structure */
399 SCIP_EXPR** expr, /**< pointer where to store expression */
400 SCIP_VAR* var, /**< variable to be stored */
401 SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
402 void* ownercreatedata /**< data to pass to ownercreate */
403 )
404{
405 SCIP_EXPRDATA* exprdata;
406
407 assert(expr != NULL);
408 assert(var != NULL);
409
410 /* capture the variable so that it doesn't disappear while the expr still points to it */
412
413 exprdata = (SCIP_EXPRDATA*)var;
414
415 SCIP_CALL( SCIPcreateExpr(scip, expr, SCIPgetExprhdlrVar(scip), exprdata, 0, NULL, ownercreate, ownercreatedata) );
416
417 return SCIP_OKAY;
418}
419
420/* from pub_expr.h */
421
422/** gets the variable of a variable expression */
424 SCIP_EXPR* expr /**< variable expression */
425 )
426{
427 assert(expr != NULL);
428 assert(SCIPexprGetData(expr) != NULL);
429
431
432 return (SCIP_VAR*)SCIPexprGetData(expr);
433}
#define NULL
Definition def.h:257
#define SCIP_INTERVAL_INFINITY
Definition def.h:189
#define SCIP_STRINGEQ(name, reference, retcode)
Definition def.h:454
#define SCIP_Real
Definition def.h:165
#define TRUE
Definition def.h:102
#define REALABS(x)
Definition def.h:191
#define SCIP_CALL(x)
Definition def.h:364
#define EXPRHDLR_HASHKEY
Definition expr_abs.c:41
#define EXPRHDLR_NAME
Definition expr_abs.c:38
#define EXPRHDLR_DESC
Definition expr_abs.c:39
#define EXPRHDLR_PRECEDENCE
Definition expr_abs.c:40
sum expression handler
#define infty2infty(infty1, infty2, val)
Definition expr_var.c:51
variable expression handler
SCIP_RETCODE SCIPcreateExprVar(SCIP *scip, SCIP_EXPR **expr, SCIP_VAR *var, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_var.c:397
SCIP_RETCODE SCIPappendExprSumExpr(SCIP *scip, SCIP_EXPR *expr, SCIP_EXPR *child, SCIP_Real childcoef)
Definition expr_sum.c:1154
SCIP_RETCODE SCIPcreateExprSum(SCIP *scip, SCIP_EXPR **expr, int nchildren, SCIP_EXPR **children, SCIP_Real *coefficients, SCIP_Real constant, SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), void *ownercreatedata)
Definition expr_sum.c:1117
SCIP_RETCODE SCIPincludeExprhdlrVar(SCIP *scip)
Definition expr_var.c:372
void SCIPinfoMessage(SCIP *scip, FILE *file, const char *formatstr,...)
unsigned int SCIPcalcFibHash(SCIP_Real v)
Definition misc.c:10462
const char * SCIPexprhdlrGetName(SCIP_EXPRHDLR *exprhdlr)
Definition expr.c:545
void SCIPexprhdlrSetCompare(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:462
void SCIPexprhdlrSetIntegrality(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:440
void SCIPexprhdlrSetCurvature(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:418
void SCIPexprhdlrSetIntEval(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:488
void SCIPexprhdlrSetMonotonicity(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:429
SCIP_EXPRHDLR * SCIPgetExprhdlrVar(SCIP *scip)
Definition scip_expr.c:906
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
void SCIPexprhdlrSetPrint(SCIP_EXPRHDLR *exprhdlr,)
Definition expr.c:396
void SCIPexprhdlrSetCopyFreeData(SCIP_EXPRHDLR *exprhdlr, SCIP_DECL_EXPRCOPYDATA((*copydata)),)
Definition expr.c:383
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_RETCODE SCIPreleaseExpr(SCIP *scip, SCIP_EXPR **expr)
Definition scip_expr.c:1443
SCIP_EXPRDATA * SCIPexprGetData(SCIP_EXPR *expr)
Definition expr.c:3905
SCIP_RETCODE SCIPprintExpr(SCIP *scip, SCIP_EXPR *expr, FILE *file)
Definition scip_expr.c:1512
SCIP_VAR * SCIPgetVarExprVar(SCIP_EXPR *expr)
Definition expr_var.c:423
void SCIPcaptureExpr(SCIP_EXPR *expr)
Definition scip_expr.c:1435
SCIP_EXPRHDLR * SCIPexprGetHdlr(SCIP_EXPR *expr)
Definition expr.c:3895
void SCIPintervalSetBounds(SCIP_INTERVAL *resultant, SCIP_Real inf, SCIP_Real sup)
#define SCIPallocBufferArray(scip, ptr, num)
Definition scip_mem.h:124
#define SCIPreallocBufferArray(scip, ptr, num)
Definition scip_mem.h:128
#define SCIPfreeBufferArray(scip, ptr)
Definition scip_mem.h:136
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition scip_sol.c:1763
SCIP_Real SCIPinfinity(SCIP *scip)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition var.c:23674
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition var.c:24300
int SCIPvarGetIndex(SCIP_VAR *var)
Definition var.c:23684
const char * SCIPvarGetName(SCIP_VAR *var)
Definition var.c:23299
SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
Definition scip_var.c:1887
SCIP_RETCODE SCIPgetProbvarLinearSum(SCIP *scip, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize)
Definition scip_var.c:2378
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition var.c:23522
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition var.c:24266
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition var.c:23449
SCIP_IMPLINTTYPE SCIPvarGetImplType(SCIP_VAR *var)
Definition var.c:23495
SCIP_RETCODE SCIPcaptureVar(SCIP *scip, SCIP_VAR *var)
Definition scip_var.c:1853
return SCIP_OKAY
static SCIP_SOL * sol
assert(minobj< SCIPgetCutoffbound(scip))
int nvars
SCIP_VAR * var
static SCIP_VAR ** vars
struct SCIP_Expr SCIP_EXPR
Definition type_expr.h:55
#define SCIP_DECL_EXPR_OWNERCREATE(x)
Definition type_expr.h:143
#define SCIP_DECL_EXPRBWFWDIFF(x)
Definition type_expr.h:522
#define SCIP_DECL_EXPRCURVATURE(x)
Definition type_expr.h:340
struct SCIP_ExprData SCIP_EXPRDATA
Definition type_expr.h:54
#define SCIP_DECL_EXPRFREEDATA(x)
Definition type_expr.h:268
#define SCIP_DECL_EXPRBWDIFF(x)
Definition type_expr.h:451
#define SCIP_DECL_EXPRINTEVAL(x)
Definition type_expr.h:541
#define SCIP_DECL_EXPRMONOTONICITY(x)
Definition type_expr.h:358
@ SCIP_MONOTONE_INC
Definition type_expr.h:72
struct SCIP_Exprhdlr SCIP_EXPRHDLR
Definition type_expr.h:194
#define SCIP_DECL_EXPRCOMPARE(x)
Definition type_expr.h:412
#define SCIP_DECL_EXPRSIMPLIFY(x)
Definition type_expr.h:634
#define SCIP_DECL_EXPREVAL(x)
Definition type_expr.h:428
#define SCIP_DECL_EXPRFWDIFF(x)
Definition type_expr.h:482
#define SCIP_DECL_EXPRHASH(x)
Definition type_expr.h:393
#define SCIP_DECL_EXPRCOPYHDLR(x)
Definition type_expr.h:210
#define SCIP_DECL_EXPRPRINT(x)
Definition type_expr.h:289
#define SCIP_DECL_EXPRINTEGRALITY(x)
Definition type_expr.h:377
#define SCIP_DECL_EXPRCOPYDATA(x)
Definition type_expr.h:249
#define SCIP_EXPRITER_ENTEREXPR
Definition type_expr.h:694
@ SCIP_INVALIDCALL
enum SCIP_Retcode SCIP_RETCODE
struct Scip SCIP
Definition type_scip.h:39
struct SCIP_Var SCIP_VAR
Definition type_var.h:166
@ SCIP_IMPLINTTYPE_NONE
Definition type_var.h:90
@ SCIP_IMPLINTTYPE_STRONG
Definition type_var.h:106
@ SCIP_IMPLINTTYPE_WEAK
Definition type_var.h:91