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 stat.c 26 * @ingroup OTHER_CFILES 27 * @brief methods for problem statistics 28 * @author Tobias Achterberg 29 * @author Stefan Heinz 30 * @author Gregor Hendel 31 * @author Gerald Gamrath 32 * @author Marc Pfetsch 33 * @author Stefan Vigerske 34 */ 35 36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/ 37 38 #include "scip/clock.h" 39 #include "scip/history.h" 40 #include "scip/mem.h" 41 #include "scip/prob.h" 42 #include "scip/pub_message.h" 43 #include "scip/pub_misc.h" 44 #include "scip/pub_var.h" 45 #include "scip/set.h" 46 #include "scip/stat.h" 47 #include "scip/struct_set.h" 48 #include "scip/struct_stat.h" 49 #include "scip/var.h" 50 #include "scip/visual.h" 51 52 53 54 /** creates problem statistics data */ 55 SCIP_RETCODE SCIPstatCreate( 56 SCIP_STAT** stat, /**< pointer to problem statistics data */ 57 BMS_BLKMEM* blkmem, /**< block memory */ 58 SCIP_SET* set, /**< global SCIP settings */ 59 SCIP_PROB* transprob, /**< transformed problem, or NULL */ 60 SCIP_PROB* origprob, /**< original problem, or NULL */ 61 SCIP_MESSAGEHDLR* messagehdlr /**< message handler */ 62 ) 63 { 64 assert(stat != NULL); 65 assert(set != NULL); 66 67 SCIP_ALLOC( BMSallocMemory(stat) ); 68 69 SCIP_CALL( SCIPclockCreate(&(*stat)->solvingtime, SCIP_CLOCKTYPE_DEFAULT) ); 70 SCIP_CALL( SCIPclockCreate(&(*stat)->solvingtimeoverall, SCIP_CLOCKTYPE_DEFAULT) ); 71 SCIP_CALL( SCIPclockCreate(&(*stat)->presolvingtime, SCIP_CLOCKTYPE_DEFAULT) ); 72 SCIP_CALL( SCIPclockCreate(&(*stat)->presolvingtimeoverall, SCIP_CLOCKTYPE_DEFAULT) ); 73 SCIP_CALL( SCIPclockCreate(&(*stat)->primallptime, SCIP_CLOCKTYPE_DEFAULT) ); 74 SCIP_CALL( SCIPclockCreate(&(*stat)->duallptime, SCIP_CLOCKTYPE_DEFAULT) ); 75 SCIP_CALL( SCIPclockCreate(&(*stat)->lexduallptime, SCIP_CLOCKTYPE_DEFAULT) ); 76 SCIP_CALL( SCIPclockCreate(&(*stat)->barrierlptime, SCIP_CLOCKTYPE_DEFAULT) ); 77 SCIP_CALL( SCIPclockCreate(&(*stat)->resolveinstablelptime, SCIP_CLOCKTYPE_DEFAULT) ); 78 SCIP_CALL( SCIPclockCreate(&(*stat)->divinglptime, SCIP_CLOCKTYPE_DEFAULT) ); 79 SCIP_CALL( SCIPclockCreate(&(*stat)->strongbranchtime, SCIP_CLOCKTYPE_DEFAULT) ); 80 SCIP_CALL( SCIPclockCreate(&(*stat)->conflictlptime, SCIP_CLOCKTYPE_DEFAULT) ); 81 SCIP_CALL( SCIPclockCreate(&(*stat)->lpsoltime, SCIP_CLOCKTYPE_DEFAULT) ); 82 SCIP_CALL( SCIPclockCreate(&(*stat)->relaxsoltime, SCIP_CLOCKTYPE_DEFAULT) ); 83 SCIP_CALL( SCIPclockCreate(&(*stat)->pseudosoltime, SCIP_CLOCKTYPE_DEFAULT) ); 84 SCIP_CALL( SCIPclockCreate(&(*stat)->sbsoltime, SCIP_CLOCKTYPE_DEFAULT) ); 85 SCIP_CALL( SCIPclockCreate(&(*stat)->nodeactivationtime, SCIP_CLOCKTYPE_DEFAULT) ); 86 SCIP_CALL( SCIPclockCreate(&(*stat)->nlpsoltime, SCIP_CLOCKTYPE_DEFAULT) ); 87 SCIP_CALL( SCIPclockCreate(&(*stat)->copyclock, SCIP_CLOCKTYPE_DEFAULT) ); 88 SCIP_CALL( SCIPclockCreate(&(*stat)->strongpropclock, SCIP_CLOCKTYPE_DEFAULT) ); 89 SCIP_CALL( SCIPclockCreate(&(*stat)->reoptupdatetime, SCIP_CLOCKTYPE_DEFAULT) ); 90 91 /* turn statistic timing on or off, depending on the user parameter */ 92 SCIPstatEnableOrDisableStatClocks(*stat, set->time_statistictiming); 93 94 SCIP_CALL( SCIPhistoryCreate(&(*stat)->glbhistory, blkmem) ); 95 SCIP_CALL( SCIPhistoryCreate(&(*stat)->glbhistorycrun, blkmem) ); 96 SCIP_CALL( SCIPvisualCreate(&(*stat)->visual, messagehdlr) ); 97 98 SCIP_CALL( SCIPregressionCreate(&(*stat)->regressioncandsobjval) ); 99 100 (*stat)->status = SCIP_STATUS_UNKNOWN; 101 (*stat)->marked_nvaridx = 0; 102 (*stat)->marked_ncolidx = 0; 103 (*stat)->marked_nrowidx = 0; 104 (*stat)->subscipdepth = 0; 105 (*stat)->detertimecnt = 0.0; 106 (*stat)->nreoptruns = 0; 107 108 SCIPstatReset(*stat, set, transprob, origprob); 109 110 return SCIP_OKAY; 111 } 112 113 /** frees problem statistics data */ 114 SCIP_RETCODE SCIPstatFree( 115 SCIP_STAT** stat, /**< pointer to problem statistics data */ 116 BMS_BLKMEM* blkmem /**< block memory */ 117 ) 118 { 119 assert(stat != NULL); 120 assert(*stat != NULL); 121 122 SCIPclockFree(&(*stat)->solvingtime); 123 SCIPclockFree(&(*stat)->solvingtimeoverall); 124 SCIPclockFree(&(*stat)->presolvingtime); 125 SCIPclockFree(&(*stat)->presolvingtimeoverall); 126 SCIPclockFree(&(*stat)->primallptime); 127 SCIPclockFree(&(*stat)->duallptime); 128 SCIPclockFree(&(*stat)->lexduallptime); 129 SCIPclockFree(&(*stat)->barrierlptime); 130 SCIPclockFree(&(*stat)->resolveinstablelptime); 131 SCIPclockFree(&(*stat)->divinglptime); 132 SCIPclockFree(&(*stat)->strongbranchtime); 133 SCIPclockFree(&(*stat)->conflictlptime); 134 SCIPclockFree(&(*stat)->lpsoltime); 135 SCIPclockFree(&(*stat)->relaxsoltime); 136 SCIPclockFree(&(*stat)->pseudosoltime); 137 SCIPclockFree(&(*stat)->sbsoltime); 138 SCIPclockFree(&(*stat)->nodeactivationtime); 139 SCIPclockFree(&(*stat)->nlpsoltime); 140 SCIPclockFree(&(*stat)->copyclock); 141 SCIPclockFree(&(*stat)->strongpropclock); 142 SCIPclockFree(&(*stat)->reoptupdatetime); 143 144 SCIPhistoryFree(&(*stat)->glbhistory, blkmem); 145 SCIPhistoryFree(&(*stat)->glbhistorycrun, blkmem); 146 SCIPvisualFree(&(*stat)->visual); 147 148 SCIPregressionFree(&(*stat)->regressioncandsobjval); 149 150 BMSfreeMemory(stat); 151 152 return SCIP_OKAY; 153 } 154 155 /** diables the collection of any statistic for a variable */ 156 void SCIPstatDisableVarHistory( 157 SCIP_STAT* stat /**< problem statistics data */ 158 ) 159 { 160 assert(stat != NULL); 161 162 stat->collectvarhistory = FALSE; 163 } 164 165 /** enables the collection of statistics for a variable */ 166 void SCIPstatEnableVarHistory( 167 SCIP_STAT* stat /**< problem statistics data */ 168 ) 169 { 170 assert(stat != NULL); 171 172 stat->collectvarhistory = TRUE; 173 } 174 175 /** marks statistics to be able to reset them when solving process is freed */ 176 void SCIPstatMark( 177 SCIP_STAT* stat /**< problem statistics data */ 178 ) 179 { 180 assert(stat != NULL); 181 182 stat->marked_nvaridx = stat->nvaridx; 183 stat->marked_ncolidx = stat->ncolidx; 184 stat->marked_nrowidx = stat->nrowidx; 185 } 186 187 /** reset statistics to the data before solving started */ 188 void SCIPstatReset( 189 SCIP_STAT* stat, /**< problem statistics data */ 190 SCIP_SET* set, /**< global SCIP settings */ 191 SCIP_PROB* transprob, /**< transformed problem, or NULL */ 192 SCIP_PROB* origprob /**< original problem, or NULL */ 193 ) 194 { 195 assert(stat != NULL); 196 assert(stat->marked_nvaridx >= 0); 197 assert(stat->marked_ncolidx >= 0); 198 assert(stat->marked_nrowidx >= 0); 199 200 SCIPclockReset(stat->solvingtime); 201 SCIPclockReset(stat->presolvingtime); 202 SCIPclockReset(stat->primallptime); 203 SCIPclockReset(stat->duallptime); 204 SCIPclockReset(stat->lexduallptime); 205 SCIPclockReset(stat->barrierlptime); 206 SCIPclockReset(stat->resolveinstablelptime); 207 SCIPclockReset(stat->divinglptime); 208 SCIPclockReset(stat->strongbranchtime); 209 SCIPclockReset(stat->conflictlptime); 210 SCIPclockReset(stat->lpsoltime); 211 SCIPclockReset(stat->relaxsoltime); 212 SCIPclockReset(stat->pseudosoltime); 213 SCIPclockReset(stat->sbsoltime); 214 SCIPclockReset(stat->nodeactivationtime); 215 SCIPclockReset(stat->nlpsoltime); 216 SCIPclockReset(stat->copyclock); 217 SCIPclockReset(stat->strongpropclock); 218 219 SCIPhistoryReset(stat->glbhistory); 220 221 stat->lastsblpsolstats[0] = stat->lastsblpsolstats[1] = SCIP_LPSOLSTAT_NOTSOLVED; 222 223 stat->vsidsweight = 1.0; 224 stat->nlpiterations = 0; 225 stat->nrootlpiterations = 0; 226 stat->nrootfirstlpiterations = 0; 227 stat->nprimallpiterations = 0; 228 stat->nduallpiterations = 0; 229 stat->nlexduallpiterations = 0; 230 stat->nbarrierlpiterations = 0; 231 stat->nprimalresolvelpiterations = 0; 232 stat->ndualresolvelpiterations = 0; 233 stat->nlexdualresolvelpiterations = 0; 234 stat->nnodelpiterations = 0; 235 stat->ninitlpiterations = 0; 236 stat->ndivinglpiterations = 0; 237 stat->nsbdivinglpiterations = 0; 238 stat->nsblpiterations = 0; 239 stat->nsbtimesiterlimhit = 0L; 240 stat->nrootsblpiterations = 0; 241 stat->nconflictlpiterations = 0; 242 stat->nresolveinstablelps = 0; 243 stat->nresolveinstablelpiters = 0; 244 stat->ntotalnodes = 0; 245 stat->ntotalinternalnodes = 0; 246 stat->ntotalnodesmerged = 0; 247 stat->ncreatednodes = 0; 248 stat->nlpsolsfound = 0; 249 stat->nrelaxsolsfound = 0; 250 stat->npssolsfound = 0; 251 stat->nsbsolsfound = 0; 252 stat->nlpbestsolsfound = 0; 253 stat->nrelaxbestsolsfound = 0; 254 stat->npsbestsolsfound = 0; 255 stat->nsbbestsolsfound = 0; 256 stat->nexternalsolsfound = 0; 257 stat->domchgcount = 0; 258 stat->nboundchgs = 0; 259 stat->nholechgs = 0; 260 stat->nprobboundchgs = 0; 261 stat->nprobholechgs = 0; 262 stat->nsbdowndomchgs = 0; 263 stat->nsbupdomchgs = 0; 264 stat->nruns = 0; 265 stat->nconfrestarts = 0; 266 stat->nrootboundchgs = 0; 267 stat->nrootintfixings = 0; 268 stat->prevrunnvars = 0; 269 stat->nvaridx = stat->marked_nvaridx; 270 stat->ncolidx = stat->marked_ncolidx; 271 stat->nrowidx = stat->marked_nrowidx; 272 stat->nnz = 0; 273 stat->avgnnz = 0; 274 stat->lpcount = 0; 275 stat->relaxcount = 0; 276 stat->nlps = 0; 277 stat->nrootlps = 0; 278 stat->nprimallps = 0; 279 stat->nprimalzeroitlps = 0; 280 stat->nduallps = 0; 281 stat->ndualzeroitlps = 0; 282 stat->nlexduallps = 0; 283 stat->nbarrierlps = 0; 284 stat->nbarrierzeroitlps = 0; 285 stat->nprimalresolvelps = 0; 286 stat->ndualresolvelps = 0; 287 stat->nlexdualresolvelps = 0; 288 stat->nnodelps = 0; 289 stat->nnodezeroitlps = 0; 290 stat->nisstoppedcalls = 0; 291 stat->ninitlps = 0; 292 stat->ndivinglps = 0; 293 stat->nsbdivinglps = 0; 294 stat->nnumtroublelpmsgs = 0; 295 stat->nstrongbranchs = 0; 296 stat->nrootstrongbranchs = 0; 297 stat->nconflictlps = 0; 298 stat->nnlps = 0; 299 stat->maxtotaldepth = -1; 300 stat->nactiveconss = 0; 301 stat->nenabledconss = 0; 302 stat->solindex = 0; 303 stat->memsavemode = FALSE; 304 stat->nnodesbeforefirst = -1; 305 stat->ninitconssadded = 0; 306 stat->nactiveconssadded = 0; 307 stat->externmemestim = 0; 308 stat->exprlastvisitedtag = 0; 309 stat->exprlastsoltag = 0; 310 stat->exprlastdifftag = 0; 311 stat->nrunsbeforefirst = -1; 312 stat->firstprimalheur = NULL; 313 stat->firstprimaltime = SCIP_DEFAULT_INFINITY; 314 stat->firstprimalbound = SCIP_DEFAULT_INFINITY; 315 stat->firstsolgap = SCIP_DEFAULT_INFINITY; 316 stat->lastsolgap = SCIP_DEFAULT_INFINITY; 317 stat->primalzeroittime = 0.0; 318 stat->dualzeroittime = 0.0; 319 stat->barrierzeroittime = 0.0; 320 stat->maxcopytime = SCIP_REAL_MIN; 321 stat->mincopytime = SCIP_REAL_MAX; 322 stat->firstlptime = 0.0; 323 stat->firstlpdualbound = SCIP_UNKNOWN; 324 stat->ncopies = 0; 325 stat->nclockskipsleft = 0; 326 stat->nactiveexpriter = 0; 327 stat->marked_nvaridx = -1; 328 stat->marked_ncolidx = -1; 329 stat->marked_nrowidx = -1; 330 stat->branchedunbdvar = FALSE; 331 stat->bestefficacy = 0.0; 332 stat->minefficacyfac = 0.5; 333 stat->ncutpoolfails = 0; 334 335 stat->ndivesetlpiterations = 0; 336 stat->ndivesetcalls = 0; 337 stat->ndivesetlps = 0; 338 stat->totaldivesetdepth = 0; 339 340 stat->userinterrupt = FALSE; 341 stat->userrestart = FALSE; 342 stat->inrestart = FALSE; 343 stat->collectvarhistory = TRUE; 344 stat->performpresol = FALSE; 345 stat->disableenforelaxmsg = FALSE; 346 347 SCIPstatResetImplications(stat); 348 SCIPstatResetPresolving(stat, set, transprob, origprob); 349 SCIPstatResetPrimalDualIntegrals(stat, set, FALSE); 350 } 351 352 /** reset implication counter */ 353 void SCIPstatResetImplications( 354 SCIP_STAT* stat /**< problem statistics data */ 355 ) 356 { 357 assert(stat != NULL); 358 359 stat->nimplications = 0; 360 } 361 362 /** reset presolving and current run specific statistics */ 363 void SCIPstatResetPresolving( 364 SCIP_STAT* stat, /**< problem statistics data */ 365 SCIP_SET* set, /**< global SCIP settings */ 366 SCIP_PROB* transprob, /**< transformed problem, or NULL if not yet existing */ 367 SCIP_PROB* origprob /**< original problem, or NULL */ 368 ) 369 { 370 assert(stat != NULL); 371 372 stat->npresolrounds = 0; 373 stat->npresolroundsfast = 0; 374 stat->npresolroundsmed = 0; 375 stat->npresolroundsext = 0; 376 stat->npresolfixedvars = 0; 377 stat->npresolaggrvars = 0; 378 stat->npresolchgvartypes = 0; 379 stat->npresolchgbds = 0; 380 stat->npresoladdholes = 0; 381 stat->npresoldelconss = 0; 382 stat->npresoladdconss = 0; 383 stat->npresolupgdconss = 0; 384 stat->npresolchgcoefs = 0; 385 stat->npresolchgsides = 0; 386 387 SCIPstatResetCurrentRun(stat, set, transprob, origprob, FALSE); 388 } 389 390 /** reset primal-dual, primal-reference, and reference-dual integral */ 391 void SCIPstatResetPrimalDualIntegrals( 392 SCIP_STAT* stat, /**< problem statistics data */ 393 SCIP_SET* set, /**< global SCIP settings */ 394 SCIP_Bool partialreset /**< should time and integral value be kept? (in combination with no statistical 395 * reset, integrals are added for each problem to be solved) */ 396 ) 397 { 398 assert(stat != NULL); 399 400 stat->previousgap = 100.0; 401 stat->previousdualrefgap = 100.0; 402 stat->previousprimalrefgap = 100.0; 403 stat->lastprimalbound = SCIP_UNKNOWN; 404 stat->lastdualbound = SCIP_UNKNOWN; 405 stat->lastlowerbound = -SCIPsetInfinity(set); 406 stat->lastupperbound = SCIPsetInfinity(set); 407 408 /* partial resets keep the integral value and previous evaluation time */ 409 if( !partialreset ) 410 { 411 stat->previntegralevaltime = 0.0; 412 stat->dualrefintegral = 0.0; 413 stat->primalrefintegral = 0.0; 414 stat->primaldualintegral = 0.0; 415 } 416 } 417 418 /** returns the gap bounded by 100 */ 419 static 420 SCIP_Real getGap( 421 SCIP_SET* set, /**< global SCIP settings */ 422 SCIP_Real primalbound, /**< current primal bound */ 423 SCIP_Real dualbound, /**< current dual bound */ 424 SCIP_Real upperbound, /**< current upper bound in transformed problem, or infinity */ 425 SCIP_Real lowerbound /**< current lower bound in transformed space, or -infinity */ 426 ) 427 { 428 SCIP_Real gap; 429 430 /* computation of the gap, special cases are handled first */ 431 if( primalbound >= SCIP_UNKNOWN || dualbound >= SCIP_UNKNOWN ) /*lint !e777*/ 432 gap = 100.0; 433 /* the gap is 0.0 if bounds coincide */ 434 else if( SCIPsetIsGE(set, lowerbound, upperbound) || SCIPsetIsEQ(set, primalbound, dualbound) ) 435 gap = 0.0; 436 /* the gap is 100.0 if bounds have different signs */ 437 else if( primalbound * dualbound <= 0.0 ) /*lint !e777*/ 438 gap = 100.0; 439 else if( !SCIPsetIsInfinity(set, REALABS(primalbound)) && !SCIPsetIsInfinity(set, REALABS(dualbound)) ) 440 { 441 SCIP_Real absprim = REALABS(primalbound); 442 SCIP_Real absdual = REALABS(dualbound); 443 444 /* The gap in the definition of the primal-dual integral differs from the default SCIP gap function. 445 * Here, the MAX(primalbound, dualbound) is taken for gap quotient in order to ensure a gap <= 100. 446 */ 447 gap = 100.0 * REALABS(primalbound - dualbound) / MAX(absprim, absdual); 448 assert(SCIPsetIsLE(set, gap, 100.0)); 449 } 450 else 451 gap = 100.0; 452 453 return gap; 454 } 455 456 /** update the primal-dual, primal-reference, and reference-dual integral statistics. 457 * method accepts + and - SCIPsetInfinity() as values for upper and lower bound, respectively 458 */ 459 void SCIPstatUpdatePrimalDualIntegrals( 460 SCIP_STAT* stat, /**< problem statistics data */ 461 SCIP_SET* set, /**< global SCIP settings */ 462 SCIP_PROB* transprob, /**< transformed problem */ 463 SCIP_PROB* origprob, /**< original problem */ 464 SCIP_Real upperbound, /**< current upper bound in transformed problem, or infinity */ 465 SCIP_Real lowerbound /**< current lower bound in transformed space, or -infinity */ 466 ) 467 { 468 SCIP_Real currentgap; 469 SCIP_Real currentdualrefgap; 470 SCIP_Real currentprimalrefgap; 471 SCIP_Real solvingtime; 472 SCIP_Real primalbound; 473 SCIP_Real dualbound; 474 SCIP_Real deltatime; 475 476 assert(stat != NULL); 477 assert(set != NULL); 478 479 solvingtime = SCIPclockGetTime(stat->solvingtime); 480 assert(solvingtime >= stat->previntegralevaltime); 481 482 if( !SCIPsetIsInfinity(set, upperbound) ) /*lint !e777*/ 483 { 484 /* get value in original space for gap calculation */ 485 primalbound = SCIPprobExternObjval(transprob, origprob, set, upperbound); 486 487 if( SCIPsetIsZero(set, primalbound) ) 488 primalbound = 0.0; 489 } 490 else 491 { 492 /* no new upper bound: use stored values from last update */ 493 upperbound = stat->lastupperbound; 494 primalbound = stat->lastprimalbound; 495 assert(SCIPsetIsZero(set, primalbound) == (primalbound == 0.0)); /*lint !e777*/ 496 } 497 498 if( !SCIPsetIsInfinity(set, -lowerbound) ) /*lint !e777*/ 499 { 500 /* get value in original space for gap calculation */ 501 dualbound = SCIPprobExternObjval(transprob, origprob, set, lowerbound); 502 503 if( SCIPsetIsZero(set, dualbound) ) 504 dualbound = 0.0; 505 } 506 else 507 { 508 /* no new lower bound: use stored values from last update */ 509 lowerbound = stat->lastlowerbound; 510 dualbound = stat->lastdualbound; 511 assert(SCIPsetIsZero(set, dualbound) == (dualbound == 0.0)); /*lint !e777*/ 512 } 513 514 /* calculate primal-dual and dual reference gap */ 515 currentgap = getGap(set, primalbound, dualbound, upperbound, lowerbound); 516 517 /* if primal and dual bound have opposite signs, the gap always evaluates to 100.0% */ 518 assert(currentgap == 0.0 || currentgap == 100.0 || SCIPsetIsGE(set, primalbound * dualbound, 0.0)); 519 520 /* update the integral based on previous information */ 521 deltatime = solvingtime - stat->previntegralevaltime; 522 stat->primaldualintegral += deltatime * stat->previousgap; 523 stat->dualrefintegral += deltatime * stat->previousdualrefgap; 524 stat->primalrefintegral += deltatime * stat->previousprimalrefgap; 525 526 if( !SCIPsetIsInfinity(set, REALABS(set->misc_referencevalue)) ) 527 { 528 currentdualrefgap = getGap(set, set->misc_referencevalue, dualbound, upperbound, lowerbound); 529 assert(currentdualrefgap == 0.0 || currentdualrefgap == 100.0 || SCIPsetIsGE(set, set->misc_referencevalue * dualbound, 0.0)); 530 531 currentprimalrefgap = getGap(set, primalbound, set->misc_referencevalue, upperbound, lowerbound); 532 assert(currentprimalrefgap == 0.0 || currentprimalrefgap == 100.0 || SCIPsetIsGE(set, primalbound * set->misc_referencevalue, 0.0)); 533 } 534 else 535 { 536 currentdualrefgap = 100.0; 537 currentprimalrefgap = 100.0; 538 } 539 540 /* update all relevant information for next evaluation */ 541 stat->previousgap = currentgap; 542 stat->previousdualrefgap = currentdualrefgap; 543 stat->previousprimalrefgap = currentprimalrefgap; 544 stat->previntegralevaltime = solvingtime; 545 stat->lastprimalbound = primalbound; 546 stat->lastdualbound = dualbound; 547 stat->lastlowerbound = lowerbound; 548 stat->lastupperbound = upperbound; 549 } 550 551 /** optionally update and return the reference-dual integral statistic */ 552 SCIP_Real SCIPstatGetDualReferenceIntegral( 553 SCIP_STAT* stat, /**< problem statistics data */ 554 SCIP_SET* set, /**< global SCIP settings */ 555 SCIP_PROB* transprob, /**< transformed problem */ 556 SCIP_PROB* origprob, /**< original problem */ 557 SCIP_Bool update /**< should the value be updated first? */ 558 ) 559 { 560 assert(stat != NULL); 561 assert(set != NULL); 562 assert(transprob != NULL); 563 assert(origprob != NULL); 564 565 /* update the reference-dual integral first */ 566 if( update ) 567 SCIPstatUpdatePrimalDualIntegrals(stat, set, transprob, origprob, SCIPsetInfinity(set), -SCIPsetInfinity(set)); 568 569 return stat->dualrefintegral; 570 } 571 572 /** optionally update and return the primal-reference integral statistic */ 573 SCIP_Real SCIPstatGetPrimalReferenceIntegral( 574 SCIP_STAT* stat, /**< problem statistics data */ 575 SCIP_SET* set, /**< global SCIP settings */ 576 SCIP_PROB* transprob, /**< transformed problem */ 577 SCIP_PROB* origprob, /**< original problem */ 578 SCIP_Bool update /**< should the value be updated first? */ 579 ) 580 { 581 assert(stat != NULL); 582 assert(set != NULL); 583 assert(transprob != NULL); 584 assert(origprob != NULL); 585 586 /* update the primal-reference integral first */ 587 if( update ) 588 SCIPstatUpdatePrimalDualIntegrals(stat, set, transprob, origprob, SCIPsetInfinity(set), -SCIPsetInfinity(set)); 589 590 return stat->primalrefintegral; 591 } 592 593 /** optionally update and return the primal-dual integral statistic */ 594 SCIP_Real SCIPstatGetPrimalDualIntegral( 595 SCIP_STAT* stat, /**< problem statistics data */ 596 SCIP_SET* set, /**< global SCIP settings */ 597 SCIP_PROB* transprob, /**< transformed problem */ 598 SCIP_PROB* origprob, /**< original problem */ 599 SCIP_Bool update /**< should the value be updated first? */ 600 ) 601 { 602 assert(stat != NULL); 603 assert(set != NULL); 604 assert(transprob != NULL); 605 assert(origprob != NULL); 606 607 /* update the primal dual reference integral first */ 608 if( update ) 609 SCIPstatUpdatePrimalDualIntegrals(stat, set, transprob, origprob, SCIPsetInfinity(set), -SCIPsetInfinity(set)); 610 611 return stat->primaldualintegral; 612 } 613 614 /** reset current branch and bound run specific statistics */ 615 void SCIPstatResetCurrentRun( 616 SCIP_STAT* stat, /**< problem statistics data */ 617 SCIP_SET* set, /**< global SCIP settings */ 618 SCIP_PROB* transprob, /**< transformed problem, or NULL */ 619 SCIP_PROB* origprob, /**< original problem, or NULL */ 620 SCIP_Bool solved /**< is problem already solved? */ 621 ) 622 { 623 assert(stat != NULL); 624 625 stat->nnodes = 0; 626 stat->ninternalnodes = 0; 627 stat->ncreatednodesrun = 0; 628 stat->nactivatednodes = 0; 629 stat->ndeactivatednodes = 0; 630 stat->nbacktracks = 0; 631 stat->ndelayedcutoffs = 0; 632 stat->nreprops = 0; 633 stat->nrepropboundchgs = 0; 634 stat->nrepropcutoffs = 0; 635 stat->lastdivenode = 0; 636 stat->lastconflictnode = 0; 637 stat->bestsolnode = 0; 638 stat->rootlowerbound = SCIP_REAL_MIN; 639 stat->lastbranchvalue = SCIP_UNKNOWN; 640 stat->rootlpbestestimate = SCIP_INVALID; 641 stat->lastbranchvar = NULL; 642 stat->lastbranchdir = SCIP_BRANCHDIR_DOWNWARDS; 643 stat->nrootboundchgsrun = 0; 644 stat->nrootintfixingsrun = 0; 645 stat->npricerounds = 0; 646 stat->nseparounds = 0; 647 stat->maxdepth = -1; 648 stat->plungedepth = 0; 649 stat->nobjleaves = 0; 650 stat->ninfeasleaves = 0; 651 stat->nfeasleaves = 0; 652 stat->branchedunbdvar = FALSE; 653 stat->nnumtroublelpmsgs = 0; 654 655 stat->nearlybacktracks = 0; 656 stat->nnodesaboverefbound = 0; 657 658 assert(transprob == NULL || origprob != NULL); 659 /* calculate the reference bound in transformed space from the reference value */ 660 if( transprob != NULL && !SCIPsetIsInfinity(set, SCIPsetGetReferencevalue(set)) ) 661 stat->referencebound = SCIPprobInternObjval(transprob, origprob, set, SCIPsetGetReferencevalue(set)); 662 else 663 stat->referencebound = SCIPsetInfinity(set); 664 665 if( !solved ) 666 stat->status = SCIP_STATUS_UNKNOWN; 667 668 SCIPhistoryReset(stat->glbhistorycrun); 669 670 SCIPregressionReset(stat->regressioncandsobjval); 671 672 SCIPstatResetDisplay(stat); 673 } 674 675 /** resets display statistics, such that a new header line is displayed before the next display line */ 676 void SCIPstatResetDisplay( 677 SCIP_STAT* stat /**< problem statistics data */ 678 ) 679 { 680 assert(stat != NULL); 681 682 stat->lastdispnode = 0; 683 stat->ndisplines = 0; 684 } 685 686 /** increases LP count, such that all lazy updates depending on the LP are enforced again */ 687 void SCIPstatEnforceLPUpdates( 688 SCIP_STAT* stat /**< problem statistics data */ 689 ) 690 { 691 assert(stat != NULL); 692 693 stat->lpcount++; 694 } 695 696 /** depending on the current memory usage, switches mode flag to standard or memory saving mode */ 697 void SCIPstatUpdateMemsaveMode( 698 SCIP_STAT* stat, /**< problem statistics data */ 699 SCIP_SET* set, /**< global SCIP settings */ 700 SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */ 701 SCIP_MEM* mem /**< block memory pools */ 702 ) 703 { 704 assert(stat != NULL); 705 assert(set != NULL); 706 707 if( SCIPsetIsLT(set, set->mem_savefac, 1.0) ) 708 { 709 SCIP_Longint memused; 710 711 memused = SCIPmemGetTotal(mem); 712 if( !stat->memsavemode && memused >= set->mem_savefac * set->limit_memory * 1024.0 * 1024.0 ) 713 { 714 /* switch to memory saving mode */ 715 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH, 716 "(node %" SCIP_LONGINT_FORMAT ") switching to memory saving mode (mem: %.1fM/%.1fM)\n", 717 stat->nnodes, (SCIP_Real)memused/(1024.0*1024.0), set->limit_memory); 718 stat->memsavemode = TRUE; 719 set->nodesel = NULL; 720 } 721 else if( stat->memsavemode && memused < 0.5 * set->mem_savefac * set->limit_memory * 1024.0 * 1024.0 ) 722 { 723 /* switch to standard mode */ 724 SCIPmessagePrintVerbInfo(messagehdlr, set->disp_verblevel, SCIP_VERBLEVEL_HIGH, 725 "(node %" SCIP_LONGINT_FORMAT ") switching to standard mode (mem: %.1fM/%.1fM)\n", 726 stat->nnodes, (SCIP_Real)memused/(1024.0*1024.0), set->limit_memory); 727 stat->memsavemode = FALSE; 728 set->nodesel = NULL; 729 } 730 } 731 else 732 stat->memsavemode = FALSE; 733 } 734 735 /** returns the estimated number of bytes used by extern software, e.g., the LP solver */ 736 SCIP_Longint SCIPstatGetMemExternEstim( 737 SCIP_STAT* stat /**< dynamic SCIP statistics */ 738 ) 739 { 740 return stat->externmemestim; 741 } 742 743 /** enables or disables all statistic clocks of \p stat concerning LP execution time, strong branching time, etc. 744 * 745 * @note: The (pre-)solving time clocks which are relevant for the output during (pre-)solving 746 * are not affected by this method 747 * 748 * @see: For completely disabling all timing of SCIP, consider setting the parameter timing/enabled to FALSE 749 */ 750 void SCIPstatEnableOrDisableStatClocks( 751 SCIP_STAT* stat, /**< SCIP statistics */ 752 SCIP_Bool enable /**< should the LP clocks be enabled? */ 753 ) 754 { 755 assert(stat != NULL); 756 757 SCIPclockEnableOrDisable(stat->primallptime, enable); 758 SCIPclockEnableOrDisable(stat->duallptime, enable); 759 SCIPclockEnableOrDisable(stat->lexduallptime, enable); 760 SCIPclockEnableOrDisable(stat->barrierlptime, enable); 761 SCIPclockEnableOrDisable(stat->resolveinstablelptime, enable); 762 SCIPclockEnableOrDisable(stat->divinglptime, enable); 763 SCIPclockEnableOrDisable(stat->strongbranchtime, enable); 764 SCIPclockEnableOrDisable(stat->conflictlptime, enable); 765 SCIPclockEnableOrDisable(stat->lpsoltime, enable); 766 SCIPclockEnableOrDisable(stat->relaxsoltime, enable); 767 SCIPclockEnableOrDisable(stat->pseudosoltime, enable); 768 SCIPclockEnableOrDisable(stat->sbsoltime, enable); 769 SCIPclockEnableOrDisable(stat->nodeactivationtime, enable); 770 SCIPclockEnableOrDisable(stat->nlpsoltime, enable); 771 SCIPclockEnableOrDisable(stat->copyclock, enable); 772 SCIPclockEnableOrDisable(stat->strongpropclock, enable); 773 } 774 775 /** recompute root LP best-estimate from scratch */ 776 void SCIPstatComputeRootLPBestEstimate( 777 SCIP_STAT* stat, /**< SCIP statistics */ 778 SCIP_SET* set, /**< global SCIP settings */ 779 SCIP_Real rootlpobjval, /**< root LP objective value */ 780 SCIP_VAR** vars, /**< problem variables */ 781 int nvars /**< number of variables */ 782 ) 783 { 784 int v; 785 stat->rootlpbestestimate = rootlpobjval; 786 787 /* compute best-estimate contribution for every variable */ 788 for( v = 0; v < nvars; ++v ) 789 { 790 SCIP_Real rootlpsol; 791 SCIP_Real varminpseudoscore; 792 793 /* stop at the first continuous variable */ 794 if( !SCIPvarIsIntegral(vars[v]) ) 795 break; 796 797 rootlpsol = SCIPvarGetRootSol(vars[v]); 798 varminpseudoscore = SCIPvarGetMinPseudocostScore(vars[v], stat, set, rootlpsol); 799 assert(varminpseudoscore >= 0); 800 stat->rootlpbestestimate += varminpseudoscore; 801 802 SCIPstatDebugMsg(stat, "Root LP Estimate initialization: <%s> + %15.9f\n", SCIPvarGetName(vars[v]), varminpseudoscore); 803 } 804 } 805 806 /** update root LP best-estimate with changed variable pseudo-costs */ 807 SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate( 808 SCIP_STAT* stat, /**< SCIP statistics */ 809 SCIP_SET* set, /**< global SCIP settings */ 810 SCIP_VAR* var, /**< variable with changed pseudo costs */ 811 SCIP_Real oldrootpscostscore /**< old minimum pseudo cost score of variable */ 812 ) 813 { 814 SCIP_Real rootlpsol; 815 SCIP_Real varminpseudoscore; 816 817 assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN || SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE ); 818 819 /* entire root LP best-estimate must be computed from scratch first */ 820 if( stat->rootlpbestestimate == SCIP_INVALID ) /*lint !e777*/ 821 return SCIP_OKAY; 822 823 rootlpsol = SCIPvarGetRootSol(var); 824 825 /* LP root estimate only works for variables with fractional LP root solution */ 826 if( SCIPsetIsFeasIntegral(set, rootlpsol) ) 827 return SCIP_OKAY; 828 829 /* subtract old pseudo cost contribution and add new contribution afterwards */ 830 stat->rootlpbestestimate -= oldrootpscostscore; 831 832 varminpseudoscore = SCIPvarGetMinPseudocostScore(var, stat, set, rootlpsol); 833 assert(varminpseudoscore >= 0.0); 834 stat->rootlpbestestimate += varminpseudoscore; 835 836 SCIPstatDebugMsg(stat, "Root LP estimate update: <%s> - %15.9f + %15.9f\n", SCIPvarGetName(var), oldrootpscostscore, varminpseudoscore); 837 838 return SCIP_OKAY; 839 } 840 841 /** prints a debug message */ 842 void SCIPstatPrintDebugMessage( 843 SCIP_STAT* stat, /**< SCIP statistics */ 844 const char* sourcefile, /**< name of the source file that called the function */ 845 int sourceline, /**< line in the source file where the function was called */ 846 const char* formatstr, /**< format string like in printf() function */ 847 ... /**< format arguments line in printf() function */ 848 ) 849 { 850 const char* filename; 851 va_list ap; 852 853 assert( sourcefile != NULL ); 854 assert( stat != NULL ); 855 856 /* strip directory from filename */ 857 #if defined(_WIN32) || defined(_WIN64) 858 filename = strrchr(sourcefile, '\\'); 859 #else 860 filename = strrchr(sourcefile, '/'); 861 #endif 862 if ( filename == NULL ) 863 filename = sourcefile; 864 else 865 ++filename; 866 867 if ( stat->subscipdepth > 0 ) 868 printf("%d: [%s:%d] debug: ", stat->subscipdepth, filename, sourceline); 869 else 870 printf("[%s:%d] debug: ", filename, sourceline); 871 872 va_start(ap, formatstr); /*lint !e838*/ 873 printf(formatstr, ap); 874 va_end(ap); 875 } 876 877 /** prints a debug message without precode */ 878 void SCIPstatDebugMessagePrint( 879 SCIP_STAT* stat, /**< SCIP statistics */ 880 const char* formatstr, /**< format string like in printf() function */ 881 ... /**< format arguments line in printf() function */ 882 ) 883 { /*lint --e{715}*/ 884 va_list ap; 885 886 assert(stat != NULL); 887 888 va_start(ap, formatstr); /*lint !e838*/ 889 printf(formatstr, ap); 890 va_end(ap); 891 } 892