/Src/Dependencies/Boost/libs/random/test/statistic_tests.cpp
http://hadesmem.googlecode.com/ · C++ · 503 lines · 434 code · 57 blank · 12 comment · 13 complexity · f418934ff21eb5dc0bab4779978d96d8 MD5 · raw file
- /* statistic_tests.cpp file
- *
- * Copyright Jens Maurer 2000, 2002
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id: statistic_tests.cpp 60755 2010-03-22 00:45:06Z steven_watanabe $
- *
- * Revision history
- */
- #include <iostream>
- #include <iomanip>
- #include <string>
- #include <functional>
- #include <vector>
- #include <set>
- #include <algorithm>
- #include <boost/cstdint.hpp>
- #include <boost/random.hpp>
- #include <boost/math/special_functions/gamma.hpp>
- #include <boost/math/distributions/uniform.hpp>
- #include <boost/math/distributions/chi_squared.hpp>
- #include <boost/math/distributions/normal.hpp>
- #include <boost/math/distributions/triangular.hpp>
- #include <boost/math/distributions/cauchy.hpp>
- #include <boost/math/distributions/gamma.hpp>
- #include <boost/math/distributions/exponential.hpp>
- #include <boost/math/distributions/lognormal.hpp>
- #include "statistic_tests.hpp"
- #include "integrate.hpp"
- class test_environment;
- class test_base
- {
- protected:
- explicit test_base(test_environment & env) : environment(env) { }
- void check_(double val) const;
- private:
- test_environment & environment;
- };
- class equidistribution_test : test_base
- {
- public:
- equidistribution_test(test_environment & env, unsigned int classes,
- unsigned int high_classes)
- : test_base(env), classes(classes),
- test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "equidistribution: " << std::flush;
- equidistribution_experiment equi(classes);
- variate_generator<RNG&, uniform_smallint<> > uint_linear(rng, uniform_smallint<>(0, classes-1));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(equi, uint_linear, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(equi, uint_linear, n1), 2*n2));
- std::cout << " 2D: " << std::flush;
- equidistribution_2d_experiment equi_2d(classes);
- unsigned int root = static_cast<unsigned int>(std::sqrt(double(classes)));
- assert(root * root == classes);
- variate_generator<RNG&, uniform_smallint<> > uint_square(rng, uniform_smallint<>(0, root-1));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(equi_2d, uint_square, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(equi_2d, uint_square, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- unsigned int classes;
- distribution_experiment test_distrib_chi_square;
- };
- class ks_distribution_test : test_base
- {
- public:
- ks_distribution_test(test_environment & env, unsigned int classes)
- : test_base(env),
- test_distrib_chi_square(kolmogorov_smirnov_probability(5000),
- classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- boost::math::uniform ud(static_cast<double>((rng.min)()), static_cast<double>((rng.max)()));
- run(rng, ud, n1, n2);
- }
- template<class RNG, class Dist>
- void run(RNG & rng, const Dist& dist, int n1, int n2)
- {
- using namespace boost;
- std::cout << "KS: " << std::flush;
- kolmogorov_experiment ks(n1);
- check_(run_experiment(test_distrib_chi_square,
- ks_experiment_generator(ks, rng, dist), n2));
- check_(run_experiment(test_distrib_chi_square,
- ks_experiment_generator(ks, rng, dist), 2*n2));
- std::cout << std::endl;
- }
- private:
- distribution_experiment test_distrib_chi_square;
- };
- class runs_test : test_base
- {
- public:
- runs_test(test_environment & env, unsigned int classes,
- unsigned int high_classes)
- : test_base(env), classes(classes),
- test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "runs: up: " << std::flush;
- runs_experiment<true> r_up(classes);
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(r_up, rng, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(r_up, rng, n1), 2*n2));
- std::cout << " down: " << std::flush;
- runs_experiment<false> r_down(classes);
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(r_down, rng, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(r_down, rng, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- unsigned int classes;
- distribution_experiment test_distrib_chi_square;
- };
- class gap_test : test_base
- {
- public:
- gap_test(test_environment & env, unsigned int classes,
- unsigned int high_classes)
- : test_base(env), classes(classes),
- test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- boost::math::uniform ud(
- static_cast<double>((rng.min)()),
- static_cast<double>((rng.max)()) +
- (std::numeric_limits<typename RNG::result_type>::is_integer? 0.0 : 1.0));
- run(rng, ud, n1, n2);
- }
- template<class RNG, class Dist>
- void run(RNG & rng, const Dist& dist, int n1, int n2)
- {
- using namespace boost;
- std::cout << "gaps: " << std::flush;
- gap_experiment gap(classes, dist, 0.2, 0.8);
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(gap, rng, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(gap, rng, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- unsigned int classes;
- distribution_experiment test_distrib_chi_square;
- };
- class poker_test : test_base
- {
- public:
- poker_test(test_environment & env, unsigned int classes,
- unsigned int high_classes)
- : test_base(env), classes(classes),
- test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "poker: " << std::flush;
- poker_experiment poker(8, classes);
- variate_generator<RNG&, uniform_smallint<> > usmall(rng, uniform_smallint<>(0, 7));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(poker, usmall, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(poker, usmall, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- unsigned int classes;
- distribution_experiment test_distrib_chi_square;
- };
- class coupon_collector_test : test_base
- {
- public:
- coupon_collector_test(test_environment & env, unsigned int classes,
- unsigned int high_classes)
- : test_base(env), classes(classes),
- test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "coupon collector: " << std::flush;
- coupon_collector_experiment coupon(5, classes);
- variate_generator<RNG&, uniform_smallint<> > usmall(rng, uniform_smallint<>(0, 4));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(coupon, usmall, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(coupon, usmall, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- unsigned int classes;
- distribution_experiment test_distrib_chi_square;
- };
- class permutation_test : test_base
- {
- public:
- permutation_test(test_environment & env, unsigned int classes,
- unsigned int high_classes)
- : test_base(env), classes(classes),
- test_distrib_chi_square(boost::math::chi_squared(fac<int>(classes)-1),
- high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "permutation: " << std::flush;
- permutation_experiment perm(classes);
-
- // generator_reference_t<RNG> gen_ref(rng);
- RNG& gen_ref(rng);
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(perm, gen_ref, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(perm, gen_ref, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- unsigned int classes;
- distribution_experiment test_distrib_chi_square;
- };
- class maximum_test : test_base
- {
- public:
- maximum_test(test_environment & env, unsigned int high_classes)
- : test_base(env),
- test_distrib_chi_square(kolmogorov_smirnov_probability(1000),
- high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "maximum-of-t: " << std::flush;
- maximum_experiment<RNG> mx(rng, n1, 5);
- check_(run_experiment(test_distrib_chi_square, mx, n2));
- check_(run_experiment(test_distrib_chi_square, mx, 2*n2));
- std::cout << std::endl;
- }
- private:
- distribution_experiment test_distrib_chi_square;
- };
- class birthday_test : test_base
- {
- public:
- birthday_test(test_environment & env, unsigned int high_classes)
- : test_base(env),
- test_distrib_chi_square(boost::math::chi_squared(4-1), high_classes)
- { }
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "birthday spacing: " << std::flush;
- boost::variate_generator<RNG&, boost::uniform_int<> > uni(rng, boost::uniform_int<>(0, (1<<25)-1));
- birthday_spacing_experiment bsp(4, 512, (1<<25));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(bsp, uni, n1), n2));
- check_(run_experiment(test_distrib_chi_square,
- experiment_generator(bsp, uni, n1), 2*n2));
- std::cout << std::endl;
- }
- private:
- distribution_experiment test_distrib_chi_square;
- };
- #ifdef BOOST_MSVC
- #pragma warning(disable:4355)
- #endif
- class test_environment
- {
- public:
- static const int classes = 20;
- explicit test_environment(double confid)
- : confidence(confid),
- confidence_chi_square_quantil(quantile(boost::math::chi_squared(classes-1), confidence)),
- test_distrib_chi_square6(boost::math::chi_squared(7-1), classes),
- ksdist_test(*this, classes),
- equi_test(*this, 100, classes),
- rns_test(*this, 7, classes),
- gp_test(*this, 7, classes),
- pk_test(*this, 5, classes),
- cpn_test(*this, 15, classes),
- perm_test(*this, 5, classes),
- max_test(*this, classes),
- bday_test(*this, classes)
- {
- std::cout << "Confidence level: " << confid
- << "; 1-alpha = " << (1-confid)
- << "; chi_square(" << (classes-1)
- << ", " << confidence_chi_square_quantil
- << ") = "
- << cdf(boost::math::chi_squared(classes-1), confidence_chi_square_quantil)
- << std::endl;
- }
-
- bool check_confidence(double val, double chi_square_conf) const
- {
- std::cout << val;
- bool result = (val <= chi_square_conf);
- if(!result) {
- std::cout << "* [";
- double prob = (val > 10*chi_square_conf ? 1 :
- cdf(boost::math::chi_squared(classes-1), val));
- std::cout << (1-prob) << "]";
- }
- std::cout << " " << std::flush;
- return result;
- }
- bool check_(double chi_square_value) const
- {
- return check_confidence(chi_square_value, confidence_chi_square_quantil);
- }
- template<class RNG>
- void run_test(const std::string & name)
- {
- using namespace boost;
- std::cout << "Running tests on " << name << std::endl;
- RNG rng(1234567);
- ksdist_test.run(rng, 5000, 250);
- equi_test.run(rng, 5000, 250);
- rns_test.run(rng, 100000, 250);
- gp_test.run(rng, 10000, 250);
- pk_test.run(rng, 5000, 250);
- cpn_test.run(rng, 500, 250);
- perm_test.run(rng, 1200, 250);
- max_test.run(rng, 1000, 250);
- bday_test.run(rng, 1000, 150);
- std::cout << std::endl;
- }
- template<class RNG, class Dist, class ExpectedDist>
- void run_test(const std::string & name, const Dist & dist, const ExpectedDist & expected_dist)
- {
- using namespace boost;
- std::cout << "Running tests on " << name << std::endl;
- RNG rng;
- variate_generator<RNG&, Dist> vgen(rng, dist);
-
- ksdist_test.run(vgen, expected_dist, 5000, 250);
- rns_test.run(vgen, 100000, 250);
- gp_test.run(vgen, expected_dist, 10000, 250);
- perm_test.run(vgen, 1200, 250);
- std::cout << std::endl;
- }
- private:
- double confidence;
- double confidence_chi_square_quantil;
- distribution_experiment test_distrib_chi_square6;
- ks_distribution_test ksdist_test;
- equidistribution_test equi_test;
- runs_test rns_test;
- gap_test gp_test;
- poker_test pk_test;
- coupon_collector_test cpn_test;
- permutation_test perm_test;
- maximum_test max_test;
- birthday_test bday_test;
- };
- void test_base::check_(double val) const
- {
- environment.check_(val);
- }
- class program_args
- {
- public:
- program_args(int argc, char** argv)
- {
- if(argc > 0) {
- names.insert(argv + 1, argv + argc);
- }
- }
- bool check_(const std::string & test_name) const
- {
- return(names.empty() || names.find(test_name) != names.end());
- }
- private:
- std::set<std::string> names;
- };
- int main(int argc, char* argv[])
- {
- program_args args(argc, argv);
- test_environment env(0.99);
- #define TEST(name) \
- if(args.check_(#name)) \
- env.run_test<boost::name>(#name)
- TEST(minstd_rand0);
- TEST(minstd_rand);
- TEST(rand48);
- TEST(ecuyer1988);
- TEST(kreutzer1986);
- TEST(taus88);
- TEST(hellekalek1995);
- TEST(mt11213b);
- TEST(mt19937);
- TEST(lagged_fibonacci607);
- TEST(lagged_fibonacci1279);
- TEST(lagged_fibonacci2281);
- TEST(lagged_fibonacci3217);
- TEST(lagged_fibonacci4423);
- TEST(lagged_fibonacci9689);
- TEST(lagged_fibonacci19937);
- TEST(lagged_fibonacci23209);
- TEST(lagged_fibonacci44497);
- TEST(ranlux3);
- TEST(ranlux4);
- #if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
- TEST(ranlux64_3);
- TEST(ranlux64_4);
- #endif
- TEST(ranlux3_01);
- TEST(ranlux4_01);
- TEST(ranlux64_3_01);
- TEST(ranlux64_4_01);
-
- if(args.check_("normal"))
- env.run_test<boost::mt19937>("normal", boost::normal_distribution<>(), boost::math::normal());
- if(args.check_("triangle"))
- env.run_test<boost::mt19937>("triangle", boost::triangle_distribution<>(0, 1, 3), boost::math::triangular(0, 1, 3));
- if(args.check_("cauchy"))
- env.run_test<boost::mt19937>("cauchy", boost::cauchy_distribution<>(), boost::math::cauchy());
- if(args.check_("gamma"))
- env.run_test<boost::mt19937>("gamma", boost::gamma_distribution<>(1), boost::math::gamma_distribution<>(1));
- if(args.check_("exponential"))
- env.run_test<boost::mt19937>("exponential", boost::exponential_distribution<>(), boost::math::exponential());
- if(args.check_("lognormal"))
- env.run_test<boost::mt19937>("lognormal", boost::lognormal_distribution<>(1, 1),
- boost::math::lognormal(std::log(1.0/std::sqrt(2.0)), std::sqrt(std::log(2.0))));
- }