From 0c82be47df56cd913794446c438afba988def763 Mon Sep 17 00:00:00 2001 From: Johann Dreo Date: Thu, 13 Jun 2013 14:50:08 +0200 Subject: [PATCH] Add an Nth element stat to compute median without sorting the pop --- eo/src/utils/eoStat.h | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/eo/src/utils/eoStat.h b/eo/src/utils/eoStat.h index ae2569ab7..7099470cd 100644 --- a/eo/src/utils/eoStat.h +++ b/eo/src/utils/eoStat.h @@ -475,6 +475,51 @@ public : }; */ +//! A robust measure of the mass (generally used to compute the median). Do not alter the given pop. +template +class eoNthElementStat : public eoStat< EOT, typename EOT::Fitness > +{ +protected: + int _nth; + double _ratio; + +public: + using eoStat::value; + + eoNthElementStat( int nth = 0, std::string description = "NthElement") + : eoStat( 0.0, description ), _nth(nth), _ratio(-1.0) + {} + + eoNthElementStat( double ratio = 0.5, std::string description = "Median" ) + : eoStat( 0.0, description ), _nth(-1), _ratio(ratio) + {} + + virtual void operator()( const eoPop & _pop ) + { + if( _nth == -1 ) { // asked for a ratio + _nth = static_cast( std::floor(_pop.size() * _ratio) ); + } else { + assert( _ratio == -1 ); // asked for a position + } + + if( _pop.size() == 0 ) { + //FIXME how to implement value() = 0 ? + eo::log << eo::warnings << "Called " << className() << " on an empty pop, value unchanged" << std::endl; + + } else { + eoPop pop = _pop; // copy, thus no sorting of the original pop + + std::nth_element( pop.begin(), pop.begin()+_nth, pop.end() ); + value() = pop[_nth].fitness(); + } + } + + virtual std::string className(void) const { return "eoNthElementStat"; } +}; +/** @example t-eoIQRStat.cpp + */ + + //! A robust measure of dispersion (also called midspread or middle fifty) that is the difference between the third and the first quartile. template