Skip to content

Commit 4ad1675

Browse files
feat(RandomEngine): implement the random engine for to sample uniform,gaussian and bernoulli distributions.
1 parent 124ccb4 commit 4ad1675

7 files changed

Lines changed: 237 additions & 150 deletions

File tree

include/geode/stochastic/geometry/common.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include <geode/basic/common.hpp>
2626
#include <geode/basic/library.hpp>
27+
#include <geode/basic/logger.hpp>
2728
#include <geode/stochastic/geometry/opengeode_stochastic_geometry_export.hpp>
2829

2930
namespace geode

include/geode/stochastic/geometry/random_sample_spec.hpp renamed to include/geode/stochastic/geometry/distributions.hpp

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
#pragma once
2525

2626
#include <geode/stochastic/geometry/common.hpp>
27-
28-
#include <geode/basic/pimpl.hpp>
29-
30-
#include <variant>
27+
#include <optional>
3128

3229
namespace geode
3330
{
@@ -44,51 +41,38 @@ namespace geode
4441
struct Uniform
4542
{
4643
Uniform() = default;
47-
44+
Uniform( Type min_val, Type max_val )
45+
: min{ IntervalLimit< Type >{ min_val, true } },
46+
max{ IntervalLimit< Type >{ max_val, true } }
47+
{
48+
}
4849
IntervalLimit< Type > min;
4950
IntervalLimit< Type > max;
5051
};
5152

52-
/*!
53-
* Spec to draw a double value in a Uniform Distribution. Describe a
54-
* semi closed interval [min,max[
55-
*/
56-
struct UniformDouble
57-
{
58-
double min;
59-
double max;
60-
};
61-
62-
/*!
63-
* Spec to draw a double value in a Gaussian Distribution defined by its
64-
* mean and standard deviation.
65-
*/
6653
struct Gaussian
6754
{
68-
double mean;
69-
double stddev;
70-
};
55+
Gaussian() = default;
56+
Gaussian( double mean_val, double standard_deviation_val )
57+
: mean{ mean_val }, standard_deviation{ standard_deviation_val }
58+
{
59+
}
60+
Gaussian( double mean_val,
61+
double standard_deviation_val,
62+
double min_val,
63+
double max_val )
64+
: mean{ mean_val },
65+
standard_deviation{ standard_deviation_val },
66+
min{ min_val },
67+
max{ max_val }
68+
{
69+
}
7170

72-
/*!
73-
* Spec to draw a sucess/fail of an experiement. the experiment is defined
74-
* by its probability of success.
75-
*/
76-
struct Bernoulli
77-
{
78-
double probability;
79-
};
71+
double mean{ 0. };
72+
double standard_deviation{ 1. };
8073

81-
// struct PointInDisk
82-
// {
83-
// double radius;
84-
// };
85-
//
86-
// struct PointInBox2D
87-
// {
88-
// geode::BoundingBox2D box;
89-
// };
74+
std::optional< double > min;
75+
std::optional< double > max;
76+
};
9077

91-
using RandomDoubleSpec = std::variant< UniformDouble, Gaussian >;
92-
// PointInDisk,
93-
// PointInBox2D >;
9478
} // namespace geode

include/geode/stochastic/geometry/random_engine.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#include <geode/stochastic/geometry/common.hpp>
2727

28-
#include <geode/stochastic/geometry/random_sample_spec.hpp>
28+
#include <geode/stochastic/geometry/distributions.hpp>
2929

3030
#include <geode/basic/pimpl.hpp>
3131
namespace geode
@@ -35,17 +35,18 @@ namespace geode
3535
OPENGEODE_DISABLE_COPY_AND_MOVE( RandomEngine );
3636

3737
public:
38-
explicit RandomEngine( uint64_t seed );
38+
explicit RandomEngine();
3939
~RandomEngine();
4040

41-
double sample( const RandomDoubleSpec& double_spec );
42-
43-
template < typename RANDSPEC >
44-
auto sample( const RANDSPEC& spec );
41+
void set_seed( std::string_view word );
4542

4643
template < typename Type >
4744
Type sample_uniform( const Uniform< Type >& law );
4845

46+
double sample_gaussian( const Gaussian& law );
47+
48+
bool sample_bernoulli( double probability_of_success );
49+
4950
private:
5051
IMPLEMENTATION_MEMBER( impl_ );
5152
};

src/geode/stochastic/geometry/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,11 @@ add_geode_library(
2424
SOURCES
2525
"common.cpp"
2626
"random_engine.cpp"
27-
"random_sample_spec.cpp"
2827
"hello_world.cpp"
2928
PUBLIC_HEADERS
3029
"common.hpp"
3130
"random_engine.hpp"
32-
"random_sample_spec.hpp"
31+
"distributions.hpp"
3332
"hello_world.hpp"
3433
PRIVATE_DEPENDENCIES
3534
OpenGeode::basic

src/geode/stochastic/geometry/random_engine.cpp

Lines changed: 73 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
#include <geode/stochastic/geometry/random_engine.hpp>
2525

26-
#include <geode/stochastic/geometry/random_sample_spec.hpp>
26+
#include <geode/stochastic/geometry/distributions.hpp>
2727

2828
#include <geode/basic/pimpl_impl.hpp>
2929

@@ -33,15 +33,17 @@
3333
#include "absl/random/uniform_int_distribution.h"
3434
#include "absl/random/uniform_real_distribution.h"
3535

36-
#include <variant>
36+
#include "absl/hash/hash.h"
37+
#include <limits>
3738

3839
namespace
3940
{
40-
std::seed_seq create_seed_seq( uint64_t seed )
41+
std::seed_seq create_seed_seq( std::string_view word )
4142
{
43+
uint64_t seed = absl::Hash< std::string_view >{}( word );
4244
std::vector< uint32_t > seed_data = { static_cast< uint32_t >(
43-
seed & 0xFFFFFFFF ),
44-
static_cast< uint32_t >( seed >> 32 ) };
45+
seed >> 32 ),
46+
static_cast< uint32_t >( seed & 0xFFFFFFFF ) };
4547
return std::seed_seq( seed_data.begin(), seed_data.end() );
4648
}
4749
} // namespace
@@ -51,79 +53,96 @@ namespace geode
5153
class RandomEngine::Impl
5254
{
5355
public:
54-
explicit Impl( uint64_t seed ) : rand_gen_{ create_seed_seq( seed ) } {}
56+
explicit Impl() = default;
5557
~Impl() = default;
5658

57-
template < typename RANDSPEC >
58-
auto do_sample( const RANDSPEC& spec )
59+
void set_seed( std::string_view word )
5960
{
60-
return do_sample_impl( spec );
61+
rand_gen_ = absl::BitGen{ create_seed_seq( word ) };
6162
}
6263

6364
template < typename Type >
6465
Type sample_uniform( const Uniform< Type >& law )
6566
{
66-
// check interval values correctness
67+
OPENGEODE_DATA_EXCEPTION( law.min.value < law.max.value,
68+
"Uniform sampling cannot be done since ", law.min.value,
69+
" is not < than ", law.max.value, "." );
6770
if( law.min.is_included )
6871
{
6972
if( law.max.is_included )
7073
{
71-
return absl::Uniform(
72-
absl::IntervalClosed, rand_gen_, law.min, law.max );
74+
return absl::Uniform( absl::IntervalClosed, rand_gen_,
75+
law.min.value, law.max.value );
7376
}
74-
return absl::Uniform(
75-
absl::IntervalClosedOpen, rand_gen_, law.min, law.max );
77+
return absl::Uniform( absl::IntervalClosedOpen, rand_gen_,
78+
law.min.value, law.max.value );
7679
}
7780
if( law.max.is_included )
7881
{
79-
return absl::Uniform(
80-
absl::IntervalOpenClosed, rand_gen_, law.min, law.max );
82+
return absl::Uniform( absl::IntervalOpenClosed, rand_gen_,
83+
law.min.value, law.max.value );
8184
}
8285
return absl::Uniform(
83-
absl::IntervalOpen, rand_gen_, law.min, law.max );
86+
absl::IntervalOpen, rand_gen_, law.min.value, law.max.value );
8487
}
8588

