void ifaGroup::detectTwoTier() { int mlen = maxAbilities; if (!twotier || mlen < 3) return; std::vector<int> orthogonal; if (mlen >= 3) { Eigen::Map<Eigen::MatrixXd> Ecov(cov, mlen, mlen); Eigen::Matrix<Eigen::DenseIndex, Eigen::Dynamic, 1> numCov((Ecov.array() != 0.0).matrix().colwise().count()); std::vector<int> candidate; for (int fx=0; fx < numCov.rows(); ++fx) { if (numCov(fx) == 1) candidate.push_back(fx); } if (candidate.size() > 1) { std::vector<bool> mask(numItems()); for (int cx=candidate.size() - 1; cx >= 0; --cx) { std::vector<bool> loading(numItems()); for (int ix=0; ix < numItems(); ++ix) { loading[ix] = param[ix * paramRows + candidate[cx]] != 0; } std::vector<bool> overlap(loading.size()); std::transform(loading.begin(), loading.end(), mask.begin(), overlap.begin(), std::logical_and<bool>()); if (std::find(overlap.begin(), overlap.end(), true) == overlap.end()) { std::transform(loading.begin(), loading.end(), mask.begin(), mask.begin(), std::logical_or<bool>()); orthogonal.push_back(candidate[cx]); } } } std::reverse(orthogonal.begin(), orthogonal.end()); } if (orthogonal.size() == 1) orthogonal.clear(); if (orthogonal.size() && orthogonal[0] != mlen - int(orthogonal.size())) { Rf_error("Independent factors must be given after dense factors"); } numSpecific = orthogonal.size(); if (numSpecific) { Sgroup.assign(numItems(), 0); for (int ix=0; ix < numItems(); ix++) { for (int dx=orthogonal[0]; dx < maxAbilities; ++dx) { if (param[ix * paramRows + dx] != 0) { Sgroup[ix] = dx - orthogonal[0]; continue; } } } } }
void normalToStdVector(omxMatrix *cov, omxMatrix *mean, omxMatrix *slope, omxMatrix *thr, int numOrdinal, std::vector< omxThresholdColumn > &ti, Eigen::Ref<Eigen::VectorXd> out) { // order of elements: (c.f. lav_model_wls, lavaan 0.6-2) // 1. thresholds + means (interleaved) // 2. slopes (if any, columnwise per exo) // 3. variances (continuous indicators only) // 4. covariances; not correlations (lower triangle) EigenMatrixAdaptor Ecov(cov); if (numOrdinal == 0) { int dx = 0; if (mean) { EigenVectorAdaptor Emean(mean); for (int rx=0; rx < cov->cols; ++rx) { out[dx++] = Emean(rx); } } if (slope) { EigenMatrixAdaptor Eslope(slope); for (int cx=0; cx < Eslope.cols(); ++cx) { for (int rx=0; rx < Eslope.rows(); ++rx) { out[dx++] = Eslope(rx,cx); } } } for (int cx=0; cx < cov->cols; ++cx) { out[dx++] = Ecov(cx,cx); } for (int cx=0; cx < cov->cols-1; ++cx) { for (int rx=cx+1; rx < cov->rows; ++rx) { out[dx++] = Ecov(rx,cx); } } return; } if (!mean) Rf_error("ordinal indicators and no mean vector"); EigenVectorAdaptor Emean(mean); EigenMatrixAdaptor Eth(thr); Eigen::VectorXd sdTmp(1.0/Ecov.diagonal().array().sqrt()); Eigen::DiagonalMatrix<double, Eigen::Dynamic> sd(Emean.size()); sd.setIdentity(); int dx = 0; for (auto &th : ti) { for (int t1=0; t1 < th.numThresholds; ++t1) { double sd1 = sdTmp[th.dColumn]; out[dx++] = (Eth(t1, th.column) - Emean[th.dColumn]) * sd1; sd.diagonal()[th.dColumn] = sd1; } if (!th.numThresholds) { out[dx++] = Emean[th.dColumn]; } } if (slope) { EigenMatrixAdaptor Eslope(slope); for (int cx=0; cx < Eslope.cols(); ++cx) { for (int rx=0; rx < Eslope.rows(); ++rx) { out[dx++] = Eslope(rx,cx); } } } Eigen::MatrixXd stdCov(sd * Ecov * sd); for (int cx=0; cx < cov->cols; ++cx) { if (ti[cx].numThresholds) continue; out[dx++] = stdCov(cx,cx); } for (int cx=0; cx < cov->cols-1; ++cx) { for (int rx=cx+1; rx < cov->rows; ++rx) { out[dx++] = stdCov(rx,cx); } } }