SymPy-1-13-中文文档-四十三-

44 阅读1小时+

SymPy 1.13 中文文档(四十三)

原文:docs.sympy.org/latest/index.html

工具

原文:docs.sympy.org/latest/modules/utilities/index.html

该模块包含一些跨 SymPy 使用的通用工具。

内容:

  • 自动包装模块

  • 代码生成

  • 装饰器

  • 枚举

  • 异常和警告

  • 可迭代对象

  • Lambda 化

  • 记忆化

  • 杂项

  • 源代码检查

  • 时间工具

Autowrap 模块

原文链接:docs.sympy.org/latest/modules/utilities/autowrap.html

autowrap 模块与 Tensor 的 Indexed 类协同工作非常出色。以下是一个简单的示例,展示如何设置计算矩阵-向量乘积的二进制例程。

>>> 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]) 

因为代码打印程序将具有重复索引的 Indexed 对象视为求和,上述相等实例将转换为矩阵向量乘积的低级代码。这是告诉 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 使用的模块。

注意

要使用 autowrap 模块,必须先导入它。

>>> from sympy.utilities.autowrap import autowrap 

该模块为不同的外部后端(如 f2py、fwrap、Cython、SWIG(?) 等)提供了一个通用接口。(目前仅实现了 f2py 和 Cython)目标是通过单按钮用户界面提供性能可接受的编译二进制访问。

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

尽管 SymPy 用户主要关注与数学表达式的工作,而不是在数值形式下有效评估这些表达式所需的封装工具的细节,但用户在没有对目标语言的限制有一定理解的情况下无法实现。例如,扩展表达式包含大系数,计算该表达式时会导致精度损失:

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

封装未扩展的表达式会产生预期的行为:

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

autowrap() 返回的可调用对象是一个二进制的 Python 函数,而不是 SymPy 对象。如果希望在符号表达式中使用编译后的函数,最好使用 binary_function(),它返回一个 SymPy 函数对象。二进制可调用对象附加在 _imp_ 属性上,当使用 evalf()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. 如果您正在使用 codegen 实用程序生成代码以在另一个项目中使用它,则自动的 Python 包装器可以让您立即从 SymPy 内部测试二进制文件。
  4. 为了创建用于 numpy 数组的定制 ufuncs。参见ufuncify

何时此模块不是最佳方法?

  1. 如果您真的关心速度或内存优化,可能直接使用包装工具和低级代码会有更好的效果。但是,此实用程序生成的文件可能提供一个有用的起点和参考代码。如果提供了关键字 tempdir="path/to/files/",则临时文件将保持不变。
  2. 如果数组计算可以很容易地由 numpy 处理,并且您不需要为另一个项目的二进制文件。
class sympy.utilities.autowrap.CodeWrapper(generator, filepath=None, flags=[], verbose=False)

用于代码包装器的基类

class sympy.utilities.autowrap.CythonCodeWrapper(*args, **kwargs)

使用 Cython 的包装器

dump_pyx(routines, f, prefix)

编写一个带有 Python 包装的 Cython 文件

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

参数

routines

例程列表

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)

编写一个带有 Python 包装的 C 文件

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

参数

routines

例程列表

f

要写入文件的类文件对象

前缀

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

funcname

要返回的主函数的名称。

sympy.utilities.autowrap.autowrap(expr, language=None, backend='f2py', tempdir=None, args=None, flags=None, verbose=False, helpers=None, code_gen=None, **kwargs)

基于数学表达式生成 Python 可调用二进制文件。

参数:

expr

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

language:字符串,可选的

如果提供(选项:'C'或'F95'),则指定生成代码的语言。如果None(默认),则根据指定的后端推断语言。

backend:字符串,可选的

用于包装生成代码的后端。可以是'f2py' [默认]或'cython'。

tempdir:字符串,可选的

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

args:可迭代的,可选的

有序的符号可迭代对象。指定函数的参数序列。

flags:可迭代的,可选的

附加选项标志,将传递给后端。

verbose:布尔值,可选的

如果为 True,则 autowrap 将不会静音命令行后端。这对于调试可能很有帮助。

helpers:3 元组或 3 元组的可迭代对象,可选的

用于定义主表达式所需的辅助表达式。如果主表达式需要调用特殊函数,则应通过helpers传递。Autowrap 然后确保编译的主表达式可以链接到辅助例程。项目应该是 3 元组(<function_name>,<sympy_expression>,<argument_tuple>)。必须向辅助例程提供参数序列。

code_gen:CodeGen 实例

CodeGen 子类的实例。覆盖language

include_dirs:[字符串]

用于搜索 C/C++头文件的目录列表(以 Unix 格式以保证可移植性)。

library_dirs:[字符串]

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

libraries:[字符串]

一个库名称列表(不是文件名或路径),用于链接。

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)

返回具有 expr 作为二进制实现的 SymPy 函数。

这是一个便利函数,自动完成将 SymPy 表达式包装到 Function 对象中并用 implemented_function()实现的步骤。

参数:

symfunc:SymPy 函数

绑定可调用对象的函数。

expr:SymPy 表达式

用于生成函数的表达式。

kwargs:字典

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:可迭代

符号或符号的可迭代。指定函数的参数序列。

expr

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

language:字符串,可选的

如果提供(选项:'C'或'F95'),则指定生成代码的语言。如果为None[默认],则根据指定的后端推断语言。

backend:字符串,可选的

用于包装生成的代码的后端。要么是'numpy' [默认],'cython'或'f2py'。

tempdir:字符串,可选的

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

flags:可迭代的,可选的

将传递给后端的额外选项标志。

verbose:布尔值,可选的

如果为 True,autowrap 将不会将命令行后端静音。这对于调试很有帮助。

helpers:可迭代的,可选的

用于定义主表达式所需的辅助表达式。如果主表达式需要调用特定函数,则应将其放入helpers可迭代对象中。Autowrap 将确保编译的主表达式可以链接到辅助例程。项目应为元组(<函数名>,<sympy 表达式>,<参数>)。向辅助例程提供参数序列是强制性的。

kwargs:dict

如果使用‘f2py’或‘cython’后端,这些 kwargs 将传递给 autowrap,并且如果使用‘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.]) 

参考

[R1052]

numpy.org/doc/stable/reference/ufuncs.html

Codegen

原文链接:docs.sympy.org/latest/modules/utilities/codegen.html

此模块提供功能,可以从 SymPy 表达式直接生成可编译的代码。codegen函数是 SymPy 中代码生成功能的用户界面。以下是实现的一些细节,供希望直接使用该框架的高级用户参考。

注意

codegen可调用项不会自动位于 sympy 命名空间中,要使用它,您必须先执行

>>> from sympy.utilities.codegen import codegen 

实现细节

在此,我们介绍了内部结构的最重要部分,因为高级用户可能希望直接使用它,例如通过为专业应用程序的代码生成器创建子类。很可能您更喜欢使用上面记录的 codegen()函数。

基本假设:

  • 通用的 Routine 数据结构描述了必须转换为 C/Fortran/...代码的例程。此数据结构涵盖了一个或多个支持语言中存在的所有特性。

  • CodeGen 类的后代将多个 Routine 实例转换为可编译的代码。每个派生类将其转换为特定语言。

  • 在许多情况下,人们希望有一个简单的工作流程。最后部分的友好功能是 Routine/CodeGen 的简单 API。它们使用起来更简单,但功能较弱。

Routine

Routine类是 codegen 模块非常重要的一部分。将 codegen 实用程序视为将数学表达式转换为编程语言中的一组语句的翻译器,Routine实例负责提取和存储关于如何将数学内容封装为函数调用的信息。因此,是Routine构造函数决定例程将需要什么参数,以及是否应该有返回值。

API 参考

用于生成评估 SymPy 表达式的 C、C++、Fortran77、Fortran90、Julia、Rust 和 Octave/Matlab 例程的模块。该模块正在开发中。下面列表中带有‘+’字符的里程碑已经完成。

— sympy.utilities.codegen 与 sympy.printing.ccode 有何不同?—

我们考虑了扩展 SymPy 函数的打印例程的想法,使其打印完整的可编译代码,但这导致了一些无法克服的问题,只能用专用代码生成器来解决:

  • 对于 C 语言,需要同时有代码文件和头文件,而打印例程只生成一个字符串。这个代码生成器可以扩展为支持.pyf 文件用于 f2py。

  • SymPy 函数不涉及编程技术问题,如输入、输出和输入-输出参数。其他示例是连续或非连续的数组,包括其他库的头文件,如 gsl 或其他库。

  • 在一个 C 例程中评估多个 SymPy 函数非常有趣,最终可以借助 cse 例程共享共同的中间结果。这不仅仅是打印。

  • 从编程角度来看,应尽可能在代码生成器中评估带有常量的表达式。这在打印时是不同的。

— 基本假设 —

  • 通用的 Routine 数据结构描述了必须转换为 C/Fortran/… 代码的例程。此数据结构涵盖了所有支持语言中的一个或多个特性。

  • 派生自 CodeGen 类的后代将多个 Routine 实例转换为可编译代码。每个派生类都会翻译成特定语言。

  • 在许多情况下,人们希望有一个简单的工作流程。最后部分的友好函数是 Routine/CodeGen 系统之上的简单 API。它们更易于使用,但功能较弱。

— 里程碑 —

  • 第一个工作版本使用标量输入参数,生成 C 代码和测试。

  • 友好函数,比严格的 Routine/CodeGen 工作流程更易于使用。

  • 整数和实数作为输入和输出

  • 输出参数

  • 输入输出参数

  • 适当排序输入/输出参数

  • 连续数组参数(numpy 矩阵)

  • 同时生成 .pyf 代码以供 f2py 使用(在 autowrap 模块中)

  • 孤立常量并在双精度中预先评估它们

  • Fortran 90

  • Octave/Matlab

  • 公共子表达式消除

  • 在生成的代码中用户定义的注释

  • 可选的额外包含用于评估特殊函数的库/对象的行

  • 测试其他 C 编译器和库:gcc、tcc、libtcc、gcc+gsl 等

  • 连续数组参数(SymPy 矩阵)

  • 非连续数组参数(SymPy 矩阵)

  • ccode 在遇到无法转换为 C 代码的情况时必须引发错误。ccode(integrate(sin(x)/x, x)) 没有意义。

  • 复数作为输入和输出

  • 默认的复杂数据类型

  • 在头文件中包含额外信息:日期、用户、主机名、sha1 哈希等

  • Fortran 77

  • C++

  • Python

  • Julia

  • Rust

class sympy.utilities.codegen.Argument(name, datatype=None, dimensions=None, precision=None)

抽象的 Argument 数据结构:名称和数据类型。

此结构在下面的后代中得到细化。

class sympy.utilities.codegen.CCodeGen(project='project', printer=None, preprocessor_statements=None, cse=False)

C 代码生成器。

.write() 方法从 CodeGen 继承,将输出一个代码文件和一个接口文件,分别为 <prefix>.c<prefix>.h

dump_c(routines, f, prefix, header=True, empty=True)

通过调用特定于语言的方法编写代码。

生成的文件包含低级代码中所有例程的定义,并在适当时引用头文件。

参数:

routines : 列表

一个 Routine 实例列表。

f : 类文件对象

文件写入位置。

prefix : 字符串

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

header : 布尔型,可选

当为 True 时,将在每个源文件顶部包含一个头注释。[默认值:True]

empty : 布尔型,可选

当为 True 时,包括空行以结构化源文件。[默认值:True]

dump_h(routines, f, prefix, header=True, empty=True)

写入 C 头文件。

此文件包含所有函数声明。

参数:

routines:列表

一组 Routine 实例。

f:类似文件的

写入文件的位置。

prefix:字符串

文件名前缀,用于构建包含保护。仅使用前缀的基本名称。

header:布尔值,可选

当为 True 时,在每个源文件顶部包括头部注释。[默认:True]

empty:布尔值,可选

当为 True 时,包括空行以结构化源文件。[默认:True]

get_prototype(routine)

返回例程的函数原型字符串。

如果例程具有多个结果对象,则引发 CodeGenError。

