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_event.c
17 * @ingroup OTHER_CFILES
18 * @brief public methods for event handler plugins and event handlers
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/event.h"
38 #include "scip/lp.h"
39 #include "scip/pub_message.h"
40 #include "scip/pub_var.h"
41 #include "scip/scip_event.h"
42 #include "scip/set.h"
43 #include "scip/struct_mem.h"
44 #include "scip/struct_scip.h"
45 #include "scip/struct_set.h"
46 #include "scip/var.h"
47
48 /** creates an event handler and includes it in SCIP
49 *
50 * @note method has all event handler callbacks as arguments and is thus changed every time a new
51 * callback is added in future releases; consider using SCIPincludeEventhdlrBasic() and setter functions
52 * if you seek for a method which is less likely to change in future releases
53 */
SCIPincludeEventhdlr(SCIP * scip,const char * name,const char * desc,SCIP_DECL_EVENTCOPY ((* eventcopy)),SCIP_DECL_EVENTFREE ((* eventfree)),SCIP_DECL_EVENTINIT ((* eventinit)),SCIP_DECL_EVENTEXIT ((* eventexit)),SCIP_DECL_EVENTINITSOL ((* eventinitsol)),SCIP_DECL_EVENTEXITSOL ((* eventexitsol)),SCIP_DECL_EVENTDELETE ((* eventdelete)),SCIP_DECL_EVENTEXEC ((* eventexec)),SCIP_EVENTHDLRDATA * eventhdlrdata)54 SCIP_RETCODE SCIPincludeEventhdlr(
55 SCIP* scip, /**< SCIP data structure */
56 const char* name, /**< name of event handler */
57 const char* desc, /**< description of event handler */
58 SCIP_DECL_EVENTCOPY ((*eventcopy)), /**< copy method of event handler or NULL if you don't want to copy your plugin into sub-SCIPs */
59 SCIP_DECL_EVENTFREE ((*eventfree)), /**< destructor of event handler */
60 SCIP_DECL_EVENTINIT ((*eventinit)), /**< initialize event handler */
61 SCIP_DECL_EVENTEXIT ((*eventexit)), /**< deinitialize event handler */
62 SCIP_DECL_EVENTINITSOL((*eventinitsol)), /**< solving process initialization method of event handler */
63 SCIP_DECL_EVENTEXITSOL((*eventexitsol)), /**< solving process deinitialization method of event handler */
64 SCIP_DECL_EVENTDELETE ((*eventdelete)), /**< free specific event data */
65 SCIP_DECL_EVENTEXEC ((*eventexec)), /**< execute event handler */
66 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
67 )
68 {
69 SCIP_EVENTHDLR* eventhdlr;
70
71 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeEventhdlr", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
72
73 /* check whether event handler is already present */
74 if( SCIPfindEventhdlr(scip, name) != NULL )
75 {
76 SCIPerrorMessage("event handler <%s> already included.\n", name);
77 return SCIP_INVALIDDATA;
78 }
79
80 SCIP_CALL( SCIPeventhdlrCreate(&eventhdlr, scip->set, name, desc,
81 eventcopy, eventfree, eventinit, eventexit, eventinitsol, eventexitsol, eventdelete, eventexec,
82 eventhdlrdata) );
83 SCIP_CALL( SCIPsetIncludeEventhdlr(scip->set, eventhdlr) );
84
85 return SCIP_OKAY;
86 }
87
88 /** creates an event handler and includes it in SCIP with all its non-fundamental callbacks set
89 * to NULL; if needed, non-fundamental callbacks can be set afterwards via setter functions
90 * SCIPsetEventhdlrCopy(), SCIPsetEventhdlrFree(), SCIPsetEventhdlrInit(), SCIPsetEventhdlrExit(),
91 * SCIPsetEventhdlrInitsol(), SCIPsetEventhdlrExitsol(), and SCIPsetEventhdlrDelete()
92 *
93 * @note if you want to set all callbacks with a single method call, consider using SCIPincludeEventhdlr() instead
94 */
SCIPincludeEventhdlrBasic(SCIP * scip,SCIP_EVENTHDLR ** eventhdlrptr,const char * name,const char * desc,SCIP_DECL_EVENTEXEC ((* eventexec)),SCIP_EVENTHDLRDATA * eventhdlrdata)95 SCIP_RETCODE SCIPincludeEventhdlrBasic(
96 SCIP* scip, /**< SCIP data structure */
97 SCIP_EVENTHDLR** eventhdlrptr, /**< reference to an event handler, or NULL */
98 const char* name, /**< name of event handler */
99 const char* desc, /**< description of event handler */
100 SCIP_DECL_EVENTEXEC ((*eventexec)), /**< execute event handler */
101 SCIP_EVENTHDLRDATA* eventhdlrdata /**< event handler data */
102 )
103 {
104 SCIP_EVENTHDLR* eventhdlr;
105
106 SCIP_CALL( SCIPcheckStage(scip, "SCIPincludeEventhdlrBasic", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
107
108 /* check whether event handler is already present */
109 if( SCIPfindEventhdlr(scip, name) != NULL )
110 {
111 SCIPerrorMessage("event handler <%s> already included.\n", name);
112 return SCIP_INVALIDDATA;
113 }
114
115 SCIP_CALL( SCIPeventhdlrCreate(&eventhdlr, scip->set, name, desc,
116 NULL, NULL, NULL, NULL, NULL, NULL, NULL, eventexec,
117 eventhdlrdata) );
118 SCIP_CALL( SCIPsetIncludeEventhdlr(scip->set, eventhdlr) );
119
120 if( eventhdlrptr != NULL )
121 *eventhdlrptr = eventhdlr;
122
123 return SCIP_OKAY;
124 }
125
126 /** sets copy callback of the event handler */
SCIPsetEventhdlrCopy(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTCOPY ((* eventcopy)))127 SCIP_RETCODE SCIPsetEventhdlrCopy(
128 SCIP* scip, /**< scip instance */
129 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
130 SCIP_DECL_EVENTCOPY ((*eventcopy)) /**< copy callback of the event handler */
131 )
132 {
133 assert(scip != NULL);
134 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrCopy", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
135
136 SCIPeventhdlrSetCopy(eventhdlr, eventcopy);
137 return SCIP_OKAY;
138 }
139
140 /** sets deinitialization callback of the event handler */
SCIPsetEventhdlrFree(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTFREE ((* eventfree)))141 SCIP_RETCODE SCIPsetEventhdlrFree(
142 SCIP* scip, /**< scip instance */
143 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
144 SCIP_DECL_EVENTFREE ((*eventfree)) /**< deinitialization callback of the event handler */
145 )
146 {
147 assert(scip != NULL);
148 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrFree", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
149
150 SCIPeventhdlrSetFree(eventhdlr, eventfree);
151 return SCIP_OKAY;
152 }
153
154 /** sets initialization callback of the event handler */
SCIPsetEventhdlrInit(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTINIT ((* eventinit)))155 SCIP_RETCODE SCIPsetEventhdlrInit(
156 SCIP* scip, /**< scip instance */
157 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
158 SCIP_DECL_EVENTINIT ((*eventinit)) /**< initialize event handler */
159 )
160 {
161 assert(scip != NULL);
162 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrInit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
163
164 SCIPeventhdlrSetInit(eventhdlr, eventinit);
165 return SCIP_OKAY;
166 }
167
168 /** sets deinitialization callback of the event handler */
SCIPsetEventhdlrExit(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTEXIT ((* eventexit)))169 SCIP_RETCODE SCIPsetEventhdlrExit(
170 SCIP* scip, /**< scip instance */
171 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
172 SCIP_DECL_EVENTEXIT ((*eventexit)) /**< deinitialize event handler */
173 )
174 {
175 assert(scip != NULL);
176 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrExit", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
177
178 SCIPeventhdlrSetExit(eventhdlr, eventexit);
179 return SCIP_OKAY;
180 }
181
182 /** sets solving process initialization callback of the event handler */
SCIPsetEventhdlrInitsol(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTINITSOL ((* eventinitsol)))183 SCIP_RETCODE SCIPsetEventhdlrInitsol(
184 SCIP* scip, /**< scip instance */
185 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
186 SCIP_DECL_EVENTINITSOL((*eventinitsol)) /**< solving process initialization callback of event handler */
187 )
188 {
189 assert(scip != NULL);
190 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrInitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
191
192 SCIPeventhdlrSetInitsol(eventhdlr, eventinitsol);
193 return SCIP_OKAY;
194 }
195
196 /** sets solving process deinitialization callback of the event handler */
SCIPsetEventhdlrExitsol(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTEXITSOL ((* eventexitsol)))197 SCIP_RETCODE SCIPsetEventhdlrExitsol(
198 SCIP* scip, /**< scip instance */
199 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
200 SCIP_DECL_EVENTEXITSOL((*eventexitsol)) /**< solving process deinitialization callback of event handler */
201 )
202 {
203 assert(scip != NULL);
204 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrExitsol", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
205
206 SCIPeventhdlrSetExitsol(eventhdlr, eventexitsol);
207 return SCIP_OKAY;
208 }
209
210 /** sets callback of the event handler to free specific event data */
SCIPsetEventhdlrDelete(SCIP * scip,SCIP_EVENTHDLR * eventhdlr,SCIP_DECL_EVENTDELETE ((* eventdelete)))211 SCIP_RETCODE SCIPsetEventhdlrDelete(
212 SCIP* scip, /**< scip instance */
213 SCIP_EVENTHDLR* eventhdlr, /**< event handler */
214 SCIP_DECL_EVENTDELETE ((*eventdelete)) /**< free specific event data */
215 )
216 {
217 assert(scip != NULL);
218 SCIP_CALL( SCIPcheckStage(scip, "SCIPsetEventhdlrDelete", TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE) );
219
220 SCIPeventhdlrSetDelete(eventhdlr, eventdelete);
221 return SCIP_OKAY;
222 }
223
224 /** returns the event handler of the given name, or NULL if not existing */
SCIPfindEventhdlr(SCIP * scip,const char * name)225 SCIP_EVENTHDLR* SCIPfindEventhdlr(
226 SCIP* scip, /**< SCIP data structure */
227 const char* name /**< name of event handler */
228 )
229 {
230 assert(scip != NULL);
231 assert(scip->set != NULL);
232 assert(name != NULL);
233
234 return SCIPsetFindEventhdlr(scip->set, name);
235 }
236
237 /** returns the array of currently available event handlers */
SCIPgetEventhdlrs(SCIP * scip)238 SCIP_EVENTHDLR** SCIPgetEventhdlrs(
239 SCIP* scip /**< SCIP data structure */
240 )
241 {
242 assert(scip != NULL);
243 assert(scip->set != NULL);
244
245 return scip->set->eventhdlrs;
246 }
247
248 /** returns the number of currently available event handlers */
SCIPgetNEventhdlrs(SCIP * scip)249 int SCIPgetNEventhdlrs(
250 SCIP* scip /**< SCIP data structure */
251 )
252 {
253 assert(scip != NULL);
254 assert(scip->set != NULL);
255
256 return scip->set->neventhdlrs;
257 }
258
259 /** catches a global (not variable or row dependent) event
260 *
261 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
262 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
263 *
264 * @pre This method can be called if @p scip is in one of the following stages:
265 * - \ref SCIP_STAGE_TRANSFORMING
266 * - \ref SCIP_STAGE_TRANSFORMED
267 * - \ref SCIP_STAGE_INITPRESOLVE
268 * - \ref SCIP_STAGE_PRESOLVING
269 * - \ref SCIP_STAGE_EXITPRESOLVE
270 * - \ref SCIP_STAGE_PRESOLVED
271 * - \ref SCIP_STAGE_INITSOLVE
272 * - \ref SCIP_STAGE_SOLVING
273 * - \ref SCIP_STAGE_SOLVED
274 * - \ref SCIP_STAGE_EXITSOLVE
275 * - \ref SCIP_STAGE_FREETRANS
276 */
SCIPcatchEvent(SCIP * scip,SCIP_EVENTTYPE eventtype,SCIP_EVENTHDLR * eventhdlr,SCIP_EVENTDATA * eventdata,int * filterpos)277 SCIP_RETCODE SCIPcatchEvent(
278 SCIP* scip, /**< SCIP data structure */
279 SCIP_EVENTTYPE eventtype, /**< event type mask to select events to catch */
280 SCIP_EVENTHDLR* eventhdlr, /**< event handler to process events with */
281 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler when processing this event */
282 int* filterpos /**< pointer to store position of event filter entry, or NULL */
283 )
284 {
285 SCIP_CALL( SCIPcheckStage(scip, "SCIPcatchEvent", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
286
287 SCIP_CALL( SCIPeventfilterAdd(scip->eventfilter, scip->mem->probmem, scip->set,
288 eventtype, eventhdlr, eventdata, filterpos) );
289
290 return SCIP_OKAY;
291 }
292
293 /** drops a global event (stops to track event)
294 *
295 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
296 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
297 *
298 * @pre This method can be called if @p scip is in one of the following stages:
299 * - \ref SCIP_STAGE_TRANSFORMING
300 * - \ref SCIP_STAGE_TRANSFORMED
301 * - \ref SCIP_STAGE_INITPRESOLVE
302 * - \ref SCIP_STAGE_PRESOLVING
303 * - \ref SCIP_STAGE_EXITPRESOLVE
304 * - \ref SCIP_STAGE_PRESOLVED
305 * - \ref SCIP_STAGE_INITSOLVE
306 * - \ref SCIP_STAGE_SOLVING
307 * - \ref SCIP_STAGE_SOLVED
308 * - \ref SCIP_STAGE_EXITSOLVE
309 * - \ref SCIP_STAGE_FREETRANS
310 */
SCIPdropEvent(SCIP * scip,SCIP_EVENTTYPE eventtype,SCIP_EVENTHDLR * eventhdlr,SCIP_EVENTDATA * eventdata,int filterpos)311 SCIP_RETCODE SCIPdropEvent(
312 SCIP* scip, /**< SCIP data structure */
313 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
314 SCIP_EVENTHDLR* eventhdlr, /**< event handler to process events with */
315 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler when processing this event */
316 int filterpos /**< position of event filter entry returned by SCIPcatchEvent(), or -1 */
317 )
318 {
319 SCIP_CALL( SCIPcheckStage(scip, "SCIPdropEvent", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
320
321 SCIP_CALL( SCIPeventfilterDel(scip->eventfilter, scip->mem->probmem, scip->set,
322 eventtype, eventhdlr, eventdata, filterpos) );
323
324 return SCIP_OKAY;
325 }
326
327 /** catches an objective value or domain change event on the given transformed variable
328 *
329 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
330 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
331 *
332 * @pre This method can be called if @p scip is in one of the following stages:
333 * - \ref SCIP_STAGE_TRANSFORMING
334 * - \ref SCIP_STAGE_TRANSFORMED
335 * - \ref SCIP_STAGE_INITPRESOLVE
336 * - \ref SCIP_STAGE_PRESOLVING
337 * - \ref SCIP_STAGE_EXITPRESOLVE
338 * - \ref SCIP_STAGE_PRESOLVED
339 * - \ref SCIP_STAGE_INITSOLVE
340 * - \ref SCIP_STAGE_SOLVING
341 * - \ref SCIP_STAGE_SOLVED
342 * - \ref SCIP_STAGE_EXITSOLVE
343 * - \ref SCIP_STAGE_FREETRANS
344 */
SCIPcatchVarEvent(SCIP * scip,SCIP_VAR * var,SCIP_EVENTTYPE eventtype,SCIP_EVENTHDLR * eventhdlr,SCIP_EVENTDATA * eventdata,int * filterpos)345 SCIP_RETCODE SCIPcatchVarEvent(
346 SCIP* scip, /**< SCIP data structure */
347 SCIP_VAR* var, /**< transformed variable to catch event for */
348 SCIP_EVENTTYPE eventtype, /**< event type mask to select events to catch */
349 SCIP_EVENTHDLR* eventhdlr, /**< event handler to process events with */
350 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler when processing this event */
351 int* filterpos /**< pointer to store position of event filter entry, or NULL */
352 )
353 {
354 SCIP_CALL( SCIPcheckStage(scip, "SCIPcatchVarEvent", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
355
356 if( (eventtype & SCIP_EVENTTYPE_VARCHANGED) == 0 )
357 {
358 SCIPerrorMessage("event does not operate on a single variable\n");
359 return SCIP_INVALIDDATA;
360 }
361
362 if( SCIPvarIsOriginal(var) )
363 {
364 SCIPerrorMessage("cannot catch events on original variable <%s>\n", SCIPvarGetName(var));
365 return SCIP_INVALIDDATA;
366 }
367
368 SCIP_CALL( SCIPvarCatchEvent(var, scip->mem->probmem, scip->set, eventtype, eventhdlr, eventdata, filterpos) );
369
370 return SCIP_OKAY;
371 }
372
373 /** drops an objective value or domain change event (stops to track event) on the given transformed variable
374 *
375 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
376 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
377 *
378 * @pre This method can be called if @p scip is in one of the following stages:
379 * - \ref SCIP_STAGE_TRANSFORMING
380 * - \ref SCIP_STAGE_TRANSFORMED
381 * - \ref SCIP_STAGE_INITPRESOLVE
382 * - \ref SCIP_STAGE_PRESOLVING
383 * - \ref SCIP_STAGE_EXITPRESOLVE
384 * - \ref SCIP_STAGE_PRESOLVED
385 * - \ref SCIP_STAGE_INITSOLVE
386 * - \ref SCIP_STAGE_SOLVING
387 * - \ref SCIP_STAGE_SOLVED
388 * - \ref SCIP_STAGE_EXITSOLVE
389 * - \ref SCIP_STAGE_FREETRANS
390 */
SCIPdropVarEvent(SCIP * scip,SCIP_VAR * var,SCIP_EVENTTYPE eventtype,SCIP_EVENTHDLR * eventhdlr,SCIP_EVENTDATA * eventdata,int filterpos)391 SCIP_RETCODE SCIPdropVarEvent(
392 SCIP* scip, /**< SCIP data structure */
393 SCIP_VAR* var, /**< transformed variable to drop event for */
394 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
395 SCIP_EVENTHDLR* eventhdlr, /**< event handler to process events with */
396 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler when processing this event */
397 int filterpos /**< position of event filter entry returned by SCIPcatchVarEvent(), or -1 */
398 )
399 {
400 SCIP_CALL( SCIPcheckStage(scip, "SCIPdropVarEvent", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
401
402 if( SCIPvarIsOriginal(var) )
403 {
404 SCIPerrorMessage("cannot drop events on original variable <%s>\n", SCIPvarGetName(var));
405 return SCIP_INVALIDDATA;
406 }
407
408 SCIP_CALL( SCIPvarDropEvent(var, scip->mem->probmem, scip->set, eventtype, eventhdlr, eventdata, filterpos) );
409
410 return SCIP_OKAY;
411 }
412
413 /** catches a row coefficient, constant, or side change event on the given row
414 *
415 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
416 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
417 *
418 * @pre This method can be called if @p scip is in one of the following stages:
419 * - \ref SCIP_STAGE_TRANSFORMING
420 * - \ref SCIP_STAGE_TRANSFORMED
421 * - \ref SCIP_STAGE_INITPRESOLVE
422 * - \ref SCIP_STAGE_PRESOLVING
423 * - \ref SCIP_STAGE_EXITPRESOLVE
424 * - \ref SCIP_STAGE_PRESOLVED
425 * - \ref SCIP_STAGE_INITSOLVE
426 * - \ref SCIP_STAGE_SOLVING
427 * - \ref SCIP_STAGE_SOLVED
428 * - \ref SCIP_STAGE_EXITSOLVE
429 * - \ref SCIP_STAGE_FREETRANS
430 */
SCIPcatchRowEvent(SCIP * scip,SCIP_ROW * row,SCIP_EVENTTYPE eventtype,SCIP_EVENTHDLR * eventhdlr,SCIP_EVENTDATA * eventdata,int * filterpos)431 SCIP_RETCODE SCIPcatchRowEvent(
432 SCIP* scip, /**< SCIP data structure */
433 SCIP_ROW* row, /**< linear row to catch event for */
434 SCIP_EVENTTYPE eventtype, /**< event type mask to select events to catch */
435 SCIP_EVENTHDLR* eventhdlr, /**< event handler to process events with */
436 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler when processing this event */
437 int* filterpos /**< pointer to store position of event filter entry, or NULL */
438 )
439 {
440 SCIP_CALL( SCIPcheckStage(scip, "SCIPcatchRowEvent", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
441
442 if( (eventtype & SCIP_EVENTTYPE_ROWCHANGED) == 0 )
443 {
444 SCIPerrorMessage("event does not operate on a single row\n");
445 return SCIP_INVALIDDATA;
446 }
447
448 SCIP_CALL( SCIProwCatchEvent(row, scip->mem->probmem, scip->set, eventtype, eventhdlr, eventdata, filterpos) );
449
450 return SCIP_OKAY;
451 }
452
453 /** drops a row coefficient, constant, or side change event (stops to track event) on the given row
454 *
455 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
456 * SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
457 *
458 * @pre This method can be called if @p scip is in one of the following stages:
459 * - \ref SCIP_STAGE_TRANSFORMING
460 * - \ref SCIP_STAGE_TRANSFORMED
461 * - \ref SCIP_STAGE_INITPRESOLVE
462 * - \ref SCIP_STAGE_PRESOLVING
463 * - \ref SCIP_STAGE_EXITPRESOLVE
464 * - \ref SCIP_STAGE_PRESOLVED
465 * - \ref SCIP_STAGE_INITSOLVE
466 * - \ref SCIP_STAGE_SOLVING
467 * - \ref SCIP_STAGE_SOLVED
468 * - \ref SCIP_STAGE_EXITSOLVE
469 * - \ref SCIP_STAGE_FREETRANS
470 */
SCIPdropRowEvent(SCIP * scip,SCIP_ROW * row,SCIP_EVENTTYPE eventtype,SCIP_EVENTHDLR * eventhdlr,SCIP_EVENTDATA * eventdata,int filterpos)471 SCIP_RETCODE SCIPdropRowEvent(
472 SCIP* scip, /**< SCIP data structure */
473 SCIP_ROW* row, /**< linear row to drop event for */
474 SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
475 SCIP_EVENTHDLR* eventhdlr, /**< event handler to process events with */
476 SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler when processing this event */
477 int filterpos /**< position of event filter entry returned by SCIPcatchVarEvent(), or -1 */
478 )
479 {
480 SCIP_CALL( SCIPcheckStage(scip, "SCIPdropRowEvent", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
481
482 SCIP_CALL( SCIProwDropEvent(row, scip->mem->probmem, scip->set, eventtype, eventhdlr, eventdata, filterpos) );
483
484 return SCIP_OKAY;
485 }
486