Skip to content

Commit 6769480

Browse files
committedDec 23, 2020
use Rcpp
1 parent b902621 commit 6769480

8 files changed

+538
-132
lines changed
 

‎DESCRIPTION

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ LazyData: true
1313
RoxygenNote: 7.1.1
1414
Imports:
1515
rcdd,
16-
Runuran,
1716
lazyeval,
1817
spatstat,
1918
EigenR,
2019
stats,
21-
BB
20+
Rcpp
21+
LinkingTo: Rcpp, RcppArmadillo, roptim
2222
Suggests:
2323
knitr,
2424
rmarkdown

‎NAMESPACE

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ export(gfiConfInt)
55
export(gfiQuantile)
66
export(gfiSummary)
77
export(gfilogisreg)
8-
importFrom(BB,BBoptim)
98
importFrom(EigenR,Eigen_range)
109
importFrom(EigenR,Eigen_rank)
10+
importFrom(Rcpp,evalCpp)
1111
importFrom(lazyeval,f_eval_lhs)
1212
importFrom(lazyeval,f_eval_rhs)
1313
importFrom(rcdd,addHin)
@@ -18,10 +18,10 @@ importFrom(rcdd,q2d)
1818
importFrom(rcdd,scdd)
1919
importFrom(spatstat,ewcdf)
2020
importFrom(spatstat,quantile.ewcdf)
21-
importFrom(stats,dlogis)
2221
importFrom(stats,model.matrix)
2322
importFrom(stats,plogis)
2423
importFrom(stats,qlogis)
2524
importFrom(stats,rlogis)
2625
importFrom(stats,rmultinom)
2726
importFrom(stats,runif)
27+
useDynLib(gfilogisreg)

‎R/RcppExports.R

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
2+
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
3+
4+
get_umax <- function(P, b) {
5+
.Call('_gfilogisreg_get_umax', PACKAGE = 'gfilogisreg', P, b)
6+
}
7+
8+
get_vmin_i <- function(P, b, i, mu) {
9+
.Call('_gfilogisreg_get_vmin_i', PACKAGE = 'gfilogisreg', P, b, i, mu)
10+
}
11+
12+
get_vmin <- function(P, b, mu) {
13+
.Call('_gfilogisreg_get_vmin', PACKAGE = 'gfilogisreg', P, b, mu)
14+
}
15+
16+
get_bounds <- function(P, b) {
17+
.Call('_gfilogisreg_get_bounds', PACKAGE = 'gfilogisreg', P, b)
18+
}
19+
20+
rcd <- function(n, P, b) {
21+
.Call('_gfilogisreg_rcd', PACKAGE = 'gfilogisreg', n, P, b)
22+
}
23+

