Lambdify

此模块提供了方便的函数,用于将 SymPy 表达式转换为可以用于快速计算数值的 lambda 函数。

sympy.utilities.lambdify.implemented_function(symfunc, implementation)[源代码][源代码]

将数值 implementation 添加到函数 symfunc 中。

symfunc 可以是一个 UndefinedFunction 实例,或者是一个名称字符串。在后一种情况下,我们用该名称创建一个 UndefinedFunction 实例。

请注意,这是一个快速的权宜之计,而不是创建特殊符号函数的一般方法。如果你想创建一个符号函数供SymPy的所有机制使用,你应该子类化 Function 类。

参数:
symfunc : strUndefinedFunction 实例str 或 UndefinedFunction 实例

如果 str,则使用此名称创建新的 UndefinedFunction。如果 symfunc 是一个未定义的函数,则创建一个具有相同名称并附加了实现函数的新函数。

实现可调用

通过 evalf()lambdify 调用的数值实现

返回:
afuncsympy.FunctionClass 实例

带有附加实现的函数

示例

>>> from sympy.abc import x
>>> from sympy.utilities.lambdify import implemented_function
>>> from sympy import lambdify
>>> f = implemented_function('f', lambda x: x+1)
>>> lam_f = lambdify(x, f(x))
>>> lam_f(4)
5
sympy.utilities.lambdify.lambdastr(args, expr, printer=None, dummify=None)[源代码][源代码]

返回一个可以被评估为 lambda 函数的字符串。

示例

>>> from sympy.abc import x, y, z
>>> from sympy.utilities.lambdify import lambdastr
>>> lambdastr(x, x**2)
'lambda x: (x**2)'
>>> lambdastr((x,y,z), [z,y,x])
'lambda x,y,z: ([z, y, x])'

虽然元组可能不会作为参数出现在 Python 3 的 lambda 中,但 lambdastr 将创建一个 lambda 函数,该函数将解包原始参数,以便可以处理嵌套参数:

>>> lambdastr((x, (y, z)), x + y)
'lambda _0,_1: (lambda x,y,z: (x + y))(_0,_1[0],_1[1])'
sympy.utilities.lambdify.lambdify(
args,
expr,
modules=None,
printer=None,
use_imps=True,
dummify=False,
cse=False,
docstring_limit=1000,
)[源代码][源代码]

将 SymPy 表达式转换为一个允许快速数值评估的函数。

警告

此函数使用 exec,因此不应在未经净化的输入上使用。

自 1.7 版本弃用: 传递一个集合给 args 参数已被弃用,因为集合是无序的。请使用有序的可迭代对象,如列表或元组。

参数:
参数列表[符号]

一个变量或变量列表,其嵌套结构表示将传递给函数的参数的嵌套结构。

变量可以是符号、未定义的函数或矩阵符号。

>>> from sympy import Eq
>>> from sympy.abc import x, y, z

变量列表应与传递给函数的参数结构相匹配。只需将参数按传递时的顺序放入列表中。

要调用像 f(x) 这样的函数,那么 [x] 应该是 lambdify 的第一个参数;在这种情况下,也可以使用单个 x

>>> f = lambdify(x, x + 1)
>>> f(1)
2
>>> f = lambdify([x], x + 1)
>>> f(1)
2

要调用一个像 f(x, y) 这样的函数,那么 [x, y] 将是 lambdify 的第一个参数:

>>> f = lambdify([x, y], x + y)
>>> f(1, 1)
2

要调用一个带有单个3元素元组的函数,如 f((x, y, z)),那么 [(x, y, z)] 将是 lambdify 的第一个参数:

>>> f = lambdify([(x, y, z)], Eq(z**2, x**2 + y**2))
>>> f((3, 4, 5))
True

如果传递两个参数,第一个是标量而第二个是包含两个参数的元组,那么列表中的项目应匹配该结构:

>>> f = lambdify([x, (y, z)], x + y + z)
>>> f(1, (2, 3))
6
表达式表达式

要计算的表达式、表达式列表或矩阵。

