Skip to content

Commit 38e5031

Browse files
committed
family-basin Weyl probe: harden gate + add unit tests + fix DK wording (coderabbit #551)
Three CodeRabbit comments, all valid: 1. Gate false-positive (Major): weyl_ok defaulted to true when no within-basin line existed (is_none_or), and ratio became ∞ when no seam samples existed — either could label a tier HOP-LOCAL without a valid check. Fixed: weyl_ok unwraps to false on no within-line; ratio = 0 (not ∞) on no seam; extracted a single-source tier_supported() that requires has_within && has_straddle. 2. Missing tests (Major): added #[cfg(test)] for containment (incl. zero-field and empty-members edges), dipole balance, and the gate (incl. the missing- evidence cases that would previously false-positive). 3/3 pass. 3. EPIPHANIES DK wording (Minor): line 1 framed Davis-Kahan as the evidence while the body drops the DK bound as evidence. Reworded line 1 to anchor on the containment ratio (the retained gate) and mark DK explicitly as the mechanism, not the numeric evidence. Probe verdict unchanged (HEEL HOP-LOCAL, HIP/LEAF leak); clippy --tests + fmt clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
1 parent 41e75cf commit 38e5031

2 files changed

Lines changed: 71 additions & 8 deletions

File tree

.claude/board/EPIPHANIES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## 2026-06-19 — E-FAMILY-BASIN-WEYL-HOP-LOCAL-AT-CRISP-TIER — REINSTATEMENT (tier-scoped) of `E-OUTAGE-CASCADE-IS-NON-LOCAL`: WITH the family-basin partition, a within-basin perturbation is block-localized (Davis-Kahan) at the **crisp top split**, so multi-hop Weyl IS hop-local there; finer tiers leak. The earlier non-locality was the *un-partitioned* global solve.
1+
## 2026-06-19 — E-FAMILY-BASIN-WEYL-HOP-LOCAL-AT-CRISP-TIER — REINSTATEMENT (tier-scoped) of `E-OUTAGE-CASCADE-IS-NON-LOCAL`: WITH the family-basin partition, a within-basin perturbation is block-localized (95.7 % containment, within/seam ratio 1.54) at the **crisp top split**, so multi-hop Weyl IS hop-local there; finer tiers leak. The earlier non-locality was the *un-partitioned* global solve. (Davis-Kahan is the *mechanism* — see body — NOT the numeric evidence; the gate is the containment ratio.)
22

33
**Status:** FINDING (measured, real ES PyPSA data; probe `perturbation-sim/examples/family_basin_weyl_multihop.rs`). **Tier-scoped reinstatement** of the reach claim that `E-OUTAGE-CASCADE-IS-NON-LOCAL` had corrected. Operator hypothesis: "with family basin it works now with weyl multihop." Confirmed — at the crisp tier only.
44

crates/perturbation-sim/examples/family_basin_weyl_multihop.rs

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ fn dipole(n: usize, s: usize, t: usize) -> Vec<f64> {
6161
p
6262
}
6363

64+
/// The honest HOP-LOCAL gate (single source, used by `main` and tested):
65+
/// block-tight within-basin containment (`wm ≥ 0.70`) AND a real within/seam
66+
/// margin (`ratio ≥ 1.30`) AND a valid within-basin Weyl check — **and the
67+
/// evidence must actually exist** (`has_within && has_straddle`). Missing
68+
/// evidence ⇒ NOT supported (no ∞-ratio or defaulted-true Weyl false positives).
69+
/// No "2×null" gate (the null ≈ 0.5 for coarse tiers and breaks the test); no
70+
/// Davis-Kahan bound (it is vacuous when the eigengap is tiny).
71+
fn tier_supported(
72+
has_within: bool,
73+
has_straddle: bool,
74+
wm: f64,
75+
ratio: f64,
76+
weyl_ok: bool,
77+
) -> bool {
78+
has_within && has_straddle && wm >= 0.70 && ratio >= 1.30 && weyl_ok
79+
}
80+
6481
fn main() {
6582
let args: Vec<String> = std::env::args().collect();
6683
let (bpath, lpath, country) = (
@@ -149,19 +166,25 @@ fn main() {
149166
let theta = eig.pseudo_apply(&dipole(n, e.from, e.to), REL_TOL);
150167
straddle.push(containment(&theta, ma).max(containment(&theta, mb)));
151168
}
152-
// Weyl on a within-basin line trip at this tier.
169+
// Weyl on a within-basin line trip at this tier. No within-basin line ⇒
170+
// `false` (no valid check ⇒ not supported), NOT a defaulted `true`.
153171
let weyl_ok = grid
154172
.edges
155173
.iter()
156174
.position(|e| part(keys[e.from]) == part(keys[e.to]))
157-
.is_none_or(|line| spectral_perturbation(grid, &alive, line).weyl_satisfied);
175+
.map(|line| spectral_perturbation(grid, &alive, line).weyl_satisfied)
176+
.unwrap_or(false);
158177

178+
let (has_within, has_straddle) = (!within.is_empty(), !straddle.is_empty());
159179
let (wm, sm) = (mean(&within), mean(&straddle));
160-
let ratio = if sm > 0.0 { wm / sm } else { f64::INFINITY };
161-
// Honest gate: block-tight containment AND a real within/seam margin.
162-
// (No "2×null" — the null is ~0.5 for coarse tiers and breaks the test;
163-
// no DK bound — it's vacuous when the eigengap is tiny.)
164-
let supported = wm >= 0.70 && ratio >= 1.30 && weyl_ok;
180+
// ratio = 0 (not ∞) when there are no seam samples — a missing seam
181+
// comparison must never pass the margin trivially.
182+
let ratio = if has_straddle && sm > 0.0 {
183+
wm / sm
184+
} else {
185+
0.0
186+
};
187+
let supported = tier_supported(has_within, has_straddle, wm, ratio, weyl_ok);
165188
any_tier_supported |= supported;
166189
println!(
167190
" {name:<5} {:>6} {wm:>10.3} {sm:>10.3} {ratio:>10.2} {:>8} {}",
@@ -195,3 +218,43 @@ fn main() {
195218
ratio, not the absolute, is the hop-boundary test."
196219
);
197220
}
221+
222+
#[cfg(test)]
223+
mod tests {
224+
use super::*;
225+
226+
#[test]
227+
fn containment_basic_and_edges() {
228+
// All energy on members → 1.0.
229+
assert!((containment(&[3.0, 4.0, 0.0], &[0, 1]) - 1.0).abs() < 1e-12);
230+
// θ=[3,4] → energies 9,16; members={0} → 9/25.
231+
assert!((containment(&[3.0, 4.0], &[0]) - 9.0 / 25.0).abs() < 1e-12);
232+
// Zero field → 0.0, never NaN.
233+
assert_eq!(containment(&[0.0, 0.0], &[0]), 0.0);
234+
// Empty members → 0.0.
235+
assert_eq!(containment(&[1.0, 2.0], &[]), 0.0);
236+
}
237+
238+
#[test]
239+
fn dipole_is_balanced() {
240+
let p = dipole(5, 1, 3);
241+
assert_eq!(p, vec![0.0, 1.0, 0.0, -1.0, 0.0]);
242+
assert!(p.iter().sum::<f64>().abs() < 1e-12); // Σp = 0
243+
}
244+
245+
#[test]
246+
fn gate_requires_evidence_not_just_thresholds() {
247+
// Strong, complete evidence → supported.
248+
assert!(tier_supported(true, true, 0.96, 1.54, true));
249+
// Missing seam samples (ratio would have been ∞) → NOT supported.
250+
assert!(!tier_supported(true, false, 0.96, 0.0, true));
251+
// Missing within-basin line / Weyl false → NOT supported.
252+
assert!(!tier_supported(true, true, 0.96, 1.54, false));
253+
// No within evidence → NOT supported.
254+
assert!(!tier_supported(false, true, 0.96, 1.54, true));
255+
// Thin margin (the leaky tiers) → NOT supported.
256+
assert!(!tier_supported(true, true, 0.58, 0.93, true));
257+
// Block-tight but margin just under 1.30 → NOT supported.
258+
assert!(!tier_supported(true, true, 0.95, 1.29, true));
259+
}
260+
}

0 commit comments

Comments
 (0)