我想获得280个元素的总和,总和为274,但是每个值都必须是整数,且介于0和4之间。
有一个几乎可以执行此操作的函数,它是受限制的部分(我在这里找到:Getting all combinations which sum up to 100 using R)...但是仍然必须仅获取值最大为4的元素。
答案 0 :(得分:1)
通常,partitions
包可以解决这些类型的问题,但是,我无法使用该包找到解决方案。我还不会完全排除此软件包,因为在过去的几年中,我一直不断发现非常好的惊喜。我离题了。
首先,总和为274的正整数的最小数目为274(例如sum(rep(1, 274))
)。因此,任何包含超过274个元素(例如 n )的解决方案都是相同的,除了每个组合额外有n - 274
个零。
作为演示此问题的示例,假设我们正在寻找10个元素的每种组合,这些元素的总和为8,其中每个元素都是0到2之间的整数。
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 0 0 0 0 0 0 2 2 2 2
[2,] 0 0 0 0 0 1 1 2 2 2
[3,] 0 0 0 0 1 1 1 1 2 2
[4,] 0 0 0 1 1 1 1 1 1 2
[5,] 0 0 1 1 1 1 1 1 1 1
如您所见,最后一行具有最大数目的正元素(即8个)。
这是一个重要的发现,因为我们可以通过将元素的数量限制为所需的总和来大大减少要测试的组合的数量。
n 个元素的number of combinations with repetition选择 k 由二项式系数给出,其中最高位数为 n + k-1 ,底部数字为 k :
因此,在我们的示例中,我们可以减少超过2000万的可能支票数量:
choose(280 + 5 - 1, 280)
[1] 265368251
choose(274 + 5 - 1, 274)
[1] 243531475
265368251 - 243531475
[1] 21836776
尽管我们减少了可能性的空间,但我们仍然面临着艰巨的任务。生成所有组合并测试它们的总和不可能在合理的时间内产生任何解决方案。
更合理的解决方案是排除许多组合,而无需检查它们的总和。通过按字典顺序生成组合,一旦特定组合超出限制,我们就可以跳过许多组合,知道它们也将超出限制。这正是comboGeneral
(我是作者)中的RcppAlgos
所做的。
library(RcppAlgos)
comb274 <- comboGeneral(0:4, m = 274, TRUE,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = 274)
Error: vector memory exhausted (limit reached?)
如您所见,这将无法以其原始形式进行,因为要测试的组合太多(至少在我的机器上。您可以在macOS {{3}上更改R中的内存限制}。
这没问题。我们需要做的就是使用upper
参数限制预期结果的数量。我将其任意设置为100万。如果我们得到一百万个结果,则我们将增加该限制,直到结果数小于我们的界限为止。
system.time(comb274 <- comboGeneral(0:4, m = 274, TRUE,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = 274,
upper = 1e6))
user system elapsed
3.624 0.079 3.705
dim(comb274)
[1] 150811 274
就在那里!确认每一行总计为274,我们有:
all(rowSums(comb274) == 274)
[1] TRUE
如果确实需要280个元素,则可以运行上面的代码,以效率为代价将参数m
设置为280,或者简单地cbind
由150811行和6列组成的零矩阵到comb274
。