列表可以嵌套。如果表达式是一个列表,输出也将是一个列表。

>>> f = lambdify(x, [x, [x + 1, x + 2]])
>>> f(1)
[1, [2, 3]]

如果是矩阵,将返回一个数组(针对NumPy模块)。

>>> from sympy import Matrix
>>> f = lambdify(x, Matrix([x, x + 1]))
>>> f(1)
[[1]
[2]]

注意这里的参数顺序(变量然后表达式)是用来模拟Python的``lambda``关键字。``lambdify(x, expr)``的工作方式(大致上)类似于``lambda x: expr``(参见下面的 示例)。

模块str, 可选

指定要使用的数值库。

如果未指定,modules 默认为:

  • ["scipy", "numpy"] 如果安装了 SciPy

  • ["numpy"] 如果只安装了 NumPy

  • ["math", "mpmath", "sympy"] 如果两者都未安装。

也就是说,如果可能的话,SymPy 函数会被替换为 scipynumpy 函数(如果可用),否则会使用 Python 标准库中的 mathmpmath 函数。

modules 可以是以下类型之一:

  • 字符串 "math", "mpmath", "numpy", "numexpr", "scipy", "sympy", 或 "tensorflow""jax"。这使用相应模块的打印机和命名空间映射。

  • 一个模块(例如,math)。这使用模块的全局命名空间。如果该模块是上述已知模块之一,它还将使用相应的打印机和命名空间映射(即,modules=numpy 等同于 modules="numpy")。

  • 一个将 SymPy 函数名称映射到任意函数(例如,{'sin': custom_sin})的字典。

  • 一个包含上述参数混合的列表,优先级较高的条目出现在前面(例如,要使用 NumPy 模块但用自定义版本覆盖 sin 函数,可以使用 [{'sin': custom_sin}, 'numpy'])。

dummifybool, 可选

提供的表达式中是否将不是有效 Python 标识符的变量替换为虚拟符号。

这允许像 Function('f')(t) 这样的未定义函数作为参数提供。默认情况下,变量仅在它们不是有效的 Python 标识符时才会被虚拟化。

设置 dummify=True 以用虚拟符号替换所有参数(如果 args 不是字符串) - 例如,以确保参数不会重新定义任何内置名称。

csebool, 或可调用对象, 可选

当识别并预先计算公共子表达式时,可以更有效地计算大型表达式,这些子表达式在多次使用之前被预先计算。然而,查找这些子表达式会使 ‘lambdify’ 函数的创建变慢。

True 时,使用 sympy.simplify.cse ,否则(默认)用户可以传递一个匹配 cse 签名的函数。

docstring_limit整数或无

在lambdify化大型表达式时,lambdify 内部花费的时间中,有很大一部分用于生成表达式的字符串表示,以便用于返回函数的自动生成文档字符串中。对于包含数百个或更多节点的表达式,生成的文档字符串通常会变得非常长且密集,难以阅读。为了减少lambdify的运行时间,可以禁用文档字符串中完整表达式的渲染。

None 时,完整的表达式会在文档字符串中呈现。当 0 或负 int 时,省略号会在文档字符串中代替表达式呈现。当严格为正的 int 时,如果表达式中的节点数超过 docstring_limit ,省略号会在文档字符串中呈现,否则表达式的字符串表示会正常呈现。默认值为 1000

注释

  • 对于涉及大型数组计算的函数,numexpr 可以比 numpy 提供显著的加速。请注意,numexpr 可用的函数比 numpy 更有限,但可以通过 implemented_function 和用户定义的 Function 子类来扩展。如果指定,numexpr 可能是模块中的唯一选项。numexpr 函数的官方列表可以在以下网址找到:https://numexpr.readthedocs.io/en/latest/user_guide.html#supported-functions

  • 在上面的例子中,生成的函数可以接受标量值或 numpy 数组作为参数。然而,在某些情况下,生成的函数依赖于输入是一个 numpy 数组:

    >>> import numpy
    >>> from sympy import Piecewise
    >>> from sympy.testing.pytest import ignore_warnings
    >>> f = lambdify(x, Piecewise((x, x <= 1), (1/x, x > 1)), "numpy")
    
    >>> with ignore_warnings(RuntimeWarning):
    ...     f(numpy.array([-1, 0, 1, 2]))
    [-1.   0.   1.   0.5]
    
    >>> f(0)
    Traceback (most recent call last):
        ...
    ZeroDivisionError: division by zero
    

    在这种情况下,输入应包装在一个numpy数组中:

    >>> with ignore_warnings(RuntimeWarning):
    ...     float(f(numpy.array([0])))
    0.0
    

    或者,如果不需要 numpy 功能,可以使用另一个模块:

    >>> f = lambdify(x, Piecewise((x, x <= 1), (1/x, x > 1)), "math")
    >>> f(0)
    0
    

