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 scip_presol.c 26 * @ingroup OTHER_CFILES 27 * @brief public methods for presolving plugins 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 * @author Gerald Gamrath 31 * @author Leona Gottwald 32 * @author Stefan Heinz 33 * @author Gregor Hendel 34 * @author Thorsten Koch 35 * @author Alexander Martin 36 * @author Marc Pfetsch 37 * @author Michael Winkler 38 * @author Kati Wolter 39 * 40 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE 41 */ 42 43 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 44 45 #include "scip/debug.h" 46 #include "scip/presol.h" 47 #include "scip/pub_message.h" 48 #include "scip/scip_presol.h" 49 #include "scip/set.h" 50 #include "scip/struct_mem.h" 51 #include "scip/struct_scip.h" 52 #include "scip/struct_set.h" 53 #include "scip/struct_stat.h" 54 55 /** creates a presolver and includes it in SCIP. 56 * 57 * @note method has all presolver callbacks as arguments and is thus changed every time a new 58 * callback is added 59 * in future releases; consider using SCIPincludePresolBasic() and setter functions 60 * if you seek for a method which is less likely to change in future releases 61 */ 62 SCIP_RETCODE SCIPincludePresol( 63 SCIP* scip, /**< SCIP data structure */ 64 const char* name, /**< name of presolver */ 65 const char* desc, /**< description of presolver */ 66 int priority, /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */ 67 int maxrounds, /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */ 68 SCIP_PRESOLTIMING timing, /**< timing mask of the presolver */ 69 SCIP_DECL_PRESOLCOPY ((*presolcopy)), /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */ 70 SCIP_DECL_PRESOLFREE ((*presolfree)), /**< destructor of presolver to free user data (called when SCIP is exiting) */ 71 SCIP_DECL_PRESOLINIT ((*presolinit)), /**< initialization method of presolver (called after problem was transformed) */ 72 SCIP_DECL_PRESOLEXIT ((*presolexit)), /**< deinitialization method of presolver (called before transformed problem is freed) */ 73 SCIP_DECL_PRESOLINITPRE((*presolinitpre)),/**< presolving initialization method of presolver (called when presolving is about to begin) */ 74 SCIP_DECL_PRESOLEXITPRE((*presolexitpre)),/**< presolving deinitialization method of presolver (called after presolving has been finished) */ 75 SCIP_DECL_PRESOLEXEC ((*presolexec)), /**< execution method of presolver */ 76 SCIP_PRESOLDATA* presoldata /**< presolver data */ 77 ) 78 { 79 SCIP_PRESOL* presol; 80 81 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludePresol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 82 83 /* check whether presolver is already present */ 84 if( SCIPfindPresol(scip, name) != NULL ) 85 { 86 SCIPerrorMessage("presolver <%s> already included.\n", name); 87 return SCIP_INVALIDDATA; 88 } 89 90 SCIP_CALL( SCIPpresolCreate(&presol, scip->set, scip->messagehdlr, scip->mem->setmem, name, desc, priority, 91 maxrounds, timing, presolcopy, 92 presolfree, presolinit, presolexit, presolinitpre, presolexitpre, presolexec, presoldata) ); 93 SCIP_CALL( SCIPsetIncludePresol(scip->set, presol) ); 94 95 return SCIP_OKAY; 96 } 97 98 /** creates a presolver and includes it in SCIP with its fundamental callback. All non-fundamental (or optional) 99 * callbacks as, e.g., init and exit callbacks, will be set to NULL. Optional callbacks can be set via specific setter 100 * functions. These are SCIPsetPresolCopy(), SCIPsetPresolFree(), SCIPsetPresolInit(), SCIPsetPresolExit(), 101 * SCIPsetPresolInitpre(), and SCIPsetPresolExitPre(). 102 * 103 * @note if you want to set all callbacks with a single method call, consider using SCIPincludePresol() instead 104 */ 105 SCIP_RETCODE SCIPincludePresolBasic( 106 SCIP* scip, /**< SCIP data structure */ 107 SCIP_PRESOL** presolptr, /**< reference to presolver, or NULL */ 108 const char* name, /**< name of presolver */ 109 const char* desc, /**< description of presolver */ 110 int priority, /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */ 111 int maxrounds, /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */ 112 SCIP_PRESOLTIMING timing, /**< timing mask of the presolver */ 113 SCIP_DECL_PRESOLEXEC ((*presolexec)), /**< execution method of presolver */ 114 SCIP_PRESOLDATA* presoldata /**< presolver data */ 115 ) 116 { 117 SCIP_PRESOL* presol; 118 119 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludePresolBasic", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 120 121 /* check whether presolver is already present */ 122 if( SCIPfindPresol(scip, name) != NULL ) 123 { 124 SCIPerrorMessage("presolver <%s> already included.\n", name); 125 return SCIP_INVALIDDATA; 126 } 127 128 SCIP_CALL( SCIPpresolCreate(&presol, scip->set, scip->messagehdlr, scip->mem->setmem, name, desc, priority, maxrounds, timing, 129 NULL, 130 NULL, NULL, NULL, NULL, NULL, presolexec, presoldata) ); 131 SCIP_CALL( SCIPsetIncludePresol(scip->set, presol) ); 132 133 if( presolptr != NULL ) 134 *presolptr = presol; 135 136 return SCIP_OKAY; 137 } 138 139 /** sets copy method of presolver */ 140 SCIP_RETCODE SCIPsetPresolCopy( 141 SCIP* scip, /**< SCIP data structure */ 142 SCIP_PRESOL* presol, /**< presolver */ 143 SCIP_DECL_PRESOLCOPY ((*presolcopy)) /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */ 144 ) 145 { 146 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPresolCopy", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 147 148 assert(presol != NULL); 149 150 SCIPpresolSetCopy(presol, presolcopy); 151 152 return SCIP_OKAY; 153 } 154 155 /** sets destructor method of presolver */ 156 SCIP_RETCODE SCIPsetPresolFree( 157 SCIP* scip, /**< SCIP data structure */ 158 SCIP_PRESOL* presol, /**< presolver */ 159 SCIP_DECL_PRESOLFREE ((*presolfree)) /**< destructor of presolver */ 160 ) 161 { 162 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPresolFree", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 163 164 assert(presol != NULL); 165 166 SCIPpresolSetFree(presol, presolfree); 167 168 return SCIP_OKAY; 169 } 170 171 /** sets initialization method of presolver */ 172 SCIP_RETCODE SCIPsetPresolInit( 173 SCIP* scip, /**< SCIP data structure */ 174 SCIP_PRESOL* presol, /**< presolver */ 175 SCIP_DECL_PRESOLINIT ((*presolinit)) /**< initialize presolver */ 176 ) 177 { 178 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPresolInit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 179 180 assert(presol != NULL); 181 182 SCIPpresolSetInit(presol, presolinit); 183 184 return SCIP_OKAY; 185 } 186 187 /** sets deinitialization method of presolver */ 188 SCIP_RETCODE SCIPsetPresolExit( 189 SCIP* scip, /**< SCIP data structure */ 190 SCIP_PRESOL* presol, /**< presolver */ 191 SCIP_DECL_PRESOLEXIT ((*presolexit)) /**< deinitialize presolver */ 192 ) 193 { 194 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPresolExit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 195 196 assert(presol != NULL); 197 198 SCIPpresolSetExit(presol, presolexit); 199 200 return SCIP_OKAY; 201 } 202 203 /** sets solving process initialization method of presolver */ 204 SCIP_RETCODE SCIPsetPresolInitpre( 205 SCIP* scip, /**< SCIP data structure */ 206 SCIP_PRESOL* presol, /**< presolver */ 207 SCIP_DECL_PRESOLINITPRE ((*presolinitpre))/**< solving process initialization method of presolver */ 208 ) 209 { 210 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPresolInitpre", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 211 212 assert(presol != NULL); 213 214 SCIPpresolSetInitpre(presol, presolinitpre); 215 216 return SCIP_OKAY; 217 } 218 219 /** sets solving process deinitialization method of presolver */ 220 SCIP_RETCODE SCIPsetPresolExitpre( 221 SCIP* scip, /**< SCIP data structure */ 222 SCIP_PRESOL* presol, /**< presolver */ 223 SCIP_DECL_PRESOLEXITPRE ((*presolexitpre))/**< solving process deinitialization method of presolver */ 224 ) 225 { 226 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetPresolExitpre", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 227 228 assert(presol != NULL); 229 230 SCIPpresolSetExitpre(presol, presolexitpre); 231 232 return SCIP_OKAY; 233 } 234 235 /** returns the presolver of the given name, or NULL if not existing */ 236 SCIP_PRESOL* SCIPfindPresol( 237 SCIP* scip, /**< SCIP data structure */ 238 const char* name /**< name of presolver */ 239 ) 240 { 241 assert(scip != NULL); 242 assert(scip->set != NULL); 243 assert(name != NULL); 244 245 return SCIPsetFindPresol(scip->set, name); 246 } 247 248 /** returns the array of currently available presolvers */ 249 SCIP_PRESOL** SCIPgetPresols( 250 SCIP* scip /**< SCIP data structure */ 251 ) 252 { 253 assert(scip != NULL); 254 assert(scip->set != NULL); 255 256 SCIPsetSortPresols(scip->set); 257 258 return scip->set->presols; 259 } 260 261 /** returns the number of currently available presolvers */ 262 int SCIPgetNPresols( 263 SCIP* scip /**< SCIP data structure */ 264 ) 265 { 266 assert(scip != NULL); 267 assert(scip->set != NULL); 268 269 return scip->set->npresols; 270 } 271 272 /** sets the priority of a presolver */ 273 SCIP_RETCODE SCIPsetPresolPriority( 274 SCIP* scip, /**< SCIP data structure */ 275 SCIP_PRESOL* presol, /**< presolver */ 276 int priority /**< new priority of the presolver */ 277 ) 278 { 279 assert(scip != NULL); 280 assert(scip->set != NULL); 281 282 SCIPpresolSetPriority(presol, scip->set, priority); 283 284 return SCIP_OKAY; 285 } 286 287 /** returns the number of presolve rounds (current or last presolve) */ 288 int SCIPgetNPresolRounds( 289 SCIP* scip /**< SCIP data structure */ 290 ) 291 { 292 assert(scip != NULL); 293 assert(scip->stat != NULL); 294 295 return scip->stat->npresolrounds; 296 } 297