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