This is simulated with the fast, thread-safe threefry simulator and can use multiple cores to generate the random deviates.
Usage
rxRmvn(
n,
mu = NULL,
sigma,
lower = -Inf,
upper = Inf,
ncores = 1,
isChol = FALSE,
keepNames = TRUE,
a = 0.4,
tol = 2.05,
nlTol = 1e-10,
nlMaxiter = 100L
)
Arguments
- n
Number of random row vectors to be simulated OR the matrix to use for simulation (faster).
- mu
mean vector
- sigma
Covariance matrix for multivariate normal or a list of covariance matrices. If a list of covariance matrix, each matrix will simulate
n
matrices and combine them to a full matrix- lower
is a vector of the lower bound for the truncated multivariate norm
- upper
is a vector of the upper bound for the truncated multivariate norm
- ncores
Number of cores used in the simulation
- isChol
A boolean indicating if
sigma
is a cholesky decomposition of the covariance matrix.- keepNames
Keep the names from either the mean or covariance matrix.
- a
threshold for switching between methods; They can be tuned for maximum speed; There are three cases that are considered:
case 1: a < l < u
case 2: l < u < -a
case 3: otherwise
where l=lower and u = upper
- tol
When case 3 is used from the above possibilities, the tol value controls the acceptance rejection and inverse-transformation;
When abs(u-l)>tol, uses accept-reject from randn
- nlTol
Tolerance for newton line-search
- nlMaxiter
Maximum iterations for newton line-search
Value
If n==integer
(default) the output is an (n x d) matrix
where the i-th row is the i-th simulated vector.
If is.matrix(n)
then the random vector are store in n
,
which is provided by the user, and the function returns
NULL
invisibly.
References
John K. Salmon, Mark A. Moraes, Ron O. Dror, and David E. Shaw (2011). Parallel Random Numbers: As Easy as 1, 2, 3. D. E. Shaw Research, New York, NY 10036, USA.
The thread safe multivariate normal was inspired from the mvnfast
package by Matteo Fasiolo https://CRAN.R-project.org/package=mvnfast
The concept of the truncated multivariate normal was taken from Zdravko Botev Botev (2017) doi:10.1111/rssb.12162 and Botev and L'Ecuyer (2015) doi:10.1109/WSC.2015.7408180 and converted to thread safe simulation;
Examples
## From mvnfast
## Unlike mvnfast, uses threefry simulation
d <- 5
mu <- 1:d
# Creating covariance matrix
tmp <- matrix(rnorm(d^2), d, d)
mcov <- tcrossprod(tmp, tmp)
set.seed(414)
rxRmvn(4, 1:d, mcov)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.4281796 0.8961586 3.90027665 3.144310 2.659440
#> [2,] -0.1075642 -1.3464338 3.27586623 2.747352 2.949371
#> [3,] 4.1302390 3.1918023 0.07558033 4.828756 5.897353
#> [4,] -0.1817968 1.5098620 3.45393319 3.798816 6.843902
set.seed(414)
rxRmvn(4, 1:d, mcov)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.4281796 0.8961586 3.90027665 3.144310 2.659440
#> [2,] -0.1075642 -1.3464338 3.27586623 2.747352 2.949371
#> [3,] 4.1302390 3.1918023 0.07558033 4.828756 5.897353
#> [4,] -0.1817968 1.5098620 3.45393319 3.798816 6.843902
set.seed(414)
rxRmvn(4, 1:d, mcov, ncores = 2) # r.v. generated on the second core are different
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.4281796 3.5841792 3.455956 2.942954 5.815208
#> [2,] 0.4281796 3.5841792 3.455956 2.942954 5.815208
#> [3,] -0.1075642 -0.1725148 2.883767 4.389230 5.809539
#> [4,] -0.1075642 -0.1725148 2.883767 4.389230 5.809539
###### Here we create the matrix that will hold the simulated
# random variables upfront.
A <- matrix(NA, 4, d)
class(A) <- "numeric" # This is important. We need the elements of A to be of class "numeric".
set.seed(414)
rxRmvn(A, 1:d, mcov, ncores = 2) # This returns NULL ...
A # ... but the result is here
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.4281796 3.5841792 3.455956 2.942954 5.815208
#> [2,] 0.4281796 3.5841792 3.455956 2.942954 5.815208
#> [3,] -0.1075642 -0.1725148 2.883767 4.389230 5.809539
#> [4,] -0.1075642 -0.1725148 2.883767 4.389230 5.809539
## You can also simulate from a truncated normal:
rxRmvn(10, 1:d, mcov, lower = 1:d - 1, upper = 1:d + 1)
#> [,1] [,2] [,3] [,4] [,5]
#> [1,] 0.7907865 2.401943 2.791634 4.998496 5.326100
#> [2,] 1.4542276 1.920439 3.165505 3.894709 4.043283
#> [3,] 0.5902641 1.029716 3.024185 4.462161 5.822886
#> [4,] 0.8880729 1.739535 3.061836 4.984464 5.097672
#> [5,] 0.9891773 1.764719 3.196117 4.907312 5.477384
#> [6,] 0.7735614 1.097578 2.830009 3.298237 5.322111
#> [7,] 0.5936143 2.195169 2.989334 4.462135 5.668588
#> [8,] 1.3516733 2.009184 2.933446 4.887022 4.423623
#> [9,] 1.4968879 2.488339 2.995883 4.929367 4.682948
#> [10,] 1.1974489 1.528600 2.766949 4.001004 5.665883
# You can also simulate from different matrices (if they match
# dimensions) by using a list of matrices.
matL <- lapply(1:4, function(...) {
tmp <- matrix(rnorm(d^2), d, d)
tcrossprod(tmp, tmp)
})
rxRmvn(4, setNames(1:d, paste0("a", 1:d)), matL)
#> a1 a2 a3 a4 a5
#> [1,] 2.1027689 -3.1277802 -1.7058664 3.877449 6.160238
#> [2,] -0.1528749 0.3372425 1.4079033 3.204818 6.771887
#> [3,] -1.6178920 2.4185331 4.2854089 4.204923 6.115151
#> [4,] 5.2850177 6.0162640 1.1522397 6.009218 8.423744
#> [5,] -0.8389005 1.8108360 3.9390837 2.635257 3.078044
#> [6,] 2.4044119 0.2584573 2.4396218 4.687467 7.747550
#> [7,] 7.2635180 5.5533803 -0.2744354 9.627871 4.788654
#> [8,] -0.3358839 -1.7501935 4.1309667 2.961912 6.318101
#> [9,] 3.4028706 1.1584222 4.5627803 3.408984 3.627014
#> [10,] 3.4927361 -1.5055971 1.0890217 2.867575 4.036955
#> [11,] 2.2089477 -1.0108105 -0.6234824 1.745858 4.178149
#> [12,] 1.9045759 -3.5353019 3.6738287 3.085417 2.755276
#> [13,] -1.0910176 1.6896066 -0.1344867 5.810620 3.303876
#> [14,] 0.7032309 2.5654064 2.7642640 3.706315 5.057585
#> [15,] -3.4067706 2.3051387 4.4260234 6.692458 8.170364
#> [16,] -3.7727314 4.2737997 -0.8379328 6.990844 1.255809