Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Reduction

get_reduction builds the operators of Extraction and embedding for every weight and channel in one call. For each (ell, p) it gives the embedding operator GG under "embedding" and the extraction operator G~\widetilde G under "extraction", and it takes the same ell, symmetry and basis arguments.

Reducing a rank-2 tensor extracts each ICT and embeds it back into the part of the tensor it carries:

import numpy as np

from natto import act, evaluate, get_reduction

T = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 12.0]])

reduction = get_reduction(n=2)

for (ell, p), operators in reduction.items():
    G = operators["embedding"]
    G_tilde = operators["extraction"]

    X = act(G_tilde, T)
    T_part = act(G, X)

    print(f"--- weight {ell}, channel {p} ---")
    print(f"G~: {G_tilde}")
    print(f"G:  {G}")
    print(f"X, the ICT:\n{X}")
    print(f"G · X, the part of T:\n{T_part}\n")
--- weight 0, channel 1 ---
G~: +1/3 δ_AB
G:  +1 δ_AB
X, the ICT:
6.0
G · X, the part of T:
[[6. 0. 0.]
 [0. 6. 0.]
 [0. 0. 6.]]

--- weight 1, channel 1 ---
G~: +1/2 ε_ABa
G:  +1 ε_ABa
X, the ICT:
[-1.  2. -1.]
G · X, the part of T:
[[ 0. -1. -2.]
 [ 1.  0. -1.]
 [ 2.  1.  0.]]

--- weight 2, channel 1 ---
G~: +1/2 δ_Aa δ_Bb  +1/2 δ_Ab δ_Ba  -1/3 δ_AB δ_ab
G:  +1/2 δ_Aa δ_Bb  +1/2 δ_Ab δ_Ba  -1/3 δ_AB δ_ab
X, the ICT:
[[-5.  3.  5.]
 [ 3. -1.  7.]
 [ 5.  7.  6.]]
G · X, the part of T:
[[-5.  3.  5.]
 [ 3. -1.  7.]
 [ 5.  7.  6.]]

The three parts are tr⁡T/3\operatorname{tr}\mathbf T/3 times the identity, the antisymmetric part and the symmetric traceless part, and they sum to T.

The same reduction with arrays and einsum rules, each operator evaluated once:

for (ell, p), operators in reduction.items():
    G_array, G_rule = evaluate(operators["embedding"])
    G_tilde_array, G_tilde_rule = evaluate(operators["extraction"])

    X = np.einsum(G_tilde_rule, G_tilde_array, T)
    T_part = np.einsum(G_rule, G_array, X)

    print(f"--- weight {ell}, channel {p} ---")
    print(f"rule of G~: {G_tilde_rule}")
    print(f"rule of G:  {G_rule}")
    print(f"G · X, the part of T:\n{T_part}\n")
--- weight 0, channel 1 ---
rule of G~: AB,...AB->...
rule of G:  AB,...->...AB
G · X, the part of T:
[[6. 0. 0.]
 [0. 6. 0.]
 [0. 0. 6.]]

--- weight 1, channel 1 ---
rule of G~: aAB,...AB->...a
rule of G:  aAB,...a->...AB
G · X, the part of T:
[[ 0. -1. -2.]
 [ 1.  0. -1.]
 [ 2.  1.  0.]]

--- weight 2, channel 1 ---
rule of G~: abAB,...AB->...ab
rule of G:  abAB,...ab->...AB
G · X, the part of T:
[[-5.  3.  5.]
 [ 3. -1.  7.]
 [ 5.  7.  6.]]