Skip to content

feat(psychometric): restore Driver p.16 TIPREDVARstd v/v=1 on main - #475

Closed
seonghobae wants to merge 1 commit into
mainfrom
agent/psychometric-tipred-var-std-restore-on-main
Closed

feat(psychometric): restore Driver p.16 TIPREDVARstd v/v=1 on main#475
seonghobae wants to merge 1 commit into
mainfrom
agent/psychometric-tipred-var-std-restore-on-main

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Restore one named Driver, Oud, and Voelkle (2017) p. 16 map on current main: scalar TIPREDVARstd as v / v = 1 after strictly positive TIPREDVAR.

Paper (re-opened this cycle)

JSS PDF re-opened 2026-09-01T19:20Z from https://www.jstatsoft.org/index.php/jss/article/download/v077i05/1104.

  • Table 3, p. 13 names TIPREDVAR the lower-triangular n.TIpred × n.TIpred Cholesky matrix of time-independent predictors variance/covariance.
  • Table 2, p. 12 does not name TIPREDVAR.
  • p. 16 prints standardised matrices with the suffix std when appropriate. The printed example is discreteDRIFTstd, not TIPREDVARstd.
  • Footnote 4: standardisations use only the relevant variance, not the total.

2017-era cran/ctsem 2.5.0 R/summary.ctsemFit.R (re-opened this cycle):

if(verbose==TRUE){
  TIPREDVARdiag<-tryCatch({diag(diag(TIPREDVAR),n.TIpred)+diag(c(ridging),n.TIpred)}, error=function(e) e )
  TIPREDVARstd<-tryCatch({suppressWarnings(solve(sqrt(TIPREDVARdiag)) %&% TIPREDVAR)}, error=function(e) e )
  tryCatch({  dimnames(TIPREDVARstd)<-list(TIpredNames,TIpredNames)}, error=function(e) e )

if(ridging==TRUE) ridging<- .0001 else ridging <- 0. Default ridge is 0. Unlike TRAITVAR / MANIFESTTRAITVAR, that source does not skip forming TIPREDVARstd when v = 0; solve(sqrt(0)) fails. OpenMx %&% is t(A) %*% B %*% A.

Meredith (1993) remains unread. Mislevy (1991) remains unread.

Map

recover_standardised_time_independent_predictor_variance:

  1. Event clock only.
  2. Finite, non-negative v.
  3. Zero v fails closed (StandardisedTimeIndependentPredictorVarianceRequiresPositivePredictorVariance).
  4. Form 1 / √v, then (1 / √v) v (1 / √v). Return the quadratic form, not a hardcoded Ok(1.0).
  5. Distinct positive v recover the same 1.
  6. TIPREDVAR does not require stable a < 0.

Refuses (equal numbers remain distinct named quantities):

  • unstandardised TIPREDVAR is not TIPREDVARstd
  • MANIFESTVARstd θ / θ = 1 is not TIPREDVARstd (this crate already exports MANIFESTVARstd)
  • §7.2 addedTIPREDVAR (B / a)² v is extra process variance, not this correlation

The existing refuse of TIPREDVARstd as asymDIFFUSIONstd is kept.

Not this PR

Local verification

  • cargo +1.98.0 test -p psychometric_core --lib — 189 passed
  • focused TIPREDVARstd integration tests — passed
  • cargo +1.98.0 clippy -p psychometric_core --all-targets -- -D warnings — clean
  • RUSTDOCFLAGS='-D warnings' cargo +1.98.0 doc -p psychometric_core --no-deps — clean
  • cargo +1.98.0 fmt --all -- --check — clean

Devin Review

Restore recover_standardised_time_independent_predictor_variance as
the footnote-4 quadratic form of Table 3 TIPREDVAR after strictly
positive v. Zero predictor variance fails closed, matching 2017-era
solve(sqrt(0)). Distinct named quantities remain distinct when they
equal 1.

JSS PDF re-opened 2026-09-01T19:20Z. Meredith (1993) and Mislevy
(1991) remain unread.
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 41 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 74a0d7ee-6e85-413a-89a0-6d0425af7568

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc02f5 and d99d946.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • crates/psychometric_core/src/error.rs
  • crates/psychometric_core/src/event_time.rs
  • crates/psychometric_core/src/lib.rs
  • crates/psychometric_core/tests/multilevel_event_time_recovery_contract.rs
  • crates/psychometric_core/tests/scientific_claim_boundary_contract.rs
  • docs/adr/0005-posterior-esem-dsem.md
  • docs/research/multilevel-event-time-recovery.md

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.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Devin Review

Comment on lines +1933 to +1937
/// and remains a distinct named quantity. This crate now exports
/// `TIPREDVARstd`. This crate does not currently export
/// `DIFFUSIONstd`; the refuse still names that quantity. This is
/// not a Kalman filter, not a matrix `expm`, not DSEM, and not
/// ctsem estimation.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Adjacent estimator docs remain merged

The recover_standardised_asymptotic_diffusion comment absorbs the following TRAITVARstd discussion. Rustdoc misattributes that contract and leaves the trait estimator undocumented.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +2241 to +2244
let predictor_sd = time_independent_predictor_variance.sqrt();
let inverse_sd = require_finite(1.0 / predictor_sd)?;
let scaled = require_finite(inverse_sd * time_independent_predictor_variance)?;
require_finite(scaled * inverse_sd)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Extreme inputs remain representable

The sqrt and staged scaling sequence keeps all positive finite inputs representable. Subnormal inputs can return a few ulps from mathematical one.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Canonical-owner repair started in ContextualWisdomLab/fast-mlsirm#1721 (issue #1720). This PR's static D^{-1/2} Σ D^{-1/2} arithmetic belongs to fast-mlsirm; TEPP owns the EventTime admission/temporal adapter. The upstream PR preserves a test-first generic scalar+matrix contract and the Driver/ctsem provenance without importing TEPP clocks or names. Closing this TEPP implementation prevents duplicate production authority while preserving this branch's TIPREDVARstd fixtures/research as downstream parity evidence. TEPP should add only the EventTime ACL after a released/versioned fast-mlsirm contract exists; an open upstream PR head is not a production dependency.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant