简体   繁体   English

将NumPy数组传递给SymPy中使用lambdify创建的函数时出现语法错误

[英]A syntax error when passing a NumPy array to a function created with lambdify in SymPy

I am trying to use pytest on a function which takes as input a string and it parses it with lambdify. 我正在尝试在将字符串作为输入并使用lambdify解析的函数上使用pytest。

from sympy import sympify, symbols, lambdify
import numpy as np


def func(x):
    a = np.arange(10)
    expr = 'sin(x)'
    f = lambdify(x, sympify(expr), 'numpy')
    return f(a)


def test_answer():
    thelist = np.array([
        0., 0.84147098, 0.90929743, 0.14112001, -0.7568025, -0.95892427,
        -0.2794155, 0.6569866, 0.98935825, 0.41211849])
        assert func(np.arange(10)) == thelist


if __name__ == "__main__":
    x = symbols('x')
    func(x)

I am receiving : 我收到:

assert func(np.arange(10)) == thelist

test_sample.py:23: (it is the `assert func()`)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test_sample.py:13: in func  (it is the `f = lambdify(x, sympify(expr), 'numpy')`)
    f = lambdify(x, sympify(expr), 'numpy')
...
func = eval(lstr, namespace)
E         File "<string>", line 1
E           lambda 0,1,2,3,4,5,6,7,8,9: (sin(x))
E                  ^
E       SyntaxError: invalid syntax

../anaconda2/envs/pytest/lib/python3.6/site-packages/sympy/utilities/lambdify.py:387: SyntaxError

---- UPDATE ---------------- ----更新----------------

If I use this code: 如果我使用此代码:

from sympy import symbols, sin
from sympy.utilities.autowrap import ufuncify
import numpy as np


def func(x):

    a = np.arange(10)
    f = ufuncify(x, sin(x), backend='numpy')
    return f(a)


def test_answer():
    thelist = np.array([
        0., 0.84147098, 0.90929743, 0.14112001, -0.7568025, -0.95892427,
        -0.2794155, 0.6569866, 0.98935825, 0.41211849])
    assert all(func(np.arange(10)) == thelist)


if __name__ == "__main__":
    x = symbols('x')
    func(x)

and run it with pytest, I am getting : 并用pytest运行它,我得到:

args = (sin, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])), kwargs = {}

    def wrapper(*args, **kwargs):
        try:
>           retval = cfunc(*args, **kwargs)
E           TypeError: unhashable type: 'numpy.ndarray'

../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/core/cache.py:93: TypeError

During handling of the above exception, another exception occurred:

args = (sin, array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])), kwargs = {}

    def wrapper(*args, **kwargs):
        try:
>           retval = cfunc(*args, **kwargs)
E           TypeError: unhashable type: 'numpy.ndarray'

../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/core/cache.py:93: TypeError

During handling of the above exception, another exception occurred:

    def test_answer():
        thelist = np.array([
            0., 0.84147098, 0.90929743, 0.14112001, -0.7568025, -0.95892427,
            -0.2794155, 0.6569866, 0.98935825, 0.41211849])
>       assert all(func(np.arange(10)) == thelist)

test_ufuncify.py:23: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
test_ufuncify.py:14: in func
    f = ufuncify(x, sin(x), backend='numpy')
../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/core/cache.py:95: in wrapper
    retval = func(*args, **kwargs)
../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/core/function.py:385: in __new__
    result = super(Function, cls).__new__(cls, *args, **options)
../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/core/cache.py:95: in wrapper
    retval = func(*args, **kwargs)
../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/core/function.py:209: in __new__
    evaluated = cls.eval(*args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cls = sin, arg = array([], shape=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), dtype=float64)

    @classmethod
    def eval(cls, arg):
        from sympy.calculus import AccumBounds
>       if arg.is_Number:
E       AttributeError: 'numpy.ndarray' object has no attribute 'is_Number'

../anaconda3/envs/parsing/lib/python3.6/site-packages/sympy/functions/elementary/trigonometric.py:228: AttributeError

In order to create a binary function that supports NumPy broadcasting, you need ufuncify , not lambdify . 为了创建支持NumPy广播的二进制函数,您需要ufuncify而不是lambdify There are other issues with your code: 您的代码还有其他问题:

  • The assertion statement should be of the form all(array1 == array2) 断言语句的形式应为all(array1 == array2)
  • You use x as a function parameter and also as a SymPy symbol - within the same function. 您可以在同一函数中将x用作函数参数以及SymPy符号。
  • You have copied low-precision rounded values of sin(1), sin(2), ... which are not equal to the actual output of sine function. 您已经复制了sin(1),sin(2),...的低精度舍入值,这些值等于正弦函数的实际输出。
  • You have not imported the sine function 您尚未导入正弦函数

Here is this code with the issues rectified: 这是已纠正问题的代码:

from sympy import symbols, sin
from sympy.utilities.autowrap import ufuncify
import numpy as np

def test_answer():
    thelist = np.array([0.0, 0.8414709848078965, 0.90929742682568171, 0.14112000805986721, -0.7568024953079282, -0.95892427466313845, -0.27941549819892586, 0.65698659871878906, 0.98935824662338179, 0.41211848524175659])
    assert all(func(np.arange(10)) == thelist)

x = symbols('x')
func = ufuncify(x, sin(x), backend='numpy')
test_answer()

Remark 备注

Use repr(a) to get a string that accurately represents a number a. 使用repr(a)获得一个准确表示数字a的字符串。 The values printed with print are rounded. 用print打印的值是四舍五入的。 There is also set_printoptions 还有set_printoptions

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM