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 relax.c 26 * @ingroup OTHER_CFILES 27 * @brief methods and datastructures for relaxation 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 #include <string.h> 36 37 #include "scip/def.h" 38 #include "scip/set.h" 39 #include "scip/tree.h" 40 #include "scip/stat.h" 41 #include "scip/clock.h" 42 #include "scip/paramset.h" 43 #include "scip/scip.h" 44 #include "scip/scip_cut.h" 45 #include "scip/sol.h" 46 #include "scip/var.h" 47 #include "scip/relax.h" 48 #include "scip/pub_message.h" 49 #include "scip/pub_misc.h" 50 51 #include "scip/struct_relax.h" 52 53 54 55 /** compares two relaxation handlers w. r. to their priority */ 56 SCIP_DECL_SORTPTRCOMP(SCIPrelaxComp) 57 { /*lint --e{715}*/ 58 return ((SCIP_RELAX*)elem2)->priority - ((SCIP_RELAX*)elem1)->priority; 59 } 60 61 /** comparison method for sorting relaxators w.r.t. to their name */ 62 SCIP_DECL_SORTPTRCOMP(SCIPrelaxCompName) 63 { 64 return strcmp(SCIPrelaxGetName((SCIP_RELAX*)elem1), SCIPrelaxGetName((SCIP_RELAX*)elem2)); 65 } 66 67 /** method to call, when the priority of a relaxation handler was changed */ 68 static 69 SCIP_DECL_PARAMCHGD(paramChgdRelaxPriority) 70 { /*lint --e{715}*/ 71 SCIP_PARAMDATA* paramdata; 72 73 paramdata = SCIPparamGetData(param); 74 assert(paramdata != NULL); 75 76 /* use SCIPsetRelaxPriority() to mark the relaxs unsorted */ 77 SCIP_CALL( SCIPsetRelaxPriority(scip, (SCIP_RELAX*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/ 78 79 return SCIP_OKAY; 80 } 81 82 /** copies the given relaxation handler to a new scip */ 83 SCIP_RETCODE SCIPrelaxCopyInclude( 84 SCIP_RELAX* relax, /**< relaxation handler */ 85 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ 86 ) 87 { 88 assert(relax != NULL); 89 assert(set != NULL); 90 assert(set->scip != NULL); 91 92 if( relax->relaxcopy != NULL ) 93 { 94 SCIPsetDebugMsg(set, "including relaxation handler %s in subscip %p\n", SCIPrelaxGetName(relax), (void*)set->scip); 95 SCIP_CALL( relax->relaxcopy(set->scip, relax) ); 96 } 97 return SCIP_OKAY; 98 } 99 100 /** internal method for creating a relaxation handler */ 101 static 102 SCIP_RETCODE doRelaxCreate( 103 SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */ 104 SCIP_SET* set, /**< global SCIP settings */ 105 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 106 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 107 const char* name, /**< name of relaxation handler */ 108 const char* desc, /**< description of relaxation handler */ 109 int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */ 110 int freq, /**< frequency for calling relaxation handler */ 111 SCIP_DECL_RELAXCOPY ((*relaxcopy)), /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 112 SCIP_DECL_RELAXFREE ((*relaxfree)), /**< destructor of relaxation handler */ 113 SCIP_DECL_RELAXINIT ((*relaxinit)), /**< initialize relaxation handler */ 114 SCIP_DECL_RELAXEXIT ((*relaxexit)), /**< deinitialize relaxation handler */ 115 SCIP_DECL_RELAXINITSOL((*relaxinitsol)), /**< solving process initialization method of relaxation handler */ 116 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), /**< solving process deinitialization method of relaxation handler */ 117 SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */ 118 SCIP_RELAXDATA* relaxdata /**< relaxation handler data */ 119 ) 120 { 121 char paramname[SCIP_MAXSTRLEN]; 122 char paramdesc[SCIP_MAXSTRLEN]; 123 124 assert(relax != NULL); 125 assert(name != NULL); 126 assert(desc != NULL); 127 assert(freq >= -1); 128 assert(relaxexec != NULL); 129 130 SCIP_ALLOC( BMSallocMemory(relax) ); 131 BMSclearMemory(*relax); 132 133 SCIP_ALLOC( BMSduplicateMemoryArray(&(*relax)->name, name, strlen(name)+1) ); 134 SCIP_ALLOC( BMSduplicateMemoryArray(&(*relax)->desc, desc, strlen(desc)+1) ); 135 (*relax)->priority = priority; 136 (*relax)->freq = freq; 137 (*relax)->relaxcopy = relaxcopy; 138 (*relax)->relaxfree = relaxfree; 139 (*relax)->relaxinit = relaxinit; 140 (*relax)->relaxexit = relaxexit; 141 (*relax)->relaxinitsol = relaxinitsol; 142 (*relax)->relaxexitsol = relaxexitsol; 143 (*relax)->relaxexec = relaxexec; 144 (*relax)->relaxdata = relaxdata; 145 SCIP_CALL( SCIPclockCreate(&(*relax)->setuptime, SCIP_CLOCKTYPE_DEFAULT) ); 146 SCIP_CALL( SCIPclockCreate(&(*relax)->relaxclock, SCIP_CLOCKTYPE_DEFAULT) ); 147 (*relax)->ncalls = 0; 148 (*relax)->ncutoffs = 0; 149 (*relax)->nimprbounds = 0; 150 (*relax)->imprtime = 0.0; 151 (*relax)->naddedconss = 0; 152 (*relax)->nreduceddom = 0; 153 (*relax)->nseparated = 0; 154 (*relax)->lastsolvednode = -1; 155 (*relax)->initialized = FALSE; 156 157 /* add parameters */ 158 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "relaxing/%s/priority", name); 159 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of relaxation handler <%s>", name); 160 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 161 &(*relax)->priority, FALSE, priority, INT_MIN/4, INT_MAX/4, 162 paramChgdRelaxPriority, (SCIP_PARAMDATA*)(*relax)) ); /*lint !e740*/ 163 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "relaxing/%s/freq", name); 164 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "frequency for calling relaxation handler <%s> (-1: never, 0: only in root node)", name); 165 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 166 &(*relax)->freq, FALSE, freq, -1, SCIP_MAXTREEDEPTH, NULL, NULL) ); 167 168 return SCIP_OKAY; 169 } 170 171 /** creates a relaxation handler */ 172 SCIP_RETCODE SCIPrelaxCreate( 173 SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */ 174 SCIP_SET* set, /**< global SCIP settings */ 175 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 176 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 177 const char* name, /**< name of relaxation handler */ 178 const char* desc, /**< description of relaxation handler */ 179 int priority, /**< priority of the relaxation handler (negative: after LP, non-negative: before LP) */ 180 int freq, /**< frequency for calling relaxation handler */ 181 SCIP_DECL_RELAXCOPY ((*relaxcopy)), /**< copy method of relaxation handler or NULL if you don't want to copy your plugin into sub-SCIPs */ 182 SCIP_DECL_RELAXFREE ((*relaxfree)), /**< destructor of relaxation handler */ 183 SCIP_DECL_RELAXINIT ((*relaxinit)), /**< initialize relaxation handler */ 184 SCIP_DECL_RELAXEXIT ((*relaxexit)), /**< deinitialize relaxation handler */ 185 SCIP_DECL_RELAXINITSOL((*relaxinitsol)), /**< solving process initialization method of relaxation handler */ 186 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)), /**< solving process deinitialization method of relaxation handler */ 187 SCIP_DECL_RELAXEXEC ((*relaxexec)), /**< execution method of relaxation handler */ 188 SCIP_RELAXDATA* relaxdata /**< relaxation handler data */ 189 ) 190 { 191 assert(relax != NULL); 192 assert(name != NULL); 193 assert(desc != NULL); 194 assert(freq >= -1); 195 assert(relaxexec != NULL); 196 197 SCIP_CALL_FINALLY( doRelaxCreate(relax, set, messagehdlr, blkmem, name, desc, priority, freq, relaxcopy, relaxfree, 198 relaxinit, relaxexit, relaxinitsol, relaxexitsol, relaxexec, relaxdata), (void) SCIPrelaxFree(relax, set) ); 199 200 return SCIP_OKAY; 201 } 202 203 /** calls destructor and frees memory of relaxation handler */ 204 SCIP_RETCODE SCIPrelaxFree( 205 SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */ 206 SCIP_SET* set /**< global SCIP settings */ 207 ) 208 { 209 assert(relax != NULL); 210 if( *relax == NULL ) 211 return SCIP_OKAY; 212 assert(!(*relax)->initialized); 213 assert(set != NULL); 214 215 /* call destructor of relaxation handler */ 216 if( (*relax)->relaxfree != NULL ) 217 { 218 SCIP_CALL( (*relax)->relaxfree(set->scip, *relax) ); 219 } 220 221 SCIPclockFree(&(*relax)->relaxclock); 222 SCIPclockFree(&(*relax)->setuptime); 223 BMSfreeMemoryArrayNull(&(*relax)->name); 224 BMSfreeMemoryArrayNull(&(*relax)->desc); 225 BMSfreeMemory(relax); 226 227 return SCIP_OKAY; 228 } 229 230 /** initializes relaxation handler */ 231 SCIP_RETCODE SCIPrelaxInit( 232 SCIP_RELAX* relax, /**< relaxation handler */ 233 SCIP_SET* set /**< global SCIP settings */ 234 ) 235 { 236 assert(relax != NULL); 237 assert(set != NULL); 238 239 if( relax->initialized ) 240 { 241 SCIPerrorMessage("relaxation handler <%s> already initialized\n", relax->name); 242 return SCIP_INVALIDCALL; 243 } 244 245 if( set->misc_resetstat ) 246 { 247 SCIPclockReset(relax->setuptime); 248 SCIPclockReset(relax->relaxclock); 249 relax->ncalls = 0; 250 relax->ncutoffs = 0; 251 relax->nimprbounds = 0; 252 relax->imprtime = 0.0; 253 relax->naddedconss = 0; 254 relax->nreduceddom = 0; 255 relax->nseparated = 0; 256 relax->lastsolvednode = -1; 257 } 258 259 if( relax->relaxinit != NULL ) 260 { 261 /* start timing */ 262 SCIPclockStart(relax->setuptime, set); 263 264 SCIP_CALL( relax->relaxinit(set->scip, relax) ); 265 266 /* stop timing */ 267 SCIPclockStop(relax->setuptime, set); 268 } 269 relax->initialized = TRUE; 270 271 return SCIP_OKAY; 272 } 273 274 /** calls exit method of relaxation handler */ 275 SCIP_RETCODE SCIPrelaxExit( 276 SCIP_RELAX* relax, /**< relaxation handler */ 277 SCIP_SET* set /**< global SCIP settings */ 278 ) 279 { 280 assert(relax != NULL); 281 assert(set != NULL); 282 283 if( !relax->initialized ) 284 { 285 SCIPerrorMessage("relaxation handler <%s> not initialized\n", relax->name); 286 return SCIP_INVALIDCALL; 287 } 288 289 if( relax->relaxexit != NULL ) 290 { 291 /* start timing */ 292 SCIPclockStart(relax->setuptime, set); 293 294 SCIP_CALL( relax->relaxexit(set->scip, relax) ); 295 296 /* stop timing */ 297 SCIPclockStop(relax->setuptime, set); 298 } 299 relax->initialized = FALSE; 300 301 return SCIP_OKAY; 302 } 303 304 /** informs relaxation handler that the branch and bound process is being started */ 305 SCIP_RETCODE SCIPrelaxInitsol( 306 SCIP_RELAX* relax, /**< relaxation handler */ 307 SCIP_SET* set /**< global SCIP settings */ 308 ) 309 { 310 assert(relax != NULL); 311 assert(set != NULL); 312 313 /* call solving process initialization method of relaxation handler */ 314 if( relax->relaxinitsol != NULL ) 315 { 316 /* start timing */ 317 SCIPclockStart(relax->setuptime, set); 318 319 SCIP_CALL( relax->relaxinitsol(set->scip, relax) ); 320 321 /* stop timing */ 322 SCIPclockStop(relax->setuptime, set); 323 } 324 325 return SCIP_OKAY; 326 } 327 328 /** informs relaxation handler that the branch and bound process data is being freed */ 329 SCIP_RETCODE SCIPrelaxExitsol( 330 SCIP_RELAX* relax, /**< relaxation handler */ 331 SCIP_SET* set /**< global SCIP settings */ 332 ) 333 { 334 assert(relax != NULL); 335 assert(set != NULL); 336 337 /* call solving process deinitialization method of relaxation handler */ 338 if( relax->relaxexitsol != NULL ) 339 { 340 /* start timing */ 341 SCIPclockStart(relax->setuptime, set); 342 343 SCIP_CALL( relax->relaxexitsol(set->scip, relax) ); 344 345 /* stop timing */ 346 SCIPclockStop(relax->setuptime, set); 347 } 348 349 return SCIP_OKAY; 350 } 351 352 /** calls execution method of relaxation handler */ 353 SCIP_RETCODE SCIPrelaxExec( 354 SCIP_RELAX* relax, /**< relaxation handler */ 355 SCIP_SET* set, /**< global SCIP settings */ 356 SCIP_TREE* tree, /**< branch and bound tree */ 357 SCIP_STAT* stat, /**< dynamic problem statistics */ 358 int depth, /**< depth of current node */ 359 SCIP_Real* lowerbound, /**< pointer to lower bound computed by the relaxation handler */ 360 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 361 ) 362 { 363 assert(relax != NULL); 364 assert(relax->relaxexec != NULL); 365 assert(relax->freq >= -1); 366 assert(set != NULL); 367 assert(set->scip != NULL); 368 assert(depth >= 0); 369 assert(result != NULL); 370 371 *result = SCIP_DIDNOTRUN; 372 373 /* check, if the relaxation is already solved */ 374 if( relax->lastsolvednode == stat->ntotalnodes && ! SCIPinProbing(set->scip) ) 375 return SCIP_OKAY; 376 377 relax->lastsolvednode = stat->ntotalnodes; 378 379 if( (depth == 0 && relax->freq == 0) || (relax->freq > 0 && depth % relax->freq == 0) ) 380 { 381 SCIP_Real starttime; 382 int oldnactiveconss; 383 int oldncuts; 384 385 SCIPsetDebugMsg(set, "executing relaxation handler <%s>\n", relax->name); 386 387 oldnactiveconss = stat->nactiveconss; 388 oldncuts = SCIPgetNCuts(set->scip); 389 390 /* start timing */ 391 starttime = SCIPclockGetTime(relax->relaxclock); 392 SCIPclockStart(relax->relaxclock, set); 393 394 /* call external relaxation method */ 395 SCIP_CALL( relax->relaxexec(set->scip, relax, lowerbound, result) ); 396 397 /* stop timing */ 398 SCIPclockStop(relax->relaxclock, set); 399 400 /* evaluate result */ 401 if( *result != SCIP_CUTOFF 402 && *result != SCIP_CONSADDED 403 && *result != SCIP_REDUCEDDOM 404 && *result != SCIP_SEPARATED 405 && *result != SCIP_SUCCESS 406 && *result != SCIP_SUSPENDED 407 && *result != SCIP_DIDNOTRUN ) 408 { 409 SCIPerrorMessage("execution method of relaxation handler <%s> returned invalid result <%d>\n", 410 relax->name, *result); 411 return SCIP_INVALIDRESULT; 412 } 413 if( *result != SCIP_DIDNOTRUN ) 414 { 415 relax->ncalls++; 416 stat->relaxcount++; 417 if( *result == SCIP_SUSPENDED ) 418 SCIPrelaxMarkUnsolved(relax); 419 else if( *result == SCIP_CUTOFF || SCIPsetIsInfinity(set, *lowerbound) ) 420 { 421 ++relax->ncutoffs; 422 relax->imprtime += SCIPclockGetTime(relax->relaxclock) - starttime; 423 } 424 else 425 { 426 SCIP_NODE* node; 427 SCIP_Real oldlowerbound; 428 429 node = SCIPtreeGetCurrentNode(tree); 430 if( node != NULL ) 431 oldlowerbound = SCIPnodeGetLowerbound(node); 432 else 433 oldlowerbound = -SCIPsetInfinity(set); 434 435 if( !SCIPsetIsInfinity(set, -*lowerbound) && SCIPsetIsRelGT(set, *lowerbound, oldlowerbound) ) 436 { 437 ++relax->nimprbounds; 438 relax->imprtime += SCIPclockGetTime(relax->relaxclock) - starttime; 439 } 440 441 if( stat->nactiveconss > oldnactiveconss ) 442 ++relax->naddedconss; 443 if( SCIPgetNCuts(set->scip) > oldncuts ) 444 ++relax->nseparated; 445 if( *result == SCIP_REDUCEDDOM ) 446 ++relax->nreduceddom; 447 } 448 } 449 } 450 451 return SCIP_OKAY; 452 } 453 454 /** gets user data of relaxation handler */ 455 SCIP_RELAXDATA* SCIPrelaxGetData( 456 SCIP_RELAX* relax /**< relaxation handler */ 457 ) 458 { 459 assert(relax != NULL); 460 461 return relax->relaxdata; 462 } 463 464 /** sets user data of relaxation handler; user has to free old data in advance! */ 465 void SCIPrelaxSetData( 466 SCIP_RELAX* relax, /**< relaxation handler */ 467 SCIP_RELAXDATA* relaxdata /**< new relaxation handler user data */ 468 ) 469 { 470 assert(relax != NULL); 471 472 relax->relaxdata = relaxdata; 473 } 474 475 /** set copy method of relaxation handler */ 476 void SCIPrelaxSetCopy( 477 SCIP_RELAX* relax, /**< relaxation handler */ 478 SCIP_DECL_RELAXCOPY ((*relaxcopy)) /**< copy method of relaxation handler */ 479 ) 480 { 481 assert(relax != NULL); 482 483 relax->relaxcopy = relaxcopy; 484 } 485 486 /** set destructor of relaxation handler */ 487 void SCIPrelaxSetFree( 488 SCIP_RELAX* relax, /**< relaxation handler */ 489 SCIP_DECL_RELAXFREE ((*relaxfree)) /**< destructor of relaxation handler */ 490 ) 491 { 492 assert(relax != NULL); 493 494 relax->relaxfree = relaxfree; 495 } 496 497 /** set initialization method of relaxation handler */ 498 void SCIPrelaxSetInit( 499 SCIP_RELAX* relax, /**< relaxation handler */ 500 SCIP_DECL_RELAXINIT ((*relaxinit)) /**< initialize relaxation handler */ 501 ) 502 { 503 assert(relax != NULL); 504 505 relax->relaxinit = relaxinit; 506 } 507 508 /** set deinitialization method of relaxation handler */ 509 void SCIPrelaxSetExit( 510 SCIP_RELAX* relax, /**< relaxation handler */ 511 SCIP_DECL_RELAXEXIT ((*relaxexit)) /**< deinitialize relaxation handler */ 512 ) 513 { 514 assert(relax != NULL); 515 516 relax->relaxexit = relaxexit; 517 } 518 519 /** set solving process initialization method of relaxation handler */ 520 void SCIPrelaxSetInitsol( 521 SCIP_RELAX* relax, /**< relaxation handler */ 522 SCIP_DECL_RELAXINITSOL((*relaxinitsol)) /**< solving process initialization method of relaxation handler */ 523 ) 524 { 525 assert(relax != NULL); 526 527 relax->relaxinitsol = relaxinitsol; 528 } 529 530 /** set solving process deinitialization method of relaxation handler */ 531 void SCIPrelaxSetExitsol( 532 SCIP_RELAX* relax, /**< relaxation handler */ 533 SCIP_DECL_RELAXEXITSOL((*relaxexitsol)) /**< solving process deinitialization relaxation handler */ 534 ) 535 { 536 assert(relax != NULL); 537 538 relax->relaxexitsol = relaxexitsol; 539 } 540 541 /** gets name of relaxation handler */ 542 const char* SCIPrelaxGetName( 543 SCIP_RELAX* relax /**< relaxation handler */ 544 ) 545 { 546 assert(relax != NULL); 547 548 return relax->name; 549 } 550 551 /** gets description of relaxation handler */ 552 const char* SCIPrelaxGetDesc( 553 SCIP_RELAX* relax /**< relaxation handler */ 554 ) 555 { 556 assert(relax != NULL); 557 558 return relax->desc; 559 } 560 561 /** gets priority of relaxation handler */ 562 int SCIPrelaxGetPriority( 563 SCIP_RELAX* relax /**< relaxation handler */ 564 ) 565 { 566 assert(relax != NULL); 567 568 return relax->priority; 569 } 570 571 /** sets priority of relaxation handler */ 572 void SCIPrelaxSetPriority( 573 SCIP_RELAX* relax, /**< relaxation handler */ 574 SCIP_SET* set, /**< global SCIP settings */ 575 int priority /**< new priority of the relaxation handler */ 576 ) 577 { 578 assert(relax != NULL); 579 assert(set != NULL); 580 581 relax->priority = priority; 582 set->relaxssorted = FALSE; 583 } 584 585 /** gets frequency of relaxation handler */ 586 int SCIPrelaxGetFreq( 587 SCIP_RELAX* relax /**< relaxation handler */ 588 ) 589 { 590 assert(relax != NULL); 591 592 return relax->freq; 593 } 594 595 /** gets time in seconds used in this relaxator for setting up for next stages */ 596 SCIP_Real SCIPrelaxGetSetupTime( 597 SCIP_RELAX* relax /**< relaxator */ 598 ) 599 { 600 assert(relax != NULL); 601 602 return SCIPclockGetTime(relax->setuptime); 603 } 604 605 /** enables or disables all clocks of \p relax, depending on the value of the flag */ 606 void SCIPrelaxEnableOrDisableClocks( 607 SCIP_RELAX* relax, /**< the relaxation handler for which all clocks should be enabled or disabled */ 608 SCIP_Bool enable /**< should the clocks of the relaxation handler be enabled? */ 609 ) 610 { 611 assert(relax != NULL); 612 613 SCIPclockEnableOrDisable(relax->setuptime, enable); 614 SCIPclockEnableOrDisable(relax->relaxclock, enable); 615 } 616 617 /** gets time in seconds used in this relaxation handler */ 618 SCIP_Real SCIPrelaxGetTime( 619 SCIP_RELAX* relax /**< relaxation handler */ 620 ) 621 { 622 assert(relax != NULL); 623 624 return SCIPclockGetTime(relax->relaxclock); 625 } 626 627 /** gets the total number of times the relaxation handler was called */ 628 SCIP_Longint SCIPrelaxGetNCalls( 629 SCIP_RELAX* relax /**< relaxation handler */ 630 ) 631 { 632 assert(relax != NULL); 633 634 return relax->ncalls; 635 } 636 637 /** gets the total number of times the relaxation handler cut off a node */ 638 SCIP_Longint SCIPrelaxGetNCutoffs( 639 SCIP_RELAX* relax /**< relaxation handler */ 640 ) 641 { 642 assert(relax != NULL); 643 644 return relax->ncutoffs; 645 } 646 647 /** gets the total number of times the relaxation handler improved a node's lower bound */ 648 SCIP_Longint SCIPrelaxGetNImprovedLowerbound( 649 SCIP_RELAX* relax /**< relaxation handler */ 650 ) 651 { 652 assert(relax != NULL); 653 654 return relax->nimprbounds; 655 } 656 657 /** gets the total number of times the relaxation handler added constraints */ 658 SCIP_Longint SCIPrelaxGetNAddedConss( 659 SCIP_RELAX* relax /**< relaxation handler */ 660 ) 661 { 662 assert(relax != NULL); 663 664 return relax->naddedconss; 665 } 666 667 /** gets the time in seconds spent for the execution of the relaxation handler when a node's lower bound could be improved (or a cutoff was found) */ 668 SCIP_Real SCIPrelaxGetImprovedLowerboundTime( 669 SCIP_RELAX* relax /**< relaxation handler */ 670 ) 671 { 672 assert(relax != NULL); 673 674 return relax->imprtime; 675 } 676 677 /** gets the total number of times the relaxation handler reduced variable domains */ 678 SCIP_Longint SCIPrelaxGetNReducedDomains( 679 SCIP_RELAX* relax /**< relaxation handler */ 680 ) 681 { 682 assert(relax != NULL); 683 684 return relax->nreduceddom; 685 } 686 687 /** gets the total number of times the relaxation handler separated cutting planes */ 688 SCIP_Longint SCIPrelaxGetNSeparatedCuts( 689 SCIP_RELAX* relax /**< relaxation handler */ 690 ) 691 { 692 assert(relax != NULL); 693 694 return relax->nseparated; 695 } 696 697 /** is relaxation handler initialized? */ 698 SCIP_Bool SCIPrelaxIsInitialized( 699 SCIP_RELAX* relax /**< relaxation handler */ 700 ) 701 { 702 assert(relax != NULL); 703 704 return relax->initialized; 705 } 706 707 /** returns whether the relaxation was completely solved at the current node */ 708 SCIP_Bool SCIPrelaxIsSolved( 709 SCIP_RELAX* relax, /**< relaxation handler */ 710 SCIP_STAT* stat /**< dynamic problem statistics */ 711 ) 712 { 713 assert(relax != NULL); 714 assert(stat != NULL); 715 716 return (relax->lastsolvednode == stat->ntotalnodes); 717 } 718 719 /** marks the current relaxation unsolved, s.t. the relaxation handler is called again in the next solving round */ 720 void SCIPrelaxMarkUnsolved( 721 SCIP_RELAX* relax /**< relaxation handler */ 722 ) 723 { 724 assert(relax != NULL); 725 726 relax->lastsolvednode = -1; 727 } 728 729 /* 730 * methods for the global relaxation data 731 */ 732 733 /** creates global relaxation data */ 734 SCIP_RETCODE SCIPrelaxationCreate( 735 SCIP_RELAXATION** relaxation, /**< global relaxation data */ 736 BMS_BLKMEM* blkmem, /**< block memory */ 737 SCIP_SET* set, /**< global SCIP settings */ 738 SCIP_STAT* stat, /**< problem statistics data */ 739 SCIP_PRIMAL* primal, /**< primal data */ 740 SCIP_TREE* tree /**< branch and bound tree */ 741 ) 742 { 743 assert(relaxation != NULL); 744 assert(blkmem != NULL); 745 assert(set != NULL); 746 assert(stat != NULL); 747 assert(primal != NULL); 748 assert(tree != NULL); 749 750 SCIP_ALLOC( BMSallocMemory(relaxation) ); 751 752 (*relaxation)->relaxsolobjval = 0.0; 753 (*relaxation)->relaxsolvalid = FALSE; 754 (*relaxation)->relaxsolincludeslp = FALSE; 755 (*relaxation)->relaxsolzero = TRUE; 756 (*relaxation)->lastsolrelax = NULL; 757 758 return SCIP_OKAY; 759 } 760 761 /** frees global relaxation data */ 762 SCIP_RETCODE SCIPrelaxationFree( 763 SCIP_RELAXATION** relaxation /**< global relaxation data */ 764 ) 765 { 766 assert(relaxation != NULL); 767 768 BMSfreeMemory(relaxation); 769 770 return SCIP_OKAY; 771 } 772 773 /** sets the relaxsolzero flag in the relaxation data to the given value */ 774 void SCIPrelaxationSetSolZero( 775 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 776 SCIP_Bool iszero /**< are all values of the relaxation solution set to zero? */ 777 ) 778 { 779 assert(relaxation != NULL); 780 781 relaxation->relaxsolzero = iszero; 782 } 783 784 /** returns whether the global relaxation solution is cleared and all values are set to zero */ 785 SCIP_Bool SCIPrelaxationIsSolZero( 786 SCIP_RELAXATION* relaxation /**< global relaxation data */ 787 ) 788 { 789 assert(relaxation != NULL); 790 791 return relaxation->relaxsolzero; 792 } 793 794 /** sets the relaxsolvalid and includeslp flags in the relaxation data to the given values */ 795 void SCIPrelaxationSetSolValid( 796 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 797 SCIP_Bool isvalid, /**< is the stored solution valid? */ 798 SCIP_Bool includeslp /**< does the relaxator contain all cuts in the LP? */ 799 ) 800 { 801 assert(relaxation != NULL); 802 803 relaxation->relaxsolvalid = isvalid; 804 relaxation->relaxsolincludeslp = includeslp; 805 } 806 807 /** returns whether the global relaxation solution is valid */ 808 SCIP_Bool SCIPrelaxationIsSolValid( 809 SCIP_RELAXATION* relaxation /**< global relaxation data */ 810 ) 811 { 812 assert(relaxation != NULL); 813 814 return relaxation->relaxsolvalid; 815 } 816 817 /** returns whether the global relaxation solution was computed by a relaxator which included all LP cuts */ 818 SCIP_Bool SCIPrelaxationIsLpIncludedForSol( 819 SCIP_RELAXATION* relaxation /**< global relaxation data */ 820 ) 821 { 822 assert(relaxation != NULL); 823 824 return relaxation->relaxsolincludeslp; 825 } 826 827 /** sets the objective value of the global relaxation solution */ 828 void SCIPrelaxationSetSolObj( 829 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 830 SCIP_Real obj /**< objective value */ 831 ) 832 { 833 assert(relaxation != NULL); 834 835 relaxation->relaxsolobjval = obj; 836 } 837 838 /** returns the objective value of the global relaxation solution w.r.t. the transformed problem */ 839 SCIP_Real SCIPrelaxationGetSolObj( 840 SCIP_RELAXATION* relaxation /**< global relaxation data */ 841 ) 842 { 843 assert(relaxation != NULL); 844 845 return relaxation->relaxsolobjval; 846 } 847 848 /** adds the given value to the global relaxation solution's objective value */ 849 void SCIPrelaxationSolObjAdd( 850 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 851 SCIP_Real val /**< value to add to the objective value */ 852 ) 853 { 854 assert(relaxation != NULL); 855 856 relaxation->relaxsolobjval += val; 857 } 858 859 /** updates objective value of current relaxation solution after change of objective coefficient */ 860 void SCIPrelaxationUpdateVarObj( 861 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 862 SCIP_SET* set, /**< global SCIP settings */ 863 SCIP_VAR* var, /**< variable with changed objective coefficient */ 864 SCIP_Real oldobj, /**< old objective coefficient */ 865 SCIP_Real newobj /**< new objective coefficient */ 866 ) 867 { 868 SCIP_Real relaxsolval; 869 870 assert(relaxation != NULL); 871 assert(set != NULL); 872 assert(var != NULL); 873 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN); 874 875 relaxsolval = SCIPvarGetRelaxSol(var, set); 876 relaxation->relaxsolobjval += (newobj - oldobj) * relaxsolval; 877 } 878 879 /** store the most recent relaxation handler \p relax responsible for the solution */ 880 void SCIPrelaxationSetSolRelax( 881 SCIP_RELAXATION* relaxation, /**< global relaxation data */ 882 SCIP_RELAX* relax /**< responsible relaxation handler, or NULL */ 883 ) 884 { 885 assert(relaxation != NULL); 886 887 relaxation->lastsolrelax = relax; 888 } 889 890 /** returns the most recent relaxation handler responsible for the solution, or NULL if unspecified */ 891 SCIP_RELAX* SCIPrelaxationGetSolRelax( 892 SCIP_RELAXATION* relaxation /**< global relaxation data */ 893 ) 894 { 895 assert(relaxation != NULL); 896 897 return relaxation->lastsolrelax; 898 } 899