% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/nmf.ffb.R, R/nmf.sem.R
\name{nmf.ffb}
\alias{nmf.ffb}
\alias{nmf.sem}
\title{NMF-FFB Main Estimation Algorithm (formerly NMF-SEM)}
\usage{
nmf.ffb(
  Y1,
  Y2,
  rank = NULL,
  X.init = "nndsvd",
  X.L2.ortho = 100,
  C1.L1 = 1,
  C2.L1 = 0.1,
  epsilon = 1e-06,
  maxit = 5000,
  seed = 123,
  ...
)

nmf.sem(
  Y1,
  Y2,
  rank = NULL,
  X.init = "nndsvd",
  X.L2.ortho = 100,
  C1.L1 = 1,
  C2.L1 = 0.1,
  epsilon = 1e-06,
  maxit = 5000,
  seed = 123,
  ...
)
}
\arguments{
\item{Y1}{A non-negative numeric matrix of endogenous variables with
\strong{rows = variables (P1), columns = samples (N)}.}

\item{Y2}{A non-negative numeric matrix of exogenous variables with
\strong{rows = variables (P2), columns = samples (N)}.
Must satisfy \code{ncol(Y1) == ncol(Y2)}.}

\item{rank}{Integer; number of latent factors \eqn{Q}. If \code{NULL},
\eqn{Q} is taken from a hidden argument in \code{...} or defaults to
\code{nrow(Y2)}.}

\item{X.init}{Initialization strategy for the basis matrix
\code{X} (\eqn{P_1 \times Q}).  One of:
\itemize{
\item \code{"nndsvd"} (default): Non-negative Double SVD with
additive randomness (NNDSVDar; Boutsidis & Gallopoulos 2008),
computed internally via \code{.nndsvdar(Y1, Q)}.  Requires
\eqn{Q \le \min(P_1, N)} (over-rank case falls back to
\code{"runif"}).  Uses a full SVD of \eqn{Y_1}, so for very
large \eqn{Y_1} consider switching to \code{"kmeans"} to
avoid SVD memory / compute cost.
\item \code{"kmeans"}: k-means on the columns of \eqn{Y_1}
(samples clustered into \eqn{Q} groups); the transposed
cluster centers become \eqn{X}.  Scales well for large
\eqn{Y_1}; this is the default of \code{\link{nmfkc}}.
\item \code{"kmeansar"}: \code{"kmeans"} followed by filling
zero entries of \eqn{X} with \eqn{\mathrm{Uniform}(0,
      \bar Y_1 / 100)} (NNDSVDar-style additive randomness to
escape trivial stationary points).
\item \code{"runif"}: Uniform random entries in \eqn{[0, 1]}.
\item A numeric \eqn{P_1 \times Q} matrix supplied by the user;
negative entries are projected to 0.
\item \code{NULL}: backward-compatible alias for \code{"nndsvd"}.
}
In all cases the result is column-normalized to \code{colSums(X) = 1}
before iteration.  The menu mirrors \code{\link{nmfkc}}'s
\code{X.init} option for consistency across the package.}

\item{X.L2.ortho}{L2 orthogonality penalty for \code{X}. This controls
the penalty term \eqn{\lambda_X \lVert X^\top X - \mathrm{diag}(X^\top X)
  \rVert_F^2}. Default: \code{100}.}

\item{C1.L1}{L1 sparsity penalty for \code{C1} (i.e., \eqn{\Theta_1}).
Default: \code{1.0}.}

\item{C2.L1}{L1 sparsity penalty for \code{C2} (i.e., \eqn{\Theta_2}).
Default: \code{0.1}.}

\item{epsilon}{Relative convergence threshold for the objective function.
Iterations stop when the relative change in reconstruction loss falls
below this value. Default: \code{1e-6}.}

\item{maxit}{Maximum number of iterations for the multiplicative updates.
Default: \code{5000} (matches \code{\link{nmfkc}} and other MU
functions in the package).}

\item{seed}{Random seed used to initialize \code{X}, \code{C1}, and \code{C2}.
Default: \code{123}.}

\item{...}{Additional hidden arguments controlling the optional
feedforward baseline (used both as an \eqn{X} warm-start and as
the reference for \code{SC.map}, the input-output structural
fidelity defined in Satoh (2025) §4.SC.map):
\describe{
\item{\code{nmfkc.baseline}}{Controls whether a feedforward
\code{\link{nmfkc}}(Y1, A = Y2) fit is used as baseline.
Possible values:
\itemize{
\item Default (not given) — \code{nmf.sem} runs
\code{\link{nmfkc}} \strong{internally} when \code{X.init}
is a string method (\code{"nndsvd"}, \code{"kmeans"},
\dots) or \code{NULL}, forwarding \code{X.init},
\code{X.L2.ortho}, \code{epsilon}, \code{maxit},
\code{seed}.  The fitted \eqn{X} of the baseline is then
used as warm-start for the nmf.sem MU iterations, and
\code{SC.map} is computed.  This means
\code{nmf.sem(Y1, Y2, rank = Q)} runs end-to-end without
a prior \code{nmfkc} call.
\item \code{TRUE} — same as above, but force the internal
\code{\link{nmfkc}} call even when \code{X.init} is a
user-supplied matrix (the matrix is overridden).
\item \code{FALSE} — opt out; no internal call,
\code{SC.map = NA} (pre-v0.6.8 behavior).
\item An \code{\link{nmfkc}} result (list with \code{$X}
and \code{$C}) — use as the baseline directly (no
internal call); also adopted as \code{X.init} when the
latter is a string / NULL.
}}
\item{\code{M.simple}}{Optional \eqn{P_1 \times P_2} pre-computed
baseline mapping.  Takes precedence over \code{nmfkc.baseline}
for the SC.map calculation but does not affect warm-start.}
\item{\code{Q}}{Backward-compat alias for \code{rank}.}
}}
}
\value{
A list with components:
\item{X}{Estimated basis matrix (\eqn{P_1 \times Q}).}
\item{C1}{Estimated latent feedback matrix (\eqn{\Theta_1}, \eqn{Q \times P_1}).}
\item{C2}{Estimated exogenous loading matrix (\eqn{\Theta_2}, \eqn{Q \times P_2}).}
\item{XC1}{Feedback matrix \eqn{X \Theta_1}.}
\item{XC2}{Direct-effect matrix \eqn{X \Theta_2}.}
\item{XC1.radius}{Spectral radius \eqn{\rho(X \Theta_1)}.}
\item{XC1.norm1}{Induced 1-norm \eqn{\lVert X \Theta_1 \rVert_{1,\mathrm{op}}}.}
\item{Leontief.inv}{Leontief-type inverse \eqn{(I - X \Theta_1)^{-1}.}}
\item{M.model}{Equilibrium mapping
\eqn{M_{\mathrm{model}} = (I - X \Theta_1)^{-1} X \Theta_2}.}
\item{amplification}{Latent amplification factor
\eqn{\lVert M_{\mathrm{model}} \rVert_{1,\mathrm{op}} /
         \bigl\lVert X \Theta_2 \bigr\rVert_{1,\mathrm{op}}}.}
\item{amplification.bound}{Geometric-series upper bound
\eqn{1 / (1 - \lVert X \Theta_1 \rVert_{1,\mathrm{op}})} if
\eqn{\lVert X \Theta_1 \rVert_{1,\mathrm{op}} < 1}, otherwise \code{Inf}.}
\item{Q}{Effective latent dimension used in the fit.}
\item{SC.cov}{Correlation between sample and model-implied covariance
(flattened) of \eqn{Y_1}.  See \emph{second-moment fidelity} in
Satoh (2025).}
\item{SC.map}{Correlation between the equilibrium operator
\eqn{M_{\mathrm{model}}} and a feedforward baseline mapping
\eqn{M_{\mathrm{simple}} = X_0 \Theta_0}, computed only when the
baseline is supplied via \code{M.simple} or \code{nmfkc.baseline}
in \code{...}; otherwise \code{NA}.  See \emph{input-output
structural fidelity} in Satoh (2025).}
\item{MAE}{Mean absolute error between \eqn{Y_1} and its equilibrium
prediction \eqn{\hat Y_1 = M_{\mathrm{model}} Y_2}.}
\item{objfunc}{Vector of reconstruction losses per iteration.}
\item{objfunc.full}{Vector of penalized objective values per iteration.}
\item{iter}{Number of iterations actually performed.}
}
\description{
Fits the NMF-FFB model
\deqn{
  Y_1 \approx X \bigl( \Theta_1 Y_1 + \Theta_2 Y_2 \bigr)
}
under non-negativity constraints with orthogonality and sparsity regularization.
The function returns the estimated latent factors, structural coefficient matrices,
and the implied equilibrium (input–output) mapping.

At equilibrium, the model can be written as
\deqn{
  Y_1 \approx (I - X \Theta_1)^{-1} X \Theta_2 Y_2
  \equiv M_{\mathrm{model}} Y_2,
}
where \eqn{M_{\mathrm{model}} = (I - X \Theta_1)^{-1} X \Theta_2} is a
Leontief-type cumulative-effect operator in latent space.

Internally, the latent feedback and exogenous loading matrices are stored as
\code{C1} and \code{C2}, corresponding to \eqn{\Theta_1} and \eqn{\Theta_2},
respectively.
}
\examples{
# Simple NMF-FFB with iris data (non-negative)
Y <- t(iris[, -5])
Y1 <- Y[1:2, ]  # Sepal
Y2 <- Y[3:4, ]  # Petal
result <- nmf.sem(Y1, Y2, rank = 2, maxit = 500)
result$MAE

}
\references{
Satoh, K. (2025). Applying non-negative matrix factorization with covariates
to structural equation modeling for blind input-output analysis.
arXiv:2512.18250. \url{https://arxiv.org/abs/2512.18250}
}
\seealso{
\code{\link{nmf.sem.inference}}, \code{\link{nmf.sem.cv}},
\code{\link{nmf.sem.split}}, \code{\link{nmf.sem.DOT}},
\code{\link{summary.nmf.sem}}
}
