高次元分割表
昨日、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) }