The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Stage-2 SE workflow
(define_model_system(..., previous_stage = ...) with
factor_structure = "SE_linear" or
"SE_quadratic") was silently fixing
typeprob_*_intercept and type_*_loading_*
parameters when the previous stage already had
n_types > 1. The factor_dist_patterns regex
list in define_model_system() enumerated only
factor_var_*, se_*, chol_*, and
factor_mean_* as factor-distribution parameters, so
typeprob and type-loading slots fell through into
measurement_params and were forced to their Stage 1 values.
The C++ initialization correctly left those parameters free. The
disagreement scrambled the mapping between the C++ free-parameter vector
and the R-side free_idx:
evaluate_likelihood_rcpp() extracted 7 free gradient
entries from C++ and scattered them into a 5-slot R map, shifting every
value past position 5. The result was a Hessian whose SE x SE sub-block
looked permuted (max rel_err ~1.67, previously flagged as the “TEST 4
known issue”). Added ^typeprob_ and
^type_[0-9]+_loading_ to the pattern list; now the two
sides agree that those are factor-level free parameters. Also matches
TEST 1’s explicit expectation that typeprob and
input-factor type loadings stay free in Stage 2.
Type-probability mixture contribution to the Hessian on the
d^2 L_mix / d(sigma^2_k)^2 diagonal was missing two terms
in FactorModel::CalcLkhd (section 3b):
2 * dpi_t/d(sigma^2_k) * dL_t/d(sigma^2_k) was added only
once rather than twice. The off-diagonal code correctly added both
orderings of the cross term; the k == l branch kept a “we
only add once due to symmetry in sum” comment that was wrong. On the
diagonal the two orderings coincide so the correct behavior is a factor
of 2.f_k = sigma_k * x_q, the full diagonal second derivative
of pi_t w.r.t. sigma^2_k is
d^2(pi)/d(f_k)^2 * (df_k/d(sigma^2_k))^2 + d(pi)/d(f_k) * d^2(f_k)/d(sigma^2_k)^2.
Only the first term was being accumulated; the
d(pi)/d(f_k) * d^2(f_k)/d(sigma^2_k)^2 term is now added
when k == l. In combination with the free/fixed mapping
fix, the Stage-1 with-types to Stage-2 SE_linear Hessian FD max rel_err
dropped from 1.67 to ~8e-6 at n_quad = 12, reaching machine
precision at n_quad >= 24. The previously skipped TEST 4
in test-two-stage-se-types.R has been re-enabled as a
regression guard.define_model_component(): the no-intercept sanity
warning now fires only when the caller has NOT explicitly opted out of
an intercept via intercept = FALSE. The explicit opt-out is
a deliberate choice (common in validation and shape-only tests and in
ordered-probit setups where the intercept is absorbed into the
cutpoints); treating it as a candidate for the misspecification warning
produced noise without signal. Accidental omissions
(intercept left at its default of TRUE, but no
intercept covariate provided) still trigger the warning.
Attempted re-enable of the Stage-1-with-types / Stage-2-SE_linear
Hessian FD placeholder (test-two-stage-se-types.R TEST 4):
still fails after the v1.1.7 Hessian accumulation fix (max err ~1.7 on
the SE x SE sub-block, gradient passes). The remaining mismatch is a
separate issue in how the type-probability model interacts with
SE_linear under previous_stage, not covered by the general
accumulation fix. Re-skipped with an updated comment.
Analytical Hessian now accumulates correctly under equality
constraints. Previously FactorModel::CalcLkhd iterated over
freeparlist for its Hessian contribution loops, which
skipped equality-tied (derived) parameters. The subsequent
ExtractFreeHessian aggregation had no tied-position values
to sum into the primaries, so the analytical Hessian at primary x
primary positions missed the d^2L / d(primary) d(derived),
d^2L / d(derived) d(primary), and
d^2L / d(derived) d(derived) terms. This produced
analytical zeros at positions where finite differences (with equality
enforced at reinitialisation) reported magnitudes of 10 to 50, meaning
SE estimates under equality constraints were biased. Fix: iterate over
gradparlist (free plus tied) in the Hessian loops and
symmetrise full_hessL before
ExtractFreeHessian. Validated by the now-passing Stage 1 FD
tests in test-dynamic-single-factor.R (linear max_err
~2.5e-6, oprobit Hessian max_err ~3.3e-6).
The C++ name-to-index map for ordered-probit thresholds was
looking up the field n_categories instead of the actual
component field num_choices, so threshold equality
constraints were silently dropped. Fixed in
rcpp_interface.cpp. This was the root cause of the conv = 1
+ “items to replace” warnings observed in the Mental Health Trap
simulation’s Stage 1 oprobit estimation.
define_dynamic_measurement() for
model_type = "oprobit" now ties only the threshold
INCREMENTS (_thresh_k for k = 2..K-1) across
periods and leaves _thresh_1 period-specific, mirroring the
linear strategy (tie sigmas, free intercepts). Patch contributed by an
external agent on the MH Trap project.
define_dynamic_measurement() now silently strips
"intercept" / "constant" from
covariates when model_type = "oprobit"
(ordered probit absorbs the intercept into the cutpoints). The default
covariates = "intercept" now works for every supported
model type.
test-se-models.R: .build_se_type_model
gains an indicator_type argument ("linear" or
"oprobit") and two new tests exercise single-stage
SE_linear + n_types = 2 FD (gradient and Hessian) with
ordered-probit indicators.
test-two-stage-se-types.R: TEST 3 adds an oprobit
variant of the two-stage FD test at Stage 2 (analog of the linear TEST
2). The old TEST 3 known-issue placeholder is renumbered to TEST
4.
test-dynamic-single-factor.R:
define_dynamic_measurement() with
model_type = "oprobit" now ties only the threshold
INCREMENTS across periods (_thresh_k for
k = 2..K-1) and leaves _thresh_1
period-specific. Previously all thresholds were tied, which forced any
wave-to-wave shift in the latent factor mean into the factor variances
and produced Stage 1 convergence code 1 (false convergence) plus
boundary warnings. The new behaviour mirrors the linear case: tie the
scale (sigmas / threshold increments), leave the location (intercepts /
thresh_1) period-specific. Patch contributed by an external agent
working on the Mental Health Trap simulation, where Stage 1 convergence
went from conv = 1 with factor_var_1 = 4.06 /
factor_var_2 = 0.98 to conv = 0 with balanced
variances.
define_dynamic_measurement() now silently strips
"intercept" or "constant" from
covariates when model_type = "oprobit".
Ordered probit absorbs the intercept into the cutpoints, so factorana
rejects an intercept covariate on oprobit components. The wrapper’s
default covariates = "intercept" now works for every
supported model type without requiring the user to tailor it by model
type.
test-dynamic-single-factor.R gains a structural test
for the oprobit wrapper path that verifies: the intercept covariate is
stripped, equality constraints contain only threshold increments
k = 2..K-1 (not thresh_1),
thresh_1 appears as a free parameter in every period, and
build_dynamic_previous_stage() produces a dummy with no
_intercept parameters and with the anchor-period
thresh_1 carried into every period’s slot. Estimation-level
recovery for oprobit is not asserted: the oprobit dynamic model is
empirically fragile at moderate n and identification is tracked
separately.build_dynamic_previous_stage() now handles oprobit,
probit, and logit model types. Those types do not have explicit
_intercept parameters (location is absorbed into cutpoints
or the link function); the previous version would error when looking up
a missing intercept. Linear behaviour is unchanged.test-dynamic-single-factor.R gains a third test that
exercises the wrapper plus Stage 2 SE_linear with
n_types = 2. Types shift the period-2 factor mean via
se_intercept_type_2. Recovery of the well-identified
structural parameters (factor_var_1, se_linear_1, se_intercept_type_2,
se_residual_var) is verified on a simulated DGP, with a more generous
tolerance on se_intercept (which trades off against
typeprob_2_intercept and type_2_loading_1 when
measurement information density is low).define_dynamic_measurement() and
build_dynamic_previous_stage() encapsulate the standard
workflow for estimating an SE_linear or SE_quadratic structural model on
a single latent construct observed at two or more time points:
define_dynamic_measurement() builds the Stage 1
measurement model (a k-factor independent system with loadings and
residual sigmas tied across periods via
equality_constraints, measurement intercepts left
period-specific).build_dynamic_previous_stage() constructs a Stage 2
previous_stage object that plugs the anchor-period (wave 1
by default) intercepts into every factor slot. This anchors the
measurement level under the factor-identification convention
E[f_k] = 0 and lets the observed period-to-period mean
shift in Y identify the structural intercept (alpha) in Stage 2.model_type of “linear”, “oprobit”, “probit”,
and “logit” with appropriate tying of thresholds (oprobit) or sigmas
(linear).tests/testthat/test-dynamic-single-factor.R
to use the wrapper; recovery results are unchanged.vignettes/dynamic_structural.Rmd to use the
wrapper.tests/testthat/test-dynamic-single-factor.R covers
the standard workflow for estimating an SE_linear dynamic structural
equation on a single latent construct measured at two time points:
equality_constraints tying factor loadings and residual
sigmas across periods but leaving measurement intercepts
period-specific.previous_stage object is built that
carries the wave-1 intercepts into both factor slots (discarding the
wave-2 intercepts, which absorb the structural-equation mean
shift).SE_linear and recovers the structural
intercept se_intercept (alpha), slope
se_linear_1 (beta), residual variance
se_residual_var, and input factor variance
factor_var_1.vignettes/dynamic_structural.Rmd walks
through the same workflow with executable code and explains the
motivation for using wave-1 intercepts in Stage 2.test-two-stage-se-types.R (its Stage-1-no-types ->
Stage-2-with-types setup is not a canonical workflow); the shape test,
FD gradient/Hessian test, and the skipped Stage-1-with-types known-issue
placeholder remain in place.previous_stage + SE_linear/SE_quadratic and
n_types > 1 now correctly builds the Stage 2 parameter
vector. Prior versions omitted the typeprob_* and
type_*_loading_* slots, causing either a crash in
setup_parameter_constraints() or silently mis-fixed
parameters. The measurement-parameter filter in
initialize_parameters() was also tightened so that
factor-level type parameters from Stage 1 are no longer duplicated into
the measurement block. Discovered during analysis of a structural model
where types are introduced at Stage 2.tests/testthat/test-two-stage-se-types.R adds:
n_types = 2 produces the expected parameter vector aligned
with build_parameter_metadata(),se_linear_1,
se_intercept_type_2, se_residual_var,
factor_var_1) with init se_intercept = -0.5
(Stage 1 absorbs E[f2] into the measurement intercepts, so the MLE
se_intercept is negative even if the DGP constant is 0),
andDESCRIPTION
field: Heckman, Humphries & Veramendi (2016, 2018) and Humphries,
Joensen & Veramendi (2024).\value (via @return) to all exported
functions that were missing it, including as_kv,
estimate_and_write, write_model_config_csv,
the adaptive-quadrature and observation-weight setters, and every
print method.\dontrun{} with runnable examples
(fix_coefficient, fix_type_intercepts) or
\donttest{} blocks (results_table,
results_to_latex, components_table,
estimate_factorscores_rcpp,
cleanup_parallel_workers).estimate_and_write() and
write_model_config_csv() no longer write to a default path;
results_dir / file is now required (use
tempdir() in examples and tests).introduction vignette with
two executable vignettes: measurement_system (two-factor
CFA) and roy_model (sector choice with a latent ability
factor).intercept in its covariates; this
configuration is rejected (the intercept is absorbed into the cut
points).equality_constraints parameteruse_types
parametercheckpoint_file parameterexclude_chosen = FALSErankshare_var parameterfactor_specfactor_structure = "correlation"These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.