1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* This file is part of the program and library */
/* SCIP --- Solving Constraint Integer Programs */
/* */
/* Copyright 2002-2022 Zuse Institute Berlin */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
/* You may obtain a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* */
/* You should have received a copy of the Apache-2.0 license */
/* along with SCIP; see the file LICENSE. If not visit scipopt.org. */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**@file stat.h
* @ingroup INTERNALAPI
* @brief internal methods for problem statistics
* @author Tobias Achterberg
*/
/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
#ifndef __SCIP_STAT_H__
#define __SCIP_STAT_H__
#include "scip/def.h"
#include "blockmemshell/memory.h"
#include "scip/type_prob.h"
#include "scip/type_retcode.h"
#include "scip/type_set.h"
#include "scip/type_stat.h"
#include "scip/type_mem.h"
#include "scip/pub_message.h"
#include "scip/concurrent.h"
#include "scip/struct_stat.h"
#ifdef __cplusplus
extern "C" {
#endif
/** creates problem statistics data */
SCIP_RETCODE SCIPstatCreate(
SCIP_STAT** stat, /**< pointer to problem statistics data */
BMS_BLKMEM* blkmem, /**< block memory */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem, or NULL */
SCIP_PROB* origprob, /**< original problem, or NULL */
SCIP_MESSAGEHDLR* messagehdlr /**< message handler */
);
/** frees problem statistics data */
SCIP_RETCODE SCIPstatFree(
SCIP_STAT** stat, /**< pointer to problem statistics data */
BMS_BLKMEM* blkmem /**< block memory */
);
/** diables the collection of any statistic for a variable */
void SCIPstatDisableVarHistory(
SCIP_STAT* stat /**< problem statistics data */
);
/** enables the collection of statistics for a variable */
void SCIPstatEnableVarHistory(
SCIP_STAT* stat /**< problem statistics data */
);
/** marks statistics to be able to reset them when solving process is freed */
void SCIPstatMark(
SCIP_STAT* stat /**< problem statistics data */
);
/** reset statistics to the data before solving started */
void SCIPstatReset(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem, or NULL */
SCIP_PROB* origprob /**< original problem, or NULL */
);
/** reset implication counter */
void SCIPstatResetImplications(
SCIP_STAT* stat /**< problem statistics data */
);
/** reset presolving and current run specific statistics */
void SCIPstatResetPresolving(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem, or NULL */
SCIP_PROB* origprob /**< original problem, or NULL */
);
/** reset primal-dual, primal-reference, and dual-reference integral */
void SCIPstatResetPrimalDualIntegrals(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_Bool partialreset /**< should time and integral value be kept? (in combination with no statistical
* reset, integrals are added for each problem to be solved) */
);
/** update the primal-dual, primal-reference, and reference-dual integral statistics.
* method accepts + and - SCIPsetInfinity() as values for upper and lower bound, respectively
*/
void SCIPstatUpdatePrimalDualIntegrals(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem */
SCIP_PROB* origprob, /**< original problem */
SCIP_Real primalbound, /**< current primal bound in transformed problem, or infinity */
SCIP_Real dualbound /**< current lower bound in transformed space, or -infinity */
);
/** optionally update and return the reference-dual integral statistic */
SCIP_Real SCIPstatGetDualReferenceIntegral(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem */
SCIP_PROB* origprob, /**< original problem */
SCIP_Bool update /**< should the value be updated first? */
);
/** optionally update and return the primal-reference integral statistic */
SCIP_Real SCIPstatGetPrimalReferenceIntegral(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem */
SCIP_PROB* origprob, /**< original problem */
SCIP_Bool update /**< should the value be updated first? */
);
/** optionally update and return the primal-dual integral statistic */
SCIP_Real SCIPstatGetPrimalDualIntegral(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem */
SCIP_PROB* origprob, /**< original problem */
SCIP_Bool update /**< should the value be updated first? */
);
/** reset current branch and bound run specific statistics */
void SCIPstatResetCurrentRun(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_PROB* transprob, /**< transformed problem, or NULL */
SCIP_PROB* origprob, /**< original problem, or NULL */
SCIP_Bool solved /**< is problem already solved? */
);
/** resets display statistics, such that a new header line is displayed before the next display line */
void SCIPstatResetDisplay(
SCIP_STAT* stat /**< problem statistics data */
);
/** increases LP count, such that all lazy updates depending on the LP are enforced again */
void SCIPstatEnforceLPUpdates(
SCIP_STAT* stat /**< problem statistics data */
);
/** depending on the current memory usage, switches mode flag to standard or memory saving mode */
void SCIPstatUpdateMemsaveMode(
SCIP_STAT* stat, /**< problem statistics data */
SCIP_SET* set, /**< global SCIP settings */
SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
SCIP_MEM* mem /**< block memory pools */
);
/** returns the estimated number of bytes used by extern software, e.g., the LP solver */
SCIP_Longint SCIPstatGetMemExternEstim(
SCIP_STAT* stat /**< dynamic SCIP statistics */
);
/** enables or disables all statistic clocks of \p stat concerning LP execution time, strong branching time, etc.
*
* @note: The (pre-)solving time clocks which are relevant for the output during (pre-)solving
* are not affected by this method
*
* @see: For completely disabling all timing of SCIP, consider setting the parameter timing/enabled to FALSE
*/
void SCIPstatEnableOrDisableStatClocks(
SCIP_STAT* stat, /**< SCIP statistics */
SCIP_Bool enable /**< should the LP clocks be enabled? */
);
/** recompute root LP best-estimate from scratch */
void SCIPstatComputeRootLPBestEstimate(
SCIP_STAT* stat, /**< SCIP statistics */
SCIP_SET* set, /**< global SCIP settings */
SCIP_Real rootlpobjval, /**< root LP objective value */
SCIP_VAR** vars, /**< problem variables */
int nvars /**< number of variables */
);
/** update root LP best-estimate with changed variable pseudo-costs */
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(
SCIP_STAT* stat, /**< SCIP statistics */
SCIP_SET* set, /**< global SCIP settings */
SCIP_VAR* var, /**< variable with changed pseudo costs */
SCIP_Real oldrootpscostscore /**< old minimum pseudo cost score of variable */
);
#ifdef TPI_NONE
/* no TPI included so just update the stats */
#define SCIPstatUpdate(stat, set, field, val) do { \
(stat)->field = (val); \
} while(0)
#define SCIPstatIncrement(stat, set, field) do { \
++(stat)->field; \
} while(0)
#define SCIPstatAdd(stat, set, field, val) do { \
(stat)->field += (val); \
} while(0)
#else
/* TPI not none, so increment deterministic time for relevant stats */
#define SCIPupdateDeterministicTimeCount(stat, set, val) do { \
(stat)->detertimecnt += (val); \
if( (stat)->detertimecnt > 10000.0 ) { \
SCIP_CALL_ABORT( SCIPincrementConcurrentTime( (set)->scip, (stat)->detertimecnt ) ); \
(stat)->detertimecnt = 0.0; \
}\
} while(0) \
#define SCIPstatUpdate(stat, set, field, val) do { \
switch( offsetof(SCIP_STAT, field) ) \
{ \
default: \
break; \
case offsetof(SCIP_STAT, nprimalresolvelpiterations): \
SCIPupdateDeterministicTimeCount(stat, set, 0.00328285264101 * ((val) - (stat)->field) * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, ndualresolvelpiterations): \
SCIPupdateDeterministicTimeCount(stat, set, 0.00531625104146 * ((val) - (stat)->field) * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, nprobboundchgs): \
SCIPupdateDeterministicTimeCount(stat, set, 0.000738719124051 * ((val) - (stat)->field) * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, nisstoppedcalls): \
SCIPupdateDeterministicTimeCount(stat, set, 0.0011123144764 * ((val) - (stat)->field) * (stat)->nnz ); \
} \
(stat)->field = (val); \
} while(0)
#define SCIPstatIncrement(stat, set, field) do { \
switch( offsetof(SCIP_STAT, field) ) \
{ \
default: \
break; \
case offsetof(SCIP_STAT, nprimalresolvelpiterations): \
SCIPupdateDeterministicTimeCount(stat, set, 0.00328285264101 * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, ndualresolvelpiterations): \
SCIPupdateDeterministicTimeCount(stat, set, 0.00531625104146 * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, nprobboundchgs): \
SCIPupdateDeterministicTimeCount(stat, set, 0.000738719124051 * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, nisstoppedcalls): \
SCIPupdateDeterministicTimeCount(stat, set, 0.0011123144764 * (stat)->nnz ); \
} \
++(stat)->field; \
} while(0)
#define SCIPstatAdd(stat, set, field, val) do { \
switch( offsetof(SCIP_STAT, field) ) \
{ \
default: \
break; \
case offsetof(SCIP_STAT, nprimalresolvelpiterations): \
SCIPupdateDeterministicTimeCount(stat, set, 0.00328285264101 * (val) * (stat)->nnz); \
break; \
case offsetof(SCIP_STAT, ndualresolvelpiterations): \
SCIPupdateDeterministicTimeCount(stat, set, 0.00531625104146 * (val) * (stat)->nnz); \
break; \
case offsetof(SCIP_STAT, nprobboundchgs): \
SCIPupdateDeterministicTimeCount(stat, set, 0.000738719124051 * (val) * (stat)->nnz ); \
break; \
case offsetof(SCIP_STAT, nisstoppedcalls): \
SCIPupdateDeterministicTimeCount(stat, set, 0.0011123144764 * (val) * (stat)->nnz ); \
} \
(stat)->field += (val); \
} while(0)
#endif
/* if we have a C99 compiler */
#ifdef SCIP_HAVE_VARIADIC_MACROS
/** prints a debugging message if SCIP_DEBUG flag is set */
#ifdef SCIP_DEBUG
#define SCIPstatDebugMsg(set, ...) SCIPstatPrintDebugMessage(stat, __FILE__, __LINE__, __VA_ARGS__)
#define SCIPstatDebugMsgPrint(set, ...) SCIPstatPrintDebugMessagePrint(stat, __VA_ARGS__)
#else
#define SCIPstatDebugMsg(set, ...) while ( FALSE ) SCIPstatPrintDebugMessage(stat, __FILE__, __LINE__, __VA_ARGS__)
#define SCIPstatDebugMsgPrint(set, ...) while ( FALSE ) SCIPstatPrintDebugMessagePrint(stat, __VA_ARGS__)
#endif
#else
/* if we do not have a C99 compiler, use a workaround that prints a message, but not the file and linenumber */
/** prints a debugging message if SCIP_DEBUG flag is set */
#ifdef SCIP_DEBUG
#define SCIPstatDebugMsg printf("debug: "), SCIPstatDebugMessagePrint
#define SCIPstatDebugMsgPrint SCIPstatDebugMessagePrint
#else
#define SCIPstatDebugMsg while ( FALSE ) SCIPstatDebugMessagePrint
#define SCIPstatDebugMsgPrint while ( FALSE ) SCIPstatDebugMessagePrint
#endif
#endif
/** prints a debug message */
#ifdef __GNUC__
__attribute__((format(printf, 4, 5)))
#endif
SCIP_EXPORT
void SCIPstatPrintDebugMessage(
SCIP_STAT* stat, /**< SCIP statistics */
const char* sourcefile, /**< name of the source file that called the function */
int sourceline, /**< line in the source file where the function was called */
const char* formatstr, /**< format string like in printf() function */
... /**< format arguments line in printf() function */
);
/** prints a debug message without precode */
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
SCIP_EXPORT
void SCIPstatDebugMessagePrint(
SCIP_STAT* stat, /**< SCIP statistics */
const char* formatstr, /**< format string like in printf() function */
... /**< format arguments line in printf() function */
);
#ifdef __cplusplus
}
#endif
#endif