chi_squared_test.hpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /* chi_squared_test.hpp header file
  2. *
  3. * Copyright Steven Watanabe 2010
  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_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED
  12. #define BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED
  13. #include <vector>
  14. #include <boost/math/special_functions/pow.hpp>
  15. #include <boost/math/distributions/chi_squared.hpp>
  16. // This only works for discrete distributions with fixed
  17. // upper and lower bounds.
  18. template<class IntType>
  19. struct chi_squared_collector {
  20. static const IntType cutoff = 5;
  21. chi_squared_collector()
  22. : chi_squared(0),
  23. variables(0),
  24. prev_actual(0),
  25. prev_expected(0),
  26. current_actual(0),
  27. current_expected(0)
  28. {}
  29. void operator()(IntType actual, double expected) {
  30. current_actual += actual;
  31. current_expected += expected;
  32. if(current_expected >= cutoff) {
  33. if(prev_expected != 0) {
  34. update(prev_actual, prev_expected);
  35. }
  36. prev_actual = current_actual;
  37. prev_expected = current_expected;
  38. current_actual = 0;
  39. current_expected = 0;
  40. }
  41. }
  42. void update(IntType actual, double expected) {
  43. chi_squared += boost::math::pow<2>(actual - expected) / expected;
  44. ++variables;
  45. }
  46. double cdf() {
  47. if(prev_expected != 0) {
  48. update(prev_actual + current_actual, prev_expected + current_expected);
  49. prev_actual = 0;
  50. prev_expected = 0;
  51. current_actual = 0;
  52. current_expected = 0;
  53. }
  54. if(variables <= 1) {
  55. return 0;
  56. } else {
  57. return boost::math::cdf(boost::math::chi_squared(static_cast<double>(variables - 1)), chi_squared);
  58. }
  59. }
  60. double chi_squared;
  61. std::size_t variables;
  62. IntType prev_actual;
  63. double prev_expected;
  64. IntType current_actual;
  65. double current_expected;
  66. };
  67. template<class IntType>
  68. double chi_squared_test(const std::vector<IntType>& results, const std::vector<double>& probabilities, IntType iterations) {
  69. chi_squared_collector<IntType> calc;
  70. for(std::size_t i = 0; i < results.size(); ++i) {
  71. calc(results[i], iterations * probabilities[i]);
  72. }
  73. return calc.cdf();
  74. }
  75. #endif