张量正则化#

sympy.combinatorics.tensor_can.canonicalize(g, dummies, msym, *v)[源代码]#

由张量构成的正则化张量

参数:

g :表示张量的排列

假人 :表示虚拟索引的列表

它可以是相同类型的虚拟索引列表,也可以是虚拟索引列表的列表,每种类型的索引都有一个列表;虚拟索引必须位于自由索引之后,并按逆变、协变的顺序排列 [d0, -d0, d1,-d1,...]

msym :度量的对称性

它可以是整数或列表;在第一种情况下,它是虚拟索引度量的对称性;在第二种情况下,它是每种类型的索引度量的对称性列表

v 基本类型:符号 \(i\)

base_i, gens_i :BSGS表示这种类型的张量。

在字典序下,bsg应该有最小的基;如果没有,尝试得到最小的bsg;如果失败,则使用canonicalize_naive,这要慢得多。

n_i :类型张量的数量 \(i\) .

sym_i 对称分量下的交换张量 \(i\) .

对于msym和sym嫒i来说,情况都是这样的
  • 没有没有没有对称性

  • 0通勤

  • 1抗干扰

返回:

0如果张量为零,则返回数组形式

表示张量标准形的排列。

算法

第一种方法是利用正则_-free来求字典序下的最小张量,只利用槽对称。如果分量张量没有最小的bsg,则尝试查找它;如果尝试失败,则使用canonicalize_naive代替。

使用张量μgens(base,gens,list_free_index,sym)计算保持自由指数固定的剩余槽对称性。

消除自由指数的问题。

然后用双倍陪集表示,并将结果重新引入自由指数。

实例

一类具有交换度量的指标;

\(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}\)

可以= [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{}_{e b} * A_m{}^d * A^{m b} * A_n{}^a * A^{n e}\)

作战需求文件= [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_{{m d}} * A^n{{}}_b * A_{{n e}}\)

可以= [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 algorithm for tensor canonicalization with dummy indices.

参数:

dummies

虚拟索引列表的列表,每种类型的索引都有一个列表;虚拟索引按逆变、协变的顺序排列 [d0, -d0, d1, -d1, ...] .

sym公司

每种类型的索引度量的对称性列表。

度量的可能对称性
  • 0对称

  • 1反对称

  • 没有没有没有对称性

b_S

最小槽对称BSGS的基。

斯根斯

槽对称BSG的发生器。

S_transversals

槽BSG的横截面。

G

表示张量的排列。

返回:

如果张量为零,则返回0,否则返回

表示张量标准形的排列。

笔记

具有伪指数的张量可以用许多等价的方法来表示,这些方法通常随着指数的数量而呈指数增长。在缺乏有效算法的情况下,确定两个具有多个指数的张量是否相等的问题变得非常缓慢。

巴特勒葡萄牙算法 [3] 是一种将张量置于正则形式的有效算法,解决了上述问题。

葡萄牙发现张量可以用置换来表示,在狭缝对称和伪对称下与其等价的一类张量等价于双陪集 \(D*g*S\) (注:在本文档中,我们使用置换p,q与(p*q)(i)=p相乘的约定 [q[i] ]与置换类中使用的相反)

利用Butler算法寻找双陪集的一个代表,可以找到张量的一个典型形式。

为了看这封信,让 \(g\) 是数组形式的排列;有指数的张量 \(ind\) (指数包括反变量和协变指数)可以写成

\(t = T(ind[g[0]], \dots, ind[g[n-1]])\),

where \(n = len(ind)\); \(g\) has size \(n + 2\), the last two indices for the sign of the tensor (trick introduced in [4]).

A slot symmetry transformation \(s\) is a permutation acting on the slots \(t \rightarrow T(ind[(g*s)[0]], \dots, ind[(g*s)[n-1]])\)

A dummy symmetry transformation acts on \(ind\) \(t \rightarrow T(ind[(d*g)[0]], \dots, ind[(d*g)[n-1]])\)

由于只对这些对称性下张量的变换感兴趣,我们可以用 \(g\) ,转换为

\(g -> d*g*s\) ,所以它属于陪护 \(D*g*S\) ,或者换句话说,是插槽和伪对称所允许的所有排列集。

让我们用一个例子来解释这些惯例。

给定张量 \(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^{{d1 d2 d3}}{{}}_{{d1 d2 d3}}\) 使用获得 \(T^{{a0 a1 a2 a3 a4 a5}} = -T^{{a2 a1 a0 a3 a4 a5}}\) .

若要在该函数的输入中转换此问题,请使用以下索引名称的顺序(缩写为convariant) \(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)]\)

斯根斯 [0] 槽对称吗 \(-(0, 2)\) \(T^{{a0 a1 a2 a3 a4 a5}} = -T^{{a2 a1 a0 a3 a4 a5}}\)

