Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ARCHITECTURE.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to TEPP are documented here. The format follows Keep a Chang

## [Unreleased]

- `psychometric_core` recovers the Driver, Oud, and Voelkle (2017, §4.3, pp. 9–10; Eq. 3–5, pp. 4–5; Table 2, p. 12; p. 16; §7.2, pp. 20–21; JSS PDF re-opened 2026-08-23T10:27Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104) scalar later-start lagged covariance of §4.3 predetermined `T0VAR`. Section 4.3 treats the first time point as predetermined when no assumptions are made about the process prior to the initial time point. Free `T0VAR` `p_0` is then estimated. Section 4.3 notes that the process gradually transitions from the initial variances toward the stationary variances, and that the initial time point need not reflect the first measurement occasion (`startoffset`). Equation 3 writes `η(t) = exp(A Δt) η(t0) + … +` the stochastic integral. Equation 4 writes `cov(η_t, η_{t-1}) = A_Δt cov(η_{t-1})`. After a later start `u` the within-subject state variance is `e^{2 a u} p_0 + Q_u`. Lagging that later start over `s` is `e^{a s}(e^{2 a u} p_0 + Q_u)`. Trait variance and `addedTIPREDVAR` are time-invariant between-subject and do not decay with `e^{a s}`. The lagged composition is `trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v`. Form the later-start within-subject variance first, then lag that state, then include the trait, then include the TI extra variance, then add. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. Stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not this map when `p_0` is free. First-occasion lagged covariance `trait + e^{a s} p_0 + (B / a)² v` omits `e^{a s} Q_u` and is not this map when `u > 0`. Later-occasion variance includes `Q_u` without lagging that later state and is not this map. Evolving the later total as if it were all state (`e^{a s}` of `trait + e^{2 a u} p_0 + Q_u + (B / a)² v`) is not this map. As `u → 0+` the composition approaches first-occasion lagged covariance. As `s → 0+` the composition approaches later-occasion variance at `u`. As `s → ∞` with stable `a < 0` the state term vanishes. A zero trait, a zero initial variance, a zero diffusion, and a zero TI contribution is exactly zero. A zero initial variance, a zero diffusion, and a zero TI contribution is exactly the trait. Trait-only variance does not require a stable drift. `a ≥ 0` cannot hold a finite TI extra variance when that contribution is nonzero and fails closed. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. Both intervals must be event time and strictly positive. Equation 5 of that later-start lagged covariance is `λ²(trait + e^{a s}(e^{2 a u} p_0 + Q_u) + (B / a)² v) + ψ`. Independent `ε_t` does not enter. `MANIFESTVAR` is not that later-start lagged observed covariance. The later-start lagged latent covariance is not the later-start lagged observed covariance. First-occasion lagged observed covariance omits `e^{a s} Q_u` and is not that observed covariance when `u > 0`. Predetermined later observed variance includes `Q_u` and `θ` and is not that later-start lagged observed covariance. Stationary lagged observed covariance is not that observed covariance when `p_0` is free. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. Meredith (1993) remains unread (Unpaywall 2026-08-23T10:27Z: `is_oa: false`; title *Measurement Invariance, Factor Analysis and Factorial Invariance*). Mislevy (1991, *Psychometrika, 56*, 177–196) remains unread (Unpaywall 2026-08-23T10:27Z: `is_oa: false`; title *Randomization-Based Inference about Latent Variables from Complex Samples*).
- `psychometric_core` recovers the Driver, Oud, and Voelkle (2017, §4.3, pp. 9–10; Eq. 5, p. 5; Table 2, p. 12; p. 16; §7.2, pp. 20–21; JSS PDF re-opened 2026-08-23T10:03Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104) scalar first-occasion variance of §4.3 predetermined `T0VAR`. Section 4.3 treats the first time point as predetermined when no assumptions are made about the process prior to the initial time point. Free `T0VAR` `p_0` is then estimated. Between-subject `TRAITVAR` and `addedTIPREDVAR` are inherently stationary. The first-occasion composition is `trait + p_0 + (B / a)² v`. Form the free first-occasion state variance first, then include the trait, then include the TI extra variance, then add. Setting `p_0 = −q / (2 a)` recovers the stationary first-occasion map. Stationary first-occasion variance uses `−q / (2 a)` in place of `p_0` and is not this map when `p_0` is free. Free `T0VAR` `p_0` is not this map. The lagged map `trait + e^{a Δt} p_0 + (B / a)² v` decays the state and is not this map. The later-occasion map `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` includes `Q_Δt` and is not this map. As `Δt → 0+` those maps approach this composition. A zero trait, a zero initial variance, and a zero TI contribution is exactly zero. A zero initial variance and a zero TI contribution is exactly the trait. Trait-only variance does not require a stable drift. `a ≥ 0` cannot hold a finite TI extra variance when that contribution is nonzero and fails closed. Equation 5 of that first-occasion variance is `λ²(trait + p_0 + (B / a)² v) + θ + ψ`. `MANIFESTVAR` is not that first-occasion observed variance. The predetermined first-occasion latent variance is not the predetermined first-occasion observed variance. Stationary first-occasion observed variance is not that observed variance when `p_0` is free. Predetermined later observed variance includes `Q_Δt` and is not that first-occasion observed variance. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. Meredith (1993) remains unread (Unpaywall 2026-08-23T10:03Z: `is_oa: false`; title *Measurement Invariance, Factor Analysis and Factorial Invariance*). Mislevy (1991, *Psychometrika, 56*, 177–196) remains unread (Unpaywall 2026-08-23T10:03Z: `is_oa: false`; title *Randomization-Based Inference about Latent Variables from Complex Samples*).
- `psychometric_core` recovers the Driver, Oud, and Voelkle (2017, §4.3, pp. 9–10; Eq. 3–5, pp. 4–5; Table 2, p. 12; p. 16; §7.2, pp. 20–21; JSS PDF re-opened 2026-08-23T09:04Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104) scalar lagged covariance of §4.3 predetermined `T0VAR`. Section 4.3 treats the first time point as predetermined when no assumptions are made about the process prior to the initial time point. Free `T0VAR` `p_0` is then estimated. Equation 3 writes `η(t) = exp(A Δt) η(t0) + …`. Equation 4 writes `cov(η_t, η_{t-1}) = A_Δt cov(η_{t-1})`. Trait variance and `addedTIPREDVAR` are time-invariant between-subject and do not decay with `e^{a Δt}`. The lagged composition is `trait + e^{a Δt} p_0 + (B / a)² v`. Form the lagged free first-occasion covariance first, then include the trait, then include the TI extra variance, then add. Setting `p_0 = −q / (2 a)` recovers the stationary lagged map. Stationary lagged covariance uses `−q / (2 a)` in place of `p_0` and is not this map when `p_0` is free. Evolving `trait + p_0 + (B / a)² v` as if it were all state (`e^{a Δt}` of that total) is not this map. Free `T0VAR` `p_0` is not this map. The later-occasion map `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v` includes `Q_Δt` and is not this map. As `Δt → ∞` with stable `a < 0` the state term vanishes. As `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`. A zero-diffusion carry with `a ≥ 0` is `e^{a Δt} p_0` and is kept. Trait-only variance does not require a stable drift. The interval must be event time and strictly positive. Equation 5 of that lagged covariance is `λ²(trait + e^{a Δt} p_0 + (B / a)² v) + ψ`. Independent `ε_t` does not enter. `MANIFESTVAR` is not that lagged observed covariance. The predetermined lagged latent covariance is not the predetermined lagged observed covariance. Predetermined later observed variance includes `Q_Δt` and `θ` and is not that lagged observed covariance. Stationary lagged observed covariance is not that observed covariance when `p_0` is free. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. Meredith (1993) remains unread (Unpaywall 2026-08-23T09:04Z: `is_oa: false`; title *Measurement Invariance, Factor Analysis and Factorial Invariance*). Mislevy (1991, *Psychometrika, 56*, 177–196) remains unread (Unpaywall 2026-08-23T09:04Z: `is_oa: false`; title *Randomization-Based Inference about Latent Variables from Complex Samples*).
- `psychometric_core` recovers the Driver, Oud, and Voelkle (2017, §4.3, pp. 9–10; Eq. 3–5, pp. 4–5; Table 2, p. 12; p. 16; §7.2, pp. 20–21; JSS PDF re-opened 2026-08-23T05:12Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104) scalar later-occasion variance of §4.3 predetermined `T0VAR`. Section 4.3 treats the first time point as predetermined when no assumptions are made about the process prior to the initial time point. Free `T0VAR` `p_0` is then estimated. The process gradually transitions from the variances of the initial parameters toward those of the parameters when the model is stationary. Equation 3 writes `η(t) = exp(A Δt) η(t0) + … +` the stochastic integral. Equation 4 writes that the integral exhibits covariance `Q_Δt`. The law of total variance on the within-subject state is `e^{2 a Δt} p_0 + Q_Δt`. Trait variance and `addedTIPREDVAR` are time-invariant between-subject and do not enter that process-noise integral. The later-occasion composition is `trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v`. Form the evolved free first-occasion variance first, then include the trait, then include the TI extra variance, then add. Setting `p_0 = −q / (2 a)` recovers the stationary later-occasion map. Stationary later-occasion variance uses `−q / (2 a)` in place of `p_0` and is not this map when `p_0` is free. Evolving `trait + p_0 + (B / a)² v` as if it were all state (`e^{2 a Δt}` of that total plus `Q_Δt`) is not this map. Free `T0VAR` `p_0` is not this map. As `Δt → ∞` with stable `a < 0` the carried `p_0` vanishes and `Q_Δt` approaches `−q / (2 a)`, so the composition approaches contemporaneous stationary `T0VAR`. As `Δt → 0+` the composition approaches `trait + p_0 + (B / a)² v`. Nonzero diffusion with `a ≥ 0` is a growing process and is kept. The interval must be event time and strictly positive. Equation 5 of that later-occasion variance is `λ²(trait + e^{2 a Δt} p_0 + Q_Δt + (B / a)² v) + θ + ψ`. `MANIFESTVAR` is not that later-occasion observed variance. The predetermined later-occasion latent variance is not the predetermined later-occasion observed variance. Stationary later-occasion observed variance is not that observed variance when `p_0` is free. Still not a Kalman filter, not a matrix `expm`, not ESEM estimation, not DSEM, and not ctsem estimation. Meredith (1993) remains unread (Unpaywall 2026-08-23T05:12Z: `is_oa: false`; title *Measurement Invariance, Factor Analysis and Factorial Invariance*). Mislevy (1991, *Psychometrika, 56*, 177–196) remains unread (Unpaywall 2026-08-23T05:12Z: `is_oa: false`; title *Randomization-Based Inference about Latent Variables from Complex Samples*).
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md

