用 sympy 求解代数方程

Solving an algebraic equation with sympy

提问人:George Yeo 提问时间:9/13/2023 最后编辑:President James K. PolkGeorge Yeo 更新时间:9/13/2023 访问量:96

问:

我有这个代数方程,可以在 WolframAlpha 中求解:

Algebraic Equation with solution

但它无法在 Python 中解决。

出现以下错误:

NotImplementedError: multiple generators [10**x, 2**x]
No algorithms are implemented to solve equation 
       (1/2)**(1 - x) - 10**(x - 1)/4 - 3/4

我想知道我的代码有什么问题?

x = symbols('x')
eq1 = Eq(0.5**(1-x)-1-((1/4)*(0.1**(1-x)-1)),0)
sol = solve((eq1),(x))
sol
Python 数学 sympy 求解器 代数

评论

0赞 David Waterworth 9/13/2023
问题是什么?
0赞 trincot 9/13/2023
似乎您需要包含一些模块。你用的是哪个?其次,“NotImplementedError”并不意味着你的代码是错误的,而只是你想使用一个尚未由该模块实现的功能。
0赞 pho 9/13/2023
记得标记你的问题,这样人们就知道你在问什么图书馆
0赞 David Waterworth 9/13/2023
这是吗?您是否期待一个数字解决方案 - 如果是这样,SymPy 不是正确的工具,那么您可能想要?SymPyscipy.optimize
0赞 bereal 9/13/2023
方程可能无法解析求解,但仍可以通过数值求解,例如:stackoverflow.com/a/64717448/770830

答:

4赞 Davide_sd 9/13/2023 #1

失败时,您可以尝试使用 找到数值解。首先,您需要找到合理的初始猜测。在这种情况下,一个简单的就足够了:solvensolveplot

from sympy import *
x = symbols("x")
eq = 0.5**(1-x)-1-((1/4)*(0.1**(1-x)-1))
plot(eq, ylim=(-5, 5))

enter image description here

似乎至少有一个根。让我们放大一下:x=1

plot(eq, (x, 0, 2))

enter image description here

有两个根。让我们找到它们:

initial_guesses = [1, 1.5]
r = [nsolve(eq, x, i) for i in initial_guesses]
print(r)
# out: [1.00000000000000, 1.21889091552120]
0赞 Serge Ballesta 9/13/2023 #2

这并不是一个真正的代数方程......像这样的方程的解并不能保证是代数数。换句话说,除了明显(和确切)的解决方案之外,任何其他解决方案都可能是一个先验数x = 1

由于这个方程没有很好的属性(至少我乍一看找不到任何属性),我认为它不能通过解析求解,而 SymPy 说它不能求解是正确的:它没有算法......因为数学家不知道!

我不知道 WolframAlpha,但我认为它只是在数值上解决了它。在 Python 中也可以,无论是手动进行一点二分法,然后是 Euler 方法,或者像 @Davide_sd 的答案中所示,或者使用 scipy,或者......sympy.nsolve

2赞 lastchance 9/13/2023 #3

您可以编写自己的求解器,通过单点迭代来求解方程。

首先重写等式会很有帮助:

0.5 * 2 x -3/4 -0.025 * 10x = 0

或者,乘以 40 并重新排列,

20 * 2 x - 30 = 10x

您可以重新排列以使任何包含 x 的项成为主题,然后获取日志(任何基数)以给出两个可能的迭代公式:

x = log(20 * 2x - 30)/log(10)

x = log(1.5+0.05 * 10x)/log(2)

前者适用于x>=1时的单点迭代,后者适用于x<=1时的单点迭代。此外,由于 10 x 是正数,那么 20 * 2 x - 30 也必须是正数,这意味着x > log(1.5)/log(2)。

在下面的代码中,输入小于 1 的起点以获得较小的解决方案,输入大于 1 的起点以获得第二个解决方案。

from math import log

def RHS( x ):
    if x > 1.0:
       return log( 20 * 2 ** x - 30 ) / log( 10.0 )
    else:
       return log( 1.5 + 0.05 * 10 ** x ) / log( 2.0 )

TOLERANCE = 1.0e-20;
XMIN = log( 1.5 ) / log( 2.0 )

print( "Enter a starting point for iteration (greater than ", XMIN, "): " )
x = float( input() )
xprev = x + 1.0

while abs( x - xprev ) > TOLERANCE:
    xprev = x
    x = RHS( x )

print( "Solution: {:13.6f}".format( x ) )

输出示例:

Enter a starting point for iteration (greater than  0.5849625007211562 ): 
0.7
Solution:      1.000000


Enter a starting point for iteration (greater than  0.5849625007211562 ): 
10
Solution:      1.218891