qec 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,3 @@
1
1
  from .stabilizer_code import StabilizerCode
2
2
  from .css_code import CSSCode
3
3
  from .hgp_code import HypergraphProductCode
4
-
@@ -1,12 +1,13 @@
1
1
  import numpy as np
2
- import scipy
2
+ import scipy
3
3
  from typing import Union, Tuple
4
- import ldpc.mod2
4
+ import ldpc.mod2
5
5
  import time
6
6
 
7
7
  from qec.code_constructions import CSSCode
8
8
  from qec.utils.sparse_binary_utils import convert_to_binary_scipy_sparse
9
9
 
10
+
10
11
  class HypergraphProductCode(CSSCode):
11
12
  """
12
13
  Implements a Hypergraph Product (HGP) code - derived from two classical linear binary codes.
@@ -59,15 +60,19 @@ class HypergraphProductCode(CSSCode):
59
60
 
60
61
  def __init__(
61
62
  self,
62
- seed_matrix_1 : Union[np.ndarray, scipy.sparse.spmatrix],
63
- seed_matrix_2 : Union[np.ndarray, scipy.sparse.spmatrix],
64
- name : str = None
63
+ seed_matrix_1: Union[np.ndarray, scipy.sparse.spmatrix],
64
+ seed_matrix_2: Union[np.ndarray, scipy.sparse.spmatrix],
65
+ name: str = None,
65
66
  ):
66
-
67
67
  self.name = name if name else "Hypergraph product code"
68
68
 
69
- if not all(isinstance(seed_m, (np.ndarray, scipy.sparse.spmatrix)) for seed_m in (seed_matrix_1, seed_matrix_2)):
70
- raise TypeError("The seed matrices must be either numpy arrays or scipy sparse matrices.")
69
+ if not all(
70
+ isinstance(seed_m, (np.ndarray, scipy.sparse.spmatrix))
71
+ for seed_m in (seed_matrix_1, seed_matrix_2)
72
+ ):
73
+ raise TypeError(
74
+ "The seed matrices must be either numpy arrays or scipy sparse matrices."
75
+ )
71
76
 
72
77
  self.seed_matrix_1 = convert_to_binary_scipy_sparse(seed_matrix_1)
73
78
  self.seed_matrix_2 = convert_to_binary_scipy_sparse(seed_matrix_2)
@@ -90,31 +95,30 @@ class HypergraphProductCode(CSSCode):
90
95
  # --------------------------------------------------------------------------
91
96
 
92
97
  super().__init__(self.x_stabilizer_matrix, self.z_stabilizer_matrix, self.name)
93
-
94
98
 
95
99
  def compute_exact_code_distance(self) -> int:
96
100
  """
97
101
  Computes the exact code distance of the HGP code.
98
-
102
+
99
103
  Returns
100
104
  -------
101
- int
102
- The distance of the code.
105
+ int
106
+ The distance of the code.
103
107
 
104
108
  Notes
105
109
  -----
106
- The distance of a HGP code is given as:
107
-
110
+ The distance of a HGP code is given as:
111
+
108
112
  .. math::
109
113
 
110
114
  \min(d_1, d_2, d_1^T, d_2^T)
111
115
 
112
116
  corresponding to the distance of the seed codes and the distance of their transposes.
113
117
  """
114
-
118
+
115
119
  rank_seed_m1 = ldpc.mod2.rank(self.seed_matrix_1)
116
120
  rank_seed_m2 = ldpc.mod2.rank(self.seed_matrix_2)
117
-
121
+
118
122
  if self.seed_matrix_1.shape[1] != rank_seed_m1:
119
123
  self.d1 = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_1)
120
124
  else:
@@ -124,7 +128,7 @@ class HypergraphProductCode(CSSCode):
124
128
  self.d2 = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_2)
125
129
  else:
126
130
  self.d2 = np.inf
127
-
131
+
128
132
  # note: rank(A) = rank(A^T):
129
133
  if self.seed_matrix_1.shape[0] != rank_seed_m1:
130
134
  self.d1T = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_1.T)
@@ -141,70 +145,86 @@ class HypergraphProductCode(CSSCode):
141
145
  self.code_distance = min(self.x_code_distance, self.z_code_distance)
142
146
 
143
147
  return self.code_distance
144
-
145
148
 
146
149
  def estimate_min_distance(self, timeout_seconds: float = 0.025) -> int:
147
150
  """
148
151
  Estimate the minimum X and Z distance of the HGP code. Parameters
149
152
  ----------
150
- timeout_seconds : float, optional
151
- Time limit in seconds for the full search. Default: 0.25
152
-
153
+ timeout_seconds : float, optional
154
+ Time limit in seconds for the full search. Default: 0.25
155
+
153
156
  Returns
154
157
  -------
155
158
  int
156
- Best estimate of the (overall) code distance found within time limit.
159
+ Best estimate of the (overall) code distance found within time limit.
157
160
 
158
161
  """
159
-
162
+
160
163
  rank_seed_m1 = ldpc.mod2.rank(self.seed_matrix_1)
161
164
  rank_seed_m2 = ldpc.mod2.rank(self.seed_matrix_2)
162
165
 
163
-
164
- d1_timeout_seconds = timeout_seconds/4
165
- if self.seed_matrix_1.shape[1] != rank_seed_m1:
166
+ d1_timeout_seconds = timeout_seconds / 4
167
+ if self.seed_matrix_1.shape[1] != rank_seed_m1:
166
168
  d1_start_time = time.time()
167
- d1_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_1, d1_timeout_seconds, 0)
169
+ d1_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(
170
+ self.seed_matrix_1, d1_timeout_seconds, 0
171
+ )
168
172
  d1_run_time = time.time() - d1_start_time
169
173
  else:
170
174
  d1_min_estimate = np.inf
171
175
  d1_run_time = 0
172
176
 
173
- d1T_timeout_seconds = (d1_timeout_seconds * 4 - d1_run_time)/3 if d1_run_time <= d1_timeout_seconds else timeout_seconds/4
177
+ d1T_timeout_seconds = (
178
+ (d1_timeout_seconds * 4 - d1_run_time) / 3
179
+ if d1_run_time <= d1_timeout_seconds
180
+ else timeout_seconds / 4
181
+ )
174
182
  if self.seed_matrix_1.shape[0] != rank_seed_m1:
175
183
  d1T_start_time = time.time()
176
- d1T_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_1.T, d1T_timeout_seconds, 0)
184
+ d1T_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(
185
+ self.seed_matrix_1.T, d1T_timeout_seconds, 0
186
+ )
177
187
  d1T_run_time = time.time() - d1T_start_time
178
188
  else:
179
189
  d1T_min_estimate = np.inf
180
190
  d1T_run_time = 0
181
191
 
182
- d2_timeout_seconds = (d1T_timeout_seconds * 3 - d1T_run_time)/2 if d1T_run_time <= d1T_timeout_seconds else timeout_seconds/4
192
+ d2_timeout_seconds = (
193
+ (d1T_timeout_seconds * 3 - d1T_run_time) / 2
194
+ if d1T_run_time <= d1T_timeout_seconds
195
+ else timeout_seconds / 4
196
+ )
183
197
  if self.seed_matrix_2.shape[1] != rank_seed_m2:
184
198
  d2_start_time = time.time()
185
- d2_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_2, d2_timeout_seconds, 0)
199
+ d2_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(
200
+ self.seed_matrix_2, d2_timeout_seconds, 0
201
+ )
186
202
  d2_run_time = time.time() - d2_start_time
187
203
  else:
188
204
  d2_min_estimate = np.inf
189
205
  d2_run_time = 0
190
206
 
191
-
192
- d2T_timeout_seconds = (d2_timeout_seconds * 2 - d2_run_time) if d2_run_time <= d2_timeout_seconds else timeout_seconds/4
207
+ d2T_timeout_seconds = (
208
+ (d2_timeout_seconds * 2 - d2_run_time)
209
+ if d2_run_time <= d2_timeout_seconds
210
+ else timeout_seconds / 4
211
+ )
193
212
  if self.seed_matrix_2.shape[0] != rank_seed_m2:
194
- d2T_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_2.T, d2T_timeout_seconds, 0)
213
+ d2T_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(
214
+ self.seed_matrix_2.T, d2T_timeout_seconds, 0
215
+ )
195
216
  else:
196
217
  d2T_min_estimate = np.inf
197
-
218
+
198
219
  self.x_code_distance = min(d1T_min_estimate, d2_min_estimate)
199
220
  self.z_code_distance = min(d1_min_estimate, d2T_min_estimate)
200
221
  self.code_distance = min(self.x_code_distance, self.z_code_distance)
201
222
 
202
-
203
223
  return self.code_distance
204
224
 
205
-
206
-
207
- def compute_logical_basis(self) -> Tuple[scipy.sparse.spmatrix, scipy.sparse.spmatrix]:
225
+ def compute_logical_basis(
226
+ self,
227
+ ) -> Tuple[scipy.sparse.spmatrix, scipy.sparse.spmatrix]:
208
228
  """
209
229
  Compute the logical operator basis for the given HGP code.
210
230
 
@@ -225,40 +245,64 @@ class HypergraphProductCode(CSSCode):
225
245
  row_comp_h2T = ldpc.mod2.row_complement_basis(self.seed_matrix_2.T)
226
246
 
227
247
  temp = scipy.sparse.kron(ker_h1, row_comp_h2)
228
- lz1 = scipy.sparse.hstack([temp, scipy.sparse.csr_matrix((temp.shape[0], self._m1*self._m2), dtype=np.uint8)])
248
+ lz1 = scipy.sparse.hstack(
249
+ [
250
+ temp,
251
+ scipy.sparse.csr_matrix(
252
+ (temp.shape[0], self._m1 * self._m2), dtype=np.uint8
253
+ ),
254
+ ]
255
+ )
229
256
 
230
257
  temp = scipy.sparse.kron(row_comp_h1T, ker_h2T)
231
- lz2 = scipy.sparse.hstack([scipy.sparse.csr_matrix((temp.shape[0], self._n1*self._n2), dtype=np.uint8), temp])
258
+ lz2 = scipy.sparse.hstack(
259
+ [
260
+ scipy.sparse.csr_matrix(
261
+ (temp.shape[0], self._n1 * self._n2), dtype=np.uint8
262
+ ),
263
+ temp,
264
+ ]
265
+ )
232
266
 
233
267
  self.z_logical_operator_basis = scipy.sparse.vstack([lz1, lz2], dtype=np.uint8)
234
268
 
235
-
236
269
  temp = scipy.sparse.kron(row_comp_h1, ker_h2)
237
- lx1 = scipy.sparse.hstack([temp, scipy.sparse.csr_matrix((temp.shape[0], self._m1*self._m2), dtype=np.uint8)])
270
+ lx1 = scipy.sparse.hstack(
271
+ [
272
+ temp,
273
+ scipy.sparse.csr_matrix(
274
+ (temp.shape[0], self._m1 * self._m2), dtype=np.uint8
275
+ ),
276
+ ]
277
+ )
238
278
 
239
279
  temp = scipy.sparse.kron(ker_h1T, row_comp_h2T)
240
- lx2 = scipy.sparse.hstack([scipy.sparse.csr_matrix((temp.shape[0], self._n1*self._n2), dtype=np.uint8), temp])
241
-
242
- self.x_logical_operator_basis= scipy.sparse.vstack([lx1, lx2], dtype = np.uint8)
243
-
244
- # Follows the way it is done in CSSCode -> move it into __init__?
245
- #----------------------------------------------------------------
280
+ lx2 = scipy.sparse.hstack(
281
+ [
282
+ scipy.sparse.csr_matrix(
283
+ (temp.shape[0], self._n1 * self._n2), dtype=np.uint8
284
+ ),
285
+ temp,
286
+ ]
287
+ )
288
+
289
+ self.x_logical_operator_basis = scipy.sparse.vstack([lx1, lx2], dtype=np.uint8)
290
+
291
+ # Follows the way it is done in CSSCode -> move it into __init__?
292
+ # ----------------------------------------------------------------
246
293
  self.logical_qubit_count = self.x_logical_operator_basis.shape[0]
247
- #----------------------------------------------------------------
294
+ # ----------------------------------------------------------------
248
295
 
249
296
  return (self.x_logical_operator_basis, self.z_logical_operator_basis)
250
297
 
251
-
252
298
  def __str__(self):
253
299
  """
254
300
  String representation of the HGP code. Includes the name and [[n, k, d]] properties of the code.
255
301
 
256
302
  Returns
257
303
  -------
258
- str
259
- String representation of the HGP code.
304
+ str
305
+ String representation of the HGP code.
260
306
  """