Large diffs are not rendered by default.

113 changes: 113 additions & 0 deletions crates/psychometric_core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,43 @@ pub enum PsychometricError {
/// as predetermined first-occasion observed variance. Later
/// variance includes `Q_Δt`.
PredeterminedLaterObservedVarianceIsNotPredeterminedInitialObservedVariance,
/// Driver §4.3 later-start lagged covariance of predetermined
/// `T0VAR` was treated as first-occasion lagged covariance.
/// Later-start lag includes `e^{a s} Q_u`.
PredeterminedLaterLaggedLatentCovarianceIsNotPredeterminedLaggedCovariance,
/// Driver §4.3 later-start lagged covariance of predetermined
/// `T0VAR` was treated as later-occasion variance. Lagged
/// covariance is `e^{a s}` of the later state, not that variance.
PredeterminedLaterLaggedLatentCovarianceIsNotLaterLatentVariance,
/// Driver §4.3 later-start lagged covariance of predetermined
/// `T0VAR` was treated as lagged stationary `T0VAR`. Free `T0VAR`
/// is not `−q / (2 a)`.
PredeterminedLaterLaggedLatentCovarianceIsNotStationaryLaggedCovariance,
/// Driver §4.3 later-start lagged covariance of predetermined
/// `T0VAR` was treated as the decayed later total. Trait variance
/// and `addedTIPREDVAR` do not decay.
PredeterminedLaterLaggedLatentCovarianceIsNotDecayedLaterTotal,
/// Driver §4.3 later-start lagged covariance of predetermined
/// `T0VAR` was treated as later-start lagged observed covariance.
/// Equation 5 maps `cov(y, y_{lag}) = λ²` of that covariance plus
/// `ψ`.
PredeterminedLaterLaggedLatentCovarianceIsNotObservedCovariance,
/// Driver Eq. 5 measurement error was treated as later-start lagged
/// observed covariance of predetermined `T0VAR`. Independent `ε_t`
/// does not enter.
MeasurementErrorIsNotPredeterminedLaterLaggedObservedCovariance,
/// Driver Eq. 5 of first-occasion lagged predetermined `T0VAR` was
/// treated as later-start lagged observed covariance. First-occasion
/// lag omits `e^{a s} Q_u`.
PredeterminedLaggedObservedCovarianceIsNotPredeterminedLaterLaggedObservedCovariance,
/// Driver Eq. 5 of lagged §4.3 stationary `T0VAR` was treated as
/// later-start lagged observed covariance of predetermined `T0VAR`.
/// Stationary lagged covariance uses `−q / (2 a)`, not free `p_0`.
StationaryLaggedObservedCovarianceIsNotPredeterminedLaterLaggedObservedCovariance,
/// Driver Eq. 5 of predetermined later-occasion `T0VAR` was treated
/// as later-start lagged observed covariance. Later variance
/// includes `Q_Δt` and `θ`.
PredeterminedLaterObservedVarianceIsNotPredeterminedLaterLaggedObservedCovariance,
}

