root / src / sim / cstddev.cc @ e26d3d25
History  View  Annotate  Download (9.67 KB)
1  01873262  Georg Kunz  //=========================================================================


2  // CSTDDEV.CC  part of


3  //


4  // OMNeT++/OMNEST


5  // Discrete System Simulation in C++


6  //


7  // Based on the MISS simulator's result collection


8  //


9  // Member functions of


10  // cStdDev: basic statistics (mean, stddev, min, max, etc)


11  // cWeightedStdDev: weighted version


12  //


13  // Author: Andras Varga


14  //


15  //=========================================================================


16  
17  /**


18  Copyright (C) 19922008 Andras Varga


19  Copyright (C) 20062008 OpenSim Ltd.


20  
21  This file is distributed WITHOUT ANY WARRANTY. See the file


22  `license' for details on this and other legal matters.


23  **/


24  
25  #include <stdio.h> 

26  #include <string.h> 

27  #include <math.h> 

28  #include <string> 

29  
30  #include "cstddev.h" 

31  #include "random.h" 

32  #include "distrib.h" 

33  #include "globals.h" 

34  #include "cdetect.h" //NL 

35  #include "csimplemodule.h" 

36  #include "cexception.h" 

37  #include "cenvir.h" 

38  #include "stringutil.h" 

39  
40  #ifdef WITH_PARSIM


41  #include "ccommbuffer.h" 

42  #endif


43  
44  USING_NAMESPACE 

45  
46  using std::ostream;


47  
48  Register_Class(cStdDev); 

49  Register_Class(cWeightedStdDev); 

50  
51  
52  cStdDev::cStdDev(const char *s) : cStatistic(s) 

53  { 

54  num_vals = 0L;


55  sum_vals = sqrsum_vals = 0;


56  min_vals = max_vals= 0;


57  } 

58  
59  std::string cStdDev::info() const 

60  { 

61  std::stringstream out; 

62  out << "n=" << getCount()


63  << " mean=" << getMean()


64  << " stddev=" << getStddev()


65  << " min=" << getMin()


66  << " max=" << getMax();


67  return out.str();


68  } 

69  
70  void cStdDev::parsimPack(cCommBuffer *buffer)


71  { 

72  #ifndef WITH_PARSIM


73  throw cRuntimeError(this,eNOPARSIM); 

74  #else


75  cStatistic::parsimPack(buffer); 

76  buffer>pack(num_vals); 

77  buffer>pack(min_vals); 

78  buffer>pack(max_vals); 

79  buffer>pack(sum_vals); 

80  buffer>pack(sqrsum_vals); 

81  #endif


82  } 

83  
84  void cStdDev::parsimUnpack(cCommBuffer *buffer)


85  { 

86  #ifndef WITH_PARSIM


87  throw cRuntimeError(this,eNOPARSIM); 

88  #else


89  cStatistic::parsimUnpack(buffer); 

90  buffer>unpack(num_vals); 

91  buffer>unpack(min_vals); 

92  buffer>unpack(max_vals); 

93  buffer>unpack(sum_vals); 

94  buffer>unpack(sqrsum_vals); 

95  #endif


96  } 

97  
98  cStdDev& cStdDev::operator=(const cStdDev& res) 

99  { 

100  if (this==&res) return *this; 

101  
102  cStatistic::operator=(res);


103  num_vals = res.num_vals; 

104  min_vals = res.min_vals; 

105  max_vals = res.max_vals; 

106  sum_vals = res.sum_vals; 

107  sqrsum_vals = res.sqrsum_vals; 

108  
109  return *this; 

110  } 

111  
112  void cStdDev::collect(double value) 

113  { 

114  if (++num_vals <= 0) 

115  { 

116  // num_vals overflow: issue warning and stop collecting


117  ev.printf("\a\nWARNING: (%s)%s: collect(): observation count overflow!\n\n",getClassName(),getFullPath().c_str()); 

118  num_vals; // restore


119  return;


120  }


121 


122  sum_vals += value;


123  sqrsum_vals += value*value;


124 


125  if (num_vals > 1)


126  {


127  if (value < min_vals)


128  min_vals = value;


129  else if (value > max_vals)


130  max_vals = value;


131  }


132  else


133  {


134  min_vals = max_vals = value;


135  }


136 


137  if (getTransientDetectionObject()) td>collect(value); //NL


138  if (getAccuracyDetectionObject()) ra>collect(value); //NL


139  }


