2
0
Fork 0

del: old CVE implementation

This commit is contained in:
Daniel Kapla 2019-09-16 11:18:20 +02:00
parent 9e46a2d3d7
commit 03153ef05e
21 changed files with 0 additions and 1347 deletions

View File

@ -1,13 +0,0 @@
Package: CVE
Type: Package
Title: Conditional Variance Estimator for Sufficient Dimension Reduction
Version: 1.0
Date: 2019-07-29
Author: Loki
Maintainer: Loki <loki@no.mail>
Description: Implementation of the Conditional Variance Estimation (CVE) method. This package version is writen by using Rcpp, RcppArmadillo.
License: GPL-3
Imports: Rcpp (>= 1.0.2)
LinkingTo: Rcpp, RcppArmadillo
Encoding: UTF-8
RoxygenNote: 6.1.1

View File

@ -1,18 +0,0 @@
# Generated by roxygen2: do not edit by hand
S3method(plot,cve)
export(cve)
export(cve.call)
export(dataset)
export(estimateBandwidth)
export(rStiefel)
import(Rcpp)
import(stats)
importFrom(Rcpp,evalCpp)
importFrom(graphics,lines)
importFrom(graphics,plot)
importFrom(graphics,points)
importFrom(stats,model.frame)
importFrom(stats,rbinom)
importFrom(stats,rnorm)
useDynLib(CVE)

View File

@ -1,159 +0,0 @@
#' Implementation of the CVE method.
#'
#' Conditional Variance Estimator (CVE) is a novel sufficient dimension
#' reduction (SDR) method assuming a model
#' \deqn{Y \sim g(B'X) + \epsilon}{Y ~ g(B'X) + epsilon}
#' where B'X is a lower dimensional projection of the predictors.
#'
#' @param formula Formel for the regression model defining `X`, `Y`.
#' See: \code{\link{formula}}.
#' @param data data.frame holding data for formula.
#' @param method The different only differe in the used optimization.
#' All of them are Gradient based optimization on a Stiefel manifold.
#' \itemize{
#' \item "simple" Simple reduction of stepsize.
#' \item "linesearch" determines stepsize with backtracking linesearch
#' using Armijo-Wolf conditions.
#' \item TODO: further
#' }
#' @param ... Further parameters depending on the used method.
#' TODO: See ...
#' @examples
#' library(CVE)
#'
#' # sample dataset
#' ds <- dataset("M5")
#'
#' # call ´cve´ with default method (aka "simple")
#' dr.simple <- cve(ds$Y ~ ds$X, k = ncol(ds$B))
#' # plot optimization history (loss via iteration)
#' plot(dr.simple, main = "CVE M5 simple")
#'
#' # call ´cve´ with method "linesearch" using ´data.frame´ as data.
#' data <- data.frame(Y = ds$Y, X = ds$X)
#' # Note: ´Y, X´ are NOT defined, they are extracted from ´data´.
#' dr.linesearch <- cve(Y ~ ., data, method = "linesearch", k = ncol(ds$B))
#' plot(dr.linesearch, main = "CVE M5 linesearch")
#'
#' @references Fertl L., Bura E. Conditional Variance Estimation for Sufficient Dimension Reduction, 2019
#'
#' @import stats
#' @importFrom stats model.frame
#' @export
cve <- function(formula, data, method = "simple", ...) {
# check for type of `data` if supplied and set default
if (missing(data)) {
data <- environment(formula)
} else if (!is.data.frame(data)) {
stop('Parameter `data` must be a `data.frame` or missing.')
}
# extract `X`, `Y` from `formula` with `data`
model <- stats::model.frame(formula, data)
X <- as.matrix(model[,-1, drop=FALSE])
Y <- as.matrix(model[, 1, drop=FALSE])
# pass extracted data on to [cve.call()]
dr <- cve.call(X, Y, method = method, ...)
# overwrite `call` property from [cve.call()]
dr$call <- match.call()
return(dr)
}
#' @param nObs as describet in the Paper.
#' @rdname cve
#' @export
cve.call <- function(X, Y, method = "simple", nObs = nrow(X)^.5, k, ...) {
# TODO: replace default value of `k` by `max.dim` when fast enough
if (missing(k)) {
stop("TODO: parameter `k` (rank(B)) is required, replace by `max.dim`.")
}
# parameter checking
if (!(is.matrix(X) && is.matrix(Y))) {
stop('X and Y should be matrices.')
}
if (nrow(X) != nrow(Y)) {
stop('Rows of X and Y are not compatible.')
}
if (ncol(X) < 2) {
stop('X is one dimensional, no need for dimension reduction.')
}
if (ncol(Y) > 1) {
stop('Only one dimensional responces Y are supported.')
}
# call C++ CVE implementation
# dr ... Dimension Reduction
dr <- cve_cpp(X, Y, tolower(method), k = k, nObs = nObs, ...)
# augment result information
dr$method <- method
dr$call <- match.call()
class(dr) <- "cve"
return(dr)
}
# TODO: write summary
# summary.cve <- function() {
# # code #
# }
#' Ploting helper for objects of class \code{cve}.
#'
#' @param x Object of class \code{cve} (result of [cve()]).
#' @param content Specifies what to plot:
#' \itemize{
#' \item "history" Plots the loss history from stiefel optimization
#' (default).
#' \item ... TODO: add (if there are any)
#' }
#' @param ... Pass through parameters to [plot()] and [lines()]
#'
#' @usage ## S3 method for class 'cve'
#' plot(x, content = "history", ...)
#' @seealso see \code{\link{par}} for graphical parameters to pass through
#' as well as \code{\link{plot}} for standard plot utility.
#' @importFrom graphics plot lines points
#' @method plot cve
#' @export
plot.cve <- function(x, ...) {
H <- x$history
H_1 <- H[H[, 1] > 0, 1]
defaults <- list(
main = "History",
xlab = "Iterations i",
ylab = expression(loss == L[n](V^{(i)})),
xlim = c(1, nrow(H)),
ylim = c(0, max(H)),
type = "l"
)
call.plot <- match.call()
keys <- names(defaults)
keys <- keys[match(keys, names(call.plot)[-1], nomatch = 0) == 0]
for (key in keys) {
call.plot[[key]] <- defaults[[key]]
}
call.plot[[1L]] <- quote(plot)
call.plot$x <- quote(1:length(H_1))
call.plot$y <- quote(H_1)
eval(call.plot)
if (ncol(H) > 1) {
for (i in 2:ncol(H)) {
H_i <- H[H[, i] > 0, i]
lines(1:length(H_i), H_i)
}
}
x.ends <- apply(H, 2, function(h) { length(h[h > 0]) })
y.ends <- apply(H, 2, function(h) { min(h[h > 0]) })
points(x.ends, y.ends)
}

