Source code for qugradlab.hilbert_spaces._qudit_hilbert_spaces

  1from typing import Optional, Iterable, Union
  2from abc import ABC, abstractmethod
  3from ._get_digit import get_digit
  4
  5import numpy as np
  6
  7from qugrad import HilbertSpace
  8
  9
[docs] 10class QuditSpace(HilbertSpace, ABC): 11 """ 12 An abstract class defining the Hilbert space for a collection of qudits. 13 """
[docs] 14 @abstractmethod 15 def computational_projector(self) -> np.ndarray[bool]: 16 """ 17 Important 18 --------- 19 This is an abstract method. 20 21 22 Generates a boolean filter for the computation basis states in 23 :attr:`basis`. 24 25 Returns 26 ------- 27 NDArray[Shape[:attr:`dim`], bool] 28 A boolean filter for the computation basis states in 29 :attr:`basis`. 30 """ 31 ...
[docs] 32 def computational_subspace(self) -> HilbertSpace: 33 """ 34 Initialises a :class:`qugrad.HilbertSpace` corresponding the computation 35 subspace. 36 37 Returns 38 ------- 39 qugrad.HilbertSpace 40 The computational subspace 41 """ 42 return self.get_subspace(self.computational_projector())
[docs] 43 def dialate_operator(self, operator: np.ndarray) -> np.ndarray: 44 r""" 45 Dialates an operator $\hat O$ that acts on the computational subspace to 46 an operator $\hat O\oplus 0$ that acts on the whole Hilbert space. 47 48 Parameters 49 ---------- 50 operator : NDArray[Shape[``computational_subspace().dim``, ``computational_subspace().dim``] complex] 51 The operator that acts on the computational subspace 52 53 Returns 54 ------- 55 NDArray[Shape[:attr:`dim`, :attr:`dim`] complex] 56 The dialated operator that acts on the whole Hilbert space 57 """ 58 proj = np.identity(self.dim)[self.computational_projector()] 59 return proj.T@operator@proj
[docs] 60 def project_operator(self, operator: np.ndarray) -> np.ndarray: 61 """ 62 Projects an operator that acts on the Hilbert space to an 63 operator that acts only on the computational subspace. 64 65 Parameters 66 ---------- 67 operator : NDArray[Shape[:attr:`dim`, :attr:`dim`] complex] 68 The operator that acts on the whole Hilbert space 69 70 Returns 71 ------- 72 NDArray[Shape[``computational_subspace().dim``, ``computational_subspace().dim``] complex] 73 The projected operator that acts on the computational subspace. 74 """ 75 proj = self.computational_projector() 76 return operator[proj][:, proj]
77
[docs] 78class QubitSpace(QuditSpace): 79 """ 80 A computational Hilbert space. 81 """ 82 83 _qubits: int 84 "The number of qubits" 85
[docs] 86 def __init__(self, qubits: int): 87 """ 88 Initialises a :class:`QubitSpace` 89 90 Parameters 91 ---------- 92 qubits : int 93 The number of qubits 94 """ 95 self._qubits = qubits 96 super().__init__(np.arange(2**qubits))
97 @property 98 def qubits(self) -> int: 99 "The number of qubits" 100 return self._qubits
[docs] 101 def computational_projector(self): 102 """ 103 Generates a boolean filter for the computation basis states in 104 :attr:`basis`. 105 106 Returns 107 ------- 108 NDArray[Shape[:attr:`dim`], bool] 109 A boolean filter for the computation basis states in 110 :attr:`basis`. 111 """ 112 return np.ones(len(self), dtype=bool)
113 @staticmethod 114 def _labels(digits: Iterable[str]) -> str: 115 """ 116 Generates a strings that represent the state specified by the `digits`. 117 118 Parameters 119 ---------- 120 digits : Iterable[str] 121 The digits representing the state 122 123 Returns 124 ------- 125 str 126 The label for the specified state. 127 """ 128 return f"|{''.join(digits)}⟩"
[docs] 129 def labels(self, 130 states: Optional[Union[int, list[int]]] = None 131 ) -> Union[str, list[str]]: 132 """ 133 Generates a string (list of strings) that represent the state(s). 134 135 Parameters 136 ---------- 137 states : int | list[int], optional 138 The state(s) to label. If ``None`` then the labels for all states in 139 :attr:`basis` are returned. By default ``None``. 140 141 Returns 142 ------- 143 str | list[str] 144 The label(s) for the specified states. 145 """ 146 if states is None: states = self.basis 147 digits = get_digit(states, 148 2, 149 np.arange(self._qubits) 150 ).astype(str) 151 if isinstance(states, int): 152 return self._labels(digits) 153 return [self._labels(d) for d in digits]