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_relax.c 26 * @ingroup OTHER_CFILES 27 * @brief public methods for relaxator 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/pub_message.h" 47 #include "scip/relax.h" 48 #include "scip/scip_relax.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 54 /** creates a relaxation handler and includes it in SCIP 55 * 56 * @note method has all relaxation handler callbacks as arguments and is thus changed every time a new 57 * callback is added 58 * in future releases; consider using SCIPincludeRelaxBasic() and setter functions 59 * if you seek for a method which is less likely to change in future releases 60 */ 61 SCIP_RETCODE SCIPincludeRelax( 62 SCIP* scip, /**< SCIP data structure */ 63 const char* name, /**< name of relaxation handler */ 64 const char* desc, /**< description of relaxation handler */ 65 int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */ 66 int freq, /**< frequency for calling relaxation handler */ 67 SCIP_DECL_RELAXCOPY ((*relaxcopy)), /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 68 SCIP_DECL_RELAXFREE ((*relaxfree)), /**< destructor of relaxation handler */ 69 SCIP_DECL_RELAXINIT ((*relaxinit)), /**< initialize relaxation handler */ 70 SCIP_DECL_RELAXEXIT ((*relaxexit)), /**< deinitialize relaxation handler */ 71 SCIP_DECL_RELAXINITSOL((*relaxinitsol)), /**< solving process initialization method of relaxation handler */ 72 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), /**< solving process deinitialization method of relaxation handler */ 73 SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */ 74 SCIP_RELAXDATA* relaxdata /**< relaxation handler data */ 75 ) 76 { 77 SCIP_RELAX* relax; 78 79 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeRelax", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 80 81 /* check whether relaxation handler is already present */ 82 if( SCIPfindRelax(scip, name) != NULL ) 83 { 84 SCIPerrorMessage("relaxation handler <%s> already included.\n", name); 85 return SCIP_INVALIDDATA; 86 } 87 88 SCIP_CALL( SCIPrelaxCreate(&relax, scip->set, scip->messagehdlr, scip->mem->setmem, 89 name, desc, priority, freq, relaxcopy, 90 relaxfree, relaxinit, relaxexit, relaxinitsol, relaxexitsol, relaxexec, relaxdata) ); 91 SCIP_CALL( SCIPsetIncludeRelax(scip->set, relax) ); 92 93 return SCIP_OKAY; 94 } 95 96 /** creates a relaxation handler and includes it in SCIP. All non fundamental 97 * (or optional) callbacks as, e.g., init and exit callbacks, will be set to NULL. 98 * Optional callbacks can be set via specific setter functions, see SCIPsetRelaxInit(), SCIPsetRelaxExit(), 99 * SCIPsetRelaxCopy(), SCIPsetRelaxFree(), SCIPsetRelaxInitsol(), and SCIPsetRelaxExitsol() 100 * 101 * @note if you want to set all callbacks with a single method call, consider using SCIPincludeRelax() instead 102 */ 103 SCIP_RETCODE SCIPincludeRelaxBasic( 104 SCIP* scip, /**< SCIP data structure */ 105 SCIP_RELAX** relaxptr, /**< reference to relaxation pointer, or NULL */ 106 const char* name, /**< name of relaxation handler */ 107 const char* desc, /**< description of relaxation handler */ 108 int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */ 109 int freq, /**< frequency for calling relaxation handler */ 110 SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */ 111 SCIP_RELAXDATA* relaxdata /**< relaxation handler data */ 112 ) 113 { 114 SCIP_RELAX* relax; 115 116 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeRelaxBasic", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 117 118 /* check whether relaxation handler is already present */ 119 if( SCIPfindRelax(scip, name) != NULL ) 120 { 121 SCIPerrorMessage("relaxation handler <%s> already included.\n", name); 122 return SCIP_INVALIDDATA; 123 } 124 125 SCIP_CALL( SCIPrelaxCreate(&relax, scip->set, scip->messagehdlr, scip->mem->setmem, 126 name, desc, priority, freq, 127 NULL, NULL, NULL, NULL, NULL, NULL, relaxexec, relaxdata) ); 128 SCIP_CALL( SCIPsetIncludeRelax(scip->set, relax) ); 129 130 if( relaxptr != NULL ) 131 *relaxptr = relax; 132 133 return SCIP_OKAY; 134 } 135 136 /** sets copy method of relaxation handler */ 137 SCIP_RETCODE SCIPsetRelaxCopy( 138 SCIP* scip, /**< SCIP data structure */ 139 SCIP_RELAX* relax, /**< relaxation handler */ 140 SCIP_DECL_RELAXCOPY ((*relaxcopy)) /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 141 ) 142 { 143 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxCopy", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 144 145 assert(relax != NULL); 146 147 SCIPrelaxSetCopy(relax, relaxcopy); 148 149 return SCIP_OKAY; 150 } 151 152 /** sets destructor method of relaxation handler */ 153 SCIP_RETCODE SCIPsetRelaxFree( 154 SCIP* scip, /**< SCIP data structure */ 155 SCIP_RELAX* relax, /**< relaxation handler */ 156 SCIP_DECL_RELAXFREE ((*relaxfree)) /**< destructor of relaxation handler */ 157 ) 158 { 159 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxFree", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 160 161 assert(relax != NULL); 162 163 SCIPrelaxSetFree(relax, relaxfree); 164 165 return SCIP_OKAY; 166 } 167 168 /** sets initialization method of relaxation handler */ 169 SCIP_RETCODE SCIPsetRelaxInit( 170 SCIP* scip, /**< SCIP data structure */ 171 SCIP_RELAX* relax, /**< relaxation handler */ 172 SCIP_DECL_RELAXINIT ((*relaxinit)) /**< initialize relaxation handler */ 173 ) 174 { 175 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxInit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 176 177 assert(relax != NULL); 178 179 SCIPrelaxSetInit(relax, relaxinit); 180 181 return SCIP_OKAY; 182 } 183 184 /** sets deinitialization method of relaxation handler */ 185 SCIP_RETCODE SCIPsetRelaxExit( 186 SCIP* scip, /**< SCIP data structure */ 187 SCIP_RELAX* relax, /**< relaxation handler */ 188 SCIP_DECL_RELAXEXIT ((*relaxexit)) /**< deinitialize relaxation handler */ 189 ) 190 { 191 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxExit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 192 193 assert(relax != NULL); 194 195 SCIPrelaxSetExit(relax, relaxexit); 196 197 return SCIP_OKAY; 198 } 199 200 /** sets solving process initialization method of relaxation handler */ 201 SCIP_RETCODE SCIPsetRelaxInitsol( 202 SCIP* scip, /**< SCIP data structure */ 203 SCIP_RELAX* relax, /**< relaxation handler */ 204 SCIP_DECL_RELAXINITSOL((*relaxinitsol)) /**< solving process initialization method of relaxation handler */ 205 ) 206 { 207 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxInitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 208 209 assert(relax != NULL); 210 211 SCIPrelaxSetInitsol(relax, relaxinitsol); 212 213 return SCIP_OKAY; 214 } 215 216 /** sets solving process deinitialization method of relaxation handler */ 217 SCIP_RETCODE SCIPsetRelaxExitsol( 218 SCIP* scip, /**< SCIP data structure */ 219 SCIP_RELAX* relax, /**< relaxation handler */ 220 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)) /**< solving process deinitialization method of relaxation handler */ 221 ) 222 { 223 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetRelaxExitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) ); 224 225 assert(relax != NULL); 226 227 SCIPrelaxSetExitsol(relax, relaxexitsol); 228 229 return SCIP_OKAY; 230 } 231 232 233 /** returns the relaxation handler of the given name, or NULL if not existing */ 234 SCIP_RELAX* SCIPfindRelax( 235 SCIP* scip, /**< SCIP data structure */ 236 const char* name /**< name of relaxation handler */ 237 ) 238 { 239 assert(scip != NULL); 240 assert(scip->set != NULL); 241 assert(name != NULL); 242 243 return SCIPsetFindRelax(scip->set, name); 244 } 245 246 /** returns the array of currently available relaxation handlers */ 247 SCIP_RELAX** SCIPgetRelaxs( 248 SCIP* scip /**< SCIP data structure */ 249 ) 250 { 251 assert(scip != NULL); 252 assert(scip->set != NULL); 253 254 SCIPsetSortRelaxs(scip->set); 255 256 return scip->set->relaxs; 257 } 258 259 /** returns the number of currently available relaxation handlers */ 260 int SCIPgetNRelaxs( 261 SCIP* scip /**< SCIP data structure */ 262 ) 263 { 264 assert(scip != NULL); 265 assert(scip->set != NULL); 266 267 return scip->set->nrelaxs; 268 } 269 270 /** sets the priority of a relaxation handler */ 271 SCIP_RETCODE SCIPsetRelaxPriority( 272 SCIP* scip, /**< SCIP data structure */ 273 SCIP_RELAX* relax, /**< relaxation handler */ 274 int priority /**< new priority of the relaxation handler */ 275 ) 276 { 277 assert(scip != NULL); 278 assert(scip->set != NULL); 279 280 SCIPrelaxSetPriority(relax, scip->set, priority); 281 282 return SCIP_OKAY; 283 } 284