View File

@ -1,113 +0,0 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' Gradient computation of the loss `L_n(V)`.
#'
#' The loss is defined as
#' \deqn{L_n(V) := \frac{1}{n}\sum_{j=1}^n y_2(V, X_j) - y_1(V, X_j)^2}{L_n(V) := 1/n sum_j( (y_2(V, X_j) - y_1(V, X_j)^2 )}
#' with
#' \deqn{y_l(s_0) := \sum_{i=1}^n w_i(V, s_0)Y_i^l}{y_l(s_0) := sum_i(w_i(V, s_0) Y_i^l)}
#'
#' @rdname optStiefel
#' @keywords internal
#' @name gradient
NULL
#' Stiefel Optimization.
#'
#' Stiefel Optimization for \code{V} given a dataset \code{X} and responces
#' \code{Y} for the model \deqn{Y\sim g(B'X) + \epsilon}{Y ~ g(B'X) + epsilon}
#' to compute the matrix `B` such that \eqn{span{B} = span(V)^{\bot}}{%
#' span(B) = orth(span(B))}.
#'
#' @param X data points
#' @param Y response
#' @param k assumed \eqn{rank(B)}
#' @param nObs parameter for bandwidth estimation, typical value
#' \code{nObs = nrow(X)^lambda} with \code{lambda} in the range [0.3, 0.8].
#' @param tau Initial step size
#' @param tol Tolerance for update error used for stopping criterion
#' \eqn{|| V(j) V(j)' - V(j+1) V(j+1)' ||_2 < tol}{%
#' \| V_j V_j' - V_{j+1} V_{j+1}' \|_2 < tol}.
#' @param maxIter Upper bound of optimization iterations
#'
#' @return List containing the bandwidth \code{h}, optimization objective \code{V}
#' and the matrix \code{B} estimated for the model as a orthogonal basis of the
#' orthogonal space spaned by \code{V}.
#'
#' @rdname optStiefel
#' @keywords internal
#' @name optStiefel_simple
NULL
#' @rdname optStiefel
#' @keywords internal
#' @name optStiefel_linesearch
NULL
#' Estimated bandwidth for CVE.
#'
#' Estimates a propper bandwidth \code{h} according
#' \deqn{h = \chi_{p-q}^{-1}\left(\frac{nObs - 1}{n-1}\right)\frac{2 tr(\Sigma)}{p}}{%
#' h = qchisq( (nObs - 1)/(n - 1), p - q ) 2 tr(Sigma) / p}
#'
#' @param X data matrix of dimension (n x p) with n data points X_i of dimension
#' q. Therefor each row represents a datapoint of dimension p.
#' @param k Guess for rank(B).
#' @param nObs Ether numeric of a function. If specified as numeric value
#' its used in the computation of the bandwidth directly. If its a function
#' `nObs` is evaluated as \code{nObs(nrow(x))}. The default behaviou if not
#' supplied at all is to use \code{nObs <- nrow(x)^0.5}.
#'
#' @seealso [qchisq()]
#'
#' @export
estimateBandwidth <- function(X, k, nObs) {
.Call('_CVE_estimateBandwidth', PACKAGE = 'CVE', X, k, nObs)
}
#' Random element from Stiefel Manifold `S(p, q)`.
#'
#' Draws an element of \eqn{S(p, q)} which is the Stiefel Manifold.
#' This is done by taking the Q-component of the QR decomposition
#' from a `(p, q)` Matrix with independent standart normal entries.
#' As a semi-orthogonal Matrix the result `V` satisfies \eqn{V'V = I_q}.
#'
#' @param p Row dimension
#' @param q Column dimension
#'
#' @return Matrix of dim `(p, q)`.
#'
#' @seealso <https://en.wikipedia.org/wiki/Stiefel_manifold>
#'
#' @export
rStiefel <- function(p, q) {
.Call('_CVE_rStiefel', PACKAGE = 'CVE', p, q)
}
#' Conditional Variance Estimation (CVE) method.
#'
#' This version uses a "simple" stiefel optimization schema.
#'
#' @param X data points
#' @param Y response
#' @param k assumed \eqn{rank(B)}
#' @param nObs parameter for bandwidth estimation, typical value
#' \code{nObs = nrow(X)^lambda} with \code{lambda} in the range [0.3, 0.8].
#' @param h Bandwidth, if not specified \code{nObs} is used to compute a bandwidth.
#' on the other hand if given (positive floating point number) \code{nObs} is ignored.
#' @param tau Initial step size (default 1)
#' @param tol Tolerance for update error used for stopping criterion (default 1e-5)
#' @param slack Ratio of small negative error allowed in loss optimization (default -1e-10)
#' @param maxIter Upper bound of optimization iterations (default 50)
#' @param attempts Number of tryes with new random optimization starting points (default 10)
#'
#' @return List containing the bandwidth \code{h}, optimization objective \code{V}
#' and the matrix \code{B} estimated for the model as a orthogonal basis of the
#' orthogonal space spaned by \code{V}.
#'
#' @keywords internal
cve_cpp <- function(X, Y, method, k, nObs, h = -1., tauInitial = 1., rho1 = 0.1, rho2 = 0.9, tol = 1e-5, maxIter = 50L, maxLineSearchIter = 10L, attempts = 10L) {
.Call('_CVE_cve_cpp', PACKAGE = 'CVE', X, Y, method, k, nObs, h, tauInitial, rho1, rho2, tol, maxIter, maxLineSearchIter, attempts)
}

View File