参见:zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0%E5%8E%9F%E5%9E%8B

class sympy.utilities.codegen.CodeGen(project='project', cse=False)

代码生成器的抽象类。

dump_code(routines, f, prefix, header=True, empty=True)

写入代码时,请调用特定语言的方法。

生成的文件包含低级代码中所有例程的定义,并在适当时引用头文件。

参数:

routines:列表

一组 Routine 实例。

f:类似文件的

写入文件的位置。

prefix:字符串

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

header:布尔值,可选

当为 True 时,在每个源文件顶部包括头部注释。[默认:True]

empty:布尔值,可选

当为 True 时,包括空行以结构化源文件。[默认:True]

routine(name, expr, argument_sequence=None, global_vars=None)

创建适合该语言的 Routine 对象。

至少对于 C/Fortran 适用的此实现。如有必要,子类可以覆盖这一点。

在这里,我们假设最多有一个返回值(左值),它必须是标量。额外的输出是 OutputArguments(例如右手边的指针或通过引用传递)。矩阵始终通过 OutputArguments 返回。如果argument_sequence为 None,则参数将按字母顺序排序,但所有 InputArguments 首先,然后是 OutputArgument 和 InOutArguments。

write(routines, prefix, to_files=False, header=True, empty=True)

写入所有给定例程的源代码文件。

生成的源代码作为(文件名,内容)元组列表返回,或写入文件(见下文)。每个文件名由给定前缀加上适当的扩展名组成。

参数:

routines:列表

要写入的 Routine 实例列表

prefix:字符串

输出文件的前缀

to_files:布尔值,可选

当为 True 时,将输出写入文件。否则,将返回(文件名,内容)元组的列表。[默认:False]

header:布尔值,可选

当为 True 时,在每个源文件顶部包括头部注释。[默认:True]

empty:布尔值,可选

当为 True 时,包括空行以结构化源文件。[默认:True]

class sympy.utilities.codegen.DataType(cname, fname, pyname, jlname, octname, rsname)

在不同语言中为某种数据类型保存字符串。

class sympy.utilities.codegen.FCodeGen(project='project', printer=None)

生成 Fortran 95 代码的生成器

继承自 CodeGen 的.write()方法将输出一个代码文件和一个接口文件,分别为.f90 和.h。

dump_f95(routines, f, prefix, header=True, empty=True)

写入代码时,请调用特定语言的方法。

生成的文件包含低级代码中所有例程的定义,并在适当时引用头文件。

参数:

routines:列表

例程实例列表。

f:类似文件

写入文件的位置。

prefix:字符串

文件名前缀,用于引用适当的头文件。只使用前缀的基本名称。

header:布尔值,可选

当为 True 时,在每个源文件顶部包括一个头注释。[默认:True]

empty:布尔值,可选

当为 True 时,包括空行以结构化源文件。[默认:True]

dump_h(routines, f, prefix, header=True, empty=True)

写入接口到头文件。

此文件包含所有函数声明。

参数:

routines:列表

例程实例列表。

f:类似文件

写入文件的位置。

prefix:字符串

文件名前缀。

header:布尔值,可选

当为 True 时,在每个源文件顶部包括一个头注释。[默认:True]

empty:布尔值,可选

当为 True 时,包括空行以结构化源文件。[默认:True]

get_interface(routine)

返回函数接口的字符串。

例程应具有单个结果对象,可以为 None。如果例程具有多个结果对象,则会引发 CodeGenError。

参见:zh.wikipedia.org/wiki/函数原型

class sympy.utilities.codegen.JuliaCodeGen(project='project', printer=None)

Julia 代码生成器。

从 CodeGen 继承的.write()方法将输出一个代码文件 .jl。

dump_jl(routines, f, prefix, header=True, empty=True)

通过调用特定于语言的方法编写代码。

生成的文件包含低级代码中所有例程的定义,并在适当时引用头文件。

参数:

routines:列表

例程实例列表。

f:类似文件

写入文件的位置。

prefix:字符串

文件名前缀,用于引用适当的头文件。只使用前缀的基本名称。

header:布尔值,可选

当为 True 时,在每个源文件顶部包括一个头注释。[默认:True]

empty:布尔值,可选

当为 True 时,包括空行以结构化源文件。[默认:True]

routine(name, expr, argument_sequence, global_vars)

Julia 专用例程创建。

class sympy.utilities.codegen.OctaveCodeGen(project='project', printer=None)

Octave 代码生成器。

从 CodeGen 继承的.write()方法将输出一个代码文件 .m。

Octave .m 文件通常只包含一个函数。该函数名称应与文件名(prefix)匹配。如果传递多个name_expr对,则后面的被假定为由主函数访问的私有函数。

你应该只将输入传递给argument_sequence:输出按照它们在name_expr中的顺序排序。

dump_m(routines, f, prefix, header=True, empty=True, inline=True)

通过调用特定于语言的方法编写代码。

生成的文件包含低级代码中所有例程的定义,并在适当时引用头文件。

参数:

routines:列表

例程实例列表。

f:类似文件

写入文件的位置。

prefix:字符串

文件名前缀,用于引用适当的头文件。只使用前缀的基本名称。

header:布尔值,可选

当设置为 True 时,在每个源文件的顶部包含一个头部注释。[默认值:True]

empty:布尔值,可选

当设置为 True 时,包括空行以结构化源文件。[默认值:True]

routine(name, expr, argument_sequence, global_vars)

为 Octave 创建专用的例程。

class sympy.utilities.codegen.OutputArgument(name, result_var, expr, datatype=None, dimensions=None, precision=None)

OutputArgument 在例程中始终被初始化。

class sympy.utilities.codegen.Result(expr, name=None, result_var=None, datatype=None, dimensions=None, precision=None)

返回值的表达式。

在 Python 语言中,名称“result”用于避免与保留字“return”发生冲突。它也比“ReturnValue”更短。

在目标中可能需要这些名称(例如,“return(x*y)”可能会返回一个值,但从未命名它)。

class sympy.utilities.codegen.Routine(name, arguments, results, local_vars, global_vars)

对一组表达式进行评估例程的通用描述。

CodeGen 类可以将此类的实例转换为特定语言的代码。例程规范涵盖了这些语言中所有存在的特性。CodeGen 部分在目标语言中缺少某些特性时必须引发异常。例如,Python 中可能存在多个返回值,但 C 或 Fortran 中不存在。另一个例子是 Fortran 和 Python 支持复数,而 C 不支持。

property result_variables

返回 OutputArgument、InOutArgument 和 Result 的列表。

如果存在返回值,则它们位于列表的末尾。

property variables

返回可能在例程中使用的所有变量的集合。

对于具有无名称返回值的例程,可能或可能不会使用的虚拟变量将包含在集合中。

class sympy.utilities.codegen.RustCodeGen(project='project', printer=None)

Rust 代码生成器。

从 CodeGen 继承的.write()方法将输出一个名为.rs 的代码文件。

dump_rs(routines, f, prefix, header=True, empty=True)

通过调用特定于语言的方法编写代码。

生成的文件包含所有低级代码中的例程定义,并在适当时引用头文件。

参数:

例程:列表

一组例程实例的列表。

f:类似文件

写入文件的位置。

前缀:字符串

文件名前缀,用于引用适当的头文件。仅使用前缀的基本名称。

header:布尔值,可选

当设置为 True 时,在每个源文件的顶部包含一个头部注释。[默认值:True]

empty:布尔值,可选

当设置为 True 时,包括空行以结构化源文件。[默认值:True]

get_prototype(routine)

返回例程的函数原型字符串。

如果例程具有多个结果对象,则引发 CodeGenError。

参见:zh.wikipedia.org/wiki/函式原型

routine(name, expr, argument_sequence, global_vars)

为 Rust 创建专用的例程。

sympy.utilities.codegen.codegen(name_expr, language=None, prefix=None, project='project', to_files=False, header=True, empty=True, argument_sequence=None, global_vars=None, standard=None, code_gen=None, printer=None)

为给定语言中的表达式生成源代码。

参数:

name_expr:元组或元组列表

单个(名称,表达式)元组或(名称,表达式)元组列表。每个元组对应一个例程。如果表达式是等式(Equality 类的实例),则左侧被视为输出参数。如果表达式是可迭代的,则例程将具有多个输出。

language:字符串,

表示源代码语言的字符串。不区分大小写。目前支持'C'、'F95'和'Octave'。'Octave'生成与 Octave 和 Matlab 兼容的代码。

prefix:字符串,可选

文件名称的前缀,用于包含源代码的文件。语言相关的后缀将被附加。如果省略,则使用第一个 name_expr 元组的名称。

project:字符串,可选

项目名称,用于生成唯一的预处理器指令。[默认值:“project”]

to_files:布尔值,可选

当设置为 True 时,代码将被写入一个或多个具有给定前缀的文件中,否则将返回包含这些文件名称和内容的字符串。[默认值:False]

header:布尔值,可选

当设置为 True 时,在每个源文件顶部写入头文件。[默认值:True]

empty:布尔值,可选

当设置为 True 时,空行用于代码的结构化。[默认值:True]

argument_sequence:可迭代对象,可选

按照首选顺序为例程的参数序列。如果缺少必需的参数,则引发 CodeGenError。冗余的参数将不会有警告。如果省略,则参数将按字母顺序排列,但所有输入参数先排列,然后是输出或输入输出参数。

global_vars:可迭代对象,可选

例程使用的全局变量序列。此处列出的变量不会显示为函数参数。

standard:字符串,可选

code_gen:CodeGen 实例,可选

一个 CodeGen 子类的实例。覆盖language

printer:Printer 实例,可选

一个 Printer 子类的实例。

示例

>>> from sympy.utilities.codegen import codegen
>>> from sympy.abc import x, y, z
>>> [(c_name, c_code), (h_name, c_header)] = codegen(
...     ("f", x+y*z), "C89", "test", header=False, empty=False)
>>> print(c_name)
test.c
>>> print(c_code)
#include "test.h"
#include <math.h>
double f(double x, double y, double z) {
 double f_result;
 f_result = x + y*z;
 return f_result;
}

>>> print(h_name)
test.h
>>> print(c_header)
#ifndef PROJECT__TEST__H
#define PROJECT__TEST__H
double f(double x, double y, double z);
#endif 

另一个使用 Equality 对象的示例,以给出具有命名输出的例程。这里的文件名(前缀)来自第一个(name,expr)对。

>>> from sympy.abc import f, g
>>> from sympy import Eq
>>> [(c_name, c_code), (h_name, c_header)] = codegen(
...      [("myfcn", x + y), ("fcn2", [Eq(f, 2*x), Eq(g, y)])],
...      "C99", header=False, empty=False)
>>> print(c_name)
myfcn.c
>>> print(c_code)
#include "myfcn.h"
#include <math.h>
double myfcn(double x, double y) {
 double myfcn_result;
 myfcn_result = x + y;
 return myfcn_result;
}
void fcn2(double x, double y, double *f, double *g) {
 (*f) = 2*x;
 (*g) = y;
} 

如果生成的函数将成为一个更大项目的一部分,其中定义了各种全局变量,则可以使用‘global_vars’选项从函数签名中移除指定的变量。

>>> from sympy.utilities.codegen import codegen
>>> from sympy.abc import x, y, z
>>> [(f_name, f_code), header] = codegen(
...     ("f", x+y*z), "F95", header=False, empty=False,
...     argument_sequence=(x, y), global_vars=(z,))
>>> print(f_code)
REAL*8 function f(x, y)
implicit none
REAL*8, intent(in) :: x
REAL*8, intent(in) :: y
f = x + y*z
end function 
sympy.utilities.codegen.get_default_datatype(expr, complex_allowed=None)

基于表达式推导出适当的数据类型。

sympy.utilities.codegen.make_routine(name, expr, argument_sequence=None, global_vars=None, language='F95')

从表达式生成适当的 Routine 的工厂。

参数:

name:字符串

在生成的代码中此例程的名称。

expr:表达式或表达式列表/元组

Routine 实例将表示的 SymPy 表达式。如果给定一个表达式列表或元组,则认为该例程具有多个返回值和/或输出参数。

