R中方程的所有可能解

时间:2015-06-21 20:00:50

标签: r equation-solving

我想写一个R代码来生成方程x1 + x2 + ... + xm = n的所有不同解,其中n是正整数,xi> = 0,是非负整数。

我为此目的编写了一个R代码,但我不喜欢它的运行时间。此外,它对于相对较大的m和n值不起作用,如n = m = 10。 我的代码如下。

 A<-matrix(ncol=m,nrow=choose((n+m-1),(m-1)))
  a<-1
  for (h in 1:((n+1)^m)) {
        l <- rep(NA, m)
        for (il in 1:m) {
            l[il] <- (((h-1) %/% ((n+1)^(il-1))) %% (n+1)) + 1
            l[il]<-l[il]-1
        }
         if(sum(l)==n) { A[a,]<-l;a<-a+1}
    }
  A

任何人都知道找到该等式的解决方案的更有效方法吗? 谢谢。

1 个答案:

答案 0 :(得分:1)

您似乎正在经历更多数字组合而非需要。当您输入代码时,n + m - 1选择m - 1表示将满足此类问题的解决方案的数量。想想为什么它的工作原理如下:我们想把n分成m组。如果我们将n个元素并排排列,我们需要制作m-1个印章来创建m个组。我们可以考虑每个印章作为它自己的元素。让我们用n = 8,m = 5来具体考虑它。就好像我们需要将8个a分成5组(4个剁,用“/”表示)。这就像我们有一排12个空格一样,我们不得不在行中加上8个和4个。示例输出可以是:

a a / / a / a a a a / a

如果我们找到斜杠的索引之间的差异并减去一个(并且假设在0和n + m的外部索引上有2个额外的斜杠),我们可以找到每个解决方案。对于上面的例子,5个数字将是2(3 - 0 - 1),0(4 - 3 - 1),1(6 - 4 - 1),4(11 - 6 - 1)和1(13 - 11 - 1)。因此,如果我们生成所有(n + m - 1)选择(m - 1)结果,我们可以做简单的减法,而不需要担心任何额外的组合。

我们也可以使用combinations()库中的gtools函数来使用代码模拟这一点。

library(gtools)
nums <- rep(0, m)
combs <- combinations(n + m - 1, m - 1)
for(i in 1:choose(n + m - 1,m - 1)){
  for(j in 1:m){
    #edge case for beginning
    if(j == 1){
      nums[j] <- combs[i, j] - 1
    }
    #edge case for end
    else if(j == m){
      nums[j] <- n + m - combs[i, j-1] - 1
    }
    else {
      nums[j] <- combs[i, j] - combs[i, j-1] - 1
    }
  }
  A[i,] <- nums
}

如果你想进一步提高速度,可以将内部for循环放在一个函数中,该函数接受组合矩阵,n和m的一行,并返回所需解决方案输出的单行。然后,您可以对该函数使用apply函数:

rowSummer <- function(spaces, size, max){
  nums <- rep(0, size)
  for(j in 1:size){
    if(j == 1){
      nums[j] <- spaces[j] - 1
    }
    else if(j == size){
      nums[j] <- max - spaces[j-1] - 1
    }
    else {
      nums[j] <- spaces[j] - spaces[j-1] - 1
    }
  }
  nums
}

combs <- combinations(n+m-1, m-1)
A <- apply(combs, 1, rowSummer, size=m, max=n+m)
t(A)

但是,上面的原始解决方案只需通过必要的组合即可加快速度。