templatevalueanalysation.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2011 LpzRobots development team                    *
00003  *    Georg Martius  <georg dot martius at web dot de>                     *
00004  *    Frank Guettler <guettler at informatik dot uni-leipzig dot de        *
00005  *    Frank Hesse    <frank at nld dot ds dot mpg dot de>                  *
00006  *    Ralf Der       <ralfder at mis dot mpg dot de>                       *
00007  *                                                                         *
00008  *   This program is free software; you can redistribute it and/or modify  *
00009  *   it under the terms of the GNU General Public License as published by  *
00010  *   the Free Software Foundation; either version 2 of the License, or     *
00011  *   (at your option) any later version.                                   *
00012  *                                                                         *
00013  *   This program is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00016  *   GNU General Public License for more details.                          *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU General Public License     *
00019  *   along with this program; if not, write to the                         *
00020  *   Free Software Foundation, Inc.,                                       *
00021  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #ifndef TEMPLATEVALUEANALYSATION_H_
00026 #define TEMPLATEVALUEANALYSATION_H_
00027 
00028 //macros
00029 #define ANALYSATION_CONTEXT TemplateValueAnalysation<type,zero,lower,higher,doubleDiv,doubleMul,add,sub,mul,div>
00030 #define DOUBLE_ANALYSATION_CONTEXT TemplateValueAnalysation<double,defaultZero>
00031 
00032 //includes
00033 #include <vector>
00034 #include <list>
00035 
00036 /**
00037  * default function for "lower as" operation.
00038  * @param a operator a
00039  * @param b operator b
00040  * @return (bool) true if a lower than b
00041  */
00042 template
00043 <class type>
00044 bool defaultLower(const type& a, const type& b) {
00045         if(a<b)
00046                 return true;
00047 
00048         return false;
00049 }
00050 
00051 /**
00052  * default function for divide by a double value.
00053  * @param a operator a
00054  * @param b (double) the double value
00055  * @return the result of the division
00056  */
00057 template
00058 <class type>
00059 type defaultDoubleDiv(const type& a, const double& b) {
00060         return a/b;
00061 }
00062 
00063 /**
00064  * default function for mul. with a double value.
00065  * @param a operator a
00066  * @param b (double) the double value
00067  * @return the result of the mul.
00068  */
00069 template
00070 <class type>
00071 type defaultDoubleMul(const type& a, const double& b) {
00072         return a*b;
00073 }
00074 
00075 /**
00076  * default function for "higher than" operation.
00077  * @param a operator a
00078  * @param b operator b
00079  * @return (bool) true if a higher than b
00080  */
00081 template
00082 <class type>
00083 bool defaultHigher(const type& a,const type& b) {
00084         if(a>b)
00085                 return true;
00086 
00087         return false;
00088 }
00089 
00090 /**
00091  * default function for add two values
00092  * @param a operator a
00093  * @param b operator b
00094  * @return the result of the add.
00095  */
00096 template
00097 <class type>
00098 type defaultAdd(const type& a, const type& b) {
00099         return a+b;
00100 }
00101 
00102 /**
00103  * default function for sub. two values
00104  * @param a operator a
00105  * @param b operator b
00106  * @return the result of the sub.
00107  */
00108 template
00109 <class type>
00110 type defaultSub(const type& a, const type& b) {
00111         return a-b;
00112 }
00113 
00114 /**
00115  * default function for mul. of two values
00116  * @param a operator a
00117  * @param b operator b
00118  * @return the result of the mul.
00119  */
00120 template
00121 <class type>
00122 type defaultMul(const type& a, const type& b) {
00123         return a*b;
00124 }
00125 
00126 /**
00127  * default function for div. of two values
00128  * @param a operator a
00129  * @param b operator b
00130  * @return the result of the div.
00131  */
00132 template
00133 <class type>
00134 type defaultDiv(const type& a, const type& b) {
00135         return a/b;
00136 }
00137 
00138 /**
00139  * default function for zero double value
00140  * @return (double) 0.0
00141  */
00142 double defaultZero();
00143 
00144 /**
00145  * This template class give you some methods to calculate some statistical values like average, min, max, upper quartil,
00146  * lower quartil and many more.
00147  *
00148  * All functions are implemented in the header because by generating the library it isn't known which type are later used.
00149  * And a later compiling needs the implementation two!
00150  */
00151 template
00152 <class type,                                                                                                                    //data type of the calculation
00153 type zero(void),                                                                                                                //gives the zero of this data type back
00154 bool lower(const type&, const type&)=defaultLower<type>,                                //test if one element of the type lower than the other
00155 bool higher(const type&, const type&)=defaultHigher<type>,                      //test if one element of the type higher than the other
00156 type doubleDiv(const type&, const double&)=defaultDoubleDiv<type>,      //divide a element of the type by a double value
00157 type doubleMul(const type&, const double&)=defaultDoubleMul<type>,      //mul. a element of the type by a double value
00158 type add(const type&, const type&)=defaultAdd<type>,                                    //add two elements of type
00159 type sub(const type&, const type&)=defaultSub<type>,                                    //sub two elements of type
00160 type mul(const type&, const type&)=defaultMul<type>,                                    //mul two elements of type
00161 type div(const type&, const type&)=defaultDiv<type> >                           //div two elements of type
00162 class TemplateValueAnalysation {
00163 public:
00164         /**
00165          * constructor
00166          * Needs a set of values for which the statistical values will calculate.
00167          * @param values (vector<type>& the set)
00168          */
00169         TemplateValueAnalysation(std::vector<type>& values) : m_vector(values), m_list(), m_listCreated(false) {}
00170 
00171         /**
00172          * default destructor
00173          */
00174         ~TemplateValueAnalysation() {}
00175 
00176         /**
00177          * this function calculate the average of the giving set
00178          *
00179          * It used zero, add and doubleDiv to calculate the average.
00180          * @return the average
00181          */
00182         type getAvg() {
00183                 type avg=zero();                                                                                                                                                //by begin the average is zero
00184                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter;
00185 
00186                 for(iter = m_vector.begin(); iter != m_vector.end(); iter++) {
00187                         avg = add(avg,(*iter));                                                                                                                         //for all elements in the set add it to the average.
00188                                                                                                                                                                                                 //So we become the sum. of all elements in the set.
00189                 }
00190 
00191                 if(m_vector.size()!=0)
00192                         avg = doubleDiv(avg,m_vector.size());                                                                                           //now devide the sum by the count of elements in the set.
00193 
00194                 return avg;                                                                                                                                                             //return the result
00195         }
00196 
00197         /**
00198          * this function search the min. value in the set
00199          *
00200          * For this it use lower
00201          * @return the minimum
00202          */
00203         type getMin() {
00204                 type min = m_vector[0];                 //the lowest element is at begin the first element
00205                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter = m_vector.begin();
00206 
00207                 for(iter++; iter != m_vector.end(); iter++) {
00208                         if(lower((*iter),min))          //if a element lower than min, so reset the min to the lower value.
00209                                 min=(*iter);
00210                 }
00211 
00212                 return min;                                             //return the lowest element
00213         }
00214 
00215         /**
00216          * this function search the max. value in the set
00217          *
00218          * For this it use lower
00219          * @return the minimum
00220          */
00221         type getMax() {
00222                 type max = m_vector[0];                 //the highest element is at begin the first element
00223                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter = m_vector.begin();
00224 
00225                 for(iter++; iter != m_vector.end(); iter++) {
00226                         if(lower(max,(*iter)))          //if a element higher than max, so reset the max to the higher value.
00227                                 max=(*iter);
00228                 }
00229 
00230                 return max;                                             //return the lowest element
00231         }
00232 
00233         /**
00234          * this function calculate the range of all values. For this he search the mibn and max and calculate from this values.
00235          *
00236          * use sub
00237          * @return the range of the values in the set
00238          */
00239         type getRange() {
00240                 type dMax = getMax();                   //become max
00241                 type dMin = getMin();                   //become min
00242 
00243                 return sub(dMax,dMin);                  //range=max-min
00244         }
00245 
00246         /**
00247          * this function search the median of the giving set of values.
00248          *
00249          * use add and doubleMul
00250          * @return the median
00251          */
00252         type getMedian() {
00253                 type median;
00254                 int x;
00255                 int num = m_vector.size()/2;
00256                 std::_List_iterator<TYPE_SAVE> iter;
00257 
00258                 if(!m_listCreated)
00259                         sort();                                                         //sort the set. to define the middle
00260 
00261                 iter = m_list.begin();                                  //go to the middle
00262                 for(x=0;x<num;x++) iter++;
00263 
00264                 if(m_vector.size() % 2 == 0) {                  //if the real middle between two values add this values and calculate the arithmetical middle.
00265                         median = (*iter->pointer);
00266                         iter--;
00267                         median = add(median,(*iter->pointer));
00268                         median = doubleMul(median,0.5);
00269                 }
00270 
00271                 else {
00272                         median = (*iter->pointer);                      //else gives the middle back
00273                 }
00274 
00275                 return median;
00276         }
00277 
00278         /**
00279          * this function calculate the under quartil
00280          *
00281          * use add and doubleMul
00282          * @return the under quartil
00283          */
00284         type getQuartil1() {
00285                 type q;
00286                 int x;
00287                 int num = m_vector.size()/4;
00288                 std::_List_iterator<TYPE_SAVE> iter;
00289 
00290                 if(!m_listCreated)
00291                         sort();                                                         //sort the set.
00292 
00293                 iter = m_list.begin();                                  //go to the under quartil
00294                 for(x=0;x<num;x++) iter++;
00295 
00296                 if(m_vector.size() % 4 == 0) {                  //if the real under quartil between two values add this values and calculate the arithmetical middle.
00297                         q = (*iter->pointer);
00298                         iter--;
00299                         q = add(q,(*iter->pointer));
00300                         q = doubleMul(q,0.5);
00301                 }
00302                 else {                                                                  //else return the quartil
00303                         q = (*iter->pointer);
00304                 }
00305 
00306                 return q;
00307         }
00308 
00309         /**
00310          * this function calculate the upper quartil.
00311          *
00312          * use add and doubleMul
00313          * @return the upper quartil
00314          */
00315         type getQuartil3() {
00316                 type q;
00317                 int x;
00318                 int num = m_vector.size()*3/4;
00319                 std::_List_iterator<TYPE_SAVE> iter;
00320 
00321                 if(!m_listCreated)
00322                         sort();                                                         //sort the set.
00323 
00324                 iter = m_list.begin();
00325                 for(x=0;x<num;x++) iter++;                              //go to the upper quartil
00326 
00327                 if(m_vector.size() % 4 == 0) {                  //if the real upper quartil between two values add this values and calculate the arithmetical middle.
00328                         q = (*iter->pointer);
00329                         iter--;
00330                         q = add(q,(*iter->pointer));
00331                         q = doubleMul(q,0.5);
00332                 }
00333                 else {                                                                  //else return the quartil
00334                         q = (*iter->pointer);
00335                 }
00336 
00337                 return q;
00338         }
00339 
00340         /**
00341          * this function calculate the range between the upper and under quartil. This range is called inter-quartil-range.
00342          *
00343          * use sub
00344          * @return the IQR
00345          */
00346         type getIQR() {
00347                 type q1 = getQuartil1();                        //calculate the under quartil
00348                 type q3 = getQuartil3();                        //calculate the upper quartil
00349 
00350                 return sub(q3,q1);                                      //IQR = Q3 - Q1
00351         }
00352 
00353         /**
00354          * this function calculate the whisker distance
00355          *
00356          * use doubleMul
00357          * @param factor (double) the factor for this distance
00358          * @return the result
00359          */
00360         type getWhisker(double factor) {
00361                 type dIqr = getIQR();                   //calculate the IQR
00362 
00363                 return doubleMul(dIqr,factor);  //WHISKER distance is factor*IQR
00364         }
00365 
00366         /**
00367          * this function search the lowest value in the set which is from under quartil inside the whisker distance
00368          *
00369          * use sub, lower and zero
00370          * @param factor (double) this factor is for calculating the whisker distance.
00371          * @return the lowest value inside
00372          */
00373         type getWhisker1(double factor) {
00374                 type dW = getWhisker(factor);                           //calculate the whisker distance
00375                 type dQ1 = getQuartil1();                                       //calculate the under quartil
00376                                                                                                         //TODO for optimization: getWhisker use getIQR and this calculate Q1 so it will be calculate two times!!!
00377                 type dBorder = sub(dQ1,dW);                                     //where is the border for the lowest value
00378                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
00379 
00380                 while(lower((*iter->pointer),dBorder) && iter!=m_list.end()) {          //search
00381                         iter++;
00382                         if(iter==m_list.end())
00383                                 break;
00384                 }
00385 
00386                 if(iter==m_list.end())          // ERROR
00387                         return zero();
00388 
00389                 return (*iter->pointer);
00390         }
00391 
00392         /**
00393          * this function search the highest value in the set which is from the upper quartil inside the whisker distance
00394          *
00395          * use add and lower
00396          * @param factor (double) this factor is for calculating the whisker distance.
00397          * @return the highest value inside
00398          */
00399         type getWhisker3(double factor) {
00400                 type dW = getWhisker(factor);                           //calculate the whisker distance
00401                 type dQ3 = getQuartil3();                                       //calculate the upper quartil
00402                                                                                                         //TODO for optimization: getWhisker use getIQR and this calculate Q3 so it will be calculate two times!!!
00403                 type dBorder = add(dQ3,dW);                                     //where is the border for the lowest value
00404                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
00405 
00406                 while(lower((*iter->pointer),dBorder) && iter!=m_list.end()) {          //search
00407                         iter++;
00408                         if(iter==m_list.end())
00409                                 break;
00410                 }
00411 
00412                 if(iter!=m_list.begin())
00413                         iter--;
00414 
00415                 return (*iter->pointer);
00416         }
00417 
00418         /**
00419          * this function give you the number of elements in the giving set, which aren't in the whisker distance
00420          *
00421          * use lower and higher
00422          * @param factor (double) this factor is for calculating the whisker distance
00423          * @return (int) the number of extreme values in the set
00424          */
00425         unsigned int getNumExtrems(double factor) {
00426                 unsigned int result = 0;
00427                 type dW1 = getWhisker1(factor);                                                         //find W1
00428                 type dW3 = getWhisker3(factor);                                                         //find W3
00429                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
00430 
00431                 while(lower((*iter->pointer),dW1) && iter!=m_list.end()) {      //count all elements which are lower than W1
00432                         iter++;
00433                         if(iter==m_list.end())
00434                                 break;
00435                         result++;
00436                 }
00437 
00438                 while(!higher((*iter->pointer),dW3) && iter!=m_list.end()) {    //go from W1 to W3
00439                         iter++;
00440                         if(iter==m_list.end())
00441                                 break;
00442                 }
00443 
00444                 while(iter!=m_list.end()) {                                                                     //count all element which are higher than W3
00445                         iter++;
00446                         result++;
00447                 }
00448 
00449                 return result;
00450         }
00451 
00452         /**
00453          * this function gives one extreme value back
00454          *
00455          * use lower, higher and zero
00456          * @param factor (double) the factor for the whisker distance
00457          * @param i (unsigned int) the index of the searched extreme value
00458          * @return the founded extreme value
00459          */
00460         type getExtrem(double factor, unsigned int i) {
00461                 type dW1 = getWhisker1(factor);                                                 //find W1
00462                 type dW3 = getWhisker3(factor);                                                 //find W3
00463                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
00464 
00465                 while(lower((*iter->pointer),dW1) && iter!=m_list.end()) {                      //search in lower area
00466                         i--;
00467 
00468                         if(i==0)
00469                                 return (*iter->pointer);
00470 
00471                         iter++;
00472                         if(iter==m_list.end())
00473                                 break;
00474                 }
00475 
00476                 while(!higher((*iter->pointer),dW3) && iter!=m_list.end()) {            //go from W1 to W3
00477                         iter++;
00478                         if(iter==m_list.end())
00479                                 break;
00480                 }
00481 
00482                 while(iter!=m_list.end()) {                                                                                     //search in upper area
00483                         i--;
00484 
00485                         if(i==0)
00486                                 return (*iter->pointer);
00487 
00488                         iter++;
00489                 }
00490 
00491                 return zero();          //not found                                                                             //if not found return zero
00492         }
00493 
00494         /**
00495          * this function search the value which is next to zero.
00496          *
00497          * use zero, sub and lower
00498          * @return the best value
00499          */
00500         type getBest(void) {
00501                 type z = zero();                                                                                        //test value is zero
00502                 type* l;
00503                 type* h;
00504 
00505                 if(!m_listCreated)
00506                         sort();                                                                                                 //sort the list
00507 
00508                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
00509 
00510                 while(lower((*iter->pointer),z) && iter!=m_list.end()) {        //search the element which is as first higher than zero
00511                         iter++;
00512                         if(iter==m_list.end())
00513                                 break;
00514                 }
00515 
00516                 if(iter!=m_list.end())
00517                         //return (*iter->pointer);
00518                         h = iter->pointer;
00519 
00520                 else {
00521                         iter--;
00522                         //return (*iter->pointer);
00523                         h = iter->pointer;
00524                 }
00525 
00526                 while(!lower((*iter->pointer),z) && iter!= m_list.begin()) {    //search the element which is as first lower than zero
00527                         iter--;
00528                         if(iter==m_list.begin())
00529                                 break;
00530                 }
00531 
00532                 l = iter->pointer;
00533 
00534                 if(lower(sub(*h,z),sub(z,*l)))          //test which is next to zero
00535                         return *h;
00536                 else
00537                         return *l;
00538         }
00539 
00540 protected:
00541 
00542         /**
00543          * help structur for sorting the set.
00544          * define the lower than operator
00545          */
00546         struct TYPE_SAVE {
00547                 TYPE_SAVE(type& a) : pointer(&a) {}
00548 
00549                 type* pointer;
00550 
00551                 bool operator<(const TYPE_SAVE& other) {
00552                         return lower((*pointer),(*other.pointer));
00553                 }
00554         };
00555 
00556         /**
00557          * this vector save the giving set.
00558          */
00559         std::vector<type>& m_vector;
00560 
00561         /**
00562          * this list saves the sorted set
00563          */
00564         std::list<TYPE_SAVE> m_list;
00565 
00566         /**
00567          * this variable remember if the sorted list is created
00568          */
00569         bool m_listCreated;
00570 
00571         /**
00572          * this function create the sorted list
00573          */
00574         void sort(void) {
00575                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter;
00576 
00577                 for(iter = m_vector.begin(); iter != m_vector.end(); iter++) {                  //fill the sorted list with elements of the help structur
00578                         m_list.push_back(TYPE_SAVE((*iter)));
00579                 }
00580 
00581                 m_list.sort();                          //sort the list
00582                 m_listCreated = true;           //remember that it is created.
00583         }
00584 };
00585 
00586 #endif /* TEMPLATEVALUEANALYSATION_H_ */
Generated on Thu Jun 28 14:45:37 2012 for Robot Simulator of the Robotics Group for Self-Organization of Control by  doxygen 1.6.3