Chebyshev
Unit testing for scientific software
Loading...
Searching...
No Matches
estimator.h
Go to the documentation of this file.
1
5
6#ifndef CHEBYSHEV_ESTIMATOR
7#define CHEBYSHEV_ESTIMATOR
8
9
10#include <functional>
11#include <cmath>
12
13#include "../core/common.h"
14#include "../core/random.h"
15#include "./prec_structures.h"
16
17
18namespace chebyshev {
19namespace prec {
20
21
23 namespace estimator {
24
25
29 template<typename FloatType = real_t>
30 inline auto quadrature1D() {
31
32 return [](
36
37 if(options.domain.size() != 1) {
38 throw std::runtime_error(
39 "estimator::quadrature1D only works on mono-dimensional domains"
40 );
41 }
42
43 interval domain = options.domain[0];
44
45 FloatType sum = 0;
46 FloatType sumSqr = 0;
47 FloatType sumAbs = 0;
48 FloatType max = 0;
49
50 const FloatType length = domain.length();
51 const FloatType dx = length / options.iterations;
54
55 FloatType diff = std::abs(funcApprox(domain.a) - funcExpected(domain.a));
56
57 sum += diff;
58 sumSqr += diff * diff;
59 sumAbs += std::abs(funcExpected(domain.a));
60 max = diff;
61
62 for (unsigned int i = 1; i < options.iterations; ++i) {
63
64 x = domain.a + i * dx;
65 diff = std::abs(funcApprox(x) - funcExpected(x));
66
67 if(diff > max)
68 max = diff;
69
70 if(i % 2 == 0)
71 coeff = 2;
72 else
73 coeff = 4;
74
75 sum += coeff * diff;
76 sumSqr += coeff * diff * diff;
78 }
79
80 diff = std::abs(funcApprox(domain.b) - funcExpected(domain.b));
81
82 sum += diff;
83 sumSqr += diff * diff;
84 sumAbs += std::abs(funcExpected(domain.b));
85
86 if(diff > max)
87 max = diff;
88
90 res.absErr = sum;
91 res.maxErr = max;
92 res.meanErr = (sum * dx / 3.0) / length;
93 res.rmsErr = std::sqrt((sumSqr * dx / 3.0) / length);
94 res.relErr = std::abs((sum * dx / 3.0) / (sumAbs * dx / 3.0));
95
96 return res;
97 };
98 }
99
100
109 template <
110 typename IntType = int,
111 typename ReturnType = IntType
112 >
113 inline auto discrete1D() {
114
115 // Return a one-dimensional discrete estimator as a lambda function
116 return [](
117 std::function<IntType(ReturnType)> funcApprox,
118 std::function<IntType(ReturnType)> funcExpected,
120
121 if(options.domain.size() != 1) {
122 throw std::runtime_error(
123 "estimator::discrete1D only works on mono-dimensional domains"
124 );
125 }
126
127 IntType extreme1 = IntType(std::ceil(options.domain[0].a));
128 IntType extreme2 = IntType(std::floor(options.domain[0].b));
129
132
133 prec_t maxErr = 0;
134 prec_t sumDiff = 0;
135 prec_t sumSqr = 0;
136 prec_t sumAbs = 0;
138
139 for (IntType n = lower; n <= upper; ++n) {
140
143
146
147 maxErr = std::max(maxErr, diff);
148 sumDiff += diff;
149 sumSqr += diff * diff;
150 sumAbs += std::abs((prec_t) funcExpected(n));
151 totalPoints++;
152 }
153
155 res.absErr = sumAbs;
156 res.maxErr = maxErr;
157 res.meanErr = totalPoints > 0 ? (sumDiff / totalPoints) : 0;
158 res.rmsErr = totalPoints > 0 ? (std::sqrt(sumSqr) / totalPoints) : 0;
159 res.relErr = sumDiff / sumAbs;
160 return res;
161 };
162 }
163
164
171 template<typename FloatType = real_t>
172 inline auto montecarlo1D(std::shared_ptr<random::random_context> rnd_ctx) {
173
174 // Return a one-dimensional Monte Carlo estimator as a lambda function
175 return [rnd_ctx](
179
180 random::random_source rnd = rnd_ctx->get_rnd();
181
182 if(options.domain.size() != 1) {
183 throw std::runtime_error(
184 "estimator::montecarlo1D only works on mono-dimensional domains"
185 );
186 }
187
188 FloatType sum = 0;
189 FloatType sumSqr = 0;
190 FloatType sumAbs = 0;
191 FloatType max = 0;
192 const FloatType length = options.domain[0].length();
193
194 for (int i = 0; i < options.iterations; ++i) {
195
196 FloatType x = rnd.uniform(options.domain[0].a, options.domain[0].b);
197 const FloatType diff = std::abs(funcApprox(x) - funcExpected(x));
198
199 max = std::max(max, diff);
200 sum += diff;
201 sumSqr += diff * diff;
202 sumAbs += std::abs(funcExpected(x));
203 }
204
206 res.maxErr = max;
207 res.meanErr = sum / options.iterations;
208 res.absErr = sum * (length / options.iterations);
209 res.rmsErr = std::sqrt(sumSqr * (length / options.iterations));
210 res.relErr = sum / sumAbs;
211
212 return res;
213 };
214 }
215
216
229 template <
230 typename FloatType = real_t,
231 typename Vector = std::vector<FloatType>
232 >
233 inline auto montecarlo(
234 std::shared_ptr<random::random_context> rnd_ctx, unsigned int dimensions) {
235
236 // Return an n-dimensional Monte Carlo estimator as a lambda function
237 return [rnd_ctx, dimensions](
238 std::function<FloatType(Vector)> funcApprox,
239 std::function<FloatType(Vector)> funcExpected,
241
242 random::random_source rnd = rnd_ctx->get_rnd();
243
244 if(options.domain.size() != dimensions) {
245 throw std::runtime_error(
246 "The estimation domain's dimension does not match "
247 "the instantiated number of dimensions "
248 "in estimator::montecarlo"
249 );
250 }
251
252 FloatType sum = 0;
253 FloatType sumSqr = 0;
254 FloatType sumAbs = 0;
255 FloatType max = 0;
256
257 // Compute the measure of a multi-interval
258 FloatType volume = 1;
259 for (interval k : options.domain)
260 volume *= k.length();
261
263
264 for (unsigned int i = 0; i < options.iterations; ++i) {
265
266 rnd.uniform(x, options.domain);
267
268 const FloatType diff = std::abs(funcApprox(x) - funcExpected(x));
269
270 if(max < diff)
271 max = diff;
272
273 sum += diff;
274 sumSqr += diff * diff;
275 sumAbs += std::abs(funcExpected(x));
276 }
277
279 res.maxErr = max;
280 res.meanErr = sum / options.iterations;
281 res.absErr = sum * (volume / options.iterations);
282 res.rmsErr = std::sqrt(sumSqr * (volume / options.iterations));
283 res.relErr = sum / sumAbs;
284
285 return res;
286 };
287 }
288 }
289}}
290
291
292#endif
long double prec_t
Floating-point type of higher precision, used in computations, such as error estimation.
Definition common.h:42
double real_t
Floating-point type, used as default for function arguments.
Definition common.h:37
auto quadrature1D()
Use Simpson's quadrature scheme to approximate error integrals for univariate real functions (endofun...
Definition estimator.h:30
auto montecarlo(std::shared_ptr< random::random_context > rnd_ctx, unsigned int dimensions)
Use crude Monte Carlo integration to approximate error integrals for multivariate real functions.
Definition estimator.h:233
auto montecarlo1D(std::shared_ptr< random::random_context > rnd_ctx)
Use crude Monte Carlo integration to approximate error integrals for univariate real functions.
Definition estimator.h:172
auto discrete1D()
Use a discrete estimator over a lattice of points, here implemented in one dimension,...
Definition estimator.h:113
General namespace of the framework.
Definition benchmark.h:22
constexpr FloatType get_nan()
Get a quiet NaN of the specified floating point type.
Definition common.h:65
std::function< Type(Type)> EndoFunction
An endofunction is a function which has the same type of input and output, such as a real function of...
Definition common.h:60
Structures for precision testing.
A structure holding the options for precision estimation.
Definition prec_structures.h:77
A structure holding the result of precision estimation.
Definition prec_structures.h:25
prec_t maxErr
Estimated maximum absolute error on interval.
Definition prec_structures.h:37
prec_t absErr
Estimated absolute error on interval.
Definition prec_structures.h:49
An interval on the real numbers.
Definition interval.h:16
real_t length() const
Returns the length of the interval.
Definition interval.h:33
double a
Lower extreme of the interval.
Definition interval.h:19
double b
Upper extreme of the interval.
Definition interval.h:22
A source of pseudorandom numbers.
Definition random.h:39
real_t uniform(real_t a, real_t b)
Generate a uniformly distributed random number.
Definition random.h:76