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