argument_sequence:列表或元组,可选

按首选顺序列出例程的列表参数。如果省略,则结果依赖于语言,例如按字母顺序或按给定表达式的相同顺序。

global_vars:可迭代对象,可选

例程使用的全局变量序列。此处列出的变量不会显示为函数参数。

language:字符串,可选

指定目标语言。例程本身应该是语言无关的,但是创建方式、错误检查等依赖于语言。[默认值:“F95”]。

注意

根据语言和具体的数学表达式,决定是使用输出参数还是返回值。对于类型为 Equality 的表达式,通常左侧会被转换为一个输出参数(或者在合适的情况下是一个 InOutArgument)。否则,通常计算后的表达式会成为例程的返回值。

示例

>>> from sympy.utilities.codegen import make_routine
>>> from sympy.abc import x, y, f, g
>>> from sympy import Eq
>>> r = make_routine('test', [Eq(f, 2*x), Eq(g, x + y)])
>>> [arg.result_var for arg in r.results]
[]
>>> [arg.name for arg in r.arguments]
[x, y, f, g]
>>> [arg.name for arg in r.result_variables]
[f, g]
>>> r.local_vars
set() 

另一个更复杂的示例,混合了指定和自动分配的名称。还具有矩阵输出。

>>> from sympy import Matrix
>>> r = make_routine('fcn', [x*y, Eq(f, 1), Eq(g, x + g), Matrix([[x, 2]])])
>>> [arg.result_var for arg in r.results]  
[result_5397460570204848505]
>>> [arg.expr for arg in r.results]
[x*y]
>>> [arg.name for arg in r.arguments]  
[x, y, f, g, out_8598435338387848786] 

我们可以更仔细地检查各种参数:

>>> from sympy.utilities.codegen import (InputArgument, OutputArgument,
...                                      InOutArgument)
>>> [a.name for a in r.arguments if isinstance(a, InputArgument)]
[x, y] 
>>> [a.name for a in r.arguments if isinstance(a, OutputArgument)]  
[f, out_8598435338387848786]
>>> [a.expr for a in r.arguments if isinstance(a, OutputArgument)]
[1, Matrix([[x, 2]])] 
>>> [a.name for a in r.arguments if isinstance(a, InOutArgument)]
[g]
>>> [a.expr for a in r.arguments if isinstance(a, InOutArgument)]
[g + x] 

装饰器

原文链接:docs.sympy.org/latest/modules/utilities/decorator.html

有用的实用装饰器。

@sympy.utilities.decorator.deprecated(message, *, deprecated_since_version, active_deprecations_target, stacklevel=3)

将函数标记为已弃用。

如果整个函数或类已被弃用,应使用此装饰器。如果只弃用了某些功能,则应直接使用warns_deprecated_sympy()。此装饰器只是一种便利。在使用此装饰器和在函数顶部调用warns_deprecated_sympy()之间没有功能上的区别。

装饰器使用与warns_deprecated_sympy()相同的参数。有关此装饰器关键字的详细信息,请参阅其文档。

有关何时以及如何在 SymPy 中弃用事物的详细信息,请参阅弃用政策文档。

示例

>>> from sympy.utilities.decorator import deprecated
>>> from sympy import simplify
>>> @deprecated("""    ... The simplify_this(expr) function is deprecated. Use simplify(expr)
... instead.""", deprecated_since_version="1.1",
... active_deprecations_target='simplify-this-deprecation')
... def simplify_this(expr):
...  """
...     Simplify ``expr``.
...
...     .. deprecated:: 1.1
...
...        The ``simplify_this`` function is deprecated. Use :func:`simplify`
...        instead. See its documentation for more information. See
...        :ref:`simplify-this-deprecation` for details.
...
...     """
...     return simplify(expr)
>>> from sympy.abc import x
>>> simplify_this(x*(x + 1) - x**2) 
<stdin>:1: SymPyDeprecationWarning:

The simplify_this(expr) function is deprecated. Use simplify(expr)
instead.

See https://docs.sympy.org/latest/explanation/active-deprecations.html#simplify-this-deprecation
for details.

This has been deprecated since SymPy version 1.1\. It
will be removed in a future version of SymPy.

 simplify_this(x)
x 

另见

sympy.utilities.exceptions.SymPyDeprecationWarning, sympy.utilities.exceptions.sympy_deprecation_warning, sympy.utilities.exceptions.ignore_warnings, sympy.testing.pytest.warns_deprecated_sympy

sympy.utilities.decorator.conserve_mpmath_dps(func)

在函数完成后,将mpmath.mp.dps的值重置为函数运行之前的值。

sympy.utilities.decorator.doctest_depends_on(exe=None, modules=None, disable_viewers=None, python_version=None, ground_types=None)

添加关于必须满足的依赖项的元数据,以对装饰对象的文档字符串进行文档测试。

exe应该是可执行文件的列表

modules应该是模块的列表

disable_viewers应该是禁用preview()的查看器列表

