Source code for qugradlab.hilbert_spaces.bosonic._bosonic_hilbert_spaces
1from typing import Optional, Iterable, Union
2
3import numpy as np
4
5from qugrad import HilbertSpace
6
7from .. import QuditSpace
8from .._get_digit import get_digit
9
[docs]
10class BosonSpace(HilbertSpace):
11 """
12 Represents a truncated Fock space of boson modes.
13 """
14
15 _n_single_particle_states: int
16 "The number of single particle states"
17
18
19 _truncation_level: int
20 "The maximum number of bosons per single particle state"
21
[docs]
22 def __init__(self, n_single_particle_states: int, truncation_level: int):
23 """
24 Initialises a :class:`BosonSpace`
25
26 Parameters
27 ----------
28 n_single_particle_states: int
29 The number of single particle states
30 truncation_level: int
31 The maximum number of bosons per single particle state
32 """
33 self._n_single_particle_states = n_single_particle_states
34 self._truncation_level = truncation_level
35 super().__init__(np.arange(truncation_level**n_single_particle_states))
36 @property
37 def n_single_particle_states(self) -> int:
38 "The number of single particle states"
39 return self._n_single_particle_states
40 @property
41 def truncation_level(self) -> int:
42 "The maximum number of bosons per single particle state"
43 return self._truncation_level
44 @staticmethod
45 def _labels(digits: Iterable[str]) -> str:
46 """
47 Generates a strings that represent the state specified by the `digits`.
48
49 Parameters
50 ----------
51 digits : Iterable[str]
52 The digits representing the state
53
54 Returns
55 -------
56 str
57 The label for the specified state.
58 """
59
60 return f"|{', '.join(digits)}⟩"
[docs]
61 def labels(self,
62 states: Optional[Union[int, list[int]]] = None
63 ) -> Union[str, list[str]]:
64 """
65 Generates a string (list of strings) that represent the state(s).
66
67 Parameters
68 ----------
69 states : int | list[int], optional
70 The state(s) to label. If ``None`` then the labels for all states in
71 :attr:`basis` are returned. By default ``None``.
72
73 Returns
74 -------
75 str | list[str]
76 The label(s) for the specified states.
77 """
78 if states is None: states = self.basis
79 digits = get_digit(states,
80 self._truncation_level,
81 np.arange(self._n_single_particle_states)
82 ).astype(str)
83 if isinstance(states, int):
84 return self._labels(digits)
85 return [self._labels(d) for d in digits]
86
[docs]
87class BosonQuditSpace(BosonSpace, QuditSpace):
88 """
89 A :class:`BosonSpace` with a computational structure. The computational
90 subspace consists of the states which have unoccupied and singly occupied
91 single particle states.
92 """
[docs]
93 def computational_projector(self)-> np.ndarray[bool]:
94 """
95 Generates a boolean filter for the computation basis states in
96 :attr:`basis`. The computational subspace consists of the states which
97 have unoccupied and singly occupied single particle states.
98
99 Returns
100 -------
101 NDArray[Shape[:attr:`dim`], bool]
102 A boolean filter for the computation basis states in :attr:`basis`.
103 """
104 projector = get_digit(self.basis,
105 self._truncation_level,
106 np.arange(self._n_single_particle_states)) <= 1
107 return np.all(projector, axis=-1)