- 空間に点がばらまかれているときに、その点を頂点とする単体(三角形の一般次元化したもの)の敷き詰めとするのがドロネー図作成
- 二次元でやれば
library(geometry)
X <- matrix(rnorm(50),ncol=2)
delaunay.X <- delaunayn(X)
plot(X)
delaunay.X.2 <- rbind(delaunay.X[,1:2],delaunay.X[,2:3],delaunay.X[,c(3,1)])
segments(X[delaunay.X.2[,1],1],X[delaunay.X.2[,1],2],X[delaunay.X.2[,2],1],X[delaunay.X.2[,2],2])
- 各点が空間に占める支配領域で考えると、このドロネー図の各線分の垂直二等分線を引いて区画する方法があって、そのようにして支配領域を定めた図がボロノイ図
- 支配領域の広さを考えるなら、ボロノイ図における支配面積が適当だ
- が、ドロネー図とボロノイ図とでは情報量が違う
- ドロネー図は点の座標とn次元空間にあるn+1頂点を持つn単体の頂点座標IDの組で情報のすべてになるが
- ボロノイ図では、国境を構成する点の数が増えるので、情報量が増える
- ドロネー図における、「ある点を含む単体の体積の総和」を「各点の周りの体積」とみなすことにすれば、計算はずいぶん軽くなる
- ちなみに、n次元空間にある頂点数n+1の単体の体積は、そのn+1本の長さnのベクトルのうちの1本のベクトルについて、残りのn本のベクトルから、この1本のベクトルを引いたベクトルを取り出し、それが作るnxn行列を作れば、体積はそのnxn行列のdeterminantにを掛けたもの、と言う簡単なものになっている(こちら)
my.simplex.volume <- function(V,factorial=FALSE){
n <- length(V[1,])
K <- matrix(V[1:n,],ncol=n)
K. <- t(K)-V[n+1,]
if(factorial){
return(det(K.)/factorial(n))
}else{
return(det(K.))
}
}
delaunay.X <- delaunayn(X)
my.delaunay.vol <- function(a,X){
tmp <- matrix(X[a,],ncol=length(X[1,]))
my.simplex.volume(tmp)
}
spx.vol <- apply(delaunay.X,1,my.delaunay.vol,X)
Vol <- rep(0,length(X[,1]))
for(i in 1:length(Vol)){
tmp <- (delaunay.X==i)
tmp.2 <- apply(tmp,1,any)
Vol[i] <- sum(abs(spx.vol[which(tmp.2)]))
}
- ドロネー単体ができると、その内部が外部かを判定したくなる
- n次元のn+1頂点のうち1頂点を基準として、それが張っている「三角錐」の内部の点は、そのn本のベクトルの線形和で表され、係数はすべて非負でかつ、係数の和は1以下、それが内部と表面。
judge.inside <- function(x,V){
n <- length(x)
K <- matrix(V[1:n,],ncol=n)
K. <- t(K)-V[n+1,]
tmp <- solve(K.,x-V[n+1,])
all(tmp>=0 & sum(tmp)<=1)
}
V <- matrix(c(1,0,0,0,1,0,0,0,1,-1,-1,-1),byrow=TRUE,ncol=3)
xx <- matrix(runif(30000,min=-1,max=1),ncol=3)
tf <- apply(xx,1,judge.inside,V)
plot3d(xx[which(tf),])
- どのドロネー三角形の内部かがわかったら、その頂点ベクトルを使って線形和でその点を表したい
my.linear.delaunay <- function(v,X,delaunay.X,Y.post){
inside. <- t(apply(delaunay.X,1,my.judge.inside.ID,X,v))
inside.ID <- which(inside.[,1]==1)
inside.coef <- inside.[inside.ID,2:length(inside.[inside.ID,])]
tmp <- c(inside.coef,1-sum(inside.coef))
print(tmp)
print(Y.post[delaunay.X[inside.ID,]])
print(X[delaunay.X[inside.ID,]])
sum(tmp*Y.post[delaunay.X[inside.ID,]])
}
my.simplex.volume <- function(V,factorial=FALSE){
n <- length(V[1,])
K <- matrix(V[1:n,],ncol=n)
K. <- t(K)-V[n+1,]
if(factorial){
return(det(K.)/factorial(n))
}else{
return(det(K.))
}
}
my.delaunay.vol <- function(a,X){
tmp <- matrix(X[a,],ncol=length(X[1,]))
my.simplex.volume(tmp)
}
judge.inside <- function(x,V){
n <- length(x)
K <- matrix(V[1:n,],ncol=n)
K. <- t(K)-V[n+1,]
tmp <- solve(K.,x-V[n+1,])
judge <- all(tmp>=0 & sum(tmp)<=1)
return(c(as.numeric(judge),tmp))
}
V <- matrix(c(1,0,0,0,1,0,0,0,1,-1,-1,-1),byrow=TRUE,ncol=3)
xx <- matrix(runif(30000,min=-1,max=1),ncol=3)
tf <- apply(xx,1,judge.inside,V)
plot3d(xx[which(tf),])
my.rw.density.mx <- function(X,Y,n,r){
D <- as.matrix(dist(X))
D.e <- exp(-D^2)
diag(D.e) <- 0
D.e.2 <- D.e/apply(D.e,1,sum)
diag(D.e.2) <- r
D.e.2 <- D.e.2/apply(D.e.2,1,sum)
eigen.out <- eigen(t(D.e.2))
V <- eigen.out[[2]]
S <- diag(eigen.out[[1]]^n)
U <- solve(V)
V%*%S%*%U
}
my.delaunay.rw.density <- function(X,n=1000,r=0.1){
n.pt <- length(X[,1])
delaunay.X <- delaunayn(X)
spx.vol <- apply(delaunay.X,1,my.delaunay.vol,X)
spx.per.v <- list()
Vol <- rep(0,n.pt)
for(i in 1:n.pt){
tmp <- (delaunay.X==i)
tmp.2 <- apply(tmp,1,any)
spx.per.v[[i]] <- which(tmp.2)
Vol[i] <- sum(abs(spx.vol[which(tmp.2)]))
}
Vol <- Vol/(length(X[1,])+1)
Y.d <- 1/Vol
RW.Mx.d <- my.rw.density.mx(X,Y.d,n,r)
Y.post <- RW.Mx.d %*% Y.d
spx.weight <- rep(0,length(delaunay.X[,1]))
for(i in 1:n.pt){
tmp <- spx.per.v[[i]]
spx.weight[tmp] <- spx.weight[tmp] + Y.post[i] * Vol[i]*abs(spx.vol[tmp])/sum(abs(spx.vol[tmp]))
}
return(list(Vol=Vol,Y.d=Y.d,Y.post=Y.post,M = RW.Mx.d,delaunay.X = delaunay.X,spx.vol=spx.vol,spx.weight=spx.weight))
}
my.judge.inside.ID <- function(a,X,v){
tmp <- as.matrix(X[a,],ncol=length(X[1,]))
judge.inside(v,tmp)
}
my.linear.delaunay <- function(v,X,delaunay.X,Y.post){
inside. <- t(apply(delaunay.X,1,my.judge.inside.ID,X,v))
inside.ID <- which(inside.[,1]==1)
inside.coef <- inside.[inside.ID,2:length(inside.[inside.ID,])]
tmp <- c(inside.coef,1-sum(inside.coef))
print(tmp)
print(Y.post[delaunay.X[inside.ID,]])
print(X[delaunay.X[inside.ID,]])
sum(tmp*Y.post[delaunay.X[inside.ID,]])
}
means <- c(0,0)
sds <- c(1,1)
ratio <- c(0.4,0.6)
N.pt <- 50
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.0001
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
means <- c(0,3)
sds <- c(1,1)
ratio <- c(0.4,0.6)
N.pt <- 200
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
means <- c(0,10)
sds <- c(1,1)
ratio <- c(0.4,0.6)
N.pt <- 200
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
means <- c(0,50)
sds <- c(1,8)
ratio <- c(0.2,0.8)
N.pt <- 500
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
means <- c(0,2)
sds <- c(1,8)
ratio <- c(0.3,0.7)
N.pt <- 500
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
xx <- seq(from=min(X),to=max(X),length=20)
Y.xx <- rep(0,length(xx))
for(i in 1:length(xx)){
Y.xx[i] <- my.linear.delaunay(xx[i],X,D.out$delaunay.X,D.out$Y.post)
}
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
points(xx,Y.xx/max(Y.xx)*max(dens.X[[2]]),pch=20,col=5)
means <- c(0,50)
sds <- c(1,5)
ratio <- c(0.2,0.8)
N.pt <- 100
X <- c(rnorm(N.pt*ratio[1],means[1],sds[1]),rnorm(N.pt*ratio[2],means[2],sds[2]))
true.Dens <- ratio[1] * dnorm(X,means[1],sds[1])+ratio[2]*dnorm(X,means[2],sds[2])
X <- matrix(X,ncol=1)
Y <- rep(1,length(X[,1]))
r <- 0.1
RW.Mx <- my.rw.density.mx(X,Y,n,r)
Z <- RW.Mx %*% Y
D.out <- my.delaunay.rw.density(X,n,r)
Z.d <- D.out$Y.post
dens.X <- density(X,bw = "SJ-ste")
xx <- seq(from=min(X),to=max(X),length=100)
Y.xx <- rep(0,length(xx))
for(i in 1:length(xx)){
Y.xx[i] <- my.linear.delaunay(xx[i],X,D.out$delaunay.X,D.out$Y.post)
}
plot(dens.X,lwd=3)
ord <- order(X)
points(X[ord],Z[ord]/max(Z)*max(dens.X[[2]]),pch=20,col=2,type="b")
points(X[ord],Z.d[ord]/max(Z.d)*max(dens.X[[2]]),pch=20,col=3,type="b")
points(X[ord],true.Dens[ord]/max(true.Dens)*max(dens.X[[2]]),pch=20,col=4,type="l",lwd=3)
points(xx,Y.xx/max(Y.xx)*max(dens.X[[2]]),pch=20,col=5)
D.X <- as.matrix(dist(X))
plot(D.out$M,D.X)
my.dirichlet.est.1d <- function(X.obs,X.target=X.obs,Y,Y.level){
if(length(X.obs)<=1){
return(list(est=matrix(1/length(Y.level),length(X.target),length(Y.level)),bw=range(X.target)))
}
bw <- density(X.obs,bw = "SJ-ste")
ret <- matrix(0,length(X.target),length(Y.level))
for(i in 1:length(Y.level)){
s <- which(Y==Y.level[i])
tmp.X <- X.obs[s]
X.obs.target <- expand.grid(tmp.X,X.target)
tmp.d <- dnorm(X.obs.target[,1]-X.obs.target[,2],0,bw)
tmp.d.m <- matrix(t(tmp.d),length(tmp.X),length(X.target))
ret[,i] <- apply(tmp.d.m,2,sum)
}
return(list(est=ret,bw=bw))
}