Core – Symmetries, Indices, and Tensors

Symmetry

Symmetry group definitions for symmetric tensor networks.

This module provides the mathematical foundation for symmetric tensors. All symmetry classes operate on numpy integer arrays of charge values. No JAX dependency — pure Python/numpy arithmetic.

class tenax.core.symmetry.BraidingStyle(*values)[source]

Bases: Enum

Classification of particle exchange statistics.

BOSONIC: Trivial exchange (sign = +1 always). FERMIONIC: Anti-commuting exchange (sign = (-1)^{p_a * p_b}). ANYONIC: General phase on exchange (reserved for future use).

BOSONIC = 'bosonic'
FERMIONIC = 'fermionic'
ANYONIC = 'anyonic'
class tenax.core.symmetry.BaseSymmetry[source]

Bases: ABC

Abstract base for symmetry groups governing tensor index charges.

A symmetry group defines how charges combine (fuse) when tensor legs are merged, and how charges transform when a leg’s flow is reversed (dual).

Concrete subclasses must implement fuse, dual, identity, and n_values. All concrete classes should implement __eq__ and __hash__ so they can serve as dict keys and be compared for compatibility checks.

abstractmethod fuse(charges_a, charges_b)[source]

Fuse two charge arrays element-wise under group multiplication.

Parameters:
  • charges_a (ndarray) – Integer charge array of shape (D,).

  • charges_b (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Fused charge array of shape (D,).

abstractmethod dual(charges)[source]

Return the group inverse (dual) of each charge.

Used to flip a leg’s flow direction while preserving compatibility.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Dual charge array of shape (D,).

abstractmethod identity()[source]

Return the identity element (neutral charge, typically 0).

Return type:

int

abstractmethod n_values()[source]

Return the number of distinct charge values, or None if infinite (U(1)).

Return type:

int | None

fuse_many(charge_list)[source]

Fuse a list of charge arrays left-to-right via repeated fuse().

Parameters:

charge_list (list[ndarray]) – Non-empty list of integer charge arrays, all shape (D,).

Return type:

ndarray

Returns:

Fully fused charge array of shape (D,).

property braiding_style: BraidingStyle

Exchange statistics of this symmetry (bosonic by default).

property is_fermionic: bool

True if this symmetry has fermionic exchange statistics.

parity(charges)[source]

Return the Z2 parity grading of each charge (0=even, 1=odd).

For bosonic symmetries, all charges have even parity.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Integer array of shape (D,) with values in {0, 1}.

exchange_sign(charge_a, charge_b)[source]

Sign from exchanging two particles with given charges.

Returns (-1)^{p_a * p_b} where p is the parity grading. For bosonic symmetries, always returns +1.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

int

Returns:

+1 or -1.

exchange_phase(charge_a, charge_b)[source]

Phase from exchanging two particles (generalizes exchange_sign).

For fermionic symmetries this equals exchange_sign. For anyonic symmetries this can be a general complex phase.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

complex

Returns:

Complex phase factor.

twist_phase(charge)[source]

Topological twist (ribbon element) for a charge sector.

For fermions: (-1)^p where p is the parity of the charge. For bosons: always 1.

Parameters:

charge (int) – Charge value.

Return type:

complex

Returns:

Complex phase factor.

is_conserved(charges_per_leg, flows, target=None)[source]

Check if a single charge combination satisfies conservation.

Parameters:
  • charges_per_leg (list[ndarray]) – List of scalar-or-array charge values per leg.

  • flows (list[int]) – List of +1 (IN) or -1 (OUT) per leg.

  • target (int | None) – Required net charge; defaults to identity().

Return type:

bool

Returns:

True if the net charge equals target.

class tenax.core.symmetry.U1Symmetry[source]

Bases: BaseSymmetry

U(1) symmetry: integer charges, fusion by addition.

Represents the continuous U(1) group (particle number conservation, total Sz conservation, etc.). Charges are unbounded integers.

Example

>>> sym = U1Symmetry()
>>> sym.fuse(np.array([0, 1, -1]), np.array([1, -1, 0]))
array([1, 0, -1])
fuse(charges_a, charges_b)[source]

Fuse two charge arrays element-wise under group multiplication.

Parameters:
  • charges_a (ndarray) – Integer charge array of shape (D,).

  • charges_b (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Fused charge array of shape (D,).

dual(charges)[source]

Return the group inverse (dual) of each charge.

Used to flip a leg’s flow direction while preserving compatibility.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Dual charge array of shape (D,).

identity()[source]

Return the identity element (neutral charge, typically 0).

Return type:

int

n_values()[source]

Return the number of distinct charge values, or None if infinite (U(1)).

Return type:

None

class tenax.core.symmetry.ZnSymmetry(n)[source]

Bases: BaseSymmetry

Z_n symmetry: integer charges mod n, fusion by addition mod n.

Represents the discrete cyclic group Z_n (e.g., Z_2 for fermion parity, Z_3 for three-state Potts model, etc.).

Parameters:

n (int) – The order of the group. Must be >= 2.

Example

>>> sym = ZnSymmetry(3)
>>> sym.fuse(np.array([1, 2]), np.array([2, 2]))
array([0, 1])
fuse(charges_a, charges_b)[source]

Fuse two charge arrays element-wise under group multiplication.

Parameters:
  • charges_a (ndarray) – Integer charge array of shape (D,).

  • charges_b (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Fused charge array of shape (D,).

dual(charges)[source]

Return the group inverse (dual) of each charge.

Used to flip a leg’s flow direction while preserving compatibility.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Dual charge array of shape (D,).

identity()[source]

Return the identity element (neutral charge, typically 0).

Return type:

int

n_values()[source]

Return the number of distinct charge values, or None if infinite (U(1)).

Return type:

int

class tenax.core.symmetry.BaseNonAbelianSymmetry[source]

Bases: BaseSymmetry

Stub base class for non-Abelian symmetries (e.g., SU(2)).

Non-Abelian symmetries require Clebsch-Gordan / recoupling coefficients for tensor contractions, making them significantly more complex than Abelian symmetries. This base provides the interface contract for future concrete implementations.

Note

Concrete subclasses must implement recoupling_coefficients and allowed_fusions in addition to the BaseSymmetry abstract methods. The fuse/dual/identity/n_values methods for non-Abelian groups operate on irrep labels (e.g., spin quantum numbers).

abstractmethod recoupling_coefficients(j1, j2, j3)[source]

Return Clebsch-Gordan or 6j-symbol coefficients for recoupling.

These coefficients are needed when contracting non-Abelian symmetric tensors. The specific form depends on the group (CG coefficients for SU(2), etc.).

Parameters:
  • j1 (int) – First irrep label.

  • j2 (int) – Second irrep label.

  • j3 (int) – Output irrep label (must be in allowed_fusions(j1, j2)).

Return type:

ndarray

Returns:

Coefficient array for the (j1, j2) -> j3 channel.

abstractmethod allowed_fusions(j1, j2)[source]

Return list of irrep labels appearing in tensor product j1 x j2.

For SU(2) with spin quantum numbers j1, j2, this returns [abs(j1 - j2), ..., j1 + j2] (triangular rule).

Parameters:
  • j1 (int) – First irrep label.

  • j2 (int) – Second irrep label.

Return type:

list[int]

Returns:

Sorted list of irrep labels in the decomposition.

class tenax.core.symmetry.FermionParity[source]

Bases: BaseSymmetry

Z2 symmetry with fermionic braiding statistics.

Charges are 0 (even/bosonic) or 1 (odd/fermionic). Fusion is addition mod 2. Exchanging two odd-parity objects yields a minus sign.

Example

>>> sym = FermionParity()
>>> sym.exchange_sign(1, 1)
-1
>>> sym.exchange_sign(0, 1)
1
property braiding_style: BraidingStyle

Exchange statistics of this symmetry (bosonic by default).

property is_fermionic: bool

True if this symmetry has fermionic exchange statistics.

fuse(charges_a, charges_b)[source]

Fuse two charge arrays element-wise under group multiplication.

Parameters:
  • charges_a (ndarray) – Integer charge array of shape (D,).

  • charges_b (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Fused charge array of shape (D,).

dual(charges)[source]

Return the group inverse (dual) of each charge.

Used to flip a leg’s flow direction while preserving compatibility.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Dual charge array of shape (D,).

identity()[source]

Return the identity element (neutral charge, typically 0).

Return type:

int

n_values()[source]

Return the number of distinct charge values, or None if infinite (U(1)).

Return type:

int

parity(charges)[source]

Return the Z2 parity grading of each charge (0=even, 1=odd).

For bosonic symmetries, all charges have even parity.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Integer array of shape (D,) with values in {0, 1}.

exchange_sign(charge_a, charge_b)[source]

Sign from exchanging two particles with given charges.

Returns (-1)^{p_a * p_b} where p is the parity grading. For bosonic symmetries, always returns +1.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

int

Returns:

+1 or -1.

exchange_phase(charge_a, charge_b)[source]

Phase from exchanging two particles (generalizes exchange_sign).

For fermionic symmetries this equals exchange_sign. For anyonic symmetries this can be a general complex phase.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

complex

Returns:

Complex phase factor.

twist_phase(charge)[source]

Topological twist (ribbon element) for a charge sector.

For fermions: (-1)^p where p is the parity of the charge. For bosons: always 1.

Parameters:

charge (int) – Charge value.

Return type:

complex

Returns:

Complex phase factor.

class tenax.core.symmetry.FermionicU1(grading=None, grading_key='abs_mod_2')[source]

Bases: BaseSymmetry

U(1) symmetry with fermionic exchange statistics.

Charges are unbounded integers (like U1Symmetry), but a grading function maps each charge to a Z2 parity (0=even, 1=odd).

Parameters:
  • grading (object) – Callable mapping int -> {0, 1}. If None, uses the default |q| % 2 (odd particle number = fermionic).

  • grading_key (Text) – String key identifying the grading function. Used for equality/hash so that two FermionicU1 instances with the same grading are considered equal.

Example

>>> sym = FermionicU1()
>>> sym.parity(np.array([0, 1, 2, 3]))
array([0, 1, 0, 1])
property braiding_style: BraidingStyle

Exchange statistics of this symmetry (bosonic by default).

property is_fermionic: bool

True if this symmetry has fermionic exchange statistics.

fuse(charges_a, charges_b)[source]

Fuse two charge arrays element-wise under group multiplication.

Parameters:
  • charges_a (ndarray) – Integer charge array of shape (D,).

  • charges_b (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Fused charge array of shape (D,).

dual(charges)[source]

Return the group inverse (dual) of each charge.

Used to flip a leg’s flow direction while preserving compatibility.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Dual charge array of shape (D,).

identity()[source]

Return the identity element (neutral charge, typically 0).

Return type:

int

n_values()[source]

Return the number of distinct charge values, or None if infinite (U(1)).

Return type:

None

parity(charges)[source]

Return the Z2 parity grading of each charge (0=even, 1=odd).

For bosonic symmetries, all charges have even parity.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Integer array of shape (D,) with values in {0, 1}.

exchange_sign(charge_a, charge_b)[source]

Sign from exchanging two particles with given charges.

Returns (-1)^{p_a * p_b} where p is the parity grading. For bosonic symmetries, always returns +1.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

int

Returns:

+1 or -1.

exchange_phase(charge_a, charge_b)[source]

Phase from exchanging two particles (generalizes exchange_sign).

For fermionic symmetries this equals exchange_sign. For anyonic symmetries this can be a general complex phase.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

complex

Returns:

Complex phase factor.

twist_phase(charge)[source]

Topological twist (ribbon element) for a charge sector.

For fermions: (-1)^p where p is the parity of the charge. For bosons: always 1.

Parameters:

charge (int) – Charge value.

Return type:

complex

Returns:

Complex phase factor.

class tenax.core.symmetry.ProductSymmetry(sym1, sym2)[source]

Bases: BaseSymmetry

Direct product of two symmetries with bit-packed charges.

Charges from the two factor symmetries are encoded into a single int32 via bit-packing: encoded = (q2 << 16) | (q1 & 0xFFFF). Component charges are limited to the int16 range [-32768, 32767].

Parameters:
Raises:

TypeError – If either factor is itself a ProductSymmetry (no nesting).

Example

>>> sym = ProductSymmetry(FermionParity(), U1Symmetry())
>>> encoded = ProductSymmetry.encode(1, 3)
>>> ProductSymmetry.decode(encoded)
(1, 3)
static encode(q1, q2)[source]

Pack two int16 charges into one int32.

Return type:

int

Parameters:
static decode(encoded)[source]

Unpack one int32 into two int16 charges.

Return type:

KeyPath[int, int]

Parameters:

encoded (int)

static encode_charges(arr1, arr2)[source]

Vectorized encoding of two charge arrays.

Return type:

ndarray

Parameters:
static decode_charges(arr)[source]

Vectorized decoding of a packed charge array.

Return type:

KeyPath[ndarray, ndarray]

Parameters:

arr (ndarray)

fuse(charges_a, charges_b)[source]

Fuse two charge arrays element-wise under group multiplication.

Parameters:
  • charges_a (ndarray) – Integer charge array of shape (D,).

  • charges_b (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Fused charge array of shape (D,).

dual(charges)[source]

Return the group inverse (dual) of each charge.

Used to flip a leg’s flow direction while preserving compatibility.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Dual charge array of shape (D,).

identity()[source]

Return the identity element (neutral charge, typically 0).

Return type:

int

n_values()[source]

Return the number of distinct charge values, or None if infinite (U(1)).

Return type:

int | None

property braiding_style: BraidingStyle

Exchange statistics of this symmetry (bosonic by default).

property is_fermionic: bool

True if this symmetry has fermionic exchange statistics.

parity(charges)[source]

Return the Z2 parity grading of each charge (0=even, 1=odd).

For bosonic symmetries, all charges have even parity.

Parameters:

charges (ndarray) – Integer charge array of shape (D,).

Return type:

ndarray

Returns:

Integer array of shape (D,) with values in {0, 1}.

exchange_sign(charge_a, charge_b)[source]

Sign from exchanging two particles with given charges.

Returns (-1)^{p_a * p_b} where p is the parity grading. For bosonic symmetries, always returns +1.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

int

Returns:

+1 or -1.

exchange_phase(charge_a, charge_b)[source]

Phase from exchanging two particles (generalizes exchange_sign).

For fermionic symmetries this equals exchange_sign. For anyonic symmetries this can be a general complex phase.

Parameters:
  • charge_a (int) – Charge of first particle.

  • charge_b (int) – Charge of second particle.

Return type:

complex

Returns:

Complex phase factor.

twist_phase(charge)[source]

Topological twist (ribbon element) for a charge sector.

For fermions: (-1)^p where p is the parity of the charge. For bosons: always 1.

Parameters:

charge (int) – Charge value.

Return type:

complex

Returns:

Complex phase factor.

Index

class tenax.core.index.FlowDirection(*values)[source]

Bases: IntEnum

Flow direction of a tensor leg.

IN (+1): Incoming leg — corresponds to a “ket” index, arrow pointing

into the tensor. Positive charge flows in.

OUT (-1): Outgoing leg — corresponds to a “bra” index, arrow pointing

out of the tensor. Positive charge flows out.

Conservation law: sum_i(flow_i * charge_i) == symmetry.identity() for any valid block of a symmetric tensor.

IN = 1
OUT = -1
class tenax.core.index.TensorIndex(symmetry, charges, flow, label='')[source]

Bases: object

Metadata for one leg (index) of a symmetric tensor.

TensorIndex is frozen and slots-based for memory efficiency — large networks create millions of these objects.

Parameters:
symmetry

The symmetry group governing charges on this leg.

charges

1-D numpy int32 array of length D (bond dimension). charges[i] is the charge of basis state i.

flow

Whether this leg is incoming (IN) or outgoing (OUT).

label

Human-readable or integer identifier for this leg. Shared labels across tensors drive automatic contraction.

Example

>>> u1 = U1Symmetry()
>>> idx = TensorIndex(u1, np.array([-1, 0, 1], dtype=np.int32), FlowDirection.IN, label="left")
>>> idx.dim
3
>>> idx.dual().flow
<FlowDirection.OUT: -1>
symmetry: BaseSymmetry
charges: ndarray
flow: FlowDirection
label: str | int
property dim: int

Bond dimension of this leg (number of basis states).

dual()[source]

Return a new TensorIndex with flipped flow and dual charges.

Used when reversing a leg direction. The dual of an IN leg is an OUT leg with negated (for U(1)) or modular-negated (for Zn) charges.

Return type:

TensorIndex

Returns:

New TensorIndex with opposite flow and dual charges.

relabel(new_label)[source]

Return a new TensorIndex with a different label, otherwise identical.

Parameters:

new_label (Text | int) – The replacement label.

Return type:

TensorIndex

Returns:

New frozen TensorIndex with the updated label.

is_dual_of(other)[source]

Check if this index is the exact dual of other.

Strict check: requires opposite flows AND charge arrays that are dual of each other. Used to validate that two legs can be contracted while preserving exact charge conservation.

Parameters:

other (TensorIndex) – Another TensorIndex to compare against.

Return type:

bool

Returns:

True if self and other are exact duals.

compatible_with(other)[source]

Check if this index can be connected to other in a network.

Looser than is_dual_of: requires same symmetry type, same bond dimension, and opposite flows. Does not require exact charge matching (useful for connecting tensors where charges may differ by relabeling).

Parameters:

other (TensorIndex) – Another TensorIndex to check compatibility with.

Return type:

bool

Returns:

True if the two indices can be connected.

Tensor

class tenax.core.tensor.DenseTensor(data, indices)[source]

Bases: Tensor

A tensor stored as a plain JAX array with index metadata.

Used when no symmetry structure is exploited. Full compatibility with jax.jit, jax.vmap, jax.grad via pytree registration.

Pytree structure:

Leaves: (data_array,) Aux data: indices tuple (static, not traced by JAX)

Parameters:
  • data (Array) – JAX array of shape matching the dimension of each index.

  • indices (KeyPath[TensorIndex, ...]) – Tuple of TensorIndex objects, one per leg.

Example

>>> data = jnp.ones((2, 3))
>>> t = DenseTensor(data, (idx_a, idx_b))
>>> t.norm()
DeviceArray(2.4494898, dtype=float32)
tree_flatten()[source]
Return type:

KeyPath[KeyPath[Array], KeyPath[TensorIndex, ...]]

classmethod tree_unflatten(aux, children)[source]
Return type:

DenseTensor

Parameters:
property indices: tuple[TensorIndex, ...]
property ndim: int
property dtype: Any
todense()[source]
Return type:

Array

conj()[source]
Return type:

DenseTensor

transpose(axes)[source]

Permute tensor legs.

Parameters:

axes (KeyPath[int, ...]) – New ordering of leg indices.

Return type:

DenseTensor

Returns:

New DenseTensor with permuted data and reordered indices.

norm()[source]

Frobenius norm.

Return type:

Array

relabel(old, new)[source]

Return a copy with one leg label renamed.

Parameters:
  • old (Text | int) – Current label to replace.

  • new (Text | int) – New label value.

Return type:

DenseTensor

Returns:

New DenseTensor with the specified label changed.

Raises:

KeyError – If old is not found among the tensor’s labels.

relabels(mapping)[source]

Return a copy with multiple leg labels renamed at once.

Parameters:

mapping (WSGIEnvironment[Text | int, Text | int]) – {old_label: new_label} pairs. Labels not present in the mapping are left unchanged.

Return type:

DenseTensor

Returns:

New DenseTensor with the specified labels changed.

class tenax.core.tensor.SymmetricTensor(blocks, indices)[source]

Bases: Tensor

Block-sparse tensor storing only symmetry-allowed charge sectors.

Storage model:

  • _blocks: dict[BlockKey, jax.Array] – Key is a tuple of one representative charge per leg. Value is a JAX array of shape (n_states_leg0, ..., n_states_legN) for that charge sector.

  • _indices: tuple[TensorIndex, ...] – Full index metadata per leg.

Conservation law enforced on all stored blocks:

sum_i(flow_i * charge_i) == symmetry.identity()
Pytree structure:

Leaves: list of block arrays [blocks[k] for k in sorted_keys] Aux data: (sorted_keys, indices) — static, not traced by JAX

Note on JAX JIT compatibility:

Block structure (keys) is static Python data. jax.jit recompiles only when the set of keys changes (i.e., when bond dimension changes after SVD truncation). Within a DMRG sweep at fixed bond dim, no recompilation occurs.

Parameters:
  • blocks (WSGIEnvironment[KeyPath[int, ...], Array]) – Dict mapping BlockKey -> JAX array for each allowed sector.

  • indices (KeyPath[TensorIndex, ...]) – Tuple of TensorIndex objects, one per leg.

Example

>>> t = SymmetricTensor.zeros(indices=(idx_in, idx_out))
>>> t.n_blocks
3  # one block per unique charge value
tree_flatten()[source]
Return type:

KeyPath[list[Array], KeyPath[list[KeyPath[int, ...]], KeyPath[TensorIndex, ...]]]

classmethod tree_unflatten(aux, children)[source]
Return type:

SymmetricTensor

Parameters:
classmethod zeros(indices, dtype=<class 'jax.numpy.float64'>)[source]

Create a zero tensor with all valid charge sectors initialized to zero.

Parameters:
  • indices (KeyPath[TensorIndex, ...]) – Tuple of TensorIndex objects.

  • dtype (Any) – Data type for block arrays.

Return type:

SymmetricTensor

Returns:

SymmetricTensor with all valid blocks set to zero.

classmethod random_normal(indices, key, dtype=<class 'jax.numpy.float64'>, stddev=1.0)[source]

Create a random tensor with blocks drawn from N(0, stddev).

Splits the JAX random key sequentially over blocks.

Parameters:
  • indices (KeyPath[TensorIndex, ...]) – Tuple of TensorIndex objects.

  • key (Array) – JAX random key.

  • dtype (Any) – Data type for block arrays.

  • stddev (float) – Standard deviation of the normal distribution.

Return type:

SymmetricTensor

Returns:

SymmetricTensor with random entries in all valid blocks.

classmethod from_dense(data, indices, tol=1e-12)[source]

Extract block-sparse structure from a dense JAX array.

Elements outside valid charge sectors must be zero (within tol) or a ValueError is raised.

Parameters:
  • data (Array) – Dense JAX array of shape matching index dimensions.

  • indices (KeyPath[TensorIndex, ...]) – Tuple of TensorIndex objects.

  • tol (float) – Tolerance for checking zero elements outside blocks.

Return type:

SymmetricTensor

Returns:

SymmetricTensor with blocks extracted from data.

Raises:

ValueError – If data has non-zero elements outside valid sectors.

property indices: tuple[TensorIndex, ...]
property ndim: int
property dtype: Any
property n_blocks: int

Number of non-empty charge sectors.

property blocks: dict[tuple[int, ...], Array]

Read-only view of the block dict.

todense()[source]

Materialize the full dense tensor (for testing/debugging only).

Warning: Creates an array of full size; avoid for large tensors.

Return type:

Array

Returns:

Dense JAX array of shape tuple(idx.dim for idx in indices).

conj()[source]

Return conjugate tensor (conjugate all block arrays).

Return type:

SymmetricTensor

dagger()[source]

Conjugate transpose with fermionic twist phases.

For each block, applies complex conjugation, reverses all leg flows (via dual), and multiplies by the product of twist phases for all charges in the block key. For bosonic symmetries this is equivalent to conj() with dualled indices.

Return type:

SymmetricTensor

Returns:

New SymmetricTensor with conjugated data, dual indices, and twist phase corrections.

transpose(axes)[source]

Permute tensor legs.

For fermionic symmetries, each block acquires a Koszul sign determined by the charges’ parities and the permutation.

Parameters:

axes (KeyPath[int, ...]) – New ordering of leg indices.

Return type:

SymmetricTensor

Returns:

New SymmetricTensor with permuted blocks and reordered indices.

norm()[source]

Frobenius norm across all blocks.

Return type:

Array

block_shapes()[source]

Return the shape of each stored block.

Return type:

WSGIEnvironment[KeyPath[int, ...], KeyPath[int, ...]]

relabel(old, new)[source]

Return a copy with one leg label renamed.

Parameters:
  • old (Text | int) – Current label to replace.

  • new (Text | int) – New label value.

Return type:

SymmetricTensor

Returns:

New SymmetricTensor sharing the same block data.

Raises:

KeyError – If old is not found among the tensor’s labels.

relabels(mapping)[source]

Return a copy with multiple leg labels renamed at once.

Parameters:

mapping (WSGIEnvironment[Text | int, Text | int]) – {old_label: new_label} pairs. Labels not present in the mapping are left unchanged.

Return type:

SymmetricTensor

Returns:

New SymmetricTensor sharing the same block data.