python_version应该是所需的最低 Python 版本,格式为元组(如(3, 0)

sympy.utilities.decorator.memoize_property(propfunc)

缓存可能昂贵的propfunc的值的属性装饰器,在第一次评估之后。缓存的值存储在相应的属性名称上,附加了下划线。

class sympy.utilities.decorator.no_attrs_in_subclass(cls, f)

不要从基类‘继承’某些属性

>>> from sympy.utilities.decorator import no_attrs_in_subclass 
>>> class A(object):
...     x = 'test' 
>>> A.x = no_attrs_in_subclass(A, A.x) 
>>> class B(A):
...     pass 
>>> hasattr(A, 'x')
True
>>> hasattr(B, 'x')
False 
sympy.utilities.decorator.public(obj)

obj的名称附加到全局__all__变量(调用位置)。

通过在函数或类上使用此装饰器,您可以达到与手动填写__all__变量相同的目的,只是无需重复自己(对象的名称)。您还可以在定义位置知道对象在公共还是随机位置(设置了__all__的地方)。

请注意,在多个装饰器设置中(几乎所有情况下),必须在任何其他装饰器之前应用@public装饰器,因为它依赖于指向对象全局命名空间的指针。如果您先应用其他装饰器,@public可能会修改错误的命名空间。

示例

>>> from sympy.utilities.decorator import public 
>>> __all__ # noqa: F821
Traceback (most recent call last):
...
NameError: name '__all__' is not defined 
>>> @public
... def some_function():
...     pass 
>>> __all__ # noqa: F821
['some_function'] 
sympy.utilities.decorator.threaded(func)

对对象的子元素应用func,包括Add

此装饰器旨在统一地使得能够将函数应用于复合对象的所有元素,例如矩阵、列表、元组和其他可迭代容器,或者只是表达式。

此版本的threaded()装饰器允许对Add类的元素进行线程处理。如果不希望此行为,请使用xthreaded()装饰器。

函数使用此装饰器必须具有以下签名:

@threaded
def function(expr, *args, **kwargs): 
sympy.utilities.decorator.threaded_factory(func, use_add)

一个用于threaded装饰器的工厂。

sympy.utilities.decorator.xthreaded(func)

对对象的子元素应用func,不包括Add

此装饰器旨在统一地使得能够将函数应用于复合对象的所有元素,例如矩阵、列表、元组和其他可迭代容器,或者只是表达式。

此版本的threaded()装饰器禁止对Add类的元素进行线程处理。如果不希望此行为,请使用threaded()装饰器。

函数使用此装饰器必须具有以下签名:

@xthreaded
def function(expr, *args, **kwargs): 

枚举

原文:docs.sympy.org/latest/modules/utilities/enumerative.html

此模块包括用于枚举和计数多重集分区的函数和类。

sympy.utilities.enumerative.multiset_partitions_taocp(multiplicities)

枚举多重集的分区。

参数:

多重性

组件的整数多重性列表。

产生:

state

内部数据结构,用于编码特定的分区。然后,通常通过访问函数处理此输出数据结构,将其与组件本身结合起来生成实际的分区。

除非他们希望创建自己的访问函数,否则用户几乎没有必要查看此数据结构的内部。但是,供参考,它是一个具有三个元素的列表,其组件为:

f

是一个帧数组,用于将 pstack 分成部分。

lpart

指向最顶部部分的基础。

pstack

是一个 PartComponent 对象数组。

输出的state提供了对枚举函数内部数据结构的一瞥。客户端应将其视为只读;对数据结构的任何修改将导致不可预测(几乎肯定不正确)的结果。此外,state的组件在每次迭代中都是就地修改的。因此,必须在每次循环迭代时调用访问者。累积state实例并稍后处理它们将不起作用。

示例

>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import multiset_partitions_taocp
>>> # variables components and multiplicities represent the multiset 'abb'
>>> components = 'ab'
>>> multiplicities = [1, 2]
>>> states = multiset_partitions_taocp(multiplicities)
>>> list(list_visitor(state, components) for state in states)
[[['a', 'b', 'b']],
[['a', 'b'], ['b']],
[['a'], ['b', 'b']],
[['a'], ['b'], ['b']]] 

参见

sympy.utilities.iterables.multiset_partitions

接受多重集作为输入并直接生成多重集分区。它调度到许多函数,包括此函数,进行实现。大多数用户将发现它比multiset_partitions_taocp更方便使用。

sympy.utilities.enumerative.factoring_visitor(state, primes)

multiset_partitions_taocp一起使用,以枚举将一个数表示为因子乘积的方式。对于此用法,一个数的质因数的指数是分区枚举器的参数,而相应的质因数是此处的输入。

示例

要枚举一个数的因子化,我们可以将分区的元素视为其质因数,而多重性视为其指数。

>>> from sympy.utilities.enumerative import factoring_visitor
>>> from sympy.utilities.enumerative import multiset_partitions_taocp
>>> from sympy import factorint
>>> primes, multiplicities = zip(*factorint(24).items())
>>> primes
(2, 3)
>>> multiplicities
(3, 1)
>>> states = multiset_partitions_taocp(multiplicities)
>>> list(factoring_visitor(state, primes) for state in states)
[[24], [8, 3], [12, 2], [4, 6], [4, 2, 3], [6, 2, 2], [2, 2, 2, 3]] 
sympy.utilities.enumerative.list_visitor(state, components)

返回一个列表的列表来表示分区。

示例

>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import multiset_partitions_taocp
>>> states = multiset_partitions_taocp([1, 2, 1])
>>> s = next(states)
>>> list_visitor(s, 'abc')  # for multiset 'a b b c'
[['a', 'b', 'b', 'c']]
>>> s = next(states)
>>> list_visitor(s, [1, 2, 3])  # for multiset '1 2 2 3
[[1, 2, 2], [3]] 

函数multiset_partitions_taocp的方法被类MultisetPartitionTraverser扩展和泛化的方法。

class sympy.utilities.enumerative.MultisetPartitionTraverser

具有枚举和计数多重集分区的方法。

这实现了 Knuth 算法 7.1.2.5M 的重构和扩展版本[AOCP]

此类的枚举方法是生成器,并返回可以由用于multiset_partitions_taocp输出的相同访问函数解释的数据结构。

示例

>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> m.count_partitions([4,4,4,2])
127750
>>> m.count_partitions([3,3,3])
686 

参见

multiset_partitions_taocpsympy.utilities.iterables.multiset_partitions

参考资料

[AOCP] (1,2,3,4)

第 4A 卷,组合算法的第一部分中的算法 7.1.2.5M,《计算机编程艺术》作者 Donald Knuth。

[Factorisatio]

关于 Oppenheim 问题的一个问题:“Factorisatio Numerorum”,E. R. Canfield,Paul Erdos,Carl Pomerance,NUMBER THEORY 杂志,第 17 卷,第 1 号。1983 年 8 月。请参见第七部分,了解与 Knuth 相似的算法的描述。

[Yorgey]

生成多重集合分区,Brent Yorgey,Monad.Reader,第 8 期,2007 年 9 月。

count_partitions(multiplicities)

返回具有给定multiplicities中的组件的多重集合的分区数。

对于较大的计数,这种方法比调用一个枚举器并计数结果要快得多。使用动态规划来减少实际探索的节点数。用于加速计数过程的字典存储在MultisetPartitionTraverser对象中,并且跨调用保持不变。如果用户不希望为任何额外的多重集调用count_partitions,则应清除对象以节省内存。另一方面,从一个计数运行中建立起来的缓存可以显著加快后续调用count_partitions的速度,因此不清除对象可能是有利的。

例子

>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> m.count_partitions([9,8,2])
288716
>>> m.count_partitions([2,2])
9
>>> del m 

注意

如果我们观察 Knuth 的算法 M [AOCP]的运行方式,可以将其视为部分二叉树的遍历。一个部分最多有两个子节点,左子节点是由扩展操作产生的,右子节点是由减少操作产生的。普通的多重集合分区枚举是这棵树的中序遍历,其中分区对应于从根到叶子的路径。从路径到分区的映射有些复杂,因为分区只包含那些是叶子或扩展链接的父节点,而不包含那些是减少链接的父节点。

对于计数目的,只需计算叶子即可,这可以通过递归的中序遍历来完成。在特定部分为根的子树的叶子数仅是该部分本身的函数,因此记忆化具有显著加速计数的潜力。

这种方法采用了类似于假设化的记忆递归函数的计算方法,但有两个不同之处:

  1. 该方法是迭代的,借鉴其他枚举的结构,并维护正在计数的部分的显式堆栈。(此实现可能会快速地计算一些多重集,但在使用递归实现时可能会超出默认的 Python 递归限制。)

  2. 而不是直接使用部件数据结构,会构造更紧凑的键。这样做可以节省空间,但更重要的是,可以将某些本来会保持分离的物理键合并在一起。

与枚举函数不同,目前没有 _range 版本的 count_partitions。如果有人想要挑战自己,可以通过使用计数直方图而不是单个计数进行记忆化,并结合这些直方图来构造一个。

enum_all(multiplicities)

枚举多重集的分区。

示例

>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> states = m.enum_all([2,2])
>>> list(list_visitor(state, 'ab') for state in states)
[[['a', 'a', 'b', 'b']],
[['a', 'a', 'b'], ['b']],
[['a', 'a'], ['b', 'b']],
[['a', 'a'], ['b'], ['b']],
[['a', 'b', 'b'], ['a']],
[['a', 'b'], ['a', 'b']],
[['a', 'b'], ['a'], ['b']],
[['a'], ['a'], ['b', 'b']],
[['a'], ['a'], ['b'], ['b']]] 

另请参阅

multiset_partitions_taocp

提供了与此方法相同的结果,但大约快了一倍。因此,enum_all 主要用于测试。还请参见该函数有关状态和访问者的讨论。

enum_large(multiplicities, lb)

枚举多重集的分区,其中 lb < num(parts)

等同于 enum_range(multiplicities, lb, sum(multiplicities))

参数:

分量的重复次数

多重集分量的重复列表。

lb

分区中的部分数必须大于此下限。

示例

>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> states = m.enum_large([2,2], 2)
>>> list(list_visitor(state, 'ab') for state in states)
[[['a', 'a'], ['b'], ['b']],
[['a', 'b'], ['a'], ['b']],
[['a'], ['a'], ['b', 'b']],
[['a'], ['a'], ['b'], ['b']]] 

另请参阅

enum_all, enum_small, enum_range

enum_range(multiplicities, lb, ub)

枚举多重集的分区,其中lb < num(parts) <= ub

特别是,如果要求确切有 k 个部分的分区,则调用 (multiplicities, k - 1, k)。该方法泛化了 enum_all、enum_small 和 enum_large。

示例

>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> states = m.enum_range([2,2], 1, 2)
>>> list(list_visitor(state, 'ab') for state in states)
[[['a', 'a', 'b'], ['b']],
[['a', 'a'], ['b', 'b']],
[['a', 'b', 'b'], ['a']],
[['a', 'b'], ['a', 'b']]] 
enum_small(multiplicities, ub)

枚举多重集分区,部件数不超过 ub

等同于 enum_range(multiplicities, 0, ub)

参数:

分量的重复次数

多重集分量的重复列表。

ub

最大部分数

示例

>>> from sympy.utilities.enumerative import list_visitor
>>> from sympy.utilities.enumerative import MultisetPartitionTraverser
>>> m = MultisetPartitionTraverser()
>>> states = m.enum_small([2,2], 2)
>>> list(list_visitor(state, 'ab') for state in states)
[[['a', 'a', 'b', 'b']],
[['a', 'a', 'b'], ['b']],
[['a', 'a'], ['b', 'b']],
[['a', 'b', 'b'], ['a']],
[['a', 'b'], ['a', 'b']]] 

实现部分基于 Knuth 在《TAOCP》中练习 69 的答案。

另请参阅

enum_all, enum_large, enum_range

异常和警告

原文:docs.sympy.org/latest/modules/utilities/exceptions.html

一般的 SymPy 异常和警告。

exception sympy.utilities.exceptions.SymPyDeprecationWarning(message, *, deprecated_since_version, active_deprecations_target)

关于 SymPy 弃用特性的警告。

有关在 SymPy 中何时以及如何弃用事物的详细信息,请参阅 Deprecation Policy 文档。

请注意,仅仅构造这个类不会引发警告。为此,必须调用 :funcsympy_deprecation_warning 函数。因此,不建议直接构造这个类。

解释

SymPyDeprecationWarning 类是 DeprecationWarning 的子类,用于 SymPy 中的所有弃用警告。使用特殊子类是为了能够自动增加警告消息,包括有关引入弃用的版本的附加元数据和指向文档的链接。这也允许用户使用 warnings 过滤器显式地过滤 SymPy 的弃用警告(参见 Silencing SymPy Deprecation Warnings)。

此外,默认情况下启用了 SymPyDeprecationWarning 的显示,不像普通的 DeprecationWarning,只有在交互式会话中才默认显示。这确保了 SymPy 中的弃用警告实际上会被用户看到。

有关此函数参数的描述,请参见 sympy_deprecation_warning() 的文档。

要标记函数为弃用,可以使用 @deprecated 装饰器。

另请参见

sympy.utilities.exceptions.sympy_deprecation_warningsympy.utilities.exceptions.ignore_warningssympy.utilities.decorator.deprecatedsympy.testing.pytest.warns_deprecated_sympy

sympy.utilities.exceptions.ignore_warnings(warningcls)

在测试期间抑制警告的上下文管理器。

注意

在测试中不要与 SymPyDeprecationWarning 一起使用。应改用 warns_deprecated_sympy()。

此函数在测试期间抑制警告很有用。应该使用 warns 函数来断言是否会引发警告。ignore_warnings 函数在警告不一定会被引发时很有用(例如在导入模块时)或者警告来自第三方代码时。

由于递归调用而导致相同或类似警告被发出两次时,此函数也非常有用。

当警告(可靠地)来自 SymPy 时,应优先使用 warns 函数而不是 ignore_warnings。

>>> from sympy.utilities.exceptions import ignore_warnings
>>> import warnings 

这里有一个警告:

>>> with warnings.catch_warnings():  # reset warnings in doctest
...     warnings.simplefilter('error')
...     warnings.warn('deprecated', UserWarning)
Traceback (most recent call last):
  ...
UserWarning: deprecated 

让我们使用 ignore_warnings 来抑制它:

>>> with warnings.catch_warnings():  # reset warnings in doctest
...     warnings.simplefilter('error')
...     with ignore_warnings(UserWarning):
...         warnings.warn('deprecated', UserWarning) 

(未发出警告)

另见

sympy.utilities.exceptions.SymPyDeprecationWarning, sympy.utilities.exceptions.sympy_deprecation_warning, sympy.utilities.decorator.deprecated, sympy.testing.pytest.warns_deprecated_sympy

sympy.utilities.exceptions.sympy_deprecation_warning(message, *, deprecated_since_version, active_deprecations_target, stacklevel=3)

在 SymPy 中警告某个特性已弃用。

请查看弃用策略文档,了解 SymPy 中事物何时以及如何进行弃用。

要标记整个函数或类作为弃用,可以使用 @deprecated 装饰器。

参数:

message : str

弃用消息。可能跨越多行且包含代码示例。消息应该被限制在 80 个字符内。消息会自动去除缩进和前后空白。消息可能包含基于用户输入的动态内容,但是如果表达式可以是任意的,请避免使用 str(expression),因为它可能会很大,使得警告消息难以阅读。

deprecated_since_version : str

特性自 SymPy 弃用的版本。对于新的弃用,应使用不带 .dev 的版本在 sympy/release.py 中。如果下一个 SymPy 版本与此不同,发布经理将需要更新任何使用不正确版本的 SymPyDeprecationWarning

active_deprecations_target : str

对应于活跃弃用列表文档中弃用部分的 Sphinx 目标(参见 doc/src/explanation/active-deprecations.md)。这用于自动生成警告消息中页面的 URL。此参数是必需的,并且必须作为关键字参数传递。(示例:active_deprecations_target="deprecated-feature-abc"

stacklevel : int, 默认值:3

warnings.warn 函数中传递的 stacklevel 参数。如果您创建一个调用此函数的包装器,应增加此参数,以便警告消息显示出产生警告的代码行。请注意,在某些情况下,可能会有多个可能导致警告的用户代码路径。在这种情况下,只需选择最小的公共 stacklevel

示例

>>> from sympy.utilities.exceptions import sympy_deprecation_warning
>>> def is_this_zero(x, y=0):
...  """
...     Determine if x = 0.
...
...     Parameters
...     ==========
...
...     x : Expr
...       The expression to check.
...
...     y : Expr, optional
...       If provided, check if x = y.
...
...       .. deprecated:: 1.1
...
...          The ``y`` argument to ``is_this_zero`` is deprecated. Use
...          ``is_this_zero(x - y)`` instead.
...
...     """
...     from sympy import simplify
...
...     if y != 0:
...         sympy_deprecation_warning("""
...     The y argument to is_zero() is deprecated. Use is_zero(x - y) instead.""",
...             deprecated_since_version="1.1",
...             active_deprecations_target='is-this-zero-y-deprecation')
...     return simplify(x - y) == 0
>>> is_this_zero(0)
True
>>> is_this_zero(1, 1) 
<stdin>:1: SymPyDeprecationWarning:

The y argument to is_zero() is deprecated. Use is_zero(x - y) instead.

See https://docs.sympy.org/latest/explanation/active-deprecations.html#is-this-zero-y-deprecation
for details.

This has been deprecated since SymPy version 1.1\. It
will be removed in a future version of SymPy.

 is_this_zero(1, 1)
True 

另请参见

sympy.utilities.exceptions.SymPyDeprecationWarning, sympy.utilities.exceptions.ignore_warnings, sympy.utilities.decorator.deprecated, sympy.testing.pytest.warns_deprecated_sympy

可迭代对象

原文链接:docs.sympy.org/latest/modules/utilities/iterables.html

class sympy.utilities.iterables.NotIterable

在创建不应在其实例上调用 iterable()时返回 true 的类时使用此方法,例如,对实例调用 list()将导致无限循环。

sympy.utilities.iterables.binary_partitions(n)

生成n的二进制分区。

二进制分区仅由 2 的幂次数构成。每一步将(2^{k+1})减少为(2^k)和(2^k)。因此,16 转换为 8 和 8。

示例

>>> from sympy.utilities.iterables import binary_partitions
>>> for i in binary_partitions(5):
...     print(i)
...
[4, 1]
[2, 2, 1]
[2, 1, 1, 1]
[1, 1, 1, 1, 1] 

参考文献

[R1053]

TAOCP 4,第 7.2.1.5 节,问题 64

sympy.utilities.iterables.bracelets(n, k)

项链转换器以返回自由(无限制)项链。

sympy.utilities.iterables.capture(func)

返回 func()的打印输出。

func应为不带参数的函数,其通过打印语句产生输出。

>>> from sympy.utilities.iterables import capture
>>> from sympy import pprint
>>> from sympy.abc import x
>>> def foo():
...     print('hello world!')
...
>>> 'hello' in capture(foo) # foo, not foo()
True
>>> capture(lambda: pprint(2/x))
'2\n-\nx\n' 
sympy.utilities.iterables.common_prefix(*seqs)

返回 seqs 中的公共起始子序列。

>>> from sympy.utilities.iterables import common_prefix
>>> common_prefix(list(range(3)))
[0, 1, 2]
>>> common_prefix(list(range(3)), list(range(4)))
[0, 1, 2]
>>> common_prefix([1, 2, 3], [1, 2, 5])
[1, 2]
>>> common_prefix([1, 2, 3], [1, 3, 5])
[1] 
sympy.utilities.iterables.common_suffix(*seqs)

返回 seqs 中的公共结束子序列。

>>> from sympy.utilities.iterables import common_suffix
>>> common_suffix(list(range(3)))
[0, 1, 2]
>>> common_suffix(list(range(3)), list(range(4)))
[]
>>> common_suffix([1, 2, 3], [9, 2, 3])
[2, 3]
>>> common_suffix([1, 2, 3], [9, 7, 3])
[3] 
sympy.utilities.iterables.connected_components(G)

无向图的连通分量或有向图的弱连通分量。

参数:

G:元组[列表,列表[元组[T,T]]]

由图的顶点列表和边列表组成的元组,其连接的组件将被找到。

示例

给定一个无向图:

graph {
    A -- B
    C -- D
} 

图 { A -- B C -- D }

如果我们在两个方向上都包含每条边,则可以使用此函数找到连接的组件。

>>> from sympy.utilities.iterables import connected_components

>>> V = ['A', 'B', 'C', 'D']
>>> E = [('A', 'B'), ('B', 'A'), ('C', 'D'), ('D', 'C')]
>>> connected_components((V, E))
[['A', 'B'], ['C', 'D']] 

可以通过相同的方式找到有向图的弱连通分量。

注意事项

用于数据结构中必须为哈希的图顶点。如果顶点是不可哈希的,请用整数索引替换。

此函数使用 Tarjan 算法在(O(|V|+|E|))(线性)时间内计算连接的组件。

另见

sympy.utilities.iterables.strongly_connected_components

参考文献

[R1054]

图论组件

[R1055]

Tarjan 强连通分量算法

sympy.utilities.iterables.dict_merge(*dicts)

将字典合并为单个字典。

sympy.utilities.iterables.filter_symbols(iterator, exclude)

仅从(iterator)中生成不出现在(exclude)中的元素。

参数:

iterator:可迭代对象

从中取元素的迭代器

exclude:可迭代对象

要排除的元素

返回:

iterator:迭代器

过滤的迭代器

sympy.utilities.iterables.flatten(iterable, levels=None, cls=None)

递归地去嵌套可迭代容器。

>>> from sympy import flatten 
>>> flatten([1, 2, 3])
[1, 2, 3]
>>> flatten([1, 2, [3]])
[1, 2, 3]
>>> flatten([1, [2, 3], [4, 5]])
[1, 2, 3, 4, 5]
>>> flatten([1.0, 2, (1, None)])
[1.0, 2, 1, None] 

如果要仅取消嵌套的容器的指定层数,则将levels标志设置为所需的层数:

>>> ls = [[(-2, -1), (1, 2)], [(0, 0)]] 
>>> flatten(ls, levels=1)
[(-2, -1), (1, 2), (0, 0)] 

如果指定了 cls 参数,则仅展开该类的实例,例如:

>>> from sympy import Basic, S
>>> class MyOp(Basic):
...     pass
...
>>> flatten([MyOp(S(1), MyOp(S(2), S(3)))], cls=MyOp)
[1, 2, 3] 

改编自Python 技巧

sympy.utilities.iterables.generate_bell(n)

返回[0, 1, …, n - 1]的排列,使得每个排列与上一个排列仅通过交换一对相邻元素不同。将返回n!排列作为迭代器。为了从随机起始排列获取下一个排列,请使用 Permutation 类的next_trotterjohnson方法(以不同的方式生成相同的序列)。

示例

>>> from itertools import permutations
>>> from sympy.utilities.iterables import generate_bell
>>> from sympy import zeros, Matrix 

这是用于物理钟声的排列,不按字典顺序生成排列。相反,排列彼此之间仅有一个反转,并且交换发生的位置以简单的方式周期性地变化。考虑由permutationsgenerate_bell生成的前几个 4 个元素的排列:

>>> list(permutations(range(4)))[:5]
[(0, 1, 2, 3), (0, 1, 3, 2), (0, 2, 1, 3), (0, 2, 3, 1), (0, 3, 1, 2)]
>>> list(generate_bell(4))[:5]
[(0, 1, 2, 3), (0, 1, 3, 2), (0, 3, 1, 2), (3, 0, 1, 2), (3, 0, 2, 1)] 

注意第二和第三字典序排列的元素位置不同,而每个“贝尔”排列始终与前一个排列相比只有两个元素位置不同(因此排列的符号(+/-1)与前一个排列的符号相反)。

可以通过跟踪最大数出现的排列来看反转的位置是如何变化的:

>>> m = zeros(4, 24)
>>> for i, p in enumerate(generate_bell(4)):
...     m[:, i] = Matrix([j - 3 for j in list(p)])  # make largest zero
>>> m.print_nonzero('X')
[XXX  XXXXXX  XXXXXX  XXX]
[XX XX XXXX XX XXXX XX XX]
[X XXXX XX XXXX XX XXXX X]
[ XXXXXX  XXXXXX  XXXXXX ] 

参见

sympy.combinatorics.permutations.Permutation.next_trotterjohnson

参考文献

[R1056]

en.wikipedia.org/wiki/Method_ringing

[R1057]

stackoverflow.com/questions/4856615/recursive-permutation/4857018

[R1058]

web.archive.org/web/20160313023044/http://programminggeeks.com/bell-algorithm-for-permutation/

[R1059]

en.wikipedia.org/wiki/Steinhaus%E2%80%93Johnson%E2%80%93Trotter_algorithm

[R1060]

生成自反排列、错位排列和亲戚的方法由 ECO Vincent Vajnovszki, DMTCS vol 1 issue 12, 2010

sympy.utilities.iterables.generate_derangements(s)

返回可迭代对象s的唯一错位排列。

示例

>>> from sympy.utilities.iterables import generate_derangements
>>> list(generate_derangements([0, 1, 2]))
[[1, 2, 0], [2, 0, 1]]
>>> list(generate_derangements([0, 1, 2, 2]))
[[2, 2, 0, 1], [2, 2, 1, 0]]
>>> list(generate_derangements([0, 1, 1]))
[] 

参见

sympy.functions.combinatorial.factorials.subfactorial

sympy.utilities.iterables.generate_involutions(n)

生成自反排列。

一个自反排列是一个乘以自身得到单位排列的排列。在这个实现中,自反排列使用固定点生成。

或者,可以将自反排列视为不包含长度大于两个的循环的排列。

示例

>>> from sympy.utilities.iterables import generate_involutions
>>> list(generate_involutions(3))
[(0, 1, 2), (0, 2, 1), (1, 0, 2), (2, 1, 0)]
>>> len(list(generate_involutions(4)))
10 

参考文献

[R1061]

mathworld.wolfram.com/PermutationInvolution.html

sympy.utilities.iterables.generate_oriented_forest(n)

此算法生成有向森林。

有向图是一种没有对称有向边的有向图。森林是无环图,即没有循环。森林也可以描述为树的不相交并集,其中任意两个顶点都恰好由一条简单路径连接。

示例

>>> from sympy.utilities.iterables import generate_oriented_forest
>>> list(generate_oriented_forest(4))
[[0, 1, 2, 3], [0, 1, 2, 2], [0, 1, 2, 1], [0, 1, 2, 0],     [0, 1, 1, 1], [0, 1, 1, 0], [0, 1, 0, 1], [0, 1, 0, 0], [0, 0, 0, 0]] 

参考

[R1062]

T. Beyer 和 S.M. Hedetniemi:常数时间生成根树,SIAM J.计算机 Vol. 9,No. 4,1980 年 11 月

[R1063]

stackoverflow.com/questions/1633833/oriented-forest-taocp-algorithm-in-python

sympy.utilities.iterables.group(seq, multiple=True)

将序列拆分为相等、相邻元素的列表。

示例

>>> from sympy import group 
>>> group([1, 1, 1, 2, 2, 3])
[[1, 1, 1], [2, 2], [3]]
>>> group([1, 1, 1, 2, 2, 3], multiple=False)
[(1, 3), (2, 2), (3, 1)]
>>> group([1, 1, 3, 2, 2, 1], multiple=False)
[(1, 2), (3, 1), (2, 2), (1, 1)] 

参见也

multiset

sympy.utilities.iterables.has_dups(seq)

如果seq中有任何重复元素,则返回 True。

示例

>>> from sympy import has_dups, Dict, Set
>>> has_dups((1, 2, 1))
True
>>> has_dups(range(3))
False
>>> all(has_dups(c) is False for c in (set(), Set(), dict(), Dict()))
True 
sympy.utilities.iterables.has_variety(seq)

如果seq中有任何不同的元素,则返回 True。

示例

>>> from sympy import has_variety 
>>> has_variety((1, 2, 1))
True
>>> has_variety((1, 1, 1))
False 
sympy.utilities.iterables.ibin(n, bits=None, str=False)

返回一个长度为bits的列表,表示n的二进制值,小位于右侧(最后)。如果省略了bits,则长度将是表示n所需的位数。如果希望位的顺序是反向的,请使用返回列表的[::-1]切片。

如果希望从[0, 0,..., 0][1, 1, ..., 1]开始的所有位长列表序列,则传递非整数以表示位,例如'all'

如果需要位,请传递str=True

示例

>>> from sympy.utilities.iterables import ibin
>>> ibin(2)
[1, 0]
>>> ibin(2, 4)
[0, 0, 1, 0] 

如果所有列表与 0 到 2 ** n - 1 对应,则传递非整数以表示位:

>>> bits = 2
>>> for i in ibin(2, 'all'):
...     print(i)
(0, 0)
(0, 1)
(1, 0)
(1, 1) 

如果需要指定特定长度的位串,请使用str=True

>>> n = 123
>>> bits = 10
>>> ibin(n, bits, str=True)
'0001111011'
>>> ibin(n, bits, str=True)[::-1]  # small bits left
'1101111000'
>>> list(ibin(3, 'all', str=True))
['000', '001', '010', '011', '100', '101', '110', '111'] 
sympy.utilities.iterables.iproduct(*iterables)

可迭代集合的笛卡尔积。

生成可迭代集合的笛卡尔积。这类似于 itertools.product,但它可以处理无限可迭代对象,并且最终会产生来自无限积的任何项。

示例

>>> from sympy.utilities.iterables import iproduct
>>> sorted(iproduct([1,2], [3,4]))
[(1, 3), (1, 4), (2, 3), (2, 4)] 

使用无限迭代器:

>>> from sympy import S
>>> (3,) in iproduct(S.Integers)
True
>>> (3, 4) in iproduct(S.Integers, S.Integers)
True 

参见也

itertools.product

sympy.utilities.iterables.is_palindromic(s, i=0, j=None)

如果序列从左到右与整个序列中的右到左相同(默认),或在 Python 切片s[i: j]中,则返回 True;否则返回 False。

示例

>>> from sympy.utilities.iterables import is_palindromic
>>> is_palindromic([1, 0, 1])
True
>>> is_palindromic('abcbb')
False
>>> is_palindromic('abcbb', 1)
False 

在原地执行普通的 Python 切片,因此不需要为测试创建序列的切片:

>>> is_palindromic('abcbb', 1, -1)
True
>>> is_palindromic('abcbb', -4, -1)
True 

参见也

sympy.ntheory.digits.is_palindromic

测试整数

sympy.utilities.iterables.is_sequence(i, include=None)

返回一个布尔值,指示i是否在 SymPy 意义上是序列。如果你的应用程序需要包含任何不通过以下测试的对象作为序列,请将'include'设置为该对象的类型;多个类型应作为类型元组传递。

注意:虽然生成器可以生成一个序列,但通常需要特殊处理以确保其元素在生成器耗尽之前被捕获,因此默认情况下不包括这些在序列的定义中。

参见:可迭代对象

示例

>>> from sympy.utilities.iterables import is_sequence
>>> from types import GeneratorType
>>> is_sequence([])
True
>>> is_sequence(set())
False
>>> is_sequence('abc')
False
>>> is_sequence('abc', include=str)
True
>>> generator = (c for c in 'abc')
>>> is_sequence(generator)
False
>>> is_sequence(generator, include=(str, GeneratorType))
True 
sympy.utilities.iterables.iterable(i, exclude=(<class 'str'>, <class 'dict'>, <class 'sympy.utilities.iterables.NotIterable'>))

返回一个布尔值,指示i是否为 SymPy 可迭代对象。True 也表示迭代器是有限的,例如可以在实例上调用 list(…)。

当 SymPy 处理可迭代对象时,几乎总是假设可迭代对象不是字符串或映射,因此默认情况下排除它们。如果希望纯 Python 定义,请设置 exclude=None。要排除多个项,请作为元组传递它们。

您还可以在您的类上将 _iterable 属性设置为 True 或 False,这将覆盖这里的检查,包括排除测试。

一般来说,某些 SymPy 函数使用这个来检查它们是否应该递归地映射一个对象。如果一个对象在 Python 意义上是可迭代的,但不希望有此行为(例如因为其迭代不是有限的,或者因为迭代可能引起不想要的计算),它应该通过将 _iterable 属性设置为 False 来禁用它。

参见:is_sequence

示例

>>> from sympy.utilities.iterables import iterable
>>> from sympy import Tuple
>>> things = [[1], (1,), set([1]), Tuple(1), (j for j in [1, 2]), {1:2}, '1', 1]
>>> for i in things:
...     print('%s  %s' % (iterable(i), type(i)))
True <... 'list'>
True <... 'tuple'>
True <... 'set'>
True <class 'sympy.core.containers.Tuple'>
True <... 'generator'>
False <... 'dict'>
False <... 'str'>
False <... 'int'> 
>>> iterable({}, exclude=None)
True
>>> iterable({}, exclude=str)
True
>>> iterable("no", exclude=str)
False 
sympy.utilities.iterables.kbins(l, k, ordered=None)

返回序列l分成k个箱子。

示例

默认情况下,按相同顺序提供项目,但分成 k 个分区而无需重新排序:

>>> from sympy.utilities.iterables import kbins
>>> for p in kbins(list(range(5)), 2):
...     print(p)
...
[[0], [1, 2, 3, 4]]
[[0, 1], [2, 3, 4]]
[[0, 1, 2], [3, 4]]
[[0, 1, 2, 3], [4]] 

ordered标志要么为 None(提供元素的简单分区),要么为一个两位数表示箱子的顺序和箱子中项目的顺序是否重要。给定:

A = [[0], [1, 2]]
B = [[1, 2], [0]]
C = [[2, 1], [0]]
D = [[0], [2, 1]] 

ordered的以下值具有所示的含义:

00 means A == B == C == D
01 means A == B
10 means A == D
11 means A == A 
>>> for ordered_flag in [None, 0, 1, 10, 11]:
...     print('ordered = %s' % ordered_flag)
...     for p in kbins(list(range(3)), 2, ordered=ordered_flag):
...         print(' %s' % p)
...
ordered = None
 [[0], [1, 2]]
 [[0, 1], [2]]
ordered = 0
 [[0, 1], [2]]
 [[0, 2], [1]]
 [[0], [1, 2]]
ordered = 1
 [[0], [1, 2]]
 [[0], [2, 1]]
 [[1], [0, 2]]
 [[1], [2, 0]]
 [[2], [0, 1]]
 [[2], [1, 0]]
ordered = 10
 [[0, 1], [2]]
 [[2], [0, 1]]
 [[0, 2], [1]]
 [[1], [0, 2]]
 [[0], [1, 2]]
 [[1, 2], [0]]
ordered = 11
 [[0], [1, 2]]
 [[0, 1], [2]]
 [[0], [2, 1]]
 [[0, 2], [1]]
 [[1], [0, 2]]
 [[1, 0], [2]]
 [[1], [2, 0]]
 [[1, 2], [0]]
 [[2], [0, 1]]
 [[2, 0], [1]]
 [[2], [1, 0]]
 [[2, 1], [0]] 

参见

partitions, multiset_partitions

sympy.utilities.iterables.least_rotation(x, key=None)

返回获取词汇上最小的字符串/列表/元组等所需的左旋转步骤数。

示例

>>> from sympy.utilities.iterables import least_rotation, rotate_left
>>> a = [3, 1, 5, 1, 2]
>>> least_rotation(a)
3
>>> rotate_left(a, _)
[1, 2, 3, 1, 5] 

参考文献

[R1064]

zh.wikipedia.org/wiki/词汇最小化字符串旋转

sympy.utilities.iterables.minlex(seq, directed=True, key=None)

返回序列的旋转,在其中词汇上最小的元素首先出现,例如 (cba \rightarrow acb)。

返回的序列是一个元组,除非输入序列是一个字符串,此时返回一个字符串。

如果directed为 False,则返回序列和反向序列中较小的那个,例如 (cba \rightarrow abc)。

如果key不为 None,则用于从可迭代对象的每个元素中提取比较键。

示例

>>> from sympy.combinatorics.polyhedron import minlex
>>> minlex((1, 2, 0))
(0, 1, 2)
>>> minlex((1, 0, 2))
(0, 2, 1)
>>> minlex((1, 0, 2), directed=False)
(0, 1, 2) 
>>> minlex('11010011000', directed=True)
'00011010011'
>>> minlex('11010011000', directed=False)
'00011001011' 
>>> minlex(('bb', 'aaa', 'c', 'a'))
('a', 'bb', 'aaa', 'c')
>>> minlex(('bb', 'aaa', 'c', 'a'), key=len)
('c', 'a', 'bb', 'aaa') 
sympy.utilities.iterables.multiset(seq)

返回可散列序列的多重集形式,其中值是序列中项目的多重性。

示例

>>> from sympy.utilities.iterables import multiset
>>> multiset('mississippi')
{'i': 4, 'm': 1, 'p': 2, 's': 4} 

参见

group

sympy.utilities.iterables.multiset_combinations(m, n, g=None)

返回从多重集m中大小为n的唯一组合。

示例

>>> from sympy.utilities.iterables import multiset_combinations
>>> from itertools import combinations
>>> [''.join(i) for i in  multiset_combinations('baby', 3)]
['abb', 'aby', 'bby'] 
>>> def count(f, s): return len(list(f(s, 3))) 

组合数取决于字母的数量;唯一组合的数量取决于字母的重复方式。

>>> s1 = 'abracadabra'
>>> s2 = 'banana tree'
>>> count(combinations, s1), count(multiset_combinations, s1)
(165, 23)
>>> count(combinations, s2), count(multiset_combinations, s2)
(165, 54) 
sympy.utilities.iterables.multiset_derangements(s)

在原地生成集合s的错排。

示例

>>> from sympy.utilities.iterables import multiset_derangements, uniq 

因为多重集合(而不是集合)的错排是原地生成的,如果需要一组错排的副本,则必须进行复制,否则所有值将相同:

>>> list(uniq([i for i in multiset_derangements('1233')]))
[[None, None, None, None]]
>>> [i.copy() for i in multiset_derangements('1233')]
[['3', '3', '1', '2'], ['3', '3', '2', '1']]
>>> [''.join(i) for i in multiset_derangements('1233')]
['3312', '3321'] 
sympy.utilities.iterables.multiset_partitions(multiset, m=None)

返回给定多重集合的唯一分区(以列表形式)。如果m为 None,则将返回所有多重集合,否则仅返回具有m部分的分区。

如果multiset是整数,则提供一个范围[0, 1, …, multiset - 1]。

示例

>>> from sympy.utilities.iterables import multiset_partitions
>>> list(multiset_partitions([1, 2, 3, 4], 2))
[[[1, 2, 3], [4]], [[1, 2, 4], [3]], [[1, 2], [3, 4]],
[[1, 3, 4], [2]], [[1, 3], [2, 4]], [[1, 4], [2, 3]],
[[1], [2, 3, 4]]]
>>> list(multiset_partitions([1, 2, 3, 4], 1))
[[[1, 2, 3, 4]]] 

只返回唯一的分区,并且不管输入的顺序如何,它们将以规范顺序返回:

>>> a = [1, 2, 2, 1]
>>> ans = list(multiset_partitions(a, 2))
>>> a.sort()
>>> list(multiset_partitions(a, 2)) == ans
True
>>> a = range(3, 1, -1)
>>> (list(multiset_partitions(a)) ==
...  list(multiset_partitions(sorted(a))))
True 

如果省略m,则将返回所有分区:

>>> list(multiset_partitions([1, 1, 2]))
[[[1, 1, 2]], [[1, 1], [2]], [[1, 2], [1]], [[1], [1], [2]]]
>>> list(multiset_partitions([1]*3))
[[[1, 1, 1]], [[1], [1, 1]], [[1], [1], [1]]] 

计数

集合的分区数由贝尔数给出:

>>> from sympy import bell
>>> len(list(multiset_partitions(5))) == bell(5) == 52
True 

从大小为 n 的集合中长度为 k 的分区数量由第二类斯特林数给出:

>>> from sympy.functions.combinatorial.numbers import stirling
>>> stirling(5, 2) == len(list(multiset_partitions(5, 2))) == 15
True 

这些计数的注释适用于集合,而不是多重集。

注释

当多重集中的所有元素相同时,返回分区的顺序由partitions例程决定。如果要计数分区,则最好使用nT函数。

另请参阅

partitions, sympy.combinatorics.partitions.Partition, sympy.combinatorics.partitions.IntegerPartition, sympy.functions.combinatorial.numbers.nT

sympy.utilities.iterables.multiset_permutations(m, size=None, g=None)

返回多重集合m的唯一排列。

示例

>>> from sympy.utilities.iterables import multiset_permutations
>>> from sympy import factorial
>>> [''.join(i) for i in multiset_permutations('aab')]
['aab', 'aba', 'baa']
>>> factorial(len('banana'))
720
>>> len(list(multiset_permutations('banana')))
60 
sympy.utilities.iterables.necklaces(n, k, free=False)

一个用于生成项链的例程,可能(free=True)或者不可以(free=False)被翻转查看。返回的“项链”由n个整数(珠子)组成,有k个不同的值(颜色)。只返回唯一的项链。

示例

>>> from sympy.utilities.iterables import necklaces, bracelets
>>> def show(s, i):
...     return ''.join(s[j] for j in i) 

“无限制项链”有时也被称为“手镯”(一个可以翻转的对象,一个可以反转的序列),术语“项链”用来暗示一个不能被反转的序列。因此,对于手镯(旋转和反转),ACB == ABC,而对于项链,这两个序列是不同的,因为仅仅旋转不能使两个序列相同。

(记忆法:手镯可以反向查看,但项链不行。)

>>> B = [show('ABC', i) for i in bracelets(3, 3)]
>>> N = [show('ABC', i) for i in necklaces(3, 3)]
>>> set(N) - set(B)
{'ACB'} 
>>> list(necklaces(4, 2))
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 1),
 (0, 1, 0, 1), (0, 1, 1, 1), (1, 1, 1, 1)] 
