过滤排列以避免内存不足

时间:2014-03-24 12:59:19

标签: r bigdata combinatorics

此问题的背景是资产分配。如果我有N个资产,并且可以以5%的块分配它们,那么存在的排列是什么,使得分配的总和恰好等于100%。

例如,如果我有2个资产,则会有21个(使用我的函数" fMakeAllocationsWeb(2)"在此帖子底部的代码创建:

      [,1] [,2]
 [1,]    0  100
 [2,]    5   95
 [3,]   10   90
 [4,]   15   85
 [5,]   20   80
 [6,]   25   75
 [7,]   30   70
 [8,]   35   65
 [9,]   40   60
[10,]   45   55
[11,]   50   50
[12,]   55   45
[13,]   60   40
[14,]   65   35
[15,]   70   30
[16,]   75   25
[17,]   80   20
[18,]   85   15
[19,]   90   10
[20,]   95    5
[21,]  100    0

当资产数量增加时,问题当然是适度的。这是可以理解的,因为重复的排列数是n ^(n)并且我不能分配创建所有排列到存储器的中间步骤。例如,有20个资产,排列数为5.84258701838598E + 27 !!

我希望能够动态过滤这些(sum == 100),以免遇到内存分配问题。深入研究gtools :: permutations下面的代码,它似乎是矢量化的,干预过滤似乎是不可能的。

非常感谢任何想法 - 理想情况下更愿意坚持使用R代码和包。

非常感谢

拉​​斯

installifMissing <- function(sPackageName) {
  if (!sPackageName %in% installed.packages()) install.packages(sPackageName)
}


fMakeAllocationsWeb<-function(iNumAssets=10,iIncrement=5){
installifMissing("gtools")
require(gtools)

iAlloc<-seq(0,100,by=iIncrement) #'the allocation increments eg 0,5,10...,95,100
#'generate permutations
permut<-permutations(n=length(iAlloc),r=iNumAssets,v=iAlloc,repeats.allowed=TRUE)
#'filter permuatations for those which sum to exactly 100'
permutSum<-apply(permut,MARGIN=1,FUN=sum)
permut100<-permut[which(permutSum==100),]
return(permut100)
}

2 个答案:

答案 0 :(得分:1)

如果您安装了partitions软件包,那么您将拥有restrictedparts函数,该函数将枚举您可以将 n 数字加在一起以获得总和 S的所有方法。在您的情况下,您希望将加数限制为5的倍数,限制是加起来 S = 100 。相反,将您的加数除以5并使总加起来为20.如果您想要2个资产,那么代码restrictedparts(100/5,2) * 5将为您提供10个无序对。

然后,您可以循环遍历列,并为每个列枚举资产分配的所有排列集。您必须仔细处理存在重复元素的情况 - 例如,我们生成{100,0},其表示&lt; 100,0&gt;和&lt; 0,100&gt;而{50,50}仅代表单个分配&lt; 50,50&gt;。您可以使用set

permuatations属性来处理此问题

restrictedparts(100/5,20) * 5提供了627个分区,最多可达100% - 而且您需要对每个分区进行置换以获取完整的分配列表。

答案 1 :(得分:1)

在您的问题中,即使在过滤后,您仍然会有大量的组合要处理。

您的问题基本上归结为n multichoose k问题,如here所述 您希望从n个资产中选择k = 20个5%权重的插槽。

因此,在您的20个资产的示例中,您的组合数仍然是

choose(39, 20)
## [1] 68923264410

我建议您查看DEoptim包,其中包含与您手头的问题直接相关的具体示例。它使用差异进化。