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