@ -1,109 +0,0 @@
#' Generates test datasets.
#'
#' Provides sample datasets. There are 5 different datasets named
#' M1, M2, M3, M4 and M5 describet in the paper references below.
#' The general model is given by:
#' \deqn{Y ~ g(B'X) + \epsilon}
#'
#' @param name One of \code{"M1"}, \code{"M2"}, \code{"M3"}, \code{"M4"} or \code{"M5"}
#' @param n nr samples
#' @param p Dim. of random variable \code{X}.
#' @param p.mix Only for \code{"M4"}, see: below.
#' @param lambda Only for \code{"M4"}, see: below.
#'
#' @return List with elements
#' \itemize{
#' \item{X}{data}
#' \item{Y}{response}
#' \item{B}{Used dim-reduction matrix}
#' \item{name}{Name of the dataset (name parameter)}
#' }
#'
#' @section M1:
#' The data follows \eqn{X\sim N_p(0, \Sigma)}{X ~ N_p(0, Sigma)} for a subspace
#' dimension of \eqn{k = 2} with a default of \eqn{n = 200} data points.
#' The link function \eqn{g} is given as
#' \deqn{g(x) = \frac{x_1}{0.5 + (x_2 + 1.5)^2} + 0.5\epsilon}{g(x) = x_1 / (0.5 + (x_2 + 1.5)^2) + 0.5 epsilon}
#' @section M2:
#' \eqn{X\sim N_p(0, \Sigma)}{X ~ N_p(0, Sigma)} with \eqn{k = 2} with a default of \eqn{n = 200} data points.
#' The link function \eqn{g} is given as
#' \deqn{g(x) = x_1 x_2^2 + 0.5\epsilon}{g(x) = x_1 x_2^2 + 0.5 epsilon}
#' @section M3:
#' TODO:
#' @section M4:
#' TODO:
#' @section M5:
#' TODO:
#'
#' @import stats
#' @importFrom stats rnorm rbinom
#' @export
dataset <- function(name = "M1", n, B, p.mix = 0.3, lambda = 1.0) {
# validate parameters
stopifnot(name %in% c("M1", "M2", "M3", "M4", "M5"))
# set default values if not supplied
if (missing(n)) {
n <- if (name %in% c("M1", "M2")) 200 else if (name != "M5") 100 else 42
}
if (missing(B)) {
p <- 12
if (name == "M1") {
B <- cbind(
c( 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0),
c( 1,-1, 1,-1, 1,-1, 0, 0, 0, 0, 0, 0)
) / sqrt(6)
} else if (name == "M2") {
B <- cbind(
c(c(1, 0), rep(0, 10)),
c(c(0, 1), rep(0, 10))
)
} else {
B <- matrix(c(rep(1 / sqrt(6), 6), rep(0, 6)), 12, 1)
}
} else {
p <- dim(B)[1]
# validate col. nr to match dataset `k = dim(B)[2]`
stopifnot(
name %in% c("M1", "M2") && dim(B)[2] == 2,
name %in% c("M3", "M4", "M5") && dim(B)[2] == 1
)
}
# set link function `g` for model `Y ~ g(B'X) + epsilon`
if (name == "M1") {
g <- function(BX) { BX[1] / (0.5 + (BX[2] + 1.5)^2) }
} else if (name == "M2") {
g <- function(BX) { BX[1] * BX[2]^2 }
} else if (name %in% c("M3", "M4")) {
g <- function(BX) { cos(BX[1]) }
} else { # name == "M5"
g <- function(BX) { 2 * log(abs(BX[1]) + 1) }
}
# compute X
if (name != "M4") {
# compute root of the covariance matrix according the dataset
if (name %in% c("M1", "M3")) {
# Variance-Covariance structure for `X ~ N_p(0, \Sigma)` with
# `\Sigma_{i, j} = 0.5^{|i - j|}`.
Sigma <- matrix(0.5^abs(kronecker(1:p, 1:p, '-')), p, p)
# decompose Sigma to Sigma.root^T Sigma.root = Sigma for usage in creation of `X`
Sigma.root <- chol(Sigma)
} else { # name %in% c("M2", "M5")
Sigma.root <- diag(rep(1, p)) # d-dim identity
}
# data `X` as multivariate random normal variable with
# variance matrix `Sigma`.
X <- replicate(p, rnorm(n, 0, 1)) %*% Sigma.root
} else { # name == "M4"
X <- t(replicate(100, rep((1 - 2 * rbinom(1, 1, p.mix)) * lambda, p) + rnorm(p, 0, 1)))
}
# responce `y ~ g(B'X) + epsilon` with `epsilon ~ N(0, 1 / 2)`
Y <- apply(X, 1, function(X_i) {
g(t(B) %*% X_i) + rnorm(1, 0, 0.5)
})
return(list(X = X, Y = Y, B = B, name = name))
}

View File

@ -1,16 +0,0 @@
#' Conditional Variance Estimator (CVE)
#'
#' Conditional Variance Estimator for Sufficient Dimension
#' Reduction
#'
#' TODO: And some details
#'
#'
#' @references Fertl Likas, Bura Efstathia. Conditional Variance Estimation for Sufficient Dimension Reduction, 2019
#'
#' @docType package
#' @author Loki
#' @import Rcpp
#' @importFrom Rcpp evalCpp
#' @useDynLib CVE
"_PACKAGE"

View File

@ -1 +0,0 @@
runtime_test Runtime comparison of CVE against MAVE for M1 - M5 datasets.

View File

