【发布时间】:2020-10-08 12:45:36
【问题描述】:
我寻找的基本上是这个问题答案的 R 版本:Generating all permutation of numbers that sums up to N。首先,答案使用 java,我很难阅读。其次,代码使用“双端队列”,我想不出在 R 中实现的方法。 我找到了几种算法来做到这一点,但它们都是用编程语言编写的,使用 R 中不可用的结构,例如双端队列、堆或列表理解。
我真正需要的是找到长度为 N-1 的所有向量 v 的方法,其中:
sum(v * 1:(N-1)) == N
而且我认为只要我找到一种获取所有有序整数分区的方法,我自己就可以做到这一点。
以 N = 4 为例,所有使用数字 1 到 N-1 的有序整数分区是:
1+1+1+1
1+1+2
1+3
2+2
我实际上需要的是两种形式的输出:
c(1,1,1,1)
c(1,1,2)
c(1,3)
c(2,2)
或形式:
c(4,0,0)
c(2,1,0)
c(1,0,1)
c(0,2,0)
因为我应该能够自己将前一种格式转换为后一种格式。任何有关如何使用 R 解决此问题的提示将不胜感激。后一种格式恰好是向量v,使得sum(v * 1:3) 为4。
编辑: 我自己的尝试:
rek = function(mat, id1, id2){
if(id1 + id2 != length(mat) + 1){ #If next state not absorbing
mat[id1] = mat[id1] - 1
mat[id2] = mat[id2] - 1
mat[id1+id2] = mat[id1+id2] + 1
out = mat
id = which(mat > 0)
for(i in id){
for(j in id[id>=i]){
if(j == i & mat[i] == 1){
next
}
out = rbind(out, rek(mat,i,j))
}
}
return(out)
}
}
start = c(n, rep(0, n-2))
states = rbind(start, rek(start, 1, 1))
states = states[!duplicated(states), ] #only unique states.
这是非常低效的。例如。当n = 11 时,我的states 在删除重复项之前有超过 120,000 行,只剩下 55 行。
编辑 2:
使用下面描述的parts() 函数我想出了:
temp = partitions::parts(n)
temp = t(temp)
for(i in 1:length(temp[,1])){
row = temp[i,]
if(any(row>(n-1))){#if absorbing state
next
}
counts = plyr::count(row[row>0])
newrow = rep(0,n-1)
id = counts$x
numbs = counts$freq
newrow[id] = numbs
states = rbind(states, newrow)
}
states = states[-1,]#removing the first row, added manually
这恰好给了我向量v,使得sum(v * 1:(N-1)) 是N。
如果有人感兴趣,这将在合并理论中使用,作为描述 N 个个体之间可能的关系的一种方式,当所有人都相关时省略。以 N = 4 为例:
(4, 0, 0) -- 没有个人相关
(2, 1, 0) -- 两个人有关系,其他人没有关系
(0, 2, 0) -- 个体是成对相关的
(1, 0, 1) -- 三个人有关系,另一个人没有关系。
【问题讨论】:
-
你需要用这个解决的真正问题有多大?
-
我希望可以为非常大的 N 做,但我认为有一个限制。我实际上想出了一个非常低效的方法,它在 N = 13 左右“死亡”。为此,我发现排列是:N=2:1,N=3:2,N=4:4,N= 5:6,N=6:10,N=7:14,N=8:21,N=9:29,N=10:41,N=11:55,N=12:76 但是,我是不是 100% 确定它是正确的,因为我没有费心检查我是否得到了所有东西,因为算法太慢了。
-
@polkas 谢谢。这在我未来的功能中也将非常有用。
标签: r