Source code for qugrad._hilbert_space
1"""
2Defines a class representing a Hilbert space.
3"""
4
5import numpy as np
6from typing import Optional, Any, Union
7
[docs]
8class HilbertSpace():
9 """
10 Represents a Hilbert space with a prefered basis indexed by non-negative
11 integers.
12
13 Note
14 ----
15 The class also can be treated as an iterator and will return :attr:`basis`
16 as the iterator.
17
18
19 ---
20 """
21
22 _basis: np.ndarray[int]
23 "An array of positive integers labeling the Hilbert space basis"
24 _inverse: np.ndarray[int]
25 "An array satisfying the property ``_inverse[basis[i]]=i``"
26
[docs]
27 def __init__(self, basis: np.ndarray[int]):
28 """
29 Initialises a new :class:`HilbertSpace`.
30
31 Parameters
32 ----------
33 basis : NDArray[Shape[:attr:`dim`], int]
34 The labels for the basis vectors.
35 """
36 self._basis = np.array(basis)
37 self._basis.flags.writeable = False
38 if len(self._basis) == 0:
39 self._inverse = np.empty(0, dtype=np.int64)
40 else:
41 self._inverse = np.zeros(self._basis.max()+1, dtype=np.int64)
42 for i, x in enumerate(self._basis):
43 self._inverse[x] = i
44 self._inverse.flags.writeable = False
45 def __iter__(self): return iter(self._basis)
46 def __getitem__(self, key): return self._basis[key]
47 def __len__(self): return len(self._basis)
48 def __eq__(self, other: "HilbertSpace") -> bool:
49 if isinstance(other, self.__class__):
50 return np.array_equal(self._basis, other._basis)
51 return False
52 @property
53 def dim(self):
54 """
55 The Hilbert space dimension
56 """
57 return len(self)
58 @property
59 def basis(self) -> np.ndarray[int]:
60 """
61 An array of positive integers labeling the Hilbert space basis
62 """
63 return self._basis
64 @property
65 def inverse(self) -> np.ndarray[int]:
66 "An array satisfying the property ``self.inverse[self.basis[i]]=i``"
67 return self._inverse
[docs]
68 def basis_vector(self, basis_state_label: int) -> np.ndarray[np.complex128]:
69 """Returns a column vector represnetation corresponding to the input
70 basis state label.
71
72 Parameters
73 ----------
74 basis_state_label : int
75 A positive integer denoting the label of the basis state to generate
76 the basis vector for.
77
78 Returns
79 -------
80 NDArray[Shape[:attr:`dim`], np.complex128]
81 The basis vector corresponding to the input basis state label.
82 """
83 return np.eye(1,
84 len(self._basis),
85 self._inverse[basis_state_label]
86 ).flatten().astype(np.complex128)
[docs]
87 def get_subspace(self, filter: np.ndarray[bool]) -> "HilbertSpace":
88 """Generates a new subspace by filtering the basis state labels.
89
90 Parameters
91 ----------
92 filter : NDArray[Shape[:attr:`dim`], bool]
93 ``True`` entries are retained in the new subspace.
94
95 Returns
96 -------
97 HilbertSpace
98 The filtered subspace.
99 """
100 return HilbertSpace(self._basis[filter])
101 @staticmethod
102 def _labels(state: Any) -> str:
103 """
104 Generates a strings that represent the state.
105
106 Parameters
107 ----------
108 state : Any
109 The state to label.
110
111 Returns
112 -------
113 str
114 The label for the specified state.
115 """
116 return f"|{repr(state)}⟩"
[docs]
117 def labels(self,
118 states: Optional[Union[int, list[int]]] = None
119 ) -> Union[str, list[str]]:
120 """
121 Generates a string (list of strings) that represent the state(s).
122
123 Parameters
124 ----------
125 states : int | list[int], optional
126 The state(s) to label. If ``None`` then the labels for all states in
127 :attr:`basis` are returned. By default ``None``.
128
129 Returns
130 -------
131 str | list[str]
132 The label(s) for the specified states.
133 """
134 if isinstance(states, int):
135 return self._labels(states)
136 elif states is None: states = self.basis
137 return [self._labels(int(s)) for s in states]