//! Pre-registered prediction status computation for the six-domain tau-Epoch framework. //! //! CAB-certified extraction from: //! HeytingLean.Bridge.AlMayahi.TauEpoch.Predictions //! //! Provenance: Lean 4 kernel-verified -> LambdaIR -> MiniC -> C -> Rust use crate::tau_epoch_stats::{spearman, pearson, weighted_mean, binomial_sign_pvalue, linear_regression}; /// Status class for a pre-registered prediction. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PredictionStatus { Confirmed, Directional, NotMet, Pending, } /// H1: Cosmology -- Spearman rho(log10 tau, H0) < -0.5 pub fn h1_status(log_tau: &[f64], h0_values: &[f64]) -> PredictionStatus { let rho = spearman(log_tau, h0_values); if rho < -0.5 { PredictionStatus::Confirmed } else { PredictionStatus::Directional } } /// L2: LHC -- All delta_kappa > 0 with p <= 0.01 pub fn l2_status(delta_kappa: &[f64]) -> PredictionStatus { let n_pos = delta_kappa.iter().filter(|&&x| x > 0.0).count(); let p = binomial_sign_pvalue(n_pos, delta_kappa.len()); if n_pos == delta_kappa.len() && p <= 0.01 { PredictionStatus::Confirmed } else { PredictionStatus::NotMet } } /// N1_NMR: Linear R-squared > 0.90 pub fn n1_nmr_status(field_inv: &[f64], shift: &[f64]) -> PredictionStatus { let (_, _, r_sq) = linear_regression(field_inv, shift); if r_sq > 0.90 { PredictionStatus::Confirmed } else { PredictionStatus::Directional } } /// N1_Neutron: Weighted mean bottle < weighted mean beam pub fn n1_neutron_status( bottle_lifetimes: &[f64], bottle_sigmas: &[f64], beam_lifetimes: &[f64], beam_sigmas: &[f64], ) -> PredictionStatus { let bottle_wm = weighted_mean(bottle_lifetimes, bottle_sigmas); let beam_wm = weighted_mean(beam_lifetimes, beam_sigmas); if bottle_wm < beam_wm { PredictionStatus::Confirmed } else { PredictionStatus::NotMet } } /// P1: Proton -- Pearson r > 0.4 (direction check) pub fn p1_status(tau_proxy: &[f64], radius: &[f64]) -> PredictionStatus { let r = pearson(tau_proxy, radius); if r > 0.4 { PredictionStatus::Confirmed } else if r > 0.0 { PredictionStatus::Directional } else { PredictionStatus::NotMet } } /// M1: Muon g-2 -- Pearson r < -0.4 (direction check) pub fn m1_status(tau_proxy: &[f64], a_mu: &[f64]) -> PredictionStatus { let r = pearson(tau_proxy, a_mu); if r < -0.4 { PredictionStatus::Confirmed } else if r < 0.0 { PredictionStatus::Directional } else { PredictionStatus::NotMet } } /// Verified output: (3, 3, 0, 0) via native_decide in Lean sanity test pub fn status_counts(statuses: &[PredictionStatus]) -> (usize, usize, usize, usize) { let c = statuses.iter().filter(|&&s| s == PredictionStatus::Confirmed).count(); let d = statuses.iter().filter(|&&s| s == PredictionStatus::Directional).count(); let n = statuses.iter().filter(|&&s| s == PredictionStatus::NotMet).count(); let p = statuses.iter().filter(|&&s| s == PredictionStatus::Pending).count(); (c, d, n, p) } #[cfg(test)] mod tests { use super::*; #[test] fn test_l2_all_positive() { let dk = vec![0.02, 0.11, 0.15, 0.04, 0.07, 0.05, 0.03]; assert_eq!(l2_status(&dk), PredictionStatus::Confirmed); } #[test] fn test_l2_mixed_signs() { let dk = vec![0.02, -0.01, 0.05]; assert_eq!(l2_status(&dk), PredictionStatus::NotMet); } }