[英]How can I get a list of all possible partition of a vector in R when the vector is large?
我正在尝试使用R寻找所有可能的方法来将长度为n
的向量x
划分为最多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)
如何在不耗尽内存的情况下执行此操作? 我怀疑是否有一种快速的方法来执行此操作,因此我怀疑我必须分批执行并写入磁盘。
如果像我一样,您不是组合技术领域的超级巨星,但是您相信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
因此,是的,您必须编写自己的算法并将其存储到矩阵列表中,或者如果确实占用了太多内存,则如果确实要执行此操作,则写入文件。 否则,鉴于大量的排列以及您要对它们进行的处理,请返回到绘图板...
如果您要分批计算它们,则看来对于至少某些列而言,这可能是可能的。 我无法在像您这样的机器上完成对restrictedparts(15,4)
中几个单独列的计算。 在第40列之前,我可以一次成功获得5-10列的批处理,但除此之外,有几个单列在引发malloc错误之前确实报告了许多列。 因此,您可能只需要一台更大的机器。 在具有32 GB的Mac上,构造第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
(对于这个项目是否明智,我没有任何意见。)
由于无法安装分区软件包(缺少库),因此我想到了:
## 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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.