test_real_distribution.ipp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /* test_real_distribution.ipp
  2. *
  3. * Copyright Steven Watanabe 2011
  4. * Distributed under the Boost Software License, Version 1.0. (See
  5. * accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * $Id$
  9. *
  10. */
  11. #ifndef BOOST_MATH_DISTRIBUTION_INIT
  12. #ifdef BOOST_RANDOM_ARG2_TYPE
  13. #define BOOST_MATH_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME, BOOST_RANDOM_ARG2_NAME)
  14. #else
  15. #define BOOST_MATH_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME)
  16. #endif
  17. #endif
  18. #ifndef BOOST_RANDOM_DISTRIBUTION_INIT
  19. #ifdef BOOST_RANDOM_ARG2_TYPE
  20. #define BOOST_RANDOM_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME, BOOST_RANDOM_ARG2_NAME)
  21. #else
  22. #define BOOST_RANDOM_DISTRIBUTION_INIT (BOOST_RANDOM_ARG1_NAME)
  23. #endif
  24. #endif
  25. #ifndef BOOST_RANDOM_P_CUTOFF
  26. #define BOOST_RANDOM_P_CUTOFF 0.99
  27. #endif
  28. #include <boost/random/mersenne_twister.hpp>
  29. #include <boost/lexical_cast.hpp>
  30. #include <boost/exception/diagnostic_information.hpp>
  31. #include <boost/preprocessor/stringize.hpp>
  32. #include <boost/range/numeric.hpp>
  33. #include <boost/numeric/conversion/cast.hpp>
  34. #include <iostream>
  35. #include <vector>
  36. #include "statistic_tests.hpp"
  37. #include "chi_squared_test.hpp"
  38. bool do_test(BOOST_RANDOM_ARG1_TYPE BOOST_RANDOM_ARG1_NAME,
  39. #ifdef BOOST_RANDOM_ARG2_TYPE
  40. BOOST_RANDOM_ARG2_TYPE BOOST_RANDOM_ARG2_NAME,
  41. #endif
  42. long long max, boost::mt19937& gen) {
  43. std::cout << "running " BOOST_PP_STRINGIZE(BOOST_RANDOM_DISTRIBUTION_NAME) "("
  44. << BOOST_RANDOM_ARG1_NAME;
  45. #ifdef BOOST_RANDOM_ARG2_NAME
  46. std::cout << ", " << BOOST_RANDOM_ARG2_NAME;
  47. #endif
  48. std::cout << ")" << " " << max << " times: " << std::flush;
  49. BOOST_MATH_DISTRIBUTION expected BOOST_MATH_DISTRIBUTION_INIT;
  50. BOOST_RANDOM_DISTRIBUTION dist BOOST_RANDOM_DISTRIBUTION_INIT;
  51. #ifdef BOOST_RANDOM_DISTRIBUTION_MAX
  52. BOOST_RANDOM_DISTRIBUTION::result_type max_value = BOOST_RANDOM_DISTRIBUTION_MAX;
  53. std::vector<double> expected_pdf(max_value+1);
  54. {
  55. for(int i = 0; i <= max_value; ++i) {
  56. expected_pdf[i] = pdf(expected, i);
  57. }
  58. expected_pdf.back() += 1 - boost::accumulate(expected_pdf, 0.0);
  59. }
  60. std::vector<long long> results(max_value + 1);
  61. for(long long i = 0; i < max; ++i) {
  62. ++results[(std::min)(dist(gen), max_value)];
  63. }
  64. long long sum = boost::accumulate(results, 0ll);
  65. if(sum != max) {
  66. std::cout << "*** Failed: incorrect total: " << sum << " ***" << std::endl;
  67. return false;
  68. }
  69. double prob = chi_squared_test(results, expected_pdf, max);
  70. #else
  71. kolmogorov_experiment test(boost::numeric_cast<int>(max));
  72. boost::variate_generator<boost::mt19937&, BOOST_RANDOM_DISTRIBUTION > vgen(gen, dist);
  73. double prob = test.probability(test.run(vgen, expected));
  74. #endif
  75. bool result = prob < BOOST_RANDOM_P_CUTOFF;
  76. const char* err = result? "" : "*";
  77. std::cout << std::setprecision(17) << prob << err << std::endl;
  78. std::cout << std::setprecision(6);
  79. return result;
  80. }
  81. template<class Dist1
  82. #ifdef BOOST_RANDOM_ARG2_NAME
  83. , class Dist2
  84. #endif
  85. >
  86. bool do_tests(int repeat, Dist1 d1,
  87. #ifdef BOOST_RANDOM_ARG2_NAME
  88. Dist2 d2,
  89. #endif
  90. long long trials) {
  91. boost::mt19937 gen;
  92. int errors = 0;
  93. for(int i = 0; i < repeat; ++i) {
  94. if(!do_test(d1(gen),
  95. #ifdef BOOST_RANDOM_ARG2_NAME
  96. d2(gen),
  97. #endif
  98. trials, gen)) {
  99. ++errors;
  100. }
  101. }
  102. if(errors != 0) {
  103. std::cout << "*** " << errors << " errors detected ***" << std::endl;
  104. }
  105. return errors == 0;
  106. }
  107. int usage() {
  108. std::cerr << "Usage: test_" BOOST_PP_STRINGIZE(BOOST_RANDOM_DISTRIBUTION_NAME)
  109. " -r <repeat>"
  110. " -" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG1_NAME)
  111. " <max " BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG1_NAME) ">"
  112. #ifdef BOOST_RANDOM_ARG2_NAME
  113. " -" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG2_NAME)
  114. " <max " BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG2_NAME) ">"
  115. #endif
  116. " -t <trials>" << std::endl;
  117. return 2;
  118. }
  119. template<class T>
  120. bool handle_option(int& argc, char**& argv, const char* opt, T& value) {
  121. if(std::strcmp(argv[0], opt) == 0 && argc > 1) {
  122. --argc;
  123. ++argv;
  124. value = boost::lexical_cast<T>(argv[0]);
  125. return true;
  126. } else {
  127. return false;
  128. }
  129. }
  130. int main(int argc, char** argv) {
  131. int repeat = 1;
  132. BOOST_RANDOM_ARG1_TYPE max_arg1 = BOOST_RANDOM_ARG1_DEFAULT;
  133. #ifdef BOOST_RANDOM_ARG2_TYPE
  134. BOOST_RANDOM_ARG2_TYPE max_arg2 = BOOST_RANDOM_ARG2_DEFAULT;
  135. #endif
  136. long long trials = 100000;
  137. if(argc > 0) {
  138. --argc;
  139. ++argv;
  140. }
  141. while(argc > 0) {
  142. if(argv[0][0] != '-') return usage();
  143. else if(!handle_option(argc, argv, "-r", repeat)
  144. && !handle_option(argc, argv, "-" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG1_NAME), max_arg1)
  145. #ifdef BOOST_RANDOM_ARG2_TYPE
  146. && !handle_option(argc, argv, "-" BOOST_PP_STRINGIZE(BOOST_RANDOM_ARG2_NAME), max_arg2)
  147. #endif
  148. && !handle_option(argc, argv, "-t", trials)) {
  149. return usage();
  150. }
  151. --argc;
  152. ++argv;
  153. }
  154. try {
  155. if(do_tests(repeat,
  156. BOOST_RANDOM_ARG1_DISTRIBUTION(max_arg1),
  157. #ifdef BOOST_RANDOM_ARG2_TYPE
  158. BOOST_RANDOM_ARG2_DISTRIBUTION(max_arg2),
  159. #endif
  160. trials)) {
  161. return 0;
  162. } else {
  163. return EXIT_FAILURE;
  164. }
  165. } catch(...) {
  166. std::cerr << boost::current_exception_diagnostic_information() << std::endl;
  167. return EXIT_FAILURE;
  168. }
  169. }