svd¶
Low-level SVD returning singular values as dictionary.
svd
¶
svd(T: Tensor, axis: int | str, trunc: Optional[Dict[str, Union[int, float]]] = None, *, requires_info: bool = False) -> Tuple[Tensor, MutableMapping[BlockKey, torch.Tensor], Tensor] | Tuple[Tensor, MutableMapping[BlockKey, torch.Tensor], Tensor, Dict[str, Any]]
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:
|
None
|
requires_info
|
bool
|
If True, return a 4-tuple |
False
|
Returns:
| Type | Description |
|---|---|
tuple[Tensor, MutableMapping[BlockKey, Tensor], Tensor]
|
When
|
tuple[Tensor, MutableMapping[BlockKey, Tensor], Tensor, dict[str, Any]]
|
When
|
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})
>>>
>>> # Special case: inspect discarded weight
>>> U, S_blocks, Vh, info = svd(T, axis=0, trunc={"nkeep": 10}, requires_info=True)
>>> dw = info["discarded_weight"]
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
- info (optional): Dict of auxiliary data, returned only when
requires_info=True. Currently contains: "discarded_weight":float, sum of all singular values truncated away across all charge sectors.
This low-level function provides direct access to singular values for each block before they're combined into a tensor.
Import¶
(Not exported in public API)
See Also¶
- decomp: High-level decomposition
- qr: Low-level QR function
- eig: Eigenvalue decomposition
- Examples: Decomposition
Notes¶
- Use
decomp()for most cases. Usesvd()when you need per-block singular value access before tensor creation. - Pass
requires_info=Trueto obtain theinfodict containing"discarded_weight". This incurs a small extra computation and is intended for diagnostic use. - For Abelian tensors,
VhsatisfiesVh @ Vh† = Idirectly from the standard block-wise matrix SVD. - For SU(2) tensors, the intertwiner weight matrix is canonicalized to a scaled unitary form before the SVD, ensuring
Vhis a physical isometry (Vh @ Vh† = I).