qec 0.3.2__py3-none-any.whl → 0.3.3__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.
@@ -0,0 +1,142 @@
1
+ import json
2
+ from typing import Union
3
+ import inspect
4
+ from pathlib import Path
5
+ from qec.utils.sparse_binary_utils import dict_to_binary_csr_matrix
6
+ import qec.code_constructions
7
+
8
+
9
+ def load_code(filepath: Union[str, Path]):
10
+ """
11
+ Loads a quantum error correction code from a JSON file.
12
+
13
+ Parameters
14
+ ----------
15
+ filepath : Union[str, Path]
16
+ Path to JSON file containing code data
17
+
18
+ Returns
19
+ -------
20
+ object
21
+ An instance of the quantum error correction code class.
22
+
23
+ Raises
24
+ ------
25
+ FileNotFoundError
26
+ If the specified file does not exist.
27
+ ValueError
28
+ If the input file is missing the 'class_name' key.
29
+ AttributeError
30
+ If the specified class does not exist in qec.code_constructions.
31
+ """
32
+
33
+ file_path = Path(filepath)
34
+ if not file_path.exists():
35
+ raise FileNotFoundError(
36
+ f"Error: No file found at the specified path: {file_path}"
37
+ )
38
+
39
+ with open(file_path, "r") as file:
40
+ code_data = json.load(file)
41
+
42
+ if "class_name" not in code_data:
43
+ raise ValueError(
44
+ "Error: The input JSON file must contain a 'class_name' key specifying the class to instantiate."
45
+ )
46
+
47
+ try:
48
+ class_reference = eval(
49
+ f"qec.code_constructions.{code_data['class_name']}", {"qec": qec}
50
+ )
51
+ except AttributeError:
52
+ raise AttributeError(
53
+ f"Error: The specified class '{code_data['class_name']}' does not exist in qec.code_constructions."
54
+ )
55
+
56
+ constructor_parameters = inspect.signature(
57
+ class_reference.__init__
58
+ ).parameters.keys()
59
+ filtered_input_parameters = {}
60
+
61
+ for key, value in code_data.items():
62
+ if key in constructor_parameters:
63
+ if isinstance(value, dict) and all(
64
+ k in value for k in ["indices", "indptr", "shape"]
65
+ ):
66
+ filtered_input_parameters[key] = dict_to_binary_csr_matrix(
67
+ value
68
+ ) # Convert sparse matrix
69
+ else:
70
+ filtered_input_parameters[key] = value # Keep as-is if not a matrix
71
+
72
+ # Instantiate the class
73
+ code_instance = class_reference(**filtered_input_parameters)
74
+
75
+ # Add extra attributes from JSON that are valid class attributes but not constructor parameters
76
+ class_attributes = dir(code_instance)
77
+ for key, value in code_data.items():
78
+ if key not in constructor_parameters and key in class_attributes:
79
+ if isinstance(value, dict) and all(
80
+ k in value for k in ["indices", "indptr", "shape"]
81
+ ):
82
+ value = dict_to_binary_csr_matrix(value) # Convert sparse matrix
83
+ else:
84
+ pass
85
+
86
+ if (not isinstance(value, str) or value != "?") and value is not None:
87
+ setattr(code_instance, key, value)
88
+
89
+ return code_instance
90
+
91
+
92
+ def load_code_from_id(code_id: int):
93
+ """
94
+ Load a quantum error correction code from a JSON file based on its ID from the package data.
95
+
96
+ The code files are packaged as data in the directory:
97
+ qec/code_instances/saved_codes
98
+ and are named as f"{code_id}.json".
99
+
100
+ Parameters
101
+ ----------
102
+ code_id : int
103
+ The identifier of the saved code.
104
+
105
+ Returns
106
+ -------
107
+ object
108
+ An instance of the quantum error correction code class loaded from the JSON data.
109
+
110
+ Raises
111
+ ------
112
+ FileNotFoundError
113
+ If the JSON file corresponding to code_id is not found.
114
+ """
115
+ from importlib.resources import files, as_file
116
+ from importlib import import_module
117
+ from pathlib import Path
118
+
119
+ filename = f"{code_id}.json"
120
+ package = "qec.code_instances.saved_codes"
121
+ try:
122
+ pkg = import_module(package)
123
+ # If the package spec lacks an origin, fall back.
124
+ if pkg.__spec__ is None or pkg.__spec__.origin is None:
125
+ raise ImportError("Package spec origin not found; fallback to filesystem.")
126
+ resource = files(pkg).joinpath(filename)
127
+ except Exception:
128
+ # Fallback: construct the path relative to this file.
129
+ resource = (
130
+ Path(__file__).parent.parent / "code_instances" / "saved_codes" / filename
131
+ )
132
+
133
+ if not resource.is_file():
134
+ raise FileNotFoundError(
135
+ f"File '{filename}' does not exist in package data at '{package}' "
136
+ f"or via fallback path '{resource}'."
137
+ )
138
+
139
+ with as_file(resource) as resource_path:
140
+ if not resource_path.exists():
141
+ raise FileNotFoundError(f"File '{resource_path}' does not exist on disk.")
142
+ return load_code(resource_path)
@@ -0,0 +1,80 @@
1
+ import numpy.typing
2
+ import numpy as np
3
+ import scipy.sparse
4
+
5
+
6
+ def convert_to_binary_scipy_sparse(
7
+ matrix: numpy.typing.ArrayLike,
8
+ ) -> scipy.sparse.csr_matrix:
9
+ """
10
+ Convert and validate a matrix as a sparse binary matrix in CSR format.
11
+
12
+ This function checks whether all elements of the input matrix are binary (0 or 1).
13
+ If the input is not already a sparse matrix, it converts it to a CSR (Compressed Sparse Row) matrix.
14
+
15
+ Parameters
16
+ ----------
17
+ matrix : array-like
18
+ Input matrix of shape (M, N). Can be a dense array-like or any SciPy sparse matrix format.
19
+
20
+ Returns
21
+ -------
22
+ scipy.sparse.csr_matrix
23
+ Binary sparse matrix in CSR format, of shape (M, N).
24
+
25
+ Raises
26
+ ------
27
+ ValueError
28
+ If the input matrix has elements outside {0, 1}.
29
+ TypeError
30
+ If the input is not array-like.
31
+
32
+ Examples
33
+ --------
34
+ >>> import numpy as np
35
+ >>> from scipy.sparse import csr_matrix
36
+ >>> from qec.utils.sparse_binary_utils import convert_to_binary_scipy_sparse
37
+ >>> mat = np.array([[0, 1], [1, 0]])
38
+ >>> convert_to_binary_scipy_sparse(mat).toarray()
39
+ array([[0, 1],
40
+ [1, 0]])
41
+
42
+ >>> mat = csr_matrix([[0, 1], [1, 0]])
43
+ >>> convert_to_binary_scipy_sparse(mat).toarray()
44
+ array([[0, 1],
45
+ [1, 0]])
46
+
47
+ >>> mat = np.array([[0, 2], [1, 0]])
48
+ >>> convert_to_binary_scipy_sparse(mat)
49
+ Traceback (most recent call last):
50
+ ...
51
+ ValueError: All elements of the input matrix must be binary.
52
+ """
53
+ if not isinstance(matrix, (np.ndarray, list, scipy.sparse.spmatrix)):
54
+ raise TypeError("Input must be array-like.")
55
+
56
+ if not isinstance(matrix, scipy.sparse.csr_matrix):
57
+ matrix = scipy.sparse.csr_matrix(matrix, dtype=np.uint8)
58
+
59
+ if not matrix.dtype == np.uint8:
60
+ matrix = matrix.astype(np.uint8)
61
+
62
+ if not np.all(np.isin(matrix.data, [0, 1])):
63
+ raise ValueError("All elements of the input matrix must be binary.")
64
+
65
+ return matrix
66
+
67
+
68
+ def binary_csr_matrix_to_dict(matrix: scipy.sparse.spmatrix):
69
+ return {
70
+ "indices": matrix.indices.tolist(),
71
+ "indptr": matrix.indptr.tolist(),
72
+ "shape": matrix.shape,
73
+ }
74
+
75
+
76
+ def dict_to_binary_csr_matrix(csr_dict: dict):
77
+ return scipy.sparse.csr_matrix(
78
+ ([1] * len(csr_dict["indices"]), csr_dict["indices"], csr_dict["indptr"]),
79
+ shape=csr_dict["shape"],
80
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qec
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: Python Tools for Quantum Error Correction
5
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>
6
6
  License: MIT License
@@ -0,0 +1,27 @@
1
+ qec/__init__.py,sha256=daEdpEyAJIa8b2VkCqSKcw8PaExcB6Qro80XNes_sHA,2
2
+ qec/code_constructions/__init__.py,sha256=Jg7aUTYaTuFnLGcpqPmc7iSQeM6Kwi_p9eUQBLNvePQ,600
3
+ qec/code_constructions/css_code.py,sha256=e4X6QMnZ_xHdZENsaqrfFe-tl0XgEHvm7Fw2yBM3low,38614
4
+ qec/code_constructions/hgp_code.py,sha256=FqghbZ6mQIBlQIJwhaPU_Zb1LjnmHBS_PGtQVNPl_mA,12310
5
+ qec/code_constructions/periodic_surface_xzzx.py,sha256=iF95s-py85ivELlCiL5oEWe87OUVaKI3r4mJjaKy_-o,3551
6
+ qec/code_constructions/rotated_xzzx.py,sha256=wSWH9H1AaNn_Yyhnr_NSvZdlo_sV9HW5JHFcBrjAnQY,4400
7
+ qec/code_constructions/stabilizer_code.py,sha256=InPbSrqzMxueMQaFbUt-ytDHCWIzgIddnlAwYegpRFg,24258
8
+ qec/code_constructions/surface_code.py,sha256=s49uyMZPRjOwBqpfLeB5Dl38O8w7BP8Y1tBemFhyDr0,2561
9
+ qec/code_constructions/toric_code.py,sha256=Q8f3jU80gwsjqRVtp2tBuO6yRltQI5KeD49xQm8vuAw,1952
10
+ qec/code_instances/__init__.py,sha256=5T_Qw26-cQc5BC6RM23_oDAYRdB3UPU5MeCGPxsoSRs,79
11
+ qec/code_instances/five_qubit_code.py,sha256=ZHyusTEnnnmUv4QxPLXQSKbEQv2QOoBqn2V9N4SgrQE,2177
12
+ qec/code_instances/saved_codes/1.json,sha256=PEErxvbeDupmZ4woHxC6EGAaRxfZ34fb4cOpBkfHvrs,850
13
+ qec/code_instances/saved_codes/2.json,sha256=Dwp5XT65s9Wu51WFJjzNzkP5WYLcVPkVoIpfLb92PMM,2920
14
+ qec/code_instances/saved_codes/3.json,sha256=3FeCj54tl708TeEsaChb_qqr92kw4_9S1wf4VASN-5U,4687
15
+ qec/code_instances/saved_codes/4.json,sha256=H4ktJy02VGPxqSAZkjam1HMlPex2KjmbcG9CBdP4NhI,5452
16
+ qec/codetables_de/__init__.py,sha256=_BQq4cIgZHbGPsA6qsJnMJ-B5eHqiYvUKbSubmJP8jA,68
17
+ qec/codetables_de/codetables_de.py,sha256=4tkoHtr4VXHm0qY9r397EUhxFXR1Mp6DqqtfblGyzbw,3725
18
+ qec/utils/__init__.py,sha256=lSkUeUQhk2KU8EgH63jSehwAMHQAJ3XBDmmRIKXRuN8,123
19
+ qec/utils/binary_pauli_utils.py,sha256=Vtqw-wWlOmrj2CDDhjjNmgUZHe5TJ2bU5-c_pV_Q4ks,13280
20
+ qec/utils/codetables_de_utils.py,sha256=Qbk2y-4sMufSrgQyuC6pDBOteeC3By_BiykVz4mIL7o,9467
21
+ qec/utils/load_code_util.py,sha256=w4icqtSKvEiA9JuFAc1AdkCt31dDC-SYK4-d4G4YfAY,4642
22
+ qec/utils/sparse_binary_utils.py,sha256=02qxK1iC_8jFIeuH1vjSd_3OwuKT5wWsVBshklc2IIA,2397
23
+ qec-0.3.3.dist-info/licenses/LICENSE,sha256=1b_xwNz1znYBfEaCL6pN2gNBAn8pQIjDRs_UhDp1EJI,1066
24
+ qec-0.3.3.dist-info/METADATA,sha256=r6ZBxOp3OYOhSOvjah90naZqy93BQcnHUpqIgfJpLoU,6392
25
+ qec-0.3.3.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
26
+ qec-0.3.3.dist-info/top_level.txt,sha256=d8l_7pJ5u9uWdviNp0FUK-j8VPZqywkDek7qa4NDank,4
27
+ qec-0.3.3.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- qec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- qec/code_instances/saved_codes/1.json,sha256=PEErxvbeDupmZ4woHxC6EGAaRxfZ34fb4cOpBkfHvrs,850
3
- qec/code_instances/saved_codes/2.json,sha256=Dwp5XT65s9Wu51WFJjzNzkP5WYLcVPkVoIpfLb92PMM,2920
4
- qec/code_instances/saved_codes/3.json,sha256=3FeCj54tl708TeEsaChb_qqr92kw4_9S1wf4VASN-5U,4687
5
- qec/code_instances/saved_codes/4.json,sha256=H4ktJy02VGPxqSAZkjam1HMlPex2KjmbcG9CBdP4NhI,5452
6
- qec-0.3.2.dist-info/licenses/LICENSE,sha256=1b_xwNz1znYBfEaCL6pN2gNBAn8pQIjDRs_UhDp1EJI,1066
7
- qec-0.3.2.dist-info/METADATA,sha256=dXPczwlUgmEfniM9ImiaDIRhIKgGtUH65ycJcMrg_Ek,6392
8
- qec-0.3.2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
9
- qec-0.3.2.dist-info/top_level.txt,sha256=d8l_7pJ5u9uWdviNp0FUK-j8VPZqywkDek7qa4NDank,4
10
- qec-0.3.2.dist-info/RECORD,,
File without changes