feat(edm): implement EDM prediction framework (Simplex, S-Map, GP-EDM) - #1561
Conversation
added the comments to the following files: modified: R/distribution_formulas.R modified: R/fimsfit.R modified: R/initialize_modules.R modified: inst/include/common/information.hpp modified: inst/include/common/model.hpp modified: inst/include/distributions/functors/density_components_base.hpp modified: inst/include/distributions/functors/normal_lpdf.hpp modified: inst/include/interface/rcpp/rcpp_objects/rcpp_distribution.hpp modified: src/FIMS.cpp
- Created rcpp_edm.hpp defining EDMInterfaceBase and DelayEmbeddingInterface wrapper classes. - Exposed the construct(), construct_drop_missing(), and at() methods to R. - Exposed fields/metadata (such as embedding_dimension, time_lag, n_rows, n_cols, values, and target_indices) to R. - Registered the DelayEmbedding class in the RCPP_MODULE(fims) block within fims_modules.hpp.
- Add edm_embeddings list slot to the FIMSFrame S4 class to store delay-embedding results produced by create_edm_embedding() - Add create_edm_embedding() helper that pulls a named time series from the data slot, calls the Rcpp DelayEmbedding module, and returns a new FIMSFrame with the result stored by name - Add get_edm_embeddings() accessor following the existing get_*() pattern in fimsframe.R - Add model_edm_matrix() accessor that returns a numeric matrix (n_rows x E) ready to pass to an EDM prediction module, following the existing model_*() pattern - Register 'edm' as a valid FIMSFrame input type in data-raw/fims_input_types.R and regenerate data/fims_input_types.rda - Add tests/testthat/test-edm-fimsframe.R with 6 test blocks covering default empty slot, error handling, input validation, metadata correctness, matrix shape, and chaining multiple embeddings This completes proposal deliverable: 'Create structures in FIMSFrame for embedded matrices' (Weeks 1-3).
…r review feedback
80c0d37 to
3b443a3
Compare
|
Reverted the S-Map commit temporarily for further review before re-pushing |
|
@stevemunch @nathanvaughan-NOAA while implementing the S-Map predictor, I came across a few design questions where I'd appreciate feedback before I push the implementation. I have currently implemented the standard S-Map formulation described in Section 2.1 of Esguerra & Munch (2024), i.e., the local linear model that serves as the baseline/M-step component of the full HMS-map. For each local neighborhood, the implementation constructs a design matrix: and solves the weighted least-squares system: using a CppAD-safe Gaussian elimination routine. Before finalizing the implementation, I wanted to get your thoughts on a couple of design choices. 1. Weighting Kernel / Distance MetricClassic S-Map implementations (e.g., Sugihara 1994 and rEDM) typically use an exponential kernel based on Euclidean distance: However, Section 2.1 of Esguerra & Munch (2024) defines the weighting function as: which is effectively a Gaussian kernel based on squared Euclidean distance. For the generic FIMS S-Map predictor, would you prefer:
Using squared distances has the additional benefit of avoiding a 2. Target Alignment in Delay EmbeddingThe paper formulates the delay embedding map as a one-step-ahead forecast: While wiring the implementation, I noticed that the current Am I interpreting this correctly, or is the intended target shift handled elsewhere in the workflow? If not, would aligning the embedding construction with the standard one-step-ahead formulation be the preferred approach? 3. Scope of This PRMy understanding is that this PR should focus on the standard S-Map predictor only:
The EM iteration and state-estimation machinery required for the full HMS-map would then be a separate follow-up effort. Just wanted to confirm that this matches the intended project scope before I proceed further. Thanks! I currently have the S-Map implementation and associated tests working locally, and I wanted to verify these design details before pushing the next commit. |
|
Aman-In my experience using distance v. squared distance in the weighting kernel doesn’t make a huge difference in performance except in rare cases. I’d use whatever was easier/faster. In the state-estimation step of the HMS algorithm, we are updating all of the states based on the current estimates of the S-map coefficients and the observations. There’s no time lag in this step. In the S-map step, the model is fit one step ahead as usual. Regarding HMS map being a separate project - I will let others chime in. For my two cents - that’s the part that requires the most care in implementation. The rest is pretty straightforward. Critically ‘standard EDM’ does not handle observation error explicitly. The statistically minded folks at NMFS generally care about observation uncertainty, so it would be most valuable to if you completed the HMS map code or some other algorithm for handling observation uncertainty.Sent from my iPadOn Jun 24, 2026, at 12:04 PM, Aman Raj ***@***.***> wrote:aman-raj-srivastva left a comment (NOAA-FIMS/FIMS#1561)
@stevemunch @nathanvaughan-NOAA while implementing the S-Map predictor, I came across a few design questions where I'd appreciate feedback before I push the implementation.
I have currently implemented the standard S-Map formulation described in Section 2.1 of Esguerra & Munch (2024), i.e., the local linear model that serves as the baseline/M-step component of the full HMS-map.
For each local neighborhood, the implementation constructs a design matrix:
$$X_i = [1, x_t, x_{t-\tau}, \ldots, x_{t-(E-1)\tau}]$$
and solves the weighted least-squares system:
$$(X^T W X)\beta = X^T W y$$
using a CppAD-safe Gaussian elimination routine.
Before finalizing the implementation, I wanted to get your thoughts on a couple of design choices.
1. Weighting Kernel / Distance Metric
Classic S-Map implementations (e.g., Sugihara 1994 and rEDM) typically use an exponential kernel based on Euclidean distance:
$$w_i = \exp\left(-\theta \frac{d_i}{\bar d}\right)$$
However, Section 2.1 of Esguerra & Munch (2024) defines the weighting function as:
$$w_i = \exp\left(-\theta^2 \left(\frac{d_i}{D}\right)^2\right)$$
which is effectively a Gaussian kernel based on squared Euclidean distance.
For the generic FIMS S-Map predictor, would you prefer:
the formulation used in the HMS-map paper, or
compatibility with the more traditional rEDM-style weighting?
Using squared distances has the additional benefit of avoiding a sqrt() inside the AD tape.
2. Target Alignment in Delay Embedding
The paper formulates the delay embedding map as a one-step-ahead forecast:
$$x_{t+1} = f(x_t, \ldots, x_{t-E+1})$$
While wiring the implementation, I noticed that the current DelayEmbeddingMatrix assigns target_values[row] and embedded_values[row][0] to the same observation, which appears to correspond to a 0-step-ahead target.
Am I interpreting this correctly, or is the intended target shift handled elsewhere in the workflow?
If not, would aligning the embedding construction with the standard one-step-ahead formulation be the preferred approach?
3. Scope of This PR
My understanding is that this PR should focus on the standard S-Map predictor only:
local weighted linear regression
prediction interface integration
testing and validation infrastructure
The EM iteration and state-estimation machinery required for the full HMS-map would then be a separate follow-up effort.
Just wanted to confirm that this matches the intended project scope before I proceed further.
Thanks! I currently have the S-Map implementation and associated tests working locally, and I wanted to verify these design details before pushing the next commit.
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Hey @aman-raj-srivastva, great job on your progress so far. For these questions I would suggest
|
…rget
Per mentor feedback (nathanvaughan-NOAA, stevemunch):
1. Selectable weighting kernel (SMapKernel enum):
- kExponential (default): w = exp(-theta * d / d_mean) [rEDM / Sugihara 1994]
- kGaussian: w = exp(-theta^2 * (d/D)^2) [Esguerra & Munch 2024]
Both reduce to global OLS when theta=0. Kernel field exposed on
SMapProjection<Type> so users can compare formulations.
2. One-step-ahead target alignment in MakeDelayEmbedding:
Added forecast_horizon parameter (default=1). target_values[row] now
points to series[target_index + h], matching the standard EDM
formulation: predict x_{t+h} from the embedding state x_t.
n_rows reduced by forecast_horizon to keep all target pointers in bounds.
MakeDelayEmbeddingDropMissing forwards the parameter unchanged.
3. Tests: 12 S-Map + 9 Simplex = 21 passing GoogleTests.
- edm.hpp: remove stale 'S-map will be added' note; SMapProjection
is already included
- delay_embedding.hpp: correct target_values struct description from
'x_t' to 'x_{t+h}'; fix target_uncertainty comment to say
sigma_{target_index + forecast_horizon} not sigma_t
|
Hey @aman-raj-srivastva ! I met with @kellijohnson-NOAA and @Andrea-Havron-NOAA this afternoon, and we have an updated plan forward that will require much less overhead. The rebase to main conducted here will be the only full rebase we'll do until the end of the project, where we'll leave a few days for you to handle any additional merge conflicts / breaks that occur. For the remainder of the project, you can just work off this main-edm branch, and @Andrea-Havron-NOAA will let us know if we need to cherry pick any changes from the main branch that will affect your work. Bringing in @nathanvaughan-NOAA for awareness. Hope your resolution of conflicts here is going well, and please let us know if you have any questions or concerns! |
…IMSFrame rebase rename
|
Thanks @aman-raj-srivastva ! I see this version is passing all checks, and looks good to me. Before I merge this pull request, I wanted to circle back with @nathanvaughan-NOAA and @Andrea-Havron-NOAA to make sure that it fits as expected within the FIMS framework. |
|
Thanks @aman-raj-srivastva for all the great work and @mollystevens-noaa for testing out the new functions. I had a discussion with @Andrea-Havron-NOAA who will have a more detailed comment but we are concerned that at the moment the EDM module is still isolated from the rest of the FIMS codebase. Specifically there are a lot of calculations added inside the GP-EDM for estimating scale that should be a part of the FIMS distributions module. In it's final state the EDM module should only be creating the delay embedding map, calculating distance weights for each of the embedded vectors, and calculating predicted values from the embedding map and weights which are all deterministic calculations. The multivariate normal embedding function should be a part of the distributions functor so it can be used in EDM and for other relationships in FIMS, and the scale parameters should be specified as fixed or estimable similarly to all the other parameters in FIMS. @e-perl-NOAA is working on a similar issue in pull request #1594 to add a GMRF likelihood function. |
| } | ||
|
|
||
| // --- Solve Sigma * alpha = y (alpha overwrites y) --- | ||
| GaussianElimination<Type>(Sigma, y, N); |
There was a problem hiding this comment.
It is more efficient to calculate this using the Cholesky decomposition than Gaussian Elimination, which can be evaluated using Eigen's ldlt, for example:
Given a matrix Sigma(n,n):
// Perform LLT (Cholesky) decomposition using Eigen via TMB
Eigen::LDLT<Eigen::Matrix<scalartype,Dynamic,Dynamic> > ldlt(Sigma);
// 1. Solve Sigma * alpha = y --> L L^T alpha = y
vector<Type> alpha = ldlt.solve(y);
For reference, see TMB's MVNORM function here
There was a problem hiding this comment.
Updated predict_one() to use Eigen::LDLT Cholesky factorization (Eigen::LDLT<Eigen::Matrix<Type, Dynamic, Dynamic>> ldlt(Sigma_mat); alpha = ldlt.solve(y_mat)).
| } | ||
|
|
||
| /** @brief Sign function returning -1, 0, or +1 as a double. */ | ||
| static double sign_d(double x) { |
There was a problem hiding this comment.
@msupernaw, should this use CppAD::sign (uses an atomic) instead so it is differentiable?
There was a problem hiding this comment.
Added fims_math::sign() to fims_math.hpp which wraps CppAD::sign() under #ifdef TMB_MODEL so it is differentiable on the AD tape, and updated gp_edm_projection.hpp to use it.
| * @param N, E Library dimensions. | ||
| * @param ve_min, ve_max, s2_min, s2_max Parameter bounds. | ||
| */ | ||
| LogPosteriorResult compute_log_posterior_grad( |
There was a problem hiding this comment.
It's great to the see the multivariate normal function in FIMS! I would prefer you put it, however, in the distribution functors so that this likelihood can be used by the entire code base. You can use TMB's MVNORM function. If you use an explicit definition, update the inverse calculation of Sigma to use the cholesky decomposition instead of the Gaussian Elimination as mentioned above.
There was a problem hiding this comment.
Done on both points:
- Created
MVNormLPDF<Type>ininst/include/distributions/functors/mvnorm_lpdf.hppinheriting fromDensityComponentBase<Type>and exposed it throughdistributions/distributions.hpp. UnderTMB_MODEL, it delegates to TMB'sdensity::MVNORM_t<Type>. For standalone execution, it evaluates usingEigen::LDLT. - Updated
GaussianEliminationreferences acrossGPEdmProjection(predict_one()andcompute_log_posterior_grad()) andSMapProjectionto useEigen::LDLTCholesky factorization for matrix solves, log-determinant, and inverse covariance calculations. RemovedGaussianEliminationfromedm_linear_algebra.hpp.
|
|
||
| // --- Untransform parameters --- | ||
| std::vector<double> phi_cur(E); | ||
| for (size_t d = 0; d < E; ++d) phi_cur[d] = std::exp(parst[d]); |
There was a problem hiding this comment.
use fims_math::exp() throughout
There was a problem hiding this comment.
Updated — replaced std::exp, std::log, std::sqrt, and std::abs with fims_math:: throughout the file.
| for (size_t row = 0; row < N; ++row) iKVs[row * N + col] = e_col[row]; | ||
| } | ||
|
|
||
| // Log determinant via triangular factor diagonal |
There was a problem hiding this comment.
see TMB example for efficiently calculating the log determinant from a cholesky decomposition
There was a problem hiding this comment.
Updated compute_log_posterior_grad() to use Eigen::LDLT for solving alpha (ldlt.solve(y)), inverting the covariance matrix (ldlt.solve(Identity)), and computing the log-determinant (ldlt.vectorD().array().abs().log().sum()).
| lp_phi += -0.5 * phi_cur[d] * phi_cur[d] / kLamPhi; | ||
| dlp_phi[d] = -phi_cur[d] / kLamPhi; | ||
| } | ||
| // sigma2 and ve: Beta-shaped (a=2, b=2) on (0, max) |
There was a problem hiding this comment.
as noted above for the multivariate normal distribution, please add the beta distribution to the distribution functor folder and expose using the FIMS distribution pathway so these distribtions are available throughout the codebase.
There was a problem hiding this comment.
Created BetaLPDF<Type> in inst/include/distributions/functors/beta_lpdf.hpp following the DensityComponentBase<Type> architecture, supporting shape1 (shape2 (scale (TMB_MODEL, it calls dbeta(x / s, alpha, beta, true) - log(s). Exposed via distributions/distributions.hpp so it's accessible across FIMS.
| * - SMapKernel::kExponential (default): w = exp(-θ · d / d̄) [rEDM style] | ||
| * - SMapKernel::kGaussian: w = exp(-θ² · (d/D)²) [Esguerra & Munch 2024] | ||
| * Per Munch (pers. comm.) the performance difference is rarely large; | ||
| * use kGaussian to avoid a sqrt() inside the AD tape. |
There was a problem hiding this comment.
it is safe to use a sqrt() inside the AD tape, we use fims_math::sqrt(). Generally, when taking the sqrt of a parameter, we estimate the parameter in log space and take the exponential to keep the value positive. If you can't use this trick, however, when evaluating the s-map projections, please feel free to leave the kGaussian approach as is.
There was a problem hiding this comment.
Updated — standardized all square root and exponential calls to use fims_math::sqrt() and fims_math::exp().
| // Step 4: Solve A β = b via Gaussian elimination (in-place). | ||
| // On exit b_vec holds the solution β. | ||
| // ----------------------------------------------------------------------- | ||
| GaussianElimination(A, b_vec, p); |
There was a problem hiding this comment.
use cholesky factorization as noted in the gp_edm_projection file.
There was a problem hiding this comment.
Updated — replaced GaussianElimination in SMapProjection::predict_one() with Eigen::LDLT Cholesky factorization solve for
|
Thanks for this PR and all your hard work! As @nathanvaughan-NOAA mentioned above, I think there are some changes that can be made to better integrate this code into the larger FIMS code base. Specifically,
I noticed in your next PR, you have more code that helps integrate the edm piece into FIMS, I am looking forward to checking it out! |
|
Thank you all for the thorough review and the feedback. I see what you’re suggesting about architectural adjustments to help integrate the EDM implementation into the FIMS codebase. I’ll begin working through these updates and will put these changes into logical commits as I tackle each piece. Thanks again for the guidance! |
|
Folks-
Just a quick 2cents - While the matrices we're inverting are theoretically
postive definite, they do become singular for extreme values of the local
weighting parameters. So, although Cholesky is preferred for things that
must be symmetric and p.d., we'll want to be sure we have some way to
handle p.s.d matrices as well.
Cheers,
Steve
…On Tue, Jul 21, 2026 at 10:51 AM Aman Raj ***@***.***> wrote:
*aman-raj-srivastva* left a comment (NOAA-FIMS/FIMS#1561)
<#1561 (comment)>
Thank you all for the thorough review and the feedback. I see what you’re
suggesting about architectural adjustments to help integrate the EDM
implementation into the FIMS codebase. I’ll begin working through these
updates and will put these changes into logical commits as I tackle each
piece. Thanks again for the guidance!
—
Reply to this email directly, view it on GitHub
<#1561?email_source=notifications&email_token=AFSAKFYMINKQ2MROW2EJXW35F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5037258824>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AFSAKF7C55UVUS4WHE4TU2D5F6URLAVCNFSNUABFKJSXA33TNF2G64TZHM2DKMRQGEZDAMBUHNEXG43VMU5TINZSGY4TKMRUGI22C5QC>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/AFSAKF3ATR75CITJGZGN4ZD5F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/AFSAKFZNCHTWKNPHJINWMDL5F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@stevemunch, thanks for raising these concerns! The Eigen |
|
Yes - just crank the locally parameter (theta or phi depending on naming convention) to something really large / really small with some artificial data where several rows of inputs are identical or nearly so.Sent from my iPadOn Jul 21, 2026, at 11:55 AM, Andrea-Havron-NOAA ***@***.***> wrote:Andrea-Havron-NOAA left a comment (NOAA-FIMS/FIMS#1561)
Folks- Just a quick 2cents - While the matrices we're inverting are theoretically postive definite, they do become singular for extreme values of the local weighting parameters. So, although Cholesky is preferred for things that must be symmetric and p.d., we'll want to be sure we have some way to handle p.s.d matrices as well. Cheers, Steve
…
On Tue, Jul 21, 2026 at 10:51 AM Aman Raj @.> wrote: aman-raj-srivastva left a comment (NOAA-FIMS/FIMS#1561) <#1561 (comment)> Thank you all for the thorough review and the feedback. I see what you’re suggesting about architectural adjustments to help integrate the EDM implementation into the FIMS codebase. I’ll begin working through these updates and will put these changes into logical commits as I tackle each piece. Thanks again for the guidance! — Reply to this email directly, view it on GitHub <#1561?email_source=notifications&email_token=AFSAKFYMINKQ2MROW2EJXW35F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5037258824>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFSAKF7C55UVUS4WHE4TU2D5F6URLAVCNFSNUABFKJSXA33TNF2G64TZHM2DKMRQGEZDAMBUHNEXG43VMU5TINZSGY4TKMRUGI22C5QC . Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS https://github.com/notifications/mobile/ios/AFSAKF3ATR75CITJGZGN4ZD5F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y and Android https://github.com/notifications/mobile/android/AFSAKFZNCHTWKNPHJINWMDL5F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI. Download it today! You are receiving this because you were mentioned.Message ID: @.>
@stevemunch, thanks for raising these concerns! The Eigen ldlt method is the robust version of the Cholesky, it returns a solution even if A isn't positive definite. If A is singular or semi-positive definite, the ldlt method defaults to computing the least squares solution (Eigen documentation: Eigen::LDLT, solve). That being said, I'm not an expert by any means on EDMs, so I don't know if we will run into issues using ldlt in the context of these models. Is there a way to test an ill-formed use case with the ldlt method to see if it holds up?
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Oh yeah - when trying this for the GP, we’d also want to make sure that the process variance (Ve ?) is set close to zero. If it is large enough, it acts as a regularizer and hides / eliminates the numerical issue.Sent from my iPadOn Jul 21, 2026, at 3:04 PM, Stephan Munch ***@***.***> wrote:Yes - just crank the locally parameter (theta or phi depending on naming convention) to something really large / really small with some artificial data where several rows of inputs are identical or nearly so.Sent from my iPadOn Jul 21, 2026, at 11:55 AM, Andrea-Havron-NOAA ***@***.***> wrote:Andrea-Havron-NOAA left a comment (NOAA-FIMS/FIMS#1561)
Folks- Just a quick 2cents - While the matrices we're inverting are theoretically postive definite, they do become singular for extreme values of the local weighting parameters. So, although Cholesky is preferred for things that must be symmetric and p.d., we'll want to be sure we have some way to handle p.s.d matrices as well. Cheers, Steve
…
On Tue, Jul 21, 2026 at 10:51 AM Aman Raj @.> wrote: aman-raj-srivastva left a comment (NOAA-FIMS/FIMS#1561) <#1561 (comment)> Thank you all for the thorough review and the feedback. I see what you’re suggesting about architectural adjustments to help integrate the EDM implementation into the FIMS codebase. I’ll begin working through these updates and will put these changes into logical commits as I tackle each piece. Thanks again for the guidance! — Reply to this email directly, view it on GitHub <#1561?email_source=notifications&email_token=AFSAKFYMINKQ2MROW2EJXW35F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5037258824>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFSAKF7C55UVUS4WHE4TU2D5F6URLAVCNFSNUABFKJSXA33TNF2G64TZHM2DKMRQGEZDAMBUHNEXG43VMU5TINZSGY4TKMRUGI22C5QC . Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS https://github.com/notifications/mobile/ios/AFSAKF3ATR75CITJGZGN4ZD5F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y and Android https://github.com/notifications/mobile/android/AFSAKFZNCHTWKNPHJINWMDL5F6URLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMBTG4ZDKOBYGI2KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI. Download it today! You are receiving this because you were mentioned.Message ID: @.>
@stevemunch, thanks for raising these concerns! The Eigen ldlt method is the robust version of the Cholesky, it returns a solution even if A isn't positive definite. If A is singular or semi-positive definite, the ldlt method defaults to computing the least squares solution (Eigen documentation: Eigen::LDLT, solve). That being said, I'm not an expert by any means on EDMs, so I don't know if we will run into issues using ldlt in the context of these models. Is there a way to test an ill-formed use case with the ldlt method to see if it holds up?
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
3c243dc to
be959a2
Compare
…ims_math usage - Replace GaussianElimination with Eigen::LDLT Cholesky factorization in GPEdmProjection (both predict_one and compute_log_posterior_grad) and SMapProjection - Update GP log-marginal likelihood gradient solve, inverse covariance matrix (iKVs), and log-determinant calculation to use Eigen::LDLT - Add fims_math::sign() using CppAD::sign() under TMB_MODEL for AD tape differentiability and replace custom sign_d() helper - Standardize math functions (std::exp, std::log, std::sqrt, std::abs) to use fims_math:: across EDM functors - Add GoogleTest test cases for ill-conditioned systems (extreme theta = 1000 and near-zero nugget ve = 1e-6) to verify LDLT least-squares fallback
be959a2 to
c8b7161
Compare
…ounds in MVNormLPDF and BetaLPDF
Summary
This PR implements the core EDM prediction framework for Empirical Dynamic Modeling (EDM) in FIMS as part of the GSoC 2026 project:
"Add Empirical Dynamic Modeling to FIMS."
This work builds on the delay embedding infrastructure introduced in PR #1528 and implements the prediction algorithms described in Issue #1487.
Target Branch:
main-edmThis PR completes the standalone prediction framework for EDM. Integration of these prediction methods into the FIMS likelihood/TMB pipeline will be addressed in a subsequent PR.
What this PR adds
Generic EDM Prediction Framework
Implemented a reusable and extensible prediction framework for EDM algorithms.
Features include:
Simplex Projection
Implemented the Standard Simplex Projection algorithm (Sugihara & May, 1990).
Features include:
Distance Weighting Infrastructure
Implemented reusable distance weighting utilities shared across prediction algorithms.
Features include:
Standard S-Map
Implemented the Standard S-Map prediction algorithm (Sugihara, 1994).
Features include:
GP-EDM
Implemented the GP-EDM prediction algorithm following the reference GPEDM implementation (Munch et al. 2017; Rogers 2023).
Features include:
phi)phiBug fix: Corrected a missing
0.5factor on the log-determinant term in the GP log-marginal likelihood. This was identified during numerical verification against the GPEDM reference package.Known intentional differences from the GPEDM reference package:
chol2inv)rhoparameterglobal/local/noneRcpp Interfaces
Implemented R-callable interfaces for all prediction methods via Rcpp modules.
Includes:
SimplexProjectionInterface— fields:embedding_dimension,n_neighborsSMapProjectionInterface— fields:embedding_dimension,theta,kernelGPEdmProjectionInterface— fields:embedding_dimension,phi,sigma2,ve; methods:fit(),predict()to_matrix()helper bridgingDelayEmbeddingInterfacestorage to the C++ prediction frameworkEDMInterfaceBase::live_objectsfor Rcpp memory safetyAll three interfaces are callable from R via
methods::new().Validation
Numerical verification was performed for all three prediction methods:
2.22e-16(machine ε)1.30e-14predict.GP)2.53e-10For GP-EDM, the
sigma2andvegradients were additionally verified to match the reference package exactly (these do not depend on the per-dimension distance matrices), confirming the covariance matrix math is correct.Testing
This PR includes comprehensive testing for the EDM prediction framework.
Current coverage:
Testing covers:
Future Work
This PR completes the standalone EDM prediction framework. Future work can focus on:
Related Issues