@ -1,89 +0,0 @@
# Usage:
# ~$ Rscript runtime_test.R
library(CVE) # load CVE
#' Writes progress to console.
tell.user <- function(name, start.time, i, length) {
cat("\rRunning Test (", name, "):",
i, "/", length,
" - elapsed:", format(Sys.time() - start.time), "\033[K")
}
subspace.dist <- function(B1, B2){
P1 <- B1 %*% solve(t(B1) %*% B1) %*% t(B1)
P2 <- B2 %*% solve(t(B2) %*% B2) %*% t(B2)
return(norm(P1 - P2, type = 'F'))
}
# Number of simulations
SIM.NR <- 50
# maximal number of iterations in curvilinear search algorithm
MAXIT <- 50
# number of arbitrary starting values for curvilinear optimization
ATTEMPTS <- 10
# set names of datasets
dataset.names <- c("M1", "M2", "M3", "M4", "M5")
# Set used CVE method
methods <- c("simple") # c("legacy", "simple", "sgd", "linesearch")
# Setup error and time tracking variables
error <- matrix(NA, SIM.NR, length(methods) * length(dataset.names))
time <- matrix(NA, SIM.NR, ncol(error))
colnames(error) <- kronecker(paste0(dataset.names, '-'), methods, paste0)
colnames(time) <- colnames(error)
# only for telling user (to stdout)
count <- 0
start.time <- Sys.time()
# Start simulation loop.
for (sim in 1:SIM.NR) {
# Repeat for each dataset.
for (name in dataset.names) {
count <- count + 1
tell.user(name, start.time, count, SIM.NR * length(dataset.names))
# Create a new dataset
ds <- dataset(name)
# Prepare X, Y and combine to data matrix
Y <- ds$Y
X <- ds$X
data <- cbind(Y, X)
# get dimensions
dim <- ncol(X)
truedim <- ncol(ds$B)
for (method in methods) {
dr.time <- system.time(
dr <- cve.call(X, Y,
method = method,
k = truedim,
attempts = ATTEMPTS
)
)
dr <- dr[[truedim]]
key <- paste0(name, '-', method)
error[sim, key] <- subspace.dist(dr$B, ds$B) / sqrt(2 * truedim)
time[sim, key] <- dr.time["elapsed"]
}
}
}
cat("\n\n## Time [sec] Means:\n")
print(colMeans(time))
cat("\n## Error Means:\n")
print(colMeans(error))
at <- seq(ncol(error)) + rep(seq(ncol(error) / length(methods)) - 1, each = length(methods))
boxplot(error,
main = paste0("Error (Nr of simulations ", SIM.NR, ")"),
ylab = "Error",
las = 2,
at = at
)
boxplot(time,
main = paste0("Time (Nr of simulations ", SIM.NR, ")"),
ylab = "Time [sec]",
las = 2,
at = at
)

Binary file not shown.

View File

@ -1,20 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/package.R
\docType{package}
\name{CVE-package}
\alias{CVE}
\alias{CVE-package}
\title{Conditional Variance Estimator (CVE)}
\description{
Conditional Variance Estimator for Sufficient Dimension
Reduction
}
\details{
TODO: And some details
}
\references{
Fertl Likas, Bura Efstathia. Conditional Variance Estimation for Sufficient Dimension Reduction, 2019
}
\author{
Loki
}

View File

@ -1,58 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/CVE.R
\name{cve}
\alias{cve}
\alias{cve.call}
\title{Implementation of the CVE method.}
\usage{
cve(formula, data, method = "simple", ...)
cve.call(X, Y, method = "simple", nObs = nrow(X)^0.5, k, ...)
}
\arguments{
\item{formula}{Formel for the regression model defining `X`, `Y`.
See: \code{\link{formula}}.}
\item{data}{data.frame holding data for formula.}
\item{method}{The different only differe in the used optimization.
All of them are Gradient based optimization on a Stiefel manifold.
\itemize{
\item "simple" Simple reduction of stepsize.
\item "linesearch" determines stepsize with backtracking linesearch
using Armijo-Wolf conditions.
\item TODO: further
}}
\item{...}{Further parameters depending on the used method.
TODO: See ...}
\item{nObs}{as describet in the Paper.}
}
\description{
Conditional Variance Estimator (CVE) is a novel sufficient dimension
reduction (SDR) method assuming a model
\deqn{Y \sim g(B'X) + \epsilon}{Y ~ g(B'X) + epsilon}
where B'X is a lower dimensional projection of the predictors.
}
\examples{
library(CVE)
# sample dataset
ds <- dataset("M5")
# call ´cve´ with default method (aka "simple")
dr.simple <- cve(ds$Y ~ ds$X, k = ncol(ds$B))
# plot optimization history (loss via iteration)
plot(dr.simple, main = "CVE M5 simple")
# call ´cve´ with method "linesearch" using ´data.frame´ as data.
data <- data.frame(Y = ds$Y, X = ds$X)
# Note: ´Y, X´ are NOT defined, they are extracted from ´data´.
dr.linesearch <- cve(Y ~ ., data, method = "linesearch", k = ncol(ds$B))
plot(dr.linesearch, main = "CVE M5 linesearch")
}
\references{
Fertl L., Bura E. Conditional Variance Estimation for Sufficient Dimension Reduction, 2019
}

View File

@ -1,42 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/RcppExports.R
\name{cve_cpp}
\alias{cve_cpp}
\title{Conditional Variance Estimation (CVE) method.}
\usage{
cve_cpp(X, Y, method, k, nObs, h = -1, tauInitial = 1, rho1 = 0.1,
rho2 = 0.9, tol = 1e-05, maxIter = 50L, maxLineSearchIter = 10L,
attempts = 10L)
}
\arguments{
\item{X}{data points}
\item{Y}{response}
\item{k}{assumed \eqn{rank(B)}}
\item{nObs}{parameter for bandwidth estimation, typical value
\code{nObs = nrow(X)^lambda} with \code{lambda} in the range [0.3, 0.8].}
\item{h}{Bandwidth, if not specified \code{nObs} is used to compute a bandwidth.
on the other hand if given (positive floating point number) \code{nObs} is ignored.}
\item{tol}{Tolerance for update error used for stopping criterion (default 1e-5)}
\item{maxIter}{Upper bound of optimization iterations (default 50)}
\item{attempts}{Number of tryes with new random optimization starting points (default 10)}
\item{tau}{Initial step size (default 1)}
\item{slack}{Ratio of small negative error allowed in loss optimization (default -1e-10)}
}
\value{
List containing the bandwidth \code{h}, optimization objective \code{V}
and the matrix \code{B} estimated for the model as a orthogonal basis of the
orthogonal space spaned by \code{V}.
}
\description{
This version uses a "simple" stiefel optimization schema.
}
\keyword{internal}

View File

