Unverified Commit 0ff61299 authored by pfeatherstone's avatar pfeatherstone Committed by GitHub
Browse files

Adding exponential and weibull distributions (#2247)



* Added exponential distribution

* tab problem removed?

* forgot std::

* Also added Weibull distribution. Very useful indeed.

* Simple Weibull distribution unit test

* don't forget std::

* sorry, typo

* [RAND] 	- seed the random number generators for consistency and no nasty surprises
		- added parameter for tolerance
		- added unit test for exponential distribution

* [RAND] print the spinner more often

* [RAND] up the tolerance for kurtosis a bit

* [RAND] refactored parameters to reflect documentation on wikipedia.

* [RAND] added documentation to _abstract

* [RAND] i switched the order of the arguments to get_random_weibull and didn't update the unit tests. oops
Co-authored-by: default avatarpf <pf@pf-ubuntu-dev>
parent e58da513
......@@ -265,6 +265,31 @@ namespace dlib
return r.real();
}
double get_random_exponential (
double lambda
)
{
DLIB_ASSERT(lambda > 0, "lambda must be greater than zero");
double u = 0.0;
while (u == 0.0)
u = get_random_double();
return -std::log( u ) / lambda;
}
double get_random_weibull (
double lambda,
double k,
double gamma
)
{
DLIB_ASSERT(k > 0, "k must be greater than zero");
DLIB_ASSERT(lambda > 0, "lambda must be greater than zero");
double u = 0.0;
while (u == 0.0)
u = get_random_double();
return gamma + lambda*std::pow(-std::log(u), 1.0 / k);
}
void swap (
rand& item
)
......
......@@ -188,7 +188,28 @@ namespace dlib
- returns a random complex number sampled from a Gaussian distribution
with mean 0 and standard deviation 1.
!*/
double get_random_exponential (
double lambda
);
/*!
ensures
- returns a random number sampled from an exponential distribution
with rate parameter lambda
!*/
double get_random_weibull (
double lambda,
double k,
double gamma
);
/*!
ensures
- returns a random number sampled from a Weibull distribution
with shape parameter k, scale parameter lambda and
threshold parameter gamma.
!*/
void swap (
rand& item
);
......
......@@ -10,6 +10,7 @@
#include <dlib/rand.h>
#include <dlib/compress_stream.h>
#include <dlib/hash.h>
#include <dlib/statistics.h>
#include "tester.h"
......@@ -407,6 +408,47 @@ namespace
}
void test_weibull_distribution()
{
print_spinner();
dlib::rand rnd(0);
const size_t N = 1024*1024*4;
const double tol = 0.01;
double k=1.0, lambda=2.0, g=6.0;
dlib::running_stats<double> stats;
for (size_t i = 0; i < N; i++)
stats.add(rnd.get_random_weibull(lambda, k, g));
double expected_mean = g + lambda*std::tgamma(1 + 1.0 / k);
double expected_var = lambda*lambda*(std::tgamma(1 + 2.0 / k) - std::pow(std::tgamma(1 + 1.0 / k),2));
DLIB_TEST(std::abs(stats.mean() - expected_mean) < tol);
DLIB_TEST(std::abs(stats.variance() - expected_var) < tol);
}
void test_exponential_distribution()
{
print_spinner();
dlib::rand rnd(0);
const size_t N = 1024*1024*128;
const double tol = 0.01;
for (double lambda = 6 ; lambda < 20 ; lambda += 0.1)
{
print_spinner();
dlib::running_stats<double> stats;
for (size_t i = 0; i < N; i++)
stats.add(rnd.get_random_exponential(lambda));
DLIB_TEST(std::abs(stats.mean() - 1.0 / lambda) < tol);
DLIB_TEST(std::abs(stats.variance() - 1.0 / (lambda*lambda)) < tol);
DLIB_TEST(std::abs(stats.skewness() - 2.0) < tol);
DLIB_TEST(std::abs(stats.ex_kurtosis() - 6.0) < 0.1);
}
}
class rand_tester : public tester
{
public:
......@@ -428,6 +470,8 @@ namespace
test_gaussian_random_hash();
test_uniform_random_hash();
test_get_integer();
test_weibull_distribution();
test_exponential_distribution();
}
} a;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment