mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
Kolmogorov-Smirnov distribution (#422)
* Kolmogorov-Smirnov distribution #421 Add a new distribution, kolmogorov_smirnov_distribution, which takes a parameter that represents the number of observations used in a Kolmogorov-Smirnov test. (The K-S test is a popular test for comparing two CDFs, but the test statistic is not implemented here.) This implementation includes Kolmogorov's original 1st order Taylor expansion. There is a literature on the distribution's other mathematical properties (higher order terms and exact version); this literature is summarized in the main header file for anyone who may want to expand the implementation later. The CDF is implemented using a Jacobi theta function, and the PDF is a hand-rolled derivative of that function. Quantiles plug the CDF and PDF into a Newton-Raphson iteration. The mean and variance have nice closed-form expressions, and the mode uses a dumb run-time maximizer. This commit includes graphs, a ULP plotter for the PDF, and the usual compilation and numerical tests. The test file is on the small side, but it integrates the distribution from zero to infinity, and covers the quantiles pretty well. As of now the numerical tests only verify self-consistency (e.g. distribution moments and CDF-quantile relations), so there's room to add some external checks. * Implement skewness for K-S distribution [CI SKIP] The third moment integrates nicely with the help of Apery's constant (zeta_three). Verify the result via quadrature. * Implement kurtosis for the K-S distribution Verify the result via quadrature.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
[include inverse_chi_squared.qbk]
|
||||
[include inverse_gamma.qbk]
|
||||
[include inverse_gaussian.qbk]
|
||||
[include kolmogorov_smirnov.qbk]
|
||||
[include laplace.qbk]
|
||||
[include logistic.qbk]
|
||||
[include lognormal.qbk]
|
||||
|
||||
122
doc/distributions/kolmogorov_smirnov.qbk
Normal file
122
doc/distributions/kolmogorov_smirnov.qbk
Normal file
@@ -0,0 +1,122 @@
|
||||
[section:kolmogorov_smirnov_dist Kolmogorov-Smirnov Distribution]
|
||||
|
||||
``#include <boost/math/distributions/kolmogorov_smirnov.hpp>``
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
template <class RealType = double,
|
||||
class ``__Policy`` = ``__policy_class`` >
|
||||
class kolmogorov_smirnov_distribution;
|
||||
|
||||
typedef kolmogorov_smirnov_distribution<> kolmogorov_smirnov;
|
||||
|
||||
template <class RealType, class ``__Policy``>
|
||||
class kolmogorov_smirnov_distribution
|
||||
{
|
||||
public:
|
||||
typedef RealType value_type;
|
||||
typedef Policy policy_type;
|
||||
|
||||
// Constructor:
|
||||
kolmogorov_smirnov_distribution(RealType n);
|
||||
|
||||
// Accessor to parameter:
|
||||
RealType number_of_observations()const;
|
||||
|
||||
}} // namespaces
|
||||
|
||||
The Kolmogorov-Smirnov test in statistics compares two empirical distributions,
|
||||
or an empirical distribution against any theoretical distribution.[footnote
|
||||
[@https://en.wikipedia.org/wiki/Kolmogorov–Smirnov_test Wikipedia:
|
||||
Kolmogorov-Smirnov test]] It makes use of a specific distribution which is
|
||||
informally known in the literature as the Kolmogorv-Smirnov distribution,
|
||||
implemented here.
|
||||
|
||||
Formally, if /n/ observations are taken from a theoretical distribution /G(x)/,
|
||||
and if /G/[sub /n/](/x/) represents the empirical CDF of those /n/ observations,
|
||||
then the test statistic
|
||||
|
||||
[equation kolmogorov_smirnov_test_statistic] [/ D_n = \sup_x|G(x)-\hat{G}(x)| ]
|
||||
|
||||
will be distributed according to a Kolmogorov-Smirnov distribution parameterized by /n/.
|
||||
|
||||
The exact form of a Kolmogorov-Smirnov distribution is the subject of a large,
|
||||
decades-old literature.[footnote
|
||||
[@https://www.jstatsoft.org/article/view/v039i11 Simard, R. and L'Ecuyer, P.
|
||||
(2011) "Computing the Two-Sided Kolmogorov-Smirnov Distribution". Journal of
|
||||
Statistical Software, vol. 39, no. 11.]] In the interest of simplicity, Boost
|
||||
implements the first-order, limiting form of this distribution (the same form
|
||||
originally identified by Kolmogorov[footnote Kolmogorov A (1933). "Sulla
|
||||
determinazione empirica di una legge di distribuzione". G. Ist. Ital. Attuari.
|
||||
4: 83–91.]), namely
|
||||
|
||||
[equation kolmogorov_smirnov_distribution]
|
||||
[/ \lim_{n \to \infty} F_n(x/\sqrt{n})=1+2\sum_{k=1}^\infty (-1)^k e^{-2k^2x^2} ]
|
||||
|
||||
Note that while the exact distribution only has support over \[0, 1\], this
|
||||
limiting form has positive mass above unity, particularly for small /n/. The
|
||||
following graph illustrations how the distribution changes for different values
|
||||
of /n/:
|
||||
|
||||
[graph kolmogorov_smirnov_pdf]
|
||||
|
||||
[h4 Member Functions]
|
||||
|
||||
kolmogorov_smirnov_distribution(RealType n);
|
||||
|
||||
Constructs a Kolmogorov-Smirnov distribution with /n/ observations.
|
||||
|
||||
Requires n > 0, otherwise calls __domain_error.
|
||||
|
||||
RealType number_of_observations()const;
|
||||
|
||||
Returns the parameter /n/ from which this object was constructed.
|
||||
|
||||
[h4 Non-member Accessors]
|
||||
|
||||
All the [link math_toolkit.dist_ref.nmp usual non-member accessor functions]
|
||||
that are generic to all distributions are supported: __usual_accessors.
|
||||
|
||||
The domain of the random variable is \[0, +[infin]\].
|
||||
|
||||
[h4 Accuracy]
|
||||
|
||||
The CDF of the Kolmogorov-Smirnov distribution is implemented in terms of the
|
||||
fourth [link math_toolkit.jacobi_theta.jacobi_theta_overview Jacobi Theta
|
||||
function]; please refer to the accuracy ULP plots for that function.
|
||||
|
||||
The PDF is implemented separately, and the following ULP plot illustrates its
|
||||
accuracy:
|
||||
|
||||
[graph kolmogorov_smirnov_pdf_ulp]
|
||||
|
||||
Because PDF values are simply scaled out and up by the square root of /n/, the
|
||||
above plot is representative for all values of /n/. Note that for present
|
||||
purposes, "accuracy" refers to deviations from the limiting approximation,
|
||||
rather than deviations from the exact distribution.
|
||||
|
||||
[h4 Implementation]
|
||||
|
||||
In the following table, /n/ is the number of observations, /x/ is the random variable,
|
||||
[pi] is Archimedes' constant, and [zeta](3) is Apéry's constant.
|
||||
|
||||
[table
|
||||
[[Function][Implementation Notes]]
|
||||
[[cdf][Using the relation: cdf = __jacobi_theta4tau(0, 2*x*x/[pi])]]
|
||||
[[pdf][Using a manual derivative of the CDF]]
|
||||
[[cdf complement][
|
||||
When x*x*n == 0: 1
|
||||
|
||||
When 2*x*x*n <= [pi]: 1 - __jacobi_theta4tau(0, 2*x*x*n/[pi])
|
||||
|
||||
When 2*x*x*n > [pi]: -__jacobi_theta4m1tau(0, 2*x*x*n/[pi])]]
|
||||
[[quantile][Using a Newton-Raphson iteration]]
|
||||
[[quantile from the complement][Using a Newton-Raphson iteration]]
|
||||
[[mode][Using a run-time PDF maximizer]]
|
||||
[[mean][sqrt([pi]/2) * ln(2) / sqrt(n)]]
|
||||
[[variance][([pi][super 2]/12 - [pi]/2*ln[super 2](2))/n]]
|
||||
[[skewness][(9/16*sqrt([pi]/2)*[zeta](3)/n[super 3/2] - 3 * mean * variance - mean[super 2] * variance) / (variance[super 3/2])]]
|
||||
[[kurtosis][(7/720*[pi][super 4]/n[super 2] - 4 * mean * skewness * variance[super 3/2] - 6 * mean[super 2] * variance - mean[super 4]) / (variance[super 2])]]
|
||||
]
|
||||
|
||||
[endsect] [/section:kolmogorov_smirnov_dist Kolmogorov-Smirnov]
|
||||
1
doc/equations/kolmogorov_smirnov_distribution.svg
Normal file
1
doc/equations/kolmogorov_smirnov_distribution.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 26 KiB |
1
doc/equations/kolmogorov_smirnov_test_statistic.svg
Normal file
1
doc/equations/kolmogorov_smirnov_test_statistic.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 24 KiB |
@@ -84,8 +84,9 @@ public:
|
||||
m_distributions.push_back(std::make_pair(name, d));
|
||||
//
|
||||
// Get the extent of the distribution from the support:
|
||||
double a, b;
|
||||
std::tr1::tie(a, b) = support(d);
|
||||
std::pair<double, double> r = support(d);
|
||||
double a = r.first;
|
||||
double b = r.second;
|
||||
//
|
||||
// PDF maximum is at the mode (probably):
|
||||
double mod;
|
||||
@@ -253,7 +254,7 @@ public:
|
||||
if(!is_discrete_distribution<Dist>::value)
|
||||
{
|
||||
// Continuous distribution:
|
||||
for(std::list<std::pair<std::string, Dist> >::const_iterator i = m_distributions.begin();
|
||||
for(typename std::list<std::pair<std::string, Dist> >::const_iterator i = m_distributions.begin();
|
||||
i != m_distributions.end(); ++i)
|
||||
{
|
||||
double x = m_min_x;
|
||||
@@ -280,7 +281,7 @@ public:
|
||||
// Discrete distribution:
|
||||
double x_width = 0.75 / m_distributions.size();
|
||||
double x_off = -0.5 * 0.75;
|
||||
for(std::list<std::pair<std::string, Dist> >::const_iterator i = m_distributions.begin();
|
||||
for(typename std::list<std::pair<std::string, Dist> >::const_iterator i = m_distributions.begin();
|
||||
i != m_distributions.end(); ++i)
|
||||
{
|
||||
double x = ceil(m_min_x);
|
||||
@@ -469,6 +470,22 @@ int main()
|
||||
fisher_f_plotter.add(boost::math::fisher_f_distribution<>(4, 10), "n=4, m=10");
|
||||
fisher_f_plotter.plot("F Distribution PDF", "fisher_f_pdf.svg");
|
||||
|
||||
distribution_plotter<boost::math::kolmogorov_smirnov_distribution<> >
|
||||
kolmogorov_smirnov_cdf_plotter(false);
|
||||
kolmogorov_smirnov_cdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(1), "n=1");
|
||||
kolmogorov_smirnov_cdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(2), "n=2");
|
||||
kolmogorov_smirnov_cdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(5), "n=5");
|
||||
kolmogorov_smirnov_cdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(10), "n=10");
|
||||
kolmogorov_smirnov_cdf_plotter.plot("Kolmogorov-Smirnov Distribution CDF", "kolmogorov_smirnov_cdf.svg");
|
||||
|
||||
distribution_plotter<boost::math::kolmogorov_smirnov_distribution<> >
|
||||
kolmogorov_smirnov_pdf_plotter;
|
||||
kolmogorov_smirnov_pdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(1), "n=1");
|
||||
kolmogorov_smirnov_pdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(2), "n=2");
|
||||
kolmogorov_smirnov_pdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(5), "n=5");
|
||||
kolmogorov_smirnov_pdf_plotter.add(boost::math::kolmogorov_smirnov_distribution<>(10), "n=10");
|
||||
kolmogorov_smirnov_pdf_plotter.plot("Kolmogorov-Smirnov Distribution PDF", "kolmogorov_smirnov_pdf.svg");
|
||||
|
||||
distribution_plotter<boost::math::lognormal_distribution<> >
|
||||
lognormal_plotter;
|
||||
lognormal_plotter.add(boost::math::lognormal_distribution<>(-1), "location=-1");
|
||||
|
||||
70
doc/graphs/kolmogorov_smirnov_pdf.svg
Normal file
70
doc/graphs/kolmogorov_smirnov_pdf.svg
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="750" height ="400" version="1.1"
|
||||
xmlns:svg ="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns ="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<!-- SVG plot written using Boost.Plot program (Creator Jacob Voytko) -->
|
||||
<!-- Use, modification and distribution of Boost.Plot subject to 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) -->
|
||||
|
||||
<!-- SVG Plot Copyright John Maddock 2008 -->
|
||||
<meta name="copyright" content="John Maddock" />
|
||||
<meta name="date" content="2008" />
|
||||
<!-- Use, modification and distribution of this Scalable Vector Graphic file -->
|
||||
<!-- are subject to 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) -->
|
||||
|
||||
<clipPath id="plot_window"><rect x="44.9" y="53.5" width="614.7" height="292"/></clipPath>
|
||||
<g id="imageBackground" stroke="rgb(119,136,153)" fill="rgb(255,255,255)" stroke-width="2"><rect x="0" y="0" width="750" height="400"/></g>
|
||||
<g id="plotBackground" stroke="rgb(119,136,153)" fill="rgb(255,255,255)" stroke-width="2"><rect x="43.9" y="52.5" width="616.7" height="294"/></g>
|
||||
<g id="yMinorGrid" stroke="rgb(200,220,255)" stroke-width="0.5"></g>
|
||||
<g id="yMajorGrid" stroke="rgb(200,220,255)" stroke-width="1"></g>
|
||||
<g id="xMinorGrid" stroke="rgb(200,220,255)" stroke-width="0.5"></g>
|
||||
<g id="xMajorGrid" stroke="rgb(200,220,255)" stroke-width="1"></g>
|
||||
<g id="yAxis" stroke="rgb(0,0,0)" stroke-width="1"><line x1="43.9" y1="52.5" x2="43.9" y2="351.5"/><line x1="43.9" y1="52.5" x2="43.9" y2="346.5"/></g>
|
||||
<g id="xAxis" stroke="rgb(0,0,0)" stroke-width="1"><line x1="38.9" y1="346.5" x2="660.6" y2="346.5"/><line x1="38.9" y1="346.5" x2="660.6" y2="346.5"/></g>
|
||||
<g id="yMinorTicks" stroke="rgb(0,0,0)" stroke-width="1"><path d="M41.9,336.5 L43.9,336.5 M41.9,326.5 L43.9,326.5 M41.9,316.4 L43.9,316.4 M41.9,306.4 L43.9,306.4 M41.9,286.4 L43.9,286.4 M41.9,276.4 L43.9,276.4 M41.9,266.3 L43.9,266.3 M41.9,256.3 L43.9,256.3 M41.9,236.3 L43.9,236.3 M41.9,226.2 L43.9,226.2 M41.9,216.2 L43.9,216.2 M41.9,206.2 L43.9,206.2 M41.9,186.2 L43.9,186.2 M41.9,176.1 L43.9,176.1 M41.9,166.1 L43.9,166.1 M41.9,156.1 L43.9,156.1 M41.9,136.1 L43.9,136.1 M41.9,126 L43.9,126 M41.9,116 L43.9,116 M41.9,106 L43.9,106 M41.9,85.95 L43.9,85.95 M41.9,75.93 L43.9,75.93 M41.9,65.91 L43.9,65.91 M41.9,55.89 L43.9,55.89 M41.9,346.5 L43.9,346.5 " fill="none"/></g>
|
||||
<g id="xMinorTicks" stroke="rgb(0,0,0)" stroke-width="1"><path d="M82.86,346.5 L82.86,348.5 M121.8,346.5 L121.8,348.5 M160.8,346.5 L160.8,348.5 M199.7,346.5 L199.7,348.5 M277.7,346.5 L277.7,348.5 M316.6,346.5 L316.6,348.5 M355.6,346.5 L355.6,348.5 M394.6,346.5 L394.6,348.5 M472.5,346.5 L472.5,348.5 M511.4,346.5 L511.4,348.5 M550.4,346.5 L550.4,348.5 M589.4,346.5 L589.4,348.5 " fill="none"/></g>
|
||||
<g id="yMajorTicks" stroke="rgb(0,0,0)" stroke-width="2"><path d="M38.9,346.5 L43.9,346.5 M38.9,296.4 L43.9,296.4 M38.9,246.3 L43.9,246.3 M38.9,196.2 L43.9,196.2 M38.9,146.1 L43.9,146.1 M38.9,95.98 L43.9,95.98 M38.9,346.5 L43.9,346.5 " fill="none"/></g>
|
||||
<g id="xMajorTicks" stroke="rgb(0,0,0)" stroke-width="2"><path d="M43.9,346.5 L43.9,351.5 M238.7,346.5 L238.7,351.5 M433.5,346.5 L433.5,351.5 M628.3,346.5 L628.3,351.5 M43.9,346.5 L43.9,351.5 " fill="none"/></g>
|
||||
<g id="xTicksValues">
|
||||
<text x="43.9" y="367.1" text-anchor="middle" font-size="12" font-family="Lucida Sans Unicode">0</text>
|
||||
<text x="238.7" y="367.1" text-anchor="middle" font-size="12" font-family="Lucida Sans Unicode">0.5</text>
|
||||
<text x="433.5" y="367.1" text-anchor="middle" font-size="12" font-family="Lucida Sans Unicode">1</text>
|
||||
<text x="628.3" y="367.1" text-anchor="middle" font-size="12" font-family="Lucida Sans Unicode">1.5</text>
|
||||
<text x="43.9" y="367.1" text-anchor="middle" font-size="12" font-family="Lucida Sans Unicode">0</text></g>
|
||||
<g id="yTicksValues">
|
||||
<text x="32.9" y="348.9" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">0</text>
|
||||
<text x="32.9" y="298.8" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">1</text>
|
||||
<text x="32.9" y="248.7" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">2</text>
|
||||
<text x="32.9" y="198.6" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">3</text>
|
||||
<text x="32.9" y="148.5" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">4</text>
|
||||
<text x="32.9" y="98.38" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">5</text>
|
||||
<text x="32.9" y="348.9" text-anchor="end" font-size="12" font-family="Lucida Sans Unicode">0</text></g>
|
||||
<g id="yLabel">
|
||||
<text x="19.4" y="199.5" text-anchor="middle" transform = "rotate(-90 19.4 199.5 )" font-size="14" font-family="Lucida Sans Unicode">Probability</text></g>
|
||||
<g id="xLabel">
|
||||
<text x="352.3" y="382.2" text-anchor="middle" font-size="14" font-family="Lucida Sans Unicode">Random Variable</text></g>
|
||||
<g id="plotLines" stroke-width="2"><g clip-path="url(#plot_window)" stroke="rgb(0,0,139)" stroke-width="1"><path d="M43.9,346.5 L43.9,346.5 L46.98,346.5 L50.07,346.5 L53.15,346.5 L56.23,346.5 L59.32,346.5 L62.4,346.5 L65.49,346.5 L68.57,346.5 L71.65,346.5 L74.74,346.5 L77.82,346.5 L80.9,346.5 L83.99,346.5 L87.07,346.5 L90.16,346.5 L93.24,346.5 L96.32,346.5 L99.41,346.5 L102.5,346.5 L105.6,346.5 L108.7,346.5 L111.7,346.5 L114.8,346.5 L117.9,346.5 L121,346.5 L124.1,346.5 L127.2,346.5 L130.2,346.5 L133.3,346.5 L136.4,346.5 L139.5,346.5 L142.6,346.5 L145.7,346.5 L148.7,346.5 L151.8,346.5 L154.9,346.5 L158,346.5 L161.1,346.5 L164.2,346.4 L167.2,346.4 L170.3,346.3 L173.4,346.2 L176.5,346 L179.6,345.7 L182.7,345.4 L185.8,345 L188.8,344.4 L191.9,343.8 L195,343 L198.1,342 L201.2,340.9 L204.3,339.6 L207.3,338.1 L210.4,336.5 L213.5,334.6 L216.6,332.7 L219.7,330.5 L222.8,328.2 L225.8,325.8 L228.9,323.2 L232,320.5 L235.1,317.8 L238.2,314.9 L241.3,312.1 L244.3,309.2 L247.4,306.2 L250.5,303.3 L253.6,300.4 L256.7,297.6 L259.8,294.8 L262.8,292 L265.9,289.4 L269,286.8 L272.1,284.3 L275.2,282 L278.3,279.7 L281.3,277.6 L284.4,275.6 L287.5,273.8 L290.6,272.1 L293.7,270.5 L296.8,269.1 L299.8,267.8 L302.9,266.6 L306,265.6 L309.1,264.7 L312.2,264 L315.3,263.3 L318.3,262.8 L321.4,262.4 L324.5,262.2 L327.6,262 L330.7,262 L333.8,262 L336.9,262.2 L339.9,262.4 L343,262.8 L346.1,263.2 L349.2,263.7 L352.3,264.3 L355.4,264.9 L358.4,265.6 L361.5,266.4 L364.6,267.2 L367.7,268.1 L370.8,269 L373.9,270 L376.9,271 L380,272 L383.1,273.1 L386.2,274.2 L389.3,275.3 L392.4,276.5 L395.4,277.7 L398.5,278.8 L401.6,280 L404.7,281.3 L407.8,282.5 L410.9,283.7 L413.9,284.9 L417,286.2 L420.1,287.4 L423.2,288.7 L426.3,289.9 L429.4,291.1 L432.4,292.4 L435.5,293.6 L438.6,294.8 L441.7,296 L444.8,297.2 L447.9,298.4 L450.9,299.6 L454,300.7 L457.1,301.9 L460.2,303 L463.3,304.1 L466.4,305.3 L469.5,306.3 L472.5,307.4 L475.6,308.5 L478.7,309.5 L481.8,310.6 L484.9,311.6 L488,312.6 L491,313.5 L494.1,314.5 L497.2,315.4 L500.3,316.3 L503.4,317.2 L506.5,318.1 L509.5,319 L512.6,319.8 L515.7,320.7 L518.8,321.5 L521.9,322.3 L525,323 L528,323.8 L531.1,324.5 L534.2,325.3 L537.3,326 L540.4,326.7 L543.5,327.3 L546.5,328 L549.6,328.6 L552.7,329.2 L555.8,329.8 L558.9,330.4 L562,331 L565,331.5 L568.1,332.1 L571.2,332.6 L574.3,333.1 L577.4,333.6 L580.5,334.1 L583.5,334.5 L586.6,335 L589.7,335.4 L592.8,335.8 L595.9,336.2 L599,336.6 L602,337 L605.1,337.4 L608.2,337.8 L611.3,338.1 L614.4,338.4 L617.5,338.8 L620.6,339.1 L623.6,339.4 L626.7,339.7 L629.8,340 L632.9,340.2 L636,340.5 L639.1,340.7 L642.1,341 L645.2,341.2 L648.3,341.4 L651.4,341.7 L654.5,341.9 L657.6,342.1 " fill="none"/></g>
|
||||
<g clip-path="url(#plot_window)" stroke="rgb(139,0,0)" stroke-width="1"><path d="M43.9,346.5 L43.9,346.5 L46.98,346.5 L50.07,346.5 L53.15,346.5 L56.23,346.5 L59.32,346.5 L62.4,346.5 L65.49,346.5 L68.57,346.5 L71.65,346.5 L74.74,346.5 L77.82,346.5 L80.9,346.5 L83.99,346.5 L87.07,346.5 L90.16,346.5 L93.24,346.5 L96.32,346.5 L99.41,346.5 L102.5,346.5 L105.6,346.5 L108.7,346.5 L111.7,346.5 L114.8,346.5 L117.9,346.5 L121,346.5 L124.1,346.5 L127.2,346.4 L130.2,346.3 L133.3,346.2 L136.4,345.9 L139.5,345.5 L142.6,344.8 L145.7,343.9 L148.7,342.6 L151.8,340.9 L154.9,338.7 L158,336.1 L161.1,332.9 L164.2,329.3 L167.2,325.2 L170.3,320.7 L173.4,315.7 L176.5,310.5 L179.6,305 L182.7,299.3 L185.8,293.5 L188.8,287.6 L191.9,281.8 L195,276.1 L198.1,270.6 L201.2,265.2 L204.3,260.2 L207.3,255.4 L210.4,251 L213.5,246.9 L216.6,243.2 L219.7,239.9 L222.8,237 L225.8,234.4 L228.9,232.3 L232,230.5 L235.1,229.1 L238.2,228.1 L241.3,227.4 L244.3,227 L247.4,227 L250.5,227.2 L253.6,227.7 L256.7,228.4 L259.8,229.4 L262.8,230.6 L265.9,232 L269,233.5 L272.1,235.2 L275.2,237 L278.3,239 L281.3,241 L284.4,243.2 L287.5,245.4 L290.6,247.7 L293.7,250.1 L296.8,252.5 L299.8,254.9 L302.9,257.3 L306,259.8 L309.1,262.3 L312.2,264.8 L315.3,267.2 L318.3,269.7 L321.4,272.2 L324.5,274.6 L327.6,277 L330.7,279.3 L333.8,281.7 L336.9,284 L339.9,286.2 L343,288.4 L346.1,290.6 L349.2,292.7 L352.3,294.8 L355.4,296.9 L358.4,298.8 L361.5,300.8 L364.6,302.7 L367.7,304.5 L370.8,306.3 L373.9,308 L376.9,309.7 L380,311.3 L383.1,312.9 L386.2,314.4 L389.3,315.8 L392.4,317.3 L395.4,318.6 L398.5,320 L401.6,321.2 L404.7,322.5 L407.8,323.6 L410.9,324.8 L413.9,325.9 L417,326.9 L420.1,327.9 L423.2,328.9 L426.3,329.8 L429.4,330.7 L432.4,331.5 L435.5,332.3 L438.6,333.1 L441.7,333.9 L444.8,334.6 L447.9,335.2 L450.9,335.9 L454,336.5 L457.1,337 L460.2,337.6 L463.3,338.1 L466.4,338.6 L469.5,339.1 L472.5,339.5 L475.6,340 L478.7,340.4 L481.8,340.7 L484.9,341.1 L488,341.4 L491,341.8 L494.1,342.1 L497.2,342.3 L500.3,342.6 L503.4,342.9 L506.5,343.1 L509.5,343.3 L512.6,343.5 L515.7,343.7 L518.8,343.9 L521.9,344.1 L525,344.3 L528,344.4 L531.1,344.6 L534.2,344.7 L537.3,344.8 L540.4,345 L543.5,345.1 L546.5,345.2 L549.6,345.3 L552.7,345.4 L555.8,345.4 L558.9,345.5 L562,345.6 L565,345.7 L568.1,345.7 L571.2,345.8 L574.3,345.8 L577.4,345.9 L580.5,345.9 L583.5,346 L586.6,346 L589.7,346.1 L592.8,346.1 L595.9,346.1 L599,346.2 L602,346.2 L605.1,346.2 L608.2,346.2 L611.3,346.3 L614.4,346.3 L617.5,346.3 L620.6,346.3 L623.6,346.3 L626.7,346.3 L629.8,346.4 L632.9,346.4 L636,346.4 L639.1,346.4 L642.1,346.4 L645.2,346.4 L648.3,346.4 L651.4,346.4 L654.5,346.4 L657.6,346.4 " fill="none"/></g>
|
||||
<g clip-path="url(#plot_window)" stroke="rgb(0,100,0)" stroke-width="1"><path d="M43.9,346.5 L43.9,346.5 L46.98,346.5 L50.07,346.5 L53.15,346.5 L56.23,346.5 L59.32,346.5 L62.4,346.5 L65.49,346.5 L68.57,346.5 L71.65,346.5 L74.74,346.5 L77.82,346.5 L80.9,346.5 L83.99,346.5 L87.07,346.5 L90.16,346.5 L93.24,346.5 L96.32,346.4 L99.41,346.2 L102.5,345.6 L105.6,344.3 L108.7,342 L111.7,338.2 L114.8,332.8 L117.9,325.3 L121,316 L124.1,304.8 L127.2,292.2 L130.2,278.4 L133.3,264 L136.4,249.4 L139.5,235.1 L142.6,221.4 L145.7,208.6 L148.7,197.1 L151.8,186.9 L154.9,178.3 L158,171.2 L161.1,165.7 L164.2,161.6 L167.2,159 L170.3,157.7 L173.4,157.6 L176.5,158.7 L179.6,160.7 L182.7,163.5 L185.8,167.1 L188.8,171.4 L191.9,176.2 L195,181.3 L198.1,186.9 L201.2,192.7 L204.3,198.7 L207.3,204.8 L210.4,210.9 L213.5,217.1 L216.6,223.3 L219.7,229.4 L222.8,235.5 L225.8,241.4 L228.9,247.2 L232,252.8 L235.1,258.3 L238.2,263.5 L241.3,268.6 L244.3,273.5 L247.4,278.2 L250.5,282.7 L253.6,287 L256.7,291.1 L259.8,295 L262.8,298.6 L265.9,302.1 L269,305.4 L272.1,308.5 L275.2,311.4 L278.3,314.2 L281.3,316.7 L284.4,319.1 L287.5,321.4 L290.6,323.5 L293.7,325.4 L296.8,327.2 L299.8,328.9 L302.9,330.5 L306,331.9 L309.1,333.2 L312.2,334.5 L315.3,335.6 L318.3,336.6 L321.4,337.6 L324.5,338.4 L327.6,339.2 L330.7,340 L333.8,340.6 L336.9,341.2 L339.9,341.8 L343,342.3 L346.1,342.7 L349.2,343.1 L352.3,343.5 L355.4,343.8 L358.4,344.1 L361.5,344.4 L364.6,344.6 L367.7,344.8 L370.8,345 L373.9,345.2 L376.9,345.4 L380,345.5 L383.1,345.6 L386.2,345.7 L389.3,345.8 L392.4,345.9 L395.4,346 L398.5,346 L401.6,346.1 L404.7,346.1 L407.8,346.2 L410.9,346.2 L413.9,346.3 L417,346.3 L420.1,346.3 L423.2,346.4 L426.3,346.4 L429.4,346.4 L432.4,346.4 L435.5,346.4 L438.6,346.4 L441.7,346.4 L444.8,346.4 L447.9,346.5 L450.9,346.5 L454,346.5 L457.1,346.5 L460.2,346.5 L463.3,346.5 L466.4,346.5 L469.5,346.5 L472.5,346.5 L475.6,346.5 L478.7,346.5 L481.8,346.5 L484.9,346.5 L488,346.5 L491,346.5 L494.1,346.5 L497.2,346.5 L500.3,346.5 L503.4,346.5 L506.5,346.5 L509.5,346.5 L512.6,346.5 L515.7,346.5 L518.8,346.5 L521.9,346.5 L525,346.5 L528,346.5 L531.1,346.5 L534.2,346.5 L537.3,346.5 L540.4,346.5 L543.5,346.5 L546.5,346.5 L549.6,346.5 L552.7,346.5 L555.8,346.5 L558.9,346.5 L562,346.5 L565,346.5 L568.1,346.5 L571.2,346.5 L574.3,346.5 L577.4,346.5 L580.5,346.5 L583.5,346.5 L586.6,346.5 L589.7,346.5 L592.8,346.5 L595.9,346.5 L599,346.5 L602,346.5 L605.1,346.5 L608.2,346.5 L611.3,346.5 L614.4,346.5 L617.5,346.5 L620.6,346.5 L623.6,346.5 L626.7,346.5 L629.8,346.5 L632.9,346.5 L636,346.5 L639.1,346.5 L642.1,346.5 L645.2,346.5 L648.3,346.5 L651.4,346.5 L654.5,346.5 L657.6,346.5 " fill="none"/></g>
|
||||
<g clip-path="url(#plot_window)" stroke="rgb(255,140,0)" stroke-width="1"><path d="M43.9,346.5 L43.9,346.5 L46.98,346.5 L50.07,346.5 L53.15,346.5 L56.23,346.5 L59.32,346.5 L62.4,346.5 L65.49,346.5 L68.57,346.5 L71.65,346.5 L74.74,346.5 L77.82,346.5 L80.9,346.4 L83.99,345.8 L87.07,343.8 L90.16,339.2 L93.24,330.3 L96.32,316.1 L99.41,296.5 L102.5,272.1 L105.6,244.5 L108.7,215.4 L111.7,186.7 L114.8,159.8 L117.9,136.1 L121,116.3 L124.1,100.7 L127.2,89.54 L130.2,82.57 L133.3,79.47 L136.4,79.83 L139.5,83.15 L142.6,88.96 L145.7,96.78 L148.7,106.2 L151.8,116.8 L154.9,128.2 L158,140.2 L161.1,152.5 L164.2,164.9 L167.2,177.2 L170.3,189.3 L173.4,201.1 L176.5,212.5 L179.6,223.4 L182.7,233.8 L185.8,243.7 L188.8,252.9 L191.9,261.6 L195,269.8 L198.1,277.3 L201.2,284.3 L204.3,290.8 L207.3,296.7 L210.4,302.1 L213.5,307.1 L216.6,311.6 L219.7,315.6 L222.8,319.3 L225.8,322.6 L228.9,325.6 L232,328.2 L235.1,330.6 L238.2,332.7 L241.3,334.5 L244.3,336.1 L247.4,337.6 L250.5,338.8 L253.6,339.9 L256.7,340.9 L259.8,341.7 L262.8,342.4 L265.9,343 L269,343.6 L272.1,344 L275.2,344.4 L278.3,344.8 L281.3,345 L284.4,345.3 L287.5,345.5 L290.6,345.7 L293.7,345.8 L296.8,345.9 L299.8,346 L302.9,346.1 L306,346.2 L309.1,346.2 L312.2,346.3 L315.3,346.3 L318.3,346.4 L321.4,346.4 L324.5,346.4 L327.6,346.4 L330.7,346.4 L333.8,346.5 L336.9,346.5 L339.9,346.5 L343,346.5 L346.1,346.5 L349.2,346.5 L352.3,346.5 L355.4,346.5 L358.4,346.5 L361.5,346.5 L364.6,346.5 L367.7,346.5 L370.8,346.5 L373.9,346.5 L376.9,346.5 L380,346.5 L383.1,346.5 L386.2,346.5 L389.3,346.5 L392.4,346.5 L395.4,346.5 L398.5,346.5 L401.6,346.5 L404.7,346.5 L407.8,346.5 L410.9,346.5 L413.9,346.5 L417,346.5 L420.1,346.5 L423.2,346.5 L426.3,346.5 L429.4,346.5 L432.4,346.5 L435.5,346.5 L438.6,346.5 L441.7,346.5 L444.8,346.5 L447.9,346.5 L450.9,346.5 L454,346.5 L457.1,346.5 L460.2,346.5 L463.3,346.5 L466.4,346.5 L469.5,346.5 L472.5,346.5 L475.6,346.5 L478.7,346.5 L481.8,346.5 L484.9,346.5 L488,346.5 L491,346.5 L494.1,346.5 L497.2,346.5 L500.3,346.5 L503.4,346.5 L506.5,346.5 L509.5,346.5 L512.6,346.5 L515.7,346.5 L518.8,346.5 L521.9,346.5 L525,346.5 L528,346.5 L531.1,346.5 L534.2,346.5 L537.3,346.5 L540.4,346.5 L543.5,346.5 L546.5,346.5 L549.6,346.5 L552.7,346.5 L555.8,346.5 L558.9,346.5 L562,346.5 L565,346.5 L568.1,346.5 L571.2,346.5 L574.3,346.5 L577.4,346.5 L580.5,346.5 L583.5,346.5 L586.6,346.5 L589.7,346.5 L592.8,346.5 L595.9,346.5 L599,346.5 L602,346.5 L605.1,346.5 L608.2,346.5 L611.3,346.5 L614.4,346.5 L617.5,346.5 L620.6,346.5 L623.6,346.5 L626.7,346.5 L629.8,346.5 L632.9,346.5 L636,346.5 L639.1,346.5 L642.1,346.5 L645.2,346.5 L648.3,346.5 L651.4,346.5 L654.5,346.5 L657.6,346.5 " fill="none"/></g>
|
||||
</g>
|
||||
<g id="plotPoints" clip-path="url(#plot_window)"></g>
|
||||
<g id="legendBackground" stroke="rgb(119,136,153)" fill="rgb(255,255,255)" stroke-width="1"><rect x="674.6" y="52.5" width="72.86" height="135"/><rect x="674.6" y="52.5" width="72.86" height="135"/></g>
|
||||
<g id="legendPoints"></g>
|
||||
<g id="legendText">
|
||||
<text x="689.6" y="82.5" font-size="15" font-family="Lucida Sans Unicode">n=1</text>
|
||||
<text x="689.6" y="112.5" font-size="15" font-family="Lucida Sans Unicode">n=2</text>
|
||||
<text x="689.6" y="142.5" font-size="15" font-family="Lucida Sans Unicode">n=5</text>
|
||||
<text x="689.6" y="172.5" font-size="15" font-family="Lucida Sans Unicode">n=10</text></g>
|
||||
<g id="title">
|
||||
<text x="375" y="40" text-anchor="middle" font-size="20" font-family="Lucida Sans Unicode">Kolmogorov-Smirnov Distribution PDF</text></g>
|
||||
<g id="plotXValues"></g>
|
||||
<g id="plotYValues"></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 16 KiB |
2551
doc/graphs/kolmogorov_smirnov_pdf_ulp.svg
Normal file
2551
doc/graphs/kolmogorov_smirnov_pdf_ulp.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 196 KiB |
@@ -169,6 +169,8 @@
|
||||
Gamma Distribution</a></span></dt>
|
||||
<dt><span class="section"><a href="math_toolkit/dist_ref/dists/inverse_gaussian_dist.html">Inverse
|
||||
Gaussian (or Inverse Normal) Distribution</a></span></dt>
|
||||
<dt><span class="section"><a href="math_toolkit/dist_ref/dists/kolmogorov_smirnov_dist.html">Kolmogorov-Smirnov
|
||||
Distribution</a></span></dt>
|
||||
<dt><span class="section"><a href="math_toolkit/dist_ref/dists/laplace_dist.html">Laplace Distribution</a></span></dt>
|
||||
<dt><span class="section"><a href="math_toolkit/dist_ref/dists/logistic_dist.html">Logistic
|
||||
Distribution</a></span></dt>
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Kolmogorov-Smirnov Distribution</title>
|
||||
<link rel="stylesheet" href="../../../math.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.79.2">
|
||||
<link rel="home" href="../../../index.html" title="Math Toolkit 2.12.0">
|
||||
<link rel="up" href="../dists.html" title="Distributions">
|
||||
<link rel="prev" href="inverse_gaussian_dist.html" title="Inverse Gaussian (or Inverse Normal) Distribution">
|
||||
<link rel="next" href="laplace_dist.html" title="Laplace Distribution">
|
||||
</head>
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<table cellpadding="2" width="100%"><tr>
|
||||
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
|
||||
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
|
||||
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
|
||||
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
|
||||
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="inverse_gaussian_dist.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../dists.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="laplace_dist.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h4 class="title">
|
||||
<a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist"></a><a class="link" href="kolmogorov_smirnov_dist.html" title="Kolmogorov-Smirnov Distribution">Kolmogorov-Smirnov
|
||||
Distribution</a>
|
||||
</h4></div></div></div>
|
||||
|
||||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">distributions</span><span class="special">/</span><span class="identifier">kolmogorov_smirnov</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></pre>
|
||||
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span><span class="special">{</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">RealType</span> <span class="special">=</span> <span class="keyword">double</span><span class="special">,</span>
|
||||
<span class="keyword">class</span> <a class="link" href="../../../policy.html" title="Chapter 21. Policies: Controlling Precision, Error Handling etc">Policy</a> <span class="special">=</span> <a class="link" href="../../pol_ref/pol_ref_ref.html" title="Policy Class Reference">policies::policy<></a> <span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">kolmogorov_smirnov_distribution</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">typedef</span> <span class="identifier">kolmogorov_smirnov_distribution</span><span class="special"><></span> <span class="identifier">kolmogorov_smirnov</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">RealType</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../../policy.html" title="Chapter 21. Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">></span>
|
||||
<span class="keyword">class</span> <span class="identifier">kolmogorov_smirnov_distribution</span>
|
||||
<span class="special">{</span>
|
||||
<span class="keyword">public</span><span class="special">:</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">RealType</span> <span class="identifier">value_type</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">Policy</span> <span class="identifier">policy_type</span><span class="special">;</span>
|
||||
|
||||
<span class="comment">// Constructor:</span>
|
||||
<span class="identifier">kolmogorov_smirnov_distribution</span><span class="special">(</span><span class="identifier">RealType</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
|
||||
<span class="comment">// Accessor to parameter:</span>
|
||||
<span class="identifier">RealType</span> <span class="identifier">number_of_observations</span><span class="special">()</span><span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="special">}}</span> <span class="comment">// namespaces</span>
|
||||
</pre>
|
||||
<p>
|
||||
The Kolmogorov-Smirnov test in statistics compares two empirical distributions,
|
||||
or an empirical distribution against any theoretical distribution.<a href="#ftn.math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f0" class="footnote" name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f0"><sup class="footnote">[1]</sup></a> It makes use of a specific distribution which is informally
|
||||
known in the literature as the Kolmogorv-Smirnov distribution, implemented
|
||||
here.
|
||||
</p>
|
||||
<p>
|
||||
Formally, if <span class="emphasis"><em>n</em></span> observations are taken from a theoretical
|
||||
distribution <span class="emphasis"><em>G(x)</em></span>, and if <span class="emphasis"><em>G</em></span><sub><span class="emphasis"><em>n</em></span></sub>(<span class="emphasis"><em>x</em></span>)
|
||||
represents the empirical CDF of those <span class="emphasis"><em>n</em></span> observations,
|
||||
then the test statistic
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../../equations/kolmogorov_smirnov_test_statistic.svg"></span>
|
||||
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<p>
|
||||
will be distributed according to a Kolmogorov-Smirnov distribution parameterized
|
||||
by <span class="emphasis"><em>n</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
The exact form of a Kolmogorov-Smirnov distribution is the subject of a
|
||||
large, decades-old literature.<a href="#ftn.math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f1" class="footnote" name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f1"><sup class="footnote">[2]</sup></a> In the interest of simplicity, Boost implements the first-order,
|
||||
limiting form of this distribution (the same form originally identified
|
||||
by Kolmogorov<a href="#ftn.math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f2" class="footnote" name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f2"><sup class="footnote">[3]</sup></a>), namely
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../../equations/kolmogorov_smirnov_distribution.svg"></span>
|
||||
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<p>
|
||||
Note that while the exact distribution only has support over [0, 1], this
|
||||
limiting form has positive mass above unity, particlularly for small <span class="emphasis"><em>n</em></span>.
|
||||
The following graph illustrations how the distribution changes for different
|
||||
values of <span class="emphasis"><em>n</em></span>:
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../../graphs/kolmogorov_smirnov_pdf.svg" align="middle"></span>
|
||||
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<h5>
|
||||
<a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.h0"></a>
|
||||
<span class="phrase"><a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.member_functions"></a></span><a class="link" href="kolmogorov_smirnov_dist.html#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.member_functions">Member
|
||||
Functions</a>
|
||||
</h5>
|
||||
<pre class="programlisting"><span class="identifier">kolmogorov_smirnov_distribution</span><span class="special">(</span><span class="identifier">RealType</span> <span class="identifier">n</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Constructs a Kolmogorov-Smirnov distribution with <span class="emphasis"><em>n</em></span>
|
||||
observations.
|
||||
</p>
|
||||
<p>
|
||||
Requires n > 0, otherwise calls <a class="link" href="../../error_handling.html#math_toolkit.error_handling.domain_error">domain_error</a>.
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">RealType</span> <span class="identifier">number_of_observations</span><span class="special">()</span><span class="keyword">const</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Returns the parameter <span class="emphasis"><em>n</em></span> from which this object was
|
||||
constructed.
|
||||
</p>
|
||||
<h5>
|
||||
<a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.h1"></a>
|
||||
<span class="phrase"><a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.non_member_accessors"></a></span><a class="link" href="kolmogorov_smirnov_dist.html#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.non_member_accessors">Non-member
|
||||
Accessors</a>
|
||||
</h5>
|
||||
<p>
|
||||
All the <a class="link" href="../nmp.html" title="Non-Member Properties">usual non-member accessor
|
||||
functions</a> that are generic to all distributions are supported:
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.cdf">Cumulative Distribution Function</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.pdf">Probability Density Function</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.quantile">Quantile</a>, <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.hazard">Hazard Function</a>, <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.chf">Cumulative Hazard Function</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.mean">mean</a>, <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.median">median</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.mode">mode</a>, <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.variance">variance</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.sd">standard deviation</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.skewness">skewness</a>, <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.kurtosis">kurtosis</a>, <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.kurtosis_excess">kurtosis_excess</a>,
|
||||
<a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.range">range</a> and <a class="link" href="../nmp.html#math_toolkit.dist_ref.nmp.support">support</a>.
|
||||
</p>
|
||||
<p>
|
||||
The domain of the random variable is [0, +∞].
|
||||
</p>
|
||||
<h5>
|
||||
<a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.h2"></a>
|
||||
<span class="phrase"><a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.accuracy"></a></span><a class="link" href="kolmogorov_smirnov_dist.html#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.accuracy">Accuracy</a>
|
||||
</h5>
|
||||
<p>
|
||||
The CDF of the Kolmogorov-Smirnov distribution is implemented in terms
|
||||
of the fourth <a class="link" href="../../jacobi_theta/jacobi_theta_overview.html" title="Overview of the Jacobi Theta Functions">Jacobi
|
||||
Theta function</a>; please refer to the accuracy ULP plots for that
|
||||
function.
|
||||
</p>
|
||||
<p>
|
||||
The PDF is implemented separately, and the following ULP plot illustrates
|
||||
its accuracy:
|
||||
</p>
|
||||
<div class="blockquote"><blockquote class="blockquote">
|
||||
<p>
|
||||
<span class="inlinemediaobject"><img src="../../../../graphs/kolmogorov_smirnov_pdf_ulp.svg" align="middle"></span>
|
||||
|
||||
</p>
|
||||
</blockquote></div>
|
||||
<p>
|
||||
Because PDF values are simply scaled out and up by the square root of
|
||||
<span class="emphasis"><em>n</em></span>, the above plot is representative for all values
|
||||
of <span class="emphasis"><em>n</em></span>. Note that for present purposes, "accuracy"
|
||||
refers to deviations from the limiting approximation, rather than deviations
|
||||
from the exact distribution.
|
||||
</p>
|
||||
<h5>
|
||||
<a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.h3"></a>
|
||||
<span class="phrase"><a name="math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.implementation"></a></span><a class="link" href="kolmogorov_smirnov_dist.html#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.implementation">Implementation</a>
|
||||
</h5>
|
||||
<p>
|
||||
In the following table, <span class="emphasis"><em>n</em></span> is the number of observations,
|
||||
<span class="emphasis"><em>x</em></span> is the random variable, π is Archimedes' constant,
|
||||
and ζ(3) is Apéry's constant.
|
||||
</p>
|
||||
<div class="informaltable">
|
||||
<table class="informaltable" border="1">
|
||||
<colgroup>
|
||||
<col>
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead><tr>
|
||||
<th>
|
||||
<p>
|
||||
Function
|
||||
</p>
|
||||
</th>
|
||||
<th>
|
||||
<p>
|
||||
Implementation Notes
|
||||
</p>
|
||||
</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
cdf
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Using the relation: cdf = <a class="link" href="../../jacobi_theta/jacobi_theta4.html" title="Jacobi Theta Function θ4">jacobi_theta4tau</a>(0,
|
||||
2*x*x/π)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
pdf
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Using a manual derivative of the CDF
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
cdf complement
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
When x*x*n == 0: 1
|
||||
</p>
|
||||
<p>
|
||||
When 2*x*x*n <= π: 1 - <a class="link" href="../../jacobi_theta/jacobi_theta4.html" title="Jacobi Theta Function θ4">jacobi_theta4tau</a>(0,
|
||||
2*x*x*n/π)
|
||||
</p>
|
||||
<p>
|
||||
When 2*x*x*n > π: -<a class="link" href="../../jacobi_theta/jacobi_theta4.html" title="Jacobi Theta Function θ4">jacobi_theta4m1tau</a>(0,
|
||||
2*x*x*n/π)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
quantile
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Using a Newton-Raphson iteration
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
quantile from the complement
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Using a Newton-Raphson iteration
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
mode
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
Using a run-time PDF maximizer
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
mean
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
sqrt(π/2) * ln(2) / sqrt(n)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
variance
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
(π<sup>2</sup>/12 - π/2*ln<sup>2</sup>(2))/n
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
skewness
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
(9/16*sqrt(π/2)*ζ(3)/n<sup>3/2</sup> - 3 * mean * variance - mean<sup>2</sup> * variance)
|
||||
/ (variance<sup>3/2</sup>)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
kurtosis
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p>
|
||||
(7/720*π<sup>4</sup>/n<sup>2</sup> - 4 * mean * skewness * variance<sup>3/2</sup> - 6 * mean<sup>2</sup> * variance
|
||||
- mean<sup>4</sup>) / (variance<sup>2</sup>)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="footnotes">
|
||||
<br><hr style="width:100; text-align:left;margin-left: 0">
|
||||
<div id="ftn.math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f0" class="footnote">
|
||||
<p><a href="#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f0" class="para"><sup class="para">[1] </sup></a>
|
||||
<a class="ulink" href="https://en.wikipedia.org/wiki/Kolmogorov%%E0%EpSmirnov_test" target="_top">Wikipedia:
|
||||
Kolmogorov-Smirnov test</a>
|
||||
</p>
|
||||
</div>
|
||||
<div id="ftn.math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f1" class="footnote">
|
||||
<p><a href="#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f1" class="para"><sup class="para">[2] </sup></a>
|
||||
<a class="ulink" href="https://www.jstatsoft.org/article/view/v039i11" target="_top">Simard, R.
|
||||
and L'Ecuyer, P. (2011) "Computing the Two-Sided Kolmogorov-Smirnov
|
||||
Distribution". Journal of Statistical Software, vol. 39, no. 11.</a>
|
||||
</p>
|
||||
</div>
|
||||
<div id="ftn.math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f2" class="footnote">
|
||||
<p><a href="#math_toolkit.dist_ref.dists.kolmogorov_smirnov_dist.f2" class="para"><sup class="para">[3] </sup></a>
|
||||
Kolmogorov A (1933). "Sulla determinazione empirica di una legge
|
||||
di distribuzione". G. Ist. Ital. Attuari. 4: 83–91.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||||
<td align="left"></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav">
|
||||
<a accesskey="p" href="inverse_gaussian_dist.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../dists.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="laplace_dist.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -130,6 +130,7 @@ math_toolkit/dist_ref/dists/hypergeometric_dist.html
|
||||
math_toolkit/dist_ref/dists/inverse_chi_squared_dist.html
|
||||
math_toolkit/dist_ref/dists/inverse_gamma_dist.html
|
||||
math_toolkit/dist_ref/dists/inverse_gaussian_dist.html
|
||||
math_toolkit/dist_ref/dists/kolmogorov_smirnov_dist.html
|
||||
math_toolkit/dist_ref/dists/laplace_dist.html
|
||||
math_toolkit/dist_ref/dists/logistic_dist.html
|
||||
math_toolkit/dist_ref/dists/lognormal_dist.html
|
||||
|
||||
@@ -387,6 +387,7 @@ and use the function's name as the link text.]
|
||||
[def __inverse_gamma_distrib [link math_toolkit.dist_ref.dists.inverse_gamma_dist Inverse Gamma Distribution]]
|
||||
[def __inverse_gaussian_distrib [link math_toolkit.dist_ref.dists.inverse_gaussian_dist Inverse Gaussian Distribution]]
|
||||
[def __inverse_chi_squared_distrib [link math_toolkit.dist_ref.dists.inverse_chi_squared_dist Inverse chi squared Distribution]]
|
||||
[def __kolmogorov_smirnov_distrib [link math_toolkit.dist_ref.dists.kolmogorov_smirnov Kolmogorov-Smirnov Distribution]]
|
||||
[def __laplace_distrib [link math_toolkit.dist_ref.dists.laplace_dist Laplace Distribution]]
|
||||
[def __logistic_distrib [link math_toolkit.dist_ref.dists.logistic_dist Logistic Distribution]]
|
||||
[def __lognormal_distrib [link math_toolkit.dist_ref.dists.lognormal_dist Log-normal Distribution]]
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <boost/math/distributions/inverse_chi_squared.hpp>
|
||||
#include <boost/math/distributions/inverse_gamma.hpp>
|
||||
#include <boost/math/distributions/inverse_gaussian.hpp>
|
||||
#include <boost/math/distributions/kolmogorov_smirnov.hpp>
|
||||
#include <boost/math/distributions/laplace.hpp>
|
||||
#include <boost/math/distributions/logistic.hpp>
|
||||
#include <boost/math/distributions/lognormal.hpp>
|
||||
|
||||
@@ -63,6 +63,9 @@ class inverse_gamma_distribution;
|
||||
template <class RealType, class Policy>
|
||||
class inverse_gaussian_distribution;
|
||||
|
||||
template <class RealType, class Policy>
|
||||
class kolmogorov_smirnov_distribution;
|
||||
|
||||
template <class RealType, class Policy>
|
||||
class laplace_distribution;
|
||||
|
||||
@@ -129,6 +132,7 @@ class weibull_distribution;
|
||||
typedef boost::math::gamma_distribution<Type, Policy> gamma;\
|
||||
typedef boost::math::geometric_distribution<Type, Policy> geometric;\
|
||||
typedef boost::math::hypergeometric_distribution<Type, Policy> hypergeometric;\
|
||||
typedef boost::math::kolmogorov_smirnov_distribution<Type, Policy> kolmogorov_smirnov;\
|
||||
typedef boost::math::inverse_chi_squared_distribution<Type, Policy> inverse_chi_squared;\
|
||||
typedef boost::math::inverse_gaussian_distribution<Type, Policy> inverse_gaussian;\
|
||||
typedef boost::math::inverse_gamma_distribution<Type, Policy> inverse_gamma;\
|
||||
|
||||
494
include/boost/math/distributions/kolmogorov_smirnov.hpp
Normal file
494
include/boost/math/distributions/kolmogorov_smirnov.hpp
Normal file
@@ -0,0 +1,494 @@
|
||||
// Kolmogorov-Smirnov 1st order asymptotic distribution
|
||||
// Copyright Evan Miller 2020
|
||||
//
|
||||
// Use, modification and distribution are subject to 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)
|
||||
//
|
||||
// The Kolmogorov-Smirnov test in statistics compares two empirical distributions,
|
||||
// or an empirical distribution against any theoretical distribution. It makes
|
||||
// use of a specific distribution which doesn't have a formal name, but which
|
||||
// is often called the Kolmogorv-Smirnov distribution for lack of anything
|
||||
// better. This file implements the limiting form of this distribution, first
|
||||
// identified by Andrey Kolmogorov in
|
||||
//
|
||||
// Kolmogorov, A. (1933) “Sulla Determinazione Empirica di una Legge di
|
||||
// Distribuzione.” Giornale dell’ Istituto Italiano degli Attuari
|
||||
//
|
||||
// This limiting form of the CDF is a first-order Taylor expansion that is
|
||||
// easily implemented by the fourth Jacobi Theta function (setting z=0). The
|
||||
// PDF is then implemented here as a derivative of the Theta function. Note
|
||||
// that this derivative is with respect to x, which enters into \tau, and not
|
||||
// with respect to the z argument, which is always zero, and so the derivative
|
||||
// identities in DLMF 20.4 do not apply here.
|
||||
//
|
||||
// A higher order order expansion is possible, and was first outlined by
|
||||
//
|
||||
// Pelz W, Good IJ (1976). “Approximating the Lower Tail-Areas of the
|
||||
// Kolmogorov-Smirnov One-sample Statistic.” Journal of the Royal Statistical
|
||||
// Society B.
|
||||
//
|
||||
// The terms in this expansion get fairly complicated, and as far as I know the
|
||||
// Pelz-Good expansion is not used in any statistics software. Someone could
|
||||
// consider updating this implementation to use the Pelz-Good expansion in the
|
||||
// future, but the math gets considerably hairier with each additional term.
|
||||
//
|
||||
// A formula for an exact version of the Kolmogorov-Smirnov test is laid out in
|
||||
// Equation 2.4.4 of
|
||||
//
|
||||
// Durbin J (1973). “Distribution Theory for Tests Based on the Sample
|
||||
// Distribution Func- tion.” In SIAM CBMS-NSF Regional Conference Series in
|
||||
// Applied Mathematics. SIAM, Philadelphia, PA.
|
||||
//
|
||||
// which is available in book form from Amazon and others. This exact version
|
||||
// involves taking powers of large matrices. To do that right you need to
|
||||
// compute eigenvalues and eigenvectors, which are beyond the scope of Boost.
|
||||
// (Some recent work indicates the exact form can also be computed via FFT, see
|
||||
// https://cran.r-project.org/web/packages/KSgeneral/KSgeneral.pdf).
|
||||
//
|
||||
// Even if the CDF of the exact distribution could be computed using Boost
|
||||
// libraries (which would be cumbersome), the PDF would present another
|
||||
// difficulty. Therefore I am limiting this implementation to the asymptotic
|
||||
// form, even though the exact form has trivial values for certain specific
|
||||
// values of x and n. For more on trivial values see
|
||||
//
|
||||
// Ruben H, Gambino J (1982). “The Exact Distribution of Kolmogorov’s Statistic
|
||||
// Dn for n ≤ 10.” Annals of the Institute of Statistical Mathematics.
|
||||
//
|
||||
// For a good bibliography and overview of the various algorithms, including
|
||||
// both exact and asymptotic forms, see
|
||||
// https://www.jstatsoft.org/article/view/v039i11
|
||||
//
|
||||
// As for this implementation: the distribution is parameterized by n (number
|
||||
// of observations) in the spirit of chi-squared's degrees of freedom. It then
|
||||
// takes a single argument x. In terms of the Kolmogorov-Smirnov statistical
|
||||
// test, x represents the distribution of D_n, where D_n is the maximum
|
||||
// difference between the CDFs being compared, that is,
|
||||
//
|
||||
// D_n = sup|F_n(x) - G(x)|
|
||||
//
|
||||
// In the exact distribution, x is confined to the support [0, 1], but in this
|
||||
// limiting approximation, we allow x to exceed unity (similar to how a normal
|
||||
// approximation always spills over any boundaries).
|
||||
//
|
||||
// As mentioned previously, the CDF is implemented using the \tau
|
||||
// parameterization of the fourth Jacobi Theta function as
|
||||
//
|
||||
// CDF=θ₄(0|2*x*x*n/pi)
|
||||
//
|
||||
// The PDF is a hand-coded derivative of that function. Actually, there are two
|
||||
// (independent) derivatives, as separate code paths are used for "small x"
|
||||
// (2*x*x*n < pi) and "large x", mirroring the separate code paths in the
|
||||
// Jacobi Theta implementation to achieve fast convergence. Quantiles are
|
||||
// computed using a Newton-Raphson iteration from an initial guess that I
|
||||
// arrived at by trial and error.
|
||||
//
|
||||
// The mean and variance are implemented using simple closed-form expressions.
|
||||
// Skewness and kurtosis use slightly more complicated closed-form expressions
|
||||
// that involve the zeta function. The mode is calculated at run-time by
|
||||
// maximizing the PDF. If you have an analytical solution for the mode, feel
|
||||
// free to plop it in.
|
||||
//
|
||||
// The CDF and PDF could almost certainly be re-implemented and sped up using a
|
||||
// polynomial or rational approximation, since the only meaningful argument is
|
||||
// x * sqrt(n). But that is left as an exercise for the next maintainer.
|
||||
//
|
||||
// In the future, the Pelz-Good approximation could be added. I suggest adding
|
||||
// a second parameter representing the order, e.g.
|
||||
//
|
||||
// kolmogorov_smirnov_dist<>(100) // N=100, order=1
|
||||
// kolmogorov_smirnov_dist<>(100, 1) // N=100, order=1, i.e. Kolmogorov's formula
|
||||
// kolmogorov_smirnov_dist<>(100, 4) // N=100, order=4, i.e. Pelz-Good formula
|
||||
//
|
||||
// The exact distribution could be added to the API with a special order
|
||||
// parameter (e.g. 0 or infinity), or a separate distribution type altogether
|
||||
// (e.g. kolmogorov_smirnov_exact_distribution).
|
||||
//
|
||||
#ifndef BOOST_MATH_DISTRIBUTIONS_KOLMOGOROV_SMIRNOV_HPP
|
||||
#define BOOST_MATH_DISTRIBUTIONS_KOLMOGOROV_SMIRNOV_HPP
|
||||
|
||||
#include <boost/math/distributions/fwd.hpp>
|
||||
#include <boost/math/distributions/complement.hpp>
|
||||
#include <boost/math/distributions/detail/common_error_handling.hpp>
|
||||
#include <boost/math/special_functions/jacobi_theta.hpp>
|
||||
#include <boost/math/tools/tuple.hpp>
|
||||
#include <boost/math/tools/roots.hpp> // Newton-Raphson
|
||||
#include <boost/math/tools/minima.hpp> // For the mode
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
namespace detail {
|
||||
template <class RealType>
|
||||
inline RealType kolmogorov_smirnov_quantile_guess(RealType p) {
|
||||
// Choose a starting point for the Newton-Raphson iteration
|
||||
if (p > 0.9)
|
||||
return RealType(1.8) - 5 * (1 - p);
|
||||
if (p < 0.3)
|
||||
return p + RealType(0.45);
|
||||
return p + RealType(0.3);
|
||||
}
|
||||
|
||||
// d/dk (theta2(0, 1/(2*k*k/M_PI))/sqrt(2*k*k*M_PI))
|
||||
template <class RealType, class Policy>
|
||||
RealType kolmogorov_smirnov_pdf_small_x(RealType x, RealType n, const Policy&) {
|
||||
BOOST_MATH_STD_USING
|
||||
RealType value = RealType(0), delta = RealType(0), last_delta = RealType(0);
|
||||
RealType eps = policies::get_epsilon<RealType, Policy>();
|
||||
int i = 0;
|
||||
RealType pi2 = constants::pi_sqr<RealType>();
|
||||
RealType x2n = x*x*n;
|
||||
if (x2n*x2n == 0.0) {
|
||||
return static_cast<RealType>(0);
|
||||
}
|
||||
while (1) {
|
||||
delta = exp(-RealType(i+0.5)*RealType(i+0.5)*pi2/(2*x2n)) * (RealType(i+0.5)*RealType(i+0.5)*pi2 - x2n);
|
||||
|
||||
if (delta == 0.0)
|
||||
break;
|
||||
|
||||
if (last_delta != 0.0 && fabs(delta/last_delta) < eps)
|
||||
break;
|
||||
|
||||
value += delta + delta;
|
||||
last_delta = delta;
|
||||
i++;
|
||||
}
|
||||
|
||||
return value * sqrt(n) * constants::root_half_pi<RealType>() / (x2n*x2n);
|
||||
}
|
||||
|
||||
// d/dx (theta4(0, 2*x*x*n/M_PI))
|
||||
template <class RealType, class Policy>
|
||||
inline RealType kolmogorov_smirnov_pdf_large_x(RealType x, RealType n, const Policy&) {
|
||||
BOOST_MATH_STD_USING
|
||||
RealType value = RealType(0), delta = RealType(0), last_delta = RealType(0);
|
||||
RealType eps = policies::get_epsilon<RealType, Policy>();
|
||||
int i = 1;
|
||||
while (1) {
|
||||
delta = 8*x*i*i*exp(-2*i*i*x*x*n);
|
||||
|
||||
if (delta == 0.0)
|
||||
break;
|
||||
|
||||
if (last_delta != 0.0 && fabs(delta / last_delta) < eps)
|
||||
break;
|
||||
|
||||
if (i%2 == 0)
|
||||
delta = -delta;
|
||||
|
||||
value += delta;
|
||||
last_delta = delta;
|
||||
i++;
|
||||
}
|
||||
|
||||
return value * n;
|
||||
}
|
||||
|
||||
}; // detail
|
||||
|
||||
template <class RealType = double, class Policy = policies::policy<> >
|
||||
class kolmogorov_smirnov_distribution
|
||||
{
|
||||
public:
|
||||
typedef RealType value_type;
|
||||
typedef Policy policy_type;
|
||||
|
||||
// Constructor
|
||||
kolmogorov_smirnov_distribution( RealType n ) : n_obs_(n)
|
||||
{
|
||||
RealType result;
|
||||
detail::check_df(
|
||||
"boost::math::kolmogorov_smirnov_distribution<%1%>::kolmogorov_smirnov_distribution", n_obs_, &result, Policy());
|
||||
}
|
||||
|
||||
RealType number_of_observations()const
|
||||
{
|
||||
return n_obs_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
RealType n_obs_; // positive integer
|
||||
};
|
||||
|
||||
typedef kolmogorov_smirnov_distribution<double> kolmogorov_k; // Convenience typedef for double version.
|
||||
|
||||
namespace detail {
|
||||
template <class RealType, class Policy>
|
||||
struct kolmogorov_smirnov_quantile_functor
|
||||
{
|
||||
kolmogorov_smirnov_quantile_functor(const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> dist, RealType const& p)
|
||||
: distribution(dist), prob(p)
|
||||
{
|
||||
}
|
||||
|
||||
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
|
||||
{
|
||||
RealType fx = cdf(distribution, x) - prob; // Difference cdf - value - to minimize.
|
||||
RealType dx = pdf(distribution, x); // pdf is 1st derivative.
|
||||
// return both function evaluation difference f(x) and 1st derivative f'(x).
|
||||
return boost::math::make_tuple(fx, dx);
|
||||
}
|
||||
private:
|
||||
const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> distribution;
|
||||
RealType prob;
|
||||
};
|
||||
|
||||
template <class RealType, class Policy>
|
||||
struct kolmogorov_smirnov_complementary_quantile_functor
|
||||
{
|
||||
kolmogorov_smirnov_complementary_quantile_functor(const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> dist, RealType const& p)
|
||||
: distribution(dist), prob(p)
|
||||
{
|
||||
}
|
||||
|
||||
boost::math::tuple<RealType, RealType> operator()(RealType const& x)
|
||||
{
|
||||
RealType fx = cdf(complement(distribution, x)) - prob; // Difference cdf - value - to minimize.
|
||||
RealType dx = -pdf(distribution, x); // pdf is the negative of the derivative of (1-CDF)
|
||||
// return both function evaluation difference f(x) and 1st derivative f'(x).
|
||||
return boost::math::make_tuple(fx, dx);
|
||||
}
|
||||
private:
|
||||
const boost::math::kolmogorov_smirnov_distribution<RealType, Policy> distribution;
|
||||
RealType prob;
|
||||
};
|
||||
|
||||
template <class RealType, class Policy>
|
||||
struct kolmogorov_smirnov_negative_pdf_functor
|
||||
{
|
||||
RealType operator()(RealType const& x) {
|
||||
if (2*x*x < constants::pi<RealType>()) {
|
||||
return -kolmogorov_smirnov_pdf_small_x(x, static_cast<RealType>(1), Policy());
|
||||
}
|
||||
return -kolmogorov_smirnov_pdf_large_x(x, static_cast<RealType>(1), Policy());
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline const std::pair<RealType, RealType> range(const kolmogorov_smirnov_distribution<RealType, Policy>& /*dist*/)
|
||||
{ // Range of permissible values for random variable x.
|
||||
using boost::math::tools::max_value;
|
||||
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
|
||||
}
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline const std::pair<RealType, RealType> support(const kolmogorov_smirnov_distribution<RealType, Policy>& /*dist*/)
|
||||
{ // Range of supported values for random variable x.
|
||||
// This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
|
||||
// In the exact distribution, the upper limit would be 1.
|
||||
using boost::math::tools::max_value;
|
||||
return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
|
||||
}
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType pdf(const kolmogorov_smirnov_distribution<RealType, Policy>& dist, const RealType& x)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
BOOST_MATH_STD_USING // for ADL of std functions.
|
||||
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
static const char* function = "boost::math::pdf(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
|
||||
if(false == detail::check_x_not_NaN(function, x, &error_result, Policy()))
|
||||
return error_result;
|
||||
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
|
||||
if (x < 0 || !(boost::math::isfinite)(x))
|
||||
{
|
||||
return policies::raise_domain_error<RealType>(
|
||||
function, "Kolmogorov-Smirnov parameter was %1%, but must be > 0 !", x, Policy());
|
||||
}
|
||||
|
||||
if (2*x*x*n < constants::pi<RealType>()) {
|
||||
return detail::kolmogorov_smirnov_pdf_small_x(x, n, Policy());
|
||||
}
|
||||
|
||||
return detail::kolmogorov_smirnov_pdf_large_x(x, n, Policy());
|
||||
} // pdf
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType cdf(const kolmogorov_smirnov_distribution<RealType, Policy>& dist, const RealType& x)
|
||||
{
|
||||
BOOST_MATH_STD_USING // for ADL of std function exp.
|
||||
static const char* function = "boost::math::cdf(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
|
||||
RealType error_result;
|
||||
RealType n = dist.number_of_observations();
|
||||
if(false == detail::check_x_not_NaN(function, x, &error_result, Policy()))
|
||||
return error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
if((x < 0) || !(boost::math::isfinite)(x)) {
|
||||
return policies::raise_domain_error<RealType>(
|
||||
function, "Random variable parameter was %1%, but must be between > 0 !", x, Policy());
|
||||
}
|
||||
|
||||
if (x*x*n == 0)
|
||||
return 0;
|
||||
|
||||
return jacobi_theta4tau(RealType(0), 2*x*x*n/constants::pi<RealType>(), Policy());
|
||||
} // cdf
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType cdf(const complemented2_type<kolmogorov_smirnov_distribution<RealType, Policy>, RealType>& c) {
|
||||
BOOST_MATH_STD_USING // for ADL of std function exp.
|
||||
RealType x = c.param;
|
||||
static const char* function = "boost::math::cdf(const complemented2_type<const kolmogorov_smirnov_distribution<%1%>&, %1%>)";
|
||||
RealType error_result;
|
||||
kolmogorov_smirnov_distribution<RealType, Policy> const& dist = c.dist;
|
||||
RealType n = dist.number_of_observations();
|
||||
|
||||
if(false == detail::check_x_not_NaN(function, x, &error_result, Policy()))
|
||||
return error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
|
||||
if((x < 0) || !(boost::math::isfinite)(x))
|
||||
return policies::raise_domain_error<RealType>(
|
||||
function, "Random variable parameter was %1%, but must be between > 0 !", x, Policy());
|
||||
|
||||
if (x*x*n == 0)
|
||||
return 1;
|
||||
|
||||
if (2*x*x*n > constants::pi<RealType>())
|
||||
return -jacobi_theta4m1tau(RealType(0), 2*x*x*n/constants::pi<RealType>(), Policy());
|
||||
|
||||
return RealType(1) - jacobi_theta4tau(RealType(0), 2*x*x*n/constants::pi<RealType>(), Policy());
|
||||
} // cdf (complemented)
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType quantile(const kolmogorov_smirnov_distribution<RealType, Policy>& dist, const RealType& p)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::quantile(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
|
||||
// Error check:
|
||||
RealType error_result;
|
||||
RealType n = dist.number_of_observations();
|
||||
if(false == detail::check_probability(function, p, &error_result, Policy()))
|
||||
return error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
|
||||
RealType k = detail::kolmogorov_smirnov_quantile_guess(p) / sqrt(n);
|
||||
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
|
||||
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
|
||||
|
||||
return tools::newton_raphson_iterate(detail::kolmogorov_smirnov_quantile_functor<RealType, Policy>(dist, p),
|
||||
k, RealType(0), boost::math::tools::max_value<RealType>(), get_digits, m);
|
||||
} // quantile
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType quantile(const complemented2_type<kolmogorov_smirnov_distribution<RealType, Policy>, RealType>& c) {
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::quantile(const kolmogorov_smirnov_distribution<%1%>&, %1%)";
|
||||
kolmogorov_smirnov_distribution<RealType, Policy> const& dist = c.dist;
|
||||
RealType n = dist.number_of_observations();
|
||||
// Error check:
|
||||
RealType error_result;
|
||||
RealType p = c.param;
|
||||
|
||||
if(false == detail::check_probability(function, p, &error_result, Policy()))
|
||||
return error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
|
||||
RealType k = detail::kolmogorov_smirnov_quantile_guess(RealType(1-p)) / sqrt(n);
|
||||
|
||||
const int get_digits = policies::digits<RealType, Policy>();// get digits from policy,
|
||||
boost::uintmax_t m = policies::get_max_root_iterations<Policy>(); // and max iterations.
|
||||
|
||||
return tools::newton_raphson_iterate(
|
||||
detail::kolmogorov_smirnov_complementary_quantile_functor<RealType, Policy>(dist, p),
|
||||
k, RealType(0), boost::math::tools::max_value<RealType>(), get_digits, m);
|
||||
} // quantile (complemented)
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType mode(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::mode(const kolmogorov_smirnov_distribution<%1%>&)";
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
|
||||
std::pair<RealType, RealType> r = boost::math::tools::brent_find_minima(
|
||||
detail::kolmogorov_smirnov_negative_pdf_functor<RealType, Policy>(),
|
||||
static_cast<RealType>(0), static_cast<RealType>(1), policies::digits<RealType, Policy>());
|
||||
return r.first / sqrt(n);
|
||||
}
|
||||
|
||||
// Mean and variance come directly from
|
||||
// https://www.jstatsoft.org/article/view/v008i18 Section 3
|
||||
template <class RealType, class Policy>
|
||||
inline RealType mean(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::mean(const kolmogorov_smirnov_distribution<%1%>&)";
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
return constants::root_half_pi<RealType>() * constants::ln_two<RealType>() / sqrt(n);
|
||||
}
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType variance(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
|
||||
{
|
||||
static const char* function = "boost::math::variance(const kolmogorov_smirnov_distribution<%1%>&)";
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
return (constants::pi_sqr_div_six<RealType>()
|
||||
- constants::pi<RealType>() * constants::ln_two<RealType>() * constants::ln_two<RealType>()) / (2*n);
|
||||
}
|
||||
|
||||
// Skewness and kurtosis come from integrating the PDF
|
||||
// The alternating series pops out a Dirichlet eta function which is related to the zeta function
|
||||
template <class RealType, class Policy>
|
||||
inline RealType skewness(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::skewness(const kolmogorov_smirnov_distribution<%1%>&)";
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
RealType ex3 = RealType(0.5625) * constants::root_half_pi<RealType>() * constants::zeta_three<RealType>() / n / sqrt(n);
|
||||
RealType mean = boost::math::mean(dist);
|
||||
RealType var = boost::math::variance(dist);
|
||||
return (ex3 - 3 * mean * var - mean * mean * mean) / var / sqrt(var);
|
||||
}
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType kurtosis(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
static const char* function = "boost::math::kurtosis(const kolmogorov_smirnov_distribution<%1%>&)";
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
RealType ex4 = 7 * constants::pi_sqr_div_six<RealType>() * constants::pi_sqr_div_six<RealType>() / 20 / n / n;
|
||||
RealType mean = boost::math::mean(dist);
|
||||
RealType var = boost::math::variance(dist);
|
||||
RealType skew = boost::math::skewness(dist);
|
||||
return (ex4 - 4 * mean * skew * var * sqrt(var) - 6 * mean * mean * var - mean * mean * mean * mean) / var / var;
|
||||
}
|
||||
|
||||
template <class RealType, class Policy>
|
||||
inline RealType kurtosis_excess(const kolmogorov_smirnov_distribution<RealType, Policy>& dist)
|
||||
{
|
||||
static const char* function = "boost::math::kurtosis_excess(const kolmogorov_smirnov_distribution<%1%>&)";
|
||||
RealType n = dist.number_of_observations();
|
||||
RealType error_result;
|
||||
if(false == detail::check_df(function, n, &error_result, Policy()))
|
||||
return error_result;
|
||||
return kurtosis(dist) - 3;
|
||||
}
|
||||
}}
|
||||
#endif
|
||||
38
reporting/accuracy/plot_kolmogorov_smirnov_pdf.cpp
Normal file
38
reporting/accuracy/plot_kolmogorov_smirnov_pdf.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright Evan Miller 2020
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/math/tools/ulps_plot.hpp>
|
||||
#include <boost/core/demangle.hpp>
|
||||
#include <boost/math/distributions/kolmogorov_smirnov.hpp>
|
||||
|
||||
using boost::math::tools::ulps_plot;
|
||||
|
||||
int main() {
|
||||
using PreciseReal = long double;
|
||||
using CoarseReal = float;
|
||||
|
||||
boost::math::kolmogorov_smirnov_distribution<CoarseReal> dist_coarse(10);
|
||||
auto pdf_coarse = [&, dist_coarse](CoarseReal x) {
|
||||
return boost::math::pdf(dist_coarse, x);
|
||||
};
|
||||
boost::math::kolmogorov_smirnov_distribution<PreciseReal> dist_precise(10);
|
||||
auto pdf_precise = [&, dist_precise](PreciseReal x) {
|
||||
return boost::math::pdf(dist_precise, x);
|
||||
};
|
||||
|
||||
int samples = 2500;
|
||||
int width = 800;
|
||||
PreciseReal clip = 100;
|
||||
|
||||
std::string filename1 = "kolmogorov_smirnov_pdf_" + boost::core::demangle(typeid(CoarseReal).name()) + ".svg";
|
||||
auto plot1 = ulps_plot<decltype(pdf_precise), PreciseReal, CoarseReal>(pdf_precise, 0.0, 1.0, samples);
|
||||
plot1.clip(clip).width(width);
|
||||
std::string title1 = "Kolmogorov-Smirnov PDF (N=10) ULP plot at " + boost::core::demangle(typeid(CoarseReal).name()) + " precision";
|
||||
plot1.title(title1);
|
||||
plot1.vertical_lines(10);
|
||||
plot1.add_fn(pdf_coarse);
|
||||
plot1.write(filename1);
|
||||
}
|
||||
@@ -436,6 +436,16 @@ int main()
|
||||
|
||||
test_boost_2_param<boost::math::inverse_gaussian_distribution>(inverse_gaussian);
|
||||
|
||||
distribution_tester kolmogorov("KolmogorovSmirnov");
|
||||
kolmogorov.add_test_case(3, one_param_quantile<boost::math::kolmogorov_smirnov_distribution<> >());
|
||||
kolmogorov.add_test_case(20, one_param_quantile<boost::math::kolmogorov_smirnov_distribution<> >());
|
||||
kolmogorov.add_test_case(200, one_param_quantile<boost::math::kolmogorov_smirnov_distribution<> >());
|
||||
kolmogorov.add_test_case(2000, one_param_quantile<boost::math::kolmogorov_smirnov_distribution<> >());
|
||||
kolmogorov.add_test_case(20000, one_param_quantile<boost::math::kolmogorov_smirnov_distribution<> >());
|
||||
kolmogorov.add_test_case(200000, one_param_quantile<boost::math::kolmogorov_smirnov_distribution<> >());
|
||||
|
||||
test_boost_1_param<boost::math::kolmogorov_smirnov_distribution>(kolmogorov);
|
||||
|
||||
distribution_tester laplace("Laplace");
|
||||
laplace.add_test_case(0, 1, two_param_quantile<boost::math::laplace_distribution<> >());
|
||||
laplace.add_test_case(20, 20, two_param_quantile<boost::math::laplace_distribution<> >());
|
||||
|
||||
@@ -630,6 +630,7 @@ test-suite distribution_tests :
|
||||
[ run test_inverse_chi_squared_distribution.cpp ../../test/build//boost_unit_test_framework ]
|
||||
[ run test_inverse_gamma_distribution.cpp ../../test/build//boost_unit_test_framework ]
|
||||
[ run test_inverse_gaussian.cpp ../../test/build//boost_unit_test_framework ]
|
||||
[ run test_kolmogorov_smirnov.cpp ../../test/build//boost_unit_test_framework : : : [ requires cxx11_hdr_initializer_list cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_smart_ptr ] ]
|
||||
[ run test_laplace.cpp ../../test/build//boost_unit_test_framework ]
|
||||
[ run test_inv_hyp.cpp pch ../../test/build//boost_unit_test_framework ]
|
||||
[ run test_logistic_dist.cpp ../../test/build//boost_unit_test_framework ]
|
||||
|
||||
25
test/compile_test/dist_kolmogorov_smirnov_incl_test.cpp
Normal file
25
test/compile_test/dist_kolmogorov_smirnov_incl_test.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright Evan Miller 2020
|
||||
// Use, modification and distribution are subject to 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)
|
||||
//
|
||||
// Basic sanity check that header <boost/math/distributions/kolmogorov_smirnov.hpp>
|
||||
// #includes all the files that it needs to.
|
||||
//
|
||||
#include <boost/math/distributions/kolmogorov_smirnov.hpp>
|
||||
//
|
||||
// Note this header includes no other headers, this is
|
||||
// important if this test is to be meaningful:
|
||||
//
|
||||
#include "test_compile_result.hpp"
|
||||
|
||||
void compile_and_link_test()
|
||||
{
|
||||
TEST_DIST_FUNC(kolmogorov_smirnov)
|
||||
}
|
||||
|
||||
template class boost::math::kolmogorov_smirnov_distribution<float, boost::math::policies::policy<> >;
|
||||
template class boost::math::kolmogorov_smirnov_distribution<double, boost::math::policies::policy<> >;
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
template class boost::math::kolmogorov_smirnov_distribution<long double, boost::math::policies::policy<> >;
|
||||
#endif
|
||||
@@ -33,6 +33,7 @@ void instantiate(RealType)
|
||||
function_requires<DistributionConcept<inverse_chi_squared_distribution<RealType, custom_policy> > >();
|
||||
function_requires<DistributionConcept<inverse_gamma_distribution<RealType, custom_policy> > >();
|
||||
function_requires<DistributionConcept<inverse_gaussian_distribution<RealType, custom_policy> > >();
|
||||
function_requires<DistributionConcept<kolmogorov_smirnov_distribution<RealType, custom_policy> > >();
|
||||
function_requires<DistributionConcept<laplace_distribution<RealType, custom_policy> > >();
|
||||
function_requires<DistributionConcept<logistic_distribution<RealType, custom_policy> > >();
|
||||
function_requires<DistributionConcept<lognormal_distribution<RealType, custom_policy> > >();
|
||||
|
||||
@@ -76,6 +76,7 @@ void instantiate(RealType)
|
||||
function_requires<DistributionConcept<inverse_chi_squared_distribution<RealType> > >();
|
||||
function_requires<DistributionConcept<inverse_gamma_distribution<RealType> > >();
|
||||
function_requires<DistributionConcept<inverse_gaussian_distribution<RealType> > >();
|
||||
function_requires<DistributionConcept<kolmogorov_smirnov_distribution<RealType> > >();
|
||||
function_requires<DistributionConcept<laplace_distribution<RealType> > >();
|
||||
function_requires<DistributionConcept<logistic_distribution<RealType> > >();
|
||||
function_requires<DistributionConcept<lognormal_distribution<RealType> > >();
|
||||
@@ -111,6 +112,7 @@ void instantiate(RealType)
|
||||
function_requires<DistributionConcept<inverse_chi_squared_distribution<RealType, test_policy> > >();
|
||||
function_requires<DistributionConcept<inverse_gamma_distribution<RealType, test_policy> > >();
|
||||
function_requires<DistributionConcept<inverse_gaussian_distribution<RealType, test_policy> > >();
|
||||
function_requires<DistributionConcept<kolmogorov_smirnov_distribution<RealType, test_policy> > >();
|
||||
function_requires<DistributionConcept<laplace_distribution<RealType, test_policy> > >();
|
||||
function_requires<DistributionConcept<logistic_distribution<RealType, test_policy> > >();
|
||||
function_requires<DistributionConcept<lognormal_distribution<RealType, test_policy> > >();
|
||||
|
||||
102
test/test_kolmogorov_smirnov.cpp
Normal file
102
test/test_kolmogorov_smirnov.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright Evan Miller 2020
|
||||
// Use, modification and distribution are subject to 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)
|
||||
//
|
||||
#include <pch_light.hpp>
|
||||
#include <boost/math/concepts/real_concept.hpp>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp> // for test_main
|
||||
#include <boost/test/tools/floating_point_comparison.hpp> // for BOOST_CHECK_CLOSE
|
||||
#include <boost/math/distributions/kolmogorov_smirnov.hpp>
|
||||
#include <boost/math/quadrature/exp_sinh.hpp>
|
||||
|
||||
template <typename RealType> // Any floating-point type RealType.
|
||||
void test_spots(RealType)
|
||||
{
|
||||
using namespace boost::math;
|
||||
// Test quantiles, CDFs, and complements
|
||||
RealType eps = tools::epsilon<RealType>();
|
||||
RealType tol = tools::epsilon<RealType>() * 25;
|
||||
for (int n=10; n<100; n += 10) {
|
||||
kolmogorov_smirnov_distribution<RealType> dist(n);
|
||||
for (int i=0; i<1000; i++) {
|
||||
RealType p = 1.0 * (i+1) / 1001;
|
||||
RealType crit1 = quantile(dist, 1 - p);
|
||||
RealType crit2 = quantile(complement(dist, p));
|
||||
RealType p1 = cdf(dist, crit1);
|
||||
BOOST_CHECK_CLOSE_FRACTION(crit1, crit2, tol);
|
||||
BOOST_CHECK_CLOSE_FRACTION(1 - p, p1, tol);
|
||||
}
|
||||
|
||||
for (int i=0; i<1000; i++) {
|
||||
RealType x = 1.0 * (i+1) / 1001;
|
||||
RealType p = cdf(dist, x);
|
||||
RealType p1 = cdf(complement(dist, x));
|
||||
RealType x1;
|
||||
if (p < 0.5)
|
||||
x1 = quantile(dist, p);
|
||||
else
|
||||
x1 = quantile(complement(dist, p1));
|
||||
if (p > tol && p1 > tol) // skip the extreme tails
|
||||
BOOST_CHECK_CLOSE_FRACTION(x, x1, tol);
|
||||
}
|
||||
}
|
||||
|
||||
kolmogorov_smirnov_distribution<RealType> dist(100);
|
||||
|
||||
// Basics
|
||||
BOOST_CHECK_THROW(pdf(dist, RealType(-1.0)), std::domain_error);
|
||||
BOOST_CHECK_THROW(cdf(dist, RealType(-1.0)), std::domain_error);
|
||||
BOOST_CHECK_THROW(quantile(dist, RealType(-1.0)), std::domain_error);
|
||||
BOOST_CHECK_THROW(quantile(dist, RealType(2.0)), std::domain_error);
|
||||
|
||||
// Confirm mode is at least a local minimum
|
||||
RealType mode = boost::math::mode(dist);
|
||||
|
||||
BOOST_TEST_CHECK(pdf(dist, mode) >= pdf(dist, mode - sqrt(eps)));
|
||||
BOOST_TEST_CHECK(pdf(dist, mode) >= pdf(dist, mode + sqrt(eps)));
|
||||
|
||||
// Test the moments - each one integrates the entire distribution
|
||||
quadrature::exp_sinh<RealType> integrator;
|
||||
|
||||
auto f_one = [&, dist](RealType t) { return pdf(dist, t); };
|
||||
BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f_one, eps), RealType(1), tol);
|
||||
|
||||
RealType mean = boost::math::mean(dist);
|
||||
auto f_mean = [&, dist](RealType t) { return pdf(dist, t) * t; };
|
||||
BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f_mean, eps), mean, tol);
|
||||
|
||||
RealType var = variance(dist);
|
||||
auto f_var = [&, dist, mean](RealType t) { return pdf(dist, t) * (t - mean) * (t - mean); };
|
||||
BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f_var, eps), var, tol);
|
||||
|
||||
RealType skew = skewness(dist);
|
||||
auto f_skew = [&, dist, mean, var](RealType t) { return pdf(dist, t)
|
||||
* (t - mean) * (t - mean) * (t - mean) / var / sqrt(var); };
|
||||
BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f_skew, eps), skew, 10*tol);
|
||||
|
||||
RealType kurt = kurtosis(dist);
|
||||
auto f_kurt= [&, dist, mean, var](RealType t) { return pdf(dist, t)
|
||||
* (t - mean) * (t - mean) * (t - mean) * (t - mean) / var / var; };
|
||||
BOOST_CHECK_CLOSE_FRACTION(integrator.integrate(f_kurt, eps), kurt, 5*tol);
|
||||
|
||||
BOOST_CHECK_CLOSE_FRACTION(kurt, kurtosis_excess(dist) + 3, eps);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
BOOST_MATH_CONTROL_FP;
|
||||
|
||||
// (Parameter value, arbitrarily zero, only communicates the floating point type).
|
||||
test_spots(0.0F); // Test float.
|
||||
test_spots(0.0); // Test double.
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
test_spots(0.0L); // Test long double.
|
||||
#if !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS)
|
||||
test_spots(boost::math::concepts::real_concept(0.)); // Test real concept.
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user