【问题标题】:Evaluate sympy expression from an array of values从值数组评估 sympy 表达式
【发布时间】:2012-05-27 13:48:27
【问题描述】:

我正在尝试 sympy,但遇到了一个我无法解决的问题。

使用 scipy,我可以编写一个表达式并为 x 值数组评估它,如下所示:

import scipy
xvals = scipy.arange(-100,100,0.1)
f = lambda x: x**2
f(xvals)

使用 sympy 我可以编写如下相同的表达式:

import sympy
x = sympy.symbols('x')
g = x**2

我可以通过执行以下操作来评估此表达式的单个值:

g.evalf(subs={x:10})

但是我不知道如何评估它的 x 值数组,就像我对 scipy 所做的那样。我该怎么做?

【问题讨论】:

    标签: python scipy sympy


    【解决方案1】:

    首先,目前 SymPy 不保证支持 numpy 数组,这是您在这种情况下想要的。检查此错误报告http://code.google.com/p/sympy/issues/detail?id=537

    其次,如果您想对 many 值进行数值评估,SymPy 不是最佳选择(毕竟它是一个符号库)。使用 numpy 和 scipy。

    但是,以数字方式评估某事物的一个正当理由是,导出要评估的表达式很困难,因此您在 SymPy 中导出它,然后在 NumPy/SciPy/C/Fortran 中对其进行评估。要将表达式转换为 numpy,只需使用

    from sympy.utilities.lambdify import lambdify
    func = lambdify(x, big_expression_containing_x,'numpy') # returns a numpy-ready function
    numpy_array_of_results = func(numpy_array_of_arguments)
    

    查看 lambdify 的文档字符串以获取更多详细信息。请注意,lambdify 仍有一些问题,可能需要重写。

    顺便说一句,如果您想多次评估表达式really,您可以使用 sympy 中的 codegen/autowrap 模块来创建包装好的 fortran 或 C 代码可从 python 调用。

    编辑:可以在 wiki https://github.com/sympy/sympy/wiki/Philosophy-of-Numerics-and-Code-Generation-in-SymPy 上找到在 SymPy 中执行数字的方法的更新列表

    【讨论】:

      【解决方案2】:

      虽然the accepted answer 明确表示 OP 正在寻找 numerical 评估,但我仍然要指出,也可以使用 @987654322 进行 symbolic 评估@:

      import sympy
      xs = sympy.symarray('x', 10)
      f = lambda x: x**2
      f(xs)
      

      产量

      array([x_0**2, x_1**2, x_2**2, x_3**2, x_4**2, x_5**2, x_6**2, x_7**2,
             x_8**2, x_9**2], dtype=object)
      

      请注意,这在内部也使用了numpy 数组,但其中填充了sympy.Expressions。

      【讨论】:

      • 但是 symarray 并没有为每个 x_i 赋予一个数值,那么你将如何评估问题中指定的 arange 的表达式?
      • @fccoelho 我会使用 numpy 开始,或者至少从接受的答案中使用lambdify。但是如果由于某种原因你真的有一个符号表达式数组,你可能不得不使用列表推导(或for 循环)。也许有更简单的方法,但我从不为symarrays 烦恼。我的回答真的只是在这里作为旁注
      【解决方案3】:

      或者你可以通过 numpy.vectorize 来实现。 我正在使用问题正文中的xgxvals

      scalar_func = lambda xx: float(g.evalf(subs={x: xx}))
      vector_func = numpy.vectorize(scalar_func)
      vector_func(xvals) # returns a numpy array [10000.0, 9980.01, 9960.04, ...]
      

      【讨论】:

        【解决方案4】:

        试试

        import sympy
        x = sympy.symbols('x')
        f = lambda x: x**2
        print [f(k) for k in range(4)]
        

        或者你也可以试试

        g = x**2
        print [g.subs(x,k) for k in range(4)]
        

        【讨论】:

        • 您的第一个示例没有以任何方式使用 sympy。您定义的符号不会在 lambda 中访问。此外,问题是关于 numpy 数组以及 numpy 支持的所有特殊的每元素操作。这些不是 python 列表中存在的功能(您实际使用的功能)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-05
        • 1970-01-01
        相关资源
        最近更新 更多