-
Notifications
You must be signed in to change notification settings - Fork 1.6k
<random>: Fix catastrophic cancellation in piecewise_linear_distribution evaluation
#6350
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7df2ba3
7e25901
f0e99f4
3efc19e
612ad26
de6ac05
5cd7f94
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| RUNALL_INCLUDE ..\usual_matrix.lst |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
|
||
| #include <algorithm> | ||
| #include <cassert> | ||
| #include <cmath> | ||
| #include <cstddef> | ||
| #include <random> | ||
| #include <vector> | ||
|
|
||
| using namespace std; | ||
|
|
||
| int main() { | ||
| constexpr double delta = 1.0e-15; | ||
| static constexpr double b[2] = {0.0, 1.0}; | ||
| static constexpr double p[2] = {1.0 - delta, 1.0 + delta}; | ||
| piecewise_linear_distribution<double> dist(b, b + 2, p); | ||
|
|
||
| mt19937_64 urbg; | ||
|
|
||
| constexpr size_t N = 100'000; | ||
| vector<double> samples(N); | ||
| for (size_t i = 0; i < N; ++i) { | ||
| samples[i] = dist(urbg); | ||
| } | ||
|
|
||
| sort(samples.begin(), samples.end()); | ||
|
|
||
| // Given the empirical CDF for $n$ samples, $F_n(x)$, and a hypothesized CDF $F(x)$, the Kolmogorov-Smirnov | ||
| // statistic is $D_n = \sup_x |F_n(x)-F(x)|$. For large samples, reject the null hypothesis (that the samples come | ||
| // from the distribution) if $\sqrt{n}D_n > K(p)$. | ||
|
|
||
| // Both $F_n$ and $F$ are monotone and $F_n$ is piecewise constant, so the extreme value occurs at one of the | ||
| // discontinuities. | ||
|
|
||
| double ks_stat = 0.0; | ||
| for (size_t i = 0; i < N;) { | ||
| const double x = samples[i]; | ||
| const double ecdf_lo = i / static_cast<double>(N); | ||
|
|
||
| while (++i < N && samples[i] == x) { | ||
| } | ||
|
|
||
| const double ecdf_hi = i / static_cast<double>(N); | ||
| const double cdf = x + x * (x - 1.0) * delta; | ||
|
|
||
| const double max_diff = max(abs(cdf - ecdf_lo), abs(cdf - ecdf_hi)); | ||
| if (max_diff > ks_stat) { | ||
| ks_stat = max_diff; | ||
| } | ||
| } | ||
|
|
||
| constexpr double crit_val = 1.224; // critical value for p = 0.1 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think p=0.1 is too high for a CI test
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear, you're suggesting a lower p value and therefore a higher critical value? So that the test is less sensitive to the seed? FWIW, in the current code the K-S statistic is 0.0016 and the critical value is 0.0039, so it's not exactly on the threshold of failing.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand that correctly, it sounds like no change is required here. |
||
| assert(sqrt(N) * ks_stat < crit_val); | ||
|
|
||
| return 0; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pre-existing: the expression inside
sqrtmay overflow or underflowThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, and I see generally how it could happen (very wide or narrow intervals). But I'm not sure that I'll have time in the foreseeable future to address it and add testing. I'll report back in a week or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is pre-existing, a followup PR would be fine.