1

我有一个由 sympy 表示的方程组:

def test1a(A):
    t, tt = sym.symbols('t tt')
    return sym.cos(t+tt+A)*A

def test1b(B):
    t, tt = sym.symbols('t tt')
    return sym.sin(t-tt+B)*B

我想在使用以下命令评估结果之前转换为 numpy 表达式fsolve()

def testprep(variables, A, B):
    
    t, tt = sym.symbols('t tt')
    
    fA = lambdify([(t, tt)], test1a(A))
    fB = lambdify([(t, tt)], test1b(B))
    
    t, tt = variables
    
    return [fA,fB]

def testsolve(A, B):
    
    print(so.fsolve(testprep, [-1, 1], args = (A, B)))
    
    return

运行时,我得到以下结果:

import scipy.optimize as so
import sympy as sym
from sympy.utilities.lambdify import lambdify as lambdify
import numpy as np

def main():
    A = 1
    B = 2
    testsolve(A,B)
    return

if __name__ == '__main__':
    main()

输出:

error: Result from function call is not a proper array of floats.

作为健全性检查,我根据 numpy 表达式起草了相同的系统并解决了它:

def standard(variables, A, B):
    
    t, tt = variables
    
    eq1 = np.cos(t+tt+A)*A
    eq2 = np.sin(t-tt+B)*B
    
    return [eq1, eq2]

def solvestandard(A, B):
    
    print(so.fsolve(standard, np.array([-1, 1]), args = (A,B)))
    
    return

带输出:

[-0.71460184  1.28539816]

我是新手,lambdify( )对从 sympy 转换为 numpy 的过程不太熟悉。为了使测试用例工作,我需要改变什么?

4

1 回答 1

2

对于 SO 问题,您以非常复杂的方式呈现了您的代码。您不需要这么多函数来显示基本上是 5 行代码!

请将您的示例简化为尽可能简单的代码,即可以复制粘贴完整的所有导入的单个代码块。然后请通过复制粘贴并在新的 python 进程中运行来测试它。

lambdifywith的使用方式fsolve是这样的:

import sympy as sym
import scipy.optimize as so

t, tt = sym.symbols('t tt')
A, B = 1, 2
eq1 = sym.cos(t+tt+A)*A
eq2 = sym.sin(t-tt+B)*B
f = lambdify([(t, tt)], [eq1, eq2])
print(so.fsolve(f, [-1, 1]))

这个想法是lambdify 生成了一个可以多次计算的高效函数(例如fsolve,将迭代地调用它)。然后你将那个有效的函数传递给fsolve.

您传递给的函数fsolve不应调用lambdify自身(如您testprep所做的那样),因为lambdify它比评估函数慢得多:

In [22]: %time f = lambdify([(t, tt)], [eq1, eq2])
CPU times: user 4.74 ms, sys: 77 µs, total: 4.82 ms
Wall time: 4.96 ms

In [23]: %time f([1, 2])
CPU times: user 36 µs, sys: 1e+03 ns, total: 37 µs
Wall time: 41 µs
Out[23]: [-0.6536436208636119, 1.682941969615793]

也许你真正的问题更复杂,但我会使用 sympy 来nsolve解决这样的问题:

In [16]: nsolve([eq1, eq2], [t, tt], [-1, 1])
Out[16]: 
⎡-0.714601836602552⎤
⎢                  ⎥
⎣ 1.28539816339745 ⎦

In [17]: nsolve([eq1, eq2], [t, tt], [-1, 1], prec=100)
Out[17]: 
⎡-0.714601836602551690384339154180124278950707650156223544756263851923045898428447750342991293664470733⎤
⎢                                                                                                      ⎥
⎣1.285398163397448309615660845819875721049292349843776455243736148076954101571552249657008706335529267 ⎦

SymPynsolve会负责lambdify为您打电话。它比fsolve使用任意精度浮点数要慢一些,但这意味着它还可以计算更准确的结果。

于 2021-07-07T20:19:02.467 回答