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   scip_timing.c
26   	 * @ingroup OTHER_CFILES
27   	 * @brief  public methods for timing
28   	 * @author Tobias Achterberg
29   	 * @author Timo Berthold
30   	 * @author Gerald Gamrath
31   	 * @author Leona Gottwald
32   	 * @author Stefan Heinz
33   	 * @author Gregor Hendel
34   	 * @author Thorsten Koch
35   	 * @author Alexander Martin
36   	 * @author Marc Pfetsch
37   	 * @author Michael Winkler
38   	 * @author Kati Wolter
39   	 *
40   	 * @todo check all SCIP_STAGE_* switches, and include the new stages TRANSFORMED and INITSOLVE
41   	 */
42   	
43   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
44   	
45   	#include "scip/clock.h"
46   	#include "scip/conflict.h"
47   	#include "scip/debug.h"
48   	#include "scip/pub_message.h"
49   	#include "scip/reader.h"
50   	#include "scip/scip_numerics.h"
51   	#include "scip/scip_timing.h"
52   	#include "scip/set.h"
53   	#include "scip/stat.h"
54   	#include "scip/struct_scip.h"
55   	#include "scip/struct_set.h"
56   	#include "scip/struct_stat.h"
57   	
58   	/** gets current time of day in seconds (standard time zone)
59   	 *
60   	 *  @return the current time of day in seconds (standard time zone).
61   	 */
62   	SCIP_Real SCIPgetTimeOfDay(
63   	   SCIP*                 scip                /**< SCIP data structure */
64   	   )
65   	{
66   	   assert(scip != NULL);
67   	
68   	   return SCIPclockGetTimeOfDay();
69   	}
70   	
71   	/** creates a clock using the default clock type
72   	 *
73   	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
74   	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
75   	 */
76   	SCIP_RETCODE SCIPcreateClock(
77   	   SCIP*                 scip,               /**< SCIP data structure */
78   	   SCIP_CLOCK**          clck                /**< pointer to clock timer */
79   	   )
80   	{
81   	   assert(scip != NULL);
82   	
83   	   SCIP_CALL( SCIPclockCreate(clck, SCIP_CLOCKTYPE_DEFAULT) );
84   	
85   	   return SCIP_OKAY;
86   	}
87   	
88   	/** creates a clock counting the CPU user seconds
89   	 *
90   	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
91   	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
92   	 */
93   	SCIP_RETCODE SCIPcreateCPUClock(
94   	   SCIP*                 scip,               /**< SCIP data structure */
95   	   SCIP_CLOCK**          clck                /**< pointer to clock timer */
96   	   )
97   	{
98   	   assert(scip != NULL);
99   	
100  	   SCIP_CALL( SCIPclockCreate(clck, SCIP_CLOCKTYPE_CPU) );
101  	
102  	   return SCIP_OKAY;
103  	}
104  	
105  	/** creates a clock counting the wall clock seconds
106  	 *
107  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
108  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
109  	 */
110  	SCIP_RETCODE SCIPcreateWallClock(
111  	   SCIP*                 scip,               /**< SCIP data structure */
112  	   SCIP_CLOCK**          clck                /**< pointer to clock timer */
113  	   )
114  	{
115  	   assert(scip != NULL);
116  	
117  	   SCIP_CALL( SCIPclockCreate(clck, SCIP_CLOCKTYPE_WALL) );
118  	
119  	   return SCIP_OKAY;
120  	}
121  	
122  	/** frees a clock
123  	 *
124  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
125  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
126  	 */
127  	SCIP_RETCODE SCIPfreeClock(
128  	   SCIP*                 scip,               /**< SCIP data structure */
129  	   SCIP_CLOCK**          clck                /**< pointer to clock timer */
130  	   )
131  	{
132  	   assert(scip != NULL);
133  	
134  	   SCIPclockFree(clck);
135  	
136  	   return SCIP_OKAY;
137  	}
138  	
139  	/** resets the time measurement of a clock to zero and completely stops the clock
140  	 *
141  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
142  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
143  	 */
144  	SCIP_RETCODE SCIPresetClock(
145  	   SCIP*                 scip,               /**< SCIP data structure */
146  	   SCIP_CLOCK*           clck                /**< clock timer */
147  	   )
148  	{
149  	   assert(scip != NULL);
150  	
151  	   SCIPclockReset(clck);
152  	
153  	   return SCIP_OKAY;
154  	}
155  	
156  	/** starts the time measurement of a clock
157  	 *
158  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
159  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
160  	 */
161  	SCIP_RETCODE SCIPstartClock(
162  	   SCIP*                 scip,               /**< SCIP data structure */
163  	   SCIP_CLOCK*           clck                /**< clock timer */
164  	   )
165  	{
166  	   assert(scip != NULL);
167  	
168  	   SCIPclockStart(clck, scip->set);
169  	
170  	   return SCIP_OKAY;
171  	}
172  	
173  	/** stops the time measurement of a clock
174  	 *
175  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
176  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
177  	 */
178  	SCIP_RETCODE SCIPstopClock(
179  	   SCIP*                 scip,               /**< SCIP data structure */
180  	   SCIP_CLOCK*           clck                /**< clock timer */
181  	   )
182  	{
183  	   assert(scip != NULL);
184  	
185  	   SCIPclockStop(clck, scip->set);
186  	
187  	   return SCIP_OKAY;
188  	}
189  	
190  	/** enables or disables \p clck */
191  	void SCIPsetClockEnabled(
192  	   SCIP_CLOCK*           clck,               /**< the clock to be disabled/enabled */
193  	   SCIP_Bool             enable              /**< should the clock be enabled or disabled? */
194  	   )
195  	{
196  	   SCIPclockEnableOrDisable(clck, enable);
197  	}
198  	
199  	/** enables or disables all statistic clocks of SCIP concerning plugin statistics,
200  	 *  LP execution time, strong branching time, etc.
201  	 *
202  	 *  Method reads the value of the parameter timing/statistictiming. In order to disable statistic timing,
203  	 *  set the parameter to FALSE.
204  	 *
205  	 *  @note: The (pre-)solving time clocks which are relevant for the output during (pre-)solving
206  	 *         are not affected by this method
207  	 *
208  	 *  @see: For completely disabling all timing of SCIP, consider setting the parameter timing/enabled to FALSE
209  	 *
210  	 *  @pre This method can be called if SCIP is in one of the following stages:
211  	 *       - \ref SCIP_STAGE_INIT
212  	 *       - \ref SCIP_STAGE_PROBLEM
213  	 *       - \ref SCIP_STAGE_TRANSFORMING
214  	 *       - \ref SCIP_STAGE_TRANSFORMED
215  	 *       - \ref SCIP_STAGE_INITPRESOLVE
216  	 *       - \ref SCIP_STAGE_PRESOLVING
217  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
218  	 *       - \ref SCIP_STAGE_PRESOLVED
219  	 *       - \ref SCIP_STAGE_INITSOLVE
220  	 *       - \ref SCIP_STAGE_SOLVING
221  	 *       - \ref SCIP_STAGE_SOLVED
222  	 *       - \ref SCIP_STAGE_EXITSOLVE
223  	 *       - \ref SCIP_STAGE_FREETRANS
224  	 *
225  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
226  	 */
227  	SCIP_RETCODE SCIPenableOrDisableStatisticTiming(
228  	   SCIP*                 scip                /**< SCIP data structure */
229  	   )
230  	{
231  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPenableOrDisableStatisticTiming", TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
232  	
233  	   SCIPsetEnableOrDisablePluginClocks(scip->set, scip->set->time_statistictiming);
234  	
235  	   if( scip->set->stage > SCIP_STAGE_INIT )
236  	   {
237  	      assert(scip->stat != NULL);
238  	      SCIPstatEnableOrDisableStatClocks(scip->stat, scip->set->time_statistictiming);
239  	   }
240  	   if( scip->set->stage >= SCIP_STAGE_TRANSFORMING )
241  	   {
242  	      assert(scip->conflict != NULL);
243  	      SCIPconflictEnableOrDisableClocks(scip->conflict, scip->set->time_statistictiming);
244  	   }
245  	
246  	   return SCIP_OKAY;
247  	}
248  	
249  	/** starts the current solving time
250  	 *
251  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
252  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
253  	 *
254  	 *  @pre This method can be called if SCIP is in one of the following stages:
255  	 *       - \ref SCIP_STAGE_PROBLEM
256  	 *       - \ref SCIP_STAGE_TRANSFORMING
257  	 *       - \ref SCIP_STAGE_TRANSFORMED
258  	 *       - \ref SCIP_STAGE_INITPRESOLVE
259  	 *       - \ref SCIP_STAGE_PRESOLVING
260  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
261  	 *       - \ref SCIP_STAGE_PRESOLVED
262  	 *       - \ref SCIP_STAGE_INITSOLVE
263  	 *       - \ref SCIP_STAGE_SOLVING
264  	 *       - \ref SCIP_STAGE_SOLVED
265  	 *       - \ref SCIP_STAGE_EXITSOLVE
266  	 *       - \ref SCIP_STAGE_FREETRANS
267  	 *
268  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
269  	 */
270  	SCIP_RETCODE SCIPstartSolvingTime(
271  	   SCIP*                 scip                /**< SCIP data structure */
272  	   )
273  	{
274  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPstartSolvingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
275  	
276  	   SCIPclockStart(scip->stat->solvingtime, scip->set);
277  	   SCIPclockStart(scip->stat->solvingtimeoverall, scip->set);
278  	
279  	   return SCIP_OKAY;
280  	}
281  	
282  	/** stops the current solving time in seconds
283  	 *
284  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
285  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
286  	 *
287  	 *  @pre This method can be called if SCIP is in one of the following stages:
288  	 *       - \ref SCIP_STAGE_PROBLEM
289  	 *       - \ref SCIP_STAGE_TRANSFORMING
290  	 *       - \ref SCIP_STAGE_TRANSFORMED
291  	 *       - \ref SCIP_STAGE_INITPRESOLVE
292  	 *       - \ref SCIP_STAGE_PRESOLVING
293  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
294  	 *       - \ref SCIP_STAGE_PRESOLVED
295  	 *       - \ref SCIP_STAGE_INITSOLVE
296  	 *       - \ref SCIP_STAGE_SOLVING
297  	 *       - \ref SCIP_STAGE_SOLVED
298  	 *       - \ref SCIP_STAGE_EXITSOLVE
299  	 *       - \ref SCIP_STAGE_FREETRANS
300  	 *
301  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
302  	 */
303  	SCIP_RETCODE SCIPstopSolvingTime(
304  	   SCIP*                 scip                /**< SCIP data structure */
305  	   )
306  	{
307  	   SCIP_CALL( SCIPcheckStage(scip, "SCIPstopSolvingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE) );
308  	
309  	   SCIPclockStop(scip->stat->solvingtime, scip->set);
310  	   SCIPclockStop(scip->stat->solvingtimeoverall, scip->set);
311  	
312  	   return SCIP_OKAY;
313  	}
314  	
315  	/** gets the measured time of a clock in seconds
316  	 *
317  	 *  @return the measured time of a clock in seconds.
318  	 */
319  	SCIP_Real SCIPgetClockTime(
320  	   SCIP*                 scip,               /**< SCIP data structure */
321  	   SCIP_CLOCK*           clck                /**< clock timer */
322  	   )
323  	{
324  	   assert(scip != NULL);
325  	
326  	   return SCIPclockGetTime(clck);
327  	}
328  	
329  	/** sets the measured time of a clock to the given value in seconds
330  	 *
331  	 *  @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
332  	 *          SCIP_Retcode "SCIP_RETCODE" for a complete list of error codes.
333  	 */
334  	SCIP_RETCODE SCIPsetClockTime(
335  	   SCIP*                 scip,               /**< SCIP data structure */
336  	   SCIP_CLOCK*           clck,               /**< clock timer */
337  	   SCIP_Real             sec                 /**< time in seconds to set the clock's timer to */
338  	   )
339  	{
340  	   assert(scip != NULL);
341  	
342  	   SCIPclockSetTime(clck, sec);
343  	
344  	   return SCIP_OKAY;
345  	}
346  	
347  	/** gets the current total SCIP time in seconds, possibly accumulated over several problems.
348  	 *
349  	 *  @return the current total SCIP time in seconds, ie. the total time since the SCIP instance has been created
350  	 */
351  	SCIP_Real SCIPgetTotalTime(
352  	   SCIP*                 scip                /**< SCIP data structure */
353  	   )
354  	{
355  	   assert(scip != NULL);
356  	
357  	   return SCIPclockGetTime(scip->totaltime);
358  	}
359  	
360  	/** gets the current solving time in seconds
361  	 *
362  	 *  @return the current solving time in seconds.
363  	 *
364  	 *  @pre This method can be called if SCIP is in one of the following stages:
365  	 *       - \ref SCIP_STAGE_PROBLEM
366  	 *       - \ref SCIP_STAGE_TRANSFORMING
367  	 *       - \ref SCIP_STAGE_TRANSFORMED
368  	 *       - \ref SCIP_STAGE_INITPRESOLVE
369  	 *       - \ref SCIP_STAGE_PRESOLVING
370  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
371  	 *       - \ref SCIP_STAGE_PRESOLVED
372  	 *       - \ref SCIP_STAGE_INITSOLVE
373  	 *       - \ref SCIP_STAGE_SOLVING
374  	 *       - \ref SCIP_STAGE_SOLVED
375  	 *
376  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
377  	 */
378  	SCIP_Real SCIPgetSolvingTime(
379  	   SCIP*                 scip                /**< SCIP data structure */
380  	   )
381  	{
382  	   SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetSolvingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
383  	
384  	   return SCIPclockGetTime(scip->stat->solvingtime);
385  	}
386  	
387  	/** gets the current reading time in seconds
388  	 *
389  	 *  @return the current reading time in seconds.
390  	 *
391  	 *  @pre This method can be called if SCIP is in one of the following stages:
392  	 *       - \ref SCIP_STAGE_PROBLEM
393  	 *       - \ref SCIP_STAGE_TRANSFORMING
394  	 *       - \ref SCIP_STAGE_TRANSFORMED
395  	 *       - \ref SCIP_STAGE_INITPRESOLVE
396  	 *       - \ref SCIP_STAGE_PRESOLVING
397  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
398  	 *       - \ref SCIP_STAGE_PRESOLVED
399  	 *       - \ref SCIP_STAGE_INITSOLVE
400  	 *       - \ref SCIP_STAGE_SOLVING
401  	 *       - \ref SCIP_STAGE_SOLVED
402  	 *
403  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
404  	 */
405  	SCIP_Real SCIPgetReadingTime(
406  	   SCIP*                 scip                /**< SCIP data structure */
407  	   )
408  	{
409  	   SCIP_Real readingtime;
410  	   int r;
411  	
412  	   SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetReadingTime", FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
413  	
414  	   readingtime = 0.0;
415  	
416  	   /* sum up the reading time of all readers */
417  	   for( r = 0; r < scip->set->nreaders; ++r )
418  	   {
419  	      assert(scip->set->readers[r] != NULL);
420  	      assert(!SCIPisNegative(scip, SCIPreaderGetReadingTime(scip->set->readers[r])));
421  	      readingtime += SCIPreaderGetReadingTime(scip->set->readers[r]);
422  	   }
423  	
424  	   return readingtime;
425  	}
426  	
427  	/** gets the current presolving time in seconds
428  	 *
429  	 *  @return the current presolving time in seconds.
430  	 *
431  	 *  @pre This method can be called if SCIP is in one of the following stages:
432  	 *       - \ref SCIP_STAGE_INITPRESOLVE
433  	 *       - \ref SCIP_STAGE_PRESOLVING
434  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
435  	 *       - \ref SCIP_STAGE_PRESOLVED
436  	 *       - \ref SCIP_STAGE_INITSOLVE
437  	 *       - \ref SCIP_STAGE_SOLVING
438  	 *       - \ref SCIP_STAGE_SOLVED
439  	 *
440  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
441  	 */
442  	SCIP_Real SCIPgetPresolvingTime(
443  	   SCIP*                 scip                /**< SCIP data structure */
444  	   )
445  	{
446  	   SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetPresolvingTime", FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
447  	
448  	   return SCIPclockGetTime(scip->stat->presolvingtime);
449  	}
450  	
451  	/** gets the time need to solve the first LP in the root node
452  	 *
453  	 *  @return the solving time for the first LP in the root node in seconds.
454  	 *
455  	 *  @pre This method can be called if SCIP is in one of the following stages:
456  	 *       - \ref SCIP_STAGE_TRANSFORMING
457  	 *       - \ref SCIP_STAGE_TRANSFORMED
458  	 *       - \ref SCIP_STAGE_INITPRESOLVE
459  	 *       - \ref SCIP_STAGE_PRESOLVING
460  	 *       - \ref SCIP_STAGE_EXITPRESOLVE
461  	 *       - \ref SCIP_STAGE_PRESOLVED
462  	 *       - \ref SCIP_STAGE_INITSOLVE
463  	 *       - \ref SCIP_STAGE_SOLVING
464  	 *       - \ref SCIP_STAGE_SOLVED
465  	 *
466  	 *  See \ref SCIP_Stage "SCIP_STAGE" for a complete list of all possible solving stages.
467  	 */
468  	SCIP_Real SCIPgetFirstLPTime(
469  	   SCIP*                 scip                /**< SCIP data structure */
470  	   )
471  	{
472  	   SCIP_CALL_ABORT( SCIPcheckStage(scip, "SCIPgetFirstLPTime", FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE) );
473  	
474  	   return scip->stat->firstlptime;
475  	}
476