ROL
ROL_MonteCarloGenerator.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_MONTECARLOGENERATOR_HPP
45 #define ROL_MONTECARLOGENERATOR_HPP
46 
47 #include "ROL_SampleGenerator.hpp"
48 #include "ROL_Distribution.hpp"
49 
50 namespace ROL {
51 
52 template<class Real>
53 class MonteCarloGenerator : public SampleGenerator<Real> {
54 private:
55  int nSamp_;
56  const bool use_normal_;
57  const bool use_SA_;
58  const bool adaptive_;
59  const int numNewSamps_;
60  std::vector<std::vector<Real> > data_;
61 
62  Real sum_val_;
63  Real sum_val2_;
64  Real sum_ng_;
65  Real sum_ng2_;
66 
67  const bool useDist_;
68  const std::vector<ROL::Ptr<Distribution<Real> > > dist_;
69 
70  const int seed_;
71 
72  Real ierf(Real input) const {
73  std::vector<Real> coeff;
74  Real pi = ROL::ScalarTraits<Real>::pi(), zero(0), one(1), two(2), tol(1e-4);
75  Real c(1);
76  Real tmp = c * (std::sqrt(pi)/two * input);
77  Real val = tmp;
78  coeff.push_back(c);
79  int cnt = 1;
80  while (std::abs(tmp) > tol*std::abs(val)) {
81  c = zero;
82  for ( unsigned i = 0; i < coeff.size(); i++ ) {
83  c += coeff[i]*coeff[coeff.size()-1-i]/((i+1)*(2*i+1));
84  }
85  Real ind = static_cast<Real>(cnt);
86  tmp = c/(two*ind+one) * std::pow(std::sqrt(pi)/two*input, two*ind+one);
87  val += tmp;
88  coeff.push_back(c);
89  cnt++;
90  }
91  return val;
92  }
93 
94  Real random(void) const {
95  return static_cast<Real>(rand())/static_cast<Real>(RAND_MAX);
96  }
97 
98  std::vector<std::vector<Real> > sample(int nSamp, bool store = true) {
99  srand(seed_);
100  const Real zero(0), one(1), two(2), tol(0.1);
101  int rank = SampleGenerator<Real>::batchID();
102  const int dim = (!useDist_ ? data_.size() : dist_.size());
103  std::vector<Real> pts(nSamp*dim, zero);
104  if (rank == 0) {
105  // Generate samples
106  for (int i = 0; i < nSamp; ++i) {
107  if ( !useDist_ ) {
108  for (int j = 0; j < dim; ++j) {
109  if ( use_normal_ ) {
110  pts[j + i*dim] = std::sqrt(two*(data_[j])[1])*ierf(two*random()-one) + (data_[j])[0];
111  }
112  else {
113  pts[j + i*dim] = ((data_[j])[1]-(data_[j])[0])*random()+(data_[j])[0];
114  }
115  }
116  }
117  else {
118  for (int j = 0; j < dim; ++j) {
119  pts[j + i*dim] = (dist_[j])->invertCDF(random());
120  while (std::abs(pts[j + i*dim]) > tol*ROL_INF<Real>()) {
121  pts[j + i*dim] = (dist_[j])->invertCDF(random());
122  }
123  }
124  }
125  }
126  }
127  SampleGenerator<Real>::broadcast(&pts[0],nSamp*dim,0);
128  // Separate samples across processes
129  int nProc = SampleGenerator<Real>::numBatches();
130  int frac = nSamp / nProc;
131  int rem = nSamp % nProc;
132  int N = frac + ((rank < rem) ? 1 : 0);
133  int offset = 0;
134  for (int i = 0; i < rank; ++i) {
135  offset += frac + ((i < rem) ? 1 : 0);
136  }
137  std::vector<std::vector<Real> > mypts;
138  std::vector<Real> pt(dim);
139  for (int i = 0; i < N; ++i) {
140  int I = offset+i;
141  for (int j = 0; j < dim; ++j) {
142  pt[j] = pts[j + I*dim];
143  }
144  mypts.push_back(pt);
145  }
146  if ( store ) {
147  std::vector<Real> mywts(N, one/static_cast<Real>(nSamp));
150  }
151  return mypts;
152  }
153 
154  void sample(void) {
155  sample(nSamp_,true);
156  }
157 
158 public:
159  MonteCarloGenerator(const int nSamp,
160  const std::vector<ROL::Ptr<Distribution<Real> > > &dist,
161  const ROL::Ptr<BatchManager<Real> > &bman,
162  const bool use_SA = false,
163  const bool adaptive = false,
164  const int numNewSamps = 0,
165  const int seed = 123454321)
166  : SampleGenerator<Real>(bman),
167  nSamp_(nSamp),
168  use_normal_(false),
169  use_SA_(use_SA),
170  adaptive_(adaptive),
171  numNewSamps_(numNewSamps),
172  sum_val_(0),
173  sum_val2_(0),
174  sum_ng_(0),
175  sum_ng2_(0),
176  useDist_(true),
177  dist_(dist),
178  seed_(seed) {
179  int nProc = SampleGenerator<Real>::numBatches();
180  ROL_TEST_FOR_EXCEPTION( nSamp_ < nProc, std::invalid_argument,
181  ">>> ERROR (ROL::MonteCarloGenerator): Total number of samples is less than the number of batches!");
182  sample();
183  }
184 
185  MonteCarloGenerator(const int nSamp,
186  std::vector<std::vector<Real> > &bounds,
187  const ROL::Ptr<BatchManager<Real> > &bman,
188  const bool use_SA = false,
189  const bool adaptive = false,
190  const int numNewSamps = 0,
191  const int seed = 123454321)
192  : SampleGenerator<Real>(bman),
193  nSamp_(nSamp),
194  use_normal_(false),
195  use_SA_(use_SA),
196  adaptive_(adaptive),
197  numNewSamps_(numNewSamps),
198  sum_val_(0),
199  sum_val2_(0),
200  sum_ng_(0),
201  sum_ng2_(0),
202  useDist_(false),
203  seed_(seed) {
204  int nProc = SampleGenerator<Real>::numBatches();
205  ROL_TEST_FOR_EXCEPTION( nSamp_ < nProc, std::invalid_argument,
206  ">>> ERROR (ROL::MonteCarloGenerator): Total number of samples is less than the number of batches!");
207  unsigned dim = bounds.size();
208  data_.clear();
209  Real tmp(0);
210  for ( unsigned j = 0; j < dim; j++ ) {
211  if ( (bounds[j])[0] > (bounds[j])[1] ) {
212  tmp = (bounds[j])[0];
213  (bounds[j])[0] = (bounds[j])[1];
214  (bounds[j])[1] = tmp;
215  data_.push_back(bounds[j]);
216  }
217  data_.push_back(bounds[j]);
218  }
219  sample();
220  }
221 
222  MonteCarloGenerator(const int nSamp,
223  const std::vector<Real> &mean,
224  const std::vector<Real> &std,
225  const ROL::Ptr<BatchManager<Real> > &bman,
226  const bool use_SA = false,
227  const bool adaptive = false,
228  const int numNewSamps = 0,
229  const int seed = 123454321)
230  : SampleGenerator<Real>(bman),
231  nSamp_(nSamp),
232  use_normal_(true),
233  use_SA_(use_SA),
234  adaptive_(adaptive),
235  numNewSamps_(numNewSamps),
236  sum_val_(0),
237  sum_val2_(0),
238  sum_ng_(0),
239  sum_ng2_(0),
240  useDist_(false),
241  seed_(seed) {
242  int nProc = SampleGenerator<Real>::numBatches();
243  ROL_TEST_FOR_EXCEPTION( nSamp_ < nProc, std::invalid_argument,
244  ">>> ERROR (ROL::MonteCarloGenerator): Total number of samples is less than the number of batches!");
245  unsigned dim = mean.size();
246  data_.clear();
247  std::vector<Real> tmp(2,static_cast<Real>(0));
248  for ( unsigned j = 0; j < dim; j++ ) {
249  tmp[0] = mean[j];
250  tmp[1] = std[j];
251  data_.push_back(tmp);
252  }
253  sample();
254  }
255 
256  void update( const Vector<Real> &x ) {
258  Real zero(0);
259  sum_val_ = zero;
260  sum_val2_ = zero;
261  sum_ng_ = zero;
262  sum_ng_ = zero;
263  if ( use_SA_ ) {
264  sample();
265  }
266  }
267 
268  Real computeError( std::vector<Real> &vals ) {
269  if ( adaptive_ && !use_SA_ ) {
270  Real zero(0), one(1), tol(1e-8);
271  // Compute unbiased sample variance
272  int cnt = 0;
273  for ( int i = SampleGenerator<Real>::start(); i < SampleGenerator<Real>::numMySamples(); i++ ) {
274  sum_val_ += vals[cnt];
275  sum_val2_ += vals[cnt]*vals[cnt];
276  cnt++;
277  }
278  Real mymean = sum_val_ / nSamp_;
279  Real mean = zero;
280  SampleGenerator<Real>::sumAll(&mymean,&mean,1);
281 
282  Real myvar = (sum_val2_ - mean*mean)/(nSamp_-one);
283  Real var = zero;
284  SampleGenerator<Real>::sumAll(&myvar,&var,1);
285  // Return Monte Carlo error
286  vals.clear();
287  return std::sqrt(var/(nSamp_))*tol;
288  }
289  else {
290  vals.clear();
291  return static_cast<Real>(0);
292  }
293  }
294 
295  Real computeError( std::vector<ROL::Ptr<Vector<Real> > > &vals, const Vector<Real> &x ) {
296  if ( adaptive_ && !use_SA_ ) {
297  Real zero(0), one(1), tol(1e-4);
298  // Compute unbiased sample variance
299  int cnt = 0;
300  Real ng = zero;
301  for ( int i = SampleGenerator<Real>::start(); i < SampleGenerator<Real>::numMySamples(); i++ ) {
302  ng = (vals[cnt])->norm();
303  sum_ng_ += ng;
304  sum_ng2_ += ng*ng;
305  cnt++;
306  }
307  Real mymean = sum_ng_ / nSamp_;
308  Real mean = zero;
309  SampleGenerator<Real>::sumAll(&mymean,&mean,1);
310 
311  Real myvar = (sum_ng2_ - mean*mean)/(nSamp_-one);
312  Real var = zero;
313  SampleGenerator<Real>::sumAll(&myvar,&var,1);
314  // Return Monte Carlo error
315  vals.clear();
316  return std::sqrt(var/(nSamp_))*tol;
317  }
318  else {
319  vals.clear();
320  return static_cast<Real>(0);
321  }
322  }
323 
324  void refine(void) {
325  if ( adaptive_ && !use_SA_ ) {
326  Real zero(0), one(1);
327  std::vector<std::vector<Real> > pts;
328  std::vector<Real> pt(data_.size(),zero);
329  for ( int i = 0; i < SampleGenerator<Real>::numMySamples(); i++ ) {
331  pts.push_back(pt);
332  }
333  std::vector<std::vector<Real> > pts_new = sample(numNewSamps_,false);
334  pts.insert(pts.end(),pts_new.begin(),pts_new.end());
335  nSamp_ += numNewSamps_;
336  std::vector<Real> wts(pts.size(),one/((Real)nSamp_));
340  }
341  }
342 
343  int numGlobalSamples(void) const {
344  return nSamp_;
345  }
346 
347 };
348 
349 }
350 
351 #endif
Real ierf(Real input) const
virtual void update(const Vector< Real > &x)
Real computeError(std::vector< ROL::Ptr< Vector< Real > > > &vals, const Vector< Real > &x)
MonteCarloGenerator(const int nSamp, std::vector< std::vector< Real > > &bounds, const ROL::Ptr< BatchManager< Real > > &bman, const bool use_SA=false, const bool adaptive=false, const int numNewSamps=0, const int seed=123454321)
virtual std::vector< Real > getMyPoint(const int i) const
void broadcast(Real *input, int cnt, int root) const
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
MonteCarloGenerator(const int nSamp, const std::vector< Real > &mean, const std::vector< Real > &std, const ROL::Ptr< BatchManager< Real > > &bman, const bool use_SA=false, const bool adaptive=false, const int numNewSamps=0, const int seed=123454321)
void sumAll(Real *input, Real *output, int dim) const
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
Real computeError(std::vector< Real > &vals)
static constexpr Real pi() noexcept
std::vector< std::vector< Real > > sample(int nSamp, bool store=true)
virtual void refine(void)
void setPoints(std::vector< std::vector< Real > > &p)
MonteCarloGenerator(const int nSamp, const std::vector< ROL::Ptr< Distribution< Real > > > &dist, const ROL::Ptr< BatchManager< Real > > &bman, const bool use_SA=false, const bool adaptive=false, const int numNewSamps=0, const int seed=123454321)
const std::vector< ROL::Ptr< Distribution< Real > > > dist_
void update(const Vector< Real > &x)
void setWeights(std::vector< Real > &w)
std::vector< std::vector< Real > > data_