Быстрое решение уравнения с помощью SymPy
Имеется некоторое уравнение, описывающее состав компонентов газа. Количество компонентов N может варьироваться (от 2 до ~50), как и количество корней J этого уравнения (обычно, J<N).
На данный момент решение осуществляется следующим образом:
Из функции get_sum возвращается строка - уравнение
def Wapor_finder(Wapor_result):
eq = get_sum(Wapor_result)
eq2 = sympify(eq, rational=False, strict=False)
x = symbols('x')
eq3 = Eq(eq2, rhs=0)
solution = solve(eq3, x, check=False)
print(solution)
Wapor = solution[3]
return Wapor
Проблема в том, что решение уравнения на всей области (поиск всех корней) занимает большое количество времени - примерно 30 с. Каким способом можно ускорить работу функции? Также стоит отметить, что среди J корней, корень X зачастую один и принадлежит промежутку [0,1].
Пример уравнения, которое находится в переменной eq2:
0.000965315027005431/(42.3383783774312*x + 1) +
0.130558956077151/(15.6212108541903*x + 1) +
0.000143666330482448/(2.37465009061897*x + 1) +
0.000889776726935506/(1.20240098234528*x + 1) -
0.000165767766880803/(1 - 0.495568809808081*x) -
6.13258440394361e^-5/(1 - 0.812262834959418*x) -
8.35671329085777e^-5/(1 - 0.86868121526588*x) -
3.21097701586257e^-5/(1 - 0.94999319995934*x) -
3.04033228739349e^-5/(1 - 0.962130470694144*x) -
3.51696655775184e^-5/(1 - 0.987911954424673*x) -
4.8147821393156e^-5/(1 - 0.996849304206127*x) -
5.92247573833024e^-5/(1 - 0.99873115317542*x) -
2.74857659912139e^-5/(1 - 0.999482399680507*x) -
2.96938154545349e^-5/(1 - 0.999791766145955*x) -
1.62992744082793e^-5/(1 - 0.999955485170511*x) -
1.11998924928786e^-5/(1 - 0.999990401149874*x) -
8.99998645388585e^-6/(1 - 0.999998494876206*x) -
3.49999886245156e^-6/(1 - 0.99999967498616*x) -
3.89999979169195e^-6/(1 - 0.999999946587679*x) -
2.09999999191464e^-6/(1 - 0.999999996149829*x) -
7.99999999842176e^-7/(1 - 0.99999999980272*x) -
9.99999999999502e-8/(1 - 0.999999999999502*x) = 0
Ответы (1 шт):
Можно представить выражение в виде рациональной функции, взять числитель (многочлен), вычислить его корни. Работает быстро:
import sympy
text = '''
0.000965315027005431/(42.3383783774312*x + 1)
+ 0.130558956077151/(15.6212108541903*x + 1)
+ 0.000143666330482448/(2.37465009061897*x + 1)
+ 0.000889776726935506/(1.20240098234528*x + 1)
- 0.000165767766880803/(1 - 0.495568809808081*x)
- 6.13258440394361e-5/(1 - 0.812262834959418*x)
- 8.35671329085777e-5/(1 - 0.86868121526588*x)
- 3.21097701586257e-5/(1 - 0.94999319995934*x)
- 3.04033228739349e-5/(1 - 0.962130470694144*x)
- 3.51696655775184e-5/(1 - 0.987911954424673*x)
- 4.8147821393156e-5/(1 - 0.996849304206127*x)
- 5.92247573833024e-5/(1 - 0.99873115317542*x)
- 2.74857659912139e-5/(1 - 0.999482399680507*x)
- 2.96938154545349e-5/(1 - 0.999791766145955*x)
- 1.62992744082793e-5/(1 - 0.999955485170511*x)
- 1.11998924928786e-5/(1 - 0.999990401149874*x)
- 8.99998645388585e-6/(1 - 0.999998494876206*x)
- 3.49999886245156e-6/(1 - 0.99999967498616*x)
- 3.89999979169195e-6/(1 - 0.999999946587679*x)
- 2.09999999191464e-6/(1 - 0.999999996149829*x)
- 7.99999999842176e-7/(1 - 0.99999999980272*x)
- 9.99999999999502e-8/(1 - 0.999999999999502*x)
'''
expr = sympy.sympify(text, rational=False, strict=False)
# print(expr)
numer = sympy.numer(sympy.ratsimp(expr))
# print(numer)
solution = sympy.nroots(numer)
print(*solution, sep='\n')
$ time python roots.py -0.771951952001311 -0.418403363891386 -0.0237288907337462 0.831751455805850 1.95109964842774 0.839505580583856 - 0.0571933498084203*I 0.839505580583856 + 0.0571933498084203*I 0.863830901118666 - 0.112636723077199*I 0.863830901118666 + 0.112636723077199*I 0.906694330419874 - 0.162460480670462*I 0.906694330419874 + 0.162460480670462*I 0.969296556651912 - 0.200266247590756*I 0.969296556651912 + 0.200266247590756*I 1.05040816885601 - 0.21694089834209*I 1.05040816885601 + 0.21694089834209*I 1.14344069499961 - 0.201528815060721*I 1.14344069499961 + 0.201528815060721*I 1.23298803838187 - 0.145571009454562*I 1.23298803838187 + 0.145571009454562*I 1.29312805289712 - 0.0530740362950097*I 1.29312805289712 + 0.0530740362950097*I real 0m2.333s user 0m2.296s sys 0m0.036s