高次元分割表
昨日、N個のものをk種類に分けるわけ方について、各種類に上限数があるときに、何通りの分け方があるかについて書いた。
少し、変える。
N個のものがあって、第1の因子では、あるわけ方をされ、第2の因子では、別の分け方をされ、。。。と高次に分けられているときの、分け方について考える。まずは単純にするために、それぞれの因子では、2種類に分けられるものとする。すると、k因子があるときにはその因子の持ち方が通り存在する。これらの持ち方には、上限があるが、この上限は、k個の因子の2種類の数に依存する。このような条件で、さて、何通りあるか・・・
- Rのコマンド
- 任意次元2^k分割。総数Nにおいて、第1因子で(n1,N-n1) に分かれていたとする。その後、第2因子で(n2,N-n2),第3因子で(n3,N-n3),..,第i因子で(ni,N-ni)に分けたときに、1,...,k要素が(0,...,0)(0,..,0,1),(0,,,1,0),...,(1,1,...,1)の2^iパターンがあるが、その数の割り振り方がいくつあるかを算出。重いです
- 全サンプル数が15で、因子数が3つ、第1因子が(10,5),第2因子が(3,12)、第3因子が(8,7)であるときに、次のようにする。depthは2から変えないこと。silent=FALSEにすると、場合数だけでなく、分配パターンも表示される
- PatternsHighDim(nlist=c(10,5),k=c(10,30,8),depth=2,silent=TRUE)
- Rのソース
PatternsHighDim<-function(nlist=c(10,5),k=c(10,3,8),depth=2,silent=TRUE){
#print("nlist,depth,val,count")
#print(nlist)
#print(depth)
#print(val)
#print(count)
#print("------")
if(depth>length(k)){
if(!silent){
print(nlist)
}
return(list(count=1))
}
#write.table(res,file="TEXTFILE1.txt",quote=F,sep="\t",row.names=F,col.names=F)
#sink("TEXTFILE1.txt")
lenNlist<-length(nlist)
MinMaxList<-LimitRange(nlist,k[depth])
#newNlist<-rep(0,lenNlist*2)
N<-sum(nlist)
patterncounter<-0
plusQ<-InitPlusMinMax(MinMaxList$MinList,MinMaxList$MaxList,k[depth])
loop=plusQ$judge
while(loop!=0){
#print("plusQplus")
#print(plusQ$plus)
if(plusQ$judge==1){
newNlist<-UpDateNlist(nlist,plusQ$plus)
#print(newNlist)
#newval<-lExp(newNlist,LogFact)
#print("newval")
#print(newval)
if(FALSE){
#return(newval)
#val<-val+newval
#patterncounter<-patterncounter+1
}else{
ans<-PatternsHighDim(newNlist,k,depth+1,silent)
#val<-val+ans$val
patterncounter<-patterncounter+ans$count
}
}
plusQ<-UpdatePlusMinMax(plusQ$plus,MinMaxList$MinList,MinMaxList$MaxList,k[depth])
loop<-plusQ$judge
}
return(list(count=patterncounter))
}
Patterns<-function(nlist=c(10,20,6,8),k=20,silent=TRUE){
#write.table(res,file="TEXTFILE1.txt",quote=F,sep="\t",row.names=F,col.names=F)
#sink("TEXTFILE1.txt")
lenNlist<-length(nlist)
MinMaxList<-LimitRange(nlist,k)
#newNlist<-rep(0,lenNlist*2)
N<-sum(nlist)
patterncounter<-0
plusQ<-InitPlusMinMax(MinMaxList$MinList,MinMaxList$MaxList,k)
loop=plusQ$judge
while(loop!=0){
#newNlist<-UpDateNlist(nlist,plusQ$plus)
#print(plusQ$plus)
if(plusQ$judge==1){
if(!silent){
print(plusQ$plus)
}
patterncounter<-patterncounter+1
}
plusQ<-UpdatePlusMinMax(plusQ$plus,MinMaxList$MinList,MinMaxList$MaxList,k)
loop<-plusQ$judge
}
#sink()
return(list(NumPatterns=patterncounter))
}
InitPlusMinMax<-function(MinList,MaxList,k){
plus<-MinList
plus[length(plus)]<-k-sum(plus)+plus[length(plus)]
if(plus[length(plus)]<=MaxList[length(plus)] && plus[length(plus)]>=MinList[length(plus)]){
return(list(plus=plus,judge=1))
}else{
ans<-UpdatePlusMinMax(plus,MinList,MaxList,k)
return(list(plus=ans$plus,judge=ans$judge))
}
}
UpdatePlusMinMax<-function(plus,MinList,MaxList,k){
#print("update")
plusLen<-length(plus)
retplus<-plus
success<-1
while(success==1){
retplus[1]<-retplus[1]+1
retplus[plusLen]<-retplus[plusLen]-1
for(i in 1:(plusLen-1)){
if(retplus[i]<=MaxList[i]){
#if(retplus[plusLen]<MinList[plusLen]){
# loop<-0
#}else if(retplus[plusLen]>MaxList[plusLen]){
# retplus[i]<-retplus[i]+retplus[plusLen]-MaxList[plusLen]
# retplus[plusLen]<-MaxList[plusLen]
# if(retplus[i]<=MaxList[i] && retplus[i]>=MinList[i]){
# return(list(plus=retplus,judge=1))
# }else{
# loop<-0
# }
#}else
if(retplus[plusLen]<=MaxList[plusLen] && retplus[plusLen]>=MinList[plusLen]){
return(list(plus=retplus,judge=1))
}else{
return(list(plus=retplus,judge=2))
}
#retplus[i]<-retplus[i]+1
#retplus[plusLen]<-retplus[plusLen]-1
}
retplus[plusLen]<-retplus[plusLen]+retplus[i]-MinList[i]-1
retplus[i]<-MinList[i]
retplus[i+1]<-retplus[i+1]+1
if(i==(plusLen-1)){
#if(retplus[i+1]>MaxList[i+1]){
return(list(plus=retplus,judge=0))
#}
}
}
}
#return(list(plus=retplus,judge=0))
}
LimitRangeKeta<-function(nlist,k,keta,loopMax=10){
MinList<-rep(0,keta)
MaxList<-nlist[1:keta]
dif<-1
loop<-0
while(dif!=0 && loop<loopMax){
loop<-loop+1
tmpMinList<-UpdateMinList(MinList,MaxList,k)
tmpMaxList<-UpdateMaxList(MinList,MaxList,k)
dif<-sum(abs(tmpMinList-MinList)+abs(tmpMaxList-MaxList))
MinList<-tmpMinList
MaxList<-tmpMaxList
}
return(list(MinList=MinList,MaxList=MaxList))
}
LimitRange<-function(nlist,k,loopMax=10){
MinList<-rep(0,length(nlist))
MaxList<-nlist
LEN<-length(nlist)
dif<-1
loop<-0
while(dif!=0 && loop<loopMax){
#print("#")
loop<-loop+1
#print(loop)
tmpMinList<-UpdateMinList(MinList,MaxList,k)
tmpMaxList<-UpdateMaxList(MinList,MaxList,k)
#print(tmpMinList)
#print(tmpMaxList)
dif<-sum(abs(tmpMinList-MinList)+abs(tmpMaxList-MaxList))
MinList<-tmpMinList
MaxList<-tmpMaxList
}
return(list(MinList=MinList,MaxList=MaxList))
}
UpdateMinList<-function(MinList,MaxList,k){
list<-MinList
sumMax<-sum(MaxList)
for(i in 1:(length(list))){
if(MinList[i]<k-sumMax+MaxList[i]){
list[i]<-k-sumMax+MaxList[i]
}
}
return(list)
}
UpdateMaxList<-function(MinList,MaxList,k){
list<-MaxList
sumMin<-sum(MinList)
for(i in 1:(length(list))){
if(MaxList[i]>k-sumMin+MinList[i]){
list[i]<-k-sumMin+MinList[i]
}
}
return(list)
}
InitPlus<-function(nlist,k){
retplus<-rep(0,length(nlist))
sofar<-k
for(i in 1:length(nlist)){
if(sofar>=nlist[i]){
retplus[i]<-nlist[i]
sofar<-sofar-nlist[i]
}else{
retplus[i]<-sofar
return(retplus)
}
}
return(retplus)
}
UpdatePlus<-function(plus,nlist){
plusLen<-length(plus)
totalplus<-sum(plus)
plus[1]<-plus[1]+1
# if(plusLen>2){
for(i in 1:plusLen){
#print(plus)
if(plus[i]>nlist[i]){
#plus[plusLen]<-plus[plusLen]+plus[i]-1
plus[i]<-0
if(i<plusLen){
plus[i+1]<-plus[i+1]+1
}else{
plus[i]<-plus[i]+1
return(plus)
}
}else{
return(plus)
}
}
#}
return(plus)
}
UpDateNlist<-function(nlist,plus){
newNlist<-rep(0,length(nlist)*2)
for(i in 1:length(nlist)){
newNlist[i*2-1]<-plus[i]
newNlist[i*2]<-nlist[i]-plus[i]
}
return(newNlist)
}
lExp<-function(nlist,LogFact){
ret<-0
for(i in 1:length(nlist)){
ret<-ret+LogFact[nlist[i]+1]
}
return(ret)
}
lExpHighDim<-function(nlist,LogFact,k,depth){
ret<-0
N<-sum(nlist)
sortlist<-sort(nlist)
for(i in 1:length(nlist)){
ret<-ret-LogFact[sortlist[i]+1]
}
for(i in 1:depth){
ret<-ret+LogFact[k[i]+1]+LogFact[N-k[i]+1]
}
ret<-ret-(depth-1)*LogFact[N+1]
return(ret)
}
MakeLogFact<-function(n){
ret<-rep(0,n+1)
ret[1]<-0
for(i in 2:(n+1)){
ret[i]<-ret[i-1]+log(i-1)
}
return(ret)
}