qLDPC 0.3.2__tar.gz → 0.3.3__tar.gz

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.
Files changed (70) hide show
  1. {qldpc-0.3.2 → qldpc-0.3.3}/PKG-INFO +28 -16
  2. {qldpc-0.3.2 → qldpc-0.3.3}/README.md +3 -3
  3. qldpc-0.3.3/pyproject.toml +109 -0
  4. qldpc-0.3.3/src/qldpc/_util.py +68 -0
  5. qldpc-0.3.3/src/qldpc/_util_test.py +54 -0
  6. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/__init__.py +11 -9
  7. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/groups.py +95 -47
  8. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/groups_test.py +19 -2
  9. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/linalg.py +23 -14
  10. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/linalg_test.py +1 -1
  11. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/rings.py +89 -58
  12. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/rings_test.py +6 -6
  13. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/wedderburn_artin.py +167 -100
  14. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/abstract/wedderburn_artin_test.py +1 -1
  15. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/cache.py +2 -2
  16. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/cache_test.py +1 -1
  17. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/__init__.py +26 -22
  18. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/benchmarking.py +25 -15
  19. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/benchmarking_test.py +1 -1
  20. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/bookkeeping.py +14 -7
  21. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/bookkeeping_test.py +1 -1
  22. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/common.py +28 -11
  23. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/common_test.py +1 -1
  24. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/encoding.py +26 -35
  25. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/encoding_test.py +14 -1
  26. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/alpha_syndrome.py +19 -14
  27. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/alpha_syndrome_test.py +12 -8
  28. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/memory.py +29 -18
  29. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/memory_test.py +2 -2
  30. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/syndrome_measurement.py +12 -10
  31. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/syndrome_measurement_test.py +6 -3
  32. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/noise_model.py +229 -107
  33. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/noise_model_test.py +20 -2
  34. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/transversal.py +7 -6
  35. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/transversal_test.py +2 -2
  36. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/__init__.py +21 -17
  37. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/classical.py +64 -22
  38. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/classical_test.py +8 -1
  39. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/common.py +425 -248
  40. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/common_test.py +114 -12
  41. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/distance.py +23 -21
  42. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/distance_test.py +9 -3
  43. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/quantum.py +263 -164
  44. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/codes/quantum_test.py +27 -8
  45. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/custom.py +175 -68
  46. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/custom_test.py +74 -2
  47. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/dems.py +83 -20
  48. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/dems_test.py +22 -1
  49. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/retrieval.py +34 -16
  50. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/retrieval_test.py +1 -1
  51. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/sinter.py +22 -17
  52. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/sinter_test.py +3 -3
  53. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/codes.py +1 -1
  54. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/codes_test.py +2 -2
  55. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/gap.py +4 -3
  56. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/gap_test.py +1 -1
  57. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/groups.py +13 -11
  58. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/groups_test.py +1 -1
  59. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/math.py +36 -33
  60. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/math_test.py +1 -1
  61. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/objects.py +52 -37
  62. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/objects_test.py +1 -1
  63. qldpc-0.3.2/pyproject.toml +0 -89
  64. qldpc-0.3.2/src/qldpc/circuits/conftest_probe.py +0 -13
  65. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/__init__.py +0 -0
  66. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/circuits/memory/__init__.py +3 -3
  67. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/conftest.py +0 -0
  68. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/decoders/__init__.py +14 -14
  69. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/external/__init__.py +0 -0
  70. {qldpc-0.3.2 → qldpc-0.3.3}/src/qldpc/py.typed +0 -0
@@ -1,39 +1,51 @@
1
1
  Metadata-Version: 2.4
2
- Name: qLDPC
3
- Version: 0.3.2
2
+ Name: qldpc
3
+ Version: 0.3.3
4
4
  Summary: Tools for constructing and analyzing quantum low density parity check (qLDPC) codes.
5
- Keywords: quantum computing,quantum error correction,low density parity check codes,LDPC
5
+ Keywords: LDPC,low density parity check codes,quantum computing,quantum error correction
6
6
  Author: Michael A. Perlin
7
7
  Author-email: Michael A. Perlin <mika.perlin@gmail.com>
8
8
  License-Expression: Apache-2.0
9
9
  Classifier: Development Status :: 3 - Alpha
10
10
  Classifier: Intended Audience :: Science/Research
