Skip to content

inv

Invert a diagonal matrix tensor.

inv

inv(tensor: Tensor) -> Tensor

Invert a diagonal matrix tensor.

Takes a diagonal matrix tensor and returns its inverse by inverting each diagonal element. For charge conservation, the input tensor must have opposite index directions.

Supports both Abelian groups (U1Group, Z2Group, etc.) and non-Abelian groups (SU2Group, ProductGroup with SU2Group). For non-Abelian tensors, blocks carry a trailing outer-multiplicity (OM) dimension and an intertwiner (intw) field; both are handled correctly and preserved in the output.

Parameters:

Name Type Description Default
tensor Tensor

Input diagonal matrix tensor with exactly 2 indices. If labeled "Diagonal", the diagonal structure check is skipped.

required

Returns:

Type Description
Tensor

Inverted diagonal matrix with the same structure as input, including the intertwiner field for non-Abelian tensors.

Raises:

Type Description
ValueError

If tensor does not have exactly 2 indices, or if tensor is not diagonal (when label != "Diagonal").

ZeroDivisionError

If any diagonal element is zero (within machine epsilon).

Examples:

>>> from nicole import Tensor, Index, Sector, Direction, U1Group, diag
>>> from nicole.decomp import svd
>>> import torch
>>> # Create a diagonal tensor from SVD
>>> T = Tensor.random([idx_i, idx_j], itags=["i", "j"])
>>> U, S_blocks, Vh = svd(T, axis=0)
>>> S_diag = diag(S_blocks, U.indices[1])
>>> 
>>> # Invert the diagonal matrix
>>> S_inv = inv(S_diag)
>>> 
>>> # Verify: S @ S_inv should give identity
>>> from nicole import contract
>>> result = contract(S_diag, S_inv)
>>> # Manual diagonal tensor (Abelian)
>>> idx = Index(Direction.IN, U1Group(), (Sector(0, 2),))
>>> D = Tensor(
...     indices=(idx.flip(), idx),
...     itags=("i", "j"),
...     data={(0, 0): torch.diag(torch.tensor([2.0, 4.0]))},
...     label="Diagonal"
... )
>>> D_inv = inv(D)
>>> D_inv.data[(0, 0)]
array([[0.5 , 0.  ],
       [0.  , 0.25]])
>>> # SU(2) diagonal tensor (non-Abelian)
>>> from nicole import SU2Group
>>> group = SU2Group()
>>> idx = Index(Direction.IN, group, (Sector(1, 2),))
>>> S_blocks_su2 = {(1, 1): torch.tensor([2.0, 0.5])}
>>> S_diag_su2 = diag(S_blocks_su2, idx)
>>> S_inv_su2 = inv(S_diag_su2)
>>> # S_inv_su2.intw is preserved with same weights as S_diag_su2
Notes

The function inverts each diagonal matrix block independently by computing 1/x for each diagonal element. Off-diagonal elements are assumed to be zero (only checked if label != "Diagonal").

For non-Abelian (SU(2)) tensors, blocks have shape (n, n, 1) with a trailing OM dimension. The diagonal is extracted from block[:, :, 0], and the output block is reconstructed with the same trailing dimension. The intertwiner (Bridge) weights encode the irrep normalisation √(irrep_dim) and are unchanged by inversion; new Bridge objects are built with the transposed index directions.

For numerical stability, elements with absolute value below machine epsilon for float64 will raise ZeroDivisionError.

Description

Takes a diagonal matrix tensor and returns its inverse by inverting each diagonal element. The function handles diagonal tensors created by diag() or manually constructed diagonal matrices.

For charge conservation, the output tensor has transposed index structure (swapped and flipped indices) compared to the input.

Usage

from nicole import decomp, diag, inv, contract

# Create diagonal tensor from SVD
U, S_blocks, Vh = decomp(T, axes=0, mode="SVD")
S_diag = diag(S_blocks, U.indices[1])

# Invert the diagonal matrix
S_inv = inv(S_diag)

# Verify: S @ S_inv should give identity (approximately)
result = contract(S_diag, S_inv)

Manual Diagonal Tensor

import torch
from nicole import Tensor, Index, Sector, Direction, U1Group, inv

group = U1Group()
idx = Index(Direction.IN, group, sectors=(Sector(0, 2),))

# Create manual diagonal tensor
D = Tensor(
    indices=(idx.flip(), idx),
    itags=("i", "j"),
    data={(0, 0): torch.diag(torch.tensor([2.0, 4.0]))},
    label="Diagonal"
)

# Invert it
D_inv = inv(D)
# D_inv.data[(0, 0)] = [[0.5, 0], [0, 0.25]]

See Also

  • diag: Create diagonal tensor from 1D arrays
  • decomp: Tensor decomposition
  • identity: Identity tensor

Notes

  • Input tensor must have exactly 2 indices
  • Each block must be a square diagonal matrix
  • Diagonal elements must be non-zero (raises ZeroDivisionError otherwise)
  • If tensor label is "Diagonal", diagonal structure check is skipped for efficiency
  • Output tensor has transposed index structure for charge conservation