Skip to content

svd

Low-level SVD returning singular values as dictionary.

svd

svd(
    T: Tensor,
    axis: int | str,
    trunc: Optional[Dict[str, Union[int, float]]] = None,
) -> Tuple[Tensor, MutableMapping[BlockKey, torch.Tensor], Tensor]

Perform a symmetry-preserving SVD separating one axis from all others.

Parameters:

Name Type Description Default
T Tensor

Tensor to be decomposed.

required
axis int | str

Axis to separate from all others. Can be an integer axis or itag. This axis forms the left partition, all others form the right partition.

required
trunc Optional[Dict[str, Union[int, float]]]

Truncation specification as a dict. If None, no truncation. Supported keys:

  • "nkeep": Keep at most n singular values globally (largest across all blocks)
  • "thresh": Keep singular values >= t per block
Both can be specified together: thresh is applied first, then nkeep.

None

Returns:

Type Description
tuple[Tensor, MutableMapping[BlockKey, Tensor], Tensor]

Triplet (U, S_blocks, Vh) where:

  • U has indices (left_index, bond_index)
  • S_blocks is a Dict mapping block keys to 1D arrays of singular values
  • Vh has indices (bond_index.flip(), *right_indices)

Raises:

Type Description
ValueError

If trunc format is invalid or contains unsupported modes.

Notes

The singular values are returned as 1D arrays for memory efficiency. Use the decomp() function with mode="SVD" if you need S as a diagonal matrix tensor.

For "nkeep" mode, truncation is applied globally: the top n singular values across all blocks are retained. For "thresh" mode, truncation is applied per block: each block independently keeps singular values >= threshold.

When both modes are specified, "thresh" is applied first (per-block filtering), then "nkeep" is applied globally to the remaining singular values.

Examples:

>>> # No truncation
>>> U, S_blocks, Vh = svd(T, axis=0)
>>> 
>>> # Keep top 10 singular values
>>> U, S_blocks, Vh = svd(T, axis=0, trunc={"nkeep": 10})
>>> 
>>> # Keep singular values >= 0.01
>>> U, S_blocks, Vh = svd(T, axis=0, trunc={"thresh": 0.01})
>>> 
>>> # Apply both: first thresh, then nkeep
>>> U, S_blocks, Vh = svd(T, axis=0, trunc={"thresh": 0.01, "nkeep": 10})

Description

Performs block-wise SVD, returning:

  • U: Left unitary tensor
  • S_dict: Dictionary mapping block keys to 1D singular value arrays
  • Vh: Right unitary tensor

This low-level function provides direct access to singular values for each block before they're combined into a tensor.

Import

from nicole.decomp import svd

(Not exported in public API)

See Also

Notes

Use decomp() for most cases. Use svd() when you need per-block singular value access before tensor creation.