自动换行模块#

autowrap模块与 张量 . 下面是一个简单的例子,演示如何设置一个计算矩阵向量积的二进制例程。

>>> from sympy.utilities.autowrap import autowrap
>>> from sympy import symbols, IndexedBase, Idx, Eq
>>> A, x, y = map(IndexedBase, ['A', 'x', 'y'])
>>> m, n = symbols('m n', integer=True)
>>> i = Idx('i', m)
>>> j = Idx('j', n)
>>> instruction = Eq(y[i], A[i, j]*x[j]); instruction
Eq(y[i], A[i, j]*x[j])

因为代码打印机将具有重复索引的索引对象视为求和,所以上面的等式实例将被转换为矩阵向量积的低级代码。下面是告诉SymPy生成代码、编译代码并将其包装为python函数的方式:

>>> matvec = autowrap(instruction)                 

就这样。现在让我们用一些numpy数组来测试它。默认的包装器后端是f2py。它提供的包装器函数被设置为接受python列表,它将静默地将其转换为numpy数组。所以我们可以这样测试矩阵向量积:

>>> M = [[0, 1],
...      [1, 0]]
>>> matvec(M, [2, 3])                              
[ 3.  2.]

实施细节#

autowrap模块由CodeWrapper对象组成的后端实现。基类 CodeWrapper 处理有关模块名、文件名和选项的详细信息。它还包含驱动程序例程,它以正确的顺序运行所有步骤,还负责设置和删除临时工作目录。

实际的编译和包装是由外部资源完成的,比如系统安装的f2py命令。Cython后端在子进程中运行distutils安装脚本。CodeWrapper的子类处理这些依赖于后端的细节。

API引用#

用于编译codegen输出的模块,并包装二进制文件以在python中使用。

备注

要使用自动换行模块,必须首先导入它

>>> from sympy.utilities.autowrap import autowrap

This module provides a common interface for different external backends, such as f2py, fwrap, Cython, SWIG(?) etc. (Currently only f2py and Cython are implemented) The goal is to provide access to compiled binaries of acceptable performance with a one-button user interface, e.g.,

>>> from sympy.abc import x,y
>>> expr = (x - y)**25
>>> flat = expr.expand()
>>> binary_callable = autowrap(flat)
>>> binary_callable(2, 3)
-1.0

Although a SymPy user might primarily be interested in working with mathematical expressions and not in the details of wrapping tools needed to evaluate such expressions efficiently in numerical form, the user cannot do so without some understanding of the limits in the target language. For example, the expanded expression contains large coefficients which result in loss of precision when computing the expression:

>>> binary_callable(3, 2)
0.0
>>> binary_callable(4, 5), binary_callable(5, 4)
(-22925376.0, 25165824.0)

Wrapping the unexpanded expression gives the expected behavior:

>>> e = autowrap(expr)
>>> e(4, 5), e(5, 4)
(-1.0, 1.0)

The callable returned from autowrap() is a binary Python function, not a SymPy object. If it is desired to use the compiled function in symbolic expressions, it is better to use binary_function() which returns a SymPy Function object. The binary callable is attached as the _imp_ attribute and invoked when a numerical evaluation is requested with evalf(), or with lambdify().

>>> from sympy.utilities.autowrap import binary_function
>>> f = binary_function('f', expr)
>>> 2*f(x, y) + y
y + 2*f(x, y)
>>> (2*f(x, y) + y).evalf(2, subs={x: 1, y:2})
0.e-110

这个什么时候有用?

  1. 对于大型数组上的计算,Python迭代可能太慢,并且根据数学表达式,很难利用NumPy提供的高级索引操作。

  2. 为了 真正地 如果要重复调用长表达式,则编译的二进制文件应比SymPy的.evalf()快得多

  3. If you are generating code with the codegen utility in order to use it in another project, the automatic Python wrappers let you test the binaries immediately from within SymPy.

  4. 创建用于numpy数组的自定义ufunc。看到了吗 乌芬奇 .