86-
private:
87-
int do_sample_impl( const UniformInt& spec )
89+
double sample_gaussian( const Gaussian& law )
8890
{
89-
return absl::Uniform(
90-
absl::IntervalClosed, rand_gen_, spec.min, spec.max );
91-
}
92-
double do_sample_impl( const UniformDouble& spec )
93-
{
94-
return absl::Uniform( rand_gen_, spec.min, spec.max );
95-
}
96-
double do_sample_impl( const Gaussian& spec )
97-
{
98-
return absl::gaussian_distribution< double >(
99-
spec.mean, spec.stddev )( rand_gen_ );
91+
OPENGEODE_DATA_EXCEPTION(
92+
law.standard_deviation > 0
93+
&& std::isfinite( law.standard_deviation )
94+
&& std::isfinite( law.mean ),
95+
"Gaussian sampling cannot be done, please check the mean (",
96+
law.mean, ") and the standard deviation (",
97+
law.standard_deviation, ")." );
98+
if( !law.min.has_value() || !law.max.has_value() )
99+
{
100+
return absl::gaussian_distribution< double >(
101+
law.mean, law.standard_deviation )( rand_gen_ );
102+
};
103+
const auto max =
104+
law.max.value_or( std::numeric_limits< double >::infinity() );
105+
const auto min =
106+
law.min.value_or( -std::numeric_limits< double >::infinity() );
107+
108+
OPENGEODE_DATA_EXCEPTION( min < max,
109+
"Gaussian sampling cannot be done since ", min,
110+
" is not < than ", max, "." );
111+
112+
OPENGEODE_DATA_EXCEPTION( law.mean > min && law.mean < max,
113+
"Gaussian sampling cannot be done since please the mean value "
114+
"(",
115+
law.mean, ") is not in [", min, ",", max, "]." );
116+
double value;
117+
do
118+
{
119+
value = absl::gaussian_distribution< double >(
120+
law.mean, law.standard_deviation )( rand_gen_ );
121+
} while( value < min || value > max );
122+
return value;
100123
}
101-
bool do_sample_impl( const Bernoulli& spec )
124+
125+
bool sample_bernoulli( double probability_of_success )
102126
{
103-
return absl::bernoulli_distribution( spec.probability )(
127+
OPENGEODE_DATA_EXCEPTION(
128+
probability_of_success >= 0. && probability_of_success <= 1.0,
129+
"Bernoulli sampling cannot be done since ",
130+
probability_of_success, " is not in [0.,1.]." );
131+
return absl::bernoulli_distribution( probability_of_success )(
104132
rand_gen_ );
105133
}
106134

107135
private:
108136
absl::BitGen rand_gen_;
109137
};
110138

111-
RandomEngine::RandomEngine( uint64_t seed ) : impl_{ seed } {}
112-
RandomEngine::~RandomEngine() = default;
139+
RandomEngine::RandomEngine() = default;
113140

114-
double RandomEngine::sample( const RandomDoubleSpec& random_double_spec )
115-
{
116-
return std::visit(
117-
[this]( const auto& s ) {
118-
return impl_->do_sample( s );
119-
},
120-
random_double_spec );
121-
}
141+
RandomEngine::~RandomEngine() = default;
122142

123-
template < typename RANDSPEC >
124-
auto RandomEngine::sample( const RANDSPEC& spec )
143+
void RandomEngine::set_seed( std::string_view word )
125144
{
126-
return impl_->do_sample( spec );
145+
impl_->set_seed( word );
127146
}
128147

129148
template < typename Type >
@@ -143,11 +162,14 @@ namespace geode
143162
template double opengeode_stochastic_geometry_api
144163
RandomEngine::sample_uniform( const Uniform< double >& );
145164

146-
template auto opengeode_stochastic_geometry_api RandomEngine::sample(
147-
const UniformDouble& );
148-
template auto opengeode_stochastic_geometry_api RandomEngine::sample(
149-
const Gaussian& );
150-
template auto opengeode_stochastic_geometry_api RandomEngine::sample(
151-
const Bernoulli& );
165+
double RandomEngine::sample_gaussian( const Gaussian& law )
166+
{
167+
return impl_->sample_gaussian( law );
168+
}
169+
170+
bool RandomEngine::sample_bernoulli( double probability_of_success )
171+
{
172+
return impl_->sample_bernoulli( probability_of_success );
173+
}
152174

153175
} // namespace geode

src/geode/stochastic/geometry/random_sample_spec.cpp

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)