关于python:使用sympify并对其进行评估来传递函数公式

Passing a function formula using sympify and evaluating it

我已经看到并尝试对类似问题实施以下答案无济于事:https://stackoverflow.com/a/23687379/3696204

我还查看了SymPy evalf的文档,大约是本文的一半:
http://docs.sympy.org/latest/tutorial/basic_operations.html

我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from sympy import sympify


def test_function(a, b, c, d, funct):

    f = sympify(funct)
    dx = 0.2
    J = int(2/dx)

    for i in range(J-1):
        x = -1 + (i * dx)
        print("f(", x,") =", f.evalf(x))

    print("Just for fun:", a, b, c, d)

    return c + d


if __name__ == '__main__':

    print(test_function(1, 2, 3, 4, funct="pow(x, 4) - 2 * pow(x, 2) + 2"))

    print(test_function(1, 2, 3, 4, funct="x**4 - 2 * x**2 + 2"))

结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    f( -1.0 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( -0.8 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( -0.6 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( -0.3999999999999999 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( -0.19999999999999996 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( 0.0 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( 0.20000000000000018 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( 0.40000000000000013 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    f( 0.6000000000000001 ) =  -0.e+0*pow(x, 2) + pow(x, 4) + 0.e+0
    Just for fun:  1 2 3 4
    7
    f( -1.0 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( -0.8 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( -0.6 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( -0.3999999999999999 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( -0.19999999999999996 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( 0.0 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( 0.20000000000000018 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( 0.40000000000000013 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    f( 0.6000000000000001 ) =  x**4 - 0.e+0*x**2 + 0.e+0
    Just for fun:  1 2 3 4
    7

在阅读文档的基础上,还尝试了f.evalf(subs=x)f.evalf(subs={x: x_i}),我根据x_i重新定义了循环。在第一种情况下,我得到关于"浮动不可订阅"的投诉,在第二种情况下,我收到投诉说"x未定义"。

好的,到目前为止,这都是我的努力。如果有人好奇,我已经编写了用于求解三对角矩阵的Thomas算法,现在我创建了一种方法,应用Thomas来解决PDE,其初始条件由某些方程给出。我想将该等式传递给我的算法,以便可以即时提供初始条件。


sympify之后,f是表达式。 我们可以使用lambdifyf变成一个sympy函数:

1
2
3
4
>>> x = Symbol('x')
>>> f = lambdify(x, sympify("pow(x, 4) - 2 * pow(x, 2) + 2"))
>>> [f(0.2 * i) for i in range(5)]
[2.0, 1.9216, 1.7056, 1.4096, 1.1296]

当对字符串执行sympify时,子字符串"x"将被解释为符号,即Symbol("x")。 此对象与您可能称为x的任何Python变量无关。 符号名称和变量名称是不同的东西。

要用名为x的Python变量替换Symbol("x"),您需要

1
f.subs(Symbol('x'), x)

这个subs就足够了,因为你提供了一个浮点参数,所以自动进行浮点计算。 否则,evalf可能会被强制使用

1
f.evalf(subs={Symbol('x'): x})

顺便说一句,f.evalf(x)表示:评估f返回x十进制数字; 与替代无关。

旁白

函数名称:x**4Pow(x, 4)都有效,但Pow(x, 4)对SymPy没有意义。

要查看变量名称和符号名称之间的区别,请尝试

1
2
3
b = Symbol("a")
print(b)  # prints"a"
print(a)  # undefined