Source code for openquantumsim.hilbert
"""Hilbert-space descriptors for OpenQuantumSim."""
from __future__ import annotations
from collections.abc import Iterator
from dataclasses import dataclass
from functools import reduce
from math import isclose
from operator import mul
[docs]
class HilbertSpace:
"""Base Hilbert-space descriptor."""
@property
def dim(self) -> int:
"""Return the finite Hilbert-space dimension."""
raise NotImplementedError
def __mul__(self, other: HilbertSpace) -> CompositeSpace:
"""Tensor-product composition using `space_a * space_b`."""
if isinstance(self, CompositeSpace):
left = self.spaces
else:
left = (self,)
if isinstance(other, CompositeSpace):
right = other.spaces
else:
right = (other,)
return CompositeSpace(left + right)
[docs]
@dataclass(frozen=True)
class FockSpace(HilbertSpace):
"""Truncated bosonic Fock space with states `|0>` through `|N-1>`."""
N: int = 2
label: str | None = None
def __post_init__(self) -> None:
if self.N <= 0:
msg = "FockSpace dimension N must be positive."
raise ValueError(msg)
@property
def dim(self) -> int:
"""Return the truncation dimension."""
return self.N
[docs]
@dataclass(frozen=True)
class SpinSpace(HilbertSpace):
"""Spin-S irreducible representation with dimension `2S + 1`."""
S: float = 0.5
label: str | None = None
def __post_init__(self) -> None:
dim = 2 * self.S + 1
if self.S < 0 or not isclose(dim, round(dim), rel_tol=0.0, abs_tol=1e-12):
msg = "SpinSpace requires S >= 0 and 2S + 1 to be an integer."
raise ValueError(msg)
@property
def dim(self) -> int:
"""Return `2S + 1`."""
return int(round(2 * self.S + 1))
[docs]
@dataclass(frozen=True)
class DickeSpace(HilbertSpace):
"""Permutation-symmetric Dicke manifold for ``n_spins`` two-level systems."""
n_spins: int
label: str | None = None
def __post_init__(self) -> None:
if self.n_spins < 0:
msg = "DickeSpace requires n_spins >= 0."
raise ValueError(msg)
@property
def dim(self) -> int:
"""Return the symmetric-manifold dimension ``n_spins + 1``."""
return self.n_spins + 1
@property
def total_spin(self) -> float:
"""Return the collective spin ``S = n_spins / 2``."""
return self.n_spins / 2
[docs]
@dataclass(frozen=True)
class CompositeSpace(HilbertSpace):
"""Tensor product of multiple Hilbert spaces."""
spaces: tuple[HilbertSpace, ...]
label: str | None = None
def __post_init__(self) -> None:
if len(self.spaces) == 0:
msg = "CompositeSpace requires at least one subsystem."
raise ValueError(msg)
@property
def dim(self) -> int:
"""Return the product dimension."""
return reduce(mul, (space.dim for space in self.spaces), 1)
def __iter__(self) -> Iterator[HilbertSpace]:
return iter(self.spaces)
def __len__(self) -> int:
return len(self.spaces)