Processing math: 100%

Initialisation

The Van de Corput sequence

The van der Corput sequence is the simplest one-dimensional low-discrepancy sequence over the unit interval; it was first described in 1935 by the Dutch mathematician J. G. van der Corput. It is constructed by reversing the base-p representation of the sequence of natural numbers (1, 2, 3, …).

The p-ary representation of the positive integer n(≥1) is

n=L−1∑k=0dk(n)pk

where p is the base in which the number n is represented, and 0≤dp(n)<p, i.e. the k-th digit in the p-ary expansion of n. The n-th number in the van der Corput sequence is

gp(n)=L−1∑k=0dk(n)1pk+1 # Evaluation of the Van der Corput sequence

A single dimension

U = vanDerCorput(n = 10000, nd=1)$getColumn(0)
summary(U)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## 0.000061 0.249970 0.499939 0.499833 0.749908 0.999878
hist(U, col = "orange", main = "VDC in one dimension")

Two dimensions

UG <- vanDerCorput(n = 10000, nd = 2)
UG1 = UG$getColumn(0)
UG2 = UG$getColumn(1)

hist(UG1)

hist(UG2)

plot(UG1[1:1000], UG2[1:1000], 
     xlab = "U", ylab = "V", main = "The first 1000 points")

Many dimensions and few points

np <- 100
nd <- 50
Umat <- vanDerCorput(n = np, nd = nd)
U = matrix(Umat$getValues(),nrow=Umat$getNRows())
means <- apply(X = U, MARGIN = 2, FUN = mean)
stds  <- apply(X = U, MARGIN = 2, FUN = sd)
plot(NULL, NULL, xlim = c(1,50), ylim = c(0,1),
     xlab = "Number of dimensions",
     ylab = "Mean or Std.", main = paste0("Van Der Corput sequence - N = ", np))
abline(h = 0.5, col = "orange", lty = 2)
abline(h = sqrt(1/12), col = "skyblue", lty = 2)
lines(1:50, means, lty = 1, col = "orange")
lines(1:50, stds , lty = 1, col = "skyblue")

Many dimensions and many points

np <- 100000
nd <- 50
Umat <- vanDerCorput(n = np, nd = nd)
U = matrix(Umat$getValues(),nrow=Umat$getNRows())
means <- apply(X = U, MARGIN = 2, FUN = mean)
stds  <- apply(X = U, MARGIN = 2, FUN = sd)
plot(NULL, NULL, xlim = c(1,50), ylim = c(0,1),
     xlab = "Number of dimensions",
     ylab = "Mean or Std.", main = paste0("Van Der Corput sequence - N = ", np))
abline(h = 0.5, col = "orange", lty = 2)
abline(h = sqrt(1/12), col = "skyblue", lty = 2)
lines(1:50, means, lty = 1, col = "orange")
lines(1:50, stds , lty = 1, col = "skyblue")

n-sphere and (quasi) random directions

The n-sphere is defined as Sn={s∈Rn+1:||x||=1} and a direction in Rn+1 is a point on the half n-sphere.

A simple approach to generating a uniform point on Sn uses the fact that the multivariate normal distribution with independent standardized components is radially symmetric, i.e., it is invariant under orthogonal rotations. Therefore, if Y∼N(0n+1,In+1), then Sn=Y/||Y|| has the uniform distribution on the unit n-sphere.

For the simulation of a direction, i.e. a point on Sn+, the last axis is selected as a reference and points with a negative coordinate along this axis are replaced by their symmetric points relatively to the origin.

Finally, in order to build a quasi random values on the half n-sphere, the normal variables are simulated using the inverse method and the pseudo random generator on [0,1]n+1 is replaced by the Van der Corput sequence which is a quasi random generator on [0,1]n+1.

Test in two-dimensions

phi <- 2*pi*(0:1000)/1001
cs <- cos(phi)
sn <- sin(phi)
# Directions in R^3
nd <- 3
for (meth in c("vdc", "prng")) {
  for (np in c(100, 1000, 10000)){
    for (ix in 1:(nd-1)) {
      for (iy in (ix+1):nd){
        plot_dir(np, nd = nd, meth = meth, ix = ix, iy = iy) 
      }
    }
  }
}

# Directions in R^6
np <- 1000
nd <- 6
meth <- "vdc" 
ix <- 1
iy <- 4
plot_dir(np, nd = nd, meth = meth, ix = ix, iy = iy)  

References