可以将lambdaify()与Sympy一起使用,以利用三个方程和三个未知数的数值求解器

问题描述 投票:0回答:1

我需要同时求解三个实数多元方程(三个变量)以获得数值结果(在本例中不是符号性的)。过去,我只使用了 SymPy 的solve() 函数,该函数效果很好对于我所做的大部分工作(线性符号方程。)

但这三个是非线性的。假设三个符号表达式 e1、e2 和 e3 具有实数正变量 c1、c2 和 c3:

c1, c2, c3 = symbols( 'c1,c2,c3', real=True, positive=True )
e1 = f(c1, c2, c3)               # f() is actually too long to write out
e2 = g(c1, c2, c3)               # g() is actually too long to write out
e3 = h(c1, c2, c3)               # h() is actually too long to write out
                                 # .. but see at-bottom for f() for clarity

尝试以下操作时,我没有收到任何错误:

solve( [ Eq(e1, -1), Eq(e2, -0.5), Eq(e3, -sqrt(3)/2) ], [ c1, c2, c3 ] )

我碰巧知道正确答案的附近:c1=3.5472、c2=1.39199 和 c3=0.20238(大致)

但是,我在等待几个小时后终止了解决方案尝试。

我不确定如何使用附近的值“帮助”上述求解器。 (我是一个临时用户,因此可能非常无知,不知道如何轻松找到正确的文档(如果存在的话)。我确实尝试过并考虑在在那里呆了几个小时后才考虑寻求帮助。我不会在这里记录我所有失败的尝试。)

所以我决定,如果我要对上述方程进行羔羊化,那么也许我可以利用其他求解器。

我的第一个倾向是设置 lambda 化函数以产生零,因为我想象了减少选项集的可能性,否则。所以,如下:

f1 = lambdify( (c1,c2,c3), e1 + 1 )
f2 = lambdify( (c1,c2,c3), e2 + 0.5 )
f3 = lambdify( (c1,c2,c3), e3 + sqrt(3)/2 )

当我插入 c1、c2 和 c3 的近似值时,我确实从 f1、f2 和 f3 获得接近于零的输出。这很好。这意味着我至少设法以一种符合我预期的方式使用lambda(第一次)。

但是,现在我不知道从这里该走哪条路。

我确实有很多失败的结果可以记录下来。但是,回顾它们,它们完全是我的无知,而且可能在这里没有特别的帮助。我认为那里有噪音和信号很少。

存在且只有一种可能的解决方案,并且所有三个解决方案将同时收敛于零。所以这不完全是一个模拟退火类型的问题(尽管我想是可以接受的。)我完全期望 SymPy 的solve()能够相当快地处理这个问题,但现在我怀疑它正在旋转它的轮子采用符号导数。 (当然,我不确定。)但这就是为什么我正在考虑将这些表达式移植到更数值的方面,希望求解器能够处理数值差异而不是符号导数。

正确的做法是什么?我迷路了。我认为答案应该更多地是让我学习一些我目前所缺乏的语法新知识。但请记住,e1、e2 和 e3 不是 c1、c2 和 c3 的线性组合。它们涉及各种整数幂、平方根、立方根以及其中任意两个或三个的各种乘积的组合。

就是这样。如果不是一个彻底的“方法如下”答案,我希望能朝正确的方向推动。

注意: e1 位于下面,供任何关心这些东西是什么样子的人使用:

-(-3*(c2 + 3*c3)/(c1*c2*c3) + (2*c1*c3 + 2*c2*c3)**2/(c1**2*c2**2*c3**2))/(3*(sqrt(-4*(-3*(c2 + 3*c3)/(c1*c2*c3) + (2*c1*c3 + 2*c2*c3)**2/(c1**2*c2**2*c3**2))**3 + (27/(c1*c2*c3) - 9*(c2 + 3*c3)*(2*c1*c3 + 2*c2*c3)/(c1**2*c2**2*c3**2) + 2*(2*c1*c3 + 2*c2*c3)**3/(c1**3*c2**3*c3**3))**2)/2 + 27/(2*c1*c2*c3) - 9*(c2 + 3*c3)*(2*c1*c3 + 2*c2*c3)/(2*c1**2*c2**2*c3**2) + (2*c1*c3 + 2*c2*c3)**3/(c1**3*c2**3*c3**3))**(1/3)) - (sqrt(-4*(-3*(c2 + 3*c3)/(c1*c2*c3) + (2*c1*c3 + 2*c2*c3)**2/(c1**2*c2**2*c3**2))**3 + (27/(c1*c2*c3) - 9*(c2 + 3*c3)*(2*c1*c3 + 2*c2*c3)/(c1**2*c2**2*c3**2) + 2*(2*c1*c3 + 2*c2*c3)**3/(c1**3*c2**3*c3**3))**2)/2 + 27/(2*c1*c2*c3) - 9*(c2 + 3*c3)*(2*c1*c3 + 2*c2*c3)/(2*c1**2*c2**2*c3**2) + (2*c1*c3 + 2*c2*c3)**3/(c1**3*c2**3*c3**3))**(1/3)/3 - (2*c1*c3 + 2*c2*c3)/(3*c1*c2*c3)
python numpy sympy solver
1个回答
0
投票

Sympy 还公开了

nsolve
,它可用于对线性(或非线性)方程组进行数值求解。您所要做的就是:

nsolve([e1, e2, e3], [c1, c2, c3], [3.5472, 1.39199, 0.20238])

此函数对表达式进行羔羊化并使用 mpmath 的

findroot
。如果您碰巧知道一个好的初步猜测,这会非常方便。

由于您有 3 个方程,您还可以使用 SymPy Plotting Backend 的

plot3d_implicit
来找到一个好的初始猜测:

from spb import *
plot3d_implicit(e1, e2, e3, (c1, -5, 5), (c2, -5, 5), (c3, -5, 5), backend=KB, n=150)

无论如何,在不知道

e2, e3
的确切表达方式的情况下,这就是我能建议的。

© www.soinside.com 2019 - 2024. All rights reserved.