示例

>>> from sympy.utilities.lambdify import implemented_function
>>> from sympy import sqrt, sin, Matrix
>>> from sympy import Function
>>> from sympy.abc import w, x, y, z
>>> f = lambdify(x, x**2)
>>> f(2)
4
>>> f = lambdify((x, y, z), [z, y, x])
>>> f(1,2,3)
[3, 2, 1]
>>> f = lambdify(x, sqrt(x))
>>> f(4)
2.0
>>> f = lambdify((x, y), sin(x*y)**2)
>>> f(0, 5)
0.0
>>> row = lambdify((x, y), Matrix((x, x + y)).T, modules='sympy')
>>> row(1, 2)
Matrix([[1, 3]])

lambdify 可以用来将 SymPy 表达式转换为 mpmath 函数。在某些情况下,这可能比使用 ``evalf``(它在后台使用 mpmath)更可取。

>>> f = lambdify(x, sin(x), 'mpmath')
>>> f(1)
0.8414709848078965

元组参数被处理,并且 lambdified 函数应以创建函数时使用的相同类型的参数调用:

>>> f = lambdify((x, (y, z)), x + y)
>>> f(1, (2, 4))
3

flatten 函数可以用于始终处理扁平化的参数:

>>> from sympy.utilities.iterables import flatten
>>> args = w, (x, (y, z))
>>> vals = 1, (2, (3, 4))
>>> f = lambdify(flatten(args), w + x + y + z)
>>> f(*flatten(vals))
10

expr 中的函数也可以携带自己的数值实现,这些实现通过附加到 _imp_ 属性的可调用对象来实现。这可以通过使用 implemented_function 工厂与未定义的函数一起使用:

>>> f = implemented_function(Function('f'), lambda x: x+1)
>>> func = lambdify(x, f(x))
>>> func(4)
5

lambdify 总是优先使用 _imp_ 实现,而不是其他命名空间中的实现,除非 use_imps 输入参数为 False。

使用 Tensorflow:

>>> import tensorflow as tf
>>> from sympy import Max, sin, lambdify
>>> from sympy.abc import x
>>> f = Max(x, sin(x))
>>> func = lambdify(x, f, 'tensorflow')

在 TensorFlow v2 之后,默认启用即时执行。如果你想在本教程中获得与 TensorFlow v1 和 v2 兼容的结果,请运行此行。

>>> tf.compat.v1.enable_eager_execution()

如果你启用了eager执行,你可以立即得到结果,就像你可以使用numpy一样。

如果你传递 TensorFlow 对象,你可能会得到一个 EagerTensor 对象而不是值。

>>> result = func(tf.constant(1.0))
>>> print(result)
tf.Tensor(1.0, shape=(), dtype=float32)
>>> print(result.__class__)
<class 'tensorflow.python.framework.ops.EagerTensor'>

你可以使用 .numpy() 来获取张量的 numpy 值。

>>> result.numpy()
1.0
>>> var = tf.Variable(2.0)
>>> result = func(var) # also works for tf.Variable and tf.Placeholder
>>> result.numpy()
2.0

并且它适用于任何形状的数组。

>>> tensor = tf.constant([[1.0, 2.0], [3.0, 4.0]])
>>> result = func(tensor)
>>> result.numpy()
[[1. 2.]
 [3. 4.]]