什么时候这个模块不是最好的方法?

  1. 如果您真的关心速度或内存优化,那么直接使用包装器工具和低级代码可能会获得更好的结果。但是,这个实用程序生成的文件可以提供有用的起点和参考代码。如果您提供关键字tempdir=“path/to/files/”,则临时文件将保持原样。

  2. If the array computation can be handled easily by numpy, and you do not need the binaries for another project.

class sympy.utilities.autowrap.CodeWrapper(generator, filepath=None, flags=[], verbose=False)[源代码]#

代码包装器的基类

class sympy.utilities.autowrap.CythonCodeWrapper(*args, **kwargs)[源代码]#

使用Cython的包装

dump_pyx(routines, f, prefix)[源代码]#

Write a Cython file with Python wrappers

此文件包含c代码中所有例程的定义,并引用头文件。

争论

日常工作

例程实例列表

F

要将文件写入的类似文件的对象

前缀

文件名前缀,用于引用正确的头文件。只使用前缀的基名称。

class sympy.utilities.autowrap.DummyWrapper(generator, filepath=None, flags=[], verbose=False)[源代码]#

用于测试独立于后端的类

class sympy.utilities.autowrap.F2PyCodeWrapper(*args, **kwargs)[源代码]#

使用f2py的包装

class sympy.utilities.autowrap.UfuncifyCodeWrapper(*args, **kwargs)[源代码]#

Ufuncify包装

dump_c(routines, f, prefix, funcname=None)[源代码]#

Write a C file with Python wrappers

这个文件包含c代码中所有例程的定义。

争论

日常工作

例程实例列表

F

要将文件写入的类似文件的对象

前缀

文件名前缀,用于命名导入的模块。

函数名

要返回的主函数的名称。

sympy.utilities.autowrap.autowrap(expr, language=None, backend='f2py', tempdir=None, args=None, flags=None, verbose=False, helpers=None, code_gen=None, **kwargs)[源代码]#

Generates Python callable binaries based on the math expression.

参数:

expr

应包装为二进制例程的SymPy表达式。

语言 :字符串,可选

If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If None [default], the language is inferred based upon the specified backend.

后端 :字符串,可选

后端用于包装生成的代码。要么是“f2py” [违约] 或者叫“赛顿”。

临时目录 :字符串,可选

临时文件的目录路径。如果提供了此参数,则生成的代码和包装器输入文件在指定的路径中保持不变。

args :iterable,可选

一组有序的符号。指定函数的参数序列。

旗帜 :iterable,可选

将传递到后端的其他选项标志。

冗长的 :bool,可选

如果为True,则自动换行不会使命令行后端静音。这有助于调试。

帮手 :3元组或3元组的iterable,可选

用于定义主表达式所需的辅助表达式。如果主表达式需要调用专用函数,则应通过 helpers . Autowrap将确保编译后的主表达式可以链接到helper例程。项应该是带有(<functionuname>,<sympyuexpression>,<argument tuple>)的3元组。必须向helper例程提供参数序列。

code_gen :CodeGen实例

CodeGen子类的实例。覆盖 language .

include_dirs : [一串]

一个目录,用于搜索C/C++头文件(以UNIX形式查找可移植性)。

library_dirs : [一串]

在链接时搜索C/C++库的目录列表。

类库 : [一串]

要链接的库名称(不是文件名或路径)的列表。

extra_compile_args : [一串]

在“sources”中编译源文件时要使用的任何额外的平台和编译器特定信息。对于“命令行”有意义的平台和编译器,这通常是命令行参数的列表,但对于其他平台,则可以是任何内容。

extra_link_args : [一串]

将对象文件链接到一起以创建扩展(或创建新的静态Python解释器)时要使用的任何额外的平台和编译器特定信息。类似于“extra_compile_args”的解释。

实例

>>> from sympy.abc import x, y, z
>>> from sympy.utilities.autowrap import autowrap
>>> expr = ((x - y + z)**(13)).expand()
>>> binary_func = autowrap(expr)
>>> binary_func(1, 4, 2)
-1.0
sympy.utilities.autowrap.binary_function(symfunc, expr, **kwargs)[源代码]#

Returns a SymPy function with expr as binary implementation

这是一个方便的函数,它可以自动包装SymPy表达式并使用已实现的_function()将其附加到函数对象所需的步骤。

参数:

symfunc : SymPy Function

要将可调用对象绑定到的函数。

expr : SymPy Expression

用于生成函数的表达式。

关键字参数 :dict命令

autowrap接受的任何kwargs。

实例

>>> from sympy.abc import x, y
>>> from sympy.utilities.autowrap import binary_function
>>> expr = ((x - y)**(25)).expand()
>>> f = binary_function('f', expr)
>>> type(f)
<class 'sympy.core.function.UndefinedFunction'>
>>> 2*f(x, y)
2*f(x, y)
>>> f(x, y).evalf(2, subs={x: 1, y: 2})
-1.0
sympy.utilities.autowrap.ufuncify(args, expr, language=None, backend='numpy', tempdir=None, flags=None, verbose=False, helpers=None, **kwargs)[源代码]#

生成一个支持在numpy数组上广播的二进制函数。

参数:

args :i可读取

一个符号或一系列符号。指定函数的参数序列。

expr

定义元素操作的SymPy表达式。

语言 :字符串,可选

If supplied, (options: 'C' or 'F95'), specifies the language of the generated code. If None [default], the language is inferred based upon the specified backend.

后端 :字符串,可选

后端用于包装生成的代码。要么是“numpy” [违约] 、'cython'或'f2py'。

临时目录 :字符串,可选

临时文件的目录路径。如果提供了此参数,则生成的代码和包装器输入文件在指定的路径中保持不变。

旗帜 :iterable,可选

将传递到后端的其他选项标志。

冗长的 :bool,可选

如果为True,则自动换行不会使命令行后端静音。这有助于调试。

帮手 :iterable,可选

用于定义主表达式所需的辅助表达式。如果主表达式需要调用专用函数,则应将其放在 helpers 很好。Autowrap将确保编译后的主表达式可以链接到helper例程。项应该是带有(<functionuname>,<sympyuexpression>,<arguments>)的元组。必须向helper例程提供参数序列。

关键字参数 :dict命令

如果 \(f2py\)\(cython\) 如果 \(numpy\) 使用后端。

笔记

默认后端(“numpy”)将创建 numpy.ufunc . 这些支持n维广播和隐式类型转换。使用其他后端将产生一个“ufunc-like”函数,该函数要求所有参数使用等长度的一维数组,并且不会执行任何类型转换。

实例

>>> from sympy.utilities.autowrap import ufuncify
>>> from sympy.abc import x, y
>>> import numpy as np
>>> f = ufuncify((x, y), y + x**2)
>>> type(f)
<class 'numpy.ufunc'>
>>> f([1, 2, 3], 2)
array([  3.,   6.,  11.])
>>> f(np.arange(5), 3)
array([  3.,   4.,   7.,  12.,  19.])

对于'f2py'和'cython'后端,输入必须是等长的一维数组。“f2py”后端将执行类型转换,但如果输入不是预期的类型,则Cython后端将出错。

>>> f_fortran = ufuncify((x, y), y + x**2, backend='f2py')
>>> f_fortran(1, 2)
array([ 3.])
>>> f_fortran(np.array([1, 2, 3]), np.array([1.0, 2.0, 3.0]))
array([  2.,   6.,  12.])
>>> f_cython = ufuncify((x, y), y + x**2, backend='Cython')
>>> f_cython(1, 2)  
Traceback (most recent call last):
  ...
TypeError: Argument '_x' has incorrect type (expected numpy.ndarray, got int)
>>> f_cython(np.array([1.0]), np.array([2.0]))
array([ 3.])

工具书类