Changes in Version 0.16.9 o The ordinal-data regression tests (GitHub issue #54) now probe whether the 'pbv' package's C++ API is usable and are skipped when it is not. On some check setups (e.g. win-builder R-devel) a stale 'pbv' binary lacks the Rcpp validation hook, which made every ordinal-data call error and halted the whole test suite. Changes in Version 0.16.8 o The saturated log-likelihood method that was ultimately used is now recorded in the fitted object (GitHub issue #53): x@baseline_saturated$satMethodUsed is "numeric", "analytic", or "analytic_fallback" (the latter when saturated = "default" fell back to the analytic formula because the saturated model optimization failed), and the new 0/1 fit measure 'satLL_analytic' indicates whether the analytic formula was used. Being numeric, satLL_analytic is retained by aggregate_bootstraps(): its bootstrap average is the proportion of (converged) bootstrap samples in which the analytic saturated log-likelihood was used. o Consistent with its documentation, saturated = "model" no longer silently falls back to the analytic saturated log-likelihood when the saturated model optimization fails; the fallback only applies to saturated = "default". o Fixed a stepup() failure with ordinal data (GitHub issue #54): freeing a parameter using its expected parameter change (EPC) as starting value could place the model in an improper (non-positive definite) region, where the fit functions return a constant penalty with a flat gradient. The optimizer then stalled on that plateau, which surfaced as "missing value where TRUE/FALSE needed" or as spurious "model did not improve" results in stepup(). Three fixes: - freepar() now checks that EPC-based starting values leave the implied matrices proper, and falls back to small starting values otherwise. - runmodel() detects an optimizer that "converged" on the improper-region penalty plateau and retries once from emergency starting values. - stepup() now handles an NA chi-square difference test gracefully (returning the previous model with a message) and, when the requested criterion (e.g. the default "bic") is not available for the estimator (information criteria are not defined for the (D)WLS estimators used with ordinal data), skips the criterion check with a single informative warning instead of erroring. Changes in Version 0.16.7 o Fixes for R-devel (found via win-builder): the example covariance matrices in the dlvm1, panelvar, and latentgrowth help pages no longer use the deprecated structure(.Dim=, .Dimnames=) names (now dim= and dimnames=), and the unit tests that cross-validate against internal lavaan kernels (lav_mvnorm_cluster_information_expected, lav_model_h1_information_observed) now skip gracefully when those internals are absent, as in lavaan >= 0.7 where they were renamed with changed interfaces. The same quantities remain covered by internal analytic-vs-numeric checks. o Naming cleanup: the plain names are now the primary names of several model families, with the historical *1 names (the "1" referred to the lag order; no lag-2 frameworks are planned) remaining fully supported aliases: dlvm() = dlvm1(), tsdlvm() = tsdlvm1(), meta_var() = meta_var1(), and ml_var()/ml_gvar() = ml_var1()/ml_gvar1() (see below). var1() and gvar() are unchanged: exporting var() would mask stats::var, and "var1" reads naturally as VAR(1). In addition, 'within' and 'between' are now the preferred argument names for the contemporaneous and between-person structures in the latent-free frameworks panelvar() and ml_var() (ml_var1() now accepts them too); the *_latent names remain accepted everywhere. o ml_var()/ml_gvar()/ml_var1()/ml_gvar1() default to estimator = "auto": full-information ML (through the panelvar framework) when the measurement-occasion grid has at most 10 occasions per subject - the panel-data regime, matching the behavior (and estimates) of ml_var() in psychonetrics 0.15 - and the two-level summary-statistics pseudo-ML for longer series, where full-information ML is infeasible. A message states which estimator was selected; set 'estimator' explicitly to override. o ml_var1()/ml_gvar1() now support estimator = "FIML": the model is dispatched to the panelvar() framework, with the measurement occasions (idvar / dayvar / beepvar) mapped to the waves of a panel model, so the exact multi-level VAR(1) likelihood is optimized with full-information ML (missing responses and missed beeps handled by FIML; a night break is bridged by one structurally missing occasion). This is exact but much slower than the default two-level summary-statistics estimator; it replaces the historical dlvm1-based FIML route of ml_var()/ml_gvar(). o ml_var() and ml_gvar() are now aliases for ml_var1() and ml_gvar1() (their 'contemporaneous' and 'between' arguments map to 'within_latent' and 'between_latent'). They were deprecated wrappers around dlvm1() with estimator = "FIML"; the new default estimator = "auto" (see above) keeps the 0.15 behavior for panel-like data and switches to the summary- statistics estimator for longer series. ml_tsdlvm1() and ml_ts_lvgvar() (the latent versions) remain deprecated wrappers for dlvm1(). o Added a summary() method for psychonetrics models: the print output extended with the main fit measures (log-likelihood, number of parameters, AIC, BIC, RMSEA, CFI, TLI). Previously summary() silently fell through to the default method and showed nothing useful. o meta_var1()/meta_gvar() now fail early with an informative error when more than 11 variables are used (the p(p+1)/2 + p^2 meta-level outcomes then exceed internal 32-bit sparse-matrix limits; estimation previously aborted mid-way with a cryptic "SpMat::init(): requested size is too large" error), and warn when the number of studies is smaller than the number of meta-level outcomes while a full random-effects structure is estimated (heavily overparameterized; results may be unstable). For subjects of a single intensive longitudinal study, ml_var1()/ml_gvar1() is recommended instead. The meta_var1 estimator itself was verified by simulation to recover the generating temporal and contemporaneous networks (see extra/). o NEW (experimental): ml_varcov() and its wrappers ml_ggm() and ml_corr() add a multi-level (two-level) variance-covariance family: the within-cluster and between-cluster (co)variance matrices of clustered data are modelled directly, with no latent layer. This is the multi-level analogue of the varcov() family, and the multi-level Gaussian graphical model (ml_ggm) is its headline use case. Each level is parameterized independently through the 'within' and 'between' arguments (each "cov", "chol", "prec", "ggm" or "cor"), with native matrix names sigma_within / sigma_between, omega_within / omega_between, and so on. Both estimators of ml_lvm() are supported and behave identically to their ml_lvm() equivalents: the two-level sufficient-statistics ML estimator (estimator = "ML"; cost independent of the number of units per cluster) and wide-format full-information ML (estimator = "FIML"; supports missing data). It is the special case of ml_lvm() with loadings equal to the identity and no residual variance, but is implemented as its own framework with its own (simpler) analytic derivatives in both R and C++. Verification: analytic gradients match numeric differentiation for all 25 within x between type combinations under both estimators; the fit function and gradient agree with ml_lvm's to machine precision at identical parameter values; R and C++ agree to machine precision; and parameter recovery / confidence-interval coverage were validated in a simulation study. The multi-level GGM is also available, via a different (nodewise multilevel regression) estimator, as mlGGM() in the mlVAR package. o Fixed ml_lvm() (and ml_varcov()) failing -- or, for exchangeable cluster positions, silently permuting observations -- when the data rows were not sorted by cluster: the internal within-cluster ID was assigned in cluster-sorted order rather than row order. Cluster labels reused across different groups of a multi-group analysis now also correctly denote different clusters. o Fixed samplestats() crashing with "missing value where TRUE/FALSE needed" when heavy missingness left some pairwise covariances undefined (e.g. a wide-format FIML analysis with sparsely observed cluster positions); the correlation-input auto-detection now treats undefined diagonals as "not correlation input" (the NA-covariance warning is still given). Changes in Version 0.16.6 o NEW (experimental): ml_var1() and its GGM-defaults wrapper ml_gvar1() add a multi-level (random intercept) lag-1 vector autoregression / graphical VAR for intensive longitudinal (ESM) data. A within-person stationary VAR(1) process (temporal network beta, contemporaneous network omega_zeta_within) is combined with a between-person random-intercept structure (network omega_zeta_between) - the three multi-level GVAR networks. The model targets the same estimand as panelvar()/panelgvar() but is estimated by applying the two-level sufficient-statistics ML machinery (ml_lvm) to the lag-embedded ("Toeplitz") data, so its per-evaluation cost is independent of the number of time points (2p x 2p matrices only) where the full-likelihood panelvar route becomes infeasible. This is a working-independence pseudo-likelihood (as in var1): use panelvar()/panelgvar() for few-waves panel data. Estimates of beta and omega_zeta_within are consistent and track the full-likelihood estimates closely; the between-person variances carry a small O(1/T) upward finite-length bias and the pseudo-likelihood standard errors are somewhat anti-conservative for the contemporaneous network (see ?ml_var1). Validated against lavaan two-level models (the saturated model, and the structured model in the saturated-innovations cov/cov case, which admits an exact lavaan reparameterization; the GGM/typed cases rest on numeric-derivative checks and the panelgvar benchmark) and against panelgvar. Complete-pairs (listwise) handling of incomplete lag pairs in this first version. The model layer is implemented in R only for now (no C++ acceleration). o Internal: tsData() gained an includeID argument (default FALSE) that attaches the subject id to each augmented lag-pair row; used by ml_var1() to define clusters. With includeID = FALSE the output is byte-identical to before, so var1()/gvar()/tsdlvm1() are unaffected. Changes in Version 0.16.5 o NEW: sampling weights (pseudo-maximum-likelihood) via the sampling_weights argument of varcov()/lvm() (and the ggm/precision/... wrappers). The moments are computed as weighted means/covariances and the model is fit with robust (MLR) Huber-White sandwich standard errors and a Yuan-Bentler-Mplus scaled test statistic, matching lavaan's sampling.weights= to numerical precision (single- and multi-group; estimates, SEs, scaled chi-square and robust fit indices). Complete-data continuous input only. o Documented that, unlike lavaan (auto.cov.lv.y = TRUE), psychonetrics does not free the residual covariances among endogenous latent variables by default; free them via sigma_zeta to reproduce a lavaan SEM (this also makes fixed_x models with latent regressions match lavaan exactly). Removed a now-obsolete caveat in the fixed_x documentation (the baseline is conditioned on x since this release). o Fixed fromlavaan(): a single-group lavaan fit WITHOUT a mean structure (the default for cfa()/sem()) was converted with colliding parameter indices, silently equating observed intercepts with loadings/variances (chi-square Inf, wrong df). Meanstructure = TRUE fits were unaffected. o Fixed fixed_x: the baseline (and saturated) reference models are now conditioned on the exogenous block, matching lavaan. Previously the baseline was an unconditioned independence model over all variables, producing a negative baseline.df, an inflated baseline chi-square, NaN TLI and incorrect CFI/TLI for every fixed_x model. o Fixed the scaled chi-square difference test in compare() for the scaled-shifted (MLMV/WLSMV) and mean-and-variance-adjusted (MLMVS) estimators. compare() now auto-selects the appropriate difference test (the exact Satorra (2000) test for those estimators, Satorra-Bentler (2001) for MLM/MLR), matching lavaan's lavTestLRT; previously the default Satorra-Bentler-2001 test used the wrong (test-specific) scaling factor for scaled-shifted/mean-var fits and returned an incorrect statistic. The mean-adjusted scaling factor is now also stored as chisq.scaling.factor.sb. A latent bug that returned NA for any scaled difference test against a saturated (df 0) reference model was also fixed. o Performance: the asymptotic covariance Gamma of the sample statistics is no longer computed for plain (non-robust) maximum-likelihood fits; it is computed only for the robust ML estimators that need it (and lazily by setestimator()). This removes a large constructor-time and memory cost for high-dimensional models (e.g. ~12 s and ~84 MB at p = 80). o Performance: the robust-ML sandwich building blocks (including the expensive numeric observed-information Jacobian for MLR) are now computed once per addfit() call and reused for the scaled test and the FIML-C robust fit indices, instead of being rebuilt several times. o Added a df <= 0 guard to the robust-ML scaled test (compute_ml_scaled_test) for consistency with the MLR path. Changes in Version 0.16.4 o NEW: the temporal effects of all lag-1 frameworks can now be parameterized directly in terms of partial directed correlations (PDC), the standardized temporal network that is usually interpreted in graphical VAR analyses: temporal = "PDC" in var1()/gvar(), panelvar()/panelgvar() and tsdlvm1()/ts_lvgvar(), and temporal_latent = "PDC" / temporal_residual = "PDC" in dlvm1() (the latter for the residual autoregression beta_epsilon, giving a PDC_epsilon matrix). The PDC parameter matrix encodes from = row and to = column (the transposed orientation relative to beta, matching getmatrix(..., "PDC")), and its elements are bounded in (-1, 1). o The PDC parameterization is a smooth, zero- and sign-preserving reparameterization of beta given the innovation structure (beta[j,i] = PDC[i,j] * sqrt(kappa_ii * sigma_jj) / sqrt(1 - PDC[i,j]^2)), so any pattern-constrained PDC model is fit-equivalent to the corresponding raw model: same likelihood, degrees of freedom and implied covariance structure, and the fitted PDC parameters equal computePDC()/getmatrix(raw fit, "PDC") exactly at the optimum (verified numerically per family). The gain is inference on the interpreted scale: Wald standard errors, confidence intervals (CIplot()), modification indices, prune()/stepup(), and cross-group equality constraints (groupequal("PDC")) all apply directly to the PDC elements - e.g. testing whether the standardized temporal network is equal across groups while innovation variances differ. o Implemented in both the R and C++ engines via a block-triangular reparameterization of the model Jacobian (the beta column block is post-multiplied by d vec(beta)/d vec(PDC), and the dependence of beta on the innovation (co)variances is routed into the innovation columns). Analytic gradients verified against numeric ones for all innovation types (cov, chol, prec, ggm, cor) in every family, and the PDC standard errors verified against delta-method standard errors from the raw parameterization. o CIplot() displays PDC edges in the correct direction (from = row -> to = column); prune(), stepup(), modelsearch(), unionmodel(), intersectionmodel(), partialprune() and penalized estimation select the PDC matrix by default for PDC-parameterized models. transmod() does not transform temporal parameterizations (re-specify the model instead; a saturated PDC model is fit-equivalent to the saturated raw model). o checkFisher() is now exact for FIML models: the expected-model reference (expectedmodel()) also replaces the scatter matrices of single-row missingness patterns (previously stored as zero and skipped) by their implied expectations. Before this fix, FIML models containing single-row patterns - notably var1()/tsdlvm1(), whose lag-augmented data always contain one boundary row - showed a spurious O(1/n) deviation (about 0.5 percent) between the analytic and numeric Fisher information in checkFisher(), even though the analytic information was correct. Estimation, standard errors and fit measures are unaffected (expectedmodel() is only used by the numeric Fisher verification tooling). Changes in Version 0.16.3 o NEW: dlvm1() gained a 'beta_epsilon' argument: lag-1 temporal effects at the residual level, epsilon_t = beta_epsilon epsilon_(t-1) + u_t. The default "zero" reproduces the previous white-noise residual structure exactly (verified against 0.16.2 reference fits: identical estimates, standard errors, degrees of freedom and likelihoods). "diag" gives each indicator its own residual autoregression, modeling item-specific carry-over (autocorrelated uniquenesses) with a geometrically decaying structure; "full" and custom pattern matrices are also supported, as are cross-group equality constraints (equal = "beta_epsilon" and groupequal("beta_epsilon")). o When beta_epsilon is non-zero, sigma_epsilon_within (and its typed variants: chol, prec, ggm, cor) parameterizes the innovation covariance of the residual process; the implied stationary residual covariance is available via getmatrix(model, "sigma_epsilon_within_stationary"). Together with sigma_epsilon_between (the perfectly stable item component), this gives each indicator a STARTS-like decomposition: stable trait + autoregressive part + latent dynamics. o Identification: a non-zero beta_epsilon requires at least three waves (a warning is issued with two); four or more are recommended. Since the white-noise model is nested (beta_epsilon = 0), modification indices for the beta_epsilon elements provide a direct diagnostic for residual autocorrelation, and the LRT against the default model is the natural test. o Implemented in both the R and C++ engines; analytic gradients verified against numeric ones for diag/full beta_epsilon across residual types (cov, chol, ggm, cor), multi-group models with equality constraints, FIML, and missing-wave designs, and the implied covariance structure verified against an independent implementation and a large Monte Carlo simulation of the generating process. Changes in Version 0.16.2 o NEW: panelvar() and panelgvar() are now implemented as their own model framework ("panelvar") rather than as a dlvm1 model with dummy matrices (identity factor loadings and zero residual variances). The model is unchanged -- a within-person stationary VAR(1) process plus a between-person (random intercept) structure -- and results are identical to the previous route (same estimates, standard errors, degrees of freedom and fit measures; the existing panel reference values reproduce exactly). Estimation skips all factor-loading algebra in both the R and C++ engines, making runmodel() roughly 1.3-2.6 times faster (the gain grows with the number of variables and waves). Analytic gradients of the new framework are verified against numeric ones for all within/between types (cov, chol, prec, ggm, cor), including multi-group models with equality constraints, FIML, and designs with missing waves. o The panelvar/panelgvar model matrices keep their dlvm1 names (beta, sigma_zeta_within, sigma_zeta_between and their typed variants), so getmatrix(), prune(), stepup(), transmod(), CIplot(), esa() and modelsearch() keep working unchanged. The mean structure is now a single 'mu' matrix of observed stationary means (previously the observed intercepts appeared as 'nu' with latent means 'mu_eta' fixed to zero); equality constraints requested on 'nu' are mapped to 'mu' for backward compatibility. Variable names now default to the design-matrix rownames (or V1, V2, ...) instead of Eta_1, Eta_2, .... o panellvgvar() (the latent panel GVAR) is unaffected and still uses the dlvm1 framework. Changes in Version 0.16.1 o NEW: the correlation parameterization (type = "cor"; a correlation matrix rho with a diagonal matrix of standard deviations SD, such that sigma = SD (I + rho) SD) is now available for every typed covariance structure in the package, alongside "cov", "chol", "prec" and "ggm": - lvm() latent and residual structures (rho_zeta/SD_zeta and rho_epsilon/SD_epsilon), including lnm()/rnm()/lrnm() and meta_lvm() - var1()/gvar() contemporaneous (innovation) structure (rho_zeta/SD_zeta), including meta_var1()/meta_gvar() - tsdlvm1()/ts_lvgvar() contemporaneous and residual structures - dlvm1() and ml_lvm() within/between latent and residual structures, including panelvar()/panelgvar()/panellvgvar() and ml_lnm()/ml_rnm()/ ml_lrnm(), and ri_clpm() (type = "cor") No new derivatives were needed: the existing analytic rho/SD Jacobian blocks (used by varcov(type = "cor") and the meta-analytic random effects) are chained into each family's gradient, in both the R and C++ engines. transmod() can transform saturated/diagonal structures to and from "cor", and CIplot() selects rho matrices for cor-typed models. o With identification = "variance", cor-typed latent structures are identified by fixing the latent standard deviations (the diagonal of the SD matrix) to 1, so the latent covariance structure becomes a correlation matrix (I + rho). o The "cor" parameterization is fit-equivalent to the "cov" parameterization when saturated (verified numerically for all families: identical log-likelihoods, degrees of freedom and implied covariance structures; analytic gradients verified against numeric ones in both the R and C++ engines). Changes in Version 0.16 o Version 0.16 is a major feature release that consolidates the 0.15.x development series. It bundles a large internal code audit (numerous bug fixes, robustness and performance improvements across all model families, and a new automated test suite) together with substantial new modeling functionality, all validated against lavaan. The detailed per-version changelog is retained below. o NEW: a fast sufficient-statistics two-level maximum-likelihood estimator for multi-level latent variable models (ml_lvm(estimator = "ML")), supporting complete and within-cluster-missing data. o NEW: robust maximum-likelihood estimators MLM, MLMV, MLMVS and MLR (robust/sandwich standard errors, scaled chi-square statistics and robust RMSEA/CFI/TLI), with Satorra-Bentler-family scaled chi-square difference tests in compare(). o NEW: lavaan interoperability via fromlavaan() and tolavaan(), standardized (std.all) solutions with delta-method standard errors, the wishart likelihood, and fixed exogenous covariates (fixed_x). o The estimators, fit measures, standard errors and converters listed above were validated against lavaan as a numerical oracle. Several of the new methods carry an experimental note (shown when verbose = TRUE) and may still change. Changes in Version 0.15.31 o This release adds new modeling functionality validated against lavaan: a fast two-level maximum-likelihood estimator for multi-level latent variable models, robust maximum-likelihood estimators (MLM/MLMV/MLMVS/MLR) with scaled test statistics and robust fit indices, scaled chi-square difference tests, converters to and from lavaan, standardized solutions, the wishart likelihood, and fixed exogenous covariates. All new features are opt-in; existing analyses are unaffected. Several new methods carry an experimental note (shown when verbose = TRUE). o MULTI-LEVEL: ml_lvm() gains a sufficient-statistics two-level ML estimator (estimator = "ML"; McDonald & Goldstein, 1989; Muthen, 1990), which optimizes the numerically identical objective as the wide-format FIML estimator but is dramatically faster for large clusters (e.g. a 100-cluster model with cluster sizes 18-25 fits in under a second versus ~90 seconds with FIML). Standard errors and modification indices use an analytic expected Fisher information (verified against lavaan's kernel to ~1e-13), with full C++ implementations. Within-cluster missing data (MCAR/MAR) is supported (matching lavaan::sem(..., missing = "ml"); R-based, numeric information). The estimator argument now defaults to "default", which picks "ML" for complete data with largest cluster > 5 units and "FIML" otherwise; explicit estimator = "FIML" reproduces previous results exactly. Saturated and baseline reference models, chi-square, df, CFI and TLI agree with lavaan's two-level SEM; sample-size-dependent measures (RMSEA, BIC) use the number of clusters J (so RMSEA is larger than lavaan's by a factor sqrt(N/J)). o ROBUST ML: added robust maximum-likelihood estimators selectable via the model constructors or setestimator(): "MLM", "MLMV", "MLMVS" (Browne-1984 robust.sem sandwich standard errors with the Satorra-Bentler, scaled-and-shifted, and mean-and-variance-adjusted scaled chi-square, respectively) and "MLR" (Huber-White sandwich standard errors with the Yuan-Bentler-Mplus scaled chi-square), plus robust RMSEA/CFI/TLI. Point estimates are unchanged maximum likelihood. "MLR" supports missing data via FIML, with the FIML-corrected (Savalei, 2010) robust fit indices, matching lavaan's estimator = "MLR", missing = "fiml". The Satorra-Bentler family is complete-data only. All quantities were validated against lavaan. o The multi-group scaled (WLSMV / Satorra-Bentler) test statistic now accumulates trace((U Gamma)^2) on the global block-diagonal stack rather than per group. The per-group form was only correct without cross-group equality constraints; multi-group equality-constrained scaled chi-squares now match lavaan (the same correction lavaan made in 0.6-13). Single-group output is unchanged. o compare() now reports a Satorra-Bentler-family scaled chi-square difference test (columns Chisq_diff_scaled, p_value_scaled) for nested models fitted with a robust or scaled estimator. A new scaled.test.method argument selects "satorra.bentler.2001" (default), "satorra.bentler.2010", or "satorra.2000" (scaled-and-shifted; appropriate for MLMV/WLSMV). Output for non-robust estimators is unchanged. Reproduces lavaan's lavTestLRT(). o LAVAAN INTEROPERABILITY: added fromlavaan(), which converts a fitted lavaan object (or model syntax + data) into an equivalent psychonetrics lvm (latent = "cov", residual = "cov"), reproducing estimates, standard errors, chi-square, df and log-likelihood for standard ML fits (multi-group, equality constraints, std.lv and FIML supported; unsupported features raise informative errors). Added tolavaan(), which converts a psychonetrics lvm (cov/cov) into a fitted lavaan object or a lavaan parameter table. o parameters(x, standardized = TRUE) now returns the completely standardized (std.all) solution with delta-method standard errors for the lvm and varcov families (new std and se_std columns), matching lavaan::standardizedSolution(). o Added likelihood = "wishart" to lvm() and varcov() (complete-data Gaussian ML): uses the unbiased (n-1) sample covariance with (n-1)-scaled chi-square and standard errors, matching lavaan(likelihood = "wishart"). The default likelihood = "normal" (n denominator) is unchanged. o Added fixed_x to lvm() and varcov(): fixes declared exogenous covariates' means and mutual (co)variances to their sample values (conditioning on x), matching lavaan(fixed.x = TRUE); estimates, standard errors, chi-square, df and the conditional log-likelihood match lavaan. Incremental fit indices use psychonetrics' unconditional baseline. o usecpp() keeps the two-level ML estimator with missing data on the R path (it has no C++ implementation) instead of failing with a cryptic error. Changes in Version 0.15.30 o This release implements the remaining findings of a large internal code audit: bug fixes across all model families, robustness and performance improvements, a documentation overhaul, and a new automated test suite. o ESTIMATION AND OPTIMIZATION: o Fixed an inverted positive-definiteness flag and re-enabled the optimizer penalty for improper (non-positive-definite) implied covariance matrices. Previously the ML objective was unbounded below at such points, which could make optimizers (notably nlminb, the default) diverge to absurd estimates on panel models (panelvar/panelgvar) and SEM models. Both the C++ and R fit paths now return a large penalty instead. o Fixed the experimental "LBFGS++" optimizer reporting convergence at infeasible points (non-finite objective, penalty bound, NA parameters, or iteration limit); such runs now trigger runmodel's emergency restart or a clear error. Also fixed runmodel's recovery logic for the C++ optimizer branches: NA optimizer output now triggers an emergency restart, and failed recoveries stop with an informative error. o Fixed emergencystart() constraining the wrong edges to zero in its glasso restart (free edges were zeroed instead of structurally fixed ones). o latentgrowth() (and lvm models with fully fixed nu and free nu_eta) now uses least-squares starting values for the latent means, fixing frequent non-convergence on growth data with nonzero means. o Fixed elastic-net penalized ML (0 < alpha < 1) applying the ridge component twice in the proximal-gradient optimizer; LASSO (alpha = 1) results are unaffected. The default beta_min for penalized-model lambda selection is now "numerical" (1e-05), matching the documentation. o Fixed an operator-precedence bug in the internal spectral shift used for start values (it added 0.001 to every element instead of shifting the diagonal and could leave matrices exactly singular). Start values of dlvm1/panelgvar-type models on difficult data may change slightly (typically improving convergence). The GGM correlation-input runtime path no longer applies a spectral shift, aligning the R and C++ paths. o solve_symmetric: the log-determinant plugin for non-positive-definite matrices now also catches NaN. Fixed a potential stale-cache issue in the C++ optimization workspace (cached model now protected from garbage collection). refit()-ed models now select the same default optimizer as freshly specified models; runmodel() warns when bounded = TRUE is ignored by ucminf. o GENERAL BUG FIXES: o fullFIML = TRUE (row-wise FIML) errored with "Not a matrix." for all standard model families; the C++ FIML fit, gradient, expected Hessian and log-likelihood now handle both single implied matrices and per-row lists. o Fixed equal = "omega_zeta" being silently ignored (and "lowertri_zeta" wrongly applied instead) in lvm/lnm/lrnm models with a latent network. o factorscores() now correctly accounts for structural regressions (beta) in the regression method and adds the model-implied latent means to both methods, fixing wrong scores in SEM-style and multi-group models. o Fixed varcov(covtype = "choose"): detected unbiased (n-1) input covariances are now correctly rescaled to ML. o Fixed multiple-comparison p-value adjustment (prune/adjust): the correction is now over unique parameters rather than parameter-table rows, so equality-constrained parameters are no longer over-penalized. o Fixed prune(recursive = TRUE) resetting alpha to 0.01 (and dropping mode/startreduce/limit) in passes after the first. o Likelihood-based fit measures (logl, AIC, BIC, ebic) are now retained when chisq/baseline measures are unavailable (e.g. baseline_saturated = FALSE). Fixed the ebic.75 fit measure (used gamma 0.7 instead of 0.75). o Fixed getmatrix(..., diag = FALSE) zeroing the wrong elements. o runmodel(analyticFisher = FALSE) now actually uses the numeric Fisher information on the default C++ path. Fixed the identification check in greedy stepup() inspecting the previous model's information. o Standard errors: inversion-failure/pseudoinverse warnings are no longer suppressed when verbose = FALSE; negative inverse-information variances now yield NA standard errors with a warning (R and C++ paths). o setestimator() now resets the computed flag, propagates the estimator to baseline/saturated models, and validates required sample statistics. o varcov-family models (ggm, corr, ...) now give an informative error when corinput = TRUE is combined with a meanstructure under (penalized) ML, instead of crashing during optimization. o Fixed parequal() argument handling (named runmodel arguments leaked into the constraint set). fixpar() and friends now error on mistyped variable labels instead of silently doing nothing. compare() reports NA p-values for equal-df models and warns on negative chi-square differences. o Fixed lvm/lnm/meta_lvm with latent = "ggm" and a single latent variable crashing at construction. lvm() now warns when there are more latent than observed variables. bifactor() uses deterministic starting values. o ISING / BLUME-CAPEL: o The partition function and moment computations now use log-sum-exp accumulation: extreme parameter values no longer produce Inf/NaN fits, gradients, or Fisher information (results unchanged in the normal regime). Long state-space enumerations can now be interrupted. o Raw data are now validated against the responses argument (stray values error instead of silently biasing the fit); only missing = "listwise" is supported and other options error at construction; the free inverse temperature beta is now bounded at 0; groupequal("delta") now correctly frees the group-specific beta in Blume-Capel models. o TIME SERIES / PANEL MODELS: o Fixed sigma_within (and sigma_crosssection) reporting in dlvm1-family models: the between-person residual covariance was added instead of the within-person residual covariance (estimation was not affected). o ri_clpm stationarity constraints ("innovation"/"contemporaneous") now select parameters structurally per wave; pruned/fixpar'd models previously produced corrupted equality constraints and now constrain correctly or stop with an informative error. Unpruned behavior unchanged (wave 1 and the random-intercept block remain free). o tsData(): grouped data previously ignored lags, scale, center and centerWithin; lags other than 1 erroneously produced lag-1 columns. Both fixed. var1()/gvar() gain a centerWithin argument (default FALSE). o ml_lvm: variable names containing regex metacharacters (e.g. "y.1") are no longer silently dropped (same fix in dlvm1/ri_clpm wide matching); the C++ implied structure now correctly subsets by the design matrix for incomplete designs, matching the R implementation; the default vars now excludes the groups column. dlvm1-family constructors error informatively with fewer than two waves. dlvm1 "version2" start values now use the between-person residual covariance estimate for epsilon_between. o META-ANALYTIC MODELS: o meta_varcov now genuinely supports covariance matrices as input (covs= defaults to corinput = FALSE as documented); previously covariances were silently modeled as correlations and corinput = FALSE crashed. o New Vmethod options "OS_individual" and "OS_pooled" in meta_varcov: the Olkin-Siotani (1976) sampling covariance of sample correlations (validated against metaSEM::asyCov), recommended when heterogeneity (random-effects) variances are of substantive interest. The default Vmethod is unchanged for backward compatibility with published analyses. o Fixed meta_varcov/meta_ggm with estimator = "ML" and meta_lvm with residual = "prec" crashing at the first gradient evaluation. Fixed bivariate (single-correlation) meta_varcov crashing at construction. Meta models now error informatively when two variables are never observed together in any study. meta_lvm uses the C++ Jacobian for the Fisher information when cpp = TRUE. o PERFORMANCE: o The joint equality score test used by addMIs/runmodel on multi-group models factorizes the bordered information system once: up to several hundred times faster on large equality-constrained models (identical results). The matrices argument of addMIs() is now implemented. o Commutation matrices are constructed directly in sparse form and, with the other algebra helper matrices, cached per dimension: substantially faster model construction (about 3x for a 30-node GGM). The sparse Fisher-information path is now reachable for sparse model Jacobians. o Ising state enumeration avoids per-state matrix copies and the log-likelihood reuses the prepared partition function (about 1.3-1.6x faster Ising runmodel). Plus assorted micro-optimizations. o INFRASTRUCTURE, DOCUMENTATION AND TESTS: o Added an automated test suite (tinytest) covering the psychonetrics.org examples plus targeted regression tests for the fixes in this release, with reference values cross-checked against lavaan. tinytest added to Suggests; removed unused dependencies GA, combinat, VCA and abind. o loop_psychonetrics() and replicator() gain a seed argument for reproducible (parallel) simulations; aggregate_bootstraps()'s remove_problematic argument is now respected. o Large documentation cleanup: fixed a broken example in partialprune.Rd, corrected the documented MIs() type values, documented lambda = "full", corrected Cholesky equations and stale paragraphs in the family pages, added missing \value sections, fixed broken examples, removed the unimplemented "MUML" option from ml_lvm(), added a ggplot2 guard to CIplot(), and fixed many typos. o Added inst/COPYRIGHTS and a DESCRIPTION Copyright field documenting the bundled LBFGS++ (MIT) headers; removed a linker flag that stripped debug symbols (CRAN policy); dev-checklist files excluded from the build. Changes in Version 0.15.29 o Bugfix: the "loadings" identification used by lvm(), ml_lvm(), dlvm1() and tsdlvm1() could silently overwrite a user-fixed (or built-in) nonzero factor loading. To identify a factor's scale the identifier fixed the first "eligible" loading in each column to 1, where "eligible" included loadings already FIXED at a nonzero value. When the first such loading was fixed at a value other than 1, it was overwritten -- changing the model. This notably affected latentgrowth() with non-default time scores: e.g. latentgrowth(vars, data, time = c(0,2,4,6)) had its slope loadings altered from 0,2,4,6 to 0,1,4,6, fitting a different growth model. The identifier now skips a factor whose column already contains a fixed nonzero loading (the scale is already identified) and otherwise fixes the first FREE loading to 1. Standard CFA behaviour (first free loading fixed to 1) is unchanged, and a user-supplied marker loading fixed at any nonzero value is now preserved. Changes in Version 0.15.28 o Bugfix: the multi-level latent variable model (ml_lvm) analytic Jacobian omitted the derivative of the implied means with respect to the between-subject regressions (beta_between). The implied mean is mu = nu + lambda %*% (I - beta_between)^-1 %*% nu_eta, which depends on beta_between whenever the latent intercepts nu_eta are nonzero, but the d/d-beta_between block of the mean rows was never filled (in both the R and C++ derivative paths). This produced an incorrect gradient/Jacobian column for any ml_lvm with free between-subject regressions and free (nonzero) latent means -- reachable since the 0.15.18 nu_eta identification fix. The analogous block is now filled via d_mu_beta_lvm() / d_mu_beta_lvm_cpp(), matching the single-level lvm. Within-cluster latents have mean zero, so beta_within correctly contributes no mean term. Changes in Version 0.15.27 o Bugfix: runmodel(addInformation = FALSE) crashed the whole call in the C++ standard-error path with "Mat::operator(): index out of bounds". addSEs_cpp() read the @information slot unconditionally, but with addInformation = FALSE that slot is empty (a 0x0 matrix), so indexing into the inverted matrix went out of bounds. It now recomputes the Fisher information on demand when the slot is absent, mirroring getVCOV(). The R getVCOV() path had the same latent bug -- its is.null() check never fired for the default empty "matrix" slot, silently returning all-NA standard errors -- and now also treats a zero-size information matrix as absent. Both paths produce identical, correct SEs. Changes in Version 0.15.26 o Bugfix: changedata() unconditionally accessed colnames(data), so the documented summary-statistics usage changedata(x, covs=, nobs=) crashed with 'argument "data" is missing'. The data-dependent label check is now guarded, and the covs/means/nobs input path is forwarded to samplestats() and the baseline/saturated constructors, mirroring how the model constructors accept either raw data or summary statistics. o Bugfix: changedata() always recomputed @sample@nobs including the mean block (nVar*(nVar+1)/2*nGroup + nVar*nGroup), which corrupted the degrees of freedom for models built with meanstructure = FALSE (e.g. a saturated model reported df = 4 instead of 0). The mean block is now counted only when the model has a mean structure, matching bootstrap() and the model constructors. Changes in Version 0.15.25 o Bugfix: transmod() attached incorrect standard errors and p-values to the transformed model (e.g. transmod(type="ggm") on a covariance model, or the reverse). The transformed estimates were correct, but addSEs() reused the Fisher information copied verbatim from the original model - which still described the pre-transformation parameterization - because getVCOV() reuses a model's stored @information whenever it is non-NULL. transmod() now recomputes the Fisher information on the transformed model before adding standard errors, so the SEs and p-values match those of an equivalent model fit directly. Point estimates are unchanged. Changes in Version 0.15.24 o Bugfix: in multi-group models, the type="free" and type="equal" modification index passes in addMIs() wrote their expected parameter changes to the "normal" epc column instead of epc_free and epc_equal. As a result, in any multi-group runmodel() (which runs normal -> free -> equal passes) the normal EPC column was overwritten twice while epc_free and epc_equal remained NA. MIs(type="free") and MIs(type="equal") now report their correct EPC columns, and the normal EPC is no longer clobbered. Single-group results are unchanged. Changes in Version 0.15.23 o Bugfix: bootstrap() resampled rows from the pooled data, ignoring the grouping structure of multi-group models. This had three consequences: (1) resampling was not stratified, so group sizes drifted between replications; (2) the rebuilt sample derived its group order from the first resampled row, which - whenever that row belonged to a different group than the original first group - permuted the group ids relative to x@parameters, so a group's parameters were fit to another group's data (e.g. a two-group model with very different group means produced nonsense estimates and failed to converge); and (3) the recomputed @sample@nobs always included a mean block, corrupting the degrees of freedom for meanstructure = FALSE models. bootstrap() now resamples within each group (preserving group sizes), rebuilds the data in the original group order so group ids stay aligned with the parameter table, and computes nobs as nVar*(nVar+1)/2*nGroup + meanstructure*nVar*nGroup (matching the model constructor). Single-group models are unaffected. Changes in Version 0.15.22 o Bugfix: for multi-group Ising() and BlumeCapel() models specified as Ising(data, groups = "group") without an explicit 'vars' argument, the grouping column was included when auto-detecting the response options (and in the 'min_sum' sum-score check). With numeric group codes this silently added the codes as extra response options - e.g. binary 0/1 data with a numeric group column was fit as a 3-state {0,1,2} model, giving wrong thresholds - and with character group labels it failed later with an opaque type error. The grouping column is now excluded from the response detection and the min_sum check (matching how samplestats() derives 'vars'), and a non-numeric response set is now rejected up front with a clear error message. Single-group models, and models with explicit 'vars' or 'responses' arguments, are unaffected. Changes in Version 0.15.21 o Bugfix: the C++ derivative routine for variance-covariance models (used by the gradient and Fisher information when cpp = TRUE) wrote the precision-matrix (kappa) derivative block into the wrong Jacobian columns: it reused the row offset of the variance block instead of the parameter- column offset. When the mean structure was present this happened to coincide with the correct columns, but for precision() models fitted without a mean structure (e.g. precision(covs = S, nobs = n) or precision(data, meanstructure = FALSE)) the column indices exceeded the width of the Jacobian and Armadillo aborted with "Mat::submat(): indices out of bounds" for every estimator. The column range now matches the sigma/cholesky blocks (and the R implementation). precision() models without a mean structure now run; mean-structure models are unaffected. Changes in Version 0.15.20 o Bugfix: standard errors for the ULS and DWLS estimators (used e.g. for ordinal data via estimator = "DWLS"/"WLSMV") were computed with the naive (Delta'WDelta)^-1 / n formula, which is only correct when the weight matrix W equals the inverse of the asymptotic covariance Gamma of the sample statistics. For ULS and (especially) DWLS this is not the case, so the reported standard errors were biased (e.g. ordinal DWLS loading and threshold SEs deviated by roughly 10-12% from lavaan's robust WLSMV standard errors, while the point estimates matched). psychonetrics now computes the robust sandwich covariance (Delta'WDelta)^-1 (Delta'W Gamma W Delta) (Delta'WDelta)^-1 / n for ULS and DWLS, matching lavaan's se = "robust" output. Full WLS (W = Gamma^-1) and the ML/FIML estimators are unaffected, as the sandwich reduces to the naive form there. When Gamma is unavailable (for instance when a model is fit to a covariance matrix rather than raw data) the non-robust standard errors are returned together with a warning. The robust covariance also propagates to confidence intervals, prune() and all other consumers of the parameter standard errors. Changes in Version 0.15.19 o Bugfix: for multi-group models with ordinal data (e.g. ggm() and other models with ordered = ... , groups = ... and estimator = "WLS"/"DWLS"), the per-group polychoric correlations, thresholds and WLS weight matrices were computed on the full pooled sample instead of each group's own rows. Every group therefore received identical (pooled) sample statistics, so multi-group ordinal models were silently fit to pooled data. Each group is now correctly computed from its own observations. Single-group ordinal models and continuous (non-ordinal) multi-group models were unaffected. Changes in Version 0.15.18 o Bugfix: the identification routine for the multi-level latent variable models (ml_lvm() and the ml_lnm/ml_rnm/ml_lrnm wrappers) referred to the latent-intercept matrix by the wrong name ("mu_eta" instead of "nu_eta"), so the latent intercepts were never fixed for identification. This left the mean structure rank-deficient: latent-intercept standard errors were nonsensical (~1e6) and the model degrees of freedom were inflated. The latent intercepts are now correctly fixed (in group 1 only for multi-group models, as for lvm()), matching the corresponding two-level SEM. Estimates and log-likelihood of previously fitted models are unaffected; only the standard errors and degrees of freedom change. Changes in Version 0.15.17 o BlumeCapel() now gives an error (instead of a warning) when fewer than three response options are supplied. With only two responses the quadratic 'delta' term is not identifiable (x^2 is constant across the two states), so it is confounded with the thresholds; use Ising() for binary data. Changes in Version 0.15.16 o New function allequal(): constrains all free elements of a model matrix to be equal within each group (a single shared parameter per group), separately per group (not across groups; use groupequal() in addition for that). Useful e.g. to model all thresholds (tau) or all Blume-Capel quadratic potentials (delta) equal, or to fit an equal-edge-weight network (omega). Optional 'row', 'col' and 'group' arguments restrict which elements/groups are affected. Changes in Version 0.15.15 o New model: BlumeCapel(). The Ising distribution has been generalized to the 'Spin' distribution, which adds a per-node quadratic potential delta: P(X = x) propto exp( sum_i tau_i x_i - sum_i delta_i x_i^2 + sum_{i expected_hessian_Ising_full_cpp). The previous path made an R callback to expected_hessian_Ising_group, which itself called IsingSampler::IsingLikelihood (one full state enumeration plus materialization of a 2^N x N states matrix) and then expHessianCpp (which made three more passes through all 2^N states: expHcpp, expH2cpp, and the main moment-accumulation loop). The new single-pass implementation also fills only the canonical lower-tri shapes of the 3rd- and 4th-order moment tensors that the Hessian assembly actually reads, eliminating the O(2^N N^4) dense fill in favour of O(2^N N^4 / 8). Per-call benchmarks (multi-group Ising): N=10 G=2 : 11.8x N=12 G=2 : 21.2x N=14 G=2 : 28.2x End-to-end partialprune() at N=15 G=2 (sample 800/group) drops from ~700s (0.15.7) to ~43s. Output is bit-identical (max abs diff in the @information slot: 6.7e-16, machine epsilon). The R-level expected_hessian_Ising / expected_hessian_Ising_group functions and the Rcpp::export expHessianCpp are kept as-is for callers outside the cpp Fisher-information path. Changes in Version 0.15.8 o partialprune() gains an 'identify' argument (default TRUE) that is threaded through prune(), unionmodel(), intersectionmodel(), groupequal(), and groupfree(). Setting identify = FALSE prevents identify() from being called on the intermediate models, so user- fixed parameters (e.g. fixpar(\"beta\", 1, 1, value = 1) in a multi- group Ising) are not re-freed when omega equality constraints are introduced. Default behavior (identify = TRUE) is unchanged. Changes in Version 0.15.7 o Performance: partialprune() inner refits skip addMIs(). The repeat-loop only consumes the BIC and the joint score-test statistic mi_free_joint, so addMIs's three Fisher-information builds (type = normal / free / equal) are wasted on every iteration. mi_free_joint is repopulated directly via .equalityScoreTestInner(joint_only = TRUE) on each candidate fit so the next selection still has the data it needs. addSEs and addInformation are kept enabled because the post-loop prune() reads p-values (from addSEs) and @information (from addInformation) on the final curMod; disabling them changed the post-loop prune behavior on multi-group cases where the inner loop iterated more than once. For useMIs = "simple" we fall back to a full addMIs() call inside the loop so the legacy per-parameter mi_free column is still populated (the simple branch reads it). Final partialprune() output is unchanged: the user-facing returned model is produced by the regular post-loop runmodel() / prune() chain, which uses default flags and populates MIs / SEs / @information. Changes in Version 0.15.6 o Performance: addMIs() now skips the univariate score-test loop in .equalityScoreTestInner() (added in 0.15.4), which was computed on every runmodel() call but never consumed -- only the joint score-test statistic populates the parameter table. The univariate output is still produced on demand when equalityScoreTest() or MIs(type="free") are called. partialprune() no longer pays this cost on every inner refit. Speedup scales with the number of groups: ~1.2x for G=2, ~1.5x for G=3, ~2.5x for G=4 on a small Ising example. Final partialprune() output is bit-identical to 0.15.5. Changes in Version 0.15.5 o partialprune() gains a new argument release_model = c("pruned", "saturated"), defaulting to "pruned". This changes the alternative model used in the stepwise BIC comparison when deciding whether to release an equality constraint: with "pruned" the just-released parameter is immediately fixed to zero in any group where the initial per-group prune (Step 1) had already removed it, before refitting and comparing BIC. The equality-constrained model is therefore tested against the asymmetric structure suggested by the initial per-group prune rather than against a fully saturated per-group alternative, which improves specificity at low sample sizes. Set release_model = "saturated" to reproduce the 0.15.4 behavior. Changes in Version 0.15.4 o New function equalityScoreTest() that computes the score (Lagrange multiplier) test for cross-group equality constraints in a multi-group model. Returns both per-group univariate score statistics and a joint multivariate score statistic (one per equality-constrained parameter, df = G - 1). With the default method = "jacobian" the test reproduces lavaan::lavTestScore exactly (to numerical precision) for both balanced and unbalanced multi-group samples. A faster method = "schur" alternative is available for complex models; it inverts only the smaller "currently free" block of the information matrix and matches lavaan in balanced samples. o The parameter table now carries three new columns: mi_free_joint, pmi_free_joint, and df_free_joint, populated whenever modification indices of type "free" are computed. o MIs() now prints two tables for type = "free": the existing summed per-group univariate statistics (header updated to "Top N summed equality-free modification indices") and a new "Top N joint equality-free modification indices" table based on the multivariate score test. o partialprune() gains a new argument useMIs = c("joint","simple"). The default "joint" ranks candidate equality releases by the joint score test (correctly accounting for cross-group covariance for G >= 3). Set useMIs = "simple" to reproduce the psychonetrics <= 0.15.3 behavior of summing per-group univariate MIs. The two options are equivalent for two-group models. Changes in Version 0.15.3 o Fixed meta_ggm() crashing with "non-numeric argument to mathematical function" when using Vestimation = "per_study". The SRMR computation in addfit() assumed sigma was a numeric matrix, but for meta_varcov models with per-study estimation it is a list of per-study matrices. SRMR now gracefully returns NA for such models. o Fixed stepup() breaking equality constraints set by groupequal() in multi-group models (GitHub issue #50). stepup() previously relied on the @equal slot to detect cross-group equality constraints, but groupequal() never populated it, so stepup() always freed parameters for a single group - silently breaking the constraint. stepup() now infers equality constraints directly from the parameters table (shared non-zero par indices), which is the canonical representation. groupequal() and groupfree() also now maintain the @equal slot for backwards compatibility with model reconstruction code. o stepup(greedy = TRUE) now falls back to the non-greedy path when any searched matrix has cross-group equality constraints. The greedy branch previously bypassed freepar()/groupequal() and assigned unique par indices to each added parameter, which would silently break equality constraints. Single-group models and multi-group models without equality constraints take the fast greedy path as before. Changes in Version 0.15.2 o Fixed incorrect (negative) chi-square and fit indices for FIML estimation with high-dimensional panel data. By default, the saturated model is still estimated numerically (using nlminb for robustness), but if the optimizer fails (saturated LL < model LL), the saturated log-likelihood is now automatically computed analytically from pattern-specific sample statistics, following the approach used by lavaan and Mplus. o Added 'saturated' argument to runmodel() with options "default" (model-based with automatic analytical fallback), "analytic" (skip optimization, use analytical formula directly -- recommended for high-dimensional panel data), and "model" (force numerical optimization with no fallback). Changes in Version 0.15.1 o panelgvar() and panelvar() now accept both wide-format (design matrix) and long-format (character vector of variable names) data, matching the flexibility of the underlying dlvm1(). Previously these convenience wrappers only accepted wide-format data. For long-format usage, pass vars as a character vector and provide idvar (and optionally beepvar) via ... (GitHub issue #48). o Updated dlvm1 family documentation to reflect long-format support in panelgvar() and panelvar(), with examples. o Replaced all Rf_error() calls in C++ code with Rcpp::stop() for proper C++ stack unwinding and destructor calls, avoiding potential memory leaks (GitHub issue #49). Changes in Version 0.15 o The package has gone through a large overhaul in the 0.14.x series of package versions. The most important changes are listed below. o Major C++ optimization of the estimation pipeline, resulting in ~45% cumulative speedup. This includes direct parameter-to-matrix mapping, OptimWorkspace caching of constant data across iterations, cache-aware prepareModel to skip redundant computations, and the new LBFGS++ pure C++ optimizer. o Added ordinal data support and WLSMV estimation for the lvm framework. lvm() now accepts ordinal variables via the 'ordered' argument, with WLS, DWLS, and ULS estimators. The WLSMV scaled test statistic (Asparouhov & Muthen, 2010) provides scaled chi-square, scaled RMSEA, and scaled incremental fit indices matching lavaan output. o Restructured dlvm1() to accept both wide-format and long-format data, unifying the interface for panel data models. Deprecated ml_tsdlvm1(), ml_gvar(), ml_var(), and related wrappers in favor of dlvm1() and panelvar() / panelgvar(). o Penalized maximum likelihood (PML) and penalized FIML (PFIML) estimation with automatic lambda selection via EBIC-based grid search. Includes beta_min thresholding, warm starts across the lambda path, and refit() for refitting parameters without regularization. o New meta_lvm() model family for single-stage meta-analytic latent variable modeling (extending the MAGNA framework to CFA/SEM), and new meta_var1() / meta_gvar() for meta-analytic VAR(1) network models pooling temporal and contemporaneous structures across studies. o New write_psychonetrics() function for exporting comprehensive Mplus/LISREL-style output to a text file, intended for supplementary materials in publications. o Standardized input arguments across all model families: new 'cors', 'groupvar', and 'corinput' arguments with consistent validation via standardize_input(). Meta-analytic models now accept raw data input. o Added SRMR (Standardized Root Mean Square Residual) fit measure using Bentler (1995) standardization. Ising models now also compute model-implied means and covariances enabling SRMR computation. o Improved starting values: OLS-based beta starting values for SEM models, fixed the 'equal' argument in multi-group lvm() models. o New loop_psychonetrics() convenience function for parallel bootstrapping and simulations with automatic variable export and progress bars. o Changed default missing data handling to missing = "auto", automatically switching to FIML/PFIML when missing data is detected. o Automatic fallback to approximate standard errors when the Fisher information matrix cannot be inverted. o lvm() now accepts lambda = "full" to specify a full loading matrix where all cross-loadings are free. Requires the 'latents' argument to be specified. FA-based starting values use promax-rotated loadings directly (no permutation matching needed for full lambda). o penalize() now accepts a matrix for the 'lambda' argument, enabling per-element penalty specification: 0 = don't penalize, NA = auto-select via EBIC grid search, numeric > 0 = fixed penalty strength. Parameters that are fixed at zero in the model are automatically freed when a non-zero penalty is specified, combining freepar() and penalize() in one step. Works for both symmetric (e.g., sigma_epsilon) and non-symmetric (e.g., lambda) matrices. o Various bugfixes for Ising Fisher information, dlvm1 Jacobian construction, dplyr/ggplot2 deprecation warnings, and CRAN compliance. Changes in Version 0.14.28 o Ising models now compute model-implied means (mu) and covariances (sigma) from the exact Ising expectations after optimization. This enables SRMR and other residual-based fit measures for Ising models (previously returned NA). The computation uses the existing isingExpectation() C++ function: mu = E[X] and sigma = E[XX'] - E[X]E[X]'. Changes in Version 0.14.27 o Removed roptim-based C++ optimizers (cpp_L-BFGS-B, cpp_BFGS, cpp_CG, cpp_SANN, cpp_Nelder-Mead) from the public interface. These optimizers are no longer available via setoptimizer() or documented in help pages. Users should use "nlminb" (default), "ucminf", "nloptr_TNEWTON", or "LBFGS++" instead. o Replaced deprecated ggplot2::aes_string() calls with ggplot2::aes(.data[[]]) in CIplot() and ESA plot methods. o Fixed delta matrix starting values when using delta_* = "zero": diagonal elements fixed at zero now correctly show est = 0 in the parameter table instead of data-derived starting values. o Added SRMR (Standardized Root Mean Square Residual) fit measure. Uses Bentler (1995) standardization, matching lavaan's default srmr_bentler. Includes mean residuals when a mean structure is present. Under FIML, uses the saturated model's EM-estimated covariance as the observed statistic (matching lavaan's h1 approach). Multi-group models use an N-weighted average across groups. o The 'beta_min' argument in find_penalized_lambda() and runmodel() now accepts "numerical" (default, uses 1e-05), "theoretical" (uses sqrt(log(p)/n)), or a numeric value. The previous default was the theoretical formula; the new default is the fixed numerical threshold. o Added C++ pipeline for meta_var1/meta_gvar models. The C++ implementation (cpp=TRUE, the default) uses OptimWorkspace caching and formModelMatrices_direct for efficient parameter-to-matrix mapping. o C++ implied model (implied_meta_var1_cpp) computes BetaStar, Sigma0, Sigma1, and meta-analytic mu/sigma/kappa entirely in C++. o C++ derivatives (d_phi_theta_meta_var1_cpp) reuse existing var1 C++ derivative helpers for the mean part and varcov helpers for the random effects variance part. o C++ prepare (prepare_meta_var1_cpp) follows the meta_lvm_prepare_cpp pattern with D_c override for the ML gradient. o Registered meta_var1 in all C++ dispatchers: prepareModel_cpp, impliedModel_cpp, psychonetrics_gradient_cpp_inner, and psychonetrics_FisherInformation_cpp_inner. Changes in Version 0.14.26 o New meta_var1() model family: meta-analytic VAR(1) model for pooling temporal and contemporaneous network structures across multiple studies. Uses a one-stage random effects framework. Accepts either raw time-series data (via data + studyvar) or pre-computed Toeplitz covariance matrices (via covs + nobs). o New meta_gvar() wrapper: convenience function that calls meta_var1() with contemporaneous = "ggm" for graphical VAR estimation. o meta_var1/meta_gvar model the stationary covariance (Sigma0) and lag-1 cross-covariance (Sigma1) blocks, excluding the nuisance exogenous covariance block from the Toeplitz matrix. o Derivatives for meta_var1 reuse existing var1 Jacobian helpers (d_sigma0_beta_var1_cpp, etc.) for the mean part, and meta_lvm random effects Jacobians for the variance part. o R-only implementation (no C++ yet); model@cpp is set to FALSE. o If studyvar is not assigned but idvar is, studyvar is set to idvar with a warning. If both are assigned, idvar functions within each study for collating time series. Changes in Version 0.14.24 o Standardized input arguments across model families. All model constructors (varcov, lvm, var1, tsdlvm1, dlvm1, meta_varcov, meta_lvm) now accept a consistent set of input arguments: - New 'cors' argument: supply correlation matrices directly (with 'nobs'). In varcov/meta_varcov, 'corinput' defaults to TRUE. In other families, correlations are treated as covariances with a warning. - New 'groupvar' argument: replaces the deprecated 'groups' argument. If both are supplied, 'groupvar' takes precedence with a deprecation warning. - New 'corinput' argument added to lvm, var1, tsdlvm1, and dlvm1 signatures (errors if set to TRUE, as correlation input is only supported in varcov and meta_varcov). o Meta-analytic models (meta_varcov, meta_lvm) now support raw data input via 'data' + 'studyvar' arguments. Correlation/covariance matrices and sample sizes are computed internally per study. o meta_varcov() now also accepts covariance matrices via 'covs' argument. o meta_lvm() now also accepts correlation matrices via 'cors' argument. o Shared input validation consolidated into standardize_input() helper function, providing consistent error messages for mutual exclusion violations, missing required arguments, and unsupported combinations. o Fixed pre-existing bug in meta_varcov() baseline/saturated model construction where R's missing() function was passed as the 'missing' argument to varcov() instead of a string value. Changes in Version 0.14.23 o Strip debug symbols from compiled shared library via linker flags in Makevars, reducing installed libs/ size on CRAN macOS builds (from ~29MB to ~2MB). o Added C++ pipeline for meta_lvm (implied, prepare, derivatives), providing ~2.8x speedup over the R-only implementation. o Fixed meta_lvm.Rd documentation to match actual function signature. Changes in Version 0.14.22 o meta_lvm() now accepts covariance matrices (not just correlations). The data vector includes diagonal elements (variances) alongside off-diagonal covariances, with free sigma_epsilon diagonal. V matrix computation, implied model, and derivatives updated to handle the full vech (with diagonal). o Fixed checkJacobian() and checkFisher() to respect the model's @cpp slot: models with cpp=FALSE (e.g., meta_lvm) now correctly use R-only fit/gradient/Fisher functions instead of always defaulting to C++ versions. o Fixed R CMD check --as-cran issues: o panelvar()/panelgvar() now handle missing data argument correctly o dlvm1() guards against missing data in auto-detect and samplestats calls o penalty_lambda documentation updated to match code default (NA, not 0) o Removed stray browser() calls from var1 implied and identify functions o Fixed non-ASCII character in NA2020.Rd reference o Removed continuous-data corinput from lvm(): correlations passed as covs are now treated as covariances with free diagonal. Ordinal corinput retained internally. Changes in Version 0.14.20 o Added meta_lvm() function for single-stage meta-analytic latent variable modeling. Combines a latent variable model (CFA/SEM) for the mean structure of pooled covariance/correlation matrices with a random-effects model for between-study heterogeneity. Extends the MAGNA framework to latent variable models. Supports all standard parameterizations for latent (cov/chol/prec/ggm), residual (cov/chol/prec/ggm), and random effects (chol/cov/prec/ggm/cor) structures. Changes in Version 0.14.18 o Standard errors now auto-fallback to approximate SEs when the Fisher information matrix cannot be inverted (e.g., due to zero cells in crosstables in multi-group Ising models). Previously this returned NA standard errors; now approximate SEs are computed automatically with an informative warning Changes in Version 0.14.17 o Fixed the 'equal' argument in multi-group lvm() models: o The equal= argument (e.g., equal="lambda") now correctly constrains parameters across groups o Previously, the equality flag was passed as a positional argument to fixMatrix, causing it to be silently ignored o Additionally fixed corrupted starting values when equal= is used: the lambda structure matrix contains integer codes (>1) for equality constraints, but these were used as multipliers for FA-derived starting values, producing extreme values that prevented convergence o Both loadings and variance identification now work correctly with equal= o Results from equal= now match those from the groupequal() workflow o Added OLS-based starting values for the beta (structural) matrix in lvm()/sem(): o For each endogenous latent, OLS regression on FA-implied latent covariance provides initial beta coefficients o Disturbance covariance (sigma_zeta) is adjusted via (I-B)*Cov(eta)*(I-B)' instead of using the raw FA factor correlations o Guard rails for near-singular covariance, ill-conditioned predictor blocks, extreme coefficients, and near-singular (I-B) o Falls back to previous zero-initialization on any numerical issue o New 'start' argument: "default" for OLS-based, "simple" for zero-initialization o Added loop_psychonetrics() convenience function for parallel bootstrapping and simulations: o Replaces boilerplate of makeCluster / clusterExport / parLapply / stopCluster o Variables referenced in the expression are automatically detected and exported to workers o Uses pbapply progress bars and safe cluster cleanup via on.exit o Works with aggregate_bootstraps() and CIplot() for bootstrap analysis o Added the NA2020 dataset: 8 self-report items (n=501) from Isvoranu (2020) for GGM examples Changes in Version 0.14.16 o Added automatic lambda selection for PML/PFIML estimation via EBIC-based grid search: o New function find_penalized_lambda() searches over a log-spaced grid of 50 lambda values o Lambda now defaults to NA in all model constructors, signaling automatic selection o runmodel() automatically triggers the grid search when NA lambdas are detected o Lambda_max computed analytically from KKT conditions at the null-penalized model o Warm starts across the lambda path for efficient computation o Supports criterion selection: "bic", "ebic.25", "ebic.5" (default), "ebic.75", "ebic1" o Users can still specify a fixed lambda (e.g., penalty_lambda = 0.1) for manual control o Added beta_min thresholding for penalized estimates: o Near-zero estimates below beta_min are set to exactly zero after convergence o Default threshold: sqrt(log(p)/n) where p = number of penalized parameters o Applied both during EBIC evaluation (for degree-of-freedom counting) and on the final model o Reduces numerical noise from ISTA optimizer, improving specificity o Exposed as user argument in runmodel() and find_penalized_lambda() o EBIC for penalized model selection uses unpenalized log-likelihood at penalized estimates (Convention A), with npar = unpenalized free params + nonzero penalized params after threshold o Print and write methods now display lambda search results (selected lambda, criterion value, beta_min) and show "auto (not yet selected)" for models with NA lambda before estimation o NA-safe comparisons throughout the codebase for penalty_lambda column (print, write, refit, penalize, unpenalize, C++ workspace builder) Changes in Version 0.14.15 o Added PFIML (Penalized Full Information Maximum Likelihood) estimator: o Combines FIML with L1/L2 penalty for penalized estimation with missing data o Available for all Gaussian models (varcov, lvm, var1, dlvm1, tsdlvm1) o Uses proximal gradient optimizer (same as PML) o refit() switches PFIML back to FIML for post-selection inference o Changed default missing data handling to missing = "auto" for all Gaussian models: o ML automatically switches to FIML when missing data is detected o PML automatically switches to PFIML when missing data is detected o LS estimators (ULS, WLS, DWLS) default to listwise deletion o Users can still override with explicit missing = "listwise" or missing = "pairwise" o No change for Ising models (missing = "listwise" default remains) o Penalty setup in model constructors now supports PFIML: o estimator = "PML" and estimator = "PFIML" both trigger penalty initialization o Baseline/saturated models use the appropriate unpenalized estimator (ML or FIML) o Added experimental feature warnings for features introduced in the 0.14.x branch: o PML, PFIML, LBFGS++ optimizer, ordinal data in lvm()/varcov(), WLSMV scaled test statistic o Warnings appear once per session and only while version < 0.15 o Users are directed to report unexpected behavior to GitHub issues Changes in Version 0.14.14 o Unified dlvm1() to accept both wide-format and long-format data: o New 'datatype' argument with options "auto" (default), "wide", and "long" o Auto-detects format from 'vars': matrix = wide, character vector = long o New 'idvar' and 'beepvar' arguments for long-format data o Long-to-wide conversion handled internally (previously required ml_tsdlvm1) o Added 'standardize' argument to dlvm1() with options: o "none" (default): no standardization o "z": global z-scores per variable across all waves (does not impose stationarity) o "quantile": quantile normalization across all waves o "z_per_wave": independent z-scores per wave column (imposes stationarity) o Added panellvgvar() as the canonical wrapper for panel latent variable GVAR models o Deprecated functions (still work but emit warnings): o ml_tsdlvm1() - use dlvm1() with long-format data instead o ml_gvar() - use dlvm1() with within_latent="ggm", between_latent="ggm" o ml_var() - use dlvm1() with desired within_latent and between_latent o ml_ts_lvgvar() - use panellvgvar() instead o panel_lvgvar() - use panellvgvar() instead Changes in Version 0.14.13 o Added write_psychonetrics() function for exporting comprehensive model output to a text file: o Produces Mplus/LISREL-style output with logo, sample info, model specification, parameter estimates, fit measures, model matrices, modification indices, and logbook o Intended for sharing as supplementary materials to papers o Supports uncomputed models: shows starting values with clear warnings, omitting SEs, p-values, fit measures, and modification indices o Model matrices section shows only modeled matrices (not derived/implied quantities) o Matrix output uses 2-digit rounding with dots for fixed zeros o Fixed prune() error when no parameters to test in the requested matrix: o adjust_p_values() now correctly returns a numeric vector (not the S4 model object) when nTest == 0 o Fixed backward compatibility for models saved without the WLS.Gamma slot: o Added .hasSlot() guard to prevent "no slot of name 'WLS.Gamma'" warnings Changes in Version 0.14.12 o Added WLSMV scaled test statistic (mean-and-variance adjusted chi-square) for WLS/DWLS/ULS estimators: o Implements the scaled-shifted test (Asparouhov & Muthen, 2010) matching lavaan's WLSMV output o New fit measures: chisq.scaled, df.scaled, pvalue.scaled, chisq.scaling.factor o Scaled incremental fit indices: cfi.scaled, tli.scaled, nfi.scaled, rfi.scaled, ifi.scaled, rni.scaled, nnfi.scaled o Scaled RMSEA: rmsea.scaled o Baseline model also receives scaled test statistic (baseline.chisq.scaled, etc.) o Added WLS.Gamma slot to store the full asymptotic covariance matrix (Gamma) per group o Added LS_Gamma() helper function for computing Gamma from raw data o Scaling factors match lavaan to 6+ decimal places for both ordinal and continuous data o Supports single-group and multi-group models o Changed the default estimator for ordinal data from WLS to DWLS, matching lavaan's convention o Added "WLSMV" as an estimator alias for "DWLS" in lvm() and varcov() o Fixed the DWLS weight matrix for ordinal data: o Previously used diag(Gamma^{-1}) (diagonal of the full inverse), which differs from standard o Now uses 1/diag(Gamma) (reciprocal of the diagonal), matching the lavaan convention o Fixed (n+1)/n scaling bug in ULS fit function, gradient, and expected Hessian (R and C++): o The weight matrix normalisation factor was (n+1)/n instead of 1, causing small systematic bias Changes in Version 0.14.11 o Added corinput support to the lvm framework: o lvm() now accepts a 'corinput' argument to specify that the input is a correlation matrix o When corinput=TRUE, residual variances (diagonal of sigma_epsilon) are derived from the constraint diag(sigma) = 1 o Diagonal sigma_epsilon parameters are fixed and derived in the implied function, not freely estimated o Supports WLS, DWLS, and ULS estimators; defaults to WLS when corinput=TRUE o Variance identification is automatically enforced o Both R and C++ code paths updated (implied and derivatives) o Fixed a bug in the identity weight matrix dimension in samplestats for corinput/meanstructure combinations o Fixed a bug in lvm Jacobian row removal when both corinput=TRUE and meanstructure=FALSE for continuous data Changes in Version 0.14.10 o Added ordinal data support to the lvm framework (Muthen, 1984 three-stage estimator): o lvm() now accepts an 'ordered' argument (character vector or TRUE) to specify ordinal variables o Supports WLS, DWLS, and ULS estimators for ordinal CFA/SEM o Polychoric correlations and thresholds are estimated from ordinal data o Variance identification is automatically enforced for ordinal models o Both R and C++ code paths (implied, prepare, derivatives) handle ordinal/continuous seamlessly o Added nloptr_TNEWTON as a new optimizer, available via setoptimizer(x, "nloptr_TNEWTON"): o Uses NLopt's preconditioned truncated Newton with restarts (NLOPT_LD_TNEWTON_PRECOND_RESTART) o Builds a local quadratic model and solves the Newton system via preconditioned conjugate-gradient o Supports box constraints and analytic gradients o Added nloptr to Imports o Fixed CRAN NOTE: commented out stray std::cout in vendored LBFGS++ header (LineSearchMoreThuente.h) Changes in Version 0.14.9 o Tuned LBFGS++ convergence parameters for better performance on ill-conditioned models: o Switched primary convergence criterion from gradient norm to relative function change (delta = 1e-8), matching nlminb behavior o Increased L-BFGS history size from 6 to 10 for better Hessian approximation on larger models o Relaxed gradient tolerance (epsilon = 1e-5) to avoid unnecessary iterations on ill-conditioned FIML problems o ~4x faster on complex dlvm1/panel models (e.g., 8.6s -> 2.0s on 84-parameter panelgvar) o Removed unused variable declarations to eliminate all compiler warnings from psychonetrics C++ source Changes in Version 0.14.8 o Added LBFGS++ (LBFGSpp) as a new pure C++ optimizer, available via setoptimizer(x, "LBFGS++"): o Vendored header-only LBFGS++ library (MIT license) into inst/include/ o Combined function+gradient evaluation exploits the prepareModel cache for efficiency o ~1.6x faster than the existing roptim-based cpp_L-BFGS-B optimizer on benchmark models o Added RcppEigen to LinkingTo for Eigen header support Changes in Version 0.14.7 o Fixed R CMD check --as-cran issues: o Guarded semPlot example with requireNamespace() since it is a Suggested package o Replaced defunct dplyr::summarize_each_() with summarize(across()) in lvm example o Added build artifacts and non-package files to .Rbuildignore Changes in Version 0.14.6 o Fixed Ising model Fisher information for the beta (inverse temperature) parameter: o Added missing beta factor in beta-threshold and beta-network cross-derivative blocks of the expected Hessian o Fixed expectedmodel() to replace sample sufficient statistics with model-implied expectations for Ising models Changes in Version 0.14.5 o Optimized dlvm1 Jacobian construction (d_phi_theta_dlvm1_group_cpp): o Added dense Kronecker helpers (kronecker_I_X_dense, kronecker_X_I_dense) to avoid slow sparse element-by-element insertion when the result is used as a dense matrix o Precompute the constant "between" Kronecker block once instead of recomputing it for every lag o Pre-extract all grouplist values before the loop to eliminate repeated string-based hash lookups o Fixed copy-paste bug: removed duplicate Jac.submat write for sigma_zeta_between in the lag loop Changes in Version 0.14.4 o Fixed dplyr 1.1.0 deprecation warning about one-column matrices in filter() calls Changes in Version 0.14.3 o Cache-aware prepareModel_cpp: skip redundant prepare when fit and gradient are called at the same parameter vector o ~24% speedup in full model fitting (e.g., 9-variable CFA: ~155ms -> ~118ms) Changes in Version 0.14.2 o Expanded OptimWorkspace to cache all constant S4 model/sample data (extramatrices, types, sample stats, etc.) o All prepare_*_cpp and implied_*_cpp_core functions now read from cached workspace instead of S4 slots o prepareModel_cpp post-processing now reads from workspace instead of S4 slots Changes in Version 0.14.1 o Performance optimization: replaced O(nMat * nPar) parameter-to-matrix mapping with O(nFreePar) direct index mapping o Eliminated S4 model cloning during optimization iterations by bypassing updateModel_cpp in all prepare functions o Refactored all 8 implied_*_cpp functions into _core variants that accept pre-formed matrices o All 8 prepare_*_cpp functions now use formModelMatrices_cpp_direct + implied_*_cpp_core pipeline o Added OptimWorkspace: static cache for MatrixMapping, M matrix, and parameter indices across optimization iterations o ~25% speedup in full model fitting (e.g., 9-variable CFA: ~200ms -> ~155ms) Changes in Version 0.13.2 o Fixed a bug in 'intersectionmodel' not properly clearing removed parameters o Improved starting values for identity model in partialprune o Fixed a bug in partialprune resulting in an uninformative error o Switch from deprecated arma::is_finite() to std::isfinite() Changes in Version 0.13.1 o Bootstrapping now occurs before standardizing the data (thanks to Yiwei Yang and Amanda Montoya) o Improved support for N=1 models in dlvm1 (e.g., for true ML estimation) o Fixed a bug with missing values in the beta starting values matrix for dlvm1 models o Changed partialprune() default for 'return' to "partialprune"; set to "best" to mimic old behavior o Added 'final_prune' argument to partialprune() and changed the default to "saturated"; set to "partialprune" to mimic old behavior Changes in Version 0.13 o Added bootstrap support: o Every model now supports 'bootstrap' (to enable bootstrap), 'boot_sub' (for subsampling) and 'boot_resample' (to resample) o Enabling these will bootstrap the data *once* and create a psychonetrics object for the bootstrap sample o The function 'aggregate_bootstraps' can be used to aggregate bootstraps: o use print(...) for some general info o use parameters(...) for the bootstrap results on the parameters o use fit(...) for the bootstrap results on the fit indices o use CIplot(...) for the bootstrap results on the confidence intervals (enable split0=TRUE if model selection is used) Changes in Version 0.12 o Updates for the dlvm1 model family: o Changed the starting values for dlvm1 models for better convergence o Added the 'start' argument to the dlvm1 model family. Use start = "version1" to use pre 0.12 start values o Added the 'baseline' argument to dlvm1 model family, which now defaults to "stationary_random_intercept". Note: this will change incremental fit indices! To recover old behavior, set baseline = "independence" o The log(det(kappa)) value used in fit function is now computed in FIML in the same way as computed in ML framework, this should lead to more stability, but might also lead to some different chi-square values o The startreduce argument in prune() now defaults to 1 o Using "empty" for matrix specification is now deprecated; use "diag" or "zero" instead. o getmatrix will no longer evaluate a model if it is not computed (now returns start values) o the 'startreduce' argument in 'prune' now defaults to 1 o Added the 'fixstart' function that can aide in fixing startvalues o The 'getmatrix' function now supports thresholded PDC matrices o Diagnostic functions 'checkJacobian' and 'checkFischer' are now exported o Added the transmod function, which can be used to transform one model type (e.g., using a Cholesky decomposition) to another model type (e.g., a GGM). o Improved support for models with only one (latent) variable o Added the 'logbook' function which can be used to more easily retrieve the psychonetrics logbook o The 'partialprune' function has been updated and now allows for pruning specific matrices as well as returning different models o Fixed some instances where the 'equal' argument wasn't working o 'partialprune' now supports multiple matrices o 'unionmodel' and 'intersectionmodel' now support the 'matrices' argument o Changed lambda starting value choice to the following: Run an EFA, set the starting values to the loadigs of the factor that has the strongest loadings in the indicators, and set correlations between factors that use the same EFA factor for starting values to 0.8 o added warning for non computed model in parameters() Changes in Version 0.11.5 o Fixes to support Matrix 1.7-0 o The groupequal, groupfree, fixpar and freepar functions can now handle multiple rows/columns for symmetric matrices o Fixed a bug in the identification function for ml_lvm models o Implemented min_sum argument for estimating Ising models on data with a minimum sum score due to selection bias. This method is further discussed in Boot, de Ron, Haslbeck & Epskamp (in preperation). Correcting for selection bias after sum score selection in the Ising model. o The 'warn_improper' argument in runmodel now defaults to FALSE, omitting the warning that a non-positive defnite matrix was encountered in parameter estimation. o SEs are now set to NA if the Fischer information matrix could not be inverted normally o Added an argument 'approximate_SEs' to runmodel to allow for SEs to be approximated using a pseudoinverse Changes in Version 0.11 o Optimised lambda starting value choice o Changed warning for when a peusdoinverse was used in model estimation. o Added 'threshold' argument to the matrix(...) function for significance thresholding o Fixed a bug in psychonetrics:::emergencystart Changes in Version 0.10.3 o Added a 'bootstrap' argument to var1() family to facilitate bootstrapping the data o Fixed a bug where the saturated log-likelihood under FIML estimation could be incorrect Changes in Version 0.10.2 o Built in a check to find NA sample covs o added diag argument to getmatrix to obtain diagonal o diagonal elements are now also thresholded when using getmatrix(..., threshold = ...) o Added 'threshold' argument to getmatrix() o Adjusting p-values is now done by default only for the tested p-values. This means that the number of tests is assumed to be the number of parameters of interest (matrices that are to be pruned), not the total number of parameters. Previous behavior can be reproduced with mode = "all" in prune(..). o panelvar and panelgvar now support arguments within_latent and between_latent Changes in Version 0.10.1 o Fixed a bug in 'prune' which did not allow intercept/mean vectors to be pruned Changes in Version 0.10 o ml_tsdlvm1 now orders data by idvar if beepvar is not supplied. o Added 'CIplot' function o Standardizing in ts_dlvm1 is now more stable. o dlvm1 now uses observed variable names as latent variable names when appropriate. o Fixed a bug with the beepvar argument in psychonetrics Changes in Version 0.9: o Changed 'rel.tol=1e-10' in the nlminb optimizer to be in line with lavaan o Added 'warn_improper' argument to runmodel(..) o The argument 'return_improper' now defaults to TRUE o Optimizer no longer uses a spectral shift when inverting a semi-positive definite matrix o Detection of non positive definite matrices is now done faster and should lead to less problems o Added the 'bounded' argument to runmodel() to define if bounded estimation should be used (defaults to TRUE) o Diagonals of symmetrical matrices can no longer be estimated to be negative (avoiding Heywood cases, although doing this with a Cholesky decomposition is nicer!) Changes in Version 0.8.1: o The nlminb estimator now uses more iterations. Changes in Version 0.8: o The log determinant is now computer better to be able to include fit measures at higher model complexities o The 'return_improper' argument in runmodel( ) now returns improper estimates without trying different starting values o Fixed a bug in meta_varcov when using individual estimates of the sampling variation o Updated optimizer default control parameters Changes in version 0.7.6: o Model estimations that used improper estimation (pseudoinverse of variance-covariance matrix) now return with an error unless return_improper = TRUE in runmodel() o Equality-free MIs are now also computed when all edges are included Changes in version 0.7.5: o Fixed a bug with nu_zeta being constrained in multigroup LGC models. o factorscores now supports multi group models Changes in version 0.7.3: o Added the 'covariates_as' argument to latentgrowth() to model covariates with regressions (now default) or covariances Changes in version 0.7.2: o Fixed a bug with removing diagonal elements of sigma_epsilon with single indicators o Fixed another bug with models with only one free indicator o Added the partialprune function for partially pruning multi-group models Changes in version 0.7.1: o Fixed a bug for Solaris Changes in version 0.7: o Major changes o Major restructuring of underlying core code. Most vital functions have been translated to C++, leading to a large speedup! o Added C++ based optimizers cpp_L-BFGS-B, cpp_CG, cpp_SANN, and cpp_Nelder. These are faster but slightly less stable than nlminb (now the default optimizer). o Verbose now defaults to FALSE everywhere. This can be set with the setverbose function for a model o Added meta-analysis model for varcov family (meta_varcov) o The ml_tsdlvm1 function now allows for multi-kevek tsdlvm1 models (dlvm1 models) to be specified using syntax familiar to those using mlVAR and graphicalVAR o Minor changes o Numerous small bugfixes and improvements (e.g., better starting values) o Added function 'fullFIML' to use true FIML computing the likelihood per row o Changed 'WLS.V' to 'WLS.W' o Several warning messages have been updated Changes in version 0.6: o The 'dlvm1' model family now also returns the implied latent variance-covarriance matrix as 'sigma_eta_within' o The latent lag-1 matrix is also returned as 'sigma_eta_within_lag1' o The dlvm1 model family now no longer requires a 'lambda' matrix to be specified (will default to a panelvar model) o Most model families now support the 'standardized' argument, which can be set to 'z' for z-scores (helps convergence) or 'quantile' for a semiparametric transformation o Added the ml_lvm family for two-level random intercept latent variable models o Added the simplestructure function to easily make a lambda matrix o addalpha in modelsearch now works as expected o addalpha and prunealpha now default to 0.01 in 'modelsearch' o recursive now defaults to FALSE in 'prune' Changes in version 0.5.1: o Fixed a bug with responses being missing when summary statistics are used in Ising() o Fixed a bug with covtype sometimes being set to UB when corinput = TRUE o Added DOI to description field Changes in version 0.5.0: o The Ising model is now supported (only ML estimation) through the Ising() model function o Added the covtype option to several models, controlling if maximum likelihood or unbiased estimates are used for the input covariances o Added the function 'covML' for maximum likelihood covariance estimates Changes in version 0.4.1: o Small fix for CRAN checks Changes in version 0.4: o type = "cor" is now supported in varcov, with rho representing the correlations and SD the diagonal standard deviations matrix. o The 'corr' function is now implemented as shorthand for varcov(..., type = "cor") o The scale of the Fisher information matrix has been adjusted to portray unit information to be similar to Lavaan o The getVCOV function has been added to obtain the estimated asymptotic var-cov matrix of the parameters. o The meanstructure can now be ignored using meanstructure = TRUE in the following model families: - varcov o A correlation matrix can now be used as input (detected or set with corinput = TRUE) for the following families: - varcov (type = "ggm" and type = "cor") o The WLS estimator will now not investigate means when meanstructure is ignored, and variances when a correlaton matrix is used as input. - The WLS weights matrix must be of the appropriate dimensions! - The WLS.V matrix will no longer be adjusted for missing means. - Added 'startEPC' argument to stepup and freepar o Added the 'modelsearch' function for extensive stepwise model search o Fixed several bugs and improved starting values in several models Changes in version 0.3.3: o prune() now removes diagonal values of temporal effects o psychonetrics now requires R 3.6 o Some C++ fixes for Solaris Changes in version 0.3.2: o The parameters function now invisibly returns the parameter estimate data frame o The MIs function now invisibly returns a data frame with MI estimates o fit now invisibly returns a data frame with fit measure estimates Changes in version 0.3.1: o Several help-files are now updated with executable examples Changes in version 0.3.0: o First version to be submitted to CRAN