@ -1,64 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/datasets.R
\name{dataset}
\alias{dataset}
\title{Generates test datasets.}
\usage{
dataset(name = "M1", n, B, p.mix = 0.3, lambda = 1)
}
\arguments{
\item{name}{One of \code{"M1"}, \code{"M2"}, \code{"M3"}, \code{"M4"} or \code{"M5"}}
\item{n}{nr samples}
\item{p.mix}{Only for \code{"M4"}, see: below.}
\item{lambda}{Only for \code{"M4"}, see: below.}
\item{p}{Dim. of random variable \code{X}.}
}
\value{
List with elements
\itemize{
\item{X}{data}
\item{Y}{response}
\item{B}{Used dim-reduction matrix}
\item{name}{Name of the dataset (name parameter)}
}
}
\description{
Provides sample datasets. There are 5 different datasets named
M1, M2, M3, M4 and M5 describet in the paper references below.
The general model is given by:
\deqn{Y ~ g(B'X) + \epsilon}
}
\section{M1}{
The data follows \eqn{X\sim N_p(0, \Sigma)}{X ~ N_p(0, Sigma)} for a subspace
dimension of \eqn{k = 2} with a default of \eqn{n = 200} data points.
The link function \eqn{g} is given as
\deqn{g(x) = \frac{x_1}{0.5 + (x_2 + 1.5)^2} + 0.5\epsilon}{g(x) = x_1 / (0.5 + (x_2 + 1.5)^2) + 0.5 epsilon}
}
\section{M2}{
\eqn{X\sim N_p(0, \Sigma)}{X ~ N_p(0, Sigma)} with \eqn{k = 2} with a default of \eqn{n = 200} data points.
The link function \eqn{g} is given as
\deqn{g(x) = x_1 x_2^2 + 0.5\epsilon}{g(x) = x_1 x_2^2 + 0.5 epsilon}
}
\section{M3}{
TODO:
}
\section{M4}{
TODO:
}
\section{M5}{
TODO:
}

View File

@ -1,27 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/RcppExports.R
\name{estimateBandwidth}
\alias{estimateBandwidth}
\title{Estimated bandwidth for CVE.}
\usage{
estimateBandwidth(X, k, nObs)
}
\arguments{
\item{X}{data matrix of dimension (n x p) with n data points X_i of dimension
q. Therefor each row represents a datapoint of dimension p.}
\item{k}{Guess for rank(B).}
\item{nObs}{Ether numeric of a function. If specified as numeric value
its used in the computation of the bandwidth directly. If its a function
`nObs` is evaluated as \code{nObs(nrow(x))}. The default behaviou if not
supplied at all is to use \code{nObs <- nrow(x)^0.5}.}
}
\description{
Estimates a propper bandwidth \code{h} according
\deqn{h = \chi_{p-q}^{-1}\left(\frac{nObs - 1}{n-1}\right)\frac{2 tr(\Sigma)}{p}}{%
h = qchisq( (nObs - 1)/(n - 1), p - q ) 2 tr(Sigma) / p}
}
\seealso{
[qchisq()]
}

View File

@ -1,42 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/RcppExports.R
\name{gradient}
\alias{gradient}
\alias{optStiefel_simple}
\alias{optStiefel_linesearch}
\title{Gradient computation of the loss `L_n(V)`.}
\arguments{
\item{X}{data points}
\item{Y}{response}
\item{k}{assumed \eqn{rank(B)}}
\item{nObs}{parameter for bandwidth estimation, typical value
\code{nObs = nrow(X)^lambda} with \code{lambda} in the range [0.3, 0.8].}
\item{tau}{Initial step size}
\item{tol}{Tolerance for update error used for stopping criterion
\eqn{|| V(j) V(j)' - V(j+1) V(j+1)' ||_2 < tol}{%
\| V_j V_j' - V_{j+1} V_{j+1}' \|_2 < tol}.}
\item{maxIter}{Upper bound of optimization iterations}
}
\value{
List containing the bandwidth \code{h}, optimization objective \code{V}
and the matrix \code{B} estimated for the model as a orthogonal basis of the
orthogonal space spaned by \code{V}.
}
\description{
The loss is defined as
\deqn{L_n(V) := \frac{1}{n}\sum_{j=1}^n y_2(V, X_j) - y_1(V, X_j)^2}{L_n(V) := 1/n sum_j( (y_2(V, X_j) - y_1(V, X_j)^2 )}
with
\deqn{y_l(s_0) := \sum_{i=1}^n w_i(V, s_0)Y_i^l}{y_l(s_0) := sum_i(w_i(V, s_0) Y_i^l)}
Stiefel Optimization for \code{V} given a dataset \code{X} and responces
\code{Y} for the model \deqn{Y\sim g(B'X) + \epsilon}{Y ~ g(B'X) + epsilon}
to compute the matrix `B` such that \eqn{span{B} = span(V)^{\bot}}{%
span(B) = orth(span(B))}.
}
\keyword{internal}

View File

@ -1,28 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/CVE.R
\name{plot.cve}
\alias{plot.cve}
\title{Ploting helper for objects of class \code{cve}.}
\usage{
## S3 method for class 'cve'
plot(x, content = "history", ...)
}
\arguments{
\item{x}{Object of class \code{cve} (result of [cve()]).}
\item{...}{Pass through parameters to [plot()] and [lines()]}
\item{content}{Specifies what to plot:
\itemize{
\item "history" Plots the loss history from stiefel optimization
(default).
\item ... TODO: add (if there are any)
}}
}
\description{
Ploting helper for objects of class \code{cve}.
}
\seealso{
see \code{\link{par}} for graphical parameters to pass through
as well as \code{\link{plot}} for standard plot utility.
}

View File

@ -1,25 +0,0 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/RcppExports.R
\name{rStiefel}
\alias{rStiefel}
\title{Random element from Stiefel Manifold `S(p, q)`.}
\usage{
rStiefel(p, q)
}
\arguments{
\item{p}{Row dimension}
\item{q}{Column dimension}
}
\value{
Matrix of dim `(p, q)`.
}
\description{
Draws an element of \eqn{S(p, q)} which is the Stiefel Manifold.
This is done by taking the Q-component of the QR decomposition
from a `(p, q)` Matrix with independent standart normal entries.
As a semi-orthogonal Matrix the result `V` satisfies \eqn{V'V = I_q}.
}
\seealso{
<https://en.wikipedia.org/wiki/Stiefel_manifold>
}

View File

@ -1,427 +0,0 @@
// only `RcppArmadillo.h` which includes `Rcpp.h`
#include <RcppArmadillo.h>
// through the depends attribute `Rcpp` is tolled to create
// hooks for `RcppArmadillo` needed by the build process.
//
// [[Rcpp::depends(RcppArmadillo)]]
// required for `R::qchisq()` used in `estimateBandwidth()`
#include <Rmath.h>
// for proper error handling
#include <stdexcept>
//' Estimated bandwidth for CVE.
//'
//' Estimates a propper bandwidth \code{h} according
//' \deqn{h = \chi_{p-q}^{-1}\left(\frac{nObs - 1}{n-1}\right)\frac{2 tr(\Sigma)}{p}}{%
//' h = qchisq( (nObs - 1)/(n - 1), p - q ) 2 tr(Sigma) / p}
//'
//' @param X data matrix of dimension (n x p) with n data points X_i of dimension
//' q. Therefor each row represents a datapoint of dimension p.
//' @param k Guess for rank(B).
//' @param nObs Ether numeric of a function. If specified as numeric value
//' its used in the computation of the bandwidth directly. If its a function
//' `nObs` is evaluated as \code{nObs(nrow(x))}. The default behaviou if not
//' supplied at all is to use \code{nObs <- nrow(x)^0.5}.
//'
//' @seealso [qchisq()]
//'
//' @export
// [[Rcpp::export]]
double estimateBandwidth(const arma::mat& X, arma::uword k, double nObs) {
using namespace arma;
uword n = X.n_rows; // nr samples
uword p = X.n_cols; // dimension of rand. var. `X`
// column mean
mat M = mean(X);
// center `X`
mat C = X.each_row() - M;
// trace of covariance matrix, `traceSigma = Tr(C' C)`
double traceSigma = accu(C % C);
// compute estimated bandwidth
double qchi2 = R::qchisq((nObs - 1.0) / (n - 1), static_cast<double>(k), 1, 0);
return 2.0 * qchi2 * traceSigma / (p * n);
}
//' Random element from Stiefel Manifold `S(p, q)`.
//'
//' Draws an element of \eqn{S(p, q)} which is the Stiefel Manifold.
//' This is done by taking the Q-component of the QR decomposition
//' from a `(p, q)` Matrix with independent standart normal entries.
//' As a semi-orthogonal Matrix the result `V` satisfies \eqn{V'V = I_q}.
//'
//' @param p Row dimension
//' @param q Column dimension
//'
//' @return Matrix of dim `(p, q)`.
//'
//' @seealso <https://en.wikipedia.org/wiki/Stiefel_manifold>
//'
//' @export
// [[Rcpp::export]]
arma::mat rStiefel(arma::uword p, arma::uword q) {
arma::mat Q, R;
arma::qr_econ(Q, R, arma::randn<arma::mat>(p, q));
return Q;
}
//' Gradient computation of the loss `L_n(V)`.
//'
//' The loss is defined as
//' \deqn{L_n(V) := \frac{1}{n}\sum_{j=1}^n y_2(V, X_j) - y_1(V, X_j)^2}{L_n(V) := 1/n sum_j( (y_2(V, X_j) - y_1(V, X_j)^2 )}
//' with
//' \deqn{y_l(s_0) := \sum_{i=1}^n w_i(V, s_0)Y_i^l}{y_l(s_0) := sum_i(w_i(V, s_0) Y_i^l)}
//'
//' @rdname optStiefel
//' @keywords internal
//' @name gradient
double gradient(const arma::mat& X,
const arma::mat& X_diff,
const arma::mat& Y,
const arma::mat& Y_rep,
const arma::mat& V,
const double h,
arma::mat* G = 0 // out
) {
using namespace arma;
uword n = X.n_rows;
// orthogonal projection matrix `Q = I - VV'` for dist computation
mat Q = -(V * V.t());
Q.diag() += 1;
// calc pairwise distances as `D` with `D(i, j) = d_i(V, X_j)`
vec D_vec = sum(square(X_diff * Q), 1);
mat D = reshape(D_vec, n, n);
// calc weights as `W` with `W(i, j) = w_i(V, X_j)`
mat W = exp(D / (-2.0 * h));
// column-wise normalization via 1-norm
W = normalise(W, 1);
vec W_vec = vectorise(W);
// weighted `Y` means (first and second order)
vec y1 = W.t() * Y;
vec y2 = W.t() * square(Y);
// loss for each `X_i`, meaning `L(i) = L_n(V, X_i)`
vec L = y2 - square(y1);
// `loss = L_n(V)`
double loss = mean(L);
// check if gradient as output variable is set
if (G != 0) {
// `G = grad(L_n(V))` a.k.a. gradient of `L` with respect to `V`
vec scale = (repelem(L, n, 1) - square(Y_rep - repelem(y1, n, 1))) % W_vec % D_vec;
mat X_diff_scale = X_diff.each_col() % scale;
(*G) = X_diff_scale.t() * X_diff * V;
(*G) *= -2.0 / (h * h * n);
}
return loss;
}
//' Stiefel Optimization.
//'
//' Stiefel Optimization for \code{V} given a dataset \code{X} and responces
//' \code{Y} for the model \deqn{Y\sim g(B'X) + \epsilon}{Y ~ g(B'X) + epsilon}
//' to compute the matrix `B` such that \eqn{span{B} = span(V)^{\bot}}{%
//' span(B) = orth(span(B))}.
//'
//' @param X data points
//' @param Y response
//' @param k assumed \eqn{rank(B)}
//' @param nObs parameter for bandwidth estimation, typical value
//' \code{nObs = nrow(X)^lambda} with \code{lambda} in the range [0.3, 0.8].
//' @param tau Initial step size
//' @param tol Tolerance for update error used for stopping criterion
//' \eqn{|| V(j) V(j)' - V(j+1) V(j+1)' ||_2 < tol}{%
//' \| V_j V_j' - V_{j+1} V_{j+1}' \|_2 < tol}.
//' @param maxIter Upper bound of optimization iterations
//'
//' @return List containing the bandwidth \code{h}, optimization objective \code{V}
//' and the matrix \code{B} estimated for the model as a orthogonal basis of the
//' orthogonal space spaned by \code{V}.
//'
//' @rdname optStiefel
//' @keywords internal
//' @name optStiefel_simple
double optStiefel_simple(
const arma::mat& X,
const arma::vec& Y,
const int k,
const double h,
const double tauInitial,
const double tol,
const int maxIter,
arma::mat& V, // out
arma::vec& history // out
) {
using namespace arma;
// get dimensions
const uword n = X.n_rows; // nr samples
const uword p = X.n_cols; // dim of random variable `X`
const uword q = p - k; // rank(V) e.g. dim of ortho space of span{B}
// all `X_i - X_j` differences, `X_diff.row(i * n + j) = X_i - X_j`
mat X_diff(n * n, p);
for (uword i = 0, k = 0; i < n; ++i) {
for (uword j = 0; j < n; ++j) {
X_diff.row(k++) = X.row(i) - X.row(j);
}
}
const vec Y_rep = repmat(Y, n, 1);
const mat I_p = eye<mat>(p, p);
// initial start value for `V`
V = rStiefel(p, q);
// init optimization `loss`es, `error` and stepsize `tau`
// double loss_next = datum::inf;
double loss;
double error = datum::inf;
double tau = tauInitial;
int iter;
// main optimization loop
for (iter = 0; iter < maxIter && error > tol; ++iter) {
// calc gradient `G = grad_V(L)(V)`
mat G;
loss = gradient(X, X_diff, Y, Y_rep, V, h, &G);
// matrix `A` for colescy-transform of the gradient
mat A = tau * ((G * V.t()) - (V * G.t()));
// next iteration step of `V`
mat V_tau = inv(I_p + A) * (I_p - A) * V;
// loss after step `L(V(tau))`
double loss_tau = gradient(X, X_diff, Y, Y_rep, V_tau, h);
// store `loss` in `history` and increase `iter`
history(iter) = loss;
// validate if loss decreased
if ((loss_tau - loss) > 0.0) {
// ignore step, retry with half the step size
tau = tau / 2.;
error = datum::inf;
} else {
// compute step error (break condition)
error = norm((V * V.t()) - (V_tau * V_tau.t()), 2) / (2 * q);
// shift for next iteration
V = V_tau;
loss = loss_tau;
}
}
// store final `loss`
history(iter) = loss;
return loss;
}
//' @rdname optStiefel
//' @keywords internal
//' @name optStiefel_linesearch
double optStiefel_linesearch(
const arma::mat& X,
const arma::vec& Y,
const int k,
const double h,
const double tauInitial,
const double tol,
const int maxIter,
const double rho1,
const double rho2,
const int maxLineSearchIter,
arma::mat& V, // out
arma::vec& history // out
) {
using namespace arma;
// get dimensions
const uword n = X.n_rows; // nr samples
const uword p = X.n_cols; // dim of random variable `X`
const uword q = p - k; // rank(V) e.g. dim of ortho space of span{B}
// all `X_i - X_j` differences, `X_diff.row(i * n + j) = X_i - X_j`
mat X_diff(n * n, p);
for (uword i = 0, k = 0; i < n; ++i) {
for (uword j = 0; j < n; ++j) {
X_diff.row(k++) = X.row(i) - X.row(j);
}
}
const vec Y_rep = repmat(Y, n, 1);
const mat I_p = eye<mat>(p, p);
const mat I_2q = eye<mat>(2 * q, 2 * q);
// initial start value for `V`
V = rStiefel(p, q);
// first gradient initialization
mat G;
double loss = gradient(X, X_diff, Y, Y_rep, V, h, &G);
// set first `loss` in history
history(0) = loss;
// main curvilinear optimization loop
double error = datum::inf;
int iter = 0;
while (iter++ < maxIter && error > tol) {
// helper matrices `lU` (linesearch U), `lV` (linesearch V)
// as describet in [Wen, Yin] Lemma 4.
mat lU = join_rows(G, V); // linesearch "U"
mat lV = join_rows(V, -1.0 * G); // linesearch "V"
// `A = G V' - V G'`
mat A = lU * lV.t();
// set initial step size for curvilinear line search
double tau = tauInitial, lower = 0., upper = datum::inf;
// TODO: check if `tau` is valid for inverting
// set line search internal gradient and loss to cycle for next iteration
mat V_tau; // next position after a step of size `tau`, a.k.a. `V(tau)`
mat G_tau; // gradient of `V` at `V(tau) = V_tau`
double loss_tau; // loss (objective) at position `V(tau)`
int lsIter = 0; // linesearch iter
// start line search
do {
mat HV = inv(I_2q + (tau/2.) * lV.t() * lU) * lV.t();
// next step `V`
V_tau = V - tau * (lU * (HV * V));
double LprimeV = -trace(G.t() * A * V);
mat lB = I_p - (tau / 2.) * lU * HV;
loss_tau = gradient(X, X_diff, Y, Y_rep, V_tau, h, &G_tau);
double LprimeV_tau = -2. * trace(G_tau.t() * lB * A * (V + V_tau));
// Armijo condition
if (loss_tau > loss + (rho1 * tau * LprimeV)) {
upper = tau;
tau = (lower + upper) / 2.;
// Wolfe condition
} else if (LprimeV_tau < rho2 * LprimeV) {
lower = tau;
if (upper == datum::inf) {
tau = 2. * lower;
} else {
tau = (lower + upper) / 2.;
}
} else {
break;
}
} while (++lsIter < maxLineSearchIter);
// compute error (break condition)
// Note: `error` is the decrease of the objective `L_n(V)` and not the
// norm of the gradient as proposed in [Wen, Yin] Algorithm 1.
error = loss - loss_tau;
// cycle `V`, `G` and `loss` for next iteration
V = V_tau;
loss = loss_tau;
G = G_tau;
// store final `loss`
history(iter) = loss;
}
return loss;
}
//' Conditional Variance Estimation (CVE) method.
//'
//' This version uses a "simple" stiefel optimization schema.
//'
//' @param X data points
//' @param Y response
//' @param k assumed \eqn{rank(B)}
//' @param nObs parameter for bandwidth estimation, typical value
//' \code{nObs = nrow(X)^lambda} with \code{lambda} in the range [0.3, 0.8].
//' @param h Bandwidth, if not specified \code{nObs} is used to compute a bandwidth.
//' on the other hand if given (positive floating point number) \code{nObs} is ignored.
//' @param tau Initial step size (default 1)
//' @param tol Tolerance for update error used for stopping criterion (default 1e-5)
//' @param slack Ratio of small negative error allowed in loss optimization (default -1e-10)
//' @param maxIter Upper bound of optimization iterations (default 50)
//' @param attempts Number of tryes with new random optimization starting points (default 10)
//'
//' @return List containing the bandwidth \code{h}, optimization objective \code{V}
//' and the matrix \code{B} estimated for the model as a orthogonal basis of the
//' orthogonal space spaned by \code{V}.
//'
//' @keywords internal
// [[Rcpp::export]]
Rcpp::List cve_cpp(
const arma::mat& X,
const arma::vec& Y,
const std::string method,
const int k,
const double nObs,
double h = -1., // default value to be overwritten
const double tauInitial = 1.,
const double rho1 = 0.1,
const double rho2 = 0.9,
const double tol = 1e-5,
const int maxIter = 50,
const int maxLineSearchIter = 10,
const int attempts = 10
) {
using namespace arma;
// tracker of current best results
mat V_best;
double loss_best = datum::inf;
// estimate bandwidth
if (h <= 0.0) {
h = estimateBandwidth(X, k, nObs);
}
// loss history for each optimization attempt
// each column contaions the iteration history for the loss
mat history = mat(maxIter + 1, attempts);
// multiple stiefel optimization attempts
for (int i = 0; i < attempts; ++i) {
// declare output variables
mat V; // estimated `V` space
vec hist = vec(history.n_rows, fill::zeros); // optimization history
double loss;
if (method == "simple") {
loss = optStiefel_simple(
X, Y, k, h,
tauInitial, tol, maxIter,
V, hist
);
} else if (method == "linesearch") {
loss = optStiefel_linesearch(
X, Y, k, h,
tauInitial, tol, maxIter, rho1, rho2, maxLineSearchIter,
V, hist
);
} else {
throw std::invalid_argument("Unknown method.");
}
if (loss < loss_best) {
loss_best = loss;
V_best = V;
}
// add history to history collection
history.col(i) = hist;
}
// get `B` as kernal of `V.t()`
mat B = null(V_best.t());
return Rcpp::List::create(
Rcpp::Named("history") = history,
Rcpp::Named("loss") = loss_best,
Rcpp::Named("h") = h,
Rcpp::Named("V") = V_best,
Rcpp::Named("B") = B
);
}

View File

@ -1,14 +0,0 @@
## With R 3.1.0 or later, you can uncomment the following line to tell R to
## enable compilation with C++11 (where available)
##
## Also, OpenMP support in Armadillo prefers C++11 support. However, for wider
## availability of the package we do not yet enforce this here. It is however
## recommended for client packages to set it.
##
## And with R 3.4.0, and RcppArmadillo 0.7.960.*, we turn C++11 on as OpenMP
## support within Armadillo prefers / requires it
CXX_STD = CXX11
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)

View File

@ -1,14 +0,0 @@
## With R 3.1.0 or later, you can uncomment the following line to tell R to
## enable compilation with C++11 (where available)
##
## Also, OpenMP support in Armadillo prefers C++11 support. However, for wider
## availability of the package we do not yet enforce this here. It is however
## recommended for client packages to set it.
##
## And with R 3.4.0, and RcppArmadillo 0.7.960.*, we turn C++11 on as OpenMP
## support within Armadillo prefers / requires it
CXX_STD = CXX11
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)

View File

@ -1,68 +0,0 @@
// Generated by using Rcpp::compileAttributes() -> do not edit by hand
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#include <RcppArmadillo.h>
#include <Rcpp.h>
using namespace Rcpp;
// estimateBandwidth
double estimateBandwidth(const arma::mat& X, arma::uword k, double nObs);
RcppExport SEXP _CVE_estimateBandwidth(SEXP XSEXP, SEXP kSEXP, SEXP nObsSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< const arma::mat& >::type X(XSEXP);
Rcpp::traits::input_parameter< arma::uword >::type k(kSEXP);
Rcpp::traits::input_parameter< double >::type nObs(nObsSEXP);
rcpp_result_gen = Rcpp::wrap(estimateBandwidth(X, k, nObs));
return rcpp_result_gen;
END_RCPP
}
// rStiefel
arma::mat rStiefel(arma::uword p, arma::uword q);
RcppExport SEXP _CVE_rStiefel(SEXP pSEXP, SEXP qSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< arma::uword >::type p(pSEXP);
Rcpp::traits::input_parameter< arma::uword >::type q(qSEXP);
rcpp_result_gen = Rcpp::wrap(rStiefel(p, q));
return rcpp_result_gen;
END_RCPP
}
// cve_cpp
Rcpp::List cve_cpp(const arma::mat& X, const arma::vec& Y, const std::string method, const int k, const double nObs, double h, const double tauInitial, const double rho1, const double rho2, const double tol, const int maxIter, const int maxLineSearchIter, const int attempts);
RcppExport SEXP _CVE_cve_cpp(SEXP XSEXP, SEXP YSEXP, SEXP methodSEXP, SEXP kSEXP, SEXP nObsSEXP, SEXP hSEXP, SEXP tauInitialSEXP, SEXP rho1SEXP, SEXP rho2SEXP, SEXP tolSEXP, SEXP maxIterSEXP, SEXP maxLineSearchIterSEXP, SEXP attemptsSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< const arma::mat& >::type X(XSEXP);
Rcpp::traits::input_parameter< const arma::vec& >::type Y(YSEXP);
Rcpp::traits::input_parameter< const std::string >::type method(methodSEXP);
Rcpp::traits::input_parameter< const int >::type k(kSEXP);
Rcpp::traits::input_parameter< const double >::type nObs(nObsSEXP);
Rcpp::traits::input_parameter< double >::type h(hSEXP);
Rcpp::traits::input_parameter< const double >::type tauInitial(tauInitialSEXP);
Rcpp::traits::input_parameter< const double >::type rho1(rho1SEXP);
Rcpp::traits::input_parameter< const double >::type rho2(rho2SEXP);
Rcpp::traits::input_parameter< const double >::type tol(tolSEXP);
Rcpp::traits::input_parameter< const int >::type maxIter(maxIterSEXP);
Rcpp::traits::input_parameter< const int >::type maxLineSearchIter(maxLineSearchIterSEXP);
Rcpp::traits::input_parameter< const int >::type attempts(attemptsSEXP);
rcpp_result_gen = Rcpp::wrap(cve_cpp(X, Y, method, k, nObs, h, tauInitial, rho1, rho2, tol, maxIter, maxLineSearchIter, attempts));
return rcpp_result_gen;
END_RCPP
}
static const R_CallMethodDef CallEntries[] = {
{"_CVE_estimateBandwidth", (DL_FUNC) &_CVE_estimateBandwidth, 3},
{"_CVE_rStiefel", (DL_FUNC) &_CVE_rStiefel, 2},
{"_CVE_cve_cpp", (DL_FUNC) &_CVE_cve_cpp, 13},
{NULL, NULL, 0}
};
RcppExport void R_init_CVE(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}