- df次元空間を考える
- ある点Aがある
- いくつかの点の集合Xsがある
- 原点とXsの各点を結んだ線によって「籠」のようになった範囲は錐
- Aの方向がこの錐の内部かどうかの判定をしよう
- df個の線形独立なベクトルがあるときそれらを用いて、Aの座標を表現できる
- そのような表現のときに、すべての係数が0以上であるとき、Aはこの錐の内側(周も含めて)
- Xsにdf個より多い点があるときは、df個ずつの組み合わせにして、そのいずれかが作る錐の内側なら、錐全体の内側である
- Xsにdf個より少ない点があるときは、その線形結合であって、すべての係数が正のときに内側
- 今、「すべての係数が正」で話を進めてきたが、「すべての係数が負」の場合も「逆向きの錐」とすることも可能なので、以下のソースでは、その設定を"bothside={TRUE,FALSE}"でオプションにしてある
df<-3 # 次元
N<-6 # 点の数
library(MCMCpack)
Xs<-matrix(rdirichlet(N,rep(1,df)),nrow=N)
#Xs<-matrix(c(1,0,0,1),nrow=2,byrow=TRUE)
if(N>=df){
#点の数が次元以上ならば、内側になるかどうかを試すべくAを作る
A<-rnorm(df)
}else{
#点の数が次元未満なら、あえて、線形結合になるようなAを作ってやる(すべてが正なら内側)
A<-apply(Xs *rnorm(N),2,sum)
}
JudgeInside<-function(A,Xs,bothside=TRUE){# bothside=TRUE は両側の錐の内側判定
B<-NULL
df<-length(A) # 次元
N<-length(Xs[,1]) # 点の数
inside<-FALSE
coefs<-NULL
if(N>=df){
library(gtools)
cmb<-combinations(N,df,repeats=FALSE)
loop<-TRUE
counter<-1
vs<-NULL
while(counter<=length(cmb[,1])&loop){
#選んだ点の組み合わせを座標としてAの位置を表す
tmp<-solve(t(Xs[cmb[counter,],]),A)
if(length(tmp[tmp<0])==0 || (bothside & length(tmp[tmp>0])==0) ){# すべての要素が0以上の条件
inside<-TRUE # 錐の内側
vs<-Xs[cmb[counter,],]
coefs<-tmp
loop<-FALSE
}
counter<-counter+1
}
if(inside){
B<-t(vs) %*% coefs
}
}else{
tmp<-solve(t(Xs[,1:N]),A[1:N])
if(sum((A-B)^2)<10^(-16)& (length(tmp[tmp<0])==0|| (bothside & length(tmp[tmp>0])==0))){
inside=TRUE
B<-t(Xs) %*% tmp
coefs<-tmp
}
}
list(inside=inside,A=A,Xs=Xs,coefs=coefs,B=B)
}
JudgeInside(A,Xs)