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 presol.c 26 * @ingroup OTHER_CFILES 27 * @brief methods for presolvers 28 * @author Tobias Achterberg 29 * @author Timo Berthold 30 * 31 * @todo add maxrounds parameter for single timings, count number of runs of a presolver with given timing 32 */ 33 34 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 35 36 #include <assert.h> 37 #include <string.h> 38 39 #include "scip/def.h" 40 #include "blockmemshell/memory.h" 41 #include "scip/set.h" 42 #include "scip/clock.h" 43 #include "scip/paramset.h" 44 #include "scip/scip.h" 45 #include "scip/pub_misc.h" 46 #include "scip/presol.h" 47 48 #include "scip/struct_presol.h" 49 50 51 52 /* 53 * presolver methods 54 */ 55 56 /** compares two presolvers w. r. to their priority */ 57 SCIP_DECL_SORTPTRCOMP(SCIPpresolComp) 58 { /*lint --e{715}*/ 59 return ((SCIP_PRESOL*)elem2)->priority - ((SCIP_PRESOL*)elem1)->priority; 60 } 61 62 /** comparison method for sorting presolvers w.r.t. to their name */ 63 SCIP_DECL_SORTPTRCOMP(SCIPpresolCompName) 64 { 65 return strcmp(SCIPpresolGetName((SCIP_PRESOL*)elem1), SCIPpresolGetName((SCIP_PRESOL*)elem2)); 66 } 67 68 /** method to call, when the priority of a presolver was changed */ 69 static 70 SCIP_DECL_PARAMCHGD(paramChgdPresolPriority) 71 { /*lint --e{715}*/ 72 SCIP_PARAMDATA* paramdata; 73 74 paramdata = SCIPparamGetData(param); 75 assert(paramdata != NULL); 76 77 /* use SCIPsetPresolPriority() to mark the presols unsorted */ 78 SCIP_CALL( SCIPsetPresolPriority(scip, (SCIP_PRESOL*)paramdata, SCIPparamGetInt(param)) ); /*lint !e740*/ 79 80 return SCIP_OKAY; 81 } 82 83 /** copies the given presolver to a new scip */ 84 SCIP_RETCODE SCIPpresolCopyInclude( 85 SCIP_PRESOL* presol, /**< presolver */ 86 SCIP_SET* set /**< SCIP_SET of SCIP to copy to */ 87 ) 88 { 89 assert(presol != NULL); 90 assert(set != NULL); 91 assert(set->scip != NULL); 92 93 if( presol->presolcopy != NULL ) 94 { 95 SCIPsetDebugMsg(set, "including presolver %s in subscip %p\n", SCIPpresolGetName(presol), (void*)set->scip); 96 SCIP_CALL( presol->presolcopy(set->scip, presol) ); 97 } 98 return SCIP_OKAY; 99 } 100 101 /** internal method for creating a presolver */ 102 static 103 SCIP_RETCODE doPresolCreate( 104 SCIP_PRESOL** presol, /**< pointer to store presolver */ 105 SCIP_SET* set, /**< global SCIP settings */ 106 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 107 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 108 const char* name, /**< name of presolver */ 109 const char* desc, /**< description of presolver */ 110 int priority, /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */ 111 int maxrounds, /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */ 112 SCIP_PRESOLTIMING timing, /**< timing mask of the presolver */ 113 SCIP_DECL_PRESOLCOPY ((*presolcopy)), /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */ 114 SCIP_DECL_PRESOLFREE ((*presolfree)), /**< destructor of presolver to free user data (called when SCIP is exiting) */ 115 SCIP_DECL_PRESOLINIT ((*presolinit)), /**< initialization method of presolver (called after problem was transformed) */ 116 SCIP_DECL_PRESOLEXIT ((*presolexit)), /**< deinitialization method of presolver (called before transformed problem is freed) */ 117 SCIP_DECL_PRESOLINITPRE((*presolinitpre)),/**< presolving initialization method of presolver (called when presolving is about to begin) */ 118 SCIP_DECL_PRESOLEXITPRE((*presolexitpre)),/**< presolving deinitialization method of presolver (called after presolving has been finished) */ 119 SCIP_DECL_PRESOLEXEC ((*presolexec)), /**< execution method of presolver */ 120 SCIP_PRESOLDATA* presoldata /**< presolver data */ 121 ) 122 { 123 char paramname[SCIP_MAXSTRLEN]; 124 char paramdesc[SCIP_MAXSTRLEN]; 125 126 assert(presol != NULL); 127 assert(name != NULL); 128 assert(desc != NULL); 129 130 /* the interface change from delay flags to timings cannot be recognized at compile time: Exit with an appropriate 131 * error message 132 */ 133 if( timing < SCIP_PRESOLTIMING_NONE || timing > SCIP_PRESOLTIMING_MAX ) 134 { 135 SCIPmessagePrintError("ERROR: 'PRESOLDELAY'-flag no longer available since SCIP 3.2, use an appropriate " 136 "'SCIP_PRESOLTIMING' for <%s> presolver instead.\n", name); 137 138 return SCIP_PARAMETERWRONGVAL; 139 } 140 141 SCIP_ALLOC( BMSallocMemory(presol) ); 142 BMSclearMemory(*presol); 143 144 SCIP_ALLOC( BMSduplicateMemoryArray(&(*presol)->name, name, strlen(name)+1) ); 145 SCIP_ALLOC( BMSduplicateMemoryArray(&(*presol)->desc, desc, strlen(desc)+1) ); 146 (*presol)->presolcopy = presolcopy; 147 (*presol)->presolfree = presolfree; 148 (*presol)->presolinit = presolinit; 149 (*presol)->presolexit = presolexit; 150 (*presol)->presolinitpre = presolinitpre; 151 (*presol)->presolexitpre = presolexitpre; 152 (*presol)->presolexec = presolexec; 153 (*presol)->presoldata = presoldata; 154 SCIP_CALL( SCIPclockCreate(&(*presol)->setuptime, SCIP_CLOCKTYPE_DEFAULT) ); 155 SCIP_CALL( SCIPclockCreate(&(*presol)->presolclock, SCIP_CLOCKTYPE_DEFAULT) ); 156 (*presol)->initialized = FALSE; 157 158 /* add parameters */ 159 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "presolving/%s/priority", name); 160 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "priority of presolver <%s>", name); 161 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 162 &(*presol)->priority, TRUE, priority, INT_MIN/4, INT_MAX/4, 163 paramChgdPresolPriority, (SCIP_PARAMDATA*)(*presol)) ); /*lint !e740*/ 164 165 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "presolving/%s/maxrounds", name); 166 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, 167 "maximal number of presolving rounds the presolver participates in (-1: no limit)", 168 &(*presol)->maxrounds, FALSE, maxrounds, -1, INT_MAX, NULL, NULL) ); /*lint !e740*/ 169 170 (void) SCIPsnprintf(paramname, SCIP_MAXSTRLEN, "presolving/%s/timing", name); 171 (void) SCIPsnprintf(paramdesc, SCIP_MAXSTRLEN, "timing mask of presolver <%s> (%u:FAST, %u:MEDIUM, %u:EXHAUSTIVE, %u:FINAL)", 172 name, SCIP_PRESOLTIMING_FAST, SCIP_PRESOLTIMING_MEDIUM, SCIP_PRESOLTIMING_EXHAUSTIVE, SCIP_PRESOLTIMING_FINAL); 173 SCIP_CALL( SCIPsetAddIntParam(set, messagehdlr, blkmem, paramname, paramdesc, 174 (int*)&(*presol)->timing, TRUE, (int)timing, (int) SCIP_PRESOLTIMING_FAST, (int) SCIP_PRESOLTIMING_MAX, NULL, NULL) ); /*lint !e740*/ 175 176 return SCIP_OKAY; 177 } 178 179 /** creates a presolver */ 180 SCIP_RETCODE SCIPpresolCreate( 181 SCIP_PRESOL** presol, /**< pointer to store presolver */ 182 SCIP_SET* set, /**< global SCIP settings */ 183 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 184 BMS_BLKMEM* blkmem, /**< block memory for parameter settings */ 185 const char* name, /**< name of presolver */ 186 const char* desc, /**< description of presolver */ 187 int priority, /**< priority of the presolver (>= 0: before, < 0: after constraint handlers) */ 188 int maxrounds, /**< maximal number of presolving rounds the presolver participates in (-1: no limit) */ 189 SCIP_PRESOLTIMING timing, /**< timing mask of the presolver */ 190 SCIP_DECL_PRESOLCOPY ((*presolcopy)), /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */ 191 SCIP_DECL_PRESOLFREE ((*presolfree)), /**< destructor of presolver to free user data (called when SCIP is exiting) */ 192 SCIP_DECL_PRESOLINIT ((*presolinit)), /**< initialization method of presolver (called after problem was transformed) */ 193 SCIP_DECL_PRESOLEXIT ((*presolexit)), /**< deinitialization method of presolver (called before transformed problem is freed) */ 194 SCIP_DECL_PRESOLINITPRE((*presolinitpre)),/**< presolving initialization method of presolver (called when presolving is about to begin) */ 195 SCIP_DECL_PRESOLEXITPRE((*presolexitpre)),/**< presolving deinitialization method of presolver (called after presolving has been finished) */ 196 SCIP_DECL_PRESOLEXEC ((*presolexec)), /**< execution method of presolver */ 197 SCIP_PRESOLDATA* presoldata /**< presolver data */ 198 ) 199 { 200 assert(presol != NULL); 201 assert(name != NULL); 202 assert(desc != NULL); 203 204 SCIP_CALL_FINALLY( doPresolCreate(presol, set, messagehdlr, blkmem, name, desc, priority, maxrounds, timing, 205 presolcopy, presolfree, presolinit, presolexit, presolinitpre, presolexitpre, presolexec, presoldata), 206 (void) SCIPpresolFree(presol, set) ); 207 208 return SCIP_OKAY; 209 } 210 211 /** frees memory of presolver */ 212 SCIP_RETCODE SCIPpresolFree( 213 SCIP_PRESOL** presol, /**< pointer to presolver data structure */ 214 SCIP_SET* set /**< global SCIP settings */ 215 ) 216 { 217 assert(presol != NULL); 218 if( *presol == NULL ) 219 return SCIP_OKAY; 220 assert(!(*presol)->initialized); 221 assert(set != NULL); 222 223 /* call destructor of presolver */ 224 if( (*presol)->presolfree != NULL ) 225 { 226 SCIP_CALL( (*presol)->presolfree(set->scip, *presol) ); 227 } 228 229 SCIPclockFree(&(*presol)->presolclock); 230 SCIPclockFree(&(*presol)->setuptime); 231 BMSfreeMemoryArrayNull(&(*presol)->name); 232 BMSfreeMemoryArrayNull(&(*presol)->desc); 233 BMSfreeMemory(presol); 234 235 return SCIP_OKAY; 236 } 237 238 /** initializes presolver */ 239 SCIP_RETCODE SCIPpresolInit( 240 SCIP_PRESOL* presol, /**< presolver */ 241 SCIP_SET* set /**< global SCIP settings */ 242 ) 243 { 244 assert(presol != NULL); 245 assert(set != NULL); 246 247 if( presol->initialized ) 248 { 249 SCIPerrorMessage("presolver <%s> already initialized\n", presol->name); 250 return SCIP_INVALIDCALL; 251 } 252 253 if( set->misc_resetstat ) 254 { 255 SCIPclockReset(presol->setuptime); 256 SCIPclockReset(presol->presolclock); 257 258 presol->lastnfixedvars = 0; 259 presol->lastnaggrvars = 0; 260 presol->lastnchgvartypes = 0; 261 presol->lastnchgbds = 0; 262 presol->lastnaddholes = 0; 263 presol->lastndelconss = 0; 264 presol->lastnaddconss = 0; 265 presol->lastnupgdconss = 0; 266 presol->lastnchgcoefs = 0; 267 presol->lastnchgsides = 0; 268 presol->nfixedvars = 0; 269 presol->naggrvars = 0; 270 presol->nchgvartypes = 0; 271 presol->nchgbds = 0; 272 presol->naddholes = 0; 273 presol->ndelconss = 0; 274 presol->naddconss = 0; 275 presol->nupgdconss = 0; 276 presol->nchgcoefs = 0; 277 presol->nchgsides = 0; 278 presol->ncalls = 0; 279 } 280 281 /* call initialization method of presolver */ 282 if( presol->presolinit != NULL ) 283 { 284 /* start timing */ 285 SCIPclockStart(presol->setuptime, set); 286 287 SCIP_CALL( presol->presolinit(set->scip, presol) ); 288 289 /* stop timing */ 290 SCIPclockStop(presol->setuptime, set); 291 } 292 presol->initialized = TRUE; 293 294 return SCIP_OKAY; 295 } 296 297 /** deinitializes presolver */ 298 SCIP_RETCODE SCIPpresolExit( 299 SCIP_PRESOL* presol, /**< presolver */ 300 SCIP_SET* set /**< global SCIP settings */ 301 ) 302 { 303 assert(presol != NULL); 304 assert(set != NULL); 305 306 if( !presol->initialized ) 307 { 308 SCIPerrorMessage("presolver <%s> not initialized\n", presol->name); 309 return SCIP_INVALIDCALL; 310 } 311 312 /* call deinitialization method of presolver */ 313 if( presol->presolexit != NULL ) 314 { 315 /* start timing */ 316 SCIPclockStart(presol->setuptime, set); 317 318 SCIP_CALL( presol->presolexit(set->scip, presol) ); 319 320 /* stop timing */ 321 SCIPclockStop(presol->setuptime, set); 322 } 323 presol->initialized = FALSE; 324 325 return SCIP_OKAY; 326 } 327 328 /** informs presolver that the presolving process is being started */ 329 SCIP_RETCODE SCIPpresolInitpre( 330 SCIP_PRESOL* presol, /**< presolver */ 331 SCIP_SET* set /**< global SCIP settings */ 332 ) 333 { 334 assert(presol != NULL); 335 assert(set != NULL); 336 337 presol->lastnfixedvars = 0; 338 presol->lastnaggrvars = 0; 339 presol->lastnchgvartypes = 0; 340 presol->lastnchgbds = 0; 341 presol->lastnaddholes = 0; 342 presol->lastndelconss = 0; 343 presol->lastnaddconss = 0; 344 presol->lastnupgdconss = 0; 345 presol->lastnchgcoefs = 0; 346 presol->lastnchgsides = 0; 347 348 /* call presolving initialization method of presolver */ 349 if( presol->presolinitpre != NULL ) 350 { 351 /* start timing */ 352 SCIPclockStart(presol->setuptime, set); 353 354 SCIP_CALL( presol->presolinitpre(set->scip, presol) ); 355 356 /* stop timing */ 357 SCIPclockStop(presol->setuptime, set); 358 } 359 360 return SCIP_OKAY; 361 } 362 363 /** informs presolver that the presolving process is finished */ 364 SCIP_RETCODE SCIPpresolExitpre( 365 SCIP_PRESOL* presol, /**< presolver */ 366 SCIP_SET* set /**< global SCIP settings */ 367 ) 368 { 369 assert(presol != NULL); 370 assert(set != NULL); 371 372 /* call presolving deinitialization method of presolver */ 373 if( presol->presolexitpre != NULL ) 374 { 375 /* start timing */ 376 SCIPclockStart(presol->setuptime, set); 377 378 SCIP_CALL( presol->presolexitpre(set->scip, presol) ); 379 380 /* stop timing */ 381 SCIPclockStop(presol->setuptime, set); 382 } 383 384 return SCIP_OKAY; 385 } 386 387 /** executes presolver */ 388 SCIP_RETCODE SCIPpresolExec( 389 SCIP_PRESOL* presol, /**< presolver */ 390 SCIP_SET* set, /**< global SCIP settings */ 391 SCIP_PRESOLTIMING timing, /**< current presolving timing */ 392 int nrounds, /**< number of presolving rounds already done */ 393 int* nfixedvars, /**< pointer to total number of variables fixed of all presolvers */ 394 int* naggrvars, /**< pointer to total number of variables aggregated of all presolvers */ 395 int* nchgvartypes, /**< pointer to total number of variable type changes of all presolvers */ 396 int* nchgbds, /**< pointer to total number of variable bounds tightened of all presolvers */ 397 int* naddholes, /**< pointer to total number of domain holes added of all presolvers */ 398 int* ndelconss, /**< pointer to total number of deleted constraints of all presolvers */ 399 int* naddconss, /**< pointer to total number of added constraints of all presolvers */ 400 int* nupgdconss, /**< pointer to total number of upgraded constraints of all presolvers */ 401 int* nchgcoefs, /**< pointer to total number of changed coefficients of all presolvers */ 402 int* nchgsides, /**< pointer to total number of changed left/right hand sides of all presolvers */ 403 SCIP_RESULT* result /**< pointer to store the result of the callback method */ 404 ) 405 { 406 int nnewfixedvars; 407 int nnewaggrvars; 408 int nnewchgvartypes; 409 int nnewchgbds; 410 int nnewaddholes; 411 int nnewdelconss; 412 int nnewaddconss; 413 int nnewupgdconss; 414 int nnewchgcoefs; 415 int nnewchgsides; 416 417 assert(presol != NULL); 418 assert(presol->presolexec != NULL); 419 assert(set != NULL); 420 assert(nfixedvars != NULL); 421 assert(naggrvars != NULL); 422 assert(nchgvartypes != NULL); 423 assert(nchgbds != NULL); 424 assert(naddholes != NULL); 425 assert(ndelconss != NULL); 426 assert(naddconss != NULL); 427 assert(nupgdconss != NULL); 428 assert(nchgcoefs != NULL); 429 assert(nchgsides != NULL); 430 assert(result != NULL); 431 432 *result = SCIP_DIDNOTRUN; 433 434 /* check number of presolving rounds */ 435 if( presol->maxrounds >= 0 && presol->ncalls >= presol->maxrounds ) 436 return SCIP_OKAY; 437 438 /* calculate the number of changes since last call */ 439 nnewfixedvars = *nfixedvars - presol->lastnfixedvars; 440 nnewaggrvars = *naggrvars - presol->lastnaggrvars; 441 nnewchgvartypes = *nchgvartypes - presol->lastnchgvartypes; 442 nnewchgbds = *nchgbds - presol->lastnchgbds; 443 nnewaddholes = *naddholes - presol->lastnaddholes; 444 nnewdelconss = *ndelconss - presol->lastndelconss; 445 nnewaddconss = *naddconss - presol->lastnaddconss; 446 nnewupgdconss = *nupgdconss - presol->lastnupgdconss; 447 nnewchgcoefs = *nchgcoefs - presol->lastnchgcoefs; 448 nnewchgsides = *nchgsides - presol->lastnchgsides; 449 450 /* remember the number of changes prior to the call of the presolver */ 451 presol->lastnfixedvars = *nfixedvars; 452 presol->lastnaggrvars = *naggrvars; 453 presol->lastnchgvartypes = *nchgvartypes; 454 presol->lastnchgbds = *nchgbds; 455 presol->lastnaddholes = *naddholes; 456 presol->lastndelconss = *ndelconss; 457 presol->lastnaddconss = *naddconss; 458 presol->lastnupgdconss = *nupgdconss; 459 presol->lastnchgcoefs = *nchgcoefs; 460 presol->lastnchgsides = *nchgsides; 461 462 /* check, if presolver should be called with the current timing */ 463 if( timing & presol->timing ) 464 { 465 SCIPsetDebugMsg(set, "calling presolver <%s> with timing %u\n", presol->name, timing); 466 467 /* start timing */ 468 SCIPclockStart(presol->presolclock, set); 469 470 /* call external method */ 471 SCIP_CALL( presol->presolexec(set->scip, presol, nrounds, timing, 472 nnewfixedvars, nnewaggrvars, nnewchgvartypes, nnewchgbds, nnewaddholes, 473 nnewdelconss, nnewaddconss, nnewupgdconss, nnewchgcoefs, nnewchgsides, 474 nfixedvars, naggrvars, nchgvartypes, nchgbds, naddholes, 475 ndelconss, naddconss, nupgdconss, nchgcoefs, nchgsides, result) ); 476 477 /* stop timing */ 478 SCIPclockStop(presol->presolclock, set); 479 480 /* add/count the new changes */ 481 presol->nfixedvars += *nfixedvars - presol->lastnfixedvars; 482 presol->naggrvars += *naggrvars - presol->lastnaggrvars; 483 presol->nchgvartypes += *nchgvartypes - presol->lastnchgvartypes; 484 presol->nchgbds += *nchgbds - presol->lastnchgbds; 485 presol->naddholes += *naddholes - presol->lastnaddholes; 486 presol->ndelconss += *ndelconss - presol->lastndelconss; 487 presol->naddconss += *naddconss - presol->lastnaddconss; 488 presol->nupgdconss += *nupgdconss - presol->lastnupgdconss; 489 presol->nchgcoefs += *nchgcoefs - presol->lastnchgcoefs; 490 presol->nchgsides += *nchgsides - presol->lastnchgsides; 491 492 /* check result code of callback method */ 493 if( *result != SCIP_CUTOFF 494 && *result != SCIP_UNBOUNDED 495 && *result != SCIP_SUCCESS 496 && *result != SCIP_DIDNOTFIND 497 && *result != SCIP_DIDNOTRUN ) 498 { 499 SCIPerrorMessage("presolver <%s> returned invalid result <%d>\n", presol->name, *result); 500 return SCIP_INVALIDRESULT; 501 } 502 503 /* increase the number of calls, if the presolver tried to find reductions */ 504 if( *result != SCIP_DIDNOTRUN ) 505 ++(presol->ncalls); 506 } 507 508 return SCIP_OKAY; 509 } 510 511 /** gets user data of presolver */ 512 SCIP_PRESOLDATA* SCIPpresolGetData( 513 SCIP_PRESOL* presol /**< presolver */ 514 ) 515 { 516 assert(presol != NULL); 517 518 return presol->presoldata; 519 } 520 521 /** sets user data of presolver; user has to free old data in advance! */ 522 void SCIPpresolSetData( 523 SCIP_PRESOL* presol, /**< presolver */ 524 SCIP_PRESOLDATA* presoldata /**< new presolver user data */ 525 ) 526 { 527 assert(presol != NULL); 528 529 presol->presoldata = presoldata; 530 } 531 532 /** sets copy method of presolver */ 533 void SCIPpresolSetCopy( 534 SCIP_PRESOL* presol, /**< presolver */ 535 SCIP_DECL_PRESOLCOPY ((*presolcopy)) /**< copy method of presolver or NULL if you don't want to copy your plugin into sub-SCIPs */ 536 ) 537 { 538 assert(presol != NULL); 539 540 presol->presolcopy = presolcopy; 541 } 542 543 /** sets destructor method of presolver */ 544 void SCIPpresolSetFree( 545 SCIP_PRESOL* presol, /**< presolver */ 546 SCIP_DECL_PRESOLFREE ((*presolfree)) /**< destructor of presolver */ 547 ) 548 { 549 assert(presol != NULL); 550 551 presol->presolfree = presolfree; 552 } 553 554 /** sets initialization method of presolver */ 555 void SCIPpresolSetInit( 556 SCIP_PRESOL* presol, /**< presolver */ 557 SCIP_DECL_PRESOLINIT ((*presolinit)) /**< initialize presolver */ 558 ) 559 { 560 assert(presol != NULL); 561 562 presol->presolinit = presolinit; 563 } 564 565 /** sets deinitialization method of presolver */ 566 void SCIPpresolSetExit( 567 SCIP_PRESOL* presol, /**< presolver */ 568 SCIP_DECL_PRESOLEXIT ((*presolexit)) /**< deinitialize presolver */ 569 ) 570 { 571 assert(presol != NULL); 572 573 presol->presolexit = presolexit; 574 } 575 576 /** sets solving process initialization method of presolver */ 577 void SCIPpresolSetInitpre( 578 SCIP_PRESOL* presol, /**< presolver */ 579 SCIP_DECL_PRESOLINITPRE ((*presolinitpre))/**< solving process initialization method of presolver */ 580 ) 581 { 582 assert(presol != NULL); 583 584 presol->presolinitpre = presolinitpre; 585 } 586 587 /** sets solving process deinitialization method of presolver */ 588 void SCIPpresolSetExitpre( 589 SCIP_PRESOL* presol, /**< presolver */ 590 SCIP_DECL_PRESOLEXITPRE ((*presolexitpre))/**< solving process deinitialization method of presolver */ 591 ) 592 { 593 assert(presol != NULL); 594 595 presol->presolexitpre = presolexitpre; 596 } 597 598 /** gets name of presolver */ 599 const char* SCIPpresolGetName( 600 SCIP_PRESOL* presol /**< presolver */ 601 ) 602 { 603 assert(presol != NULL); 604 605 return presol->name; 606 } 607 608 /** gets description of presolver */ 609 const char* SCIPpresolGetDesc( 610 SCIP_PRESOL* presol /**< presolver */ 611 ) 612 { 613 assert(presol != NULL); 614 615 return presol->desc; 616 } 617 618 /** gets priority of presolver */ 619 int SCIPpresolGetPriority( 620 SCIP_PRESOL* presol /**< presolver */ 621 ) 622 { 623 assert(presol != NULL); 624 625 return presol->priority; 626 } 627 628 /** gets round limit of presolver */ 629 int SCIPpresolGetMaxrounds( 630 SCIP_PRESOL* presol /**< presolver */ 631 ) 632 { 633 assert(presol != NULL); 634 635 return presol->maxrounds; 636 } 637 638 /** sets priority of presolver */ 639 void SCIPpresolSetPriority( 640 SCIP_PRESOL* presol, /**< presolver */ 641 SCIP_SET* set, /**< global SCIP settings */ 642 int priority /**< new priority of the presolver */ 643 ) 644 { 645 assert(presol != NULL); 646 assert(set != NULL); 647 648 presol->priority = priority; 649 set->presolssorted = FALSE; 650 } 651 652 /** gets the timing mask of the presolver */ 653 SCIP_PRESOLTIMING SCIPpresolGetTiming( 654 SCIP_PRESOL* presol /**< presolver */ 655 ) 656 { 657 assert(presol != NULL); 658 659 return presol->timing; 660 } 661 662 /** sets the timing mask of the presolver */ 663 void SCIPpresolSetTiming( 664 SCIP_PRESOL* presol, /**< presolver */ 665 SCIP_PRESOLTIMING timing /**< timing mask of the presolver */ 666 ) 667 { 668 assert(presol != NULL); 669 670 presol->timing = timing; 671 } 672 673 674 /** is presolver initialized? */ 675 SCIP_Bool SCIPpresolIsInitialized( 676 SCIP_PRESOL* presol /**< presolver */ 677 ) 678 { 679 assert(presol != NULL); 680 681 return presol->initialized; 682 } 683 684 /** enables or disables all clocks of \p presol, depending on the value of the flag */ 685 void SCIPpresolEnableOrDisableClocks( 686 SCIP_PRESOL* presol, /**< the presolver for which all clocks should be enabled or disabled */ 687 SCIP_Bool enable /**< should the clocks of the presolver be enabled? */ 688 ) 689 { 690 assert(presol != NULL); 691 692 SCIPclockEnableOrDisable(presol->setuptime, enable); 693 SCIPclockEnableOrDisable(presol->presolclock, enable); 694 } 695 696 /** gets time in seconds used in this presolver for setting up for next stages */ 697 SCIP_Real SCIPpresolGetSetupTime( 698 SCIP_PRESOL* presol /**< presolver */ 699 ) 700 { 701 assert(presol != NULL); 702 703 return SCIPclockGetTime(presol->setuptime); 704 } 705 706 /** gets time in seconds used in this presolver */ 707 SCIP_Real SCIPpresolGetTime( 708 SCIP_PRESOL* presol /**< presolver */ 709 ) 710 { 711 assert(presol != NULL); 712 713 return SCIPclockGetTime(presol->presolclock); 714 } 715 716 /** gets number of variables fixed in presolver */ 717 int SCIPpresolGetNFixedVars( 718 SCIP_PRESOL* presol /**< presolver */ 719 ) 720 { 721 assert(presol != NULL); 722 723 return presol->nfixedvars; 724 } 725 726 /** gets number of variables aggregated in presolver */ 727 int SCIPpresolGetNAggrVars( 728 SCIP_PRESOL* presol /**< presolver */ 729 ) 730 { 731 assert(presol != NULL); 732 733 return presol->naggrvars; 734 } 735 736 /** gets number of variable types changed in presolver */ 737 int SCIPpresolGetNChgVarTypes( 738 SCIP_PRESOL* presol /**< presolver */ 739 ) 740 { 741 assert(presol != NULL); 742 743 return presol->nchgvartypes; 744 } 745 746 /** gets number of bounds changed in presolver */ 747 int SCIPpresolGetNChgBds( 748 SCIP_PRESOL* presol /**< presolver */ 749 ) 750 { 751 assert(presol != NULL); 752 753 return presol->nchgbds; 754 } 755 756 /** gets number of holes added to domains of variables in presolver */ 757 int SCIPpresolGetNAddHoles( 758 SCIP_PRESOL* presol /**< presolver */ 759 ) 760 { 761 assert(presol != NULL); 762 763 return presol->naddholes; 764 } 765 766 /** gets number of constraints deleted in presolver */ 767 int SCIPpresolGetNDelConss( 768 SCIP_PRESOL* presol /**< presolver */ 769 ) 770 { 771 assert(presol != NULL); 772 773 return presol->ndelconss; 774 } 775 776 /** gets number of constraints added in presolver */ 777 int SCIPpresolGetNAddConss( 778 SCIP_PRESOL* presol /**< presolver */ 779 ) 780 { 781 assert(presol != NULL); 782 783 return presol->naddconss; 784 } 785 786 /** gets number of constraints upgraded in presolver */ 787 int SCIPpresolGetNUpgdConss( 788 SCIP_PRESOL* presol /**< presolver */ 789 ) 790 { 791 assert(presol != NULL); 792 793 return presol->nupgdconss; 794 } 795 796 /** gets number of coefficients changed in presolver */ 797 int SCIPpresolGetNChgCoefs( 798 SCIP_PRESOL* presol /**< presolver */ 799 ) 800 { 801 assert(presol != NULL); 802 803 return presol->nchgcoefs; 804 } 805 806 /** gets number of constraint sides changed in presolver */ 807 int SCIPpresolGetNChgSides( 808 SCIP_PRESOL* presol /**< presolver */ 809 ) 810 { 811 assert(presol != NULL); 812 813 return presol->nchgsides; 814 } 815 816 /** gets number of times the presolver was called and tried to find reductions */ 817 int SCIPpresolGetNCalls( 818 SCIP_PRESOL* presol /**< presolver */ 819 ) 820 { 821 assert(presol != NULL); 822 823 return presol->ncalls; 824 } 825