Skip to content

diag

Convert diagonal blocks into a diagonal matrix tensor.

diag

diag(
    S_blocks: Dict[BlockKey, Tensor],
    bond_index: Index,
    itags: Optional[Tuple[str, str]] = None,
    dtype: Optional[dtype] = None,
    device: Optional[device] = None,
) -> Tensor

Convert diagonal blocks (from SVD or eig) into a diagonal matrix tensor.

Takes a dictionary of 1D arrays (such as singular values from SVD or eigenvalues from eig) and creates a diagonal matrix tensor where each 1D array becomes a diagonal matrix block.

For Abelian groups, creates standard diagonal blocks. For generic groups (e.g., SU(2)), creates blocks with trailing reduced multiplicity dimension and intertwiner (Bridge) with proper normalization.

Parameters:

Name Type Description Default
S_blocks dict[BlockKey, Tensor]

Dictionary mapping block keys to 1D arrays. Each array contains the diagonal elements for that block. Typically from the S output of svd() or D from eig().

required
bond_index Index

The bond index defining the sectors and dimensions. Both output indices will be based on this index (one normal, one flipped).

required
itags tuple of two str

Custom itags for the two output indices. If None, uses ("_bond_L", "_bond_R"). Default: None.

None
dtype dtype

Data type for the output tensor. If None, inferred from input arrays. Default: None.

None

Returns:

Type Description
Tensor

Diagonal matrix tensor with two indices (bond_index.flip(), bond_index). For generic groups, includes intertwiner (intw) field with weights set to √(irrep_dim(q)). Label is set to "Diagonal".

Raises:

Type Description
ValueError

If any data block is not 1-dimensional.

Examples:

>>> from nicole import Tensor, Index, Sector, Direction, U1Group, decomp
>>> import torch
>>> # Perform SVD
>>> T = Tensor.random([idx_i, idx_j], itags=["i", "j"])
>>> U, S_blocks, Vh = svd(T, axis=0)  # Get S as dict
>>> 
>>> # Convert S_blocks to diagonal matrix
>>> from nicole import diag
>>> S_diag = diag(S_blocks, U.indices[1], itags=("left", "right"))
>>> S_diag.itags
('left', 'right')
>>> S_diag.label
'Diagonal'
>>> # Can now use S_diag in contractions
>>> result = contract(U, S_diag)  # Equivalent to U @ S
>>> # SU(2) case
>>> from nicole import SU2Group
>>> group = SU2Group()
>>> idx = Index(Direction.OUT, group, sectors=(Sector(1, 3),))
>>> S_blocks_su2 = {(1, 1): torch.tensor([2.0, 1.5, 0.5])}
>>> S_diag_su2 = diag(S_blocks_su2, idx)
>>> # S_diag_su2.data[(1, 1)].shape is (3, 3, 1) - includes OM dimension
>>> # S_diag_su2.intw[(1, 1)].weights is √(irrep_dim(1)) = √2
Notes

This function is useful for converting the singular values dict S from svd() or eigenvalues dict D from eig() into full diagonal matrix form for explicit matrix operations like contraction.

The output tensor will have:

  • Two indices: (bond_index.flip(), bond_index)
  • Block keys (q, q) for each charge q in S_blocks
  • Diagonal matrices as data blocks
  • For non-Abelian groups: trailing OM dimension and Bridge weights = √(irrep_dim)
  • Label "Diagonal" (overriding default "Tensor")

Description

Takes a dictionary of 1D arrays (such as singular values from SVD or eigenvalues from eigendecomposition) and creates a diagonal matrix tensor where each 1D array becomes a diagonal matrix block.

This is useful for converting the singular values dict from svd() or eigenvalues dict from eig() into full diagonal matrix form for explicit matrix operations like contraction.

Usage

from nicole import decomp, diag, contract

# Perform decomposition to get singular value dict
U, S_blocks, Vh = decomp(T, axes=0, mode="SVD")

# Convert S_blocks (dict of 1D arrays) to diagonal matrix tensor
S_diag = diag(S_blocks, U.indices[1], itags=("left", "right"))

# Now can use S_diag in contractions
result = contract(U, S_diag)  # Equivalent to U @ S

See Also

  • decomp: Tensor decomposition returning S as dict
  • inv: Matrix inversion for diagonal tensors
  • oplus: Direct sum operation

Notes

The output tensor will have:

  • Two indices: (bond_index.flip(), bond_index)
  • Block keys (q, q) for each charge q in input dict
  • Diagonal matrices as data blocks
  • Label "Diagonal"

All input arrays must be 1-dimensional (one value per charge sector).