R/RcppExports.R

Defines functions nnls Rcpp_dclust_sparse Rcpp_bipartition_dense Rcpp_bipartition_sparse Rcpp_nmf_dense Rcpp_nmf_sparse Rcpp_mse_dense Rcpp_mse_sparse Rcpp_projectH_dense Rcpp_projectW_dense Rcpp_projectH_sparse Rcpp_projectW_sparse

Documented in nnls

# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

Rcpp_projectW_sparse <- function(A, w, nonneg, L1, threads, mask_zeros) {
    .Call('_RcppML_Rcpp_projectW_sparse', PACKAGE = 'RcppML', A, w, nonneg, L1, threads, mask_zeros)
}

Rcpp_projectH_sparse <- function(A, h, nonneg, L1, threads, mask_zeros) {
    .Call('_RcppML_Rcpp_projectH_sparse', PACKAGE = 'RcppML', A, h, nonneg, L1, threads, mask_zeros)
}

Rcpp_projectW_dense <- function(A, w, nonneg, L1, threads, mask_zeros) {
    .Call('_RcppML_Rcpp_projectW_dense', PACKAGE = 'RcppML', A, w, nonneg, L1, threads, mask_zeros)
}

Rcpp_projectH_dense <- function(A, h, nonneg, L1, threads, mask_zeros) {
    .Call('_RcppML_Rcpp_projectH_dense', PACKAGE = 'RcppML', A, h, nonneg, L1, threads, mask_zeros)
}

Rcpp_mse_sparse <- function(A, w, d, h, mask_zeros, threads) {
    .Call('_RcppML_Rcpp_mse_sparse', PACKAGE = 'RcppML', A, w, d, h, mask_zeros, threads)
}

Rcpp_mse_dense <- function(A, w, d, h, mask_zeros, threads) {
    .Call('_RcppML_Rcpp_mse_dense', PACKAGE = 'RcppML', A, w, d, h, mask_zeros, threads)
}

Rcpp_nmf_sparse <- function(A, k, tol, maxit, verbose, nonneg, L1, seed, diag, mask_zeros, threads) {
    .Call('_RcppML_Rcpp_nmf_sparse', PACKAGE = 'RcppML', A, k, tol, maxit, verbose, nonneg, L1, seed, diag, mask_zeros, threads)
}

Rcpp_nmf_dense <- function(A, k, tol, maxit, verbose, nonneg, L1, seed, diag, mask_zeros, threads) {
    .Call('_RcppML_Rcpp_nmf_dense', PACKAGE = 'RcppML', A, k, tol, maxit, verbose, nonneg, L1, seed, diag, mask_zeros, threads)
}

Rcpp_bipartition_sparse <- function(A, tol, maxit, nonneg, samples, seed, verbose = FALSE, calc_dist = FALSE, diag = TRUE) {
    .Call('_RcppML_Rcpp_bipartition_sparse', PACKAGE = 'RcppML', A, tol, maxit, nonneg, samples, seed, verbose, calc_dist, diag)
}

Rcpp_bipartition_dense <- function(A, tol, maxit, nonneg, samples, seed, verbose = FALSE, calc_dist = FALSE, diag = TRUE) {
    .Call('_RcppML_Rcpp_bipartition_dense', PACKAGE = 'RcppML', A, tol, maxit, nonneg, samples, seed, verbose, calc_dist, diag)
}

Rcpp_dclust_sparse <- function(A, min_samples, min_dist, verbose, tol, maxit, nonneg, seed, threads) {
    .Call('_RcppML_Rcpp_dclust_sparse', PACKAGE = 'RcppML', A, min_samples, min_dist, verbose, tol, maxit, nonneg, seed, threads)
}

