Skip to content

Commit 5e1161d

Browse files
committed
feat: 密度曲线右轴新增近似正交概率曲线(单对 P(|ρ|≤t) 与全部 P(max|ρ|≤t))
1 parent b475999 commit 5e1161d

3 files changed

Lines changed: 82 additions & 7 deletions

File tree

web-tools/orthogonal-demo/README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
三条线对比:F^M(beta 幂次,全 K 适用)、Gumbel 渐近、一阶近似 `√(2·lnM/N)`
77
(双侧 `√(2·ln(2M)/N)`)。
88
- **密度曲线**:给定 (N, K),max ρ 的分布密度(F^M 与 Gumbel 渐近两条),叠加单对点乘的
9-
精确 beta 密度作对比;单侧且 K 小时横轴自动扩展到负半轴。
9+
精确 beta 密度作对比;单侧且 K 小时横轴自动扩展到负半轴。右纵轴(概率轴,0~1)叠加
10+
两条**近似正交概率**曲线——把 $|\rho| < t$ 当作"正交":单对 $P(|\rho|\le t)$
11+
(精确,只依赖 N)与 $P(\max|\rho|\le t)$(K 个向量全部两两近似正交的概率,
12+
即 F^M 双侧 CDF)。
1013

1114
理论来源:Cai, Fan, Jiang, *Distributions of Angles in Random Packing on Spheres*,
1215
JMLR 14 (2013), arXiv:1306.0256。
@@ -35,6 +38,8 @@ K 的调节上限取 $N^2$(多项式增长,$\ln K/N = 2\ln N/N$ 全程较小
3538

3639
两张图除 ρ 主轴外均带**角度副轴**(中位数曲线右侧、密度曲线顶部,
3740
θ = arccos(ρ),ρ = 0 对应 90°),tooltip 悬浮也同时显示 ρ 与对应夹角。
41+
密度曲线另有**右侧概率纵轴**(0~1),供两条近似正交概率曲线使用
42+
(tooltip 中该两系列按百分比显示)。
3843

3944
控制区可运行**蒙特卡洛模拟**(设计细节见 `monte-carlo-design.md`):
4045
顺序逐条轨迹流式推进、时间片可中断,密度曲线叠加点积直方图(贴合单对 beta
@@ -80,6 +85,12 @@ $$g(\rho) = \frac{\Gamma(N/2)}{\sqrt{\pi}\,\Gamma\!\left(\frac{N-1}{2}\right)}\,
8085
- 几何意义:$P(\rho > t)$ 就是球面被一个球冠截取的面积占比;因子 $(1-\rho^2)^{(N-3)/2}$
8186
表明 N 越大,质量越向"赤道"($\rho=0$,即 90°)集中——这是"高维近乎正交"的根源。
8287
- 大 N 近似:$\rho \approx \mathcal N(0,\,1/N)$,即标准差 $\sigma \approx 1/\sqrt{N}$。
88+
- **近似正交概率**(密度曲线右轴的红线):把 $|\rho| < t$ 当作"正交",两个随机向量
89+
近似正交的概率有精确式
90+
$$P(|\rho| \le t) = 1 - I_{1-t^2}\!\left(\tfrac{N-1}{2}, \tfrac12\right)
91+
\;\approx\; 2\Phi(t\sqrt N) - 1 \quad (N \gg 1)$$
92+
它只依赖 N:$t = 3\sigma \approx 3/\sqrt N$ 时已 ≈ 99.7%——"高维随机向量近乎正交"
93+
的定量表述(`theory.js``pairAbsDotCDF`)。
8394
- 实现细节(`theory.js`):归一化常数用 Lanczos 近似的 `lgamma` 在对数域计算,
8495
避免 N 很大时 $\Gamma$ 函数溢出。
8596

@@ -103,6 +114,11 @@ f_{\max}(t) = 2M\,\bigl(2F(t)-1\bigr)^{M-1} g(t) \quad\text{(双侧)}$$
103114

104115
分位数通过对 CDF 二分求逆得到(`maxDotQuantileBeta`)。
105116

117+
双侧 CDF 还有一个读法:$P(\max|\rho| \le t)$ 就是 **K 个向量全部两两近似正交**
118+
(所有 $|\rho_{ij}| < t$)的概率——密度曲线右轴的青线("正交"按 $|\rho|$ 口径,
119+
总是双侧,与界面的单双侧开关无关)。它与红线的差距体现取极值的代价:K 越大,
120+
要保证全部 M 对都"正交",阈值 t 就得放得越宽。
121+
106122
**实现细节(大 K 精度)**:峰值处 $1-F(t) \sim 1/M$,K 很大时可小至 $10^{-16}$,
107123
接近 float64 机器精度($\varepsilon \approx 2.2\times10^{-16}$)。此时直接算
108124
`1 - half` 会把 $1-F$ 量化成 $\varepsilon$ 的整数倍,再被 $(M-1)\ln F$ 放大成

web-tools/orthogonal-demo/js/app.js

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
return cache1;
118118
}
119119

120-
const cache2 = { key: '', xLo: 0, xHi: 0, maxDotGumbel: null, maxDotBeta: null, singlePair: null };
120+
const cache2 = { key: '', xLo: 0, xHi: 0, maxDotGumbel: null, maxDotBeta: null, singlePair: null, probPair: null, probMax: null };
121121
function theoryData2() {
122122
const { N, K, twoSided } = state;
123123
const key = N + '|' + K + '|' + twoSided;
@@ -136,13 +136,19 @@
136136
const maxDotGumbel = [];
137137
const maxDotBeta = [];
138138
const singlePair = [];
139+
const probPair = [];
140+
const probMax = [];
139141
for (let i = 0; i <= samples; i++) {
140142
const r = xLo + (i / samples) * (xHi - xLo);
141143
maxDotGumbel.push([r, T.maxDotDensity(r, N, K, twoSided)]);
142144
maxDotBeta.push([r, T.maxDotDensityBeta(r, N, K, twoSided)]);
143145
// 双侧模式下对比基线应为单个 |ρ| 的密度:负半轴折叠到正半轴,高度翻倍
144146
const g = T.pairDotDensity(r, N);
145147
singlePair.push([r, twoSided ? 2 * g : g]);
148+
// 右轴近似正交概率:始终按 |ρ|(双侧)口径,与单双侧开关无关;
149+
// r ≤ 0 时概率为 0(保持网格一致,axis tip 负半段也能显示该系列)
150+
probPair.push([r, r > 0 ? T.pairAbsDotCDF(r, N) : 0]);
151+
probMax.push([r, r > 0 ? T.maxDotCDFBeta(r, N, K, true) : 0]);
146152
}
147153
cache2.key = key;
148154
cache2.xLo = xLo;
@@ -152,6 +158,8 @@
152158
cache2.maxDotGumbel = maxDotGumbel;
153159
cache2.maxDotBeta = maxDotBeta;
154160
cache2.singlePair = singlePair;
161+
cache2.probPair = probPair;
162+
cache2.probMax = probMax;
155163
return cache2;
156164
}
157165

@@ -673,7 +681,7 @@
673681
left: 'center',
674682
textStyle: { fontSize: 14 },
675683
},
676-
// 系列顺序:F^M(蓝)、Gumbel(黄)、单对(绿)
684+
// 系列顺序:F^M(蓝)、Gumbel(黄)、单对(绿);两条正交概率曲线自带显式配色
677685
color: ['#2563eb', '#eab308', '#2ca02c'],
678686
tooltip: {
679687
trigger: 'axis',
@@ -683,15 +691,20 @@
683691
let html =
684692
'ρ = ' + rho.toFixed(4) + '(θ≈' + rhoToDeg(rho).toFixed(2) + '°)';
685693
for (const p of params) {
694+
const v = Number(p.value[1]);
695+
if (!isFinite(v)) continue;
696+
// 正交概率曲线在右轴(0~1),按百分比显示
697+
const isProb = p.seriesName.indexOf('正交概率') >= 0;
686698
html +=
687699
'<br/>' + p.marker + p.seriesName + ':' +
688-
Number(p.value[1]).toFixed(3);
700+
(isProb ? (v * 100).toFixed(2) + '%' : v.toFixed(3));
689701
}
690702
return html;
691703
},
692704
},
693-
legend: { bottom: 0 },
694-
grid: { left: 60, right: 30, top: 45, bottom: 45 },
705+
legend: { bottom: 0, type: 'scroll' },
706+
// 右侧概率轴占位:right 由 30 加宽到 56
707+
grid: { left: 60, right: 56, top: 45, bottom: 45 },
695708
xAxis: [
696709
{
697710
type: 'value',
@@ -724,7 +737,21 @@
724737
},
725738
],
726739
// 轴名放中部:顶部要留给角度副轴的 90° 端点标签
727-
yAxis: { type: 'value', name: '密度', nameLocation: 'middle', nameGap: 40, min: 0 },
740+
yAxis: [
741+
{ type: 'value', name: '密度', nameLocation: 'middle', nameGap: 40, min: 0 },
742+
// 右侧概率轴(0~1):近似正交概率曲线专用
743+
{
744+
type: 'value',
745+
name: '概率',
746+
nameLocation: 'middle',
747+
nameGap: 32,
748+
position: 'right',
749+
min: 0,
750+
max: 1,
751+
splitLine: { show: false },
752+
axisLabel: { formatter: (v) => String(Number(v.toFixed(1))) },
753+
},
754+
],
728755
series: [
729756
{
730757
name: 'max ρ 密度(F^M,beta 幂次)',
@@ -763,6 +790,26 @@
763790
],
764791
},
765792
},
793+
// 近似正交概率曲线(右轴):把 |ρ| < t 当作正交;始终双侧口径,
794+
// 与 UI 单双侧开关无关。数据网格与密度系列一致(负半轴为 0)
795+
{
796+
name: 'P(|ρ|≤t) 单对正交概率',
797+
type: 'line',
798+
showSymbol: false,
799+
yAxisIndex: 1,
800+
color: '#dc2626',
801+
lineStyle: { width: 2 },
802+
data: td.probPair,
803+
},
804+
{
805+
name: 'P(max|ρ|≤t) 全部正交概率',
806+
type: 'line',
807+
showSymbol: false,
808+
yAxisIndex: 1,
809+
color: '#0d9488',
810+
lineStyle: { width: 2 },
811+
data: td.probMax,
812+
},
766813
].concat(mcOv.series),
767814
},
768815
{ notMerge: true }

