我正在尝试使用R来查找将长度为x
的向量n
分区为最多m
个分区的所有可能方法。我知道当n
很小时该怎么做:
library(partitions)
x <- c(10, 20, 30, 40)
n <- length(x)
m <- 3
# In how many ways can we partition n objects into at most m patitions
parts <- restrictedparts(n, m)
sets <- setparts(parts)
在此示例中,sets
的值为:
[1,] 1 1 1 1 2 1 1 1 1 1 1 2 2 2
[2,] 1 1 1 2 1 2 1 2 2 1 2 1 1 3
[3,] 1 2 1 1 1 2 2 1 3 2 1 3 1 1
[4,] 1 1 2 1 1 1 2 2 1 3 3 1 3 1
sets
的每一列都告诉我,对于每个独特的安排,应该在x
中分配每个项目的分区。
n
很大时会出现问题:
n <- 15
m <- 4
parts <- restrictedparts(n, m)
# This expression will max out your CPU usage and eventually run out of memory.
sets <- setparts(parts)
如何在不耗尽内存的情况下执行此操作?我怀疑有一个快速的方法,所以我怀疑我必须分批进行并写入磁盘。
答案 0 :(得分:3)
如果像我一样,你不是组合学中的超级巨星,但你相信partitions
说得对,那么至少你可以利用包的代码来计算最终的分区数。在这里,我攻击了setparts
函数,因此,它不是分区本身,而是返回分区数:
num.partitions <- function (x) {
if (length(x) == 1) {
if (x < 1) {
stop("if single value, x must be >= 1")
}
else if (x == 1) {
out <- 1
}
else return(Recall(parts(x)))
}
if (is.matrix(x)) {
out <- sum(apply(x, 2, num.partitions))
}
else {
x <- sort(x[x > 0], decreasing = TRUE)
out <- factorial(sum(x))/(prod(c(factorial(x),
factorial(table(x)))))
}
return(out)
}
让我们检查函数是否返回了正确数量的分区:
num.partitions(restrictedparts(4, 3))
# [1] 14
ncol(setparts(restrictedparts(4, 3)))
# [1] 14
num.partitions(restrictedparts(8, 4))
# [1] 2795
ncol(setparts(restrictedparts(8, 4)))
# [1] 2795
现在让我们来看看你的大案:
num.partitions(restrictedparts(15, 4))
# [1] 44747435
确实有很多分区......无论写出setparts
的好坏,输出都不适合单个数组:
sets <- matrix(1, 15, 44747435)
# Error in matrix(1, 15, 44747435) :
# cannot allocate vector of length 671211525
所以是的,您必须编写自己的算法并存储到矩阵列表中,或者如果它对您的内存来说太多,请写入文件,如果这真的是您想要做的。否则,考虑到相当多的排列以及你想要用它们做什么,请回到绘图板......
答案 1 :(得分:1)
如果您想分批计算它们,看起来这可能至少对某些列来说是可能的。我无法在像您这样的机器上完成restrictedparts(15,4)
中几个单独列的计算。直到第40列,我一次可以成功地批量生成5-10列,但是高于这一点,有几个单列在抛出malloc错误之前报告了多个列。所以你可能只需要一台更大的机器。在我的Mac上,32 GB构造第53列消耗了一半的内存。大机器上的列数估计与4GB机器上的报告一致:
> ncol( setparts( restrictedparts(15,4)[,53]))
[1] 6306300
R(317,0xa077a720) malloc: *** mmap(size=378380288) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
(我不会就这是否是一个明智的项目提出意见。)
答案 2 :(得分:0)
由于我无法安装分区包(缺少库),我想出了这个:
## Recursive function to get all partitions of a vector
## Returns a list of logical vectors
parts <- function(x) {
if (length(x) == 1) return(list(FALSE, TRUE))
do.call(c, lapply(parts(x[-1]), function(y) list(c(FALSE, y), c(TRUE, y))))
}
此函数采用向量并返回相同大小的逻辑向量列表。列表中的向量数是可能的分区数(2 ^ n)。它无法处理巨大的n,但在我的电脑上它在不到一秒的时间内运行n = 19。
如果您只想要非空分区,并且没有重复项,请使用:
partitions <- parts(x)
partitions <- partitions[1:(length(partitions)/2)][-1]