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