Skip to content

qten.phys

Package reference for qten.phys.

phys

Physics-facing operator assembly built on symbolic basis states.

This package provides small data structures for describing quantum-mechanical terms before they are materialized as tensors. Its current focus is the free-fermionic workflow: collect weighted transitions between symbolic basis states, reduce those states to a minimal Hilbert space, and build the Hermitian matrix representation used by the tensor layer.

Two related APIs are exposed here:

  • Bond stores a weighted directed transition between two U1Basis states.
  • FFObservable accumulates bond terms and converts them into a rank-2 Tensor.
Repository usage

qten.phys sits between qten.symbolics and qten.linalg. Symbolic basis objects carry the state labels and amplitudes, while the observable builder decides which rays span the output HilbertSpace and allocates the corresponding tensor data.

Exported API

Bond dataclass

Bond(coef: Number, base: BaseType)

Bases: Multiple[Tuple[U1Basis, U1Basis]]

Weighted directed transition between two U1Basis states.

Bond specializes Multiple for the common physics case where the base object is an ordered pair (src, dst) of basis states. The scalar coefficient is kept separate from the endpoint states so symbolic manipulations can preserve the structural meaning of the bond until a later tensor-construction step.

In an FFObservable, the ordered pair is interpreted as a matrix element from src to dst. The observable is responsible for adding the Hermitian conjugate contribution when converting the collected bonds to a tensor.

In index notation this directed entry is \(O_{\mathrm{src},\mathrm{dst}}\).

Attributes:

Name Type Description
coef Number

Symbolic coefficient multiplying the bond contribution.

base Tuple[U1Basis, U1Basis]

Ordered pair (src, dst) describing the directed basis-state transition represented by the bond.

See Also

qten.phys.FFObservable Observable builder that consumes Bond instances.

coef instance-attribute

coef: Number

Numeric SymPy coefficient applied to base, kept separate so callers can accumulate scalar factors without eagerly rebuilding symbolic expressions.

base instance-attribute

base: BaseType

The symbolic or scalar object being multiplied by coef, preserved in structured form for later operator application or simplification.

FFObservable

FFObservable()

Free-fermionic observable assembled from symbolic Bond terms.

The observable stores a list of weighted basis-state transitions and can convert them into a Hermitian matrix representation on the minimal HilbertSpace spanned by the bond endpoints after ray reduction.

Each accumulated Bond contributes one directed matrix element. During tensor conversion, endpoint basis states are reduced to their rays, repeated rays are coalesced into a single Hilbert-space basis, and off-diagonal entries are mirrored by complex conjugation.

In matrix notation, inserting a bond from \(|i\rangle\) to \(|j\rangle\) with coefficient \(c\) writes \(O_{ij} = c\) and, for \(i \ne j\), the Hermitian completion \(O_{ji} = c^{*}\).

Notes

Bonds are retained internally in insertion order so the generated Hilbert space is deterministic for a fixed sequence of add_bond calls.

Initialize an empty observable with no bond contributions.

New terms can be added with add_bond().

Source code in src/qten/phys/_ff_observables.py
67
68
69
70
71
72
73
def __init__(self):
    """
    Initialize an empty observable with no bond contributions.

    New terms can be added with [`add_bond()`][qten.phys.FFObservable.add_bond].
    """
    self._bonds = []

add_bond

add_bond(bond: Bond)

Append a bond contribution to the observable.

Supported forms
  • add_bond(bond)
  • add_bond(coef, src, dst)

Parameters:

Name Type Description Default
bond Bond

Already-constructed bond term for the single-argument form.

required

Returns:

Type Description
None

The observable is updated in place.

Raises:

Type Description
TypeError

If bond is not an instance of Bond.

Source code in src/qten/phys/_ff_observables.py
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
@multimethod
def add_bond(self, bond: Bond):
    """
    Append a bond contribution to the observable.

    Supported forms
    ---------------
    - `add_bond(bond)`
    - `add_bond(coef, src, dst)`

    Parameters
    ----------
    bond : Bond
        Already-constructed bond term for the single-argument form.

    Returns
    -------
    None
        The observable is updated in place.

    Raises
    ------
    TypeError
        If `bond` is not an instance of `Bond`.
    """
    if not isinstance(bond, Bond):
        raise TypeError(f"Expected a Bond instance, got {type(bond).__name__}")
    self._bonds.append(bond)

to_tensor

to_tensor(*, device: Optional[Device] = None) -> Tensor

Convert the accumulated bonds into a Hermitian matrix Tensor.

Each bond contributes the matrix element induced by its coefficient and endpoint basis-state amplitudes. Basis states are first reduced to their ray representatives, and the output HilbertSpace is built from the resulting insertion-ordered unique rays. Off-diagonal entries are mirrored by complex conjugation so the returned tensor is Hermitian.

The resulting data satisfy \(O_{ij} = O_{ji}^{*}\).

Parameters:

Name Type Description Default
device Device | None

Logical device on which to allocate the output tensor data. If omitted, PyTorch uses its default device.

None

Returns:

Type Description
Tensor

Rank-2 tensor whose dimensions are the minimal Hilbert space spanned by the bond endpoint rays.

Source code in src/qten/phys/_ff_observables.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def to_tensor(self, *, device: Optional[Device] = None) -> Tensor:
    r"""
    Convert the accumulated bonds into a Hermitian matrix [`Tensor`][qten.linalg.tensors.Tensor].

    Each bond contributes the matrix element induced by its coefficient and
    endpoint basis-state amplitudes. Basis states are first reduced to their
    ray representatives, and the output [`HilbertSpace`][qten.symbolics.hilbert_space.HilbertSpace] is built from the
    resulting insertion-ordered unique rays. Off-diagonal entries are
    mirrored by complex conjugation so the returned tensor is Hermitian.

    The resulting data satisfy \(O_{ij} = O_{ji}^{*}\).

    Parameters
    ----------
    device : Device | None
        Logical device on which to allocate the output tensor data. If
        omitted, PyTorch uses its default device.

    Returns
    -------
    Tensor
        Rank-2 tensor whose dimensions are the minimal Hilbert space
        spanned by the bond endpoint rays.
    """
    basis_index: dict[U1Basis, int] = {}
    basis_order: list[U1Basis] = []
    bond_entries: list[tuple[int, int, complex]] = []

    for bond in self._bonds:
        left, right = bond.base
        left_ray = left.rays()
        right_ray = right.rays()

        i = basis_index.setdefault(left_ray, len(basis_order))
        if i == len(basis_order):
            basis_order.append(left_ray)

        j = basis_index.setdefault(right_ray, len(basis_order))
        if j == len(basis_order):
            basis_order.append(right_ray)

        value = complex(bond.coef * left.coef * sy.conjugate(right.coef))
        bond_entries.append((i, j, value))

    space = HilbertSpace.new(basis_order)
    precision = get_precision_config()
    torch_device = device.torch_device() if device is not None else None
    data = torch.zeros(
        (space.dim, space.dim), dtype=precision.torch_complex, device=torch_device
    )

    for i, j, value in bond_entries:
        if i == j:
            data[i, i] += value.real
        else:
            data[i, j] += value
            data[j, i] += value.conjugate()

    return Tensor(data=data, dims=(space, space))