Blame libs/random/test/chi_squared_test.hpp

Packit 58578d
/* chi_squared_test.hpp header file
Packit 58578d
 *
Packit 58578d
 * Copyright Steven Watanabe 2010
Packit 58578d
 * Distributed under the Boost Software License, Version 1.0. (See
Packit 58578d
 * accompanying file LICENSE_1_0.txt or copy at
Packit 58578d
 * http://www.boost.org/LICENSE_1_0.txt)
Packit 58578d
 *
Packit 58578d
 * $Id$
Packit 58578d
 *
Packit 58578d
 */
Packit 58578d
Packit 58578d
#ifndef BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED
Packit 58578d
#define BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED
Packit 58578d
Packit 58578d
#include <vector>
Packit 58578d
Packit 58578d
#include <boost/math/special_functions/pow.hpp>
Packit 58578d
#include <boost/math/distributions/chi_squared.hpp>
Packit 58578d
Packit 58578d
// This only works for discrete distributions with fixed
Packit 58578d
// upper and lower bounds.
Packit 58578d
Packit 58578d
template<class IntType>
Packit 58578d
struct chi_squared_collector {
Packit 58578d
Packit 58578d
    static const IntType cutoff = 5;
Packit 58578d
Packit 58578d
    chi_squared_collector()
Packit 58578d
      : chi_squared(0),
Packit 58578d
        variables(0),
Packit 58578d
        prev_actual(0),
Packit 58578d
        prev_expected(0),
Packit 58578d
        current_actual(0),
Packit 58578d
        current_expected(0)
Packit 58578d
    {}
Packit 58578d
Packit 58578d
    void operator()(IntType actual, double expected) {
Packit 58578d
        current_actual += actual;
Packit 58578d
        current_expected += expected;
Packit 58578d
Packit 58578d
        if(current_expected >= cutoff) {
Packit 58578d
            if(prev_expected != 0) {
Packit 58578d
                update(prev_actual, prev_expected);
Packit 58578d
            }
Packit 58578d
            prev_actual = current_actual;
Packit 58578d
            prev_expected = current_expected;
Packit 58578d
Packit 58578d
            current_actual = 0;
Packit 58578d
            current_expected = 0;
Packit 58578d
        }
Packit 58578d
    }
Packit 58578d
Packit 58578d
    void update(IntType actual, double expected) {
Packit 58578d
        chi_squared += boost::math::pow<2>(actual - expected) / expected;
Packit 58578d
        ++variables;
Packit 58578d
    }
Packit 58578d
Packit 58578d
    double cdf() {
Packit 58578d
        if(prev_expected != 0) {
Packit 58578d
            update(prev_actual + current_actual, prev_expected + current_expected);
Packit 58578d
            prev_actual = 0;
Packit 58578d
            prev_expected = 0;
Packit 58578d
            current_actual = 0;
Packit 58578d
            current_expected = 0;
Packit 58578d
        }
Packit 58578d
        if(variables <= 1) {
Packit 58578d
            return 0;
Packit 58578d
        } else {
Packit 58578d
            return boost::math::cdf(boost::math::chi_squared(static_cast<double>(variables - 1)), chi_squared);
Packit 58578d
        }
Packit 58578d
    }
Packit 58578d
Packit 58578d
    double chi_squared;
Packit 58578d
    std::size_t variables;
Packit 58578d
    
Packit 58578d
    IntType prev_actual;
Packit 58578d
    double prev_expected;
Packit 58578d
    
Packit 58578d
    IntType current_actual;
Packit 58578d
    double current_expected;
Packit 58578d
};
Packit 58578d
Packit 58578d
template<class IntType>
Packit 58578d
double chi_squared_test(const std::vector<IntType>& results, const std::vector<double>& probabilities, IntType iterations) {
Packit 58578d
    chi_squared_collector<IntType> calc;
Packit 58578d
    for(std::size_t i = 0; i < results.size(); ++i) {
Packit 58578d
        calc(results[i], iterations * probabilities[i]);
Packit 58578d
    }
Packit 58578d
    return calc.cdf();
Packit 58578d
}
Packit 58578d
Packit 58578d
#endif