00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _MRPT_MONTE_CARLO_H_
00029 #define _MRPT_MONTE_CARLO_H_
00030
00031 #include <map>
00032 #include <cmath>
00033 #include <vector>
00034 #include <numeric>
00035 #include <algorithm>
00036 #include <stdexcept>
00037 #include <functional>
00038 #include <mrpt/gui/CDisplayWindowPlots.h>
00039 #include <mrpt/random.h>
00040 #include <mrpt/utils/CTicTac.h>
00041
00042 namespace mrpt { namespace math {
00043
00044
00045
00046
00047 template<typename T,typename NUM,typename OTHER> class CMonteCarlo {
00048
00049
00050
00051
00052
00053
00054
00055
00056 private:
00057 mrpt::random::CRandomGenerator gen;
00058 class CStatisticalAnalyzer {
00059 private:
00060 vector<NUM> data;
00061 public:
00062 template<typename VEC> inline CStatisticalAnalyzer(const VEC &v1):data(v1.begin(),v1.end()) {}
00063 template<typename VEC> inline void setData(const VEC &v1) {
00064 data.assign(v1.begin(),v1.end());
00065 }
00066 template<typename VEC> inline void getData(VEC &v1) const {
00067 v1.assign(data.begin(),data.end());
00068 }
00069 template<typename VEC1,typename VEC2> inline void getDistribution(VEC1 &vx,VEC2 &vy,const NUM width=1.0) const {
00070 mrpt::vector_double vvx,vvy;
00071 getDistribution(vvx,vvy,width);
00072 vx.assign(vvx.begin(),vvx.end());
00073 vy.assign(vvy.begin(),vvy.end());
00074 }
00075
00076 inline void getDistribution(mrpt::vector_double &vx,mrpt::vector_double &vy,const NUM width=1.0) const {
00077 CHistogram hist(CHistogram::createWithFixedWidth(0,*max_element(data.begin(),data.end()),width));
00078 hist.add(data);
00079 hist.getHistogram(vx,vy);
00080 }
00081
00082 };
00083 public:
00084
00085
00086 T (*valueGenerator)(mrpt::random::CRandomGenerator &);
00087
00088 NUM (*errorFun1)(const T &);
00089
00090 OTHER (*intermediateFun)(const T &);
00091 NUM (*errorFun2)(const T &,const OTHER &);
00092 inline CMonteCarlo():gen(),valueGenerator(NULL),errorFun1(NULL),intermediateFun(NULL),errorFun2(NULL) {}
00093 NUM doExperiment(size_t N,double &time,bool showInWindow=false) {
00094 if (!valueGenerator) throw std::logic_error("Value generator function is not set.");
00095 std::vector<T> baseData(N);
00096 std::vector<NUM> errorData(N);
00097 mrpt::utils::CTicTac meter;
00098 for (size_t i=0;i<N;++i) baseData[i]=valueGenerator(gen);
00099 if (errorFun1) {
00100 meter.Tic();
00101 std::transform(baseData.begin(),baseData.end(),errorData.begin(),errorFun1);
00102 time=meter.Tac();
00103 } else {
00104 if (!intermediateFun||!errorFun2) throw std::logic_error("Experiment-related functions are not set.");
00105 std::vector<OTHER> intermediate(N);
00106 transform(baseData.begin(),baseData.end(),intermediate.begin(),intermediateFun);
00107 meter.Tic();
00108 for (size_t i=0;i<N;++i) errorData[i]=errorFun2(baseData[i],intermediate[i]);
00109 time=meter.Tac();
00110 }
00111 NUM res=accumulate(errorData.begin(),errorData.end(),NUM(0))/errorData.size();
00112 if (showInWindow) {
00113 CStatisticalAnalyzer st(errorData);
00114 mrpt::gui::CDisplayWindowPlots wnd("Error results from Monte Carlo simulation");
00115 std::vector<NUM> errorX,errorY;
00116 st.getDistribution(errorX,errorY,0.1);
00117 wnd.plot(errorX,errorY,"b-","Plot1");
00118 NUM maxVal=*std::max_element(errorY.begin(),errorY.end());
00119 std::vector<NUM> dx(2,res),dy(mrpt::utils::make_vector<2,NUM>(0,maxVal));
00120 wnd.plot(dx,dy,"r-","Plot2");
00121 while (wnd.isOpen());
00122 }
00123 return res;
00124 }
00125 };
00126
00127 }}
00128 #endif