>>> [show('.o', i) for i in bracelets(4, 2)]
['....', '...o', '..oo', '.o.o', '.ooo', 'oooo'] 

参考

[R1065]

mathworld.wolfram.com/Necklace.html

[R1066]

Frank Ruskey, Carla Savage, and Terry Min Yih Wang, Generating necklaces, Journal of Algorithms 13 (1992), 414-430; doi.org/10.1016/0196-6774(92)90047-G

sympy.utilities.iterables.numbered_symbols(prefix='x', cls=None, start=0, exclude=(), *args, **assumptions)

生成由前缀和递增下标组成的符号的无限流,前提是它们不会出现在exclude中。

参数:

prefix:str,可选

要使用的前缀。默认情况下,此函数将生成形式为“x0”、“x1”等的符号。

cls:class,可选

要使用的类。默认情况下,它使用Symbol,但您也可以使用WildDummy

start:int,可选

起始编号。默认情况下为 0。

exclude:list、tuple、cls 的集合,可选

要排除的符号。

***args, kwargs

传递给cls类的额外位置和关键字参数。

返回:

sym:符号

带下标的符号。

sympy.utilities.iterables.ordered_partitions(n, m=None, sort=True)

生成整数n的有序分区。

参数:

n:int

m:int,可选

默认值提供所有尺寸的分区,否则只提供尺寸为 m 的分区。此外,如果m不为 None,则会生成就地分区(请参见示例)。

