Isotypic Decomposition#
What It Is#
In this library, a symmetric vector space is a pair \((\mathcal{X}, \rho_{\mathcal{X}})\) where \(\rho_{\mathcal{X}}:\mathbb{G}\to \mathrm{GL}(\mathcal{X})\) is a representation.
The isotypic decomposition can be written equivalently at the representation level and at the vector-space level:
These two views are equivalent: block-diagonalizing \(\rho_{\mathcal{X}}\) with \(\mathbf{Q}\) is exactly the same operation as decomposing \(\mathcal{X}\) into isotypic subspaces and irreducible copies.
Notation Convention#
\(\mathbb{G}\) denotes the group.
\(k\) indexes isotypic subspaces / irrep types.
\(i\) indexes multiplicity within type \(k\).
\(\mathcal{X}^{(k)}\) denotes the isotypic subspace of type \(k\).
\(\hat{\mathcal{X}}_k^{(i)}\) denotes the \(i\)-th copy of irrep type \(k\).
\(\hat{\rho}_k\) denotes an irreducible representation.
\(\rho_{\mathcal{X}}\) denotes a (possibly decomposable) representation on \(\mathcal{X}\).
The first block is the invariant subspace when present: \(\mathcal{X}^{\text{inv}}=\mathcal{X}^{(1)}\).
Change Of Basis#
The isotypic/spectral coordinates are defined by:
In practice, use symm_learning.representation_theory.isotypic_decomp_rep(),
which returns an equivalent representation object carrying this change of basis.
Practical Example (Icosahedral Group)#
import torch
from escnn.group import Icosahedral
from symm_learning.representation_theory import direct_sum, isotypic_decomp_rep
# 1) Build a decomposable representation of the Icosahedral group
G = Icosahedral()
rep_x = direct_sum([G.regular_representation] * 2)
# 2) Compute equivalent representation in canonical isotypic ordering
rep_x_iso = isotypic_decomp_rep(rep_x)
# 3) Access change-of-basis operators
Q = torch.tensor(rep_x_iso.change_of_basis, dtype=torch.float32)
Q_inv = torch.tensor(rep_x_iso.change_of_basis_inv, dtype=torch.float32)
# 4) Transform data to spectral/isotypic coordinates and back
x = torch.randn(8, rep_x.size) # batch of vectors in original basis
x_iso = torch.einsum("ij,...j->...i", Q_inv, x)
x_rec = torch.einsum("ij,...j->...i", Q, x_iso)
assert torch.allclose(x, x_rec, atol=1e-5)
# 5) Inspect contiguous slices for each isotypic subspace
# keys are irrep identifiers; values are slices in the isotypic basis coordinates
print(rep_x_iso.attributes["isotypic_subspace_dims"])
Use these slices to apply block-wise operations per irrep type (e.g., constrained statistics, equivariant least squares, and equivariant parametrizations).