TheAlgorithms/C++ 1.0.0
All the algorithms implemented in C++
Loading...
Searching...
No Matches
geometric_dist.cpp
Go to the documentation of this file.
1
22#include <cassert>
23#include <cmath>
24#include <cstdint>
25#include <ctime>
26#include <iostream>
27#include <limits>
28#include <random>
29#include <vector>
30
35namespace probability {
42namespace geometric_dist {
49 return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
50}
51
56 private:
57 float p;
58
59 public:
64 explicit geometric_distribution(const float& p) : p(p) {}
65
71 float expected_value() const { return 1.0f / p; }
72
77 float variance() const { return (1.0f - p) / (p * p); }
78
84 float standard_deviation() const { return std::sqrt(variance()); }
85
93 float probability_density(const uint32_t& k) const {
94 return std::pow((1.0f - p), static_cast<float>(k - 1)) * p;
95 }
96
104 float cumulative_distribution(const uint32_t& k) const {
105 return 1.0f - std::pow((1.0f - p), static_cast<float>(k));
106 }
107
116 float inverse_cumulative_distribution(const float& cdf) const {
117 return std::log(1.0f - cdf) / std::log(1.0f - p);
118 }
119
125 uint32_t draw_sample() const {
126 float uniform_sample = generate_uniform();
127 return static_cast<uint32_t>(
128 inverse_cumulative_distribution(uniform_sample)) +
129 1;
130 }
131
145 float range_tries(const uint32_t& min_tries = 1,
146 const uint32_t& max_tries =
147 std::numeric_limits<uint32_t>::max()) const {
148 float cdf_lower = cumulative_distribution(min_tries - 1);
149 float cdf_upper = max_tries == std::numeric_limits<uint32_t>::max()
150 ? 1.0f
151 : cumulative_distribution(max_tries);
152 return cdf_upper - cdf_lower;
153 }
154};
155} // namespace geometric_dist
156} // namespace probability
157
167 uint32_t n_tries = 1000000;
168 std::vector<float> tries;
169 tries.resize(n_tries);
170
171 float mean = 0.0f;
172 for (uint32_t i = 0; i < n_tries; ++i) {
173 tries[i] = static_cast<float>(dist.draw_sample());
174 mean += tries[i];
175 }
176
177 mean /= static_cast<float>(n_tries);
178
179 float var = 0.0f;
180 for (uint32_t i = 0; i < n_tries; ++i) {
181 var += (tries[i] - mean) * (tries[i] - mean);
182 }
183
184 // Unbiased estimate of variance
185 var /= static_cast<float>(n_tries - 1);
186
187 std::cout << "This value should be near " << dist.expected_value() << ": "
188 << mean << std::endl;
189 std::cout << "This value should be near " << dist.variance() << ": " << var
190 << std::endl;
191}
192
197static void test() {
199
200 const float threshold = 1e-3f;
201
202 std::cout << "Starting tests for p = 0.3..." << std::endl;
203 assert(std::abs(dist.expected_value() - 3.33333333f) < threshold);
204 assert(std::abs(dist.variance() - 7.77777777f) < threshold);
205 assert(std::abs(dist.standard_deviation() - 2.788866755) < threshold);
206 assert(std::abs(dist.probability_density(5) - 0.07203) < threshold);
207 assert(std::abs(dist.cumulative_distribution(6) - 0.882351) < threshold);
208 assert(std::abs(dist.inverse_cumulative_distribution(
209 dist.cumulative_distribution(8)) -
210 8) < threshold);
211 assert(std::abs(dist.range_tries() - 1.0f) < threshold);
212 assert(std::abs(dist.range_tries(3) - 0.49f) < threshold);
213 assert(std::abs(dist.range_tries(5, 11) - 0.2203267f) < threshold);
214 std::cout << "All tests passed" << std::endl;
215 sample_test(dist);
216
218
219 std::cout << "Starting tests for p = 0.5..." << std::endl;
220 assert(std::abs(dist.expected_value() - 2.0f) < threshold);
221 assert(std::abs(dist.variance() - 2.0f) < threshold);
222 assert(std::abs(dist.standard_deviation() - 1.4142135f) < threshold);
223 assert(std::abs(dist.probability_density(5) - 0.03125) < threshold);
224 assert(std::abs(dist.cumulative_distribution(6) - 0.984375) < threshold);
225 assert(std::abs(dist.inverse_cumulative_distribution(
226 dist.cumulative_distribution(8)) -
227 8) < threshold);
228 assert(std::abs(dist.range_tries() - 1.0f) < threshold);
229 assert(std::abs(dist.range_tries(3) - 0.25f) < threshold);
230 assert(std::abs(dist.range_tries(5, 11) - 0.062011f) < threshold);
231 std::cout << "All tests passed" << std::endl;
232 sample_test(dist);
233
235
236 std::cout << "Starting tests for p = 0.8..." << std::endl;
237 assert(std::abs(dist.expected_value() - 1.25f) < threshold);
238 assert(std::abs(dist.variance() - 0.3125f) < threshold);
239 assert(std::abs(dist.standard_deviation() - 0.559016f) < threshold);
240 assert(std::abs(dist.probability_density(5) - 0.00128) < threshold);
241 assert(std::abs(dist.cumulative_distribution(6) - 0.999936) < threshold);
242 assert(std::abs(dist.inverse_cumulative_distribution(
243 dist.cumulative_distribution(8)) -
244 8) < threshold);
245 assert(std::abs(dist.range_tries() - 1.0f) < threshold);
246 assert(std::abs(dist.range_tries(3) - 0.04f) < threshold);
247 assert(std::abs(dist.range_tries(5, 11) - 0.00159997f) < threshold);
248 std::cout << "All tests have successfully passed!" << std::endl;
249 sample_test(dist);
250}
251
256int main() {
257 srand(time(nullptr));
258 test(); // run self-test implementations
259 return 0;
260}
A class to model the geometric distribution.
float cumulative_distribution(const uint32_t &k) const
The cumulative distribution function.
float standard_deviation() const
The standard deviation of a geometrically distributed random variable X.
float expected_value() const
The expected value of a geometrically distributed random variable X.
float range_tries(const uint32_t &min_tries=1, const uint32_t &max_tries=std::numeric_limits< uint32_t >::max()) const
This function computes the probability to have success in a given range of tries.
uint32_t draw_sample() const
Generates a (discrete) sample according to the geometrical distribution.
geometric_distribution(const float &p)
Constructor for the geometric distribution.
float inverse_cumulative_distribution(const float &cdf) const
The inverse cumulative distribution function.
float variance() const
The variance of a geometrically distributed random variable X.
float probability_density(const uint32_t &k) const
The probability density function.
void sample_test(const probability::geometric_dist::geometric_distribution &dist)
Tests the sampling method of the geometric distribution.
float generate_uniform()
Returns a random number between [0,1].
static void test()
Self-test implementations.
int main()
Main function.
Functions for the Geometric Distribution algorithm implementation.
Probability algorithms.