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'
>>> # 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).