11
11
  Classifier: Natural Language :: English
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
12
17
  Classifier: Topic :: Scientific/Engineering :: Mathematics
13
18
  Classifier: Topic :: Scientific/Engineering :: Physics
14
19
  Requires-Dist: cvxpy>=1.3.2
15
- Requires-Dist: diskcache>=5.0.0
20
+ Requires-Dist: diskcache>=5
16
21
  Requires-Dist: galois>=0.4.2
17
22
  Requires-Dist: ldpc>=2.4.1
18
23
  Requires-Dist: networkx>=2.6.2
19
- Requires-Dist: numpy>=1.24.0
20
- Requires-Dist: platformdirs>=4.0.0
21
- Requires-Dist: pymatching>=2.1.0
22
- Requires-Dist: pyperclip>=1.11.0
24
+ Requires-Dist: numpy>=1.24
25
+ Requires-Dist: platformdirs>=4
26
+ Requires-Dist: pymatching>=2.1
27
+ Requires-Dist: pyperclip>=1.11
23
28
  Requires-Dist: scipy>=1.14.1
24
- Requires-Dist: sinter>=1.16.0
25
- Requires-Dist: stim>=1.16.0
29
+ Requires-Dist: sinter>=1.16
30
+ Requires-Dist: stim>=1.16
26
31
  Requires-Dist: sympy>=1.12
27
- Requires-Dist: bloqade-tsim>=0.1.4 ; extra == 'dev'
28
32
  Requires-Dist: checks-superstaq>=0.5.62 ; extra == 'dev'
29
33
  Requires-Dist: jupyter>=1.1.1 ; extra == 'dev'
30
- Requires-Dist: python-lsp-server[all]>=1.14.0 ; extra == 'dev'
31
- Requires-Dist: relay-bp[stim]==0.2.1 ; extra == 'dev'
34
+ Requires-Dist: pypandoc-binary>=1.13 ; extra == 'dev'
35
+ Requires-Dist: pyproject-fmt>=2 ; extra == 'dev'
36
+ Requires-Dist: python-lsp-server[all]>=1.14 ; extra == 'dev'
37
+ Requires-Dist: qldpc[docs,relay-bp,tsim] ; extra == 'dev'
38
+ Requires-Dist: ipython>=8 ; extra == 'docs'
39
+ Requires-Dist: nbsphinx>=0.9 ; extra == 'docs'
40
+ Requires-Dist: sphinx>=7 ; extra == 'docs'
41
+ Requires-Dist: sphinx-autoapi>=3 ; extra == 'docs'
42
+ Requires-Dist: sphinx-rtd-theme>=2 ; extra == 'docs'
32
43
  Requires-Dist: relay-bp[stim]==0.2.1 ; extra == 'relay-bp'
33
44
  Requires-Dist: bloqade-tsim>=0.1.4 ; extra == 'tsim'
34
45
  Requires-Python: >=3.10
35
46
  Project-URL: Repository, https://github.com/qLDPCOrg/qLDPC
36
47
  Provides-Extra: dev
48
+ Provides-Extra: docs
37
49
  Provides-Extra: relay-bp
38
50
  Provides-Extra: tsim
39
51
  Description-Content-Type: text/markdown
@@ -72,7 +84,7 @@ You can also `pip install -e 'qLDPC[dev]'` to additionally install some developm
72
84
 
73
85
  ### GAP
74
86
 
