qec 0.2.7__py3-none-any.whl → 0.2.9__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.
- qec/code_instances/saved_codes/steane.json +34 -0
- qec/code_instances/saved_codes/test.json +1 -0
- {qec-0.2.7.dist-info → qec-0.2.9.dist-info}/METADATA +1 -1
- qec-0.2.9.dist-info/RECORD +8 -0
- qec/code_constructions/__init__.py +0 -3
- qec/code_constructions/css_code.py +0 -773
- qec/code_constructions/hgp_code.py +0 -308
- qec/code_constructions/stabilizer_code.py +0 -591
- qec/code_instances/__init__.py +0 -1
- qec/code_instances/five_qubit_code.py +0 -67
- qec/codetables_de/__init__.py +0 -1
- qec/codetables_de/codetables_de.py +0 -93
- qec/utils/__init__.py +0 -0
- qec/utils/binary_pauli_utils.py +0 -403
- qec/utils/codetables_de_utils.py +0 -274
- qec/utils/sparse_binary_utils.py +0 -64
- qec-0.2.7.dist-info/RECORD +0 -18
- {qec-0.2.7.dist-info → qec-0.2.9.dist-info}/LICENSE +0 -0
- {qec-0.2.7.dist-info → qec-0.2.9.dist-info}/WHEEL +0 -0
- {qec-0.2.7.dist-info → qec-0.2.9.dist-info}/top_level.txt +0 -0
qec/utils/codetables_de_utils.py
DELETED
@@ -1,274 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
|
3
|
-
# Suppress debug and info messages from urllib3 and requests libraries
|
4
|
-
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
5
|
-
logging.getLogger("requests").setLevel(logging.WARNING)
|
6
|
-
|
7
|
-
from scipy.sparse import csr_matrix
|
8
|
-
|
9
|
-
import requests
|
10
|
-
from bs4 import BeautifulSoup
|
11
|
-
import json
|
12
|
-
|
13
|
-
|
14
|
-
def get_codetables_de_matrix(q, n, k, output_json_path=None, write_to_file=False):
|
15
|
-
"""
|
16
|
-
Retrieve quantum code data from Markus Grassl's codetables.de website.
|
17
|
-
|
18
|
-
This function queries the URL:
|
19
|
-
``https://codetables.de/QECC/QECC.php?q={q}&n={n}&k={k}``,
|
20
|
-
attempting to fetch data for a quantum code with the specified parameters
|
21
|
-
over GF(q). The HTML response is parsed to extract:
|
22
|
-
|
23
|
-
- The lower bound (``d_lower``) and upper bound (``d_upper``) on the code distance.
|
24
|
-
- The stabilizer matrix (as lines within a ``<pre>`` block).
|
25
|
-
|
26
|
-
The stabilizer matrix is then converted into a list of rows, each containing
|
27
|
-
the column indices of any '1' entries (the ``pcm``). The result is returned
|
28
|
-
as a dictionary, and optionally written to a JSON file.
|
29
|
-
|
30
|
-
Parameters
|
31
|
-
----------
|
32
|
-
q : int
|
33
|
-
The field size (e.g. 2, 4, etc.).
|
34
|
-
n : int
|
35
|
-
The length of the code (number of physical qubits).
|
36
|
-
k : int
|
37
|
-
The dimension of the code (number of logical qubits).
|
38
|
-
output_json_path : str or None, optional
|
39
|
-
File path to which the resulting dictionary will be written if
|
40
|
-
``write_to_file`` is set to True. If None and ``write_to_file`` is True,
|
41
|
-
raises a ValueError.
|
42
|
-
write_to_file : bool, optional
|
43
|
-
Whether to write the resulting dictionary to a JSON file.
|
44
|
-
|
45
|
-
Returns
|
46
|
-
-------
|
47
|
-
dict
|
48
|
-
A dictionary with the fields:
|
49
|
-
``{"n", "k", "d_upper", "d_lower", "url", "pcm"}``.
|
50
|
-
|
51
|
-
- ``pcm`` is a list of lists, where each inner list contains the column
|
52
|
-
indices of '1's for that row of the stabilizer matrix.
|
53
|
-
- ``url`` is the codetables.de URL used for the query.
|
54
|
-
- ``d_upper`` and ``d_lower`` are the distance bounds, if found.
|
55
|
-
|
56
|
-
Raises
|
57
|
-
------
|
58
|
-
ValueError
|
59
|
-
If the server response is not 200 OK, or if no valid stabilizer matrix
|
60
|
-
lines could be found in the HTML (i.e., no code data for those parameters).
|
61
|
-
Also raised if ``write_to_file`` is True and ``output_json_path`` is None.
|
62
|
-
|
63
|
-
Notes
|
64
|
-
-----
|
65
|
-
- Data is sourced from `codetables.de <https://codetables.de>`__,
|
66
|
-
maintained by Markus Grassl.
|
67
|
-
- The function does not return an actual matrix but rather a convenient
|
68
|
-
representation of it (the ``pcm``). Use ``pcm_to_csr_matrix`` or another
|
69
|
-
helper to convert it into a numerical/sparse form.
|
70
|
-
"""
|
71
|
-
url = f"https://codetables.de/QECC/QECC.php?q={q}&n={n}&k={k}"
|
72
|
-
resp = requests.get(url)
|
73
|
-
if resp.status_code != 200:
|
74
|
-
raise ValueError(
|
75
|
-
f"Failed to retrieve data (status code: {resp.status_code}). URL was: {url}"
|
76
|
-
)
|
77
|
-
|
78
|
-
soup = BeautifulSoup(resp.text, "html.parser")
|
79
|
-
|
80
|
-
# 1) Extract lower and upper distance bounds from <table> elements
|
81
|
-
lower_bound = None
|
82
|
-
upper_bound = None
|
83
|
-
tables = soup.find_all("table")
|
84
|
-
for table in tables:
|
85
|
-
rows = table.find_all("tr")
|
86
|
-
for row in rows:
|
87
|
-
cells = row.find_all("td")
|
88
|
-
if len(cells) == 2:
|
89
|
-
heading = cells[0].get_text(strip=True).lower()
|
90
|
-
value = cells[1].get_text(strip=True)
|
91
|
-
if "lower bound" in heading:
|
92
|
-
lower_bound = value
|
93
|
-
elif "upper bound" in heading:
|
94
|
-
upper_bound = value
|
95
|
-
|
96
|
-
# 2) Extract the stabilizer matrix lines from <pre> tags
|
97
|
-
matrix_lines = []
|
98
|
-
for tag in soup.find_all("pre"):
|
99
|
-
text = tag.get_text()
|
100
|
-
if "stabilizer matrix" in text.lower():
|
101
|
-
lines = text.splitlines()
|
102
|
-
capture = False
|
103
|
-
for line in lines:
|
104
|
-
if "stabilizer matrix" in line.lower():
|
105
|
-
capture = True
|
106
|
-
continue
|
107
|
-
if capture:
|
108
|
-
# Stop at 'last modified:' or if the line is empty
|
109
|
-
if "last modified:" in line.lower():
|
110
|
-
break
|
111
|
-
if line.strip() != "":
|
112
|
-
matrix_lines.append(line.strip())
|
113
|
-
|
114
|
-
if not matrix_lines:
|
115
|
-
raise ValueError(f"No valid stabilizer matrix found at {url}")
|
116
|
-
|
117
|
-
# 3) Convert lines -> list of column-index lists
|
118
|
-
pcm_list = []
|
119
|
-
for line in matrix_lines:
|
120
|
-
line = line.strip().strip("[]").replace("|", " ")
|
121
|
-
elements = line.split()
|
122
|
-
row_cols = [i for i, val in enumerate(elements) if val == "1"]
|
123
|
-
pcm_list.append(row_cols)
|
124
|
-
|
125
|
-
if not pcm_list:
|
126
|
-
raise ValueError(f"No valid rows containing '1' found at {url}")
|
127
|
-
|
128
|
-
# 4) Build final dictionary
|
129
|
-
result_dict = {
|
130
|
-
"n": n,
|
131
|
-
"k": k,
|
132
|
-
"d_upper": upper_bound,
|
133
|
-
"d_lower": lower_bound,
|
134
|
-
"url": url,
|
135
|
-
"pcm": pcm_list,
|
136
|
-
}
|
137
|
-
|
138
|
-
# 5) Optionally write to JSON file
|
139
|
-
if write_to_file:
|
140
|
-
if output_json_path is None:
|
141
|
-
raise ValueError("output_json_path must be provided if write_to_file=True.")
|
142
|
-
with open(output_json_path, "w") as out_file:
|
143
|
-
json.dump(result_dict, out_file, indent=2)
|
144
|
-
|
145
|
-
return result_dict
|
146
|
-
|
147
|
-
|
148
|
-
def pcm_to_csr_matrix(pcm, num_cols=None):
|
149
|
-
"""
|
150
|
-
Convert a "pcm" to a SciPy CSR matrix.
|
151
|
-
|
152
|
-
Each inner list of ``pcm`` is interpreted as the column indices in which
|
153
|
-
row `i` has a value of 1. The resulting CSR matrix will thus have as many
|
154
|
-
rows as ``len(pcm)``. The number of columns can either be:
|
155
|
-
|
156
|
-
- Inferred automatically (``num_cols=None``) by taking 1 + max(column index).
|
157
|
-
- Specified by the user. If a column index is >= num_cols, a ValueError is raised.
|
158
|
-
|
159
|
-
Parameters
|
160
|
-
----------
|
161
|
-
pcm : list of lists of int
|
162
|
-
Each element ``pcm[i]`` is a list of column indices where row i has '1'.
|
163
|
-
num_cols : int or None, optional
|
164
|
-
The desired number of columns (width of the matrix).
|
165
|
-
If None, the width is auto-detected from the maximum column index.
|
166
|
-
|
167
|
-
Returns
|
168
|
-
-------
|
169
|
-
csr_matrix
|
170
|
-
A sparse matrix of shape ``(len(pcm), num_cols)``.
|
171
|
-
|
172
|
-
Raises
|
173
|
-
------
|
174
|
-
ValueError
|
175
|
-
If any column index exceeds the specified ``num_cols``.
|
176
|
-
Also raised if no rows or invalid columns exist.
|
177
|
-
|
178
|
-
See Also
|
179
|
-
--------
|
180
|
-
get_codetables_de_matrix : Returns a dictionary with ``pcm`` field from codetables.de.
|
181
|
-
|
182
|
-
Notes
|
183
|
-
-----
|
184
|
-
Data is typically retrieved from `codetables.de <https://codetables.de>`__
|
185
|
-
and fed into this function to produce a numerical/sparse representation.
|
186
|
-
"""
|
187
|
-
if not pcm:
|
188
|
-
# No rows at all => shape (0, num_cols) or (0, 0) if num_cols is None
|
189
|
-
if num_cols is None:
|
190
|
-
return csr_matrix((0, 0), dtype=int)
|
191
|
-
else:
|
192
|
-
return csr_matrix((0, num_cols), dtype=int)
|
193
|
-
|
194
|
-
row_indices = []
|
195
|
-
col_indices = []
|
196
|
-
data = []
|
197
|
-
|
198
|
-
max_col_found = -1
|
199
|
-
|
200
|
-
# Collect row/col for each '1' entry
|
201
|
-
for row_idx, col_list in enumerate(pcm):
|
202
|
-
for c in col_list:
|
203
|
-
row_indices.append(row_idx)
|
204
|
-
col_indices.append(c)
|
205
|
-
data.append(1)
|
206
|
-
if c > max_col_found:
|
207
|
-
max_col_found = c
|
208
|
-
|
209
|
-
num_rows = len(pcm)
|
210
|
-
|
211
|
-
# Auto-detect columns if not specified
|
212
|
-
if num_cols is None:
|
213
|
-
num_cols = max_col_found + 1
|
214
|
-
else:
|
215
|
-
# If the user specified num_cols, ensure the data fits
|
216
|
-
if max_col_found >= num_cols:
|
217
|
-
raise ValueError(
|
218
|
-
f"Column index {max_col_found} is out of range for a matrix of width {num_cols}."
|
219
|
-
)
|
220
|
-
|
221
|
-
return csr_matrix(
|
222
|
-
(data, (row_indices, col_indices)), shape=(num_rows, num_cols), dtype=int
|
223
|
-
)
|
224
|
-
|
225
|
-
|
226
|
-
def load_codetables_de_matrix_from_json(json_data):
|
227
|
-
"""
|
228
|
-
Construct a CSR matrix from a codetables.de JSON/dict output.
|
229
|
-
|
230
|
-
This function takes either a dictionary (as returned by
|
231
|
-
``get_codetables_de_matrix``) or a JSON string that decodes to the same
|
232
|
-
structure, and converts the ``pcm`` field into a SciPy CSR matrix.
|
233
|
-
|
234
|
-
Parameters
|
235
|
-
----------
|
236
|
-
json_data : dict or str
|
237
|
-
Must contain at least the following keys:
|
238
|
-
``{"n", "k", "d_upper", "d_lower", "url", "pcm"}``.
|
239
|
-
- ``pcm`` is a list of lists of column indices.
|
240
|
-
|
241
|
-
Returns
|
242
|
-
-------
|
243
|
-
csr_matrix
|
244
|
-
The stabilizer matrix in CSR format.
|
245
|
-
dict
|
246
|
-
The original dictionary that was passed in (or parsed from JSON).
|
247
|
-
|
248
|
-
Raises
|
249
|
-
------
|
250
|
-
ValueError
|
251
|
-
If ``json_data`` is not a dict, if it cannot be parsed into one,
|
252
|
-
or if required keys are missing.
|
253
|
-
|
254
|
-
Notes
|
255
|
-
-----
|
256
|
-
- Data is assumed to come from Markus Grassl's `codetables.de <https://codetables.de>`__.
|
257
|
-
- This utility is helpful when the data is stored or transmitted in JSON form
|
258
|
-
but needs to be loaded back into a matrix representation for further processing.
|
259
|
-
"""
|
260
|
-
if isinstance(json_data, str):
|
261
|
-
json_data = json.loads(json_data)
|
262
|
-
|
263
|
-
if not isinstance(json_data, dict):
|
264
|
-
raise ValueError(
|
265
|
-
"json_data must be a dict or a JSON string that decodes to a dict."
|
266
|
-
)
|
267
|
-
|
268
|
-
required_keys = {"n", "k", "d_upper", "d_lower", "url", "pcm"}
|
269
|
-
if not required_keys.issubset(json_data.keys()):
|
270
|
-
raise ValueError(f"JSON data missing required keys: {required_keys}")
|
271
|
-
|
272
|
-
pcm = json_data["pcm"]
|
273
|
-
sparse_matrix = pcm_to_csr_matrix(pcm)
|
274
|
-
return sparse_matrix, json_data
|
qec/utils/sparse_binary_utils.py
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import scipy.sparse
|
3
|
-
|
4
|
-
|
5
|
-
def convert_to_binary_scipy_sparse(
|
6
|
-
matrix: np.typing.ArrayLike,
|
7
|
-
) -> scipy.sparse.csr_matrix:
|
8
|
-
"""
|
9
|
-
Convert and validate a matrix as a sparse binary matrix in CSR format.
|
10
|
-
|
11
|
-
This function checks whether all elements of the input matrix are binary (0 or 1).
|
12
|
-
If the input is not already a sparse matrix, it converts it to a CSR (Compressed Sparse Row) matrix.
|
13
|
-
|
14
|
-
Parameters
|
15
|
-
----------
|
16
|
-
matrix : array-like
|
17
|
-
Input matrix of shape (M, N). Can be a dense array-like or any SciPy sparse matrix format.
|
18
|
-
|
19
|
-
Returns
|
20
|
-
-------
|
21
|
-
scipy.sparse.csr_matrix
|
22
|
-
Binary sparse matrix in CSR format, of shape (M, N).
|
23
|
-
|
24
|
-
Raises
|
25
|
-
------
|
26
|
-
ValueError
|
27
|
-
If the input matrix has elements outside {0, 1}.
|
28
|
-
TypeError
|
29
|
-
If the input is not array-like.
|
30
|
-
|
31
|
-
Examples
|
32
|
-
--------
|
33
|
-
>>> import numpy as np
|
34
|
-
>>> from scipy.sparse import csr_matrix
|
35
|
-
>>> from qec.utils.sparse_binary_utils import convert_to_binary_scipy_sparse
|
36
|
-
>>> mat = np.array([[0, 1], [1, 0]])
|
37
|
-
>>> convert_to_binary_scipy_sparse(mat).toarray()
|
38
|
-
array([[0, 1],
|
39
|
-
[1, 0]])
|
40
|
-
|
41
|
-
>>> mat = csr_matrix([[0, 1], [1, 0]])
|
42
|
-
>>> convert_to_binary_scipy_sparse(mat).toarray()
|
43
|
-
array([[0, 1],
|
44
|
-
[1, 0]])
|
45
|
-
|
46
|
-
>>> mat = np.array([[0, 2], [1, 0]])
|
47
|
-
>>> convert_to_binary_scipy_sparse(mat)
|
48
|
-
Traceback (most recent call last):
|
49
|
-
...
|
50
|
-
ValueError: All elements of the input matrix must be binary.
|
51
|
-
"""
|
52
|
-
if not isinstance(matrix, (np.ndarray, list, scipy.sparse.spmatrix)):
|
53
|
-
raise TypeError("Input must be array-like.")
|
54
|
-
|
55
|
-
if not isinstance(matrix, scipy.sparse.spmatrix):
|
56
|
-
matrix = scipy.sparse.csr_matrix(matrix, dtype=np.uint8)
|
57
|
-
|
58
|
-
if not matrix.dtype == np.uint8:
|
59
|
-
matrix = matrix.astype(np.uint8)
|
60
|
-
|
61
|
-
if not np.all(np.isin(matrix.data, [0, 1])):
|
62
|
-
raise ValueError("All elements of the input matrix must be binary.")
|
63
|
-
|
64
|
-
return matrix
|
qec-0.2.7.dist-info/RECORD
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
qec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
qec/code_constructions/__init__.py,sha256=AyEYcahGs_4C8nqSUhoYmZNBt1TzuzVPZjNN1FErRyQ,118
|
3
|
-
qec/code_constructions/css_code.py,sha256=nIaC24QhQwrmWQNhmX-X4TzlkmNAYoxN0feTdWjhswo,32376
|
4
|
-
qec/code_constructions/hgp_code.py,sha256=r5E_tEilRRJWDXrMbNAbplf-N5Y0XS7VUoWWTEjh9BY,11098
|
5
|
-
qec/code_constructions/stabilizer_code.py,sha256=I5u8JKZu88ioC4E2nBJ-00xCmnL8nU6kdAvwYOfmNRk,22138
|
6
|
-
qec/code_instances/__init__.py,sha256=z6jOPjekDIx0jgbRFThI95zUzLzjl9Dh89RBzxsT_BE,43
|
7
|
-
qec/code_instances/five_qubit_code.py,sha256=ZHyusTEnnnmUv4QxPLXQSKbEQv2QOoBqn2V9N4SgrQE,2177
|
8
|
-
qec/codetables_de/__init__.py,sha256=dQBgkBK_DlnI9OrOcfarM7HUbj9NKyO-9QSvItD2cyY,40
|
9
|
-
qec/codetables_de/codetables_de.py,sha256=SdOaS7OTMt76uLa1GJXGydMTmwJdNwTDnQyD4SBQDIM,3626
|
10
|
-
qec/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
qec/utils/binary_pauli_utils.py,sha256=BSlngYDdRICu0aVu4u_m0bvLicohORyGxfk5eRER7TQ,13245
|
12
|
-
qec/utils/codetables_de_utils.py,sha256=S1wcVGJkkASQQ5s71QAsYBmpyE-3xTb6UsvgMfQtuiw,9469
|
13
|
-
qec/utils/sparse_binary_utils.py,sha256=Y9xfGKzOGFiVTyhb6iF6N7-5oMY6Ah9oLrnv8HhSBHA,1965
|
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
|
File without changes
|