简体   繁体   English

求解非线性(和非多项式)方程组

[英]Solving system of nonlinear (and nonpolynomial) equations

I would like to use python/sympy to solve simple systems of equations coming from impedance calculations in electronics.我想使用 python/sympy 来解决来自电子阻抗计算的简单方程组。

In such calculations, due to the "parallel impedance" formula, one often has to deal with expressions of the form:在此类计算中,由于“并联阻抗”公式,人们通常不得不处理以下形式的表达式:

par(x,y) := (x*y)/(x+y)

Now I have tried with the following code:现在我尝试使用以下代码:

from sympy import *

def par(var1,var2):
    return (var1 * var2)/(var1+var2)

A = Symbol('A')
B = Symbol('B')
C = Symbol('C')
D = Symbol('D')
E = Symbol('E')

eq1 = A + par(B+50 , (C+  par(D,  (E+50))  ))  - 50 
eq2 = B + par(A+50 , (C+  par(D ,  (E+50)) ))  - 50
eq3 = E + par(D+50,  (C+ par(A+50, B+50)) ) - 50

thus defining a system of three equations in five variables {A,B,C,D,E} , but then running因此在五个变量{A,B,C,D,E}中定义了三个方程组,然后运行

solve([eq1,eq2,eq3], A, B,C,D,E)

the computations just does not terminate.计算只是不会终止。

Do you have any suggestions on how I could approach these type of equations?你对我如何处理这些类型的方程式有什么建议吗? Basically polynomials with division by polynomials, with solutions in the complex numbers.基本上是除以多项式的多项式,具有复数的解。

You could also try the Z3 library :您也可以尝试Z3 库

from z3 import Reals, Solver, sat, set_option

def par(var1, var2):
    return (var1 * var2) / (var1 + var2)

vars = Reals('A B C D E')
A, B, C, D, E = vars

set_option(rational_to_decimal=True, precision=30)
s = Solver()
s.add(A + par(B + 50, (C + par(D, (E + 50)))) == 50)
s.add(B + par(A + 50, (C + par(D, (E + 50)))) == 50)
s.add(E + par(D + 50, (C + par(A + 50, B + 50))) == 50)
if s.check() == sat:
    m = s.model()
    print(m)

I get following output:我得到以下输出:

[D = 0.502507819412956050111927878839?,
 C = 0.125,
 E = 50.188198722936229689352204927638?,
 B = -50.625,
 A = -50.625]

The question mark at the end of D's and E's values means they have been approximated. D 和 E 值末尾的问号表示它们已被近似。

If you then try the values for A, B and C into the original code, sympy gives two exact expressions:如果您随后尝试将 A、B 和 C 的值放入原始代码中,sympy 会给出两个精确的表达式:

[{A: -405/8,
  B: -405/8,
  C: 1/8,
  D: -31857/1292 + 5*sqrt(676050154)/5168,
  E: 443/1304 + 5*sqrt(676050154)/2608},
 {A: -405/8,
  B: -405/8,
  C: 1/8,
  D: -5*sqrt(676050154)/5168 - 31857/1292,
  E: 443/1304 - 5*sqrt(676050154)/2608}]

Taking the suggestion of Oscar and focussing on A, B and C you can get a solution for them in terms of D and E:采纳 Oscar 的建议并专注于 A、B 和 C,您可以根据 D 和 E 为它们找到解决方案:

>>> solve((eq1, eq2, eq3), A, B, C)[0] # one solution
(
50*(D + E)*(D + E + 50)/(3*D**2 - 2*D*E + 150*D - 3*E**2 - 50*E + 5000), 
50*(D + E)*(D + E + 50)/(3*D**2 - 2*D*E + 150*D - 3*E**2 - 50*E + 5000), 
(-3*D**3*E + 50*D**3 + 2*D**2*E**2 - 500*D**2*E + 10000*D**2 + 3*D*E**3 + 50*D*E**2 - 25000*D*E + 500000*D + 200*E**3 - 5000*E**2 - 500000*E + 12500000)/(3*D**3 + D**2*E + 150*D**2 - 5*D*E**2 + 100*D*E + 5000*D - 3*E**3 - 50*E**2 + 5000*E))

Notice that the solution for A and B is the same (consistent with the symmetry of the first two equations wrt A and B).请注意,A 和 B 的解是相同的(与 A 和 B 的前两个方程的对称性一致)。

>>> sol = Dict(*zip((A,B,C),_))
>>> sol[A] = sol[B]
True

In this form, you can directly substitute values for D and E :在这种形式中,您可以直接替换DE的值:

>>> sol.subs({D:1, E:S.Half})
{A: 1030/1367, B: 1030/1367, C: 2265971/1367}

You can also see what relationships between D and E are forbidden by solving for when any of the denominators are 0:您还可以通过求解任何分母为 0 的情况来查看DE之间的哪些关系是禁止的:

>>> from sympy.solvers.solvers import denoms
>>> set([j.simplify() for i in denoms(sol) for j in solve(i,D)])
{-E, E/3 - sqrt(10*E**2 - 9375)/3 - 25, E/3 + sqrt(10*E**2 - 9375)/3 - 25}

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

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