web-tools/orthogonal-demo/js/theory.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,17 @@
170170
return t >= 0 ? 1 - half : half;
171171
}
172172

173+
/**
174+
* 单对"近似正交"概率:把 |ρ| < t 当作正交,两个随机向量近似正交的概率
175+
* P(|ρ| ≤ t) = 1 − I_{1−t²}((N−1)/2, 1/2)(t ≥ 0;精确,只依赖 N)。
176+
* 大 N 近似 2Φ(t√N) − 1(ρ ≈ N(0,1/N),t = 3/√N 时已 ≈ 99.7%)。
177+
*/
178+
function pairAbsDotCDF(t, N) {
179+
if (t <= 0) return 0;
180+
if (t >= 1) return 1;
181+
return 1 - regIncBeta(1 - t * t, (N - 1) / 2, 0.5);
182+
}
183+
173184
/**
174185
* 单对点乘的对数 CDF:log F(t)。
175186
* t ≥ 0 时用 log1p(−half) 计算 log(1−half):当 half ~ 1/M ~ 1e-16 接近
@@ -250,6 +261,7 @@
250261
centering,
251262
regIncBeta,
252263
pairDotCDF,
264+
pairAbsDotCDF,
253265
pairDotLogCDF,
254266
maxDotLogCDFBeta,
255267
maxDotCDFBeta,

0 commit comments

Comments
 (0)