1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*  Copyright (c) 1996-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 SoPlex; see the file LICENSE. If not email to soplex@zib.de.  */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	#include <iostream>
26   	#include <assert.h>
27   	
28   	#include "soplex/timerfactory.h"
29   	
30   	namespace soplex
31   	{
32   	/// default constructor
33   	template <class R>
34   	SoPlexBase<R>::Statistics::Statistics(Timer::TYPE ttype)
35   	{
36   	   timerType = ttype;
37   	   readingTime = TimerFactory::createTimer(timerType);
38   	   solvingTime = TimerFactory::createTimer(timerType);
39   	   preprocessingTime = TimerFactory::createTimer(timerType);
40   	   simplexTime = TimerFactory::createTimer(timerType);
41   	   syncTime = TimerFactory::createTimer(timerType);
42   	   transformTime = TimerFactory::createTimer(timerType);
43   	   rationalTime = TimerFactory::createTimer(timerType);
44   	   initialPrecisionTime = TimerFactory::createTimer(timerType);
45   	   extendedPrecisionTime = TimerFactory::createTimer(timerType);
46   	   reconstructionTime = TimerFactory::createTimer(timerType);
47   	   boostingStepTime = TimerFactory::createTimer(timerType);
48   	   clearAllData();
49   	}
50   	
51   	/// copy constructor
52   	template <class R>
53   	SoPlexBase<R>::Statistics::Statistics(const Statistics& base)
54   	{
55   	   timerType = base.timerType;
56   	   readingTime = TimerFactory::createTimer(timerType);
57   	   solvingTime = TimerFactory::createTimer(timerType);
58   	   preprocessingTime = TimerFactory::createTimer(timerType);
59   	   simplexTime = TimerFactory::createTimer(timerType);
60   	   syncTime = TimerFactory::createTimer(timerType);
61   	   transformTime = TimerFactory::createTimer(timerType);
62   	   rationalTime = TimerFactory::createTimer(timerType);
63   	   initialPrecisionTime = TimerFactory::createTimer(timerType);
64   	   extendedPrecisionTime = TimerFactory::createTimer(timerType);
65   	   reconstructionTime = TimerFactory::createTimer(timerType);
66   	   boostingStepTime = TimerFactory::createTimer(timerType);
67   	   clearAllData();
68   	}
69   	
70   	/// assignment operator
71   	template <class R>
72   	typename SoPlexBase<R>::Statistics& SoPlexBase<R>::Statistics::operator=(const Statistics& rhs)
73   	{
74   	   *readingTime = *(rhs.readingTime);
75   	   *solvingTime = *(rhs.solvingTime);
76   	   *preprocessingTime = *(rhs.preprocessingTime);
77   	   *simplexTime = *(rhs.simplexTime);
78   	   *syncTime = *(rhs.syncTime);
79   	   *transformTime = *(rhs.transformTime);
80   	   *rationalTime = *(rhs.rationalTime);
81   	   *initialPrecisionTime = *(rhs.initialPrecisionTime);
82   	   *extendedPrecisionTime = *(rhs.extendedPrecisionTime);
83   	   *reconstructionTime = *(rhs.reconstructionTime);
84   	   *boostingStepTime = *(rhs.boostingStepTime);
85   	   timerType = rhs.timerType;
86   	   multTimeSparse = rhs.multTimeSparse;
87   	   multTimeFull = rhs.multTimeFull;
88   	   multTimeColwise = rhs.multTimeColwise;
89   	   multTimeUnsetup = rhs.multTimeUnsetup;
90   	   multSparseCalls = rhs.multSparseCalls;
91   	   multFullCalls = rhs.multFullCalls;
92   	   multColwiseCalls = rhs.multColwiseCalls;
93   	   multUnsetupCalls = rhs.multUnsetupCalls;
94   	   luFactorizationTimeReal = rhs.luFactorizationTimeReal;
95   	   luSolveTimeReal = rhs.luSolveTimeReal;
96   	   luFactorizationTimeRational = rhs.luFactorizationTimeRational;
97   	   luSolveTimeRational = rhs.luSolveTimeRational;
98   	   fpTime = rhs.fpTime;
99   	   iterations = rhs.iterations;
100  	   iterationsPrimal = rhs.iterationsPrimal;
101  	   iterationsFromBasis = rhs.iterationsFromBasis;
102  	   iterationsPolish = rhs.iterationsPolish;
103  	   iterationsFP = rhs.iterationsFP;
104  	   boundflips = rhs.boundflips;
105  	   boostedIterations = rhs.boostedIterations;
106  	   boostedIterationsPrimal = rhs.boostedIterationsPrimal;
107  	   boostedIterationsFromBasis = rhs.boostedIterationsFromBasis;
108  	   boostedIterationsPolish = rhs.boostedIterationsPolish;
109  	   boostedBoundflips = rhs.boostedBoundflips;
110  	   luFactorizationsReal = rhs.luFactorizationsReal;
111  	   luSolvesReal = rhs.luSolvesReal;
112  	   luFactorizationsRational = rhs.luFactorizationsRational;
113  	   rationalReconstructions = rhs.rationalReconstructions;
114  	   refinements = rhs.refinements;
115  	   stallRefinements = rhs.stallRefinements;
116  	   pivotRefinements = rhs.pivotRefinements;
117  	   feasRefinements = rhs.feasRefinements;
118  	   unbdRefinements = rhs.unbdRefinements;
119  	   precBoosts = rhs.precBoosts;
120  	   stallPrecBoosts = rhs.stallPrecBoosts;
121  	   pivotPrecBoosts = rhs.pivotPrecBoosts;
122  	   feasPrecBoosts = rhs.feasPrecBoosts;
123  	   unbdPrecBoosts = rhs.unbdPrecBoosts;
124  	
125  	   return *this;
126  	}
127  	
128  	/// clears all statistics
129  	template <class R>
130  	void SoPlexBase<R>::Statistics::clearAllData()
131  	{
132  	   readingTime->reset();
133  	   clearSolvingData();
134  	}
135  	
136  	/// clears statistics on solving process
137  	template <class R>
138  	void SoPlexBase<R>::Statistics::clearSolvingData()
139  	{
140  	   solvingTime->reset();
141  	   preprocessingTime->reset();
142  	   simplexTime->reset();
143  	   syncTime->reset();
144  	   transformTime->reset();
145  	   rationalTime->reset();
146  	   initialPrecisionTime->reset();
147  	   extendedPrecisionTime->reset();
148  	   reconstructionTime->reset();
149  	   boostingStepTime->reset();
150  	   multTimeSparse = 0.0;
151  	   multTimeFull = 0.0;
152  	   multTimeColwise = 0.0;
153  	   multTimeUnsetup = 0.0;
154  	   multSparseCalls = 0;
155  	   multFullCalls = 0;
156  	   multColwiseCalls = 0;
157  	   multUnsetupCalls = 0;
158  	   luFactorizationTimeReal = 0.0;
159  	   luSolveTimeReal = 0.0;
160  	   luFactorizationTimeRational = 0.0;
161  	   luSolveTimeRational = 0.0;
162  	   fpTime = 0.0;
163  	   iterations = 0;
164  	   iterationsPrimal = 0;
165  	   iterationsFromBasis = 0;
166  	   iterationsPolish = 0;
167  	   iterationsFP = 0;
168  	   boundflips = 0;
169  	   boostedIterations = 0;
170  	   boostedIterationsPrimal = 0;
171  	   boostedIterationsFromBasis = 0;
172  	   boostedIterationsPolish = 0;
173  	   boostedBoundflips = 0;
174  	   luFactorizationsReal = 0;
175  	   luSolvesReal = 0;
176  	   luFactorizationsRational = 0;
177  	   rationalReconstructions = 0;
178  	   refinements = 0;
179  	   stallRefinements = 0;
180  	   pivotRefinements = 0;
181  	   feasRefinements = 0;
182  	   unbdRefinements = 0;
183  	   precBoosts = 0;
184  	   stallPrecBoosts = 0;
185  	   pivotPrecBoosts = 0;
186  	   feasPrecBoosts = 0;
187  	   unbdPrecBoosts = 0;
188  	
189  	   callsReducedProb = 0;
190  	   iterationsInit = 0;
191  	   iterationsRedProb = 0;
192  	   iterationsCompProb = 0;
193  	   numRedProbRows = 0;
194  	   numRedProbCols = 0;
195  	   degenPivotsPrimal = 0;
196  	   degenPivotsDual = 0;
197  	   degenPivotCandPrimal = 0;
198  	   degenPivotCandDual = 0;
199  	   sumDualDegen = 0;
200  	   sumPrimalDegen = 0;
201  	   decompBasisCondNum = 0;
202  	   totalBoundViol = 0;
203  	   totalRowViol = 0;
204  	   maxBoundViol = 0;
205  	   maxRowViol = 0;
206  	   redProbStatus = 0;
207  	   compProbStatus = 0;
208  	   finalCompObj = 0;
209  	   finalBasisCondition = 0;
210  	}
211  	
212  	/// prints statistics
213  	template <class R>
214  	void SoPlexBase<R>::Statistics::print(std::ostream& os)
215  	{
216  	   Real solTime = solvingTime->time();
217  	   Real totTime = readingTime->time() + solTime;
218  	   Real otherTime = solTime - syncTime->time() - transformTime->time() - preprocessingTime->time() -
219  	                    simplexTime->time() - rationalTime->time();
220  	
221  	   R avgPrimalDegeneracy = iterationsPrimal > 0 ? sumPrimalDegen / iterationsPrimal : 0.0;
222  	   R avgDualDegeneracy = (iterations - iterationsPrimal) > 0 ?
223  	                         (sumDualDegen / (iterations - iterationsPrimal)) : 0.0;
224  	
225  	   SPxOut::setFixed(os, 2);
226  	
227  	   os << "Total time          : " << totTime << "\n"
228  	      << "  Reading           : " << readingTime->time() << "\n"
229  	      << "  Solving           : " << solTime << "\n"
230  	      << "  Preprocessing     : " << preprocessingTime->time();
231  	
232  	   if(solTime > 0)
233  	      os << " (" << 100 * (preprocessingTime->time() / solTime) << "% of solving time)";
234  	
235  	   os << "\n  Simplex           : " << simplexTime->time();
236  	
237  	   if(solTime > 0)
238  	      os << " (" << 100 * (simplexTime->time() / solTime) << "% of solving time)";
239  	
240  	   os << "\n  Synchronization   : " << syncTime->time();
241  	
242  	   if(solTime > 0)
243  	      os << " (" << 100 * (syncTime->time() / solTime) << "% of solving time)";
244  	
245  	   os << "\n  Transformation    : " << transformTime->time();
246  	
247  	   if(solTime > 0)
248  	      os << " (" << 100 * transformTime->time() / solTime << "% of solving time)";
249  	
250  	   os << "\n  Rational          : " << rationalTime->time();
251  	
252  	   if(solTime > 0)
253  	      os << " (" << 100 * rationalTime->time() / solTime << "% of solving time)";
254  	
255  	   os << "\n  InitialPrecision  : " << initialPrecisionTime->time();
256  	
257  	   if(solTime > 0)
258  	      os << " (" << 100 * initialPrecisionTime->time() / solTime << "% of solving time)";
259  	
260  	   os << "\n  ExtendedPrecision : " << extendedPrecisionTime->time();
261  	
262  	   if(solTime > 0)
263  	      os << " (" << 100 * extendedPrecisionTime->time() / solTime << "% of solving time)";
264  	
265  	   os << "\n  BoostingStep      : " << boostingStepTime->time();
266  	
267  	   if(solTime > 0)
268  	      os << " (" << 100 * boostingStepTime->time() / solTime << "% of solving time)";
269  	
270  	   os << "\n  FpTime            : " << fpTime;
271  	
272  	   if(solTime > 0)
273  	      os << " (" << 100 * fpTime / solTime << "% of solving time)";
274  	
275  	   os << "\n  Other             : " << otherTime;
276  	
277  	   if(solTime > 0)
278  	      os << " (" << 100 * otherTime / solTime << "% of solving time)";
279  	
280  	   os << "\nRefinements         : " << refinements << "\n"
281  	      << "  Stalling          : " << stallRefinements << "\n"
282  	      << "  Pivoting          : " << pivotRefinements << "\n"
283  	      << "  Feasibility       : " << feasRefinements << "\n"
284  	      << "  Unboundedness     : " << unbdRefinements << "\n";
285  	
286  	   os << "Precision boosts    : " << precBoosts << "\n"
287  	      << "  Stalling          : " << stallPrecBoosts << "\n"
288  	      << "  Pivoting          : " << pivotPrecBoosts << "\n"
289  	      << "  Feasibility       : " << feasPrecBoosts << "\n"
290  	      << "  Unboundedness     : " << unbdPrecBoosts << "\n";
291  	
292  	   os << "Iterations          : " << iterations << "\n"
293  	      << "  From scratch      : " << iterations - iterationsFromBasis;
294  	
295  	   if(iterations > 0)
296  	      os << " (" << 100 * double((iterations - iterationsFromBasis)) / double(iterations) << "%)";
297  	
298  	   os << "\n  From basis        : " << iterationsFromBasis;
299  	
300  	   if(iterations > 0)
301  	      os << " (" << 100 * double(iterationsFromBasis) / double(iterations) << "%)";
302  	
303  	   os << "\n  Primal            : " << iterationsPrimal;
304  	
305  	   if(iterations > 0)
306  	      os << " (" << 100 * double(iterationsPrimal) / double(iterations) << "%)";
307  	
308  	   os << "\n  Dual              : " << iterations - iterationsPrimal - iterationsPolish;
309  	
310  	   if(iterations > 0)
311  	      os << " (" << 100 * double((iterations - iterationsPrimal)) / double(iterations) << "%)";
312  	
313  	   os << "\n  Bound flips       : " << boundflips;
314  	   os << "\n  Sol. polishing    : " << iterationsPolish;
315  	   os << "\n  First FP solve    : " << iterationsFP;
316  	
317  	   os << "\nIterationsBoosted   : " << boostedIterations << "\n"
318  	      << "  From scratch      : " << int(boostedIterations - boostedIterationsFromBasis);
319  	
320  	   if(boostedIterations > 0)
321  	      os << " (" << 100 * double((boostedIterations - boostedIterationsFromBasis)) / double(
322  	            boostedIterations) << "%)";
323  	
324  	   os << "\n  From basis        : " << boostedIterationsFromBasis;
325  	
326  	   if(boostedIterations > 0)
327  	      os << " (" << 100 * double(boostedIterationsFromBasis) / double(boostedIterations) << "%)";
328  	
329  	   os << "\n  Primal            : " << boostedIterationsPrimal;
330  	
331  	   if(boostedIterations > 0)
332  	      os << " (" << 100 * double(boostedIterationsPrimal) / double(boostedIterations) << "%)";
333  	
334  	   os << "\n  Dual              : " << boostedIterations - boostedIterationsPrimal -
335  	      boostedIterationsPolish;
336  	
337  	   if(boostedIterations > 0)
338  	      os << " (" << 100 * double((boostedIterations - boostedIterationsPrimal)) / double(
339  	            boostedIterations) << "%)";
340  	
341  	   os << "\n  Bound flips       : " << boostedBoundflips;
342  	   os << "\n  Sol. polishing    : " << boostedIterationsPolish;
343  	
344  	   os << "\nLU factorizations   : " << luFactorizationsReal << "\n"
345  	      << "  Factor. frequency : ";
346  	
347  	   if(luFactorizationsReal > 0)
348  	      os << double(iterations) / double(luFactorizationsReal) << " iterations per factorization\n";
349  	   else
350  	      os << "-\n";
351  	
352  	   os << "  Factor. time      : " << luFactorizationTimeReal << "\n";
353  	
354  	   os << "LU solves           : " << luSolvesReal << "\n"
355  	      << "  Solve frequency   : ";
356  	
357  	   if(iterations > 0)
358  	      os << double(luSolvesReal) / double(iterations) << " solves per iteration\n";
359  	   else
360  	      os << "-\n";
361  	
362  	   os << "  Solve time        : " << luSolveTimeReal << "\n";
363  	
364  	   os << "Matrix-Vector ops   : \n"
365  	      << "  Sparse    time    : " << multTimeSparse;
366  	
367  	   if(solTime > 0)
368  	      os << " (" << 100 * (multTimeSparse / solTime) << "% of solving time)";
369  	
370  	   os << "\n            calls   : " << multSparseCalls;
371  	   os << " (" << 100 * (multSparseCalls / (0.01 + iterations)) << "% of iterations)";
372  	   os << "\n  Full      time    : " << multTimeFull;
373  	
374  	   if(solTime > 0)
375  	      os << " (" << 100 * (multTimeFull / solTime) << "% of solving time)";
376  	
377  	   os << "\n            calls   : " << multFullCalls;
378  	   os << " (" << 100 * (multFullCalls / (0.01 + iterations)) << "% of iterations)";
379  	   os << "\n  Colwise   time    : " << multTimeColwise;
380  	
381  	   if(solTime > 0)
382  	      os << " (" << 100 * (multTimeColwise / solTime) << "% of solving time)";
383  	
384  	   os << "\n            calls   : " << multColwiseCalls;
385  	   os << " (" << 100 * (multColwiseCalls / (0.01 + iterations)) << "% of iterations)";
386  	   os << "\n  Unsetup   time    : " << multTimeUnsetup;
387  	
388  	   if(solTime > 0)
389  	      os << " (" << 100 * (multTimeUnsetup / solTime) << "% of solving time)";
390  	
391  	   os << "\n            calls   : " << multUnsetupCalls;
392  	   os << " (" << 100 * (multUnsetupCalls / (0.01 + iterations)) << "% of iterations)";
393  	   os << "\n";
394  	
395  	   os << "Rat. factorizations : " << luFactorizationsRational << "\n"
396  	      << "  Rat. factor. time : " << luFactorizationTimeRational << "\n"
397  	      << "  Rat. solve time   : " << luSolveTimeRational << "\n";
398  	
399  	   os << "Rat. reconstructions: " << rationalReconstructions << "\n"
400  	      << "  Rat. rec. time    : " << reconstructionTime->time() << "\n";
401  	
402  	   os << "Degeneracy          : \n";
403  	   os << "  Primal Pivots     : " << degenPivotsPrimal << "\n";
404  	   os << "  Dual Pivots       : " << degenPivotsDual << "\n";
405  	   os << "  Primal Candidates : " << degenPivotCandPrimal << "\n";
406  	   os << "  Dual Candidates   : " << degenPivotCandDual << "\n";
407  	   os << "  Average Primal    : " << avgPrimalDegeneracy << "\n";
408  	   os << "  Average Dual      : " << avgDualDegeneracy << "\n";
409  	
410  	   if(iterationsInit > 0)
411  	   {
412  	      os << "Algorithm Iterations: " << callsReducedProb << "\n";
413  	      os << "Decomp. Iterations  : \n";
414  	      os << "  Total             : " << iterationsInit + iterationsRedProb << "\n";
415  	      os << "  Initial           : " << iterationsInit << "\n";
416  	      os << "  Reduced Problem   : " << iterationsRedProb << "\n";
417  	      os << "  Comp. Problem     : " << iterationsCompProb << "\n";
418  	      os << "Red. Problem Size   : \n";
419  	      os << "  Rows              : " << numRedProbRows << "\n";
420  	      os << "  Columns           : " << numRedProbCols << "\n";
421  	
422  	      SPxOut::setScientific(os, 16);
423  	
424  	      os << "Decomp. Basis Cond. : " << decompBasisCondNum << "\n";
425  	      os << "Decomp Violations   : \n";
426  	      os << "  Sum Bound         : " << totalBoundViol << "\n";
427  	      os << "  Sum Row           : " << totalRowViol << "\n";
428  	      os << "  Max Bound         : " << maxBoundViol << "\n";
429  	      os << "  Max Row           : " << maxRowViol << "\n";
430  	
431  	      SPxOut::setFixed(os, 2);
432  	
433  	      os << "Red. Problem Status : " << redProbStatus << "\n";
434  	      os << "Comp. Problem Status: " << compProbStatus << "\n";
435  	
436  	      SPxOut::setScientific(os, 16);
437  	
438  	      os << "Comp. Problem Obj.  : " << finalCompObj << "\n";
439  	   }
440  	
441  	   SPxOut::setScientific(os);
442  	
443  	   os << "Numerics            :\n";
444  	   os << "  Condition Number  : " << finalBasisCondition << "\n";
445  	
446  	}
447  	} // namespace soplex
448