Contraction, SVD, and QR¶
The contraction engine translates label-based tensor operations into optimised einsum calls executed by JAX.
Label-based contraction¶
The core idea: legs with the same label across different tensors are automatically summed over.
from tenax import contract
# A has legs ("i", "bond"), B has legs ("bond", "j")
C = contract(A, B)
# "bond" appears in both -> contracted
# Result has legs ("i", "j")
Multi-tensor contraction¶
contract accepts any number of tensors. Internally it uses opt_einsum
to find the optimal contraction order:
D = contract(A, B, C) # three-tensor contraction
Controlling output label order¶
By default, free labels appear in the order they are encountered. Use
output_labels to specify an explicit ordering:
C = contract(A, B, output_labels=("j", "i"))
Optimiser selection¶
The optimize parameter selects the opt_einsum strategy:
C = contract(A, B, optimize="auto") # default
C = contract(A, B, optimize="greedy") # faster for large networks
C = contract(A, B, optimize="optimal") # brute-force optimal
Truncated SVD¶
truncated_svd decomposes a tensor into U, s, V^dagger with truncation:
from tenax import truncated_svd
# Split tensor T with legs ("left", "phys", "right") along the cut
# left_labels vs right_labels
U, s, Vh, s_full = truncated_svd(
T,
left_labels=["left", "phys"],
right_labels=["right"],
new_bond_label="bond",
max_singular_values=16,
)
# U has legs ("left", "phys", "bond")
# s is a 1D JAX array of truncated singular values
# Vh has legs ("bond", "right")
# s_full is the complete singular value spectrum before truncation
Parameters controlling truncation:
max_singular_values– hard cap on the bond dimensionmax_truncation_err– discard smallest singular values until the relative truncation error exceeds this threshold
Both dense and symmetric tensors are supported. For SymmetricTensor,
the SVD is performed block-by-block within each charge sector.
QR decomposition¶
qr_decompose splits a tensor into an orthogonal factor Q and an upper-
triangular factor R:
from tenax import qr_decompose
Q, R = qr_decompose(
T,
left_labels=["left", "phys"],
right_labels=["right"],
new_bond_label="bond",
)
# Q has legs ("left", "phys", "bond") -- isometric
# R has legs ("bond", "right")
QR is cheaper than SVD and is useful for canonicalising MPS tensors during DMRG sweeps.
Lower-level API¶
For full control, contract_with_subscripts accepts explicit einsum
subscript strings:
from tenax import contract_with_subscripts
result = contract_with_subscripts(
[A, B],
subscripts="ij,jk->ik",
output_indices=(...), # TensorIndex tuple for the result
)
This is mainly used internally by the TensorNetwork graph container.