15 std::shared_ptr<spdlog::logger>
logger = spdlog::get(
"citlali_logger");
38 template <
typename Derived>
41 Eigen::VectorXd ev = evals.derived().array().abs().log10();
43 auto n_dets = evals.size();
45 auto m_ev = ev.mean();
49 bool keep_going =
true;
50 int n_keep_last = n_dets;
53 Eigen::Matrix<bool,Eigen::Dynamic,1> good(n_dets);
60 for (Eigen::Index i=0; i<n_dets; i++) {
71 if (count >= n_keep_last) {
77 for (Eigen::Index i=0; i<n_dets; i++) {
85 for (Eigen::Index i=0; i<n_dets; i++) {
87 stddev += (ev(i) - m_ev)*(ev(i) - m_ev);
90 stddev = stddev/(count-1.);
91 stddev = sqrt(stddev);
100 Eigen::Index limit_index = 0;
103 for (Eigen::Index i=0; i<n_dets; i++) {
104 if (evals(i) <= limit){
114 template <EigenSolverBackend backend,
typename DerivedA,
typename DerivedB,
typename DerivedC>
115 auto calc_eig_values(
const Eigen::DenseBase<DerivedA> &,
const Eigen::DenseBase<DerivedB> &, Eigen::DenseBase<DerivedC> &,
119 template <EigenSolverBackend backend,
typename DerivedA,
typename DerivedB,
typename DerivedC,
typename DerivedD>
120 auto remove_eig_values(
const Eigen::DenseBase<DerivedA> &,
const Eigen::DenseBase<DerivedB> &,
121 const Eigen::DenseBase<DerivedC> &,
const Eigen::DenseBase<DerivedD> &,
122 Eigen::DenseBase<DerivedA> &,
const Eigen::Index);
127 Eigen::DenseBase<DerivedC> &apt_flags,
const Eigen::Index group_n_eig) {
130 Eigen::Index n_dets = scans.cols();
133 Eigen::MatrixXd f = abs(flags.derived().template cast<double> ().array() - 1);
138 for (Eigen::Index i=0; i<n_dets; i++) {
139 if (apt_flags.derived()(i)!=0) {
145 Eigen::MatrixXd pca_cov(n_dets, n_dets);
148 auto denom = (f.adjoint() * f).array() - 1;
151 auto det = (scans.derived().array()*f.array()).matrix();
154 pca_cov.noalias() = ((det.adjoint() * det).array() / denom.array()).matrix();
183 Eigen::VectorXd evals;
185 Eigen::MatrixXd evecs;
189 int n_ev = (
stddev_limit > 0 && group_n_eig==0) ? n_dets - 1: group_n_eig;
195 n_cv = n_ev * 2.5 < n_dets?int(n_ev * 2.5):n_dets;
203 Spectra::DenseSymMatProd<double> op(pca_cov);
204 Spectra::SymEigsSolver<Spectra::DenseSymMatProd<double>> eigs(op, n_ev, n_cv);
208 int n_conv = eigs.compute(Spectra::SortRule::LargestAlge);
211 evals = Eigen::VectorXd::Zero(n_dets);
212 evecs = Eigen::MatrixXd::Zero(n_dets, n_dets);
215 if (eigs.info() == Spectra::CompInfo::Successful) {
216 evals.head(n_ev) = eigs.eigenvalues();
217 evecs.leftCols(n_ev) = eigs.eigenvectors();
220 throw std::runtime_error(
"spectra failed to compute eigen values");
226 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> solution(pca_cov);
229 if (!solution.info()) {
230 evals = solution.eigenvalues();
231 evecs = solution.eigenvectors();
233 evals.reverseInPlace();
234 evecs.rowwise().reverseInPlace();
237 throw std::runtime_error(
"eigen failed to compute eigen values");
241 return std::tuple<Eigen::VectorXd, Eigen::MatrixXd> {evals, evecs};
246 const Eigen::DenseBase<DerivedC> &evals,
const Eigen::DenseBase<DerivedD> &evecs,
247 Eigen::DenseBase<DerivedA> &cleaned_scans,
const Eigen::Index group_n_eig) {
250 Eigen::Index n_dets = scans.cols();
253 Eigen::Index limit_index;
259 if (group_n_eig == 0) {
276 limit_index = group_n_eig;
279 logger->debug(
"removing {} largest eigenvalue(s)", limit_index);
282 Eigen::MatrixXd proj = scans.derived() * evecs.derived().leftCols(limit_index);
283 cleaned_scans.derived().noalias() = scans.derived() - proj * evecs.derived().adjoint().topRows(limit_index);