Gdy różne osie elipsoidy nie różnią się zbytnio, możliwe jest zastosowanie próbkowania odrzucania (przy dużych różnicach dużo odrzucasz, co czyni go mniej wykonalnym)
- (1) próbka w hiperferze
- (2) ściśnięcie go w hiperlipsoidę
- (3) oblicz szybkość, z jaką powierzchnia została ściśnięta
- (4) odrzucić próbki zgodnie z tą częstotliwością.
Przykład 2D
set.seed(1)
#some matrix to transform n-sphere (in this case 2x2)
m <- matrix(c(1, 0.55, 0.55, 0.55), 2)
# sample multinomial with identity covariance matrix
x <- cbind(rnorm(3000, 0, 1), rnorm(3000, 0, 1))
l1 <- sqrt(x[,1]^2 + x[,2]^2)
# perpendicular vector
per <- cbind(x[,2], -x[,1])
# transform x
x <- x %*% m
# transform perpendicular vector (to see how the area transforms)
per2 <- per %*% m
# get onto unit-"sphere"/ellipsoid
x <- x/l1
# this is how the area contracted
contract <- sqrt(per2[,1]^2 + per2[,2]^2) / sqrt(per[,1]^2 + per[,2]^2)
# then this is how we should choose to reject samples
p <- contract/max(contract)
# rejecting
choose <- which( rbinom(n=length(p), size=1, p=p) == 1)
#plotting
plot(x[1:length(choose), 1], x[1:length(choose), 2],
xlim=c(-1.2, 1.2), ylim=c(-1.2, 1.2),
xlab = expression(x[1]), ylab = expression(x[2]),
bg=rgb(0, 0, 0, 0.01), cex=0.6, pch=21, col=rgb(0, 0, 0, 0.01))
title("squeezed uniform circle \n ")
#plotting
plot(x[choose,1], x[choose,2],
xlim=c(-1.2, 1.2), ylim=c(-1.2, 1.2),
xlab = expression(x[1]), ylab = expression(x[2]),
bg=rgb(0, 0, 0, 0.01), cex=0.6, pch=21, col=rgb(0, 0, 0, 0.01))
title("squeezed uniform circle \n with rejection sampling")