sort:bool,默认为 True

控制在m不为 None 时是否返回排序的分区;当 False 时,分区尽快返回并排序元素,但当 m|n 时,分区将不按升序字典顺序返回。

示例

>>> from sympy.utilities.iterables import ordered_partitions 

所有大小为 5 的分区按升序字典顺序排列:

>>> for p in ordered_partitions(5):
...     print(p)
[1, 1, 1, 1, 1]
[1, 1, 1, 2]
[1, 1, 3]
[1, 2, 2]
[1, 4]
[2, 3]
[5] 

只有两个部分的大小为 5 的分区:

>>> for p in ordered_partitions(5, 2):
...     print(p)
[1, 4]
[2, 3] 

当给定m时,由于速度原因,将多次使用给定列表对象,因此除非在生成时复制每个对象,否则将无法看到正确的分区:

>>> [p for p in ordered_partitions(7, 3)]
[[1, 1, 1], [1, 1, 1], [1, 1, 1], [2, 2, 2]]
>>> [list(p) for p in ordered_partitions(7, 3)]
[[1, 1, 5], [1, 2, 4], [1, 3, 3], [2, 2, 3]] 

nm的倍数时,元素仍然被排序,但如果 sort 为 False,则分区本身将是无序的;默认是以升序字典顺序返回它们。