#' @title Non-negative least squares
#'
#' @description Solves the equation \code{a %*% x = b} for \code{x} subject to \eqn{x > 0}.
#'
#' @details 
#' This is a very fast implementation of non-negative least squares (NNLS), suitable for very small or very large systems.
#'
#' **Algorithm**. Sequential coordinate descent (CD) is at the core of this implementation, and requires an initialization of \eqn{x}. There are two supported methods for initialization of \eqn{x}:
#' 1. **Zero-filled initialization** when \code{fast_nnls = FALSE} and \code{cd_maxit > 0}. This is generally very efficient for well-conditioned and small systems.
#' 2. **Approximation with FAST** when \code{fast_nnls = TRUE}. Forward active set tuning (FAST), described below, finds an approximate active set using unconstrained least squares solutions found by Cholesky decomposition and substitution. To use only FAST approximation, set \code{cd_maxit = 0}.
#'
#' \code{a} must be symmetric positive definite if FAST NNLS is used, but this is not checked.
#'
#' See our BioRXiv manuscript (references) for benchmarking against Lawson-Hanson NNLS and for a more technical introduction to these methods.
#' 
#' **Coordinate Descent NNLS**. Least squares by **sequential coordinate descent** is used to ensure the solution returned is exact. This algorithm was 
#' introduced by Franc et al. (2005), and our implementation is a vectorized and optimized rendition of that found in the NNLM R package by Xihui Lin (2020).
#' 
#' **FAST NNLS.** Forward active set tuning (FAST) is an exact or near-exact NNLS approximation initialized by an unconstrained 
#' least squares solution. Negative values in this unconstrained solution are set to zero (the "active set"), and all 
#' other values are added  to a "feasible set". An unconstrained least squares solution is then solved for the 
#' "feasible set", any negative values in the resulting solution are set to zero, and the process is repeated until 
#' the feasible set solution is strictly positive. 
#' 
#' The FAST algorithm has a definite convergence guarantee because the 
#' feasible set will either converge or become smaller with each iteration. The result is generally exact or nearly 
#' exact for small well-conditioned systems (< 50 variables) within 2 iterations and thus sets up coordinate
#' descent for very rapid convergence. The FAST method is similar to the first phase of the so-called "TNT-NN" algorithm (Myre et al., 2017), 
#' but the latter half of that method relies heavily on heuristics to refine the approximate active set, which we avoid by using 
#' coordinate descent instead.
#' 
#' @param a symmetric positive definite matrix giving coefficients of the linear system
#' @param b matrix giving the right-hand side(s) of the linear system
#' @param L1 L1/LASSO penalty to be subtracted from \code{b}
#' @param fast_nnls initialize coordinate descent with a FAST NNLS approximation
#' @param cd_maxit maximum number of coordinate descent iterations
#' @param cd_tol stopping criteria, difference in \eqn{x} across consecutive solutions over the sum of \eqn{x}
#' @return vector or matrix giving solution for \code{x}
#' @export
#' @author Zach DeBruine
#' @seealso \code{\link{nmf}}, \code{\link{project}}
#' @md
#' 
#' @references
#' 
#' DeBruine, ZJ, Melcher, K, and Triche, TJ. (2021). "High-performance non-negative matrix factorization for large single-cell data." BioRXiv.
#' 
#' Franc, VC, Hlavac, VC, and Navara, M. (2005). "Sequential Coordinate-Wise Algorithm for the Non-negative Least Squares Problem. Proc. Int'l Conf. Computer Analysis of Images and Patterns."
#'
#' Lin, X, and Boutros, PC (2020). "Optimization and expansion of non-negative matrix factorization." BMC Bioinformatics.
#' 
#' Myre, JM, Frahm, E, Lilja DJ, and Saar, MO. (2017) "TNT-NN: A Fast Active Set Method for Solving Large Non-Negative Least Squares Problems". Proc. Computer Science.
#'
#' @examples 
#' \dontrun{
#' # compare solution to base::solve for a random system
#' X <- matrix(runif(100), 10, 10)
#' a <- crossprod(X)
#' b <- crossprod(X, runif(10))
#' unconstrained_soln <- solve(a, b)
#' nonneg_soln <- nnls(a, b)
#' unconstrained_err <- mean((a %*% unconstrained_soln - b)^2)
#' nonnegative_err <- mean((a %*% nonneg_soln - b)^2)
#' unconstrained_err
#' nonnegative_err
#' all.equal(solve(a, b), nnls(a, b))
#' 
#' # example adapted from multiway::fnnls example 1
#' X <- matrix(1:100,50,2)
#' y <- matrix(101:150,50,1)
#' beta <- solve(crossprod(X)) %*% crossprod(X, y)
#' beta
#' beta <- nnls(crossprod(X), crossprod(X, y))
#' beta
#' }
nnls <- function(a, b, cd_maxit = 100L, cd_tol = 1e-8, fast_nnls = FALSE, L1 = 0) {
    .Call('_RcppML_nnls', PACKAGE = 'RcppML', a, b, cd_maxit, cd_tol, fast_nnls, L1)
}

Try the RcppML package in your browser

Any scripts or data that you put into this service are public.

RcppML documentation built on Sept. 22, 2021, 1:06 a.m.