方法

包含对 IndexedBase、Indexed 和 Idx 对象进行操作的函数的模块

  • 检查形状一致性

  • 确定结果表达式中的索引

等等。

此模块中的方法可以通过调用 Expr 对象上的方法来实现。当情况稳定时,这可能是一个有用的重构。

sympy.tensor.index_methods.get_contraction_structure(expr)[源代码][源代码]

确定 expr 的虚拟索引并描述其结构

通过 dummy 我们指的是求和指标。

表达式的结构确定并描述如下:

  1. 符合条件的索引对象的求和描述为一个字典,其中键是求和索引,对应的值是包含所有适用项的集合。SymPy表达式树中的所有Add对象都以此方式描述。

  2. 对于SymPy表达式树中所有*不是*类型为Add的节点,以下规则适用:

    如果一个节点在其一个参数中发现缩写,该节点本身将被存储为字典中的一个键。对于该键,相应的值是一个字典列表,每个字典都是对 get_contraction_structure() 进行递归调用的结果。该列表仅包含非平凡更深层次缩写的字典,省略了仅有一个键为 None 的字典。

备注

字典键中表达式的存在表示索引收缩的多个层次。嵌套字典显示嵌套的收缩,并且可能本身包含来自更深层次的字典。在实际计算中,最深嵌套层次的求和必须首先计算,以便外部表达式可以访问结果的索引对象。

示例

>>> from sympy.tensor.index_methods import get_contraction_structure
>>> from sympy import default_sort_key
>>> from sympy.tensor import IndexedBase, Idx
>>> x, y, A = map(IndexedBase, ['x', 'y', 'A'])
>>> i, j, k, l = map(Idx, ['i', 'j', 'k', 'l'])
>>> get_contraction_structure(x[i]*y[i] + A[j, j])
{(i,): {x[i]*y[i]}, (j,): {A[j, j]}}
>>> get_contraction_structure(x[i]*y[j])
{None: {x[i]*y[j]}}

多个缩并因子的乘积会产生嵌套的字典,表示内部缩并。

>>> d = get_contraction_structure(x[i, i]*y[j, j])
>>> sorted(d.keys(), key=default_sort_key)
[None, x[i, i]*y[j, j]]

在这种情况下,产品没有缩写:

>>> d[None]
{x[i, i]*y[j, j]}

因素被“首先”考虑:

>>> sorted(d[x[i, i]*y[j, j]], key=default_sort_key)
[{(i,): {x[i, i]}}, {(j,): {y[j, j]}}]

一个带括号的 Add 对象也会作为嵌套字典返回。包含括号的项是一个 Mul,其参数之间存在收缩,因此它将作为结果中的一个键被找到。它存储了递归调用 Add 表达式所得到的字典。

>>> d = get_contraction_structure(x[i]*(y[i] + A[i, j]*x[j]))
>>> sorted(d.keys(), key=default_sort_key)
[(A[i, j]*x[j] + y[i])*x[i], (i,)]
>>> d[(i,)]
{(A[i, j]*x[j] + y[i])*x[i]}
>>> d[x[i]*(A[i, j]*x[j] + y[i])]
[{None: {y[i]}, (j,): {A[i, j]*x[j]}}]

在字典中,底数或指数中带有缩写的幂也将作为键出现,映射到递归调用的结果列表:

>>> d = get_contraction_structure(A[j, j]**A[i, i])
>>> d[None]
{A[j, j]**A[i, i]}
>>> nested_contractions = d[A[j, j]**A[i, i]]
>>> nested_contractions[0]
{(j,): {A[j, j]}}
>>> nested_contractions[1]
{(i,): {A[i, i]}}

当用字符串表示时,收缩结构的描述在上述例子中可能显得复杂,但迭代起来很容易:

>>> from sympy import Expr
>>> for key in d:
...     if isinstance(key, Expr):
...         continue
...     for term in d[key]:
...         if term in d:
...             # treat deepest contraction first
...             pass
...     # treat outermost contactions here
sympy.tensor.index_methods.get_indices(expr)[源代码][源代码]

确定表达式 expr 的外部索引

通过 outer 我们指的是不是求和索引的索引。返回一个集合和一个字典。集合包含外部索引,字典包含关于索引对称性的信息。

示例

>>> from sympy.tensor.index_methods import get_indices
>>> from sympy import symbols
>>> from sympy.tensor import IndexedBase
>>> x, y, A = map(IndexedBase, ['x', 'y', 'A'])
>>> i, j, a, z = symbols('i j a z', integer=True)

总表达式的指标被确定,重复的指标意味着求和,例如矩阵 A 的迹:

>>> get_indices(A[i, i])
(set(), {})

在许多术语的情况下,这些术语需要具有相同的索引。否则会引发 IndexConformanceException。

>>> get_indices(x[i] + A[i, j]*y[j])
({i}, {})
异常:

IndexConformanceException 意味着术语不兼容,例如:

>>> get_indices(x[i] + y[j])                
        (...)
IndexConformanceException: Indices are not consistent: x(i) + y(j)

警告

*外*指标的概念是递归应用的,从最深层次开始。这意味着括号内的哑元首先被假定为求和,因此以下表达式可以被优雅地处理:

>>> get_indices((x[i] + A[i, j]*y[j])*x[j])
({i, j}, {})

这是正确的,并且可能看起来很方便,但你需要小心这一点,因为如果请求,SymPy 会乐意 .expand() 这个乘积。生成的表达式会将外部的 j 与括号内的哑变量混合,这使得它成为一个不同的表达式。为了安全起见,最好通过为所有应保持独立的收缩使用唯一的指标来避免这种歧义。