75
- Some features in `qLDPC` require an installation of the [GAP](https://www.gap-system.org) computer algebra system. If you (a) use linux or macOS, and (b) use a `conda` to manage your python environment, then you can obtain GAP by running
87
+ Some features in `qLDPC` require an installation of the [GAP](https://www.gap-system.org) computer algebra system. If you (a) use Linux or macOS, and (b) use `conda` to manage your python environment, then you can obtain GAP by running
76
88
  ```
77
89
  conda install -c conda-forge gap
78
90
  ```
@@ -111,7 +123,7 @@ Notable features include:
111
123
  - `qldpc.decoders`: module for decoding code and circuit errors.
112
124
  - BP-OSD, BP-LSD, and belief-find (via [`ldpc`](https://github.com/quantumgizmos/ldpc)), Relay-BP (via [`relay-bp`](https://pypi.org/project/relay-bp)), minimum-weight perfect matching (via [`pymatching`](https://github.com/oscarhiggott/PyMatching)), lookup-table decoding, and others. Includes an interface for using custom decoders.
113
125
  - `SinterDecoder`: class to construct circuit-level decoders that are usable by [`sinter`](https://pypi.org/project/sinter).
114
- - `SlidingWindowDecoder`: the overlapping-recovery sliding-window decoder of [arXiv:quant-ph/0110143](https://arxiv.org/abs/quant-ph/0110143) and [arXiv:2209.08552](https://arxiv.org/pdf/2209.08552).
126
+ - `SlidingWindowDecoder`: the overlapping-recovery sliding-window decoder of [arXiv:quant-ph/0110143](https://arxiv.org/abs/quant-ph/0110143) and [arXiv:2209.08552](https://arxiv.org/abs/2209.08552).
115
127
  - `SequentialWindowDecoder`: a generalization of the `SlidingWindowDecoder` for arbitrary decoding and commit regions.
116
128
  - `DetectorErrorModelArrays`: representation of a `stim.DetectorErrorModel` with `scipy.sparse` and `numpy` arrays (`detector_flip_matrix`, `observable_flip_matrix`, `error_probs`).
117
129
  - `qldpc.circuits`: module for [`stim`](https://github.com/quantumlib/Stim) circuits and circuit utilities, including:
@@ -128,7 +140,7 @@ Notable features include:
128
140
 
129
141
  ## 🤔 Questions and issues
130
142
 
131
- This project aspires to one day have a proper [documentation page](https://qldpc.readthedocs.io/en/latest). In the meantime, I recommend looking at source code and the detailed comments therein, as well as `help(qldpc.object_of_interest)`. `qLDPC` requires every file (such as [`qldpc/codes/quantum.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/qldpc/codes/quantum.py)) to be covered by its own test file (such as [`qldpc/codes/quantum_test.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/qldpc/codes/quantum_test.py)), so test files are a good place to look for example usage of any function, class, etc. Finally, the [`examples`](https://github.com/qLDPCOrg/qLDPC/tree/main/examples) directory has some helpful notebooks to get you started.
143
+ This project aspires to one day have a proper [documentation page](https://qldpc.readthedocs.io/en/latest). In the meantime, I recommend looking at source code and the detailed comments therein, as well as `help(qldpc.object_of_interest)`. `qLDPC` requires every file (such as [`src/qldpc/codes/quantum.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/src/qldpc/codes/quantum.py)) to be covered by its own test file (such as [`src/qldpc/codes/quantum_test.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/src/qldpc/codes/quantum_test.py)), so test files are a good place to look for example usage of any function, class, etc. Finally, the [`examples`](https://github.com/qLDPCOrg/qLDPC/tree/main/examples) directory has some helpful notebooks to get you started.
132
144
 
133
145
  If you have any questions, feedback, or requests, please [open an issue on GitHub](https://github.com/qLDPCOrg/qLDPC/issues/new) or email me at [mika.perlin@gmail.com](mailto:mika.perlin@gmail.com)!
134
146
 
@@ -32,7 +32,7 @@ You can also `pip install -e 'qLDPC[dev]'` to additionally install some developm
32
32
 
33
33
  ### GAP
34
34
 
35
- Some features in `qLDPC` require an installation of the [GAP](https://www.gap-system.org) computer algebra system. If you (a) use linux or macOS, and (b) use a `conda` to manage your python environment, then you can obtain GAP by running
35
+ Some features in `qLDPC` require an installation of the [GAP](https://www.gap-system.org) computer algebra system. If you (a) use Linux or macOS, and (b) use `conda` to manage your python environment, then you can obtain GAP by running
36
36
  ```
37
37
  conda install -c conda-forge gap
38
38
  ```
@@ -71,7 +71,7 @@ Notable features include:
71
71
  - `qldpc.decoders`: module for decoding code and circuit errors.
72
72
  - BP-OSD, BP-LSD, and belief-find (via [`ldpc`](https://github.com/quantumgizmos/ldpc)), Relay-BP (via [`relay-bp`](https://pypi.org/project/relay-bp)), minimum-weight perfect matching (via [`pymatching`](https://github.com/oscarhiggott/PyMatching)), lookup-table decoding, and others. Includes an interface for using custom decoders.
73
73
  - `SinterDecoder`: class to construct circuit-level decoders that are usable by [`sinter`](https://pypi.org/project/sinter).
74
- - `SlidingWindowDecoder`: the overlapping-recovery sliding-window decoder of [arXiv:quant-ph/0110143](https://arxiv.org/abs/quant-ph/0110143) and [arXiv:2209.08552](https://arxiv.org/pdf/2209.08552).
74
+ - `SlidingWindowDecoder`: the overlapping-recovery sliding-window decoder of [arXiv:quant-ph/0110143](https://arxiv.org/abs/quant-ph/0110143) and [arXiv:2209.08552](https://arxiv.org/abs/2209.08552).
75
75
  - `SequentialWindowDecoder`: a generalization of the `SlidingWindowDecoder` for arbitrary decoding and commit regions.
76
76
  - `DetectorErrorModelArrays`: representation of a `stim.DetectorErrorModel` with `scipy.sparse` and `numpy` arrays (`detector_flip_matrix`, `observable_flip_matrix`, `error_probs`).
77
77
  - `qldpc.circuits`: module for [`stim`](https://github.com/quantumlib/Stim) circuits and circuit utilities, including:
@@ -88,7 +88,7 @@ Notable features include:
88
88
 
89
89
  ## 🤔 Questions and issues
90
90
 
91
- This project aspires to one day have a proper [documentation page](https://qldpc.readthedocs.io/en/latest). In the meantime, I recommend looking at source code and the detailed comments therein, as well as `help(qldpc.object_of_interest)`. `qLDPC` requires every file (such as [`qldpc/codes/quantum.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/qldpc/codes/quantum.py)) to be covered by its own test file (such as [`qldpc/codes/quantum_test.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/qldpc/codes/quantum_test.py)), so test files are a good place to look for example usage of any function, class, etc. Finally, the [`examples`](https://github.com/qLDPCOrg/qLDPC/tree/main/examples) directory has some helpful notebooks to get you started.
91
+ This project aspires to one day have a proper [documentation page](https://qldpc.readthedocs.io/en/latest). In the meantime, I recommend looking at source code and the detailed comments therein, as well as `help(qldpc.object_of_interest)`. `qLDPC` requires every file (such as [`src/qldpc/codes/quantum.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/src/qldpc/codes/quantum.py)) to be covered by its own test file (such as [`src/qldpc/codes/quantum_test.py`](https://github.com/qLDPCOrg/qLDPC/blob/main/src/qldpc/codes/quantum_test.py)), so test files are a good place to look for example usage of any function, class, etc. Finally, the [`examples`](https://github.com/qLDPCOrg/qLDPC/tree/main/examples) directory has some helpful notebooks to get you started.
92
92
 
93
93
  If you have any questions, feedback, or requests, please [open an issue on GitHub](https://github.com/qLDPCOrg/qLDPC/issues/new) or email me at [mika.perlin@gmail.com](mailto:mika.perlin@gmail.com)!
94
94
 
@@ -0,0 +1,109 @@
1
+ [build-system]
2
+ build-backend = "uv_build"
3
+ requires = [ "uv-build>=0.9.18,<0.10" ]
4
+
5
+ [project]
6
+ name = "qldpc"
7
+ version = "0.3.3"
8
+ description = "Tools for constructing and analyzing quantum low density parity check (qLDPC) codes."
9
+ readme = "README.md"
10
+ keywords = [
11
+ "LDPC",
12
+ "low density parity check codes",
13
+ "quantum computing",
14
+ "quantum error correction",
15
+ ]
16
+ license = "Apache-2.0"
17
+ authors = [ { name = "Michael A. Perlin", email = "mika.perlin@gmail.com" } ]
18
+ requires-python = ">=3.10"
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Science/Research",
22
+ "Natural Language :: English",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Programming Language :: Python :: 3.13",
28
+ "Topic :: Scientific/Engineering :: Mathematics",
29
+ "Topic :: Scientific/Engineering :: Physics",
30
+ ]
31
+ dependencies = [
32
+ "cvxpy>=1.3.2",
33
+ "diskcache>=5",
34
+ "galois>=0.4.2",
35
+ "ldpc>=2.4.1",
36
+ "networkx>=2.6.2",
37
+ "numpy>=1.24",
38
+ "platformdirs>=4",
39
+ "pymatching>=2.1",
40
+ "pyperclip>=1.11",
41
+ "scipy>=1.14.1",
42
+ "sinter>=1.16",
43
+ "stim>=1.16",
44
+ "sympy>=1.12",
45
+ ]
46
+ optional-dependencies.dev = [
47
+ "checks-superstaq>=0.5.62",
48
+ "jupyter>=1.1.1",
49
+ "pypandoc-binary>=1.13", # bundles pandoc for building the notebook docs locally
50
+ "pyproject-fmt>=2", # pyproject.toml formatting, run by checks/format_.py
51
+ "python-lsp-server[all]>=1.14",
52
+ "qldpc[docs,relay-bp,tsim]",
53
+ ]
54
+ optional-dependencies.docs = [
55
+ "ipython>=8", # for nbsphinx's IPython.sphinxext.ipython_console_highlighting extension
56
+ "nbsphinx>=0.9",
57
+ "sphinx>=7",
58
+ "sphinx-autoapi>=3",
59
+ "sphinx-rtd-theme>=2",
60
+ ]
61
+ optional-dependencies.relay-bp = [ "relay-bp[stim]==0.2.1" ]
62
+ optional-dependencies.tsim = [ "bloqade-tsim>=0.1.4" ]
63
+ urls.Repository = "https://github.com/qLDPCOrg/qLDPC"
64
+
65
+ # Check script configuration:
66
+ [tool.ruff]
67
+ line-length = 100
68
+ lint.extend-select = [
69
+ "ANN204", # return-type annotations on special methods (e.g. __init__)
70
+ "D205", # blank line between a docstring's summary and its body
71
+ "D212", # multi-line docstring summary starts on the first line
72
+ "D415", # docstring summary ends with punctuation (. ? !)
73
+ "D417", # a documented function documents all of its arguments
74
+ "I", # sorted / grouped imports (isort)
75
+ "RUF022", # sorted __all__ in __init__.py files
76
+ "W505", # docstring & comment line length (see max-doc-length below)
77
+ ]
78
+ lint.pycodestyle.max-doc-length = 100
79
+ lint.pydocstyle.convention = "google"
80
+
81
+ [tool.pyproject-fmt]
82
+ # Cap the auto-generated "Programming Language :: Python" classifiers at the highest supported/tested
83
+ # Python, so the set stays accurate and stable across pyproject-fmt versions.
84
+ max_supported_python = "3.13"
85
+
86
+ [tool.mypy]
87
+ ignore_missing_imports = true
88
+ disallow_any_generics = true
89
+ disallow_untyped_defs = true
90
+ disallow_incomplete_defs = true
91
+ warn_unused_ignores = true
92
+ pretty = true
93
+ install_types = true
94
+ no_implicit_optional = true
95
+ non_interactive = true
96
+ show_error_codes = true
97
+
98
+ [tool.pytest]
99
+ ini_options.addopts = "--disable-socket" # forbid tests from making network calls
100
+ ini_options.filterwarnings = [
101
+ "ignore:(?s).*The problem is either infeasible or unbounded.*:UserWarning", # from cvxpy
102
+ ]
103
+
104
+ [tool.coverage]
105
+ run.include = [ "./*" ]
106
+ report.exclude_lines = [ "if TYPE_CHECKING:", "pragma: no cover" ]
107
+ report.fail_under = 100
108
+ report.show_missing = true
109
+ report.skip_covered = true
@@ -0,0 +1,68 @@
1
+ """Miscellaneous internal utilities.
2
+
3
+ Copyright 2023 The qLDPC Authors and Infleqtion Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import importlib.util
21
+ import sys
22
+ from collections.abc import Callable
23
+ from types import ModuleType
24
+ from typing import TYPE_CHECKING, TypeVar
25
+
26
+ CallableType = TypeVar("CallableType", bound=Callable[..., object])
27
+
28
+
29
+ def lazy_import(name: str) -> ModuleType:
30
+ """Import a module lazily, deferring its execution until its first attribute access.
31
+
32
+ Uses importlib.util.LazyLoader so a heavy but rarely-used dependency stays out of ``import
33
+ qldpc`` while call sites keep using ``module.attr`` exactly as if it had been imported eagerly.
34
+ """
35
+ if (module := sys.modules.get(name)) is not None:
36
+ return module
37
+ spec = importlib.util.find_spec(name)
38
+ assert spec is not None and spec.loader is not None
39
+ spec.loader = importlib.util.LazyLoader(spec.loader)
40
+ module = importlib.util.module_from_spec(spec)
41
+ sys.modules[name] = module
42
+ spec.loader.exec_module(module)
43
+ return module
44
+
45
+
46
+ # networkx is loaded lazily to keep it and its ~110 ms import out of ``import qldpc``.
47
+ # Call sites import it as ``from qldpc._util import networkx as nx``.
48
+ if TYPE_CHECKING:
49
+ import networkx
50
+ else:
51
+ networkx = lazy_import("networkx")
52
+
53
+
54
+ def format_docstring(**substitutions: object) -> Callable[[CallableType], CallableType]:
55
+ """Substitute named values into a function's docstring via str.format.
56
+
57
+ This lets a docstring reference values (such as module-level constants) by name, for example
58
+ "Default: {error_rate}.", without making the docstring an f-string. An f-string cannot be used
59
+ as a docstring: Python evaluates it as an ordinary expression and leaves __doc__ set to None,
60
+ silently discarding the documentation.
61
+ """
62
+
63
+ def decorator(func: CallableType) -> CallableType:
64
+ if func.__doc__ is not None:
65
+ func.__doc__ = func.__doc__.format(**substitutions)
66
+ return func
67
+
68
+ return decorator
@@ -0,0 +1,54 @@
1
+ """Unit tests for _util.py.
2
+
3
+ Copyright 2023 The qLDPC Authors and Infleqtion Inc.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ """
17
+
18
+ import sys
19
+ from types import ModuleType
20
+
21
+ from qldpc._util import format_docstring, lazy_import
22
+
23
+
24
+ def test_lazy_import() -> None:
25
+ """A lazily imported module is only executed on first attribute access."""
26
+ name = "colorsys" # a small stdlib module not otherwise imported by the test suite
27
+ sys.modules.pop(name, None)
28
+
29
+ module = lazy_import(name) # uncached path
30
+ assert isinstance(module, ModuleType)
31
+ assert callable(module.rgb_to_hls) # force the deferred execution
32
+
33
+ assert lazy_import(name) is module # cached path returns the same module
34
+
35
+
36
+ def test_format_docstring() -> None:
37
+ """Named values are substituted into a docstring."""
38
+
39
+ @format_docstring(value=1e-3, name="tag")
40
+ def func() -> None:
41
+ """A docstring with a {value} and a {name}."""
42
+
43
+ assert func.__doc__ == "A docstring with a 0.001 and a tag."
44
+
45
+
46
+ def test_format_docstring_without_docstring() -> None:
47
+ """A function without a docstring is left untouched."""
48
+
49
+ @format_docstring(value=1)
50
+ def func() -> None:
51
+ return None
52
+
53
+ assert func.__doc__ is None
54
+ assert func() is None
@@ -14,6 +14,7 @@ from .groups import (
14
14
  SymmetricGroup,
15
15
  TrivialGroup,
16
16
  get_coefficient_and_exponents,
17
+ iter_monomial_terms,
17
18
  resolve_field,
18
19
  )
19
20
  from .linalg import (
@@ -42,25 +43,26 @@ __all__ = [
42
43
  "AlternatingGroup",
43
44
  "CyclicGroup",
44
45
  "DihedralGroup",
46
+ "Element",
45
47
  "Group",
46
48
  "GroupMember",
49
+ "GroupRing",
47
50
  "ProjectiveSpecialLinearGroup",
51
+ "Protograph",
48
52
  "QuaternionGroup",
53
+ "RingArray",
54
+ "RingMember",
49
55
  "SmallGroup",
50
56
  "SpecialLinearGroup",
51
57
  "SymmetricGroup",
52
58
  "TrivialGroup",
53
- "get_coefficient_and_exponents",
54
- "resolve_field",
59
+ "WedderburnArtinComponentTransformer",
60
+ "WedderburnArtinTransformer",
55
61
  "block_diag",
62
+ "get_coefficient_and_exponents",
56
63
  "get_howell_dual",
64
+ "iter_monomial_terms",
57
65
  "kron",
58
66
  "matmul",
59
- "Element",
60
- "GroupRing",
61
- "Protograph",
62
- "RingArray",
63
- "RingMember",
64
- "WedderburnArtinComponentTransformer",
65
- "WedderburnArtinTransformer",
67
+ "resolve_field",
66
68
  ]