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 benderscut.c 26 * @ingroup OTHER_CFILES 27 * @brief methods for Benders' decomposition cut 28 * @author Stephen J. Maher 29 */ 30 31 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 32 33 #include <assert.h> 34 #include <string.h> 35 36 #include "scip/def.h" 37 #include "scip/set.h" 38 #include "scip/clock.h" 39 #include "scip/paramset.h" 40 #include "scip/scip.h" 41 #include "scip/benderscut.h" 42 #include "scip/reopt.h" 43 #include "scip/pub_message.h" 44 #include "scip/pub_misc.h" 45 #include "scip/pub_benders.h" 46 47 #include "scip/struct_benderscut.h" 48 49 /* default parameter settings for the Benders' decomposition cuts */ 50 #define SCIP_DEFAULT_ENABLED TRUE 51 52 /** compares two Benders' cuts w. r. to their delay positions and their priority */ 53 SCIP_DECL_SORTPTRCOMP(SCIPbenderscutComp) 54 { /*lint --e{715}*/ 55 SCIP_BENDERSCUT* benderscut1 = (SCIP_BENDERSCUT*)elem1; 56 SCIP_BENDERSCUT* benderscut2 = (SCIP_BENDERSCUT*)elem2; 57 58 assert(benderscut1 != NULL); 59 assert(benderscut2 != NULL); 60 61 return benderscut2->priority - benderscut1->priority; /* prefer higher priorities */ 62 } 63 64 /** comparison method for sorting Benders' cuts w.r.t. to their name */ 65 SCIP_DECL_SORTPTRCOMP(SCIPbenderscutCompName) 66 { 67 return strcmp(SCIPbenderscutGetName((SCIP_BENDERSCUT*)elem1), SCIPbenderscutGetName((SCIP_BENDERSCUT*)elem2)); 68 } 69 70 /** method to call, when the priority of a compression was changed */ 71 static 72 SCIP_DECL_PARAMCHGD(paramChgdBenderscutPriority) 73 { /*lint --e{715}*/ 74 SCIP_PARAMDATA* paramdata; 75 76 paramdata = SCIPparamGetData(param); 77 assert(paramdata != NULL); 78 79 /* use SCIPsetBenderscutPriority() to mark the compressions unsorted */ 80 SCIP_CALL( SCIPsetBenderscutPriority(scip, (SCIP_BENDERSCUT*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/ 81 82 return SCIP_OKAY; 83 } 84 85 /** copies the given Benders' decomposition cut to a new scip */ 86 SCIP_RETCODE SCIPbenderscutCopyInclude( 87 SCIP_BENDERS* benders, /**< the Benders' decomposition that the cuts are copied to */ 88 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 89 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ 90 ) 91 { 92 assert(benderscut != NULL); 93 assert(set != NULL); 94 assert(set->scip != NULL); 95 96 if( benderscut->benderscutcopy != NULL ) 97 { 98 SCIPsetDebugMsg(set, "including benderscut %s in subscip %p\n", SCIPbenderscutGetName(benderscut), (void*)set->scip); 99 SCIP_CALL( benderscut->benderscutcopy(set->scip, benders, benderscut) ); 100 } 101 102 return SCIP_OKAY; 103 } 104 105 /** internal method for creating a Benders' decomposition structure */ 106 static 107 SCIP_RETCODE doBenderscutCreate( 108 SCIP_BENDERS* benders, /**< Benders' decomposition */ 109 SCIP_BENDERSCUT** benderscut, /**< pointer to the Benders' decomposition cut data structure */ 110 SCIP_SET* set, /**< global SCIP settings */ 111 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 112 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 113 const char* name, /**< name of the Benders' decomposition cut */ 114 const char* desc, /**< description of the Benders' decomposition cut */ 115 int priority, /**< priority of the the Benders' decomposition cut */ 116 SCIP_Bool islpcut, /**< indicates whether the cut is generated from the LP solution */ 117 SCIP_DECL_BENDERSCUTCOPY((*benderscutcopy)),/**< copy method of the Benders' decomposition cut or NULL if you don't want to copy your plugin into sub-SCIPs */ 118 SCIP_DECL_BENDERSCUTFREE((*benderscutfree)),/**< destructor of the Benders' decomposition cut */ 119 SCIP_DECL_BENDERSCUTINIT((*benderscutinit)),/**< initialize the Benders' decomposition cut */ 120 SCIP_DECL_BENDERSCUTEXIT((*benderscutexit)),/**< deinitialize the Benders' decomposition cut */ 121 SCIP_DECL_BENDERSCUTINITSOL((*benderscutinitsol)),/**< solving process initialization method of the Benders' decomposition cut */ 122 SCIP_DECL_BENDERSCUTEXITSOL((*benderscutexitsol)),/**< solving process deinitialization method of the Benders' decomposition cut */ 123 SCIP_DECL_BENDERSCUTEXEC((*benderscutexec)),/**< execution method of the Benders' decomposition cut */ 124 SCIP_BENDERSCUTDATA* benderscutdata /**< Benders' decomposition cut data */ 125 ) 126 { 127 char paramname[SCIP_MAXSTRLEN]; 128 char paramdesc[SCIP_MAXSTRLEN]; 129 130 assert(benderscut != NULL); 131 assert(name != NULL); 132 assert(desc != NULL); 133 assert(benderscutexec != NULL); 134 135 SCIP_ALLOC( BMSallocMemory(benderscut) ); 136 SCIP_ALLOC( BMSduplicateMemoryArray(&(*benderscut)->name, name, strlen(name)+1) ); 137 SCIP_ALLOC( BMSduplicateMemoryArray(&(*benderscut)->desc, desc, strlen(desc)+1) ); 138 (*benderscut)->priority = priority; 139 (*benderscut)->islpcut = islpcut; 140 (*benderscut)->benderscutcopy = benderscutcopy; 141 (*benderscut)->benderscutfree = benderscutfree; 142 (*benderscut)->benderscutinit = benderscutinit; 143 (*benderscut)->benderscutexit = benderscutexit; 144 (*benderscut)->benderscutinitsol = benderscutinitsol; 145 (*benderscut)->benderscutexitsol = benderscutexitsol; 146 (*benderscut)->benderscutexec = benderscutexec; 147 (*benderscut)->benderscutdata = benderscutdata; 148 SCIP_CALL( SCIPclockCreate(&(*benderscut)->setuptime, SCIP_CLOCKTYPE_DEFAULT) ); 149 SCIP_CALL( SCIPclockCreate(&(*benderscut)->benderscutclock, SCIP_CLOCKTYPE_DEFAULT) ); 150 (*benderscut)->ncalls = 0; 151 (*benderscut)->nfound = 0; 152 (*benderscut)->initialized = FALSE; 153 154 /* add parameters */ 155 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/benderscut/%s/priority", SCIPbendersGetName(benders), name); 156 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of Benders' cut <%s>", name); 157 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 158 &(*benderscut)->priority, TRUE, priority, INT_MIN/4, INT_MAX/4, 159 paramChgdBenderscutPriority, (SCIP_PARAMDATA*)(*benderscut)) ); /*lint !e740*/ 160 161 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "benders/%s/benderscut/%s/enabled", SCIPbendersGetName(benders), name); 162 SCIP_CALL( SCIPsetAddBoolParam(set, messagehdlr, blkmem, paramname, 163 "is this Benders' decomposition cut method used to generate cuts?", &(*benderscut)->enabled, FALSE, 164 SCIP_DEFAULT_ENABLED, NULL, NULL) ); /*lint !e740*/ 165 166 return SCIP_OKAY; 167 } 168 169 /** creates a Benders' decomposition cut */ 170 SCIP_RETCODE SCIPbenderscutCreate( 171 SCIP_BENDERS* benders, /**< Benders' decomposition */ 172 SCIP_BENDERSCUT** benderscut, /**< pointer to the Benders' decomposition cut data structure */ 173 SCIP_SET* set, /**< global SCIP settings */ 174 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 175 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 176 const char* name, /**< name of the Benders' decomposition cut */ 177 const char* desc, /**< description of the Benders' decomposition cut */ 178 int priority, /**< priority of the the Benders' decomposition cut */ 179 SCIP_Bool islpcut, /**< indicates whether the cut is generated from the LP solution */ 180 SCIP_DECL_BENDERSCUTCOPY((*benderscutcopy)),/**< copy method of the Benders' decomposition cut or NULL if you don't want to copy your plugin into sub-SCIPs */ 181 SCIP_DECL_BENDERSCUTFREE((*benderscutfree)),/**< destructor of the Benders' decomposition cut */ 182 SCIP_DECL_BENDERSCUTINIT((*benderscutinit)),/**< initialize the Benders' decomposition cut */ 183 SCIP_DECL_BENDERSCUTEXIT((*benderscutexit)),/**< deinitialize the Benders' decomposition cut */ 184 SCIP_DECL_BENDERSCUTINITSOL((*benderscutinitsol)),/**< solving process initialization method of the Benders' decomposition cut */ 185 SCIP_DECL_BENDERSCUTEXITSOL((*benderscutexitsol)),/**< solving process deinitialization method of the Benders' decomposition cut */ 186 SCIP_DECL_BENDERSCUTEXEC((*benderscutexec)),/**< execution method of the Benders' decomposition cut */ 187 SCIP_BENDERSCUTDATA* benderscutdata /**< Benders' decomposition cut data */ 188 ) 189 { 190 assert(benderscut != NULL); 191 assert(name != NULL); 192 assert(desc != NULL); 193 assert(benderscutexec != NULL); 194 195 SCIP_CALL_FINALLY( doBenderscutCreate(benders, benderscut, set, messagehdlr, blkmem, name, desc, priority, islpcut, 196 benderscutcopy, benderscutfree, benderscutinit, benderscutexit, benderscutinitsol, benderscutexitsol, 197 benderscutexec, benderscutdata), (void)SCIPbenderscutFree(benderscut, set) ); 198 199 return SCIP_OKAY; 200 } 201 202 /** calls destructor and frees memory of the Benders' decomposition cut */ 203 SCIP_RETCODE SCIPbenderscutFree( 204 SCIP_BENDERSCUT** benderscut, /**< pointer to the Benders' decomposition cut data structure */ 205 SCIP_SET* set /**< global SCIP settings */ 206 ) 207 { 208 assert(benderscut != NULL); 209 assert(*benderscut != NULL); 210 assert(!(*benderscut)->initialized); 211 assert(set != NULL); 212 213 /* call destructor of the Benders' decomposition cut */ 214 if( (*benderscut)->benderscutfree != NULL ) 215 { 216 SCIP_CALL( (*benderscut)->benderscutfree(set->scip, *benderscut) ); 217 } 218 219 SCIPclockFree(&(*benderscut)->benderscutclock); 220 SCIPclockFree(&(*benderscut)->setuptime); 221 BMSfreeMemoryArray(&(*benderscut)->name); 222 BMSfreeMemoryArray(&(*benderscut)->desc); 223 BMSfreeMemory(benderscut); 224 225 return SCIP_OKAY; 226 } 227 228 /** initializes the Benders' decomposition cut */ 229 SCIP_RETCODE SCIPbenderscutInit( 230 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 231 SCIP_SET* set /**< global SCIP settings */ 232 ) 233 { 234 assert(benderscut != NULL); 235 assert(set != NULL); 236 237 if( benderscut->initialized ) 238 { 239 SCIPerrorMessage("Benders' decomposition cut <%s> already initialized\n", benderscut->name); 240 return SCIP_INVALIDCALL; 241 } 242 243 if( set->misc_resetstat ) 244 { 245 SCIPclockReset(benderscut->setuptime); 246 SCIPclockReset(benderscut->benderscutclock); 247 248 benderscut->ncalls = 0; 249 benderscut->nfound = 0; 250 } 251 252 if( benderscut->benderscutinit != NULL ) 253 { 254 /* start timing */ 255 SCIPclockStart(benderscut->setuptime, set); 256 257 SCIP_CALL( benderscut->benderscutinit(set->scip, benderscut) ); 258 259 /* stop timing */ 260 SCIPclockStop(benderscut->setuptime, set); 261 } 262 benderscut->initialized = TRUE; 263 264 return SCIP_OKAY; 265 } 266 267 /** calls exit method of the Benders' decomposition cut */ 268 SCIP_RETCODE SCIPbenderscutExit( 269 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 270 SCIP_SET* set /**< global SCIP settings */ 271 ) 272 { 273 assert(benderscut != NULL); 274 assert(set != NULL); 275 276 if( !benderscut->initialized ) 277 { 278 SCIPerrorMessage("Benders' decomposition cut <%s> not initialized\n", benderscut->name); 279 return SCIP_INVALIDCALL; 280 } 281 282 if( benderscut->benderscutexit != NULL ) 283 { 284 /* start timing */ 285 SCIPclockStart(benderscut->setuptime, set); 286 287 SCIP_CALL( benderscut->benderscutexit(set->scip, benderscut) ); 288 289 /* stop timing */ 290 SCIPclockStop(benderscut->setuptime, set); 291 } 292 benderscut->initialized = FALSE; 293 294 return SCIP_OKAY; 295 } 296 297 /** informs Benders' cut that the branch and bound process is being started */ 298 SCIP_RETCODE SCIPbenderscutInitsol( 299 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 300 SCIP_SET* set /**< global SCIP settings */ 301 ) 302 { 303 assert(benderscut != NULL); 304 assert(set != NULL); 305 306 /* call solving process initialization method of the Benders' decomposition cut */ 307 if( benderscut->benderscutinitsol != NULL ) 308 { 309 /* start timing */ 310 SCIPclockStart(benderscut->setuptime, set); 311 312 SCIP_CALL( benderscut->benderscutinitsol(set->scip, benderscut) ); 313 314 /* stop timing */ 315 SCIPclockStop(benderscut->setuptime, set); 316 } 317 318 return SCIP_OKAY; 319 } 320 321 /** informs Benders' decomposition that the branch and bound process data is being freed */ 322 SCIP_RETCODE SCIPbenderscutExitsol( 323 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition */ 324 SCIP_SET* set /**< global SCIP settings */ 325 ) 326 { 327 assert(benderscut != NULL); 328 assert(set != NULL); 329 330 /* call solving process deinitialization method of Benders' decomposition cut */ 331 if( benderscut->benderscutexitsol != NULL ) 332 { 333 /* start timing */ 334 SCIPclockStart(benderscut->setuptime, set); 335 336 SCIP_CALL( benderscut->benderscutexitsol(set->scip, benderscut) ); 337 338 /* stop timing */ 339 SCIPclockStop(benderscut->setuptime, set); 340 } 341 342 return SCIP_OKAY; 343 } 344 345 /** calls execution method of the Benders' decomposition cut */ 346 SCIP_RETCODE SCIPbenderscutExec( 347 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 348 SCIP_SET* set, /**< global SCIP settings */ 349 SCIP_BENDERS* benders, /**< Benders' decomposition */ 350 SCIP_SOL* sol, /**< primal CIP solution */ 351 int probnumber, /**< the number of the subproblem for which the cut is generated */ 352 SCIP_BENDERSENFOTYPE type, /**< the enforcement type calling this function */ 353 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 354 ) 355 { 356 SCIP_RESULT cutresult; 357 358 assert(benderscut != NULL); 359 assert(benderscut->benderscutexec != NULL); 360 assert(set != NULL); 361 assert(set->scip != NULL); 362 assert(result != NULL); 363 364 cutresult = SCIP_DIDNOTRUN; 365 366 SCIPsetDebugMsg(set, "executing Benders' decomposition cut <%s>\n", benderscut->name); 367 368 /* start timing */ 369 SCIPclockStart(benderscut->benderscutclock, set); 370 371 /* call the Benders' decomposition cut if it is enabled */ 372 if( benderscut->enabled ) 373 { 374 SCIP_CALL( benderscut->benderscutexec(set->scip, benders, benderscut, sol, probnumber, type, &cutresult) ); 375 } 376 377 /* stop timing */ 378 SCIPclockStop(benderscut->benderscutclock, set); 379 380 /* evaluate result */ 381 if( cutresult != SCIP_DIDNOTRUN 382 && cutresult != SCIP_DIDNOTFIND 383 && cutresult != SCIP_CONSADDED 384 && cutresult != SCIP_FEASIBLE 385 && cutresult != SCIP_SEPARATED ) 386 { 387 SCIPerrorMessage("execution method of Benders' decomposition cut <%s> returned invalid result <%d>\n", 388 benderscut->name, cutresult); 389 return SCIP_INVALIDRESULT; 390 } 391 392 benderscut->ncalls++; 393 394 if( cutresult == SCIP_CONSADDED || cutresult == SCIP_SEPARATED ) 395 benderscut->nfound++; 396 397 (*result) = cutresult; 398 399 return SCIP_OKAY; 400 } 401 402 /** gets user data of the Benders' decomposition cut */ 403 SCIP_BENDERSCUTDATA* SCIPbenderscutGetData( 404 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 405 ) 406 { 407 assert(benderscut != NULL); 408 409 return benderscut->benderscutdata; 410 } 411 412 /** sets user data of the Benders' decomposition cut; user has to free old data in advance! */ 413 void SCIPbenderscutSetData( 414 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 415 SCIP_BENDERSCUTDATA* benderscutdata /**< new Benders' decomposition cut user data */ 416 ) 417 { 418 assert(benderscut != NULL); 419 420 benderscut->benderscutdata = benderscutdata; 421 } 422 423 /* new callback setter methods */ 424 425 /** sets copy callback of the Benders' decomposition cut */ 426 void SCIPbenderscutSetCopy( 427 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 428 SCIP_DECL_BENDERSCUTCOPY((*benderscutcopy))/**< copy callback of the Benders' decomposition cut or NULL if you don't want to copy your plugin into sub-SCIPs */ 429 ) 430 { 431 assert(benderscut != NULL); 432 433 benderscut->benderscutcopy = benderscutcopy; 434 } 435 436 /** sets destructor callback of the Benders' decomposition cut */ 437 void SCIPbenderscutSetFree( 438 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 439 SCIP_DECL_BENDERSCUTFREE((*benderscutfree))/**< destructor of the Benders' decomposition cut */ 440 ) 441 { 442 assert(benderscut != NULL); 443 444 benderscut->benderscutfree = benderscutfree; 445 } 446 447 /** sets initialization callback of the Benders' decomposition cut */ 448 void SCIPbenderscutSetInit( 449 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 450 SCIP_DECL_BENDERSCUTINIT((*benderscutinit))/**< initialize the Benders' decomposition cut */ 451 ) 452 { 453 assert(benderscut != NULL); 454 455 benderscut->benderscutinit = benderscutinit; 456 } 457 458 /** sets deinitialization callback of the Benders' decomposition cut */ 459 void SCIPbenderscutSetExit( 460 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 461 SCIP_DECL_BENDERSCUTEXIT((*benderscutexit))/**< deinitialize the Benders' decomposition cut */ 462 ) 463 { 464 assert(benderscut != NULL); 465 466 benderscut->benderscutexit = benderscutexit; 467 } 468 469 /** sets solving process initialization callback of the Benders' decomposition cut */ 470 void SCIPbenderscutSetInitsol( 471 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 472 SCIP_DECL_BENDERSCUTINITSOL((*benderscutinitsol))/**< solving process initialization callback of the Benders' decomposition cut */ 473 ) 474 { 475 assert(benderscut != NULL); 476 477 benderscut->benderscutinitsol = benderscutinitsol; 478 } 479 480 /** sets solving process deinitialization callback of Benders' decomposition cut */ 481 void SCIPbenderscutSetExitsol( 482 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 483 SCIP_DECL_BENDERSCUTEXITSOL((*benderscutexitsol))/**< solving process deinitialization callback of the Benders' decomposition cut */ 484 ) 485 { 486 assert(benderscut != NULL); 487 488 benderscut->benderscutexitsol = benderscutexitsol; 489 } 490 491 /** gets name of the Benders' decomposition cut */ 492 const char* SCIPbenderscutGetName( 493 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 494 ) 495 { 496 assert(benderscut != NULL); 497 498 return benderscut->name; 499 } 500 501 /** gets description of the Benders' decomposition cut */ 502 const char* SCIPbenderscutGetDesc( 503 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 504 ) 505 { 506 assert(benderscut != NULL); 507 508 return benderscut->desc; 509 } 510 511 /** gets priority of the Benders' decomposition cut */ 512 int SCIPbenderscutGetPriority( 513 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 514 ) 515 { 516 assert(benderscut != NULL); 517 518 return benderscut->priority; 519 } 520 521 /** sets priority of the Benders' decomposition cut */ 522 void SCIPbenderscutSetPriority( 523 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 524 int priority /**< new priority of the Benders' decomposition cut */ 525 ) 526 { 527 assert(benderscut != NULL); 528 529 benderscut->priority = priority; 530 } 531 532 /** gets the number of times, the heuristic was called and tried to find a solution */ 533 SCIP_Longint SCIPbenderscutGetNCalls( 534 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 535 ) 536 { 537 assert(benderscut != NULL); 538 539 return benderscut->ncalls; 540 } 541 542 /** gets the number of Benders' cuts found by this Benders' decomposition cut */ 543 SCIP_Longint SCIPbenderscutGetNFound( 544 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 545 ) 546 { 547 assert(benderscut != NULL); 548 549 return benderscut->nfound; 550 } 551 552 /** is the Benders' decomposition cut initialized? */ 553 SCIP_Bool SCIPbenderscutIsInitialized( 554 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 555 ) 556 { 557 assert(benderscut != NULL); 558 559 return benderscut->initialized; 560 } 561 562 /** gets time in seconds used by this Benders' decomposition cut for setting up */ 563 SCIP_Real SCIPbenderscutGetSetupTime( 564 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 565 ) 566 { 567 assert(benderscut != NULL); 568 569 return SCIPclockGetTime(benderscut->setuptime); 570 } 571 572 /** gets time in seconds used in this Benders' decomposition cut */ 573 SCIP_Real SCIPbenderscutGetTime( 574 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 575 ) 576 { 577 assert(benderscut != NULL); 578 579 return SCIPclockGetTime(benderscut->benderscutclock); 580 } 581 582 /** returns whether the Benders' cut uses the LP information */ 583 SCIP_Bool SCIPbenderscutIsLPCut( 584 SCIP_BENDERSCUT* benderscut /**< Benders' decomposition cut */ 585 ) 586 { 587 assert(benderscut != NULL); 588 589 return benderscut->islpcut; 590 } 591 592 /** sets the enabled flag of the Benders' decomposition cut method */ 593 void SCIPbenderscutSetEnabled( 594 SCIP_BENDERSCUT* benderscut, /**< Benders' decomposition cut */ 595 SCIP_Bool enabled /**< flag to indicate whether the Benders' decomposition cut is enabled */ 596 ) 597 { 598 assert(benderscut != NULL); 599 600 benderscut->enabled = enabled; 601 } 602