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