Scippy

SCIP

Solving Constraint Integer Programs

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