1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 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_varidx.c
26   	 * @ingroup DEFPLUGINS_EXPR
27   	 * @brief  handler for variable index expressions
28   	 * @author Benjamin Mueller
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include "scip/expr_varidx.h"
34   	#include "scip/intervalarith.h"
35   	#include "scip/pub_expr.h"
36   	#include "scip/scip_expr.h"
37   	#include "scip/scip_message.h"
38   	#include "scip/pub_misc.h"
39   	
40   	/* fundamental expression handler properties */
41   	#define EXPRHDLR_NAME         "varidx"
42   	#define EXPRHDLR_DESC         "expression that represents a variable index (typically used for NLPI)"
43   	#define EXPRHDLR_PRECEDENCE   0
44   	#define EXPRHDLR_HASHKEY      20201210
45   	
46   	/*
47   	 * Callback methods of expression handler
48   	 */
49   	
50   	/** expression handler copy callback */
51   	static
52   	SCIP_DECL_EXPRCOPYHDLR(copyhdlrVaridx)
53   	{  /*lint --e{715}*/
54   	   SCIP_CALL( SCIPincludeExprhdlrVaridx(scip) );
55   	
56   	   return SCIP_OKAY;
57   	}
58   	
59   	/** expression compare callback */
60   	static
61   	SCIP_DECL_EXPRCOMPARE(compareVaridx)
62   	{  /*lint --e{715}*/
63   	   int idx1, idx2;
64   	
65   	   assert(expr1 != NULL);
66   	   assert(expr2 != NULL);
67   	
68   	   idx1 = SCIPgetIndexExprVaridx(expr1);
69   	   idx2 = SCIPgetIndexExprVaridx(expr2);
70   	
71   	   if( idx1 < idx2 )
72   	      return -1;
73   	   if( idx1 > idx2 )
74   	      return 1;
75   	   return 0;
76   	}
77   	
78   	/** expression data copy callback */
79   	static
80   	SCIP_DECL_EXPRCOPYDATA(copydataVaridx)
81   	{  /*lint --e{715}*/
82   	   assert(targetexprdata != NULL);
83   	
84   	   *targetexprdata = SCIPexprGetData(sourceexpr);
85   	
86   	   return SCIP_OKAY;
87   	}
88   	
89   	/** expression data free callback */
90   	static
91   	SCIP_DECL_EXPRFREEDATA(freedataVaridx)
92   	{  /*lint --e{715}*/
93   	   assert(expr != NULL);
94   	
95   	   SCIPexprSetData(expr, NULL);
96   	
97   	   return SCIP_OKAY;
98   	}
99   	
100  	/** expression print callback */
101  	static
102  	SCIP_DECL_EXPRPRINT(printVaridx)
103  	{  /*lint --e{715}*/
104  	   assert(expr != NULL);
105  	
106  	   if( stage == SCIP_EXPRITER_ENTEREXPR )
107  	   {
108  	      SCIPinfoMessage(scip, file, "x%d", SCIPgetIndexExprVaridx(expr));
109  	   }
110  	
111  	   return SCIP_OKAY;
112  	}
113  	
114  	/** expression (point-) evaluation callback */
115  	static
116  	SCIP_DECL_EXPREVAL(evalVaridx)
117  	{  /*lint --e{715}*/
118  	   assert(expr != NULL);
119  	
120  	   SCIPerrorMessage("method of varidx expression handler not implemented yet\n");
121  	   SCIPABORT(); /*lint --e{527}*/
122  	
123  	   return SCIP_OKAY;
124  	}
125  	
126  	/** expression backward derivative evaluation callback */
127  	static
128  	SCIP_DECL_EXPRBWDIFF(bwdiffVaridx)
129  	{  /*lint --e{715}*/
130  	   /* this should never happen because variable expressions do not have children */
131  	   return SCIP_INVALIDCALL;
132  	}
133  	
134  	/** expression forward derivative evaluation callback */
135  	static
136  	SCIP_DECL_EXPRFWDIFF(fwdiffVaridx)
137  	{  /*lint --e{715}*/
138  	   assert(expr != NULL);
139  	
140  	   SCIPerrorMessage("method of varidx expression handler not implemented yet\n");
141  	   SCIPABORT(); /*lint --e{527}*/
142  	
143  	   return SCIP_OKAY;
144  	}
145  	
146  	/** expression backward-forward derivative evaluation callback */
147  	static
148  	SCIP_DECL_EXPRBWFWDIFF(bwfwdiffVaridx)
149  	{  /*lint --e{715}*/
150  	   /* this should never happen because variable expressions do not have children */
151  	   return SCIP_INVALIDCALL;
152  	}
153  	
154  	/** varidx hash callback */
155  	static
156  	SCIP_DECL_EXPRHASH(hashVaridx)
157  	{  /*lint --e{715}*/
158  	   assert(expr != NULL);
159  	   assert(hashkey != NULL);
160  	
161  	   *hashkey = EXPRHDLR_HASHKEY;
162  	   *hashkey ^= SCIPcalcFibHash((SCIP_Real)SCIPgetIndexExprVaridx(expr));
163  	
164  	   return SCIP_OKAY;
165  	}
166  	
167  	/** expression curvature detection callback */
168  	static
169  	SCIP_DECL_EXPRCURVATURE(curvatureVaridx)
170  	{  /*lint --e{715}*/
171  	   assert(success != NULL);
172  	
173  	   /* x -> x is linear, convex, and concave */
174  	   *success = TRUE;
175  	
176  	   return SCIP_OKAY;
177  	}
178  	
179  	/** expression monotonicity detection callback */
180  	static
181  	SCIP_DECL_EXPRMONOTONICITY(monotonicityVaridx)
182  	{  /*lint --e{715}*/
183  	   assert(result != NULL);
184  	
185  	   *result = SCIP_MONOTONE_INC;
186  	
187  	   return SCIP_OKAY;
188  	}
189  	
190  	/** creates the handler for variable index expressions and includes it into SCIP */
191  	SCIP_RETCODE SCIPincludeExprhdlrVaridx(
192  	   SCIP*                 scip                /**< SCIP data structure */
193  	   )
194  	{
195  	   SCIP_EXPRHDLRDATA* exprhdlrdata;
196  	   SCIP_EXPRHDLR* exprhdlr;
197  	
198  	   /* create expression handler data */
199  	   exprhdlrdata = NULL;
200  	
201  	   /* include expression handler */
202  	   SCIP_CALL( SCIPincludeExprhdlr(scip, &exprhdlr, EXPRHDLR_NAME, EXPRHDLR_DESC, EXPRHDLR_PRECEDENCE, evalVaridx,
203  	         exprhdlrdata) );
204  	   assert(exprhdlr != NULL);
205  	
206  	   SCIPexprhdlrSetCopyFreeHdlr(exprhdlr, copyhdlrVaridx, NULL);
207  	   SCIPexprhdlrSetCopyFreeData(exprhdlr, copydataVaridx, freedataVaridx);
208  	   SCIPexprhdlrSetCompare(exprhdlr, compareVaridx);
209  	   SCIPexprhdlrSetPrint(exprhdlr, printVaridx);
210  	   SCIPexprhdlrSetHash(exprhdlr, hashVaridx);
211  	   SCIPexprhdlrSetDiff(exprhdlr, bwdiffVaridx, fwdiffVaridx, bwfwdiffVaridx);
212  	   SCIPexprhdlrSetCurvature(exprhdlr, curvatureVaridx);
213  	   SCIPexprhdlrSetMonotonicity(exprhdlr, monotonicityVaridx);
214  	
215  	   return SCIP_OKAY;
216  	}
217  	
218  	/** creates a variable index expression */
219  	SCIP_RETCODE SCIPcreateExprVaridx(
220  	   SCIP*                 scip,               /**< SCIP data structure */
221  	   SCIP_EXPR**           expr,               /**< pointer where to store expression */
222  	   int                   varidx,             /**< variable index to represent */
223  	   SCIP_DECL_EXPR_OWNERCREATE((*ownercreate)), /**< function to call to create ownerdata */
224  	   void*                 ownercreatedata     /**< data to pass to ownercreate */
225  	   )
226  	{
227  	   SCIP_EXPRHDLR* exprhdlr;
228  	   SCIP_EXPRDATA* exprdata;
229  	
230  	   assert(expr != NULL);
231  	
232  	   exprhdlr = SCIPfindExprhdlr(scip, EXPRHDLR_NAME);
233  	
234  	   if( exprhdlr == NULL )
235  	   {
236  	      SCIPerrorMessage("could not find %s expression handler -> abort\n", EXPRHDLR_NAME);
237  	      SCIPABORT();
238  	      return SCIP_ERROR;
239  	   }
240  	
241  	   /* create expression data */
242  	   exprdata = (SCIP_EXPRDATA*)(size_t)varidx;  /*lint !e571*/
243  	
244  	   /* create expression */
245  	   SCIP_CALL( SCIPcreateExpr(scip, expr, exprhdlr, exprdata, 0, NULL, ownercreate, ownercreatedata) );
246  	
247  	   return SCIP_OKAY;
248  	}
249  	
250  	/** indicates whether expression is varidx expression */  /*lint -e{715}*/
251  	SCIP_Bool SCIPisExprVaridx(
252  	   SCIP*                 scip,               /**< SCIP data structure */
253  	   SCIP_EXPR*            expr                /**< expression */
254  	   )
255  	{ /*lint --e{715}*/
256  	   assert(expr != NULL);
257  	
258  	   /* quick inconclusive check first */
259  	   if( SCIPexprGetNChildren(expr) > 0 )
260  	      return FALSE;
261  	
262  	   return strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0;
263  	}
264  	
265  	/** gives the index stored in a varidx expression */
266  	int SCIPgetIndexExprVaridx(
267  	   SCIP_EXPR*            expr                /**< varindex expression */
268  	   )
269  	{
270  	   assert(expr != NULL);
271  	   assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
272  	
273  	   return (int)(size_t)SCIPexprGetData(expr);
274  	}
275  	
276  	/** sets the index stored in a varidx expression */
277  	void SCIPsetIndexExprVaridx(
278  	   SCIP_EXPR*            expr,               /**< varindex expression */
279  	   int                   newindex            /**< new index */
280  	   )
281  	{
282  	   assert(expr != NULL);
283  	   assert(strcmp(SCIPexprhdlrGetName(SCIPexprGetHdlr(expr)), EXPRHDLR_NAME) == 0);
284  	   assert(newindex >= 0);
285  	
286  	   SCIPexprSetData(expr, (SCIP_EXPRDATA*)(size_t)newindex);  /*lint !e571*/
287  	}
288