https://mooseframework.inl.gov
TestBootstrapCalculators.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 #include <vector>
10 #include <cmath>
11 
12 #include "gtest/gtest.h"
13 #include "Calculators.h"
14 #include "BootstrapCalculators.h"
15 #include "MooseRandom.h"
16 #include "Normal.h"
17 #include "libmesh/communicator.h"
18 #include "libmesh/parallel_object.h"
19 
20 using namespace libMesh;
21 using namespace StochasticTools;
22 
37 {
38 public:
39  NormalSampler(Real mean, Real std, unsigned int seed) : _mean(mean), _std(std)
40  {
41  _generator.seed(seed);
42  }
43 
44  Real sample() const { return _generator.randNormal(_mean, _std); }
45  std::vector<Real> sample(std::size_t n) const
46  {
47  std::vector<Real> data(n);
48  std::for_each(
49  data.begin(), data.end(), [&](Real & v) { v = _generator.randNormal(_mean, _std); });
50  return data;
51  }
52 
53  Real meanConfidence(Real level, std::size_t n) const
54  {
55  const Real z = computeZ(level);
56  const Real mean_std = _std / std::sqrt(n);
57  return z * mean_std;
58  }
59 
60  Real stdConfidence(Real level, std::size_t n) const
61  {
62  const Real z = computeZ(level);
63  const Real nr = n;
64  const Real gg = std::exp(std::lgamma(nr / 2.) - std::lgamma((nr - 1.) / 2.));
65  const Real std_std = _std * std::sqrt(1.0 - 2. / (nr - 1.) * gg * gg);
66  return z * std_std;
67  }
68 
69 private:
70  static Real computeZ(Real level)
71  {
72  const Real alpha = level < 0.5 ? level : 1. - level;
73  const Real z = -Normal::quantile(alpha / 2., 0, 1);
74  return level < 0.5 ? -z : z;
75  }
76 
77  const Real _mean;
78  const Real _std;
80 };
81 
82 TEST(BootstrapCalculators, Percentile)
83 {
84  // Sampling quantities
85  const Real mean_dist = 1993;
86  const Real std_dist = 27;
87  const std::size_t nsamp = 1000;
88 
89  // CI quantities
90  const unsigned int replicates = 1e4;
91  const std::vector<Real> levels = {0.05, 0.1, 0.2, 0.8, 0.9, 0.95};
92 
93  // Parallel object to give to calculators
95  ParallelObject po(comm);
96 
97  // Construct mean and standard-deviation calculators
98  MultiMooseEnum calc("mean stddev", "mean stddev", true);
99  auto mean_calc = makeCalculator(calc[0], po);
100  auto std_calc = makeCalculator(calc[1], po);
101 
102  // Construct bootstrap calculators
103  MooseEnum boot("percentile", "percentile", true);
104  auto mean_boot_calc = makeBootstrapCalculator(boot, po, levels, replicates, 2613, *mean_calc);
105  auto std_boot_calc = makeBootstrapCalculator(boot, po, levels, replicates, 2613, *std_calc);
106 
107  // Construct data and run bootstrapping
108  NormalSampler sampler(mean_dist, std_dist, 1945);
109  const auto data = sampler.sample(nsamp);
110  const Real mean_samp = mean_calc->compute(data, false);
111  const Real std_samp = std_calc->compute(data, false);
112  const std::vector<Real> mean_ci = mean_boot_calc->compute(data, false);
113  const std::vector<Real> std_ci = std_boot_calc->compute(data, false);
114 
115  // Compare with reference values
116  const Real tol = 5e-1;
117  for (const auto & l : index_range(levels))
118  {
119  const Real mean_ref = sampler.meanConfidence(levels[l], nsamp);
120  const Real std_ref = sampler.stdConfidence(levels[l], nsamp);
121  EXPECT_NEAR(mean_ci[l] - mean_samp, mean_ref, std::abs(mean_ref * tol));
122  EXPECT_NEAR(std_ci[l] - std_samp, std_ref, std::abs(std_ref * tol));
123  }
124 }
125 
126 TEST(BootstrapCalculators, BiasCorrectedAccelerated)
127 {
128  // Sampling quantities
129  const Real mean_dist = 1993;
130  const Real std_dist = 27;
131  const std::size_t nsamp = 1000;
132 
133  // CI quantities
134  const unsigned int replicates = 1e4;
135  const std::vector<Real> levels = {0.05, 0.1, 0.2, 0.8, 0.9, 0.95};
136 
137  // Parallel object to give to calculators
139  ParallelObject po(comm);
140 
141  // Construct mean and standard-deviation calculators
142  MultiMooseEnum calc("mean stddev", "mean stddev", true);
143  auto mean_calc = makeCalculator(calc[0], po);
144  auto std_calc = makeCalculator(calc[1], po);
145 
146  // Construct bootstrap calculators
147  MooseEnum boot("bca", "bca", true);
148  auto mean_boot_calc = makeBootstrapCalculator(boot, po, levels, replicates, 2613, *mean_calc);
149  auto std_boot_calc = makeBootstrapCalculator(boot, po, levels, replicates, 2613, *std_calc);
150 
151  // Construct data and run bootstrapping
152  NormalSampler sampler(mean_dist, std_dist, 1945);
153  const auto data = sampler.sample(nsamp);
154  const Real mean_samp = mean_calc->compute(data, false);
155  const Real std_samp = std_calc->compute(data, false);
156  const std::vector<Real> mean_ci = mean_boot_calc->compute(data, false);
157  const std::vector<Real> std_ci = std_boot_calc->compute(data, false);
158 
159  // Compare with reference values
160  const Real tol = 5e-1;
161  for (const auto & l : index_range(levels))
162  {
163  const Real mean_ref = sampler.meanConfidence(levels[l], nsamp);
164  const Real std_ref = sampler.stdConfidence(levels[l], nsamp);
165  EXPECT_NEAR(mean_ci[l] - mean_samp, mean_ref, std::abs(mean_ref * tol));
166  EXPECT_NEAR(std_ci[l] - std_samp, std_ref, std::abs(std_ref * tol));
167  }
168 }
169 
170 TEST(BootstrapCalculators, Percentile_Vec)
171 {
172  // Sampling quantities
173  const std::size_t nsamp = 1000;
174  const std::size_t nval = 26;
175  std::vector<NormalSampler> samplers;
176  for (const auto & k : make_range(nval))
177  samplers.emplace_back(/*mean = */ 1993 + 42 * k, /*std = */ 27 + 7 * k, 1945);
178 
179  // CI quantities
180  const unsigned int replicates = 1e4;
181  const std::vector<Real> levels = {0.05, 0.1, 0.2, 0.8, 0.9, 0.95};
182 
183  // Parallel object to give to calculators
185  ParallelObject po(comm);
186 
187  // Construct mean and standard-deviation calculators
188  MultiMooseEnum calc("mean stddev", "mean stddev", true);
189  auto mean_calc = makeCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(calc[0], po);
190  auto std_calc = makeCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(calc[1], po);
191 
192  // Construct bootstrap calculators
193  MooseEnum boot("percentile", "percentile", true);
194  auto mean_boot_calc = makeBootstrapCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(
195  boot, po, levels, replicates, 2613, *mean_calc);
196  auto std_boot_calc = makeBootstrapCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(
197  boot, po, levels, replicates, 2613, *std_calc);
198 
199  // Construct data and run bootstrapping
200  std::vector<std::vector<Real>> data(nsamp);
201  for (auto & dt : data)
202  for (const auto & samp : samplers)
203  dt.push_back(samp.sample());
204  const std::vector<Real> mean_samp = mean_calc->compute(data, false);
205  const std::vector<Real> std_samp = std_calc->compute(data, false);
206  const std::vector<std::vector<Real>> mean_ci = mean_boot_calc->compute(data, false);
207  const std::vector<std::vector<Real>> std_ci = std_boot_calc->compute(data, false);
208 
209  // Compare with reference values
210  const Real tol = 5e-1;
211  for (const auto & l : index_range(levels))
212  for (const auto & k : make_range(nval))
213  {
214  const Real mean_ref = samplers[k].meanConfidence(levels[l], nsamp);
215  const Real std_ref = samplers[k].stdConfidence(levels[l], nsamp);
216  EXPECT_NEAR(mean_ci[l][k] - mean_samp[k], mean_ref, std::abs(mean_ref * tol));
217  EXPECT_NEAR(std_ci[l][k] - std_samp[k], std_ref, std::abs(std_ref * tol));
218  }
219 }
220 
221 TEST(BootstrapCalculators, BiasCorrectedAccelerated_Vec)
222 {
223  // Sampling quantities
224  const std::size_t nsamp = 1000;
225  const std::size_t nval = 26;
226  std::vector<NormalSampler> samplers;
227  for (const auto & k : make_range(nval))
228  samplers.emplace_back(/*mean = */ 1993 + 42 * k, /*std = */ 27 + 7 * k, 1945);
229 
230  // CI quantities
231  const unsigned int replicates = 1e4;
232  const std::vector<Real> levels = {0.05, 0.1, 0.2, 0.8, 0.9, 0.95};
233 
234  // Parallel object to give to calculators
236  ParallelObject po(comm);
237 
238  // Construct mean and standard-deviation calculators
239  MultiMooseEnum calc("mean stddev", "mean stddev", true);
240  auto mean_calc = makeCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(calc[0], po);
241  auto std_calc = makeCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(calc[1], po);
242 
243  // Construct bootstrap calculators
244  MooseEnum boot("bca", "bca", true);
245  auto mean_boot_calc = makeBootstrapCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(
246  boot, po, levels, replicates, 2613, *mean_calc);
247  auto std_boot_calc = makeBootstrapCalculator<std::vector<std::vector<Real>>, std::vector<Real>>(
248  boot, po, levels, replicates, 2613, *std_calc);
249 
250  // Construct data and run bootstrapping
251  std::vector<std::vector<Real>> data(nsamp);
252  for (auto & dt : data)
253  for (const auto & samp : samplers)
254  dt.push_back(samp.sample());
255  const std::vector<Real> mean_samp = mean_calc->compute(data, false);
256  const std::vector<Real> std_samp = std_calc->compute(data, false);
257  const std::vector<std::vector<Real>> mean_ci = mean_boot_calc->compute(data, false);
258  const std::vector<std::vector<Real>> std_ci = std_boot_calc->compute(data, false);
259 
260  // Compare with reference values
261  const Real tol = 5e-1;
262  for (const auto & l : index_range(levels))
263  for (const auto & k : make_range(nval))
264  {
265  const Real mean_ref = samplers[k].meanConfidence(levels[l], nsamp);
266  const Real std_ref = samplers[k].stdConfidence(levels[l], nsamp);
267  EXPECT_NEAR(mean_ci[l][k] - mean_samp[k], mean_ref, std::abs(mean_ref * tol));
268  EXPECT_NEAR(std_ci[l][k] - std_samp[k], std_ref, std::abs(std_ref * tol));
269  }
270 }
Real meanConfidence(Real level, std::size_t n) const
const double tol
TEST(BootstrapCalculators, Percentile)
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
std::vector< Real > sample(std::size_t n) const
std::unique_ptr< Calculator< InType, OutType > > makeCalculator(const MooseEnumItem &item, const libMesh::ParallelObject &other)
Definition: Calculators.h:335
Real stdConfidence(Real level, std::size_t n) const
Enum for batch type in stochastic tools MultiApp.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:84
static const std::string alpha
Definition: NS.h:134
IntRange< T > make_range(T beg, T end)
These tests are meant to use the bootstrap calculators and test against analytical confidence interva...
NormalSampler(Real mean, Real std, unsigned int seed)
virtual Real quantile(const Real &p) const override
Definition: Normal.C:80
static const std::string k
Definition: NS.h:130
auto index_range(const T &sizable)
std::unique_ptr< BootstrapCalculator< InType, OutType > > makeBootstrapCalculator(const MooseEnum &, const libMesh::ParallelObject &, const std::vector< Real > &, unsigned int, unsigned int, StochasticTools::Calculator< InType, OutType > &)
static Real computeZ(Real level)