NEST main@caf0ae8
 
Loading...
Searching...
No Matches
random_generators.h
Go to the documentation of this file.
1/*
2 * random_generators.h
3 *
4 * This file is part of NEST.
5 *
6 * Copyright (C) 2004 The NEST Initiative
7 *
8 * NEST is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NEST is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NEST. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#ifndef RANDOM_GENERATORS_H
24#define RANDOM_GENERATORS_H
25
26// C++ includes:
27#include <algorithm>
28#include <initializer_list>
29#include <iterator>
30#include <memory>
31#include <random>
32#include <type_traits>
33#include <utility>
34
35// libnestutil includes:
36#include "randutils.hpp"
37
38// nestkernel includes:
39#include "node_collection.h"
40
41namespace nest
42{
43
44// Forward declarations
45class BaseRandomGenerator;
46template < typename DistributionT >
47class RandomDistribution;
48
49// Type definitions
51
61
62
67{
68public:
70 {
71 }
72
80 virtual unsigned long operator()( std::uniform_int_distribution< unsigned long >& d ) = 0;
81 virtual double operator()( std::uniform_real_distribution<>& d ) = 0;
82 virtual double operator()( std::normal_distribution<>& d ) = 0;
83 virtual double operator()( std::lognormal_distribution<>& d ) = 0;
84 virtual unsigned long operator()( std::binomial_distribution< unsigned long >& d ) = 0;
85 virtual double operator()( std::gamma_distribution<>& d ) = 0;
86 virtual double operator()( std::exponential_distribution<>& d ) = 0;
87 virtual unsigned long operator()( std::discrete_distribution< unsigned long >& d ) = 0;
88 virtual unsigned long operator()( std::poisson_distribution< unsigned long >& d ) = 0;
89
98 virtual unsigned long operator()( std::uniform_int_distribution< unsigned long >& d,
99 std::uniform_int_distribution< unsigned long >::param_type& p ) = 0;
100 virtual double operator()( std::uniform_real_distribution<>& d, std::uniform_real_distribution<>::param_type& p ) = 0;
101 virtual double operator()( std::normal_distribution<>& d, std::normal_distribution<>::param_type& p ) = 0;
102 virtual double operator()( std::lognormal_distribution<>& d, std::lognormal_distribution<>::param_type& p ) = 0;
103 virtual unsigned long operator()( std::binomial_distribution< unsigned long >& d,
104 std::binomial_distribution< unsigned long >::param_type& p ) = 0;
105 virtual double operator()( std::gamma_distribution<>& d, std::gamma_distribution<>::param_type& p ) = 0;
106 virtual double operator()( std::exponential_distribution<>& d, std::exponential_distribution<>::param_type& p ) = 0;
107 virtual unsigned long operator()( std::discrete_distribution< unsigned long >& d,
108 std::discrete_distribution< unsigned long >::param_type& p ) = 0;
109 virtual unsigned long operator()( std::poisson_distribution< unsigned long >& d,
110 std::poisson_distribution< unsigned long >::param_type& p ) = 0;
111
115 virtual double drand() = 0;
116
122 virtual unsigned long ulrand( unsigned long N ) = 0;
123
135 std::back_insert_iterator< std::vector< NodeIDTriple > > dest,
136 size_t n ) = 0;
137
148 virtual void partial_shuffle( std::vector< size_t >& data, const size_t n ) = 0;
149};
150
156template < typename RandomEngineT >
158{
159public:
160 using result_type = typename RandomEngineT::result_type;
161
162 RandomGenerator() = delete;
163 RandomGenerator( const RandomEngineT& rng ) = delete;
164
165 explicit RandomGenerator( std::initializer_list< std::uint32_t > seed )
166 : rng_()
167 , uniform_double_dist_0_1_( 0.0, 1.0 )
168 {
169 // Melissa O'Neill's seed sequence generator which provides better distributed seeds
170 // than std::seed_seq; see https://www.pcg-random.org/posts/developing-a-seed_seq-alternative.html
171 randutils::seed_seq_fe128 sseq( seed );
172 rng_.seed( sseq );
173 }
174
175 inline unsigned long
176 operator()( std::uniform_int_distribution< unsigned long >& d ) override
177 {
178 return d( rng_ );
179 }
180
181 inline double
182 operator()( std::uniform_real_distribution<>& d ) override
183 {
184 return d( rng_ );
185 }
186
187 inline double
188 operator()( std::normal_distribution<>& d ) override
189 {
190 return d( rng_ );
191 }
192
193 inline double
194 operator()( std::lognormal_distribution<>& d ) override
195 {
196 return d( rng_ );
197 }
198
199 inline unsigned long
200 operator()( std::binomial_distribution< unsigned long >& d ) override
201 {
202 return d( rng_ );
203 }
204
205 inline double
206 operator()( std::gamma_distribution<>& d ) override
207 {
208 return d( rng_ );
209 }
210
211 inline double
212 operator()( std::exponential_distribution<>& d ) override
213 {
214 return d( rng_ );
215 }
216
217 inline unsigned long
218 operator()( std::discrete_distribution< unsigned long >& d ) override
219 {
220 return d( rng_ );
221 }
222
223 inline unsigned long
224 operator()( std::poisson_distribution< unsigned long >& d ) override
225 {
226 return d( rng_ );
227 }
228
229 inline unsigned long
230 operator()( std::uniform_int_distribution< unsigned long >& d,
231 std::uniform_int_distribution< unsigned long >::param_type& p ) override
232 {
233 return d( rng_, p );
234 }
235
236 inline double
237 operator()( std::uniform_real_distribution<>& d, std::uniform_real_distribution<>::param_type& p ) override
238 {
239 return d( rng_, p );
240 }
241
242 inline double
243 operator()( std::normal_distribution<>& d, std::normal_distribution<>::param_type& p ) override
244 {
245 return d( rng_, p );
246 }
247
248 inline double
249 operator()( std::lognormal_distribution<>& d, std::lognormal_distribution<>::param_type& p ) override
250 {
251 return d( rng_, p );
252 }
253
254 inline unsigned long
255 operator()( std::binomial_distribution< unsigned long >& d,
256 std::binomial_distribution< unsigned long >::param_type& p ) override
257 {
258 return d( rng_, p );
259 }
260
261 inline double
262 operator()( std::gamma_distribution<>& d, std::gamma_distribution<>::param_type& p ) override
263 {
264 return d( rng_, p );
265 }
266
267 inline double
268 operator()( std::exponential_distribution<>& d, std::exponential_distribution<>::param_type& p ) override
269 {
270 return d( rng_, p );
271 }
272
273 inline unsigned long
274 operator()( std::discrete_distribution< unsigned long >& d,
275 std::discrete_distribution< unsigned long >::param_type& p ) override
276 {
277 return d( rng_, p );
278 }
279
280 inline unsigned long
281 operator()( std::poisson_distribution< unsigned long >& d,
282 std::poisson_distribution< unsigned long >::param_type& p ) override
283 {
284 return d( rng_, p );
285 }
286
287 inline double
288 drand() override
289 {
291 }
292
293 inline unsigned long
294 ulrand( unsigned long N ) override
295 {
296 std::uniform_int_distribution< unsigned long >::param_type param( 0, N - 1 );
297 return uniform_ulong_dist_( rng_, param );
298 }
299
300 inline void
303 std::back_insert_iterator< std::vector< NodeIDTriple > > dest,
304 size_t n ) override
305 {
306 std::sample( first, last, dest, n, rng_ );
307 }
308
309 inline void
310 partial_shuffle( std::vector< size_t >& data, const size_t n ) override
311 {
312 const size_t num_elems = std::min( n, data.size() );
313
314 // Partial Fisher-Yates-Durstenfeld-Knuth: at each step select an element from the remaining range
315 // [ next, data.size() ) and swap it to the front. Draws num_elems random numbers and
316 // leaves the selection in random order.
317 for ( size_t next = 0, remaining = data.size(); next < num_elems; ++next, --remaining )
318 {
319 const size_t rnd = next + ulrand( remaining );
320 std::swap( data[ next ], data[ rnd ] );
321 }
322 data.resize( num_elems ); // keep only the selected elements.
323 }
324
325private:
326 RandomEngineT rng_;
327 std::uniform_int_distribution< unsigned long > uniform_ulong_dist_;
328 std::uniform_real_distribution<> uniform_double_dist_0_1_;
329};
330
335{
336public:
338
344 virtual RngPtr create( std::initializer_list< std::uint32_t > seed_initializer ) const = 0;
345};
346
350template < typename RandomEngineT >
352{
353public:
354 inline RngPtr
355 create( std::initializer_list< std::uint32_t > seed_initializer ) const override
356 {
357 return new RandomGenerator< RandomEngineT >( seed_initializer );
358 }
359};
360
368template < typename DistributionT >
370{
371public:
372 using result_type = typename DistributionT::result_type;
373 using param_type = typename DistributionT::param_type;
374
380
389 inline result_type
391 {
392 static_assert( std::is_same< result_type, unsigned long >::value or std::is_same< result_type, double >::value,
393 "result_type of the distribution must be unsigned long or double" );
394 return g->operator()( distribution_ );
395 }
396
406 inline result_type
408 {
409 static_assert( std::is_same< result_type, unsigned long >::value or std::is_same< result_type, double >::value,
410 "result_type of the distribution must be unsigned long or double" );
411 return g->operator()( distribution_, params );
412 }
413
419 inline void
420 param( const param_type& params )
421 {
422 distribution_.param( params );
423 }
424
428 inline result_type
429 min() const
430 {
431 return distribution_.min();
432 }
433
437 inline result_type
438 max() const
439 {
440 return distribution_.max();
441 }
442
443private:
444 DistributionT distribution_;
445};
446
447} // namespace nest
448
449#endif /* #ifndef RANDOM_GENERATORS_H */
Base class for random generator factory.
Definition random_generators.h:335
virtual ~BaseRandomGeneratorFactory()
Definition random_generators.h:337
virtual RngPtr create(std::initializer_list< std::uint32_t > seed_initializer) const =0
Clones the RNG wrapper and sets the state of the cloned RNG engine.
Base class for RNG engine wrappers.
Definition random_generators.h:67
virtual ~BaseRandomGenerator()
Definition random_generators.h:69
virtual unsigned long operator()(std::uniform_int_distribution< unsigned long > &d, std::uniform_int_distribution< unsigned long >::param_type &p)=0
Calls the provided distribution with the wrapped RNG engine, using provided distribution parameters.
virtual unsigned long operator()(std::binomial_distribution< unsigned long > &d, std::binomial_distribution< unsigned long >::param_type &p)=0
virtual unsigned long operator()(std::binomial_distribution< unsigned long > &d)=0
virtual double operator()(std::gamma_distribution<> &d)=0
virtual double operator()(std::uniform_real_distribution<> &d)=0
virtual double operator()(std::gamma_distribution<> &d, std::gamma_distribution<>::param_type &p)=0
virtual void stable_sample(NodeCollection::const_iterator first, NodeCollection::const_iterator last, std::back_insert_iterator< std::vector< NodeIDTriple > > dest, size_t n)=0
Wrap std::sample for selection from NodeCollection.
virtual double operator()(std::lognormal_distribution<> &d, std::lognormal_distribution<>::param_type &p)=0
virtual unsigned long ulrand(unsigned long N)=0
Uses the wrapped RNG engine to draw an unsigned long from a uniform distribution in the range [0,...
virtual unsigned long operator()(std::uniform_int_distribution< unsigned long > &d)=0
Calls the provided distribution with the wrapped RNG engine.
virtual void partial_shuffle(std::vector< size_t > &data, const size_t n)=0
Select randomly shuffled elements from vector.
virtual unsigned long operator()(std::discrete_distribution< unsigned long > &d)=0
virtual double operator()(std::exponential_distribution<> &d)=0
virtual unsigned long operator()(std::poisson_distribution< unsigned long > &d, std::poisson_distribution< unsigned long >::param_type &p)=0
virtual double operator()(std::exponential_distribution<> &d, std::exponential_distribution<>::param_type &p)=0
virtual double operator()(std::normal_distribution<> &d, std::normal_distribution<>::param_type &p)=0
virtual unsigned long operator()(std::discrete_distribution< unsigned long > &d, std::discrete_distribution< unsigned long >::param_type &p)=0
virtual unsigned long operator()(std::poisson_distribution< unsigned long > &d)=0
virtual double drand()=0
Uses the wrapped RNG engine to draw a double from a uniform distribution in the range [0,...
virtual double operator()(std::normal_distribution<> &d)=0
virtual double operator()(std::lognormal_distribution<> &d)=0
virtual double operator()(std::uniform_real_distribution<> &d, std::uniform_real_distribution<>::param_type &p)=0
Wrapper for distributions.
Definition random_generators.h:370
result_type min() const
Returns the minimum value potentially generated by the distribution.
Definition random_generators.h:429
result_type operator()(RngPtr g)
Generating function.
Definition random_generators.h:390
RandomDistribution()=default
Constructs a distribution object with its default parameters.
typename DistributionT::param_type param_type
Definition random_generators.h:373
result_type operator()(RngPtr g, param_type &params)
Generating function.
Definition random_generators.h:407
result_type max() const
Returns the maximum value potentially generated by the distribution.
Definition random_generators.h:438
DistributionT distribution_
Wrapped RandomDistribution.
Definition random_generators.h:444
void param(const param_type &params)
Sets the distribution's associated parameter set to params.
Definition random_generators.h:420
typename DistributionT::result_type result_type
Definition random_generators.h:372
Definition random_generators.h:352
RngPtr create(std::initializer_list< std::uint32_t > seed_initializer) const override
Clones the RNG wrapper and sets the state of the cloned RNG engine.
Definition random_generators.h:355
Wrapper for RNG engines.
Definition random_generators.h:158
RandomGenerator(std::initializer_list< std::uint32_t > seed)
Definition random_generators.h:165
std::uniform_int_distribution< unsigned long > uniform_ulong_dist_
Definition random_generators.h:327
double operator()(std::uniform_real_distribution<> &d, std::uniform_real_distribution<>::param_type &p) override
Definition random_generators.h:237
typename RandomEngineT::result_type result_type
Definition random_generators.h:160
double operator()(std::normal_distribution<> &d, std::normal_distribution<>::param_type &p) override
Definition random_generators.h:243
unsigned long operator()(std::uniform_int_distribution< unsigned long > &d, std::uniform_int_distribution< unsigned long >::param_type &p) override
Calls the provided distribution with the wrapped RNG engine, using provided distribution parameters.
Definition random_generators.h:230
double operator()(std::uniform_real_distribution<> &d) override
Definition random_generators.h:182
RandomEngineT rng_
Wrapped RNG engine.
Definition random_generators.h:326
unsigned long ulrand(unsigned long N) override
Uses the wrapped RNG engine to draw an unsigned long from a uniform distribution in the range [0,...
Definition random_generators.h:294
double operator()(std::normal_distribution<> &d) override
Definition random_generators.h:188
double operator()(std::gamma_distribution<> &d) override
Definition random_generators.h:206
double operator()(std::gamma_distribution<> &d, std::gamma_distribution<>::param_type &p) override
Definition random_generators.h:262
unsigned long operator()(std::binomial_distribution< unsigned long > &d) override
Definition random_generators.h:200
double operator()(std::lognormal_distribution<> &d) override
Definition random_generators.h:194
double operator()(std::lognormal_distribution<> &d, std::lognormal_distribution<>::param_type &p) override
Definition random_generators.h:249
void partial_shuffle(std::vector< size_t > &data, const size_t n) override
Select randomly shuffled elements from vector.
Definition random_generators.h:310
void stable_sample(NodeCollection::const_iterator first, NodeCollection::const_iterator last, std::back_insert_iterator< std::vector< NodeIDTriple > > dest, size_t n) override
Wrap std::sample for selection from NodeCollection.
Definition random_generators.h:301
double drand() override
Uses the wrapped RNG engine to draw a double from a uniform distribution in the range [0,...
Definition random_generators.h:288
unsigned long operator()(std::binomial_distribution< unsigned long > &d, std::binomial_distribution< unsigned long >::param_type &p) override
Definition random_generators.h:255
unsigned long operator()(std::discrete_distribution< unsigned long > &d) override
Definition random_generators.h:218
unsigned long operator()(std::uniform_int_distribution< unsigned long > &d) override
Calls the provided distribution with the wrapped RNG engine.
Definition random_generators.h:176
std::uniform_real_distribution uniform_double_dist_0_1_
Definition random_generators.h:328
unsigned long operator()(std::poisson_distribution< unsigned long > &d, std::poisson_distribution< unsigned long >::param_type &p) override
Definition random_generators.h:281
double operator()(std::exponential_distribution<> &d) override
Definition random_generators.h:212
unsigned long operator()(std::discrete_distribution< unsigned long > &d, std::discrete_distribution< unsigned long >::param_type &p) override
Definition random_generators.h:274
unsigned long operator()(std::poisson_distribution< unsigned long > &d) override
Definition random_generators.h:224
RandomGenerator(const RandomEngineT &rng)=delete
double operator()(std::exponential_distribution<> &d, std::exponential_distribution<>::param_type &p) override
Definition random_generators.h:268
Iterator for NodeCollections.
Definition node_collection.h:415
Namespace for the NEST simulation kernel.
Definition beta_normalization_factor.h:33