可迭代对象

class sympy.utilities.iterables.NotIterable[源代码][源代码]

在创建一个类时使用此mixin,当在其实例上调用iterable()时,该类不应返回true,因为例如在实例上调用list()会导致无限循环。

sympy.utilities.iterables.binary_partitions(n)[源代码][源代码]

生成 n 的二进制分区。

二进制分区仅由2的幂次方组成。每一步将 \(2^{k+1}\) 分解为 \(2^k\)\(2^k\)。因此,16 被转换为 8 和 8。

参考文献

[1]

TAOCP 4, 第 7.2.1.5 节, 问题 64

示例

>>> 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]
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)[源代码][源代码]

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

参数:
Gtuple[list, list[tuple[T, T]]]

一个由图的顶点列表和边列表组成的元组,其连通分量需要被找到。

注释

图的顶点必须对所使用的数据结构是可哈希的。如果顶点是不可哈希的,请将它们替换为整数索引。

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

参考文献

示例

给定一个无向图:

graph {
    A -- B
    C -- D
}

graph { 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']]

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

sympy.utilities.iterables.dict_merge(*dicts)[源代码][源代码]

将字典合并成一个字典。

sympy.utilities.iterables.filter_symbols(iterator, exclude)[源代码][源代码]

仅从 \(iterator\) 中产生那些不在 \(exclude\) 中的元素。

参数:
迭代器可迭代对象

迭代器以获取元素

排除可迭代对象

要排除的元素

返回:
迭代器迭代器

过滤迭代器

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]

改编自 https://kogs-www.informatik.uni-hamburg.de/~meine/python_tricks

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

注意,第2和第3个字典序排列有3个元素错位,而每个“钟”排列相对于前一个排列总是只有两个元素错位(因此排列的符号(+/-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.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.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
sympy.utilities.iterables.generate_oriented_forest(n)[源代码][源代码]

该算法生成有向森林。

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

参考文献

[1]

T. Beyer and S.M. Hedetniemi: constant time generation of rooted trees, SIAM J. Computing Vol. 9, No. 4, November 1980

示例

>>> 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]]
sympy.utilities.iterables.group(seq, multiple=True)[源代码][源代码]

将一个序列分割成包含相等、相邻元素的列表的列表。

参见

multiset

示例

>>> 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)]
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] 的所有比特长度列表的序列,请为 bits 传递一个非整数,例如 '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.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]]
sympy.utilities.iterables.least_rotation(x, key=None)[源代码][源代码]

返回左旋所需的最小步数,以获得字典序最小的字符串/列表/元组等。

参考文献

[1]

https://en.wikipedia.org/wiki/字典序最小字符串旋转

示例

>>> 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]
sympy.utilities.iterables.minlex(seq, directed=True, key=None)[源代码][源代码]

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

返回的序列是一个元组,除非输入序列是字符串,在这种情况下返回的是字符串。

如果 directed 为 False,则返回序列和反转序列中较小的那个,例如 \(cba ightarrow 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)[源代码][源代码]

返回多重集中可哈希序列的形式,其中值为序列中项目的多重性。

参见

group

示例

>>> from sympy.utilities.iterables import multiset
>>> multiset('mississippi')
{'i': 4, 'm': 1, 'p': 2, 's': 4}
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]。

注释

当多重集合中的所有元素相同时,返回的分区顺序由 partitions 例程决定。如果是在计算分区,那么使用 nT 函数会更好。

示例

>>> 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]]]
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 种不同的值(颜色)。只返回唯一的项链。

参考文献

[2]

Frank Ruskey, Carla Savage, 和 Terry Min Yih Wang, 生成项链, 算法杂志 13 (1992), 414-430; https://doi.org/10.1016/0196-6774(92)90047-G

示例

>>> 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']
sympy.utilities.iterables.numbered_symbols(
prefix='x',
cls=None,
start=0,
exclude=(),
*args,
**assumptions,
)[源代码][源代码]

生成一个由前缀和递增下标组成的无限符号流,前提是这些符号不在 exclude 中出现。

参数:
前缀str, 可选

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

cls类, 可选

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

开始int, 可选

起始数字。默认情况下,它是 0。

排除列表, 元组, cls 的集合, 可选

要排除的符号。

*args, **kwargs

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

返回:
sym符号

下标符号。

sympy.utilities.iterables.ordered_partitions(n, m=None, sort=True)[源代码][源代码]

生成整数 n 的有序分区。

参数:
n整数
mint, 可选

默认值给出所有大小的分区,否则只给出大小为 m 的分区。此外,如果 m 不是 None,则分区是 就地 生成的(参见示例)。

