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 cons.c 26 * @ingroup OTHER_CFILES 27 * @brief methods for constraints and constraint handlers 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 */ 31 32 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 33 34 #include <assert.h> 35 36 #include "scip/def.h" 37 #include "scip/set.h" 38 #include "scip/stat.h" 39 #include "scip/clock.h" 40 #include "scip/var.h" 41 #include "scip/prob.h" 42 #include "scip/tree.h" 43 #include "scip/scip.h" 44 #include "scip/sepastore.h" 45 #include "scip/cons.h" 46 #include "scip/branch.h" 47 #include "scip/reopt.h" 48 #include "scip/pub_misc.h" 49 50 #ifndef NDEBUG 51 #include "scip/struct_cons.h" 52 #endif 53 54 55 #define AGERESETAVG_INIT 1000.0 /**< initial value of the exponentially decaying weighted sum for ages */ 56 #define AGERESETAVG_MIN 100.0 /**< minimal value to use for weighted sum of ages */ 57 #define AGERESETAVG_DECAY 0.0005 /**< weight of a new addend in the exponentially decyaing sum */ 58 #define AGERESETAVG_AGELIMIT 2.0 /**< in dynamic setting, a constraint is deleted if its age exceeds the 59 * average reset age by this factor */ 60 #define AGERESETAVG_OBSOLETEAGE 1.8 /**< in dynamic setting, a constraint is marked obsolete if its age exceeds the 61 * average reset age by this factor */ 62 63 64 /* #define CHECKCONSARRAYS */ 65 66 67 /* 68 * dynamic memory arrays 69 */ 70 71 72 /** resizes conss array to be able to store at least num constraints */ 73 static 74 SCIP_RETCODE conshdlrEnsureConssMem( 75 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 76 SCIP_SET* set, /**< global SCIP settings */ 77 int num /**< minimal number of slots in array */ 78 ) 79 { 80 assert(conshdlr != NULL); 81 assert(set != NULL); 82 83 if( num > conshdlr->consssize ) 84 { 85 int newsize; 86 87 newsize = SCIPsetCalcMemGrowSize(set, num); 88 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->conss, newsize) ); 89 conshdlr->consssize = newsize; 90 } 91 assert(num <= conshdlr->consssize); 92 93 return SCIP_OKAY; 94 } 95 96 /** resizes initconss array to be able to store at least num constraints */ 97 static 98 SCIP_RETCODE conshdlrEnsureInitconssMem( 99 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 100 SCIP_SET* set, /**< global SCIP settings */ 101 int num /**< minimal number of slots in array */ 102 ) 103 { 104 assert(conshdlr != NULL); 105 assert(set != NULL); 106 107 if( num > conshdlr->initconsssize ) 108 { 109 int newsize; 110 111 newsize = SCIPsetCalcMemGrowSize(set, num); 112 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->initconss, newsize) ); 113 conshdlr->initconsssize = newsize; 114 } 115 assert(num <= conshdlr->initconsssize); 116 117 return SCIP_OKAY; 118 } 119 120 /** resizes sepaconss array to be able to store at least num constraints */ 121 static 122 SCIP_RETCODE conshdlrEnsureSepaconssMem( 123 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 124 SCIP_SET* set, /**< global SCIP settings */ 125 int num /**< minimal number of slots in array */ 126 ) 127 { 128 assert(conshdlr != NULL); 129 assert(set != NULL); 130 131 if( num > conshdlr->sepaconsssize ) 132 { 133 int newsize; 134 135 newsize = SCIPsetCalcMemGrowSize(set, num); 136 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->sepaconss, newsize) ); 137 conshdlr->sepaconsssize = newsize; 138 } 139 assert(num <= conshdlr->sepaconsssize); 140 141 return SCIP_OKAY; 142 } 143 144 /** resizes enfoconss array to be able to store at least num constraints */ 145 static 146 SCIP_RETCODE conshdlrEnsureEnfoconssMem( 147 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 148 SCIP_SET* set, /**< global SCIP settings */ 149 int num /**< minimal number of slots in array */ 150 ) 151 { 152 assert(conshdlr != NULL); 153 assert(set != NULL); 154 155 if( num > conshdlr->enfoconsssize ) 156 { 157 int newsize; 158 159 newsize = SCIPsetCalcMemGrowSize(set, num); 160 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->enfoconss, newsize) ); 161 conshdlr->enfoconsssize = newsize; 162 } 163 assert(num <= conshdlr->enfoconsssize); 164 165 return SCIP_OKAY; 166 } 167 168 /** resizes checkconss array to be able to store at least num constraints */ 169 static 170 SCIP_RETCODE conshdlrEnsureCheckconssMem( 171 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 172 SCIP_SET* set, /**< global SCIP settings */ 173 int num /**< minimal number of slots in array */ 174 ) 175 { 176 assert(conshdlr != NULL); 177 assert(set != NULL); 178 179 if( num > conshdlr->checkconsssize ) 180 { 181 int newsize; 182 183 newsize = SCIPsetCalcMemGrowSize(set, num); 184 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->checkconss, newsize) ); 185 conshdlr->checkconsssize = newsize; 186 } 187 assert(num <= conshdlr->checkconsssize); 188 189 return SCIP_OKAY; 190 } 191 192 /** resizes propconss array to be able to store at least num constraints */ 193 static 194 SCIP_RETCODE conshdlrEnsurePropconssMem( 195 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 196 SCIP_SET* set, /**< global SCIP settings */ 197 int num /**< minimal number of slots in array */ 198 ) 199 { 200 assert(conshdlr != NULL); 201 assert(set != NULL); 202 203 if( num > conshdlr->propconsssize ) 204 { 205 int newsize; 206 207 newsize = SCIPsetCalcMemGrowSize(set, num); 208 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->propconss, newsize) ); 209 conshdlr->propconsssize = newsize; 210 } 211 assert(num <= conshdlr->propconsssize); 212 213 return SCIP_OKAY; 214 } 215 216 /** resizes updateconss array to be able to store at least num constraints */ 217 static 218 SCIP_RETCODE conshdlrEnsureUpdateconssMem( 219 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 220 SCIP_SET* set, /**< global SCIP settings */ 221 int num /**< minimal number of slots in array */ 222 ) 223 { 224 assert(conshdlr != NULL); 225 assert(set != NULL); 226 227 if( num > conshdlr->updateconsssize ) 228 { 229 int newsize; 230 231 newsize = SCIPsetCalcMemGrowSize(set, num); 232 SCIP_ALLOC( BMSreallocMemoryArray(&conshdlr->updateconss, newsize) ); 233 conshdlr->updateconsssize = newsize; 234 } 235 assert(num <= conshdlr->updateconsssize); 236 237 return SCIP_OKAY; 238 } 239 240 241 242 243 /* 244 * Constraint handler methods 245 */ 246 247 #define checkConssArrays(conshdlr) /**/ 248 #ifndef NDEBUG 249 #ifdef CHECKCONSARRAYS 250 #undef checkConssArrays 251 /** sanity check for the constraint arrays of the constraint handler (only in debug mode) */ 252 static 253 void checkConssArrays( 254 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 255 ) 256 { 257 int c; 258 259 assert(conshdlr != NULL); 260 assert(0 <= conshdlr->nactiveconss && conshdlr->nactiveconss <= conshdlr->nconss); 261 262 for( c = 0; c < conshdlr->nconss; ++c ) 263 { 264 assert(conshdlr->conss[c] != NULL); 265 assert(!conshdlr->conss[c]->original); 266 assert(conshdlr->conss[c]->active == (c < conshdlr->nactiveconss)); 267 assert(conshdlr->conss[c]->consspos == c); 268 } 269 270 for( c = 0; c < conshdlr->ninitconss; ++c ) 271 { 272 assert(conshdlr->initconss[c] != NULL); 273 assert(!conshdlr->initconss[c]->original); 274 assert(c < conshdlr->ninitconsskept || conshdlr->initconss[c]->active); 275 assert(conshdlr->initconss[c]->initial); 276 } 277 278 for( c = 0; c < conshdlr->nsepaconss; ++c ) 279 { 280 assert(conshdlr->sepaconss[c] != NULL); 281 assert(!conshdlr->sepaconss[c]->original); 282 assert(conshdlr->sepaconss[c]->active); 283 assert(conshdlr->sepaconss[c]->separate); 284 assert(conshdlr->sepaconss[c]->sepaenabled); 285 assert(conshdlr->sepaconss[c]->obsolete == (c >= conshdlr->nusefulsepaconss)); 286 } 287 288 for( c = 0; c < conshdlr->nenfoconss; ++c ) 289 { 290 assert(conshdlr->enfoconss[c] != NULL); 291 assert(!conshdlr->enfoconss[c]->original); 292 assert(conshdlr->enfoconss[c]->active); 293 assert(conshdlr->enfoconss[c]->enforce); 294 assert(conshdlr->enfoconss[c]->obsolete == (c >= conshdlr->nusefulenfoconss)); 295 } 296 297 for( c = 0; c < conshdlr->ncheckconss; ++c ) 298 { 299 assert(conshdlr->checkconss[c] != NULL); 300 assert(!conshdlr->checkconss[c]->original); 301 assert(conshdlr->checkconss[c]->active); 302 assert(conshdlr->checkconss[c]->check); 303 assert(conshdlr->checkconss[c]->obsolete == (c >= conshdlr->nusefulcheckconss)); 304 } 305 306 for( c = 0; c < conshdlr->npropconss; ++c ) 307 { 308 assert(conshdlr->propconss[c] != NULL); 309 assert(!conshdlr->propconss[c]->original); 310 assert(conshdlr->propconss[c]->active); 311 assert(conshdlr->propconss[c]->propagate); 312 assert(conshdlr->propconss[c]->propenabled); 313 assert(conshdlr->propconss[c]->markpropagate == (c < conshdlr->nmarkedpropconss)); 314 assert(conshdlr->propconss[c]->markpropagate || (conshdlr->propconss[c]->obsolete == (c >= conshdlr->nusefulpropconss))); 315 } 316 assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss); 317 } 318 #endif 319 #endif 320 321 /** returns whether the constraint updates of the constraint handler are currently delayed */ 322 static 323 SCIP_Bool conshdlrAreUpdatesDelayed( 324 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 325 ) 326 { 327 return (conshdlr->delayupdatecount > 0); 328 } 329 330 /** returns the exponentially decaying weighted age average for age resets */ 331 static 332 SCIP_Real conshdlrGetAgeresetavg( 333 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 334 ) 335 { 336 assert(conshdlr != NULL); 337 338 return MAX(conshdlr->ageresetavg, AGERESETAVG_MIN); 339 } 340 341 /** updates the exponentially decaying weighted age average for age resets after a constraint age was reset */ 342 static 343 void conshdlrUpdateAgeresetavg( 344 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 345 SCIP_Real age /**< age of the constraint that is reset to zero */ 346 ) 347 { 348 assert(conshdlr != NULL); 349 350 conshdlr->ageresetavg *= (1.0-AGERESETAVG_DECAY); 351 conshdlr->ageresetavg += AGERESETAVG_DECAY * age; 352 } 353 354 /** returns whether the constraint's age exceeds the age limit */ 355 static 356 SCIP_Bool consExceedsAgelimit( 357 SCIP_CONS* cons, /**< constraint to check */ 358 SCIP_SET* set /**< global SCIP settings */ 359 ) 360 { 361 assert(cons != NULL); 362 assert(set != NULL); 363 364 return (cons->dynamic 365 && ((set->cons_agelimit > 0 && cons->age > set->cons_agelimit) 366 || (set->cons_agelimit == 0 && cons->age > AGERESETAVG_AGELIMIT * conshdlrGetAgeresetavg(cons->conshdlr)))); 367 } 368 369 /** returns whether the constraint's age exceeds the obsolete age limit */ 370 static 371 SCIP_Bool consExceedsObsoleteage( 372 SCIP_CONS* cons, /**< constraint to check */ 373 SCIP_SET* set /**< global SCIP settings */ 374 ) 375 { 376 assert(cons != NULL); 377 assert(set != NULL); 378 379 return (cons->dynamic 380 && ((set->cons_obsoleteage > 0 && cons->age > set->cons_obsoleteage) 381 || (set->cons_obsoleteage == 0 && cons->age > AGERESETAVG_OBSOLETEAGE * conshdlrGetAgeresetavg(cons->conshdlr)))); 382 } 383 384 /** marks constraint to be obsolete; it will be moved to the last part of the constraint arrays, such that 385 * it is checked, enforced, separated, and propagated after the useful constraints 386 */ 387 static 388 SCIP_RETCODE conshdlrMarkConsObsolete( 389 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 390 SCIP_CONS* cons /**< constraint to be marked obsolete */ 391 ) 392 { 393 SCIP_CONS* tmpcons; 394 395 assert(conshdlr != NULL); 396 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 397 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 398 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 399 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 400 assert(cons != NULL); 401 assert(!cons->original); 402 assert(!cons->obsolete); 403 assert(!conshdlrAreUpdatesDelayed(conshdlr)); 404 405 cons->obsolete = TRUE; 406 407 if( cons->active ) 408 { 409 if( cons->check ) 410 { 411 assert(0 <= cons->checkconsspos && cons->checkconsspos < conshdlr->nusefulcheckconss); 412 413 /* switch the last useful (non-obsolete) check constraint with this constraint */ 414 tmpcons = conshdlr->checkconss[conshdlr->nusefulcheckconss-1]; 415 assert(tmpcons->checkconsspos == conshdlr->nusefulcheckconss-1); 416 417 conshdlr->checkconss[conshdlr->nusefulcheckconss-1] = cons; 418 conshdlr->checkconss[cons->checkconsspos] = tmpcons; 419 tmpcons->checkconsspos = cons->checkconsspos; 420 cons->checkconsspos = conshdlr->nusefulcheckconss-1; 421 422 conshdlr->nusefulcheckconss--; 423 } 424 } 425 if( cons->enabled ) 426 { 427 if( cons->separate && cons->sepaenabled ) 428 { 429 assert(0 <= cons->sepaconsspos && cons->sepaconsspos < conshdlr->nusefulsepaconss); 430 431 if( cons->sepaconsspos < conshdlr->lastnusefulsepaconss ) 432 conshdlr->lastnusefulsepaconss--; 433 434 /* switch the last useful (non-obsolete) sepa constraint with this constraint */ 435 tmpcons = conshdlr->sepaconss[conshdlr->nusefulsepaconss-1]; 436 assert(tmpcons->sepaconsspos == conshdlr->nusefulsepaconss-1); 437 438 conshdlr->sepaconss[conshdlr->nusefulsepaconss-1] = cons; 439 conshdlr->sepaconss[cons->sepaconsspos] = tmpcons; 440 tmpcons->sepaconsspos = cons->sepaconsspos; 441 cons->sepaconsspos = conshdlr->nusefulsepaconss-1; 442 443 conshdlr->nusefulsepaconss--; 444 } 445 if( cons->enforce ) 446 { 447 assert(0 <= cons->enfoconsspos && cons->enfoconsspos < conshdlr->nusefulenfoconss); 448 449 if( cons->enfoconsspos < conshdlr->lastnusefulenfoconss ) 450 conshdlr->lastnusefulenfoconss--; 451 else 452 { 453 /* the constraint that becomes obsolete is not yet enforced on the current solution: 454 * we have to make sure that it will be enforced the next time; this is not done, if the current 455 * solution was already enforced and only enforcement on the additional constraints is performed 456 * (because in this case, only the new useful constraints are enforced); 457 * thus, we have to reset the enforcement counters in order to enforce all constraints again, especially 458 * the now obsolete one; 459 * this case should occur almost never, because a constraint that was not enforced in the last enforcement 460 * is a newly added one, and it is very unlikely that this constraint will become obsolete before the next 461 * enforcement call; 462 * this reset is not performed for separation and propagation, because they are not vital for correctness 463 */ 464 conshdlr->lastenfolplpcount = -1; 465 conshdlr->lastenfolpdomchgcount = -1; 466 conshdlr->lastenfopsdomchgcount = -1; 467 conshdlr->lastenforelaxdomchgcount = -1; 468 conshdlr->lastenforelaxrelaxcount = -1; 469 conshdlr->lastenfolpnode = -1; 470 conshdlr->lastenfopsnode = -1; 471 } 472 473 /* switch the last useful (non-obsolete) enfo constraint with this constraint */ 474 tmpcons = conshdlr->enfoconss[conshdlr->nusefulenfoconss-1]; 475 assert(tmpcons->enfoconsspos == conshdlr->nusefulenfoconss-1); 476 477 conshdlr->enfoconss[conshdlr->nusefulenfoconss-1] = cons; 478 conshdlr->enfoconss[cons->enfoconsspos] = tmpcons; 479 tmpcons->enfoconsspos = cons->enfoconsspos; 480 cons->enfoconsspos = conshdlr->nusefulenfoconss-1; 481 482 conshdlr->nusefulenfoconss--; 483 } 484 /* in case the constraint is marked to be propagated, we do not move it in the propconss array since the first 485 * part of the array contains all marked constraints independently of their age 486 */ 487 assert((!cons->markpropagate) == (cons->propconsspos < conshdlr->nmarkedpropconss)); 488 if( cons->propagate && cons->propenabled && !cons->markpropagate ) 489 { 490 assert(0 <= cons->propconsspos && cons->propconsspos < conshdlr->nusefulpropconss); 491 492 if( cons->propconsspos < conshdlr->lastnusefulpropconss ) 493 conshdlr->lastnusefulpropconss--; 494 495 /* switch the last useful (non-obsolete) prop constraint with this constraint */ 496 tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss-1]; 497 assert(tmpcons->propconsspos == conshdlr->nusefulpropconss-1); 498 499 conshdlr->propconss[conshdlr->nusefulpropconss-1] = cons; 500 conshdlr->propconss[cons->propconsspos] = tmpcons; 501 tmpcons->propconsspos = cons->propconsspos; 502 cons->propconsspos = conshdlr->nusefulpropconss-1; 503 504 conshdlr->nusefulpropconss--; 505 } 506 } 507 508 checkConssArrays(conshdlr); 509 510 return SCIP_OKAY; 511 } 512 513 /** marks obsolete constraint to be not obsolete anymore; 514 * it will be moved to the first part of the constraint arrays, such that it is checked, enforced, separated, 515 * and propagated before the obsolete constraints 516 */ 517 static 518 SCIP_RETCODE conshdlrMarkConsUseful( 519 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 520 SCIP_CONS* cons /**< constraint to be marked obsolete */ 521 ) 522 { 523 SCIP_CONS* tmpcons; 524 525 assert(conshdlr != NULL); 526 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 527 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 528 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 529 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 530 assert(cons != NULL); 531 assert(!cons->original); 532 assert(cons->obsolete); 533 assert(!conshdlrAreUpdatesDelayed(conshdlr)); 534 535 cons->obsolete = FALSE; 536 537 if( cons->active ) 538 { 539 if( cons->check ) 540 { 541 assert(conshdlr->nusefulcheckconss <= cons->checkconsspos && cons->checkconsspos < conshdlr->ncheckconss); 542 543 /* switch the first obsolete check constraint with this constraint */ 544 tmpcons = conshdlr->checkconss[conshdlr->nusefulcheckconss]; 545 assert(tmpcons->checkconsspos == conshdlr->nusefulcheckconss); 546 547 conshdlr->checkconss[conshdlr->nusefulcheckconss] = cons; 548 conshdlr->checkconss[cons->checkconsspos] = tmpcons; 549 tmpcons->checkconsspos = cons->checkconsspos; 550 cons->checkconsspos = conshdlr->nusefulcheckconss; 551 552 conshdlr->nusefulcheckconss++; 553 } 554 } 555 if( cons->enabled ) 556 { 557 if( cons->separate && cons->sepaenabled ) 558 { 559 assert(conshdlr->nusefulsepaconss <= cons->sepaconsspos && cons->sepaconsspos < conshdlr->nsepaconss); 560 561 /* switch the first obsolete sepa constraint with this constraint */ 562 tmpcons = conshdlr->sepaconss[conshdlr->nusefulsepaconss]; 563 assert(tmpcons->sepaconsspos == conshdlr->nusefulsepaconss); 564 565 conshdlr->sepaconss[conshdlr->nusefulsepaconss] = cons; 566 conshdlr->sepaconss[cons->sepaconsspos] = tmpcons; 567 tmpcons->sepaconsspos = cons->sepaconsspos; 568 cons->sepaconsspos = conshdlr->nusefulsepaconss; 569 570 conshdlr->nusefulsepaconss++; 571 } 572 if( cons->enforce ) 573 { 574 assert(conshdlr->nusefulenfoconss <= cons->enfoconsspos && cons->enfoconsspos < conshdlr->nenfoconss); 575 576 /* switch the first obsolete enfo constraint with this constraint */ 577 tmpcons = conshdlr->enfoconss[conshdlr->nusefulenfoconss]; 578 assert(tmpcons->enfoconsspos == conshdlr->nusefulenfoconss); 579 580 conshdlr->enfoconss[conshdlr->nusefulenfoconss] = cons; 581 conshdlr->enfoconss[cons->enfoconsspos] = tmpcons; 582 tmpcons->enfoconsspos = cons->enfoconsspos; 583 cons->enfoconsspos = conshdlr->nusefulenfoconss; 584 585 conshdlr->nusefulenfoconss++; 586 } 587 /* in case the constraint is marked to be propagated, we do not move it in the propconss array since the first 588 * part of the array contains all marked constraints independently of their age 589 */ 590 assert((!cons->markpropagate) == (cons->propconsspos < conshdlr->nmarkedpropconss)); 591 if( cons->propagate && cons->propenabled && !cons->markpropagate) 592 { 593 assert(conshdlr->nusefulpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->npropconss); 594 595 /* switch the first obsolete prop constraint with this constraint */ 596 tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss]; 597 assert(tmpcons->propconsspos == conshdlr->nusefulpropconss); 598 599 conshdlr->propconss[conshdlr->nusefulpropconss] = cons; 600 conshdlr->propconss[cons->propconsspos] = tmpcons; 601 tmpcons->propconsspos = cons->propconsspos; 602 cons->propconsspos = conshdlr->nusefulpropconss; 603 604 conshdlr->nusefulpropconss++; 605 } 606 } 607 608 checkConssArrays(conshdlr); 609 610 return SCIP_OKAY; 611 } 612 613 /** marks constraint to be propagated in the next propagation round; 614 * 615 * @note the propagation array is divided into three parts in contrast to the other constraint arrays; 616 * the first part contains constraints which were marked to be propagated (independently of its age) 617 * the second part contains the useful (non-obsolete) constraints which are not marked to be propagated 618 * finally, the third part contains obsolete constraints which are not marked to be propagated 619 * 620 * @note if a constraint gets marked for propagation we put it into the first part regardless of its age 621 */ 622 static 623 void conshdlrMarkConsPropagate( 624 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 625 SCIP_CONS* cons /**< constraint to be marked obsolete */ 626 ) 627 { 628 SCIP_CONS* tmpcons; 629 630 assert(conshdlr != NULL); 631 assert(conshdlr->nmarkedpropconss <= conshdlr->nusefulpropconss); 632 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 633 assert(cons != NULL); 634 assert(!cons->original); 635 636 /* it may happen that the constraint is deleted while updates are delayed: in this case we just return */ 637 if( !cons->enabled ) 638 return; 639 640 if( cons->markpropagate ) 641 return; 642 643 cons->markpropagate = TRUE; 644 645 /* propagation of the constraint is globally or locally disabled, so we do not have to move the constraint in the 646 * propconss array 647 */ 648 if( !cons->propagate || !cons->propenabled ) 649 { 650 assert(cons->propconsspos == -1); 651 return; 652 } 653 assert(cons->propconsspos >= conshdlr->nmarkedpropconss); 654 655 /* if the constraint is obsolete, we need to move it first to the non-obsolete part of the array */ 656 if( cons->obsolete ) 657 { 658 assert(conshdlr->nusefulpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->npropconss); 659 660 /* switch the first obsolete prop constraint with this constraint */ 661 tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss]; 662 assert(tmpcons->propconsspos == conshdlr->nusefulpropconss); 663 664 conshdlr->propconss[conshdlr->nusefulpropconss] = cons; 665 conshdlr->propconss[cons->propconsspos] = tmpcons; 666 tmpcons->propconsspos = cons->propconsspos; 667 cons->propconsspos = conshdlr->nusefulpropconss; 668 669 conshdlr->nusefulpropconss++; 670 } 671 assert(conshdlr->nmarkedpropconss <= cons->propconsspos && cons->propconsspos < conshdlr->nusefulpropconss); 672 673 /* switch the first useful prop constraint with this constraint */ 674 tmpcons = conshdlr->propconss[conshdlr->nmarkedpropconss]; 675 assert(tmpcons->propconsspos == conshdlr->nmarkedpropconss); 676 677 conshdlr->propconss[conshdlr->nmarkedpropconss] = cons; 678 conshdlr->propconss[cons->propconsspos] = tmpcons; 679 tmpcons->propconsspos = cons->propconsspos; 680 cons->propconsspos = conshdlr->nmarkedpropconss; 681 682 conshdlr->nmarkedpropconss++; 683 assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss); 684 685 checkConssArrays(conshdlr); 686 } 687 688 /** unmarks constraint to be propagated in the next propagation round; 689 * 690 * @note the propagation array is divided into three parts in contrast to the other constraint arrays; 691 * the first part contains constraints which were marked to be propagated (independently of its age) 692 * the second part contains the useful (non-obsolete) constraints which are not marked to be propagated 693 * finally, the third part contains obsolete constraints which are not marked to be propagated 694 * 695 * @note if a constraint gets unmarked for propagation, it is put into the right part depending on its age 696 */ 697 static 698 void conshdlrUnmarkConsPropagate( 699 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 700 SCIP_CONS* cons /**< constraint to be marked obsolete */ 701 ) 702 { 703 SCIP_CONS* tmpcons; 704 705 assert(conshdlr != NULL); 706 assert(conshdlr->nmarkedpropconss <= conshdlr->nusefulpropconss); 707 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 708 assert(cons != NULL); 709 assert(!cons->original); 710 711 /* it may happen that the constraint is deleted while updates are delayed: in this case we just return */ 712 if( !cons->enabled ) 713 return; 714 715 if( !cons->markpropagate ) 716 return; 717 718 cons->markpropagate = FALSE; 719 720 /* propagation of the constraint is globally or locally disabled, so we do not have to move the constraint in the 721 * propconss array 722 */ 723 if( !cons->propagate || !cons->propenabled ) 724 { 725 assert(cons->propconsspos == -1); 726 return; 727 } 728 assert(cons->propconsspos >= 0); 729 assert(cons->propconsspos < conshdlr->nmarkedpropconss); 730 731 /* first, move the constraint out of the first part to the second part of the constraint array */ 732 if( cons->propconsspos < conshdlr->nmarkedpropconss - 1 ) 733 { 734 conshdlr->nmarkedpropconss--; 735 736 /* switch the last marked prop constraint with this constraint */ 737 tmpcons = conshdlr->propconss[conshdlr->nmarkedpropconss]; 738 assert(tmpcons->propconsspos == conshdlr->nmarkedpropconss); 739 740 conshdlr->propconss[conshdlr->nmarkedpropconss] = cons; 741 conshdlr->propconss[cons->propconsspos] = tmpcons; 742 tmpcons->propconsspos = cons->propconsspos; 743 cons->propconsspos = conshdlr->nmarkedpropconss; 744 } 745 else if( cons->propconsspos == conshdlr->nmarkedpropconss - 1 ) 746 conshdlr->nmarkedpropconss--; 747 assert(cons->propconsspos == conshdlr->nmarkedpropconss); 748 749 /* if the constraint is obsolete, move it to the last part of the constraint array */ 750 if( cons->obsolete ) 751 { 752 conshdlr->nusefulpropconss--; 753 754 /* switch the last useful prop constraint with this constraint */ 755 tmpcons = conshdlr->propconss[conshdlr->nusefulpropconss]; 756 assert(tmpcons->propconsspos == conshdlr->nusefulpropconss); 757 758 conshdlr->propconss[conshdlr->nusefulpropconss] = cons; 759 conshdlr->propconss[cons->propconsspos] = tmpcons; 760 tmpcons->propconsspos = cons->propconsspos; 761 cons->propconsspos = conshdlr->nusefulpropconss; 762 } 763 764 checkConssArrays(conshdlr); 765 } 766 767 768 /** adds constraint to the conss array of constraint handler */ 769 static 770 SCIP_RETCODE conshdlrAddCons( 771 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 772 SCIP_SET* set, /**< global SCIP settings */ 773 SCIP_CONS* cons /**< constraint to add */ 774 ) 775 { 776 assert(conshdlr != NULL); 777 assert(cons != NULL); 778 assert(cons->conshdlr == conshdlr); 779 assert(!cons->original); 780 assert(!cons->active); 781 assert(cons->consspos == -1); 782 assert(set != NULL); 783 assert(cons->scip == set->scip); 784 785 /* insert the constraint as inactive constraint into the transformed constraints array */ 786 SCIP_CALL( conshdlrEnsureConssMem(conshdlr, set, conshdlr->nconss+1) ); 787 conshdlr->conss[conshdlr->nconss] = cons; 788 cons->consspos = conshdlr->nconss; 789 conshdlr->nconss++; 790 791 return SCIP_OKAY; 792 } 793 794 /** deletes constraint from the conss array of constraint handler */ 795 static 796 void conshdlrDelCons( 797 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 798 SCIP_CONS* cons /**< constraint to remove */ 799 ) 800 { 801 assert(conshdlr != NULL); 802 assert(cons != NULL); 803 assert(cons->conshdlr == conshdlr); 804 assert(!cons->original); 805 assert(!cons->active); 806 assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss); 807 808 conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nconss-1]; 809 conshdlr->conss[cons->consspos]->consspos = cons->consspos; 810 conshdlr->nconss--; 811 cons->consspos = -1; 812 } 813 814 /** adds constraint to the initconss array of constraint handler */ 815 static 816 SCIP_RETCODE conshdlrAddInitcons( 817 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 818 SCIP_SET* set, /**< global SCIP settings */ 819 SCIP_STAT* stat, /**< dynamic problem statistics */ 820 SCIP_CONS* cons /**< constraint to add */ 821 ) 822 { 823 int insertpos; 824 825 assert(conshdlr != NULL); 826 assert(cons != NULL); 827 assert(cons->conshdlr == conshdlr); 828 assert(!cons->original); 829 assert(cons->active); 830 assert(cons->initial); 831 assert(cons->initconsspos == -1 || cons->initconsspos < conshdlr->ninitconsskept); 832 833 SCIP_CALL( conshdlrEnsureInitconssMem(conshdlr, set, conshdlr->ninitconss+1) ); 834 835 insertpos = conshdlr->ninitconss; 836 837 conshdlr->initconss[insertpos] = cons; 838 conshdlr->ninitconss++; 839 stat->ninitconssadded++; 840 841 /* if the constraint is kept, we keep the stored position at the beginning of the array */ 842 if( cons->initconsspos == -1 ) 843 cons->initconsspos = insertpos; 844 845 checkConssArrays(conshdlr); 846 847 return SCIP_OKAY; 848 } 849 850 /** deletes constraint from the initconss array of constraint handler */ 851 static 852 void conshdlrDelInitcons( 853 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 854 SCIP_CONS* cons /**< constraint to remove */ 855 ) 856 { 857 int delpos; 858 859 assert(conshdlr != NULL); 860 assert(cons != NULL); 861 assert(cons->conshdlr == conshdlr); 862 assert(!cons->original); 863 assert(0 <= cons->initconsspos && cons->initconsspos < conshdlr->ninitconss); 864 865 delpos = cons->initconsspos; 866 if( delpos < conshdlr->ninitconsskept ) 867 { 868 conshdlr->ninitconsskept--; 869 conshdlr->initconss[delpos] = conshdlr->initconss[conshdlr->ninitconsskept]; 870 conshdlr->initconss[delpos]->initconsspos = delpos; 871 delpos = conshdlr->ninitconsskept; 872 } 873 874 if( delpos < conshdlr->ninitconss-1 ) 875 { 876 conshdlr->initconss[delpos] = conshdlr->initconss[conshdlr->ninitconss-1]; 877 conshdlr->initconss[delpos]->initconsspos = delpos; 878 } 879 conshdlr->ninitconss--; 880 cons->initconsspos = -1; 881 882 checkConssArrays(conshdlr); 883 } 884 885 /** adds constraint to the sepaconss array of constraint handler */ 886 static 887 SCIP_RETCODE conshdlrAddSepacons( 888 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 889 SCIP_SET* set, /**< global SCIP settings */ 890 SCIP_CONS* cons /**< constraint to add */ 891 ) 892 { 893 int insertpos; 894 895 assert(conshdlr != NULL); 896 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 897 assert(cons != NULL); 898 assert(cons->conshdlr == conshdlr); 899 assert(!cons->original); 900 assert(cons->active); 901 assert(cons->separate); 902 assert(cons->sepaenabled); 903 assert(cons->sepaconsspos == -1); 904 assert(set != NULL); 905 assert(cons->scip == set->scip); 906 assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringsepa); 907 908 SCIP_CALL( conshdlrEnsureSepaconssMem(conshdlr, set, conshdlr->nsepaconss+1) ); 909 insertpos = conshdlr->nsepaconss; 910 if( !cons->obsolete ) 911 { 912 if( conshdlr->nusefulsepaconss < conshdlr->nsepaconss ) 913 { 914 conshdlr->sepaconss[conshdlr->nsepaconss] = conshdlr->sepaconss[conshdlr->nusefulsepaconss]; 915 conshdlr->sepaconss[conshdlr->nsepaconss]->sepaconsspos = conshdlr->nsepaconss; 916 insertpos = conshdlr->nusefulsepaconss; 917 } 918 conshdlr->nusefulsepaconss++; 919 } 920 conshdlr->sepaconss[insertpos] = cons; 921 cons->sepaconsspos = insertpos; 922 conshdlr->nsepaconss++; 923 924 checkConssArrays(conshdlr); 925 926 return SCIP_OKAY; 927 } 928 929 /** deletes constraint from the sepaconss array of constraint handler */ 930 static 931 void conshdlrDelSepacons( 932 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 933 SCIP_CONS* cons /**< constraint to remove */ 934 ) 935 { 936 int delpos; 937 938 assert(conshdlr != NULL); 939 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 940 assert(cons != NULL); 941 assert(cons->conshdlr == conshdlr); 942 assert(!cons->original); 943 assert(cons->separate); 944 assert(cons->sepaenabled); 945 assert(cons->sepaconsspos != -1); 946 assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringsepa); 947 948 delpos = cons->sepaconsspos; 949 if( !cons->obsolete ) 950 { 951 assert(0 <= delpos && delpos < conshdlr->nusefulsepaconss); 952 953 if( delpos < conshdlr->lastnusefulsepaconss ) 954 conshdlr->lastnusefulsepaconss--; 955 956 conshdlr->sepaconss[delpos] = conshdlr->sepaconss[conshdlr->nusefulsepaconss-1]; 957 conshdlr->sepaconss[delpos]->sepaconsspos = delpos; 958 delpos = conshdlr->nusefulsepaconss-1; 959 conshdlr->nusefulsepaconss--; 960 assert(conshdlr->nusefulsepaconss >= 0); 961 assert(conshdlr->lastnusefulsepaconss >= 0); 962 } 963 assert(conshdlr->nusefulsepaconss <= delpos && delpos < conshdlr->nsepaconss); 964 if( delpos < conshdlr->nsepaconss-1 ) 965 { 966 conshdlr->sepaconss[delpos] = conshdlr->sepaconss[conshdlr->nsepaconss-1]; 967 conshdlr->sepaconss[delpos]->sepaconsspos = delpos; 968 } 969 conshdlr->nsepaconss--; 970 cons->sepaconsspos = -1; 971 972 checkConssArrays(conshdlr); 973 } 974 975 /** adds constraint to the enfoconss array of constraint handler */ 976 static 977 SCIP_RETCODE conshdlrAddEnfocons( 978 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 979 SCIP_SET* set, /**< global SCIP settings */ 980 SCIP_CONS* cons /**< constraint to add */ 981 ) 982 { 983 int insertpos; 984 985 assert(conshdlr != NULL); 986 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 987 assert(cons != NULL); 988 assert(cons->conshdlr == conshdlr); 989 assert(!cons->original); 990 assert(cons->active); 991 assert(cons->enforce); 992 assert(cons->enfoconsspos == -1); 993 assert(set != NULL); 994 assert(cons->scip == set->scip); 995 996 SCIP_CALL( conshdlrEnsureEnfoconssMem(conshdlr, set, conshdlr->nenfoconss+1) ); 997 insertpos = conshdlr->nenfoconss; 998 if( !cons->obsolete ) 999 { 1000 if( conshdlr->nusefulenfoconss < conshdlr->nenfoconss ) 1001 { 1002 conshdlr->enfoconss[conshdlr->nenfoconss] = conshdlr->enfoconss[conshdlr->nusefulenfoconss]; 1003 conshdlr->enfoconss[conshdlr->nenfoconss]->enfoconsspos = conshdlr->nenfoconss; 1004 insertpos = conshdlr->nusefulenfoconss; 1005 } 1006 conshdlr->nusefulenfoconss++; 1007 } 1008 else 1009 { 1010 /* we have to make sure that even this obsolete constraint is enforced in the next enforcement call; 1011 * if the same LP or pseudo solution is enforced again, only the newly added useful constraints are 1012 * enforced; thus, we have to reset the enforcement counters and force all constraints to be 1013 * enforced again; this is not needed for separation and propagation, because they are not vital for correctness 1014 */ 1015 conshdlr->lastenfolplpcount = -1; 1016 conshdlr->lastenfolpdomchgcount = -1; 1017 conshdlr->lastenfopsdomchgcount = -1; 1018 conshdlr->lastenforelaxdomchgcount = -1; 1019 conshdlr->lastenforelaxrelaxcount = -1; 1020 conshdlr->lastenfolpnode = -1; 1021 conshdlr->lastenfopsnode = -1; 1022 } 1023 conshdlr->enfoconss[insertpos] = cons; 1024 cons->enfoconsspos = insertpos; 1025 conshdlr->nenfoconss++; 1026 1027 checkConssArrays(conshdlr); 1028 1029 return SCIP_OKAY; 1030 } 1031 1032 /** deletes constraint from the enfoconss array of constraint handler */ 1033 static 1034 void conshdlrDelEnfocons( 1035 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1036 SCIP_CONS* cons /**< constraint to remove */ 1037 ) 1038 { 1039 int delpos; 1040 1041 assert(conshdlr != NULL); 1042 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 1043 assert(cons != NULL); 1044 assert(cons->conshdlr == conshdlr); 1045 assert(!cons->original); 1046 assert(cons->enforce); 1047 assert(cons->enfoconsspos != -1); 1048 1049 delpos = cons->enfoconsspos; 1050 if( !cons->obsolete ) 1051 { 1052 assert(0 <= delpos && delpos < conshdlr->nusefulenfoconss); 1053 1054 if( delpos < conshdlr->lastnusefulenfoconss ) 1055 conshdlr->lastnusefulenfoconss--; 1056 1057 conshdlr->enfoconss[delpos] = conshdlr->enfoconss[conshdlr->nusefulenfoconss-1]; 1058 conshdlr->enfoconss[delpos]->enfoconsspos = delpos; 1059 delpos = conshdlr->nusefulenfoconss-1; 1060 conshdlr->nusefulenfoconss--; 1061 1062 /* if the constraint that moved to the free position was a newly added constraint and not enforced in the last 1063 * enforcement, we have to make sure it will be enforced in the next run; 1064 * this check is not performed for separation and propagation, because they are not vital for correctness 1065 */ 1066 if( delpos >= conshdlr->lastnusefulenfoconss ) 1067 conshdlr->lastnusefulenfoconss = cons->enfoconsspos; 1068 1069 assert(conshdlr->nusefulenfoconss >= 0); 1070 assert(conshdlr->lastnusefulenfoconss >= 0); 1071 } 1072 assert(conshdlr->nusefulenfoconss <= delpos && delpos < conshdlr->nenfoconss); 1073 if( delpos < conshdlr->nenfoconss-1 ) 1074 { 1075 conshdlr->enfoconss[delpos] = conshdlr->enfoconss[conshdlr->nenfoconss-1]; 1076 conshdlr->enfoconss[delpos]->enfoconsspos = delpos; 1077 } 1078 conshdlr->nenfoconss--; 1079 cons->enfoconsspos = -1; 1080 1081 checkConssArrays(conshdlr); 1082 } 1083 1084 /** adds constraint to the checkconss array of constraint handler */ 1085 static 1086 SCIP_RETCODE conshdlrAddCheckcons( 1087 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1088 SCIP_SET* set, /**< global SCIP settings */ 1089 SCIP_CONS* cons /**< constraint to add */ 1090 ) 1091 { 1092 int insertpos; 1093 1094 assert(conshdlr != NULL); 1095 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1096 assert(cons != NULL); 1097 assert(cons->conshdlr == conshdlr); 1098 assert(!cons->original); 1099 assert(cons->active); 1100 assert(cons->check); 1101 assert(cons->checkconsspos == -1); 1102 assert(set != NULL); 1103 assert(cons->scip == set->scip); 1104 1105 SCIP_CALL( conshdlrEnsureCheckconssMem(conshdlr, set, conshdlr->ncheckconss+1) ); 1106 insertpos = conshdlr->ncheckconss; 1107 if( !cons->obsolete ) 1108 { 1109 if( conshdlr->nusefulcheckconss < conshdlr->ncheckconss ) 1110 { 1111 assert(conshdlr->checkconss[conshdlr->nusefulcheckconss] != NULL); 1112 conshdlr->checkconss[conshdlr->ncheckconss] = conshdlr->checkconss[conshdlr->nusefulcheckconss]; 1113 conshdlr->checkconss[conshdlr->ncheckconss]->checkconsspos = conshdlr->ncheckconss; 1114 insertpos = conshdlr->nusefulcheckconss; 1115 } 1116 conshdlr->nusefulcheckconss++; 1117 } 1118 assert(0 <= insertpos && insertpos <= conshdlr->ncheckconss); 1119 conshdlr->checkconss[insertpos] = cons; 1120 cons->checkconsspos = insertpos; 1121 conshdlr->ncheckconss++; 1122 1123 checkConssArrays(conshdlr); 1124 1125 return SCIP_OKAY; 1126 } 1127 1128 /** deletes constraint from the checkconss array of constraint handler */ 1129 static 1130 void conshdlrDelCheckcons( 1131 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1132 SCIP_CONS* cons /**< constraint to add */ 1133 ) 1134 { 1135 int delpos; 1136 1137 assert(conshdlr != NULL); 1138 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1139 assert(cons != NULL); 1140 assert(cons->conshdlr == conshdlr); 1141 assert(!cons->original); 1142 assert(cons->active); 1143 assert(cons->check); 1144 assert(cons->checkconsspos != -1); 1145 1146 delpos = cons->checkconsspos; 1147 if( !cons->obsolete ) 1148 { 1149 assert(0 <= delpos && delpos < conshdlr->nusefulcheckconss); 1150 conshdlr->checkconss[delpos] = conshdlr->checkconss[conshdlr->nusefulcheckconss-1]; 1151 conshdlr->checkconss[delpos]->checkconsspos = delpos; 1152 delpos = conshdlr->nusefulcheckconss-1; 1153 conshdlr->nusefulcheckconss--; 1154 } 1155 assert(conshdlr->nusefulcheckconss <= delpos && delpos < conshdlr->ncheckconss); 1156 if( delpos < conshdlr->ncheckconss-1 ) 1157 { 1158 conshdlr->checkconss[delpos] = conshdlr->checkconss[conshdlr->ncheckconss-1]; 1159 conshdlr->checkconss[delpos]->checkconsspos = delpos; 1160 } 1161 conshdlr->ncheckconss--; 1162 cons->checkconsspos = -1; 1163 1164 checkConssArrays(conshdlr); 1165 } 1166 1167 /** adds constraint to the propconss array of constraint handler */ 1168 static 1169 SCIP_RETCODE conshdlrAddPropcons( 1170 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1171 SCIP_SET* set, /**< global SCIP settings */ 1172 SCIP_CONS* cons /**< constraint to add */ 1173 ) 1174 { 1175 int insertpos; 1176 1177 assert(conshdlr != NULL); 1178 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1179 assert(cons != NULL); 1180 assert(cons->conshdlr == conshdlr); 1181 assert(!cons->original); 1182 assert(cons->active); 1183 assert(cons->enabled); 1184 assert(cons->propagate); 1185 assert(cons->propenabled); 1186 assert(cons->propconsspos == -1); 1187 assert(set != NULL); 1188 assert(cons->scip == set->scip); 1189 assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringprop); 1190 1191 /* add constraint to the propagation array */ 1192 SCIP_CALL( conshdlrEnsurePropconssMem(conshdlr, set, conshdlr->npropconss+1) ); 1193 insertpos = conshdlr->npropconss; 1194 if( !cons->obsolete ) 1195 { 1196 if( conshdlr->nusefulpropconss < conshdlr->npropconss ) 1197 { 1198 conshdlr->propconss[conshdlr->npropconss] = conshdlr->propconss[conshdlr->nusefulpropconss]; 1199 conshdlr->propconss[conshdlr->npropconss]->propconsspos = conshdlr->npropconss; 1200 insertpos = conshdlr->nusefulpropconss; 1201 } 1202 conshdlr->nusefulpropconss++; 1203 } 1204 conshdlr->propconss[insertpos] = cons; 1205 cons->propconsspos = insertpos; 1206 conshdlr->npropconss++; 1207 1208 /* if the constraint is marked to be propagated, we have to move it to the first part of the array */ 1209 if( cons->markpropagate ) 1210 { 1211 /* temporarily unmark the constraint to be propagated, such that we can use the method below */ 1212 cons->markpropagate = FALSE; 1213 1214 conshdlrMarkConsPropagate(cons->conshdlr, cons); 1215 assert(cons->markpropagate); 1216 } 1217 1218 checkConssArrays(conshdlr); 1219 1220 return SCIP_OKAY; 1221 } 1222 1223 /** deletes constraint from the propconss array of constraint handler */ 1224 static 1225 void conshdlrDelPropcons( 1226 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1227 SCIP_CONS* cons /**< constraint to remove */ 1228 ) 1229 { 1230 int delpos; 1231 1232 assert(conshdlr != NULL); 1233 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1234 assert(cons != NULL); 1235 assert(cons->conshdlr == conshdlr); 1236 assert(!cons->original); 1237 assert(cons->propagate); 1238 assert(cons->propenabled); 1239 assert(cons->propconsspos != -1); 1240 assert(!conshdlrAreUpdatesDelayed(conshdlr) || !conshdlr->duringprop); 1241 1242 /* unmark constraint to be propagated; this will move the constraint to the obsolete or non-obsolete part of the 1243 * array, depending on its age 1244 */ 1245 if( cons->markpropagate ) 1246 { 1247 conshdlrUnmarkConsPropagate(cons->conshdlr, cons); 1248 assert(!cons->markpropagate); 1249 } 1250 1251 /* delete constraint from the propagation array */ 1252 delpos = cons->propconsspos; 1253 assert(delpos >= conshdlr->nmarkedpropconss); 1254 if( !cons->obsolete ) 1255 { 1256 assert(0 <= delpos && delpos < conshdlr->nusefulpropconss); 1257 1258 if( delpos < conshdlr->lastnusefulpropconss ) 1259 conshdlr->lastnusefulpropconss--; 1260 1261 conshdlr->propconss[delpos] = conshdlr->propconss[conshdlr->nusefulpropconss-1]; 1262 conshdlr->propconss[delpos]->propconsspos = delpos; 1263 delpos = conshdlr->nusefulpropconss-1; 1264 conshdlr->nusefulpropconss--; 1265 assert(conshdlr->nusefulpropconss >= 0); 1266 assert(conshdlr->lastnusefulpropconss >= 0); 1267 } 1268 assert(conshdlr->nusefulpropconss <= delpos && delpos < conshdlr->npropconss); 1269 1270 if( delpos < conshdlr->npropconss-1 ) 1271 { 1272 conshdlr->propconss[delpos] = conshdlr->propconss[conshdlr->npropconss-1]; 1273 conshdlr->propconss[delpos]->propconsspos = delpos; 1274 } 1275 conshdlr->npropconss--; 1276 cons->propconsspos = -1; 1277 assert(conshdlr->nmarkedpropconss <= conshdlr->npropconss); 1278 1279 checkConssArrays(conshdlr); 1280 } 1281 1282 /** enables separation of constraint */ 1283 static 1284 SCIP_RETCODE conshdlrEnableConsSeparation( 1285 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1286 SCIP_SET* set, /**< global SCIP settings */ 1287 SCIP_CONS* cons /**< constraint to add */ 1288 ) 1289 { 1290 assert(conshdlr != NULL); 1291 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1292 assert(cons != NULL); 1293 assert(cons->conshdlr == conshdlr); 1294 assert(!cons->sepaenabled); 1295 assert(cons->sepaconsspos == -1); 1296 assert(set != NULL); 1297 assert(cons->scip == set->scip); 1298 1299 SCIPsetDebugMsg(set, "enable separation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1300 1301 /* enable separation of constraint */ 1302 cons->sepaenabled = TRUE; 1303 1304 /* add constraint to the separation array */ 1305 if( cons->enabled && cons->separate ) 1306 { 1307 SCIP_CALL( conshdlrAddSepacons(conshdlr, set, cons) ); 1308 } 1309 1310 return SCIP_OKAY; 1311 } 1312 1313 /** disables separation of constraint */ 1314 static 1315 SCIP_RETCODE conshdlrDisableConsSeparation( 1316 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1317 SCIP_CONS* cons /**< constraint to remove */ 1318 ) 1319 { 1320 assert(conshdlr != NULL); 1321 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1322 assert(cons != NULL); 1323 assert(cons->conshdlr == conshdlr); 1324 assert(cons->sepaenabled); 1325 assert((cons->separate && cons->enabled) == (cons->sepaconsspos != -1)); 1326 1327 SCIPdebugMessage("disable separation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1328 1329 /* delete constraint from the separation array */ 1330 if( cons->separate && cons->enabled ) 1331 { 1332 conshdlrDelSepacons(conshdlr, cons); 1333 } 1334 assert(cons->sepaconsspos == -1); 1335 1336 /* disable separation of constraint */ 1337 cons->sepaenabled = FALSE; 1338 1339 return SCIP_OKAY; 1340 } 1341 1342 /** enables propagation of constraint */ 1343 static 1344 SCIP_RETCODE conshdlrEnableConsPropagation( 1345 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1346 SCIP_SET* set, /**< global SCIP settings */ 1347 SCIP_CONS* cons /**< constraint to add */ 1348 ) 1349 { 1350 assert(conshdlr != NULL); 1351 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1352 assert(cons != NULL); 1353 assert(cons->conshdlr == conshdlr); 1354 assert(!cons->propenabled); 1355 assert(cons->propconsspos == -1); 1356 assert(set != NULL); 1357 assert(cons->scip == set->scip); 1358 1359 SCIPsetDebugMsg(set, "enable propagation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1360 1361 /* enable propagation of constraint */ 1362 cons->propenabled = TRUE; 1363 1364 /* add constraint to the propagation array */ 1365 if( cons->enabled && cons->propagate ) 1366 { 1367 SCIP_CALL( conshdlrAddPropcons(conshdlr, set, cons) ); 1368 } 1369 1370 return SCIP_OKAY; 1371 } 1372 1373 /** disables propagation of constraint */ 1374 static 1375 SCIP_RETCODE conshdlrDisableConsPropagation( 1376 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1377 SCIP_CONS* cons /**< constraint to remove */ 1378 ) 1379 { 1380 assert(conshdlr != NULL); 1381 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1382 assert(cons != NULL); 1383 assert(cons->conshdlr == conshdlr); 1384 assert(cons->propenabled); 1385 assert((cons->propagate && cons->enabled) == (cons->propconsspos != -1)); 1386 1387 SCIPdebugMessage("disable propagation of constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1388 1389 /* delete constraint from the propagation array */ 1390 if( cons->propagate && cons->enabled ) 1391 { 1392 conshdlrDelPropcons(conshdlr, cons); 1393 } 1394 assert(cons->propconsspos == -1); 1395 1396 /* disable propagation of constraint */ 1397 cons->propenabled = FALSE; 1398 1399 return SCIP_OKAY; 1400 } 1401 1402 /** enables separation, enforcement, and propagation of constraint */ 1403 static 1404 SCIP_RETCODE conshdlrEnableCons( 1405 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1406 SCIP_SET* set, /**< global SCIP settings */ 1407 SCIP_STAT* stat, /**< dynamic problem statistics */ 1408 SCIP_CONS* cons /**< constraint to add */ 1409 ) 1410 { 1411 assert(conshdlr != NULL); 1412 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1413 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 1414 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1415 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1416 assert(set != NULL); 1417 assert(stat != NULL); 1418 assert(cons != NULL); 1419 assert(cons->scip == set->scip); 1420 assert(cons->conshdlr == conshdlr); 1421 assert(!cons->original); 1422 assert(cons->active); 1423 assert(!cons->enabled); 1424 assert(cons->sepaconsspos == -1); 1425 assert(cons->enfoconsspos == -1); 1426 assert(cons->propconsspos == -1); 1427 1428 SCIPsetDebugMsg(set, "enable constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1429 1430 /* enable constraint */ 1431 cons->enabled = TRUE; 1432 conshdlr->nenabledconss++; 1433 stat->nenabledconss++; 1434 1435 /* add constraint to the separation array */ 1436 if( cons->separate && cons->sepaenabled ) 1437 { 1438 SCIP_CALL( conshdlrAddSepacons(conshdlr, set, cons) ); 1439 } 1440 1441 /* add constraint to the enforcement array */ 1442 if( cons->enforce ) 1443 { 1444 SCIP_CALL( conshdlrAddEnfocons(conshdlr, set, cons) ); 1445 } 1446 1447 /* add constraint to the propagation array */ 1448 if( cons->propagate && cons->propenabled ) 1449 { 1450 SCIP_CALL( conshdlrAddPropcons(conshdlr, set, cons) ); 1451 } 1452 1453 /* call constraint handler's enabling notification method */ 1454 if( conshdlr->consenable != NULL ) 1455 { 1456 SCIP_CALL( conshdlr->consenable(set->scip, conshdlr, cons) ); 1457 } 1458 1459 checkConssArrays(conshdlr); 1460 1461 return SCIP_OKAY; 1462 } 1463 1464 /** disables separation, enforcement, and propagation of constraint */ 1465 static 1466 SCIP_RETCODE conshdlrDisableCons( 1467 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1468 SCIP_SET* set, /**< global SCIP settings */ 1469 SCIP_STAT* stat, /**< dynamic problem statistics */ 1470 SCIP_CONS* cons /**< constraint to remove */ 1471 ) 1472 { 1473 assert(conshdlr != NULL); 1474 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1475 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 1476 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1477 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1478 assert(set != NULL); 1479 assert(stat != NULL); 1480 assert(cons != NULL); 1481 assert(cons->scip == set->scip); 1482 assert(cons->conshdlr == conshdlr); 1483 assert(!cons->original); 1484 assert(cons->active); 1485 assert(cons->enabled); 1486 assert((cons->separate && cons->sepaenabled) == (cons->sepaconsspos != -1)); 1487 assert(cons->enforce == (cons->enfoconsspos != -1)); 1488 assert((cons->propagate && cons->propenabled) == (cons->propconsspos != -1)); 1489 1490 SCIPsetDebugMsg(set, "disable constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1491 1492 /* call constraint handler's disabling notification method */ 1493 if( conshdlr->consdisable != NULL ) 1494 { 1495 SCIP_CALL( conshdlr->consdisable(set->scip, conshdlr, cons) ); 1496 } 1497 1498 /* delete constraint from the separation array */ 1499 if( cons->separate && cons->sepaenabled ) 1500 { 1501 conshdlrDelSepacons(conshdlr, cons); 1502 } 1503 1504 /* delete constraint from the enforcement array */ 1505 if( cons->enforce ) 1506 { 1507 conshdlrDelEnfocons(conshdlr, cons); 1508 } 1509 1510 /* delete constraint from the propagation array */ 1511 if( cons->propagate && cons->propenabled ) 1512 { 1513 conshdlrDelPropcons(conshdlr, cons); 1514 } 1515 1516 assert(cons->sepaconsspos == -1); 1517 assert(cons->enfoconsspos == -1); 1518 assert(cons->propconsspos == -1); 1519 1520 /* disable constraint */ 1521 cons->enabled = FALSE; 1522 conshdlr->nenabledconss--; 1523 stat->nenabledconss--; 1524 1525 checkConssArrays(conshdlr); 1526 1527 return SCIP_OKAY; 1528 } 1529 1530 /** activates and adds constraint to constraint handler's constraint arrays */ 1531 static 1532 SCIP_RETCODE conshdlrActivateCons( 1533 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1534 SCIP_SET* set, /**< global SCIP settings */ 1535 SCIP_STAT* stat, /**< dynamic problem statistics */ 1536 SCIP_CONS* cons, /**< constraint to add */ 1537 int depth, /**< depth in the tree where the activation takes place, or -1 for global problem */ 1538 SCIP_Bool focusnode /**< does the constraint activation take place at the focus node? */ 1539 ) 1540 { 1541 assert(conshdlr != NULL); 1542 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1543 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 1544 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1545 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1546 assert(set != NULL); 1547 assert(stat != NULL); 1548 assert(cons != NULL); 1549 assert(cons->scip == set->scip); 1550 assert(cons->conshdlr == conshdlr); 1551 assert(!cons->original); 1552 assert(!cons->active); 1553 assert(!cons->enabled); 1554 assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss); 1555 assert(conshdlr->conss[cons->consspos] == cons); 1556 assert(cons->initconsspos < conshdlr->ninitconsskept); 1557 assert(cons->sepaconsspos == -1); 1558 assert(cons->enfoconsspos == -1); 1559 assert(cons->checkconsspos == -1); 1560 assert(cons->propconsspos == -1); 1561 assert(depth >= -1); 1562 1563 SCIPsetDebugMsg(set, "activate constraint <%s> in constraint handler <%s> (depth %d, focus=%u)\n", 1564 cons->name, conshdlr->name, depth, focusnode); 1565 1566 /* activate constraint, switch positions with first inactive constraint */ 1567 cons->active = TRUE; 1568 cons->activedepth = depth; 1569 conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nactiveconss]; 1570 conshdlr->conss[cons->consspos]->consspos = cons->consspos; 1571 conshdlr->conss[conshdlr->nactiveconss] = cons; 1572 cons->consspos = conshdlr->nactiveconss; 1573 conshdlr->nactiveconss++; 1574 conshdlr->maxnactiveconss = MAX(conshdlr->maxnactiveconss, conshdlr->nactiveconss); 1575 stat->nactiveconss++; 1576 1577 /* add constraint to the check array */ 1578 if( cons->check ) 1579 { 1580 SCIP_CALL( conshdlrAddCheckcons(conshdlr, set, cons) ); 1581 } 1582 1583 /* add constraint to the initconss array if the constraint is initial and added to the focus node */ 1584 if( cons->initial ) 1585 { 1586 SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, cons) ); 1587 } 1588 1589 /* call constraint handler's activation notification method */ 1590 if( conshdlr->consactive != NULL ) 1591 { 1592 SCIP_CALL( conshdlr->consactive(set->scip, conshdlr, cons) ); 1593 } 1594 1595 /* enable separation, enforcement, and propagation of constraint */ 1596 SCIP_CALL( conshdlrEnableCons(conshdlr, set, stat, cons) ); 1597 1598 assert(0 <= cons->consspos && cons->consspos < conshdlr->nactiveconss); 1599 1600 checkConssArrays(conshdlr); 1601 1602 return SCIP_OKAY; 1603 } 1604 1605 /** deactivates and removes constraint from constraint handler's conss array */ 1606 static 1607 SCIP_RETCODE conshdlrDeactivateCons( 1608 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1609 SCIP_SET* set, /**< global SCIP settings */ 1610 SCIP_STAT* stat, /**< dynamic problem statistics */ 1611 SCIP_CONS* cons /**< constraint to remove */ 1612 ) 1613 { 1614 assert(conshdlr != NULL); 1615 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1616 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 1617 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1618 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1619 assert(set != NULL); 1620 assert(stat != NULL); 1621 assert(cons != NULL); 1622 assert(cons->scip == set->scip); 1623 assert(cons->conshdlr == conshdlr); 1624 assert(!cons->original); 1625 assert(cons->active); 1626 assert(0 <= cons->consspos && cons->consspos < conshdlr->nactiveconss); 1627 assert(conshdlr->conss[cons->consspos] == cons); 1628 assert(cons->check == (cons->checkconsspos != -1)); 1629 1630 SCIPsetDebugMsg(set, "deactivate constraint <%s> in constraint handler <%s>\n", cons->name, conshdlr->name); 1631 1632 /* disable constraint */ 1633 if( cons->enabled ) 1634 { 1635 SCIP_CALL( conshdlrDisableCons(conshdlr, set, stat, cons) ); 1636 } 1637 assert(!cons->enabled); 1638 1639 /* call constraint handler's deactivation notification method */ 1640 if( conshdlr->consdeactive != NULL ) 1641 { 1642 SCIP_CALL( conshdlr->consdeactive(set->scip, conshdlr, cons) ); 1643 } 1644 1645 /* delete constraint from the initconss array */ 1646 if( cons->initconsspos >= 0 ) 1647 { 1648 conshdlrDelInitcons(conshdlr, cons); 1649 } 1650 1651 /* delete constraint from the check array */ 1652 if( cons->check ) 1653 { 1654 conshdlrDelCheckcons(conshdlr, cons); 1655 } 1656 1657 /* switch constraint with the last active constraint in the conss array */ 1658 conshdlr->conss[cons->consspos] = conshdlr->conss[conshdlr->nactiveconss-1]; 1659 conshdlr->conss[cons->consspos]->consspos = cons->consspos; 1660 conshdlr->conss[conshdlr->nactiveconss-1] = cons; 1661 cons->consspos = conshdlr->nactiveconss-1; 1662 conshdlr->nactiveconss--; 1663 cons->active = FALSE; 1664 cons->activedepth = -2; 1665 stat->nactiveconss--; 1666 1667 assert(conshdlr->nactiveconss <= cons->consspos && cons->consspos < conshdlr->nconss); 1668 assert(cons->initconsspos == -1); 1669 assert(cons->sepaconsspos == -1); 1670 assert(cons->enfoconsspos == -1); 1671 assert(cons->checkconsspos == -1); 1672 assert(cons->propconsspos == -1); 1673 1674 checkConssArrays(conshdlr); 1675 1676 return SCIP_OKAY; 1677 } 1678 1679 /** processes all delayed updates of constraints: 1680 * recently (de)activated constraints will be (de)activated; 1681 * recently en/disabled constraints will be en/disabled; 1682 * recent obsolete non-check constraints will be globally deleted; 1683 * recent obsolete check constraints will be moved to the last positions in the sepa-, enfo-, check-, and prop-arrays; 1684 * recent useful constraints will be moved to the first positions in the sepa-, enfo-, check-, and prop-arrays; 1685 * constraints which were recently marked to be propagated are moved to the first positions in the prop-array; 1686 * no longer used constraints will be freed and removed from the conss array 1687 */ 1688 static 1689 SCIP_RETCODE conshdlrProcessUpdates( 1690 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1691 BMS_BLKMEM* blkmem, /**< block memory */ 1692 SCIP_SET* set, /**< global SCIP settings */ 1693 SCIP_STAT* stat /**< dynamic problem statistics */ 1694 ) 1695 { 1696 SCIP_CONS* cons; 1697 int i; 1698 1699 assert(conshdlr != NULL); 1700 assert(!conshdlrAreUpdatesDelayed(conshdlr)); 1701 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 1702 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 1703 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 1704 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 1705 1706 SCIPsetDebugMsg(set, "processing %d constraints that have to be updated in constraint handler <%s>\n", 1707 conshdlr->nupdateconss, conshdlr->name); 1708 1709 for( i = conshdlr->nupdateconss - 1; i >= 0; --i ) 1710 { 1711 cons = conshdlr->updateconss[i]; 1712 assert(cons != NULL); 1713 assert(cons->conshdlr == conshdlr); 1714 assert(cons->update); 1715 assert(cons->updateinsert || cons->updateactivate || cons->updatedeactivate 1716 || cons->updateenable || cons->updatedisable 1717 || cons->updatesepaenable || cons->updatesepadisable 1718 || cons->updatepropenable || cons->updatepropdisable 1719 || cons->updateobsolete || cons->updatefree 1720 || cons->updatemarkpropagate || cons->updateunmarkpropagate); 1721 1722 SCIPsetDebugMsg(set, " -> constraint <%s>: insert=%u, activate=%u, deactivate=%u, enable=%u, disable=%u, sepaenable=%u, sepadisable=%u, propenable=%u, propdisable=%u, obsolete=%u, free=%u (consdata=%p)\n", 1723 cons->name, cons->updateinsert, cons->updateactivate, cons->updatedeactivate, 1724 cons->updateenable, cons->updatedisable, 1725 cons->updatesepaenable, cons->updatesepadisable, 1726 cons->updatepropenable, cons->updatepropdisable, 1727 cons->updateobsolete, cons->updatefree, (void*)cons->consdata); 1728 1729 if( cons->updateinsert ) 1730 { 1731 SCIP_CALL( conshdlrAddCons(conshdlr, set, cons) ); 1732 cons->updateinsert = FALSE; 1733 } 1734 1735 if( cons->updateactivate ) 1736 { 1737 assert(!cons->active); 1738 assert(!cons->updatedeactivate); 1739 assert(!cons->updateenable); 1740 assert(!cons->updatedisable); 1741 assert(!cons->updateobsolete); 1742 assert(!cons->updatefree); 1743 1744 /* the activation depth was already stored in SCIPconsActivate() */ 1745 SCIP_CALL( conshdlrActivateCons(conshdlr, set, stat, cons, cons->activedepth, cons->updateactfocus) ); 1746 assert(cons->active); 1747 cons->updateactivate = FALSE; 1748 } 1749 else if( cons->updatedeactivate ) 1750 { 1751 assert(cons->active); 1752 1753 SCIP_CALL( conshdlrDeactivateCons(conshdlr, set, stat, cons) ); 1754 assert(!cons->active); 1755 cons->updatedeactivate = FALSE; 1756 cons->updateenable = FALSE; 1757 cons->updatedisable = FALSE; 1758 cons->obsolete = consExceedsObsoleteage(cons, set); 1759 cons->updateobsolete = FALSE; 1760 } 1761 else if( cons->updateenable ) 1762 { 1763 assert(!cons->enabled); 1764 assert(!cons->updatedisable); 1765 1766 SCIP_CALL( conshdlrEnableCons(conshdlr, set, stat, cons) ); 1767 assert(cons->enabled); 1768 cons->updateenable = FALSE; 1769 } 1770 else if( cons->updatedisable ) 1771 { 1772 assert(cons->enabled); 1773 1774 SCIP_CALL( conshdlrDisableCons(conshdlr, set, stat, cons) ); 1775 assert(!cons->enabled); 1776 cons->updatedisable = FALSE; 1777 } 1778 1779 if( cons->updatesepaenable ) 1780 { 1781 assert(!cons->updatesepadisable); 1782 if( !cons->sepaenabled ) 1783 { 1784 SCIP_CALL( conshdlrEnableConsSeparation(conshdlr, set, cons) ); 1785 assert(cons->sepaenabled); 1786 } 1787 cons->updatesepaenable = FALSE; 1788 } 1789 else if( cons->updatesepadisable ) 1790 { 1791 if( cons->sepaenabled ) 1792 { 1793 SCIP_CALL( conshdlrDisableConsSeparation(conshdlr, cons) ); 1794 assert(!cons->sepaenabled); 1795 } 1796 cons->updatesepadisable = FALSE; 1797 } 1798 1799 if( cons->updatepropenable ) 1800 { 1801 assert(!cons->updatepropdisable); 1802 if( !cons->propenabled ) 1803 { 1804 SCIP_CALL( conshdlrEnableConsPropagation(conshdlr, set, cons) ); 1805 assert(cons->propenabled); 1806 } 1807 cons->updatepropenable = FALSE; 1808 } 1809 else if( cons->updatepropdisable ) 1810 { 1811 if( cons->propenabled ) 1812 { 1813 SCIP_CALL( conshdlrDisableConsPropagation(conshdlr, cons) ); 1814 assert(!cons->propenabled); 1815 } 1816 cons->updatepropdisable = FALSE; 1817 } 1818 1819 if( cons->updatefree ) 1820 { 1821 /* nothing to do here: the constraint is freed, when it is released from the updateconss array */ 1822 assert(cons->nuses == 1); /* it only exists in the updateconss array */ 1823 cons->updatefree = FALSE; 1824 cons->updateobsolete = FALSE; 1825 } 1826 else 1827 { 1828 if( cons->updateobsolete ) 1829 { 1830 if( !cons->obsolete && consExceedsObsoleteage(cons, set) ) 1831 { 1832 /* the constraint's status must be switched to obsolete */ 1833 SCIP_CALL( conshdlrMarkConsObsolete(conshdlr, cons) ); 1834 } 1835 else if( cons->obsolete && !consExceedsObsoleteage(cons, set) ) 1836 { 1837 /* the constraint's status must be switched to useful */ 1838 SCIP_CALL( conshdlrMarkConsUseful(conshdlr, cons) ); 1839 } 1840 cons->updateobsolete = FALSE; 1841 } 1842 1843 if( cons->updatemarkpropagate ) 1844 { 1845 /* the constraint must be marked to be propagated */ 1846 conshdlrMarkConsPropagate(conshdlr, cons); 1847 cons->updatemarkpropagate = FALSE; 1848 } 1849 else if( cons->updateunmarkpropagate ) 1850 { 1851 /* the constraint must be unmarked to be propagated */ 1852 conshdlrUnmarkConsPropagate(conshdlr, cons); 1853 cons->updateunmarkpropagate = FALSE; 1854 } 1855 } 1856 1857 assert(!cons->updateinsert); 1858 assert(!cons->updateactivate); 1859 assert(!cons->updatedeactivate); 1860 assert(!cons->updateenable); 1861 assert(!cons->updatedisable); 1862 assert(!cons->updatesepaenable); 1863 assert(!cons->updatesepadisable); 1864 assert(!cons->updatepropenable); 1865 assert(!cons->updatepropdisable); 1866 assert(!cons->updateobsolete); 1867 assert(!cons->updatemarkpropagate); 1868 assert(!cons->updateunmarkpropagate); 1869 assert(!cons->updatefree); 1870 cons->update = FALSE; 1871 1872 /* release the constraint */ 1873 SCIP_CALL( SCIPconsRelease(&conshdlr->updateconss[i], blkmem, set) ); 1874 } 1875 1876 conshdlr->nupdateconss = 0; 1877 1878 return SCIP_OKAY; 1879 } 1880 1881 /** marks constraint handler to delay all constraint updates until the next conshdlrProcessUpdates() call */ 1882 static 1883 void conshdlrDelayUpdates( 1884 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 1885 ) 1886 { 1887 assert(conshdlr != NULL); 1888 1889 SCIPdebugMessage("constraint updates of constraint handler <%s> will be delayed (count:%d)\n", 1890 conshdlr->name, conshdlr->delayupdatecount+1); 1891 1892 conshdlr->delayupdatecount++; 1893 } 1894 1895 /** marks constraint handler to perform all constraint updates immediately; 1896 * all delayed constraint updates will be processed 1897 */ 1898 static 1899 SCIP_RETCODE conshdlrForceUpdates( 1900 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1901 BMS_BLKMEM* blkmem, /**< block memory */ 1902 SCIP_SET* set, /**< global SCIP settings */ 1903 SCIP_STAT* stat /**< dynamic problem statistics */ 1904 ) 1905 { 1906 assert(conshdlr != NULL); 1907 assert(conshdlrAreUpdatesDelayed(conshdlr)); 1908 1909 SCIPsetDebugMsg(set, "constraint updates of constraint handler <%s> will be processed immediately (count:%d)\n", 1910 conshdlr->name, conshdlr->delayupdatecount); 1911 conshdlr->delayupdatecount--; 1912 1913 /* only run the update if all delays are taken away (reference counting) */ 1914 if( !conshdlrAreUpdatesDelayed(conshdlr) ) 1915 { 1916 SCIP_CALL( conshdlrProcessUpdates(conshdlr, blkmem, set, stat) ); 1917 assert(conshdlr->nupdateconss == 0); 1918 } 1919 1920 return SCIP_OKAY; 1921 } 1922 1923 /** adds constraint to constraint handler's update constraint array and captures it */ 1924 static 1925 SCIP_RETCODE conshdlrAddUpdateCons( 1926 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1927 SCIP_SET* set, /**< global SCIP settings */ 1928 SCIP_CONS* cons /**< constraint to add */ 1929 ) 1930 { 1931 assert(conshdlr != NULL); 1932 assert(set != NULL); 1933 assert(cons != NULL); 1934 assert(cons->conshdlr == conshdlr); 1935 1936 if( !cons->update ) 1937 { 1938 SCIPsetDebugMsg(set, "constraint <%s> of age %g has to be updated in constraint handler <%s> (consdata=%p)\n", 1939 cons->name, cons->age, conshdlr->name, (void*)cons->consdata); 1940 1941 /* add constraint to the updateconss array */ 1942 SCIP_CALL( conshdlrEnsureUpdateconssMem(conshdlr, set, conshdlr->nupdateconss+1) ); 1943 conshdlr->updateconss[conshdlr->nupdateconss] = cons; 1944 conshdlr->nupdateconss++; 1945 1946 /* capture constraint */ 1947 SCIPconsCapture(cons); 1948 1949 cons->update = TRUE; 1950 } 1951 1952 return SCIP_OKAY; 1953 } 1954 1955 /** compares two constraint handlers w.r.t. their separation priority */ 1956 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompSepa) 1957 { /*lint --e{715}*/ 1958 return ((SCIP_CONSHDLR*)elem2)->sepapriority - ((SCIP_CONSHDLR*)elem1)->sepapriority; 1959 } 1960 1961 /** compares two constraint handlers w.r.t. their enforcing priority */ 1962 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompEnfo) 1963 { /*lint --e{715}*/ 1964 return ((SCIP_CONSHDLR*)elem2)->enfopriority - ((SCIP_CONSHDLR*)elem1)->enfopriority; 1965 } 1966 1967 /** compares two constraint handlers w.r.t. their feasibility check priority */ 1968 SCIP_DECL_SORTPTRCOMP(SCIPconshdlrCompCheck) 1969 { /*lint --e{715}*/ 1970 return ((SCIP_CONSHDLR*)elem2)->checkpriority - ((SCIP_CONSHDLR*)elem1)->checkpriority; 1971 } 1972 1973 /** compares two constraints w.r.t. their feasibility check priority */ 1974 SCIP_DECL_SORTPTRCOMP(SCIPconsCompCheck) 1975 { /*lint --e{715}*/ 1976 return ((SCIP_CONS*)elem2)->conshdlr->checkpriority - ((SCIP_CONS*)elem1)->conshdlr->checkpriority; 1977 } 1978 1979 /** copies the given constraint handler to a new scip */ 1980 SCIP_RETCODE SCIPconshdlrCopyInclude( 1981 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 1982 SCIP_SET* set, /**< SCIP_SET of SCIP to copy to */ 1983 SCIP_Bool* valid /**< was the copying process valid? */ 1984 ) 1985 { 1986 assert(conshdlr != NULL); 1987 assert(set != NULL); 1988 assert(valid != NULL); 1989 assert(set->scip != NULL); 1990 1991 if( conshdlr->conshdlrcopy != NULL ) 1992 { 1993 SCIPsetDebugMsg(set, "including constraint handler %s in subscip %p\n", SCIPconshdlrGetName(conshdlr), (void*)set->scip); 1994 SCIP_CALL( conshdlr->conshdlrcopy(set->scip, conshdlr, valid) ); 1995 } 1996 1997 return SCIP_OKAY; 1998 } 1999 2000 /** internal method for creating a constraint handler */ 2001 static 2002 SCIP_RETCODE doConshdlrCreate( 2003 SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */ 2004 SCIP_SET* set, /**< global SCIP settings */ 2005 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 2006 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 2007 const char* name, /**< name of constraint handler */ 2008 const char* desc, /**< description of constraint handler */ 2009 int sepapriority, /**< priority of the constraint handler for separation */ 2010 int enfopriority, /**< priority of the constraint handler for constraint enforcing */ 2011 int checkpriority, /**< priority of the constraint handler for checking feasibility (and propagation) */ 2012 int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */ 2013 int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */ 2014 int eagerfreq, /**< frequency for using all instead of only the useful constraints in separation, 2015 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */ 2016 int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */ 2017 SCIP_Bool delaysepa, /**< should separation method be delayed, if other separators found cuts? */ 2018 SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */ 2019 SCIP_Bool needscons, /**< should the constraint handler be skipped, if no constraints are available? */ 2020 SCIP_PROPTIMING proptiming, /**< positions in the node solving loop where propagation method of constraint handlers should be executed */ 2021 SCIP_PRESOLTIMING presoltiming, /**< timing mask of the constraint handler's presolving method */ 2022 SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 2023 SCIP_DECL_CONSFREE ((*consfree)), /**< destructor of constraint handler */ 2024 SCIP_DECL_CONSINIT ((*consinit)), /**< initialize constraint handler */ 2025 SCIP_DECL_CONSEXIT ((*consexit)), /**< deinitialize constraint handler */ 2026 SCIP_DECL_CONSINITPRE ((*consinitpre)), /**< presolving initialization method of constraint handler */ 2027 SCIP_DECL_CONSEXITPRE ((*consexitpre)), /**< presolving deinitialization method of constraint handler */ 2028 SCIP_DECL_CONSINITSOL ((*consinitsol)), /**< solving process initialization method of constraint handler */ 2029 SCIP_DECL_CONSEXITSOL ((*consexitsol)), /**< solving process deinitialization method of constraint handler */ 2030 SCIP_DECL_CONSDELETE ((*consdelete)), /**< free specific constraint data */ 2031 SCIP_DECL_CONSTRANS ((*constrans)), /**< transform constraint data into data belonging to the transformed problem */ 2032 SCIP_DECL_CONSINITLP ((*consinitlp)), /**< initialize LP with relaxations of "initial" constraints */ 2033 SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */ 2034 SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */ 2035 SCIP_DECL_CONSENFOLP ((*consenfolp)), /**< enforcing constraints for LP solutions */ 2036 SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */ 2037 SCIP_DECL_CONSENFOPS ((*consenfops)), /**< enforcing constraints for pseudo solutions */ 2038 SCIP_DECL_CONSCHECK ((*conscheck)), /**< check feasibility of primal solution */ 2039 SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */ 2040 SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method */ 2041 SCIP_DECL_CONSRESPROP ((*consresprop)), /**< propagation conflict resolving method */ 2042 SCIP_DECL_CONSLOCK ((*conslock)), /**< variable rounding lock method */ 2043 SCIP_DECL_CONSACTIVE ((*consactive)), /**< activation notification method */ 2044 SCIP_DECL_CONSDEACTIVE((*consdeactive)), /**< deactivation notification method */ 2045 SCIP_DECL_CONSENABLE ((*consenable)), /**< enabling notification method */ 2046 SCIP_DECL_CONSDISABLE ((*consdisable)), /**< disabling notification method */ 2047 SCIP_DECL_CONSDELVARS ((*consdelvars)), /**< variable deletion method */ 2048 SCIP_DECL_CONSPRINT ((*consprint)), /**< constraint display method */ 2049 SCIP_DECL_CONSCOPY ((*conscopy)), /**< constraint copying method */ 2050 SCIP_DECL_CONSPARSE ((*consparse)), /**< constraint parsing method */ 2051 SCIP_DECL_CONSGETVARS ((*consgetvars)), /**< constraint get variables method */ 2052 SCIP_DECL_CONSGETNVARS((*consgetnvars)), /**< constraint get number of variable method */ 2053 SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */ 2054 SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)), /**< constraint permutation symmetry detection graph 2055 * getter method */ 2056 SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)), /**< constraint signed permutation 2057 * symmetry detection graph getter method */ 2058 SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */ 2059 ) 2060 { 2061 char paramname[SCIP_MAXSTRLEN]; 2062 char paramdesc[SCIP_MAXSTRLEN]; 2063 2064 assert(conshdlr != NULL); 2065 assert(name != NULL); 2066 assert(desc != NULL); 2067 assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1); 2068 assert(consprop != NULL || propfreq == -1); 2069 assert(eagerfreq >= -1); 2070 assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL))); 2071 2072 /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate 2073 * error message 2074 */ 2075 if( presoltiming < SCIP_PRESOLTIMING_NONE || presoltiming > SCIP_PRESOLTIMING_MAX ) 2076 { 2077 SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate " 2078 "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", name); 2079 2080 return SCIP_PARAMETERWRONGVAL; 2081 } 2082 2083 /* both callbacks have to exist or not exist */ 2084 assert((consgetvars != NULL) == (consgetnvars != NULL)); 2085 2086 SCIP_ALLOC( BMSallocMemory(conshdlr) ); 2087 BMSclearMemory(*conshdlr); 2088 2089 SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->name, name, strlen(name)+1) ); 2090 SCIP_ALLOC( BMSduplicateMemoryArray(&(*conshdlr)->desc, desc, strlen(desc)+1) ); 2091 (*conshdlr)->sepapriority = sepapriority; 2092 (*conshdlr)->enfopriority = enfopriority; 2093 (*conshdlr)->checkpriority = checkpriority; 2094 (*conshdlr)->sepafreq = sepafreq; 2095 (*conshdlr)->propfreq = propfreq; 2096 (*conshdlr)->eagerfreq = eagerfreq; 2097 (*conshdlr)->maxprerounds = maxprerounds; 2098 (*conshdlr)->conshdlrcopy = conshdlrcopy; 2099 (*conshdlr)->consfree = consfree; 2100 (*conshdlr)->consinit = consinit; 2101 (*conshdlr)->consexit = consexit; 2102 (*conshdlr)->consinitpre = consinitpre; 2103 (*conshdlr)->consexitpre = consexitpre; 2104 (*conshdlr)->consinitsol = consinitsol; 2105 (*conshdlr)->consexitsol = consexitsol; 2106 (*conshdlr)->consdelete = consdelete; 2107 (*conshdlr)->constrans = constrans; 2108 (*conshdlr)->consinitlp = consinitlp; 2109 (*conshdlr)->conssepalp = conssepalp; 2110 (*conshdlr)->conssepasol = conssepasol; 2111 (*conshdlr)->consenfolp = consenfolp; 2112 (*conshdlr)->consenforelax = consenforelax; 2113 (*conshdlr)->consenfops = consenfops; 2114 (*conshdlr)->conscheck = conscheck; 2115 (*conshdlr)->consprop = consprop; 2116 (*conshdlr)->conspresol = conspresol; 2117 (*conshdlr)->consresprop = consresprop; 2118 (*conshdlr)->conslock = conslock; 2119 (*conshdlr)->consactive = consactive; 2120 (*conshdlr)->consdeactive = consdeactive; 2121 (*conshdlr)->consenable = consenable; 2122 (*conshdlr)->consdisable = consdisable; 2123 (*conshdlr)->consprint = consprint; 2124 (*conshdlr)->consdelvars = consdelvars; 2125 (*conshdlr)->conscopy = conscopy; 2126 (*conshdlr)->consparse = consparse; 2127 (*conshdlr)->consgetvars = consgetvars; 2128 (*conshdlr)->consgetnvars = consgetnvars; 2129 (*conshdlr)->conshdlrdata = conshdlrdata; 2130 (*conshdlr)->consgetdivebdchgs = consgetdivebdchgs; 2131 (*conshdlr)->consgetpermsymgraph = consgetpermsymgraph; 2132 (*conshdlr)->consgetsignedpermsymgraph = consgetsignedpermsymgraph; 2133 (*conshdlr)->conss = NULL; 2134 (*conshdlr)->consssize = 0; 2135 (*conshdlr)->nconss = 0; 2136 (*conshdlr)->nactiveconss = 0; 2137 (*conshdlr)->maxnactiveconss = 0; 2138 (*conshdlr)->startnactiveconss = 0; 2139 (*conshdlr)->initconss = NULL; 2140 (*conshdlr)->initconsssize = 0; 2141 (*conshdlr)->ninitconss = 0; 2142 (*conshdlr)->ninitconsskept = 0; 2143 (*conshdlr)->sepaconss = NULL; 2144 (*conshdlr)->sepaconsssize = 0; 2145 (*conshdlr)->nsepaconss = 0; 2146 (*conshdlr)->nusefulsepaconss = 0; 2147 (*conshdlr)->enfoconss = NULL; 2148 (*conshdlr)->enfoconsssize = 0; 2149 (*conshdlr)->nenfoconss = 0; 2150 (*conshdlr)->nusefulenfoconss = 0; 2151 (*conshdlr)->checkconss = NULL; 2152 (*conshdlr)->checkconsssize = 0; 2153 (*conshdlr)->ncheckconss = 0; 2154 (*conshdlr)->nusefulcheckconss = 0; 2155 (*conshdlr)->propconss = NULL; 2156 (*conshdlr)->propconsssize = 0; 2157 (*conshdlr)->npropconss = 0; 2158 (*conshdlr)->nusefulpropconss = 0; 2159 (*conshdlr)->nmarkedpropconss = 0; 2160 (*conshdlr)->updateconss = NULL; 2161 (*conshdlr)->updateconsssize = 0; 2162 (*conshdlr)->nupdateconss = 0; 2163 (*conshdlr)->nenabledconss = 0; 2164 (*conshdlr)->lastnusefulpropconss = 0; 2165 (*conshdlr)->lastnusefulsepaconss = 0; 2166 (*conshdlr)->lastnusefulenfoconss = 0; 2167 2168 (*conshdlr)->storedpropconss = NULL; 2169 (*conshdlr)->storedpropconsssize = 0; 2170 (*conshdlr)->storednmarkedpropconss = 0; 2171 (*conshdlr)->storedpropdomchgcount = 0; 2172 2173 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->setuptime, SCIP_CLOCKTYPE_DEFAULT) ); 2174 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->presoltime, SCIP_CLOCKTYPE_DEFAULT) ); 2175 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sepatime, SCIP_CLOCKTYPE_DEFAULT) ); 2176 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfolptime, SCIP_CLOCKTYPE_DEFAULT) ); 2177 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enfopstime, SCIP_CLOCKTYPE_DEFAULT) ); 2178 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->enforelaxtime, SCIP_CLOCKTYPE_DEFAULT) ); 2179 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->proptime, SCIP_CLOCKTYPE_DEFAULT) ); 2180 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->sbproptime, SCIP_CLOCKTYPE_DEFAULT) ); 2181 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->checktime, SCIP_CLOCKTYPE_DEFAULT) ); 2182 SCIP_CALL( SCIPclockCreate(&(*conshdlr)->resproptime, SCIP_CLOCKTYPE_DEFAULT) ); 2183 2184 (*conshdlr)->nsepacalls = 0; 2185 (*conshdlr)->nenfolpcalls = 0; 2186 (*conshdlr)->nenfopscalls = 0; 2187 (*conshdlr)->nenforelaxcalls = 0; 2188 (*conshdlr)->npropcalls = 0; 2189 (*conshdlr)->ncheckcalls = 0; 2190 (*conshdlr)->nrespropcalls = 0; 2191 (*conshdlr)->ncutoffs = 0; 2192 (*conshdlr)->ncutsfound = 0; 2193 (*conshdlr)->ncutsapplied = 0; 2194 (*conshdlr)->nconssfound = 0; 2195 (*conshdlr)->ndomredsfound = 0; 2196 (*conshdlr)->nchildren = 0; 2197 (*conshdlr)->lastpropdomchgcount = -1; 2198 (*conshdlr)->lastsepalpcount = -1; 2199 (*conshdlr)->lastenfolplpcount = -1; 2200 (*conshdlr)->lastenfolpdomchgcount = -1; 2201 (*conshdlr)->lastenfopsdomchgcount = -1; 2202 (*conshdlr)->lastenforelaxdomchgcount = -1; 2203 (*conshdlr)->lastenforelaxrelaxcount = -1; 2204 (*conshdlr)->lastenfolpnode = -1; 2205 (*conshdlr)->lastenfopsnode = -1; 2206 (*conshdlr)->lastenfolpresult = SCIP_DIDNOTRUN; 2207 (*conshdlr)->lastenfopsresult = SCIP_DIDNOTRUN; 2208 (*conshdlr)->lastenforelaxresult = SCIP_DIDNOTRUN; 2209 (*conshdlr)->lastnfixedvars = 0; 2210 (*conshdlr)->lastnaggrvars = 0; 2211 (*conshdlr)->lastnchgvartypes = 0; 2212 (*conshdlr)->lastnchgbds = 0; 2213 (*conshdlr)->lastnaddholes = 0; 2214 (*conshdlr)->lastndelconss = 0; 2215 (*conshdlr)->lastnaddconss = 0; 2216 (*conshdlr)->lastnupgdconss = 0; 2217 (*conshdlr)->lastnchgcoefs = 0; 2218 (*conshdlr)->lastnchgsides = 0; 2219 (*conshdlr)->nfixedvars = 0; 2220 (*conshdlr)->naggrvars = 0; 2221 (*conshdlr)->nchgvartypes = 0; 2222 (*conshdlr)->nchgbds = 0; 2223 (*conshdlr)->naddholes = 0; 2224 (*conshdlr)->ndelconss = 0; 2225 (*conshdlr)->naddconss = 0; 2226 (*conshdlr)->nupgdconss = 0; 2227 (*conshdlr)->nchgcoefs = 0; 2228 (*conshdlr)->nchgsides = 0; 2229 (*conshdlr)->npresolcalls = 0; 2230 (*conshdlr)->delayupdatecount = 0; 2231 (*conshdlr)->ageresetavg = AGERESETAVG_INIT; 2232 (*conshdlr)->needscons = needscons; 2233 (*conshdlr)->sepalpwasdelayed = FALSE; 2234 (*conshdlr)->sepasolwasdelayed = FALSE; 2235 (*conshdlr)->propwasdelayed = FALSE; 2236 (*conshdlr)->duringsepa = FALSE; 2237 (*conshdlr)->duringprop = FALSE; 2238 (*conshdlr)->initialized = FALSE; 2239 2240 /* add parameters */ 2241 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/sepafreq", name); 2242 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, 2243 "frequency for separating cuts (-1: never, 0: only in root node)", 2244 &(*conshdlr)->sepafreq, FALSE, sepafreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) ); 2245 2246 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/propfreq", name); 2247 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, 2248 "frequency for propagating domains (-1: never, 0: only in root node)", 2249 &(*conshdlr)->propfreq, FALSE, propfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) ); 2250 2251 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/proptiming", name); 2252 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing when constraint propagation should be called (%u:BEFORELP, %u:DURINGLPLOOP, %u:AFTERLPLOOP, %u:ALWAYS)", SCIP_PROPTIMING_BEFORELP, SCIP_PROPTIMING_DURINGLPLOOP, SCIP_PROPTIMING_AFTERLPLOOP, SCIP_PROPTIMING_ALWAYS); 2253 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 2254 (int*)(&(*conshdlr)->proptiming), TRUE, (int) proptiming, (int) SCIP_PROPTIMING_BEFORELP, (int) SCIP_PROPTIMING_ALWAYS, NULL, NULL) ); /*lint !e713*/ 2255 2256 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/eagerfreq", name); 2257 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, 2258 "frequency for using all instead of only the useful constraints in separation, propagation and enforcement (-1: never, 0: only in first evaluation)", 2259 &(*conshdlr)->eagerfreq, TRUE, eagerfreq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) ); 2260 2261 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/maxprerounds", name); 2262 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, 2263 "maximal number of presolving rounds the constraint handler participates in (-1: no limit)", 2264 &(*conshdlr)->maxprerounds, TRUE, maxprerounds, -1, INT_MAX, NULL, NULL) ); 2265 2266 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delaysepa", name); 2267 SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname, 2268 "should separation method be delayed, if other separators found cuts?", 2269 &(*conshdlr)->delaysepa, TRUE, delaysepa, NULL, NULL) ); /*lint !e740*/ 2270 2271 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/delayprop", name); 2272 SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname, 2273 "should propagation method be delayed, if other propagators found reductions?", 2274 &(*conshdlr)->delayprop, TRUE, delayprop, NULL, NULL) ); /*lint !e740*/ 2275 2276 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "constraints/%s/presoltiming", name); 2277 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing mask of the constraint handler's presolving method (%u:FAST, %u:MEDIUM, %u:EXHAUSTIVE, %u:FINAL)", 2278 SCIP_PRESOLTIMING_FAST, SCIP_PRESOLTIMING_MEDIUM, SCIP_PRESOLTIMING_EXHAUSTIVE, SCIP_PRESOLTIMING_FINAL); 2279 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 2280 (int*)&(*conshdlr)->presoltiming, TRUE, (int) presoltiming, (int) SCIP_PRESOLTIMING_FAST, (int) SCIP_PRESOLTIMING_MAX, NULL, NULL) ); /*lint !e740 !e713*/ 2281 2282 return SCIP_OKAY; 2283 } 2284 2285 /** creates a constraint handler */ 2286 SCIP_RETCODE SCIPconshdlrCreate( 2287 SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */ 2288 SCIP_SET* set, /**< global SCIP settings */ 2289 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 2290 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 2291 const char* name, /**< name of constraint handler */ 2292 const char* desc, /**< description of constraint handler */ 2293 int sepapriority, /**< priority of the constraint handler for separation */ 2294 int enfopriority, /**< priority of the constraint handler for constraint enforcing */ 2295 int checkpriority, /**< priority of the constraint handler for checking feasibility (and propagation) */ 2296 int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */ 2297 int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */ 2298 int eagerfreq, /**< frequency for using all instead of only the useful constraints in separation, 2299 * propagation and enforcement, -1 for no eager evaluations, 0 for first only */ 2300 int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */ 2301 SCIP_Bool delaysepa, /**< should separation method be delayed, if other separators found cuts? */ 2302 SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */ 2303 SCIP_Bool needscons, /**< should the constraint handler be skipped, if no constraints are available? */ 2304 SCIP_PROPTIMING proptiming, /**< positions in the node solving loop where propagation method of constraint handlers should be executed */ 2305 SCIP_PRESOLTIMING presoltiming, /**< timing mask of the constraint handler's presolving method */ 2306 SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 2307 SCIP_DECL_CONSFREE ((*consfree)), /**< destructor of constraint handler */ 2308 SCIP_DECL_CONSINIT ((*consinit)), /**< initialize constraint handler */ 2309 SCIP_DECL_CONSEXIT ((*consexit)), /**< deinitialize constraint handler */ 2310 SCIP_DECL_CONSINITPRE ((*consinitpre)), /**< presolving initialization method of constraint handler */ 2311 SCIP_DECL_CONSEXITPRE ((*consexitpre)), /**< presolving deinitialization method of constraint handler */ 2312 SCIP_DECL_CONSINITSOL ((*consinitsol)), /**< solving process initialization method of constraint handler */ 2313 SCIP_DECL_CONSEXITSOL ((*consexitsol)), /**< solving process deinitialization method of constraint handler */ 2314 SCIP_DECL_CONSDELETE ((*consdelete)), /**< free specific constraint data */ 2315 SCIP_DECL_CONSTRANS ((*constrans)), /**< transform constraint data into data belonging to the transformed problem */ 2316 SCIP_DECL_CONSINITLP ((*consinitlp)), /**< initialize LP with relaxations of "initial" constraints */ 2317 SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */ 2318 SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */ 2319 SCIP_DECL_CONSENFOLP ((*consenfolp)), /**< enforcing constraints for LP solutions */ 2320 SCIP_DECL_CONSENFORELAX ((*consenforelax)), /**< enforcing constraints for relaxation solutions */ 2321 SCIP_DECL_CONSENFOPS ((*consenfops)), /**< enforcing constraints for pseudo solutions */ 2322 SCIP_DECL_CONSCHECK ((*conscheck)), /**< check feasibility of primal solution */ 2323 SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */ 2324 SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method */ 2325 SCIP_DECL_CONSRESPROP ((*consresprop)), /**< propagation conflict resolving method */ 2326 SCIP_DECL_CONSLOCK ((*conslock)), /**< variable rounding lock method */ 2327 SCIP_DECL_CONSACTIVE ((*consactive)), /**< activation notification method */ 2328 SCIP_DECL_CONSDEACTIVE((*consdeactive)), /**< deactivation notification method */ 2329 SCIP_DECL_CONSENABLE ((*consenable)), /**< enabling notification method */ 2330 SCIP_DECL_CONSDISABLE ((*consdisable)), /**< disabling notification method */ 2331 SCIP_DECL_CONSDELVARS ((*consdelvars)), /**< variable deletion method */ 2332 SCIP_DECL_CONSPRINT ((*consprint)), /**< constraint display method */ 2333 SCIP_DECL_CONSCOPY ((*conscopy)), /**< constraint copying method */ 2334 SCIP_DECL_CONSPARSE ((*consparse)), /**< constraint parsing method */ 2335 SCIP_DECL_CONSGETVARS ((*consgetvars)), /**< constraint get variables method */ 2336 SCIP_DECL_CONSGETNVARS((*consgetnvars)), /**< constraint get number of variable method */ 2337 SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)), /**< constraint handler diving solution enforcement method */ 2338 SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)), /**< constraint permutation symmetry detection graph 2339 * getter method */ 2340 SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)), /**< constraint signed permutation symmetry 2341 * detection graph getter method */ 2342 SCIP_CONSHDLRDATA* conshdlrdata /**< constraint handler data */ 2343 ) 2344 { 2345 assert(conshdlr != NULL); 2346 assert(name != NULL); 2347 assert(desc != NULL); 2348 assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1); 2349 assert(consprop != NULL || propfreq == -1); 2350 assert(eagerfreq >= -1); 2351 assert(!needscons || ((conshdlrcopy == NULL) == (conscopy == NULL))); 2352 2353 SCIP_CALL_FINALLY( doConshdlrCreate(conshdlr, set, messagehdlr, blkmem, name, desc, sepapriority, enfopriority, 2354 checkpriority, sepafreq, propfreq, eagerfreq, maxprerounds, delaysepa, delayprop, needscons, proptiming, 2355 presoltiming, conshdlrcopy, consfree, consinit, consexit, consinitpre, consexitpre, consinitsol, consexitsol, 2356 consdelete, constrans, consinitlp, conssepalp, conssepasol, consenfolp, consenforelax, consenfops, conscheck, 2357 consprop, conspresol, consresprop, conslock, consactive, consdeactive, consenable, consdisable, consdelvars, 2358 consprint, conscopy, consparse, consgetvars, consgetnvars, consgetdivebdchgs, consgetpermsymgraph, 2359 consgetsignedpermsymgraph, conshdlrdata), 2360 (void) SCIPconshdlrFree(conshdlr, set) ); 2361 2362 return SCIP_OKAY; 2363 } /*lint !e715*/ 2364 2365 /** calls destructor and frees memory of constraint handler */ 2366 SCIP_RETCODE SCIPconshdlrFree( 2367 SCIP_CONSHDLR** conshdlr, /**< pointer to constraint handler data structure */ 2368 SCIP_SET* set /**< global SCIP settings */ 2369 ) 2370 { 2371 assert(conshdlr != NULL); 2372 if( *conshdlr == NULL ) 2373 return SCIP_OKAY; 2374 assert(!(*conshdlr)->initialized); 2375 assert((*conshdlr)->nconss == 0); 2376 assert(set != NULL); 2377 2378 /* call destructor of constraint handler */ 2379 if( (*conshdlr)->consfree != NULL ) 2380 { 2381 SCIP_CALL( (*conshdlr)->consfree(set->scip, *conshdlr) ); 2382 } 2383 2384 SCIPclockFree(&(*conshdlr)->resproptime); 2385 SCIPclockFree(&(*conshdlr)->checktime); 2386 SCIPclockFree(&(*conshdlr)->sbproptime); 2387 SCIPclockFree(&(*conshdlr)->proptime); 2388 SCIPclockFree(&(*conshdlr)->enforelaxtime); 2389 SCIPclockFree(&(*conshdlr)->enfopstime); 2390 SCIPclockFree(&(*conshdlr)->enfolptime); 2391 SCIPclockFree(&(*conshdlr)->sepatime); 2392 SCIPclockFree(&(*conshdlr)->presoltime); 2393 SCIPclockFree(&(*conshdlr)->setuptime); 2394 2395 BMSfreeMemoryArrayNull(&(*conshdlr)->name); 2396 BMSfreeMemoryArrayNull(&(*conshdlr)->desc); 2397 BMSfreeMemoryArrayNull(&(*conshdlr)->conss); 2398 BMSfreeMemoryArrayNull(&(*conshdlr)->initconss); 2399 BMSfreeMemoryArrayNull(&(*conshdlr)->sepaconss); 2400 BMSfreeMemoryArrayNull(&(*conshdlr)->enfoconss); 2401 BMSfreeMemoryArrayNull(&(*conshdlr)->checkconss); 2402 BMSfreeMemoryArrayNull(&(*conshdlr)->propconss); 2403 BMSfreeMemoryArrayNull(&(*conshdlr)->updateconss); 2404 BMSfreeMemoryArrayNull(&(*conshdlr)->storedpropconss); 2405 BMSfreeMemory(conshdlr); 2406 2407 return SCIP_OKAY; 2408 } 2409 2410 /** calls initialization method of constraint handler */ 2411 SCIP_RETCODE SCIPconshdlrInit( 2412 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2413 BMS_BLKMEM* blkmem, /**< block memory */ 2414 SCIP_SET* set, /**< global SCIP settings */ 2415 SCIP_STAT* stat /**< dynamic problem statistics */ 2416 ) 2417 { 2418 assert(conshdlr != NULL); 2419 assert(set != NULL); 2420 2421 if( conshdlr->initialized ) 2422 { 2423 SCIPerrorMessage("constraint handler <%s> already initialized\n", conshdlr->name); 2424 return SCIP_INVALIDCALL; 2425 } 2426 2427 if( set->misc_resetstat ) 2428 { 2429 SCIPclockReset(conshdlr->setuptime); 2430 SCIPclockReset(conshdlr->presoltime); 2431 SCIPclockReset(conshdlr->sepatime); 2432 SCIPclockReset(conshdlr->enfolptime); 2433 SCIPclockReset(conshdlr->enfopstime); 2434 SCIPclockReset(conshdlr->enforelaxtime); 2435 SCIPclockReset(conshdlr->proptime); 2436 SCIPclockReset(conshdlr->sbproptime); 2437 SCIPclockReset(conshdlr->checktime); 2438 SCIPclockReset(conshdlr->resproptime); 2439 2440 conshdlr->nsepacalls = 0; 2441 conshdlr->nenfolpcalls = 0; 2442 conshdlr->nenfopscalls = 0; 2443 conshdlr->nenforelaxcalls = 0; 2444 conshdlr->npropcalls = 0; 2445 conshdlr->ncheckcalls = 0; 2446 conshdlr->nrespropcalls = 0; 2447 conshdlr->ncutoffs = 0; 2448 conshdlr->ncutsfound = 0; 2449 conshdlr->ncutsapplied = 0; 2450 conshdlr->nconssfound = 0; 2451 conshdlr->ndomredsfound = 0; 2452 conshdlr->nchildren = 0; 2453 conshdlr->lastpropdomchgcount = -1; 2454 conshdlr->lastenfolpdomchgcount = -1; 2455 conshdlr->lastenfopsdomchgcount = -1; 2456 conshdlr->lastenforelaxdomchgcount = -1; 2457 conshdlr->lastenforelaxrelaxcount = -1; 2458 conshdlr->lastenfolpnode = -1; 2459 conshdlr->lastenfopsnode = -1; 2460 conshdlr->lastenfolpresult = SCIP_DIDNOTRUN; 2461 conshdlr->lastenfopsresult = SCIP_DIDNOTRUN; 2462 conshdlr->maxnactiveconss = conshdlr->nactiveconss; 2463 conshdlr->startnactiveconss = 0; 2464 conshdlr->lastsepalpcount = -1; 2465 conshdlr->lastenfolplpcount = -1; 2466 conshdlr->lastnusefulpropconss = 0; 2467 conshdlr->lastnusefulsepaconss = 0; 2468 conshdlr->lastnusefulenfoconss = 0; 2469 conshdlr->lastnfixedvars = 0; 2470 conshdlr->lastnaggrvars = 0; 2471 conshdlr->lastnchgvartypes = 0; 2472 conshdlr->lastnchgbds = 0; 2473 conshdlr->lastnaddholes = 0; 2474 conshdlr->lastndelconss = 0; 2475 conshdlr->lastnaddconss = 0; 2476 conshdlr->lastnupgdconss = 0; 2477 conshdlr->lastnchgcoefs = 0; 2478 conshdlr->lastnchgsides = 0; 2479 conshdlr->nfixedvars = 0; 2480 conshdlr->naggrvars = 0; 2481 conshdlr->nchgvartypes = 0; 2482 conshdlr->nchgbds = 0; 2483 conshdlr->naddholes = 0; 2484 conshdlr->ndelconss = 0; 2485 conshdlr->naddconss = 0; 2486 conshdlr->nupgdconss = 0; 2487 conshdlr->nchgcoefs = 0; 2488 conshdlr->nchgsides = 0; 2489 conshdlr->npresolcalls = 0; 2490 conshdlr->ageresetavg = AGERESETAVG_INIT; 2491 conshdlr->sepalpwasdelayed = FALSE; 2492 conshdlr->sepasolwasdelayed = FALSE; 2493 conshdlr->propwasdelayed = FALSE; 2494 } 2495 2496 /* call initialization method of constraint handler */ 2497 if( conshdlr->consinit != NULL ) 2498 { 2499 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2500 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2501 * external method; to avoid this, these changes will be buffered and processed after the method call 2502 */ 2503 conshdlrDelayUpdates(conshdlr); 2504 2505 /* start timing */ 2506 SCIPclockStart(conshdlr->setuptime, set); 2507 2508 /* call external method */ 2509 SCIP_CALL( conshdlr->consinit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) ); 2510 2511 /* stop timing */ 2512 SCIPclockStop(conshdlr->setuptime, set); 2513 2514 /* perform the cached constraint updates */ 2515 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2516 } 2517 conshdlr->initialized = TRUE; 2518 assert(!conshdlrAreUpdatesDelayed(conshdlr)); 2519 2520 return SCIP_OKAY; 2521 } 2522 2523 /** calls exit method of constraint handler */ 2524 SCIP_RETCODE SCIPconshdlrExit( 2525 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2526 BMS_BLKMEM* blkmem, /**< block memory */ 2527 SCIP_SET* set, /**< global SCIP settings */ 2528 SCIP_STAT* stat /**< dynamic problem statistics */ 2529 ) 2530 { 2531 assert(conshdlr != NULL); 2532 assert(set != NULL); 2533 2534 if( !conshdlr->initialized ) 2535 { 2536 SCIPerrorMessage("constraint handler <%s> not initialized\n", conshdlr->name); 2537 return SCIP_INVALIDCALL; 2538 } 2539 2540 /* call deinitialization method of constraint handler */ 2541 if( conshdlr->consexit != NULL ) 2542 { 2543 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2544 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2545 * external method; to avoid this, these changes will be buffered and processed after the method call 2546 */ 2547 conshdlrDelayUpdates(conshdlr); 2548 2549 /* start timing */ 2550 SCIPclockStart(conshdlr->setuptime, set); 2551 2552 /* call external method */ 2553 SCIP_CALL( conshdlr->consexit(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) ); 2554 2555 /* stop timing */ 2556 SCIPclockStop(conshdlr->setuptime, set); 2557 2558 /* perform the cached constraint updates */ 2559 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2560 } 2561 conshdlr->initialized = FALSE; 2562 2563 return SCIP_OKAY; 2564 } 2565 2566 /** informs constraint handler that the presolving process is being started */ 2567 SCIP_RETCODE SCIPconshdlrInitpre( 2568 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2569 BMS_BLKMEM* blkmem, /**< block memory */ 2570 SCIP_SET* set, /**< global SCIP settings */ 2571 SCIP_STAT* stat /**< dynamic problem statistics */ 2572 ) 2573 { 2574 assert(conshdlr != NULL); 2575 assert(set != NULL); 2576 2577 /* reset conshdlr last presolved data in case of a restart */ 2578 conshdlr->lastpropdomchgcount = -1; 2579 conshdlr->lastenfolpdomchgcount = -1; 2580 conshdlr->lastenfopsdomchgcount = -1; 2581 conshdlr->lastenforelaxdomchgcount = -1; 2582 conshdlr->lastenforelaxrelaxcount = -1; 2583 conshdlr->lastenfolpnode = -1; 2584 conshdlr->lastenfopsnode = -1; 2585 conshdlr->lastenfolpresult = SCIP_DIDNOTRUN; 2586 conshdlr->lastenfopsresult = SCIP_DIDNOTRUN; 2587 conshdlr->lastenforelaxresult = SCIP_DIDNOTRUN; 2588 conshdlr->maxnactiveconss = conshdlr->nactiveconss; 2589 conshdlr->startnactiveconss = 0; 2590 conshdlr->lastsepalpcount = -1; 2591 conshdlr->lastenfolplpcount = -1; 2592 conshdlr->lastnusefulpropconss = 0; 2593 conshdlr->lastnusefulsepaconss = 0; 2594 conshdlr->lastnusefulenfoconss = 0; 2595 conshdlr->lastnfixedvars = 0; 2596 conshdlr->lastnaggrvars = 0; 2597 conshdlr->lastnchgvartypes = 0; 2598 conshdlr->lastnchgbds = 0; 2599 conshdlr->lastnaddholes = 0; 2600 conshdlr->lastndelconss = 0; 2601 conshdlr->lastnaddconss = 0; 2602 conshdlr->lastnupgdconss = 0; 2603 conshdlr->lastnchgcoefs = 0; 2604 conshdlr->lastnchgsides = 0; 2605 conshdlr->propwasdelayed = FALSE; 2606 2607 /* call presolving initialization method of constraint handler */ 2608 if( conshdlr->consinitpre != NULL ) 2609 { 2610 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2611 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2612 * external method; to avoid this, these changes will be buffered and processed after the method call 2613 */ 2614 conshdlrDelayUpdates(conshdlr); 2615 2616 /* start timing */ 2617 SCIPclockStart(conshdlr->setuptime, set); 2618 2619 /* call external method */ 2620 SCIP_CALL( conshdlr->consinitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) ); 2621 2622 /* stop timing */ 2623 SCIPclockStop(conshdlr->setuptime, set); 2624 2625 /* perform the cached constraint updates */ 2626 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2627 } 2628 2629 /* after a restart the LP is empty but the initial constraints are not included in the initialconss array anymore; 2630 * we have to put them back into this array in order to obtain the correct initial root relaxation 2631 */ 2632 if( stat->nruns >= 2 ) 2633 { 2634 int c; 2635 2636 for( c = 0; c < conshdlr->nconss; ++c ) 2637 { 2638 /**@todo should only active constraints be added to the initconss array? at least cons->active is asserted in 2639 * conshdlrAddInitcons(conshdlr, set, conshdlr->conss[c]) 2640 */ 2641 if( conshdlr->conss[c]->addarraypos >= 0 && !conshdlr->conss[c]->deleted && 2642 conshdlr->conss[c]->initial && conshdlr->conss[c]->initconsspos == -1 ) 2643 { 2644 SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->conss[c]) ); 2645 } 2646 } 2647 } 2648 2649 return SCIP_OKAY; 2650 } 2651 2652 /** informs constraint handler that the presolving is finished */ 2653 SCIP_RETCODE SCIPconshdlrExitpre( 2654 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2655 BMS_BLKMEM* blkmem, /**< block memory */ 2656 SCIP_SET* set, /**< global SCIP settings */ 2657 SCIP_STAT* stat /**< dynamic problem statistics */ 2658 ) 2659 { 2660 assert(conshdlr != NULL); 2661 assert(set != NULL); 2662 2663 /* call presolving deinitialization method of constraint handler */ 2664 if( conshdlr->consexitpre != NULL ) 2665 { 2666 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2667 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2668 * external method; to avoid this, these changes will be buffered and processed after the method call 2669 */ 2670 conshdlrDelayUpdates(conshdlr); 2671 2672 /* start timing */ 2673 SCIPclockStart(conshdlr->setuptime, set); 2674 2675 /* call external method */ 2676 SCIP_CALL( conshdlr->consexitpre(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) ); 2677 2678 /* stop timing */ 2679 SCIPclockStop(conshdlr->setuptime, set); 2680 2681 /* perform the cached constraint updates */ 2682 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2683 } 2684 2685 /* update statistics */ 2686 conshdlr->maxnactiveconss = conshdlr->nactiveconss; 2687 conshdlr->startnactiveconss = conshdlr->nactiveconss; 2688 2689 return SCIP_OKAY; 2690 } 2691 2692 /** informs constraint handler that the branch and bound process is being started */ 2693 SCIP_RETCODE SCIPconshdlrInitsol( 2694 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2695 BMS_BLKMEM* blkmem, /**< block memory */ 2696 SCIP_SET* set, /**< global SCIP settings */ 2697 SCIP_STAT* stat /**< dynamic problem statistics */ 2698 ) 2699 { 2700 assert(conshdlr != NULL); 2701 assert(set != NULL); 2702 assert(stat != NULL); 2703 2704 conshdlr->sepalpwasdelayed = FALSE; 2705 conshdlr->sepasolwasdelayed = FALSE; 2706 2707 /* call solving process initialization method of constraint handler */ 2708 if( conshdlr->consinitsol != NULL ) 2709 { 2710 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2711 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2712 * external method; to avoid this, these changes will be buffered and processed after the method call 2713 */ 2714 conshdlrDelayUpdates(conshdlr); 2715 2716 /* start timing */ 2717 SCIPclockStart(conshdlr->setuptime, set); 2718 2719 /* call external method */ 2720 SCIP_CALL( conshdlr->consinitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) ); 2721 2722 /* stop timing */ 2723 SCIPclockStop(conshdlr->setuptime, set); 2724 2725 /* perform the cached constraint updates */ 2726 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2727 } 2728 2729 return SCIP_OKAY; 2730 } 2731 2732 /** informs constraint handler that the branch and bound process data is being freed */ 2733 SCIP_RETCODE SCIPconshdlrExitsol( 2734 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2735 BMS_BLKMEM* blkmem, /**< block memory */ 2736 SCIP_SET* set, /**< global SCIP settings */ 2737 SCIP_STAT* stat, /**< dynamic problem statistics */ 2738 SCIP_Bool restart /**< was this exit solve call triggered by a restart? */ 2739 ) 2740 { 2741 assert(conshdlr != NULL); 2742 assert(set != NULL); 2743 2744 /* call solving process deinitialization method of constraint handler */ 2745 if( conshdlr->consexitsol != NULL ) 2746 { 2747 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2748 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2749 * external method; to avoid this, these changes will be buffered and processed after the method call 2750 */ 2751 conshdlrDelayUpdates(conshdlr); 2752 2753 /* start timing */ 2754 SCIPclockStart(conshdlr->setuptime, set); 2755 2756 /* call external method */ 2757 SCIP_CALL( conshdlr->consexitsol(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss, restart) ); 2758 2759 /* stop timing */ 2760 SCIPclockStop(conshdlr->setuptime, set); 2761 2762 /* perform the cached constraint updates */ 2763 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2764 } 2765 2766 return SCIP_OKAY; 2767 } 2768 2769 /** calls LP initialization method of constraint handler to separate all initial active constraints */ 2770 SCIP_RETCODE SCIPconshdlrInitLP( 2771 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2772 BMS_BLKMEM* blkmem, /**< block memory */ 2773 SCIP_SET* set, /**< global SCIP settings */ 2774 SCIP_STAT* stat, /**< dynamic problem statistics */ 2775 SCIP_TREE* tree, /**< branch and bound tree */ 2776 SCIP_Bool initkeptconss, /**< Also initialize constraints which are valid at a more global node, 2777 * but were not activated there? Should be FALSE for repeated calls at 2778 * one node or if the current focusnode is a child of the former one */ 2779 SCIP_Bool* cutoff /**< pointer to store whether infeasibility was detected while building the LP */ 2780 ) 2781 { 2782 assert(conshdlr != NULL); 2783 assert(cutoff != NULL); 2784 #ifdef MORE_DEBUG 2785 assert(stat->nnodes > 1 || conshdlr->ninitconsskept == 0 || SCIPtreeProbing(tree)); 2786 #endif 2787 2788 *cutoff = FALSE; 2789 2790 if( conshdlr->consinitlp != NULL ) 2791 { 2792 int currentdepth; 2793 int oldninitconss; 2794 int c; 2795 2796 SCIPsetDebugMsg(set, "initializing LP with %d initial constraints of handler <%s> (ninitconss=%d, kept=%d, initkept=%u)\n", 2797 initkeptconss ? conshdlr->ninitconss : conshdlr->ninitconss - conshdlr->ninitconsskept, conshdlr->name, 2798 conshdlr->ninitconss, conshdlr->ninitconsskept, initkeptconss); 2799 2800 /* no constraints to initialize (or only kept constraints which do not need to be initialized this time) -> return */ 2801 if( conshdlr->needscons && (conshdlr->ninitconss == 0 || (!initkeptconss && conshdlr->ninitconss == conshdlr->ninitconsskept)) ) 2802 return SCIP_OKAY; 2803 2804 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2805 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2806 * external method; to avoid this, these changes will be buffered and processed after the method call 2807 */ 2808 conshdlrDelayUpdates(conshdlr); 2809 2810 oldninitconss = conshdlr->ninitconss; 2811 2812 /* start timing */ 2813 SCIPclockStart(conshdlr->sepatime, set); 2814 2815 if( initkeptconss ) 2816 { 2817 /* add all kept initial constraints which are currently active to the second part of the initconss array */ 2818 /* @todo keep track of where a constraint was already initialized (e.g., in the conssetchg)? */ 2819 for( c = 0; c < conshdlr->ninitconsskept; ++c ) 2820 { 2821 assert(conshdlr->initconss[c]->initconsspos == c); 2822 2823 if( SCIPconsIsActive(conshdlr->initconss[c]) ) 2824 { 2825 SCIP_CALL( conshdlrAddInitcons(conshdlr, set, stat, conshdlr->initconss[c]) ); 2826 } 2827 } 2828 } 2829 2830 /* call external method */ 2831 SCIP_CALL( conshdlr->consinitlp(set->scip, conshdlr, &conshdlr->initconss[conshdlr->ninitconsskept], 2832 conshdlr->ninitconss - conshdlr->ninitconsskept, cutoff) ); 2833 2834 /* stop timing */ 2835 SCIPclockStop(conshdlr->sepatime, set); 2836 2837 /* perform the cached constraint updates */ 2838 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2839 2840 currentdepth = SCIPtreeGetCurrentDepth(tree); 2841 assert(currentdepth >= 0); 2842 2843 /* clear the initconss array */ 2844 for( c = conshdlr->ninitconsskept; c < oldninitconss; ++c ) 2845 { 2846 assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) >= -1); 2847 assert(SCIPconsGetActiveDepth(conshdlr->initconss[c]) <= currentdepth); 2848 2849 /* if the constraint was not initialized at its valid node, we keep it */ 2850 if( currentdepth > 0 ? SCIPconsGetActiveDepth(conshdlr->initconss[c]) != currentdepth : 2851 SCIPconsGetActiveDepth(conshdlr->initconss[c]) > 0 ) 2852 { 2853 conshdlr->initconss[conshdlr->ninitconsskept] = conshdlr->initconss[c]; 2854 conshdlr->initconss[conshdlr->ninitconsskept]->initconsspos = conshdlr->ninitconsskept; 2855 ++(conshdlr->ninitconsskept); 2856 } 2857 else 2858 conshdlr->initconss[c]->initconsspos = -1; 2859 } 2860 #ifndef NDEBUG 2861 for( ; c < conshdlr->ninitconss; ++c ) 2862 assert(conshdlr->initconss[c]->initconsspos < conshdlr->ninitconsskept); 2863 #endif 2864 conshdlr->ninitconss = conshdlr->ninitconsskept; 2865 2866 if( conshdlr->ninitconss == 0 ) 2867 { 2868 BMSfreeMemoryArrayNull(&conshdlr->initconss); 2869 conshdlr->initconsssize = 0; 2870 } 2871 } 2872 2873 return SCIP_OKAY; 2874 } 2875 2876 /** calls separator method of constraint handler to separate LP solution */ 2877 SCIP_RETCODE SCIPconshdlrSeparateLP( 2878 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 2879 BMS_BLKMEM* blkmem, /**< block memory */ 2880 SCIP_SET* set, /**< global SCIP settings */ 2881 SCIP_STAT* stat, /**< dynamic problem statistics */ 2882 SCIP_SEPASTORE* sepastore, /**< separation storage */ 2883 int depth, /**< depth of current node */ 2884 SCIP_Bool execdelayed, /**< execute separation method even if it is marked to be delayed */ 2885 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 2886 ) 2887 { 2888 assert(conshdlr != NULL); 2889 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 2890 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 2891 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 2892 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 2893 assert(stat != NULL); 2894 assert(conshdlr->lastsepalpcount != stat->lpcount 2895 || (0 <= conshdlr->lastnusefulsepaconss && conshdlr->lastnusefulsepaconss <= conshdlr->nusefulsepaconss)); 2896 assert(set != NULL); 2897 assert(result != NULL); 2898 2899 *result = SCIP_DIDNOTRUN; 2900 2901 if( conshdlr->conssepalp != NULL 2902 && ((depth == 0 && conshdlr->sepafreq == 0) 2903 || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0) 2904 || conshdlr->sepalpwasdelayed) ) 2905 { 2906 /* check, if separation method should be delayed */ 2907 if( !conshdlr->delaysepa || execdelayed ) 2908 { 2909 int nconss; 2910 int nusefulconss; 2911 int firstcons; 2912 2913 /* check, if this LP solution was already separated */ 2914 if( conshdlr->lastsepalpcount == stat->lpcount ) 2915 { 2916 /* all constraints that were not yet separated on the new LP solution must be useful constraints, which means, 2917 * that the new constraints are the last constraints of the useful ones 2918 */ 2919 nconss = conshdlr->nusefulsepaconss - conshdlr->lastnusefulsepaconss; 2920 nusefulconss = nconss; 2921 firstcons = conshdlr->lastnusefulsepaconss; 2922 } 2923 else 2924 { 2925 /* on a new LP solution, we want to separate all constraints */ 2926 nconss = conshdlr->nsepaconss; 2927 nusefulconss = conshdlr->nusefulsepaconss; 2928 firstcons = 0; 2929 } 2930 assert(firstcons >= 0); 2931 assert(firstcons + nconss <= conshdlr->nsepaconss); 2932 assert(nusefulconss <= nconss); 2933 2934 /* constraint handlers without constraints should only be called once */ 2935 if( nconss > 0 || (!conshdlr->needscons && conshdlr->lastsepalpcount != stat->lpcount) ) 2936 { 2937 SCIP_CONS** conss; 2938 SCIP_Longint oldndomchgs; 2939 SCIP_Longint oldnprobdomchgs; 2940 SCIP_Longint lastsepalpcount; 2941 int oldncuts; 2942 int oldnactiveconss; 2943 int lastnusefulsepaconss; 2944 2945 SCIPsetDebugMsg(set, "separating constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n", 2946 firstcons, firstcons + nconss - 1, conshdlr->nsepaconss, conshdlr->name, 2947 conshdlr->lastsepalpcount == stat->lpcount ? "old" : "new"); 2948 2949 /* remember the number of processed constraints on the current LP solution */ 2950 lastsepalpcount = stat->lpcount; 2951 lastnusefulsepaconss = conshdlr->nusefulsepaconss; 2952 2953 /* get the array of the constraints to be processed */ 2954 conss = &(conshdlr->sepaconss[firstcons]); 2955 2956 oldndomchgs = stat->nboundchgs + stat->nholechgs; 2957 oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs; 2958 oldncuts = SCIPsepastoreGetNCuts(sepastore); 2959 oldnactiveconss = stat->nactiveconss; 2960 2961 /* check, if we want to use eager evaluation */ 2962 if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0) 2963 || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) ) 2964 nusefulconss = nconss; 2965 2966 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 2967 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 2968 * external method; to avoid this, these changes will be buffered and processed after the method call 2969 */ 2970 conshdlrDelayUpdates(conshdlr); 2971 conshdlr->duringsepa = TRUE; 2972 2973 /* start timing */ 2974 SCIPclockStart(conshdlr->sepatime, set); 2975 2976 /* call external method */ 2977 SCIP_CALL( conshdlr->conssepalp(set->scip, conshdlr, conss, nconss, nusefulconss, result) ); 2978 SCIPsetDebugMsg(set, " -> separating LP returned result <%d>\n", *result); 2979 2980 /* stop timing */ 2981 SCIPclockStop(conshdlr->sepatime, set); 2982 2983 /* perform the cached constraint updates */ 2984 conshdlr->duringsepa = FALSE; 2985 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 2986 2987 /* update statistics */ 2988 if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED ) 2989 { 2990 conshdlr->lastsepalpcount = lastsepalpcount; 2991 conshdlr->lastnusefulsepaconss = MIN(lastnusefulsepaconss, conshdlr->nusefulsepaconss); 2992 conshdlr->nsepacalls++; 2993 } 2994 if( *result == SCIP_CUTOFF ) 2995 conshdlr->ncutoffs++; 2996 conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/ 2997 conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/ 2998 2999 /* update domain reductions; therefore remove the domain 3000 * reduction counts which were generated in probing mode */ 3001 conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs; 3002 conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs); 3003 3004 /* evaluate result */ 3005 if( *result != SCIP_CUTOFF 3006 && *result != SCIP_CONSADDED 3007 && *result != SCIP_REDUCEDDOM 3008 && *result != SCIP_SEPARATED 3009 && *result != SCIP_NEWROUND 3010 && *result != SCIP_DIDNOTFIND 3011 && *result != SCIP_DIDNOTRUN 3012 && *result != SCIP_DELAYED ) 3013 { 3014 SCIPerrorMessage("LP separation method of constraint handler <%s> returned invalid result <%d>\n", 3015 conshdlr->name, *result); 3016 return SCIP_INVALIDRESULT; 3017 } 3018 } 3019 } 3020 else 3021 { 3022 SCIPsetDebugMsg(set, "LP separation method of constraint handler <%s> was delayed\n", conshdlr->name); 3023 *result = SCIP_DELAYED; 3024 } 3025 3026 /* remember whether separation method was delayed */ 3027 conshdlr->sepalpwasdelayed = (*result == SCIP_DELAYED); 3028 } 3029 3030 return SCIP_OKAY; 3031 } 3032 3033 /** calls separator method of constraint handler to separate given primal solution */ 3034 SCIP_RETCODE SCIPconshdlrSeparateSol( 3035 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3036 BMS_BLKMEM* blkmem, /**< block memory */ 3037 SCIP_SET* set, /**< global SCIP settings */ 3038 SCIP_STAT* stat, /**< dynamic problem statistics */ 3039 SCIP_SEPASTORE* sepastore, /**< separation storage */ 3040 SCIP_SOL* sol, /**< primal solution that should be separated */ 3041 int depth, /**< depth of current node */ 3042 SCIP_Bool execdelayed, /**< execute separation method even if it is marked to be delayed */ 3043 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 3044 ) 3045 { 3046 assert(conshdlr != NULL); 3047 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 3048 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 3049 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 3050 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 3051 assert(set != NULL); 3052 assert(stat != NULL); 3053 assert(result != NULL); 3054 3055 *result = SCIP_DIDNOTRUN; 3056 3057 if( conshdlr->conssepasol != NULL 3058 && ((depth == 0 && conshdlr->sepafreq == 0) 3059 || (conshdlr->sepafreq > 0 && depth % conshdlr->sepafreq == 0) 3060 || conshdlr->sepasolwasdelayed) ) 3061 { 3062 /* check, if separation method should be delayed */ 3063 if( !conshdlr->delaysepa || execdelayed ) 3064 { 3065 int nconss; 3066 int nusefulconss; 3067 3068 /* always separate all constraints */ 3069 nconss = conshdlr->nsepaconss; 3070 nusefulconss = conshdlr->nusefulsepaconss; 3071 assert(nusefulconss <= nconss); 3072 3073 if( nconss > 0 || !conshdlr->needscons ) 3074 { 3075 SCIP_CONS** conss; 3076 SCIP_Longint oldndomchgs; 3077 SCIP_Longint oldnprobdomchgs; 3078 int oldncuts; 3079 int oldnactiveconss; 3080 3081 SCIPsetDebugMsg(set, "separating %d constraints of handler <%s> (primal solution %p)\n", 3082 nconss, conshdlr->name, (void*)sol); 3083 3084 /* get the array of the constraints to be processed */ 3085 conss = conshdlr->sepaconss; 3086 3087 oldndomchgs = stat->nboundchgs + stat->nholechgs; 3088 oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs; 3089 oldncuts = SCIPsepastoreGetNCuts(sepastore); 3090 oldnactiveconss = stat->nactiveconss; 3091 3092 /* check, if we want to use eager evaluation */ 3093 if( (conshdlr->eagerfreq == 0 && conshdlr->nsepacalls == 0) 3094 || (conshdlr->eagerfreq > 0 && conshdlr->nsepacalls % conshdlr->eagerfreq == 0) ) 3095 nusefulconss = nconss; 3096 3097 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 3098 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 3099 * external method; to avoid this, these changes will be buffered and processed after the method call 3100 */ 3101 conshdlrDelayUpdates(conshdlr); 3102 conshdlr->duringsepa = TRUE; 3103 3104 /* start timing */ 3105 SCIPclockStart(conshdlr->sepatime, set); 3106 3107 /* call external method */ 3108 SCIP_CALL( conshdlr->conssepasol(set->scip, conshdlr, conss, nconss, nusefulconss, sol, result) ); 3109 SCIPsetDebugMsg(set, " -> separating sol returned result <%d>\n", *result); 3110 3111 /* stop timing */ 3112 SCIPclockStop(conshdlr->sepatime, set); 3113 3114 /* perform the cached constraint updates */ 3115 conshdlr->duringsepa = FALSE; 3116 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 3117 3118 /* update statistics */ 3119 if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED ) 3120 conshdlr->nsepacalls++; 3121 if( *result == SCIP_CUTOFF ) 3122 conshdlr->ncutoffs++; 3123 conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/ 3124 conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/ 3125 3126 /* update domain reductions; therefore remove the domain 3127 * reduction counts which were generated in probing mode */ 3128 conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs; 3129 conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs); 3130 3131 /* evaluate result */ 3132 if( *result != SCIP_CUTOFF 3133 && *result != SCIP_CONSADDED 3134 && *result != SCIP_REDUCEDDOM 3135 && *result != SCIP_SEPARATED 3136 && *result != SCIP_NEWROUND 3137 && *result != SCIP_DIDNOTFIND 3138 && *result != SCIP_DIDNOTRUN 3139 && *result != SCIP_DELAYED ) 3140 { 3141 SCIPerrorMessage("SOL separation method of constraint handler <%s> returned invalid result <%d>\n", 3142 conshdlr->name, *result); 3143 return SCIP_INVALIDRESULT; 3144 } 3145 } 3146 } 3147 else 3148 { 3149 SCIPsetDebugMsg(set, "SOL separation method of constraint handler <%s> was delayed\n", conshdlr->name); 3150 *result = SCIP_DELAYED; 3151 } 3152 3153 /* remember whether separation method was delayed */ 3154 conshdlr->sepasolwasdelayed = (*result == SCIP_DELAYED); 3155 } 3156 3157 return SCIP_OKAY; 3158 } 3159 3160 /** calls enforcing method of constraint handler for a relaxation solution for all constraints added after last 3161 * conshdlrResetEnfo() call 3162 */ 3163 SCIP_RETCODE SCIPconshdlrEnforceRelaxSol( 3164 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3165 BMS_BLKMEM* blkmem, /**< block memory */ 3166 SCIP_SET* set, /**< global SCIP settings */ 3167 SCIP_STAT* stat, /**< dynamic problem statistics */ 3168 SCIP_TREE* tree, /**< branch and bound tree */ 3169 SCIP_SEPASTORE* sepastore, /**< separation storage */ 3170 SCIP_SOL* relaxsol, /**< solution to be enforced */ 3171 SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */ 3172 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 3173 ) 3174 { 3175 int nconss; 3176 int nusefulconss; 3177 int firstcons; 3178 SCIP_Bool relaxchanged; 3179 SCIP_Bool lastinfeasible; 3180 3181 assert(conshdlr != NULL); 3182 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 3183 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 3184 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 3185 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 3186 assert(stat != NULL); 3187 assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount 3188 || conshdlr->lastenfopsnode != stat->nnodes 3189 || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss)); 3190 assert(set != NULL); 3191 assert(tree != NULL); 3192 assert(tree->nchildren == 0); 3193 assert(relaxsol != NULL); 3194 assert(result != NULL); 3195 3196 *result = SCIP_FEASIBLE; 3197 3198 /* check, if this relaxation solution was already enforced at this node 3199 * the integrality constraint handler always needs to be enforced for all constraints since external branching 3200 * candidates are cleared before each resolve 3201 */ 3202 if( conshdlr->lastenforelaxrelaxcount == stat->relaxcount 3203 && conshdlr->lastenforelaxdomchgcount == stat->domchgcount 3204 && conshdlr->lastenforelaxnode == stat->nnodes 3205 && conshdlr->lastenforelaxresult != SCIP_CONSADDED 3206 && conshdlr->lastenforelaxresult != SCIP_SOLVELP 3207 && ( strcmp(conshdlr->name, "integral") != 0 ) 3208 ) 3209 { 3210 assert(conshdlr->lastenforelaxresult != SCIP_CUTOFF); 3211 assert(conshdlr->lastenforelaxresult != SCIP_BRANCHED); 3212 assert(conshdlr->lastenforelaxresult != SCIP_REDUCEDDOM); 3213 assert(conshdlr->lastenforelaxresult != SCIP_DIDNOTRUN); 3214 3215 /* if we already enforced the same relaxation solution at this node, we will only enforce new constraints in the 3216 * following; however, the result of the last call for the old constraint is still valid and we have to ensure 3217 * that an infeasibility in the last call is not lost because we only enforce new constraints 3218 */ 3219 if( conshdlr->lastenforelaxresult == SCIP_INFEASIBLE ) 3220 { 3221 *result = SCIP_INFEASIBLE; 3222 lastinfeasible = TRUE; 3223 } 3224 else 3225 lastinfeasible = FALSE; 3226 3227 /* all constraints that were not yet enforced on the new relaxation solution must be useful constraints, which means, 3228 * that the new constraints are the last constraints of the useful ones 3229 */ 3230 nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss; 3231 nusefulconss = nconss; 3232 firstcons = conshdlr->lastnusefulenfoconss; 3233 relaxchanged = FALSE; 3234 } 3235 else 3236 { 3237 /* on a new relaxation solution or a new node, we want to enforce all constraints */ 3238 nconss = conshdlr->nenfoconss; 3239 nusefulconss = conshdlr->nusefulenfoconss; 3240 firstcons = 0; 3241 relaxchanged = TRUE; 3242 lastinfeasible = FALSE; 3243 } 3244 assert(firstcons >= 0); 3245 assert(firstcons + nconss <= conshdlr->nenfoconss); 3246 assert(nusefulconss <= nconss); 3247 3248 /* constraint handlers without constraints should only be called once */ 3249 if( nconss > 0 || (!conshdlr->needscons && relaxchanged) ) 3250 { 3251 SCIP_CONS** conss; 3252 SCIP_Longint oldndomchgs; 3253 SCIP_Longint oldnprobdomchgs; 3254 int oldncuts; 3255 int oldnactiveconss; 3256 3257 assert(conshdlr->consenforelax != NULL); 3258 3259 SCIPdebugMessage("enforcing constraints %d to %d of %d constraints of handler <%s> (%s relaxation solution)\n", 3260 firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, relaxchanged ? "new" : "old"); 3261 3262 /* remember the number of processed constraints on the current relaxation solution */ 3263 conshdlr->lastenforelaxrelaxcount = stat->relaxcount; 3264 conshdlr->lastenforelaxdomchgcount = stat->domchgcount; 3265 conshdlr->lastenforelaxnode = stat->nnodes; 3266 conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss; 3267 3268 /* get the array of the constraints to be processed */ 3269 conss = &(conshdlr->enfoconss[firstcons]); 3270 3271 oldncuts = SCIPsepastoreGetNCuts(sepastore); 3272 oldnactiveconss = stat->nactiveconss; 3273 oldndomchgs = stat->nboundchgs + stat->nholechgs; 3274 oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs; 3275 3276 /* check, if we want to use eager evaluation */ 3277 if( (conshdlr->eagerfreq == 0 && conshdlr->nenforelaxcalls == 0) 3278 || (conshdlr->eagerfreq > 0 && conshdlr->nenforelaxcalls % conshdlr->eagerfreq == 0) ) 3279 nusefulconss = nconss; 3280 3281 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 3282 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 3283 * external method; to avoid this, these changes will be buffered and processed after the method call 3284 */ 3285 conshdlrDelayUpdates(conshdlr); 3286 3287 /* start timing */ 3288 SCIPclockStart(conshdlr->enforelaxtime, set); 3289 3290 /* call external method */ 3291 SCIP_CALL( conshdlr->consenforelax(set->scip, relaxsol, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) ); 3292 SCIPdebugMessage(" -> enforcing returned result <%d>\n", *result); 3293 3294 /* stop timing */ 3295 SCIPclockStop(conshdlr->enforelaxtime, set); 3296 3297 /* perform the cached constraint updates */ 3298 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 3299 3300 /* update statistics */ 3301 conshdlr->nenforelaxcalls++; 3302 if( *result == SCIP_CUTOFF ) 3303 conshdlr->ncutoffs++; 3304 conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/ 3305 conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/ 3306 3307 if( *result != SCIP_BRANCHED ) 3308 { 3309 assert(tree->nchildren == 0); 3310 3311 /* update domain reductions; therefore remove the domain 3312 * reduction counts which were generated in probing mode */ 3313 conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs; 3314 conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs); 3315 } 3316 else 3317 conshdlr->nchildren += tree->nchildren; 3318 3319 /* remember the result of the enforcement call */ 3320 conshdlr->lastenforelaxresult = *result; 3321 3322 /* evaluate result */ 3323 if( *result != SCIP_CUTOFF 3324 && *result != SCIP_CONSADDED 3325 && *result != SCIP_REDUCEDDOM 3326 && *result != SCIP_SEPARATED 3327 && *result != SCIP_BRANCHED 3328 && *result != SCIP_SOLVELP 3329 && *result != SCIP_INFEASIBLE 3330 && *result != SCIP_FEASIBLE ) 3331 { 3332 SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation solutions returned invalid result <%d>\n", 3333 conshdlr->name, *result); 3334 return SCIP_INVALIDRESULT; 3335 } 3336 3337 /* if the same relaxation solution was already enforced at this node, we only enforced new constraints this time; 3338 * if the enforelax call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the 3339 * last call detected infeasibility for the old constraints, we have to change the result to infeasible 3340 */ 3341 if( lastinfeasible && *result == SCIP_FEASIBLE ) 3342 *result = SCIP_INFEASIBLE; 3343 } 3344 3345 return SCIP_OKAY; 3346 } 3347 3348 /** calls enforcing method of constraint handler for LP solution for all constraints added after last 3349 * conshdlrResetEnfo() call 3350 */ 3351 SCIP_RETCODE SCIPconshdlrEnforceLPSol( 3352 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3353 BMS_BLKMEM* blkmem, /**< block memory */ 3354 SCIP_SET* set, /**< global SCIP settings */ 3355 SCIP_STAT* stat, /**< dynamic problem statistics */ 3356 SCIP_TREE* tree, /**< branch and bound tree */ 3357 SCIP_SEPASTORE* sepastore, /**< separation storage */ 3358 SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */ 3359 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 3360 ) 3361 { 3362 assert(conshdlr != NULL); 3363 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 3364 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 3365 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 3366 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 3367 assert(stat != NULL); 3368 assert(conshdlr->lastenfolplpcount != stat->lpcount 3369 || conshdlr->lastenfolpdomchgcount != stat->domchgcount 3370 || conshdlr->lastenfolpnode != stat->nnodes 3371 || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss)); 3372 assert(set != NULL); 3373 assert(tree != NULL); 3374 assert(tree->nchildren == 0); 3375 assert(result != NULL); 3376 3377 *result = SCIP_FEASIBLE; 3378 3379 if( conshdlr->consenfolp != NULL ) 3380 { 3381 int nconss; 3382 int nusefulconss; 3383 int firstcons; 3384 SCIP_Bool lpchanged; 3385 SCIP_Bool lastinfeasible; 3386 3387 /* check, if this LP solution was already enforced at this node */ 3388 if( conshdlr->lastenfolplpcount == stat->lpcount 3389 && conshdlr->lastenfolpdomchgcount == stat->domchgcount 3390 && conshdlr->lastenfolpnode == stat->nnodes 3391 && conshdlr->lastenfolpresult != SCIP_CONSADDED ) 3392 { 3393 assert(conshdlr->lastenfolpresult == SCIP_FEASIBLE || conshdlr->lastenfolpresult == SCIP_INFEASIBLE 3394 || conshdlr->lastenfolpresult == SCIP_SEPARATED ); 3395 3396 /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the 3397 * following; however, the result of the last call for the old constraint is still valid and we have to ensure 3398 * that an infeasibility in the last call is not lost because we only enforce new constraints 3399 */ 3400 if( conshdlr->lastenfolpresult == SCIP_FEASIBLE ) 3401 lastinfeasible = FALSE; 3402 else 3403 { 3404 assert(conshdlr->lastenfolpresult == SCIP_INFEASIBLE || conshdlr->lastenfolpresult == SCIP_SEPARATED); 3405 *result = SCIP_INFEASIBLE; 3406 lastinfeasible = TRUE; 3407 } 3408 3409 /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means, 3410 * that the new constraints are the last constraints of the useful ones 3411 */ 3412 nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss; 3413 nusefulconss = nconss; 3414 firstcons = conshdlr->lastnusefulenfoconss; 3415 lpchanged = FALSE; 3416 } 3417 else 3418 { 3419 /* on a new LP solution or a new node, we want to enforce all constraints */ 3420 nconss = conshdlr->nenfoconss; 3421 nusefulconss = conshdlr->nusefulenfoconss; 3422 firstcons = 0; 3423 lpchanged = TRUE; 3424 lastinfeasible = FALSE; 3425 } 3426 assert(firstcons >= 0); 3427 assert(firstcons + nconss <= conshdlr->nenfoconss); 3428 assert(nusefulconss <= nconss); 3429 3430 /* constraint handlers without constraints should only be called once */ 3431 if( nconss > 0 || (!conshdlr->needscons && lpchanged) ) 3432 { 3433 SCIP_CONS** conss; 3434 SCIP_Longint oldndomchgs; 3435 SCIP_Longint oldnprobdomchgs; 3436 int oldncuts; 3437 int oldnactiveconss; 3438 3439 SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s LP solution)\n", 3440 firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, lpchanged ? "new" : "old"); 3441 3442 /* remember the number of processed constraints on the current LP solution */ 3443 conshdlr->lastenfolplpcount = stat->lpcount; 3444 conshdlr->lastenfolpdomchgcount = stat->domchgcount; 3445 conshdlr->lastenfolpnode = stat->nnodes; 3446 conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss; 3447 3448 /* get the array of the constraints to be processed */ 3449 conss = nconss > 0 ? conshdlr->enfoconss + firstcons : NULL; 3450 3451 oldncuts = SCIPsepastoreGetNCuts(sepastore); 3452 oldnactiveconss = stat->nactiveconss; 3453 oldndomchgs = stat->nboundchgs + stat->nholechgs; 3454 oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs; 3455 3456 /* check, if we want to use eager evaluation */ 3457 if( (conshdlr->eagerfreq == 0 && conshdlr->nenfolpcalls == 0) 3458 || (conshdlr->eagerfreq > 0 && conshdlr->nenfolpcalls % conshdlr->eagerfreq == 0) ) 3459 nusefulconss = nconss; 3460 3461 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 3462 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 3463 * external method; to avoid this, these changes will be buffered and processed after the method call 3464 */ 3465 conshdlrDelayUpdates(conshdlr); 3466 3467 /* start timing */ 3468 SCIPclockStart(conshdlr->enfolptime, set); 3469 3470 /* call external method */ 3471 SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, result) ); 3472 SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result); 3473 3474 /* stop timing */ 3475 SCIPclockStop(conshdlr->enfolptime, set); 3476 3477 /* perform the cached constraint updates */ 3478 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 3479 3480 /* remember the result of the enforcement call */ 3481 conshdlr->lastenfolpresult = *result; 3482 3483 /* update statistics */ 3484 conshdlr->nenfolpcalls++; 3485 if( *result == SCIP_CUTOFF ) 3486 conshdlr->ncutoffs++; 3487 conshdlr->ncutsfound += SCIPsepastoreGetNCuts(sepastore) - oldncuts; /*lint !e776*/ 3488 conshdlr->nconssfound += MAX(stat->nactiveconss - oldnactiveconss, 0); /*lint !e776*/ 3489 if( *result != SCIP_BRANCHED ) 3490 { 3491 assert(tree->nchildren == 0); 3492 3493 /* update domain reductions; therefore remove the domain 3494 * reduction counts which were generated in probing mode */ 3495 conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs; 3496 conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs); 3497 } 3498 else 3499 conshdlr->nchildren += tree->nchildren; 3500 3501 /* evaluate result */ 3502 if( *result != SCIP_CUTOFF 3503 && *result != SCIP_CONSADDED 3504 && *result != SCIP_REDUCEDDOM 3505 && *result != SCIP_SEPARATED 3506 && *result != SCIP_SOLVELP 3507 && *result != SCIP_BRANCHED 3508 && *result != SCIP_INFEASIBLE 3509 && *result != SCIP_FEASIBLE ) 3510 { 3511 SCIPerrorMessage("enforcing method of constraint handler <%s> for LP solutions returned invalid result <%d>\n", 3512 conshdlr->name, *result); 3513 return SCIP_INVALIDRESULT; 3514 } 3515 3516 /* if the same LP solution was already enforced at this node, we only enforced new constraints this time; 3517 * if the enfolp call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the 3518 * last call detected infeasibility for the old constraints, we have to change the result to infeasible 3519 */ 3520 if( lastinfeasible && *result == SCIP_FEASIBLE ) 3521 *result = SCIP_INFEASIBLE; 3522 } 3523 } 3524 3525 return SCIP_OKAY; 3526 } 3527 3528 /** calls diving solution enforcement callback of constraint handler, if it exists */ 3529 SCIP_RETCODE SCIPconshdlrGetDiveBoundChanges( 3530 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3531 SCIP_SET* set, /**< global SCIP settings */ 3532 SCIP_DIVESET* diveset, /**< diving settings to control scoring */ 3533 SCIP_SOL* sol, /**< current solution of diving mode */ 3534 SCIP_Bool* success, /**< pointer to store whether constraint handler successfully found a variable */ 3535 SCIP_Bool* infeasible /**< pointer to store whether the current node was detected to be infeasible */ 3536 ) 3537 { 3538 assert(conshdlr != NULL); 3539 assert(set != NULL); 3540 assert(diveset != NULL); 3541 assert(sol != NULL); 3542 assert(success != NULL); 3543 assert(infeasible != NULL); 3544 3545 if( conshdlr->consgetdivebdchgs != NULL ) 3546 { 3547 SCIP_CALL( conshdlr->consgetdivebdchgs(set->scip, conshdlr, diveset, sol, success, infeasible) ); 3548 } 3549 3550 return SCIP_OKAY; 3551 } 3552 3553 /** calls enforcing method of constraint handler for pseudo solution for all constraints added after last 3554 * conshdlrResetEnfo() call 3555 */ 3556 SCIP_RETCODE SCIPconshdlrEnforcePseudoSol( 3557 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3558 BMS_BLKMEM* blkmem, /**< block memory */ 3559 SCIP_SET* set, /**< global SCIP settings */ 3560 SCIP_STAT* stat, /**< dynamic problem statistics */ 3561 SCIP_TREE* tree, /**< branch and bound tree */ 3562 SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */ 3563 SCIP_Bool solinfeasible, /**< was the solution already found out to be infeasible? */ 3564 SCIP_Bool objinfeasible, /**< is the solution infeasible anyway due to violating lower objective bound? */ 3565 SCIP_Bool forced, /**< should enforcement of pseudo solution be forced? */ 3566 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 3567 ) 3568 { 3569 assert(conshdlr != NULL); 3570 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 3571 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 3572 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 3573 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 3574 assert(stat != NULL); 3575 assert(conshdlr->lastenfopsdomchgcount != stat->domchgcount 3576 || conshdlr->lastenfopsnode != stat->nnodes 3577 || (0 <= conshdlr->lastnusefulenfoconss && conshdlr->lastnusefulenfoconss <= conshdlr->nusefulenfoconss)); 3578 assert(set != NULL); 3579 assert(tree != NULL); 3580 assert(tree->nchildren == 0); 3581 assert(result != NULL); 3582 3583 /* no enforcing of pseudo solution */ 3584 if( set->cons_disableenfops && SCIPbranchcandGetNPseudoCands(branchcand) > 0 ) 3585 { 3586 *result = SCIP_INFEASIBLE; 3587 return SCIP_OKAY; 3588 } 3589 3590 *result = SCIP_FEASIBLE; 3591 if( conshdlr->consenfops != NULL ) 3592 { 3593 int nconss; 3594 int nusefulconss; 3595 int firstcons; 3596 SCIP_Bool pschanged; 3597 SCIP_Bool lastinfeasible; 3598 3599 /* check, if this pseudo solution was already enforced at this node */ 3600 if( !forced && conshdlr->lastenfopsdomchgcount == stat->domchgcount 3601 && conshdlr->lastenfopsnode == stat->nnodes 3602 && conshdlr->lastenfopsresult != SCIP_CONSADDED 3603 && conshdlr->lastenfopsresult != SCIP_SOLVELP 3604 ) 3605 { 3606 assert(conshdlr->lastenfopsresult != SCIP_CUTOFF); 3607 assert(conshdlr->lastenfopsresult != SCIP_BRANCHED); 3608 assert(conshdlr->lastenfopsresult != SCIP_REDUCEDDOM); 3609 assert(conshdlr->lastenfopsresult != SCIP_DIDNOTRUN || objinfeasible); 3610 3611 /* if we already enforced the same pseudo solution at this node, we will only enforce new constraints in the 3612 * following; however, the result of the last call for the old constraint is still valid and we have to ensure 3613 * that an infeasibility in the last call is not lost because we only enforce new constraints 3614 */ 3615 if( conshdlr->lastenfopsresult == SCIP_INFEASIBLE ) 3616 { 3617 *result = SCIP_INFEASIBLE; 3618 lastinfeasible = TRUE; 3619 } 3620 else 3621 lastinfeasible = FALSE; 3622 3623 /* all constraints that were not yet enforced on the new LP solution must be useful constraints, which means, 3624 * that the new constraints are the last constraints of the useful ones 3625 */ 3626 nconss = conshdlr->nusefulenfoconss - conshdlr->lastnusefulenfoconss; 3627 nusefulconss = nconss; 3628 firstcons = conshdlr->lastnusefulenfoconss; 3629 pschanged = FALSE; 3630 } 3631 else 3632 { 3633 /* on a new pseudo solution or a new node, we want to enforce all constraints */ 3634 nconss = conshdlr->nenfoconss; 3635 nusefulconss = conshdlr->nusefulenfoconss; 3636 firstcons = 0; 3637 pschanged = TRUE; 3638 lastinfeasible = FALSE; 3639 } 3640 assert(firstcons >= 0); 3641 assert(firstcons + nconss <= conshdlr->nenfoconss); 3642 assert(nusefulconss <= nconss); 3643 3644 /* constraint handlers without constraints should only be called once */ 3645 if( nconss > 0 || (!conshdlr->needscons && pschanged) ) 3646 { 3647 SCIP_CONS** conss; 3648 SCIP_Longint oldndomchgs; 3649 SCIP_Longint oldnprobdomchgs; 3650 3651 SCIPsetDebugMsg(set, "enforcing constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, objinfeasible=%u)\n", 3652 firstcons, firstcons + nconss - 1, conshdlr->nenfoconss, conshdlr->name, pschanged ? "new" : "old", objinfeasible); 3653 3654 /* remember the number of processed constraints on the current pseudo solution */ 3655 conshdlr->lastenfopsdomchgcount = stat->domchgcount; 3656 conshdlr->lastenfopsnode = stat->nnodes; 3657 conshdlr->lastnusefulenfoconss = conshdlr->nusefulenfoconss; 3658 3659 /* get the array of the constraints to be processed */ 3660 conss = &(conshdlr->enfoconss[firstcons]); 3661 3662 oldndomchgs = stat->nboundchgs + stat->nholechgs; 3663 oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs; 3664 3665 /* check, if we want to use eager evaluation */ 3666 if( (conshdlr->eagerfreq == 0 && conshdlr->nenfopscalls == 0) 3667 || (conshdlr->eagerfreq > 0 && conshdlr->nenfopscalls % conshdlr->eagerfreq == 0) ) 3668 nusefulconss = nconss; 3669 3670 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 3671 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 3672 * external method; to avoid this, these changes will be buffered and processed after the method call 3673 */ 3674 conshdlrDelayUpdates(conshdlr); 3675 3676 /* start timing */ 3677 SCIPclockStart(conshdlr->enfopstime, set); 3678 3679 /* call external method */ 3680 SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, conss, nconss, nusefulconss, solinfeasible, objinfeasible, result) ); 3681 SCIPsetDebugMsg(set, " -> enforcing returned result <%d>\n", *result); 3682 3683 /* stop timing */ 3684 SCIPclockStop(conshdlr->enfopstime, set); 3685 3686 /* perform the cached constraint updates */ 3687 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 3688 3689 /* update statistics */ 3690 if( *result != SCIP_DIDNOTRUN ) 3691 conshdlr->nenfopscalls++; 3692 else if( !objinfeasible ) 3693 { 3694 SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions was skipped, even though the solution was not objective-infeasible\n", 3695 conshdlr->name); 3696 conshdlr->lastenfopsresult = *result; 3697 3698 return SCIP_INVALIDRESULT; 3699 } 3700 /* A constraint handler might return SCIP_DIDNOTRUN and not check any constraints in case objinfeasible was 3701 * TRUE; we change the result pointer to SCIP_INFEASIBLE in this case. 3702 */ 3703 else 3704 *result = SCIP_INFEASIBLE; 3705 3706 if( *result == SCIP_CUTOFF ) 3707 conshdlr->ncutoffs++; 3708 3709 if( *result != SCIP_BRANCHED ) 3710 { 3711 assert(tree->nchildren == 0); 3712 3713 /* update domain reductions; therefore remove the domain 3714 * reduction counts which were generated in probing mode */ 3715 conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs; 3716 conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs); 3717 } 3718 else 3719 conshdlr->nchildren += tree->nchildren; 3720 3721 /* remember the result of the enforcement call */ 3722 conshdlr->lastenfopsresult = *result; 3723 3724 /* evaluate result */ 3725 if( *result != SCIP_CUTOFF 3726 && *result != SCIP_CONSADDED 3727 && *result != SCIP_REDUCEDDOM 3728 && *result != SCIP_BRANCHED 3729 && *result != SCIP_SOLVELP 3730 && *result != SCIP_INFEASIBLE 3731 && *result != SCIP_FEASIBLE 3732 && *result != SCIP_DIDNOTRUN ) 3733 { 3734 SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n", 3735 conshdlr->name, *result); 3736 return SCIP_INVALIDRESULT; 3737 } 3738 3739 /* if the same pseudo solution was already enforced at this node, we only enforced new constraints this time; 3740 * if the enfops call returns feasible now, the solution is only feasible w.r.t. the new constraints, if the 3741 * last call detected infeasibility for the old constraints, we have to change the result to infeasible 3742 */ 3743 if( lastinfeasible && *result == SCIP_FEASIBLE ) 3744 *result = SCIP_INFEASIBLE; 3745 } 3746 else if( objinfeasible ) 3747 { 3748 /* 3749 * Even if nothing is enforced, the solution might still be infeasible due to violating lower bound. 3750 * Make sure the result is updated in this case as well. 3751 */ 3752 *result = SCIP_INFEASIBLE; 3753 } 3754 } 3755 3756 return SCIP_OKAY; 3757 } 3758 3759 /** calls feasibility check method of constraint handler */ 3760 SCIP_RETCODE SCIPconshdlrCheck( 3761 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3762 BMS_BLKMEM* blkmem, /**< block memory */ 3763 SCIP_SET* set, /**< global SCIP settings */ 3764 SCIP_STAT* stat, /**< dynamic problem statistics */ 3765 SCIP_SOL* sol, /**< primal CIP solution */ 3766 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */ 3767 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */ 3768 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */ 3769 SCIP_Bool completely, /**< Should all violations be checked? */ 3770 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 3771 ) 3772 { 3773 assert(conshdlr != NULL); 3774 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 3775 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 3776 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 3777 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 3778 assert(set != NULL); 3779 assert(result != NULL); 3780 3781 *result = SCIP_FEASIBLE; 3782 3783 if( conshdlr->conscheck != NULL && (!conshdlr->needscons || conshdlr->ncheckconss > 0) ) 3784 { 3785 SCIPsetDebugMsg(set, "checking %d constraints of handler <%s>\n", conshdlr->ncheckconss, conshdlr->name); 3786 3787 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 3788 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 3789 * external method; to avoid this, these changes will be buffered and processed after the method call 3790 */ 3791 conshdlrDelayUpdates(conshdlr); 3792 3793 /* start timing */ 3794 SCIPclockStart(conshdlr->checktime, set); 3795 3796 /* call external method */ 3797 SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, conshdlr->checkconss, conshdlr->ncheckconss, 3798 sol, checkintegrality, checklprows, printreason, completely, result) ); 3799 SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result); 3800 3801 /* stop timing */ 3802 SCIPclockStop(conshdlr->checktime, set); 3803 3804 /* update statistics */ 3805 conshdlr->ncheckcalls++; 3806 3807 /* perform the cached constraint updates */ 3808 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 3809 3810 /* evaluate result */ 3811 if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE ) 3812 { 3813 SCIPerrorMessage("feasibility check of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name, *result); 3814 return SCIP_INVALIDRESULT; 3815 } 3816 } 3817 3818 return SCIP_OKAY; 3819 } 3820 3821 /** calls propagation method of constraint handler */ 3822 SCIP_RETCODE SCIPconshdlrPropagate( 3823 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3824 BMS_BLKMEM* blkmem, /**< block memory */ 3825 SCIP_SET* set, /**< global SCIP settings */ 3826 SCIP_STAT* stat, /**< dynamic problem statistics */ 3827 int depth, /**< depth of current node */ 3828 SCIP_Bool fullpropagation, /**< should all constraints be propagated (or only new ones)? */ 3829 SCIP_Bool execdelayed, /**< execute propagation method even if it is marked to be delayed */ 3830 SCIP_Bool instrongbranching, /**< are we currently doing strong branching? */ 3831 SCIP_PROPTIMING proptiming, /**< current point in the node solving process */ 3832 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 3833 ) 3834 { 3835 assert(conshdlr != NULL); 3836 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 3837 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 3838 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 3839 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 3840 assert(stat != NULL); 3841 assert(conshdlr->lastpropdomchgcount != stat->domchgcount 3842 || (0 <= conshdlr->lastnusefulpropconss && conshdlr->lastnusefulpropconss <= conshdlr->nusefulpropconss)); 3843 assert(set != NULL); 3844 assert(depth >= 0); 3845 assert(result != NULL); 3846 3847 *result = SCIP_DIDNOTRUN; 3848 3849 if( conshdlr->consprop != NULL 3850 && (!conshdlr->needscons || conshdlr->npropconss > 0) 3851 && ((depth == 0 && conshdlr->propfreq == 0) 3852 || (conshdlr->propfreq > 0 && depth % conshdlr->propfreq == 0) 3853 || conshdlr->propwasdelayed) ) 3854 { 3855 /* check, if propagation method should be delayed */ 3856 if( !conshdlr->delayprop || execdelayed ) 3857 { 3858 int nconss; 3859 int nusefulconss; 3860 int nmarkedpropconss; 3861 int firstcons; 3862 3863 /* check, if the current domains were already propagated */ 3864 if( !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount && conshdlr->nmarkedpropconss == 0 ) 3865 { 3866 /* all constraints that were not yet propagated on the new domains must be useful constraints, which means, 3867 * that the new constraints are the last constraints of the useful ones 3868 */ 3869 nconss = conshdlr->nusefulpropconss - conshdlr->lastnusefulpropconss; 3870 nusefulconss = nconss; 3871 firstcons = conshdlr->lastnusefulpropconss; 3872 } 3873 else 3874 { 3875 /* on new domains, we want to propagate all constraints */ 3876 nconss = conshdlr->npropconss; 3877 nusefulconss = conshdlr->nusefulpropconss; 3878 firstcons = 0; 3879 } 3880 assert(firstcons >= 0); 3881 assert(firstcons + nconss <= conshdlr->npropconss); 3882 assert(nusefulconss <= nconss); 3883 3884 nmarkedpropconss = conshdlr->nmarkedpropconss; 3885 3886 /* constraint handlers without constraints should only be called once */ 3887 if( nconss > 0 || fullpropagation 3888 || (!conshdlr->needscons && conshdlr->lastpropdomchgcount != stat->domchgcount) ) 3889 { 3890 SCIP_CONS** conss; 3891 SCIP_Longint oldndomchgs; 3892 SCIP_Longint oldnprobdomchgs; 3893 SCIP_Longint lastpropdomchgcount; 3894 int lastnusefulpropconss; 3895 3896 SCIPsetDebugMsg(set, "propagating constraints %d to %d of %d constraints of handler <%s> (%s pseudo solution, %d useful)\n", 3897 firstcons, firstcons + nconss - 1, conshdlr->npropconss, conshdlr->name, 3898 !fullpropagation && conshdlr->lastpropdomchgcount == stat->domchgcount ? "old" : "new", nusefulconss); 3899 3900 /* remember the number of processed constraints on the current domains */ 3901 lastpropdomchgcount = stat->domchgcount; 3902 lastnusefulpropconss = conshdlr->nusefulpropconss; 3903 3904 /* get the array of the constraints to be processed */ 3905 conss = nconss > 0 ? (conshdlr->propconss + firstcons) : NULL; 3906 3907 oldndomchgs = stat->nboundchgs + stat->nholechgs; 3908 oldnprobdomchgs = stat->nprobboundchgs + stat->nprobholechgs; 3909 3910 /* check, if we want to use eager evaluation */ 3911 if( (conshdlr->eagerfreq == 0 && conshdlr->npropcalls == 0) 3912 || (conshdlr->eagerfreq > 0 && conshdlr->npropcalls % conshdlr->eagerfreq == 0) ) 3913 nusefulconss = nconss; 3914 3915 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 3916 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 3917 * external method; to avoid this, these changes will be buffered and processed after the method call 3918 */ 3919 conshdlrDelayUpdates(conshdlr); 3920 conshdlr->duringprop = TRUE; 3921 3922 /* start timing */ 3923 if( instrongbranching ) 3924 SCIPclockStart(conshdlr->sbproptime, set); 3925 else 3926 SCIPclockStart(conshdlr->proptime, set); 3927 3928 assert(nusefulconss <= nconss); 3929 assert(nmarkedpropconss <= nconss); 3930 3931 /* call external method */ 3932 SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, conss, nconss, nusefulconss, nmarkedpropconss, proptiming, result) ); 3933 SCIPsetDebugMsg(set, " -> propagation returned result <%d>\n", *result); 3934 3935 /* stop timing */ 3936 if( instrongbranching ) 3937 SCIPclockStop(conshdlr->sbproptime, set); 3938 else 3939 SCIPclockStop(conshdlr->proptime, set); 3940 3941 /* perform the cached constraint updates */ 3942 conshdlr->duringprop = FALSE; 3943 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 3944 3945 /* update statistics */ 3946 if( *result != SCIP_DIDNOTRUN && *result != SCIP_DELAYED ) 3947 { 3948 conshdlr->lastpropdomchgcount = lastpropdomchgcount; 3949 conshdlr->lastnusefulpropconss = MIN(conshdlr->nusefulpropconss, lastnusefulpropconss); 3950 conshdlr->npropcalls++; 3951 } 3952 else 3953 { 3954 assert(lastpropdomchgcount == stat->domchgcount); 3955 assert(lastnusefulpropconss == conshdlr->nusefulpropconss); 3956 } 3957 if( *result == SCIP_CUTOFF ) 3958 conshdlr->ncutoffs++; 3959 3960 /* update domain reductions; therefore remove the domain 3961 * reduction counts which were generated in probing mode */ 3962 conshdlr->ndomredsfound += stat->nboundchgs + stat->nholechgs - oldndomchgs; 3963 conshdlr->ndomredsfound -= (stat->nprobboundchgs + stat->nprobholechgs - oldnprobdomchgs); 3964 3965 /* check result code of callback method */ 3966 if( *result != SCIP_CUTOFF 3967 && *result != SCIP_REDUCEDDOM 3968 && *result != SCIP_DIDNOTFIND 3969 && *result != SCIP_DIDNOTRUN 3970 && *result != SCIP_DELAYED 3971 && *result != SCIP_DELAYNODE ) 3972 { 3973 SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n", 3974 conshdlr->name, *result); 3975 return SCIP_INVALIDRESULT; 3976 } 3977 } 3978 } 3979 else 3980 { 3981 SCIPsetDebugMsg(set, "propagation method of constraint handler <%s> was delayed\n", conshdlr->name); 3982 *result = SCIP_DELAYED; 3983 } 3984 3985 /* remember whether propagation method was delayed */ 3986 conshdlr->propwasdelayed = (*result == SCIP_DELAYED); 3987 } 3988 3989 return SCIP_OKAY; 3990 } 3991 3992 /** calls presolving method of constraint handler */ 3993 SCIP_RETCODE SCIPconshdlrPresolve( 3994 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 3995 BMS_BLKMEM* blkmem, /**< block memory */ 3996 SCIP_SET* set, /**< global SCIP settings */ 3997 SCIP_STAT* stat, /**< dynamic problem statistics */ 3998 SCIP_PRESOLTIMING timing, /**< current presolving timing */ 3999 int nrounds, /**< number of presolving rounds already done */ 4000 int* nfixedvars, /**< pointer to total number of variables fixed of all presolvers */ 4001 int* naggrvars, /**< pointer to total number of variables aggregated of all presolvers */ 4002 int* nchgvartypes, /**< pointer to total number of variable type changes of all presolvers */ 4003 int* nchgbds, /**< pointer to total number of variable bounds tightened of all presolvers */ 4004 int* naddholes, /**< pointer to total number of domain holes added of all presolvers */ 4005 int* ndelconss, /**< pointer to total number of deleted constraints of all presolvers */ 4006 int* naddconss, /**< pointer to total number of added constraints of all presolvers */ 4007 int* nupgdconss, /**< pointer to total number of upgraded constraints of all presolvers */ 4008 int* nchgcoefs, /**< pointer to total number of changed coefficients of all presolvers */ 4009 int* nchgsides, /**< pointer to total number of changed left/right hand sides of all presolvers */ 4010 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 4011 ) 4012 { 4013 assert(conshdlr != NULL); 4014 assert(conshdlr->nusefulsepaconss <= conshdlr->nsepaconss); 4015 assert(conshdlr->nusefulenfoconss <= conshdlr->nenfoconss); 4016 assert(conshdlr->nusefulcheckconss <= conshdlr->ncheckconss); 4017 assert(conshdlr->nusefulpropconss <= conshdlr->npropconss); 4018 assert(set != NULL); 4019 assert(nfixedvars != NULL); 4020 assert(naggrvars != NULL); 4021 assert(nchgvartypes != NULL); 4022 assert(nchgbds != NULL); 4023 assert(naddholes != NULL); 4024 assert(ndelconss != NULL); 4025 assert(naddconss != NULL); 4026 assert(nupgdconss != NULL); 4027 assert(nchgcoefs != NULL); 4028 assert(nchgsides != NULL); 4029 assert(result != NULL); 4030 4031 *result = SCIP_DIDNOTRUN; 4032 4033 if( conshdlr->conspresol != NULL 4034 && (!conshdlr->needscons || conshdlr->nactiveconss > 0) 4035 && (conshdlr->maxprerounds == -1 || conshdlr->npresolcalls < conshdlr->maxprerounds ) ) 4036 { 4037 SCIPsetDebugMsg(set, "presolving %d constraints of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name); 4038 4039 /* check, if presolving method should be executed for the current timing */ 4040 if( timing & conshdlr->presoltiming ) 4041 { 4042 int nnewfixedvars; 4043 int nnewaggrvars; 4044 int nnewchgvartypes; 4045 int nnewchgbds; 4046 int nnewholes; 4047 int nnewdelconss; 4048 int nnewaddconss; 4049 int nnewupgdconss; 4050 int nnewchgcoefs; 4051 int nnewchgsides; 4052 4053 /* calculate the number of changes since last call */ 4054 nnewfixedvars = *nfixedvars - conshdlr->lastnfixedvars; 4055 nnewaggrvars = *naggrvars - conshdlr->lastnaggrvars; 4056 nnewchgvartypes = *nchgvartypes - conshdlr->lastnchgvartypes; 4057 nnewchgbds = *nchgbds - conshdlr->lastnchgbds; 4058 nnewholes = *naddholes - conshdlr->lastnaddholes; 4059 nnewdelconss = *ndelconss - conshdlr->lastndelconss; 4060 nnewaddconss = *naddconss - conshdlr->lastnaddconss; 4061 nnewupgdconss = *nupgdconss - conshdlr->lastnupgdconss; 4062 nnewchgcoefs = *nchgcoefs - conshdlr->lastnchgcoefs; 4063 nnewchgsides = *nchgsides - conshdlr->lastnchgsides; 4064 4065 /* remember the old number of changes */ 4066 conshdlr->lastnfixedvars = *nfixedvars; 4067 conshdlr->lastnaggrvars = *naggrvars; 4068 conshdlr->lastnchgvartypes = *nchgvartypes; 4069 conshdlr->lastnchgbds = *nchgbds; 4070 conshdlr->lastnaddholes = *naddholes; 4071 conshdlr->lastndelconss = *ndelconss; 4072 conshdlr->lastnaddconss = *naddconss; 4073 conshdlr->lastnupgdconss = *nupgdconss; 4074 conshdlr->lastnchgcoefs = *nchgcoefs; 4075 conshdlr->lastnchgsides = *nchgsides; 4076 4077 /* because during constraint processing, constraints of this handler may be deleted, activated, deactivated, 4078 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 4079 * external method; to avoid this, these changes will be buffered and processed after the method call 4080 */ 4081 conshdlrDelayUpdates(conshdlr); 4082 4083 /* start timing */ 4084 SCIPclockStart(conshdlr->presoltime, set); 4085 4086 /* call external method */ 4087 SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, conshdlr->conss, conshdlr->nactiveconss, nrounds, timing, 4088 nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes, 4089 nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides, 4090 nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes, 4091 ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) ); 4092 4093 /* stop timing */ 4094 SCIPclockStop(conshdlr->presoltime, set); 4095 4096 /* perform the cached constraint updates */ 4097 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 4098 4099 /* count the new changes */ 4100 conshdlr->nfixedvars += *nfixedvars - conshdlr->lastnfixedvars; 4101 conshdlr->naggrvars += *naggrvars - conshdlr->lastnaggrvars; 4102 conshdlr->nchgvartypes += *nchgvartypes - conshdlr->lastnchgvartypes; 4103 conshdlr->nchgbds += *nchgbds - conshdlr->lastnchgbds; 4104 conshdlr->naddholes += *naddholes - conshdlr->lastnaddholes; 4105 conshdlr->ndelconss += *ndelconss - conshdlr->lastndelconss; 4106 conshdlr->naddconss += *naddconss - conshdlr->lastnaddconss; 4107 conshdlr->nupgdconss += *nupgdconss - conshdlr->lastnupgdconss; 4108 conshdlr->nchgcoefs += *nchgcoefs - conshdlr->lastnchgcoefs; 4109 conshdlr->nchgsides += *nchgsides - conshdlr->lastnchgsides; 4110 4111 /* check result code of callback method */ 4112 if( *result != SCIP_CUTOFF 4113 && *result != SCIP_UNBOUNDED 4114 && *result != SCIP_SUCCESS 4115 && *result != SCIP_DIDNOTFIND 4116 && *result != SCIP_DIDNOTRUN 4117 && *result != SCIP_DELAYED ) 4118 { 4119 SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n", 4120 conshdlr->name, *result); 4121 return SCIP_INVALIDRESULT; 4122 } 4123 4124 /* increase the number of calls, if the presolving method tried to find reductions */ 4125 if( *result != SCIP_DIDNOTRUN ) 4126 ++(conshdlr->npresolcalls); 4127 } 4128 4129 SCIPsetDebugMsg(set, "after presolving %d constraints left of handler <%s>\n", conshdlr->nactiveconss, conshdlr->name); 4130 } 4131 4132 return SCIP_OKAY; 4133 } 4134 4135 /** calls variable deletion method of constraint handler */ 4136 SCIP_RETCODE SCIPconshdlrDelVars( 4137 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4138 BMS_BLKMEM* blkmem, /**< block memory */ 4139 SCIP_SET* set, /**< global SCIP settings */ 4140 SCIP_STAT* stat /**< dynamic problem statistics */ 4141 ) 4142 { 4143 assert(conshdlr != NULL); 4144 assert(set != NULL); 4145 4146 if( conshdlr->consdelvars != NULL ) 4147 { 4148 SCIPsetDebugMsg(set, "deleting variables in constraints of handler <%s>\n", conshdlr->name); 4149 4150 /* during constraint processing, constraints of this handler may be deleted, activated, deactivated, 4151 * enabled, disabled, marked obsolete or useful, which would change the conss array given to the 4152 * external method; to avoid this, these changes will be buffered and processed after the method call 4153 */ 4154 conshdlrDelayUpdates(conshdlr); 4155 4156 /* call external method */ 4157 SCIP_CALL( conshdlr->consdelvars(set->scip, conshdlr, conshdlr->conss, conshdlr->nconss) ); 4158 4159 /* perform the cached constraint updates */ 4160 SCIP_CALL( conshdlrForceUpdates(conshdlr, blkmem, set, stat) ); 4161 } 4162 4163 return SCIP_OKAY; 4164 } 4165 4166 /** locks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */ 4167 SCIP_RETCODE SCIPconshdlrLockVars( 4168 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4169 SCIP_SET* set /**< global SCIP settings */ 4170 ) 4171 { 4172 assert(conshdlr != NULL); 4173 assert(conshdlr->conslock != NULL); 4174 assert(!conshdlr->needscons); 4175 4176 SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, +1, 0) ); 4177 4178 return SCIP_OKAY; 4179 } 4180 4181 /** unlocks rounding of variables involved in the given constraint constraint handler that doesn't need constraints */ 4182 SCIP_RETCODE SCIPconshdlrUnlockVars( 4183 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4184 SCIP_SET* set /**< global SCIP settings */ 4185 ) 4186 { 4187 assert(conshdlr != NULL); 4188 assert(conshdlr->conslock != NULL); 4189 assert(!conshdlr->needscons); 4190 4191 SCIP_CALL( conshdlr->conslock(set->scip, conshdlr, NULL, SCIP_LOCKTYPE_MODEL, -1, 0) ); 4192 4193 return SCIP_OKAY; 4194 } 4195 4196 /** gets name of constraint handler */ 4197 const char* SCIPconshdlrGetName( 4198 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4199 ) 4200 { 4201 assert(conshdlr != NULL); 4202 4203 return conshdlr->name; 4204 } 4205 4206 /** gets description of constraint handler */ 4207 const char* SCIPconshdlrGetDesc( 4208 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4209 ) 4210 { 4211 assert(conshdlr != NULL); 4212 4213 return conshdlr->desc; 4214 } 4215 4216 /** gets user data of constraint handler */ 4217 SCIP_CONSHDLRDATA* SCIPconshdlrGetData( 4218 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4219 ) 4220 { 4221 assert(conshdlr != NULL); 4222 4223 return conshdlr->conshdlrdata; 4224 } 4225 4226 /** sets user data of constraint handler; user has to free old data in advance! */ 4227 void SCIPconshdlrSetData( 4228 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4229 SCIP_CONSHDLRDATA* conshdlrdata /**< new constraint handler user data */ 4230 ) 4231 { 4232 assert(conshdlr != NULL); 4233 4234 conshdlr->conshdlrdata = conshdlrdata; 4235 } 4236 4237 /** sets all separation related callbacks of the constraint handler */ 4238 void SCIPconshdlrSetSepa( 4239 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4240 SCIP_DECL_CONSSEPALP ((*conssepalp)), /**< separate cutting planes for LP solution */ 4241 SCIP_DECL_CONSSEPASOL ((*conssepasol)), /**< separate cutting planes for arbitrary primal solution */ 4242 int sepafreq, /**< frequency for separating cuts; zero means to separate only in the root node */ 4243 int sepapriority, /**< priority of the constraint handler for separation */ 4244 SCIP_Bool delaysepa /**< should separation method be delayed, if other separators found cuts? */ 4245 ) 4246 { 4247 assert(conshdlr != NULL); 4248 4249 assert(conssepalp != NULL || conssepasol != NULL || sepafreq == -1); 4250 4251 conshdlr->conssepalp = conssepalp; 4252 conshdlr->conssepasol = conssepasol; 4253 conshdlr->sepafreq = sepafreq; 4254 conshdlr->sepapriority = sepapriority; 4255 conshdlr->delaysepa = delaysepa; 4256 } 4257 4258 /** sets both the propagation callback and the propagation frequency of the constraint handler */ 4259 void SCIPconshdlrSetProp( 4260 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4261 SCIP_DECL_CONSPROP ((*consprop)), /**< propagate variable domains */ 4262 int propfreq, /**< frequency for propagating domains; zero means only preprocessing propagation */ 4263 SCIP_Bool delayprop, /**< should propagation method be delayed, if other propagators found reductions? */ 4264 SCIP_PROPTIMING timingmask /**< positions in the node solving loop where propagators should be executed */ 4265 ) 4266 { 4267 assert(conshdlr != NULL); 4268 4269 assert(consprop != NULL || propfreq == -1); 4270 4271 conshdlr->consprop = consprop; 4272 conshdlr->propfreq = propfreq; 4273 conshdlr->delayprop = delayprop; 4274 conshdlr->proptiming = timingmask; 4275 } 4276 4277 /** sets copy method of both the constraint handler and each associated constraint */ 4278 void SCIPconshdlrSetEnforelax( 4279 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4280 SCIP_DECL_CONSENFORELAX ((*consenforelax)) /**< constraint copying method */ 4281 ) 4282 { 4283 assert(conshdlr != NULL); 4284 4285 conshdlr->consenforelax = consenforelax; 4286 } 4287 4288 /** sets copy method of both the constraint handler and each associated constraint */ 4289 void SCIPconshdlrSetCopy( 4290 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4291 SCIP_DECL_CONSHDLRCOPY((*conshdlrcopy)), /**< copy method of constraint handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 4292 SCIP_DECL_CONSCOPY ((*conscopy)) /**< constraint copying method */ 4293 ) 4294 { 4295 assert(conshdlr != NULL); 4296 4297 assert(!conshdlr->needscons || (conshdlrcopy == NULL) == (conscopy == NULL)); 4298 4299 conshdlr->conshdlrcopy = conshdlrcopy; 4300 conshdlr->conscopy = conscopy; 4301 } 4302 4303 /** sets destructor method of constraint handler */ 4304 void SCIPconshdlrSetFree( 4305 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4306 SCIP_DECL_CONSFREE ((*consfree)) /**< destructor of constraint handler */ 4307 ) 4308 { 4309 assert(conshdlr != NULL); 4310 4311 conshdlr->consfree = consfree; 4312 } 4313 4314 /** sets initialization method of constraint handler */ 4315 void SCIPconshdlrSetInit( 4316 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4317 SCIP_DECL_CONSINIT ((*consinit)) /**< initialize constraint handler */ 4318 ) 4319 { 4320 assert(conshdlr != NULL); 4321 4322 conshdlr->consinit = consinit; 4323 } 4324 4325 /** sets deinitialization method of constraint handler */ 4326 void SCIPconshdlrSetExit( 4327 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4328 SCIP_DECL_CONSEXIT ((*consexit)) /**< deinitialize constraint handler */ 4329 ) 4330 { 4331 assert(conshdlr != NULL); 4332 4333 conshdlr->consexit = consexit; 4334 } 4335 4336 /** sets solving process initialization method of constraint handler */ 4337 void SCIPconshdlrSetInitsol( 4338 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4339 SCIP_DECL_CONSINITSOL((*consinitsol)) /**< solving process initialization method of constraint handler */ 4340 ) 4341 { 4342 assert(conshdlr != NULL); 4343 4344 conshdlr->consinitsol = consinitsol; 4345 } 4346 4347 /** sets solving process deinitialization method of constraint handler */ 4348 void SCIPconshdlrSetExitsol( 4349 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4350 SCIP_DECL_CONSEXITSOL ((*consexitsol)) /**< solving process deinitialization method of constraint handler */ 4351 ) 4352 { 4353 assert(conshdlr != NULL); 4354 4355 conshdlr->consexitsol = consexitsol; 4356 } 4357 4358 /** sets preprocessing initialization method of constraint handler */ 4359 void SCIPconshdlrSetInitpre( 4360 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4361 SCIP_DECL_CONSINITPRE((*consinitpre)) /**< preprocessing initialization method of constraint handler */ 4362 ) 4363 { 4364 assert(conshdlr != NULL); 4365 4366 conshdlr->consinitpre = consinitpre; 4367 } 4368 4369 /** sets preprocessing deinitialization method of constraint handler */ 4370 void SCIPconshdlrSetExitpre( 4371 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4372 SCIP_DECL_CONSEXITPRE((*consexitpre)) /**< preprocessing deinitialization method of constraint handler */ 4373 ) 4374 { 4375 assert(conshdlr != NULL); 4376 4377 conshdlr->consexitpre = consexitpre; 4378 } 4379 4380 /** sets presolving method of constraint handler */ 4381 SCIP_RETCODE SCIPconshdlrSetPresol( 4382 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4383 SCIP_DECL_CONSPRESOL ((*conspresol)), /**< presolving method of constraint handler */ 4384 int maxprerounds, /**< maximal number of presolving rounds the constraint handler participates in (-1: no limit) */ 4385 SCIP_PRESOLTIMING presoltiming /**< timing mask of the constraint handler's presolving method */ 4386 ) 4387 { 4388 assert(conshdlr != NULL); 4389 4390 conshdlr->conspresol = conspresol; 4391 conshdlr->maxprerounds = maxprerounds; 4392 4393 /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate 4394 * error message 4395 */ 4396 if( presoltiming < SCIP_PRESOLTIMING_FAST || presoltiming > SCIP_PRESOLTIMING_MAX ) 4397 { 4398 SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate " 4399 "'SCIP_PRESOLTIMING' for <%s> constraint handler instead.\n", conshdlr->name); 4400 4401 return SCIP_PARAMETERWRONGVAL; 4402 } 4403 4404 conshdlr->presoltiming = presoltiming; 4405 4406 return SCIP_OKAY; 4407 } 4408 4409 /** sets method of constraint handler to free specific constraint data */ 4410 void SCIPconshdlrSetDelete( 4411 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4412 SCIP_DECL_CONSDELETE ((*consdelete)) /**< free specific constraint data */ 4413 ) 4414 { 4415 assert(conshdlr != NULL); 4416 4417 conshdlr->consdelete = consdelete; 4418 } 4419 4420 /** sets method of constraint handler to transform constraint data into data belonging to the transformed problem */ 4421 void SCIPconshdlrSetTrans( 4422 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4423 SCIP_DECL_CONSTRANS ((*constrans)) /**< transform constraint data into data belonging to the transformed problem */ 4424 ) 4425 { 4426 assert(conshdlr != NULL); 4427 4428 conshdlr->constrans = constrans; 4429 } 4430 4431 /** sets method of constraint handler to initialize LP with relaxations of "initial" constraints */ 4432 void SCIPconshdlrSetInitlp( 4433 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4434 SCIP_DECL_CONSINITLP ((*consinitlp)) /**< initialize LP with relaxations of "initial" constraints */ 4435 ) 4436 { 4437 assert(conshdlr != NULL); 4438 4439 conshdlr->consinitlp = consinitlp; 4440 } 4441 4442 /** sets propagation conflict resolving method of constraint handler */ 4443 void SCIPconshdlrSetResprop( 4444 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4445 SCIP_DECL_CONSRESPROP ((*consresprop)) /**< propagation conflict resolving method */ 4446 ) 4447 { 4448 assert(conshdlr != NULL); 4449 4450 conshdlr->consresprop = consresprop; 4451 } 4452 4453 /** sets activation notification method of constraint handler */ 4454 void SCIPconshdlrSetActive( 4455 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4456 SCIP_DECL_CONSACTIVE ((*consactive)) /**< activation notification method */ 4457 ) 4458 { 4459 assert(conshdlr != NULL); 4460 4461 conshdlr->consactive = consactive; 4462 } 4463 4464 /** sets deactivation notification method of constraint handler */ 4465 void SCIPconshdlrSetDeactive( 4466 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4467 SCIP_DECL_CONSDEACTIVE((*consdeactive)) /**< deactivation notification method */ 4468 ) 4469 { 4470 assert(conshdlr != NULL); 4471 4472 conshdlr->consdeactive = consdeactive; 4473 } 4474 4475 /** sets enabling notification method of constraint handler */ 4476 void SCIPconshdlrSetEnable( 4477 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4478 SCIP_DECL_CONSENABLE ((*consenable)) /**< enabling notification method */ 4479 ) 4480 { 4481 assert(conshdlr != NULL); 4482 4483 conshdlr->consenable = consenable; 4484 } 4485 4486 /** sets disabling notification method of constraint handler */ 4487 void SCIPconshdlrSetDisable( 4488 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4489 SCIP_DECL_CONSDISABLE ((*consdisable)) /**< disabling notification method */ 4490 ) 4491 { 4492 assert(conshdlr != NULL); 4493 4494 conshdlr->consdisable = consdisable; 4495 } 4496 4497 /** sets variable deletion method of constraint handler */ 4498 void SCIPconshdlrSetDelvars( 4499 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4500 SCIP_DECL_CONSDELVARS ((*consdelvars)) /**< variable deletion method */ 4501 ) 4502 { 4503 assert(conshdlr != NULL); 4504 4505 conshdlr->consdelvars = consdelvars; 4506 } 4507 4508 /** sets constraint display method of constraint handler */ 4509 void SCIPconshdlrSetPrint( 4510 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4511 SCIP_DECL_CONSPRINT ((*consprint)) /**< constraint display method */ 4512 ) 4513 { 4514 assert(conshdlr != NULL); 4515 4516 conshdlr->consprint = consprint; 4517 } 4518 4519 /** sets constraint parsing method of constraint handler */ 4520 void SCIPconshdlrSetParse( 4521 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4522 SCIP_DECL_CONSPARSE ((*consparse)) /**< constraint parsing method */ 4523 ) 4524 { 4525 assert(conshdlr != NULL); 4526 4527 conshdlr->consparse = consparse; 4528 } 4529 4530 /** sets constraint variable getter method of constraint handler */ 4531 void SCIPconshdlrSetGetVars( 4532 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4533 SCIP_DECL_CONSGETVARS ((*consgetvars)) /**< constraint variable getter method */ 4534 ) 4535 { 4536 assert(conshdlr != NULL); 4537 4538 conshdlr->consgetvars = consgetvars; 4539 } 4540 4541 /** sets constraint variable number getter method of constraint handler */ 4542 void SCIPconshdlrSetGetNVars( 4543 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4544 SCIP_DECL_CONSGETNVARS((*consgetnvars)) /**< constraint variable number getter method */ 4545 ) 4546 { 4547 assert(conshdlr != NULL); 4548 4549 conshdlr->consgetnvars = consgetnvars; 4550 } 4551 4552 /** sets diving enforcement method of constraint handler */ 4553 void SCIPconshdlrSetGetDiveBdChgs( 4554 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4555 SCIP_DECL_CONSGETDIVEBDCHGS((*consgetdivebdchgs)) /**< constraint handler diving solution enforcement method */ 4556 ) 4557 { 4558 assert(conshdlr != NULL); 4559 4560 conshdlr->consgetdivebdchgs = consgetdivebdchgs; 4561 } 4562 4563 /** sets permutation symmetry detection graph getter method of constraint handler */ 4564 void SCIPconshdlrSetGetPermsymGraph( 4565 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4566 SCIP_DECL_CONSGETPERMSYMGRAPH((*consgetpermsymgraph)) /**< constraint permutation symmetry detection graph 4567 * getter method */ 4568 ) 4569 { 4570 assert(conshdlr != NULL); 4571 4572 conshdlr->consgetpermsymgraph = consgetpermsymgraph; 4573 } 4574 4575 /** sets signed permutation symmetry detection graph getter method of constraint handler */ 4576 void SCIPconshdlrSetGetSignedPermsymGraph( 4577 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 4578 SCIP_DECL_CONSGETSIGNEDPERMSYMGRAPH((*consgetsignedpermsymgraph)) /**< constraint permutation symmetry detection 4579 * graph getter method */ 4580 ) 4581 { 4582 assert(conshdlr != NULL); 4583 4584 conshdlr->consgetsignedpermsymgraph = consgetsignedpermsymgraph; 4585 } 4586 4587 /** gets array with constraints of constraint handler; the first SCIPconshdlrGetNActiveConss() entries are the active 4588 * constraints, the last SCIPconshdlrGetNConss() - SCIPconshdlrGetNActiveConss() constraints are deactivated 4589 * 4590 * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local 4591 * flag is TRUE) and the current node belongs to the corresponding sub tree. 4592 */ 4593 SCIP_CONS** SCIPconshdlrGetConss( 4594 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4595 ) 4596 { 4597 assert(conshdlr != NULL); 4598 4599 return conshdlr->conss; 4600 } 4601 4602 /** gets array with enforced constraints of constraint handler; this is local information */ 4603 SCIP_CONS** SCIPconshdlrGetEnfoConss( 4604 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4605 ) 4606 { 4607 assert(conshdlr != NULL); 4608 4609 return conshdlr->enfoconss; 4610 } 4611 4612 /** gets array with checked constraints of constraint handler; this is local information */ 4613 SCIP_CONS** SCIPconshdlrGetCheckConss( 4614 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4615 ) 4616 { 4617 assert(conshdlr != NULL); 4618 4619 return conshdlr->checkconss; 4620 } 4621 4622 /** gets array with delayed update constraints 4623 * 4624 * @attention Usually, there should be no need to access this array. Use this only if you are absolutely sure what you are doing. 4625 */ 4626 SCIP_CONS** SCIPconshdlrGetUpdateConss( 4627 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4628 ) 4629 { 4630 assert(conshdlr != NULL); 4631 4632 return conshdlr->updateconss; 4633 } 4634 4635 /** gets total number of existing transformed constraints of constraint handler */ 4636 int SCIPconshdlrGetNConss( 4637 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4638 ) 4639 { 4640 assert(conshdlr != NULL); 4641 4642 return conshdlr->nconss; 4643 } 4644 4645 /** gets number of enforced constraints of constraint handler; this is local information */ 4646 int SCIPconshdlrGetNEnfoConss( 4647 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4648 ) 4649 { 4650 assert(conshdlr != NULL); 4651 4652 return conshdlr->nenfoconss; 4653 } 4654 4655 /** gets number of checked constraints of constraint handler; this is local information */ 4656 int SCIPconshdlrGetNCheckConss( 4657 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4658 ) 4659 { 4660 assert(conshdlr != NULL); 4661 4662 return conshdlr->ncheckconss; 4663 } 4664 4665 /** gets number of active constraints of constraint handler 4666 * 4667 * @note A constraint is active if it is global and was not removed or it was added locally (in that case the local 4668 * flag is TRUE) and the current node belongs to the corresponding sub tree. 4669 */ 4670 int SCIPconshdlrGetNActiveConss( 4671 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4672 ) 4673 { 4674 assert(conshdlr != NULL); 4675 4676 return conshdlr->nactiveconss; 4677 } 4678 4679 /** gets number of enabled constraints of constraint handler */ 4680 int SCIPconshdlrGetNEnabledConss( 4681 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4682 ) 4683 { 4684 assert(conshdlr != NULL); 4685 4686 return conshdlr->nenabledconss; 4687 } 4688 4689 /** gets number of constraints that have delayed updates */ 4690 int SCIPconshdlrGetNUpdateConss( 4691 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4692 ) 4693 { 4694 assert(conshdlr != NULL); 4695 4696 return conshdlr->nupdateconss; 4697 } 4698 4699 /** enables or disables all clocks of \p conshdlr, depending on the value of the flag */ 4700 void SCIPconshdlrEnableOrDisableClocks( 4701 SCIP_CONSHDLR* conshdlr, /**< the constraint handler for which all clocks should be enabled or disabled */ 4702 SCIP_Bool enable /**< should the clocks of the constraint handler be enabled? */ 4703 ) 4704 { 4705 assert(conshdlr != NULL); 4706 4707 SCIPclockEnableOrDisable(conshdlr->setuptime, enable); 4708 SCIPclockEnableOrDisable(conshdlr->checktime, enable); 4709 SCIPclockEnableOrDisable(conshdlr->enfolptime, enable); 4710 SCIPclockEnableOrDisable(conshdlr->enfopstime, enable); 4711 SCIPclockEnableOrDisable(conshdlr->enforelaxtime, enable); 4712 SCIPclockEnableOrDisable(conshdlr->presoltime, enable); 4713 SCIPclockEnableOrDisable(conshdlr->proptime, enable); 4714 SCIPclockEnableOrDisable(conshdlr->resproptime, enable); 4715 SCIPclockEnableOrDisable(conshdlr->sbproptime, enable); 4716 SCIPclockEnableOrDisable(conshdlr->sepatime, enable); 4717 } 4718 4719 /** gets time in seconds used for setting up this constraint handler for new stages */ 4720 SCIP_Real SCIPconshdlrGetSetupTime( 4721 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4722 ) 4723 { 4724 assert(conshdlr != NULL); 4725 4726 return SCIPclockGetTime(conshdlr->setuptime); 4727 } 4728 4729 /** gets time in seconds used for presolving in this constraint handler */ 4730 SCIP_Real SCIPconshdlrGetPresolTime( 4731 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4732 ) 4733 { 4734 assert(conshdlr != NULL); 4735 4736 return SCIPclockGetTime(conshdlr->presoltime); 4737 } 4738 4739 /** gets time in seconds used for separation in this constraint handler */ 4740 SCIP_Real SCIPconshdlrGetSepaTime( 4741 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4742 ) 4743 { 4744 assert(conshdlr != NULL); 4745 4746 return SCIPclockGetTime(conshdlr->sepatime); 4747 } 4748 4749 /** gets time in seconds used for LP enforcement in this constraint handler */ 4750 SCIP_Real SCIPconshdlrGetEnfoLPTime( 4751 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4752 ) 4753 { 4754 assert(conshdlr != NULL); 4755 4756 return SCIPclockGetTime(conshdlr->enfolptime); 4757 } 4758 4759 /** gets time in seconds used for pseudo enforcement in this constraint handler */ 4760 SCIP_Real SCIPconshdlrGetEnfoPSTime( 4761 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4762 ) 4763 { 4764 assert(conshdlr != NULL); 4765 4766 return SCIPclockGetTime(conshdlr->enfopstime); 4767 } 4768 4769 /** gets time in seconds used for relaxation enforcement in this constraint handler */ 4770 SCIP_Real SCIPconshdlrGetEnfoRelaxTime( 4771 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4772 ) 4773 { 4774 assert(conshdlr != NULL); 4775 4776 return SCIPclockGetTime(conshdlr->enforelaxtime); 4777 } 4778 4779 /** gets time in seconds used for propagation in this constraint handler */ 4780 SCIP_Real SCIPconshdlrGetPropTime( 4781 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4782 ) 4783 { 4784 assert(conshdlr != NULL); 4785 4786 return SCIPclockGetTime(conshdlr->proptime); 4787 } 4788 4789 /** gets time in seconds used for propagation in this constraint handler during strong branching */ 4790 SCIP_Real SCIPconshdlrGetStrongBranchPropTime( 4791 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4792 ) 4793 { 4794 assert(conshdlr != NULL); 4795 4796 return SCIPclockGetTime(conshdlr->sbproptime); 4797 } 4798 4799 /** gets time in seconds used for feasibility checking in this constraint handler */ 4800 SCIP_Real SCIPconshdlrGetCheckTime( 4801 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4802 ) 4803 { 4804 assert(conshdlr != NULL); 4805 4806 return SCIPclockGetTime(conshdlr->checktime); 4807 } 4808 4809 /** gets time in seconds used for resolving propagation in this constraint handler */ 4810 SCIP_Real SCIPconshdlrGetRespropTime( 4811 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4812 ) 4813 { 4814 assert(conshdlr != NULL); 4815 4816 return SCIPclockGetTime(conshdlr->resproptime); 4817 } 4818 4819 /** gets number of calls to the constraint handler's separation method */ 4820 SCIP_Longint SCIPconshdlrGetNSepaCalls( 4821 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4822 ) 4823 { 4824 assert(conshdlr != NULL); 4825 4826 return conshdlr->nsepacalls; 4827 } 4828 4829 /** gets number of calls to the constraint handler's LP enforcing method */ 4830 SCIP_Longint SCIPconshdlrGetNEnfoLPCalls( 4831 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4832 ) 4833 { 4834 assert(conshdlr != NULL); 4835 4836 return conshdlr->nenfolpcalls; 4837 } 4838 4839 /** gets number of calls to the constraint handler's pseudo enforcing method */ 4840 SCIP_Longint SCIPconshdlrGetNEnfoPSCalls( 4841 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4842 ) 4843 { 4844 assert(conshdlr != NULL); 4845 4846 return conshdlr->nenfopscalls; 4847 } 4848 4849 /** gets number of calls to the constraint handler's relaxation enforcing method */ 4850 SCIP_Longint SCIPconshdlrGetNEnfoRelaxCalls( 4851 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4852 ) 4853 { 4854 assert(conshdlr != NULL); 4855 4856 return conshdlr->nenforelaxcalls; 4857 } 4858 4859 /** gets number of calls to the constraint handler's propagation method */ 4860 SCIP_Longint SCIPconshdlrGetNPropCalls( 4861 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4862 ) 4863 { 4864 assert(conshdlr != NULL); 4865 4866 return conshdlr->npropcalls; 4867 } 4868 4869 /** gets number of calls to the constraint handler's checking method */ 4870 SCIP_Longint SCIPconshdlrGetNCheckCalls( 4871 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4872 ) 4873 { 4874 assert(conshdlr != NULL); 4875 4876 return conshdlr->ncheckcalls; 4877 } 4878 4879 /** gets number of calls to the constraint handler's resolve propagation method */ 4880 SCIP_Longint SCIPconshdlrGetNRespropCalls( 4881 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4882 ) 4883 { 4884 assert(conshdlr != NULL); 4885 4886 return conshdlr->nrespropcalls; 4887 } 4888 4889 /** gets total number of times, this constraint handler detected a cutoff */ 4890 SCIP_Longint SCIPconshdlrGetNCutoffs( 4891 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4892 ) 4893 { 4894 assert(conshdlr != NULL); 4895 4896 return conshdlr->ncutoffs; 4897 } 4898 4899 /** gets total number of cuts found by this constraint handler */ 4900 SCIP_Longint SCIPconshdlrGetNCutsFound( 4901 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4902 ) 4903 { 4904 assert(conshdlr != NULL); 4905 4906 return conshdlr->ncutsfound; 4907 } 4908 4909 /** gets total number of cuts found by this constraint handler applied to lp */ 4910 SCIP_Longint SCIPconshdlrGetNCutsApplied( 4911 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4912 ) 4913 { 4914 assert(conshdlr != NULL); 4915 4916 return conshdlr->ncutsapplied; 4917 } 4918 4919 /** increase count of applied cuts */ 4920 void SCIPconshdlrIncNAppliedCuts( 4921 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4922 ) 4923 { 4924 assert(conshdlr != NULL); 4925 4926 ++conshdlr->ncutsapplied; 4927 } 4928 4929 /** increase count of found cuts */ 4930 void SCIPconshdlrIncNCutsFound( 4931 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4932 ) 4933 { 4934 assert(conshdlr != NULL); 4935 4936 ++conshdlr->ncutsfound; 4937 } 4938 4939 /** gets total number of additional constraints added by this constraint handler */ 4940 SCIP_Longint SCIPconshdlrGetNConssFound( 4941 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4942 ) 4943 { 4944 assert(conshdlr != NULL); 4945 4946 return conshdlr->nconssfound; 4947 } 4948 4949 /** gets total number of domain reductions found by this constraint handler */ 4950 SCIP_Longint SCIPconshdlrGetNDomredsFound( 4951 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4952 ) 4953 { 4954 assert(conshdlr != NULL); 4955 4956 return conshdlr->ndomredsfound; 4957 } 4958 4959 /** gets number of children created by this constraint handler */ 4960 SCIP_Longint SCIPconshdlrGetNChildren( 4961 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4962 ) 4963 { 4964 assert(conshdlr != NULL); 4965 4966 return conshdlr->nchildren; 4967 } 4968 4969 /** gets maximum number of active constraints of constraint handler existing at the same time */ 4970 int SCIPconshdlrGetMaxNActiveConss( 4971 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4972 ) 4973 { 4974 assert(conshdlr != NULL); 4975 4976 return conshdlr->maxnactiveconss; 4977 } 4978 4979 /** gets initial number of active constraints of constraint handler */ 4980 int SCIPconshdlrGetStartNActiveConss( 4981 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4982 ) 4983 { 4984 assert(conshdlr != NULL); 4985 4986 return conshdlr->startnactiveconss; 4987 } 4988 4989 /** gets number of variables fixed in presolving method of constraint handler */ 4990 int SCIPconshdlrGetNFixedVars( 4991 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 4992 ) 4993 { 4994 assert(conshdlr != NULL); 4995 4996 return conshdlr->nfixedvars; 4997 } 4998 4999 /** gets number of variables aggregated in presolving method of constraint handler */ 5000 int SCIPconshdlrGetNAggrVars( 5001 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5002 ) 5003 { 5004 assert(conshdlr != NULL); 5005 5006 return conshdlr->naggrvars; 5007 } 5008 5009 /** gets number of variable types changed in presolving method of constraint handler */ 5010 int SCIPconshdlrGetNChgVarTypes( 5011 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5012 ) 5013 { 5014 assert(conshdlr != NULL); 5015 5016 return conshdlr->nchgvartypes; 5017 } 5018 5019 /** gets number of bounds changed in presolving method of constraint handler */ 5020 int SCIPconshdlrGetNChgBds( 5021 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5022 ) 5023 { 5024 assert(conshdlr != NULL); 5025 5026 return conshdlr->nchgbds; 5027 } 5028 5029 /** gets number of holes added to domains of variables in presolving method of constraint handler */ 5030 int SCIPconshdlrGetNAddHoles( 5031 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5032 ) 5033 { 5034 assert(conshdlr != NULL); 5035 5036 return conshdlr->naddholes; 5037 } 5038 5039 /** gets number of constraints deleted in presolving method of constraint handler */ 5040 int SCIPconshdlrGetNDelConss( 5041 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5042 ) 5043 { 5044 assert(conshdlr != NULL); 5045 5046 return conshdlr->ndelconss; 5047 } 5048 5049 /** gets number of constraints added in presolving method of constraint handler */ 5050 int SCIPconshdlrGetNAddConss( 5051 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5052 ) 5053 { 5054 assert(conshdlr != NULL); 5055 5056 return conshdlr->naddconss; 5057 } 5058 5059 /** gets number of constraints upgraded in presolving method of constraint handler */ 5060 int SCIPconshdlrGetNUpgdConss( 5061 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5062 ) 5063 { 5064 assert(conshdlr != NULL); 5065 5066 return conshdlr->nupgdconss; 5067 } 5068 5069 /** gets number of coefficients changed in presolving method of constraint handler */ 5070 int SCIPconshdlrGetNChgCoefs( 5071 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5072 ) 5073 { 5074 assert(conshdlr != NULL); 5075 5076 return conshdlr->nchgcoefs; 5077 } 5078 5079 /** gets number of constraint sides changed in presolving method of constraint handler */ 5080 int SCIPconshdlrGetNChgSides( 5081 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5082 ) 5083 { 5084 assert(conshdlr != NULL); 5085 5086 return conshdlr->nchgsides; 5087 } 5088 5089 /** gets number of times the presolving method of the constraint handler was called and tried to find reductions */ 5090 int SCIPconshdlrGetNPresolCalls( 5091 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5092 ) 5093 { 5094 assert(conshdlr != NULL); 5095 5096 return conshdlr->npresolcalls; 5097 } 5098 5099 /** gets separation priority of constraint handler */ 5100 int SCIPconshdlrGetSepaPriority( 5101 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5102 ) 5103 { 5104 assert(conshdlr != NULL); 5105 5106 return conshdlr->sepapriority; 5107 } 5108 5109 /** gets enforcing priority of constraint handler */ 5110 int SCIPconshdlrGetEnfoPriority( 5111 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5112 ) 5113 { 5114 assert(conshdlr != NULL); 5115 5116 return conshdlr->enfopriority; 5117 } 5118 5119 /** gets checking priority of constraint handler */ 5120 int SCIPconshdlrGetCheckPriority( 5121 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5122 ) 5123 { 5124 assert(conshdlr != NULL); 5125 5126 return conshdlr->checkpriority; 5127 } 5128 5129 /** gets separation frequency of constraint handler */ 5130 int SCIPconshdlrGetSepaFreq( 5131 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5132 ) 5133 { 5134 assert(conshdlr != NULL); 5135 5136 return conshdlr->sepafreq; 5137 } 5138 5139 /** gets propagation frequency of constraint handler */ 5140 int SCIPconshdlrGetPropFreq( 5141 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5142 ) 5143 { 5144 assert(conshdlr != NULL); 5145 5146 return conshdlr->propfreq; 5147 } 5148 5149 /** gets frequency of constraint handler for eager evaluations in separation, propagation and enforcement */ 5150 int SCIPconshdlrGetEagerFreq( 5151 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5152 ) 5153 { 5154 assert(conshdlr != NULL); 5155 5156 return conshdlr->eagerfreq; 5157 } 5158 5159 /** needs constraint handler a constraint to be called? */ 5160 SCIP_Bool SCIPconshdlrNeedsCons( 5161 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5162 ) 5163 { 5164 assert(conshdlr != NULL); 5165 5166 return conshdlr->needscons; 5167 } 5168 5169 /** does the constraint handler perform presolving? */ 5170 SCIP_Bool SCIPconshdlrDoesPresolve( 5171 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5172 ) 5173 { 5174 assert(conshdlr != NULL); 5175 5176 return (conshdlr->conspresol != NULL); 5177 } 5178 5179 /** should separation method be delayed, if other separators found cuts? */ 5180 SCIP_Bool SCIPconshdlrIsSeparationDelayed( 5181 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5182 ) 5183 { 5184 assert(conshdlr != NULL); 5185 5186 return conshdlr->delaysepa; 5187 } 5188 5189 /** should propagation method be delayed, if other propagators found reductions? */ 5190 SCIP_Bool SCIPconshdlrIsPropagationDelayed( 5191 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5192 ) 5193 { 5194 assert(conshdlr != NULL); 5195 5196 return conshdlr->delayprop; 5197 } 5198 5199 /** was LP separation method delayed at the last call? */ 5200 SCIP_Bool SCIPconshdlrWasLPSeparationDelayed( 5201 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5202 ) 5203 { 5204 assert(conshdlr != NULL); 5205 5206 return conshdlr->sepalpwasdelayed; 5207 } 5208 5209 /** was primal solution separation method delayed at the last call? */ 5210 SCIP_Bool SCIPconshdlrWasSolSeparationDelayed( 5211 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5212 ) 5213 { 5214 assert(conshdlr != NULL); 5215 5216 return conshdlr->sepasolwasdelayed; 5217 } 5218 5219 /** was propagation method delayed at the last call? */ 5220 SCIP_Bool SCIPconshdlrWasPropagationDelayed( 5221 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5222 ) 5223 { 5224 assert(conshdlr != NULL); 5225 5226 return conshdlr->propwasdelayed; 5227 } 5228 5229 /** is constraint handler initialized? */ 5230 SCIP_Bool SCIPconshdlrIsInitialized( 5231 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5232 ) 5233 { 5234 assert(conshdlr != NULL); 5235 5236 return conshdlr->initialized; 5237 } 5238 5239 /** does the constraint handler have a copy function? */ 5240 SCIP_Bool SCIPconshdlrIsClonable( 5241 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5242 ) 5243 { 5244 assert(conshdlr != NULL); 5245 5246 return (conshdlr->conshdlrcopy != NULL); 5247 } 5248 5249 /** returns the timing mask of the propagation method of the constraint handler */ 5250 SCIP_PROPTIMING SCIPconshdlrGetPropTiming( 5251 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5252 ) 5253 { 5254 assert(conshdlr != NULL); 5255 5256 return conshdlr->proptiming; 5257 } 5258 5259 /** sets the timing mask of the propagation method of the constraint handler */ 5260 void SCIPconshdlrSetPropTiming( 5261 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 5262 SCIP_PROPTIMING proptiming /**< timing mask to be set */ 5263 ) 5264 { 5265 assert(conshdlr != NULL); 5266 5267 conshdlr->proptiming = proptiming; 5268 } 5269 5270 5271 /** returns the timing mask of the presolving method of the constraint handler */ 5272 SCIP_PRESOLTIMING SCIPconshdlrGetPresolTiming( 5273 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5274 ) 5275 { 5276 assert(conshdlr != NULL); 5277 5278 return conshdlr->presoltiming; 5279 } 5280 5281 /** sets the timing mask of the presolving method of the constraint handler */ 5282 void SCIPconshdlrSetPresolTiming( 5283 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 5284 SCIP_PRESOLTIMING presoltiming /** timing mask to be set */ 5285 ) 5286 { 5287 assert(conshdlr != NULL); 5288 5289 conshdlr->presoltiming = presoltiming; 5290 } 5291 5292 /** returns whether conshdlr supports permutation symmetry detection */ 5293 SCIP_Bool SCIPconshdlrSupportsPermsymDetection( 5294 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5295 ) 5296 { 5297 assert(conshdlr != NULL); 5298 5299 return conshdlr->consgetpermsymgraph != NULL; 5300 } 5301 5302 /** returns whether conshdlr supports signed permutation symmetry detection */ 5303 SCIP_Bool SCIPconshdlrSupportsSignedPermsymDetection( 5304 SCIP_CONSHDLR* conshdlr /**< constraint handler */ 5305 ) 5306 { 5307 assert(conshdlr != NULL); 5308 5309 return conshdlr->consgetsignedpermsymgraph != NULL; 5310 } 5311 5312 /* 5313 * Constraint set change methods 5314 */ 5315 5316 /** creates empty constraint set change data */ 5317 static 5318 SCIP_RETCODE conssetchgCreate( 5319 SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data */ 5320 BMS_BLKMEM* blkmem /**< block memory */ 5321 ) 5322 { 5323 assert(conssetchg != NULL); 5324 assert(blkmem != NULL); 5325 5326 SCIP_ALLOC( BMSallocBlockMemory(blkmem, conssetchg) ); 5327 (*conssetchg)->addedconss = NULL; 5328 (*conssetchg)->disabledconss = NULL; 5329 (*conssetchg)->addedconsssize = 0; 5330 (*conssetchg)->naddedconss = 0; 5331 (*conssetchg)->disabledconsssize = 0; 5332 (*conssetchg)->ndisabledconss = 0; 5333 5334 return SCIP_OKAY; 5335 } 5336 5337 /** releases all constraints of the constraint set change data */ 5338 static 5339 SCIP_RETCODE conssetchgRelease( 5340 SCIP_CONSSETCHG* conssetchg, /**< constraint set change data */ 5341 BMS_BLKMEM* blkmem, /**< block memory */ 5342 SCIP_SET* set /**< global SCIP settings */ 5343 ) 5344 { 5345 int i; 5346 5347 assert(conssetchg != NULL); 5348 5349 /* release constraints */ 5350 for( i = 0; i < conssetchg->naddedconss; ++i ) 5351 { 5352 if( conssetchg->addedconss[i] != NULL ) 5353 { 5354 SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[i], blkmem, set) ); 5355 } 5356 } 5357 for( i = 0; i < conssetchg->ndisabledconss; ++i ) 5358 { 5359 if( conssetchg->disabledconss[i] != NULL ) 5360 { 5361 SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[i], blkmem, set) ); 5362 } 5363 } 5364 5365 return SCIP_OKAY; 5366 } 5367 5368 /** frees constraint set change data and releases all included constraints */ 5369 SCIP_RETCODE SCIPconssetchgFree( 5370 SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change */ 5371 BMS_BLKMEM* blkmem, /**< block memory */ 5372 SCIP_SET* set /**< global SCIP settings */ 5373 ) 5374 { 5375 assert(conssetchg != NULL); 5376 assert(blkmem != NULL); 5377 5378 if( *conssetchg != NULL ) 5379 { 5380 /* release constraints */ 5381 SCIP_CALL( conssetchgRelease(*conssetchg, blkmem, set) ); 5382 5383 /* free memory */ 5384 BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->addedconss, (*conssetchg)->addedconsssize); 5385 BMSfreeBlockMemoryArrayNull(blkmem, &(*conssetchg)->disabledconss, (*conssetchg)->disabledconsssize); 5386 BMSfreeBlockMemory(blkmem, conssetchg); 5387 } 5388 5389 return SCIP_OKAY; 5390 } 5391 5392 /** ensures, that addedconss array can store at least num entries */ 5393 static 5394 SCIP_RETCODE conssetchgEnsureAddedconssSize( 5395 SCIP_CONSSETCHG* conssetchg, /**< constraint set change data structure */ 5396 BMS_BLKMEM* blkmem, /**< block memory */ 5397 SCIP_SET* set, /**< global SCIP settings */ 5398 int num /**< minimum number of entries to store */ 5399 ) 5400 { 5401 assert(conssetchg != NULL); 5402 5403 if( num > conssetchg->addedconsssize ) 5404 { 5405 int newsize; 5406 5407 newsize = SCIPsetCalcMemGrowSize(set, num); 5408 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conssetchg->addedconss, conssetchg->addedconsssize, newsize) ); 5409 conssetchg->addedconsssize = newsize; 5410 } 5411 assert(num <= conssetchg->addedconsssize); 5412 5413 return SCIP_OKAY; 5414 } 5415 5416 /** ensures, that disabledconss array can store at least num entries */ 5417 static 5418 SCIP_RETCODE conssetchgEnsureDisabledconssSize( 5419 SCIP_CONSSETCHG* conssetchg, /**< constraint set change data structure */ 5420 BMS_BLKMEM* blkmem, /**< block memory */ 5421 SCIP_SET* set, /**< global SCIP settings */ 5422 int num /**< minimum number of entries to store */ 5423 ) 5424 { 5425 assert(conssetchg != NULL); 5426 5427 if( num > conssetchg->disabledconsssize ) 5428 { 5429 int newsize; 5430 5431 newsize = SCIPsetCalcMemGrowSize(set, num); 5432 SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &conssetchg->disabledconss, conssetchg->disabledconsssize, newsize) ); 5433 conssetchg->disabledconsssize = newsize; 5434 } 5435 assert(num <= conssetchg->disabledconsssize); 5436 5437 return SCIP_OKAY; 5438 } 5439 5440 /** adds constraint addition to constraint set changes, and captures constraint; activates constraint if the 5441 * constraint set change data is currently active 5442 */ 5443 SCIP_RETCODE SCIPconssetchgAddAddedCons( 5444 SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data structure */ 5445 BMS_BLKMEM* blkmem, /**< block memory */ 5446 SCIP_SET* set, /**< global SCIP settings */ 5447 SCIP_STAT* stat, /**< dynamic problem statistics */ 5448 SCIP_CONS* cons, /**< added constraint */ 5449 int depth, /**< depth of constraint set change's node */ 5450 SCIP_Bool focusnode, /**< does the constraint set change belong to the focus node? */ 5451 SCIP_Bool active /**< is the constraint set change currently active? */ 5452 ) 5453 { 5454 assert(conssetchg != NULL); 5455 assert(cons != NULL); 5456 5457 /* if constraint set change doesn't exist, create it */ 5458 if( *conssetchg == NULL ) 5459 { 5460 SCIP_CALL( conssetchgCreate(conssetchg, blkmem) ); 5461 } 5462 5463 /* add constraint to the addedconss array */ 5464 SCIP_CALL( conssetchgEnsureAddedconssSize(*conssetchg, blkmem, set, (*conssetchg)->naddedconss+1) ); 5465 (*conssetchg)->addedconss[(*conssetchg)->naddedconss] = cons; 5466 (*conssetchg)->naddedconss++; 5467 5468 /* undelete constraint, if it was globally deleted in the past */ 5469 cons->deleted = FALSE; 5470 5471 /* capture constraint */ 5472 SCIPconsCapture(cons); 5473 5474 /* activate constraint, if node is active */ 5475 if( active && !SCIPconsIsActive(cons) ) 5476 { 5477 SCIP_CALL( SCIPconsActivate(cons, set, stat, depth, focusnode) ); 5478 assert(SCIPconsIsActive(cons)); 5479 5480 /* remember, that this constraint set change data was responsible for the constraint's addition */ 5481 cons->addconssetchg = *conssetchg; 5482 cons->addarraypos = (*conssetchg)->naddedconss-1; 5483 } 5484 5485 return SCIP_OKAY; 5486 } 5487 5488 /** adds constraint disabling to constraint set changes, and captures constraint */ 5489 SCIP_RETCODE SCIPconssetchgAddDisabledCons( 5490 SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data structure */ 5491 BMS_BLKMEM* blkmem, /**< block memory */ 5492 SCIP_SET* set, /**< global SCIP settings */ 5493 SCIP_CONS* cons /**< disabled constraint */ 5494 ) 5495 { 5496 assert(conssetchg != NULL); 5497 assert(cons != NULL); 5498 5499 /* if constraint set change doesn't exist, create it */ 5500 if( *conssetchg == NULL ) 5501 { 5502 SCIP_CALL( conssetchgCreate(conssetchg, blkmem) ); 5503 } 5504 5505 /* add constraint to the disabledconss array */ 5506 SCIP_CALL( conssetchgEnsureDisabledconssSize(*conssetchg, blkmem, set, (*conssetchg)->ndisabledconss+1) ); 5507 (*conssetchg)->disabledconss[(*conssetchg)->ndisabledconss] = cons; 5508 (*conssetchg)->ndisabledconss++; 5509 5510 /* capture constraint */ 5511 SCIPconsCapture(cons); 5512 5513 return SCIP_OKAY; 5514 } 5515 5516 /** deactivates, deletes, and releases constraint from the addedconss array of the constraint set change data */ 5517 static 5518 SCIP_RETCODE conssetchgDelAddedCons( 5519 SCIP_CONSSETCHG* conssetchg, /**< constraint set change to delete constraint from */ 5520 BMS_BLKMEM* blkmem, /**< block memory */ 5521 SCIP_SET* set, /**< global SCIP settings */ 5522 int arraypos /**< position of constraint in disabledconss array */ 5523 ) 5524 { 5525 SCIP_CONS* cons; 5526 5527 assert(conssetchg != NULL); 5528 assert(conssetchg->addedconss != NULL); 5529 assert(0 <= arraypos && arraypos < conssetchg->naddedconss); 5530 5531 cons = conssetchg->addedconss[arraypos]; 5532 assert(cons != NULL); 5533 5534 SCIPsetDebugMsg(set, "delete added constraint <%s> at position %d from constraint set change data\n", cons->name, arraypos); 5535 5536 /* remove the link to the constraint set change data */ 5537 if( cons->addconssetchg == conssetchg ) 5538 { 5539 cons->addconssetchg = NULL; 5540 cons->addarraypos = -1; 5541 } 5542 5543 /* release constraint */ 5544 SCIP_CALL( SCIPconsRelease(&conssetchg->addedconss[arraypos], blkmem, set) ); 5545 5546 /* we want to keep the order of the constraint additions: move all subsequent constraints one slot to the front */ 5547 for( ; arraypos < conssetchg->naddedconss-1; ++arraypos ) 5548 { 5549 conssetchg->addedconss[arraypos] = conssetchg->addedconss[arraypos+1]; 5550 assert(conssetchg->addedconss[arraypos] != NULL); 5551 if( conssetchg->addedconss[arraypos]->addconssetchg == conssetchg ) 5552 { 5553 assert(conssetchg->addedconss[arraypos]->addarraypos == arraypos+1); 5554 conssetchg->addedconss[arraypos]->addarraypos = arraypos; 5555 } 5556 } 5557 conssetchg->naddedconss--; 5558 5559 return SCIP_OKAY; 5560 } 5561 5562 /** deletes and releases deactivated constraint from the disabledconss array of the constraint set change data */ 5563 static 5564 SCIP_RETCODE conssetchgDelDisabledCons( 5565 SCIP_CONSSETCHG* conssetchg, /**< constraint set change to apply */ 5566 BMS_BLKMEM* blkmem, /**< block memory */ 5567 SCIP_SET* set, /**< global SCIP settings */ 5568 int arraypos /**< position of constraint in disabledconss array */ 5569 ) 5570 { 5571 assert(conssetchg != NULL); 5572 assert(0 <= arraypos && arraypos < conssetchg->ndisabledconss); 5573 assert(conssetchg->disabledconss[arraypos] != NULL); 5574 5575 SCIPsetDebugMsg(set, "delete disabled constraint <%s> at position %d from constraint set change data\n", 5576 conssetchg->disabledconss[arraypos]->name, arraypos); 5577 5578 /* release constraint */ 5579 SCIP_CALL( SCIPconsRelease(&conssetchg->disabledconss[arraypos], blkmem, set) ); 5580 5581 /* we want to keep the order of the constraint disablings: move all subsequent constraints one slot to the front */ 5582 for( ; arraypos < conssetchg->ndisabledconss-1; ++arraypos ) 5583 { 5584 conssetchg->disabledconss[arraypos] = conssetchg->disabledconss[arraypos+1]; 5585 assert(conssetchg->disabledconss[arraypos] != NULL); 5586 } 5587 conssetchg->ndisabledconss--; 5588 5589 return SCIP_OKAY; 5590 } 5591 5592 /** gets added constraints data for a constraint set change */ 5593 void SCIPconssetchgGetAddedConsData( 5594 SCIP_CONSSETCHG* conssetchg, /**< constraint set change to get data from */ 5595 SCIP_CONS*** conss, /**< reference to constraints array added in the conssetchg, or NULL */ 5596 int* nconss /**< reference to store the size of the constraints array, or NULL */ 5597 ) 5598 { 5599 assert(conssetchg != NULL); 5600 if( conss != NULL ) 5601 *conss = conssetchg->addedconss; 5602 if( nconss != NULL ) 5603 *nconss = conssetchg->naddedconss; 5604 } 5605 5606 /** applies constraint set change */ 5607 SCIP_RETCODE SCIPconssetchgApply( 5608 SCIP_CONSSETCHG* conssetchg, /**< constraint set change to apply */ 5609 BMS_BLKMEM* blkmem, /**< block memory */ 5610 SCIP_SET* set, /**< global SCIP settings */ 5611 SCIP_STAT* stat, /**< dynamic problem statistics */ 5612 int depth, /**< depth of constraint set change's node */ 5613 SCIP_Bool focusnode /**< does the constraint set change belong to the focus node? */ 5614 ) 5615 { 5616 SCIP_CONS* cons; 5617 int i; 5618 5619 if( conssetchg == NULL ) 5620 return SCIP_OKAY; 5621 5622 SCIPsetDebugMsg(set, "applying constraint set changes at %p: %d constraint additions, %d constraint disablings\n", 5623 (void*)conssetchg, conssetchg->naddedconss, conssetchg->ndisabledconss); 5624 5625 /* apply constraint additions */ 5626 i = 0; 5627 while( i < conssetchg->naddedconss ) 5628 { 5629 cons = conssetchg->addedconss[i]; 5630 assert(cons != NULL); 5631 assert(!cons->update); 5632 5633 /* if constraint is already active, or if constraint is globally deleted, it can be removed from addedconss array */ 5634 if( cons->active || cons->deleted ) 5635 { 5636 /* delete constraint from addedcons array, the empty slot is now used by the next constraint, 5637 * and naddedconss was decreased, so do not increase i 5638 */ 5639 SCIP_CALL( conssetchgDelAddedCons(conssetchg, blkmem, set, i) ); 5640 } 5641 else 5642 { 5643 assert(cons->addconssetchg == NULL); 5644 assert(cons->addarraypos == -1); 5645 5646 /* activate constraint */ 5647 SCIP_CALL( SCIPconsActivate(cons, set, stat, depth, focusnode) ); 5648 assert(cons->active); 5649 assert(!cons->update); 5650 5651 /* remember, that this constraint set change data was responsible for the constraint's addition */ 5652 cons->addconssetchg = conssetchg; 5653 cons->addarraypos = i; 5654 5655 ++i; /* handle the next constraint */ 5656 } 5657 } 5658 5659 /* apply constraint disablings */ 5660 i = 0; 5661 while( i < conssetchg->ndisabledconss ) 5662 { 5663 cons = conssetchg->disabledconss[i]; 5664 assert(cons != NULL); 5665 assert(!cons->update); 5666 5667 /* if the constraint is disabled, we can permanently remove it from the disabledconss array */ 5668 if( !cons->enabled ) 5669 { 5670 SCIPsetDebugMsg(set, "constraint <%s> of handler <%s> was deactivated -> remove it from disabledconss array\n", 5671 cons->name, cons->conshdlr->name); 5672 5673 /* release and remove constraint from the disabledconss array, the empty slot is now used by the next constraint 5674 * and ndisabledconss was decreased, so do not increase i 5675 */ 5676 SCIP_CALL( conssetchgDelDisabledCons(conssetchg, blkmem, set, i) ); 5677 } 5678 else 5679 { 5680 assert(cons->addarraypos >= 0); 5681 assert(!cons->deleted); /* deleted constraints must not be enabled! */ 5682 SCIP_CALL( SCIPconsDisable(conssetchg->disabledconss[i], set, stat) ); 5683 assert(!cons->update); 5684 assert(!cons->enabled); 5685 5686 ++i; /* handle the next constraint */ 5687 } 5688 } 5689 5690 return SCIP_OKAY; 5691 } 5692 5693 /** undoes constraint set change */ 5694 SCIP_RETCODE SCIPconssetchgUndo( 5695 SCIP_CONSSETCHG* conssetchg, /**< constraint set change to undo */ 5696 BMS_BLKMEM* blkmem, /**< block memory */ 5697 SCIP_SET* set, /**< global SCIP settings */ 5698 SCIP_STAT* stat /**< dynamic problem statistics */ 5699 ) 5700 { 5701 SCIP_CONS* cons; 5702 int i; 5703 5704 if( conssetchg == NULL ) 5705 return SCIP_OKAY; 5706 5707 SCIPsetDebugMsg(set, "undoing constraint set changes at %p: %d constraint additions, %d constraint disablings\n", 5708 (void*)conssetchg, conssetchg->naddedconss, conssetchg->ndisabledconss); 5709 5710 /* undo constraint disablings */ 5711 for( i = conssetchg->ndisabledconss-1; i >= 0; --i ) 5712 { 5713 cons = conssetchg->disabledconss[i]; 5714 assert(cons != NULL); 5715 assert(!cons->update); 5716 5717 /* If the constraint is inactive, we can permanently remove it from the disabledconss array. It was deactivated 5718 * in the subtree of the current node but not reactivated on the switching way back to the current node, which 5719 * means, the deactivation was more global (i.e. valid on a higher level node) than the current node and the 5720 * disabling at the current node doesn't have any effect anymore. 5721 * If the constraint is already enabled, we need not to do anything. This may happen on a path A -> B, 5722 * if the constraint is disabled at node B, and while processing the subtree of B, it is also disabled at 5723 * the more global node A. Then on the switching path back to A, the constraint is enabled at node B (which is 5724 * actually wrong, since it now should be disabled in the whole subtree of A, but we cannot know this), and 5725 * again enabled at node A (where enabling is ignored). If afterwards, a subnode of B is processed, the 5726 * switching disables the constraint in node A, and the disabling is then removed from node B. 5727 */ 5728 if( !cons->active ) 5729 { 5730 SCIPsetDebugMsg(set, "constraint <%s> of handler <%s> was deactivated -> remove it from disabledconss array\n", 5731 cons->name, cons->conshdlr->name); 5732 5733 /* release and remove constraint from the disabledconss array */ 5734 SCIP_CALL( conssetchgDelDisabledCons(conssetchg, blkmem, set, i) ); 5735 } 5736 else if( !cons->enabled ) 5737 { 5738 assert(cons->addarraypos >= 0); 5739 assert(!cons->deleted); /* deleted constraints must not be active! */ 5740 SCIP_CALL( SCIPconsEnable(cons, set, stat) ); 5741 assert(!cons->update); 5742 assert(!cons->active || cons->enabled); 5743 } 5744 } 5745 5746 /* undo constraint additions */ 5747 for( i = conssetchg->naddedconss-1; i >= 0; --i ) 5748 { 5749 cons = conssetchg->addedconss[i]; 5750 assert(cons != NULL); 5751 assert(!cons->update); 5752 5753 /* If the constraint is already deactivated, we need not to do anything. This may happen on a path A -> B, 5754 * if the constraint is added at node B, and while processing the subtree of B, it is also added at 5755 * the more global node A. Then on the switching path back to A, the node is deactivated at node B (which is 5756 * actually wrong, since it now should be active in the whole subtree of A, but we cannot know this), and 5757 * again deactivated at node A (where deactivation is ignored). If afterwards, a subnode of B is processed, the 5758 * switching activates the constraint in node A, and the activation is then removed from node B. 5759 */ 5760 if( cons->active ) 5761 { 5762 assert(cons->addconssetchg == conssetchg); 5763 assert(cons->addarraypos == i); 5764 5765 /* deactivate constraint */ 5766 SCIP_CALL( SCIPconsDeactivate(cons, set, stat) ); 5767 5768 /* unlink the constraint and the constraint set change */ 5769 cons->addconssetchg = NULL; 5770 cons->addarraypos = -1; 5771 } 5772 assert(!cons->active); 5773 assert(!cons->update); 5774 } 5775 5776 return SCIP_OKAY; 5777 } 5778 5779 /** applies constraint set change to the global problem and deletes the constraint set change data */ 5780 SCIP_RETCODE SCIPconssetchgMakeGlobal( 5781 SCIP_CONSSETCHG** conssetchg, /**< pointer to constraint set change data */ 5782 BMS_BLKMEM* blkmem, /**< block memory */ 5783 SCIP_SET* set, /**< global SCIP settings */ 5784 SCIP_STAT* stat, /**< dynamic problem statistics */ 5785 SCIP_PROB* prob, /**< problem data */ 5786 SCIP_REOPT* reopt /**< reoptimization data */ 5787 ) 5788 { 5789 SCIP_CONS* cons; 5790 int i; 5791 5792 assert(conssetchg != NULL); 5793 5794 /* nothing to do on empty constraint set change data */ 5795 if( *conssetchg == NULL ) 5796 return SCIP_OKAY; 5797 5798 SCIPsetDebugMsg(set, "moving constraint set changes at %p to global problem: %d constraint additions, %d constraint disablings\n", 5799 (void*)*conssetchg, (*conssetchg)->naddedconss, (*conssetchg)->ndisabledconss); 5800 5801 /* apply constraint additions to the global problem (loop backwards, because then conssetchgDelAddedCons() is 5802 * more efficient) 5803 */ 5804 for( i = (*conssetchg)->naddedconss-1; i >= 0; --i ) 5805 { 5806 cons = (*conssetchg)->addedconss[i]; 5807 assert(cons != NULL); 5808 assert(!cons->update); 5809 5810 /* only move constraints that are not sticking at the current node */ 5811 if( !SCIPconsIsStickingAtNode(cons) ) 5812 { 5813 /* because we first have to delete the constraint, we have to capture it in order to not loose it */ 5814 SCIPconsCapture(cons); 5815 5816 /* delete constraint addition from constraint set change data */ 5817 SCIP_CALL( conssetchgDelAddedCons(*conssetchg, blkmem, set, i) ); 5818 5819 /* don't move deleted constraints to the global problem */ 5820 if( !cons->deleted ) 5821 { 5822 SCIP_CALL( SCIPprobAddCons(prob, set, stat, cons) ); 5823 } 5824 5825 /* release constraint */ 5826 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) ); 5827 } 5828 } 5829 5830 /* apply constraint disablings to the global problem (loop backwards, because then conssetchgDelDisabledCons() is 5831 * more efficient) 5832 */ 5833 for( i = (*conssetchg)->ndisabledconss-1; i >= 0; --i ) 5834 { 5835 cons = (*conssetchg)->disabledconss[i]; 5836 assert(cons != NULL); 5837 assert(!cons->update); 5838 5839 /* only delete constraints that are not sticking at the current node */ 5840 if( !SCIPconsIsStickingAtNode(cons) ) 5841 { 5842 /* globally delete constraint */ 5843 if( !cons->deleted ) 5844 { 5845 SCIP_CALL( SCIPconsDelete(cons, blkmem, set, stat, prob, reopt) ); 5846 } 5847 5848 /* release and remove constraint from the disabledconss array */ 5849 SCIP_CALL( conssetchgDelDisabledCons(*conssetchg, blkmem, set, i) ); 5850 } 5851 } 5852 5853 if( (*conssetchg)->naddedconss == 0 && (*conssetchg)->ndisabledconss == 0 ) 5854 { 5855 /* free empty constraint set change data */ 5856 SCIP_CALL( SCIPconssetchgFree(conssetchg, blkmem, set) ); 5857 } 5858 5859 return SCIP_OKAY; 5860 } 5861 5862 5863 5864 5865 /* 5866 * Constraint methods 5867 */ 5868 5869 /** creates and captures a constraint, and inserts it into the conss array of its constraint handler 5870 * 5871 * @warning If a constraint is marked to be checked for feasibility but not to be enforced, a LP or pseudo solution 5872 * may be declared feasible even if it violates this particular constraint. 5873 * This constellation should only be used, if no LP or pseudo solution can violate the constraint -- e.g. if a 5874 * local constraint is redundant due to the variable's local bounds. 5875 */ 5876 SCIP_RETCODE SCIPconsCreate( 5877 SCIP_CONS** cons, /**< pointer to constraint */ 5878 BMS_BLKMEM* blkmem, /**< block memory */ 5879 SCIP_SET* set, /**< global SCIP settings */ 5880 const char* name, /**< name of constraint */ 5881 SCIP_CONSHDLR* conshdlr, /**< constraint handler for this constraint */ 5882 SCIP_CONSDATA* consdata, /**< data for this specific constraint */ 5883 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? 5884 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */ 5885 SCIP_Bool separate, /**< should the constraint be separated during LP processing? 5886 * Usually set to TRUE. */ 5887 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? 5888 * TRUE for model constraints, FALSE for additional, redundant constraints. */ 5889 SCIP_Bool check, /**< should the constraint be checked for feasibility? 5890 * TRUE for model constraints, FALSE for additional, redundant constraints. */ 5891 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? 5892 * Usually set to TRUE. */ 5893 SCIP_Bool local, /**< is constraint only valid locally? 5894 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */ 5895 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? 5896 * Usually set to FALSE. In column generation applications, set to TRUE if pricing 5897 * adds coefficients to this constraint. */ 5898 SCIP_Bool dynamic, /**< is constraint subject to aging? 5899 * Usually set to FALSE. Set to TRUE for own cuts which 5900 * are separated as constraints. */ 5901 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? 5902 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */ 5903 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even 5904 * if it may be moved to a more global node? 5905 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */ 5906 SCIP_Bool original, /**< is constraint belonging to the original problem? */ 5907 SCIP_Bool deleteconsdata /**< has the constraint data to be deleted if constraint is freed? */ 5908 ) 5909 { 5910 int i; 5911 5912 assert(cons != NULL); 5913 assert(blkmem != NULL); 5914 assert(set != NULL); 5915 assert(name != NULL); 5916 assert(conshdlr != NULL); 5917 assert(!original || deleteconsdata); 5918 5919 /* create constraint data */ 5920 SCIP_ALLOC( BMSallocBlockMemory(blkmem, cons) ); 5921 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &(*cons)->name, name, strlen(name)+1) ); 5922 #ifndef NDEBUG 5923 (*cons)->scip = set->scip; 5924 #endif 5925 (*cons)->conshdlr = conshdlr; 5926 (*cons)->consdata = consdata; 5927 (*cons)->transorigcons = NULL; 5928 (*cons)->addconssetchg = NULL; 5929 (*cons)->addarraypos = -1; 5930 (*cons)->consspos = -1; 5931 (*cons)->initconsspos = -1; 5932 (*cons)->sepaconsspos = -1; 5933 (*cons)->enfoconsspos = -1; 5934 (*cons)->checkconsspos = -1; 5935 (*cons)->propconsspos = -1; 5936 (*cons)->activedepth = -2; 5937 (*cons)->validdepth = (local ? -1 : 0); 5938 (*cons)->age = 0.0; 5939 (*cons)->nuses = 0; 5940 (*cons)->nupgradelocks = 0; 5941 (*cons)->initial = initial; 5942 (*cons)->separate = separate; 5943 (*cons)->enforce = enforce; 5944 (*cons)->check = check; 5945 (*cons)->propagate = propagate; 5946 (*cons)->sepaenabled = separate; 5947 (*cons)->propenabled = propagate; 5948 (*cons)->local = local; 5949 (*cons)->modifiable = modifiable; 5950 (*cons)->dynamic = dynamic; 5951 (*cons)->removable = removable; 5952 (*cons)->stickingatnode = stickingatnode; 5953 (*cons)->original = original; 5954 (*cons)->deleteconsdata = deleteconsdata; 5955 (*cons)->active = FALSE; 5956 (*cons)->conflict = FALSE; 5957 (*cons)->enabled = FALSE; 5958 (*cons)->obsolete = FALSE; 5959 (*cons)->markpropagate = TRUE; 5960 (*cons)->deleted = FALSE; 5961 (*cons)->update = FALSE; 5962 (*cons)->updateinsert = FALSE; 5963 (*cons)->updateactivate = FALSE; 5964 (*cons)->updatedeactivate = FALSE; 5965 (*cons)->updateenable = FALSE; 5966 (*cons)->updatedisable = FALSE; 5967 (*cons)->updatesepaenable = FALSE; 5968 (*cons)->updatesepadisable = FALSE; 5969 (*cons)->updatepropenable = FALSE; 5970 (*cons)->updatepropdisable = FALSE; 5971 (*cons)->updateobsolete = FALSE; 5972 (*cons)->updatemarkpropagate = FALSE; 5973 (*cons)->updateunmarkpropagate = FALSE; 5974 (*cons)->updatefree = FALSE; 5975 (*cons)->updateactfocus = FALSE; 5976 5977 for( i = 0; i < NLOCKTYPES; i++ ) 5978 { 5979 (*cons)->nlockspos[i] = 0; 5980 (*cons)->nlocksneg[i] = 0; 5981 } 5982 5983 /* capture constraint */ 5984 SCIPconsCapture(*cons); 5985 5986 /* insert the constraint as inactive constraint into the transformed constraints array */ 5987 if( !original ) 5988 { 5989 /* check, if inserting constraint should be delayed */ 5990 if( conshdlrAreUpdatesDelayed(conshdlr) ) 5991 { 5992 SCIPsetDebugMsg(set, " -> delaying insertion of constraint <%s>\n", (*cons)->name); 5993 (*cons)->updateinsert = TRUE; 5994 SCIP_CALL( conshdlrAddUpdateCons((*cons)->conshdlr, set, *cons) ); 5995 assert((*cons)->update); 5996 assert((*cons)->nuses == 2); 5997 } 5998 else 5999 { 6000 SCIP_CALL( conshdlrAddCons(conshdlr, set, *cons) ); 6001 } 6002 } 6003 6004 checkConssArrays(conshdlr); 6005 6006 return SCIP_OKAY; 6007 } 6008 6009 /** copies source constraint of source SCIP into the target constraint for the target SCIP, using the variable map for 6010 * mapping the variables of the source SCIP to the variables of the target SCIP; if the copying process was successful 6011 * a constraint is created and captured; 6012 * 6013 * @warning If a constraint is marked to be checked for feasibility but not to be enforced, an LP or pseudo solution 6014 * may be declared feasible even if it violates this particular constraint. 6015 * This constellation should only be used, if no LP or pseudo solution can violate the constraint -- e.g. if a 6016 * local constraint is redundant due to the variable's local bounds. 6017 */ 6018 SCIP_RETCODE SCIPconsCopy( 6019 SCIP_CONS** cons, /**< pointer to store the created target constraint */ 6020 SCIP_SET* set, /**< global SCIP settings of the target SCIP */ 6021 const char* name, /**< name of constraint, or NULL if the name of the source constraint should be used */ 6022 SCIP* sourcescip, /**< source SCIP data structure */ 6023 SCIP_CONSHDLR* sourceconshdlr, /**< source constraint handler for this constraint */ 6024 SCIP_CONS* sourcecons, /**< source constraint of the source SCIP */ 6025 SCIP_HASHMAP* varmap, /**< a SCIP_HASHMAP mapping variables of the source SCIP to corresponding 6026 * variables of the target SCIP */ 6027 SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding 6028 * target constraints, must not be NULL! */ 6029 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? */ 6030 SCIP_Bool separate, /**< should the constraint be separated during LP processing? */ 6031 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? */ 6032 SCIP_Bool check, /**< should the constraint be checked for feasibility? */ 6033 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? */ 6034 SCIP_Bool local, /**< is constraint only valid locally? */ 6035 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? */ 6036 SCIP_Bool dynamic, /**< is constraint subject to aging? */ 6037 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? */ 6038 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even 6039 * if it may be moved to a more global node? */ 6040 SCIP_Bool global, /**< create a global or a local copy? */ 6041 SCIP_Bool* valid /**< pointer to store whether the copying was valid or not */ 6042 ) 6043 { 6044 assert(cons != NULL); 6045 assert(set != NULL); 6046 assert(sourcescip != NULL); 6047 assert(sourceconshdlr != NULL); 6048 assert(sourcecons != NULL); 6049 assert(varmap != NULL); 6050 assert(consmap != NULL); 6051 assert(valid != NULL); 6052 6053 /* if constraint handler does not support copying, success will return false. Constraints handlers have to actively set this to true. */ 6054 (*valid) = FALSE; 6055 6056 if( sourceconshdlr->conscopy != NULL ) 6057 { 6058 SCIP_CALL( sourceconshdlr->conscopy(set->scip, cons, name, sourcescip, sourceconshdlr, sourcecons, varmap, consmap, 6059 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, global, valid) ); 6060 } 6061 6062 return SCIP_OKAY; 6063 } 6064 6065 6066 /** parses constraint information (in cip format) out of a string; if the parsing process was successful a constraint is 6067 * created, captured, and inserted into the conss array of its constraint handler. 6068 * 6069 * @warning If a constraint is marked to be checked for feasibility but not to be enforced, an LP or pseudo solution 6070 * may be declared feasible even if it violates this particular constraint. 6071 * This constellation should only be used, if no LP or pseudo solution can violate the constraint -- e.g. if a 6072 * local constraint is redundant due to the variable's local bounds. 6073 */ 6074 SCIP_RETCODE SCIPconsParse( 6075 SCIP_CONS** cons, /**< pointer to constraint */ 6076 SCIP_SET* set, /**< global SCIP settings */ 6077 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler of target SCIP */ 6078 const char* str, /**< string to parse for constraint */ 6079 SCIP_Bool initial, /**< should the LP relaxation of constraint be in the initial LP? 6080 * Usually set to TRUE. Set to FALSE for 'lazy constraints'. */ 6081 SCIP_Bool separate, /**< should the constraint be separated during LP processing? 6082 * Usually set to TRUE. */ 6083 SCIP_Bool enforce, /**< should the constraint be enforced during node processing? 6084 * TRUE for model constraints, FALSE for additional, redundant constraints. */ 6085 SCIP_Bool check, /**< should the constraint be checked for feasibility? 6086 * TRUE for model constraints, FALSE for additional, redundant constraints. */ 6087 SCIP_Bool propagate, /**< should the constraint be propagated during node processing? 6088 * Usually set to TRUE. */ 6089 SCIP_Bool local, /**< is constraint only valid locally? 6090 * Usually set to FALSE. Has to be set to TRUE, e.g., for branching constraints. */ 6091 SCIP_Bool modifiable, /**< is constraint modifiable (subject to column generation)? 6092 * Usually set to FALSE. In column generation applications, set to TRUE if pricing 6093 * adds coefficients to this constraint. */ 6094 SCIP_Bool dynamic, /**< is constraint subject to aging? 6095 * Usually set to FALSE. Set to TRUE for own cuts which 6096 * are separated as constraints. */ 6097 SCIP_Bool removable, /**< should the relaxation be removed from the LP due to aging or cleanup? 6098 * Usually set to FALSE. Set to TRUE for 'lazy constraints' and 'user cuts'. */ 6099 SCIP_Bool stickingatnode, /**< should the constraint always be kept at the node where it was added, even 6100 * if it may be moved to a more global node? 6101 * Usually set to FALSE. Set to TRUE to for constraints that represent node data. */ 6102 SCIP_Bool* success /**< pointer store if the paring process was successful */ 6103 ) 6104 { 6105 SCIP_CONSHDLR* conshdlr; 6106 char conshdlrname[SCIP_MAXSTRLEN]; 6107 char consname[SCIP_MAXSTRLEN]; 6108 char* endptr; 6109 6110 assert(cons != NULL); 6111 assert(set != NULL); 6112 6113 (*success) = FALSE; 6114 6115 /* scan constraint handler name */ 6116 assert(str != NULL); 6117 SCIPstrCopySection(str, '[', ']', conshdlrname, SCIP_MAXSTRLEN, &endptr); 6118 if ( endptr == NULL || endptr == str ) 6119 { 6120 SCIPmessagePrintWarning(messagehdlr, "Syntax error: Could not find constraint handler name.\n"); 6121 return SCIP_OKAY; 6122 } 6123 assert(endptr != NULL); 6124 SCIPsetDebugMsg(set, "constraint handler name <%s>\n", conshdlrname); 6125 6126 /* scan constraint name */ 6127 SCIPstrCopySection(endptr, '<', '>', consname, SCIP_MAXSTRLEN, &endptr); 6128 if ( endptr == NULL || endptr == str ) 6129 { 6130 SCIPmessagePrintWarning(messagehdlr, "Syntax error: Could not find constraint name.\n"); 6131 return SCIP_OKAY; 6132 } 6133 assert(endptr != NULL); 6134 SCIPsetDebugMsg(set, "constraint name <%s>\n", consname); 6135 6136 str = endptr; 6137 6138 /* skip white space */ 6139 SCIP_CALL( SCIPskipSpace((char**)&str) ); 6140 6141 /* check for colon */ 6142 if( *str != ':' ) 6143 { 6144 SCIPmessagePrintWarning(messagehdlr, "Syntax error: Could not find colon ':' after constraint name.\n"); 6145 return SCIP_OKAY; 6146 } 6147 6148 /* skip colon */ 6149 ++str; 6150 6151 /* skip white space */ 6152 SCIP_CALL( SCIPskipSpace((char**)&str) ); 6153 6154 /* check if a constraint handler with parsed name exists */ 6155 conshdlr = SCIPsetFindConshdlr(set, conshdlrname); 6156 6157 if( conshdlr == NULL ) 6158 { 6159 SCIPmessagePrintWarning(messagehdlr, "constraint handler <%s> doesn't exist in SCIP data structure\n", conshdlrname); 6160 } 6161 else 6162 { 6163 assert( conshdlr != NULL ); 6164 if ( conshdlr->consparse == NULL ) 6165 { 6166 SCIPmessagePrintWarning(messagehdlr, "constraint handler <%s> does not support parsing constraints\n", conshdlrname); 6167 } 6168 else 6169 { 6170 SCIP_CALL( conshdlr->consparse(set->scip, conshdlr, cons, consname, str, 6171 initial, separate, enforce, check, propagate, local, modifiable, dynamic, removable, stickingatnode, success) ); 6172 } 6173 } 6174 6175 return SCIP_OKAY; 6176 } 6177 6178 /** change name of given constraint */ 6179 SCIP_RETCODE SCIPconsChgName( 6180 SCIP_CONS* cons, /**< problem constraint */ 6181 BMS_BLKMEM* blkmem, /**< block memory buffer */ 6182 const char* name /**< new name of constraint */ 6183 ) 6184 { 6185 assert(cons != NULL); 6186 assert(cons->name != NULL); 6187 6188 /* free old constraint name */ 6189 BMSfreeBlockMemoryArray(blkmem, &cons->name, strlen(cons->name)+1); 6190 6191 /* copy new constraint name */ 6192 SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &cons->name, name, strlen(name)+1) ); 6193 6194 return SCIP_OKAY; 6195 } 6196 6197 6198 /** frees a constraint and removes it from the conss array of its constraint handler */ 6199 SCIP_RETCODE SCIPconsFree( 6200 SCIP_CONS** cons, /**< constraint to free */ 6201 BMS_BLKMEM* blkmem, /**< block memory buffer */ 6202 SCIP_SET* set /**< global SCIP settings */ 6203 ) 6204 { 6205 assert(cons != NULL); 6206 assert(*cons != NULL); 6207 assert((*cons)->conshdlr != NULL); 6208 assert((*cons)->nuses == 0); 6209 assert(!(*cons)->active); 6210 assert(!(*cons)->update); 6211 assert(!(*cons)->original || (*cons)->transorigcons == NULL); 6212 assert(blkmem != NULL); 6213 assert(set != NULL); 6214 assert((*cons)->scip == set->scip); 6215 6216 SCIPsetDebugMsg(set, "freeing constraint <%s> at conss pos %d of handler <%s>\n", 6217 (*cons)->name, (*cons)->consspos, (*cons)->conshdlr->name); 6218 6219 /* free constraint data */ 6220 if( (*cons)->conshdlr->consdelete != NULL && (*cons)->consdata != NULL && (*cons)->deleteconsdata ) 6221 { 6222 SCIP_CALL( (*cons)->conshdlr->consdelete(set->scip, (*cons)->conshdlr, *cons, &(*cons)->consdata) ); 6223 } 6224 else if( !(*cons)->deleteconsdata ) 6225 (*cons)->consdata = NULL; 6226 assert((*cons)->consdata == NULL); 6227 6228 /* unlink transformed and original constraint */ 6229 if( (*cons)->transorigcons != NULL ) 6230 { 6231 assert(!(*cons)->original); 6232 assert((*cons)->transorigcons->original); 6233 assert((*cons)->transorigcons->transorigcons == *cons); 6234 6235 (*cons)->transorigcons->transorigcons = NULL; 6236 } 6237 6238 /* remove constraint from the transformed constraints array */ 6239 if( !(*cons)->original ) 6240 { 6241 conshdlrDelCons((*cons)->conshdlr, *cons); 6242 checkConssArrays((*cons)->conshdlr); 6243 } 6244 assert((*cons)->consspos == -1); 6245 6246 /* free constraint */ 6247 BMSfreeBlockMemoryArray(blkmem, &(*cons)->name, strlen((*cons)->name)+1); 6248 BMSfreeBlockMemory(blkmem, cons); 6249 6250 return SCIP_OKAY; 6251 } 6252 6253 /** increases usage counter of constraint */ 6254 void SCIPconsCapture( 6255 SCIP_CONS* cons /**< constraint */ 6256 ) 6257 { 6258 assert(cons != NULL); 6259 assert(cons->nuses >= 0); 6260 6261 SCIPdebugMessage("capture constraint <%s> with nuses=%d, cons pointer %p\n", cons->name, cons->nuses, (void*)cons); 6262 cons->nuses++; 6263 } 6264 6265 /** decreases usage counter of constraint, and frees memory if necessary */ 6266 SCIP_RETCODE SCIPconsRelease( 6267 SCIP_CONS** cons, /**< pointer to constraint */ 6268 BMS_BLKMEM* blkmem, /**< block memory */ 6269 SCIP_SET* set /**< global SCIP settings */ 6270 ) 6271 { 6272 assert(blkmem != NULL); 6273 assert(cons != NULL); 6274 assert(*cons != NULL); 6275 assert((*cons)->conshdlr != NULL); 6276 assert((*cons)->nuses >= 1); 6277 assert(set != NULL); 6278 assert((*cons)->scip == set->scip); 6279 6280 SCIPsetDebugMsg(set, "release constraint <%s> with nuses=%d, cons pointer %p\n", (*cons)->name, (*cons)->nuses, (void*)(*cons)); 6281 (*cons)->nuses--; 6282 if( (*cons)->nuses == 0 ) 6283 { 6284 assert(!(*cons)->active || (*cons)->updatedeactivate); 6285 6286 /* check, if freeing constraint should be delayed */ 6287 if( conshdlrAreUpdatesDelayed((*cons)->conshdlr) ) 6288 { 6289 SCIPsetDebugMsg(set, " -> delaying freeing constraint <%s>\n", (*cons)->name); 6290 (*cons)->updatefree = TRUE; 6291 SCIP_CALL( conshdlrAddUpdateCons((*cons)->conshdlr, set, *cons) ); 6292 assert((*cons)->update); 6293 assert((*cons)->nuses == 1); 6294 } 6295 else 6296 { 6297 SCIP_CALL( SCIPconsFree(cons, blkmem, set) ); 6298 } 6299 } 6300 *cons = NULL; 6301 6302 return SCIP_OKAY; 6303 } 6304 6305 /** outputs constraint information to file stream */ 6306 SCIP_RETCODE SCIPconsPrint( 6307 SCIP_CONS* cons, /**< constraint to print */ 6308 SCIP_SET* set, /**< global SCIP settings */ 6309 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 6310 FILE* file /**< output file (or NULL for standard output) */ 6311 ) 6312 { 6313 SCIP_CONSHDLR* conshdlr; 6314 6315 assert(cons != NULL); 6316 assert(set != NULL); 6317 assert(cons->scip == set->scip); 6318 6319 conshdlr = cons->conshdlr; 6320 assert(conshdlr != NULL); 6321 6322 SCIPmessageFPrintInfo(messagehdlr, file, " [%s] <%s>: ", conshdlr->name, cons->name); 6323 6324 if( conshdlr->consprint != NULL ) 6325 { 6326 SCIP_CALL( conshdlr->consprint(set->scip, conshdlr, cons, file) ); 6327 } 6328 else 6329 SCIPmessageFPrintInfo(messagehdlr, file, "constraint handler <%s> doesn't support printing constraint", conshdlr->name); 6330 6331 return SCIP_OKAY; 6332 } 6333 6334 /** method to collect the variables of a constraint 6335 * 6336 * If the number of variables is greater than the available slots in the variable array, nothing happens except that 6337 * the success point is set to FALSE. With the method SCIPconsGetNVars() it is possible to get the number of variables 6338 * a constraint has in its scope. 6339 * 6340 * @note The success pointer indicates if all variables were copied into the vars arrray. 6341 * 6342 * @note It might be that a constraint handler does not support this functionality, in that case the success pointer is 6343 * set to FALSE. 6344 */ 6345 SCIP_RETCODE SCIPconsGetVars( 6346 SCIP_CONS* cons, /**< constraint to get variables for */ 6347 SCIP_SET* set, /**< global SCIP settings */ 6348 SCIP_VAR** vars, /**< array to store the involved variable of the constraint */ 6349 int varssize, /**< available slots in vars array which is needed to check if the array is large enough */ 6350 SCIP_Bool* success /**< pointer to store whether the variables are successfully copied */ 6351 ) 6352 { 6353 SCIP_CONSHDLR* conshdlr; 6354 6355 assert(cons != NULL); 6356 assert(set != NULL); 6357 assert(cons->scip == set->scip); 6358 6359 conshdlr = cons->conshdlr; 6360 assert(conshdlr != NULL); 6361 6362 if( conshdlr->consgetvars != NULL ) 6363 { 6364 SCIP_CALL( conshdlr->consgetvars(set->scip, conshdlr, cons, vars, varssize, success) ); 6365 } 6366 else 6367 { 6368 (*success) = FALSE; 6369 } 6370 6371 return SCIP_OKAY; 6372 } 6373 6374 /** method to collect the number of variables of a constraint 6375 * 6376 * @note The success pointer indicates if the contraint handler was able to return the number of variables 6377 * 6378 * @note It might be that a constraint handler does not support this functionality, in that case the success pointer is 6379 * set to FALSE 6380 */ 6381 SCIP_RETCODE SCIPconsGetNVars( 6382 SCIP_CONS* cons, /**< constraint to get number of variables for */ 6383 SCIP_SET* set, /**< global SCIP settings */ 6384 int* nvars, /**< pointer to store the number of variables */ 6385 SCIP_Bool* success /**< pointer to store whether the constraint successfully returned the number of variables */ 6386 ) 6387 { 6388 SCIP_CONSHDLR* conshdlr; 6389 6390 assert(cons != NULL); 6391 assert(set != NULL); 6392 assert(cons->scip == set->scip); 6393 6394 conshdlr = cons->conshdlr; 6395 assert(conshdlr != NULL); 6396 6397 if( conshdlr->consgetnvars != NULL ) 6398 { 6399 SCIP_CALL( conshdlr->consgetnvars(set->scip, conshdlr, cons, nvars, success) ); 6400 } 6401 else 6402 { 6403 (*nvars) = 0; 6404 (*success) = FALSE; 6405 } 6406 6407 return SCIP_OKAY; 6408 } 6409 6410 /** method to collect the permutation symmetry detection graph of a constraint 6411 * 6412 * @note The success pointer indicates whether the constraint handler was able to return the graph. 6413 * 6414 * @note If a constraint handler does not support this functionality, the success pointer is set to FALSE. 6415 */ 6416 SCIP_RETCODE SCIPconsGetPermsymGraph( 6417 SCIP_CONS* cons, /**< constraint to get graph for */ 6418 SCIP_SET* set, /**< global SCIP settings */ 6419 SYM_GRAPH* graph, /**< symmetry detection graph */ 6420 SCIP_Bool* success /**< pointer to store whether the constraint successfully returned the graph */ 6421 ) 6422 { 6423 SCIP_CONSHDLR* conshdlr; 6424 6425 assert(cons != NULL); 6426 assert(set != NULL); 6427 assert(cons->scip == set->scip); 6428 assert(success != NULL); 6429 6430 conshdlr = cons->conshdlr; 6431 assert(conshdlr != NULL); 6432 6433 if( conshdlr->consgetpermsymgraph != NULL ) 6434 { 6435 SCIP_CALL( conshdlr->consgetpermsymgraph(set->scip, conshdlr, cons, graph, success) ); 6436 } 6437 else 6438 *success = FALSE; 6439 6440 return SCIP_OKAY; 6441 } 6442 6443 /** method to collect the signed permutation symmetry detection graph of a constraint 6444 * 6445 * @note The success pointer indicates whether the constraint handler was able to return the graph. 6446 * 6447 * @note If a constraint handler does not support this functionality, the success pointer is set to FALSE. 6448 */ 6449 SCIP_RETCODE SCIPconsGetSignedPermsymGraph( 6450 SCIP_CONS* cons, /**< constraint to get graph for */ 6451 SCIP_SET* set, /**< global SCIP settings */ 6452 SYM_GRAPH* graph, /**< symmetry detection graph */ 6453 SCIP_Bool* success /**< pointer to store whether the constraint successfully returned the graph */ 6454 ) 6455 { 6456 SCIP_CONSHDLR* conshdlr; 6457 6458 assert(cons != NULL); 6459 assert(set != NULL); 6460 assert(cons->scip == set->scip); 6461 assert(success != NULL); 6462 6463 conshdlr = cons->conshdlr; 6464 assert(conshdlr != NULL); 6465 6466 if( conshdlr->consgetsignedpermsymgraph != NULL ) 6467 { 6468 SCIP_CALL( conshdlr->consgetsignedpermsymgraph(set->scip, conshdlr, cons, graph, success) ); 6469 } 6470 else 6471 *success = FALSE; 6472 6473 return SCIP_OKAY; 6474 } 6475 6476 /** globally removes constraint from all subproblems; removes constraint from the constraint set change data of the 6477 * node, where it was created, or from the problem, if it was a problem constraint 6478 */ 6479 SCIP_RETCODE SCIPconsDelete( 6480 SCIP_CONS* cons, /**< constraint to delete */ 6481 BMS_BLKMEM* blkmem, /**< block memory */ 6482 SCIP_SET* set, /**< global SCIP settings */ 6483 SCIP_STAT* stat, /**< dynamic problem statistics */ 6484 SCIP_PROB* prob, /**< problem data */ 6485 SCIP_REOPT* reopt /**< reoptimization data */ 6486 ) 6487 { 6488 assert(cons != NULL); 6489 assert(cons->conshdlr != NULL); 6490 assert(!cons->active || cons->updatedeactivate || cons->addarraypos >= 0); 6491 assert(set != NULL); 6492 assert(cons->scip == set->scip); 6493 6494 SCIPsetDebugMsg(set, "globally deleting constraint <%s> (delay updates: %d)\n", 6495 cons->name, cons->conshdlr->delayupdatecount); 6496 6497 /* mark constraint deleted */ 6498 cons->deleted = TRUE; 6499 6500 /* deactivate constraint, if it is currently active */ 6501 if( cons->active && !cons->updatedeactivate ) 6502 { 6503 SCIP_CALL( SCIPconsDeactivate(cons, set, stat) ); 6504 } 6505 else 6506 cons->updateactivate = FALSE; 6507 6508 if( set->reopt_enable && !SCIPreoptConsCanBeDeleted(reopt, cons) ) 6509 return SCIP_OKAY; 6510 6511 assert(!cons->active || cons->updatedeactivate); 6512 assert(!cons->enabled || cons->updatedeactivate); 6513 6514 /* remove formerly active constraint from the conssetchg's addedconss / prob's conss array */ 6515 if( cons->addarraypos >= 0 ) 6516 { 6517 if( cons->addconssetchg == NULL ) 6518 { 6519 /* remove problem constraint from the problem */ 6520 SCIP_CALL( SCIPprobDelCons(prob, blkmem, set, stat, cons) ); 6521 } 6522 else 6523 { 6524 assert(cons->addconssetchg->addedconss != NULL); 6525 assert(0 <= cons->addarraypos && cons->addarraypos < cons->addconssetchg->naddedconss); 6526 assert(cons->addconssetchg->addedconss[cons->addarraypos] == cons); 6527 6528 /* remove constraint from the constraint set change addedconss array */ 6529 SCIP_CALL( conssetchgDelAddedCons(cons->addconssetchg, blkmem, set, cons->addarraypos) ); 6530 } 6531 } 6532 6533 return SCIP_OKAY; 6534 } 6535 6536 /** gets and captures transformed constraint of a given original constraint; if the constraint is not yet transformed, 6537 * a new transformed constraint for this constraint is created 6538 */ 6539 SCIP_RETCODE SCIPconsTransform( 6540 SCIP_CONS* origcons, /**< original constraint */ 6541 BMS_BLKMEM* blkmem, /**< block memory buffer */ 6542 SCIP_SET* set, /**< global SCIP settings */ 6543 SCIP_CONS** transcons /**< pointer to store the transformed constraint */ 6544 ) 6545 { 6546 assert(origcons != NULL); 6547 assert(set != NULL); 6548 assert(origcons->scip == set->scip); 6549 assert(origcons->conshdlr != NULL); 6550 assert(origcons->original); 6551 assert(transcons != NULL); 6552 6553 /* check, if the constraint is already transformed */ 6554 if( origcons->transorigcons != NULL ) 6555 { 6556 *transcons = origcons->transorigcons; 6557 SCIPconsCapture(*transcons); 6558 } 6559 else 6560 { 6561 /* create transformed constraint */ 6562 if( origcons->conshdlr->constrans != NULL ) 6563 { 6564 /* use constraint handler's own method to transform constraint */ 6565 SCIP_CALL( origcons->conshdlr->constrans(set->scip, origcons->conshdlr, origcons, transcons) ); 6566 } 6567 else 6568 { 6569 /* create new constraint with a pointer copy of the constraint data */ 6570 SCIP_CALL( SCIPconsCreate(transcons, blkmem, set, origcons->name, origcons->conshdlr, origcons->consdata, origcons->initial, 6571 origcons->separate, origcons->enforce, origcons->check, origcons->propagate, 6572 origcons->local, origcons->modifiable, origcons->dynamic, origcons->removable, origcons->stickingatnode, 6573 FALSE, FALSE) ); 6574 } 6575 6576 /* link original and transformed constraint */ 6577 origcons->transorigcons = *transcons; 6578 (*transcons)->transorigcons = origcons; 6579 6580 /* copy the number of upgradelocks */ 6581 (*transcons)->nupgradelocks = origcons->nupgradelocks; /*lint !e732*/ 6582 } 6583 assert(*transcons != NULL); 6584 6585 return SCIP_OKAY; 6586 } 6587 6588 /** sets the initial flag of the given constraint */ 6589 SCIP_RETCODE SCIPconsSetInitial( 6590 SCIP_CONS* cons, /**< constraint */ 6591 SCIP_SET* set, /**< global SCIP settings */ 6592 SCIP_STAT* stat, /**< dynamic problem statistics */ 6593 SCIP_Bool initial /**< new value */ 6594 ) 6595 { 6596 assert(cons != NULL); 6597 assert(set != NULL); 6598 assert(cons->scip == set->scip); 6599 6600 if( cons->initial != initial ) 6601 { 6602 cons->initial = initial; 6603 if( !cons->original ) 6604 { 6605 if( cons->initial ) 6606 { 6607 SCIP_CALL( conshdlrAddInitcons(SCIPconsGetHdlr(cons), set, stat, cons) ); 6608 } 6609 else 6610 { 6611 if( cons->initconsspos >= 0 ) 6612 { 6613 conshdlrDelInitcons(SCIPconsGetHdlr(cons), cons); 6614 } 6615 } 6616 } 6617 } 6618 6619 return SCIP_OKAY; 6620 } 6621 6622 /** sets the separate flag of the given constraint */ 6623 SCIP_RETCODE SCIPconsSetSeparated( 6624 SCIP_CONS* cons, /**< constraint */ 6625 SCIP_SET* set, /**< global SCIP settings */ 6626 SCIP_Bool separate /**< new value */ 6627 ) 6628 { 6629 assert(cons != NULL); 6630 assert(set != NULL); 6631 assert(cons->scip == set->scip); 6632 6633 if( cons->separate != separate ) 6634 { 6635 if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM ) 6636 { 6637 cons->separate = separate; 6638 } 6639 else if( cons->enabled && cons->sepaenabled ) 6640 { 6641 if( separate ) 6642 { 6643 cons->separate = separate; 6644 SCIP_CALL( conshdlrAddSepacons(cons->conshdlr, set, cons) ); 6645 } 6646 else 6647 { 6648 conshdlrDelSepacons(cons->conshdlr, cons); 6649 cons->separate = separate; 6650 } 6651 } 6652 } 6653 6654 return SCIP_OKAY; 6655 } 6656 6657 /** sets the enforce flag of the given constraint */ 6658 SCIP_RETCODE SCIPconsSetEnforced( 6659 SCIP_CONS* cons, /**< constraint */ 6660 SCIP_SET* set, /**< global SCIP settings */ 6661 SCIP_Bool enforce /**< new value */ 6662 ) 6663 { 6664 assert(cons != NULL); 6665 assert(set != NULL); 6666 assert(cons->scip == set->scip); 6667 6668 if( cons->enforce != enforce ) 6669 { 6670 if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM ) 6671 { 6672 cons->enforce = enforce; 6673 } 6674 else if( cons->enabled ) 6675 { 6676 if( enforce ) 6677 { 6678 cons->enforce = enforce; 6679 SCIP_CALL( conshdlrAddEnfocons(cons->conshdlr, set, cons) ); 6680 } 6681 else 6682 { 6683 conshdlrDelEnfocons(cons->conshdlr, cons); 6684 cons->enforce = enforce; 6685 } 6686 } 6687 } 6688 6689 return SCIP_OKAY; 6690 } 6691 6692 /** sets the check flag of the given constraint */ 6693 SCIP_RETCODE SCIPconsSetChecked( 6694 SCIP_CONS* cons, /**< constraint */ 6695 SCIP_SET* set, /**< global SCIP settings */ 6696 SCIP_Bool check /**< new value */ 6697 ) 6698 { 6699 assert(cons != NULL); 6700 assert(set != NULL); 6701 assert(cons->scip == set->scip); 6702 6703 if( cons->check != check ) 6704 { 6705 cons->check = check; 6706 6707 if( !cons->original ) 6708 { 6709 /* if constraint is a problem constraint, update variable roundings locks */ 6710 if( cons->addconssetchg == NULL && cons->addarraypos >= 0 ) 6711 { 6712 if( cons->check ) 6713 { 6714 SCIP_CALL( SCIPconsAddLocks(cons, set, SCIP_LOCKTYPE_MODEL, +1, 0) ); 6715 } 6716 else 6717 { 6718 SCIP_CALL( SCIPconsAddLocks(cons, set, SCIP_LOCKTYPE_MODEL, -1, 0) ); 6719 } 6720 } 6721 6722 /* if constraint is active, update the checkconss array of the constraint handler */ 6723 if( cons->active ) 6724 { 6725 if( cons->check ) 6726 { 6727 SCIP_CALL( conshdlrAddCheckcons(cons->conshdlr, set, cons) ); 6728 } 6729 else 6730 { 6731 conshdlrDelCheckcons(cons->conshdlr, cons); 6732 } 6733 } 6734 } 6735 } 6736 6737 return SCIP_OKAY; 6738 } 6739 6740 /** sets the propagate flag of the given constraint */ 6741 SCIP_RETCODE SCIPconsSetPropagated( 6742 SCIP_CONS* cons, /**< constraint */ 6743 SCIP_SET* set, /**< global SCIP settings */ 6744 SCIP_Bool propagate /**< new value */ 6745 ) 6746 { 6747 assert(cons != NULL); 6748 assert(set != NULL); 6749 assert(cons->scip == set->scip); 6750 6751 if( cons->propagate != propagate ) 6752 { 6753 if( SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM ) 6754 { 6755 cons->propagate = propagate; 6756 } 6757 else if( cons->enabled && cons->propenabled ) 6758 { 6759 if( propagate ) 6760 { 6761 cons->propagate = propagate; 6762 SCIP_CALL( conshdlrAddPropcons(cons->conshdlr, set, cons) ); 6763 } 6764 else 6765 { 6766 conshdlrDelPropcons(cons->conshdlr, cons); 6767 cons->propagate = propagate; 6768 } 6769 } 6770 } 6771 6772 return SCIP_OKAY; 6773 } 6774 6775 /** sets the local flag of the given constraint */ 6776 void SCIPconsSetLocal( 6777 SCIP_CONS* cons, /**< constraint */ 6778 SCIP_Bool local /**< new value */ 6779 ) 6780 { 6781 assert(cons != NULL); 6782 6783 cons->local = local; 6784 if( !local ) 6785 cons->validdepth = 0; 6786 } 6787 6788 /** sets the modifiable flag of the given constraint */ 6789 void SCIPconsSetModifiable( 6790 SCIP_CONS* cons, /**< constraint */ 6791 SCIP_Bool modifiable /**< new value */ 6792 ) 6793 { 6794 assert(cons != NULL); 6795 6796 cons->modifiable = modifiable; 6797 } 6798 6799 /** sets the dynamic flag of the given constraint */ 6800 void SCIPconsSetDynamic( 6801 SCIP_CONS* cons, /**< constraint */ 6802 SCIP_Bool dynamic /**< new value */ 6803 ) 6804 { 6805 assert(cons != NULL); 6806 6807 cons->dynamic = dynamic; 6808 } 6809 6810 /** sets the removable flag of the given constraint */ 6811 void SCIPconsSetRemovable( 6812 SCIP_CONS* cons, /**< constraint */ 6813 SCIP_Bool removable /**< new value */ 6814 ) 6815 { 6816 assert(cons != NULL); 6817 6818 cons->removable = removable; 6819 } 6820 6821 /** sets the stickingatnode flag of the given constraint */ 6822 void SCIPconsSetStickingAtNode( 6823 SCIP_CONS* cons, /**< constraint */ 6824 SCIP_Bool stickingatnode /**< new value */ 6825 ) 6826 { 6827 assert(cons != NULL); 6828 6829 cons->stickingatnode = stickingatnode; 6830 } 6831 6832 /** gives the constraint a new name; ATTENTION: to old pointer is over written that might 6833 * result in a memory leakage */ 6834 void SCIPconsSetNamePointer( 6835 SCIP_CONS* cons, /**< constraint */ 6836 const char* name /**< new name of constraint */ 6837 ) 6838 { 6839 assert( cons != NULL ); 6840 assert( name != NULL ); 6841 6842 cons->name = (char*)name; 6843 } 6844 6845 /** gets associated transformed constraint of an original constraint, or NULL if no associated transformed constraint 6846 * exists 6847 */ 6848 SCIP_CONS* SCIPconsGetTransformed( 6849 SCIP_CONS* cons /**< constraint */ 6850 ) 6851 { 6852 assert(cons->original); 6853 6854 return cons->transorigcons; 6855 } 6856 6857 /** activates constraint or marks constraint to be activated in next update */ 6858 SCIP_RETCODE SCIPconsActivate( 6859 SCIP_CONS* cons, /**< constraint */ 6860 SCIP_SET* set, /**< global SCIP settings */ 6861 SCIP_STAT* stat, /**< dynamic problem statistics */ 6862 int depth, /**< depth in the tree where the constraint activation takes place, or -1 for global problem */ 6863 SCIP_Bool focusnode /**< does the constraint activation take place at the focus node? */ 6864 ) 6865 { 6866 assert(cons != NULL); 6867 assert(!cons->original); 6868 assert(!cons->active); 6869 assert(!cons->updateactivate); 6870 assert(!cons->updatedeactivate); 6871 assert(!cons->updateenable); 6872 assert(!cons->updatedisable); 6873 assert(!cons->updateobsolete); 6874 assert(!cons->updatefree); 6875 assert(cons->activedepth == -2); 6876 assert(cons->conshdlr != NULL); 6877 assert(set != NULL); 6878 assert(cons->scip == set->scip); 6879 6880 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 6881 { 6882 SCIPsetDebugMsg(set, "delayed activation of constraint <%s> in constraint handler <%s> (depth %d)\n", 6883 cons->name, cons->conshdlr->name, depth); 6884 cons->updateactivate = TRUE; 6885 cons->activedepth = depth; 6886 cons->updateactfocus = focusnode; 6887 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 6888 assert(cons->update); 6889 } 6890 else 6891 { 6892 SCIP_CALL( conshdlrActivateCons(cons->conshdlr, set, stat, cons, depth, focusnode) ); 6893 assert(cons->active); 6894 } 6895 6896 return SCIP_OKAY; 6897 } 6898 6899 /** deactivates constraint or marks constraint to be deactivated in next update */ 6900 SCIP_RETCODE SCIPconsDeactivate( 6901 SCIP_CONS* cons, /**< constraint */ 6902 SCIP_SET* set, /**< global SCIP settings */ 6903 SCIP_STAT* stat /**< dynamic problem statistics */ 6904 ) 6905 { 6906 assert(cons != NULL); 6907 assert(!cons->original); 6908 assert(cons->active); 6909 assert(!cons->updateactivate); 6910 assert(!cons->updatedeactivate); 6911 assert(cons->activedepth >= -1); 6912 assert(cons->conshdlr != NULL); 6913 assert(set != NULL); 6914 assert(cons->scip == set->scip); 6915 6916 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 6917 { 6918 SCIPsetDebugMsg(set, "delayed deactivation of constraint <%s> in constraint handler <%s>\n", 6919 cons->name, cons->conshdlr->name); 6920 cons->updatedeactivate = TRUE; 6921 cons->activedepth = -2; 6922 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 6923 assert(cons->update); 6924 } 6925 else 6926 { 6927 SCIP_CALL( conshdlrDeactivateCons(cons->conshdlr, set, stat, cons) ); 6928 assert(!cons->active); 6929 } 6930 6931 return SCIP_OKAY; 6932 } 6933 6934 /** enables constraint's separation, enforcing, and propagation capabilities or marks them to be enabled in next update */ 6935 SCIP_RETCODE SCIPconsEnable( 6936 SCIP_CONS* cons, /**< constraint */ 6937 SCIP_SET* set, /**< global SCIP settings */ 6938 SCIP_STAT* stat /**< dynamic problem statistics */ 6939 ) 6940 { 6941 assert(cons != NULL); 6942 assert(!cons->original); 6943 assert(cons->conshdlr != NULL); 6944 assert(set != NULL); 6945 assert(cons->scip == set->scip); 6946 6947 if( !cons->active || cons->updatedeactivate || cons->updateenable || (cons->enabled && !cons->updatedisable) ) 6948 return SCIP_OKAY; 6949 6950 assert(!cons->updateactivate); 6951 6952 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 6953 { 6954 cons->updateenable = TRUE; 6955 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 6956 assert(cons->update); 6957 } 6958 else 6959 { 6960 SCIP_CALL( conshdlrEnableCons(cons->conshdlr, set, stat, cons) ); 6961 assert(cons->enabled); 6962 } 6963 6964 return SCIP_OKAY; 6965 } 6966 6967 /** disables constraint's separation, enforcing, and propagation capabilities or marks them to be disabled in next update */ 6968 SCIP_RETCODE SCIPconsDisable( 6969 SCIP_CONS* cons, /**< constraint */ 6970 SCIP_SET* set, /**< global SCIP settings */ 6971 SCIP_STAT* stat /**< dynamic problem statistics */ 6972 ) 6973 { 6974 assert(cons != NULL); 6975 assert(!cons->original); 6976 assert(cons->conshdlr != NULL); 6977 assert(set != NULL); 6978 assert(cons->scip == set->scip); 6979 6980 if( cons->updatedisable || (!cons->enabled && !cons->updateenable) ) 6981 return SCIP_OKAY; 6982 6983 assert(cons->active); 6984 assert(!cons->updateactivate); 6985 6986 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 6987 { 6988 cons->updatedisable = TRUE; 6989 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 6990 assert(cons->update); 6991 } 6992 else 6993 { 6994 SCIP_CALL( conshdlrDisableCons(cons->conshdlr, set, stat, cons) ); 6995 assert(!cons->enabled); 6996 } 6997 6998 return SCIP_OKAY; 6999 } 7000 7001 /** enables constraint's separation capabilities or marks them to be enabled in next update */ 7002 SCIP_RETCODE SCIPconsEnableSeparation( 7003 SCIP_CONS* cons, /**< constraint */ 7004 SCIP_SET* set /**< global SCIP settings */ 7005 ) 7006 { 7007 assert(cons != NULL); 7008 assert(cons->conshdlr != NULL); 7009 assert(set != NULL); 7010 assert(cons->scip == set->scip); 7011 7012 if( cons->updatesepaenable || (cons->sepaenabled && !cons->updatesepadisable) ) 7013 return SCIP_OKAY; 7014 7015 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7016 { 7017 cons->updatesepadisable = FALSE; 7018 cons->updatesepaenable = TRUE; 7019 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7020 assert(cons->update); 7021 } 7022 else 7023 { 7024 SCIP_CALL( conshdlrEnableConsSeparation(cons->conshdlr, set, cons) ); 7025 assert(cons->sepaenabled); 7026 } 7027 7028 return SCIP_OKAY; 7029 } 7030 7031 /** disables constraint's separation capabilities or marks them to be disabled in next update */ 7032 SCIP_RETCODE SCIPconsDisableSeparation( 7033 SCIP_CONS* cons, /**< constraint */ 7034 SCIP_SET* set /**< global SCIP settings */ 7035 ) 7036 { 7037 assert(cons != NULL); 7038 assert(cons->conshdlr != NULL); 7039 7040 if( cons->updatesepadisable || (!cons->sepaenabled && !cons->updatesepaenable) ) 7041 return SCIP_OKAY; 7042 7043 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7044 { 7045 cons->updatesepaenable = FALSE; 7046 cons->updatesepadisable = TRUE; 7047 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7048 assert(cons->update); 7049 } 7050 else 7051 { 7052 SCIP_CALL( conshdlrDisableConsSeparation(cons->conshdlr, cons) ); 7053 assert(!cons->sepaenabled); 7054 } 7055 7056 return SCIP_OKAY; 7057 } 7058 7059 /** enables constraint's propagation capabilities or marks them to be enabled in next update */ 7060 SCIP_RETCODE SCIPconsEnablePropagation( 7061 SCIP_CONS* cons, /**< constraint */ 7062 SCIP_SET* set /**< global SCIP settings */ 7063 ) 7064 { 7065 assert(cons != NULL); 7066 assert(cons->conshdlr != NULL); 7067 assert(set != NULL); 7068 assert(cons->scip == set->scip); 7069 7070 if( cons->updatepropenable || (cons->propenabled && !cons->updatepropdisable) ) 7071 return SCIP_OKAY; 7072 7073 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7074 { 7075 cons->updatepropdisable = FALSE; 7076 cons->updatepropenable = TRUE; 7077 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7078 assert(cons->update); 7079 } 7080 else 7081 { 7082 SCIP_CALL( conshdlrEnableConsPropagation(cons->conshdlr, set, cons) ); 7083 assert(cons->propenabled); 7084 } 7085 7086 return SCIP_OKAY; 7087 } 7088 7089 /** disables constraint's propagation capabilities or marks them to be disabled in next update */ 7090 SCIP_RETCODE SCIPconsDisablePropagation( 7091 SCIP_CONS* cons, /**< constraint */ 7092 SCIP_SET* set /**< global SCIP settings */ 7093 ) 7094 { 7095 assert(cons != NULL); 7096 assert(cons->conshdlr != NULL); 7097 assert(set != NULL); 7098 assert(cons->scip == set->scip); 7099 7100 if( cons->updatepropdisable || (!cons->propenabled && !cons->updatepropenable) ) 7101 return SCIP_OKAY; 7102 7103 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7104 { 7105 cons->updatepropenable = FALSE; 7106 cons->updatepropdisable = TRUE; 7107 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7108 assert(cons->update); 7109 } 7110 else 7111 { 7112 SCIP_CALL( conshdlrDisableConsPropagation(cons->conshdlr, cons) ); 7113 assert(!cons->propenabled); 7114 } 7115 7116 return SCIP_OKAY; 7117 } 7118 7119 /** marks the constraint to be a conflict */ 7120 void SCIPconsMarkConflict( 7121 SCIP_CONS* cons /**< constraint */ 7122 ) 7123 { 7124 assert(cons != NULL); 7125 7126 cons->conflict = TRUE; 7127 } 7128 7129 /** marks the constraint to be propagated (update might be delayed) */ 7130 SCIP_RETCODE SCIPconsMarkPropagate( 7131 SCIP_CONS* cons, /**< constraint */ 7132 SCIP_SET* set /**< global SCIP settings */ 7133 ) 7134 { 7135 assert(cons != NULL); 7136 assert(cons->conshdlr != NULL); 7137 assert(set != NULL); 7138 assert(cons->scip == set->scip); 7139 7140 if( cons->updatemarkpropagate || (cons->markpropagate && !cons->updateunmarkpropagate) ) 7141 return SCIP_OKAY; 7142 7143 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7144 { 7145 cons->updateunmarkpropagate = FALSE; 7146 cons->updatemarkpropagate = TRUE; 7147 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7148 assert(cons->update); 7149 } 7150 else 7151 { 7152 conshdlrMarkConsPropagate(cons->conshdlr, cons); 7153 assert(cons->markpropagate || !cons->enabled); 7154 } 7155 7156 return SCIP_OKAY; 7157 } 7158 7159 /** unmarks the constraint to be propagated (update might be delayed) */ 7160 SCIP_RETCODE SCIPconsUnmarkPropagate( 7161 SCIP_CONS* cons, /**< constraint */ 7162 SCIP_SET* set /**< global SCIP settings */ 7163 ) 7164 { 7165 assert(cons != NULL); 7166 assert(cons->conshdlr != NULL); 7167 assert(set != NULL); 7168 assert(cons->scip == set->scip); 7169 7170 if( cons->updateunmarkpropagate || (!cons->markpropagate && !cons->updatemarkpropagate) ) 7171 return SCIP_OKAY; 7172 7173 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7174 { 7175 cons->updatemarkpropagate = FALSE; 7176 cons->updateunmarkpropagate = TRUE; 7177 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7178 assert(cons->update); 7179 } 7180 else 7181 { 7182 conshdlrUnmarkConsPropagate(cons->conshdlr, cons); 7183 assert(!cons->markpropagate || !cons->enabled); 7184 } 7185 7186 return SCIP_OKAY; 7187 } 7188 7189 /** adds given value to age of constraint, but age can never become negative; 7190 * should be called 7191 * - in constraint separation, if no cut was found for this constraint, 7192 * - in constraint enforcing, if constraint was feasible, and 7193 * - in constraint propagation, if no domain reduction was deduced; 7194 * if it's age exceeds the constraint age limit, makes constraint obsolete or marks constraint to be made obsolete 7195 * in next update 7196 */ 7197 SCIP_RETCODE SCIPconsAddAge( 7198 SCIP_CONS* cons, /**< constraint */ 7199 BMS_BLKMEM* blkmem, /**< block memory */ 7200 SCIP_SET* set, /**< global SCIP settings */ 7201 SCIP_STAT* stat, /**< dynamic problem statistics */ 7202 SCIP_PROB* prob, /**< problem data */ 7203 SCIP_Real deltaage, /**< value to add to the constraint's age */ 7204 SCIP_REOPT* reopt /**< reoptimization data */ 7205 ) 7206 { 7207 assert(cons != NULL); 7208 assert(cons->conshdlr != NULL); 7209 assert(!cons->updateactivate); 7210 assert(set != NULL); 7211 assert(cons->scip == set->scip); 7212 7213 /* no aging in presolving */ 7214 if( set->stage == SCIP_STAGE_PRESOLVING ) 7215 return SCIP_OKAY; 7216 7217 SCIPsetDebugMsg(set, "adding %g to age (%g) of constraint <%s> of handler <%s>\n", 7218 deltaage, cons->age, cons->name, cons->conshdlr->name); 7219 7220 cons->age += deltaage; 7221 cons->age = MAX(cons->age, 0.0); 7222 7223 if( !cons->original ) 7224 { 7225 if( !cons->check && consExceedsAgelimit(cons, set) ) 7226 { 7227 SCIP_CALL( SCIPconsDelete(cons, blkmem, set, stat, prob, reopt) ); 7228 } 7229 else if( !cons->obsolete && consExceedsObsoleteage(cons, set) ) 7230 { 7231 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7232 { 7233 cons->updateobsolete = TRUE; 7234 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7235 assert(cons->update); 7236 } 7237 else 7238 { 7239 SCIP_CALL( conshdlrMarkConsObsolete(cons->conshdlr, cons) ); 7240 assert(cons->obsolete); 7241 } 7242 } 7243 } 7244 7245 return SCIP_OKAY; 7246 } 7247 7248 /** increases age of constraint by 1.0; 7249 * should be called 7250 * - in constraint separation, if no cut was found for this constraint, 7251 * - in constraint enforcing, if constraint was feasible, and 7252 * - in constraint propagation, if no domain reduction was deduced; 7253 * if it's age exceeds the constraint age limit, makes constraint obsolete or marks constraint to be made obsolete 7254 * in next update 7255 */ 7256 SCIP_RETCODE SCIPconsIncAge( 7257 SCIP_CONS* cons, /**< constraint */ 7258 BMS_BLKMEM* blkmem, /**< block memory */ 7259 SCIP_SET* set, /**< global SCIP settings */ 7260 SCIP_STAT* stat, /**< dynamic problem statistics */ 7261 SCIP_PROB* prob, /**< problem data */ 7262 SCIP_REOPT* reopt /**< reoptimization data */ 7263 ) 7264 { 7265 SCIP_CALL( SCIPconsAddAge(cons, blkmem, set, stat, prob, 1.0, reopt) ); 7266 7267 return SCIP_OKAY; 7268 } 7269 7270 /** resets age of constraint to zero; 7271 * should be called 7272 * - in constraint separation, if a cut was found for this constraint, 7273 * - in constraint enforcing, if the constraint was violated, and 7274 * - in constraint propagation, if a domain reduction was deduced; 7275 * if it was obsolete, makes constraint useful again or marks constraint to be made useful again in next update 7276 */ 7277 SCIP_RETCODE SCIPconsResetAge( 7278 SCIP_CONS* cons, /**< constraint */ 7279 SCIP_SET* set /**< global SCIP settings */ 7280 ) 7281 { 7282 assert(cons != NULL); 7283 assert(cons->conshdlr != NULL); 7284 assert(!cons->updateactivate); 7285 assert(set != NULL); 7286 assert(cons->scip == set->scip); 7287 7288 SCIPsetDebugMsg(set, "resetting age %g of constraint <%s> of handler <%s>\n", cons->age, cons->name, cons->conshdlr->name); 7289 7290 conshdlrUpdateAgeresetavg(cons->conshdlr, cons->age); 7291 cons->age = 0.0; 7292 7293 if( cons->obsolete ) 7294 { 7295 assert(!cons->original); 7296 if( conshdlrAreUpdatesDelayed(cons->conshdlr) ) 7297 { 7298 cons->updateobsolete = TRUE; 7299 SCIP_CALL( conshdlrAddUpdateCons(cons->conshdlr, set, cons) ); 7300 assert(cons->update); 7301 } 7302 else 7303 { 7304 SCIP_CALL( conshdlrMarkConsUseful(cons->conshdlr, cons) ); 7305 assert(!cons->obsolete); 7306 } 7307 } 7308 7309 return SCIP_OKAY; 7310 } 7311 7312 /** resolves the given conflicting bound, that was deduced by the given constraint, by putting all "reason" bounds 7313 * leading to the deduction into the conflict queue with calls to SCIPaddConflictLb(), SCIPaddConflictUb(), SCIPaddConflictBd(), 7314 * SCIPaddConflictRelaxedLb(), SCIPaddConflictRelaxedUb(), SCIPaddConflictRelaxedBd(), or SCIPaddConflictBinvar(); 7315 * 7316 * @note it is sufficient to explain the relaxed bound change 7317 */ 7318 SCIP_RETCODE SCIPconsResolvePropagation( 7319 SCIP_CONS* cons, /**< constraint that deduced the assignment */ 7320 SCIP_SET* set, /**< global SCIP settings */ 7321 SCIP_VAR* infervar, /**< variable whose bound was deduced by the constraint */ 7322 int inferinfo, /**< user inference information attached to the bound change */ 7323 SCIP_BOUNDTYPE inferboundtype, /**< bound that was deduced (lower or upper bound) */ 7324 SCIP_BDCHGIDX* bdchgidx, /**< bound change index, representing the point of time where change took place */ 7325 SCIP_Real relaxedbd, /**< the relaxed bound */ 7326 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7327 ) 7328 { 7329 SCIP_CONSHDLR* conshdlr; 7330 7331 assert(set != NULL); 7332 assert(cons != NULL); 7333 assert((inferboundtype == SCIP_BOUNDTYPE_LOWER 7334 && SCIPgetVarLbAtIndex(set->scip, infervar, bdchgidx, TRUE) > SCIPvarGetLbGlobal(infervar)) 7335 || (inferboundtype == SCIP_BOUNDTYPE_UPPER 7336 && SCIPgetVarUbAtIndex(set->scip, infervar, bdchgidx, TRUE) < SCIPvarGetUbGlobal(infervar))); 7337 assert(result != NULL); 7338 assert(cons->scip == set->scip); 7339 7340 *result = SCIP_DIDNOTRUN; 7341 7342 conshdlr = cons->conshdlr; 7343 assert(conshdlr != NULL); 7344 7345 if( conshdlr->consresprop != NULL ) 7346 { 7347 /* start timing */ 7348 SCIPclockStart(conshdlr->resproptime, set); 7349 7350 SCIP_CALL( conshdlr->consresprop(set->scip, conshdlr, cons, infervar, inferinfo, inferboundtype, bdchgidx, 7351 relaxedbd, result) ); 7352 7353 /* stop timing */ 7354 SCIPclockStop(conshdlr->resproptime, set); 7355 7356 /* update statistics */ 7357 conshdlr->nrespropcalls++; 7358 7359 /* check result code */ 7360 if( *result != SCIP_SUCCESS && *result != SCIP_DIDNOTFIND ) 7361 { 7362 SCIPerrorMessage("propagation conflict resolving method of constraint handler <%s> returned invalid result <%d>\n", 7363 conshdlr->name, *result); 7364 return SCIP_INVALIDRESULT; 7365 } 7366 } 7367 else 7368 { 7369 SCIPerrorMessage("propagation conflict resolving method of constraint handler <%s> is not implemented\n", 7370 conshdlr->name); 7371 return SCIP_PLUGINNOTFOUND; 7372 } 7373 7374 return SCIP_OKAY; 7375 } 7376 7377 /** adds given values to lock status of the constraint and updates the locks of the given locktype of the involved variables */ 7378 SCIP_RETCODE SCIPconsAddLocks( 7379 SCIP_CONS* cons, /**< constraint */ 7380 SCIP_SET* set, /**< global SCIP settings */ 7381 SCIP_LOCKTYPE locktype, /**< type of variable locks */ 7382 int nlockspos, /**< increase in number of rounding locks for constraint */ 7383 int nlocksneg /**< increase in number of rounding locks for constraint's negation */ 7384 ) 7385 { 7386 int oldnlockspos; 7387 int oldnlocksneg; 7388 int updlockpos; 7389 int updlockneg; 7390 7391 assert(cons != NULL); 7392 assert(cons->conshdlr != NULL); 7393 assert(cons->conshdlr->conslock != NULL); 7394 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/ 7395 assert(cons->nlockspos[locktype] >= 0); 7396 assert(cons->nlocksneg[locktype] >= 0); 7397 assert(-2 <= nlockspos && nlockspos <= 2); 7398 assert(-2 <= nlocksneg && nlocksneg <= 2); 7399 assert(set != NULL); 7400 assert(cons->scip == set->scip); 7401 7402 /* update the rounding locks */ 7403 oldnlockspos = cons->nlockspos[locktype]; 7404 oldnlocksneg = cons->nlocksneg[locktype]; 7405 cons->nlockspos[locktype] += nlockspos; 7406 cons->nlocksneg[locktype] += nlocksneg; 7407 assert(cons->nlockspos[locktype] >= 0); 7408 assert(cons->nlocksneg[locktype] >= 0); 7409 7410 /* check, if the constraint switched from unlocked to locked, or from locked to unlocked */ 7411 updlockpos = (int)(cons->nlockspos[locktype] > 0) - (int)(oldnlockspos > 0); 7412 updlockneg = (int)(cons->nlocksneg[locktype] > 0) - (int)(oldnlocksneg > 0); 7413 7414 /* lock the variables, if the constraint switched from unlocked to locked or from locked to unlocked */ 7415 if( updlockpos != 0 || updlockneg != 0 ) 7416 { 7417 SCIP_CALL( cons->conshdlr->conslock(set->scip, cons->conshdlr, cons, locktype, updlockpos, updlockneg) ); 7418 } 7419 7420 return SCIP_OKAY; 7421 } 7422 7423 /** checks single constraint for feasibility of the given solution */ 7424 SCIP_RETCODE SCIPconsCheck( 7425 SCIP_CONS* cons, /**< constraint to check */ 7426 SCIP_SET* set, /**< global SCIP settings */ 7427 SCIP_SOL* sol, /**< primal CIP solution */ 7428 SCIP_Bool checkintegrality, /**< Has integrality to be checked? */ 7429 SCIP_Bool checklprows, /**< Do constraints represented by rows in the current LP have to be checked? */ 7430 SCIP_Bool printreason, /**< Should the reason for the violation be printed? */ 7431 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7432 ) 7433 { 7434 SCIP_CONSHDLR* conshdlr; 7435 7436 assert(cons != NULL); 7437 assert(set != NULL); 7438 assert(cons->scip == set->scip); 7439 assert(result != NULL); 7440 7441 conshdlr = cons->conshdlr; 7442 assert(conshdlr != NULL); 7443 7444 /* call external method */ 7445 assert(conshdlr->conscheck != NULL); 7446 7447 SCIP_CALL( conshdlr->conscheck(set->scip, conshdlr, &cons, 1, sol, checkintegrality, checklprows, printreason, 7448 FALSE, result) ); 7449 SCIPsetDebugMsg(set, " -> checking returned result <%d>\n", *result); 7450 7451 if( *result != SCIP_INFEASIBLE && *result != SCIP_FEASIBLE ) 7452 { 7453 SCIPerrorMessage("feasibility check of constraint handler <%s> on constraint <%s> returned invalid result <%d>\n", 7454 conshdlr->name, cons->name, *result); 7455 return SCIP_INVALIDRESULT; 7456 } 7457 7458 return SCIP_OKAY; 7459 } 7460 7461 /** enforces single constraint for a given pseudo solution */ 7462 SCIP_RETCODE SCIPconsEnfops( 7463 SCIP_CONS* cons, /**< constraint to enforce */ 7464 SCIP_SET* set, /**< global SCIP settings */ 7465 SCIP_Bool solinfeasible, /**< was the solution already declared infeasible by a constraint handler? */ 7466 SCIP_Bool objinfeasible, /**< is the solution infeasible anyway due to violating lower objective bound? */ 7467 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7468 ) 7469 { 7470 SCIP_CONSHDLR* conshdlr; 7471 7472 assert(cons != NULL); 7473 assert(set != NULL); 7474 assert(cons->scip == set->scip); 7475 assert(result != NULL); 7476 7477 conshdlr = cons->conshdlr; 7478 assert(conshdlr != NULL); 7479 7480 /* call external method */ 7481 assert(conshdlr->consenfops != NULL); 7482 7483 SCIP_CALL( conshdlr->consenfops(set->scip, conshdlr, &cons, 1, 1, solinfeasible, objinfeasible, result) ); 7484 SCIPsetDebugMsg(set, " -> enfops returned result <%d>\n", *result); 7485 7486 if( *result != SCIP_CUTOFF 7487 && *result != SCIP_CONSADDED 7488 && *result != SCIP_REDUCEDDOM 7489 && *result != SCIP_BRANCHED 7490 && *result != SCIP_SOLVELP 7491 && *result != SCIP_INFEASIBLE 7492 && *result != SCIP_FEASIBLE 7493 && *result != SCIP_DIDNOTRUN ) 7494 { 7495 SCIPerrorMessage("enforcing method of constraint handler <%s> for pseudo solutions returned invalid result <%d>\n", 7496 conshdlr->name, *result); 7497 return SCIP_INVALIDRESULT; 7498 } 7499 7500 /* do not update statistics */ 7501 7502 return SCIP_OKAY; 7503 } 7504 7505 /** enforces single constraint for a given LP solution */ 7506 SCIP_RETCODE SCIPconsEnfolp( 7507 SCIP_CONS* cons, /**< constraint to enforce */ 7508 SCIP_SET* set, /**< global SCIP settings */ 7509 SCIP_Bool solinfeasible, /**< was the solution already declared infeasible by a constraint handler? */ 7510 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7511 ) 7512 { 7513 SCIP_CONSHDLR* conshdlr; 7514 7515 assert(cons != NULL); 7516 assert(set != NULL); 7517 assert(cons->scip == set->scip); 7518 assert(result != NULL); 7519 7520 conshdlr = cons->conshdlr; 7521 assert(conshdlr != NULL); 7522 7523 /* call external method */ 7524 assert(conshdlr->consenfolp != NULL); 7525 7526 SCIP_CALL( conshdlr->consenfolp(set->scip, conshdlr, &cons, 1, 1, solinfeasible, result) ); 7527 SCIPsetDebugMsg(set, " -> enfolp returned result <%d>\n", *result); 7528 7529 if( *result != SCIP_CUTOFF 7530 && *result != SCIP_CONSADDED 7531 && *result != SCIP_REDUCEDDOM 7532 && *result != SCIP_BRANCHED 7533 && *result != SCIP_SEPARATED 7534 && *result != SCIP_INFEASIBLE 7535 && *result != SCIP_FEASIBLE) 7536 { 7537 SCIPerrorMessage("enforcing method of constraint handler <%s> for LP returned invalid result <%d>\n", 7538 conshdlr->name, *result); 7539 return SCIP_INVALIDRESULT; 7540 } 7541 7542 /* do not update statistics */ 7543 7544 return SCIP_OKAY; 7545 } 7546 7547 /** enforces single constraint for a given relaxation solution */ 7548 SCIP_RETCODE SCIPconsEnforelax( 7549 SCIP_CONS* cons, /**< constraint to enforce */ 7550 SCIP_SET* set, /**< global SCIP settings */ 7551 SCIP_SOL* sol, /**< solution to be enforced */ 7552 SCIP_Bool solinfeasible, /**< was the solution already declared infeasible by a constraint handler? */ 7553 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7554 ) 7555 { 7556 SCIP_CONSHDLR* conshdlr; 7557 7558 assert(cons != NULL); 7559 assert(set != NULL); 7560 assert(cons->scip == set->scip); 7561 assert(sol != NULL); 7562 assert(result != NULL); 7563 7564 conshdlr = cons->conshdlr; 7565 assert(conshdlr != NULL); 7566 7567 /* call external method */ 7568 assert(conshdlr->consenfolp != NULL); 7569 7570 SCIP_CALL( conshdlr->consenforelax(set->scip, sol, conshdlr, &cons, 1, 1, solinfeasible, result) ); 7571 SCIPdebugMessage(" -> enforelax returned result <%d>\n", *result); 7572 7573 if( *result != SCIP_CUTOFF 7574 && *result != SCIP_CONSADDED 7575 && *result != SCIP_REDUCEDDOM 7576 && *result != SCIP_BRANCHED 7577 && *result != SCIP_SEPARATED 7578 && *result != SCIP_INFEASIBLE 7579 && *result != SCIP_FEASIBLE) 7580 { 7581 SCIPerrorMessage("enforcing method of constraint handler <%s> for relaxation returned invalid result <%d>\n", 7582 conshdlr->name, *result); 7583 return SCIP_INVALIDRESULT; 7584 } 7585 7586 /* do not update statistics */ 7587 7588 return SCIP_OKAY; 7589 } 7590 7591 /** calls LP initialization method for single constraint */ 7592 SCIP_RETCODE SCIPconsInitlp( 7593 SCIP_CONS* cons, /**< constraint to initialize */ 7594 SCIP_SET* set, /**< global SCIP settings */ 7595 SCIP_Bool* infeasible /**< pointer to store whether infeasibility was detected while building the LP */ 7596 ) 7597 { 7598 SCIP_CONSHDLR* conshdlr; 7599 7600 assert(cons != NULL); 7601 assert(set != NULL); 7602 assert(infeasible != NULL); 7603 assert(cons->scip == set->scip); 7604 7605 conshdlr = cons->conshdlr; 7606 assert(conshdlr != NULL); 7607 7608 /* call external method */ 7609 if( conshdlr->consinitlp != NULL ) 7610 { 7611 SCIP_CALL( conshdlr->consinitlp(set->scip, conshdlr, &cons, 1, infeasible) ); 7612 } 7613 7614 return SCIP_OKAY; 7615 } 7616 7617 /** calls separation method of single constraint for LP solution */ 7618 SCIP_RETCODE SCIPconsSepalp( 7619 SCIP_CONS* cons, /**< constraint to separate */ 7620 SCIP_SET* set, /**< global SCIP settings */ 7621 SCIP_RESULT* result /**< pointer to store the result of the separation call */ 7622 ) 7623 { 7624 SCIP_CONSHDLR* conshdlr; 7625 7626 assert(cons != NULL); 7627 assert(set != NULL); 7628 assert(cons->scip == set->scip); 7629 assert(result != NULL); 7630 7631 conshdlr = cons->conshdlr; 7632 assert(conshdlr != NULL); 7633 7634 /* call external method */ 7635 if( conshdlr->conssepalp != NULL ) 7636 { 7637 SCIP_CALL( conshdlr->conssepalp(set->scip, conshdlr, &cons, 1, 1, result) ); 7638 SCIPsetDebugMsg(set, " -> sepalp returned result <%d>\n", *result); 7639 7640 if( *result != SCIP_CUTOFF 7641 && *result != SCIP_CONSADDED 7642 && *result != SCIP_REDUCEDDOM 7643 && *result != SCIP_SEPARATED 7644 && *result != SCIP_NEWROUND 7645 && *result != SCIP_DIDNOTFIND 7646 && *result != SCIP_DIDNOTRUN 7647 && *result != SCIP_DELAYED ) 7648 { 7649 SCIPerrorMessage("separation method of constraint handler <%s> returned invalid result <%d>\n", conshdlr->name, 7650 *result); 7651 return SCIP_INVALIDRESULT; 7652 } 7653 } 7654 7655 return SCIP_OKAY; 7656 } 7657 7658 /** calls separation method of single constraint for given primal solution */ 7659 SCIP_RETCODE SCIPconsSepasol( 7660 SCIP_CONS* cons, /**< constraint to separate */ 7661 SCIP_SET* set, /**< global SCIP settings */ 7662 SCIP_SOL* sol, /**< primal solution that should be separated */ 7663 SCIP_RESULT* result /**< pointer to store the result of the separation call */ 7664 ) 7665 { 7666 SCIP_CONSHDLR* conshdlr; 7667 7668 assert(cons != NULL); 7669 assert(set != NULL); 7670 assert(cons->scip == set->scip); 7671 assert(sol != NULL); 7672 assert(result != NULL); 7673 7674 conshdlr = cons->conshdlr; 7675 assert(conshdlr != NULL); 7676 7677 /* call external method */ 7678 if( conshdlr->conssepasol != NULL ) 7679 { 7680 SCIP_CALL( conshdlr->conssepasol(set->scip, conshdlr, &cons, 1, 1, sol, result) ); 7681 SCIPsetDebugMsg(set, " -> sepasol returned result <%d>\n", *result); 7682 7683 if( *result != SCIP_CUTOFF 7684 && *result != SCIP_CONSADDED 7685 && *result != SCIP_REDUCEDDOM 7686 && *result != SCIP_SEPARATED 7687 && *result != SCIP_NEWROUND 7688 && *result != SCIP_DIDNOTFIND 7689 && *result != SCIP_DIDNOTRUN 7690 && *result != SCIP_DELAYED ) 7691 { 7692 SCIPerrorMessage("separation method of constraint handler for arbitrary primal solution <%s> returned invalid result <%d>\n", 7693 conshdlr->name, *result); 7694 return SCIP_INVALIDRESULT; 7695 } 7696 } 7697 7698 return SCIP_OKAY; 7699 } 7700 7701 /** calls domain propagation method of single constraint */ 7702 SCIP_RETCODE SCIPconsProp( 7703 SCIP_CONS* cons, /**< constraint to propagate */ 7704 SCIP_SET* set, /**< global SCIP settings */ 7705 SCIP_PROPTIMING proptiming, /**< current point in the node solving loop */ 7706 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7707 ) 7708 { 7709 SCIP_CONSHDLR* conshdlr; 7710 7711 assert(cons != NULL); 7712 assert(set != NULL); 7713 assert(cons->scip == set->scip); 7714 assert(result != NULL); 7715 7716 conshdlr = cons->conshdlr; 7717 assert(conshdlr != NULL); 7718 7719 /* call external method */ 7720 if( conshdlr->consprop != NULL ) 7721 { 7722 SCIP_CALL( conshdlr->consprop(set->scip, conshdlr, &cons, 1, 1, 1, proptiming, result) ); 7723 SCIPsetDebugMsg(set, " -> prop returned result <%d>\n", *result); 7724 7725 if( *result != SCIP_CUTOFF 7726 && *result != SCIP_CONSADDED 7727 && *result != SCIP_REDUCEDDOM 7728 && *result != SCIP_DIDNOTFIND 7729 && *result != SCIP_DIDNOTRUN 7730 && *result != SCIP_DELAYED ) 7731 { 7732 SCIPerrorMessage("propagation method of constraint handler <%s> returned invalid result <%d>\n", 7733 conshdlr->name, *result); 7734 return SCIP_INVALIDRESULT; 7735 } 7736 } 7737 7738 return SCIP_OKAY; 7739 } 7740 7741 /** resolves propagation conflict of single constraint */ 7742 SCIP_RETCODE SCIPconsResprop( 7743 SCIP_CONS* cons, /**< constraint to resolve conflict for */ 7744 SCIP_SET* set, /**< global SCIP settings */ 7745 SCIP_VAR* infervar, /**< the conflict variable whose bound change has to be resolved */ 7746 int inferinfo, /**< the user information passed to the corresponding SCIPinferVarLbCons() or SCIPinferVarUbCons() call */ 7747 SCIP_BOUNDTYPE boundtype, /**< the type of the changed bound (lower or upper bound) */ 7748 SCIP_BDCHGIDX* bdchgidx, /**< the index of the bound change, representing the point of time where the change took place */ 7749 SCIP_Real relaxedbd, /**< the relaxed bound which is sufficient to be explained */ 7750 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7751 ) 7752 { 7753 SCIP_CONSHDLR* conshdlr; 7754 7755 assert(cons != NULL); 7756 assert(set != NULL); 7757 assert(cons->scip == set->scip); 7758 assert(result != NULL); 7759 assert(infervar != NULL); 7760 assert(bdchgidx != NULL); 7761 7762 conshdlr = cons->conshdlr; 7763 assert(conshdlr != NULL); 7764 7765 /* call external method */ 7766 if( conshdlr->consresprop != NULL ) 7767 { 7768 SCIP_CALL( conshdlr->consresprop(set->scip, conshdlr, cons, infervar, inferinfo, boundtype, bdchgidx, relaxedbd, result) ); 7769 SCIPsetDebugMsg(set, " -> resprop returned result <%d>\n", *result); 7770 7771 if( *result != SCIP_SUCCESS 7772 && *result != SCIP_DIDNOTFIND ) 7773 { 7774 SCIPerrorMessage("propagation conflict resolving method of constraint handler <%s> returned invalid result <%d>\n", 7775 conshdlr->name, *result); 7776 return SCIP_INVALIDRESULT; 7777 } 7778 } 7779 7780 return SCIP_OKAY; 7781 } 7782 7783 /** presolves single constraint */ 7784 SCIP_RETCODE SCIPconsPresol( 7785 SCIP_CONS* cons, /**< constraint to presolve */ 7786 SCIP_SET* set, /**< global SCIP settings */ 7787 int nrounds, /**< number of presolving rounds already done */ 7788 SCIP_PRESOLTIMING timing, /**< current presolving timing */ 7789 int nnewfixedvars, /**< number of variables fixed since the last call to the presolving method */ 7790 int nnewaggrvars, /**< number of variables aggregated since the last call to the presolving method */ 7791 int nnewchgvartypes, /**< number of variable type changes since the last call to the presolving method */ 7792 int nnewchgbds, /**< number of variable bounds tightened since the last call to the presolving method */ 7793 int nnewholes, /**< number of domain holes added since the last call to the presolving method */ 7794 int nnewdelconss, /**< number of deleted constraints since the last call to the presolving method */ 7795 int nnewaddconss, /**< number of added constraints since the last call to the presolving method */ 7796 int nnewupgdconss, /**< number of upgraded constraints since the last call to the presolving method */ 7797 int nnewchgcoefs, /**< number of changed coefficients since the last call to the presolving method */ 7798 int nnewchgsides, /**< number of changed left or right hand sides since the last call to the presolving method */ 7799 int* nfixedvars, /**< pointer to count total number of variables fixed of all presolvers */ 7800 int* naggrvars, /**< pointer to count total number of variables aggregated of all presolvers */ 7801 int* nchgvartypes, /**< pointer to count total number of variable type changes of all presolvers */ 7802 int* nchgbds, /**< pointer to count total number of variable bounds tightened of all presolvers */ 7803 int* naddholes, /**< pointer to count total number of domain holes added of all presolvers */ 7804 int* ndelconss, /**< pointer to count total number of deleted constraints of all presolvers */ 7805 int* naddconss, /**< pointer to count total number of added constraints of all presolvers */ 7806 int* nupgdconss, /**< pointer to count total number of upgraded constraints of all presolvers */ 7807 int* nchgcoefs, /**< pointer to count total number of changed coefficients of all presolvers */ 7808 int* nchgsides, /**< pointer to count total number of changed left/right hand sides of all presolvers */ 7809 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 7810 ) 7811 { 7812 SCIP_CONSHDLR* conshdlr; 7813 7814 assert(cons != NULL); 7815 assert(set != NULL); 7816 assert(cons->scip == set->scip); 7817 assert(nfixedvars != NULL); 7818 assert(naggrvars != NULL); 7819 assert(nchgvartypes != NULL); 7820 assert(nchgbds != NULL); 7821 assert(naddholes != NULL); 7822 assert(ndelconss != NULL); 7823 assert(naddconss != NULL); 7824 assert(nupgdconss != NULL); 7825 assert(nchgcoefs != NULL); 7826 assert(nchgsides != NULL); 7827 assert(result != NULL); 7828 7829 conshdlr = cons->conshdlr; 7830 assert(conshdlr != NULL); 7831 7832 /* call external method */ 7833 if( conshdlr->conspresol != NULL ) 7834 { 7835 SCIP_CALL( conshdlr->conspresol(set->scip, conshdlr, &cons, 1, nrounds, timing, 7836 nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewholes, nnewdelconss, nnewaddconss, 7837 nnewupgdconss, nnewchgcoefs, nnewchgsides, nfixedvars, naggrvars, nchgvartypes, 7838 nchgbds, naddholes, ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) ); 7839 SCIPsetDebugMsg(set, " -> presol returned result <%d>\n", *result); 7840 7841 if( *result != SCIP_UNBOUNDED 7842 && *result != SCIP_CUTOFF 7843 && *result != SCIP_SUCCESS 7844 && *result != SCIP_DIDNOTFIND 7845 && *result != SCIP_DIDNOTRUN 7846 && *result != SCIP_DELAYED ) 7847 { 7848 SCIPerrorMessage("presolving method of constraint handler <%s> returned invalid result <%d>\n", 7849 conshdlr->name, *result); 7850 return SCIP_INVALIDRESULT; 7851 } 7852 } 7853 7854 return SCIP_OKAY; 7855 } 7856 7857 /** calls constraint activation notification method of single constraint */ 7858 SCIP_RETCODE SCIPconsActive( 7859 SCIP_CONS* cons, /**< constraint to notify */ 7860 SCIP_SET* set /**< global SCIP settings */ 7861 ) 7862 { 7863 SCIP_CONSHDLR* conshdlr; 7864 7865 assert(cons != NULL); 7866 assert(set != NULL); 7867 assert(cons->scip == set->scip); 7868 7869 conshdlr = cons->conshdlr; 7870 assert(conshdlr != NULL); 7871 7872 /* call external method */ 7873 if( conshdlr->consactive != NULL ) 7874 { 7875 SCIP_CALL( conshdlr->consactive(set->scip, conshdlr, cons) ); 7876 } 7877 7878 return SCIP_OKAY; 7879 } 7880 7881 /** calls constraint deactivation notification method of single constraint */ 7882 SCIP_RETCODE SCIPconsDeactive( 7883 SCIP_CONS* cons, /**< constraint to notify */ 7884 SCIP_SET* set /**< global SCIP settings */ 7885 ) 7886 { 7887 SCIP_CONSHDLR* conshdlr; 7888 7889 assert(cons != NULL); 7890 assert(set != NULL); 7891 assert(cons->scip == set->scip); 7892 7893 conshdlr = cons->conshdlr; 7894 assert(conshdlr != NULL); 7895 7896 /* call external method */ 7897 if( conshdlr->consdeactive != NULL ) 7898 { 7899 SCIP_CALL( conshdlr->consdeactive(set->scip, conshdlr, cons) ); 7900 } 7901 7902 return SCIP_OKAY; 7903 } 7904 7905 7906 7907 /* 7908 * Hash functions 7909 */ 7910 7911 /** gets the key (i.e. the name) of the given constraint */ 7912 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyCons) 7913 { /*lint --e{715}*/ 7914 SCIP_CONS* cons = (SCIP_CONS*)elem; 7915 7916 assert(cons != NULL); 7917 return cons->name; 7918 } 7919 7920 7921 /* 7922 * method for arrays of contraint handlers 7923 */ 7924 7925 /** ensures size of storage for propagable constraints with a minimum size of num */ 7926 static 7927 SCIP_RETCODE ensurePropagationStorage( 7928 SCIP_SET* set, /**< global SCIP settings */ 7929 SCIP_CONSHDLR* conshdlr, /**< constraint handler */ 7930 int num /**< minimum number of entries to store */ 7931 ) 7932 { 7933 assert(set != NULL); 7934 assert(conshdlr != NULL); 7935 7936 if( num > conshdlr->storedpropconsssize ) 7937 { 7938 int newsize; 7939 7940 newsize = SCIPsetCalcMemGrowSize(set, num); 7941 SCIP_ALLOC( BMSreallocMemoryArray(&(conshdlr->storedpropconss), newsize) ); 7942 7943 conshdlr->storedpropconsssize = newsize; 7944 } 7945 assert(num <= conshdlr->storedpropconsssize); 7946 7947 return SCIP_OKAY; 7948 } 7949 7950 /** stores all constraints marked for propagation away when probing is started */ 7951 SCIP_RETCODE SCIPconshdlrsStorePropagationStatus( 7952 SCIP_SET* set, /**< global SCIP settings */ 7953 SCIP_CONSHDLR** conshdlrs, /**< all constraint handlers */ 7954 int nconshdlrs /**< number of contraint handlers */ 7955 ) 7956 { 7957 SCIP_CONSHDLR* conshdlr; 7958 int c; 7959 7960 assert(set != NULL); 7961 assert(conshdlrs != NULL || nconshdlrs == 0); 7962 7963 for( c = nconshdlrs - 1; c >= 0; --c ) 7964 { 7965 conshdlr = conshdlrs[c]; /*lint !e613*/ 7966 assert(conshdlr != NULL); 7967 assert(conshdlr->storednmarkedpropconss == 0); 7968 7969 if( conshdlr->nmarkedpropconss > 0 ) 7970 { 7971 int v; 7972 7973 SCIP_CALL( ensurePropagationStorage(set, conshdlr, conshdlr->nmarkedpropconss) ); 7974 BMScopyMemoryArray(conshdlr->storedpropconss, conshdlr->propconss, conshdlr->nmarkedpropconss); 7975 7976 conshdlr->storednmarkedpropconss = conshdlr->nmarkedpropconss; 7977 conshdlr->storedpropdomchgcount = conshdlr->lastpropdomchgcount; 7978 7979 for( v = conshdlr->storednmarkedpropconss - 1; v >= 0; --v ) 7980 { 7981 SCIPconsCapture(conshdlr->storedpropconss[v]); 7982 } 7983 /* assert(conshdlr->nmarkedpropconss == 0); this assert does not hold if updates are delayed */ 7984 } 7985 } 7986 7987 return SCIP_OKAY; 7988 } 7989 7990 /** reset all constraints marked for propagation when probing was finished */ 7991 SCIP_RETCODE SCIPconshdlrsResetPropagationStatus( 7992 SCIP_SET* set, /**< global SCIP settings */ 7993 BMS_BLKMEM* blkmem, /**< block memory */ 7994 SCIP_CONSHDLR** conshdlrs, /**< all constraint handlers */ 7995 int nconshdlrs /**< number of contraint handlers */ 7996 ) 7997 { 7998 SCIP_CONSHDLR* conshdlr; 7999 int c; 8000 8001 assert(set != NULL); 8002 assert(blkmem != NULL); 8003 assert(conshdlrs != NULL || nconshdlrs == 0); 8004 8005 for( c = nconshdlrs - 1; c >= 0; --c ) 8006 { 8007 conshdlr = conshdlrs[c]; /*lint !e613*/ 8008 assert(conshdlr != NULL); 8009 8010 if( conshdlr->storednmarkedpropconss > 0 ) 8011 { 8012 #ifndef NDEBUG 8013 int ndisabled = 0; 8014 #endif 8015 int v; 8016 8017 for( v = conshdlr->nmarkedpropconss - 1; v >= 0; --v ) 8018 { 8019 SCIP_CALL( SCIPconsUnmarkPropagate(conshdlr->propconss[v], set) ); 8020 } 8021 8022 /* mark all previously marked constraint, which were marked before probing */ 8023 for( v = 0; v < conshdlr->storednmarkedpropconss; ++v ) 8024 { 8025 SCIP_CONS* cons = conshdlr->storedpropconss[v]; 8026 assert(cons != NULL); 8027 8028 if( cons->enabled && cons->propagate && cons->propenabled ) 8029 { 8030 SCIP_CALL( SCIPconsMarkPropagate(cons, set) ); 8031 } 8032 #ifndef NDEBUG 8033 else 8034 ++ndisabled; 8035 #endif 8036 SCIP_CALL( SCIPconsRelease(&cons, blkmem, set) ); 8037 } /*lint !e438*/ 8038 8039 assert(conshdlr->storednmarkedpropconss - ndisabled <= conshdlr->npropconss); 8040 assert(conshdlr->nmarkedpropconss + ndisabled >= conshdlr->storednmarkedpropconss || (conshdlrAreUpdatesDelayed(conshdlr) && conshdlr->nupdateconss + ndisabled >= conshdlr->storednmarkedpropconss)); 8041 8042 conshdlr->lastpropdomchgcount = conshdlr->storedpropdomchgcount; 8043 conshdlr->storednmarkedpropconss = 0; 8044 } 8045 } 8046 8047 return SCIP_OKAY; 8048 } 8049 8050 /** create linear constraint statistics */ 8051 SCIP_RETCODE SCIPlinConsStatsCreate( 8052 SCIP* scip, /**< scip data structure */ 8053 SCIP_LINCONSSTATS** linconsstats /**< pointer to linear constraint classification statistics */ 8054 ) 8055 { 8056 assert(linconsstats != NULL); 8057 8058 SCIP_CALL( SCIPallocBlockMemory(scip, linconsstats) ); 8059 8060 return SCIP_OKAY; 8061 } 8062 8063 /** free linear constraint statistics */ 8064 void SCIPlinConsStatsFree( 8065 SCIP* scip, /**< scip data structure */ 8066 SCIP_LINCONSSTATS** linconsstats /**< pointer to linear constraint classification statistics */ 8067 ) 8068 { 8069 assert(linconsstats != NULL); 8070 assert(*linconsstats != NULL); 8071 8072 SCIPfreeBlockMemory(scip, linconsstats); 8073 } 8074 8075 /** resets linear constraint statistics */ 8076 void SCIPlinConsStatsReset( 8077 SCIP_LINCONSSTATS* linconsstats /**< linear constraint classification statistics */ 8078 ) 8079 { 8080 BMSclearMemoryArray(linconsstats->counter, SCIP_NLINCONSTYPES); 8081 linconsstats->sum = 0; 8082 } 8083 8084 /** returns the number of occurrences of a specific type of linear constraint */ 8085 int SCIPlinConsStatsGetTypeCount( 8086 SCIP_LINCONSSTATS* linconsstats, /**< linear constraint classification statistics */ 8087 SCIP_LINCONSTYPE linconstype /**< linear constraint type */ 8088 ) 8089 { 8090 assert(linconsstats != NULL); 8091 assert(0 <= (int)linconstype && (int)linconstype < SCIP_NLINCONSTYPES); /*lint !e587 !e685 !e568*/ 8092 assert(linconsstats->counter != NULL); 8093 8094 return linconsstats->counter[(int)linconstype]; 8095 } 8096 8097 /** returns the total number of classified constraints */ 8098 int SCIPlinConsStatsGetSum( 8099 SCIP_LINCONSSTATS* linconsstats /**< linear constraint classification statistics */ 8100 ) 8101 { 8102 assert(linconsstats != NULL); 8103 8104 return linconsstats->sum; 8105 } 8106 8107 /** increases the number of occurrences of a specific type of linear constraint */ 8108 void SCIPlinConsStatsIncTypeCount( 8109 SCIP_LINCONSSTATS* linconsstats, /**< linear constraint classification statistics */ 8110 SCIP_LINCONSTYPE linconstype, /**< linear constraint type */ 8111 int increment /**< positive increment */ 8112 ) 8113 { 8114 assert(linconsstats != NULL); 8115 assert(increment >= 1); 8116 assert(0 <= (int)linconstype && (int)linconstype < SCIP_NLINCONSTYPES); /*lint !e587 !e685 !e568*/ 8117 assert(linconsstats->counter != NULL); 8118 8119 linconsstats->counter[(int)linconstype] += increment; 8120 linconsstats->sum += increment; 8121 } 8122 8123 /** print linear constraint classification statistics */ 8124 void SCIPprintLinConsStats( 8125 SCIP* scip, /**< scip data structure */ 8126 FILE* file, /**< file handle or NULL to print to standard out */ 8127 SCIP_LINCONSSTATS* linconsstats /**< linear constraint classification statistics */ 8128 ) 8129 { 8130 assert(scip != NULL); 8131 assert(linconsstats != NULL); 8132 8133 /* print statistics */ 8134 SCIPinfoMessage(scip, file, "\n"); 8135 SCIPinfoMessage(scip, file, "%-19s : %10s\n", "Linear cons types", "count"); 8136 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "total", SCIPlinConsStatsGetSum(linconsstats)); 8137 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "empty", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_EMPTY)); 8138 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "free", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_FREE)); 8139 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "singleton", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SINGLETON)); 8140 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "aggregation", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_AGGREGATION)); 8141 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "precedence", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_PRECEDENCE)); 8142 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "varbound", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_VARBOUND)); 8143 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "setpartition", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPARTITION)); 8144 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "setpacking", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SETPACKING)); 8145 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "setcovering", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_SETCOVERING)); 8146 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "cardinality", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_CARDINALITY)); 8147 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "invknapsack", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_INVKNAPSACK)); 8148 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "eqknapsack", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_EQKNAPSACK)); 8149 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "binpacking", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_BINPACKING)); 8150 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "knapsack", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_KNAPSACK)); 8151 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "intknapsack", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_INTKNAPSACK)); 8152 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "mixedbinary", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_MIXEDBINARY)); 8153 SCIPinfoMessage(scip, file, " %-17s : %10d\n", "general", SCIPlinConsStatsGetTypeCount(linconsstats, SCIP_LINCONSTYPE_GENERAL)); 8154 SCIPinfoMessage(scip, file, "\n"); 8155 } 8156 8157 /* 8158 * simple functions implemented as defines 8159 */ 8160 8161 /* In debug mode, the following methods are implemented as function calls to ensure 8162 * type validity. 8163 * In optimized mode, the methods are implemented as defines to improve performance. 8164 * However, we want to have them in the library anyways, so we have to undef the defines. 8165 */ 8166 8167 #undef SCIPconsGetName 8168 #undef SCIPconsGetPos 8169 #undef SCIPconsGetHdlr 8170 #undef SCIPconsGetData 8171 #undef SCIPconsGetNUses 8172 #undef SCIPconsGetActiveDepth 8173 #undef SCIPconsGetValidDepth 8174 #undef SCIPconsIsActive 8175 #undef SCIPconsIsEnabled 8176 #undef SCIPconsIsSeparationEnabled 8177 #undef SCIPconsIsPropagationEnabled 8178 #undef SCIPconsIsDeleted 8179 #undef SCIPconsIsObsolete 8180 #undef SCIPconsIsConflict 8181 #undef SCIPconsGetAge 8182 #undef SCIPconsIsInitial 8183 #undef SCIPconsIsSeparated 8184 #undef SCIPconsIsEnforced 8185 #undef SCIPconsIsChecked 8186 #undef SCIPconsIsMarkedPropagate 8187 #undef SCIPconsIsPropagated 8188 #undef SCIPconsIsGlobal 8189 #undef SCIPconsIsLocal 8190 #undef SCIPconsIsModifiable 8191 #undef SCIPconsIsDynamic 8192 #undef SCIPconsIsRemovable 8193 #undef SCIPconsIsStickingAtNode 8194 #undef SCIPconsIsInProb 8195 #undef SCIPconsIsOriginal 8196 #undef SCIPconsIsTransformed 8197 #undef SCIPconsIsLockedPos 8198 #undef SCIPconsIsLockedNeg 8199 #undef SCIPconsIsLocked 8200 #undef SCIPconsGetNLocksPos 8201 #undef SCIPconsGetNLocksNeg 8202 #undef SCIPconsIsLockedTypePos 8203 #undef SCIPconsIsLockedTypeNeg 8204 #undef SCIPconsIsLockedType 8205 #undef SCIPconsGetNLocksTypePos 8206 #undef SCIPconsGetNLocksTypeNeg 8207 #undef SCIPconsIsAdded 8208 #undef SCIPconsGetNUpgradeLocks 8209 8210 /** returns the name of the constraint 8211 * 8212 * @note to change the name of a constraint, use SCIPchgConsName() from scip.h 8213 */ 8214 const char* SCIPconsGetName( 8215 SCIP_CONS* cons /**< constraint */ 8216 ) 8217 { 8218 assert(cons != NULL); 8219 8220 return cons->name; 8221 } 8222 8223 /** returns the position of constraint in the corresponding handler's conss array */ 8224 int SCIPconsGetPos( 8225 SCIP_CONS* cons /**< constraint */ 8226 ) 8227 { 8228 assert(cons != NULL); 8229 8230 return cons->consspos; 8231 } 8232 8233 /** returns the constraint handler of the constraint */ 8234 SCIP_CONSHDLR* SCIPconsGetHdlr( 8235 SCIP_CONS* cons /**< constraint */ 8236 ) 8237 { 8238 assert(cons != NULL); 8239 8240 return cons->conshdlr; 8241 } 8242 8243 /** returns the constraint data field of the constraint */ 8244 SCIP_CONSDATA* SCIPconsGetData( 8245 SCIP_CONS* cons /**< constraint */ 8246 ) 8247 { 8248 assert(cons != NULL); 8249 8250 return cons->consdata; 8251 } 8252 8253 /** gets number of times, the constraint is currently captured */ 8254 int SCIPconsGetNUses( 8255 SCIP_CONS* cons /**< constraint */ 8256 ) 8257 { 8258 assert(cons != NULL); 8259 8260 return cons->nuses; 8261 } 8262 8263 /** for an active constraint, returns the depth in the tree at which the constraint was activated */ 8264 int SCIPconsGetActiveDepth( 8265 SCIP_CONS* cons /**< constraint */ 8266 ) 8267 { 8268 assert(cons != NULL); 8269 assert(SCIPconsIsActive(cons)); 8270 8271 return cons->activedepth; 8272 } 8273 8274 /** returns TRUE iff constraint is active in the current node */ 8275 SCIP_Bool SCIPconsIsActive( 8276 SCIP_CONS* cons /**< constraint */ 8277 ) 8278 { 8279 assert(cons != NULL); 8280 8281 return cons->updateactivate || (cons->active && !cons->updatedeactivate); 8282 } 8283 8284 /** returns TRUE iff constraint is active in the current node */ 8285 SCIP_Bool SCIPconsIsUpdatedeactivate( 8286 SCIP_CONS* cons /**< constraint */ 8287 ) 8288 { 8289 assert(cons != NULL); 8290 8291 return cons->updatedeactivate; 8292 } 8293 8294 /** returns the depth in the tree at which the constraint is valid; returns INT_MAX, if the constraint is local 8295 * and currently not active 8296 */ 8297 int SCIPconsGetValidDepth( 8298 SCIP_CONS* cons /**< constraint */ 8299 ) 8300 { 8301 assert(cons != NULL); 8302 assert(cons->validdepth == 0 || cons->local); 8303 8304 return (!cons->local ? 0 8305 : !SCIPconsIsActive(cons) ? INT_MAX 8306 : cons->validdepth == -1 ? SCIPconsGetActiveDepth(cons) 8307 : cons->validdepth); 8308 } 8309 8310 /** returns TRUE iff constraint is enabled in the current node */ 8311 SCIP_Bool SCIPconsIsEnabled( 8312 SCIP_CONS* cons /**< constraint */ 8313 ) 8314 { 8315 assert(cons != NULL); 8316 8317 return cons->updateenable || (cons->enabled && !cons->updatedisable); 8318 } 8319 8320 /** returns TRUE iff constraint's separation is enabled in the current node */ 8321 SCIP_Bool SCIPconsIsSeparationEnabled( 8322 SCIP_CONS* cons /**< constraint */ 8323 ) 8324 { 8325 assert(cons != NULL); 8326 8327 return SCIPconsIsEnabled(cons) 8328 && (cons->updatesepaenable || (cons->sepaenabled && !cons->updatesepadisable)); 8329 } 8330 8331 /** returns TRUE iff constraint's propagation is enabled in the current node */ 8332 SCIP_Bool SCIPconsIsPropagationEnabled( 8333 SCIP_CONS* cons /**< constraint */ 8334 ) 8335 { 8336 assert(cons != NULL); 8337 8338 return SCIPconsIsEnabled(cons) 8339 && (cons->updatepropenable || (cons->propenabled && !cons->updatepropdisable)); 8340 } 8341 8342 /** returns TRUE iff constraint is deleted or marked to be deleted */ 8343 SCIP_Bool SCIPconsIsDeleted( 8344 SCIP_CONS* cons /**< constraint */ 8345 ) 8346 { 8347 assert(cons != NULL); 8348 8349 return cons->deleted; 8350 } 8351 8352 /** returns TRUE iff constraint is marked obsolete */ 8353 SCIP_Bool SCIPconsIsObsolete( 8354 SCIP_CONS* cons /**< constraint */ 8355 ) 8356 { 8357 assert(cons != NULL); 8358 8359 return cons->updateobsolete || cons->obsolete; 8360 } 8361 8362 /** returns TRUE iff constraint is marked as a conflict */ 8363 SCIP_Bool SCIPconsIsConflict( 8364 SCIP_CONS* cons /**< constraint */ 8365 ) 8366 { 8367 assert(cons != NULL); 8368 8369 return cons->conflict; 8370 } 8371 8372 /** gets age of constraint */ 8373 SCIP_Real SCIPconsGetAge( 8374 SCIP_CONS* cons /**< constraint */ 8375 ) 8376 { 8377 assert(cons != NULL); 8378 8379 return cons->age; 8380 } 8381 8382 /** returns TRUE iff the LP relaxation of constraint should be in the initial LP */ 8383 SCIP_Bool SCIPconsIsInitial( 8384 SCIP_CONS* cons /**< constraint */ 8385 ) 8386 { 8387 assert(cons != NULL); 8388 8389 return cons->initial; 8390 } 8391 8392 /** returns TRUE iff constraint should be separated during LP processing */ 8393 SCIP_Bool SCIPconsIsSeparated( 8394 SCIP_CONS* cons /**< constraint */ 8395 ) 8396 { 8397 assert(cons != NULL); 8398 8399 return cons->separate; 8400 } 8401 8402 /** returns TRUE iff constraint should be enforced during node processing */ 8403 SCIP_Bool SCIPconsIsEnforced( 8404 SCIP_CONS* cons /**< constraint */ 8405 ) 8406 { 8407 assert(cons != NULL); 8408 8409 return cons->enforce; 8410 } 8411 8412 /** returns TRUE iff constraint should be checked for feasibility */ 8413 SCIP_Bool SCIPconsIsChecked( 8414 SCIP_CONS* cons /**< constraint */ 8415 ) 8416 { 8417 assert(cons != NULL); 8418 8419 return cons->check; 8420 } 8421 8422 /** returns whether the constraint is marked for propagation */ 8423 SCIP_Bool SCIPconsIsMarkedPropagate( 8424 SCIP_CONS* cons /**< constraint */ 8425 ) 8426 { 8427 assert(cons != NULL); 8428 8429 return (cons->updatemarkpropagate || (cons->markpropagate && !cons->updateunmarkpropagate)); 8430 } 8431 8432 /** returns TRUE iff constraint should be propagated during node processing */ 8433 SCIP_Bool SCIPconsIsPropagated( 8434 SCIP_CONS* cons /**< constraint */ 8435 ) 8436 { 8437 assert(cons != NULL); 8438 8439 return cons->propagate; 8440 } 8441 8442 /** returns TRUE iff constraint is globally valid */ 8443 SCIP_Bool SCIPconsIsGlobal( 8444 SCIP_CONS* cons /**< constraint */ 8445 ) 8446 { 8447 assert(cons != NULL); 8448 8449 return !cons->local; 8450 } 8451 8452 /** returns TRUE iff constraint is only locally valid or not added to any (sub)problem */ 8453 SCIP_Bool SCIPconsIsLocal( 8454 SCIP_CONS* cons /**< constraint */ 8455 ) 8456 { 8457 assert(cons != NULL); 8458 8459 return cons->local; 8460 } 8461 8462 /** returns TRUE iff constraint is modifiable (subject to column generation) */ 8463 SCIP_Bool SCIPconsIsModifiable( 8464 SCIP_CONS* cons /**< constraint */ 8465 ) 8466 { 8467 assert(cons != NULL); 8468 8469 return cons->modifiable; 8470 } 8471 8472 /** returns TRUE iff constraint is subject to aging */ 8473 SCIP_Bool SCIPconsIsDynamic( 8474 SCIP_CONS* cons /**< constraint */ 8475 ) 8476 { 8477 assert(cons != NULL); 8478 8479 return cons->dynamic; 8480 } 8481 8482 /** returns TRUE iff constraint's relaxation should be removed from the LP due to aging or cleanup */ 8483 SCIP_Bool SCIPconsIsRemovable( 8484 SCIP_CONS* cons /**< constraint */ 8485 ) 8486 { 8487 assert(cons != NULL); 8488 8489 return cons->removable; 8490 } 8491 8492 /** returns TRUE iff constraint's relaxation should be removed from the LP due to aging or cleanup */ 8493 SCIP_Bool SCIPconsIsStickingAtNode( 8494 SCIP_CONS* cons /**< constraint */ 8495 ) 8496 { 8497 assert(cons != NULL); 8498 8499 return cons->stickingatnode; 8500 } 8501 8502 /** returns TRUE iff constraint belongs to the global problem */ 8503 SCIP_Bool SCIPconsIsInProb( 8504 SCIP_CONS* cons /**< constraint */ 8505 ) 8506 { 8507 assert(cons != NULL); 8508 8509 return (cons->addconssetchg == NULL && cons->addarraypos >= 0); 8510 } 8511 8512 /** returns TRUE iff constraint is belonging to original space */ 8513 SCIP_Bool SCIPconsIsOriginal( 8514 SCIP_CONS* cons /**< constraint */ 8515 ) 8516 { 8517 assert(cons != NULL); 8518 8519 return cons->original; 8520 } 8521 8522 /** returns TRUE iff constraint is belonging to transformed space */ 8523 SCIP_Bool SCIPconsIsTransformed( 8524 SCIP_CONS* cons /**< constraint */ 8525 ) 8526 { 8527 assert(cons != NULL); 8528 8529 return !cons->original; 8530 } 8531 8532 /** returns TRUE iff roundings for variables in constraint are locked */ 8533 SCIP_Bool SCIPconsIsLockedPos( 8534 SCIP_CONS* cons /**< constraint */ 8535 ) 8536 { 8537 assert(cons != NULL); 8538 8539 return (cons->nlockspos[SCIP_LOCKTYPE_MODEL] > 0); 8540 } 8541 8542 /** returns TRUE iff roundings for variables in constraint's negation are locked */ 8543 SCIP_Bool SCIPconsIsLockedNeg( 8544 SCIP_CONS* cons /**< constraint */ 8545 ) 8546 { 8547 assert(cons != NULL); 8548 8549 return (cons->nlocksneg[SCIP_LOCKTYPE_MODEL] > 0); 8550 } 8551 8552 /** returns TRUE iff roundings for variables in constraint or in constraint's negation are locked */ 8553 SCIP_Bool SCIPconsIsLocked( 8554 SCIP_CONS* cons /**< constraint */ 8555 ) 8556 { 8557 assert(cons != NULL); 8558 8559 return (cons->nlockspos[SCIP_LOCKTYPE_MODEL] > 0 || cons->nlocksneg[SCIP_LOCKTYPE_MODEL] > 0); 8560 } 8561 8562 /** get number of times the roundings for variables in constraint are locked */ 8563 int SCIPconsGetNLocksPos( 8564 SCIP_CONS* cons /**< constraint */ 8565 ) 8566 { 8567 assert(cons != NULL); 8568 8569 return cons->nlockspos[SCIP_LOCKTYPE_MODEL]; 8570 } 8571 8572 /** get number of times the roundings for variables in constraint's negation are locked */ 8573 int SCIPconsGetNLocksNeg( 8574 SCIP_CONS* cons /**< constraint */ 8575 ) 8576 { 8577 assert(cons != NULL); 8578 8579 return cons->nlocksneg[SCIP_LOCKTYPE_MODEL]; 8580 } 8581 8582 /** returns TRUE iff roundings of the given locktype for variables in constraint are locked */ 8583 SCIP_Bool SCIPconsIsLockedTypePos( 8584 SCIP_CONS* cons, /**< constraint */ 8585 SCIP_LOCKTYPE locktype /**< variable lock type */ 8586 ) 8587 { 8588 assert(cons != NULL); 8589 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/ 8590 8591 return (cons->nlockspos[locktype] > 0); 8592 } 8593 8594 /** returns TRUE iff roundings of the given locktype for variables in constraint are locked */ 8595 SCIP_Bool SCIPconsIsLockedTypeNeg( 8596 SCIP_CONS* cons, /**< constraint */ 8597 SCIP_LOCKTYPE locktype /**< variable lock type */ 8598 ) 8599 { 8600 assert(cons != NULL); 8601 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/ 8602 8603 return (cons->nlocksneg[locktype] > 0); 8604 } 8605 8606 /** returns TRUE iff roundings of given locktype for variables in constraint or in constraint's negation are locked */ 8607 SCIP_Bool SCIPconsIsLockedType( 8608 SCIP_CONS* cons, /**< constraint */ 8609 SCIP_LOCKTYPE locktype /**< variable lock type */ 8610 ) 8611 { 8612 assert(cons != NULL); 8613 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/ 8614 8615 return (cons->nlockspos[locktype] > 0 || cons->nlocksneg[locktype] > 0); 8616 } 8617 8618 /** get number of times the roundings of given locktype for variables in constraint are locked */ 8619 int SCIPconsGetNLocksTypePos( 8620 SCIP_CONS* cons, /**< constraint */ 8621 SCIP_LOCKTYPE locktype /**< variable lock type */ 8622 ) 8623 { 8624 assert(cons != NULL); 8625 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/ 8626 8627 return cons->nlockspos[locktype]; 8628 } 8629 8630 /** get number of times the roundings of given locktype for variables in constraint's negation are locked */ 8631 int SCIPconsGetNLocksTypeNeg( 8632 SCIP_CONS* cons, /**< constraint */ 8633 SCIP_LOCKTYPE locktype /**< variable lock type */ 8634 ) 8635 { 8636 assert(cons != NULL); 8637 assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568 !e587 !e650*/ 8638 8639 return cons->nlocksneg[locktype]; 8640 } 8641 8642 /** returns if the constraint was already added to a SCIP instance */ 8643 SCIP_Bool SCIPconsIsAdded( 8644 SCIP_CONS* cons /**< constraint */ 8645 ) 8646 { 8647 assert(cons != NULL); 8648 8649 return (cons->addarraypos >= 0); 8650 } 8651 8652 /** adds locks to (dis-)allow upgrading of constraint */ 8653 void SCIPconsAddUpgradeLocks( 8654 SCIP_CONS* cons, /**< constraint to add locks */ 8655 int nlocks /**< number of locks to add */ 8656 ) 8657 { 8658 assert(cons != NULL); 8659 8660 assert(cons->nupgradelocks < (1 << 28) - nlocks); /*lint !e574*/ 8661 cons->nupgradelocks += (unsigned int) nlocks; 8662 } 8663 8664 /** gets number of locks against upgrading the constraint, 0 means this constraint can be upgraded */ 8665 int SCIPconsGetNUpgradeLocks( 8666 SCIP_CONS* cons /**< constraint */ 8667 ) 8668 { 8669 assert(cons != NULL); 8670 8671 return (int) cons->nupgradelocks; 8672 } 8673