【问题标题】:R: Generating all permutations of N weights in multiples of PR:以 P 的倍数生成 N 个权重的所有排列
【发布时间】:2011-07-31 18:50:11
【问题描述】:

我需要创建一个函数(在 R 中):
- 给定 N 个可能的变量来赋予权重;
- 创建所有可能的权重排列(总和为 100%);
- 受限于权重必须以 P 的倍数出现(通常为 1%)

显然,因为 N 和 P 是负相关的 - 即我不能指定 N=7 和 P=0.4。但是,我希望能够仅指定整数解,即 P=0.01。

对不起,如果这是一个众所周知的问题 - 我不是数学专家,我使用我知道的术语进行了搜索,但没有找到足够接近的内容。

我会发布我编写的代码,但是......它并不令人印象深刻或富有洞察力。

感谢您的帮助!

【问题讨论】:

  • 你能举个小N和P的例子吗?我不太明白你所说的权重排列是什么意思。在没有权重限制的情况下,这些可以是 [0,1] 之间的实数值。这些值的集合是不可数的。或者“P的倍数”是否意味着这必须是整数倍?
  • 描述应用程序也可能有所帮助。这听起来像是在受某些约束的整数晶格上找到所有点。如果它可以简化为一个标准的背包问题,祝你好运。
  • 我还是建议发布代码。

标签: r permutation combinations combinatorics


【解决方案1】:

假设权重的顺序很重要,这些是组合;如果他们不这样做,那么这些是分区。在任何一种情况下,它们都受到部件数量的限制,你称之为 N,尽管下面的代码使用numparts。还有一个问题是是否允许权重为 0。

由于要权重加起来为 1,因此需要 1/p 为整数,在以下代码中为 sumparts;它不取决于权重的数量。一旦你有了这些组合,你可以将它们乘以 p,即除以 n,得到你的权重。

R 有一个partitions 包来生成此类组合或受限分区。下面的代码应该是不言自明的:矩阵中的每一列都是一组权重。我取了 7 个权重,p=0.1 或 10%,禁止权重为 0:这给出了 84 种可能性;允许权重为 0 意味着 8008 种可能性。在 p=0.01 或 1% 的情况下,没有权重为 0 的可能性有 1,120,529,256 种,而有 1,705,904,746 种可能性。如果顺序无关紧要,请使用restrictedparts 而不是compositions

> library(partitions)
> numparts <- 7  # number of weights
> sumparts <- 10  # reciprocal of p
> weights <- compositions(n=sumparts, m=numparts, include.zero=FALSE)/sumparts
> weights

[1,] 0.4 0.3 0.2 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1
[2,] 0.1 0.2 0.3 0.4 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1
[3,] 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.1 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2
[4,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

[1,] 0.1 0.3 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.3 0.2 0.1
[2,] 0.1 0.1 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.3
[3,] 0.1 0.1 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[4,] 0.4 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[5,] 0.1 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.3 0.4 0.1 0.1 0.1
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1

[1,] 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.3
[2,] 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[3,] 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[4,] 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[6,] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.3 0.3 0.4 0.1
[7,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2

[1,] 0.2 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[2,] 0.2 0.3 0.1 0.2 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[3,] 0.1 0.1 0.2 0.2 0.3 0.1 0.1 0.2 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[4,] 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.2 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.3 0.1 0.1 0.1 0.1 0.2
[6,] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2
[7,] 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2 0.2

[1,] 0.1 0.2 0.1 0.1 0.1 0.1 0.1 0.1
[2,] 0.1 0.1 0.2 0.1 0.1 0.1 0.1 0.1
[3,] 0.1 0.1 0.1 0.2 0.1 0.1 0.1 0.1
[4,] 0.1 0.1 0.1 0.1 0.2 0.1 0.1 0.1
[5,] 0.1 0.1 0.1 0.1 0.1 0.2 0.1 0.1
[6,] 0.3 0.1 0.1 0.1 0.1 0.1 0.2 0.1
[7,] 0.2 0.3 0.3 0.3 0.3 0.3 0.3 0.4

【讨论】:

  • 嗨@Henry,效果很好。并且很快!感谢您的帮助。
【解决方案2】:

编辑:函数已更新,因为它给出了两次结果。

你可以试试这个函数,基于递归计算。无论顺序如何,它都会为您提供所有可能的组合。我已经这样做了,否则您将获得具有所有可能排列的多个行。

计算基于整数。最小权重 P 设为 1,Pint 为可划分的权重单位数。 max.W 将是可以赋予​​一个变量的最大单位数量。

算法如下:

  • 如果 N=2,则针对给定的最小和最大权重进行所有可能的组合。

  • 如果 N > 2,则将此算法应用于 N = 1 到上限(max.weight / N),最大权重指定为当前最大权重 +1 减去 N,最小权重指定为 N。

这为您提供了所有可能的整数组合。与 P 相乘得到原始权重。

或者在函数中:

myfunc <- function(N,P){
  if(100%%(P*100) !=0){
    stop("100% cannot be divided in portions of P")
  }
  Pint <- 100/(P*100)
  max.W <- Pint- N + 1

  combs <- function(n,max.w,min){
    mw <- max.w + 1

    if(n==2){

      w <- seq.int(min,floor((mw)/2))
      out <- cbind(w,mw-w)

    } else if (n > 2){

      x <- lapply(1:ceiling(max.w/n),function(i){

        newcombs <- combs(n-1,mw-i,i)
        cbind(newcombs,rep(i,nrow(newcombs)))

      })

      out <- do.call("rbind",x)
    }
    colnames(out) <-rownames(out) <- NULL
    out
  }  
  res <- combs(N,max.W)
  apply(res,1,sort)*P
}

这给出了矩阵列中的组合:

> Y <- myfunc(3,0.1)
> Y
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]  0.1  0.1  0.1  0.1  0.2  0.2  0.2  0.3
[2,]  0.1  0.2  0.3  0.4  0.2  0.3  0.4  0.3
[3,]  0.8  0.7  0.6  0.5  0.6  0.5  0.4  0.4

请注意!使用您提供的测试用例(7 个变量,0.01 的跳跃),您将为大量可能性计算很长时间。当 N=7 和 P=0.04 时,您已经有 3555 种可能的组合。当 N=0.2 时,这变成了 336,443 种可能性。如果这是你所追求的,你必须考虑这些组合的每一种可能的排列。

【讨论】:

  • 您在其中有一些重复项:第 2 & 5、3 & 9、4 & 12、7 & 10、8 & 13 和 11 & 14 列。
  • @Henry :抓住了他们,现在问题解决了。在第二次通知中,您显然已经使用更简单的方法解决了问题。好吧,我玩这个很开心。玩递归总是很有趣:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多