Skip to content

contract

Contract two tensors along specified index pairs.

contract

contract(
    A: Tensor,
    B: Tensor,
    axes: Optional[
        Tuple[int, int] | Tuple[Sequence[int], Sequence[int]]
    ] = None,
    excl: Optional[Tuple[Sequence[int], Sequence[int]]] = None,
    perm: Optional[Sequence[int]] = None,
) -> Tensor

Contract two tensors along provided index pairs while respecting symmetry.

Parameters:

Name Type Description Default
A Tensor

Input tensors to be contracted.

required
B Tensor

Input tensors to be contracted.

required
axes Optional[Tuple[int, int] | Tuple[Sequence[int], Sequence[int]]]

Optional specification of axes to contract. Can be either:

  • Single pair: (axis_in_A, axis_in_B) for contracting one pair
  • Multiple pairs: ([axes_in_A], [axes_in_B]) for contracting multiple pairs
Similar to np.tensordot syntax. Validates that each pair has matching itags and opposite directions. Mutually exclusive with excl.

None
excl Optional[Tuple[Sequence[int], Sequence[int]]]

Optional tuple of two sequences specifying axes to exclude from automatic contraction: ([excl_axes_in_A], [excl_axes_in_B]). When specified, automatically contracts all indices with matching itags and opposite directions, except those in the exclusion lists. Examples: excl=((0,), ()) excludes A's axis 0; excl=((), (1,)) excludes B's axis 1. Mutually exclusive with axes.

None
perm Optional[Sequence[int]]

Optional permutation for the resulting tensor axes. If provided, the axes of the contracted tensor will be reordered according to this sequence.

None

Returns:

Type Description
Tensor

Tensor whose indices are the non-contracted axes of A followed by those of B, populated with blocks that satisfy charge conservation.

Raises:

Type Description
ValueError

If both axes and excl are specified, or if manually specified axes have mismatched itags or non-opposite directions, or if no valid contraction pairs are found, or if automatic detection encounters ambiguous pairing.

Examples:

Automatic contraction (recommended for most cases):

>>> # Tensors with matching itags and opposite directions
>>> A = Tensor.random([idx_a, idx_b], itags=["left", "mid"])
>>> B = Tensor.random([idx_b_flip, idx_c], itags=["mid", "right"])
>>> result = contract(A, B)  # Automatically contracts "mid" indices
>>> result.itags
('left', 'right')

Manual contraction with axes parameter:

>>> # Single pair: concise syntax (axis_in_A, axis_in_B)
>>> A = Tensor.random([idx_i, idx_j], itags=["i", "j"])
>>> B = Tensor.random([idx_j_flip, idx_k], itags=["j", "k"])
>>> result = contract(A, B, axes=(1, 0))
>>> result.itags
('i', 'k')
>>> # Single pair: also works with sequence syntax
>>> result = contract(A, B, axes=([1], [0]))

Multiple contractions:

>>> # Contract multiple index pairs at once
>>> A = Tensor.random([idx_a, idx_b, idx_c], itags=["a", "b", "c"])
>>> B = Tensor.random([idx_b_flip, idx_c_flip, idx_d], itags=["b", "c", "d"])
>>> result = contract(A, B, axes=([1, 2], [0, 1]))  # or use automatic mode
>>> result.itags
('a', 'd')

Using excl parameter for automatic contraction with exclusions:

>>> # Contract all matching itags except A's axis 0
>>> result = contract(A, B, excl=((0,), ()))
>>> # Contract all matching itags except B's axis 0
>>> result = contract(A, B, excl=((), (0,)))
>>> # Exclude axes from both tensors
>>> result = contract(A, B, excl=((0, 1), (2,)))

Using permutation to reorder output:

>>> # Contract and then permute the result
>>> A = Tensor.random([idx_i, idx_j], itags=["i", "j"])
>>> B = Tensor.random([idx_j_flip, idx_k], itags=["j", "k"])
>>> result = contract(A, B, axes=(1, 0), perm=[1, 0])
>>> result.itags  # Swapped from default order
('k', 'i')

Resolving ambiguity with manual axes:

>>> # When automatic detection is ambiguous, specify explicitly
>>> A = Tensor.random([idx_a, idx_a], itags=["x", "x"])  # Duplicate tags
>>> B = Tensor.random([idx_a_flip, idx_a_flip], itags=["x", "x"])
>>> # contract(A, B) would raise ValueError due to ambiguity
>>> result = contract(A, B, axes=([0, 1], [0, 1]))  # Explicitly pair them
Notes

The automatic detection mode checks for unique pairings. If an itag appears multiple times with valid opposite directions, manual specification is required to avoid ambiguity.

The output tensor has indices ordered as: non-contracted indices from A, followed by non-contracted indices from B. Use the perm parameter to reorder if needed.

Description

Performs tensor contraction while preserving charge conservation. Can automatically contract indices with matching tags and opposite directions, or manually specify pairs.

Automatic vs Manual Contraction

Automatic (axes=None):

  • Finds all indices where tags match
  • Requires opposite directions (OUT ↔ IN)
  • Contracts all matching pairs

Manual (axes specified):

  • Contract only specified index pairs
  • Still requires opposite directions
  • Validates tag matching

See Also

Notes

Only blocks satisfying charge conservation are computed. For contracted indices, charges must match. Output blocks must conserve total charge.