Skip to content

Commit bb70b61

Browse files
alexnodelandclaude
andcommitted
docs: rhat-spark — make the collapse visually read (envelope must shrink)
Starts at ±3.4 stationary SDs with thin warmup threads (SD 0.32), a held separated phase, then a smoothstep funnel onto the shared band. Before, starts ±2.2 with SD 0.65 meant the merged band spanned nearly the same pixels as the separated chains — nothing visibly converged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018yo1jdkckG7yQ9eBqLbaDB
1 parent df6c078 commit bb70b61

1 file changed

Lines changed: 17 additions & 14 deletions

File tree

docs/viz/inline.js

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -576,14 +576,15 @@
576576
// the live split-R̂ falls past 1.1 (coral→green) as they merge — or, in
577577
// "bad" mode, stay trapped in three separate modes with R̂ pinned high.
578578
//
579-
// The convergence STORY has to be visible: chains start well separated with
580-
// a tight wiggle (three distinct threads), then relax toward one shared
581-
// stationary Normal(0,1) — mean pulled to 0 while the wiggle grows to full
582-
// scale — merging within roughly the first third of the window, then mixing
583-
// indistinguishably. That relaxation-to-a-shared-target is exactly what an
584-
// AR(1)/Langevin move toward N(0,1) does in expectation (mean decays
585-
// geometrically, variance settles), so we drive the mean-collapse and the
586-
// mixing wiggle with separate rates: a clean fall, a clean green flip.
579+
// The convergence STORY has to be visible, which means the vertical
580+
// ENVELOPE must shrink: three thin threads far apart (dark space between
581+
// them), a held separated phase, then a crisp funnel onto one shared
582+
// stationary Normal(0,1) band. Over-dispersion only reads if the start
583+
// separation is several stationary SDs and the warmup wiggle is tight —
584+
// otherwise "before" and "after" span the same pixels and nothing
585+
// collapses. That relaxation-to-a-shared-target is what an AR(1)/Langevin
586+
// move toward N(0,1) does in expectation (mean decays, variance settles);
587+
// we drive mean-collapse and wiggle-growth on one eased schedule.
587588
//
588589
// The readout R̂ is real split-R̂ (same rhatCore as everywhere) computed on
589590
// the recent (post-warmup) draws — a trailing window — so it falls to ~1.00
@@ -596,16 +597,18 @@
596597
var mode = (root.getAttribute("data-mode") || "good").toLowerCase();
597598
var GOOD = mode !== "bad";
598599
var NCH = 3, MAXN = 140;
599-
var MIXN = Math.round(MAXN / 3); // over-dispersed chains merge by ~here
600+
var SEPN = Math.round(MAXN * 0.22); // fully separated threads until here…
601+
var MIXN = Math.round(MAXN * 0.42); // …then funnel; fully merged by here
600602
var NPHI = 0.2; // mixing autocorrelation (low → clean R̂)
601-
var SD0 = 0.65, SD1 = 1.0; // wiggle grows tight→full as chains merge
603+
var SD0 = 0.32, SD1 = 1.0; // thin warmup threads → full stationary band
602604
var DWIN = 38; // trailing window for the live (post-warmup) R̂
603605
var BPHI = 0.82; // bad-mode within-mode autocorrelation
604606

605-
// smoothstep-eased schedules for the "good" collapse.
607+
// Hold separated, then smoothstep-funnel onto the shared band.
606608
function ease(u) { return u * u * (3 - 2 * u); }
607-
function collapse(k) { return k >= MIXN ? 0 : 1 - ease(k / MIXN); } // 1→0 mean scale
608-
function sdScale(k) { return k >= MIXN ? SD1 : SD0 + (SD1 - SD0) * ease(k / MIXN); }
609+
function phase01(k) { return k <= SEPN ? 0 : k >= MIXN ? 1 : (k - SEPN) / (MIXN - SEPN); }
610+
function collapse(k) { return 1 - ease(phase01(k)); } // 1→0 mean scale
611+
function sdScale(k) { return SD0 + (SD1 - SD0) * ease(phase01(k)); }
609612

610613
mount(root, {
611614
height: 150, hz: 6,
@@ -620,7 +623,7 @@
620623
S.eta = []; S.cur = [];
621624
// good: dispersed starts, one shared Normal(0,1) target → chains mix.
622625
// bad: chains trapped in three separate modes → split-R̂ stuck ≫ 1.1.
623-
S.starts = GOOD ? [-2.2, 0.0, 2.2] : [-1.7, 0.1, 1.7];
626+
S.starts = GOOD ? [-3.4, 0.0, 3.4] : [-1.7, 0.1, 1.7];
624627
S.centers = GOOD ? [0, 0, 0] : [-1.5, 0.0, 1.5];
625628
for (var i = 0; i < NCH; i++) { S.eta[i] = FV.randn(S.rng); S.cur[i] = S.starts[i]; }
626629
}

0 commit comments

Comments
 (0)