SymPy-1-13-中文文档-五-
SymPy 1.13 中文文档(五)
置换群
原文:
docs.sympy.org/latest/modules/combinatorics/perm_groups.html
class sympy.combinatorics.perm_groups.PermutationGroup(*args, dups=True, **kwargs)
定义置换群的类。
解释
PermutationGroup([p1, p2, ..., pn])
返回由置换列表生成的置换群。如果希望装饰与置换索引相关的元素,则可以将此群提供给Polyhedron
。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> from sympy.combinatorics import Polyhedron
定义作用于(2 \times 2)魔方的前、右和底面的置换:
>>> F = Permutation(2, 19, 21, 8)(3, 17, 20, 10)(4, 6, 7, 5)
>>> R = Permutation(1, 5, 21, 14)(3, 7, 23, 12)(8, 10, 11, 9)
>>> D = Permutation(6, 18, 14, 10)(7, 19, 15, 11)(20, 22, 23, 21)
将它们作为置换传递给PermutationGroup
:
>>> G = PermutationGroup(F, R, D)
>>> G.order()
3674160
可以将此群提供给Polyhedron
以跟踪正在移动的对象。在那里给出了一个涉及(2 \times 2)魔方的示例,但这里是一个简单的演示:
>>> a = Permutation(2, 1)
>>> b = Permutation(1, 0)
>>> G = PermutationGroup(a, b)
>>> P = Polyhedron(list('ABC'), pgroup=G)
>>> P.corners
(A, B, C)
>>> P.rotate(0) # apply permutation 0
>>> P.corners
(A, C, B)
>>> P.reset()
>>> P.corners
(A, B, C)
或者可以将置换作为选定置换的乘积,并直接将它们应用于可迭代对象:
>>> P10 = G.make_perm([0, 1])
>>> P10('ABC')
['C', 'A', 'B']
参见
sympy.combinatorics.polyhedron.Polyhedron
, sympy.combinatorics.permutations.Permutation
参考文献
[R62]
Holt, D., Eick, B., O’Brien, E. “计算群论手册”
[R63]
Seress, A. “置换群算法”
[R64]
en.wikipedia.org/wiki/Schreier_vector
[R65]
en.wikipedia.org/wiki/Nielsen_transformation#Product_replacement_algorithm
[R66]
Frank Celler, Charles R.Leedham-Green, Scott H.Murray, Alice C.Niemeyer, 和 E.A.O’Brien. “生成有限群的随机元素”
[R67]
en.wikipedia.org/wiki/Block_%28permutation_group_theory%29
[R68]
algorithmist.com/wiki/Union_find
[R69]
en.wikipedia.org/wiki/Multiply_transitive_group#Multiply_transitive_groups
[R70]
en.wikipedia.org/wiki/Center_%28group_theory%29
__contains__(i)
如果i包含在PermutationGroup
中,则返回True
。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> p = Permutation(1, 2, 3)
>>> Permutation(3) in PermutationGroup(p)
True
__mul__(other)
返回两个置换群的直积作为一个置换群。
解释
这个实现通过移动第二个群生成器的索引集来实现直积:因此,如果我们有G
作用于n1
个点,H
作用于n2
个点,那么G*H
作用于n1 + n2
个点。
示例
>>> from sympy.combinatorics.named_groups import CyclicGroup
>>> G = CyclicGroup(5)
>>> H = G*G
>>> H
PermutationGroup([
(9)(0 1 2 3 4),
(5 6 7 8 9)])
>>> H.order()
25
static __new__(cls, *args, dups=True, **kwargs)
默认构造函数。接受循环和置换形式。除非dups
关键字为False
,否则会删除重复项。
__weakref__
对对象的弱引用列表
_coset_representative(g, H)
返回由self.coset_transversal(H)
计算的 Hg 的代表。
classmethod _distinct_primes_lemma(primes)
子例程用于测试是否只有一个循环群的顺序。
_eval_is_alt_sym_monte_carlo(eps=0.05, perms=None)
使用蒙特卡罗算法进行测试。
参数:
eps:浮点数,可选
错误的判定标准是
False
返回。
perms:列表[置换],可选
如果明确给出,它会对给定的测试候选进行测试。
如果
None
,则随机计算N_eps
并从群的样本中选择N_eps
个置换。
另见。
_check_cycles_alt_sym
_eval_is_alt_sym_naive(only_sym=False, only_alt=False)
使用群的顺序的朴素测试。
_p_elements_group(p)
对于阿贝尔 p-群,返回由所有 p 阶元素(和单位元素)组成的子群。
_random_pr_init(r, n, _random_prec_n=None)
初始化产品替换算法的随机生成器。
说明
该实现使用了 Leedham-Green 修改过的原始产品替换算法,详见[1]第 69-71 页;另请参阅[2]第 27-29 页对原始产品替换算法的详细理论分析,以及[4]。
产品替换算法用于生成群( G )的随机、均匀分布的元素。对于初始化_random_pr_init
,创建一个包含(\max{r, |S|})个群生成器的列表R
作为属性G._random_gens
,如有必要重复( S )的元素,并将( G )的单位元素附加到R
- 我们将最后一个元素称为累加器。然后调用函数random_pr()
n
次,随机化列表R
,同时保持由R
生成( G )。random_pr()
函数本身从R
的所有元素中选取两个随机元素g, h
(除了累加器),并用({gh, g(~h), hg, (~h)g})中随机选择的元素替换g
。然后累加器乘以被替换的g
。random_pr()
然后返回累加器的新值。
返回的元素最终(对于足够大的n
)将在( G )中均匀分布([5])。然而,对于实际目的,建议在[1]中使用n = 50, r = 11
。
注释
此函数具有副作用:它改变了属性self._random_gens
。
另见。
random_pr
_sylow_alt_sym(p)
返回对称或交替群的 p-希罗亚子群。
说明
该算法在[1]章节 4 练习 4 中有提示。
对于 Sym(n),其中 n = p^i,其思想如下。将区间[0..n-1]分成 p 个相等的部分,每部分长度为 p(i-1):[0..p(i-1)-1],[p(i-1)..2*p(i-1)-1]…[(p-1)*p(i-1)..pi-1]。找到 Sym(p^(i-1))的 p-Sylow 子群(作为self
的子群)作用于每个部分。称这些子群为 P_1,P_2…P_p。可以通过将“移位”置换应用到它们上,即将[0..p^(i-1)-1]映射到第二部分(其他部分通过多次移位获得)。这些置换与 P_1 的生成器的并集是self
的 p-Sylow 子群。
对于 n 不等于 p 的幂的情况,按照 n 在 p 进制中的表示方式对[0..n-1]进行分区。例如,对于 p=2 和 n=11,11 = 2³ + 2² + 1,所以分区是[[0..7],[8..9],{10}]。要生成 p-Sylow 子群,取每个部分的生成器的并集。对于上述示例,来自第一个部分的{(0 1),(0 2)(1 3),(0 4),(1 5)(2 7)},来自第二个部分的{(8 9)},第三个部分没有生成器。总共有 4 个生成器,它们生成的子群是 p-Sylow。
交替群在 p=2 时被视为相同,除非(p=2)。在这种情况下,应为适当的 s(部分的起始点),为每个部分添加(0 1)(s s+1)。
另请参阅
sylow_subgroup
,is_alt_sym
_union_find_merge(first, second, ranks, parents, not_rep)
合并两个类在并查集数据结构中。
说明
在 Atkinson 算法的实现中使用,如[1]建议的,第 83-87 页。类合并过程使用了按秩合并作为优化。([7])
注意
此函数有副作用:类代表列表parents
,类大小列表ranks
和非代表元素列表not_rep
由于类合并而发生改变。
另请参阅
minimal_block
,_union_find_rep
参考文献
[R71]
Holt, D., Eick, B., O’Brien, E. 的“计算群论手册”。
[R77]
algorithmist.com/wiki/Union_find
的解释。
_union_find_rep(num, parents)
在并查集数据结构中查找类的代表。
解释
在 Atkinson 算法的实现中使用,如[1]建议的,第 83-87 页。在找到num
所属类的代表后,进行路径压缩以优化([7])。
注意
此函数有副作用:类代表列表parents
由于路径压缩而被更改。
另请参阅
minimal_block
, _union_find_merge
参考文献
[R73]
Holt, D., Eick, B., O’Brien, E. “计算群论手册”
[R79]
algorithmist.com/wiki/Union_find
_verify(K, phi, z, alpha)
返回在生成器 pygens`_h` that are mapped to ``H.generators
下由 phi
给出的关系列表 rels
,以便给定 K
在 gens_h
的子集上的有限表示 <gens_h | rels_k + rels>
是 H
的有限表示。
解释
H
应由 K.generators
和 z
(一个单一的生成器)的并集生成,并且 H.stabilizer(alpha) == K
;phi
是从自由群到包含 H
的置换群的规范注入。
算法见 [1],第六章。
示例
>>> from sympy.combinatorics import free_group, Permutation, PermutationGroup
>>> from sympy.combinatorics.homomorphisms import homomorphism
>>> from sympy.combinatorics.fp_groups import FpGroup
>>> H = PermutationGroup(Permutation(0, 2), Permutation (1, 5))
>>> K = PermutationGroup(Permutation(5)(0, 2))
>>> F = free_group("x_0 x_1")[0]
>>> gens = F.generators
>>> phi = homomorphism(F, H, F.generators, H.generators)
>>> rels_k = [gens[0]**2] # relators for presentation of K
>>> z= Permutation(1, 5)
>>> check, rels_h = H._verify(K, phi, z, 1)
>>> check
True
>>> rels = rels_k + rels_h
>>> G = FpGroup(F, rels) # presentation of H
>>> G.order() == H.order()
True
另请参阅
strong_presentation
, presentation
, stabilizer
abelian_invariants()
返回给定群的阿贝尔不变量。设 G
是一个非平凡有限阿贝尔群。那么 G
同构于有限多个非平凡循环群的素数幂次序的直积。
解释
出现为因子次序的素数幂次唯一确定了 G
。更确切地说,出现在 G
的任何此类分解的因子次序中的素数,正好是整除 |G|
的素数,并且对于任何这样的素数 p
,如果在 G
的一种这样的分解中是 p^{t_1} >= p^{t_2} >= ... p^{t_r}
的因子次序,那么在 G
的任何这样的分解中是 p^{t_1} >= p^{t_2} >= ... p^{t_r}
。
对于非平凡群 G
,对所有整除 |G|
的素数取唯一确定的整数 p^{t_1} >= p^{t_2} >= ... p^{t_r}
,如 ([14], p. 542) 所建议的,称为其不变量。
注意事项
我们采用的惯例是一个平凡群的不变量为 []。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.abelian_invariants()
[2]
>>> from sympy.combinatorics import CyclicGroup
>>> G = CyclicGroup(7)
>>> G.abelian_invariants()
[7]
property base
返回 Schreier-Sims 算法的基础。
解释
对于置换群 (G),一个基是一组点的序列 (B = (b_1, b_2, \dots, b_k)),使得除单位元素外,G
中没有元素能够固定所有 B
中的点。基和强生成集的概念及其应用在 [1],第 87-89 页和 [2],第 55-57 页中有详细讨论。
另一种思考 B
的方法是,它提供了包含非单位置换的稳定子余类的指标。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> G = PermutationGroup([Permutation(0, 1, 3)(2, 4)])
>>> G.base
[0, 2]
另请参阅
strong_gens
, basic_transversals
, basic_orbits
, basic_stabilizers
baseswap(base, strong_gens, pos, randomized=False, transversals=None, basic_orbits=None, strong_gens_distr=None)
交换基和强生成集中的两个连续基点。
参数:
基础,强生成集
基础和强生成集。
pos
执行交换的位置。
随机化
随机化版本与确定性版本之间的切换。
横断面
如果已知基轨道的横断面。
基本轨道
如果已知的基本轨道。
强生成集分布
已知的强生成器由基本稳定子分布。
返回:
(base, strong_gens)
base
是新基,strong_gens
是相对于它的生成集。
解释
如果群 (G) 的一个基由 ((b_1, b_2, \dots, b_k)) 给出,则此函数返回一个基 ((b_1, b_2, \dots, b_{i+1}, b_i, \dots, b_k)),其中 (i) 由 pos
给出,并且相对于该基的一个强生成集。原始基和强生成集不会被修改。
随机化版本(默认)为拉斯维加斯类型。
示例
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> S = SymmetricGroup(4)
>>> S.schreier_sims()
>>> S.base
[0, 1, 2]
>>> base, gens = S.baseswap(S.base, S.strong_gens, 1, randomized=False)
>>> base, gens
([0, 2, 1],
[(0 1 2 3), (3)(0 1), (1 3 2),
(2 3), (1 3)])
检查该基和生成集是否为 BSGS。
>>> S1 = PermutationGroup(gens)
>>> _verify_bsgs(S1, base, gens)
True
注意事项
算法的确定性版本在 [1] 第 102-103 页讨论;随机化版本在 [1] 第 103 页和 [2] 第 98 页讨论。这是拉斯维加斯类型。注意在 [1] 的伪代码和 BASESWAP 的讨论中有一个错误:伪代码的第 3 行中,(|\beta_{i+1}^{\left\langle T\right\rangle}|) 应替换为 (|\beta_{i}^{\left\langle T\right\rangle}|),算法的讨论中也是如此。
参见
property basic_orbits
返回相对于基和强生成集的基本轨道。
解释
如果 ((b_1, b_2, \dots, b_k)) 是群 (G) 的一个基,并且 (G^{(i)} = G_{b_1, b_2, \dots, b_{i-1}}) 是第 i
个基本稳定子(使得 (G^{(1)} = G)),则相对于此基的第 i
个基本轨道是 (b_i) 在 (G^{(i)}) 下的轨道。详见 [1] 第 87-89 页了解更多信息。
示例
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(4)
>>> S.basic_orbits
[[0, 1, 2, 3], [1, 2, 3], [2, 3]]
参见
base
,strong_gens
,basic_transversals
,basic_stabilizers
property basic_stabilizers
返回基于基和强生成集的稳定子链。
解释
相对于基 ((b_1, b_2, \dots, b_k)),第 i
个基本稳定子 (G^{(i)}) 是 (G_{b_1, b_2, \dots, b_{i-1}})。更多信息见 [1],第 87-89 页。
示例
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> A = AlternatingGroup(4)
>>> A.schreier_sims()
>>> A.base
[0, 1]
>>> for g in A.basic_stabilizers:
... print(g)
...
PermutationGroup([
(3)(0 1 2),
(1 2 3)])
PermutationGroup([
(1 2 3)])
另见
base
,strong_gens
,basic_orbits
,basic_transversals
property basic_transversals
返回基于基和强生成集的基本横截面。
解释
基本横截面是基本轨道的横截面。它们被提供为字典列表,每个字典具有键 - 一个基本轨道的元素,和值 - 相应的横截面元素。更多信息见 [1],第 87-89 页。
示例
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> A = AlternatingGroup(4)
>>> A.basic_transversals
[{0: (3), 1: (3)(0 1 2), 2: (3)(0 2 1), 3: (0 3 1)}, {1: (3), 2: (1 2 3), 3: (1 3 2)}]
另见
strong_gens
,base
,basic_orbits
,basic_stabilizers
center()
返回置换群的中心。
解释
对于群 (G) 的中心定义为 (Z(G) = {z\in G | \forall g\in G, zg = gz }),即与 (G) 中所有元素都可交换的 (G) 的元素的集合。它等于 (G) 在 (G) 中的中心化子,并且自然地是 (G) 的一个子群([9])。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(4)
>>> G = D.center()
>>> G.order()
2
注意事项
这是一个简单的应用 .centralizer()
的简单实现。
另见
centralizer
centralizer(other)
返回群/集合/元素的中心化子。
参数:
其他
置换群/置换列表/单一置换
解释:
集合 S
在群 G
内的中心化子是与 S
中所有元素都可交换的 G
中的元素集:
`C_G(S) = \{ g \in G | gs = sg \forall s \in S\}` ([10])
通常,S
是 G
的子集,但如果 G
是全置换群的真子群,则允许 S
中有元素在 G
外。
它自然是 G
的子群;置换群的中心化子等于该群任何一组生成元的中心化子,因为与生成元可交换的元素也与生成元的任何乘积可交换。
示例
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... CyclicGroup)
>>> S = SymmetricGroup(6)
>>> C = CyclicGroup(6)
>>> H = S.centralizer(C)
>>> H.is_subgroup(C)
True
注意:
实现是使用特定基础对群 G
进行 .subgroup_search()
应用的。
参见:
subgroup_search
commutator(G, H)
返回两个子群的对易子。
解释:
对于置换群 K
和子群 G
, H
,G
和 H
的对易子被定义为所有对易子 ([g, h] = hgh{-1}g) 生成的群。它自然是 K
的子群 ([1], p.27)。
示例:
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup)
>>> S = SymmetricGroup(5)
>>> A = AlternatingGroup(5)
>>> G = S.commutator(S, A)
>>> G.is_subgroup(A)
True
注意:
两个子群 (H, G) 的对易子等于所有生成元的对易子的正规闭包,即对 (H) 的生成元 (h) 和 (G) 的生成元 (g),即 (hgh{-1}g) ([1], p.28)
参见:
derived_subgroup
composition_series()
以列表形式返回群的组成系列。
解释:
对于群 (G) 的组成系列被定义为一个次正规系列 (G = H_0 > H_1 > H_2 \ldots)。组成系列是一个最长长度的次正规系列,每个因子群 (H(i+1) / H(i)) 都是简单的。
算法工作如下:从派生系列开始,想法是填补 (G = der[i]) 和 (H = der[i+1]) 之间的空白,对于每个 (i) 独立地。由于阿贝尔群 (G/H) 的所有子群都是正规的,因此第一步是将生成元 (g) 加入到生成元 (H) 中。
形成的因子群一般不是简单的。每个群是从前一个群 (H) 添加一个生成元 (g) 而得到的,如果前一个群用 (H) 表示,则下一个群 (K) 是由 (g) 和 (H) 生成的。因子群 (K/H) 是循环的,其阶数为 (K.order()//G.order()),然后通过 (g) 和 (H) 的幂来扩展这个系列。然后将形成的系列前置到已存在的系列。
示例:
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> from sympy.combinatorics.named_groups import CyclicGroup
>>> S = SymmetricGroup(12)
>>> G = S.sylow_subgroup(2)
>>> C = G.composition_series()
>>> [H.order() for H in C]
[1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
>>> G = S.sylow_subgroup(3)
>>> C = G.composition_series()
>>> [H.order() for H in C]
[243, 81, 27, 9, 3, 1]
>>> G = CyclicGroup(12)
>>> C = G.composition_series()
>>> [H.order() for H in C]
[12, 6, 3, 1]
conjugacy_class(x)
返回群中一个元素的共轭类。
解释
在群 G
中元素 g
的共轭类是与 g
共轭的元素 x
的集合,即对于这样的 x
,(x = hgh^{-1})。
g = xax^{-1}
对于G
中的某些a
。
注意共轭是一种等价关系,因此共轭类是G
的分区。要获得群的所有共轭类的列表,请使用 conjugacy_classes()方法。
在置换群中,每个共轭类对应于特定的cycle structure
:例如,在S_3
中,共轭类是:
- 单位类,
{()}
- 所有换位对,
{(1 2), (1 3), (2 3)}
- 所有 3-循环,
{(1 2 3), (1 3 2)}
例子
>>> from sympy.combinatorics import Permutation, SymmetricGroup
>>> S3 = SymmetricGroup(3)
>>> S3.conjugacy_class(Permutation(0, 1, 2))
{(0 1 2), (0 2 1)}
注意
该过程通过找到元素在G
下共轭的轨道直接计算共轭类。这种算法仅适用于相对较小阶的置换群,但在这方面类似于 orbit()函数本身。
conjugacy_classes()
返回群的共轭类。
解释
如在.conjugacy_class()函数的文档中描述的那样,共轭是群G
上的等价关系,它将元素集合划分为共轭类。此方法返回群G
的所有这些共轭类的列表。
例子
>>> from sympy.combinatorics import SymmetricGroup
>>> SymmetricGroup(3).conjugacy_classes()
[{(2)}, {(0 1 2), (0 2 1)}, {(0 2), (1 2), (2)(0 1)}]
contains(g, strict=True)
测试排列g
是否属于自身G
。
解释
如果g
是G
的元素,则它可以写成从G
的稳定子群的陪集中抽取因子的乘积。要查看g
是否是定义群的实际生成元之一,请使用G.has(g)
。
如果strict
不为True
,则如果需要,将调整g
的大小以匹配self
中的置换大小。
例子
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation(1, 2)
>>> b = Permutation(2, 3, 1)
>>> G = PermutationGroup(a, b, degree=5)
>>> G.contains(G[0]) # trivial check
True
>>> elem = Permutation([[2, 3]], size=5)
>>> G.contains(elem)
True
>>> G.contains(Permutation(4)(0, 1, 2, 3))
False
如果 strict 为 False,则将调整置换,如果需要:
>>> H = PermutationGroup(Permutation(5))
>>> H.contains(Permutation(3))
False
>>> H.contains(Permutation(3), strict=False)
True
测试给定置换是否存在于群中:
>>> elem in G.generators
False
>>> G.has(elem)
False
另见
coset_factor
, sympy.core.basic.Basic.has
, __contains__
coset_factor(g, factor_index=False)
返回G
的(自身的)g
的陪集因子分解。
解释
如果g
是G
的元素,则它可以写成从 Schreier-Sims 陪集分解中抽取的置换的乘积,
返回f
中的排列是那些其乘积给出g
的排列:g = f[n]*...f[1]*f[0]
,其中n = len(B)
且B = G.base
。f[i]
是self._basic_orbits[i]
中的置换之一。
如果factor_index==True
,返回元组[b[0],..,b[n]]
,其中b[i]
属于self._basic_orbits[i]
例子
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation(0, 1, 3, 7, 6, 4)(2, 5)
>>> b = Permutation(0, 1, 3, 2)(4, 5, 7, 6)
>>> G = PermutationGroup([a, b])
定义g
:
>>> g = Permutation(7)(1, 2, 4)(3, 6, 5)
确认它是G
的一个元素:
>>> G.contains(g)
True
因此,它可以写成从u
中抽取的因子(最多 3 个)的乘积。请参见下面,使用了来自u1
和u2
以及单位置换的因子:
>>> f = G.coset_factor(g)
>>> f[2]*f[1]*f[0] == g
True
>>> f1 = G.coset_factor(g, True); f1
[0, 4, 4]
>>> tr = G.basic_transversals
>>> f[0] == tr[0][f1[0]]
True
如果g
不是G
的元素,则返回[]
:
>>> c = Permutation(5, 6, 7)
>>> G.coset_factor(c)
[]
另见
sympy.combinatorics.util._strip
coset_rank(g)
使用 Schreier-Sims 表示排名。
解释
g
的陪集秩是它在按字典顺序列出的陪集分解中出现的顺序号。
排序与G.generate(method=’coset’)
中的相同。如果g
不属于该组,则返回 None。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation(0, 1, 3, 7, 6, 4)(2, 5)
>>> b = Permutation(0, 1, 3, 2)(4, 5, 7, 6)
>>> G = PermutationGroup([a, b])
>>> c = Permutation(7)(2, 4)(3, 5)
>>> G.coset_rank(c)
16
>>> G.coset_unrank(16)
(7)(2 4)(3 5)
参见
coset_factor
coset_table(H)
以列表形式返回自身在 H 中的标准化(右)陪集表。
coset_transversal(H)
使用[1]中描述的第二种方法,返回群self
在其子群H
的右陪集的横截面。
coset_unrank(rank, af=False)
使用 Schreier-Sims 表示法进行unrank
操作
如果 0 <= rank < order,则coset_unrank
是coset_rank
的反向操作;否则返回 None。
property degree
返回群中置换的大小。
解释
组合中的置换数量由len(group)
给出;可以由该组生成的置换数量由group.order()
给出。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([1, 0, 2])
>>> G = PermutationGroup([a])
>>> G.degree
3
>>> len(G)
1
>>> G.order()
2
>>> list(G.generate())
[(2), (2)(0 1)]
参见
order
derived_series()
返回群的衍生系列。
返回:
包含衍生成员的置换群列表
按照(G = G_0, G_1, G_2, \ldots)的顺序。
解释
对于群(G)的衍生系列定义为(G = G_0 > G_1 > G_2 > \ldots),其中(G_i = [G_{i-1}, G_{i-1}]),即(G_i)是(G_{i-1})的衍生子群,对于(i\in\mathbb{N})。当存在某个(k\in\mathbb{N}),使得(G_k = G_{k-1})时,系列终止。
示例
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup, DihedralGroup)
>>> A = AlternatingGroup(5)
>>> len(A.derived_series())
1
>>> S = SymmetricGroup(4)
>>> len(S.derived_series())
4
>>> S.derived_series()[1].is_subgroup(AlternatingGroup(4))
True
>>> S.derived_series()[2].is_subgroup(DihedralGroup(2))
True
参见
derived_subgroup
derived_subgroup()
计算衍生子群。
解释
衍生子群或交换子群是由所有交换子([g, h] = hgh{-1}g)生成的群;它等于生成器的交换子集的正规闭包([1],p.28,[11])。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([1, 0, 2, 4, 3])
>>> b = Permutation([0, 1, 3, 2, 4])
>>> G = PermutationGroup([a, b])
>>> C = G.derived_subgroup()
>>> list(C.generate(af=True))
[[0, 1, 2, 3, 4], [0, 1, 3, 4, 2], [0, 1, 4, 2, 3]]
参见
derived_series
property elements
以列表形式返回置换群的所有元素
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> p = PermutationGroup(Permutation(1, 3), Permutation(1, 2))
>>> p.elements
[(3), (3)(1 2), (1 3), (2 3), (1 2 3), (1 3 2)]
equals(other)
如果由群中元素生成的置换群相同,则返回True
,即它们表示同一个置换群。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> p = Permutation(0, 1, 2, 3, 4, 5)
>>> G = PermutationGroup([p, p**2])
>>> H = PermutationGroup([p**2, p])
>>> G.generators == H.generators
False
>>> G.equals(H)
True
generate(method='coset', af=False)
返回迭代器以生成群的元素。
解释
使用这些方法之一进行迭代:
method='coset' using the Schreier-Sims coset representation
method='dimino' using the Dimino method
如果af = True
,则产生置换的数组形式
示例
>>> from sympy.combinatorics import PermutationGroup
>>> from sympy.combinatorics.polyhedron import tetrahedron
在四面体对象中给出的置换群也是真实的群:
>>> G = tetrahedron.pgroup
>>> G.is_group
True
甚至四面体 pgroup 中生成的置换群(甚至前两个)也是一个适当的群:
>>> H = PermutationGroup(G[0], G[1])
>>> J = PermutationGroup(list(H.generate())); J
PermutationGroup([
(0 1)(2 3),
(1 2 3),
(1 3 2),
(0 3 1),
(0 2 3),
(0 3)(1 2),
(0 1 3),
(3)(0 2 1),
(0 3 2),
(3)(0 1 2),
(0 2)(1 3)])
>>> _.is_group
True
generate_dimino(af=False)
使用 Dimino 算法生成群元素。
如果af == True
,则产生置换的数组形式。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([0, 2, 3, 1])
>>> g = PermutationGroup([a, b])
>>> list(g.generate_dimino(af=True))
[[0, 1, 2, 3], [0, 2, 1, 3], [0, 2, 3, 1],
[0, 1, 3, 2], [0, 3, 2, 1], [0, 3, 1, 2]]
参考文献
[R75]
计算代数系统中排列群的各种算法的实现:AXIOM,N.J. Doye,M.Sc. Thesis
generate_schreier_sims(af=False)
使用 Schreier-Sims 表示法按照coset_rank
顺序生成群元素
如果 af = True
,则返回置换的数组形式。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([0, 2, 3, 1])
>>> g = PermutationGroup([a, b])
>>> list(g.generate_schreier_sims(af=True))
[[0, 1, 2, 3], [0, 2, 1, 3], [0, 3, 2, 1],
[0, 1, 3, 2], [0, 2, 3, 1], [0, 3, 1, 2]]
generator_product(g, original=False)
返回强生成器列表 ([s1, \dots, sn]),使得 (g = sn \times \dots \times s1)。如果 original=True
,则只包含原始群生成器的列表。
property generators
返回群的生成元。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.generators
[(1 2), (2)(0 1)]
property identity
返回置换群的单位元素。
index(H)
返回置换群的索引。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation(1,2,3)
>>> b =Permutation(3)
>>> G = PermutationGroup([a])
>>> H = PermutationGroup([b])
>>> G.index(H)
3
property is_abelian
测试群是否是阿贝尔的。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.is_abelian
False
>>> a = Permutation([0, 2, 1])
>>> G = PermutationGroup([a])
>>> G.is_abelian
True
is_alt_sym(eps=0.05, _random_prec=None)
对于度数大于等于 8 的对称/交替群进行蒙特卡罗测试。
解释
更具体地说,这是一个单侧蒙特卡罗测试,如果答案为 True(即,G 是对称/交替群),则保证是正确的,而答案为 False 则以 eps 的概率是错误的。
对于度数小于 8 的情况,检查群的顺序以确保测试是确定性的。
注意
算法本身使用了一些群论和数论中的非平凡结果:1)如果度数为 n
的传递群 G
包含一个长度为 n/2 < p < n-2
的循环元素,其中 p
是一个素数,则 G
是对称群或交替群([1],第 81-82 页)2)对称/交替群中具有 1)描述的属性的元素比例约为 (\log(2)/\log(n))([1],第 82 页;[2],第 226-227 页)。辅助函数 _check_cycles_alt_sym
用于检查排列中满足 1)的循环。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(10)
>>> D.is_alt_sym()
False
另请参阅
_check_cycles_alt_sym
property is_alternating
如果群是交替的,则返回True
。
示例
>>> from sympy.combinatorics import AlternatingGroup
>>> g = AlternatingGroup(5)
>>> g.is_alternating
True
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> g = PermutationGroup(
... Permutation(0, 1, 2, 3, 4),
... Permutation(2, 3, 4))
>>> g.is_alternating
True
注意
这使用了一个简单的测试,涉及到计算完整的群序。如果需要更快速的大群分类,可以使用PermutationGroup.is_alt_sym()
。然而,PermutationGroup.is_alt_sym()
可能不够准确,并且无法区分交替群和对称群。
另请参阅
is_alt_sym
property is_cyclic
如果群是循环的,则返回True
。
示例
>>> from sympy.combinatorics.named_groups import AbelianGroup
>>> G = AbelianGroup(3, 4)
>>> G.is_cyclic
True
>>> G = AbelianGroup(4, 4)
>>> G.is_cyclic
False
注意
如果群的顺序 (n) 可以分解为不同的素数 (p_1, p_2, \dots , p_s),并且如果
[\forall i, j \in {1, 2, \dots, s }: p_i \not \equiv 1 \pmod {p_j}]
如果成立,那么顺序为 (n) 的群只有一个循环群 [R76]。这是群的顺序为 (15, 35, \dots) 的引理的一般化。
同时,这些额外的引理还可以用来测试群是否循环,如果已知群的顺序。
-
如果群是阿贝尔群并且群的顺序是无平方的,则群是循环的。
-
如果群的顺序小于 (6) 并且不是 (4),则该群是循环的。
-
如果群的阶是素数,则群是循环的。
参考文献
[R76] (1,2)
1978: John S. Rose: A Course on Group Theory, Introduction to Finite Group Theory: 1.4
property is_dihedral
如果群是二面角的,则返回 True
。
示例
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.named_groups import SymmetricGroup, CyclicGroup
>>> G = PermutationGroup(Permutation(1, 6)(2, 5)(3, 4), Permutation(0, 1, 2, 3, 4, 5, 6))
>>> G.is_dihedral
True
>>> G = SymmetricGroup(3)
>>> G.is_dihedral
True
>>> G = CyclicGroup(6)
>>> G.is_dihedral
False
参考文献
[Di1]
[Di2]
kconrad.math.uconn.edu/blurbs/grouptheory/dihedral.pdf
[Di3]
kconrad.math.uconn.edu/blurbs/grouptheory/dihedral2.pdf
[Di4]
en.wikipedia.org/wiki/Dihedral_group
is_elementary(p)
如果群是基本阿贝尔的,则返回 True
。一个基本阿贝尔群是一个有限阿贝尔群,其中每个非平凡元素的阶为 (p),其中 (p) 是一个素数。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> G = PermutationGroup([a])
>>> G.is_elementary(2)
True
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([3, 1, 2, 0])
>>> G = PermutationGroup([a, b])
>>> G.is_elementary(2)
True
>>> G.is_elementary(3)
False
property is_nilpotent
测试群是否幂零。
解释
如果一个群 (G) 具有有限长度的中心级数,则它是幂零的。或者,如果 (G) 的下中心级数以平凡群终止,则 (G) 是幂零的。每个幂零群也是可解的([1], p.29, [12])。
示例
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... CyclicGroup)
>>> C = CyclicGroup(6)
>>> C.is_nilpotent
True
>>> S = SymmetricGroup(5)
>>> S.is_nilpotent
False
参见
lower_central_series
, is_solvable
is_normal(gr, strict=True)
测试 G=self
是否是 gr
的正规子群。
解释
如果对于每个 g2
属于 G
和 g1
属于 gr
,g = g1*g2*g1**-1
属于 G
,则 G
在 gr
中是正规的。对于 gr.generators
中的每个 g1
和 G.generators
中的每个 g2
检查这一点就足够了。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([1, 2, 0])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G1 = PermutationGroup([a, Permutation([2, 0, 1])])
>>> G1.is_normal(G)
True
property is_perfect
如果群是完全的,则返回 True
。如果一个群等于它的导出子群,则它是完全的。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation(1,2,3)(4,5)
>>> b = Permutation(1,2,3,4,5)
>>> G = PermutationGroup([a, b])
>>> G.is_perfect
False
property is_polycyclic
如果一个群是多项循环的,则返回 True
。如果一个群具有循环因子的子正规级数,则该群是多项循环的。对于有限群,这与群是否可解是相同的。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([2, 0, 1, 3])
>>> G = PermutationGroup([a, b])
>>> G.is_polycyclic
True
is_primitive(randomized=True)
测试一个群是否是原始的。
解释
如果一个置换群 G
作用在集合 S
上,且 S
不含 G
的非平凡块(块的基数大于 1
),则称 G
为原始的。
注意
算法在 [1], p.83 中描述,并使用函数 minimal_block 来搜索形式为 ({0, k}) 的块,其中 k
是 (G_0) 的轨道代表的范围。该算法的复杂度为 (O(n²)),其中 n
是群的阶数,在 (G_0) 较小时性能较差。
提供两种实现:一种使用函数stabilizer
确定性地找到 (G_0),另一种(默认)使用random_stab
产生 (G_0) 的随机元素,希望它们生成的子群具有不多于 (G_0) 的轨道(这在[1], p.83 中建议)。行为由randomized
标志改变。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(10)
>>> D.is_primitive()
False
另见
minimal_block
, random_stab
property is_solvable
测试群是否可解。
如果其导出级数以平凡群结束,则G
是可解的([1], p.29)。
示例
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(3)
>>> S.is_solvable
True
另见
is_nilpotent
, derived_series
is_subgroup(G, strict=True)
如果self
的所有元素都属于G
,则返回True
。
如果strict
为False
,则如果self
的次数小于G
的次数,则将调整元素大小以使它们具有相同的次数。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> from sympy.combinatorics import SymmetricGroup, CyclicGroup
默认情况下测试是严格的:每个群的次数必须相同:
>>> p = Permutation(0, 1, 2, 3, 4, 5)
>>> G1 = PermutationGroup([Permutation(0, 1, 2), Permutation(0, 1)])
>>> G2 = PermutationGroup([Permutation(0, 2), Permutation(0, 1, 2)])
>>> G3 = PermutationGroup([p, p**2])
>>> assert G1.order() == G2.order() == G3.order() == 6
>>> G1.is_subgroup(G2)
True
>>> G1.is_subgroup(G3)
False
>>> G3.is_subgroup(PermutationGroup(G3[1]))
False
>>> G3.is_subgroup(PermutationGroup(G3[0]))
True
若要忽略大小,请将strict
设置为False
:
>>> S3 = SymmetricGroup(3)
>>> S5 = SymmetricGroup(5)
>>> S3.is_subgroup(S5, strict=False)
True
>>> C7 = CyclicGroup(7)
>>> G = S5*C7
>>> S5.is_subgroup(G, False)
True
>>> C7.is_subgroup(G, 0)
False
property is_symmetric
如果群是对称的,则返回True
。
示例
>>> from sympy.combinatorics import SymmetricGroup
>>> g = SymmetricGroup(5)
>>> g.is_symmetric
True
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> g = PermutationGroup(
... Permutation(0, 1, 2, 3, 4),
... Permutation(2, 3))
>>> g.is_symmetric
True
注释
这使用一个涉及计算完整群序的朴素测试。如果您需要更快速地为大群分类,您可以使用PermutationGroup.is_alt_sym()
。然而,PermutationGroup.is_alt_sym()
可能不够精确,并且不能区分交替群和对称群。
另见
is_alt_sym
is_transitive(strict=True)
测试群是否是传递的。
解释
如果一个群只有一个轨道,则该群是传递的。
如果strict
为False
,则如果群只有一个长度不为 1 的轨道,则该群是传递的。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1, 3])
>>> b = Permutation([2, 0, 1, 3])
>>> G1 = PermutationGroup([a, b])
>>> G1.is_transitive()
False
>>> G1.is_transitive(strict=False)
True
>>> c = Permutation([2, 3, 0, 1])
>>> G2 = PermutationGroup([a, c])
>>> G2.is_transitive()
True
>>> d = Permutation([1, 0, 2, 3])
>>> e = Permutation([0, 1, 3, 2])
>>> G3 = PermutationGroup([d, e])
>>> G3.is_transitive() or G3.is_transitive(strict=False)
False
property is_trivial
测试群是否是平凡群。
如果群仅包含单位置换,则为真。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> G = PermutationGroup([Permutation([0, 1, 2])])
>>> G.is_trivial
True
lower_central_series()
返回群的下中心级数。
一个群 (G) 的下中心级数是级数 (G = G_0 > G_1 > G_2 > \ldots),其中 (G_k = [G, G_{k-1}]),即第一个术语之后的每个术语都等于(G)与(G1)中的上一个术语的交换([1], p.29)。
返回:
按顺序列出排列群的列表 (G = G_0, G_1, G_2, \ldots)
示例
>>> from sympy.combinatorics.named_groups import (AlternatingGroup,
... DihedralGroup)
>>> A = AlternatingGroup(4)
>>> len(A.lower_central_series())
2
>>> A.lower_central_series()[1].is_subgroup(DihedralGroup(2))
True
另见
commutator
, derived_series
make_perm(n, seed=None)
将 pgroup 中随机选择的 n
个排列相乘,从单位排列开始。如果 n
是整数列表,则这些整数将用于选择排列,并且它们将按照从左到右的顺序应用:make_perm((A, B, C)) 将给出 CBA(I),其中 I 是单位排列。
seed
用于设置从 pgroup 中随机选择排列的种子。如果这是一个整数列表,则将按照给定的顺序选择 pgroup 中对应的排列。这主要用于测试目的。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a, b = [Permutation([1, 0, 3, 2]), Permutation([1, 3, 0, 2])]
>>> G = PermutationGroup([a, b])
>>> G.make_perm(1, [0])
(0 1)(2 3)
>>> G.make_perm(3, [0, 1, 0])
(0 2 3 1)
>>> G.make_perm([0, 1, 0])
(0 2 3 1)
另见
random
property max_div
排列群的最大真约数。
解释
显然,这是度数除以其最小真约数(大于 1
,如果存在的话)。由于它保证是素数,所以使用 sympy.ntheory
中的 sieve
。此函数也用作函数 minimal_block
和 _union_find_merge
的优化工具。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> G = PermutationGroup([Permutation([0, 2, 1, 3])])
>>> G.max_div
2
另见
minimal_block
, _union_find_merge
minimal_block(points)
对于传递群,找到由 points
生成的块系统。
解释
如果群 G
作用于集合 S
,则 S
的非空子集 B
在 G
的作用下称为一个块,如果对于所有 g
属于 G
,我们有 gB = B
(g
使 B
固定)或者 gB
和 B
没有共同的点(g
将 B
移动整个)。([1],第 23 页; [6])。
对于群 G
中的 g
的块 B
的不同平移 gB
,将集合 S
划分,并且这组平移被称为一个块系统。此外,显然地,分区中的所有块具有相同的大小,因此块大小整除 |S|
([1],第 23 页)。G
-同余是集合 S
上的等价关系 ~
,使得 a ~ b
意味着对于所有 g
属于 G
,有 g(a) ~ g(b)
。对于一个传递群,G
-同余的等价类与块系统中的块是同一回事([1],第 23 页)。
下面的算法检查群是否传递,然后找到由对 (p_0, p_1), (p_0, p_2), ..., (p_0,p_{k-1})
生成的 G
-同余,这与找到具有最小块大小的最大块系统相同,使得 p_0, ..., p_{k-1}
在同一个块中([1],第 83 页)。
它是 Atkinson 算法的实现,如[1]建议的,使用并查集数据结构操作集合 S
上的等价关系。运行时间略高于 (O(|points||S|))。([1], pp. 83-87; [7])。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(10)
>>> D.minimal_block([0, 5])
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
>>> D.minimal_block([0, 1])
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
参见
_union_find_rep
, _union_find_merge
, is_transitive
, is_primitive
minimal_blocks(randomized=True)
对于一个传递群,返回所有最小块系统的列表。如果一个群是不可传递的,则返回 (False)。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> DihedralGroup(6).minimal_blocks()
[[0, 1, 0, 1, 0, 1], [0, 1, 2, 0, 1, 2]]
>>> G = PermutationGroup(Permutation(1,2,5))
>>> G.minimal_blocks()
False
参见
minimal_block
, is_transitive
, is_primitive
normal_closure(other, k=10)
返回子群/排列集合的正规闭包。
参数:
other
排列的子群/列表/单个排列
k
一个特定于实现的参数,确定一次将多少共轭附加到
other
上
解释
若 S
是群 G
的子集,则 A
在 G
中的正规闭包定义为包含 A
的所有 G
的正规子群的交集 ([1], p.14)。或者,它是由共轭元 x^{-1}yx
生成的群,其中 x
是 G
的生成元,y
是子群 \left\langle S\right\rangle
(对于 \left\langle S\right\rangle
的某个选择的生成集)的生成元 ([1], p.73)。
示例
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... CyclicGroup, AlternatingGroup)
>>> S = SymmetricGroup(5)
>>> C = CyclicGroup(5)
>>> G = S.normal_closure(C)
>>> G.order()
60
>>> G.is_subgroup(AlternatingGroup(5))
True
注意
该算法在[1]第 73-74 页中描述;它利用产品替换算法生成排列群的随机元素。
参见
commutator
, derived_subgroup
, random_pr
orbit(alpha, action='tuples')
计算 alpha 的轨道 ({g(\alpha) | g \in G}) 作为一个集合。
解释
此处使用的算法的时间复杂度为(O(|Orb|*r)),其中( |Orb| )是轨道的大小,r
是群的生成器数目。有关更详细的分析,请参见[1],第 78 页,[2],第 19-21 页。这里的 alpha 可以是单个点,也可以是点列表。
如果 alpha 是单个点,则计算普通轨道。如果 alpha 是点列表,则有三个可用选项:
'union' - 计算列表中点的轨道的并集 'tuples' - 在群作用下计算列表的轨道(即,g((1,2,3)) = (g(1), g(2), g(3))) 'sets' - 计算列表的轨道,解释为集合
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([1, 2, 0, 4, 5, 6, 3])
>>> G = PermutationGroup([a])
>>> G.orbit(0)
{0, 1, 2}
>>> G.orbit([0, 4], 'union')
{0, 1, 2, 3, 4, 5, 6}
参见
orbit_transversal
orbit_rep(alpha, beta, schreier_vector=None)
返回一个将alpha
发送到beta
的群元素。
解释
如果beta
不在alpha
的轨道上,则函数返回False
。此实现使用了 Schreier 向量。关于正确性的证明,请参见[1],第 80 页。
示例
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> G = AlternatingGroup(5)
>>> G.orbit_rep(0, 4)
(0 4 1 2 3)
参见
schreier_vector
orbit_transversal(alpha, pairs=False)
计算alpha
轨道的横断面。
解释
对于置换群( G ),轨道( Orb = {g(\alpha) | g \in G} )的一个横断面是集合( {g_\beta | g_\beta(\alpha) = \beta} ),其中( \beta \in Orb )。请注意可能存在多个可能的横断面。如果pairs
设为True
,则返回配对列表((\beta, g_\beta))。关于正确性的证明,请参见[1],第 79 页。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> G = DihedralGroup(6)
>>> G.orbit_transversal(0)
[(5), (0 1 2 3 4 5), (0 5)(1 4)(2 3), (0 2 4)(1 3 5), (5)(0 4)(1 3), (0 3)(1 4)(2 5)]
参见
orbit
orbits(rep=False)
返回self
的轨道,根据每个轨道中的最小元素排序。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation(1, 5)(2, 3)(4, 0, 6)
>>> b = Permutation(1, 5)(3, 4)(2, 6, 0)
>>> G = PermutationGroup([a, b])
>>> G.orbits()
[{0, 2, 3, 4, 6}, {1, 5}]
order()
返回群的阶数:可以从群的元素生成的排列数。
群的排列数由len(group)
给出;群中每个排列的长度由group.size
给出。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([1, 0, 2])
>>> G = PermutationGroup([a])
>>> G.degree
3
>>> len(G)
1
>>> G.order()
2
>>> list(G.generate())
[(2), (2)(0 1)]
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.order()
6
参见
degree
pointwise_stabilizer(points, incremental=True)
返回点集的点对稳定子。
解释
对于置换群( G )和点集({p_1, p_2,\ldots, p_k}),(p_1, p_2, \ldots, p_k)的点对稳定子定义为(G_{p_1,\ldots, p_k} = {g\in G | g(p_i) = p_i \forall i\in{1, 2,\ldots,k}})([1],第 20 页)。它是(G)的子群。
示例
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(7)
>>> Stab = S.pointwise_stabilizer([2, 3, 5])
>>> Stab.is_subgroup(S.stabilizer(2).stabilizer(3).stabilizer(5))
True
注意
当incremental == True
时,与使用连续调用.stabilizer()
的明显实现不同,这里使用增量 Schreier-Sims 算法来获得具有起始段的基。
参见
stabilizer
, schreier_sims_incremental
polycyclic_group()
返回具有以下参数的 PolycyclicGroup 实例:
解释
-
pc_sequence:多项式序列是通过在给定置换群的导出序列中的相邻群之间收集所有缺失的生成器而形成的。
-
pc_series:多项式系列是通过在
der[i]
中添加der[i+1]
中的所有缺失生成器而形成的,其中der
表示导出系列。 -
相对阶:由 pc_series 中相邻群的比率计算的列表。
presentation(eliminate_gens=True)
返回群的(FpGroup)演示。
该算法在[1],第 6.1 章中描述。
random(af=False)
返回一个随机群元素
random_pr(gen_count=11, iterations=50, _random_prec=None)
使用乘积替换返回一个随机群元素。
解释
有关乘积替换算法的详细信息,请参见_random_pr_init
在random_pr
中执行实际的‘乘积替换’。请注意,如果属性_random_gens
为空,则需要通过_random_pr_init
进行初始化。
另请参阅
_random_pr_init
random_stab(alpha, schreier_vector=None, _random_prec=None)
alpha
的稳定器的随机元素。
alpha
的 Schreier 向量是用于加速重复调用的可选参数。该算法在[1],第 81 页中描述。
另请参阅
random_pr
, orbit_rep
schreier_sims()
Schreier-Sims 算法。
解释
它计算稳定器链(G > G_{b_1} > .. > G_{b1,..,b_r} > 1)的生成器,其中(G_{b_1,..,b_i})稳定(b_1,..,b_i),以及相应的s
余类。群的一个元素可以写成乘积(h_1..h_s)。
我们使用增量 Schreier-Sims 算法。
例子
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([0, 2, 1])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.schreier_sims()
>>> G.basic_transversals
[{0: (2)(0 1), 1: (2), 2: (1 2)},
{0: (2), 2: (0 2)}]
schreier_sims_incremental(base=None, gens=None, slp_dict=False)
将一系列点和生成集扩展为基础和强生成集。
参数:
base
要扩展为基础的点序列。可选参数,默认值为
[]
。
gens
要扩展的生成集相对于获得的基础的强生成集。可选参数,默认值为
self.generators
。
slp_dict
如果为(True),则为每个强生成器(g)返回一个字典({g: gens}),其中(gens)是在(strong_gens)中的(g)之前出现的强生成器的列表,使得(gens)的元素的乘积等于(g)。
返回:
(base, strong_gens)
base
是获得的基础,strong_gens
是相对于它的强生成集。原始参数base
,gens
保持不变。
例子
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> A = AlternatingGroup(7)
>>> base = [2, 3]
>>> seq = [2, 3]
>>> base, strong_gens = A.schreier_sims_incremental(base=seq)
>>> _verify_bsgs(A, base, strong_gens)
True
>>> base[:2]
[2, 3]
注意
该版本的 Schreier-Sims 算法运行在多项式时间内。实施中存在某些假设 - 如果提供了平凡群,则立即返回base
和gens
,因为任何点序列都是平凡群的基础。如果生成器gens
中存在恒等元素,则将其移除,因为它是冗余生成器。实现描述在[1],第 90-93 页。
参见
schreier_sims
,schreier_sims_random
schreier_sims_random(base=None, gens=None, consec_succ=10, _random_prec=None)
随机化的 Schreier-Sims 算法。
参数:
base
要扩展为基础的序列。
gens
要扩展为强生成集的生成集。
consec_succ
定义错误答案概率的参数。
_random_prec
用于测试目的的内部参数。
返回:
(base, strong_gens)
base
是基础,strong_gens
是相对于它的强生成集。
解释
随机化的 Schreier-Sims 算法使用序列base
和生成集gens
,将base
扩展到基础,并相对于该基础将gens
扩展为强生成集,提供错误答案的概率最多为(2^{-consec_succ}),前提是随机生成器足够随机。
示例
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(5)
>>> base, strong_gens = S.schreier_sims_random(consec_succ=5)
>>> _verify_bsgs(S, base, strong_gens)
True
注释
该算法详细描述在[1],第 97-98 页。它将轨道orbs
和置换群stabs
扩展到最终生成的基本轨道和基本稳定器的基础和强生成集。扩展过程的思想是通过稳定器链“筛选”随机群元素,并在筛选不成功时在路上修正稳定器/轨道。助手函数_strip
用于尝试根据当前稳定器链的状态分解随机群元素,并报告元素是否完全分解(成功筛选)或否(失败筛选)。在后一种情况下,报告筛选失败的级别,并相应地修正stabs
,base
,gens
和orbs
。停止条件是连续consec_succ
次成功筛选。这确保当前的base
和gens
以至少(1 - 1/\text{consec_succ})的概率形成 BSGS。
参见
schreier_sims
schreier_vector(alpha)
计算alpha
的 Schreier 向量。
解释
Schreier 向量高效存储关于 alpha
轨道的信息。稍后可用于快速获取将 alpha
发送到轨道中特定元素的群的元素。注意,Schreier 向量取决于群生成器列出的顺序。定义详见 [3]。由于列表索引从零开始,我们采用“None”作为标记,表示元素不属于轨道。有关算法及其正确性详见 [2],第 78-80 页。
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([2, 4, 6, 3, 1, 5, 0])
>>> b = Permutation([0, 1, 3, 5, 4, 6, 2])
>>> G = PermutationGroup([a, b])
>>> G.schreier_vector(0)
[-1, None, 0, 1, None, 1, 0]
参见
orbit
stabilizer(alpha)
返回 alpha
的稳定子群。
解释
(\alpha) 的稳定子群是群 (G_\alpha = {g \in G | g(\alpha) = \alpha})。正确性证明见 [1],第 79 页。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> G = DihedralGroup(6)
>>> G.stabilizer(5)
PermutationGroup([
(5)(0 4)(1 3)])
参见
orbit
property strong_gens
从 Schreier-Sims 算法返回一个强生成集。
解释
置换群 (G) 的生成集合 (S = {g_1, g_2, \dots, g_t}) 相对于点序列(称为“基”)((b_1, b_2, \dots, b_k)) 是强生成集,如果对于 (1 \leq i \leq k),点对稳定子 (G^{(i+1)} := G_{b_1, b_2, \dots, b_i}) 与 (S) 的交集生成点对稳定子 (G^{(i+1)})。关于基和强生成集的概念及其应用在 [1],第 87-89 页和 [2],第 55-57 页详细讨论。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> D = DihedralGroup(4)
>>> D.strong_gens
[(0 1 2 3), (0 3)(1 2), (1 3)]
>>> D.base
[0, 1]
参见
base
,basic_transversals
,basic_orbits
,basic_stabilizers
strong_presentation()
返回群的强有限表示。返回群的生成器与强生成器的顺序相同。
该算法基于 Sims 的 Verify 算法,详见 [1],第六章。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> P = DihedralGroup(4)
>>> G = P.strong_presentation()
>>> P.order() == G.order()
True
参见
presentation
,_verify
subgroup(gens)
返回由群元素列表 gens
生成的子群。
subgroup_search(prop, base=None, strong_gens=None, tests=None, init_subgroup=None)
查找所有满足属性 prop
的元素的子群。
参数:
prop
用于被使用的属性。必须在群元素上可调用,并始终返回
True
或False
。假设所有满足prop
的群元素确实形成一个子群。
base
超群的一个基。
strong_gens
超群的一个强生成集。
tests
一个长度等于
base
长度的可调用对象列表。这些用于通过部分基映像排除群元素,因此如果元素g
已知不满足prop
,则testsl
返回 False。
init_subgroup
如果预先知道所寻找群的一个子群,则可以将其作为此参数传递给函数。
返回:
res
满足
prop
的所有元素的子群。保证该群的生成集相对于基base
是一个强生成集。
解释
这是一种深度优先搜索,考虑基映像,并使用多个测试来修剪搜索树。
示例
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup)
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> S = SymmetricGroup(7)
>>> prop_even = lambda x: x.is_even
>>> base, strong_gens = S.schreier_sims_incremental()
>>> G = S.subgroup_search(prop_even, base=base, strong_gens=strong_gens)
>>> G.is_subgroup(AlternatingGroup(7))
True
>>> _verify_bsgs(G, base, G.generators)
True
注意事项
这个函数非常长且复杂,需要仔细注意。该实现在[1],第 114-117 页中描述,此处的代码注释遵循书中伪代码以确保清晰。
一般情况下,复杂度是指数级的,因为搜索过程本身访问超群的所有成员。然而,有许多测试用于修剪搜索树,用户可以通过tests
参数定义自己的测试,因此在实践中,对于某些计算而言,情况并不糟糕。
程序中关键的一部分是执行频繁的基变换(这是伪代码中的第 11 行),以获得一个新的基本稳定器。书中提到可以通过使用.baseswap(...)
来实现,但当前的实现使用更直接的方法来找到下一个基本稳定器 - 在前一个基本稳定器上调用函数.stabilizer(...)
。
sylow_subgroup(p)
返回群的一个 p-Sylow 子群。
该算法在[1],第四章,第七部分中描述。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> D = DihedralGroup(6)
>>> S = D.sylow_subgroup(2)
>>> S.order()
4
>>> G = SymmetricGroup(6)
>>> S = G.sylow_subgroup(5)
>>> S.order()
5
>>> G1 = AlternatingGroup(3)
>>> G2 = AlternatingGroup(5)
>>> G3 = AlternatingGroup(9)
>>> S1 = G1.sylow_subgroup(3)
>>> S2 = G2.sylow_subgroup(3)
>>> S3 = G3.sylow_subgroup(3)
>>> len1 = len(S1.lower_central_series())
>>> len2 = len(S2.lower_central_series())
>>> len3 = len(S3.lower_central_series())
>>> len1 == len2
True
>>> len1 < len3
True
property transitivity_degree
计算群的传递度。
解释
作用于集合(\Omega = {0, 1, \dots, n-1})的置换群(G)是k
-重传递的,如果对于任意(k)个点((a_1, a_2, \dots, a_k) \in \Omega)和任意(k)个点((b_1, b_2, \dots, b_k) \in \Omega),存在(g \in G)使得(g(a_1) = b_1, g(a_2) = b_2, \dots, g(a_k) = b_k)。群(G)的传递度是最大的k
,使得(G)是k
-重传递的。([8])
示例
>>> from sympy.combinatorics import Permutation, PermutationGroup
>>> a = Permutation([1, 2, 0])
>>> b = Permutation([1, 0, 2])
>>> G = PermutationGroup([a, b])
>>> G.transitivity_degree
3
另请参阅
is_transitive
,orbit
多面体
原文:
docs.sympy.org/latest/modules/combinatorics/polyhedron.html
class sympy.combinatorics.polyhedron.Polyhedron(corners, faces=(), pgroup=())
表示多面体对称群(PSG)。
解释
PSG 是五正立体的对称群之一。有三个多面体群:12 阶四面体群,24 阶八面体群和 60 阶二十面体群。
所有的 doctest 都在对象构造函数的 docstring 中给出。
参考文献
[R92]
mathworld.wolfram.com/PolyhedralGroup.html
property array_form
返回角落的索引。
索引是相对于角落的原始位置给出的。
示例
>>> from sympy.combinatorics.polyhedron import tetrahedron
>>> tetrahedron = tetrahedron.copy()
>>> tetrahedron.array_form
[0, 1, 2, 3]
>>> tetrahedron.rotate(0)
>>> tetrahedron.array_form
[0, 2, 3, 1]
>>> tetrahedron.pgroup[0].array_form
[0, 2, 3, 1]
请参见
corners
,cyclic_form
property corners
获取多面体的角落。
方法vertices
是corners
的别名。
示例
>>> from sympy.combinatorics import Polyhedron
>>> from sympy.abc import a, b, c, d
>>> p = Polyhedron(list('abcd'))
>>> p.corners == p.vertices == (a, b, c, d)
True
请参见
array_form
,cyclic_form
property cyclic_form
返回循环表示法中角落的索引。
索引是相对于角落的原始位置给出的。
请参见
corners
,array_form
property edges
给定多面体的面,我们可以获得边。
示例
>>> from sympy.combinatorics import Polyhedron
>>> from sympy.abc import a, b, c
>>> corners = (a, b, c)
>>> faces = [(0, 1, 2)]
>>> Polyhedron(corners, faces).edges
{(0, 1), (0, 2), (1, 2)}
property faces
获取多面体的面。
property pgroup
获取多面体的排列。
reset()
将角落返回到它们的原始位置。
示例
>>> from sympy.combinatorics.polyhedron import tetrahedron as T
>>> T = T.copy()
>>> T.corners
(0, 1, 2, 3)
>>> T.rotate(0)
>>> T.corners
(0, 2, 3, 1)
>>> T.reset()
>>> T.corners
(0, 1, 2, 3)
rotate(perm)
将置换就地应用于多面体。置换可以作为置换实例或表示应用于多面体的pgroup
中的哪个置换的整数来给出。
这是一种类似于围绕轴的固定增量旋转的操作。
注意事项
当应用置换时,不检查它是否对多面体有效。例如,可以给立方体应用一个只交换两个顶点的置换。如果只使用多面体的pgroup
中的置换,则会获得有效的置换(将对象以物理方式旋转)。另一方面,允许任意旋转(应用置换)可以通过名称元素的方式进行跟踪,因为多面体允许对顶点进行命名,而置换仅使用索引。
示例
>>> from sympy.combinatorics import Polyhedron, Permutation
>>> from sympy.combinatorics.polyhedron import cube
>>> cube = cube.copy()
>>> cube.corners
(0, 1, 2, 3, 4, 5, 6, 7)
>>> cube.rotate(0)
>>> cube.corners
(1, 2, 3, 0, 5, 6, 7, 4)
非物理“旋转”,不受此方法禁止。
>>> cube.reset()
>>> cube.rotate(Permutation([[1, 2]], size=8))
>>> cube.corners
(0, 2, 1, 3, 4, 5, 6, 7)
多面体可以用于跟踪用字母标识而不是整数的集合元素:
>>> shadow = h5 = Polyhedron(list('abcde'))
>>> p = Permutation([3, 0, 1, 2, 4])
>>> h5.rotate(p)
>>> h5.corners
(d, a, b, c, e)
>>> _ == shadow.corners
True
>>> copy = h5.copy()
>>> h5.rotate(p)
>>> h5.corners == copy.corners
False
property size
获取多面体的角落数。
property vertices
获取多面体的角点。
方法vertices
是corners
的别名。
示例
>>> from sympy.combinatorics import Polyhedron
>>> from sympy.abc import a, b, c, d
>>> p = Polyhedron(list('abcd'))
>>> p.corners == p.vertices == (a, b, c, d)
True
另请参见
array_form
, cyclic_form
Prufer 序列
class sympy.combinatorics.prufer.Prufer(*args, **kw_args)
Prufer 对应是一种描述标记树和 Prufer 代码之间双射的算法。标记树的 Prufer 代码在同构下是唯一的,并且长度为 n - 2。
Prufer 序列最初由 Heinz Prufer 使用,用于证明 Cayley 公式。
参考文献
[R93]
mathworld.wolfram.com/LabeledTree.html
static edges(*runs)
返回给定运行连接整数标记的树中节点的边列表和节点数量。
所有节点编号将被转移,以使最小节点为 0. 如果在运行中重复边,不会产生问题;仅返回唯一边。对节点标签的范围没有假设,但必须包含从最小到最大的所有节点。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer.edges([1, 2, 3], [2, 4, 5]) # a T
([[0, 1], [1, 2], [1, 3], [3, 4]], 5)
删除重复的边:
>>> Prufer.edges([0, 1, 2, 3], [1, 4, 5], [1, 4, 6]) # a K
([[0, 1], [1, 2], [1, 4], [2, 3], [4, 5], [4, 6]], 7)
next(delta=1)
生成当前序列之后的 delta Prufer 序列。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> b = a.next(1) # == a.next()
>>> b.tree_repr
[[0, 2], [0, 1], [1, 3]]
>>> b.rank
1
参见
prufer_rank
, rank
, prev
, size
property nodes
返回树中节点的数量。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).nodes
6
>>> Prufer([1, 0, 0]).nodes
5
prev(delta=1)
生成当前序列之前的 -delta Prufer 序列。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [1, 2], [2, 3], [1, 4]])
>>> a.rank
36
>>> b = a.prev()
>>> b
Prufer([1, 2, 0])
>>> b.rank
35
参见
prufer_rank
, rank
, next
, size
prufer_rank()
计算 Prufer 序列的秩。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> a.prufer_rank()
0
参见
rank
, next
, prev
, size
property prufer_repr
返回 Prufer 对象的 Prufer 序列。
此序列是通过移除编号最高的顶点、记录其连接到的节点,并继续此过程直到仅剩两个顶点为止找到的。Prufer 序列即为记录的节点列表。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).prufer_repr
[3, 3, 3, 4]
>>> Prufer([1, 0, 0]).prufer_repr
[1, 0, 0]
参见
to_prufer
property rank
返回 Prufer 序列的秩。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> p = Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]])
>>> p.rank
778
>>> p.next(1).rank
779
>>> p.prev().rank
777
参见
prufer_rank
, next
, prev
, size
property size
返回此 Prufer 对象可能的树的数量。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([0]*4).size == Prufer([6]*4).size == 1296
True
参见
prufer_rank
, rank
, next
, prev
static to_prufer(tree, n)
返回作为边列表的树的 Prufer 序列,其中n
是树中的节点数。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> a.prufer_repr
[0, 0]
>>> Prufer.to_prufer([[0, 1], [0, 2], [0, 3]], 4)
[0, 0]
参见
prufer_repr
返回 Prufer 对象的 Prufer 序列。
static to_tree(prufer)
返回给定 Prufer 序列的树(作为边列表)。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([0, 2], 4)
>>> a.tree_repr
[[0, 1], [0, 2], [2, 3]]
>>> Prufer.to_tree([0, 2])
[[0, 1], [0, 2], [2, 3]]
参见
tree_repr
返回 Prufer 对象的树表示。
参考文献
[R94]
hamberg.no/erlend/posts/2010-11-06-prufer-sequence-compact-tree-representation.html
property tree_repr
返回 Prufer 对象的树表示。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).tree_repr
[[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]
>>> Prufer([1, 0, 0]).tree_repr
[[1, 2], [0, 1], [0, 3], [0, 4]]
参见
to_tree
classmethod unrank(rank, n)
找到未排序的 Prufer 序列。
示例
>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer.unrank(0, 4)
Prufer([0, 0])
子集
class sympy.combinatorics.subsets.Subset(subset, superset)
表示基本子集对象。
解释
我们基本上使用两种技术生成子集,即二进制枚举和词典排序枚举。Subset 类接受两个参数,第一个描述要考虑的初始子集,第二个描述超集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.next_binary().subset
['b']
>>> a.prev_binary().subset
['c']
classmethod bitlist_from_subset(subset, superset)
获取与子集对应的位列表。
示例
>>> from sympy.combinatorics import Subset
>>> Subset.bitlist_from_subset(['c', 'd'], ['a', 'b', 'c', 'd'])
'0011'
另请参阅
subset_from_bitlist
property cardinality
返回所有可能子集的数量。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.cardinality
16
另请参阅
subset
, superset
, size
, superset_size
iterate_binary(k)
这是一个辅助函数。它通过k
步迭代二进制子集。该变量可以是正数或负数。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.iterate_binary(-2).subset
['d']
>>> a = Subset(['a', 'b', 'c'], ['a', 'b', 'c', 'd'])
>>> a.iterate_binary(2).subset
[]
另请参阅
next_binary
, prev_binary
iterate_graycode(k)
用于 prev_gray 和 next_gray 的辅助函数。它执行k
步跨越以获取相应的 Gray 码。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset([1, 2, 3], [1, 2, 3, 4])
>>> a.iterate_graycode(3).subset
[1, 4]
>>> a.iterate_graycode(-2).subset
[1, 2, 4]
另请参阅
next_gray
, prev_gray
next_binary()
生成下一个二进制有序子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.next_binary().subset
['b']
>>> a = Subset(['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.next_binary().subset
[]
另请参阅
prev_binary
, iterate_binary
next_gray()
生成下一个 Gray 码排序子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset([1, 2, 3], [1, 2, 3, 4])
>>> a.next_gray().subset
[1, 3]
另请参阅
iterate_graycode
, prev_gray
next_lexicographic()
生成下一个词典顺序有序子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.next_lexicographic().subset
['d']
>>> a = Subset(['d'], ['a', 'b', 'c', 'd'])
>>> a.next_lexicographic().subset
[]
另请参阅
prev_lexicographic
prev_binary()
生成前一个二进制有序子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset([], ['a', 'b', 'c', 'd'])
>>> a.prev_binary().subset
['a', 'b', 'c', 'd']
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.prev_binary().subset
['c']
另请参阅
next_binary
, iterate_binary
prev_gray()
生成前一个 Gray 码排序子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset([2, 3, 4], [1, 2, 3, 4, 5])
>>> a.prev_gray().subset
[2, 3, 4, 5]
另请参阅
迭代格雷码
, 下一个格雷码
prev_lexicographic()
生成前一个词典顺序的子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset([], ['a', 'b', 'c', 'd'])
>>> a.prev_lexicographic().subset
['d']
>>> a = Subset(['c','d'], ['a', 'b', 'c', 'd'])
>>> a.prev_lexicographic().subset
['c']
另请参阅
下一个词典顺序
property rank_binary
计算二进制有序排名。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset([], ['a','b','c','d'])
>>> a.rank_binary
0
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.rank_binary
3
另请参阅
迭代二进制
, 二进制反向排序
property rank_gray
计算子集的格雷码排名。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c','d'], ['a','b','c','d'])
>>> a.rank_gray
2
>>> a = Subset([2, 4, 5], [1, 2, 3, 4, 5, 6])
>>> a.rank_gray
27
另请参阅
迭代格雷码
, 格雷码反向排序
property rank_lexicographic
计算子集的词典排名。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.rank_lexicographic
14
>>> a = Subset([2, 4, 5], [1, 2, 3, 4, 5, 6])
>>> a.rank_lexicographic
43
property size
获取子集的大小。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.size
2
另请参阅
子集
, 超集
, 超集大小
, 基数
property subset
获取当前实例所表示的子集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.subset
['c', 'd']
另请参阅
超集
, 大小
, 超集大小
, 基数
classmethod subset_from_bitlist(super_set, bitlist)
获取由位列表定义的子集。
示例
>>> from sympy.combinatorics import Subset
>>> Subset.subset_from_bitlist(['a', 'b', 'c', 'd'], '0011').subset
['c', 'd']
另请参阅
从子集生成位列表
classmethod subset_indices(subset, superset)
返回列表中子集在超集中的索引;如果subset
的所有元素都不在superset
中,则列表为空。
示例
>>> from sympy.combinatorics import Subset
>>> superset = [1, 3, 2, 5, 4]
>>> Subset.subset_indices([3, 2, 1], superset)
[1, 2, 0]
>>> Subset.subset_indices([1, 6], superset)
[]
>>> Subset.subset_indices([], superset)
[]
property superset
获取子集的超集。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.superset
['a', 'b', 'c', 'd']
另请参阅
子集
, 大小
, 超集大小
, 基数
property superset_size
返回超集的大小。
示例
>>> from sympy.combinatorics import Subset
>>> a = Subset(['c', 'd'], ['a', 'b', 'c', 'd'])
>>> a.superset_size
4
另请参阅
subset
, superset
, size
, cardinality
classmethod unrank_binary(rank, superset)
获取指定等级的二进制排序子集。
示例
>>> from sympy.combinatorics import Subset
>>> Subset.unrank_binary(4, ['a', 'b', 'c', 'd']).subset
['b']
另请参阅
iterate_binary
, rank_binary
classmethod unrank_gray(rank, superset)
获取指定等级的格雷码排序子集。
示例
>>> from sympy.combinatorics import Subset
>>> Subset.unrank_gray(4, ['a', 'b', 'c']).subset
['a', 'b']
>>> Subset.unrank_gray(0, ['a', 'b', 'c']).subset
[]
另请参阅
iterate_graycode
, rank_gray
subsets.ksubsets(k)
按字典顺序找到大小为k
的子集。
这使用了 itertools 生成器。
示例
>>> from sympy.combinatorics.subsets import ksubsets
>>> list(ksubsets([1, 2, 3], 2))
[(1, 2), (1, 3), (2, 3)]
>>> list(ksubsets([1, 2, 3, 4, 5], 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
另请参阅
Subset
Gray 码
原文:
docs.sympy.org/latest/modules/combinatorics/graycode.html
class sympy.combinatorics.graycode.GrayCode(n, *args, **kw_args)
Gray 码本质上是 n 维立方体上的哈密顿路径,边长为 1。立方体的顶点由其值为二进制的向量表示。哈密顿路径访问每个顶点恰好一次。3D 立方体的 Gray 码是['000','100','110','010','011','111','101','001']。
Gray 码解决了顺序生成 n 个对象所有可能子集的问题,每个子集从前一个子集仅通过删除或添加一个对象获得。在上述示例中,1 表示对象存在,0 表示对象不存在。
Gray 码在统计学中也有应用,特别是当我们希望以高效的方式计算与子集相关的各种统计量时。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(3)
>>> list(a.generate_gray())
['000', '001', '011', '010', '110', '111', '101', '100']
>>> a = GrayCode(4)
>>> list(a.generate_gray())
['0000', '0001', '0011', '0010', '0110', '0111', '0101', '0100', '1100', '1101', '1111', '1110', '1010', '1011', '1001', '1000']
参考文献
[R44]
Nijenhuis,A. 和 Wilf,H.S.(1978). 组合算法. Academic Press.
[R45]
Knuth, D. (2011). 计算机程序设计艺术,第 4 卷 Addison Wesley
property current
返回当前引用的 Gray 码作为比特字符串。
示例
>>> from sympy.combinatorics import GrayCode
>>> GrayCode(3, start='100').current
'100'
generate_gray(**hints)
生成 Gray 码的比特向量序列。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(3)
>>> list(a.generate_gray())
['000', '001', '011', '010', '110', '111', '101', '100']
>>> list(a.generate_gray(start='011'))
['011', '010', '110', '111', '101', '100']
>>> list(a.generate_gray(rank=4))
['110', '111', '101', '100']
参见
skip
参考文献
[R46]
Knuth, D. (2011). 计算机程序设计艺术,第 4 卷, Addison Wesley
property n
返回 Gray 码的维度。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(5)
>>> a.n
5
next(delta=1)
返回 Gray 码从当前值开始的距离delta
(默认= 1)的 Gray 码。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(3, start='110')
>>> a.next().current
'111'
>>> a.next(-1).current
'010'
property rank
对 Gray 码进行排序。
排名算法确定在给定顺序下,组合对象在所有对象中的位置(或排名)。例如,4 位二进制反射 Gray 码(BRGC)'0101'的排名为 6,因为它在 4 位 Gray 码家族的规范顺序中出现在第 6 个位置。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(3)
>>> list(a.generate_gray())
['000', '001', '011', '010', '110', '111', '101', '100']
>>> GrayCode(3, start='100').rank
7
>>> GrayCode(3, rank=7).current
'100'
参见
unrank
参考文献
[R47]
web.archive.org/web/20200224064753/http://statweb.stanford.edu/~susan/courses/s208/node12.html
property selections
返回 Gray 码中的比特向量数。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(3)
>>> a.selections
8
skip()
跳过比特生成。
示例
>>> from sympy.combinatorics import GrayCode
>>> a = GrayCode(3)
>>> for i in a.generate_gray():
... if i == '010':
... a.skip()
... print(i)
...
000
001
011
010
111
101
100
参见
generate_gray
classmethod unrank(n, rank)
反排 n 位大小的 Gray 码的排名 k。此方法存在,以便派生 GrayCode 类可以定义其给定排名的自己的代码。
这里生成的字符串是为了允许尾递归优化。
示例
>>> from sympy.combinatorics import GrayCode
>>> GrayCode(5, rank=3).current
'00010'
>>> GrayCode.unrank(5, 3)
'00010'
参见
rank
graycode.random_bitstring()
生成长度为 n 的随机比特列表。
示例
>>> from sympy.combinatorics.graycode import random_bitstring
>>> random_bitstring(3)
100
graycode.gray_to_bin()
从 Gray 编码转换为二进制编码。
我们假设使用大端编码。
示例
>>> from sympy.combinatorics.graycode import gray_to_bin
>>> gray_to_bin('100')
'111'
参见
bin_to_gray
graycode.bin_to_gray()
将二进制编码转换为格雷编码。
我们假设使用大端编码。
示例
>>> from sympy.combinatorics.graycode import bin_to_gray
>>> bin_to_gray('111')
'100'
另请参见
gray_to_bin
graycode.get_subset_from_bitstring(bitstring)
获取由比特字符串定义的子集。
示例
>>> from sympy.combinatorics.graycode import get_subset_from_bitstring
>>> get_subset_from_bitstring(['a', 'b', 'c', 'd'], '0011')
['c', 'd']
>>> get_subset_from_bitstring(['c', 'a', 'c', 'c'], '1100')
['c', 'a']
另请参见
graycode_subsets
graycode.graycode_subsets()
生成由格雷码枚举的子集。
示例
>>> from sympy.combinatorics.graycode import graycode_subsets
>>> list(graycode_subsets(['a', 'b', 'c']))
[[], ['c'], ['b', 'c'], ['b'], ['a', 'b'], ['a', 'b', 'c'], ['a', 'c'], ['a']]
>>> list(graycode_subsets(['a', 'b', 'c', 'c']))
[[], ['c'], ['c', 'c'], ['c'], ['b', 'c'], ['b', 'c', 'c'], ['b', 'c'], ['b'], ['a', 'b'], ['a', 'b', 'c'], ['a', 'b', 'c', 'c'], ['a', 'b', 'c'], ['a', 'c'], ['a', 'c', 'c'], ['a', 'c'], ['a']]
另请参见
get_subset_from_bitstring
命名的群
原文:
docs.sympy.org/latest/modules/combinatorics/named_groups.html
sympy.combinatorics.named_groups.SymmetricGroup(n)
生成 n
元素的对称群作为一个置换群。
解释
采取的生成器是 n
-循环 (0 1 2 ... n-1)
和换位 (0 1)
(在循环表示中)。 (见 [1])。生成群之后,设置了一些其基本属性。
例子
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> G = SymmetricGroup(4)
>>> G.is_group
True
>>> G.order()
24
>>> list(G.generate_schreier_sims(af=True))
[[0, 1, 2, 3], [1, 2, 3, 0], [2, 3, 0, 1], [3, 1, 2, 0], [0, 2, 3, 1],
[1, 3, 0, 2], [2, 0, 1, 3], [3, 2, 0, 1], [0, 3, 1, 2], [1, 0, 2, 3],
[2, 1, 3, 0], [3, 0, 1, 2], [0, 1, 3, 2], [1, 2, 0, 3], [2, 3, 1, 0],
[3, 1, 0, 2], [0, 2, 1, 3], [1, 3, 2, 0], [2, 0, 3, 1], [3, 2, 1, 0],
[0, 3, 2, 1], [1, 0, 3, 2], [2, 1, 0, 3], [3, 0, 2, 1]]
参见
CyclicGroup
, DihedralGroup
, AlternatingGroup
参考文献
[R57]
en.wikipedia.org/wiki/Symmetric_group#Generators_and_relations
sympy.combinatorics.named_groups.CyclicGroup(n)
生成 n
阶循环群作为一个置换群。
解释
采取的生成器是 n
-循环 (0 1 2 ... n-1)
(在循环表示中)。生成群之后,设置了一些其基本属性。
例子
>>> from sympy.combinatorics.named_groups import CyclicGroup
>>> G = CyclicGroup(6)
>>> G.is_group
True
>>> G.order()
6
>>> list(G.generate_schreier_sims(af=True))
[[0, 1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 0], [2, 3, 4, 5, 0, 1],
[3, 4, 5, 0, 1, 2], [4, 5, 0, 1, 2, 3], [5, 0, 1, 2, 3, 4]]
参见
SymmetricGroup
, DihedralGroup
, AlternatingGroup
sympy.combinatorics.named_groups.DihedralGroup(n)
生成二面角群 (D_n) 作为一个置换群。
解释
二面角群 (D_n) 是正规 n
-边形的对称群。采取的生成器是 n
-循环 a = (0 1 2 ... n-1)
(n
-边形的旋转)和 b = (0 n-1)(1 n-2)...
(n
-边形的反射)在循环旋转中。很容易看出它们满足 a**n = b**2 = 1
和 bab = ~a
,因此它们确实生成了 (D_n)(见 [1])。生成群之后,设置了一些其基本属性。
例子
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> G = DihedralGroup(5)
>>> G.is_group
True
>>> a = list(G.generate_dimino())
>>> [perm.cyclic_form for perm in a]
[[], [[0, 1, 2, 3, 4]], [[0, 2, 4, 1, 3]],
[[0, 3, 1, 4, 2]], [[0, 4, 3, 2, 1]], [[0, 4], [1, 3]],
[[1, 4], [2, 3]], [[0, 1], [2, 4]], [[0, 2], [3, 4]],
[[0, 3], [1, 2]]]
参见
SymmetricGroup
, CyclicGroup
, AlternatingGroup
参考文献
[R58]
en.wikipedia.org/wiki/Dihedral_group
sympy.combinatorics.named_groups.AlternatingGroup(n)
生成 n
元素的交错群作为一个置换群。
解释
对于 n > 2
,采取的生成器是 (0 1 2), (0 1 2 ... n-1)
对于奇数 n
和 (0 1 2), (1 2 ... n-1)
对于偶数 n
(见 [1], p.31, ex.6.9.)。生成群之后,设置了一些其基本属性。处理了 n = 1, 2
的情况。
例子
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> G = AlternatingGroup(4)
>>> G.is_group
True
>>> a = list(G.generate_dimino())
>>> len(a)
12
>>> all(perm.is_even for perm in a)
True
参见
SymmetricGroup
, CyclicGroup
, DihedralGroup
参考文献
[R59]
Armstrong, M. “Groups and Symmetry”
sympy.combinatorics.named_groups.AbelianGroup(*cyclic_orders)
返回具有给定阶数的循环群的直积。
解释
根据有限阿贝尔群的结构定理([1]),每个有限阿贝尔群都可以写成有限多个循环群的直积。
例子
>>> from sympy.combinatorics.named_groups import AbelianGroup
>>> AbelianGroup(3, 4)
PermutationGroup([
(6)(0 1 2),
(3 4 5 6)])
>>> _.is_group
True
另见
DirectProduct
参考文献
[R60]
groupprops.subwiki.org/wiki/Structure_theorem_for_finitely_generated_abelian_groups
Galois 群
构造对称群的可迁子群,在 Galois 理论中很有用。
除了构造PermutationGroup
类的实例以表示小(n)的(S_n)的可迁子群外,此模块还为这些群提供名称。
在某些应用中,知道群的名称可能比接收PermutationGroup
类的实例并额外工作来确定群更可取。
名称是此模块中定义的Enum
类的实例。有了名称,可以使用名称的get_perm_group
方法检索PermutationGroup
。
此模块中用于群的名称取自[1]。
参考文献
[R41]
Cohen, H. 计算代数数论课程.
class sympy.combinatorics.galois.S6TransitiveSubgroups(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
S6 的可迁子群的名称。
class sympy.combinatorics.galois.S5TransitiveSubgroups(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
S5 的可迁子群的名称。
class sympy.combinatorics.galois.S4TransitiveSubgroups(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
S4 的可迁子群的名称。
class sympy.combinatorics.galois.S3TransitiveSubgroups(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
S3 的可迁子群的名称。
class sympy.combinatorics.galois.S2TransitiveSubgroups(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
S2 的可迁子群的名称。
class sympy.combinatorics.galois.S1TransitiveSubgroups(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)
S1 的可迁子群的名称。
sympy.combinatorics.galois.four_group()
返回 Klein 四群作为 S4 的可迁子群的表示。
sympy.combinatorics.galois.M20()
返回 M20 的元循环群的表示,这是 S5 的可迁子群,也是 5 次多项式的可能 Galois 群之一。
笔记
见[1],第 323 页。
sympy.combinatorics.galois.S3_in_S6()
返回 S3 作为 S6 的可迁子群的表示。
笔记
通过将群视为三角柱的对称性来找到表示。
sympy.combinatorics.galois.A4_in_S6()
返回 A4 作为 S6 的可迁子群的表示。
笔记
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.S4m()
返回 S4-作为 S6 的可迁子群的表示。
笔记
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.S4p()
返回 S4+作为 S6 的可迁子群的表示。
笔记
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.A4xC2()
返回(A4 x C2)作为 S6 的可迁子群的表示。
笔记
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.S4xC2()
返回(\boldsymbol{(S4 \times C2)})的表示,作为 S6 的一个传递子群。
注释
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.G18()
返回 G18 群的表示,这是 S6 的一个传递子群,同构于 C3² 与 C2 的半直积。
注释
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.G36m()
返回 G36-群的表示,这是 S6 的一个传递子群,同构于 C3² 与 C2² 的半直积。
注释
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.G36p()
返回 G36+群的表示,这是 S6 的一个传递子群,同构于 C3² 与 C4 的半直积。
注释
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.G72()
返回 G72 群的表示,这是 S6 的一个传递子群,同构于 C3² 与 D4 的半直积。
注释
见[1],第 325 页。
sympy.combinatorics.galois.PSL2F5()
返回(\boldsymbol{PSL_2(\mathbb{F}_5)})群的表示,作为 S6 的一个传递子群,同构于(\boldsymbol{A_5})。
注释
这是使用find_transitive_subgroups_of_S6()
计算得出的。
sympy.combinatorics.galois.PGL2F5()
返回(\boldsymbol{PGL_2(\mathbb{F}_5)})群的表示,作为 S6 的一个传递子群,同构于(\boldsymbol{S_5})。
注释
见[1],第 325 页。
sympy.combinatorics.galois.find_transitive_subgroups_of_S6(*targets, print_report=False)
搜索(\boldsymbol{S_6})的某些传递子群。
对称群(\boldsymbol{S_6})有 16 个不同的传递子群,直到共轭。有些比其他的更容易构造。例如,二面角群(\boldsymbol{D_6})可以立即找到,但如何在(\boldsymbol{S_6})内实现(\boldsymbol{S_4})或(\boldsymbol{S_5})的传递性则一点也不明显。
在某些情况下,有可以使用的众所周知的构造。例如,(\boldsymbol{S_5})同构于(\boldsymbol{PGL_2(\mathbb{F}_5)}),它在射影线(\boldsymbol{P¹(\mathbb{F}_5)})上的自然作用,一个包含 6 个元素的集合。
在缺少这样的特殊构造的情况下,我们可以简单地搜索生成元。例如,可以通过这种方式在(\boldsymbol{S_6})内找到(\boldsymbol{A_4})和(\boldsymbol{S_4})的传递实例。
一旦我们进行这样的搜索,然后通过简单的搜索,甚至可以更容易(虽然不太优雅地)找到像(\boldsymbol{S_5})这样的群,这些群确实具有特殊的构造。
此函数定位 S6 中以下传递子群的生成元:
-
(\boldsymbol{A_4})
-
(\boldsymbol{S_4^-})((\boldsymbol{S_4})不包含在(\boldsymbol{A_6})中)
-
(\boldsymbol{S_4^+})((\boldsymbol{S_4})包含在(\boldsymbol{A_6})中)
-
(\boldsymbol{A_4 \times C_2})
-
(\boldsymbol{S_4 \times C_2})
-
(\boldsymbol{G_{18} = C_3² \rtimes C_2})
-
(G_{36}^- = C_3² \rtimes C_2²)
-
(G_{36}^+ = C_3² \rtimes C_4)
-
(G_{72} = C_3² \rtimes D_4)
-
(A_5)
-
(S_5)
注意:这些组的每一个在该模块中还有一个专用函数,可以立即返回使用此搜索过程找到的生成器的组。
搜索过程记录了这些生成器是如何找到的。此外,由于置换群元素生成的随机性,可以再次调用它,以便(可能)获得同一组的不同生成器。
参数:
targets : S6TransitiveSubgroups
值的列表
您想要查找的组。
print_report : 布尔值(默认为 False)
如果为 True,则打印每个组找到的生成器到标准输出。
返回:
字典
将targets中的每个名称映射到找到的
PermutationGroup
。
参考文献
[R43]
zh.wikipedia.org/wiki/射影线性群#特殊同构
[R44]
zh.wikipedia.org/wiki/对称群和交错群的自同构#PGL%282,5%29
群组数量
原文:
docs.sympy.org/latest/modules/combinatorics/group_numbers.html
sympy.combinatorics.group_numbers.is_nilpotent_number(n) → bool
检查 (n) 是否为幂零数。如果一个数 (n) 的任意有限阶群都是幂零群,则称其为幂零数。详细信息参见[R48]。
示例
>>> from sympy.combinatorics.group_numbers import is_nilpotent_number
>>> from sympy import randprime
>>> is_nilpotent_number(21)
False
>>> is_nilpotent_number(randprime(1, 30)**12)
True
参考文献
[R48] (1,2)
Pakianathan, J., Shankar, K., Nilpotent Numbers, The American Mathematical Monthly, 107(7), 631-634.
[R49]
sympy.combinatorics.group_numbers.is_abelian_number(n) → bool
检查 (n) 是否为阿贝尔数。如果一个数 (n) 的任意有限阶群都是阿贝尔群,则称其为阿贝尔数。详细信息参见[R50]。
示例
>>> from sympy.combinatorics.group_numbers import is_abelian_number
>>> from sympy import randprime
>>> is_abelian_number(4)
True
>>> is_abelian_number(randprime(1, 2000)**2)
True
>>> is_abelian_number(60)
False
参考文献
[R50] (1,2)
Pakianathan, J., Shankar, K., Nilpotent Numbers, The American Mathematical Monthly, 107(7), 631-634.
[R51]
sympy.combinatorics.group_numbers.is_cyclic_number(n) → bool
检查 (n) 是否为循环数。如果一个数 (n) 的任意有限阶群都是循环群,则称其为循环数。详细信息参见[R52]。
示例
>>> from sympy.combinatorics.group_numbers import is_cyclic_number
>>> from sympy import randprime
>>> is_cyclic_number(15)
True
>>> is_cyclic_number(randprime(1, 2000)**2)
False
>>> is_cyclic_number(4)
False
参考文献
[R52] (1,2)
Pakianathan, J., Shankar, K., Nilpotent Numbers, The American Mathematical Monthly, 107(7), 631-634.
[R53]
sympy.combinatorics.group_numbers.groups_count(n)
数量为 (n) 的群组。在[R54]中,给出了 gnu(n)
,因此我们在这里也采用这种符号。
参数:
n : 整数
n
是正整数
返回:
整数 : gnu(n)
引发:
数值错误
数量为
n
的群组尚不明确或未实现。例如,gnu((2^{11})) 尚不为人知。另一方面,gnu(12) 已知为 5,但在此函数中尚未实现。
示例
>>> from sympy.combinatorics.group_numbers import groups_count
>>> groups_count(3) # There is only one cyclic group of order 3
1
>>> # There are two groups of order 10: the cyclic group and the dihedral group
>>> groups_count(10)
2
另请参阅
is_cyclic_number
(n) 是循环数当且仅当 gnu(n) = 1
参考文献
[R54] (1,2)
John H. Conway, Heiko Dietrich 和 E.A. O’Brien, Counting groups: gnus, moas and other exotica The Mathematical Intelligencer 30, 6-15 (2008) doi.org/10.1007/BF02985731
[R55]
Utilities
sympy.combinatorics.util._base_ordering(base, degree)
Order ({0, 1, \dots, n-1}) so that base points come first and in order.
Parameters:
base : the base
degree : the degree of the associated permutation group
Returns:
A list base_ordering
such that base_ordering[point]
is the
number of point
in the ordering.
Examples
>>> from sympy.combinatorics import SymmetricGroup
>>> from sympy.combinatorics.util import _base_ordering
>>> S = SymmetricGroup(4)
>>> S.schreier_sims()
>>> _base_ordering(S.base, S.degree)
[0, 1, 2, 3]
Notes
This is used in backtrack searches, when we define a relation (\ll) on the underlying set for a permutation group of degree (n), ({0, 1, \dots, n-1}), so that if ((b_1, b_2, \dots, b_k)) is a base we have (b_i \ll b_j) whenever (i<j) and (b_i \ll a) for all (i\in{1,2, \dots, k}) and (a) is not in the base. The idea is developed and applied to backtracking algorithms in [1], pp.108-132. The points that are not in the base are taken in increasing order.
References
[R95]
Holt, D., Eick, B., O’Brien, E. “Handbook of computational group theory”
sympy.combinatorics.util._check_cycles_alt_sym(perm)
Checks for cycles of prime length p with n/2 < p < n-2.
Explanation
Here (n) is the degree of the permutation. This is a helper function for the function is_alt_sym from sympy.combinatorics.perm_groups.
Examples
>>> from sympy.combinatorics.util import _check_cycles_alt_sym
>>> from sympy.combinatorics import Permutation
>>> a = Permutation([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12]])
>>> _check_cycles_alt_sym(a)
False
>>> b = Permutation([[0, 1, 2, 3, 4, 5, 6], [7, 8, 9, 10]])
>>> _check_cycles_alt_sym(b)
True
See also
sympy.combinatorics.perm_groups.PermutationGroup.is_alt_sym
sympy.combinatorics.util._distribute_gens_by_base(base, gens)
Distribute the group elements gens
by membership in basic stabilizers.
Parameters:
base : a sequence of points in ({0, 1, \dots, n-1})
gens : a list of elements of a permutation group of degree (n).
Returns:
list
List of length (k), where (k) is the length of base. The (i)-th entry contains those elements in gens which fix the first (i) elements of base (so that the (0)-th entry is equal to gens itself). If no element fixes the first (i) elements of base, the (i)-th element is set to a list containing the identity element.
Explanation
Notice that for a base ((b_1, b_2, \dots, b_k)), the basic stabilizers are defined as (G^{(i)} = G_{b_1, \dots, b_{i-1}}) for (i \in{1, 2, \dots, k}).
Examples
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> from sympy.combinatorics.util import _distribute_gens_by_base
>>> D = DihedralGroup(3)
>>> D.schreier_sims()
>>> D.strong_gens
[(0 1 2), (0 2), (1 2)]
>>> D.base
[0, 1]
>>> _distribute_gens_by_base(D.base, D.strong_gens)
[[(0 1 2), (0 2), (1 2)],
[(1 2)]]
See also
_strong_gens_from_distr
, _orbits_transversals_from_bsgs
, _handle_precomputed_bsgs
sympy.combinatorics.util._handle_precomputed_bsgs(base, strong_gens, transversals=None, basic_orbits=None, strong_gens_distr=None)
Calculate BSGS-related structures from those present.
Parameters:
base : the base
strong_gens : the strong generators
transversals : basic transversals
basic_orbits : basic orbits
strong_gens_distr : strong generators distributed by membership in basic stabilizers
Returns:
(transversals, basic_orbits, strong_gens_distr)
其中横截面是基本横截面,基本轨道是基本轨道,strong_gens_distr是按基本稳定器成员分布的强生成器。
说明
必须提供基础和强生成集;如果未提供任何横截面、基本轨道或分布的强生成器,则会从基础和强生成集计算它们。
示例
>>> from sympy.combinatorics.named_groups import DihedralGroup
>>> from sympy.combinatorics.util import _handle_precomputed_bsgs
>>> D = DihedralGroup(3)
>>> D.schreier_sims()
>>> _handle_precomputed_bsgs(D.base, D.strong_gens,
... basic_orbits=D.basic_orbits)
([{0: (2), 1: (0 1 2), 2: (0 2)}, {1: (2), 2: (1 2)}], [[0, 1, 2], [1, 2]], [[(0 1 2), (0 2), (1 2)], [(1 2)]])
另见
_orbits_transversals_from_bsgs
,_distribute_gens_by_base
sympy.combinatorics.util._orbits_transversals_from_bsgs(base, strong_gens_distr, transversals_only=False, slp=False)
从基础和强生成集计算基本轨道和横截面。
参数:
基础 : 基础。
strong_gens_distr : 按基本稳定器成员分布的强生成器。
transversals_only : 布尔值,默认值:False
一个标志,在仅返回横截面和返回轨道与横截面两者之间切换。
slp : 布尔值,默认值:False
如果
True
,返回包含生成器展示的元素的字典列表,即横截面元素的生成器索引列表,从strong_gens_distr[i]
中获取这些生成器的乘积即为相关横截面元素。
说明
生成器按基本稳定器的成员分布提供。如果将可选参数transversals_only
设置为 True,则仅返回横截面。
示例
>>> from sympy.combinatorics import SymmetricGroup
>>> from sympy.combinatorics.util import _distribute_gens_by_base
>>> S = SymmetricGroup(3)
>>> S.schreier_sims()
>>> strong_gens_distr = _distribute_gens_by_base(S.base, S.strong_gens)
>>> (S.base, strong_gens_distr)
([0, 1], [[(0 1 2), (2)(0 1), (1 2)], [(1 2)]])
另见
_distribute_gens_by_base
,_handle_precomputed_bsgs
sympy.combinatorics.util._remove_gens(base, strong_gens, basic_orbits=None, strong_gens_distr=None)
从强生成集中删除冗余生成器。
参数:
base : 基础
strong_gens : 相对于base的强生成集
basic_orbits : 基本轨道
strong_gens_distr : 按基本稳定器成员分布的强生成器
返回:
关于基础base
的强生成集,这是一个子集。
strong_gens
。
示例
>>> from sympy.combinatorics import SymmetricGroup
>>> from sympy.combinatorics.util import _remove_gens
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> S = SymmetricGroup(15)
>>> base, strong_gens = S.schreier_sims_incremental()
>>> new_gens = _remove_gens(base, strong_gens)
>>> len(new_gens)
14
>>> _verify_bsgs(S, base, new_gens)
True
注意
此过程详见[1],p.95。
参考文献
[R96]
Holt, D., Eick, B., O’Brien, E. “计算群论手册”
sympy.combinatorics.util._strip(g, base, orbits, transversals)
尝试使用(可能是部分的)BSGS 结构分解置换。
参数:
g : 要分解的置换
base : 点序列
orbits : 列表
列表中的第
i
个条目是在\(base[0], base[1], ..., base[i - 1]
)的点稳定器的某个子群下
base[i]`的轨道。由于我们只需要轨道和横截面的信息,这些群本身在此函数中是隐含的。
横截面 : 列表
与轨道orbits相关的轨道横截面列表。
说明
这是通过将序列 base
视为实际的基础,将轨道 orbits
和横穿 transversals
视为相对其的基本轨道和横穿来完成的。
这个过程被称为“筛选”。当某个轨道元素未找到或者在筛选后分解结果不以单位元结束时,筛选失败。
参数 transversals
是一个字典列表,提供了轨道 orbits
的横穿元素。
示例
>>> from sympy.combinatorics import Permutation, SymmetricGroup
>>> from sympy.combinatorics.util import _strip
>>> S = SymmetricGroup(5)
>>> S.schreier_sims()
>>> g = Permutation([0, 2, 3, 1, 4])
>>> _strip(g, S.base, S.basic_orbits, S.basic_transversals)
((4), 5)
注意
该算法在 [1],pp.89-90 中描述。为什么返回正在分解的元素的当前状态以及筛选结束的级别是因为它们为随机版本的 Schreier-Sims 算法提供了重要信息。
参见
sympy.combinatorics.perm_groups.PermutationGroup.schreier_sims
, sympy.combinatorics.perm_groups.PermutationGroup.schreier_sims_random
参考文献
[R97]
Holt, D., Eick, B., O’Brien, E.《计算群论手册》
sympy.combinatorics.util._strong_gens_from_distr(strong_gens_distr)
从基本稳定子的生成器中检索强生成集。
这只是第一个和第二基本稳定子生成器的并集。
参数:
strong_gens_distr:按基本稳定子成员分布的强生成器
示例
>>> from sympy.combinatorics import SymmetricGroup
>>> from sympy.combinatorics.util import (_strong_gens_from_distr,
... _distribute_gens_by_base)
>>> S = SymmetricGroup(3)
>>> S.schreier_sims()
>>> S.strong_gens
[(0 1 2), (2)(0 1), (1 2)]
>>> strong_gens_distr = _distribute_gens_by_base(S.base, S.strong_gens)
>>> _strong_gens_from_distr(strong_gens_distr)
[(0 1 2), (2)(0 1), (1 2)]
参见
_distribute_gens_by_base
群构造器
原文:
docs.sympy.org/latest/modules/combinatorics/group_constructs.html
sympy.combinatorics.group_constructs.DirectProduct(*groups)
返回几个群的直积作为一个置换群。
解释
这与取两个置换群的直积的 mul 过程实现方式非常相似,但在任意数量的群的情况下实现了生成器的移位思想。一般预期调用 DirectProduct(G1, G2, …, Gn) 比调用 G1G2…*Gn 更快(因此需要此算法)。
示例
>>> from sympy.combinatorics.group_constructs import DirectProduct
>>> from sympy.combinatorics.named_groups import CyclicGroup
>>> C = CyclicGroup(4)
>>> G = DirectProduct(C, C, C)
>>> G.order()
64
另请参阅
sympy.combinatorics.perm_groups.PermutationGroup.__mul__
测试实用工具
原文:
docs.sympy.org/latest/modules/combinatorics/testutil.html
sympy.combinatorics.testutil._cmp_perm_lists(first, second)
比较两个排列列表作为集合。
解释
这用于测试目的。由于排列的数组形式目前是一个列表,排列不可哈希化且无法放入集合中。
例子
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.testutil import _cmp_perm_lists
>>> a = Permutation([0, 2, 3, 4, 1])
>>> b = Permutation([1, 2, 0, 4, 3])
>>> c = Permutation([3, 4, 0, 1, 2])
>>> ls1 = [a, b, c]
>>> ls2 = [b, c, a]
>>> _cmp_perm_lists(ls1, ls2)
True
sympy.combinatorics.testutil._naive_list_centralizer(self, other, af=False)
sympy.combinatorics.testutil._verify_bsgs(group, base, gens)
验证基和强生成集的正确性。
解释
这是一个使用基本定义和相对于其的强生成集的朴素实现。有其他程序用于验证基和强生成集,但这个将用于更健壮的测试。
例子
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> from sympy.combinatorics.testutil import _verify_bsgs
>>> A = AlternatingGroup(4)
>>> A.schreier_sims()
>>> _verify_bsgs(A, A.base, A.strong_gens)
True
另请参见
sympy.combinatorics.perm_groups.PermutationGroup.schreier_sims
sympy.combinatorics.testutil._verify_centralizer(group, arg, centr=None)
验证一个组/集合/元素在另一个组内的中心化器。
这用于测试.centralizer()
函数来自sympy.combinatorics.perm_groups
。
例子
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup)
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.testutil import _verify_centralizer
>>> S = SymmetricGroup(5)
>>> A = AlternatingGroup(5)
>>> centr = PermutationGroup([Permutation([0, 1, 2, 3, 4])])
>>> _verify_centralizer(S, A, centr)
True
另请参见
_naive_list_centralizer
, sympy.combinatorics.perm_groups.PermutationGroup.centralizer
, _cmp_perm_lists
sympy.combinatorics.testutil._verify_normal_closure(group, arg, closure=None)
张量规范化
原文:
docs.sympy.org/latest/modules/combinatorics/tensor_can.html
sympy.combinatorics.tensor_can.canonicalize(g, dummies, msym, *v)
形成张量的张量规范化
参数:
g:表示张量的排列
dummies:表示虚拟指标的列表
它可以是相同类型的虚拟指标列表或虚拟指标列表的列表,每种类型一个列表;虚拟指标必须在自由指标之后,并按逆变、协变顺序排列 [d0, -d0, d1,-d1,…]
msym:度规的对称性
它可以是整数或列表;在第一种情况下,它是虚拟指标度规的对称性;在第二种情况下,它是每种类型指标度规对称性的列表
v:列表,对于类型 (i) 的张量为 (base_i, gens_i, n_i, sym_i)
base_i, gens_i:该类型张量的 BSGS。
BSGS 应按字典顺序具有最小基数;如果不是,则尝试获取最小的 BSGS;如果失败,则使用
canonicalize_naive
,这会慢得多。
n_i:类型 (i) 的张量数量。
sym_i:在类型 (i) 的分量张量交换下的对称性。
对于
msym
和sym_i
情况如下
- 无对称性
- 0 交换
- 1 反交换
返回:
如果张量为零,则返回数组形式;
表示张量的规范形式的排列。
算法
首先使用 canonical_free
获取使用只有槽对称性的字典顺序下的最小张量。如果分量张量没有最小的 BSGS,则尝试找到它;如果尝试失败,则使用 canonicalize_naive
。
使用 tensor_gens(base, gens, list_free_indices, sym)
计算保持固定自由指标的残余槽对称性。
通过消除自由指标来减少问题。
然后使用 double_coset_can_rep
并通过重新引入自由指标提升结果。
示例
具有交换度规的一种类型的指标;
(A_{a b}) 和 (B_{a b}) 反对称且交换
(T = A_{d0 d1} * B^{d0}{}_{d2} * B^{d2 d1})
(ord = [d0,-d0,d1,-d1,d2,-d2]) 指标的顺序
g = [1, 3, 0, 5, 4, 2, 6, 7]
(T_c = 0)
>>> from sympy.combinatorics.tensor_can import get_symmetric_group_sgs, canonicalize, bsgs_direct_product
>>> from sympy.combinatorics import Permutation
>>> base2a, gens2a = get_symmetric_group_sgs(2, 1)
>>> t0 = (base2a, gens2a, 1, 0)
>>> t1 = (base2a, gens2a, 2, 0)
>>> g = Permutation([1, 3, 0, 5, 4, 2, 6, 7])
>>> canonicalize(g, range(6), 0, t0, t1)
0
如上所述,但与 (B_{a b}) 反交换
(T_c = -A^{d0 d1} * B_{d0}{}^{d2} * B_{d1 d2})
can = [0,2,1,4,3,5,7,6]
>>> t1 = (base2a, gens2a, 2, 1)
>>> canonicalize(g, range(6), 0, t0, t1)
[0, 2, 1, 4, 3, 5, 7, 6]
两种类型的指标 ([a,b,c,d,e,f]) 和 ([m,n]),以这种顺序,都具有交换度规
(f^{a b c}) 反对称,交换
(A_{m a}) 无对称性,交换
(T = f^c{}{d a} * f^f{} * A_m{}^d * A^{m b} * A_n{}^a * A^{n e})
ord = [c,f,a,-a,b,-b,d,-d,e,-e,m,-m,n,-n]
g = [0,7,3, 1,9,5, 11,6, 10,4, 13,2, 12,8, 14,15]
规范张量为 (T_c = -f^{c a b} * f^{f d e} * A^m{}a * A * A^n{}b * A)
can = [0,2,4, 1,6,8, 10,3, 11,7, 12,5, 13,9, 15,14]
>>> base_f, gens_f = get_symmetric_group_sgs(3, 1)
>>> base1, gens1 = get_symmetric_group_sgs(1)
>>> base_A, gens_A = bsgs_direct_product(base1, gens1, base1, gens1)
>>> t0 = (base_f, gens_f, 2, 0)
>>> t1 = (base_A, gens_A, 4, 0)
>>> dummies = [range(2, 10), range(10, 14)]
>>> g = Permutation([0, 7, 3, 1, 9, 5, 11, 6, 10, 4, 13, 2, 12, 8, 14, 15])
>>> canonicalize(g, dummies, [0, 0], t0, t1)
[0, 2, 4, 1, 6, 8, 10, 3, 11, 7, 12, 5, 13, 9, 15, 14]
sympy.combinatorics.tensor_can.double_coset_can_rep(dummies, sym, b_S, sgens, S_transversals, g)
Butler-Portugal 张量规范化算法,带有虚拟指标。
参数:
dummies
虚拟指标列表的列表,每种类型一个列表;虚拟指标按逆变、协变[d0, -d0, d1, -d1, ...]排序。
对称
指标度量的对称性列表对每种类型。
指标度量的可能对称性
- 0 对称
- 1 反对称
- 无,没有对称性
b_S
最小插槽对称 BSGS 的基础。
sgens
插槽对称 BSGS 的生成器。
S 横截面
插槽 BSGS 的横截面。
g
表示张量的置换。
返回:
如果张量为零则返回 0,否则返回数组形式的
表示张量规范形式的置换。
注意事项
一个具有虚拟指标的张量可以用多种等价方式表示,通常随着指标数量的增加而呈指数级增长。在没有有效算法的情况下,要确定两个具有许多指标的张量是否相等变得计算非常缓慢。
Butler-Portugal 算法[3]是一个将张量置于规范形式的高效算法,解决上述问题。
Portugal 观察到一个张量可以用置换表示,并且在插槽和虚拟对称性下等效的张量类等价于双余类(DgS)(注意:在本文档中我们使用置换乘法的约定 p,q 与(p*q)(i) = p[q[i]]相反,这与 Permutation 类中使用的约定相反)
使用 Butler 算法找到双余类的代表可以找到张量的规范形式。
要看到这种对应关系,设(g)是数组形式的置换;具有指标(ind)的张量(包括逆变和协变指标)可以写成
(t = T(ind[g[0]], \dots, ind[g[n-1]])),
其中(n = len(ind));(g)的大小为(n + 2),最后两个指标是张量的符号(引入[4]中的技巧)。
插槽对称性变换(s)是作用于插槽上的置换(t \rightarrow T(ind[(gs)[0]], \dots, ind[(gs)[n-1]]))
虚拟对称性变换作用于指标(ind) (t \rightarrow T(ind[(dg)[0]], \dots, ind[(dg)[n-1]]))
仅对这些对称性下的张量变换感兴趣,可以将张量表示为(g),该张量的变换如下
(g -> dgs), 所以它属于余类(DgS),或者换句话说,它属于由插槽和虚拟对称性允许的所有排列的集合。
让我们通过一个例子解释惯例。
给定张量(T^{d3 d2 d1}{}_{d1 d2 d3})与插槽对称性
(T^{a0 a1 a2 a3 a4 a5} = -T^{a2 a1 a0 a3 a4 a5})
(T^{a0 a1 a2 a3 a4 a5} = -T^{a4 a1 a2 a3 a0 a5})
并且对称度量,找到与之等价的张量,该张量在指标的排序下是最低的:词典顺序(d1, d2, d3),然后是逆变指标在协变指标之前;即张量的规范形式。
规范形式是通过(T^{a0 a1 a2 a3 a4 a5} = -T^{a2 a1 a0 a3 a4 a5})获得的(-T^{d1 d2 d3}{}_{d1 d2 d3})。
要将此问题转换为此函数的输入,请使用索引名称的以下顺序 (- 表示缩短的协变) (d1, -d1, d2, -d2, d3, -d3)
(T^{d3 d2 d1}{}_{d1 d2 d3}) 对应于 (g = [4, 2, 0, 1, 3, 5, 6, 7]),其中最后两个指标是为了符号
(sgens = [Permutation(0, 2)(6, 7), Permutation(0, 4)(6, 7)])
sgens[0] 是槽对称性 (-(0, 2)),(T^{a0 a1 a2 a3 a4 a5} = -T^{a2 a1 a0 a3 a4 a5})
sgens[1] 是槽对称性 (-(0, 4)),(T^{a0 a1 a2 a3 a4 a5} = -T^{a4 a1 a2 a3 a0 a5})
虚拟对称群 D 是由强基生成器生成的 ([(0, 1), (2, 3), (4, 5), (0, 2)(1, 3), (0, 4)(1, 5)]),前三个交换同一指标的协变和逆变位置(d1 <-> -d1),后两个交换虚拟指标本身(d1 <-> d2)。
虚拟对称性从左侧作用 (d = [1, 0, 2, 3, 4, 5, 6, 7]),交换 (d1 \leftrightarrow -d1) (T^{d3 d2 d1}{}{d1 d2 d3} == T^{d3 d2}{}^{d1}{}_{d2 d3})
(g=[4, 2, 0, 1, 3, 5, 6, 7] -> [4, 2, 1, 0, 3, 5, 6, 7] = _af_rmul(d, g)),与 (_af_rmul(g, d)) 不同。
槽对称性从右侧作用 (s = [2, 1, 0, 3, 4, 5, 7, 6]),交换槽 0 和 2,并改变符号 (T^{d3 d2 d1}{}{d1 d2 d3} == -T^{d1 d2 d3}{})
(g=[4,2,0,1,3,5,6,7] -> [0, 2, 4, 1, 3, 5, 7, 6] = _af_rmul(g, s))
张量为零的示例,与上述相同的槽对称性:(T^{d2}{}{d1 d3}{}^{d1 d3}{})
(= -T^{d3}{}{d1 d3}{}^{d1 d2}{}) 在槽对称性 (-(0,4)) 下;
(= T_{d3 d1}{}{d3}{}_{d2}) 在槽对称性 (-(0,2)) 下;
(= T^{d3}{}{d1 d3}{}^{d1 d2}{}) 对称度量;
(= 0) 因为这两行张量仅在符号上有所不同。
双余类 DgS 包括与等价张量对应的排列 (h = dgs);如果有两个相同除了符号的 (h),返回零;否则按照 ([d1, -d1, d2, -d2, d3, -d3]) 的字典顺序选择张量作为代表,即 rep = min(D*g*S) = min([d*g*s for d in D for s in S])
指标依次固定;首先选择槽 0 的最低指标,然后选择剩余槽 1 的最低指标,依此类推。这样做可以获得一系列的稳定子。
(S \rightarrow S_{b0} \rightarrow S_{b0,b1} \rightarrow \dots) 和 (D \rightarrow D_{p0} \rightarrow D_{p0,p1} \rightarrow \dots)
其中 [b0, b1, ...] = range(b)
是对称群的基;S 的强基 (b_S) 是其有序子列表;因此仅需使用 Schreier-Sims 算法一次计算 S 的强基生成器;强基生成器的稳定子是稳定子子群的强基生成器。
dbase = [p0, p1, ...]
通常不是字典顺序的,因此每次都必须重新计算强基生成器;然而这很简单,不需要使用 Schreier-Sims 算法来处理 D。
该算法保持元素((s_i, d_i, h_i))的 TAB,其中(h_i = d_i \times g \times s_i)满足(h_i[j] = p_j),对于(0 \le j < i),从(s_0 = id, d_0 = id, h_0 = g)开始。
方程(h_0[0] = p_0, h_1[1] = p_1, \dots)按照这个顺序解决,每次选择最低可能的 p_i 值。
对于(j < i),(d_igs_iS_{b_0, \dots, b_{i-1}}b_j = D_{p_0, \dots, p_{i-1}}p_j),因此对于(D_{p_0,\dots,p_{i-1}})中的 dx 和(S_{base[0], \dots, base[i-1]})中的 sx,有(dxd_igs_isxb_j = p_j)
寻找 dx, sx,使得这个方程对于(j = i)成立;它可以写成(s_isxb_j = J, dxd_igJ = p_j) (sxb_j = s_i-1*J; sx = trace(s_i-1, S_{b_0,...,b_{i-1}})) (dx**-1p_j = d_igJ; dx = trace(d_ig*J, D_{p_0,...,p_{i-1}}))
(s_{i+1} = s_itrace(s_i**-1J, S_{b_0,...,b_{i-1}})) (d_{i+1} = trace(d_igJ, D_{p_0,...,p_{i-1}})**-1d_i) (h_{i+1}b_i = d_{i+1}gs_{i+1}*b_i = p_i)
对所有的 j,(h_n*b_j = p_j),因此(h_n)是解。
将找到的((s, d, h))添加到 TAB1 中。
在迭代结束时,按照(h)对 TAB1 进行排序;如果 TAB1 中有两个连续的(h)只有符号不同,张量为零,所以返回 0;如果有两个连续的(h)相等,则保留一个。
然后稳定(i)下的槽生成器和(p_i)下的虚拟生成器。
在迭代步骤结束时将(TAB = TAB1)赋值。
最后(TAB)包含一个独特的((s, d, h)),因为张量(h)的所有槽都被固定为符合对称性的最小值。算法返回(h)。
重要的是槽 BSGS 具有字典顺序下的最小基,否则存在一个(i),它不属于槽基,而(p_i)仅由虚拟对称性固定,而(i)不是来自槽稳定器,所以(p_i)通常不是最小值。
这个算法与原始算法[3]略有不同:
规范形式在字典顺序下是最小的,而 BSGS 在字典顺序下具有最小的基。相等的张量(h)从 TAB 中消除。
示例
>>> from sympy.combinatorics.permutations import Permutation
>>> from sympy.combinatorics.tensor_can import double_coset_can_rep, get_transversals
>>> gens = [Permutation(x) for x in [[2, 1, 0, 3, 4, 5, 7, 6], [4, 1, 2, 3, 0, 5, 7, 6]]]
>>> base = [0, 2]
>>> g = Permutation([4, 2, 0, 1, 3, 5, 6, 7])
>>> transversals = get_transversals(base, gens)
>>> double_coset_can_rep([list(range(6))], [0], base, gens, transversals, g)
[0, 1, 2, 3, 4, 5, 7, 6]
>>> g = Permutation([4, 1, 3, 0, 5, 2, 6, 7])
>>> double_coset_can_rep([list(range(6))], [0], base, gens, transversals, g)
0
sympy.combinatorics.tensor_can.get_symmetric_group_sgs(n, antisym=False)
返回( (反)对称张量的最小 BSGS 的基和生成元 )
参数:
n:张量的秩
antisym:布尔值
antisym = False
表示对称张量antisym = True
表示反对称张量
示例
>>> from sympy.combinatorics.tensor_can import get_symmetric_group_sgs
>>> get_symmetric_group_sgs(3)
([0, 1], [(4)(0 1), (4)(1 2)])
sympy.combinatorics.tensor_can.bsgs_direct_product(base1, gens1, base2, gens2, signed=True)
两个 BSGS 的直接积。
参数:
base1:第一个 BSGS 的基。
gens1:第一个 BSGS 的强生成序列。
base2, gens2:第二个 BSGS 类似。
signed:表示有符号排列的标志。
示例
>>> from sympy.combinatorics.tensor_can import (get_symmetric_group_sgs, bsgs_direct_product)
>>> base1, gens1 = get_symmetric_group_sgs(1)
>>> base2, gens2 = get_symmetric_group_sgs(2)
>>> bsgs_direct_product(base1, gens1, base2, gens2)
([1], [(4)(1 2)])
有限呈现群
原文:
docs.sympy.org/latest/modules/combinatorics/fp_groups.html
介绍
本模块提供了用于有限呈现群(fp-groups 简称)计算的功能。对应的 SymPy 对象名称是 FpGroup
。这里描述的函数或类是在计算群论下研究的。所有代码示例假设:
>>> from sympy.combinatorics.free_groups import free_group, vfree_group, xfree_group
>>> from sympy.combinatorics.fp_groups import FpGroup, CosetTable, coset_enumeration_r
设施概述
为有限呈现群提供的设施分为几个自然分组
-
使用自由群和该自由群的生成元词列表构造 fp-groups。
-
使用著名的 Todd-Coxeter 程序确定指数。
-
使用低指标子群算法构造所有指数小于某个(小的)指定正整数的子群。
-
算法用于计算由有限呈现定义的群中有限指数子群的表示。
对于有限呈现群的基本算法描述,我们经常使用计算群论手册。
有限呈现群的构造
有限呈现群通过将自由群因子分解为一组关系者而构造。关系者集合以 SymPy 中自由群的生成元的词列表形式给出,使用列表为关系者提供了顺序。如果关系者列表为空,则返回关联的自由群。
一个有限呈现群构造的示例。四阶对称群可以表示为具有表示 (\left\langle a, b \mid a², b³, (ab)⁴ \right\rangle) 的两个生成元群。将关系者作为关系者列表提供,SymPy 中的群将指定为:
>>> F, a, b = free_group("a, b")
>>> G = FpGroup(F, [a**2, b**3, (a*b)**4])
>>> G
<fp group on the generators (a, b)>
当前的群具有类似于 (\left\langle r, s, t \mid r², s², t², rst = str = trs \right\rangle) 的表示时,必须指定为:
>>> F, r, s, t = free_group("r, s, t")
>>> G = FpGroup(F, [r**2, s**2, t**2, r*s*t*r**-1*t**-1*s**-1, s*t*r*s**-1*r**-1*t**-1])
显然,这不是制造特定群的唯一方法,但重点在于,如果与非身份相等,用户必须手动执行此操作。
自由群和词
自由群的构造
free_group("gen0, gen1, ..., gen_(n-1)")
在 n
个生成元上构造了一个自由群 F
,其中 n
是正整数。可以使用方法 .generators[i]
获取 F
的第 i
个生成元,其中 (i = 0, \ldots n-1)。
>>> F, x, y = free_group("x, y")
创建了一个秩为 2 的自由群 F
,并将变量 x
和 y
分配给这两个生成元。
>>> F = vfree_group("x, y")
>>> F
<free group on the generators (x, y)>
创建了一个秩为 2 的自由群 F
,并用生成元组 F.generators
插入 x
和 y
作为全局命名空间中的生成元。
>>> F = xfree_group("x, y")
>>> F
(<free group on the generators (x, y)>, (x, y))
>>> x**2
x**2
创建了一个秩为 2 的自由群 F[0]
,并用生成元组 F[1]
。
词的构造
本节适用于 FreeGroup
和 FpGroup
中的词。当我们在 SymPy 中提到 word 时,实际上指的是一个简化词,因为这些词会自动进行简化。给定一个群 G
,其由 (n) 个生成元 (x_1, x_2, x_3, \ldots, x_n) 定义,一个词构造为 (s_1{r_1}s_2 \cdots s_k^{r_k}),其中 (s_i \in {x_1, x_2, \ldots, x_n}),(r_i \in \mathbb{Z}) 对所有的 (k) 成立。
每个词可以以各种方式构造,因为它们经过简化后可能是等效的。
余陪枚举:Todd-Coxeter 算法
本节描述了 SymPy 中余陪枚举技术的使用。用于余陪枚举过程的算法是 Todd-Coxeter 算法,并且是在 SymPy 中使用 [Ho05] 和 [CDHW73] 开发的。读者应参考 [CDHW73] 和 [Hav91] 了解算法的一般描述。
我们有两种余陪枚举策略 relator-based 和 coset-table based,并且两者都作为 coset_enumeration_r
、coset_enumeration_c
实现了。这两种策略在它们为余陪制定新定义的方式上有所不同。
尽管从用户的角度建议使用 FpGroup
的 .coset_enumeration
方法,并指定 strategy
参数。
strategy
:
(default=”relator_based”) 指定余陪枚举策略的策略,可能的值是 “relator_based” 或 “coset_table_based”。
余陪表
用于操作有限呈现群 G
在子群 H
的余陪上余陪枚举信息的类。
基本上 coset table CosetTable(G,H)
是有限呈现群在一个子群的余陪上的置换表示。大多数集合论和群函数使用 G
的常规表示,即在平凡子群上的余陪表。
实际的数学余陪表通过 .table
属性获取,并且是一个列表的列表。对于 G
的每个生成元 g
,它包含一列,下一列对应于 g**-1
,依此类推对其他生成元,因此总共有 2*G.rank()
列。每列简单地是一个整数列表。如果 l
是生成元列表用于生成元 (g),如果 l[i] = j
,那么生成元 g
将余陪 (i) 送到余陪 (j),通过右侧乘法。
对于有限呈现的群,余陪表通过 Todd-Coxeter 余陪枚举计算。请注意,您可以通过更改变量 CosetTable.coset_table_max_limit
的值来影响该枚举的性能。
CosetTable 的属性
对于 CosetTable(G, H)
,其中 G
是群,H
是子群。
-
n
:一个非负整数,非可变属性,作为活余陪(即 (\Omega))的最大值计算。 -
table
:一个列表的列表,可变属性,数学上表示余陪表。 -
omega
:一个列表,依赖于内部属性p
。 (\Omega) 表示活余类的列表。一个 标准 余类表具有其 (\Omega = {0, 1, \ldots, index-1 }),其中 (index) 是子群 (H) 在 (G) 中的指标。
对于有经验的用户,我们有一些可以用来操纵算法的参数,如
-
coset_table_max_limit
(默认值为 (4096000)):操纵允许的余类数目在余类枚举中,即在余类表中允许的行数。如果子群没有有限指标,则余类枚举将不会结束,即使它有可能会比子群的实际指标多很多中间余类。为了避免余类枚举“失控”,因此 SymPy 具有内置的“安全停止”功能。这由此变量控制。要更改它,请使用max_cosets
关键字。例如:>>> F, a, b = free_group("a, b") >>> Cox = FpGroup(F, [a**6, b**6, (a*b)**2, (a**2*b**2)**2, (a**3*b**3)**5]) >>> C_r = coset_enumeration_r(Cox, [a], max_cosets=50) Traceback (most recent call last): ... ValueError: the coset enumeration has defined more than 50 cosets
-
max_stack_size
(默认值为 (500)):操纵deduction_stack
的最大大小,大于或等于该大小时堆栈被清空。
压缩和标准化
对于余类表中的任意两个条目 (i, j),其中 (i < j),在余类表条目的行顺序中,(i) 的第一次出现先于 (j) 的第一次出现。我们称这样的表为标准余类表。要将 CosetTable
标准化,我们使用 .standardize
方法。
注意:该方法改变给定的表,而不是创建一个副本。
有限指标的子群
本节的功能涉及构造有限指标子群。我们描述了一种计算所有指标不超过某个(适度的)整数界限的子群的方法。
低指标子群
low_index_subgroups(G, N)
: 给定一个有限表达群 (G = \left\langle X \mid R \right\rangle)(可以是自由群),以及一个正整数 N
,确定 G
的指标小于或等于 N
的子群的共轭类。
例如,要找到所有满足 (\le 4) 的子群 (G = \left\langle a, b \mid a² = b³ = (ab)⁴ = 1 \right\rangle) 的方法如下所示:
>>> from sympy.combinatorics.fp_groups import low_index_subgroups
>>> F, a, b = free_group("a, b")
>>> G = FpGroup(F, [a**2, b**3, (a*b)**4])
>>> l = low_index_subgroups(G, 4)
>>> for coset_table in l:
... print(coset_table.table)
...
[[0, 0, 0, 0]]
[[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 3, 3]]
[[0, 0, 1, 2], [2, 2, 2, 0], [1, 1, 0, 1]]
[[1, 1, 0, 0], [0, 0, 1, 1]]
这返回满足子群在群中的指标为 ( \le n ) 的子群的余类表。
构建子群的表示
在本节中,我们讨论在有限表达群中找到子群的表示。虽然 子群 目前只允许作为子群的生成器列表的形式输入,但是你可以期待不久的将来将 余类表 的功能作为子群的输入。
有两种方法从 G
的那些到 H
的生成关系中构造一个子群的定义关系。第一种是在一组 Schreier 生成器上,通常称为 Reidemeister-Schreier 算法或给定的 H
的生成器列表上。
Reidemeister Schreier 算法
使用 reidemeister_presentation(G, Y)
调用,其中 G
是群,Y
是我们想要找到其表示的子群 H
的生成器列表。
>>> from sympy.combinatorics.fp_groups import reidemeister_presentation
>>> F, x, y = free_group("x, y")
>>> f = FpGroup(F, [x**3, y**5, (x*y)**2])
>>> H = [x*y, x**-1*y**-1*x*y*x]
>>> p1 = reidemeister_presentation(f, H)
>>> p1
((y_1, y_2), (y_1**2, y_2**3, y_2*y_1*y_2*y_1*y_2*y_1))
参考文献
[CDHW73]
John J. Cannon, Lucien A. Dimino, George Havas 和 Jane M. Watson。《Todd-Coxeter 算法的实现与分析》。Math. Comp.,27:463– 490,1973 年。
[Ho05]
Derek F. Holt,《计算群论手册》。在系列“离散数学及其应用”中,Chapman & Hall/CRC 2005, xvi + 514 p。
[Hav91]
George Havas,《余类枚举策略》。在国际符号与代数计算研讨会(ISSAC’91)论文集,1991 年波恩,页码 191–199. ACM 出版社,1991 年。