impl fmt::Display for PsychometricError {
Expand Down Expand Up @@ -1048,6 +1085,33 @@ impl fmt::Display for PsychometricError {
Self::PredeterminedLaterObservedVarianceIsNotPredeterminedInitialObservedVariance => {
"predetermined later-occasion observed variance is not the predetermined first-occasion observed variance"
}
Self::PredeterminedLaterLaggedLatentCovarianceIsNotPredeterminedLaggedCovariance => {
"predetermined later-start lagged latent covariance is not the predetermined first-occasion lagged latent covariance"
}
Self::PredeterminedLaterLaggedLatentCovarianceIsNotLaterLatentVariance => {
"predetermined later-start lagged latent covariance is not the predetermined later-occasion latent variance"
}
Self::PredeterminedLaterLaggedLatentCovarianceIsNotStationaryLaggedCovariance => {
"predetermined later-start lagged latent covariance is not the stationary lagged latent covariance"
}
Self::PredeterminedLaterLaggedLatentCovarianceIsNotDecayedLaterTotal => {
"predetermined later-start lagged latent covariance is not the decayed later-occasion total"
}
Self::PredeterminedLaterLaggedLatentCovarianceIsNotObservedCovariance => {
"predetermined later-start lagged latent covariance is not the predetermined later-start lagged observed covariance"
}
Self::MeasurementErrorIsNotPredeterminedLaterLaggedObservedCovariance => {
"measurement-error variance is not the predetermined later-start lagged observed covariance"
}
Self::PredeterminedLaggedObservedCovarianceIsNotPredeterminedLaterLaggedObservedCovariance => {
"predetermined first-occasion lagged observed covariance is not the predetermined later-start lagged observed covariance"
}
Self::StationaryLaggedObservedCovarianceIsNotPredeterminedLaterLaggedObservedCovariance => {
"stationary lagged observed covariance is not the predetermined later-start lagged observed covariance"
}
Self::PredeterminedLaterObservedVarianceIsNotPredeterminedLaterLaggedObservedCovariance => {
"predetermined later-occasion observed variance is not the predetermined later-start lagged observed covariance"
}
};
formatter.write_str(message)
}
Expand Down Expand Up @@ -1781,4 +1845,53 @@ mod tests {
"predetermined later-occasion observed variance is not the predetermined first-occasion observed variance"
);
}