排序bool, 默认: True

控制当 m 不为 None 时,分区是否按排序顺序返回;当为 False 时,分区将尽可能快地返回,元素已排序,但当 m|n 时,分区将不会按升序字典顺序排列。

参考文献

[1]

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

[2]

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

示例

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

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

>>> for p in ordered_partitions(6, 2, sort=False):
...     print(p)
[1, 5]
[3, 3]
[2, 4]
sympy.utilities.iterables.partitions(n, m=None, k=None, size=False)[源代码][源代码]

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

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

参数:
n整数
mint, 可选

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

kint, 可选

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

大小bool, 默认值: False

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

参考文献

[1]

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

示例

>>> 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.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)[源代码][源代码]

返回一个元素列表,其中没有任何元素处于它们原来的位置。如果一个元素占据了超过一半的位置,则会引发错误,因为不可能进行重排。要尽可能多地重排项目——其中一些最常见的元素仍保留在它们原来的位置——请传递 \(strict=False\)。要生成一个伪随机重排,请传递一个伪随机选择器,如 `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)[源代码][源代码]

从 itertools 文档中提取的 roundrobin 配方:https://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\) 个区间的结果

参数:
lSequence[T]

任意 Python 对象的非空序列

n整数

一个正整数

Yields:
list[Sequence[T]]

一个包含连接操作的序列列表等于 \(l\)。这应符合 \(l\) 的类型。

注释

这是从 https://stackoverflow.com/questions/13131491/partition-n-items-into-k-bins-in-python-lazily 修改的 EnricoGiampieri 的分区生成器版本。

示例

>>> 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]]
sympy.utilities.iterables.sequence_partitions_empty(l, n, /)[源代码][源代码]

返回将序列 \(l\) 划分为 \(n\) 个空序列的划分结果

参数:
lSequence[T]

一个由任意Python对象组成的序列(可以是空的)

n整数

一个正整数

Yields:
list[Sequence[T]]

一个包含连接操作的序列列表等于 \(l\)。这应符合 \(l\) 的类型。

示例

>>> 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], []]
sympy.utilities.iterables.sift(seq, keyfunc, binary=False)[源代码][源代码]

根据 keyfunc 筛选序列 seq

返回:
binaryFalse (默认)时,输出是一个字典
seq 的元素存储在一个以值为键的列表中
对于该元素的 keyfunc。如果 binary 为 True,则返回一个元组
返回包含列表 TF,其中 T 是一个列表
包含 keyfuncTrue 的 seq 元素
F 包含那些 keyfuncFalse 的元素;
如果 keyfunc 不是二进制的,则会引发 ValueError。

参见

ordered

示例

>>> 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 可能会更好,它可以在排序时经济地对序列应用多个排序键。

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)[源代码][源代码]

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

参数:
Gtuple[list, list[tuple[T, T]]]

一个由图的顶点列表和边列表组成的元组,其强连通分量需要被找到。

注释

图的顶点必须对所使用的数据结构是可哈希的。如果顶点是不可哈希的,请将它们替换为整数索引。

此函数使用 Tarjan 算法来计算强连通分量,时间复杂度为 `O(|V|+|E|)`(线性时间)。

参考文献

示例

考虑一个有向图(在dot表示法中):

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

digraph { 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 与图的其他部分相连,但不是以循环方式相连,因此它们各自形成独立的强连通分量。

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)[源代码][源代码]

图顶点的拓扑排序。

参数:
tuple[list, list[tuple[T, T]]]

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

关键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
sympy.utilities.iterables.unflatten(iter, n=2)[源代码][源代码]

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

sympy.utilities.iterables.uniq(seq, result=None)[源代码][源代码]

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

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

示例

>>> 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 中的项目是否可以出现多次;

示例

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

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

变化

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

有一个可选的第三个参数。必须是布尔值,如果设置为 True,则该方法返回包含重复的排列;如果设置为 False,则返回不包含重复的排列。

示例:
>>> 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)]

分区

尽管组合数学模块包含用于研究和操作分区的 Partition 和 IntegerPartition 类,但有一些函数可以生成分区,这些函数可以作为例程的低级工具使用:partitionsmultiset_partitions。前者给出整数分区,后者给出元素的枚举分区。还有一个例程 kbins,它将给出分区的各种排列。为了以列表而不是字典的形式获取分区,有一个非常快的 ordered_partition 函数。最后,为了简单地获取分区数量的计数而不枚举它们,有一个 nT 函数。

另请参阅

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