‎R/gfilogisreg.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ gfilogisreg <- function(formula, data = NULL, N, thresh = N/2, progress = TRUE){
126126
# assign("B", B, envir = .GlobalEnv)
127127
# #
128128
# stop()
129-
BTILDES <- rcd(ncopies-1L, P, b, B)
129+
BTILDES <- rcd(ncopies-1L, P, b)#rcd(ncopies-1L, P, b, B)
130130
points <- VT[isone(VT[, 2L]), idx, drop = FALSE]
131131
rays <- VT[!isone(VT[, 2L]), idx, drop = FALSE]
132132
for(j in 2L:ncopies){

‎R/internal.R

+138-127
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#' @useDynLib gfilogisreg
2+
#' @importFrom Rcpp evalCpp
3+
NULL
4+
15
isone <- function(x){
26
abs(x-1) < 0.1
37
}
@@ -25,134 +29,141 @@ rtlogis2 <- function(b){
2529
out
2630
}
2731

28-
logit <- function(u) log(u/(1-u)) # = qlogis
29-
dlogit <- function(u) 1 / (u*(1-u))
30-
expit <- function(x) 1 / (1+exp(-x)) # = plogis
31-
32-
ldlogit <- function(u) -log(u) - log1p(-u)
33-
ldlogis <- function(x) x - 2*log1p(exp(x))
34-
dldlogis <- function(x) 1 - 2*expit(x)
32+
# logit <- function(u) log(u/(1-u)) # = qlogis
33+
# dlogit <- function(u) 1 / (u*(1-u))
34+
# expit <- function(x) 1 / (1+exp(-x)) # = plogis
35+
#
36+
# ldlogit <- function(u) -log(u) - log1p(-u)
37+
# ldlogis <- function(x) x - 2*log1p(exp(x))
38+
# dldlogis <- function(x) 1 - 2*expit(x)
3539

36-
#' @importFrom BB BBoptim
37-
#' @importFrom stats dlogis runif
38-
#' @noRd
39-
rcd <- function(n, P, b, B){
40-
d <- length(B)
41-
f <- function(uv){
42-
vecx <- c(P %*% logit(uv) + b)
43-
prod(dlogis(vecx)) * prod(dlogit(uv))
44-
}
45-
logf <- function(uv){
46-
vecx <- c(P %*% logit(uv) + b)
47-
sum(ldlogis(vecx)) + sum(ldlogit(uv))
48-
}
49-
grl_i <- function(uv, i){
50-
vecx <- c(P %*% logit(uv) + b)
51-
dlogit(uv[i]) * sum(P[, i] * dldlogis(vecx)) + (2*uv[i]-1)/(uv[i]*(1-uv[i]))
52-
}
53-
grl <- function(uv){
54-
vapply(1L:d, function(i) grl_i(uv, i), numeric(1L))
55-
}
56-
gr <- function(uv){
57-
f(uv) * grl(uv)
58-
}
59-
eps <- .Machine$double.eps
60-
# umax ####
61-
opt <- BBoptim(
62-
par = expit(c(B)),
63-
fn = logf,
64-
gr = grl,
65-
lower = rep(eps, d),
66-
upper = rep(1-eps, d),
67-
control = list(
68-
maximize = TRUE,
69-
trace = FALSE,
70-
checkGrad = FALSE,
71-
maxit = 10000,
72-
maxfeval = 100000
73-
),
74-
quiet = TRUE
75-
)
76-
if(opt[["convergence"]] != 0){
77-
stop(
78-
sprintf(
79-
"Convergence not achieved (umax) - code: %d.",
80-
opt[["convergence"]]
81-
)
82-
)
83-
}
84-
mu <- opt[["par"]]
85-
umax <- (exp(opt[["value"]]))^(2/(d+2))
86-
# vmin ####
87-
vmin <- numeric(d)
88-
for(i in 1L:d){
89-
opt <- BBoptim(
90-
par = `[<-`(rep(0.5, d), i, mu[i]/2),
91-
fn = function(uv) -(logf(uv) + (d+2) * log(mu[i] - uv[i])),
92-
gr = function(uv) -grl(uv) + (d+2) * `[<-`(numeric(d), i, 1/(mu[i] - uv[i])),
93-
lower = rep(eps, d),
94-
upper = `[<-`(rep(1, d), i, mu[i]) - eps,
95-
control = list(
96-
maximize = FALSE,
97-
trace = FALSE,
98-
checkGrad = FALSE,
99-
maxit = 10000,
100-
maxfeval = 100000
101-
),
102-
quiet = TRUE
103-
)
104-
if(opt[["convergence"]] != 0){
105-
stop(
106-
sprintf(
107-
"Convergence not achieved (vmin) - code: %d.",
108-
opt[["convergence"]]
109-
)
110-
)
111-
}
112-
vmin[i] <- -exp(-opt[["value"]]/(d+2))
113-
}
114-
# vmax ####
115-
vmax <- numeric(d)
116-
for(i in 1L:d){
117-
opt <- BBoptim(
118-
par = `[<-`(rep(0.5, d), i, (mu[i]+1)/2),
119-
fn = function(uv) logf(uv) + (d+2) * log(uv[i] - mu[i]),
120-
gr = function(uv) grl(uv) - (d+2) * `[<-`(numeric(d), i, 1/(mu[i] - uv[i])),
121-
lower = `[<-`(numeric(d), i, mu[i]) + eps,
122-
upper = rep(1-eps, d),
123-
control = list(
124-
maximize = TRUE,
125-
trace = FALSE,
126-
checkGrad = FALSE,
127-
maxit = 10000,
128-
maxfeval = 100000
129-
),
130-
quiet = TRUE
131-
)
132-
if(opt[["convergence"]] != 0){
133-
stop(
134-
sprintf(
135-
"Convergence not achieved (vmax) - code: %d.",
136-
opt[["convergence"]]
137-
)
138-
)
139-
}
140-
vmax[i] <- exp(opt[["value"]]/(d+2))
141-
}
142-
# simulations
143-
sims <- matrix(NA_real_, nrow = n, ncol = d)
144-
k <- 0L
145-
while(k < n){
146-
u <- runif(1L, 0, umax)
147-
v <- runif(d, vmin, vmax)
148-
x <- v/sqrt(u) + mu
149-
if(all(x > 0) && all(x < 1) && u < f(x)^(2/(d+2))){
150-
k <- k + 1L
151-
sims[k, ] <- x
152-
}
153-
}
154-
logit(sims)
155-
}
40+
# #' @importFrom BB BBoptim
41+
# #' @importFrom stats dlogis runif
42+
# #' @noRd
43+
# rcd <- function(n, P, b, B){
44+
# d <- length(B)
45+
# f <- function(uv){
46+
# vecx <- c(P %*% logit(uv) + b)
47+
# prod(dlogis(vecx)) * prod(dlogit(uv))
48+
# }
49+
# # logf <- function(uv){
50+
# # vecx <- c(P %*% logit(uv) + b)
51+
# # sum(ldlogis(vecx)) + sum(ldlogit(uv))
52+
# # }
53+
# # grl_i <- function(uv, i){
54+
# # vecx <- c(P %*% logit(uv) + b)
55+
# # dlogit(uv[i]) * sum(P[, i] * dldlogis(vecx)) + (2*uv[i]-1)/(uv[i]*(1-uv[i]))
56+
# # }
57+
# # grl <- function(uv){
58+
# # vapply(1L:d, function(i) grl_i(uv, i), numeric(1L))
59+
# # }
60+
# # gr <- function(uv){
61+
# # f(uv) * grl(uv)
62+
# # }
63+
# # eps <- .Machine$double.eps
64+
# # # umax ####
65+
# # opt <- BBoptim(
66+
# # par = expit(c(B)),
67+
# # fn = logf,
68+
# # gr = grl,
69+
# # lower = rep(eps, d),
70+
# # upper = rep(1-eps, d),
71+
# # control = list(
72+
# # maximize = TRUE,
73+
# # trace = FALSE,
74+
# # checkGrad = FALSE,
75+
# # maxit = 10000,
76+
# # maxfeval = 100000
77+
# # ),
78+
# # quiet = TRUE
79+
# # )
80+
# # if(opt[["convergence"]] != 0){
81+
# # stop(
82+
# # sprintf(
83+
# # "Convergence not achieved (umax) - code: %d.",
84+
# # opt[["convergence"]]
85+
# # )
86+
# # )
87+
# # }
88+
# # mu <- opt[["par"]]
89+
# # umax <- (exp(opt[["value"]]))^(2/(d+2))
90+
# # # vmin ####
91+
# # vmin <- numeric(d)
92+
# # for(i in 1L:d){
93+
# # opt <- BBoptim(
94+
# # par = `[<-`(rep(0.5, d), i, mu[i]/2),
95+
# # fn = function(uv) -(logf(uv) + (d+2) * log(mu[i] - uv[i])),
96+
# # gr = function(uv) -grl(uv) + (d+2) * `[<-`(numeric(d), i, 1/(mu[i] - uv[i])),
97+
# # lower = rep(eps, d),
98+
# # upper = `[<-`(rep(1, d), i, mu[i]) - eps,
99+
# # control = list(
100+
# # maximize = FALSE,
101+
# # trace = FALSE,
102+
# # checkGrad = FALSE,
103+
# # maxit = 10000,
104+
# # maxfeval = 100000
105+
# # ),
106+
# # quiet = TRUE
107+
# # )
108+
# # if(opt[["convergence"]] != 0){
109+
# # stop(
110+
# # sprintf(
111+
# # "Convergence not achieved (vmin) - code: %d.",
112+
# # opt[["convergence"]]
113+
# # )
114+
# # )
115+
# # }
116+
# # vmin[i] <- -exp(-opt[["value"]]/(d+2))
117+
# # }
118+
# # # vmax ####
119+
# # vmax <- numeric(d)
120+
# # for(i in 1L:d){
121+
# # opt <- BBoptim(
122+
# # par = `[<-`(rep(0.5, d), i, (mu[i]+1)/2),
123+
# # fn = function(uv) logf(uv) + (d+2) * log(uv[i] - mu[i]),
124+
# # gr = function(uv) grl(uv) - (d+2) * `[<-`(numeric(d), i, 1/(mu[i] - uv[i])),
125+
# # lower = `[<-`(numeric(d), i, mu[i]) + eps,
126+
# # upper = rep(1-eps, d),
127+
# # control = list(
128+
# # maximize = TRUE,
129+
# # trace = FALSE,
130+
# # checkGrad = FALSE,
131+
# # maxit = 10000,
132+
# # maxfeval = 100000
133+
# # ),
134+
# # quiet = TRUE
135+
# # )
136+
# # if(opt[["convergence"]] != 0){
137+
# # stop(
138+
# # sprintf(
139+
# # "Convergence not achieved (vmax) - code: %d.",
140+
# # opt[["convergence"]]
141+
# # )
142+
# # )
143+
# # }
144+
# # vmax[i] <- exp(opt[["value"]]/(d+2))
145+
# # }
146+
#
147+
# bounds <- routmp::get_bounds(P, b)
148+
# umax <- bounds$umax
149+
# mu <- c(bounds$mu)
150+
# #print(mu) # TODO: check always corner - not really
151+
# vmin <- c(bounds$vmin)
152+
# vmax <- c(bounds$vmax)
153+
# # simulations
154+
# sims <- matrix(NA_real_, nrow = n, ncol = d)
155+
# k <- 0L
156+
# while(k < n){
157+
# u <- runif(1L, 0, umax)
158+
# v <- runif(d, vmin, vmax)
159+
# x <- v/sqrt(u) + mu
160+
# if(all(x > 0) && all(x < 1) && u < f(x)^(2/(d+2))){
161+
# k <- k + 1L
162+
# sims[k, ] <- x
163+
# }
164+
# }
165+
# logit(sims)
166+
# }
156167

157168

158169
# #' @importFrom Runuran ur vnrou.new

‎src/Makevars

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

‎src/Makevars.win

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

‎src/gfilogisreg.cpp

+344
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
#include "RcppArmadillo.h"
2+
#include "roptim.h"
3+
using namespace roptim;
4+
5+
// [[Rcpp::depends(RcppArmadillo)]]
6+
// [[Rcpp::depends(roptim)]]
7+
8+
std::vector<size_t> CantorExpansion(size_t n, std::vector<size_t> s) {
9+
std::vector<size_t> out(s.size());
10+
std::vector<size_t>::iterator it;
11+
it = s.begin();
12+
it = s.insert(it, 1);
13+
size_t G[s.size()];
14+
std::partial_sum(s.begin(), s.end(), G, std::multiplies<size_t>());
15+
size_t k;
16+
while(n > 0) {
17+
k = 1;
18+
while(G[k] <= n) {
19+
k++;
20+
}
21+
out[k - 1] = n / G[k - 1];
22+
n = n % G[k - 1];
23+
}
24+
return out;
25+
}
26+
27+
arma::mat grid(const size_t d) {
28+
std::array<double, 3> x = {0.01, 0.5, 0.99};
29+
size_t p = pow((size_t)3, d);
30+
arma::mat out(d, p);
31+
std::vector<size_t> threes(d, 3);
32+
for(size_t n = 0; n < p; n++) {
33+
std::vector<size_t> indices = CantorExpansion(n, threes);
34+
for(size_t i = 0; i < d; i++) {
35+
out.at(i, n) = x[indices[i]];
36+
}
37+
}
38+
return out;
39+
}
40+
41+
arma::vec logit(const arma::vec& u) {
42+
return arma::log(u / (1.0 - u));
43+
}
44+
45+
double dlogit(double u) {
46+
return 1.0 / (u * (1.0 - u));
47+
}
48+
49+
arma::vec ldlogit(const arma::vec& u) {
50+
return -arma::log(u % (1.0-u));
51+
}
52+
53+
arma::vec ldlogis(const arma::vec& x) {
54+
return x - 2.0 * arma::log1p(arma::exp(x));
55+
}
56+
57+
arma::vec dldlogis(const arma::vec& x) {
58+
return 1.0 - 2.0 / (1.0 + arma::exp(-x));
59+
}
60+
61+
double log_f(const arma::vec& u, const arma::mat& P, const arma::vec& b) {
62+
const arma::vec x = P * logit(u) + b;
63+
return arma::sum(ldlogis(x)) + arma::sum(ldlogit(u));
64+
}
65+
66+
double dlog_f(const double ui, const arma::vec& Pi, const arma::vec& y) {
67+
return dlogit(ui) * arma::sum(Pi % y) + (2.0 * ui - 1.0) / (ui * (1.0 - ui));
68+
}
69+
70+
class Logf : public Functor {
71+
public:
72+
arma::mat P;
73+
arma::vec b;
74+
double operator()(const arma::vec& u) override { return log_f(u, P, b); }
75+
void Gradient(const arma::vec& u, arma::vec& gr) override {
76+
const size_t d = P.n_cols;
77+
gr = arma::zeros<arma::vec>(d);
78+
const arma::vec y = dldlogis(P * logit(u) + b);
79+
for(size_t i = 0; i < d; i++) {
80+
gr(i) = dlog_f(u[i], P.col(i), y);
81+
}
82+
}
83+
};
84+
85+
class uLogf1 : public Functor {
86+
public:
87+
arma::mat P;
88+
arma::vec b;
89+
arma::vec mu;
90+
size_t j;
91+
double operator()(const arma::vec& u) override {
92+
const size_t d = P.n_cols;
93+
return -log_f(u, P, b) - (d+2) * log(mu[j] - u.at(j));
94+
}
95+
void Gradient(const arma::vec& u, arma::vec& gr) override {
96+
const size_t d = P.n_cols;
97+
gr = arma::zeros<arma::vec>(d);
98+
const arma::vec y = dldlogis(P * logit(u) + b);
99+
for(size_t i = 0; i < d; i++) {
100+
if(i == j){
101+
gr(i) = -dlog_f(u[i], P.col(i), y) + (d+2) / (mu[i] - u.at(i));
102+
}else{
103+
gr(i) = -dlog_f(u[i], P.col(i), y);
104+
}
105+
}
106+
}
107+
};
108+
109+
class uLogf2 : public Functor {
110+
public:
111+
arma::mat P;
112+
arma::vec b;
113+
arma::vec mu;
114+
size_t j;
115+
double operator()(const arma::vec& u) override {
116+
const size_t d = P.n_cols;
117+
return log_f(u, P, b) + (d+2) * log(u.at(j) - mu[j]);
118+
}
119+
void Gradient(const arma::vec& u, arma::vec& gr) override {
120+
const size_t d = P.n_cols;
121+
gr = arma::zeros<arma::vec>(d);
122+
const arma::vec y = dldlogis(P * logit(u) + b);
123+
for(size_t i = 0; i < d; i++) {
124+
if(i == j){
125+
gr(i) = dlog_f(u[i], P.col(i), y) - (d+2) / (mu[i] - u.at(i));
126+
}else{
127+
gr(i) = dlog_f(u[i], P.col(i), y);
128+
}
129+
}
130+
}
131+
};
132+
133+
Rcpp::List get_umax0(const arma::mat& P, const arma::vec& b, arma::vec init) {
134+
double eps = sqrt(std::numeric_limits<double>::epsilon());
135+
Logf logf;
136+
logf.P = P;
137+
logf.b = b;
138+
Roptim<Logf> opt("L-BFGS-B");
139+
opt.control.trace = 0;
140+
opt.control.maxit = 10000;
141+
opt.control.fnscale = -1.0; // maximize
142+
//opt.control.factr = 1.0;
143+
opt.set_hessian(false);
144+
arma::vec lwr = arma::zeros(init.size()) + eps;
145+
arma::vec upr = arma::ones(init.size()) - eps;
146+
opt.set_lower(lwr);
147+
opt.set_upper(upr);
148+
opt.minimize(logf, init);
149+
if(opt.convergence() != 0){
150+
Rcpp::Rcout << "-- umax -----------------------" << std::endl;
151+
opt.print();
152+
}
153+
//Rcpp::Rcout << "-------------------------" << std::endl;
154+
// opt.print();
155+
return Rcpp::List::create(Rcpp::Named("par") = opt.par(),
156+
Rcpp::Named("value") = opt.value());
157+
}
158+
159+
// [[Rcpp::export]]
160+
Rcpp::List get_umax(const arma::mat& P, const arma::vec& b) {
161+
const size_t d = P.n_cols;
162+
const arma::mat inits = grid(d);
163+
const size_t n = inits.n_cols;
164+
std::vector<arma::vec> pars(n);
165+
arma::vec values(n);
166+
for(size_t i = 0; i < n; i++) {
167+
const Rcpp::List L = get_umax0(P, b, inits.col(i));
168+
const arma::vec par = L["par"];
169+
pars[i] = par;
170+
// double value = L["value"];
171+
values(i) = L["value"];
172+
}
173+
const size_t imax = values.index_max();
174+
return Rcpp::List::create(
175+
Rcpp::Named("mu") = pars[imax],
176+
Rcpp::Named("umax") = pow(exp(values(imax)), 2.0 / (2.0 + d)));
177+
}
178+
179+
// [[Rcpp::export]]
180+
double get_vmin_i(
181+
const arma::mat& P, const arma::vec& b, const size_t i, const arma::vec& mu
182+
) {
183+
double eps = sqrt(std::numeric_limits<double>::epsilon()) / 3.0;
184+
uLogf1 ulogf1;
185+
ulogf1.P = P;
186+
ulogf1.b = b;
187+
ulogf1.j = i;
188+
ulogf1.mu = mu;
189+
Roptim<uLogf1> opt("L-BFGS-B");
190+
opt.control.trace = 0;
191+
opt.control.maxit = 10000;
192+
//opt.control.fnscale = 1.0; // minimize
193+
//opt.control.factr = 1.0;
194+
opt.set_hessian(false);
195+
const size_t d = P.n_cols;
196+
arma::vec init = 0.5 * arma::ones(d);
197+
init.at(i) = mu.at(i) / 2.0;
198+
arma::vec lwr = arma::zeros(d) + eps;
199+
arma::vec upr = arma::ones(d);
200+
upr.at(i) = mu.at(i);
201+
opt.set_lower(lwr);
202+
opt.set_upper(upr - eps);
203+
opt.minimize(ulogf1, init);
204+
if(opt.convergence() != 0){
205+
Rcpp::Rcout << "-- vmin -----------------------" << std::endl;
206+
opt.print();
207+
}
208+
//Rcpp::Rcout << "-------------------------" << std::endl;
209+
return -exp(-opt.value() / (d+2));
210+
}
211+
212+
// [[Rcpp::export]]
213+
arma::vec get_vmin(
214+
const arma::mat& P, const arma::vec& b, const arma::vec& mu
215+
) {
216+
const size_t d = P.n_cols;
217+
arma::vec vmin(d);
218+
for(size_t i = 0; i < d; i++){
219+
vmin.at(i) = get_vmin_i(P, b, i, mu);
220+
}
221+
return vmin;
222+
}
223+
224+
double get_vmax_i(
225+
const arma::mat& P, const arma::vec& b, const size_t i, const arma::vec& mu
226+
) {
227+
double eps = sqrt(std::numeric_limits<double>::epsilon()) / 3.0;
228+
uLogf2 ulogf2;
229+
ulogf2.P = P;
230+
ulogf2.b = b;
231+
ulogf2.j = i;
232+
ulogf2.mu = mu;
233+
Roptim<uLogf2> opt("L-BFGS-B");
234+
opt.control.trace = 0;
235+
opt.control.maxit = 10000;
236+
opt.control.fnscale = -1.0; // maximize
237+
//opt.control.factr = 1.0;
238+
opt.set_hessian(false);
239+
const size_t d = P.n_cols;
240+
arma::vec init = 0.5 * arma::ones(d);
241+
init.at(i) = (mu.at(i) + 1.0) / 2.0;
242+
arma::vec lwr = arma::zeros(d);
243+
lwr.at(i) = mu.at(i);
244+
arma::vec upr = arma::ones(d) - eps;
245+
opt.set_lower(lwr + eps);
246+
opt.set_upper(upr);
247+
opt.minimize(ulogf2, init);
248+
if(opt.convergence() != 0){
249+
Rcpp::Rcout << "-- vmax -----------------------" << std::endl;
250+
opt.print();
251+
}
252+
return exp(opt.value() / (d+2));
253+
}
254+
255+
arma::vec get_vmax(
256+
const arma::mat& P, const arma::vec& b, const arma::vec& mu
257+
) {
258+
const size_t d = P.n_cols;
259+
arma::vec vmax(d);
260+
for(size_t i = 0; i < d; i++){
261+
vmax.at(i) = get_vmax_i(P, b, i, mu);
262+
}
263+
return vmax;
264+
}
265+
266+
// [[Rcpp::export]]
267+
Rcpp::List get_bounds(const arma::mat& P, const arma::vec& b){
268+
Rcpp::List L = get_umax(P, b);
269+
arma::vec mu = L["mu"];
270+
double umax = L["umax"];
271+
arma::vec vmin = get_vmin(P, b, mu);
272+
arma::vec vmax = get_vmax(P, b, mu);
273+
return Rcpp::List::create(Rcpp::Named("umax") = umax,
274+
Rcpp::Named("mu") = mu,
275+
Rcpp::Named("vmin") = vmin,
276+
Rcpp::Named("vmax") = vmax);
277+
}
278+
279+
280+
// std::uniform_real_distribution<double> runif(0.0, 1.0);
281+
// std::default_random_engine generator(seed);
282+
// runif(generator)
283+
std::default_random_engine generator;
284+
std::uniform_real_distribution<double> runif(0.0, 1.0);
285+
286+
// [[Rcpp::export]]
287+
arma::mat rcd(const size_t n, const arma::mat& P, const arma::vec& b){
288+
//, const size_t seed){
289+
// std::default_random_engine generator(seed);
290+
// std::uniform_real_distribution<double> runif(0.0, 1.0);
291+
const size_t d = P.n_cols;
292+
arma::mat tout(d, n);
293+
const Rcpp::List bounds = get_bounds(P, b);
294+
const double umax = bounds["umax"];
295+
const arma::vec mu = bounds["mu"];
296+
const arma::vec vmin = bounds["vmin"];
297+
const arma::vec vmax = bounds["vmax"];
298+
size_t k = 0;
299+
while(k < n){
300+
const double u = umax * runif(generator);
301+
arma::vec v(d);
302+
for(size_t i = 0; i < d; i++){
303+
v.at(i) = vmin.at(i) + (vmax.at(i) - vmin.at(i)) * runif(generator);
304+
}
305+
const arma::vec x = v / sqrt(u) + mu;
306+
bool test = arma::all(x > 0.0) && arma::all(x < 1.0) &&
307+
(d+2) * log(u) < 2.0 * log_f(x, P, b);
308+
if(test){
309+
tout.col(k) = logit(x);
310+
k++;
311+
}
312+
}
313+
return tout.t();
314+
}
315+
316+
317+
////////////////////////////////////////////////////////////////////////////////
318+
double plogis(double x){
319+
return 1.0/(1.0 + exp(-x));
320+
}
321+
322+
double qlogis(double u){
323+
return log(u/(1.0-u));
324+
}
325+
326+
double MachineEps = std::numeric_limits<double>::epsilon();
327+
328+
double rlogis1(double x){
329+
double b = plogis(x);
330+
if(b <= MachineEps){
331+
return x;
332+
}
333+
std::uniform_real_distribution<double> ru(MachineEps, b);
334+
return qlogis(ru(generator));
335+
}
336+
337+
double rlogis2(double x){
338+
double a = plogis(x);
339+
if(a == 1){
340+
return x;
341+
}
342+
std::uniform_real_distribution<double> ru(a, 1);
343+
return qlogis(ru(generator));
344+
}

0 commit comments

Comments
 (0)
Please sign in to comment.