>>> for p in ordered_partitions(6, 2):
...     print(p)
[1, 5]
[2, 4]
[3, 3] 

但是,如果速度比顺序更重要,则可以将排序设置为 False:

>>> for p in ordered_partitions(6, 2, sort=False):
...     print(p)
[1, 5]
[3, 3]
[2, 4] 

参考文献

[R1067]

生成整数分区,[在线],可用:jeromekelleher.net/generating-integer-partitions.html

[R1068]

Jerome Kelleher 和 Barry O’Sullivan,“生成所有分区:两种编码的比较”,[在线],可用:arxiv.org/pdf/0909.2331v2.pdf

sympy.utilities.iterables.partitions(n, m=None, k=None, size=False)

生成正整数 n 的所有分区。

每个分区都表示为字典,将整数映射到分区中该整数的副本数。例如,返回的第一个大小为 4 的分区是{4: 1},“4:其中一个”。

参数:

n:int

m:int,可选

限制分区中部分的数量(助记符:m,最大部分)

k:int,可选

限制保留在分区中的数字(助记符:k,键)

size:bool,默认为 False

如果为True,则返回(M, P),其中 M 是多重度的总和,P 是生成的分区。如果为False,则仅返回生成的分区。

示例

>>> from sympy.utilities.iterables import partitions 

在分区中出现的数字(返回字典的键)限制为 k:

>>> for p in partitions(6, k=2):  
...     print(p)
{2: 3}
{1: 2, 2: 2}
{1: 4, 2: 1}
{1: 6} 

分区中的部分数目最多为分区中的值之和(返回的字典中的值之和),受 m 限制(默认值为 None,给出从 1 到 n 的分区):

>>> for p in partitions(6, m=2):  
...     print(p)
...
{6: 1}
{1: 1, 5: 1}
{2: 1, 4: 1}
{3: 2} 

另见

sympy.combinatorics.partitions.Partitionsympy.combinatorics.partitions.IntegerPartition

参考文献

[R1069]

修改自 Tim Peter 的版本,以允许 k 和 m 值:code.activestate.com/recipes/218332-generator-for-integer-partitions/

sympy.utilities.iterables.permute_signs(t)

返回一个迭代器,其中 t 的非零元素的符号被排列。

示例

>>> from sympy.utilities.iterables import permute_signs
>>> list(permute_signs((0, 1, 2)))
[(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2)] 
sympy.utilities.iterables.postfixes(seq)

生成序列的所有后缀。

示例

>>> from sympy.utilities.iterables import postfixes 
>>> list(postfixes([1,2,3,4]))
[[4], [3, 4], [2, 3, 4], [1, 2, 3, 4]] 
sympy.utilities.iterables.prefixes(seq)

生成序列的所有前缀。

示例

>>> from sympy.utilities.iterables import prefixes 
>>> list(prefixes([1,2,3,4]))
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]] 
sympy.utilities.iterables.random_derangement(t, choice=None, strict=True)

返回一个元素列表,其中没有元素处于原始位置。如果一个元素填充了超过一半的位置,则会引发错误,因为不可能有一个置换。要获得尽可能多项目的置换 - 一些最多的保留在它们的原始位置 - 通过传递像 choice 这样的伪随机选择器来产生一个伪随机置换(见下文)。

示例

>>> from sympy.utilities.iterables import random_derangement
>>> t = 'SymPy: a CAS in pure Python'
>>> d = random_derangement(t)
>>> all(i != j for i, j in zip(d, t))
True 

使用伪随机生成器选择可以得到可预测的结果:

>>> from sympy.core.random import seed, choice as c
>>> seed(1)
>>> d = [''.join(random_derangement(t, c)) for i in range(5)]
>>> assert len(set(d)) != 1  # we got different values 

通过重新播种,可以获得相同的序列:

>>> seed(1)
>>> d2 = [''.join(random_derangement(t, c)) for i in range(5)]
>>> assert d == d2 
sympy.utilities.iterables.reshape(seq, how)

根据 how 中的模板重新整形序列。

示例

>>> from sympy.utilities import reshape
>>> seq = list(range(1, 9)) 
>>> reshape(seq, [4]) # lists of 4
[[1, 2, 3, 4], [5, 6, 7, 8]] 
>>> reshape(seq, (4,)) # tuples of 4
[(1, 2, 3, 4), (5, 6, 7, 8)] 
>>> reshape(seq, (2, 2)) # tuples of 4
[(1, 2, 3, 4), (5, 6, 7, 8)] 
>>> reshape(seq, (2, [2])) # (i, i, [i, i])
[(1, 2, [3, 4]), (5, 6, [7, 8])] 
>>> reshape(seq, ((2,), [2])) # etc....
[((1, 2), [3, 4]), ((5, 6), [7, 8])] 
>>> reshape(seq, (1, [2], 1))
[(1, [2, 3], 4), (5, [6, 7], 8)] 
>>> reshape(tuple(seq), ([[1], 1, (2,)],))
(([[1], 2, (3, 4)],), ([[5], 6, (7, 8)],)) 
>>> reshape(tuple(seq), ([1], 1, (2,)))
(([1], 2, (3, 4)), ([5], 6, (7, 8))) 
>>> reshape(list(range(12)), [2, [3], {2}, (1, (3,), 1)])
[[0, 1, [2, 3, 4], {5, 6}, (7, (8, 9, 10), 11)]] 
sympy.utilities.iterables.rotate_left(x, y)

左旋转列表 x 按 y 中指定的步数。

示例

>>> from sympy.utilities.iterables import rotate_left
>>> a = [0, 1, 2]
>>> rotate_left(a, 1)
[1, 2, 0] 
sympy.utilities.iterables.rotate_right(x, y)

右旋转列表 x 按 y 中指定的步数。

示例

>>> from sympy.utilities.iterables import rotate_right
>>> a = [0, 1, 2]
>>> rotate_right(a, 1)
[2, 0, 1] 
sympy.utilities.iterables.rotations(s, dir=1)

返回一个生成器,将 s 中的项作为列表给出,其中每个后续列表相对于前一个列表向左(默认)或向右(dir=-1)旋转。

示例

>>> from sympy import rotations
>>> list(rotations([1,2,3]))
[[1, 2, 3], [2, 3, 1], [3, 1, 2]]
>>> list(rotations([1,2,3], -1))
[[1, 2, 3], [3, 1, 2], [2, 3, 1]] 
sympy.utilities.iterables.roundrobin(*iterables)

roundrobin 配方取自 itertools 文档:docs.python.org/3/library/itertools.html#itertools-recipes

roundrobin('ABC', 'D', 'EF') –> A D E B F C

由 George Sakkis 贡献的配方

sympy.utilities.iterables.runs(seq, op=<built-in function gt>)

将序列分组成列表,其中连续元素都使用比较运算符 op 相同:op(seq[i + 1], seq[i]) 从一个运行中的所有元素为 True。

示例

>>> from sympy.utilities.iterables import runs
>>> from operator import ge
>>> runs([0, 1, 2, 2, 1, 4, 3, 2, 2])
[[0, 1, 2], [2], [1, 4], [3], [2], [2]]
>>> runs([0, 1, 2, 2, 1, 4, 3, 2, 2], op=ge)
[[0, 1, 2, 2], [1, 4], [3], [2, 2]] 
sympy.utilities.iterables.sequence_partitions(l, n, /)

返回序列 (l) 的分区为 (n) 个箱子

参数:

l : Sequence[T]

任意 Python 对象的非空序列

n : int

正整数

产生:

out : list[Sequence[T]]

一个序列列表,其连接等于 (l)。这应符合 (l) 的类型。

解释

给定序列 (l_1 \cdots l_m \in V^+),其中 (V^+) 是 (V) 的 Kleene 加号

(l) 的 (n) 个分区集合定义为:

[{(s_1, \cdots, s_n) | s_1 \in V^+, \cdots, s_n \in V^+, s_1 \cdots s_n = l_1 \cdots l_m}]

示例

>>> from sympy.utilities.iterables import sequence_partitions
>>> for out in sequence_partitions([1, 2, 3, 4], 2):
...     print(out)
[[1], [2, 3, 4]]
[[1, 2], [3, 4]]
[[1, 2, 3], [4]] 

笔记

这是对 EnricoGiampieri 的分区生成器的修改版本,来源于 stackoverflow.com/questions/13131491/partition-n-items-into-k-bins-in-python-lazily

参见

sequence_partitions_empty

sympy.utilities.iterables.sequence_partitions_empty(l, n, /)

返回序列 (l) 的分区,分为 (n) 个空序列

参数:

l : Sequence[T]

任意 Python 对象的序列(可能为空)

n : int

一个正整数

产生:

out : list[Sequence[T]]

一个序列的列表,其连接等于 (l)。这应符合 (l) 的类型。

解释

给定序列 (l_1 \cdots l_m \in V^),其中 (V^) 是 (V) 的 Kleene 星号

(l) 的 (n) 个分区集合被定义为:

[{(s_1, \cdots, s_n) | s_1 \in V^, \cdots, s_n \in V^, s_1 \cdots s_n = l_1 \cdots l_m}]

sequence_partitions() 相比,有更多的组合,因为空序列可以填充到任何地方,因此我们尝试为此提供不同的实用工具。

示例

>>> from sympy.utilities.iterables import sequence_partitions_empty
>>> for out in sequence_partitions_empty([1, 2, 3, 4], 2):
...     print(out)
[[], [1, 2, 3, 4]]
[[1], [2, 3, 4]]
[[1, 2], [3, 4]]
[[1, 2, 3], [4]]
[[1, 2, 3, 4], []] 

参见

sequence_partitions

sympy.utilities.iterables.sift(seq, keyfunc, binary=False)

根据 keyfunc 对序列 seq 进行筛选。

返回:

binaryFalse(默认)时,输出是一个字典

其中 seq 的元素存储在一个列表中,以值为键

对于该元素的 keyfunc。如果 binary 为 True,则返回一个元组

返回 TF 的列表,其中 T 是一个列表

包含了 seq 的元素,其中 keyfuncTrue,并且

包含那些 keyfuncFalse 的元素的 F;

如果 keyfunc 不是二进制的,则会引发 ValueError。

示例

>>> from sympy.utilities import sift
>>> from sympy.abc import x, y
>>> from sympy import sqrt, exp, pi, Tuple 
>>> sift(range(5), lambda x: x % 2)
{0: [0, 2, 4], 1: [1, 3]} 

sift() 返回一个 defaultdict() 对象,因此任何没有匹配的键都会返回 []。

>>> sift([x], lambda x: x.is_commutative)
{True: [x]}
>>> _[False]
[] 

有 有时您不知道将获得多少个键:

>>> sift([sqrt(x), exp(x), (y**x)**2],
...      lambda x: x.as_base_exp()[0])
{E: [exp(x)], x: [sqrt(x)], y: [y**(2*x)]} 

有时您希望结果是二进制的;结果可以通过将 binary 设置为 True 来解包:

>>> sift(range(4), lambda x: x % 2, binary=True)
([1, 3], [0, 2])
>>> sift(Tuple(1, pi), lambda x: x.is_rational, binary=True)
([1], [pi]) 

如果谓词实际上不是二进制的(这是用于测试筛选逻辑并且期望二进制结果的好测试)则引发 ValueError:

>>> unknown = exp(1) - pi  # the rationality of this is unknown
>>> args = Tuple(1, pi, unknown)
>>> sift(args, lambda x: x.is_rational, binary=True)
Traceback (most recent call last):
...
ValueError: keyfunc gave non-binary output 

非二进制筛选显示产生了 3 个键:

>>> set(sift(args, lambda x: x.is_rational).keys())
{None, False, True} 

如果需要对筛选后的项目进行排序,最好使用 ordered,它可以在排序时将多个排序键经济地应用于序列。

参见

ordered

sympy.utilities.iterables.signed_permutations(t)

返回迭代器,其中 t 的非零元素的符号和元素的顺序被排列,并且所有返回的值都是唯一的。

示例

>>> from sympy.utilities.iterables import signed_permutations
>>> list(signed_permutations((0, 1, 2)))
[(0, 1, 2), (0, -1, 2), (0, 1, -2), (0, -1, -2), (0, 2, 1),
(0, -2, 1), (0, 2, -1), (0, -2, -1), (1, 0, 2), (-1, 0, 2),
(1, 0, -2), (-1, 0, -2), (1, 2, 0), (-1, 2, 0), (1, -2, 0),
(-1, -2, 0), (2, 0, 1), (-2, 0, 1), (2, 0, -1), (-2, 0, -1),
(2, 1, 0), (-2, 1, 0), (2, -1, 0), (-2, -1, 0)] 
sympy.utilities.iterables.strongly_connected_components(G)

有向图的强连通分量按反向拓扑顺序排列。

参数:

G : tuple[list, list[tuple[T, T]]

由顶点列表和边列表组成的元组,其中强连通分量的图将被找到。

示例

考虑一个有向图(使用点表示法):

digraph {
    A -> B
    A -> C
    B -> C
    C -> B
    B -> D
} 

有向图 { A -> B A -> C B -> C C -> B B -> D }

其中顶点是字母 A、B、C 和 D。此图可以使用 Python 的基本数据结构编码,如下所示:

>>> V = ['A', 'B', 'C', 'D']
>>> E = [('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'B'), ('B', 'D')] 

此图的强连通分量可以计算为

>>> from sympy.utilities.iterables import strongly_connected_components 
>>> strongly_connected_components((V, E))
[['D'], ['B', 'C'], ['A']] 

这也按照反向拓扑顺序给出组件。

由于包含 B 和 C 的子图具有循环,它们必须作为一个强连通分量出现。A 和 D 与图的其余部分连接,但不是以循环方式连接,因此它们会作为它们自己的强连通分量出现。

注释

图的顶点必须可散列以供所使用的数据结构使用。如果顶点不可散列,请用整数索引替换它们。

此函数使用 Tarjan 算法以 (O(|V|+|E|))(线性)时间计算强连通分量。

另请参见

sympy.utilities.iterables.connected_components

参考文献

[R1070]

en.wikipedia.org/wiki/Strongly_connected_component

[R1071]

en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm

sympy.utilities.iterables.subsets(seq, k=None, repetition=False)

从 (n)-元素集合 seq 生成所有 (k)-子集(组合)。

一个 (n)-元素集合的 (k)-子集是长度为 (k) 的任意子集。 (n)-元素集合的 (k)-子集数由 binomial(n, k) 给出,总共有 (2^n) 个子集。如果 (k) 是 None,则将按从最短到最长的顺序返回所有 (2^n) 个子集。

示例

>>> from sympy import subsets 

subsets(seq, k) 将返回不重复的 (\frac{n!}{k!(n - k)!}) 个 (k)-子集(组合):

>>> list(subsets([1, 2], 2))
[(1, 2)]
>>> list(subsets([1, 2]))
[(), (1,), (2,), (1, 2)]
>>> list(subsets([1, 2, 3], 2))
[(1, 2), (1, 3), (2, 3)] 

subsets(seq, k, repetition=True) 将返回带有重复的 (\frac{(n - 1 + k)!}{k!(n - 1)!}) 组合:

>>> list(subsets([1, 2], 2, repetition=True))
[(1, 1), (1, 2), (2, 2)] 

如果要求的项数超过集合中的项数,则会返回空集,除非允许重复:

>>> list(subsets([0, 1], 3, repetition=False))
[]
>>> list(subsets([0, 1], 3, repetition=True))
[(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)] 
sympy.utilities.iterables.take(iter, n)

iter 迭代器返回 n 个项。

sympy.utilities.iterables.topological_sort(graph, key=None)

图的顶点的拓扑排序。

参数:

graph:元组[list, list[tuple[T, T]]

由图的顶点列表和边列表组成的元组,用于对图进行拓扑排序。

key:callable[T](可选)

在同一级别上对顶点进行排序的键。默认情况下使用自然(如词典)排序(在这种情况下,基本类型必须实现排序关系)。

示例

考虑一个图:

+---+     +---+     +---+
| 7 |\    | 5 |     | 3 |
+---+ \   +---+     +---+
  |   _\___/ ____   _/ |
  |  /  \___/    \ /   |
  V  V           V V   |
 +----+         +---+  |
 | 11 |         | 8 |  |
 +----+         +---+  |
  | | \____   ___/ _   |
  | \      \ /    / \  |
  V  \     V V   /  V  V
+---+ \   +---+ |  +----+
| 2 |  |  | 9 | |  | 10 |
+---+  |  +---+ |  +----+
       \________/ 

其中顶点是整数。此图可以使用 Python 的基本数据结构进行编码,如下所示:

>>> V = [2, 3, 5, 7, 8, 9, 10, 11]
>>> E = [(7, 11), (7, 8), (5, 11), (3, 8), (3, 10),
...      (11, 2), (11, 9), (11, 10), (8, 9)] 

要计算图 (V, E) 的拓扑排序,请执行:

>>> from sympy.utilities.iterables import topological_sort

>>> topological_sort((V, E))
[3, 5, 7, 8, 11, 2, 9, 10] 

如果需要特定的破解方法,请使用 key 参数:

>>> topological_sort((V, E), key=lambda v: -v)
[7, 5, 11, 3, 10, 8, 9, 2] 

只有非循环图可以进行排序。如果输入图有循环,则会引发 ValueError

>>> topological_sort((V, E + [(10, 7)]))
Traceback (most recent call last):
...
ValueError: cycle detected 

参考文献

[R1072]

en.wikipedia.org/wiki/Topological_sorting

sympy.utilities.iterables.unflatten(iter, n=2)

iter中的项分组成长度为n的元组。如果iter的长度不是n的倍数,则会引发错误。

sympy.utilities.iterables.uniq(seq, result=None)

seq中的唯一元素作为迭代器返回。第二个参数result在内部使用;对于此参数,不需要传递任何内容。

注意:在迭代过程中更改序列将引发 RuntimeError(如果序列的大小已知);如果传递一个迭代器并推进迭代器,您将更改此例程的输出,但不会收到警告。

Examples

>>> from sympy.utilities.iterables import uniq
>>> dat = [1, 4, 1, 5, 4, 2, 1, 2]
>>> type(uniq(dat)) in (list, tuple)
False 
>>> list(uniq(dat))
[1, 4, 5, 2]
>>> list(uniq(x for x in dat))
[1, 4, 5, 2]
>>> list(uniq([[1], [2, 1], [1]]))
[[1], [2, 1]] 
sympy.utilities.iterables.variations(seq, n, repetition=False)

返回seq的大小为 N 的 n 元变异的迭代器。repetition控制seq中的项是否可以多次出现;

Examples

variations(seq, n)将返回seq元素的无重复排列的(\frac{N!}{(N - n)!}):

>>> from sympy import variations
>>> list(variations([1, 2], 2))
[(1, 2), (2, 1)] 

variations(seq, n, True)将返回允许元素重复的(N^n)排列:

>>> list(variations([1, 2], 2, repetition=True))
[(1, 1), (1, 2), (2, 1), (2, 2)] 

如果你请求的项数超过集合中的项数,则会得到空集,除非允许重复:

>>> list(variations([0, 1], 3, repetition=False))
[]
>>> list(variations([0, 1], 3, repetition=True))[:4]
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)] 

See also

itertools.permutations, itertools.product

variations

variations(seq, n) 返回大小为 n 的列表的所有变异。

有一个可选的第三个参数。必须是布尔值,如果设置为 True,则方法返回带重复项的变异,如果设置为 False,则返回不带重复项的变异。

Examples::

>>> from sympy.utilities.iterables import variations
>>> list(variations([1,2,3], 2))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
>>> list(variations([1,2,3], 2, True))
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3)] 

partitions

虽然组合模块包含用于研究和操作分区的 Partition 和 IntegerPartition 类,但有一些函数可生成分区,可用作低级工具进行例程:partitionsmultiset_partitions。前者提供整数分区,后者提供元素的枚举分区。还有一个名为kbins的例程,它将给出分区的各种排列。为了将分区作为列表而不是字典获取,有ordered_partition函数,其速度相当快。最后,为了简单地获得分区数量的计数,有nT函数。

See Also

sympy.utilities.iterables.ordered_partitions, sympy.functions.combinatorial.numbers.nT

partitions:

>>> from sympy.utilities.iterables import partitions
>>> [p.copy() for s, p in partitions(7, m=2, size=True) if s == 2]
[{1: 1, 6: 1}, {2: 1, 5: 1}, {3: 1, 4: 1}] 

multiset_partitions:

>>> from sympy.utilities.iterables import multiset_partitions
>>> [p for p in multiset_partitions(3, 2)]
[[[0, 1], [2]], [[0, 2], [1]], [[0], [1, 2]]]
>>> [p for p in multiset_partitions([1, 1, 1, 2], 2)]
[[[1, 1, 1], [2]], [[1, 1, 2], [1]], [[1, 1], [1, 2]]] 

kbins:

>>> from sympy.utilities.iterables import kbins
>>> def show(k):
...     rv = []
...     for p in k:
...         rv.append(','.join([''.join(j) for j in p]))
...     return sorted(rv)
...
>>> show(kbins("ABCD", 2))
['A,BCD', 'AB,CD', 'ABC,D']
>>> show(kbins("ABC", 2))
['A,BC', 'AB,C']
>>> show(kbins("ABC", 2, ordered=0))  # same as multiset_partitions
['A,BC', 'AB,C', 'AC,B']
>>> show(kbins("ABC", 2, ordered=1))
['A,BC', 'A,CB',
 'B,AC', 'B,CA',
 'C,AB', 'C,BA']
>>> show(kbins("ABC", 2, ordered=10))
['A,BC', 'AB,C', 'AC,B',
 'B,AC', 'BC,A',
 'C,AB']
>>> show(kbins("ABC", 2, ordered=11))
['A,BC', 'A,CB', 'AB,C', 'AC,B',
 'B,AC', 'B,CA', 'BA,C', 'BC,A',
 'C,AB', 'C,BA', 'CA,B', 'CB,A']