261
-
262
- return f"{self.name} Hypergraphproduct Code: [[N={self.physical_qubit_count}, K={self.logical_qubit_count}, dx={self.x_code_distance}, dz={self.z_code_distance}]]"
263
-
264
307
 
308
+ return f"{self.name} Hypergraphproduct Code: [[N={self.physical_qubit_count}, K={self.logical_qubit_count}, dx={self.x_code_distance}, dz={self.z_code_distance}]]"
@@ -1,9 +1,8 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: qec
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Python Tools for Quantum Error Correction
5
- Author: Tamas Noszko, Liam Veeder-Sweeney
6
- Author-email: Joschka Roffe <joschka@roffe.eu>
5
+ Author-email: Joschka Roffe <joschka@roffe.eu>, Tamas Noszko <T.K.Noszko@sms.ed.ac.uk>, Liam Veeder-Sweeney <L.D.Veeder-Sweeney@sms.ed.ac.uk>
7
6
  License: MIT License
8
7
 
9
8
  Copyright (c) 2023 qec.Codes
@@ -1,7 +1,7 @@
1
1
  qec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- qec/code_constructions/__init__.py,sha256=MWyNUCS5mYcDzjGr_nbr2-ifkJigRJIzsw7sQIQXDfM,119
2
+ qec/code_constructions/__init__.py,sha256=AyEYcahGs_4C8nqSUhoYmZNBt1TzuzVPZjNN1FErRyQ,118
3
3
  qec/code_constructions/css_code.py,sha256=nIaC24QhQwrmWQNhmX-X4TzlkmNAYoxN0feTdWjhswo,32376
4
- qec/code_constructions/hgp_code.py,sha256=VAKU2lfZnDXSmAk6xFZCYT5b0hbtXpEoQUw4qHFcaEk,10419
4
+ qec/code_constructions/hgp_code.py,sha256=r5E_tEilRRJWDXrMbNAbplf-N5Y0XS7VUoWWTEjh9BY,11098
5
5
  qec/code_constructions/stabilizer_code.py,sha256=I5u8JKZu88ioC4E2nBJ-00xCmnL8nU6kdAvwYOfmNRk,22138
6
6
  qec/code_instances/__init__.py,sha256=z6jOPjekDIx0jgbRFThI95zUzLzjl9Dh89RBzxsT_BE,43
7
7
  qec/code_instances/five_qubit_code.py,sha256=ZHyusTEnnnmUv4QxPLXQSKbEQv2QOoBqn2V9N4SgrQE,2177
@@ -11,8 +11,8 @@ qec/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  qec/utils/binary_pauli_utils.py,sha256=BSlngYDdRICu0aVu4u_m0bvLicohORyGxfk5eRER7TQ,13245
12
12
  qec/utils/codetables_de_utils.py,sha256=S1wcVGJkkASQQ5s71QAsYBmpyE-3xTb6UsvgMfQtuiw,9469
13
13
  qec/utils/sparse_binary_utils.py,sha256=Y9xfGKzOGFiVTyhb6iF6N7-5oMY6Ah9oLrnv8HhSBHA,1965
14
- qec-0.2.5.dist-info/LICENSE,sha256=1b_xwNz1znYBfEaCL6pN2gNBAn8pQIjDRs_UhDp1EJI,1066
15
- qec-0.2.5.dist-info/METADATA,sha256=xK6P1cPR5OyCWe7rsFb1OO3BYL_k9kmHwW-75uAEIu8,4558
16
- qec-0.2.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
17
- qec-0.2.5.dist-info/top_level.txt,sha256=d8l_7pJ5u9uWdviNp0FUK-j8VPZqywkDek7qa4NDank,4
18
- qec-0.2.5.dist-info/RECORD,,
14
+ qec-0.2.7.dist-info/LICENSE,sha256=1b_xwNz1znYBfEaCL6pN2gNBAn8pQIjDRs_UhDp1EJI,1066
15
+ qec-0.2.7.dist-info/METADATA,sha256=KJk3mjCfJkluDMXt7-jh3lhPMpd_bvX3e3KPmKurRbo,4611
16
+ qec-0.2.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
17
+ qec-0.2.7.dist-info/top_level.txt,sha256=d8l_7pJ5u9uWdviNp0FUK-j8VPZqywkDek7qa4NDank,4
18
+ qec-0.2.7.dist-info/RECORD,,
File without changes
File without changes