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   event.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  methods and datastructures for managing events
28   	 * @author Tobias Achterberg
29   	 */
30   	
31   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
32   	
33   	#include <assert.h>
34   	#include <string.h>
35   	
36   	#include "scip/branch.h"
37   	#include "scip/clock.h"
38   	#include "scip/event.h"
39   	#include "scip/lp.h"
40   	#include "scip/primal.h"
41   	#include "scip/pub_event.h"
42   	#include "scip/pub_message.h"
43   	#include "scip/pub_var.h"
44   	#include "scip/set.h"
45   	#include "scip/struct_event.h"
46   	#include "scip/struct_lp.h"
47   	#include "scip/struct_set.h"
48   	#include "scip/struct_var.h"
49   	#include "scip/var.h"
50   	
51   	/* timing the execution methods for event handling takes a lot of time, so it is disabled */
52   	/* #define TIMEEVENTEXEC */
53   	
54   	
55   	/*
56   	 * Event handler methods
57   	 */
58   	
59   	/** copies the given event handler to a new scip */
60   	SCIP_RETCODE SCIPeventhdlrCopyInclude(
61   	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
62   	   SCIP_SET*             set                 /**< SCIP_SET of SCIP to copy to */
63   	   )
64   	{
65   	   assert(eventhdlr != NULL);
66   	   assert(set != NULL);
67   	   assert(set->scip != NULL);
68   	
69   	   if( eventhdlr->eventcopy != NULL )
70   	   {
71   	      SCIPsetDebugMsg(set, "including event handler %s in subscip %p\n", SCIPeventhdlrGetName(eventhdlr), (void*)set->scip);
72   	      SCIP_CALL( eventhdlr->eventcopy(set->scip, eventhdlr) );
73   	   }
74   	
75   	   return SCIP_OKAY;
76   	}
77   	
78   	/** internal method for creating an event handler */
79   	static
80   	SCIP_RETCODE doEventhdlrCreate(
81   	   SCIP_EVENTHDLR**      eventhdlr,          /**< pointer to event handler data structure */
82   	   const char*           name,               /**< name of event handler */
83   	   const char*           desc,               /**< description of event handler */
84   	   SCIP_DECL_EVENTCOPY   ((*eventcopy)),     /**< copy method of event handler or NULL if you don't want to copy your plugin into sub-SCIPs */
85   	   SCIP_DECL_EVENTFREE   ((*eventfree)),     /**< destructor of event handler */
86   	   SCIP_DECL_EVENTINIT   ((*eventinit)),     /**< initialize event handler */
87   	   SCIP_DECL_EVENTEXIT   ((*eventexit)),     /**< deinitialize event handler */
88   	   SCIP_DECL_EVENTINITSOL((*eventinitsol)),  /**< solving process initialization method of event handler */
89   	   SCIP_DECL_EVENTEXITSOL((*eventexitsol)),  /**< solving process deinitialization method of event handler */
90   	   SCIP_DECL_EVENTDELETE ((*eventdelete)),   /**< free specific event data */
91   	   SCIP_DECL_EVENTEXEC   ((*eventexec)),     /**< execute event handler */
92   	   SCIP_EVENTHDLRDATA*   eventhdlrdata       /**< event handler data */
93   	   )
94   	{
95   	   assert(eventhdlr != NULL);
96   	   assert(name != NULL);
97   	   assert(desc != NULL);
98   	   assert(eventexec != NULL);
99   	
100  	   SCIP_ALLOC( BMSallocMemory(eventhdlr) );
101  	   BMSclearMemory(*eventhdlr);
102  	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*eventhdlr)->name, name, strlen(name)+1) );
103  	   SCIP_ALLOC( BMSduplicateMemoryArray(&(*eventhdlr)->desc, desc, strlen(desc)+1) );
104  	   (*eventhdlr)->eventcopy = eventcopy;
105  	   (*eventhdlr)->eventfree = eventfree;
106  	   (*eventhdlr)->eventinit = eventinit;
107  	   (*eventhdlr)->eventexit = eventexit;
108  	   (*eventhdlr)->eventinitsol = eventinitsol;
109  	   (*eventhdlr)->eventexitsol = eventexitsol;
110  	   (*eventhdlr)->eventdelete = eventdelete;
111  	   (*eventhdlr)->eventexec = eventexec;
112  	   (*eventhdlr)->eventhdlrdata = eventhdlrdata;
113  	   (*eventhdlr)->initialized = FALSE;
114  	
115  	   /* create clocks */
116  	   SCIP_CALL( SCIPclockCreate(&(*eventhdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) );
117  	   SCIP_CALL( SCIPclockCreate(&(*eventhdlr)->eventtime, SCIP_CLOCKTYPE_DEFAULT) );
118  	
119  	   return SCIP_OKAY;
120  	}
121  	
122  	/** creates an event handler */
123  	SCIP_RETCODE SCIPeventhdlrCreate(
124  	   SCIP_EVENTHDLR**      eventhdlr,          /**< pointer to event handler data structure */
125  	   SCIP_SET*             set,                /**< global SCIP settings */
126  	   const char*           name,               /**< name of event handler */
127  	   const char*           desc,               /**< description of event handler */
128  	   SCIP_DECL_EVENTCOPY   ((*eventcopy)),     /**< copy method of event handler or NULL if you don't want to copy your plugin into sub-SCIPs */
129  	   SCIP_DECL_EVENTFREE   ((*eventfree)),     /**< destructor of event handler */
130  	   SCIP_DECL_EVENTINIT   ((*eventinit)),     /**< initialize event handler */
131  	   SCIP_DECL_EVENTEXIT   ((*eventexit)),     /**< deinitialize event handler */
132  	   SCIP_DECL_EVENTINITSOL((*eventinitsol)),  /**< solving process initialization method of event handler */
133  	   SCIP_DECL_EVENTEXITSOL((*eventexitsol)),  /**< solving process deinitialization method of event handler */
134  	   SCIP_DECL_EVENTDELETE ((*eventdelete)),   /**< free specific event data */
135  	   SCIP_DECL_EVENTEXEC   ((*eventexec)),     /**< execute event handler */
136  	   SCIP_EVENTHDLRDATA*   eventhdlrdata       /**< event handler data */
137  	   )
138  	{
139  	   assert(eventhdlr != NULL);
140  	   assert(set != NULL);
141  	
142  	   SCIP_CALL_FINALLY( doEventhdlrCreate(eventhdlr, name, desc, eventcopy, eventfree, eventinit, eventexit,
143  	      eventinitsol, eventexitsol, eventdelete, eventexec, eventhdlrdata), (void) SCIPeventhdlrFree(eventhdlr, set) );
144  	
145  	   return SCIP_OKAY;
146  	}
147  	
148  	/** calls destructor and frees memory of event handler */
149  	SCIP_RETCODE SCIPeventhdlrFree(
150  	   SCIP_EVENTHDLR**      eventhdlr,          /**< pointer to event handler data structure */
151  	   SCIP_SET*             set                 /**< global SCIP settings */
152  	   )
153  	{
154  	   assert(eventhdlr != NULL);
155  	   assert(set != NULL);
156  	
157  	   if( *eventhdlr == NULL )
158  	      return SCIP_OKAY;
159  	
160  	   assert(!(*eventhdlr)->initialized);
161  	
162  	   /* call destructor of event handler */
163  	   if( (*eventhdlr)->eventfree != NULL )
164  	   {
165  	      SCIP_CALL( (*eventhdlr)->eventfree(set->scip, *eventhdlr) );
166  	   }
167  	
168  	   /* free clocks */
169  	   SCIPclockFree(&(*eventhdlr)->eventtime);
170  	   SCIPclockFree(&(*eventhdlr)->setuptime);
171  	
172  	   BMSfreeMemoryArrayNull(&(*eventhdlr)->name);
173  	   BMSfreeMemoryArrayNull(&(*eventhdlr)->desc);
174  	   BMSfreeMemory(eventhdlr);
175  	
176  	   return SCIP_OKAY;
177  	}
178  	
179  	/** initializes event handler */
180  	SCIP_RETCODE SCIPeventhdlrInit(
181  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler for this event */
182  	   SCIP_SET*             set                 /**< global SCIP settings */
183  	   )
184  	{
185  	   assert(eventhdlr != NULL);
186  	   assert(set != NULL);
187  	
188  	   if( eventhdlr->initialized )
189  	   {
190  	      SCIPerrorMessage("event handler <%s> already initialized\n", eventhdlr->name);
191  	      return SCIP_INVALIDCALL;
192  	   }
193  	
194  	   if( set->misc_resetstat )
195  	   {
196  	      SCIPclockReset(eventhdlr->setuptime);
197  	      SCIPclockReset(eventhdlr->eventtime);
198  	   }
199  	
200  	   if( eventhdlr->eventinit != NULL )
201  	   {
202  	      /* start timing */
203  	      SCIPclockStart(eventhdlr->setuptime, set);
204  	
205  	      SCIP_CALL( eventhdlr->eventinit(set->scip, eventhdlr) );
206  	
207  	      /* stop timing */
208  	      SCIPclockStop(eventhdlr->setuptime, set);
209  	   }
210  	   eventhdlr->initialized = TRUE;
211  	
212  	   return SCIP_OKAY;
213  	}
214  	
215  	/** calls exit method of event handler */
216  	SCIP_RETCODE SCIPeventhdlrExit(
217  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler for this event */
218  	   SCIP_SET*             set                 /**< global SCIP settings */
219  	   )
220  	{
221  	   assert(eventhdlr != NULL);
222  	   assert(set != NULL);
223  	
224  	   if( !eventhdlr->initialized )
225  	   {
226  	      SCIPerrorMessage("event handler <%s> not initialized\n", eventhdlr->name);
227  	      return SCIP_INVALIDCALL;
228  	   }
229  	
230  	   if( eventhdlr->eventexit != NULL )
231  	   {
232  	      /* start timing */
233  	      SCIPclockStart(eventhdlr->setuptime, set);
234  	
235  	      SCIP_CALL( eventhdlr->eventexit(set->scip, eventhdlr) );
236  	
237  	      /* stop timing */
238  	      SCIPclockStop(eventhdlr->setuptime, set);
239  	   }
240  	   eventhdlr->initialized = FALSE;
241  	
242  	   return SCIP_OKAY;
243  	}
244  	
245  	/** informs event handler that the branch and bound process is being started */
246  	SCIP_RETCODE SCIPeventhdlrInitsol(
247  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
248  	   SCIP_SET*             set                 /**< global SCIP settings */
249  	   )
250  	{
251  	   assert(eventhdlr != NULL);
252  	   assert(set != NULL);
253  	
254  	   /* call solving process initialization method of event handler */
255  	   if( eventhdlr->eventinitsol != NULL )
256  	   {
257  	      /* start timing */
258  	      SCIPclockStart(eventhdlr->setuptime, set);
259  	
260  	      SCIP_CALL( eventhdlr->eventinitsol(set->scip, eventhdlr) );
261  	
262  	      /* stop timing */
263  	      SCIPclockStop(eventhdlr->setuptime, set);
264  	   }
265  	
266  	   return SCIP_OKAY;
267  	}
268  	
269  	/** informs event handler that the branch and bound process data is being freed */
270  	SCIP_RETCODE SCIPeventhdlrExitsol(
271  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
272  	   SCIP_SET*             set                 /**< global SCIP settings */
273  	   )
274  	{
275  	   assert(eventhdlr != NULL);
276  	   assert(set != NULL);
277  	
278  	   /* call solving process deinitialization method of event handler */
279  	   if( eventhdlr->eventexitsol != NULL )
280  	   {
281  	      /* start timing */
282  	      SCIPclockStart(eventhdlr->setuptime, set);
283  	
284  	      SCIP_CALL( eventhdlr->eventexitsol(set->scip, eventhdlr) );
285  	
286  	      /* stop timing */
287  	      SCIPclockStop(eventhdlr->setuptime, set);
288  	   }
289  	
290  	   return SCIP_OKAY;
291  	}
292  	
293  	/** calls execution method of event handler */
294  	SCIP_RETCODE SCIPeventhdlrExec(
295  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
296  	   SCIP_SET*             set,                /**< global SCIP settings */
297  	   SCIP_EVENT*           event,              /**< event to call event handler with */
298  	   SCIP_EVENTDATA*       eventdata           /**< user data for the issued event */
299  	   )
300  	{
301  	   assert(eventhdlr != NULL);
302  	   assert(eventhdlr->eventexec != NULL);
303  	   assert(set != NULL);
304  	   assert(event != NULL);
305  	
306  	   SCIPsetDebugMsg(set, "execute event of handler <%s> with event %p of type 0x%" SCIP_EVENTTYPE_FORMAT "\n", eventhdlr->name, (void*)event, event->eventtype);
307  	
308  	#ifdef TIMEEVENTEXEC
309  	   /* start timing */
310  	   SCIPclockStart(eventhdlr->eventtime, set);
311  	#endif
312  	
313  	   SCIP_CALL( eventhdlr->eventexec(set->scip, eventhdlr, event, eventdata) );
314  	
315  	#ifdef TIMEEVENTEXEC
316  	   /* stop timing */
317  	   SCIPclockStop(eventhdlr->eventtime, set);
318  	#endif
319  	
320  	   return SCIP_OKAY;
321  	}
322  	
323  	/** gets name of event handler */
324  	const char* SCIPeventhdlrGetName(
325  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
326  	   )
327  	{
328  	   assert(eventhdlr != NULL);
329  	
330  	   return eventhdlr->name;
331  	}
332  	
333  	/** gets user data of event handler */
334  	SCIP_EVENTHDLRDATA* SCIPeventhdlrGetData(
335  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
336  	   )
337  	{
338  	   assert(eventhdlr != NULL);
339  	
340  	   return eventhdlr->eventhdlrdata;
341  	}
342  	
343  	/** sets user data of event handler; user has to free old data in advance! */
344  	void SCIPeventhdlrSetData(
345  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
346  	   SCIP_EVENTHDLRDATA*   eventhdlrdata       /**< new event handler user data */
347  	   )
348  	{
349  	   assert(eventhdlr != NULL);
350  	
351  	   eventhdlr->eventhdlrdata = eventhdlrdata;
352  	}
353  	
354  	/** sets copy callback for all events of this event handler */
355  	void SCIPeventhdlrSetCopy(
356  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
357  	   SCIP_DECL_EVENTCOPY   ((*eventcopy))      /**< copy callback for events */
358  	   )
359  	{
360  	   assert(eventhdlr != NULL);
361  	
362  	   eventhdlr->eventcopy = eventcopy;
363  	}
364  	
365  	/** sets destructor callback of this event handler */
366  	void SCIPeventhdlrSetFree(
367  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
368  	   SCIP_DECL_EVENTFREE   ((*eventfree))      /**< destructor callback of event handler */
369  	   )
370  	{
371  	   assert(eventhdlr != NULL);
372  	
373  	   eventhdlr->eventfree = eventfree;
374  	}
375  	
376  	/** sets initialization callback of this event handler */
377  	void SCIPeventhdlrSetInit(
378  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
379  	   SCIP_DECL_EVENTINIT   ((*eventinit))      /**< initialization callback of event handler */
380  	   )
381  	{
382  	   assert(eventhdlr != NULL);
383  	
384  	   eventhdlr->eventinit = eventinit;
385  	}
386  	
387  	/** sets deinitialization callback of this event handler */
388  	void SCIPeventhdlrSetExit(
389  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
390  	   SCIP_DECL_EVENTEXIT   ((*eventexit))      /**< deinitialization callback of event handler */
391  	   )
392  	{
393  	   assert(eventhdlr != NULL);
394  	
395  	   eventhdlr->eventexit = eventexit;
396  	}
397  	
398  	/** sets solving process initialization callback of this event handler */
399  	void SCIPeventhdlrSetInitsol(
400  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
401  	   SCIP_DECL_EVENTINITSOL((*eventinitsol))   /**< solving process initialization callback of event handler */
402  	   )
403  	{
404  	   assert(eventhdlr != NULL);
405  	
406  	   eventhdlr->eventinitsol = eventinitsol;
407  	}
408  	
409  	/** sets solving process deinitialization callback of this event handler */
410  	void SCIPeventhdlrSetExitsol(
411  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
412  	   SCIP_DECL_EVENTEXITSOL((*eventexitsol))   /**< solving process deinitialization callback of event handler */
413  	   )
414  	{
415  	   assert(eventhdlr != NULL);
416  	
417  	   eventhdlr->eventexitsol = eventexitsol;
418  	}
419  	
420  	/** sets callback to free specific event data */
421  	void SCIPeventhdlrSetDelete(
422  	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler */
423  	   SCIP_DECL_EVENTDELETE ((*eventdelete))    /**< callback to free specific event data */
424  	   )
425  	{
426  	   assert(eventhdlr != NULL);
427  	
428  	   eventhdlr->eventdelete = eventdelete;
429  	}
430  	
431  	/** is event handler initialized? */
432  	SCIP_Bool SCIPeventhdlrIsInitialized(
433  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
434  	   )
435  	{
436  	   assert(eventhdlr != NULL);
437  	
438  	   return eventhdlr->initialized;
439  	}
440  	
441  	/** enables or disables all clocks of \p eventhdlr, depending on the value of the flag */
442  	void SCIPeventhdlrEnableOrDisableClocks(
443  	   SCIP_EVENTHDLR*       eventhdlr,          /**< the event handler for which all clocks should be enabled or disabled */
444  	   SCIP_Bool             enable              /**< should the clocks of the event handler be enabled? */
445  	   )
446  	{
447  	   assert(eventhdlr != NULL);
448  	
449  	   SCIPclockEnableOrDisable(eventhdlr->setuptime, enable);
450  	   SCIPclockEnableOrDisable(eventhdlr->eventtime, enable);
451  	}
452  	
453  	/** gets time in seconds used in this event handler for setting up for next stages */
454  	SCIP_Real SCIPeventhdlrGetSetupTime(
455  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
456  	   )
457  	{
458  	   assert(eventhdlr != NULL);
459  	
460  	   return SCIPclockGetTime(eventhdlr->setuptime);
461  	}
462  	
463  	/** gets time in seconds used in this event handler, this measurement is currently disabled so this method will return
464  	 *  0, define TIMEEVENTEXEC in the beginning of this file to enable
465  	 */
466  	SCIP_Real SCIPeventhdlrGetTime(
467  	   SCIP_EVENTHDLR*       eventhdlr           /**< event handler */
468  	   )
469  	{
470  	   assert(eventhdlr != NULL);
471  	
472  	   return SCIPclockGetTime(eventhdlr->eventtime);
473  	}
474  	
475  	
476  	
477  	/*
478  	 * Event methods
479  	 */
480  	
481  	
482  	/** creates a synchronization event */
483  	SCIP_RETCODE SCIPeventCreateSync(
484  	   SCIP_EVENT**          event,              /**< pointer to store the event */
485  	   BMS_BLKMEM*           blkmem              /**< block memory */
486  	   )
487  	{
488  	   assert(event != NULL);
489  	
490  	   /* create event data */
491  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
492  	   (*event)->eventtype = SCIP_EVENTTYPE_SYNC;
493  	
494  	   return SCIP_OKAY;
495  	}
496  	
497  	/*
498  	 * simple functions implemented as defines
499  	 */
500  	
501  	/* In debug mode, the following methods are implemented as function calls to ensure
502  	 * type validity.
503  	 * In optimized mode, the methods are implemented as defines to improve performance.
504  	 * However, we want to have them in the library anyways, so we have to undef the defines.
505  	 */
506  	
507  	#undef SCIPeventGetType
508  	#undef SCIPeventGetOldobj
509  	#undef SCIPeventGetNewobj
510  	#undef SCIPeventGetOldtype
511  	#undef SCIPeventGetNewtype
512  	#undef SCIPeventGetOldbound
513  	#undef SCIPeventGetNewbound
514  	#undef SCIPeventGetNode
515  	#undef SCIPeventGetSol
516  	#undef SCIPeventGetRowCol
517  	#undef SCIPeventGetRowOldCoefVal
518  	#undef SCIPeventGetRowNewCoefVal
519  	#undef SCIPeventGetRowOldConstVal
520  	#undef SCIPeventGetRowNewConstVal
521  	#undef SCIPeventGetRowSide
522  	#undef SCIPeventGetRowOldSideVal
523  	#undef SCIPeventGetRowNewSideVal
524  	
525  	/** creates an event for an addition of a variable to the problem */
526  	SCIP_RETCODE SCIPeventCreateVarAdded(
527  	   SCIP_EVENT**          event,              /**< pointer to store the event */
528  	   BMS_BLKMEM*           blkmem,             /**< block memory */
529  	   SCIP_VAR*             var                 /**< variable that was added to the problem */
530  	   )
531  	{
532  	   assert(event != NULL);
533  	   assert(blkmem != NULL);
534  	
535  	   /* create event data */
536  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
537  	   (*event)->eventtype = SCIP_EVENTTYPE_VARADDED;
538  	   (*event)->data.eventvaradded.var = var;
539  	
540  	   return SCIP_OKAY;
541  	}
542  	
543  	/** creates an event for a deletion of a variable from the problem */
544  	SCIP_RETCODE SCIPeventCreateVarDeleted(
545  	   SCIP_EVENT**          event,              /**< pointer to store the event */
546  	   BMS_BLKMEM*           blkmem,             /**< block memory */
547  	   SCIP_VAR*             var                 /**< variable that is to be deleted from the problem */
548  	   )
549  	{
550  	   assert(event != NULL);
551  	   assert(blkmem != NULL);
552  	
553  	   /* create event data */
554  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
555  	   (*event)->eventtype = SCIP_EVENTTYPE_VARDELETED;
556  	   (*event)->data.eventvardeleted.var = var;
557  	
558  	   return SCIP_OKAY;
559  	}
560  	
561  	/** creates an event for a fixing of a variable */
562  	SCIP_RETCODE SCIPeventCreateVarFixed(
563  	   SCIP_EVENT**          event,              /**< pointer to store the event */
564  	   BMS_BLKMEM*           blkmem,             /**< block memory */
565  	   SCIP_VAR*             var                 /**< variable that was fixed */
566  	   )
567  	{
568  	   assert(event != NULL);
569  	   assert(blkmem != NULL);
570  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED
571  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_AGGREGATED
572  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR
573  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
574  	
575  	   /* create event data */
576  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
577  	   (*event)->eventtype = SCIP_EVENTTYPE_VARFIXED;
578  	   (*event)->data.eventvarfixed.var = var;
579  	
580  	   return SCIP_OKAY;
581  	}
582  	
583  	/** creates an event for a change in the number of locks of a variable down to zero or one */
584  	SCIP_RETCODE SCIPeventCreateVarUnlocked(
585  	   SCIP_EVENT**          event,              /**< pointer to store the event */
586  	   BMS_BLKMEM*           blkmem,             /**< block memory */
587  	   SCIP_VAR*             var                 /**< variable that changed the number of locks */
588  	   )
589  	{
590  	   assert(event != NULL);
591  	   assert(blkmem != NULL);
592  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
593  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
594  	      || SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
595  	
596  	   /* create event data */
597  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
598  	   (*event)->eventtype = SCIP_EVENTTYPE_VARUNLOCKED;
599  	   (*event)->data.eventvarunlocked.var = var;
600  	
601  	   return SCIP_OKAY;
602  	}
603  	
604  	/** creates an event for a change in the objective value of a variable */
605  	SCIP_RETCODE SCIPeventCreateObjChanged(
606  	   SCIP_EVENT**          event,              /**< pointer to store the event */
607  	   BMS_BLKMEM*           blkmem,             /**< block memory */
608  	   SCIP_VAR*             var,                /**< variable whose objective value changed */
609  	   SCIP_Real             oldobj,             /**< old objective value before value changed */
610  	   SCIP_Real             newobj              /**< new objective value after value changed */
611  	   )
612  	{
613  	   assert(event != NULL);
614  	   assert(blkmem != NULL);
615  	   assert(oldobj != newobj); /*lint !e777*/
616  	
617  	   /* create event data */
618  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
619  	   (*event)->eventtype = SCIP_EVENTTYPE_OBJCHANGED;
620  	   (*event)->data.eventobjchg.var = var;
621  	   (*event)->data.eventobjchg.oldobj = oldobj;
622  	   (*event)->data.eventobjchg.newobj = newobj;
623  	
624  	   return SCIP_OKAY;
625  	}
626  	
627  	/** creates an event for a change in the global lower bound of a variable */
628  	SCIP_RETCODE SCIPeventCreateGlbChanged(
629  	   SCIP_EVENT**          event,              /**< pointer to store the event */
630  	   BMS_BLKMEM*           blkmem,             /**< block memory */
631  	   SCIP_VAR*             var,                /**< variable whose bound changed */
632  	   SCIP_Real             oldbound,           /**< old bound before bound changed */
633  	   SCIP_Real             newbound            /**< new bound after bound changed */
634  	   )
635  	{
636  	   assert(event != NULL);
637  	   assert(blkmem != NULL);
638  	   assert(oldbound != newbound); /*lint !e777*/
639  	
640  	   /* create event data */
641  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
642  	   (*event)->eventtype = SCIP_EVENTTYPE_GLBCHANGED;
643  	   (*event)->data.eventbdchg.var = var;
644  	   (*event)->data.eventbdchg.oldbound = oldbound;
645  	   (*event)->data.eventbdchg.newbound = newbound;
646  	
647  	   return SCIP_OKAY;
648  	}
649  	
650  	/** creates an event for a change in the global upper bound of a variable */
651  	SCIP_RETCODE SCIPeventCreateGubChanged(
652  	   SCIP_EVENT**          event,              /**< pointer to store the event */
653  	   BMS_BLKMEM*           blkmem,             /**< block memory */
654  	   SCIP_VAR*             var,                /**< variable whose bound changed */
655  	   SCIP_Real             oldbound,           /**< old bound before bound changed */
656  	   SCIP_Real             newbound            /**< new bound after bound changed */
657  	   )
658  	{
659  	   assert(event != NULL);
660  	   assert(blkmem != NULL);
661  	   assert(oldbound != newbound); /*lint !e777*/
662  	
663  	   /* create event data */
664  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
665  	   (*event)->eventtype = SCIP_EVENTTYPE_GUBCHANGED;
666  	   (*event)->data.eventbdchg.var = var;
667  	   (*event)->data.eventbdchg.oldbound = oldbound;
668  	   (*event)->data.eventbdchg.newbound = newbound;
669  	
670  	   return SCIP_OKAY;
671  	}
672  	
673  	/** creates an event for a change in the lower bound of a variable */
674  	SCIP_RETCODE SCIPeventCreateLbChanged(
675  	   SCIP_EVENT**          event,              /**< pointer to store the event */
676  	   BMS_BLKMEM*           blkmem,             /**< block memory */
677  	   SCIP_VAR*             var,                /**< variable whose bound changed */
678  	   SCIP_Real             oldbound,           /**< old bound before bound changed */
679  	   SCIP_Real             newbound            /**< new bound after bound changed */
680  	   )
681  	{
682  	   assert(event != NULL);
683  	   assert(blkmem != NULL);
684  	   assert(oldbound != newbound); /*lint !e777*/
685  	
686  	   /* create event data */
687  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
688  	   if( newbound > oldbound )
689  	      (*event)->eventtype = SCIP_EVENTTYPE_LBTIGHTENED;
690  	   else
691  	      (*event)->eventtype = SCIP_EVENTTYPE_LBRELAXED;
692  	   (*event)->data.eventbdchg.var = var;
693  	   (*event)->data.eventbdchg.oldbound = oldbound;
694  	   (*event)->data.eventbdchg.newbound = newbound;
695  	
696  	   return SCIP_OKAY;
697  	}
698  	
699  	/** creates an event for a change in the upper bound of a variable */
700  	SCIP_RETCODE SCIPeventCreateUbChanged(
701  	   SCIP_EVENT**          event,              /**< pointer to store the event */
702  	   BMS_BLKMEM*           blkmem,             /**< block memory */
703  	   SCIP_VAR*             var,                /**< variable whose bound changed */
704  	   SCIP_Real             oldbound,           /**< old bound before bound changed */
705  	   SCIP_Real             newbound            /**< new bound after bound changed */
706  	   )
707  	{
708  	   assert(event != NULL);
709  	   assert(blkmem != NULL);
710  	   assert(oldbound != newbound); /*lint !e777*/
711  	
712  	   /* create event data */
713  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
714  	   if( newbound < oldbound )
715  	      (*event)->eventtype = SCIP_EVENTTYPE_UBTIGHTENED;
716  	   else
717  	      (*event)->eventtype = SCIP_EVENTTYPE_UBRELAXED;
718  	   (*event)->data.eventbdchg.var = var;
719  	   (*event)->data.eventbdchg.oldbound = oldbound;
720  	   (*event)->data.eventbdchg.newbound = newbound;
721  	
722  	   return SCIP_OKAY;
723  	}
724  	
725  	/** creates an event for an addition of a domain hole to a variable */
726  	SCIP_RETCODE SCIPeventCreateGholeAdded(
727  	   SCIP_EVENT**          event,              /**< pointer to store the event */
728  	   BMS_BLKMEM*           blkmem,             /**< block memory */
729  	   SCIP_VAR*             var,                /**< variable whose bound changed */
730  	   SCIP_Real             left,               /**< left bound of open interval in new hole */
731  	   SCIP_Real             right               /**< right bound of open interval in new hole */
732  	   )
733  	{
734  	   assert(event != NULL);
735  	   assert(blkmem != NULL);
736  	
737  	   /* create event data */
738  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
739  	   (*event)->eventtype = SCIP_EVENTTYPE_GHOLEADDED;
740  	   (*event)->data.eventhole.var = var;
741  	   (*event)->data.eventhole.left = left;
742  	   (*event)->data.eventhole.right = right;
743  	
744  	   return SCIP_OKAY;
745  	}
746  	
747  	/** creates an event for removing a domain hole of a variable */
748  	SCIP_RETCODE SCIPeventCreateGholeRemoved(
749  	   SCIP_EVENT**          event,              /**< pointer to store the event */
750  	   BMS_BLKMEM*           blkmem,             /**< block memory */
751  	   SCIP_VAR*             var,                /**< variable whose bound changed */
752  	   SCIP_Real             left,               /**< left bound of open interval in hole */
753  	   SCIP_Real             right               /**< right bound of open interval in hole */
754  	   )
755  	{
756  	   assert(event != NULL);
757  	   assert(blkmem != NULL);
758  	
759  	   /* create event data */
760  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
761  	   (*event)->eventtype = SCIP_EVENTTYPE_GHOLEREMOVED;
762  	   (*event)->data.eventhole.var = var;
763  	   (*event)->data.eventhole.left = left;
764  	   (*event)->data.eventhole.right = right;
765  	
766  	   return SCIP_OKAY;
767  	}
768  	
769  	/** creates an event for an addition of a domain hole to a variable */
770  	SCIP_RETCODE SCIPeventCreateLholeAdded(
771  	   SCIP_EVENT**          event,              /**< pointer to store the event */
772  	   BMS_BLKMEM*           blkmem,             /**< block memory */
773  	   SCIP_VAR*             var,                /**< variable whose bound changed */
774  	   SCIP_Real             left,               /**< left bound of open interval in new hole */
775  	   SCIP_Real             right               /**< right bound of open interval in new hole */
776  	   )
777  	{
778  	   assert(event != NULL);
779  	   assert(blkmem != NULL);
780  	
781  	   /* create event data */
782  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
783  	   (*event)->eventtype = SCIP_EVENTTYPE_LHOLEADDED;
784  	   (*event)->data.eventhole.var = var;
785  	   (*event)->data.eventhole.left = left;
786  	   (*event)->data.eventhole.right = right;
787  	
788  	   return SCIP_OKAY;
789  	}
790  	
791  	/** creates an event for removing a domain hole of a variable */
792  	SCIP_RETCODE SCIPeventCreateLholeRemoved(
793  	   SCIP_EVENT**          event,              /**< pointer to store the event */
794  	   BMS_BLKMEM*           blkmem,             /**< block memory */
795  	   SCIP_VAR*             var,                /**< variable whose bound changed */
796  	   SCIP_Real             left,               /**< left bound of open interval in hole */
797  	   SCIP_Real             right               /**< right bound of open interval in hole */
798  	   )
799  	{
800  	   assert(event != NULL);
801  	   assert(blkmem != NULL);
802  	
803  	   /* create event data */
804  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
805  	   (*event)->eventtype = SCIP_EVENTTYPE_LHOLEREMOVED;
806  	   (*event)->data.eventhole.var = var;
807  	   (*event)->data.eventhole.left = left;
808  	   (*event)->data.eventhole.right = right;
809  	
810  	   return SCIP_OKAY;
811  	}
812  	
813  	/** creates an event for an addition to the variable's implications list, clique or variable bounds information */
814  	SCIP_RETCODE SCIPeventCreateImplAdded(
815  	   SCIP_EVENT**          event,              /**< pointer to store the event */
816  	   BMS_BLKMEM*           blkmem,             /**< block memory */
817  	   SCIP_VAR*             var                 /**< variable that was fixed */
818  	   )
819  	{
820  	   assert(event != NULL);
821  	   assert(blkmem != NULL);
822  	   assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
823  	
824  	   /* create event data */
825  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
826  	   (*event)->eventtype = SCIP_EVENTTYPE_IMPLADDED;
827  	   (*event)->data.eventimpladd.var = var;
828  	
829  	   return SCIP_OKAY;
830  	}
831  	
832  	/** creates an event for a changeing the type of a variable */
833  	SCIP_RETCODE SCIPeventCreateTypeChanged(
834  	   SCIP_EVENT**          event,              /**< pointer to store the event */
835  	   BMS_BLKMEM*           blkmem,             /**< block memory */
836  	   SCIP_VAR*             var,                /**< variable whose objective value changed */
837  	   SCIP_VARTYPE          oldtype,            /**< old variable type */
838  	   SCIP_VARTYPE          newtype             /**< new variable type */
839  	   )
840  	{
841  	   assert(event != NULL);
842  	   assert(blkmem != NULL);
843  	   assert(oldtype != newtype);
844  	
845  	   /* create event data */
846  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
847  	   (*event)->eventtype = SCIP_EVENTTYPE_TYPECHANGED;
848  	   (*event)->data.eventtypechg.var = var;
849  	   (*event)->data.eventtypechg.oldtype = oldtype;
850  	   (*event)->data.eventtypechg.newtype = newtype;
851  	
852  	   return SCIP_OKAY;
853  	}
854  	
855  	/** creates an event for the addition of a linear row to the separation storage */
856  	SCIP_RETCODE SCIPeventCreateRowAddedSepa(
857  	   SCIP_EVENT**          event,              /**< pointer to store the event */
858  	   BMS_BLKMEM*           blkmem,             /**< block memory */
859  	   SCIP_ROW*             row                 /**< row that was added to the separation storage*/
860  	   )
861  	{
862  	   assert(event != NULL);
863  	   assert(blkmem != NULL);
864  	   assert(row != NULL);
865  	
866  	   /* create event data */
867  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
868  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWADDEDSEPA;
869  	   (*event)->data.eventrowaddedsepa.row = row;
870  	
871  	   return SCIP_OKAY;
872  	}
873  	
874  	/** creates an event for the deletion of a linear row from the separation storage */
875  	SCIP_RETCODE SCIPeventCreateRowDeletedSepa(
876  	   SCIP_EVENT**          event,              /**< pointer to store the event */
877  	   BMS_BLKMEM*           blkmem,             /**< block memory */
878  	   SCIP_ROW*             row                 /**< row that was deleted from the separation storage */
879  	   )
880  	{
881  	   assert(event != NULL);
882  	   assert(blkmem != NULL);
883  	   assert(row != NULL);
884  	
885  	   /* create event data */
886  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
887  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWDELETEDSEPA;
888  	   (*event)->data.eventrowdeletedsepa.row = row;
889  	
890  	   return SCIP_OKAY;
891  	}
892  	
893  	/** creates an event for the addition of a linear row to the LP */
894  	SCIP_RETCODE SCIPeventCreateRowAddedLP(
895  	   SCIP_EVENT**          event,              /**< pointer to store the event */
896  	   BMS_BLKMEM*           blkmem,             /**< block memory */
897  	   SCIP_ROW*             row                 /**< row that was added to the LP */
898  	   )
899  	{
900  	   assert(event != NULL);
901  	   assert(blkmem != NULL);
902  	   assert(row != NULL);
903  	
904  	   /* create event data */
905  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
906  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWADDEDLP;
907  	   (*event)->data.eventrowaddedlp.row = row;
908  	
909  	   return SCIP_OKAY;
910  	}
911  	
912  	/** creates an event for the deletion of a linear row from the LP */
913  	SCIP_RETCODE SCIPeventCreateRowDeletedLP(
914  	   SCIP_EVENT**          event,              /**< pointer to store the event */
915  	   BMS_BLKMEM*           blkmem,             /**< block memory */
916  	   SCIP_ROW*             row                 /**< row that was deleted from the LP */
917  	   )
918  	{
919  	   assert(event != NULL);
920  	   assert(blkmem != NULL);
921  	   assert(row != NULL);
922  	
923  	   /* create event data */
924  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
925  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWDELETEDLP;
926  	   (*event)->data.eventrowdeletedlp.row = row;
927  	
928  	   return SCIP_OKAY;
929  	}
930  	
931  	/** creates an event for the change of a coefficient in a linear row */
932  	SCIP_RETCODE SCIPeventCreateRowCoefChanged(
933  	   SCIP_EVENT**          event,              /**< pointer to store the event */
934  	   BMS_BLKMEM*           blkmem,             /**< block memory */
935  	   SCIP_ROW*             row,                /**< row in which a coefficient changed */
936  	   SCIP_COL*             col,                /**< column which coefficient changed */
937  	   SCIP_Real             oldval,             /**< old value of coefficient */
938  	   SCIP_Real             newval              /**< new value of coefficient */
939  	   )
940  	{
941  	   assert(event != NULL);
942  	   assert(blkmem != NULL);
943  	   assert(row != NULL);
944  	
945  	   /* create event data */
946  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
947  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWCOEFCHANGED;
948  	   (*event)->data.eventrowcoefchanged.row = row;
949  	   (*event)->data.eventrowcoefchanged.col = col;
950  	   (*event)->data.eventrowcoefchanged.oldval = oldval;
951  	   (*event)->data.eventrowcoefchanged.newval = newval;
952  	
953  	   return SCIP_OKAY;
954  	}
955  	
956  	/** creates an event for the change of a constant in a linear row */
957  	SCIP_RETCODE SCIPeventCreateRowConstChanged(
958  	   SCIP_EVENT**          event,              /**< pointer to store the event */
959  	   BMS_BLKMEM*           blkmem,             /**< block memory */
960  	   SCIP_ROW*             row,                /**< row in which the constant changed */
961  	   SCIP_Real             oldval,             /**< old value of constant */
962  	   SCIP_Real             newval              /**< new value of constant */
963  	   )
964  	{
965  	   assert(event != NULL);
966  	   assert(blkmem != NULL);
967  	   assert(row != NULL);
968  	
969  	   /* create event data */
970  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
971  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWCONSTCHANGED;
972  	   (*event)->data.eventrowconstchanged.row = row;
973  	   (*event)->data.eventrowconstchanged.oldval = oldval;
974  	   (*event)->data.eventrowconstchanged.newval = newval;
975  	
976  	   return SCIP_OKAY;
977  	}
978  	
979  	/** creates an event for the change of a side of a linear row */
980  	SCIP_RETCODE SCIPeventCreateRowSideChanged(
981  	   SCIP_EVENT**          event,              /**< pointer to store the event */
982  	   BMS_BLKMEM*           blkmem,             /**< block memory */
983  	   SCIP_ROW*             row,                /**< row which side has changed */
984  	   SCIP_SIDETYPE         side,               /**< which side has changed */
985  	   SCIP_Real             oldval,             /**< old value of side */
986  	   SCIP_Real             newval              /**< new value of side */
987  	   )
988  	{
989  	   assert(event != NULL);
990  	   assert(blkmem != NULL);
991  	   assert(row != NULL);
992  	
993  	   /* create event data */
994  	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, event) );
995  	   (*event)->eventtype = SCIP_EVENTTYPE_ROWSIDECHANGED;
996  	   (*event)->data.eventrowsidechanged.row = row;
997  	   (*event)->data.eventrowsidechanged.side = side;
998  	   (*event)->data.eventrowsidechanged.oldval = oldval;
999  	   (*event)->data.eventrowsidechanged.newval = newval;
1000 	
1001 	   return SCIP_OKAY;
1002 	}
1003 	
1004 	/** frees an event */
1005 	SCIP_RETCODE SCIPeventFree(
1006 	   SCIP_EVENT**          event,              /**< event to free */
1007 	   BMS_BLKMEM*           blkmem              /**< block memory buffer */
1008 	   )
1009 	{
1010 	   assert(event != NULL);
1011 	   assert(blkmem != NULL);
1012 	
1013 	   BMSfreeBlockMemory(blkmem, event);
1014 	
1015 	   return SCIP_OKAY;
1016 	}
1017 	
1018 	/** disables an event */
1019 	static
1020 	void eventDisable(
1021 	   SCIP_EVENT*           event               /**< event to disable */
1022 	   )
1023 	{
1024 	   assert(event != NULL);
1025 	
1026 	   event->eventtype = SCIP_EVENTTYPE_DISABLED;
1027 	}
1028 	
1029 	/** gets type of event */
1030 	SCIP_EVENTTYPE SCIPeventGetType(
1031 	   SCIP_EVENT*           event               /**< event */
1032 	   )
1033 	{
1034 	   assert(event != NULL);
1035 	
1036 	   return event->eventtype;
1037 	}
1038 	
1039 	/** sets type of event */
1040 	SCIP_RETCODE SCIPeventChgType(
1041 	   SCIP_EVENT*           event,              /**< event */
1042 	   SCIP_EVENTTYPE        eventtype           /**< new event type */
1043 	   )
1044 	{
1045 	   assert(event != NULL);
1046 	
1047 	   event->eventtype = eventtype;
1048 	
1049 	   return SCIP_OKAY;
1050 	}
1051 	
1052 	/** gets variable for a variable event (var added, var deleted, var fixed, objective value or domain change) */
1053 	SCIP_VAR* SCIPeventGetVar(
1054 	   SCIP_EVENT*           event               /**< event */
1055 	   )
1056 	{
1057 	   assert(event != NULL);
1058 	
1059 	   switch( event->eventtype )
1060 	   {  
1061 	   case SCIP_EVENTTYPE_VARADDED:
1062 	      assert(event->data.eventvaradded.var != NULL);
1063 	      return event->data.eventvaradded.var;
1064 	
1065 	   case SCIP_EVENTTYPE_VARDELETED:
1066 	      assert(event->data.eventvardeleted.var != NULL);
1067 	      return event->data.eventvardeleted.var;
1068 	
1069 	   case SCIP_EVENTTYPE_VARFIXED:
1070 	      assert(event->data.eventvarfixed.var != NULL);
1071 	      return event->data.eventvarfixed.var;
1072 	
1073 	   case SCIP_EVENTTYPE_VARUNLOCKED:
1074 	      assert(event->data.eventvarunlocked.var != NULL);
1075 	      return event->data.eventvarunlocked.var;
1076 	
1077 	   case SCIP_EVENTTYPE_OBJCHANGED:
1078 	      assert(event->data.eventobjchg.var != NULL);
1079 	      return event->data.eventobjchg.var;
1080 	
1081 	   case SCIP_EVENTTYPE_GLBCHANGED:
1082 	   case SCIP_EVENTTYPE_GUBCHANGED:
1083 	   case SCIP_EVENTTYPE_LBTIGHTENED:
1084 	   case SCIP_EVENTTYPE_LBRELAXED:
1085 	   case SCIP_EVENTTYPE_UBTIGHTENED:
1086 	   case SCIP_EVENTTYPE_UBRELAXED:
1087 	      assert(event->data.eventbdchg.var != NULL);
1088 	      return event->data.eventbdchg.var;
1089 	
1090 	   case SCIP_EVENTTYPE_GHOLEADDED:
1091 	   case SCIP_EVENTTYPE_GHOLEREMOVED:
1092 	   case SCIP_EVENTTYPE_LHOLEADDED:
1093 	   case SCIP_EVENTTYPE_LHOLEREMOVED:
1094 	      assert(event->data.eventhole.var != NULL);
1095 	      return event->data.eventhole.var;
1096 	
1097 	   case SCIP_EVENTTYPE_IMPLADDED:
1098 	      assert(event->data.eventimpladd.var != NULL);
1099 	      return event->data.eventimpladd.var;
1100 	
1101 	   case SCIP_EVENTTYPE_TYPECHANGED:
1102 	      assert(event->data.eventtypechg.var != NULL);
1103 	      return event->data.eventtypechg.var;
1104 	
1105 	   default:
1106 	      SCIPerrorMessage("event does not belong to a variable\n");
1107 	      SCIPABORT();
1108 	      return NULL; /*lint !e527*/
1109 	   }  /*lint !e788*/
1110 	}
1111 	
1112 	/** sets variable for a variable event */
1113 	SCIP_RETCODE SCIPeventChgVar(
1114 	   SCIP_EVENT*           event,              /**< event */
1115 	   SCIP_VAR*             var                 /**< new variable */
1116 	   )
1117 	{
1118 	   assert(event != NULL);
1119 	
1120 	   switch( event->eventtype )
1121 	   {  
1122 	   case SCIP_EVENTTYPE_VARADDED:
1123 	      assert(event->data.eventvaradded.var != NULL);
1124 	      event->data.eventvaradded.var = var;
1125 	      break;
1126 	
1127 	   case SCIP_EVENTTYPE_VARDELETED:
1128 	      assert(event->data.eventvardeleted.var != NULL);
1129 	      event->data.eventvardeleted.var = var;
1130 	      break;
1131 	
1132 	   case SCIP_EVENTTYPE_VARFIXED:
1133 	      assert(event->data.eventvarfixed.var != NULL);
1134 	      event->data.eventvarfixed.var = var;
1135 	      break;
1136 	
1137 	   case SCIP_EVENTTYPE_VARUNLOCKED:
1138 	      assert(event->data.eventvarunlocked.var != NULL);
1139 	      event->data.eventvarunlocked.var = var;
1140 	      break;
1141 	
1142 	   case SCIP_EVENTTYPE_OBJCHANGED:
1143 	      assert(event->data.eventobjchg.var != NULL);
1144 	      event->data.eventobjchg.var = var;
1145 	      break;
1146 	
1147 	   case SCIP_EVENTTYPE_GLBCHANGED:
1148 	   case SCIP_EVENTTYPE_GUBCHANGED:
1149 	   case SCIP_EVENTTYPE_LBTIGHTENED:
1150 	   case SCIP_EVENTTYPE_LBRELAXED:
1151 	   case SCIP_EVENTTYPE_UBTIGHTENED:
1152 	   case SCIP_EVENTTYPE_UBRELAXED:
1153 	      assert(event->data.eventbdchg.var != NULL);
1154 	      event->data.eventbdchg.var = var;
1155 	      break;
1156 	
1157 	   case SCIP_EVENTTYPE_GHOLEADDED:
1158 	   case SCIP_EVENTTYPE_GHOLEREMOVED:
1159 	   case SCIP_EVENTTYPE_LHOLEADDED:
1160 	   case SCIP_EVENTTYPE_LHOLEREMOVED:
1161 	      assert(event->data.eventhole.var != NULL);
1162 	      event->data.eventhole.var = var;
1163 	      break;
1164 	
1165 	   case SCIP_EVENTTYPE_IMPLADDED:
1166 	      assert(event->data.eventimpladd.var != NULL);
1167 	      event->data.eventimpladd.var = var;
1168 	      break;
1169 	
1170 	   case SCIP_EVENTTYPE_TYPECHANGED:
1171 	      assert(event->data.eventtypechg.var != NULL);
1172 	      event->data.eventtypechg.var = var;
1173 	      break;
1174 	
1175 	   default:
1176 	      SCIPerrorMessage("event does not belong to a variable\n");
1177 	      return SCIP_INVALIDDATA;
1178 	   }  /*lint !e788*/
1179 	
1180 	   return SCIP_OKAY;
1181 	}
1182 	
1183 	/** gets old objective value for an objective value change event */
1184 	SCIP_Real SCIPeventGetOldobj(
1185 	   SCIP_EVENT*           event               /**< event */
1186 	   )
1187 	{
1188 	   assert(event != NULL);
1189 	
1190 	   if( event->eventtype != SCIP_EVENTTYPE_OBJCHANGED )
1191 	   {
1192 	      SCIPerrorMessage("event is not an objective value change event\n");
1193 	      SCIPABORT();
1194 	      return SCIP_INVALID;  /*lint !e527*/
1195 	   }
1196 	
1197 	   return event->data.eventobjchg.oldobj;
1198 	}
1199 	
1200 	/** gets new objective value for an objective value change event */
1201 	SCIP_Real SCIPeventGetNewobj(
1202 	   SCIP_EVENT*           event               /**< event */
1203 	   )
1204 	{
1205 	   assert(event != NULL);
1206 	
1207 	   if( event->eventtype != SCIP_EVENTTYPE_OBJCHANGED )
1208 	   {
1209 	      SCIPerrorMessage("event is not an objective value change event\n");
1210 	      SCIPABORT();
1211 	      return SCIP_INVALID;  /*lint !e527*/
1212 	   }
1213 	
1214 	   return event->data.eventobjchg.newobj;
1215 	}
1216 	
1217 	/** gets old bound for a bound change event */
1218 	SCIP_Real SCIPeventGetOldbound(
1219 	   SCIP_EVENT*           event               /**< event */
1220 	   )
1221 	{
1222 	   assert(event != NULL);
1223 	
1224 	   switch( event->eventtype )
1225 	   {  
1226 	   case SCIP_EVENTTYPE_GLBCHANGED:
1227 	   case SCIP_EVENTTYPE_GUBCHANGED:
1228 	   case SCIP_EVENTTYPE_LBTIGHTENED:
1229 	   case SCIP_EVENTTYPE_LBRELAXED:
1230 	   case SCIP_EVENTTYPE_UBTIGHTENED:
1231 	   case SCIP_EVENTTYPE_UBRELAXED:
1232 	      return event->data.eventbdchg.oldbound;
1233 	
1234 	   default:
1235 	      SCIPerrorMessage("event is not a bound change event\n");
1236 	      SCIPABORT();
1237 	      return 0.0; /*lint !e527*/
1238 	   }  /*lint !e788*/
1239 	}
1240 	
1241 	/** gets new bound for a bound change event */
1242 	SCIP_Real SCIPeventGetNewbound(
1243 	   SCIP_EVENT*           event               /**< event */
1244 	   )
1245 	{
1246 	   assert(event != NULL);
1247 	
1248 	   switch( event->eventtype )
1249 	   {  
1250 	   case SCIP_EVENTTYPE_GLBCHANGED:
1251 	   case SCIP_EVENTTYPE_GUBCHANGED:
1252 	   case SCIP_EVENTTYPE_LBTIGHTENED:
1253 	   case SCIP_EVENTTYPE_LBRELAXED:
1254 	   case SCIP_EVENTTYPE_UBTIGHTENED:
1255 	   case SCIP_EVENTTYPE_UBRELAXED:
1256 	      return event->data.eventbdchg.newbound;
1257 	
1258 	   default:
1259 	      SCIPerrorMessage("event is not a bound change event\n");
1260 	      SCIPABORT();
1261 	      return 0.0; /*lint !e527*/
1262 	   }  /*lint !e788*/
1263 	}
1264 	
1265 	/** gets old variable type for a variable type change event */
1266 	SCIP_VARTYPE SCIPeventGetOldtype(
1267 	   SCIP_EVENT*           event               /**< event */
1268 	   )
1269 	{
1270 	   assert(event != NULL);
1271 	
1272 	   if( event->eventtype != SCIP_EVENTTYPE_TYPECHANGED )
1273 	   {
1274 	      SCIPerrorMessage("event is not an variable type change event\n");
1275 	      SCIPABORT();
1276 	      return SCIP_VARTYPE_CONTINUOUS;  /*lint !e527*/
1277 	   }
1278 	
1279 	   return event->data.eventtypechg.oldtype;
1280 	}
1281 	
1282 	/** gets new variable type for a variable type change event */
1283 	SCIP_VARTYPE SCIPeventGetNewtype(
1284 	   SCIP_EVENT*           event               /**< event */
1285 	   )
1286 	{
1287 	   assert(event != NULL);
1288 	
1289 	   if( event->eventtype != SCIP_EVENTTYPE_TYPECHANGED )
1290 	   {
1291 	      SCIPerrorMessage("event is not an variable type change event\n");
1292 	      SCIPABORT();
1293 	      return SCIP_VARTYPE_CONTINUOUS;  /*lint !e527*/
1294 	   }
1295 	
1296 	   return event->data.eventtypechg.newtype;
1297 	}
1298 	
1299 	/** gets node for a node or LP event */
1300 	SCIP_NODE* SCIPeventGetNode(
1301 	   SCIP_EVENT*           event               /**< event */
1302 	   )
1303 	{
1304 	   assert(event != NULL);
1305 	
1306 	   if( (event->eventtype & (SCIP_EVENTTYPE_NODEEVENT | SCIP_EVENTTYPE_NODEDELETE | SCIP_EVENTTYPE_LPEVENT)) == 0 )
1307 	   {
1308 	      SCIPerrorMessage("event is neither node nor LP event\n");
1309 	      SCIPABORT();
1310 	      return NULL;  /*lint !e527*/
1311 	   }
1312 	
1313 	   return event->data.node;
1314 	}
1315 	
1316 	/** sets node for a node or LP event */
1317 	SCIP_RETCODE SCIPeventChgNode(
1318 	   SCIP_EVENT*           event,              /**< event */
1319 	   SCIP_NODE*            node                /**< new node */
1320 	   )
1321 	{
1322 	   assert(event != NULL);
1323 	
1324 	   if( (event->eventtype & (SCIP_EVENTTYPE_NODEEVENT |  SCIP_EVENTTYPE_NODEDELETE | SCIP_EVENTTYPE_LPEVENT)) == 0 )
1325 	   {
1326 	      SCIPerrorMessage("event is neither node nor LP event\n");
1327 	      SCIPABORT();
1328 	      return SCIP_INVALIDDATA;  /*lint !e527*/
1329 	   }
1330 	
1331 	   event->data.node = node;
1332 	
1333 	   return SCIP_OKAY;
1334 	}
1335 	
1336 	/** gets solution for a primal solution event */
1337 	SCIP_SOL* SCIPeventGetSol(
1338 	   SCIP_EVENT*           event               /**< event */
1339 	   )
1340 	{
1341 	   assert(event != NULL);
1342 	
1343 	   if( (event->eventtype & SCIP_EVENTTYPE_SOLEVENT) == 0 )
1344 	   {
1345 	      SCIPerrorMessage("event is not a primal solution event\n");
1346 	      SCIPABORT();
1347 	      return NULL;  /*lint !e527*/
1348 	   }
1349 	
1350 	   return event->data.sol;
1351 	}
1352 	
1353 	/** sets solution for a primal solution event */
1354 	SCIP_RETCODE SCIPeventChgSol(
1355 	   SCIP_EVENT*           event,              /**< event */
1356 	   SCIP_SOL*             sol                 /**< new primal solution */
1357 	   )
1358 	{
1359 	   assert(event != NULL);
1360 	
1361 	   if( (event->eventtype & SCIP_EVENTTYPE_SOLEVENT) == 0 )
1362 	   {
1363 	      SCIPerrorMessage("event is not a primal solution event\n");
1364 	      SCIPABORT();
1365 	      return SCIP_INVALIDDATA;  /*lint !e527*/
1366 	   }
1367 	
1368 	   event->data.sol = sol;
1369 	
1370 	   return SCIP_OKAY;
1371 	}
1372 	
1373 	/** gets the left bound of open interval in the hole */
1374 	SCIP_Real SCIPeventGetHoleLeft(
1375 	   SCIP_EVENT*           event               /**< event */
1376 	   )
1377 	{
1378 	   assert(event != NULL);
1379 	
1380 	   if( (event->eventtype & SCIP_EVENTTYPE_HOLECHANGED) == 0 )
1381 	   {
1382 	      SCIPerrorMessage("event is not a hole added or removed event\n");
1383 	      SCIPABORT();
1384 	      return SCIP_INVALID;  /*lint !e527*/
1385 	   }
1386 	
1387 	   return event->data.eventhole.left;
1388 	}
1389 	
1390 	/** gets the right bound of open interval in the hole */
1391 	SCIP_Real SCIPeventGetHoleRight(
1392 	   SCIP_EVENT*           event               /**< event */
1393 	   )
1394 	{
1395 	   assert(event != NULL);
1396 	
1397 	   if( (event->eventtype & SCIP_EVENTTYPE_HOLECHANGED) == 0 )
1398 	   {
1399 	      SCIPerrorMessage("event is not a hole added or removed event\n");
1400 	      SCIPABORT();
1401 	      return SCIP_INVALID;  /*lint !e527*/
1402 	   }
1403 	
1404 	   return event->data.eventhole.right;
1405 	}
1406 	
1407 	/** gets row for a row event */
1408 	SCIP_ROW* SCIPeventGetRow(
1409 	   SCIP_EVENT*           event               /**< event */
1410 	   )
1411 	{
1412 	   assert(event != NULL);
1413 	
1414 	   switch( event->eventtype )
1415 	   {
1416 	      case SCIP_EVENTTYPE_ROWADDEDSEPA:
1417 	         return event->data.eventrowaddedsepa.row;
1418 	      case SCIP_EVENTTYPE_ROWDELETEDSEPA:
1419 	         return event->data.eventrowdeletedsepa.row;
1420 	      case SCIP_EVENTTYPE_ROWADDEDLP:
1421 	         return event->data.eventrowaddedlp.row;
1422 	      case SCIP_EVENTTYPE_ROWDELETEDLP:
1423 	         return event->data.eventrowdeletedlp.row;
1424 	      case SCIP_EVENTTYPE_ROWCOEFCHANGED:
1425 	         return event->data.eventrowcoefchanged.row;
1426 	      case SCIP_EVENTTYPE_ROWCONSTCHANGED: /*lint !e30 !e142*/
1427 	         return event->data.eventrowconstchanged.row;
1428 	      case SCIP_EVENTTYPE_ROWSIDECHANGED: /*lint !e30 !e142*/
1429 	         return event->data.eventrowsidechanged.row;
1430 	      default:
1431 	         SCIPerrorMessage("event does not belong to a row\n");
1432 	         SCIPABORT();
1433 	         return NULL;  /*lint !e527*/
1434 	   }
1435 	}
1436 	
1437 	/** gets column for a row change coefficient event */
1438 	SCIP_COL* SCIPeventGetRowCol(
1439 	   SCIP_EVENT*           event               /**< event */
1440 	   )
1441 	{
1442 	   assert(event != NULL);
1443 	
1444 	   if( (event->eventtype & SCIP_EVENTTYPE_ROWCOEFCHANGED) == 0 )
1445 	   {
1446 	      SCIPerrorMessage("event is not a row coefficient changed event\n");
1447 	      SCIPABORT();
1448 	      return NULL;  /*lint !e527*/
1449 	   }
1450 	
1451 	   return event->data.eventrowcoefchanged.col;
1452 	}
1453 	
1454 	/** gets old coefficient value for a row change coefficient event */
1455 	SCIP_Real SCIPeventGetRowOldCoefVal(
1456 	   SCIP_EVENT*           event               /**< event */
1457 	   )
1458 	{
1459 	   assert(event != NULL);
1460 	
1461 	   if( (event->eventtype & SCIP_EVENTTYPE_ROWCOEFCHANGED) == 0 )
1462 	   {
1463 	      SCIPerrorMessage("event is not a row coefficient changed event\n");
1464 	      SCIPABORT();
1465 	      return SCIP_INVALID;  /*lint !e527*/
1466 	   }
1467 	
1468 	   return event->data.eventrowcoefchanged.oldval;
1469 	}
1470 	
1471 	/** gets new coefficient value for a row change coefficient event */
1472 	SCIP_Real SCIPeventGetRowNewCoefVal(
1473 	   SCIP_EVENT*           event               /**< event */
1474 	   )
1475 	{
1476 	   assert(event != NULL);
1477 	
1478 	   if( (event->eventtype & SCIP_EVENTTYPE_ROWCOEFCHANGED) == 0 )
1479 	   {
1480 	      SCIPerrorMessage("event is not a row coefficient changed event\n");
1481 	      SCIPABORT();
1482 	      return SCIP_INVALID;  /*lint !e527*/
1483 	   }
1484 	
1485 	   return event->data.eventrowcoefchanged.newval;
1486 	}
1487 	
1488 	/** gets old constant value for a row change constant event */
1489 	SCIP_Real SCIPeventGetRowOldConstVal(
1490 	   SCIP_EVENT*           event               /**< event */
1491 	   )
1492 	{
1493 	   assert(event != NULL);
1494 	
1495 	   if( !(event->eventtype & SCIP_EVENTTYPE_ROWCONSTCHANGED) )
1496 	   {
1497 	      SCIPerrorMessage("event is not a row coefficient changed event\n");
1498 	      SCIPABORT();
1499 	      return SCIP_INVALID;  /*lint !e527*/
1500 	   }
1501 	
1502 	   return event->data.eventrowconstchanged.oldval;
1503 	}
1504 	
1505 	/** gets new constant value for a row change constant event */
1506 	SCIP_Real SCIPeventGetRowNewConstVal(
1507 	   SCIP_EVENT*           event               /**< event */
1508 	   )
1509 	{
1510 	   assert(event != NULL);
1511 	
1512 	   if( !(event->eventtype & SCIP_EVENTTYPE_ROWCONSTCHANGED) )
1513 	   {
1514 	      SCIPerrorMessage("event is not a row coefficient changed event\n");
1515 	      SCIPABORT();
1516 	      return SCIP_INVALID;  /*lint !e527*/
1517 	   }
1518 	
1519 	   return event->data.eventrowconstchanged.newval;
1520 	}
1521 	
1522 	/** gets side for a row change side event */
1523 	SCIP_SIDETYPE SCIPeventGetRowSide(
1524 	   SCIP_EVENT*           event               /**< event */
1525 	   )
1526 	{
1527 	   assert(event != NULL);
1528 	
1529 	   if( !(event->eventtype & SCIP_EVENTTYPE_ROWSIDECHANGED) )
1530 	   {
1531 	      SCIPerrorMessage("event is not a row side changed event\n");
1532 	      SCIPABORT();
1533 	      return SCIP_SIDETYPE_LEFT;  /*lint !e527*/
1534 	   }
1535 	
1536 	   return event->data.eventrowsidechanged.side;
1537 	}
1538 	
1539 	/** gets old side value for a row change side event */
1540 	SCIP_Real SCIPeventGetRowOldSideVal(
1541 	   SCIP_EVENT*           event               /**< event */
1542 	   )
1543 	{
1544 	   assert(event != NULL);
1545 	
1546 	   if( !(event->eventtype & SCIP_EVENTTYPE_ROWSIDECHANGED) )
1547 	   {
1548 	      SCIPerrorMessage("event is not a row side changed event\n");
1549 	      SCIPABORT();
1550 	      return SCIP_INVALID;  /*lint !e527*/
1551 	   }
1552 	
1553 	   return event->data.eventrowsidechanged.oldval;
1554 	}
1555 	
1556 	/** gets new side value for a row change side event */
1557 	SCIP_Real SCIPeventGetRowNewSideVal(
1558 	   SCIP_EVENT*           event               /**< event */
1559 	   )
1560 	{
1561 	   assert(event != NULL);
1562 	
1563 	   if( !(event->eventtype & SCIP_EVENTTYPE_ROWSIDECHANGED) )
1564 	   {
1565 	      SCIPerrorMessage("event is not a row side changed event\n");
1566 	      SCIPABORT();
1567 	      return SCIP_INVALID;  /*lint !e527*/
1568 	   }
1569 	
1570 	   return event->data.eventrowsidechanged.newval;
1571 	}
1572 	
1573 	/** processes event by calling the appropriate event handlers */
1574 	SCIP_RETCODE SCIPeventProcess(
1575 	   SCIP_EVENT*           event,              /**< event */
1576 	   SCIP_SET*             set,                /**< global SCIP settings */
1577 	   SCIP_PRIMAL*          primal,             /**< primal data; only needed for objchanged events, or NULL */
1578 	   SCIP_LP*              lp,                 /**< current LP data; only needed for obj/boundchanged events, or NULL */
1579 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage; only needed for bound change events, or NULL */
1580 	   SCIP_EVENTFILTER*     eventfilter         /**< event filter for global events; not needed for variable specific events */
1581 	   )
1582 	{
1583 	   SCIP_VAR* var;
1584 	
1585 	   assert(event != NULL);
1586 	   assert((event->eventtype & SCIP_EVENTTYPE_OBJCHANGED) == 0 || primal != NULL);
1587 	   assert((event->eventtype & (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_OBJCHANGED)) == 0 || lp != NULL);
1588 	   assert((event->eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) == 0 || branchcand != NULL);
1589 	
1590 	   SCIPsetDebugMsg(set, "processing event of type 0x%" SCIP_EVENTTYPE_FORMAT "\n", event->eventtype);
1591 	
1592 	   switch( event->eventtype )
1593 	   {
1594 	   case SCIP_EVENTTYPE_DISABLED:
1595 	      break;
1596 	
1597 	   case SCIP_EVENTTYPE_VARADDED:
1598 	   case SCIP_EVENTTYPE_PRESOLVEROUND:
1599 	   case SCIP_EVENTTYPE_NODEFOCUSED:
1600 	   case SCIP_EVENTTYPE_NODEFEASIBLE:
1601 	   case SCIP_EVENTTYPE_NODEINFEASIBLE:
1602 	   case SCIP_EVENTTYPE_NODEBRANCHED:
1603 	   case SCIP_EVENTTYPE_NODEDELETE:
1604 	   case SCIP_EVENTTYPE_FIRSTLPSOLVED:
1605 	   case SCIP_EVENTTYPE_LPSOLVED:
1606 	   case SCIP_EVENTTYPE_POORSOLFOUND:
1607 	   case SCIP_EVENTTYPE_BESTSOLFOUND:
1608 	   case SCIP_EVENTTYPE_ROWADDEDSEPA:
1609 	   case SCIP_EVENTTYPE_ROWDELETEDSEPA:
1610 	   case SCIP_EVENTTYPE_ROWADDEDLP:
1611 	   case SCIP_EVENTTYPE_ROWDELETEDLP:
1612 	   case SCIP_EVENTTYPE_ROWCOEFCHANGED:
1613 	   case SCIP_EVENTTYPE_ROWCONSTCHANGED: /*lint !e30 !e142*/
1614 	   case SCIP_EVENTTYPE_ROWSIDECHANGED: /*lint !e30 !e142*/
1615 	   case SCIP_EVENTTYPE_SYNC: /*lint !e30 !e142*/
1616 	      SCIP_CALL( SCIPeventfilterProcess(eventfilter, set, event) );
1617 	      break;
1618 	
1619 	   case SCIP_EVENTTYPE_VARDELETED:
1620 	      var = event->data.eventvardeleted.var;
1621 	      assert(var != NULL);
1622 	
1623 	      /* process variable's event filter */
1624 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1625 	      break;
1626 	
1627 	   case SCIP_EVENTTYPE_VARFIXED:
1628 	      var = event->data.eventvarfixed.var;
1629 	      assert(var != NULL);
1630 	
1631 	      /* process variable's event filter */
1632 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1633 	      break;
1634 	
1635 	   case SCIP_EVENTTYPE_VARUNLOCKED:
1636 	      var = event->data.eventvarunlocked.var;
1637 	      assert(var != NULL);
1638 	
1639 	      /* process variable's event filter */
1640 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1641 	      break;
1642 	
1643 	   case SCIP_EVENTTYPE_OBJCHANGED:
1644 	      var = event->data.eventobjchg.var;
1645 	      assert(var != NULL);
1646 	      assert(var->eventqueueindexobj == -1);
1647 	      assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
1648 	
1649 	      /* inform LP about the objective change */
1650 	      if( SCIPvarGetProbindex(var) >= 0 )
1651 	      {
1652 	         if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
1653 	         {
1654 	            SCIP_CALL( SCIPcolChgObj(SCIPvarGetCol(var), set, lp, event->data.eventobjchg.newobj) );
1655 	         }
1656 	         SCIP_CALL( SCIPlpUpdateVarObj(lp, set, var, event->data.eventobjchg.oldobj, event->data.eventobjchg.newobj) );
1657 	      }
1658 	
1659 	      /* inform all existing primal solutions about the objective change (only if this is not a temporary change in
1660 	       * probing mode)
1661 	       */
1662 	      if( ! lp->divingobjchg )
1663 	      {
1664 	         SCIPprimalUpdateVarObj(primal, var, event->data.eventobjchg.oldobj, event->data.eventobjchg.newobj);
1665 	      }
1666 	
1667 	      /* process variable's event filter */
1668 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1669 	      break;
1670 	
1671 	   case SCIP_EVENTTYPE_GLBCHANGED:
1672 	      var = event->data.eventbdchg.var;
1673 	      assert(var != NULL);
1674 	
1675 	      /* inform LP about global bound change */
1676 	      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
1677 	      {
1678 	         assert(SCIPvarGetProbindex(var) >= 0);
1679 	         SCIP_CALL( SCIPlpUpdateVarLbGlobal(lp, set, var, event->data.eventbdchg.oldbound,
1680 	               event->data.eventbdchg.newbound) );
1681 	      }
1682 	
1683 	      /* process variable's event filter */
1684 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1685 	      break;
1686 	
1687 	   case SCIP_EVENTTYPE_GUBCHANGED:
1688 	      var = event->data.eventbdchg.var;
1689 	      assert(var != NULL);
1690 	
1691 	      /* inform LP about global bound change */
1692 	      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
1693 	      {
1694 	         assert(SCIPvarGetProbindex(var) >= 0);
1695 	         SCIP_CALL( SCIPlpUpdateVarUbGlobal(lp, set, var, event->data.eventbdchg.oldbound,
1696 	               event->data.eventbdchg.newbound) );
1697 	      }
1698 	
1699 	      /* process variable's event filter */
1700 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1701 	      break;
1702 	
1703 	   case SCIP_EVENTTYPE_LBTIGHTENED:
1704 	   case SCIP_EVENTTYPE_LBRELAXED:
1705 	      var = event->data.eventbdchg.var;
1706 	      assert(var != NULL);
1707 	      assert(var->eventqueueindexlb == -1);
1708 	
1709 	      /* inform LP about bound change and update branching candidates */
1710 	      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
1711 	      {
1712 	         assert(SCIPvarGetProbindex(var) >= 0);
1713 	         if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
1714 	         {
1715 	            SCIP_CALL( SCIPcolChgLb(SCIPvarGetCol(var), set, lp, event->data.eventbdchg.newbound) );
1716 	         }
1717 	         SCIP_CALL( SCIPlpUpdateVarLb(lp, set, var, event->data.eventbdchg.oldbound,
1718 	               event->data.eventbdchg.newbound) );
1719 	         SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1720 	      }
1721 	
1722 	      /* process variable's event filter */
1723 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1724 	      break;
1725 	
1726 	   case SCIP_EVENTTYPE_UBTIGHTENED:
1727 	   case SCIP_EVENTTYPE_UBRELAXED:
1728 	      var = event->data.eventbdchg.var;
1729 	      assert(var != NULL);
1730 	      assert(var->eventqueueindexub == -1);
1731 	
1732 	      /* inform LP about bound change and update branching candidates */
1733 	      if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE )
1734 	      {
1735 	         assert(SCIPvarGetProbindex(var) >= 0);
1736 	         if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN )
1737 	         {
1738 	            SCIP_CALL( SCIPcolChgUb(SCIPvarGetCol(var), set, lp, event->data.eventbdchg.newbound) );
1739 	         }
1740 	         SCIP_CALL( SCIPlpUpdateVarUb(lp, set, var, event->data.eventbdchg.oldbound, 
1741 	               event->data.eventbdchg.newbound) );
1742 	         SCIP_CALL( SCIPbranchcandUpdateVar(branchcand, set, var) );
1743 	      }
1744 	
1745 	      /* process variable's event filter */
1746 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1747 	      break;
1748 	
1749 	   case SCIP_EVENTTYPE_GHOLEADDED:
1750 	   case SCIP_EVENTTYPE_GHOLEREMOVED:
1751 	   case SCIP_EVENTTYPE_LHOLEADDED:
1752 	   case SCIP_EVENTTYPE_LHOLEREMOVED:
1753 	      var = event->data.eventhole.var;
1754 	      assert(var != NULL);
1755 	
1756 	      /* process variable's event filter */
1757 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1758 	      break;
1759 	
1760 	   case SCIP_EVENTTYPE_IMPLADDED:
1761 	      var = event->data.eventimpladd.var;
1762 	      assert(var != NULL);
1763 	      assert(!var->eventqueueimpl);
1764 	
1765 	      /* process variable's event filter */
1766 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1767 	      break;
1768 	
1769 	   case SCIP_EVENTTYPE_TYPECHANGED:
1770 	      var = event->data.eventtypechg.var;
1771 	      assert(var != NULL);
1772 	
1773 	      /* process variable's event filter */
1774 	      SCIP_CALL( SCIPeventfilterProcess(var->eventfilter, set, event) );
1775 	      break;
1776 	
1777 	   default:
1778 	      SCIPerrorMessage("unknown event type <%" SCIP_EVENTTYPE_FORMAT ">\n", event->eventtype);
1779 	      return SCIP_INVALIDDATA;
1780 	   }
1781 	
1782 	   return SCIP_OKAY;
1783 	}
1784 	
1785 	
1786 	
1787 	/*
1788 	 * Event filter methods
1789 	 */
1790 	
1791 	/** resizes eventfilter arrays to be able to store at least num entries */
1792 	static
1793 	SCIP_RETCODE eventfilterEnsureMem(
1794 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter */
1795 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
1796 	   SCIP_SET*             set,                /**< global SCIP settings */
1797 	   int                   num                 /**< minimal number of node slots in array */
1798 	   )
1799 	{
1800 	   assert(eventfilter != NULL);
1801 	   assert(blkmem != NULL);
1802 	   assert(set != NULL);
1803 	
1804 	   if( num > eventfilter->size )
1805 	   {
1806 	      int newsize;
1807 	
1808 	      newsize = SCIPsetCalcMemGrowSize(set, num);
1809 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &eventfilter->eventtypes, eventfilter->size, newsize) );
1810 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &eventfilter->eventhdlrs, eventfilter->size, newsize) );
1811 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &eventfilter->eventdata, eventfilter->size, newsize) );
1812 	      SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &eventfilter->nextpos, eventfilter->size, newsize) );
1813 	      eventfilter->size = newsize;
1814 	   }
1815 	   assert(num <= eventfilter->size);
1816 	
1817 	   return SCIP_OKAY;
1818 	}
1819 	
1820 	/** creates an event filter */
1821 	SCIP_RETCODE SCIPeventfilterCreate(
1822 	   SCIP_EVENTFILTER**    eventfilter,        /**< pointer to store the event filter */
1823 	   BMS_BLKMEM*           blkmem              /**< block memory buffer */
1824 	   )
1825 	{
1826 	   assert(eventfilter != NULL);
1827 	   assert(blkmem != NULL);
1828 	
1829 	   SCIP_ALLOC( BMSallocBlockMemory(blkmem, eventfilter) );
1830 	   (*eventfilter)->eventtypes = NULL;
1831 	   (*eventfilter)->eventhdlrs = NULL;
1832 	   (*eventfilter)->eventdata = NULL;
1833 	   (*eventfilter)->nextpos = NULL;
1834 	   (*eventfilter)->size = 0;
1835 	   (*eventfilter)->len = 0;
1836 	   (*eventfilter)->firstfreepos = -1;
1837 	   (*eventfilter)->firstdeletedpos = -1;
1838 	   (*eventfilter)->eventmask = SCIP_EVENTTYPE_DISABLED;
1839 	   (*eventfilter)->delayedeventmask = SCIP_EVENTTYPE_DISABLED;
1840 	   (*eventfilter)->delayupdates = FALSE;
1841 	
1842 	   return SCIP_OKAY;
1843 	}
1844 	
1845 	/** frees an event filter and the associated event data entries */
1846 	SCIP_RETCODE SCIPeventfilterFree(
1847 	   SCIP_EVENTFILTER**    eventfilter,        /**< pointer to store the event filter */
1848 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
1849 	   SCIP_SET*             set                 /**< global SCIP settings */
1850 	   )
1851 	{
1852 	   int i;
1853 	
1854 	   assert(eventfilter != NULL);
1855 	   assert(*eventfilter != NULL);
1856 	   assert(!(*eventfilter)->delayupdates);
1857 	   assert(blkmem != NULL);
1858 	   assert(set != NULL);
1859 	   assert(set->scip != NULL);
1860 	
1861 	   /* free event data */
1862 	   for( i = 0; i < (*eventfilter)->len; ++i )
1863 	   {
1864 	      if( (*eventfilter)->eventtypes[i] != SCIP_EVENTTYPE_DISABLED )
1865 	      {
1866 	         assert((*eventfilter)->eventhdlrs[i] != NULL);
1867 	         if( (*eventfilter)->eventhdlrs[i]->eventdelete != NULL )
1868 	         {
1869 	            SCIP_CALL( (*eventfilter)->eventhdlrs[i]->eventdelete(set->scip, (*eventfilter)->eventhdlrs[i],
1870 	                  &(*eventfilter)->eventdata[i]) );
1871 	         }
1872 	      }
1873 	   }
1874 	
1875 	   /* free event filter data */
1876 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*eventfilter)->eventtypes, (*eventfilter)->size);
1877 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*eventfilter)->eventhdlrs, (*eventfilter)->size);
1878 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*eventfilter)->eventdata, (*eventfilter)->size);
1879 	   BMSfreeBlockMemoryArrayNull(blkmem, &(*eventfilter)->nextpos, (*eventfilter)->size);
1880 	   BMSfreeBlockMemory(blkmem, eventfilter);
1881 	
1882 	   return SCIP_OKAY;
1883 	}
1884 	
1885 	/** adds element to event filter */
1886 	SCIP_RETCODE SCIPeventfilterAdd(
1887 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter */
1888 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
1889 	   SCIP_SET*             set,                /**< global SCIP settings */
1890 	   SCIP_EVENTTYPE        eventtype,          /**< event type to catch */
1891 	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
1892 	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
1893 	   int*                  filterpos           /**< pointer to store position of event filter entry, or NULL */
1894 	   )
1895 	{
1896 	   int pos;
1897 	
1898 	   assert(eventfilter != NULL);
1899 	   assert(blkmem != NULL);
1900 	   assert(set != NULL);
1901 	   assert(eventhdlr != NULL);
1902 	
1903 	   if( eventfilter->delayupdates )
1904 	   {
1905 	      /* insert addition to the end of the arrays;
1906 	       * in delayed addition we have to add to the end of the arrays, in order to not destroy the validity of the
1907 	       * arrays we are currently iterating over
1908 	       */
1909 	      SCIP_CALL( eventfilterEnsureMem(eventfilter, blkmem, set, eventfilter->len + 1) );
1910 	      pos = eventfilter->len;
1911 	      eventfilter->len++;
1912 	
1913 	      /* update delayed event filter mask */
1914 	      eventfilter->delayedeventmask |= eventtype;
1915 	   }
1916 	   else
1917 	   {
1918 	      if( eventfilter->firstfreepos == -1 )
1919 	      {
1920 	         /* insert addition to the end of the arrays */
1921 	         SCIP_CALL( eventfilterEnsureMem(eventfilter, blkmem, set, eventfilter->len + 1) );
1922 	         pos = eventfilter->len;
1923 	         eventfilter->len++;
1924 	      }
1925 	      else
1926 	      {
1927 	         /* use the first free slot to store the added event filter entry */
1928 	         pos = eventfilter->firstfreepos;
1929 	         assert(0 <= pos && pos < eventfilter->len);
1930 	         assert(eventfilter->eventtypes[pos] == SCIP_EVENTTYPE_DISABLED);
1931 	         eventfilter->firstfreepos = eventfilter->nextpos[pos];
1932 	         assert(-1 <= eventfilter->firstfreepos && eventfilter->firstfreepos < eventfilter->len);
1933 	      }
1934 	
1935 	      /* update event filter mask */
1936 	      eventfilter->eventmask |= eventtype;
1937 	   }
1938 	   assert(0 <= pos && pos < eventfilter->len);
1939 	
1940 	   eventfilter->eventtypes[pos] = eventtype;
1941 	   eventfilter->eventhdlrs[pos] = eventhdlr;
1942 	   eventfilter->eventdata[pos] = eventdata;
1943 	   eventfilter->nextpos[pos] = -2;
1944 	
1945 	   if( filterpos != NULL )
1946 	      *filterpos = pos;
1947 	
1948 	   return SCIP_OKAY;
1949 	}
1950 	
1951 	/** linear search for the given entry in event filter */
1952 	static
1953 	int eventfilterSearch(
1954 	   SCIP_EVENTFILTER*const eventfilter,       /**< event filter */
1955 	   SCIP_EVENTTYPE const  eventtype,          /**< event type */
1956 	   SCIP_EVENTHDLR*const  eventhdlr,          /**< event handler to call for the event processing */
1957 	   SCIP_EVENTDATA*const  eventdata           /**< event data to pass to the event handler for the event processing */
1958 	   )
1959 	{
1960 	   int i;
1961 	
1962 	   assert(eventfilter != NULL);
1963 	   assert(eventtype != SCIP_EVENTTYPE_DISABLED);
1964 	   assert(eventhdlr != NULL);
1965 	
1966 	   for( i = eventfilter->len - 1; i >= 0; --i )
1967 	   {
1968 	      if( eventdata == eventfilter->eventdata[i]
1969 	         && eventhdlr == eventfilter->eventhdlrs[i]
1970 	         && eventtype == eventfilter->eventtypes[i]
1971 	         && eventfilter->nextpos[i] == -2 )
1972 	         return i;
1973 	   }
1974 	
1975 	   return -1;
1976 	}
1977 	
1978 	/** deletes element from event filter */
1979 	SCIP_RETCODE SCIPeventfilterDel(
1980 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter */
1981 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
1982 	   SCIP_SET*             set,                /**< global SCIP settings */
1983 	   SCIP_EVENTTYPE        eventtype,          /**< event type */
1984 	   SCIP_EVENTHDLR*       eventhdlr,          /**< event handler to call for the event processing */
1985 	   SCIP_EVENTDATA*       eventdata,          /**< event data to pass to the event handler for the event processing */
1986 	   int                   filterpos           /**< position of event filter entry, or -1 if unknown */
1987 	   )
1988 	{
1989 	   assert(eventfilter != NULL);
1990 	   assert(blkmem != NULL);
1991 	   assert(set != NULL);
1992 	   assert(eventtype != SCIP_EVENTTYPE_DISABLED);
1993 	   assert(eventhdlr != NULL);
1994 	   assert(-1 <= filterpos && filterpos < eventfilter->len);
1995 	
1996 	   /* search position of event filter entry, if not given by the user */
1997 	   if( filterpos == -1 )
1998 	      filterpos = eventfilterSearch(eventfilter, eventtype, eventhdlr, eventdata);
1999 	   if( filterpos == -1 )
2000 	   {
2001 	      SCIPerrorMessage("no event for event handler %p with data %p and event mask %" SCIP_EVENTTYPE_FORMAT " found in event filter %p\n",
2002 	         (void*)eventhdlr, (void*)eventdata, eventtype, (void*)eventfilter);
2003 	      return SCIP_INVALIDDATA;
2004 	   }
2005 	   assert(0 <= filterpos && filterpos < eventfilter->len);
2006 	   assert(eventfilter->eventtypes[filterpos] == eventtype);
2007 	   assert(eventfilter->eventhdlrs[filterpos] == eventhdlr);
2008 	   assert(eventfilter->eventdata[filterpos] == eventdata);
2009 	   assert(eventfilter->nextpos[filterpos] == -2);
2010 	
2011 	   /* if updates are delayed, insert entry into the list of delayed deletions;
2012 	    * otherwise, delete the entry from the filter directly and add the slot to the free list
2013 	    */
2014 	   if( eventfilter->delayupdates )
2015 	   {
2016 	      /* append filterpos to the list of deleted entries */
2017 	      eventfilter->nextpos[filterpos] = eventfilter->firstdeletedpos;
2018 	      eventfilter->firstdeletedpos = filterpos;
2019 	   }
2020 	   else
2021 	   {
2022 	      /* disable the entry in the filter and add the slot to the free list */
2023 	      assert(eventfilter->nextpos[filterpos] == -2);
2024 	      eventfilter->eventtypes[filterpos] = SCIP_EVENTTYPE_DISABLED;
2025 	      eventfilter->nextpos[filterpos] = eventfilter->firstfreepos;
2026 	      eventfilter->firstfreepos = filterpos;
2027 	   }
2028 	
2029 	   return SCIP_OKAY;
2030 	}
2031 	
2032 	/** makes the event filter to delay and buffer all updates until eventfilterProcessUpdates() is called */
2033 	static
2034 	void eventfilterDelayUpdates(
2035 	   SCIP_EVENTFILTER*     eventfilter         /**< event filter */
2036 	   )
2037 	{
2038 	   assert(eventfilter != NULL);
2039 	   assert(!eventfilter->delayupdates);
2040 	   assert(eventfilter->delayedeventmask == SCIP_EVENTTYPE_DISABLED);
2041 	
2042 	   eventfilter->delayupdates = TRUE;
2043 	}
2044 	
2045 	/** processes all delayed additions and deletions */
2046 	static
2047 	void eventfilterProcessUpdates(
2048 	   SCIP_EVENTFILTER*     eventfilter         /**< event filter */
2049 	   )
2050 	{
2051 	   int pos;
2052 	   int nextpos;
2053 	
2054 	   assert(eventfilter != NULL);
2055 	   assert(eventfilter->delayupdates);
2056 	
2057 	   /* move deleted entries into the free list and disable them */
2058 	   pos = eventfilter->firstdeletedpos;
2059 	   while( pos != -1 )
2060 	   {
2061 	      assert(0 <= pos && pos < eventfilter->len);
2062 	      assert(eventfilter->eventtypes[pos] != SCIP_EVENTTYPE_DISABLED);
2063 	      assert(eventfilter->nextpos[pos] >= -1);
2064 	
2065 	      nextpos = eventfilter->nextpos[pos];
2066 	      eventfilter->nextpos[pos] = eventfilter->firstfreepos;
2067 	      eventfilter->firstfreepos = pos;
2068 	      eventfilter->eventtypes[pos] = SCIP_EVENTTYPE_DISABLED;
2069 	      pos = nextpos;
2070 	   }
2071 	   eventfilter->firstdeletedpos = -1;
2072 	
2073 	   /* update event mask */
2074 	   eventfilter->eventmask |= eventfilter->delayedeventmask;
2075 	   eventfilter->delayedeventmask = SCIP_EVENTTYPE_DISABLED;
2076 	
2077 	   /* mark the event filter updates to be no longer delayed */
2078 	   eventfilter->delayupdates = FALSE;
2079 	}
2080 	
2081 	/** processes the event with all event handlers with matching filter setting */
2082 	SCIP_RETCODE SCIPeventfilterProcess(
2083 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter */
2084 	   SCIP_SET*             set,                /**< global SCIP settings */
2085 	   SCIP_EVENT*           event               /**< event to process */
2086 	   )
2087 	{
2088 	   SCIP_EVENTTYPE eventtype;
2089 	   SCIP_EVENTTYPE* eventtypes;
2090 	   SCIP_Bool processed;
2091 	   int len;
2092 	   int i;
2093 	
2094 	   assert(eventfilter != NULL);
2095 	   assert(set != NULL);
2096 	   assert(event != NULL);
2097 	
2098 	   SCIPsetDebugMsg(set, "processing event filter %p (len %d, mask 0x%" SCIP_EVENTTYPE_FORMAT ") with event type 0x%" SCIP_EVENTTYPE_FORMAT "\n",
2099 	      (void*)eventfilter, eventfilter->len, eventfilter->eventmask, event->eventtype);
2100 	
2101 	   eventtype = event->eventtype;
2102 	
2103 	   /* check, if there may be any event handler for specific event */
2104 	   if( (eventtype & eventfilter->eventmask) == 0 )
2105 	      return SCIP_OKAY;
2106 	
2107 	   /* delay the updates on this eventfilter, such that changes during event processing to the event filter
2108 	    * don't destroy necessary information of the arrays we are currently using
2109 	    */
2110 	   eventfilterDelayUpdates(eventfilter);
2111 	
2112 	   /* process the event by calling the event handlers */
2113 	   processed = FALSE;
2114 	   len = eventfilter->len;
2115 	   eventtypes = eventfilter->eventtypes;
2116 	   for( i = 0; i < len; ++i )
2117 	   {
2118 	      /* check, if event is applicable for the filter element */
2119 	      if( (eventtype & eventtypes[i]) != 0 )
2120 	      {
2121 	         /* call event handler */
2122 	         SCIP_CALL( SCIPeventhdlrExec(eventfilter->eventhdlrs[i], set, event, eventfilter->eventdata[i]) );
2123 	         processed = TRUE;
2124 	      }
2125 	   }
2126 	
2127 	   /* update eventfilter mask, if event was not processed by any event handler */
2128 	   if( !processed )
2129 	   {
2130 	      eventfilter->eventmask &= ~event->eventtype;
2131 	      SCIPsetDebugMsg(set, " -> event type 0x%" SCIP_EVENTTYPE_FORMAT " not processed. new mask of event filter %p: 0x%" SCIP_EVENTTYPE_FORMAT "\n",
2132 	         event->eventtype, (void*)eventfilter, eventfilter->eventmask);
2133 	   }
2134 	
2135 	   /* process delayed events on this eventfilter */
2136 	   eventfilterProcessUpdates(eventfilter);
2137 	
2138 	   return SCIP_OKAY;
2139 	}
2140 	
2141 	
2142 	
2143 	/*
2144 	 * Event queue methods
2145 	 */
2146 	
2147 	/*
2148 	 * simple functions implemented as defines
2149 	 */
2150 	
2151 	/* In debug mode, the following methods are implemented as function calls to ensure
2152 	 * type validity.
2153 	 * In optimized mode, the methods are implemented as defines to improve performance.
2154 	 * However, we want to have them in the library anyways, so we have to undef the defines.
2155 	 */
2156 	
2157 	#undef SCIPeventqueueIsDelayed
2158 	
2159 	/** resizes events array to be able to store at least num entries */
2160 	static
2161 	SCIP_RETCODE eventqueueEnsureEventsMem(
2162 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2163 	   SCIP_SET*             set,                /**< global SCIP settings */
2164 	   int                   num                 /**< minimal number of node slots in array */
2165 	   )
2166 	{
2167 	   assert(eventqueue != NULL);
2168 	   assert(set != NULL);
2169 	
2170 	   if( num > eventqueue->eventssize )
2171 	   {
2172 	      int newsize;
2173 	
2174 	      newsize = SCIPsetCalcMemGrowSize(set, num);
2175 	      SCIP_ALLOC( BMSreallocMemoryArray(&eventqueue->events, newsize) );
2176 	      eventqueue->eventssize = newsize;
2177 	   }
2178 	   assert(num <= eventqueue->eventssize);
2179 	
2180 	   return SCIP_OKAY;
2181 	}
2182 	
2183 	/** creates an event queue */
2184 	SCIP_RETCODE SCIPeventqueueCreate(
2185 	   SCIP_EVENTQUEUE**     eventqueue          /**< pointer to store the event queue */
2186 	   )
2187 	{
2188 	   assert(eventqueue != NULL);
2189 	
2190 	   SCIP_ALLOC( BMSallocMemory(eventqueue) );
2191 	   (*eventqueue)->events = NULL;
2192 	   (*eventqueue)->eventssize = 0;
2193 	   (*eventqueue)->nevents = 0;
2194 	   (*eventqueue)->delayevents = FALSE;
2195 	
2196 	   return SCIP_OKAY;
2197 	}
2198 	
2199 	/** frees event queue; there must not be any unprocessed events in the queue! */
2200 	SCIP_RETCODE SCIPeventqueueFree(
2201 	   SCIP_EVENTQUEUE**     eventqueue          /**< pointer to the event queue */
2202 	   )
2203 	{
2204 	   assert(eventqueue != NULL);
2205 	   assert(*eventqueue != NULL);
2206 	   assert((*eventqueue)->nevents == 0);
2207 	
2208 	   BMSfreeMemoryArrayNull(&(*eventqueue)->events);
2209 	   BMSfreeMemory(eventqueue);
2210 	
2211 	   return SCIP_OKAY;
2212 	}
2213 	
2214 	/** appends event to the event queue; sets event to NULL afterwards */
2215 	static
2216 	SCIP_RETCODE eventqueueAppend(
2217 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2218 	   SCIP_SET*             set,                /**< global SCIP settings */
2219 	   SCIP_EVENT**          event               /**< pointer to event to append to the queue */
2220 	   )
2221 	{
2222 	   assert(eventqueue != NULL);
2223 	   assert(eventqueue->delayevents);
2224 	   assert(event != NULL);
2225 	   assert(*event != NULL);
2226 	
2227 	   SCIPsetDebugMsg(set, "appending event %p of type 0x%" SCIP_EVENTTYPE_FORMAT " to event queue %p at position %d\n",
2228 	      (void*)*event, (*event)->eventtype, (void*)eventqueue, eventqueue->nevents);
2229 	
2230 	   SCIP_CALL( eventqueueEnsureEventsMem(eventqueue, set, eventqueue->nevents+1) );
2231 	   eventqueue->events[eventqueue->nevents] = *event;
2232 	   eventqueue->nevents++;
2233 	
2234 	   *event = NULL;
2235 	
2236 	   return SCIP_OKAY;
2237 	}
2238 	
2239 	/** processes event or adds event to the event queue */
2240 	SCIP_RETCODE SCIPeventqueueAdd(
2241 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2242 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
2243 	   SCIP_SET*             set,                /**< global SCIP settings */
2244 	   SCIP_PRIMAL*          primal,             /**< primal data; only needed for objchanged events, or NULL */
2245 	   SCIP_LP*              lp,                 /**< current LP data; only needed for obj/boundchanged events, or NULL */
2246 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage; only needed for bound change events, or NULL */
2247 	   SCIP_EVENTFILTER*     eventfilter,        /**< event filter for global events; not needed for variable specific events */
2248 	   SCIP_EVENT**          event               /**< pointer to event to add to the queue; will be NULL after queue addition */
2249 	   )
2250 	{
2251 	   SCIP_VAR* var;
2252 	   SCIP_EVENT* qevent;
2253 	   int pos;
2254 	
2255 	   assert(eventqueue != NULL);
2256 	   assert(event != NULL);
2257 	   assert(*event != NULL);
2258 	   assert(((*event)->eventtype & SCIP_EVENTTYPE_OBJCHANGED) == 0 || primal != NULL);
2259 	   assert(((*event)->eventtype & (SCIP_EVENTTYPE_BOUNDCHANGED | SCIP_EVENTTYPE_OBJCHANGED)) == 0 || lp != NULL);
2260 	   assert(((*event)->eventtype & SCIP_EVENTTYPE_BOUNDCHANGED) == 0 || branchcand != NULL);
2261 	
2262 	   if( !eventqueue->delayevents )
2263 	   {
2264 	      SCIP_CALL( SCIPeventqueueDelay(eventqueue) );
2265 	
2266 	      /* immediately process event */
2267 	      SCIP_CALL( SCIPeventProcess(*event, set, primal, lp, branchcand, eventfilter) );
2268 	      SCIP_CALL( SCIPeventFree(event, blkmem) );
2269 	
2270 	      SCIP_CALL( SCIPeventqueueProcess(eventqueue, blkmem, set, primal, lp, branchcand, eventfilter) );
2271 	   }
2272 	   else
2273 	   {
2274 	      /* delay processing of event by appending it to the event queue */
2275 	      SCIPsetDebugMsg(set, "adding event %p of type 0x%" SCIP_EVENTTYPE_FORMAT " to event queue %p\n", (void*)*event, (*event)->eventtype, (void*)eventqueue);
2276 	
2277 	      switch( (*event)->eventtype )
2278 	      {
2279 	      case SCIP_EVENTTYPE_DISABLED:
2280 	         SCIPerrorMessage("cannot add a disabled event to the event queue\n");
2281 	         return SCIP_INVALIDDATA;
2282 	
2283 	      case SCIP_EVENTTYPE_VARADDED:
2284 	      case SCIP_EVENTTYPE_VARDELETED:
2285 	      case SCIP_EVENTTYPE_VARFIXED:
2286 	      case SCIP_EVENTTYPE_VARUNLOCKED:
2287 	      case SCIP_EVENTTYPE_GLBCHANGED:
2288 	      case SCIP_EVENTTYPE_GUBCHANGED:
2289 	      case SCIP_EVENTTYPE_PRESOLVEROUND:
2290 	      case SCIP_EVENTTYPE_NODEFOCUSED:
2291 	      case SCIP_EVENTTYPE_NODEFEASIBLE:
2292 	      case SCIP_EVENTTYPE_NODEINFEASIBLE:
2293 	      case SCIP_EVENTTYPE_NODEBRANCHED:
2294 	      case SCIP_EVENTTYPE_NODEDELETE:
2295 	      case SCIP_EVENTTYPE_FIRSTLPSOLVED:
2296 	      case SCIP_EVENTTYPE_LPSOLVED:
2297 	      case SCIP_EVENTTYPE_POORSOLFOUND:
2298 	      case SCIP_EVENTTYPE_BESTSOLFOUND:
2299 	      case SCIP_EVENTTYPE_GHOLEADDED:
2300 	      case SCIP_EVENTTYPE_GHOLEREMOVED:
2301 	      case SCIP_EVENTTYPE_LHOLEADDED:
2302 	      case SCIP_EVENTTYPE_LHOLEREMOVED:
2303 	      case SCIP_EVENTTYPE_ROWADDEDSEPA: /* @todo remove previous DELETEDSEPA event */
2304 	      case SCIP_EVENTTYPE_ROWDELETEDSEPA: /* @todo remove previous ADDEDSEPA event */
2305 	      case SCIP_EVENTTYPE_ROWADDEDLP: /* @todo remove previous DELETEDLP event */
2306 	      case SCIP_EVENTTYPE_ROWDELETEDLP: /* @todo remove previous ADDEDLP event */
2307 	      case SCIP_EVENTTYPE_ROWCOEFCHANGED: /* @todo merge? */
2308 	      case SCIP_EVENTTYPE_ROWCONSTCHANGED: /* @todo merge with previous constchanged event */ /*lint !e30 !e142*/
2309 	      case SCIP_EVENTTYPE_ROWSIDECHANGED: /* @todo merge with previous sidechanged event */ /*lint !e30 !e142*/
2310 	      case SCIP_EVENTTYPE_SYNC: /*lint !e30 !e142*/
2311 	         /* these events cannot (or need not) be merged; just add them to the queue */
2312 	         SCIP_CALL( eventqueueAppend(eventqueue, set, event) );
2313 	         break;
2314 	
2315 	      case SCIP_EVENTTYPE_OBJCHANGED:
2316 	         /* changes in objective value may be merged with older changes in objective value */
2317 	         var = (*event)->data.eventobjchg.var;
2318 	         assert(var != NULL);
2319 	         pos = var->eventqueueindexobj;
2320 	         if( pos >= 0 )
2321 	         {
2322 	            /* the objective value change event already exists -> modify it accordingly */
2323 	            assert(pos < eventqueue->nevents);
2324 	            qevent = eventqueue->events[pos];
2325 	            assert(qevent != NULL);
2326 	            assert(qevent->eventtype == SCIP_EVENTTYPE_OBJCHANGED);
2327 	            assert(qevent->data.eventobjchg.var == var);
2328 	            assert(SCIPsetIsEQ(set, (*event)->data.eventobjchg.oldobj, qevent->data.eventobjchg.newobj));
2329 	
2330 	            SCIPsetDebugMsg(set, " -> merging OBJ event (<%s>,%g -> %g) with event at position %d (<%s>,%g -> %g)\n",
2331 	               SCIPvarGetName((*event)->data.eventobjchg.var), (*event)->data.eventobjchg.oldobj,
2332 	               (*event)->data.eventobjchg.newobj,
2333 	               pos, SCIPvarGetName(qevent->data.eventobjchg.var), qevent->data.eventobjchg.oldobj, 
2334 	               qevent->data.eventobjchg.newobj);
2335 	
2336 	            qevent->data.eventobjchg.newobj = (*event)->data.eventobjchg.newobj;
2337 	            if( qevent->data.eventobjchg.newobj == qevent->data.eventobjchg.oldobj ) /*lint !e777*/
2338 	            {
2339 	               /* the queued objective value change was reversed -> disable the event in the queue */
2340 	               eventDisable(qevent);
2341 	               var->eventqueueindexobj = -1;
2342 	               SCIPsetDebugMsg(set, " -> event disabled\n");
2343 	            }
2344 	
2345 	            /* free the event that is of no use any longer */
2346 	            SCIP_CALL( SCIPeventFree(event, blkmem) );
2347 	         }
2348 	         else
2349 	         {
2350 	            /* the objective value change event doesn't exist -> add it to the queue, and remember the array index */
2351 	            var->eventqueueindexobj = eventqueue->nevents;
2352 	            SCIP_CALL( eventqueueAppend(eventqueue, set, event) );
2353 	         }
2354 	         break;
2355 	
2356 	      case SCIP_EVENTTYPE_LBTIGHTENED:
2357 	      case SCIP_EVENTTYPE_LBRELAXED:
2358 	         /* changes in lower bound may be merged with older changes in lower bound */
2359 	         var = (*event)->data.eventbdchg.var;
2360 	         assert(var != NULL);
2361 	         pos = var->eventqueueindexlb;
2362 	         if( pos >= 0 )
2363 	         {
2364 	            /* the lower bound change event already exists -> modify it accordingly */
2365 	            assert(pos < eventqueue->nevents);
2366 	            qevent = eventqueue->events[pos];
2367 	            assert(qevent != NULL);
2368 	            assert(qevent->eventtype == SCIP_EVENTTYPE_LBTIGHTENED || qevent->eventtype == SCIP_EVENTTYPE_LBRELAXED);
2369 	            assert(qevent->data.eventbdchg.var == var);
2370 	            assert(SCIPsetIsEQ(set, (*event)->data.eventbdchg.oldbound, qevent->data.eventbdchg.newbound));
2371 	
2372 	            SCIPsetDebugMsg(set, " -> merging LB event (<%s>,%g -> %g) with event at position %d (<%s>,%g -> %g)\n",
2373 	               SCIPvarGetName((*event)->data.eventbdchg.var), (*event)->data.eventbdchg.oldbound,
2374 	               (*event)->data.eventbdchg.newbound,
2375 	               pos, SCIPvarGetName(qevent->data.eventbdchg.var), qevent->data.eventbdchg.oldbound, 
2376 	               qevent->data.eventbdchg.newbound);
2377 	
2378 	            qevent->data.eventbdchg.newbound = (*event)->data.eventbdchg.newbound;
2379 	            /*if( SCIPsetIsLT(set, qevent->data.eventbdchg.newbound, qevent->data.eventbdchg.oldbound) )*/
2380 	            if( qevent->data.eventbdchg.newbound < qevent->data.eventbdchg.oldbound )
2381 	               qevent->eventtype = SCIP_EVENTTYPE_LBRELAXED;
2382 	            /*else if( SCIPsetIsGT(set, qevent->data.eventbdchg.newbound, qevent->data.eventbdchg.oldbound) )*/
2383 	            else if( qevent->data.eventbdchg.newbound > qevent->data.eventbdchg.oldbound )
2384 	               qevent->eventtype = SCIP_EVENTTYPE_LBTIGHTENED;
2385 	            else
2386 	            {
2387 	               /* the queued bound change was reversed -> disable the event in the queue */
2388 	               assert(qevent->data.eventbdchg.newbound == qevent->data.eventbdchg.oldbound); /*lint !e777*/
2389 	               eventDisable(qevent);
2390 	               var->eventqueueindexlb = -1;
2391 	               SCIPsetDebugMsg(set, " -> event disabled\n");
2392 	            }
2393 	
2394 	            /* free the event that is of no use any longer */
2395 	            SCIP_CALL( SCIPeventFree(event, blkmem) );
2396 	         }
2397 	         else
2398 	         {
2399 	            /* the lower bound change event doesn't exist -> add it to the queue, and remember the array index */
2400 	            var->eventqueueindexlb = eventqueue->nevents;
2401 	            SCIP_CALL( eventqueueAppend(eventqueue, set, event) );
2402 	         }
2403 	         break;
2404 	
2405 	      case SCIP_EVENTTYPE_UBTIGHTENED:
2406 	      case SCIP_EVENTTYPE_UBRELAXED:
2407 	         /* changes in upper bound may be merged with older changes in upper bound */
2408 	         var = (*event)->data.eventbdchg.var;
2409 	         assert(var != NULL);
2410 	         pos = var->eventqueueindexub;
2411 	         if( pos >= 0 )
2412 	         {
2413 	            /* the upper bound change event already exists -> modify it accordingly */
2414 	            assert(pos < eventqueue->nevents);
2415 	            qevent = eventqueue->events[pos];
2416 	            assert(qevent != NULL);
2417 	            assert(qevent->eventtype == SCIP_EVENTTYPE_UBTIGHTENED || qevent->eventtype == SCIP_EVENTTYPE_UBRELAXED);
2418 	            assert(qevent->data.eventbdchg.var == var);
2419 	            assert(SCIPsetIsEQ(set, (*event)->data.eventbdchg.oldbound, qevent->data.eventbdchg.newbound));
2420 	
2421 	            SCIPsetDebugMsg(set, " -> merging UB event (<%s>,%g -> %g) with event at position %d (<%s>,%g -> %g)\n",
2422 	               SCIPvarGetName((*event)->data.eventbdchg.var), (*event)->data.eventbdchg.oldbound,
2423 	               (*event)->data.eventbdchg.newbound,
2424 	               pos, SCIPvarGetName(qevent->data.eventbdchg.var), qevent->data.eventbdchg.oldbound,
2425 	               qevent->data.eventbdchg.newbound);
2426 	
2427 	            qevent->data.eventbdchg.newbound = (*event)->data.eventbdchg.newbound;
2428 	            /*if( SCIPsetIsLT(set, qevent->data.eventbdchg.newbound, qevent->data.eventbdchg.oldbound) )*/
2429 	            if( qevent->data.eventbdchg.newbound < qevent->data.eventbdchg.oldbound )
2430 	               qevent->eventtype = SCIP_EVENTTYPE_UBTIGHTENED;
2431 	            /*else if( SCIPsetIsGT(set, qevent->data.eventbdchg.newbound, qevent->data.eventbdchg.oldbound) )*/
2432 	            else if( qevent->data.eventbdchg.newbound > qevent->data.eventbdchg.oldbound )
2433 	               qevent->eventtype = SCIP_EVENTTYPE_UBRELAXED;
2434 	            else
2435 	            {
2436 	               /* the queued bound change was reversed -> disable the event in the queue */
2437 	               assert(qevent->data.eventbdchg.newbound == qevent->data.eventbdchg.oldbound); /*lint !e777*/
2438 	               eventDisable(qevent);
2439 	               var->eventqueueindexub = -1;
2440 	               SCIPsetDebugMsg(set, " -> event disabled\n");
2441 	            }
2442 	
2443 	            /* free the event that is of no use any longer */
2444 	            SCIP_CALL( SCIPeventFree(event, blkmem) );
2445 	         }
2446 	         else
2447 	         {
2448 	            /* the upper bound change event doesn't exist -> add it to the queue, and remember the array index */
2449 	            var->eventqueueindexub = eventqueue->nevents;
2450 	            SCIP_CALL( eventqueueAppend(eventqueue, set, event) );
2451 	         }
2452 	         break;
2453 	
2454 	      case SCIP_EVENTTYPE_IMPLADDED:
2455 	         var = (*event)->data.eventimpladd.var;
2456 	         assert(var != NULL);
2457 	         if( var->eventqueueimpl )
2458 	         {
2459 	            /* free the event that is of no use any longer */
2460 	            SCIP_CALL( SCIPeventFree(event, blkmem) );
2461 	         }
2462 	         else
2463 	         {
2464 	            var->eventqueueimpl = TRUE;
2465 	            SCIP_CALL( eventqueueAppend(eventqueue, set, event) );
2466 	         }
2467 	         break;
2468 	
2469 	      default:
2470 	         SCIPerrorMessage("unknown event type <%" SCIP_EVENTTYPE_FORMAT ">\n", (*event)->eventtype);
2471 	         return SCIP_INVALIDDATA;
2472 	      }
2473 	   }
2474 	
2475 	   assert(*event == NULL);
2476 	
2477 	   return SCIP_OKAY;
2478 	}
2479 	
2480 	/** marks queue to delay incoming events until a call to SCIPeventqueueProcess() */
2481 	SCIP_RETCODE SCIPeventqueueDelay(
2482 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
2483 	   )
2484 	{
2485 	   assert(eventqueue != NULL);
2486 	   assert(!eventqueue->delayevents);
2487 	
2488 	   SCIPdebugMessage("event processing is delayed\n");
2489 	
2490 	   eventqueue->delayevents = TRUE;
2491 	
2492 	   return SCIP_OKAY;
2493 	}
2494 	
2495 	/** processes all delayed events, marks queue to process events immediately */
2496 	SCIP_RETCODE SCIPeventqueueProcess(
2497 	   SCIP_EVENTQUEUE*      eventqueue,         /**< event queue */
2498 	   BMS_BLKMEM*           blkmem,             /**< block memory buffer */
2499 	   SCIP_SET*             set,                /**< global SCIP settings */
2500 	   SCIP_PRIMAL*          primal,             /**< primal data */
2501 	   SCIP_LP*              lp,                 /**< current LP data */
2502 	   SCIP_BRANCHCAND*      branchcand,         /**< branching candidate storage */
2503 	   SCIP_EVENTFILTER*     eventfilter         /**< event filter for global (not variable dependent) events */
2504 	   )
2505 	{
2506 	   SCIP_EVENT* event;
2507 	   int i;
2508 	
2509 	   assert(eventqueue != NULL);
2510 	   assert(eventqueue->delayevents);
2511 	
2512 	   SCIPsetDebugMsg(set, "processing %d queued events\n", eventqueue->nevents);
2513 	
2514 	   /* pass events to the responsible event filters
2515 	    * During event processing, new events may be raised. We have to loop to the mutable eventqueue->nevents.
2516 	    * A loop to something like "nevents = eventqueue->nevents; for(...; i < nevents; ...)" would miss the
2517 	    * newly created events. The same holds for eventqueue->events, which can be moved in memory due to
2518 	    * memory reallocation in eventqueueAppend().
2519 	    */
2520 	   for( i = 0; i < eventqueue->nevents; ++i )
2521 	   {
2522 	      event = eventqueue->events[i];
2523 	      assert(event != NULL);
2524 	
2525 	      SCIPsetDebugMsg(set, "processing event %d of %d events in queue: eventtype=0x%" SCIP_EVENTTYPE_FORMAT "\n", i, eventqueue->nevents, event->eventtype);
2526 	
2527 	      /* unmark the event queue index of a variable with changed objective value or bounds, and unmark the event queue
2528 	       * member flag of a variable with added implication
2529 	       */
2530 	      if( (event->eventtype & SCIP_EVENTTYPE_OBJCHANGED) != 0 )
2531 	      {
2532 	         assert(event->data.eventobjchg.var->eventqueueindexobj == i);
2533 	         event->data.eventobjchg.var->eventqueueindexobj = -1;
2534 	      }
2535 	      else if( (event->eventtype & SCIP_EVENTTYPE_LBCHANGED) != 0 )
2536 	      {
2537 	         assert(event->data.eventbdchg.var->eventqueueindexlb == i);
2538 	         event->data.eventbdchg.var->eventqueueindexlb = -1;
2539 	      }
2540 	      else if( (event->eventtype & SCIP_EVENTTYPE_UBCHANGED) != 0 )
2541 	      {
2542 	         assert(event->data.eventbdchg.var->eventqueueindexub == i);
2543 	         event->data.eventbdchg.var->eventqueueindexub = -1;
2544 	      }
2545 	      else if( (event->eventtype & SCIP_EVENTTYPE_IMPLADDED) != 0 )
2546 	      {
2547 	         assert(event->data.eventimpladd.var->eventqueueimpl);
2548 	         event->data.eventimpladd.var->eventqueueimpl = FALSE;
2549 	      }
2550 	
2551 	      /* process event */
2552 	      SCIP_CALL( SCIPeventProcess(event, set, primal, lp, branchcand, eventfilter) );
2553 	
2554 	      /* free the event immediately, because additionally raised events during event processing
2555 	       * can lead to a large event queue
2556 	       */
2557 	      SCIP_CALL( SCIPeventFree(&eventqueue->events[i], blkmem) );
2558 	   }
2559 	
2560 	   assert(i == eventqueue->nevents);
2561 	   eventqueue->nevents = 0;
2562 	   eventqueue->delayevents = FALSE;
2563 	
2564 	   return SCIP_OKAY;
2565 	}
2566 	
2567 	/** returns TRUE iff events of the queue are delayed until the next SCIPeventqueueProcess() call */
2568 	SCIP_Bool SCIPeventqueueIsDelayed(
2569 	   SCIP_EVENTQUEUE*      eventqueue          /**< event queue */
2570 	   )
2571 	{
2572 	   assert(eventqueue != NULL);
2573 	
2574 	   return eventqueue->delayevents;
2575 	}
2576