1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2021 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /**@file scip_sepa.c
17 * @ingroup OTHER_CFILES
18 * @brief public methods for separator plugins
19 * @author Tobias Achterberg
20 * @author Timo Berthold
21 * @author Gerald Gamrath
22 * @author Leona Gottwald
23 * @author Stefan Heinz
24 * @author Gregor Hendel
25 * @author Thorsten Koch
26 * @author Alexander Martin
27 * @author Marc Pfetsch
28 * @author Michael Winkler
29 * @author Kati Wolter
30 *
31 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
32 */
33
34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35
36 #include "scip/debug.h"
37 #include "scip/pub_message.h"
38 #include "scip/scip_sepa.h"
39 #include "scip/sepa.h"
40 #include "scip/set.h"
41 #include "scip/struct_mem.h"
42 #include "scip/struct_scip.h"
43 #include "scip/struct_set.h"
44 #include "scip/tree.h"
45
46 /** creates a separator and includes it in SCIP.
47 *
48 * @note method has all separator callbacks as arguments and is thus changed every time a new
49 * callback is added
50 * in future releases; consider using SCIPincludeSepaBasic() and setter functions
51 * if you seek for a method which is less likely to change in future releases
52 */
SCIPincludeSepa(SCIP * scip,const char * name,const char * desc,int priority,int freq,SCIP_Real maxbounddist,SCIP_Bool usessubscip,SCIP_Bool delay,SCIP_DECL_SEPACOPY ((* sepacopy)),SCIP_DECL_SEPAFREE ((* sepafree)),SCIP_DECL_SEPAINIT ((* sepainit)),SCIP_DECL_SEPAEXIT ((* sepaexit)),SCIP_DECL_SEPAINITSOL ((* sepainitsol)),SCIP_DECL_SEPAEXITSOL ((* sepaexitsol)),SCIP_DECL_SEPAEXECLP ((* sepaexeclp)),SCIP_DECL_SEPAEXECSOL ((* sepaexecsol)),SCIP_SEPADATA * sepadata)53 SCIP_RETCODE SCIPincludeSepa(
54 SCIP* scip, /**< SCIP data structure */
55 const char* name, /**< name of separator */
56 const char* desc, /**< description of separator */
57 int priority, /**< priority of separator (>= 0: before, < 0: after constraint handlers) */
58 int freq, /**< frequency for calling separator */
59 SCIP_Real maxbounddist, /**< maximal relative distance from current node's dual bound to primal bound compared
60 * to best node's dual bound for applying separation */
61 SCIP_Bool usessubscip, /**< does the separator use a secondary SCIP instance? */
62 SCIP_Bool delay, /**< should separator be delayed, if other separators found cuts? */
63 SCIP_DECL_SEPACOPY ((*sepacopy)), /**< copy method of separator or NULL if you don't want to copy your plugin into sub-SCIPs */
64 SCIP_DECL_SEPAFREE ((*sepafree)), /**< destructor of separator */
65 SCIP_DECL_SEPAINIT ((*sepainit)), /**< initialize separator */
66 SCIP_DECL_SEPAEXIT ((*sepaexit)), /**< deinitialize separator */
67 SCIP_DECL_SEPAINITSOL ((*sepainitsol)), /**< solving process initialization method of separator */
68 SCIP_DECL_SEPAEXITSOL ((*sepaexitsol)), /**< solving process deinitialization method of separator */
69 SCIP_DECL_SEPAEXECLP ((*sepaexeclp)), /**< LP solution separation method of separator */
70 SCIP_DECL_SEPAEXECSOL ((*sepaexecsol)), /**< arbitrary primal solution separation method of separator */
71 SCIP_SEPADATA* sepadata /**< separator data */
72 )
73 {
74 SCIP_SEPA* sepa;
75
76 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeSepa", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
77
78 /* check whether separator is already present */
79 if( SCIPfindSepa(scip, name) != NULL )
80 {
81 SCIPerrorMessage("separator <%s> already included.\n", name);
82 return SCIP_INVALIDDATA;
83 }
84
85 SCIP_CALL( SCIPsepaCreate(&sepa, scip->set, scip->messagehdlr, scip->mem->setmem,
86 name, desc, priority, freq, maxbounddist, usessubscip, delay,
87 sepacopy, sepafree, sepainit, sepaexit, sepainitsol, sepaexitsol, sepaexeclp, sepaexecsol, sepadata) );
88 SCIP_CALL( SCIPsetIncludeSepa(scip->set, sepa) );
89
90 return SCIP_OKAY;
91 }
92
93 /** creates a separator and includes it in SCIP with its most fundamental callbacks. All non-fundamental
94 * (or optional) callbacks as, e.g., init and exit callbacks, will be set to NULL.
95 * Optional callbacks can be set via specific setter functions, see SCIPsetSepaInit(), SCIPsetSepaFree(),
96 * SCIPsetSepaInitsol(), SCIPsetSepaExitsol(), SCIPsetSepaCopy(), SCIPsetExit().
97 *
98 * @note if you want to set all callbacks with a single method call, consider using SCIPincludeSepa() instead
99 */
SCIPincludeSepaBasic(SCIP * scip,SCIP_SEPA ** sepa,const char * name,const char * desc,int priority,int freq,SCIP_Real maxbounddist,SCIP_Bool usessubscip,SCIP_Bool delay,SCIP_DECL_SEPAEXECLP ((* sepaexeclp)),SCIP_DECL_SEPAEXECSOL ((* sepaexecsol)),SCIP_SEPADATA * sepadata)100 SCIP_RETCODE SCIPincludeSepaBasic(
101 SCIP* scip, /**< SCIP data structure */
102 SCIP_SEPA** sepa, /**< reference to a separator, or NULL */
103 const char* name, /**< name of separator */
104 const char* desc, /**< description of separator */
105 int priority, /**< priority of separator (>= 0: before, < 0: after constraint handlers) */
106 int freq, /**< frequency for calling separator */
107 SCIP_Real maxbounddist, /**< maximal relative distance from current node's dual bound to primal bound compared
108 * to best node's dual bound for applying separation */
109 SCIP_Bool usessubscip, /**< does the separator use a secondary SCIP instance? */
110 SCIP_Bool delay, /**< should separator be delayed, if other separators found cuts? */
111 SCIP_DECL_SEPAEXECLP ((*sepaexeclp)), /**< LP solution separation method of separator */
112 SCIP_DECL_SEPAEXECSOL ((*sepaexecsol)), /**< arbitrary primal solution separation method of separator */
113 SCIP_SEPADATA* sepadata /**< separator data */
114 )
115 {
116 SCIP_SEPA* sepaptr;
117
118 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeSepaBasic", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
119
120 /* check whether separator is already present */
121 if( SCIPfindSepa(scip, name) != NULL )
122 {
123 SCIPerrorMessage("separator <%s> already included.\n", name);
124 return SCIP_INVALIDDATA;
125 }
126
127 SCIP_CALL( SCIPsepaCreate(&sepaptr, scip->set, scip->messagehdlr, scip->mem->setmem,
128 name, desc, priority, freq, maxbounddist, usessubscip, delay,
129 NULL, NULL, NULL, NULL, NULL, NULL, sepaexeclp, sepaexecsol, sepadata) );
130
131 assert(sepaptr != NULL);
132
133 SCIP_CALL( SCIPsetIncludeSepa(scip->set, sepaptr) );
134
135 if( sepa != NULL)
136 *sepa = sepaptr;
137
138 return SCIP_OKAY;
139 }
140
141 /** sets copy method of separator */
SCIPsetSepaCopy(SCIP * scip,SCIP_SEPA * sepa,SCIP_DECL_SEPACOPY ((* sepacopy)))142 SCIP_RETCODE SCIPsetSepaCopy(
143 SCIP* scip, /**< SCIP data structure */
144 SCIP_SEPA* sepa, /**< separator */
145 SCIP_DECL_SEPACOPY ((*sepacopy)) /**< copy method of separator or NULL if you don't want to copy your plugin into sub-SCIPs */
146 )
147 {
148 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetSepaCopy", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
149
150 assert(sepa != NULL);
151
152 SCIPsepaSetCopy(sepa, sepacopy);
153
154 return SCIP_OKAY;
155 }
156
157 /** sets destructor method of separator */
SCIPsetSepaFree(SCIP * scip,SCIP_SEPA * sepa,SCIP_DECL_SEPAFREE ((* sepafree)))158 SCIP_RETCODE SCIPsetSepaFree(
159 SCIP* scip, /**< SCIP data structure */
160 SCIP_SEPA* sepa, /**< separator */
161 SCIP_DECL_SEPAFREE ((*sepafree)) /**< destructor of separator */
162 )
163 {
164 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetSepaFree", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
165
166 assert(sepa != NULL);
167
168 SCIPsepaSetFree(sepa, sepafree);
169
170 return SCIP_OKAY;
171 }
172
173 /** sets initialization method of separator */
SCIPsetSepaInit(SCIP * scip,SCIP_SEPA * sepa,SCIP_DECL_SEPAINIT ((* sepainit)))174 SCIP_RETCODE SCIPsetSepaInit(
175 SCIP* scip, /**< SCIP data structure */
176 SCIP_SEPA* sepa, /**< separator */
177 SCIP_DECL_SEPAINIT ((*sepainit)) /**< initialize separator */
178 )
179 {
180 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetSepaInit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
181
182 assert(sepa != NULL);
183
184 SCIPsepaSetInit(sepa, sepainit);
185
186 return SCIP_OKAY;
187 }
188
189 /** sets deinitialization method of separator */
SCIPsetSepaExit(SCIP * scip,SCIP_SEPA * sepa,SCIP_DECL_SEPAEXIT ((* sepaexit)))190 SCIP_RETCODE SCIPsetSepaExit(
191 SCIP* scip, /**< SCIP data structure */
192 SCIP_SEPA* sepa, /**< separator */
193 SCIP_DECL_SEPAEXIT ((*sepaexit)) /**< deinitialize separator */
194 )
195 {
196 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetSepaExit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
197
198 assert(sepa != NULL);
199
200 SCIPsepaSetExit(sepa, sepaexit);
201
202 return SCIP_OKAY;
203 }
204
205 /** sets solving process initialization method of separator */
SCIPsetSepaInitsol(SCIP * scip,SCIP_SEPA * sepa,SCIP_DECL_SEPAINITSOL ((* sepainitsol)))206 SCIP_RETCODE SCIPsetSepaInitsol(
207 SCIP* scip, /**< SCIP data structure */
208 SCIP_SEPA* sepa, /**< separator */
209 SCIP_DECL_SEPAINITSOL ((*sepainitsol)) /**< solving process initialization method of separator */
210 )
211 {
212 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetSepaInitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
213
214 assert(sepa != NULL);
215
216 SCIPsepaSetInitsol(sepa, sepainitsol);
217
218 return SCIP_OKAY;
219 }
220
221 /** sets solving process deinitialization method of separator */
SCIPsetSepaExitsol(SCIP * scip,SCIP_SEPA * sepa,SCIP_DECL_SEPAEXITSOL ((* sepaexitsol)))222 SCIP_RETCODE SCIPsetSepaExitsol(
223 SCIP* scip, /**< SCIP data structure */
224 SCIP_SEPA* sepa, /**< separator */
225 SCIP_DECL_SEPAEXITSOL ((*sepaexitsol)) /**< solving process deinitialization method of separator */
226 )
227 {
228 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetSepaExitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
229
230 assert(sepa != NULL);
231
232 SCIPsepaSetExitsol(sepa, sepaexitsol);
233
234 return SCIP_OKAY;
235 }
236
237 /** returns the separator of the given name, or NULL if not existing */
SCIPfindSepa(SCIP * scip,const char * name)238 SCIP_SEPA* SCIPfindSepa(
239 SCIP* scip, /**< SCIP data structure */
240 const char* name /**< name of separator */
241 )
242 {
243 assert(scip != NULL);
244 assert(scip->set != NULL);
245 assert(name != NULL);
246
247 return SCIPsetFindSepa(scip->set, name);
248 }
249
250 /** returns the array of currently available separators */
SCIPgetSepas(SCIP * scip)251 SCIP_SEPA** SCIPgetSepas(
252 SCIP* scip /**< SCIP data structure */
253 )
254 {
255 assert(scip != NULL);
256 assert(scip->set != NULL);
257
258 SCIPsetSortSepas(scip->set);
259
260 return scip->set->sepas;
261 }
262
263 /** returns the number of currently available separators */
SCIPgetNSepas(SCIP * scip)264 int SCIPgetNSepas(
265 SCIP* scip /**< SCIP data structure */
266 )
267 {
268 assert(scip != NULL);
269 assert(scip->set != NULL);
270
271 return scip->set->nsepas;
272 }
273
274 /** sets the priority of a separator */
SCIPsetSepaPriority(SCIP * scip,SCIP_SEPA * sepa,int priority)275 SCIP_RETCODE SCIPsetSepaPriority(
276 SCIP* scip, /**< SCIP data structure */
277 SCIP_SEPA* sepa, /**< separator */
278 int priority /**< new priority of the separator */
279 )
280 {
281 assert(scip != NULL);
282 assert(scip->set != NULL);
283
284 SCIPsepaSetPriority(sepa, scip->set, priority);
285
286 return SCIP_OKAY;
287 }
288
289 #undef SCIPgetSepaMinEfficacy
290
291 /** gets value of minimal efficacy for a cut to enter the LP
292 *
293 * @pre This method can be called if @p scip is in one of the following stages:
294 * - \ref SCIP_STAGE_SOLVING
295 *
296 * @return value of "separating/minefficacyroot" if at root node, otherwise value of "separating/minefficacy"
297 */
SCIPgetSepaMinEfficacy(SCIP * scip)298 SCIP_Real SCIPgetSepaMinEfficacy(
299 SCIP* scip /**< SCIP data structure */
300 )
301 {
302 assert(scip != NULL);
303 assert(scip->tree != NULL);
304 assert(scip->set != NULL);
305
306 SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetSepaMinEfficacy", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE) );
307
308 if( SCIPtreeGetCurrentDepth(scip->tree) != 0 )
309 return scip->set->sepa_minefficacyroot;
310 return scip->set->sepa_minefficacy;
311 }
312