#[test]
fn predetermined_later_lagged_covariance_boundary_messages_are_stable() {
assert_eq!(
PsychometricError::PredeterminedLaterLaggedLatentCovarianceIsNotPredeterminedLaggedCovariance
.to_string(),
"predetermined later-start lagged latent covariance is not the predetermined first-occasion lagged latent covariance"
);
assert_eq!(
PsychometricError::PredeterminedLaterLaggedLatentCovarianceIsNotLaterLatentVariance
.to_string(),
"predetermined later-start lagged latent covariance is not the predetermined later-occasion latent variance"
);
assert_eq!(
PsychometricError::PredeterminedLaterLaggedLatentCovarianceIsNotStationaryLaggedCovariance
.to_string(),
"predetermined later-start lagged latent covariance is not the stationary lagged latent covariance"
);
assert_eq!(
PsychometricError::PredeterminedLaterLaggedLatentCovarianceIsNotDecayedLaterTotal
.to_string(),
"predetermined later-start lagged latent covariance is not the decayed later-occasion total"
);
assert_eq!(
PsychometricError::PredeterminedLaterLaggedLatentCovarianceIsNotObservedCovariance
.to_string(),
"predetermined later-start lagged latent covariance is not the predetermined later-start lagged observed covariance"
);
assert_eq!(
PsychometricError::MeasurementErrorIsNotPredeterminedLaterLaggedObservedCovariance
.to_string(),
"measurement-error variance is not the predetermined later-start lagged observed covariance"
);
assert_eq!(
PsychometricError::PredeterminedLaggedObservedCovarianceIsNotPredeterminedLaterLaggedObservedCovariance
.to_string(),
"predetermined first-occasion lagged observed covariance is not the predetermined later-start lagged observed covariance"
);
assert_eq!(
PsychometricError::StationaryLaggedObservedCovarianceIsNotPredeterminedLaterLaggedObservedCovariance
.to_string(),
"stationary lagged observed covariance is not the predetermined later-start lagged observed covariance"
);
assert_eq!(
PsychometricError::PredeterminedLaterObservedVarianceIsNotPredeterminedLaterLaggedObservedCovariance
.to_string(),
"predetermined later-occasion observed variance is not the predetermined later-start lagged observed covariance"
);
}
}
Loading
Loading