Diploma Thesis Percolation Simulation
C++ Sourcecode Documentation

www.AndreasKrueger.de/thesis/code

Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

statistics.h

Go to the documentation of this file.
00001 // statistics.h
00002 // (C) 2000 Andreas Krueger
00003 // v2.5 - last change: 27.9.2001
00004 //
00005 // average   mu
00006 // variance  sigma^2
00007 // skewness  alpha_3
00008 // kurtosis  alpha_4
00009 //  
00010 // of all elements of a list
00011 // AFTER these elements are each preprocessed by a given function
00012 // e.g. linear or bitone_notzero
00013 
00014 #include <list>
00015 #include <float.h>              // for DBL_MAX
00016 
00017 #ifndef LOADED_MEASURE
00018 #include "measure.h"
00019 #endif
00020 
00021 namespace statistics {
00022 
00023 template <class ELEM>                    class manipdata;
00024 template <class RES,class ELEM>  class statistical;
00025 template <class RES>                     class muvarskewkurt;
00026 class minmax;
00027 
00028 /* // predefine them here is not possible using Digital-cxx compiler
00029 template <class RES,class ELEM>
00030 muvarskewkurt<RES> calculate_moments(ELEM (manipdata<ELEM>::*function)(ELEM,ELEM), ELEM fn_arg,
00031                                                                          std::list<ELEM> &elements);
00032 template <class RES> void sdev_of_mean(long n);
00033 */ 
00034 template <class RES> ostream& operator<<(ostream& os, muvarskewkurt<RES> A);
00035 
00036 
00037 
00038 // here it starts:
00039 
00040 // the data preprocessing functions
00041 template <class ELEM> class manipdata {
00042 public:
00043         // this is the default: DO NOTHING
00044         ELEM linear(ELEM x, ELEM dummy)         {return (x);}; 
00045 
00046         // special manipulation functions:
00047         ELEM square(ELEM x, ELEM dummy)         {return (x*x);};
00048         
00049         ELEM notzero(ELEM x, ELEM dummy)        {return (x!=0);};
00050         ELEM bitone_notzero(ELEM x,ELEM dummy){return (x&1!=0);};
00051 
00052         ELEM bit_notzero(ELEM x, ELEM bit)      {return ((x&(ELEM)pow((int)2,(int)bit-1))!=0);};
00053         ELEM allbits_notzero(ELEM x, ELEM dim)  {return (x==(ELEM)pow((int)2,(int)dim)-1);};
00054         
00055         ELEM shift(ELEM x, ELEM shift)          {return (x+shift);};
00056 };
00057 
00058 
00059 
00060 template <class RES, class ELEM> class statistical {
00061 public:
00062         // four moments -> four "outer" functions
00063         RES lineardis(ELEM x, RES mu){return (RES)x-mu;};
00064         RES squaredis(ELEM x, RES mu){return pow((RES)x-mu,2);};
00065         RES cubicdis (ELEM x, RES mu){return pow((RES)x-mu,3);};
00066         RES pow4dis  (ELEM x, RES mu){return pow((RES)x-mu,4);};
00067 
00068         // the core of the game: sum up the list and divide by size...
00069         // mu is the first moment (=linear expectation value) or zero
00070         // inner_fn(x,fn_arg) manipulates x before it is summed
00071         RES average_of_list(RES (statistical<RES,ELEM>::*outer_fn)(ELEM,RES), RES mu,
00072                                                 ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00073                                                 std::list<ELEM> &L);
00074         // now do it again for the square distances from average
00075         RES standarddeviation_of_list(RES av,
00076                                                                   RES (statistical<RES,ELEM>::*outer_fn)(ELEM,RES), RES mu,
00077                                                                   ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00078                                                                   std::list<ELEM> &L);
00079 
00080         // this is used by average, variance, s3, s4
00081         measure<RES> general_moment(RES (statistical<RES,ELEM>::*distfn)(ELEM,RES), RES mu,
00082                                                                 ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM),ELEM fn_arg,
00083                                                                 std::list<ELEM> & elements);
00084         // the four moments
00085         measure<RES> average (ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,  
00086                                                   std::list<ELEM>& elements);
00087         measure<RES> variance(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg, 
00088                                                   std::list<ELEM>& elements, RES mu);
00089         measure<RES> s3 (ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg, 
00090                                                   std::list<ELEM>& elements, RES mu);
00091         measure<RES> s4 (ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg, 
00092                                                   std::list<ELEM>& elements, RES mu);
00093         // these two are "z-standardized" by 1/sigma^k
00094         measure<RES> skewness(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg, 
00095                                                   std::list<ELEM>& elements, RES mu, RES sigma);
00096         measure<RES> kurtosis(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg, 
00097                                                   std::list<ELEM>& elements, RES mu, RES sigma);
00098 
00099         // skewness ( >0 long tail to the right = steep rise at the left side)
00100         // kurtosis ( >3 leptokurtic = peak higher than normal-distribution, not platykurtic)
00101 };
00102 
00103 
00104 // --> AVERAGE <--
00105 // The average & standard-deviation of a whole list are calculated.
00106 // The two preprocessing functions outer_fn and inner_fn
00107 // process each element before it is summed:
00108 //  sum_of [ outer_fn( inner_fn(ELEMENT) )  ]
00109 //
00110 // Why?
00111 // The inner-function can be used to manipulate the stored element
00112 //  eg. to test if the element is zero - and add the resulting bool
00113 // The outer-function is used to square, cubic,... the manipulated-element - mu
00114 //  eg. to calculate the average of square(manip(elem) - mu) or cubic(manip(elem) - mu) 
00115 //  to get the higher moments variance, skewness, kurtosis
00116 
00117 template <class RES, class ELEM>
00118 RES statistical<RES,ELEM>::average_of_list(RES (statistical<RES,ELEM>::*outer_fn)(ELEM,RES), RES mu,
00119                                         ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00120                                         std::list<ELEM> &L){
00121         manipdata<ELEM>      *processdata=NULL;
00122         statistical<RES,ELEM> *distfn=NULL;
00123         std::list<ELEM>::iterator one;
00124 
00125         RES sum=(RES)0;
00126         for (one=L.begin();one!=L.end();one++){
00127                 sum += (distfn->*outer_fn)((processdata->*inner_fn)(*one, fn_arg), mu);
00128         }
00129         return sum/(RES)L.size();
00130 }
00131 
00132 template <class RES, class ELEM>
00133 RES statistical<RES,ELEM>::standarddeviation_of_list(RES av,
00134                                                           RES (statistical<RES,ELEM>::*outer_fn)(ELEM,RES), RES mu,
00135                                                           ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00136                                                           std::list<ELEM> &L){
00137         manipdata<ELEM>      *processdata=NULL;
00138         statistical<RES,ELEM> *distfn=NULL;
00139         std::list<ELEM>::iterator one;
00140 
00141         RES sdev=(RES)0;
00142         RES diff;
00143         for (one=L.begin();one!=L.end();one++){
00144                 diff=(distfn->*outer_fn)((processdata->*inner_fn)(*one, fn_arg), mu) - av ;  
00145                 sdev +=diff*diff;
00146         }
00147         if (L.size()<2) return sqrt(sdev);              // changed in version2.2:  
00148         return sqrt(sdev/(RES)(L.size()-1));    //  1/N  ->  1/(N-1)
00149 }
00150 
00151 // --> MOMENTS <--
00152 // the first 4 moments are calculated
00153 // of a list of elements of type ELEM
00154 // returned is a tupel (average, stand.deviation)
00155 // of class measure<RES>
00156 
00157 template <class RES, class ELEM>
00158 measure<RES> 
00159 statistical<RES,ELEM>::general_moment(
00160                                                 RES (statistical<RES,ELEM>::*distfn)(ELEM,RES), RES mu,
00161                                                 ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM),ELEM fn_arg,
00162                                                 std::list<ELEM> & elements)
00163 {
00164         statistical<RES,ELEM> *s=NULL;
00165         measure<RES> temp;
00166         temp.set_av  (s->average_of_list(distfn, mu, inner_fn, fn_arg, elements));
00167         temp.set_sdev(s->standarddeviation_of_list(temp.av(), distfn, mu, inner_fn, fn_arg, elements) );
00168         return temp;
00169 }
00170 
00171 template <class RES, class ELEM>
00172 measure<RES> 
00173 statistical<RES,ELEM>::average (ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM),ELEM fn_arg,
00174                                                            std::list<ELEM> & elements){
00175         RES (statistical<RES,ELEM>::*distfn)(ELEM,RES)= &statistical<RES,ELEM>::lineardis;
00176         return general_moment(distfn, 0, inner_fn, fn_arg, elements);
00177 }
00178 
00179 template <class RES, class ELEM>
00180 measure<RES> statistical<RES,ELEM>::variance(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM),ELEM fn_arg,
00181                                                                                           std::list<ELEM> & elements, RES mu){
00182         RES (statistical<RES,ELEM>::*distfn)(ELEM,RES)= &statistical<RES,ELEM>::squaredis;
00183         return general_moment(distfn, mu, inner_fn, fn_arg, elements);
00184 }
00185 
00186 // s3 and s4 are the third and fourth moments,
00187 // but not z-standardized yet:
00188 template <class RES, class ELEM>
00189 measure<RES> statistical<RES,ELEM>::s3(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM),ELEM fn_arg,
00190                                                                                 std::list<ELEM> & elements, RES mu){
00191         RES (statistical<RES,ELEM>::*distfn)(ELEM,RES)= &statistical<RES,ELEM>::cubicdis;
00192         return general_moment(distfn, mu, inner_fn, fn_arg, elements);
00193 }
00194 
00195 template <class RES, class ELEM>
00196 measure<RES> statistical<RES,ELEM>::s4(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00197                                                                                 std::list<ELEM> & elements, RES mu){
00198         RES (statistical<RES,ELEM>::*distfn)(ELEM,RES)= &statistical<RES,ELEM>::pow4dis;
00199         return general_moment(distfn, mu, inner_fn, fn_arg, elements);
00200 }
00201 
00202 // skewness and kurtosis are z-standardized:
00203 template <class RES, class ELEM>
00204 measure<RES> statistical<RES,ELEM>::skewness(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00205                                                                                           std::list<ELEM> & elements, RES mu,
00206                                                                                           RES sigma){ // changed in v2.3: sigma not measure<RES> anymore
00207         if (sigma==0) return 0;
00208         else return s3(inner_fn, fn_arg, elements, mu)/pow(sigma,3);    
00209 }
00210 
00211 template <class RES, class ELEM>
00212 measure<RES> statistical<RES,ELEM>::kurtosis(ELEM (manipdata<ELEM>::*inner_fn)(ELEM,ELEM), ELEM fn_arg,
00213                                                                                           std::list<ELEM> & elements, RES mu,
00214                                                                                           RES sigma){ // changed in v2.3: sigma not measure<RES> anymore
00215         if (sigma==0) return 0;
00216         return s4(inner_fn, fn_arg, elements, mu)/pow(sigma,4);
00217 }
00218 
00219 // end of class "statistical"
00220 
00221 template<class RES, class ELEM>
00222 void calculate_all_moments(ELEM (manipdata<ELEM>::*function)(ELEM,ELEM), ELEM fn_arg,
00223                                                    std::list<ELEM> &elements, 
00224                                                    measure<RES> &average, measure<RES> &variance,
00225                                                    measure<RES> &skewness,measure<RES> &kurtosis)
00226 {
00227         statistical<RES, ELEM> *moments=NULL;
00228         average =moments->average (function, fn_arg, elements);
00229         variance=moments->variance(function, fn_arg, elements, average.av());
00230         skewness=moments->skewness(function, fn_arg, elements, average.av(), sqrt(variance));
00231         kurtosis=moments->kurtosis(function, fn_arg, elements, average.av(), sqrt(variance));
00232 }
00233 
00234 
00235 template <class RES> class muvarskewkurt {
00236 public:
00237         measure<RES> mu;
00238         measure<RES> variance;
00239         measure<RES> skewness;
00240         measure<RES> kurtosis;
00241         void zero();
00242         void sdev_of_mean(long N);
00243 };
00244 template <class RES>
00245 void muvarskewkurt<RES>::zero (){
00246         mu=(RES)0;
00247         variance=(RES)0;
00248         skewness=(RES)0;
00249         kurtosis=(RES)0;
00250 }
00251 template <class RES> ostream& operator<<(ostream& os, muvarskewkurt<RES> A){
00252         os <<"mu="<<A.mu<<" var="<<A.variance<<" skw="<<A.skewness<<" krt="<<A.kurtosis;
00253         return os;
00254 }
00255 
00256 template <class RES>                    // new in version 2.2
00257 void muvarskewkurt<RES>::sdev_of_mean(long n){
00258         mu.set_sdev              (mu.sdev()              /sqrt((RES)n)); // manipulation! sdev of mean ~ 1/sqrt(nn)
00259         variance.set_sdev(variance.sdev()/sqrt((RES)n)); // manipulation! sdev of mean ~ 1/sqrt(nn)
00260         skewness.set_sdev(skewness.sdev()/sqrt((RES)n)); // manipulation! sdev of mean ~ 1/sqrt(nn)
00261         kurtosis.set_sdev(kurtosis.sdev()/sqrt((RES)n)); // manipulation! sdev of mean ~ 1/sqrt(nn)
00262 }
00263 
00264 template <class RES, class ELEM>
00265 muvarskewkurt<RES> calculate_moments(ELEM (manipdata<ELEM>::*function)(ELEM,ELEM), 
00266                                                                            ELEM fn_arg,
00267                                                                            std::list<ELEM> &elements,
00268                                                                            RES dummy)
00269 {
00270         statistical<RES, ELEM> *moments=NULL;
00271         muvarskewkurt<RES> temp;
00272         temp.mu      =moments->average (function, fn_arg, elements);
00273         temp.variance=moments->variance(function, fn_arg, elements, temp.mu.av());
00274         temp.skewness=moments->skewness(function, fn_arg, elements, temp.mu.av(), sqrt(temp.variance.av()));
00275         temp.kurtosis=moments->kurtosis(function, fn_arg, elements, temp.mu.av(), sqrt(temp.variance.av()));
00276         return temp;
00277 }
00278 
00279 
00280 void test_statistics(){
00281         cout <<"\nHi!\nTest statistics with a list of random numbers.";
00282         cout <<"\nHow many:"<<flush;
00283         int N=0; 
00284         while (N<1) cin>>N;
00285         std::list<float> L;
00286         for (int i=0;i<N;i++) L.push_back(rand()/(float)RAND_MAX);
00287         muvarskewkurt<double> A;
00288         int dummy=42;
00289         double dummy2=1.0; // for calculate_moments result type
00290         A=calculate_moments<double,float>(&manipdata<float>::linear, dummy, L, dummy2);
00291         cout <<"The distribution has these statistical properties:\n";
00292         cout <<"(average mu, variance, skewness, kurtosis)\n" <<A<<endl;
00293 }
00294 
00295 
00296 class minmax {
00297 public: 
00298         double min; 
00299         double max;
00300         minmax();
00301         minmax(double min_,double max_);
00302         void reset();           // has to be set to [min;max]=[+inf;-inf] before being used
00303         void set_if_more_extreme(double comparer);
00304 };
00305 
00306 minmax::minmax(){ 
00307         max=-DBL_MAX; min=DBL_MAX; 
00308 } 
00309 void minmax::reset(){ 
00310         max=-DBL_MAX; min=DBL_MAX; 
00311 } 
00312 
00313 minmax::minmax(double min_,double max_){ min=min_; max=max_; } 
00314 
00315 void minmax::set_if_more_extreme(double comparer){ 
00316         if (comparer>max) max=comparer;
00317         if (comparer<min) min=comparer;
00318 }
00319 
00320 template <class T>
00321 T minof2(T a, T b){ return (a<b)?a:b; }
00322 template <class T>
00323 T maxof2(T a, T b){ return (a<b)?b:a; }
00324 
00325 
00326 } // end of namespace statistics




Diploma Thesis Sourcecode Documentation
check out the text and the executable binaries

www.AndreasKrueger.de/thesis/code