如何使 sympy 在求解高阶方程时只求解 REAL 结果?
嗨,那里。当我使用 sympy 求解高阶非线性方程时,我发现获取所有结果太慢了。我想这是因为 sympy 也解决了complex的结果,事实是我只需要REAL的结果。那么,请问如何使 sympy 只求解 REAL 域中的结果,还是应该使用其他模块来求解这些方程?
这是代码。
from sympy import *
from sympy.solvers.solveset import nonlinsolve
h_0 = 170
b = 120
Es = 205
h = 200
M = 19760400
fc = 83
fy = 585
def cal(para):
Ec_f, As_f, ft_f = para
vp_c, vp_s, x_n = symbols('vp_c, vp_s, x_n', real=True)
f1 = vp_c / vp_s - x_n / (h_0 - x_n)
f2 = 1 / 2 * Ec_f * vp_c * b * x_n - As_f * Es * vp_s - ft_f * b * (h - x_n)
f3 = M - As_f * Es * vp_s * (h_0 - x_n / 3) - ft_f * b * (h - x_n) * (h / 2 + x_n / 6)
re = nonlinsolve([f1, f2, f3], [vp_c, vp_s, x_n])
return re
para = [42.4, 226, 3]
result = cal(para)
上面的代码在我的 i5-5500U 笔记本电脑上大约需要 20 秒。因为我需要很多循环,所以加快 sympy 的速度很重要。
这些是第一个循环的结果。
{(-0.469378305833599, 1.02614290514871, -143.317861965125), (1.00656308634739, 2.01548035330581, 56.6225231688573), ((-183.969547582998 - 351.920528939668*I)*(0.00608328163162871 - 0.00630805832877277*I + 4.48116677633078e-8*(-183.969547582998 - 351.920528939668*I)**2)/(2.44289841241567 + 1.15340253748558e-5*(-183.969547582998 - 351.920528939668*I)**2 + 2.76016101129151*I), -0.429603644119307*(-1.36072460310392 + 0.690040252822878*I)*(1.03415787737688 - 1.07236991589137*I + 7.61798351976232e-6*(-183.969547582998 - 351.920528939668*I)**2), -183.969547582998 - 351.920528939668*I), ((-183.969547582998 + 351.920528939668*I)*(0.00608328163162871 + 4.48116677633078e-8*(-183.969547582998 + 351.920528939668*I)**2 + 0.00630805832877277*I)/(2.44289841241567 - 2.76016101129151*I + 1.15340253748558e-5*(-183.969547582998 + 351.920528939668*I)**2), -0.429603644119307*(-1.36072460310392 - 0.690040252822878*I)*(1.03415787737688 + 7.61798351976232e-6*(-183.969547582998 + 351.920528939668*I)**2 + 1.07236991589137*I), -183.969547582998 + 351.920528939668*I)}
Hi, there. When I use sympy to solve high order and nonlinear equations, I found that it is too slow to get all the result. I guess it is because the sympy also solve the results of complex, the truth is I only need the results of REAL. So, may I ask how to make sympy only solve the result in the REAL domain or should I use other module to solve these equations?
This the code.
from sympy import *
from sympy.solvers.solveset import nonlinsolve
h_0 = 170
b = 120
Es = 205
h = 200
M = 19760400
fc = 83
fy = 585
def cal(para):
Ec_f, As_f, ft_f = para
vp_c, vp_s, x_n = symbols('vp_c, vp_s, x_n', real=True)
f1 = vp_c / vp_s - x_n / (h_0 - x_n)
f2 = 1 / 2 * Ec_f * vp_c * b * x_n - As_f * Es * vp_s - ft_f * b * (h - x_n)
f3 = M - As_f * Es * vp_s * (h_0 - x_n / 3) - ft_f * b * (h - x_n) * (h / 2 + x_n / 6)
re = nonlinsolve([f1, f2, f3], [vp_c, vp_s, x_n])
return re
para = [42.4, 226, 3]
result = cal(para)
The code above need about 20 seconds on my laptop with i5-5500U. Because I need a lot of loop, so it is important to speed up the sympy.
And these is the result of the first loop.
{(-0.469378305833599, 1.02614290514871, -143.317861965125), (1.00656308634739, 2.01548035330581, 56.6225231688573), ((-183.969547582998 - 351.920528939668*I)*(0.00608328163162871 - 0.00630805832877277*I + 4.48116677633078e-8*(-183.969547582998 - 351.920528939668*I)**2)/(2.44289841241567 + 1.15340253748558e-5*(-183.969547582998 - 351.920528939668*I)**2 + 2.76016101129151*I), -0.429603644119307*(-1.36072460310392 + 0.690040252822878*I)*(1.03415787737688 - 1.07236991589137*I + 7.61798351976232e-6*(-183.969547582998 - 351.920528939668*I)**2), -183.969547582998 - 351.920528939668*I), ((-183.969547582998 + 351.920528939668*I)*(0.00608328163162871 + 4.48116677633078e-8*(-183.969547582998 + 351.920528939668*I)**2 + 0.00630805832877277*I)/(2.44289841241567 - 2.76016101129151*I + 1.15340253748558e-5*(-183.969547582998 + 351.920528939668*I)**2), -0.429603644119307*(-1.36072460310392 - 0.690040252822878*I)*(1.03415787737688 + 7.61798351976232e-6*(-183.969547582998 + 351.920528939668*I)**2 + 1.07236991589137*I), -183.969547582998 + 351.920528939668*I)}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
加快求解速度的最佳方法可能是更改问题的表示形式:
f1
),Rational
实例中的每个数字我为要演示中间结果,请参阅 https:// nbviewer.org/github/cknoll/demo-material/blob/main/symbolic/groebner_basis_demo.ipynb
这是代码(没有中间结果):
→
大约需要1s。
The best way to speed up the solution is probably to change the representation of the problem:
f1
)Rational
I made a jupyter notebook for this, to demonstrate intermediate results, see https://nbviewer.org/github/cknoll/demo-material/blob/main/symbolic/groebner_basis_demo.ipynb
Here is the code (without intermediate results):
→
It takes about 1s.
如果您可以将系统简化为需要求解的单个方程,则可以使用real_roots,这应该非常快。
我假设您的循环将提供不同的 para_guessed 值。现在我们将这些称为 x、y、z,并根据这些变量得到方程组。我将对
cal
中对“nonlinsolve”的调用替换为return ([f1, f2, f3], [vp_c, vp_s, x_n])
最后两个方程很容易求解前两个变量:
现在将它们代入第一个方程——只有一个解,所以我们只需要处理一个可能的方程:
为了做好准备,让我们现在得到分子:
现在...插入您的值 - 或您感兴趣的任何其他值 - 并获得该单个变量的解决方案:
Backsubstitute 以获得其他变量:
给出
所以回顾一下:您使用 CAS 来减少您的系统 象征性地为一个单一方程,在代入已知值后可以很快求解出实根。然后用它来确定其他方程的值,这些方程已经很容易用符号求解以获得完整的数值解。没有虚部......而且很快。
If you can reduce the system down to a single equation that needs to be solved, you can use
real_roots
and that should be very fast.I assume your loop will provide different
para_guessed
values. Let's just call those x,y,z for now and get the set of equations in terms of those variables. I'm replacing your call to "nonlinsolve" incal
to bereturn ([f1, f2, f3], [vp_c, vp_s, x_n])
The last two equations are easy to solve for the the first two variables:
Now substitute those into the first equation -- there is only one solution so we only need to deal with one possible equation:
To get this most ready to go, let's get the numerator now:
Now... plug in your values -- or any others that you are interested in -- and get solutions for that single variable:
Backsubstitute to get the other variables:
Gives
So to recap: you use the CAS to reduce your system symbolically to a single equation for which the real roots can be solve very quickly after substituting in the known values. Then that is used to determine the values of the other equations that were already easy to solve symbolically to get a full numerical solution. No imaginary parts....and quickly.