- こちらにある通り、4次元空間にあるS3球面上の点に相当する四元数が表す回転がそれである
- 3つの一様乱数で定まっている。はそれぞれS1 (円)を一様に定める変数。はであるから、(とと)の分布
my.random.so3 <-function(n){
u <- matrix(runif(3*n),ncol=3)
h <- sqrt(1-u[,1]) * sin(2*pi*u[,2]) + Hi * sqrt(1-u[,1]) * cos(2*pi*u[,2]) + Hj * sqrt(u[,1]) * sin(2*pi*u[,3]) + Hk * sqrt(u[,1])*cos(2*pi*u[,3])
return(h)
}
n <- 10^4
hs <- my.random.so3(n)
plot3d(i(hs),j(hs),k(hs))
x <- rnorm(3)
x.h <- Hi*x[1]+Hj*x[2]+Hk*x[3]
rot.x <- Conj(hs) * x.h * hs
rot.x. <- cbind(i(rot.x),j(rot.x),k(rot.x))
plot3d(rot.x.)
- これをよく見ると、回転軸は3次元単位ベクトルをランダムに発生させて決まるので、それは、3次元標準正規乱数で発生させることにすれば、回転角だけをで発生させればよいことが解る
my.random.so3.2 <- function(n){
R <- matrix(rnorm(n*3),ncol=3)
R <- R/sqrt(apply(R^2,1,sum))
thetas <- acos(sqrt(1-runif(n)) * sin(2*pi*runif(n))) * 2
h <- cos(thetas/2) + sin(thetas/2) * (Hi*R[,1]+Hj*R[,2]+Hk*R[,3])
return(h)
}
-行列表現は次のように作れる
>|r|
my.random.so3.matrix <- function(n){
h <- my.random.so3(n)
ret <- list()
e1 <- 1*Hi
e2 <- 1*Hj
e3 <- 1*Hk
for(i in 1:n){
this.h <- h[i]
tmp1 <- Conj(this.h) * e1 * this.h
tmp2 <- Conj(this.h) * e2 * this.h
tmp3 <- Conj(this.h) * e3 * this.h
ret[[i]] <- cbind(c(i(tmp1),j(tmp1),k(tmp1)),c(i(tmp2),j(tmp2),k(tmp2)),c(i(tmp3),j(tmp3),k(tmp3)))
}
return(ret)
}
- QR分解を使って、ランダムな回転行列を作ることもある
library(GPArotation)
Random.Start(3)
- そのソースは、以下のように、要素が正規乱数である正方行列のQR分解によっている
> Random.Start
function (k)
{
qr.Q(qr(matrix(rnorm(k * k), k)))
}
<environment: namespace:GPArotation>
rot.x.. <- rot.x.
for(i in 1:n){
RS <- Random.Start(3)
rot.x..[i,] <- RS %*% x
}
plot3d(rot.x..)
- 移動先は、球面に一様分布しない
- 四元数の方をもう少し調べる
plot(as.data.frame(cbind(i(hs),j(hs),k(hs))))
plot(as.data.frame(cbind(Re(hs),i(hs),j(hs),k(hs))))
Mod(hs)
- では、4次元空間の単位球面上の一様乱点を発生させて、それに対応する四元数を使って回転すればよいだけでは…
n <- 10^4
RR <- matrix(rnorm(n*4),ncol=4)
RR <- RR/sqrt(apply(RR^2,1,sum))
hs <- RR[,1] + Hi*RR[,2] + Hj*RR[,3] + Hk*RR[,4]
Mod(hh)
x <- rnorm(3)
x.h <- Hi*x[1]+Hj*x[2]+Hk*x[3]
rot.x <- Conj(hs) * x.h * hs
rot.x. <- cbind(i(rot.x),j(rot.x),k(rot.x))
plot3d(rot.x.)