斯根斯 [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)。

The dummy symmetry acts from the left \(d = [1, 0, 2, 3, 4, 5, 6, 7]\) exchange \(d1 \leftrightarrow -d1\) \(T^{d3 d2 d1}{}_{d1 d2 d3} == T^{d3 d2}{}_{d1}{}^{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}}{{}}_{{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}}{{}}_{{d2}}\)

\(= -T^{{d3}}{{}}_{{d1 d3}}{{}}^{{d1 d2}}{{}}_{{d2}}\) 槽对称下 \(-(0,4)\)

\(= T_{{d3 d1}}{{}}^{{d3}}{{}}^{{d1 d2}}{{}}_{{d2}}\) 槽对称下 \(-(0,2)\)

\(= T^{{d3}}{{}}_{{d1 d3}}{{}}^{{d1 d2}}{{}}_{{d2}}\) 对称度量;

\(= 0\) 因为这两条线的张量只有符号不同。

The double coset D*g*S consists of permutations \(h = d*g*s\) corresponding to equivalent tensors; if there are two \(h\) which are the same apart from the sign, return zero; otherwise choose as representative the tensor with indices ordered lexicographically according to \([d1, -d1, d2, -d2, d3, -d3]\) that is 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\) and \(D \rightarrow D_{p0} \rightarrow D_{p0,p1} \rightarrow \dots\)

where [b0, b1, ...] = range(b) is a base of the symmetric group; the strong base \(b_S\) of S is an ordered sublist of it; therefore it is sufficient to compute once the strong base generators of S using the Schreier-Sims algorithm; the stabilizers of the strong base generators are the strong base generators of the stabilizer subgroup.

dbase = [p0, p1, ...] is not in general in lexicographic order, so that one must recompute the strong base generators each time; however this is trivial, there is no need to use the Schreier-Sims algorithm for D.

The algorithm keeps a TAB of elements \((s_i, d_i, h_i)\) where \(h_i = d_i \times g \times s_i\) satisfying \(h_i[j] = p_j\) for \(0 \le j < i\) starting from \(s_0 = id, d_0 = id, h_0 = g\).

The equations \(h_0[0] = p_0, h_1[1] = p_1, \dots\) are solved in this order, choosing each time the lowest possible value of p_i

For \(j < i\) \(d_i*g*s_i*S_{b_0, \dots, b_{i-1}}*b_j = D_{p_0, \dots, p_{i-1}}*p_j\) so that for dx in \(D_{p_0,\dots,p_{i-1}}\) and sx in \(S_{base[0], \dots, base[i-1]}\) one has \(dx*d_i*g*s_i*sx*b_j = p_j\)

搜索dx,sx,使这个方程适用于 \(j = i\) ,可以写成 \(s_i*sx*b_j = J, dx*d_i*g*J = p_j\) \(sx*b_j = s_i**-1*J; sx = trace(s_i**-1, S_{{b_0,...,b_{{i-1}}}})\) \(dx**-1*p_j = d_i*g*J; dx = trace(d_i*g*J, D_{{p_0,...,p_{{i-1}}}})\)

\(s_{i+1} = s_i*trace(s_i**-1*J, S_{b_0,...,b_{i-1}})\) \(d_{i+1} = trace(d_i*g*J, D_{p_0,...,p_{i-1}})**-1*d_i\) \(h_{i+1}*b_i = d_{i+1}*g*s_{i+1}*b_i = p_i\)

\(h_n*b_j = p_j\) 为了所有的j,所以 \(h_n\) 是解决办法。

添加找到的 \((s, d, h)\) 到表1。

在迭代结束时,根据 \(h\) ;如果有两个连续的 \(h\) 在只与符号不同的TAB1中,张量为零,因此返回0;如果有两个连续的 \(h\) 相等的,只保留一个。

然后把槽发生器稳定在 \(i\) 以及下面的虚拟发电机 \(p_i\) .

赋值 \(TAB = TAB1\) 在迭代步骤的末尾。

最后 \(TAB\) 包含唯一的 \((s, d, h)\) 因为张量的所有槽 \(h\) 根据对称性确定了最小值。算法返回 \(h\) .

重要的是槽bsg有字典序最小基,否则有一个 \(i\) 不属于的插槽 \(p_i\) 仅由虚拟对称性固定,而 \(i\) 不是固定不变的,所以 \(p_i\) 一般不是最小值。

此算法与原始算法略有不同 [3] :

正则形式在字典序上是最小的,而BSGS在字典序下具有最小基。等张量 \(h\) 从标签中删除。

实例

>>> 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 : rank of the tensor

antisym : bool

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

Direct product of two BSGS.

参数:

base1 : base of the first BSGS.

gens1 : strong generating sequence of the first BSGS.

base2, gens2 : similarly for the second BSGS.

signed : flag for signed permutations.

实例

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