简体   繁体   English

在 R 或 Python 中无需转换为矩阵即可求解联立方程 (>2)

[英]Solving simultaneous equations (>2) without conversion to matrices in R or Python

I have a set of 4 simultaneous equations:我有一组 4 个联立方程:

0.059z = x
0.06w = y
z+w = 8093
x+y = 422

All the solutions I've found so far seem to be for equations that have all the variables present in each equation, then convert to matrices and use the solve function.到目前为止,我找到的所有解决方案似乎都适用于在每个方程中都存在所有变量的方程,然后转换为矩阵并使用求解函数。

Is there an easier way to do this in R or Python using the equations in their original form?使用原始形式的方程在 R 或 Python 中是否有更简单的方法来做到这一点?

Also, how can I ensure that only positive numbers are returned in the solution?另外,如何确保解决方案中只返回正数?

Hope this makes sense...many thanks for the help希望这是有道理的...非常感谢您的帮助

You can use sympy for this:您可以为此使用sympy

from sympy import symbols, linsolve, Eq
x,y,z,w = symbols('x y z w')
linsolve([Eq(0.059*z, x), Eq(0.06*w, y), Eq(z+w, 8093), Eq(x+y, 422)], (x, y, z, w))

Output:输出:

在此处输入图片说明

Regarding your comments about negative values - there is only one solution to the system of equations, and it has negative values for y and w .关于您对负值的评论 - 方程组只有一个解,并且yw具有负值。 If there was more than one solution, sympy would return them, and you could filter the solutions from there to only positive values.如果有多个解决方案,sympy 会返回它们,并且您可以从那里过滤解决方案,使其仅得到正值。

In R , maybe you try it like below:R ,也许您可​​以像下面这样尝试:

library(rootSolve)
library(zeallot)

model <- function(v){
  c(x,y,z,w) %<-% v
  return(c(0.059*z-x, 0.06*w-y, z+w-8093, x+y-422))
}
res <- multiroot(f = model, start = c(0,0,0,0))

then you can get the solution res as那么你可以得到解决方案res

> res
[1]   3751.22  -3329.22  63580.00 -55487.00

there are a few things going on here.这里发生了一些事情。 first as CDJB notes: if there were any positive solutions then sympy would find them.首先正如 CDJB 所指出的:如果有任何积极的解决方案,那么 sympy 会找到它们。 I searched for those numbers and found this paper which suggests you should be using 7088 instead of 8093. we can do a quick sanity check:我搜索了这些数字并找到了这篇论文,它表明您应该使用 7088 而不是 8093。我们可以做一个快速的健全性检查:

def pct(value):
    return f"{value:.1%}"

print(pct(422 / 8093))  # ~5.2%
print(pct(422 / 7088))  # ~6.0%

confirming that you're going to struggle averaging ~5.9% and ~6.0% towards ~5.2%, and explaining the negative solutions in the other answers.确认您将在平均 ~5.9% 和 ~6.0% 到 ~5.2% 中挣扎,并在其他答案中解释否定解决方案。 further, these are presumably counts so all your variables also need to be whole numbers.此外,这些可能是计数,因此您的所有变量也需要是整数。

once this correct denominator is used, I'd comment that there are many solutions (11645 by my count) eg:一旦使用了这个正确的分母,我会评论说有很多解决方案(我数为 11645),例如:

cases = [1, 421]
pop = [17, 7071]

rates = [pct(c / p) for c, p in zip(cases, pop)]

gives the appropriate output, as does:给出适当的输出,如:

cases = [2, 420]
pop = [34, 7054]

this is because the data was rounded to two decimal places.这是因为数据四舍五入到小数点后两位。 you probably also don't want to use either of the above, they're just the first two valid solutions I got.您可能也不想使用上述任何一个,它们只是我得到的前两个有效解决方案。

we can define a Python function to enumerate all solutions:我们可以定义一个 Python 函数来枚举所有解决方案:

from math import floor, ceil

def solutions(pop, cases, rate1, rate2, err):
    target = (pct(rate1), pct(rate2))
    for pop1 in range(1, pop):
        pop2 = pop - pop1
        c1_lo = ceil(pop1 * (rate1 - err))
        c1_hi = floor(pop1 * (rate1 + err))

        for c1 in range(c1_lo, c1_hi+1):
            c2 = cases - c1
            if (pct(c1 / pop1), pct(c2 / pop2)) == target:
                yield c1, c2, pop1, pop2

all_sols = list(solutions(7088, 422, 0.059, 0.060, 0.0005))

which is where I got my count of 11645 above from.这是我从上面得到的 11645 的计数。

not sure what to suggest with this, but you could maybe do a bootstrap to see how much your statistic varies with different solutions.不确定对此有何建议,但您可以进行引导以查看您的统计数据随不同解决方案而变化的程度。 another option would be to do a Bayesian analysis which would let you put priors over the population sizes and hence cut this down a lot.另一种选择是进行贝叶斯分析,它可以让您将先验放在人口规模上,从而大大减少这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM