Rectangular-uniformity tests: formula and validation ledger#
This ledger covers pysht.uniformity. It follows Yang and Modarres,
Multivariate tests of
uniformity, while correcting the
calibration policy where the paper’s approximation fails the pySHT release
gate.
Domain transformation#
For declared bounds \(a_j<b_j\), both tests map
The implementation evaluates this affine map without overflowing even when a
width such as \(10^{308}-(-10^{308})\) is not representable. Bounds are finite,
have one entry per feature, and are fixed under the null. Interpoint tests allow
closed-boundary observations. The normal-quantile test requires
\(0<U_{ij}<1\); endpoints are rejected before applying ppf.
Tests cover arbitrary per-coordinate affine maps, coordinate permutations, overflowing widths, all four boundary directions, and malformed support vectors.
Interpoint statistics#
For \(n\) observations in \(d\ge2\) dimensions, define
The implementation uses the paper’s exact null moments and variances:
Independent literal calculations cover the special \(d=2\), \(d=3\), and general \(d\ge4\) formulas. Fixed results agree with the statistic values in SHT, but SHT p-values are not used as an oracle.
The published Q3 independence claim is false#
The paper argues that \(Q_1\) and \(Q_2\) become independent and therefore \(Q_3\Rightarrow\chi^2_2\). The overlapping-pair covariance does not vanish. For one uniform coordinate, direct polynomial integration gives
Applying the paper’s own U-statistic overlap counting from its equation (9) therefore gives the exact finite-\(n\) covariance
which is strictly positive. If \(Z_1\) and \(Z_2\) denote the signed standardized
versions of \(\bar\delta\) and \(\bar S\), their correlation is this covariance
divided by the square root of the exact variances in the paper’s equation (5).
For example, it is 0.884087939361298 at \((n,d)=(50,3)\) and converges to
0.920087412456472 as \(n\to\infty\) for \(d=3\).
The paper’s chi-square approximation is consequently materially liberal in a seeded direct null diagnostic. Every cell below is the rejection count out of 20,000 followed by its rate at nominal 0.05:
\(n\) |
\(d\) |
seed |
Q1 count/rate |
Q2 count/rate |
legacy Q3 count/rate |
|---|---|---|---|---|---|
20 |
2 |
20260825 |
962 (0.04810) |
947 (0.04735) |
1,413 (0.07065) |
50 |
2 |
20260825 |
1,021 (0.05105) |
896 (0.04480) |
1,479 (0.07395) |
50 |
3 |
20260825 |
955 (0.04775) |
907 (0.04535) |
1,469 (0.07345) |
50 |
10 |
20260825 |
983 (0.04915) |
964 (0.04820) |
1,310 (0.06550) |
200 |
3 |
20260825 |
1,020 (0.05100) |
997 (0.04985) |
1,559 (0.07795) |
A fresh numpy.random.default_rng(20260825) was reset for each \((n,d)\) row
and generated independent unit-hypercube datasets in replication order. The
production batched component formulas were used, with the legacy
\(\chi^2_2\) survival law applied only for this diagnostic; fixed draws were
checked against the public Q1, Q2, and Q3 statistics. The invalid legacy Q3
law is not exposed by pySHT. The paper’s own table reports 0.067 for Q3 at
\((n,d)=(10,2)\), consistent with this finding.
pySHT retains the published \(Q_3=Q_1+Q_2\) statistic but corrects its optional asymptotic law. Under the joint U-statistic central limit theorem,
where the two chi-square variables are independent and \(\rho\) is the exact finite-\(n\) correlation above. The survival probability is evaluated by an independent polar-angle integral. A separate convolution of the two weighted chi-square densities is the fixed-fixture oracle in the tests.
Two 20,000-replication audits of the corrected approximation gave the following raw counts and rates:
\((n,d)\) |
seed |
0.01 count/rate |
0.05 count/rate |
0.10 count/rate |
gate |
|---|---|---|---|---|---|
(50, 2) |
20260825 |
222 (0.01110) |
971 (0.04855) |
1,894 (0.09470) |
Pass |
(50, 2) |
20260826 |
242 (0.01210) |
980 (0.04900) |
1,936 (0.09680) |
Pass |
(50, 3) |
20260825 |
229 (0.01145) |
955 (0.04775) |
1,887 (0.09435) |
Pass |
(50, 3) |
20260826 |
236 (0.01180) |
962 (0.04810) |
1,913 (0.09565) |
Pass |
(50, 10) |
20260825 |
227 (0.01135) |
936 (0.04680) |
1,967 (0.09835) |
Pass |
(50, 10) |
20260826 |
266 (0.01330) |
1,001 (0.05005) |
1,988 (0.09940) |
Pass |
(200, 3) |
20260825 |
218 (0.01090) |
989 (0.04945) |
1,996 (0.09980) |
Pass |
(200, 3) |
20260826 |
213 (0.01065) |
1,003 (0.05015) |
2,054 (0.10270) |
Pass |
For every scenario and seed, the generator was reset before drawing
unit-hypercube datasets. The batched audit evaluated the literal public Q3
statistic formula and the production correlated-square survival law; fixed
draws were independently matched to the complete public-call path. Rejection
meant pvalue < alpha.
The smaller \((n,d)=(20,2)\) design failed at level 0.10 in both seeds (1,822/20,000 = 0.09110 for seed 20260825 and 1,802/20,000 = 0.09010 for seed 20260826), so pySHT does not advertise the corrected asymptotic law in that regime.
Normal-quantile statistic#
Set \(Z_{ij}=\Phi^{-1}(U_{ij})\). Under the rectangular-uniform null, rows of \(Z\) are exactly \(N_d(0,I)\), so
This is an exact null result, rather than an asymptotic approximation. Two 20,000-sample audits at \((n,d)=(50,3)\) gave:
seed |
0.01 count/rate |
0.05 count/rate |
0.10 count/rate |
|---|---|---|---|
20260817 |
170 (0.00850) |
957 (0.04785) |
1,975 (0.09875) |
20260818 |
196 (0.00980) |
1,017 (0.05085) |
1,988 (0.09940) |
For each seed, a fresh generator produced 20,000 independent unit-hypercube
datasets in order and every replication called public ym_quantile; rejection
meant result.pvalue < alpha. Both satisfy the release gate.
Targeted alternative-power audit#
All public paths were checked against 2,000 samples at \((n,d)=(50,3)\) with
independent Beta(5, 1) coordinates, generated in row order by
numpy.random.default_rng(20260829). For the authoritative Monte Carlo
interpoint calibration, numpy.random.default_rng(20260830) generated a
shared bank of 100,000 unit-hypercube samples. Production batched component
kernels counted upper-tail ties and rejection used
\((b+1)/(100000+1)<0.05\); fixed draws were matched to the complete public Monte
Carlo path. Public ym_quantile was called once per alternative dataset.
Public path |
Rejections/2,000 |
Rate |
|---|---|---|
|
2,000 |
1.0000 |
|
1,711 |
0.8555 |
|
2,000 |
1.0000 |
|
2,000 |
1.0000 |
This is a targeted sensitivity check for a strong skewed alternative, not a uniform power guarantee over every departure from rectangular uniformity.
Legacy mapping#
pySHT |
SHT 0.1.9 |
|---|---|
|
|
|
|