diff --git a/NAMESPACE b/NAMESPACE index e1c1c2b2d..1f3bfc453 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -34,6 +34,8 @@ export(clear) export(create_default_configurations) export(create_default_parameters) export(create_edm_embedding) +export(edm_forecast) +export(fit_edm) export(fit_fims) export(get_ages) export(get_data) diff --git a/R/edm.R b/R/edm.R new file mode 100644 index 000000000..4cc7be5cf --- /dev/null +++ b/R/edm.R @@ -0,0 +1,99 @@ +# EDM User-Facing R Interface +# This file contains high-level R wrapper functions for fitting and +# forecasting with Empirical Dynamic Modeling (EDM) methods in FIMS. +# These wrappers simplify interaction with the underlying C++ prediction +# framework implemented in previous phases (#1528, #1561, #1620). + +# fit_edm ---------------------------------------------------------------- + +#' Fit an EDM model to a time series +#' +#' @description +#' High-level interface for fitting an Empirical Dynamic Modeling (EDM) +#' prediction model to a univariate or multivariate time series stored in a +#' `FIMSFrame` object. Supports Simplex Projection, S-Map, and GP-EDM methods. +#' +#' @param data A `FIMSFrame` object containing the time series data. +#' @param method Character string specifying the EDM method to use. One of +#' `"simplex"`, `"smap"`, or `"gp"`. Default is `"simplex"`. +#' @param embedding_name A single string matching one of the named delay +#' embeddings in `data` (created via [create_edm_embedding()]). If `NULL`, +#' uses the first available embedding. +#' @param E Positive integer. Embedding dimension (number of lagged +#' coordinates). Ignored if `embedding_name` is specified. +#' @param tau Positive integer. Time lag between successive coordinates. +#' Ignored if `embedding_name` is specified. +#' @param theta Numeric. Nonlinearity parameter for S-Map. Larger values +#' weight nearby library points more strongly. Only used when +#' `method = "smap"`. Default is `1.0`. +#' @param n_neighbors Positive integer. Number of nearest neighbors for +#' Simplex Projection. Defaults to `E + 1` when set to `0`. +#' Only used when `method = "simplex"`. Default is `0`. +#' @param forecast_horizon Positive integer. Number of steps ahead to forecast. +#' Default is `1`. +#' @param ... Additional arguments passed to the underlying EDM C++ interface. +#' +#' @return An object of class `EDMFit` containing: +#' \describe{ +#' \item{method}{The EDM method used.} +#' \item{predictions}{Numeric vector of one-step-ahead predictions.} +#' \item{embedding}{The `DelayEmbeddingMatrix` used for fitting.} +#' \item{parameters}{List of method-specific hyperparameters.} +#' } +#' +#' @seealso [edm_forecast()], [create_edm_embedding()], [FIMSFrame()] +#' @export +#' @examples +#' \dontrun{ +#' data("data_big") +#' ff <- FIMSFrame(data_big) +#' ff <- create_edm_embedding(ff, type = "landings", fleet = "fishery1", E = 3, tau = 1) +#' fit <- fit_edm(ff, method = "simplex", embedding_name = "fishery1_landings") +#' } +fit_edm <- function(data, + method = c("simplex", "smap", "gp"), + embedding_name = NULL, + E = 3L, + tau = 1L, + theta = 1.0, + n_neighbors = 0L, + forecast_horizon = 1L, + ...) { + method <- match.arg(method) + stopifnot(inherits(data, "FIMSFrame")) + # TODO: Implement method dispatch to C++ EDM interfaces + stop("fit_edm() is not yet implemented. Coming in Phase 4 (GSoC 2026).") +} + +# edm_forecast ----------------------------------------------------------- + +#' Generate forecasts from a fitted EDM model +#' +#' @description +#' Generates out-of-sample empirical forecasts from a fitted `EDMFit` object +#' returned by [fit_edm()]. +#' +#' @param fit An `EDMFit` object returned by [fit_edm()]. +#' @param n_ahead Positive integer. Number of time steps to forecast ahead. +#' Default is `1`. +#' @param ... Additional arguments passed to underlying prediction methods. +#' +#' @return A tibble with columns: +#' \describe{ +#' \item{time}{Forecast time index.} +#' \item{forecast}{Point forecast value.} +#' \item{se}{Standard error of the forecast (if available).} +#' } +#' +#' @seealso [fit_edm()] +#' @export +#' @examples +#' \dontrun{ +#' fit <- fit_edm(ff, method = "smap", embedding_name = "fishery1_landings") +#' forecasts <- edm_forecast(fit, n_ahead = 5) +#' } +edm_forecast <- function(fit, n_ahead = 1L, ...) { + stopifnot(inherits(fit, "EDMFit")) + # TODO: Implement forecast generation from EDMFit object + stop("edm_forecast() is not yet implemented. Coming in Phase 4 (GSoC 2026).") +} diff --git a/man/create_edm_embedding.Rd b/man/create_edm_embedding.Rd index 38bbf997f..a85425be2 100644 --- a/man/create_edm_embedding.Rd +++ b/man/create_edm_embedding.Rd @@ -21,7 +21,11 @@ create_edm_embedding( \item{series_type}{A single string giving the \code{type} value to filter on, e.g. \code{"index"} or \code{"landings"}.} +<<<<<<< HEAD \item{series_name}{A single string giving the \code{fleet} (fleet / survey) value +======= +\item{series_name}{A single string giving the \code{name} (fleet / survey) value +>>>>>>> 5fde931e (feat(edm): add skeleton R interface with fit_edm() and edm_forecast() stubs) to filter on, e.g. \code{"survey1"}.} \item{E}{A positive integer — the embedding dimension (number of lagged @@ -33,7 +37,11 @@ coordinates per row).} the FIMS missing-value sentinel \code{-999} are dropped from the embedding matrix.} +<<<<<<< HEAD \item{uncertainty_name}{A single string giving the \code{fleet} column value for +======= +\item{uncertainty_name}{A single string giving the \code{name} column value for +>>>>>>> 5fde931e (feat(edm): add skeleton R interface with fit_edm() and edm_forecast() stubs) an uncertainty series in the data slot (e.g. \code{"survey1_sd"}), or \code{NULL} (default) to skip uncertainty propagation. The uncertainty series must have the same length as the value series after filtering on @@ -55,7 +63,11 @@ stored in the \code{edm_embeddings} slot under \code{embedding_name}. } \details{ The time series is extracted by filtering \code{get_data(x)} on \code{type} and +<<<<<<< HEAD \code{fleet} (fleet / survey name). Values encoded as \code{-999} are treated as the +======= +\code{name} (fleet / survey name). Values encoded as \code{-999} are treated as the +>>>>>>> 5fde931e (feat(edm): add skeleton R interface with fit_edm() and edm_forecast() stubs) FIMS missing-data sentinel. When \code{drop_missing = TRUE}, \code{construct_drop_missing()} is called so that rows containing \code{-999} are removed from the embedding matrix; when \code{FALSE}, \code{construct()} is called diff --git a/man/edm_forecast.Rd b/man/edm_forecast.Rd new file mode 100644 index 000000000..c43ba7cc5 --- /dev/null +++ b/man/edm_forecast.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edm.R +\name{edm_forecast} +\alias{edm_forecast} +\title{Generate forecasts from a fitted EDM model} +\usage{ +edm_forecast(fit, n_ahead = 1L, ...) +} +\arguments{ +\item{fit}{An \code{EDMFit} object returned by \code{\link[=fit_edm]{fit_edm()}}.} + +\item{n_ahead}{Positive integer. Number of time steps to forecast ahead. +Default is \code{1}.} + +\item{...}{Additional arguments passed to underlying prediction methods.} +} +\value{ +A tibble with columns: +\describe{ +\item{time}{Forecast time index.} +\item{forecast}{Point forecast value.} +\item{se}{Standard error of the forecast (if available).} +} +} +\description{ +Generates out-of-sample empirical forecasts from a fitted \code{EDMFit} object +returned by \code{\link[=fit_edm]{fit_edm()}}. +} +\examples{ +\dontrun{ +fit <- fit_edm(ff, method = "smap", embedding_name = "fishery1_landings") +forecasts <- edm_forecast(fit, n_ahead = 5) +} +} +\seealso{ +\code{\link[=fit_edm]{fit_edm()}} +} diff --git a/man/fit_edm.Rd b/man/fit_edm.Rd new file mode 100644 index 000000000..f40506cea --- /dev/null +++ b/man/fit_edm.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edm.R +\name{fit_edm} +\alias{fit_edm} +\title{Fit an EDM model to a time series} +\usage{ +fit_edm( + data, + method = c("simplex", "smap", "gp"), + embedding_name = NULL, + E = 3L, + tau = 1L, + theta = 1, + n_neighbors = 0L, + forecast_horizon = 1L, + ... +) +} +\arguments{ +\item{data}{A \code{FIMSFrame} object containing the time series data.} + +\item{method}{Character string specifying the EDM method to use. One of +\code{"simplex"}, \code{"smap"}, or \code{"gp"}. Default is \code{"simplex"}.} + +\item{embedding_name}{A single string matching one of the named delay +embeddings in \code{data} (created via \code{\link[=create_edm_embedding]{create_edm_embedding()}}). If \code{NULL}, +uses the first available embedding.} + +\item{E}{Positive integer. Embedding dimension (number of lagged +coordinates). Ignored if \code{embedding_name} is specified.} + +\item{tau}{Positive integer. Time lag between successive coordinates. +Ignored if \code{embedding_name} is specified.} + +\item{theta}{Numeric. Nonlinearity parameter for S-Map. Larger values +weight nearby library points more strongly. Only used when +\code{method = "smap"}. Default is \code{1.0}.} + +\item{n_neighbors}{Positive integer. Number of nearest neighbors for +Simplex Projection. Defaults to \code{E + 1} when set to \code{0}. +Only used when \code{method = "simplex"}. Default is \code{0}.} + +\item{forecast_horizon}{Positive integer. Number of steps ahead to forecast. +Default is \code{1}.} + +\item{...}{Additional arguments passed to the underlying EDM C++ interface.} +} +\value{ +An object of class \code{EDMFit} containing: +\describe{ +\item{method}{The EDM method used.} +\item{predictions}{Numeric vector of one-step-ahead predictions.} +\item{embedding}{The \code{DelayEmbeddingMatrix} used for fitting.} +\item{parameters}{List of method-specific hyperparameters.} +} +} +\description{ +High-level interface for fitting an Empirical Dynamic Modeling (EDM) +prediction model to a univariate or multivariate time series stored in a +\code{FIMSFrame} object. Supports Simplex Projection, S-Map, and GP-EDM methods. +} +\examples{ +\dontrun{ +data("data_big") +ff <- FIMSFrame(data_big) +ff <- create_edm_embedding(ff, type = "landings", fleet = "fishery1", E = 3, tau = 1) +fit <- fit_edm(ff, method = "simplex", embedding_name = "fishery1_landings") +} +} +\seealso{ +\code{\link[=edm_forecast]{edm_forecast()}}, \code{\link[=create_edm_embedding]{create_edm_embedding()}}, \code{\link[=FIMSFrame]{FIMSFrame()}} +}