% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/weight_estimation.R
\name{project_to_simplex}
\alias{project_to_simplex}
\title{Project study-level functions onto the simplex spanned by basis functions}
\usage{
project_to_simplex(F_hat, bases, grid_weights = NULL, ridge = 1e-10)
}
\arguments{
\item{F_hat}{An \code{m}-by-\code{G_grid} numeric matrix; row \code{i} is the study
function \eqn{\hat f^{(i)}} evaluated on the shared grid.}

\item{bases}{A \code{K}-by-\code{G_grid} numeric matrix of basis functions on the
same grid, typically the \code{bases} slot of a \code{\link[=dfspa]{dfspa()}} result.}

\item{grid_weights}{Optional length-\code{G_grid} non-negative numeric vector of
grid weights defining the \eqn{L^2(\mu)} inner product. Defaults to
uniform weights \code{1 / G_grid}.}

\item{ridge}{Small non-negative scalar added to the diagonal of the QP
Hessian for numerical stability. Defaults to \code{1e-10}.}
}
\value{
An \code{m}-by-\code{K} numeric matrix of simplex weights; rows sum to 1
and entries are non-negative.
}
\description{
For each study \code{i}, solves the constrained projection
\deqn{\hat\pi_i = \arg\min_{\pi \in \Delta_{K-1}}
  \left\| \hat f^{(i)} - \sum_{k=1}^K \pi_k \hat g_k \right\|_{L^2(\mu)}}
where the norm is the weighted \eqn{L^2} norm defined by \code{grid_weights}.
This is Equation (3) of the paper and yields the study-specific weights
\verb{hat pi_i} used downstream for weight-model fitting and prediction.
}
\details{
The projection reduces to the quadratic program
\deqn{\min_{\pi \in \mathbb R^K}\ \pi^\top D\,\pi - 2\,d^\top \pi
  \quad \text{s.t.} \quad \mathbf 1^\top \pi = 1,\ \pi \ge 0}
with \eqn{D = G W G^\top} and \eqn{d = G W f^{(i)}}, where
\eqn{G} is the \code{K}-by-\code{G_grid} basis matrix, \eqn{W = \mathrm{diag}(}\code{grid_weights}\eqn{)},
and \eqn{f^{(i)}} is the \code{i}-th row of \code{F_hat}. Solved via
\code{\link[quadprog:solve.QP]{quadprog::solve.QP()}}. A tiny ridge is added to \code{D} for numerical stability.
}
\examples{
set.seed(1)
G <- 40
x <- seq(0, 1, length.out = G)
basis <- rbind(sin(pi * x), cos(pi * x), x)
true_pi <- rbind(diag(3), c(0.4, 0.3, 0.3), c(0.1, 0.7, 0.2))
F_hat <- true_pi \%*\% basis
fit <- dfspa(F_hat, K = 3, denoise = FALSE)
pi_hat <- project_to_simplex(F_hat, fit$bases)
round(pi_hat, 3)

}
