-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtestFastCDF.cpp
137 lines (111 loc) · 3.94 KB
/
testFastCDF.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (C) 2020 EDF
// All Rights Reserved
// This code is published under the GNU Lesser General Public License (GNU LGPL)
#define BOOST_TEST_MODULE testFastCDF
#define BOOST_TEST_DYN_LINK
#include <vector>
#include <memory>
#include <iostream>
#include <boost/test/unit_test.hpp>
#include <boost/chrono.hpp>
#include <boost/timer/timer.hpp>
#include <boost/random.hpp>
#include <Eigen/Dense>
#include "fastCDF.h"
using namespace std;
using boost::timer::cpu_timer;
using boost::timer::auto_cpu_timer;
//using namespace StOpt;
using namespace Eigen;
double accuracyEqual = 1e-10;
/// \brief Calculate CDF with naive method
/// \param p_x particules (sample) size : (dimension, nbSim)
/// \param p_z rectilinear points
/// \param p_y estimate for each p_x point
ArrayXd CDFDirect(const ArrayXXd &p_x, const vector< shared_ptr<ArrayXd> > &p_z, const ArrayXd &p_y)
{
// store nbpt per dimension before
ArrayXi nbPtZ(p_z.size());
nbPtZ(0) = 1;
for (size_t id = 0; id < p_z.size() - 1; ++id)
nbPtZ(id + 1) = nbPtZ(id) * p_z[id]->size();
// nb point
int nbPtZT = nbPtZ(p_z.size() - 1) * p_z[p_z.size() - 1]->size();
// store index
ArrayXi index(p_z.size());
// for return
ArrayXd retCDF = ArrayXd::Zero(nbPtZT);
for (int ip = 0; ip < nbPtZT ; ++ip)
{
// index
int ipt = ip;
for (int id = p_z.size() - 1; id >= 0; --id)
{
index(id) = static_cast<int>(ipt / nbPtZ(id));
ipt -= index(id) * nbPtZ(id);
}
for (int is = 0 ; is < p_x.cols(); ++is)
{
bool bAdd = true;
for (int id = 0; id < p_x.rows(); ++id)
{
if (p_x(id, is) > (*p_z[id])(index(id)))
{
bAdd = false;
break;
}
}
if (bAdd)
{
retCDF(ip) += p_y(is);
}
}
}
return retCDF / p_y.size();
}
BOOST_AUTO_TEST_CASE(testFastCDF)
{
boost::mt19937 generator;
boost::normal_distribution<double> normalDistrib;
boost::variate_generator<boost::mt19937 &, boost::normal_distribution<double> > normalRand(generator, normalDistrib);
for (int ndim = 2; ndim <= 6; ++ndim)
{
int nbSim = 2000 ;
for (int iter = 0; iter < 4; ++iter)
{
// number of evaluation points per dimension
int nbEvalPerDim = static_cast<int>(pow(nbSim, 1. / ndim));
ArrayXXd x(ndim, nbSim);
vector< shared_ptr< ArrayXd > > z(ndim) ; // evaluation points
for (int id = 0; id < ndim; ++id)
{
for (int ip = 0; ip < nbSim; ++ip)
{
x(id, ip) = normalRand();
}
ArrayXd zDim = ArrayXd::LinSpaced(nbEvalPerDim, x.row(id).minCoeff() + 0.01, x.row(id).maxCoeff() - 0.01);
z[id] = make_shared<ArrayXd>(zDim);
}
// size of window
ArrayXd h = ArrayXd::Constant(ndim, 0.2);
// calculate CDF
ArrayXd y = ArrayXd::Constant(nbSim, 1.);
cpu_timer timeNaive;
timeNaive.start();
// direct
ArrayXd CDFNaive = CDFDirect(x, z, y);
timeNaive.stop();
boost::chrono::duration<double> secondNaive = boost::chrono::nanoseconds(timeNaive.elapsed().user);
cpu_timer timeFast;
timeFast.start();
// fast
ArrayXd CDFFastR = fastCDF(x, z, y);
timeFast.stop();
boost::chrono::duration<double> secondFast = boost::chrono::nanoseconds(timeFast.elapsed().user);
cout << " ndim " << ndim << " fast " << secondFast.count() << " naive " << secondNaive.count() << endl ;
for (int is = 0; is < CDFNaive.size(); ++is)
BOOST_CHECK_CLOSE(CDFNaive(is), CDFFastR(is), accuracyEqual);
nbSim *= 2;
}
}
}