140 


141  void cStdDev::doMerge(const cStatistic *other)


142  {


143  long orig_num_vals = num_vals;


144  num_vals += other>getCount();


145  if (num_vals < 0)


146  throw cRuntimeError(this, "merge(): observation count overflow"); 

147 


148  if (other>getCount()>0 && (orig_num_vals==0  min_vals>other>getMin()))


149  min_vals = other>getMin();


150  if (other>getCount()>0 && (orig_num_vals==0  max_vals<other>getMax()))


151  max_vals = other>getMax();


152 


153  sum_vals += other>getSum();


154  sqrsum_vals += other>getSqrSum();


155  }


156 


157  void cStdDev::merge(const cStatistic *other)


158  {


159  if (other>isWeighted())


160  throw cRuntimeError(this, "Cannot merge weighted statistics (%s)%s into unweighted statistics", 

161  other>getClassName(), other>getFullPath().c_str());


162  doMerge(other);


163  }


164 


165  double cStdDev::getVariance() const


166  {


167  if (num_vals <= 1)


168  return NaN;


169  else


170  {


171  // note: no check for division by zero, we prefer to return Inf or NaN


172  double devsqr = (sqrsum_vals  sum_vals*sum_vals/num_vals)/(num_vals1);


173  return devsqr<0 ? 0 : devsqr;


174  }


175  }


176 


177  double cStdDev::getStddev() const


178  {


179  return sqrt(getVariance());


180  }


181 


182  std::string cStdDev::detailedInfo() const


183  {


184  std::stringstream os;


185  os << " Number of values = " << num_vals << "\n"; 

186  if (num_vals==1)


187  os << " Value = " << min_vals << "\n"; 

188  else if (num_vals>0)


189  {


190  os << " Mean value = " << getMean() << "\n"; 

191  os << " Standard dev. = " << getStddev() << "\n"; 

192  os << " Minimal value = " << min_vals << "\n"; 

193  os << " Maximal value = " << max_vals << "\n"; 

194  }


195  return os.str();


196  }


197 


198  void cStdDev::clearResult()


199  {


200  num_vals=0;


201  sum_vals=sqrsum_vals=min_vals=max_vals=0;


202  }


203 


204  double cStdDev::random() const


205  {


206  switch (num_vals)


207  {


208  case 0: return 0.0;


209  case 1: return min_vals;


210  default: return normal(getMean(), getStddev(), genk);


211  }


212  }


213 


214  void cStdDev::saveToFile(FILE *f) const


215  {


216  fprintf(f,"\n#\n# (%s) %s\n#\n", getClassName(), getFullPath().c_str()); 

217  fprintf(f,"%ld\t #= num_vals\n",num_vals); 

218  fprintf(f,"%g %g\t #= min, max\n", min_vals, max_vals); 

219  fprintf(f,"%g\t #= sum\n", sum_vals); 

220  fprintf(f,"%g\t #= square sum\n", sqrsum_vals ); 

221  }


222 


223  void cStdDev::loadFromFile(FILE *f)


224  {


225  freadvarsf(f,""); freadvarsf(f,""); freadvarsf(f,""); freadvarsf(f,""); 

226  freadvarsf(f,"%ld\t #= num_vals",&num_vals); 

227  freadvarsf(f,"%g %g\t #= min, max", &min_vals, &max_vals); 

228  freadvarsf(f,"%g\t #= sum", &sum_vals); 

229  freadvarsf(f,"%g\t #= square sum", &sqrsum_vals); 

230  }


231 


232  //


233 


234  std::string cWeightedStdDev::info() const


235  {


236  std::stringstream out;


237  out << "n=" << getCount() 

238  << " mean=" << getMean() 

239  << " stddev=" << getStddev() 

240  << " min=" << getMin() 

241  << " max=" << getMax(); 

242  return out.str();


243  }


244 


245  void cWeightedStdDev::parsimPack(cCommBuffer *buffer)


246  {


247  #ifndef WITH_PARSIM


248  throw cRuntimeError(this,eNOPARSIM);


249  #else


250  cStdDev::parsimPack(buffer);


251  buffer>pack(sum_weights);


252  buffer>pack(sum_weighted_vals);


253  buffer>pack(sum_squared_weights);


254  buffer>pack(sum_weights_squared_vals);


255  #endif


256  }


257 


