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 objbenderscut.cpp 26 * @brief C++ wrapper for the Benders' decomposition cut plugins 27 * @author Stephen J. Maher 28 */ 29 30 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 31 32 #include <cassert> 33 34 #include "objbenderscut.h" 35 36 37 38 39 /* 40 * Data structures 41 */ 42 43 /** Benders' decomposition data */ 44 struct SCIP_BenderscutData 45 { 46 scip::ObjBenderscut* objbenderscut; /**< the Benders' decomposition object */ 47 SCIP_Bool deleteobject; /**< should the Benders' decomposition object be deleted when benders is freed? */ 48 }; 49 50 51 52 53 /* 54 * Callback methods of the Benders' decomposition framework 55 */ 56 57 extern "C" 58 { 59 60 /** copy method for Benders' decomposition cuts (called when SCIP copies plugins) */ 61 static 62 SCIP_DECL_BENDERSCUTCOPY(benderscutCopyObj) 63 { /*lint --e{715}*/ 64 SCIP_BENDERSCUTDATA* benderscutdata; 65 66 assert(scip != NULL); 67 68 benderscutdata = SCIPbenderscutGetData(benderscut); 69 assert(benderscutdata != NULL); 70 assert(benderscutdata->objbenderscut != NULL); 71 assert(benderscutdata->objbenderscut->scip_ != scip); 72 73 if( benderscutdata->objbenderscut->iscloneable() ) 74 { 75 scip::ObjBenderscut* newobjbenderscut; 76 newobjbenderscut = dynamic_cast<scip::ObjBenderscut*> (benderscutdata->objbenderscut->clone(scip)); 77 78 /* call include method of Benders' decomposition object */ 79 SCIP_CALL( SCIPincludeObjBenderscut(scip, SCIPgetObjBenders(scip, benders), newobjbenderscut, TRUE) ); 80 } 81 82 return SCIP_OKAY; 83 } 84 85 /** destructor of Benders' decomposition cut to free user data (called when SCIP is exiting) */ 86 static 87 SCIP_DECL_BENDERSCUTFREE(benderscutFreeObj) 88 { /*lint --e{715}*/ 89 SCIP_BENDERSCUTDATA* benderscutdata; 90 91 benderscutdata = SCIPbenderscutGetData(benderscut); 92 assert(benderscutdata != NULL); 93 assert(benderscutdata->objbenderscut != NULL); 94 assert(benderscutdata->objbenderscut->scip_ == scip); 95 96 /* call virtual method of benderscut object */ 97 SCIP_CALL( benderscutdata->objbenderscut->scip_free(scip, benderscut) ); 98 99 /* free benderscut object */ 100 if( benderscutdata->deleteobject ) 101 delete benderscutdata->objbenderscut; 102 103 /* free benderscut data */ 104 delete benderscutdata; 105 SCIPbenderscutSetData(benderscut, NULL); /*lint !e64*/ 106 107 return SCIP_OKAY; 108 } 109 110 111 /** initialization method of Benders' decomposition cut (called after problem was transformed) */ 112 static 113 SCIP_DECL_BENDERSCUTINIT(benderscutInitObj) 114 { /*lint --e{715}*/ 115 SCIP_BENDERSCUTDATA* benderscutdata; 116 117 benderscutdata = SCIPbenderscutGetData(benderscut); 118 assert(benderscutdata != NULL); 119 assert(benderscutdata->objbenderscut != NULL); 120 assert(benderscutdata->objbenderscut->scip_ == scip); 121 122 /* call virtual method of benderscut object */ 123 SCIP_CALL( benderscutdata->objbenderscut->scip_init(scip, benderscut) ); 124 125 return SCIP_OKAY; 126 } 127 128 129 /** deinitialization method of Benders' decomposition cut (called before transformed problem is freed) */ 130 static 131 SCIP_DECL_BENDERSCUTEXIT(benderscutExitObj) 132 { /*lint --e{715}*/ 133 SCIP_BENDERSCUTDATA* benderscutdata; 134 135 benderscutdata = SCIPbenderscutGetData(benderscut); 136 assert(benderscutdata != NULL); 137 assert(benderscutdata->objbenderscut != NULL); 138 139 /* call virtual method of benderscut object */ 140 SCIP_CALL( benderscutdata->objbenderscut->scip_exit(scip, benderscut) ); 141 142 return SCIP_OKAY; 143 } 144 145 146 /** solving process initialization method of Benders' decomposition cut (called when branch and bound process is about to begin) */ 147 static 148 SCIP_DECL_BENDERSCUTINITSOL(benderscutInitsolObj) 149 { /*lint --e{715}*/ 150 SCIP_BENDERSCUTDATA* benderscutdata; 151 152 benderscutdata = SCIPbenderscutGetData(benderscut); 153 assert(benderscutdata != NULL); 154 assert(benderscutdata->objbenderscut != NULL); 155 156 /* call virtual method of benderscut object */ 157 SCIP_CALL( benderscutdata->objbenderscut->scip_initsol(scip, benderscut) ); 158 159 return SCIP_OKAY; 160 } 161 162 163 /** solving process deinitialization method of Benders' decomposition cut (called before branch and bound process data is freed) */ 164 static 165 SCIP_DECL_BENDERSCUTEXITSOL(benderscutExitsolObj) 166 { /*lint --e{715}*/ 167 SCIP_BENDERSCUTDATA* benderscutdata; 168 169 benderscutdata = SCIPbenderscutGetData(benderscut); 170 assert(benderscutdata != NULL); 171 assert(benderscutdata->objbenderscut != NULL); 172 173 /* call virtual method of benderscut object */ 174 SCIP_CALL( benderscutdata->objbenderscut->scip_exitsol(scip, benderscut) ); 175 176 return SCIP_OKAY; 177 } 178 179 180 /** execution method of the Benders' decomposition cuts */ 181 static 182 SCIP_DECL_BENDERSCUTEXEC(benderscutExecObj) 183 { /*lint --e{715}*/ 184 SCIP_BENDERSCUTDATA* benderscutdata; 185 186 benderscutdata = SCIPbenderscutGetData(benderscut); 187 assert(benderscutdata != NULL); 188 assert(benderscutdata->objbenderscut != NULL); 189 190 /* call virtual method of benderscut object */ 191 SCIP_CALL( benderscutdata->objbenderscut->scip_exec(scip, benders, benderscut, sol, probnumber, type, result) ); 192 193 return SCIP_OKAY; 194 } 195 196 197 } 198 199 200 /* 201 * Benders' decomposition cut specific interface methods 202 */ 203 204 /** creates the Benders' decomposition cut for the given Benders' decomposition cut object and includes it in SCIP */ 205 SCIP_RETCODE SCIPincludeObjBenderscut( 206 SCIP* scip, /**< SCIP data structure */ 207 scip::ObjBenders* objbenders, /**< Benders' decomposition object */ 208 scip::ObjBenderscut* objbenderscut, /**< Benders' decomposition cut object */ 209 SCIP_Bool deleteobject /**< should the Benders' decomposition cut object be deleted when benderscut is freed? */ 210 ) 211 { 212 SCIP_BENDERS* benders; 213 SCIP_BENDERSCUTDATA* benderscutdata; 214 215 assert(scip != NULL); 216 assert(objbenderscut != NULL); 217 assert(objbenderscut->scip_ == scip); 218 219 /* create obj Benderscut' decomposition data */ 220 benderscutdata = new SCIP_BENDERSCUTDATA; 221 benderscutdata->objbenderscut = objbenderscut; 222 benderscutdata->deleteobject = deleteobject; 223 224 benders = SCIPfindBenders(scip, objbenders->scip_name_); 225 assert(benders != NULL); 226 227 /* include Benderscut' decomposition */ 228 SCIP_CALL( SCIPincludeBenderscut(scip, benders, objbenderscut->scip_name_, objbenderscut->scip_desc_, 229 objbenderscut->scip_priority_, objbenderscut->scip_islpcut_, benderscutCopyObj, benderscutFreeObj, 230 benderscutInitObj, benderscutExitObj, benderscutInitsolObj, benderscutExitsolObj, benderscutExecObj, 231 benderscutdata) ); /*lint !e429*/ 232 233 return SCIP_OKAY; /*lint !e429*/ 234 } 235 236 /** returns the benderscut object of the given name, or 0 if not existing */ 237 scip::ObjBenderscut* SCIPfindObjBenderscut( 238 scip::ObjBenders* objbenders, /**< Benders' decomposition object */ 239 const char* name /**< name of Benderscut' decomposition */ 240 ) 241 { 242 SCIP_BENDERS* benders; 243 SCIP_BENDERSCUT* benderscut; 244 SCIP_BENDERSCUTDATA* benderscutdata; 245 246 benders = SCIPfindBenders(objbenders->scip_, objbenders->scip_name_); 247 assert(benders != NULL); 248 249 benderscut = SCIPfindBenderscut(benders, name); 250 if( benderscut == NULL ) 251 return 0; 252 253 benderscutdata = SCIPbenderscutGetData(benderscut); 254 assert(benderscutdata != NULL); 255 256 return benderscutdata->objbenderscut; 257 } 258 259 /** returns the benderscut object for the given Benderscut' decomposition */ 260 scip::ObjBenderscut* SCIPgetObjBenderscut( 261 SCIP* scip, /**< SCIP data structure */ 262 SCIP_BENDERSCUT* benderscut /**< Benderscut' decomposition */ 263 ) 264 { 265 SCIP_BENDERSCUTDATA* benderscutdata; 266 267 assert(scip != NULL); 268 benderscutdata = SCIPbenderscutGetData(benderscut); 269 assert(benderscutdata != NULL); 270 271 return benderscutdata->objbenderscut; 272 } 273