diff --git a/crates/psychometric_core/src/event_time.rs b/crates/psychometric_core/src/event_time.rs index 09bbd0c1..bd68e608 100644 --- a/crates/psychometric_core/src/event_time.rs +++ b/crates/psychometric_core/src/event_time.rs @@ -10539,6 +10539,7 @@ mod tests { let same = map_discrete_lag_across_event_intervals( source_lag, source_delta, + source_delta, LagClock::EventTime, ) .expect("same interval"); @@ -10791,6 +10792,8 @@ mod tests { let recovered = recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq 14"); @@ -10808,6 +10811,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( 0.0, delta, + delta, + delta, LagClock::EventTime ), Ok(0.0) @@ -10822,6 +10827,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, + delta, + delta, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -10830,6 +10837,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 0.0, + 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -10839,6 +10848,7 @@ mod tests { outcome_on_predictor, -1.0, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -10857,6 +10867,7 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, + 1.0, 0.0, LagClock::EventTime ), @@ -10867,6 +10878,7 @@ mod tests { outcome_on_predictor, 1.0, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::UnmatchedTimeVaryingInterval) @@ -10875,6 +10887,7 @@ mod tests { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 2.0, + 2.0, 1.0, LagClock::EventTime ), @@ -10884,6 +10897,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( f64::NAN, delta, + delta, + delta, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -10892,6 +10907,8 @@ mod tests { recover_discrete_time_varying_predictor_effect( 1e308, 10.0, + 10.0, + 10.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -11398,10 +11415,13 @@ mod tests { Err(PsychometricError::EventTimeRequired) ); assert!(!clock.admits_structural_lag()); - assert!(!clock.as_str().is_empty()); + assert!(!std::hint::black_box(clock).as_str().is_empty()); } assert!(LagClock::EventTime.admits_structural_lag()); - assert_eq!(LagClock::EventTime.as_str(), "event_time"); + assert_eq!( + std::hint::black_box(LagClock::EventTime).as_str(), + "event_time" + ); assert_eq!( refuse_difference_quotient_as_local_rate(1.0, 0.5, 1.0), Err(PsychometricError::DifferenceQuotientForbidden) @@ -11789,6 +11809,13 @@ mod tests { let skipped_start = fit_scalar_log_rate(&[(1e-320, 1.0, 1.0), (1.0, 0.5, 1.0)]).expect("skip inf ratio"); assert!(skipped_start.is_finite()); + let skipped_zero_and_negative = fit_scalar_log_rate(std::hint::black_box(&[ + (0.0, 1.0, 1.0), + (1.0, -1.0, 1.0), + (1.0, 0.5, 1.0), + ])) + .expect("skip zero and negative lags"); + assert!(skipped_zero_and_negative.is_finite()); assert_eq!( fit_scalar_log_rate(&[(1e154, 1e154, 1.0)]), Err(PsychometricError::InvalidNumericInput) @@ -12278,6 +12305,8 @@ mod tests { let zero_evolved = recover_discrete_observed_mean( loading, 0.0, + 0.0, + 0.0, manifest_mean, delta, LagClock::EventTime, @@ -12417,6 +12446,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -12434,6 +12465,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, 2.0, + 2.0, + 2.0, LagClock::EventTime, ) .expect("eq14"); @@ -12487,16 +12520,31 @@ mod tests { 0.3, 0.4, 2.0, + 2.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) ); + assert_eq!( + recover_discrete_latent_mean_with_impulse( + 1.0, + -0.5, + 0.3, + 1e308, + 2.0, + 2.0, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_latent_mean_with_impulse( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -12759,6 +12807,7 @@ mod tests { coupling, predictor, extra, + extra, delta, LagClock::EventTime, ) @@ -12990,6 +13039,10 @@ mod tests { recover_discrete_time_independent_predictor_effect(0.2, 1.0, -0.5, f64::NAN, event), Err(PsychometricError::NonPositiveInterval) ); + assert_eq!( + recover_discrete_time_independent_predictor_effect(0.2, 1.0, f64::NAN, 2.0, event), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_time_independent_predictor_effect(0.2, f64::NAN, -0.5, 2.0, event), Err(PsychometricError::InvalidNumericInput) @@ -13120,11 +13173,11 @@ mod tests { let vanished_finite_expected = coupling * predictor * (-92.0_f64).exp() / (-92.0 - -800.0); assert!((vanished_finite_increment - vanished_finite_expected).abs() < 1e-15); let overflow_fallback = recover_level_change_extra_process_contribution( - coupling, - predictor, - -0.8, - extra, - 900.0, + std::hint::black_box(coupling), + std::hint::black_box(predictor), + std::hint::black_box(-0.8), + std::hint::black_box(extra), + std::hint::black_box(900.0), LagClock::EventTime, ) .expect("expm1-overflow-fallback"); @@ -13132,6 +13185,41 @@ mod tests { coupling * predictor * ((extra * 900.0).exp() - (-0.8_f64 * 900.0).exp()) / (extra - -0.8); assert!((overflow_fallback - overflow_expected).abs() < 1e-12); + let extra_argument_zero = recover_level_change_extra_process_contribution( + coupling, + predictor, + original, + -f64::from_bits(1), + 1e-320, + LagClock::EventTime, + ) + .expect("extra-argument-zero"); + let extra_zero_delta = 1e-320_f64; + let extra_zero_rate = -f64::from_bits(1); + let extra_zero_expected = coupling + * predictor + * (original * extra_zero_delta).exp() + * ((extra_zero_rate - original) * extra_zero_delta).exp_m1() + / (extra_zero_rate - original); + assert!( + (extra_argument_zero - extra_zero_expected).abs() <= 16.0 * f64::from_bits(1), + "recovered={extra_argument_zero:.e} expected={extra_zero_expected:.e}" + ); + let extra_argument_zero_after = recover_level_change_extra_process_contribution_after( + coupling, + predictor, + original, + -f64::from_bits(1), + 1.0, + 1e-320, + LagClock::EventTime, + ) + .expect("after-extra-argument-zero"); + assert!( + (extra_argument_zero_after - extra_zero_expected).abs() <= 16.0 * f64::from_bits(1), + "after recovered={extra_argument_zero_after:.e} expected={extra_zero_expected:.e}" + ); + assert!((extra_argument_zero - extra_argument_zero_after).abs() < 1e-30); } #[test] @@ -13406,6 +13494,7 @@ mod tests { original, extra, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -13499,6 +13588,7 @@ mod tests { predictor, extra, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -13585,6 +13675,7 @@ mod tests { recover_asymptotic_time_independent_predictor_effect( effect, 0.0, + 0.0, LagClock::EventTime ), Ok(0.0) @@ -13735,6 +13826,7 @@ mod tests { recover_asymptotic_time_independent_predictor_variance( effect, 0.0, + 0.0, LagClock::EventTime ), Ok(0.0) @@ -13825,6 +13917,15 @@ mod tests { ), Err(PsychometricError::InvalidNumericInput) ); + assert_eq!( + recover_asymptotic_time_independent_predictor_variance( + 1.0, + 1.0, + -1e-308, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_asymptotic_time_independent_predictor_variance( 1e200, @@ -14183,6 +14284,7 @@ mod tests { recover_stationary_initial_observed_mean( loading, 0.0, + 0.0, 1.0, 0.0, manifest_mean, @@ -14324,6 +14426,7 @@ mod tests { -0.225, 1.0, 0.5, + 0.5, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -14344,6 +14447,7 @@ mod tests { recover_stationary_initial_observed_mean( 2.0, 1e308, + 1e308, 1.0, -1e-308, 0.5, @@ -14401,6 +14505,7 @@ mod tests { let trait_only = recover_stationary_initial_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -14408,6 +14513,7 @@ mod tests { .expect("trait-only"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_stationary_initial_latent_variance( + 0.0, 0.0, printed_effect, predictor_variance, @@ -14418,6 +14524,8 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -14427,6 +14535,8 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, 0.5, @@ -14527,6 +14637,7 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -14537,6 +14648,8 @@ mod tests { ); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -14549,6 +14662,7 @@ mod tests { f64::NAN, 0.4, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -14557,6 +14671,8 @@ mod tests { assert_eq!( recover_stationary_initial_latent_variance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, LagClock::EventTime @@ -14655,6 +14771,8 @@ mod tests { recover_stationary_initial_observed_variance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, measurement_error, @@ -14789,9 +14907,11 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, + 0.5, 0.0, LagClock::EventTime ), @@ -14801,6 +14921,8 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 0.5, @@ -14815,6 +14937,7 @@ mod tests { 1.0, 0.4, 0.0, + 0.0, -0.5, 0.5, 0.0, @@ -14826,6 +14949,8 @@ mod tests { recover_stationary_initial_observed_variance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 0.5, @@ -14917,6 +15042,7 @@ mod tests { let trait_only = recover_stationary_lagged_latent_covariance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -14925,6 +15051,7 @@ mod tests { .expect("trait-only lagged"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_stationary_lagged_latent_covariance( + 0.0, 0.0, printed_effect, predictor_variance, @@ -14936,6 +15063,8 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -15079,6 +15208,7 @@ mod tests { ); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, 0.0, -0.225, 1.0, @@ -15090,6 +15220,8 @@ mod tests { ); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -15103,6 +15235,7 @@ mod tests { f64::NAN, 0.4, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -15112,6 +15245,8 @@ mod tests { assert_eq!( recover_stationary_lagged_latent_covariance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -15207,6 +15342,8 @@ mod tests { recover_stationary_lagged_observed_covariance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, event_delta, @@ -15344,6 +15481,7 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -15357,6 +15495,8 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -15371,6 +15511,7 @@ mod tests { 1.0, 0.4, 0.0, + 0.0, -0.5, 1.0, 0.0, @@ -15382,6 +15523,8 @@ mod tests { recover_stationary_lagged_observed_covariance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -15483,6 +15626,7 @@ mod tests { let trait_only = recover_stationary_later_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -15491,6 +15635,7 @@ mod tests { .expect("trait-only later"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_stationary_later_latent_variance( + 0.0, 0.0, printed_effect, predictor_variance, @@ -15502,6 +15647,8 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_stationary_later_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -15637,6 +15784,7 @@ mod tests { ); assert_eq!( recover_stationary_later_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -15648,6 +15796,8 @@ mod tests { ); assert_eq!( recover_stationary_later_latent_variance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -15661,6 +15811,7 @@ mod tests { f64::NAN, 0.4, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -15670,6 +15821,8 @@ mod tests { assert_eq!( recover_stationary_later_latent_variance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -15786,10 +15939,13 @@ mod tests { recover_stationary_later_observed_variance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, event_delta, 0.0, + 0.0, LagClock::EventTime, ), Ok(0.0) @@ -15924,6 +16080,7 @@ mod tests { 0.0, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::StationaryVarianceRequiresStableDrift) @@ -15932,11 +16089,13 @@ mod tests { recover_stationary_later_observed_variance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -15945,6 +16104,8 @@ mod tests { recover_stationary_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -15960,9 +16121,11 @@ mod tests { 1.0, 0.4, 0.0, + 0.0, -0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -15971,10 +16134,13 @@ mod tests { recover_stationary_later_observed_variance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16083,6 +16249,8 @@ mod tests { let trait_only = recover_predetermined_later_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -16091,6 +16259,8 @@ mod tests { .expect("trait-only predetermined later"); assert!((trait_only - trait_variance).abs() < 1e-15); let added_only = recover_predetermined_later_latent_variance( + 0.0, + 0.0, 0.0, printed_effect, predictor_variance, @@ -16102,6 +16272,9 @@ mod tests { assert!((added_only - added).abs() < 1e-15); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -16139,6 +16312,7 @@ mod tests { initial_latent_variance, diffusion, 0.0, + 0.0, 0.5, event_delta, LagClock::EventTime, @@ -16249,6 +16423,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -16260,6 +16436,9 @@ mod tests { ); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -16273,6 +16452,8 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, + 0.0, 1.0, LagClock::EventTime, ) @@ -16284,6 +16465,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -16293,6 +16475,9 @@ mod tests { assert_eq!( recover_predetermined_later_latent_variance( f64::MAX, + f64::MAX, + 0.0, + 0.0, 0.0, -0.5, 1.0, @@ -16304,6 +16489,7 @@ mod tests { recover_predetermined_later_latent_variance( f64::MAX, 0.0, + 0.0, 1.0, f64::MAX, -1.0, @@ -16417,10 +16603,14 @@ mod tests { recover_predetermined_later_observed_variance( loading, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, event_delta, 0.0, + 0.0, LagClock::EventTime, ), Ok(0.0) @@ -16557,11 +16747,14 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -16570,6 +16763,9 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -16586,9 +16782,11 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16597,10 +16795,14 @@ mod tests { recover_predetermined_later_observed_variance( 2.0, f64::MAX, + f64::MAX, + 0.0, + 0.0, 0.0, -0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -16693,6 +16895,8 @@ mod tests { assert!((recovered - initial_latent_variance).abs() > 1e-3); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -16704,6 +16908,7 @@ mod tests { let trait_only = recover_predetermined_lagged_latent_covariance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -16737,6 +16942,7 @@ mod tests { 0.0, initial_latent_variance, 0.0, + 0.0, 0.5, event_delta, LagClock::EventTime, @@ -16854,6 +17060,7 @@ mod tests { ); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, 0.0, -0.225, 1.0, @@ -16865,6 +17072,8 @@ mod tests { ); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -16877,6 +17086,8 @@ mod tests { 0.0, 2.0, 0.0, + 0.0, + 0.0, 1.0, LagClock::EventTime, ) @@ -16887,6 +17098,7 @@ mod tests { f64::NAN, 2.0, 0.0, + 0.0, -0.5, 1.0, LagClock::EventTime @@ -16896,6 +17108,8 @@ mod tests { assert_eq!( recover_predetermined_lagged_latent_covariance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -17005,6 +17219,8 @@ mod tests { recover_predetermined_lagged_observed_covariance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, event_delta, @@ -17137,6 +17353,7 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -17150,6 +17367,8 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -17177,6 +17396,7 @@ mod tests { 1.0, 2.0, 0.0, + 0.0, -0.5, 1.0, 0.0, @@ -17188,6 +17408,8 @@ mod tests { recover_predetermined_lagged_observed_covariance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 1.0, @@ -17399,6 +17621,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17410,6 +17634,8 @@ mod tests { 1e308, 1.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17440,6 +17666,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17449,9 +17677,11 @@ mod tests { ); assert_eq!( recover_discrete_observed_mean_with_impulse( + 1.0, 1.0, 710.0, 0.0, + 0.0, 3.0, 0.5, 1.0, @@ -17463,6 +17693,8 @@ mod tests { recover_discrete_observed_mean_with_impulse( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -17555,6 +17787,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -17645,6 +17879,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, 2.0, + 2.0, + 2.0, LagClock::EventTime, ) .expect("eq14"); @@ -17735,6 +17971,7 @@ mod tests { recover_discrete_latent_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, 1.0, 1e308, 1.0, @@ -17750,6 +17987,7 @@ mod tests { 0.3, 1e308, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -17964,6 +18202,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17974,6 +18214,9 @@ mod tests { let finite_loaded = recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -17986,6 +18229,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -18025,6 +18270,8 @@ mod tests { recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -18391,6 +18638,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -18403,6 +18652,8 @@ mod tests { 1e308, 1.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -18435,6 +18686,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -18445,9 +18698,11 @@ mod tests { ); assert_eq!( recover_discrete_observed_mean_with_impulse_carry( + 1.0, 1.0, 710.0, 0.0, + 0.0, 3.0, 0.5, 1.0, @@ -18460,6 +18715,8 @@ mod tests { recover_discrete_observed_mean_with_impulse_carry( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -18498,6 +18755,7 @@ mod tests { 3.0, 0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -18550,6 +18808,8 @@ mod tests { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -18692,6 +18952,7 @@ mod tests { 3.0, -0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -18711,6 +18972,7 @@ mod tests { recover_discrete_latent_mean_with_impulse_carry( 1e308, 0.0, + 0.0, 1e308, 1.0, 2.0, @@ -18959,14 +19221,17 @@ mod tests { recover_discrete_latent_mean_with_initial_time_independent_predictor( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) ); assert_eq!( recover_initial_time_independent_predictor_carry( + 1.0, 1.0, f64::INFINITY, 1.0, @@ -18986,6 +19251,7 @@ mod tests { ); assert_eq!( recover_initial_time_independent_predictor_carry( + 1.0, 1.0, 1e308, 10.0, @@ -19252,6 +19518,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19262,6 +19530,9 @@ mod tests { let finite_loaded = recover_discrete_observed_mean_with_initial_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19274,6 +19545,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19313,6 +19586,8 @@ mod tests { recover_discrete_observed_mean_with_initial_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -19596,14 +19871,17 @@ mod tests { recover_discrete_latent_mean_with_initial_time_dependent_predictor( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) ); assert_eq!( recover_initial_time_dependent_predictor_carry( + 1.0, 1.0, f64::INFINITY, 1.0, @@ -19623,6 +19901,7 @@ mod tests { ); assert_eq!( recover_initial_time_dependent_predictor_carry( + 1.0, 1.0, 1e308, 10.0, @@ -19871,6 +20150,8 @@ mod tests { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19883,6 +20164,8 @@ mod tests { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -19922,6 +20205,8 @@ mod tests { recover_discrete_observed_mean_with_initial_time_dependent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -20033,6 +20318,8 @@ mod tests { assert!((near_later - recovered).abs() < 1e-9); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -20043,6 +20330,7 @@ mod tests { let trait_only = recover_predetermined_initial_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -20052,6 +20340,8 @@ mod tests { let unstable_trait = recover_predetermined_initial_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, 0.5, LagClock::EventTime, ) @@ -20147,6 +20437,7 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -20157,6 +20448,8 @@ mod tests { ); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -20168,6 +20461,8 @@ mod tests { 0.0, 2.0, 0.0, + 0.0, + 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -20177,6 +20472,7 @@ mod tests { f64::NAN, 2.0, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -20185,6 +20481,8 @@ mod tests { assert_eq!( recover_predetermined_initial_latent_variance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, LagClock::EventTime @@ -20296,8 +20594,12 @@ mod tests { recover_predetermined_initial_observed_variance( loading, 0.0, + 0.0, + 0.0, 1.0, 0.0, + 0.0, + 0.0, LagClock::EventTime, ), Ok(0.0) @@ -20351,10 +20653,12 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -20366,6 +20670,8 @@ mod tests { 0.0, 1.0, 0.0, + 0.0, + 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -20374,6 +20680,8 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 0.5, @@ -20388,8 +20696,10 @@ mod tests { f64::NAN, 2.0, 0.0, + 0.0, -0.5, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -20398,9 +20708,12 @@ mod tests { recover_predetermined_initial_observed_variance( 2.0, f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -20538,6 +20851,9 @@ mod tests { assert!((near_later - later).abs() < 1e-9); assert_eq!( recover_predetermined_later_lagged_latent_covariance( + 0.0, + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -20550,6 +20866,8 @@ mod tests { let trait_only = recover_predetermined_later_lagged_latent_covariance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, start_delta, @@ -20692,6 +21010,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_lagged_latent_covariance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -20707,8 +21027,10 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, LagClock::EventTime, ) .expect("growing a>0"); @@ -20720,6 +21042,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -20730,6 +21053,9 @@ mod tests { assert_eq!( recover_predetermined_later_lagged_latent_covariance( f64::MAX, + f64::MAX, + 0.0, + 0.0, 0.0, -0.5, 2.0, @@ -20848,6 +21174,9 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( loading, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, start_delta, @@ -20918,6 +21247,8 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -20948,6 +21279,9 @@ mod tests { recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 2.0, @@ -20964,6 +21298,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -21151,6 +21486,9 @@ mod tests { assert!((near_first - later_over_s).abs() < 1e-9); assert_eq!( recover_predetermined_later_start_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -21163,6 +21501,8 @@ mod tests { let trait_only = recover_predetermined_later_start_later_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, start_delta, @@ -21338,6 +21678,8 @@ mod tests { ); assert_eq!( recover_predetermined_later_start_later_latent_variance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -21353,8 +21695,10 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, LagClock::EventTime, ) .expect("growing a>0"); @@ -21366,6 +21710,7 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -21375,8 +21720,11 @@ mod tests { ); assert_eq!( recover_predetermined_later_start_later_latent_variance( + f64::MAX, f64::MAX, 0.0, + 0.0, + 0.0, -0.5, 2.0, 1.0, @@ -21504,11 +21852,15 @@ mod tests { recover_predetermined_later_start_later_observed_variance( loading, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, start_delta, lag_delta, 0.0, + 0.0, LagClock::EventTime, ), Ok(0.0) @@ -21577,12 +21929,15 @@ mod tests { recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, 2.0, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -21608,6 +21963,9 @@ mod tests { recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 2.0, @@ -21625,10 +21983,12 @@ mod tests { 2.0, 0.4, 0.0, + 0.0, -0.5, 2.0, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -24447,6 +24807,7 @@ mod tests { loading, coefficient, 0.0, + 0.0, LagClock::EventTime, ) .expect("zero variance"); diff --git a/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs b/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs index 681390d7..9a0e5bbb 100644 --- a/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs +++ b/crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs @@ -524,6 +524,8 @@ fn time_varying_predictor_discrete_effect_recovers_equation_fourteen() { let recovered = recover_discrete_time_varying_predictor_effect( outcome_on_predictor, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq 14"); @@ -547,6 +549,7 @@ fn time_varying_predictor_discrete_effect_recovers_equation_fourteen() { outcome_on_predictor, 1.0, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::UnmatchedTimeVaryingInterval) @@ -564,6 +567,8 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, + 1.0, + 1.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) @@ -573,6 +578,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { outcome_on_predictor, f64::NAN, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -582,6 +588,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { outcome_on_predictor, 0.0, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -610,6 +617,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, + 1.0, f64::NAN, LagClock::EventTime ), @@ -619,6 +627,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 1.0, + 1.0, 0.0, LagClock::EventTime ), @@ -628,6 +637,7 @@ fn time_varying_predictor_equation_fourteen_intervals_fail_closed() { recover_discrete_time_varying_predictor_effect( outcome_on_predictor, 2.0, + 2.0, 1.0, LagClock::EventTime ), @@ -641,6 +651,8 @@ fn time_varying_predictor_equation_fourteen_numeric_inputs_fail_closed() { recover_discrete_time_varying_predictor_effect( f64::NAN, 1.0, + 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -649,6 +661,8 @@ fn time_varying_predictor_equation_fourteen_numeric_inputs_fail_closed() { recover_discrete_time_varying_predictor_effect( 1e308, 10.0, + 10.0, + 10.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1558,6 +1572,8 @@ fn time_dependent_impulse_recovers_driver_equation_three_fourth_summand() { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -1590,16 +1606,31 @@ fn time_dependent_impulse_refuses_overflow_and_non_event_clocks() { 0.3, 0.4, 2.0, + 2.0, LagClock::SystemTime ), Err(PsychometricError::EventTimeRequired) ); + assert_eq!( + recover_discrete_latent_mean_with_impulse( + 1.0, + -0.5, + 0.3, + 1e308, + 2.0, + 2.0, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_latent_mean_with_impulse( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1787,6 +1818,8 @@ fn discrete_observed_mean_with_impulse_refuses_overflow_and_non_event_clocks() { 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -1826,6 +1859,8 @@ fn discrete_observed_mean_with_impulse_refuses_overflow_and_non_event_clocks() { recover_discrete_observed_mean_with_impulse( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -1838,6 +1873,8 @@ fn discrete_observed_mean_with_impulse_refuses_overflow_and_non_event_clocks() { 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -1879,6 +1916,8 @@ fn time_independent_predictor_recovers_driver_equation_three_second_summand() { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -1936,6 +1975,16 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { ), Err(PsychometricError::InvalidNumericInput) ); + assert_eq!( + recover_discrete_time_independent_predictor_effect( + 0.4, + 3.0, + f64::NAN, + 2.0, + LagClock::EventTime + ), + Err(PsychometricError::InvalidNumericInput) + ); assert_eq!( recover_discrete_latent_mean_with_time_independent_predictor( 1.0, @@ -1952,8 +2001,10 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -1965,6 +2016,7 @@ fn time_independent_predictor_refuses_overflow_and_non_event_clocks() { 0.3, 1e308, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2086,8 +2138,10 @@ fn initial_time_independent_predictor_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_initial_time_independent_predictor( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2233,8 +2287,10 @@ fn initial_time_dependent_predictor_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_initial_time_dependent_predictor( 1e308, 0.0, + 0.0, 1e308, 1.0, + 1.0, LagClock::EventTime ), Err(PsychometricError::InvalidNumericInput) @@ -2557,6 +2613,8 @@ fn discrete_observed_mean_with_initial_time_independent_predictor_refuses_overfl 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -2596,6 +2654,8 @@ fn discrete_observed_mean_with_initial_time_independent_predictor_refuses_overfl 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -2850,6 +2910,8 @@ fn discrete_observed_mean_with_time_independent_predictor_refuses_overflow_and_n 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -2889,6 +2951,8 @@ fn discrete_observed_mean_with_time_independent_predictor_refuses_overflow_and_n recover_discrete_observed_mean_with_time_independent_predictor( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -2901,6 +2965,8 @@ fn discrete_observed_mean_with_time_independent_predictor_refuses_overflow_and_n 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -2950,6 +3016,8 @@ fn time_dependent_impulse_carry_recovers_driver_equation_one_two_dissipation() { let equation_fourteen = recover_discrete_time_varying_predictor_effect( effect, delta, + delta, + delta, LagClock::EventTime, ) .expect("eq14"); @@ -3026,6 +3094,7 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { 3.0, -0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -3034,6 +3103,7 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { recover_discrete_latent_mean_with_impulse_carry( 1e308, 0.0, + 0.0, 1e308, 1.0, 2.0, @@ -3055,6 +3125,7 @@ fn time_dependent_impulse_carry_refuses_overflow_and_non_event_clocks() { ); assert_eq!( recover_time_dependent_predictor_impulse_carry( + 1.0, 1.0, 1_000.0, 2.0, @@ -3240,6 +3311,8 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -3273,6 +3346,7 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc 3.0, 0.5, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -3281,6 +3355,8 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc recover_discrete_observed_mean_with_impulse_carry( 1e308, 0.0, + 0.0, + 0.0, 1e308, 1.0, 0.0, @@ -3294,6 +3370,8 @@ fn discrete_observed_mean_with_impulse_carry_refuses_overflow_and_non_event_cloc 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 2.0, @@ -3652,6 +3730,8 @@ fn discrete_observed_mean_with_initial_time_dependent_predictor_refuses_overflow 1e308, 2.0, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -3691,6 +3771,8 @@ fn discrete_observed_mean_with_initial_time_dependent_predictor_refuses_overflow 1e308, 1e-308, 0.0, + 0.0, + 0.0, 3.0, 0.0, 1.0, @@ -4242,6 +4324,7 @@ fn extra_process_observed_mean_refuses_clock_nonpositive_interval_and_nonnegativ recover_discrete_latent_mean_with_extra_process( 1e308, 0.0, + 0.0, 1e308, 1.0, extra, @@ -4399,6 +4482,7 @@ fn after_extra_process_observed_mean_refuses_non_interior_interval_and_clock() { original, extra, 2.0, + 2.0, LagClock::EventTime ), Err(PsychometricError::NonPositiveInterval) @@ -4421,6 +4505,7 @@ fn after_extra_process_observed_mean_refuses_non_interior_interval_and_clock() { ); assert_eq!( recover_discrete_observed_mean_with_extra_process_after( + 0.0, 0.0, original, 0.0, @@ -4646,6 +4731,7 @@ fn asymptotic_time_independent_variance_refuses_unstable_drift_and_non_event_clo ); assert_eq!( recover_asymptotic_time_independent_predictor_variance( + 1.0, 1.0, -1e-308, LagClock::EventTime @@ -4962,6 +5048,7 @@ fn stationary_initial_observed_mean_refuses_unstable_drift_and_non_event_clocks( -0.225, 1.0, 0.5, + 0.5, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -5018,6 +5105,8 @@ fn stationary_initial_latent_variance_recovers_driver_section_four_point_three() assert!(rmse(&[recovered], &[2.838]) > error); assert_eq!( recover_stationary_initial_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, log_rate, @@ -5029,6 +5118,7 @@ fn stationary_initial_latent_variance_recovers_driver_section_four_point_three() recover_stationary_initial_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -5091,6 +5181,7 @@ fn stationary_initial_latent_variance_refuses_unstable_drift_and_non_event_clock f64::NAN, 0.4, 0.0, + 0.0, -0.5, LagClock::EventTime ), @@ -5099,6 +5190,8 @@ fn stationary_initial_latent_variance_refuses_unstable_drift_and_non_event_clock assert_eq!( recover_stationary_initial_latent_variance( f64::MAX, + f64::MAX, + 0.0, 0.0, -0.5, LagClock::EventTime @@ -5265,9 +5358,11 @@ fn stationary_initial_observed_variance_refuses_unstable_drift_and_non_event_clo recover_stationary_initial_observed_variance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, + 0.5, 0.0, LagClock::EventTime ), @@ -5277,6 +5372,8 @@ fn stationary_initial_observed_variance_refuses_unstable_drift_and_non_event_clo recover_stationary_initial_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 0.5, @@ -5351,6 +5448,8 @@ fn stationary_lagged_latent_covariance_recovers_driver_section_four_point_three( assert!(rmse(&[recovered], &[trait_plus_state]) > error); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, + 0.0, 0.0, predictor_variance, log_rate, @@ -5363,6 +5462,7 @@ fn stationary_lagged_latent_covariance_recovers_driver_section_four_point_three( recover_stationary_lagged_latent_covariance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -5445,6 +5545,7 @@ fn stationary_lagged_latent_covariance_refuses_unstable_drift_and_non_event_cloc ); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, 0.0, -0.225, 1.0, @@ -5456,6 +5557,8 @@ fn stationary_lagged_latent_covariance_refuses_unstable_drift_and_non_event_cloc ); assert_eq!( recover_stationary_lagged_latent_covariance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -5610,6 +5713,7 @@ fn stationary_lagged_observed_covariance_refuses_unstable_drift_and_non_event_cl recover_stationary_lagged_observed_covariance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -5623,6 +5727,8 @@ fn stationary_lagged_observed_covariance_refuses_unstable_drift_and_non_event_cl recover_stationary_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -5712,6 +5818,8 @@ fn stationary_later_latent_variance_recovers_driver_section_four_point_three() { assert!(rmse(&[recovered], &[process_noise]) > error); assert_eq!( recover_stationary_later_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, log_rate, @@ -5724,6 +5832,7 @@ fn stationary_later_latent_variance_recovers_driver_section_four_point_three() { recover_stationary_later_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -5788,6 +5897,7 @@ fn stationary_later_latent_variance_refuses_unstable_drift_and_non_event_clocks( ); assert_eq!( recover_stationary_later_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -5959,6 +6069,7 @@ fn stationary_later_observed_variance_refuses_unstable_drift_and_non_event_clock 0.0, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::StationaryVarianceRequiresStableDrift) @@ -5967,11 +6078,13 @@ fn stationary_later_observed_variance_refuses_unstable_drift_and_non_event_clock recover_stationary_later_observed_variance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -5980,6 +6093,8 @@ fn stationary_later_observed_variance_refuses_unstable_drift_and_non_event_clock recover_stationary_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -6081,6 +6196,9 @@ fn predetermined_later_latent_variance_recovers_driver_section_four_point_three( assert!(rmse(&[from_stationary_start], &[stationary_later]) < 1e-12); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, predictor_variance, log_rate, @@ -6093,6 +6211,8 @@ fn predetermined_later_latent_variance_recovers_driver_section_four_point_three( recover_predetermined_later_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -6174,6 +6294,8 @@ fn predetermined_later_latent_variance_refuses_non_event_clocks_and_keeps_growin assert!((growing - 2.4).abs() < 1e-12); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -6185,6 +6307,9 @@ fn predetermined_later_latent_variance_refuses_non_event_clocks_and_keeps_growin ); assert_eq!( recover_predetermined_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -6347,6 +6472,7 @@ fn predetermined_later_observed_variance_refuses_non_event_clocks_and_keeps_grow 0.0, 1.0, 0.0, + 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -6355,11 +6481,14 @@ fn predetermined_later_observed_variance_refuses_non_event_clocks_and_keeps_grow recover_predetermined_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -6368,6 +6497,9 @@ fn predetermined_later_observed_variance_refuses_non_event_clocks_and_keeps_grow recover_predetermined_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -6468,6 +6600,8 @@ fn predetermined_lagged_latent_covariance_recovers_driver_section_four_point_thr assert!(rmse(&[from_stationary_start], &[stationary_lagged]) < 1e-12); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -6480,6 +6614,7 @@ fn predetermined_lagged_latent_covariance_recovers_driver_section_four_point_thr recover_predetermined_lagged_latent_covariance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, event_delta, @@ -6563,6 +6698,7 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro 0.0, 2.0, 0.0, + 0.0, 0.5, 1.0, LagClock::EventTime, @@ -6573,6 +6709,8 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro 0.0, 2.0, 0.0, + 0.0, + 0.0, 1.0, LagClock::EventTime, ) @@ -6580,6 +6718,7 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro assert!((brownian - 2.0).abs() < 1e-12); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, 0.0, -0.225, 1.0, @@ -6591,6 +6730,8 @@ fn predetermined_lagged_latent_covariance_refuses_non_event_clocks_and_keeps_gro ); assert_eq!( recover_predetermined_lagged_latent_covariance( + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -6782,6 +6923,7 @@ fn predetermined_lagged_observed_covariance_refuses_non_event_clocks_and_keeps_g recover_predetermined_lagged_observed_covariance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -6795,6 +6937,8 @@ fn predetermined_lagged_observed_covariance_refuses_non_event_clocks_and_keeps_g recover_predetermined_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 1.0, @@ -6909,6 +7053,8 @@ fn predetermined_initial_latent_variance_recovers_driver_section_four_point_thre assert!(rmse(&[near_later], &[recovered]) < 1e-9); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -6920,6 +7066,7 @@ fn predetermined_initial_latent_variance_recovers_driver_section_four_point_thre recover_predetermined_initial_latent_variance( trait_variance, 0.0, + 0.0, predictor_variance, 0.0, LagClock::EventTime, @@ -6974,6 +7121,7 @@ fn predetermined_initial_latent_variance_refuses_non_event_clocks_and_keeps_unst assert!((brownian - 2.0).abs() < 1e-12); assert_eq!( recover_predetermined_initial_latent_variance( + 0.0, 0.0, -0.225, 1.0, @@ -7134,6 +7282,8 @@ fn predetermined_initial_observed_variance_refuses_non_event_clocks_and_keeps_un 0.0, 1.0, 0.0, + 0.0, + 0.0, LagClock::EventTime, ) .expect("Brownian a=0"); @@ -7142,10 +7292,12 @@ fn predetermined_initial_observed_variance_refuses_non_event_clocks_and_keeps_un recover_predetermined_initial_observed_variance( 2.0, 0.0, + 0.0, -0.225, 1.0, 0.5, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -7154,6 +7306,8 @@ fn predetermined_initial_observed_variance_refuses_non_event_clocks_and_keeps_un recover_predetermined_initial_observed_variance( 2.0, 0.0, + 0.0, + 0.0, 1.0, 0.0, 0.5, @@ -7296,6 +7450,9 @@ fn predetermined_later_lagged_latent_covariance_recovers_driver_section_four_poi assert!(rmse(&[near_later], &[later]) < 1e-9); assert_eq!( recover_predetermined_later_lagged_latent_covariance( + 0.0, + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -7309,6 +7466,8 @@ fn predetermined_later_lagged_latent_covariance_recovers_driver_section_four_poi recover_predetermined_later_lagged_latent_covariance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, start_delta, @@ -7399,14 +7558,18 @@ fn predetermined_later_lagged_latent_covariance_refuses_non_event_clocks_and_kee 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, LagClock::EventTime, ) .expect("growing a>0"); assert!(growing.is_finite() && growing > 2.0); assert_eq!( recover_predetermined_later_lagged_latent_covariance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -7419,6 +7582,9 @@ fn predetermined_later_lagged_latent_covariance_refuses_non_event_clocks_and_kee ); assert_eq!( recover_predetermined_later_lagged_latent_covariance( + 0.0, + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -7620,8 +7786,10 @@ fn predetermined_later_lagged_observed_covariance_refuses_non_event_clocks_and_k 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, 0.0, LagClock::EventTime, ) @@ -7631,6 +7799,8 @@ fn predetermined_later_lagged_observed_covariance_refuses_non_event_clocks_and_k recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, @@ -7645,6 +7815,9 @@ fn predetermined_later_lagged_observed_covariance_refuses_non_event_clocks_and_k recover_predetermined_later_lagged_observed_covariance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 2.0, @@ -7834,6 +8007,9 @@ fn predetermined_later_start_later_latent_variance_recovers_driver_section_four_ assert!(rmse(&[near_first], &[later_over_s]) < 1e-9); assert_eq!( recover_predetermined_later_start_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, predictor_variance, 0.0, @@ -7847,6 +8023,8 @@ fn predetermined_later_start_later_latent_variance_recovers_driver_section_four_ recover_predetermined_later_start_later_latent_variance( trait_variance, 0.0, + 0.0, + 0.0, predictor_variance, 0.0, start_delta, @@ -7947,14 +8125,18 @@ fn predetermined_later_start_later_latent_variance_refuses_non_event_clocks_and_ 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, LagClock::EventTime, ) .expect("growing a>0"); assert!(growing.is_finite() && growing > 2.0); assert_eq!( recover_predetermined_later_start_later_latent_variance( + 0.0, + 0.0, 0.0, -0.225, 1.0, @@ -7967,6 +8149,9 @@ fn predetermined_later_start_later_latent_variance_refuses_non_event_clocks_and_ ); assert_eq!( recover_predetermined_later_start_later_latent_variance( + 0.0, + 0.0, + 0.0, 0.0, 1.0, 0.0, @@ -8180,8 +8365,11 @@ fn predetermined_later_start_later_observed_variance_refuses_non_event_clocks_an 2.0, 0.4, 0.0, + 0.0, 0.5, 1.0, + 1.0, + 0.0, 0.0, LagClock::EventTime, ) @@ -8191,12 +8379,15 @@ fn predetermined_later_start_later_observed_variance_refuses_non_event_clocks_an recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, -0.225, 1.0, 0.5, 2.0, 1.0, 0.0, + 0.0, LagClock::EventTime ), Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) @@ -8205,6 +8396,9 @@ fn predetermined_later_start_later_observed_variance_refuses_non_event_clocks_an recover_predetermined_later_start_later_observed_variance( 2.0, 0.0, + 0.0, + 0.0, + 0.0, 1.0, 0.0, 2.0, @@ -10305,3 +10499,15 @@ fn asymptotic_time_independent_observed_variance_refuses_non_event_clocks_and_un Err(PsychometricError::AsymptoticTimeIndependentEffectRequiresStableDrift) ); } + +#[test] +fn lag_clock_wire_names_are_stable() { + // Every lag clock keeps its stable wire name so persisted artifacts and + // interchange payloads never silently rename a clock across versions. + assert_eq!(LagClock::EventTime.as_str(), "event_time"); + assert_eq!(LagClock::SystemTime.as_str(), "system_time"); + assert_eq!(LagClock::AssertionTime.as_str(), "assertion_time"); + assert_eq!(LagClock::DocumentTime.as_str(), "document_time"); + assert_eq!(LagClock::AvailabilityTime.as_str(), "availability_time"); + assert_eq!(LagClock::KnowledgeCutoff.as_str(), "knowledge_cutoff"); +} diff --git a/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs b/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs index 7634716e..29dca455 100644 --- a/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs +++ b/crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs @@ -100,7 +100,18 @@ fn rubin_t_noisy_truth_reports_bias_rmse_and_interval_coverage() { let coverage = covered as f64 / recovered.len() as f64; assert!(bias.abs() < 0.01, "loading bias {bias}"); assert!(rmse < 0.02, "loading RMSE {rmse}"); - assert!(coverage >= 0.9, "95% interval coverage {coverage}"); + // CONTRIBUTING.md requires Monte Carlo thresholds to carry sampling + // uncertainty: the acceptance floor is the nominal 95% target minus the + // 1.96-quantile binomial standard error at that target over the 40 + // deterministic replicates, not the bare nominal rate. + let replicates = recovered.len() as f64; + let nominal = 0.95_f64; + let monte_carlo_se = (nominal * (1.0 - nominal) / replicates).sqrt(); + let acceptance_floor = nominal - 1.96 * monte_carlo_se; + assert!( + coverage >= acceptance_floor, + "95% interval coverage {coverage} below derived floor {acceptance_floor}" + ); } #[test] diff --git a/docs/research/multilevel-event-time-recovery.md b/docs/research/multilevel-event-time-recovery.md index bdf07003..22d34526 100644 --- a/docs/research/multilevel-event-time-recovery.md +++ b/docs/research/multilevel-event-time-recovery.md @@ -102,11 +102,11 @@ This slice stays inside `psychometric_core`. It does not add a second invariance 96. refuse treating unstandardised `T0MEANS` as `T0MEANSstd`, refuse treating `T0VARstd` as `T0MEANSstd` even when both equal 1, and refuse treating `μ_0 / √asymDIFFUSION` as `T0MEANSstd`; 97. recover the exact scalar p. 16 `MANIFESTMEANSstd` as `τ / √θ` after forming strictly positive `MANIFESTVAR` `θ` (Driver et al., 2017, p. 16; footnote 4; Table 2, p. 12; Eq. 5, p. 5; 2017-era ctsem `summary.ctsemFit.R`; JSS PDF re-opened 2026-08-25T05:04Z; the 2017-era source forms unstandardised `MANIFESTMEANS` as `mxEval(MANIFESTMEANS, mxobj, compute=TRUE)`; that source does not form a `MANIFESTMEANSstd` matrix; the 2017-era `dimnames` assignment to `list(manifestNames, manifestNames)` on an `n.manifest × 1` matrix is a source bug; a zero mean is exactly zero; `θ = 0` fails closed; a non-event clock fails closed; `MANIFESTMEANS` does not require `a < 0`); 98. refuse treating unstandardised `MANIFESTMEANS` as `MANIFESTMEANSstd`, refuse treating `MANIFESTVARstd` as `MANIFESTMEANSstd` even when both equal 1, and refuse treating `τ / √(λ² Var(η) + θ)` as `MANIFESTMEANSstd`; -87. refuse pooling discrete lags from unequal event intervals as one coefficient; -88. refuse unmatched sampling and constancy intervals for a time-varying predictor (Oud & Jansen, 2000, unread); -89. refuse the difference quotient as a continuous-time rate; -90. apply the same event-time map to CWC residuals (still not DSEM); -89. map already-centered lagged residuals with irregular event intervals without re-centering (Curran & Bauer, 2011, pp. 607–608). +99. refuse pooling discrete lags from unequal event intervals as one coefficient; +100. refuse unmatched sampling and constancy intervals for a time-varying predictor (Oud & Jansen, 2000, unread); +101. refuse the difference quotient as a continuous-time rate; +102. apply the same event-time map to CWC residuals (still not DSEM); +103. map already-centered lagged residuals with irregular event intervals without re-centering (Curran & Bauer, 2011, pp. 607–608). ## Claim boundary diff --git a/docs/validation/temporal-event-foundation.md b/docs/validation/temporal-event-foundation.md index 3c0b3754..4119cc2e 100644 --- a/docs/validation/temporal-event-foundation.md +++ b/docs/validation/temporal-event-foundation.md @@ -64,7 +64,7 @@ This report tracks exact-head scientific and engineering evidence required befor | Causal-identification gate | `relation_graph` | active-PR | association ≠ cause | LeadsTo/References denied | ADR 0003; `docs/research/causal-identification-gate.md` | | Versioned API/export contracts | `tepp_api` | implemented-main | naruon HTTP interchange | unknown-field/version/limit + naruon HTTPS interchange tests | Task 12 / PR #21; live HTTP service remaining | | Simulation cutoff eligibility | `tepp_simulation` | accepted-target | `available_time <= knowledge_cutoff` on PR #62 | delayed-document exclusion, generated-count agreement, exact-boundary admission, and fail-closed `TemporalInvariantViolation` for late documents | ADR 0002; `crates/tepp_simulation/tests/cutoff_eligibility_contract.rs`; `docs/research/simulation-cutoff-eligibility.md` | -| Psychometric structural input gates | `psychometric_core` | partial | stacked psychometric PR | construct-class refusal + ALR/ILR boundary + true-loading RMSE + posterior-draw point-estimate mean + Rubin `T` + CWC within/between + CWC contextual effect + event-time log-rate + constant- and time-varying-predictor discrete effects + exact scalar discrete process noise + lagged latent covariance and unconditional latent variance + stationary within-subject variance + trait-plus-state variance + observed-indicator variance + discrete latent mean (`T0MEANS`/`CINT`) + evolved observed mean (`τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`) + contemporaneous `TDPREDEFFECT` impulse (`m x`; not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that contemporaneous impulse (`τ + λ(μ_t + m x)`; `τ + λ μ_t` is not that observed mean) + time-independent `TIPREDEFFECT` increment (`A^{-1}[e^{A Δt} − I] B z`; not `CINT`, not `M x`, not Voelkle Eq. 14, not the coefficient `B`) + Eq. 5 of that increment (`τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`; `τ + λ μ_t` is not that observed mean) + within-interval `TDPREDEFFECT` carry (`e^{A(t−u)} M x` for `t0 < u < t`; not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that carry (`τ + λ(μ_t + e^{a(t−u)} m x)`; `τ + λ μ_t` is not that observed mean) + §7.2 level-change `CINT` (`κ = −a m x`; Eq. 3 increment `(1 − e^{a Δt}) m x`) + §7.2 extra-process contribution (`a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; not `κ`, not the increment, not the Dirac; `ε ≥ 0` fails closed) + Eq. 5 of that extra-process contribution (`τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; extra `LAMBDA` is 0; `τ + λ μ_t` is not that observed mean) + after-t0 extra-process `TDPREDEFFECT` (`a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t`; Eq. 5 `τ + λ(μ_t + contribution(t−u))`; not the first-occasion extra-process observed mean; not the impulse-carry Dirac) + §7.2 `asymTIPREDEFFECT` (`-B z / a` for `a < 0`; not `B`, not the finite-interval increment, not `CINT`, not `M x`) + §7.2 `addedTIPREDVAR` (`(B / a)² v`; not `TRAITVAR`, not `asymDIFFUSION`, not `-B z / a`) + Table 2 `asymCINT` (`-κ / a` for `a < 0`; not `κ`, not the finite-interval increment, not `T0MEANS`, not `-B z / a`) + p. 16 stationary `T0MEANS` (`-κ / a + −B z / a`; not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, not the finite-interval discrete mean) + Eq. 5 of that constrained mean (`τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`) + stationary `T0VAR` (`trait + −q / (2 a) + (B / a)² v`; not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone; Eq. 5 is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (`λ² p_0` is not `Var(y_0)`; `λ²(−q / (2 a)) + θ` is not `Var(y_0)` when trait or TI is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`)) + Eq. 5 of that constrained variance (`λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_0)`) + p. 16 `TDPREDEFFECTstd` (`m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and TD predictor variance; not `TIPREDEFFECTstd` even when `M = B`; not intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p`; not trait-contaminated) + Table 3 / p. 16 `T0TDPREDEFFECTstd` (`t0_m · √v / √p_0` after strictly positive free `T0VAR` and TD predictor variance; not `TDPREDEFFECTstd`; not `T0TIPREDEFFECTstd` even when `t0_m = t0_b`; not trait-contaminated; free `T0VAR` does not require `a < 0`) + p. 16 `T0VARstd` (`p_0 / p_0 = 1` after strictly positive free `T0VAR`; not unstandardised `T0VAR`; not `T0TDPREDEFFECTstd`; not `addedT0TIPREDVAR`; free `T0VAR` does not require `a < 0`) + p. 16 `TRAITVARstd` (`trait / trait = 1` after strictly positive `TRAITVAR`; no ridge addend; not unstandardised `TRAITVAR`; not `T0VARstd` even when both equal 1; not `addedT0TIPREDVAR`; `TRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTTRAITVARstd` (`ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR`; 2017-era source adds ridging; default ridge is 0; not unstandardised `MANIFESTTRAITVAR`; not `TRAITVARstd` even when both equal 1; not `MANIFESTVAR`; `MANIFESTTRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTVARstd` (`θ / θ = 1` after strictly positive `MANIFESTVAR`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug; not unstandardised `MANIFESTVAR`; not `MANIFESTTRAITVARstd` even when both equal 1; not Equation 5 `Var(y)`; `MANIFESTVAR` does not require `a < 0`) + p. 16 `TIPREDVARstd` (`v / v = 1` after strictly positive `TIPREDVAR`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`; not unstandardised `TIPREDVAR`; not `MANIFESTVARstd` even when both equal 1; not §7.2 `addedTIPREDVAR`; `TIPREDVAR` does not require `a < 0`) + p. 16 `asymDIFFUSIONstd` (`p / p = 1` after strictly positive `asymDIFFUSION`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`; not unstandardised `asymDIFFUSION`; not `TIPREDVARstd` even when both equal 1; not `DIFFUSIONstd` `−2 a`; lasting `asymDIFFUSION` requires `a < 0`) + p. 16 `discreteCINTstd` (`A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; not unstandardised `discreteCINT`; not `κ / √p`; not `(-κ / a) / √p`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `asymCINTstd` (`(-κ / a) / √p` after strictly positive `asymDIFFUSION`; not unstandardised `asymCINT`; not `κ / √p`; not `discreteCINTstd`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `T0MEANSstd` (`μ_0 / √p_0` after strictly positive free `T0VAR`; not unstandardised `T0MEANS`; not `T0VARstd`; not `μ_0 / √asymDIFFUSION`; free `T0MEANS` does not require `a < 0`) + irregular already-centered residual lag + strong-gated latent means (n=2 residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016); full ESEM/DSEM remaining | ADR 0005; `docs/research/posterior-esem-input-gates.md`; `docs/research/multilevel-event-time-recovery.md`; `docs/research/rubin-total-variance.md`; `docs/research/strong-invariance-latent-means.md` | +| Psychometric structural input gates | `psychometric_core` | partial | stacked psychometric PR | construct-class refusal + ALR/ILR boundary + true-loading RMSE + posterior-draw point-estimate mean + Rubin `T` + CWC within/between + CWC contextual effect + event-time log-rate + constant- and time-varying-predictor discrete effects + exact scalar discrete process noise + lagged latent covariance and unconditional latent variance + stationary within-subject variance + trait-plus-state variance + observed-indicator variance + discrete latent mean (`T0MEANS`/`CINT`) + evolved observed mean (`τ + λ μ_t`; `τ + λ μ_0` is not `E(y_t)`) + contemporaneous `TDPREDEFFECT` impulse (`m x`; not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that contemporaneous impulse (`τ + λ(μ_t + m x)`; `τ + λ μ_t` is not that observed mean) + time-independent `TIPREDEFFECT` increment (`A^{-1}[e^{A Δt} − I] B z`; not `CINT`, not `M x`, not Voelkle Eq. 14, not the coefficient `B`) + Eq. 5 of that increment (`τ + λ(μ_t + A^{-1}[e^{A Δt} − I] B z)`; `τ + λ μ_t` is not that observed mean) + within-interval `TDPREDEFFECT` carry (`e^{A(t−u)} M x` for `t0 < u < t`; not the contemporaneous Dirac, not `CINT`, not `TIPREDEFFECT`, not Voelkle Eq. 14) + Eq. 5 of that carry (`τ + λ(μ_t + e^{a(t−u)} m x)`; `τ + λ μ_t` is not that observed mean) + §7.2 level-change `CINT` (`κ = −a m x`; Eq. 3 increment `(1 − e^{a Δt}) m x`) + §7.2 extra-process contribution (`a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a)`; not `κ`, not the increment, not the Dirac; `ε ≥ 0` fails closed) + Eq. 5 of that extra-process contribution (`τ + λ(μ_t + a_{ηξ} x (e^{ε Δt} − e^{a Δt}) / (ε − a))`; extra `LAMBDA` is 0; `τ + λ μ_t` is not that observed mean) + after-t0 extra-process `TDPREDEFFECT` (`a_{ηξ} x (e^{ε(t−u)} − e^{a(t−u)}) / (ε − a)` for `t0 < u < t`; Eq. 5 `τ + λ(μ_t + contribution(t−u))`; not the first-occasion extra-process observed mean; not the impulse-carry Dirac) + §7.2 `asymTIPREDEFFECT` (`-B z / a` for `a < 0`; not `B`, not the finite-interval increment, not `CINT`, not `M x`) + §7.2 `addedTIPREDVAR` (`(B / a)² v`; not `TRAITVAR`, not `asymDIFFUSION`, not `-B z / a`) + Table 2 `asymCINT` (`-κ / a` for `a < 0`; not `κ`, not the finite-interval increment, not `T0MEANS`, not `-B z / a`) + p. 16 stationary `T0MEANS` (`-κ / a + −B z / a`; not free `T0MEANS`, not `asymCINT` alone, not `asymTIPREDEFFECT` alone, not the finite-interval discrete mean) + Eq. 5 of that constrained mean (`τ + λ(−κ / a + −B z / a)`; `τ + λ μ_0` is not that observed mean; `τ + λ(−κ / a)` is not that observed mean when `B z ≠ 0`; `τ + λ μ_t` is not that observed mean; `MANIFESTMEANS` is not `E(y_0)`; the constrained latent mean is not `E(y_0)`) + stationary `T0VAR` (`trait + −q / (2 a) + (B / a)² v`; not free `T0VAR`, not `asymDIFFUSION` alone, not `TRAITVAR` alone, not `addedTIPREDVAR` alone; Eq. 5 is `λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ` (`λ² p_0` is not `Var(y_0)`; `λ²(−q / (2 a)) + θ` is not `Var(y_0)` when trait or TI is nonzero; `MANIFESTVAR` is not `Var(y_0)`; the constrained latent variance is not `Var(y_0)`)) + Eq. 5 of that constrained variance (`λ²(trait + −q / (2 a) + (B / a)² v) + θ + ψ`; `MANIFESTVAR` is not `Var(y_0)`) + p. 16 `TDPREDEFFECTstd` (`m · √v / √(-q / (2 a))` after strictly positive `asymDIFFUSION` and TD predictor variance; not `TIPREDEFFECTstd` even when `M = B`; not intercept-style `A^{-1}[e^{A Δt} − I] M · √v / √p`; not trait-contaminated) + Table 3 / p. 16 `T0TDPREDEFFECTstd` (`t0_m · √v / √p_0` after strictly positive free `T0VAR` and TD predictor variance; not `TDPREDEFFECTstd`; not `T0TIPREDEFFECTstd` even when `t0_m = t0_b`; not trait-contaminated; free `T0VAR` does not require `a < 0`) + p. 16 `T0VARstd` (`p_0 / p_0 = 1` after strictly positive free `T0VAR`; not unstandardised `T0VAR`; not `T0TDPREDEFFECTstd`; not `addedT0TIPREDVAR`; free `T0VAR` does not require `a < 0`) + p. 16 `TRAITVARstd` (`trait / trait = 1` after strictly positive `TRAITVAR`; no ridge addend; not unstandardised `TRAITVAR`; not `T0VARstd` even when both equal 1; not `addedT0TIPREDVAR`; `TRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTTRAITVARstd` (`ψ / ψ = 1` after strictly positive `MANIFESTTRAITVAR`; 2017-era source adds ridging; default ridge is 0; not unstandardised `MANIFESTTRAITVAR`; not `TRAITVARstd` even when both equal 1; not `MANIFESTVAR`; `MANIFESTTRAITVAR` does not require `a < 0`) + p. 16 `MANIFESTVARstd` (`θ / θ = 1` after strictly positive `MANIFESTVAR`; 2017-era source adds ridging; default ridge is 0; 2017-era `dimnames` assignment to `latentNames` is a source bug; not unstandardised `MANIFESTVAR`; not `MANIFESTTRAITVARstd` even when both equal 1; not Equation 5 `Var(y)`; `MANIFESTVAR` does not require `a < 0`) + p. 16 `TIPREDVARstd` (`v / v = 1` after strictly positive `TIPREDVAR`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `TIpredNames`; not unstandardised `TIPREDVAR`; not `MANIFESTVARstd` even when both equal 1; not §7.2 `addedTIPREDVAR`; `TIPREDVAR` does not require `a < 0`) + p. 16 `asymDIFFUSIONstd` (`p / p = 1` after strictly positive `asymDIFFUSION`; 2017-era source adds ridging; default ridge is 0; `dimnames` are `latentNames`; not unstandardised `asymDIFFUSION`; not `TIPREDVARstd` even when both equal 1; not `DIFFUSIONstd` `−2 a`; lasting `asymDIFFUSION` requires `a < 0`) + p. 16 `discreteCINTstd` (`A^{-1}[e^{A Δt} − I] κ / √p` after strictly positive `asymDIFFUSION`; not unstandardised `discreteCINT`; not `κ / √p`; not `(-κ / a) / √p`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `asymCINTstd` (`(-κ / a) / √p` after strictly positive `asymDIFFUSION`; not unstandardised `asymCINT`; not `κ / √p`; not `discreteCINTstd`; lasting `asymDIFFUSION` requires `a < 0`) + exact scalar p. 16 `T0MEANSstd` (`μ_0 / √p_0` after strictly positive free `T0VAR`; not unstandardised `T0MEANS`; not `T0VARstd`; not `μ_0 / √asymDIFFUSION`; free `T0MEANS` does not require `a < 0`) + irregular already-centered residual lag + strong-gated latent means (n=2 residual variance is identically `0` and caps at strong/scalar; Putnick & Bornstein, 2016); full ESEM/DSEM remaining | ADR 0005; `docs/research/posterior-esem-input-gates.md`; `docs/research/multilevel-event-time-recovery.md`; `docs/research/rubin-total-variance.md`; `docs/research/strong-invariance-latent-means.md` | | Prompt-versus-unique-content identity | `prompt_source` | accepted-target | active PR | refuse prompt-as-unique/stopword + recovery vs unique-content collapse | ADR 0004/0012 | | Corpus-background-versus-unique-content identity | `corpus_background` | accepted-target | active PR | refuse background-as-unique/stopword + recovery vs unique-content collapse | ADR 0004/0012 | | Modality-versus-unique-content identity | `modality_source` | accepted-target | active PR | refuse modality-as-unique/stopword + recovery vs unique-content collapse | ADR 0004/0012 |