258  void cWeightedStdDev::parsimUnpack(cCommBuffer *buffer)


259  {


260  #ifndef WITH_PARSIM


261  throw cRuntimeError(this,eNOPARSIM);


262  #else


263  cStdDev::parsimUnpack(buffer);


264  buffer>unpack(sum_weights);


265  buffer>unpack(sum_weighted_vals);


266  buffer>unpack(sum_squared_weights);


267  buffer>unpack(sum_weights_squared_vals);


268  #endif


269  }


270 


271  cWeightedStdDev& cWeightedStdDev::operator=(const cWeightedStdDev& res)


272  {


273  if (this==&res) return *this;


274 


275  cStdDev::operator=(res);


276  sum_weights = res.sum_weights;


277  sum_weighted_vals = res.sum_weighted_vals;


278  sum_squared_weights = res.sum_squared_weights;


279  sum_weights_squared_vals = res.sum_weights_squared_vals;


280  return *this;


281  }


282 


283  void cWeightedStdDev::collect2(double value, double weight)


284  {


285  if (weight > 0)


286  {


287  if (++num_vals <= 0)


288  {


289  // num_vals overflow: issue warning and stop collecting


290  ev.printf("\a\nWARNING: (%s)%s: collect2(): observation count overflow!\n\n",getClassName(),getFullPath().c_str()); 

291  num_vals; // restore


292  return;


293  }


294 


295  sum_vals += value;


296  sqrsum_vals += value*value;


297 


298  if (num_vals > 1)


299  {


300  if (value < min_vals)


301  min_vals = value;


302  else if (value > max_vals)


303  max_vals = value;


304  }


305  else


306  {


307  min_vals = max_vals = value;


308  }


309 


310  sum_weights += weight;


311  sum_weighted_vals += weight * value;


312  sum_squared_weights += weight * weight;


313  sum_weights_squared_vals += weight * value * value;


314 


315  if (getTransientDetectionObject()) td>collect(value);


316  if (getAccuracyDetectionObject()) ra>collect(value);


317  }


318  else if (weight < 0)


319  {


320  throw cRuntimeError(this, "collect2(): negative weight %g", weight); 

321  }


322  }


323 


324  void cWeightedStdDev::merge(const cStatistic *other)


325  {


326  cStdDev::doMerge(other);


327  sum_weights += other>getWeights();


328  sum_weighted_vals += other>getWeightedSum();


329  sum_squared_weights += other>getSqrSumWeights();


330  sum_weights_squared_vals += other>getWeightedSqrSum();


331  }


332 


333  void cWeightedStdDev::clearResult()


334  {


335  cStdDev::clearResult();


336  sum_weights = 0.0;


337  sum_weighted_vals = 0.0;


338  sum_squared_weights = 0.0;


339  sum_weights_squared_vals = 0.0;


340  }


341 


342  double cWeightedStdDev::getVariance() const


343  {


344  if (num_vals <= 1)


345  return NaN;


346  else


347  {


348  // note: no check for division by zero, we prefer to return Inf or NaN


349  double denominator = sum_weights * sum_weights  sum_squared_weights;


350  double var = (sum_weights * sum_weights_squared_vals  sum_weighted_vals * sum_weighted_vals) / denominator;


351  return var<0 ? 0 : var;


352  }


353  }


354 


355  void cWeightedStdDev::saveToFile(FILE *f) const


356  {


357  cStdDev::saveToFile(f);


358  fprintf(f,"%g\t #= sum_weights\n", sum_weights); 

359  fprintf(f,"%g\t #= sum_weighted_vals\n", sum_weighted_vals); 

360  fprintf(f,"%g\t #= sum_squared_weights\n", sum_squared_weights); 

361  fprintf(f,"%g\t #= sum_weights_squared_vals\n", sum_weights_squared_vals); 

362  }


363 


364  void cWeightedStdDev::loadFromFile(FILE *f)


365  {


366  cStdDev::loadFromFile(f);


367  freadvarsf(f,"%g\t #= sum_weights", &sum_weights); 

368  freadvarsf(f,"%g\t #= sum_weighted_vals", &sum_weighted_vals); 

369  freadvarsf(f,"%g\t #= sum_squared_weights", &sum_squared_weights); 

370  freadvarsf(f,"%g\t #= sum_weights_squared_vals", &sum_weights_squared_vals); 

371  }


372 


373 
