-
Notifications
You must be signed in to change notification settings - Fork 31
Remove ldpc dependency in deltakit-explore #309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jsimbadev
wants to merge
14
commits into
Deltakit:main
Choose a base branch
from
jsimbadev:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
d0513da
feat: replace functionality of ldpc independent logical base extractiβ¦
jsimbadev ec02449
chore: move tests into logicals... its only logical.
jsimbadev eb09ea6
style: trigger pre-commit.
jsimbadev ed8163e
refactor: replace compute_lz code with new galois variant, and generaβ¦
jsimbadev 34f26a6
Merge branch 'main' into main
jsimbadev e03f03c
feat: actually do the thing and remove ldpc from explorer dependencies.
jsimbadev 63f24b9
fix(test): use full distribution name for resolving detlakit_stim
jsimbadev 87b52d2
fix(test): use distribution name instead of package name in importlibβ¦
jsimbadev 9ef8398
chore: remove pyproject.toml mypy override config for ldpc since its β¦
jsimbadev eb8362d
fix(explorer): address review comments
jsimbadev d788cef
fix(explorer): Rename variable in _logicals.py::pivot_rows
jsimbadev a8534ab
refactor(explorer): clarify logical helper naming
jsimbadev 45201b5
test(explorer): use typed ndarray annotations
jsimbadev 0a86ba1
Merge remote-tracking branch 'upstream/main'
jsimbadev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,13 @@ | ||
| from itertools import product | ||
|
|
||
| import deltakit_circuit as circuit | ||
| import deltakit_stim as stim | ||
| import numpy as np | ||
| import numpy.typing as npt | ||
| import pytest | ||
|
|
||
| from deltakit_explorer.codes._logicals import ( | ||
| css_code_compute_logicals, | ||
| paulistring_to_operator, | ||
| ) | ||
|
|
||
|
|
@@ -32,3 +37,201 @@ def test_paulistring_to_operator(string): | |
| # operators_ref = [tuple(stim.PauliString(i) for i in j) for j in operators] | ||
| # operators_res = get_str_logical_operators_from_tableau(stabilisers) | ||
| # operators_res == operators_ref | ||
|
|
||
|
|
||
| def _binary_matrix(rows: npt.ArrayLike) -> npt.NDArray[np.uint8]: | ||
| """Convert binary rows into a dense ``uint8`` array. | ||
|
|
||
| Args: | ||
| rows: Row vectors to place in the matrix. | ||
|
|
||
| Returns: | ||
| A dense ``uint8`` array built from ``rows``. | ||
| """ | ||
| return np.asarray(rows, dtype=np.uint8) | ||
|
|
||
|
|
||
| def _empty_binary_matrix(n_cols: int) -> npt.NDArray[np.uint8]: | ||
| """Construct an empty dense ``uint8`` array with a fixed column count. | ||
|
|
||
| Args: | ||
| n_cols: Number of columns in the returned matrix. | ||
|
|
||
| Returns: | ||
| A dense ``uint8`` array of shape ``(0, n_cols)``. | ||
| """ | ||
| return np.zeros((0, n_cols), dtype=np.uint8) | ||
|
|
||
|
|
||
| def _binary_row_space(matrix: npt.NDArray[np.uint8]) -> set[tuple[int, ...]]: | ||
| """Enumerate the row space of a binary array using GF(2) arithmetic. | ||
|
|
||
| Args: | ||
| matrix: A dense binary ``uint8`` array. | ||
|
|
||
| Returns: | ||
| The set of all binary vectors obtainable as mod-2 sums of rows of | ||
| ``matrix``, represented as tuples. | ||
|
|
||
| Notes: | ||
| This helper uses a brute-force enumeration over all binary choices of row | ||
| coefficients, so it is only suitable for the small matrices used in these | ||
| tests. | ||
| """ | ||
| num_rows, num_cols = matrix.shape | ||
|
|
||
| if num_rows == 0: | ||
| return {tuple([0] * num_cols)} | ||
|
|
||
| vectors: set[tuple[int, ...]] = set() | ||
| for coefficients in product((0, 1), repeat=num_rows): | ||
| vector = np.zeros(num_cols, dtype=np.uint8) | ||
| for coefficient, row in zip(coefficients, matrix, strict=True): | ||
| if coefficient: | ||
| vector ^= row | ||
| vectors.add(tuple(int(value) for value in vector)) | ||
|
|
||
| return vectors | ||
|
|
||
|
|
||
| def _binary_null_space(matrix: npt.NDArray[np.uint8]) -> set[tuple[int, ...]]: | ||
| """Enumerate the null space of a binary array using GF(2) arithmetic. | ||
|
|
||
| Args: | ||
| matrix: A dense binary ``uint8`` array. | ||
|
|
||
| Returns: | ||
| The set of all binary vectors ``v`` such that ``matrix @ v == 0`` over | ||
| GF(2), represented as tuples. | ||
|
|
||
| Notes: | ||
| This helper checks every binary vector of the appropriate length, so it is | ||
| a brute-force construction intended only for the small test cases in this | ||
| module. | ||
| """ | ||
| _, num_cols = matrix.shape | ||
|
|
||
| vectors: set[tuple[int, ...]] = set() | ||
| for entries in product((0, 1), repeat=num_cols): | ||
| vector = np.asarray(entries, dtype=np.uint8) | ||
| if np.all((matrix @ vector) % 2 == 0): | ||
| vectors.add(entries) | ||
|
|
||
| return vectors | ||
|
|
||
|
|
||
| def _dimension(space: set[tuple[int, ...]]) -> int: | ||
| return int(np.log2(len(space))) | ||
|
|
||
|
|
||
| def _assert_logical_basis( | ||
| logicals: npt.NDArray[np.uint8], | ||
| null_space_defining_checks: npt.NDArray[np.uint8], | ||
| quotient_space_defining_checks: npt.NDArray[np.uint8], | ||
| ) -> None: | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docstring.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done ) |
||
| """Assert that returned logicals have the expected CSS logical structure. | ||
|
|
||
| This checks that ``logicals`` is a well-formed binary basis for the | ||
| non-redundant rows allowed by ``null_space_defining_checks``, with the | ||
| expected number of independent rows once the rows generated by | ||
| ``quotient_space_defining_checks`` are treated as redundant. | ||
|
|
||
| Args: | ||
| logicals: Candidate logical rows returned by ``css_code_compute_logicals``. | ||
| null_space_defining_checks: Checks that define which rows are valid. | ||
| quotient_space_defining_checks: Checks whose row space is treated as | ||
| redundant when determining the expected logical rows. | ||
|
|
||
| Returns: | ||
| None. | ||
| """ | ||
| logicals_is_matrix = logicals.ndim == 2 | ||
| num_logical_columns = logicals.shape[1] | ||
| num_logical_rows = logicals.shape[0] | ||
| num_null_space_columns = null_space_defining_checks.shape[1] | ||
| num_quotient_space_columns = quotient_space_defining_checks.shape[1] | ||
| logicals_are_binary = np.all(np.isin(logicals, [0, 1])) | ||
|
|
||
| assert logicals_is_matrix | ||
| assert num_logical_columns == num_null_space_columns == num_quotient_space_columns | ||
| assert logicals_are_binary | ||
|
|
||
| null_space = _binary_null_space(null_space_defining_checks) | ||
| quotient_space = _binary_row_space(quotient_space_defining_checks) | ||
| generated_space = _binary_row_space( | ||
| np.vstack([quotient_space_defining_checks, logicals]) | ||
| ) | ||
|
|
||
| # CSS logicals should extend the quotient space into a basis for the null space. | ||
| assert generated_space == null_space | ||
|
|
||
| expected_num_logicals = _dimension(null_space) - _dimension(quotient_space) | ||
| assert num_logical_rows == expected_num_logicals | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ("hx", "hz"), | ||
| [ | ||
| (_empty_binary_matrix(3), _empty_binary_matrix(3)), | ||
| (_binary_matrix([[1, 1, 0], [0, 1, 1]]), _empty_binary_matrix(3)), | ||
| (_binary_matrix(np.eye(3, dtype=np.uint8).tolist()), _empty_binary_matrix(3)), | ||
| ( | ||
| _binary_matrix([[1, 1, 0], [0, 1, 1], [1, 0, 1]]), | ||
| _empty_binary_matrix(3), | ||
| ), | ||
| ( | ||
| _binary_matrix([[1, 1, 1, 1]]), | ||
| _binary_matrix([[1, 1, 0, 0], [0, 0, 1, 1]]), | ||
| ), | ||
| ], | ||
| ) | ||
| def test_css_code_compute_logicals_returns_valid_css_logical_bases( | ||
| hx: npt.NDArray[np.uint8], hz: npt.NDArray[np.uint8] | ||
| ): | ||
| assert np.all((hx @ hz.T) % 2 == 0) | ||
|
|
||
| lx, lz = css_code_compute_logicals(hx.astype(float), hz.astype(float)) | ||
|
|
||
| _assert_logical_basis(np.asarray(lx, dtype=np.uint8), hz, hx) | ||
| _assert_logical_basis(np.asarray(lz, dtype=np.uint8), hx, hz) | ||
|
|
||
|
|
||
| def test_css_code_compute_logicals_is_invariant_to_redundant_rows(): | ||
| hx = _binary_matrix([[1, 1, 0], [0, 1, 1]]) | ||
| redundant_hx = _binary_matrix([[1, 1, 0], [0, 1, 1], [1, 0, 1]]) | ||
| hz = _empty_binary_matrix(3) | ||
|
|
||
| lx, lz = css_code_compute_logicals(hx.astype(float), hz.astype(float)) | ||
| redundant_lx, redundant_lz = css_code_compute_logicals( | ||
| redundant_hx.astype(float), hz.astype(float) | ||
| ) | ||
|
|
||
| assert _binary_row_space(np.asarray(lx, dtype=np.uint8)) == _binary_row_space( | ||
| np.asarray(redundant_lx, dtype=np.uint8) | ||
| ) | ||
| assert _binary_row_space(np.asarray(lz, dtype=np.uint8)) == _binary_row_space( | ||
| np.asarray(redundant_lz, dtype=np.uint8) | ||
| ) | ||
|
|
||
|
|
||
| def test_css_code_compute_logicals_preserves_logical_dimension_for_known_rank_checks(): | ||
| # Adapted from the explicit GF(2) row-reduction fixture in galois/tests/fields/test_linalg.py. | ||
| hx = _binary_matrix( | ||
| [ | ||
| [1, 0, 1, 0, 1, 0, 1, 0], | ||
| [0, 1, 1, 0, 0, 1, 1, 0], | ||
| [0, 0, 0, 1, 1, 1, 1, 0], | ||
| [1, 1, 1, 1, 1, 1, 1, 1], | ||
| ] | ||
| ) | ||
| hz = _empty_binary_matrix(8) | ||
|
|
||
| rank_hx = _dimension(_binary_row_space(hx)) | ||
| assert rank_hx == 4 | ||
|
|
||
| lx, lz = css_code_compute_logicals(hx.astype(float), hz.astype(float)) | ||
|
|
||
| assert lx.shape == (8 - rank_hx, 8) | ||
| assert lz.shape == (8 - rank_hx, 8) | ||
| _assert_logical_basis(np.asarray(lx, dtype=np.uint8), hz, hx) | ||
| _assert_logical_basis(np.asarray(lz, dtype=np.uint8), hx, hz) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.