Skip to content

feat(psychometric): recover Eq. 5 of 2017-era three-term asymTOTALVAR on main - #345

Draft
seonghobae wants to merge 2 commits into
mainfrom
agent/psychometric-eq5-asym-total-var-on-main
Draft

feat(psychometric): recover Eq. 5 of 2017-era three-term asymTOTALVAR on main#345
seonghobae wants to merge 2 commits into
mainfrom
agent/psychometric-eq5-asym-total-var-on-main

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Summary

Independent-on-main scalar recovery of Equation 5 of the 2017-era commented three-term asymTOTALVAR map from cran/ctsem 2.5.0 summary.ctsemFit.R.

Driver, Oud, and Voelkle (2017, Eq. 1, p. 4; Eq. 4–5, p. 5; Table 2, p. 12; §4.3, p. 9; §7.2, pp. 20–21; p. 16; JSS PDF re-opened 2026-08-31T05:20Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104) write dη = (Aη + b + Mχ) dt + G dW and y_i(t) = τ + Λ η_i(t) + ε_i(t) with ε ~ N(0, Θ) when Ψ_τ = 0. Page 16 names asymDIFFUSION -q / (2 a). Section 4.3 adds a stable trait whose process-mean variance is trait / a². Section 7.2 names addedTIPREDVAR (B / a)² v. The 2017-era source comments (not in the active outlist):

asymTRAITVAR <- solve(DRIFT) %*% TRAITVAR %*% t(solve(DRIFT))
asymTOTALVAR <- asymDIFFUSION + asymTRAITVAR
asymTOTALVAR <- asymTOTALVAR + addedTIPREDVAR

The unstandardised three-term total is -q / (2 a) + trait / a² + (B / a)² v. Equation 5 of that latent total is λ² of it plus θ.

Form the three-term total inline (do not import unpublished #330 recover_asymptotic_trait_variance or #340/#341 asymTOTALVAR helpers). Do not export the unstandardised total. ψ = 0 this slice.

Contract

  • Event clock only (EventTimeRequired otherwise).
  • Zero loading is exactly θ.
  • All-zero latent contributions return θ even if a ≥ 0.
  • a ≥ 0 with any nonzero contribution fails closed (AsymptoticTotalObservedVarianceRequiresStableDrift).
  • Negative / non-finite variance fails closed.
  • Overflow of 1 / a, of the three-term sum, or of λ² of that total fails closed.
  • Numeric: a = −0.5, trait = 1, q = 0.4, B = 0.5, v = 1, λ = 2, θ = 0.3 recovers 21.9.

Refusals

  • Unstandardised three-term asymTOTALVAR 5.4 is not Var(y).
  • Eq. 5 of §4.3 stationary T0VAR λ²(trait + −q / (2 a) + (B / a)² v) + θ recovers 9.9 on the same numbers (TRAITVAR is not trait / a²) and remains a distinct named quantity.
  • Table 2 MANIFESTVAR θ is not Var(y).

Do not duplicate queued #330 (trait / a²), #340 (two-term p + trait / a²), #341 (three-term unstandardised total), #342 (asymTOTALVARstd), or #343 (discreteTRAITVAR).

Meredith (1993) remains unread (Springer/Cambridge paywalled; Unpaywall historically is_oa: false). Mislevy (1991, Psychometrika, 56, 177–196, DOI 10.1007/bf02294457) remains unread on the same terms.

This is not a Kalman filter, not a matrix expm, not ESEM estimation, not DSEM, and not ctsem estimation.

Test plan

  • cargo fmt -p psychometric_core
  • cargo clippy -p psychometric_core --all-targets -- -D warnings
  • cargo test -p psychometric_core --all-targets (focused asymptotic_total_observed* green; lib 189, multilevel 109, scientific_claim_boundary 53)
  • RUSTDOCFLAGS='-D warnings' cargo doc -p psychometric_core --no-deps

Do not self-approve. Do not convert #310. Do not merge without independent non-author APPROVE and exact-head required-check success.

… on main

Scalar map of Driver Eq. 5 of the commented ctsem 2.5.0
summary.ctsemFit.R three-term total
-q/(2a)+trait/a²+(B/a)²v, then λ² of that total plus θ.
Form the three-term total inline. Zero loading is exactly θ.
All-zero latent contributions return θ even if a ≥ 0.
a ≥ 0 with a nonzero contribution fails closed.
Distinct from Eq. 5 of stationary T0VAR (trait not trait/a²).
Independent of queued #330/#340/#341/#342/#343.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Resolve the CHANGELOG.md append conflict by keeping both entries.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@seonghobae

Copy link
Copy Markdown
Contributor Author

Restack on protected main (a243f18)

Non-force merge of origin/main (merge commit 98e31c7b); the only conflict was the CHANGELOG.md append, both entries kept.

Local evidence on the pushed head (toolchain 1.98.0): cargo test -p psychometric_core 368 passed / 0 failed, clippy -D warnings clean, cargo fmt --all --check clean, documentation/workspace/docstring contracts PASS, git diff --check clean.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant