qec 0.2.1__py3-none-any.whl → 0.2.2__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_constructions/__init__.py +4 -0
- qec/{stabilizer_code → code_constructions}/css_code.py +214 -50
- qec/code_constructions/hgp_code.py +264 -0
- qec/code_instances/__init__.py +1 -0
- qec/{quantum_codes → code_instances}/five_qubit_code.py +1 -1
- qec/codetables_de/__init__.py +1 -0
- qec/{quantum_codes → codetables_de}/codetables_de.py +1 -1
- qec-0.2.2.dist-info/METADATA +146 -0
- qec-0.2.2.dist-info/RECORD +18 -0
- qec/quantum_codes/__init__.py +0 -2
- qec/stabilizer_code/__init__.py +0 -1
- qec-0.2.1.dist-info/METADATA +0 -82
- qec-0.2.1.dist-info/RECORD +0 -16
- /qec/{stabilizer_code → code_constructions}/stabilizer_code.py +0 -0
- {qec-0.2.1.dist-info → qec-0.2.2.dist-info}/LICENSE +0 -0
- {qec-0.2.1.dist-info → qec-0.2.2.dist-info}/WHEEL +0 -0
- {qec-0.2.1.dist-info → qec-0.2.2.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
from qec.
|
1
|
+
from qec.code_constructions import StabilizerCode
|
2
2
|
from qec.utils.sparse_binary_utils import convert_to_binary_scipy_sparse
|
3
3
|
|
4
4
|
# Added / ammended from old code
|
@@ -10,7 +10,7 @@ from ldpc import BpOsdDecoder
|
|
10
10
|
from tqdm import tqdm
|
11
11
|
import time
|
12
12
|
import logging
|
13
|
-
from typing import Optional
|
13
|
+
from typing import Optional, Sequence
|
14
14
|
|
15
15
|
logging.basicConfig(level=logging.DEBUG)
|
16
16
|
|
@@ -76,6 +76,9 @@ class CSSCode(StabilizerCode):
|
|
76
76
|
self.x_logical_operator_basis = None
|
77
77
|
self.z_logical_operator_basis = None
|
78
78
|
|
79
|
+
self.x_code_distance = None
|
80
|
+
self.z_code_distance = None
|
81
|
+
|
79
82
|
# Check if the input matrices are NumPy arrays or SciPy sparse matrices
|
80
83
|
if not isinstance(x_stabilizer_matrix, (np.ndarray, scipy.sparse.spmatrix)):
|
81
84
|
raise TypeError(
|
@@ -182,7 +185,7 @@ class CSSCode(StabilizerCode):
|
|
182
185
|
|
183
186
|
# TODO: Add a function to save the logical operator basis to a file
|
184
187
|
|
185
|
-
def
|
188
|
+
def check_valid_logical_basis(self) -> bool:
|
186
189
|
"""
|
187
190
|
Validate that the stored logical operators form a proper logical basis for the code.
|
188
191
|
|
@@ -408,7 +411,7 @@ class CSSCode(StabilizerCode):
|
|
408
411
|
Returns
|
409
412
|
-------
|
410
413
|
int
|
411
|
-
Best estimate of code distance found within time limit.
|
414
|
+
Best estimate of code distance found within the time limit.
|
412
415
|
"""
|
413
416
|
start_time = time.time()
|
414
417
|
|
@@ -419,13 +422,13 @@ class CSSCode(StabilizerCode):
|
|
419
422
|
):
|
420
423
|
self.compute_logical_basis()
|
421
424
|
|
422
|
-
# Setup decoders for X and Z
|
423
|
-
|
425
|
+
# Setup decoders and parameters for both X and Z
|
426
|
+
bp_osd_z, x_stack, full_rank_x, x_min_distance, x_max_distance = (
|
424
427
|
self._setup_distance_estimation_decoder(
|
425
428
|
self.x_stabilizer_matrix, self.x_logical_operator_basis, decoder
|
426
429
|
)
|
427
430
|
)
|
428
|
-
|
431
|
+
bp_osd_x, z_stack, full_rank_z, z_min_distance, z_max_distance = (
|
429
432
|
self._setup_distance_estimation_decoder(
|
430
433
|
self.z_stabilizer_matrix, self.z_logical_operator_basis, decoder
|
431
434
|
)
|
@@ -434,57 +437,106 @@ class CSSCode(StabilizerCode):
|
|
434
437
|
candidate_logicals_x = []
|
435
438
|
candidate_logicals_z = []
|
436
439
|
|
437
|
-
|
440
|
+
x_weight_one_searched = 0
|
441
|
+
z_weight_one_searched = 0
|
442
|
+
|
438
443
|
with tqdm(total=timeout_seconds, desc="Estimating distance") as pbar:
|
439
444
|
while time.time() - start_time < timeout_seconds:
|
440
445
|
elapsed = time.time() - start_time
|
441
446
|
pbar.update(elapsed - pbar.n)
|
442
447
|
|
443
|
-
|
444
|
-
|
445
|
-
self.
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
448
|
+
if np.random.rand() < 0.5:
|
449
|
+
# X Logical operators
|
450
|
+
if x_weight_one_searched < self.z_logical_operator_basis.shape[0]:
|
451
|
+
dummy_syndrome_x = np.zeros(z_stack.shape[0], dtype=np.uint8)
|
452
|
+
dummy_syndrome_x[
|
453
|
+
full_rank_z.shape[0] + x_weight_one_searched
|
454
|
+
] = 1
|
455
|
+
x_weight_one_searched += 1
|
456
|
+
else:
|
457
|
+
dummy_syndrome_x = self._generate_random_logical_combination_for_distance_estimation(
|
458
|
+
z_stack, p, self.z_stabilizer_matrix.shape[0]
|
459
|
+
)
|
460
|
+
|
461
|
+
candidate_x = bp_osd_x.decode(dummy_syndrome_x)
|
462
|
+
x_weight = np.count_nonzero(candidate_x)
|
463
|
+
if x_weight < x_min_distance:
|
464
|
+
x_min_distance = x_weight
|
465
|
+
|
466
|
+
if x_weight < x_max_distance and reduce_logical_basis:
|
467
|
+
candidate_logicals_x.append(candidate_x)
|
468
|
+
|
469
|
+
# Reduce X logical operator basis independently
|
470
|
+
if len(candidate_logicals_x) >= 5:
|
471
|
+
self._reduce_logical_operator_basis(
|
472
|
+
candidate_logicals_x, []
|
473
|
+
)
|
474
|
+
(
|
475
|
+
bp_osd_x,
|
476
|
+
z_stack,
|
477
|
+
full_rank_z,
|
478
|
+
z_min_distance,
|
479
|
+
z_max_distance,
|
480
|
+
) = self._setup_distance_estimation_decoder(
|
481
|
+
self.z_stabilizer_matrix,
|
482
|
+
self.z_logical_operator_basis,
|
483
|
+
decoder,
|
484
|
+
)
|
485
|
+
candidate_logicals_x = []
|
486
|
+
x_weight_one_searched = 0
|
487
|
+
|
488
|
+
else:
|
489
|
+
# Z Logical operators
|
490
|
+
if z_weight_one_searched < self.x_logical_operator_basis.shape[0]:
|
491
|
+
dummy_syndrome_z = np.zeros(x_stack.shape[0], dtype=np.uint8)
|
492
|
+
dummy_syndrome_z[
|
493
|
+
full_rank_x.shape[0] + z_weight_one_searched
|
494
|
+
] = 1
|
495
|
+
z_weight_one_searched += 1
|
496
|
+
else:
|
497
|
+
dummy_syndrome_z = self._generate_random_logical_combination_for_distance_estimation(
|
498
|
+
x_stack, p, self.x_stabilizer_matrix.shape[0]
|
499
|
+
)
|
500
|
+
|
501
|
+
candidate_z = bp_osd_z.decode(dummy_syndrome_z)
|
502
|
+
z_weight = np.count_nonzero(candidate_z)
|
503
|
+
if z_weight < z_min_distance:
|
504
|
+
z_min_distance = z_weight
|
505
|
+
|
506
|
+
if z_weight < z_max_distance and reduce_logical_basis:
|
507
|
+
candidate_logicals_z.append(candidate_z)
|
508
|
+
|
509
|
+
# Reduce Z logical operator basis independently
|
510
|
+
if len(candidate_logicals_z) >= 5:
|
511
|
+
self._reduce_logical_operator_basis(
|
512
|
+
[], candidate_logicals_z
|
513
|
+
)
|
514
|
+
(
|
515
|
+
bp_osd_z,
|
516
|
+
x_stack,
|
517
|
+
full_rank_x,
|
518
|
+
x_min_distance,
|
519
|
+
x_max_distance,
|
520
|
+
) = self._setup_distance_estimation_decoder(
|
521
|
+
self.x_stabilizer_matrix,
|
522
|
+
self.x_logical_operator_basis,
|
523
|
+
decoder,
|
524
|
+
)
|
525
|
+
candidate_logicals_z = []
|
526
|
+
z_weight_one_searched = 0
|
527
|
+
|
528
|
+
x_weights, z_weights = self.logical_basis_weights()
|
474
529
|
pbar.set_description(
|
475
|
-
f"Estimating distance: dx <= {x_min_distance}, dz <= {z_min_distance}"
|
530
|
+
f"Estimating distance: dx <= {x_min_distance}, dz <= {z_min_distance}, x-weights: {np.mean(x_weights):.2f}, z-weights: {np.mean(z_weights):.2f}"
|
476
531
|
)
|
477
532
|
|
478
|
-
|
533
|
+
self._reduce_logical_operator_basis(candidate_logicals_x, candidate_logicals_z)
|
534
|
+
|
535
|
+
# Update distances
|
479
536
|
self.x_code_distance = x_min_distance
|
480
537
|
self.z_code_distance = z_min_distance
|
481
538
|
self.code_distance = min(x_min_distance, z_min_distance)
|
482
539
|
|
483
|
-
if reduce_logical_basis:
|
484
|
-
self._reduce_logical_operator_basis(
|
485
|
-
candidate_logicals_x, candidate_logicals_z
|
486
|
-
)
|
487
|
-
|
488
540
|
return self.code_distance
|
489
541
|
|
490
542
|
def _setup_distance_estimation_decoder(
|
@@ -569,28 +621,140 @@ class CSSCode(StabilizerCode):
|
|
569
621
|
|
570
622
|
return dummy_syndrome
|
571
623
|
|
624
|
+
def _reduce_logical_operator_basis(
|
625
|
+
self,
|
626
|
+
candidate_logicals_x: Union[Sequence, np.ndarray, scipy.sparse.spmatrix] = [],
|
627
|
+
candidate_logicals_z: Union[Sequence, np.ndarray, scipy.sparse.spmatrix] = [],
|
628
|
+
):
|
629
|
+
"""
|
630
|
+
Reduce the logical operator bases (for X and Z) to include lower-weight logicals.
|
631
|
+
|
632
|
+
Parameters
|
633
|
+
----------
|
634
|
+
candidate_logicals_x : Union[Sequence, np.ndarray, scipy.sparse.spmatrix], optional
|
635
|
+
A list or array of candidate X logical operators to consider for reducing the X basis.
|
636
|
+
Defaults to an empty list.
|
637
|
+
candidate_logicals_z : Union[Sequence, np.ndarray, scipy.sparse.spmatrix], optional
|
638
|
+
A list or array of candidate Z logical operators to consider for reducing the Z basis.
|
639
|
+
Defaults to an empty list.
|
640
|
+
"""
|
641
|
+
# Reduce X logical operator basis
|
642
|
+
if candidate_logicals_x:
|
643
|
+
# Convert candidates to a sparse matrix if they aren't already
|
644
|
+
if not isinstance(candidate_logicals_x, scipy.sparse.spmatrix):
|
645
|
+
candidate_logicals_x = scipy.sparse.csr_matrix(candidate_logicals_x)
|
646
|
+
|
647
|
+
# Stack the candidate X logicals with the existing X logicals
|
648
|
+
temp_x = scipy.sparse.vstack(
|
649
|
+
[candidate_logicals_x, self.x_logical_operator_basis]
|
650
|
+
).tocsr()
|
651
|
+
|
652
|
+
# Calculate Hamming weights for sorting
|
653
|
+
x_row_weights = temp_x.getnnz(axis=1)
|
654
|
+
sorted_x_rows = np.argsort(x_row_weights)
|
655
|
+
temp_x = temp_x[sorted_x_rows, :]
|
656
|
+
|
657
|
+
# Add the X stabilizer matrix to the top of the stack
|
658
|
+
temp_x = scipy.sparse.vstack([self.x_stabilizer_matrix, temp_x]).tocsr()
|
659
|
+
|
660
|
+
# Determine rank of the X stabilizer matrix
|
661
|
+
rank_hx = ldpc.mod2.rank(self.x_stabilizer_matrix)
|
662
|
+
|
663
|
+
# Perform row reduction to find a new X logical basis
|
664
|
+
pivots_x = ldpc.mod2.pivot_rows(temp_x)
|
665
|
+
self.x_logical_operator_basis = temp_x[pivots_x[rank_hx:], :]
|
666
|
+
|
667
|
+
# Reduce Z logical operator basis
|
668
|
+
if candidate_logicals_z:
|
669
|
+
# Convert candidates to a sparse matrix if they aren't already
|
670
|
+
if not isinstance(candidate_logicals_z, scipy.sparse.spmatrix):
|
671
|
+
candidate_logicals_z = scipy.sparse.csr_matrix(candidate_logicals_z)
|
672
|
+
|
673
|
+
# Stack the candidate Z logicals with the existing Z logicals
|
674
|
+
temp_z = scipy.sparse.vstack(
|
675
|
+
[candidate_logicals_z, self.z_logical_operator_basis]
|
676
|
+
).tocsr()
|
677
|
+
|
678
|
+
# Calculate Hamming weights for sorting
|
679
|
+
z_row_weights = temp_z.getnnz(axis=1)
|
680
|
+
sorted_z_rows = np.argsort(z_row_weights)
|
681
|
+
temp_z = temp_z[sorted_z_rows, :]
|
682
|
+
|
683
|
+
# Add the Z stabilizer matrix to the top of the stack
|
684
|
+
temp_z = scipy.sparse.vstack([self.z_stabilizer_matrix, temp_z]).tocsr()
|
685
|
+
|
686
|
+
# Determine rank of the Z stabilizer matrix
|
687
|
+
rank_hz = ldpc.mod2.rank(self.z_stabilizer_matrix)
|
688
|
+
|
689
|
+
# Perform row reduction to find a new Z logical basis
|
690
|
+
pivots_z = ldpc.mod2.pivot_rows(temp_z)
|
691
|
+
self.z_logical_operator_basis = temp_z[pivots_z[rank_hz:], :]
|
692
|
+
|
572
693
|
def fix_logical_operators(self, fix_logical: str = "X"):
|
694
|
+
"""
|
695
|
+
Create a canonical basis of logical operators where X-logical and Z-logical operators pairwise anticommute.
|
696
|
+
|
697
|
+
Parameters
|
698
|
+
----------
|
699
|
+
fix_logical : str, optional
|
700
|
+
Specify which logical operator basis to fix. "X" adjusts Z-logicals based on X-logicals, and "Z" adjusts
|
701
|
+
X-logicals based on Z-logicals. Default is "X".
|
702
|
+
|
703
|
+
Raises
|
704
|
+
------
|
705
|
+
TypeError
|
706
|
+
If `fix_logical` is not a string.
|
707
|
+
ValueError
|
708
|
+
If `fix_logical` is not "X" or "Z".
|
709
|
+
|
710
|
+
Returns
|
711
|
+
-------
|
712
|
+
bool
|
713
|
+
True if the logical operator basis is valid after fixing; False otherwise.
|
714
|
+
|
715
|
+
Notes
|
716
|
+
-----
|
717
|
+
This method ensures that the symplectic product of the logical bases results in the identity matrix.
|
718
|
+
If any issues occur during the adjustment, the method logs an error.
|
719
|
+
"""
|
573
720
|
if not isinstance(fix_logical, str):
|
574
721
|
raise TypeError("fix_logical parameter must be a string")
|
575
722
|
|
576
723
|
if fix_logical.lower() == "x":
|
577
724
|
temp = self.z_logical_operator_basis @ self.x_logical_operator_basis.T
|
578
725
|
temp.data = temp.data % 2
|
579
|
-
temp = ldpc.mod2.inverse(temp)
|
726
|
+
temp = scipy.sparse.csr_matrix(ldpc.mod2.inverse(temp), dtype=np.uint8)
|
580
727
|
self.z_logical_operator_basis = temp @ self.z_logical_operator_basis
|
581
728
|
self.z_logical_operator_basis.data = self.z_logical_operator_basis.data % 2
|
582
729
|
|
583
730
|
elif fix_logical.lower() == "z":
|
584
731
|
temp = self.x_logical_operator_basis @ self.z_logical_operator_basis.T
|
585
732
|
temp.data = temp.data % 2
|
586
|
-
temp = ldpc.mod2.inverse(temp)
|
733
|
+
temp = scipy.sparse.csr_matrix(ldpc.mod2.inverse(temp), dtype=np.uint8)
|
587
734
|
self.x_logical_operator_basis = temp @ self.x_logical_operator_basis
|
588
735
|
self.x_logical_operator_basis.data = self.x_logical_operator_basis.data % 2
|
589
736
|
else:
|
590
737
|
raise ValueError("Invalid fix_logical parameter")
|
591
738
|
|
592
|
-
|
593
|
-
|
739
|
+
try:
|
740
|
+
assert self.check_valid_logical_basis()
|
741
|
+
except AssertionError:
|
742
|
+
logging.error("Logical basis is not valid after fixing logical operators.")
|
743
|
+
return False
|
744
|
+
|
745
|
+
try:
|
746
|
+
lx_lz = self.x_logical_operator_basis @ self.z_logical_operator_basis.T
|
747
|
+
lx_lz.data = lx_lz.data % 2
|
748
|
+
assert (
|
749
|
+
lx_lz != scipy.sparse.eye(self.logical_qubit_count, format="csr")
|
750
|
+
).nnz == 0
|
751
|
+
except AssertionError:
|
752
|
+
logging.error("Logical basis is not valid after fixing logical operators.")
|
753
|
+
return False
|
754
|
+
|
755
|
+
return True
|
756
|
+
|
757
|
+
def logical_basis_weights(self) -> Tuple[np.ndarray, np.ndarray]:
|
594
758
|
x_weights = []
|
595
759
|
z_weights = []
|
596
760
|
for i in range(self.logical_qubit_count):
|
@@ -0,0 +1,264 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import scipy
|
3
|
+
from typing import Union, Tuple
|
4
|
+
import ldpc.mod2
|
5
|
+
import time
|
6
|
+
|
7
|
+
from qec.code_constructions import CSSCode
|
8
|
+
from qec.utils.sparse_binary_utils import convert_to_binary_scipy_sparse
|
9
|
+
|
10
|
+
class HypergraphProductCode(CSSCode):
|
11
|
+
"""
|
12
|
+
Implements a Hypergraph Product (HGP) code - derived from two classical linear binary codes.
|
13
|
+
|
14
|
+
Parameters
|
15
|
+
----------
|
16
|
+
seed_matrix_1 :
|
17
|
+
A classical linear binary code used as a "seed" in the HGP construction method.
|
18
|
+
seed_matrix_2 :
|
19
|
+
A classical linear binary code used as a "seed" in the HGP construction method.
|
20
|
+
name : str, default = None
|
21
|
+
The name of the code. If None, the name is set to: "Hypergraph product code"
|
22
|
+
|
23
|
+
Attributes
|
24
|
+
----------
|
25
|
+
seed_matrix_1 : scipy.sparse.spmatrix
|
26
|
+
The input seed_matrix_1 stored as a scipy sparse matrix.
|
27
|
+
seed_matrix_2 : scipy.sparse.spmatrix
|
28
|
+
The input seed_matrix_2 stored as a scipy sparse matrix.
|
29
|
+
_n1 : int
|
30
|
+
Number of columns in seed_matrix_1
|
31
|
+
_n2 : int
|
32
|
+
Number of columns in seed_matrix_2
|
33
|
+
_m1 : int
|
34
|
+
Number of rows in seed_matrix_1 (the number of columns of it's transpose)
|
35
|
+
_m2 : int
|
36
|
+
Number of rows in seed_matrix_2 (the number of columns of it's transpose)
|
37
|
+
|
38
|
+
Notes
|
39
|
+
-----
|
40
|
+
|
41
|
+
The X and Z stabilizer matrices are given by [1]_:
|
42
|
+
|
43
|
+
.. math::
|
44
|
+
|
45
|
+
\begin{align}
|
46
|
+
H_{X} &= \begin{pmatrix}
|
47
|
+
H_{1}\otimes I_{n_{2}} & \,\,I_{r_{1}}\otimes H_{2}^{T}
|
48
|
+
\end{pmatrix}\tag*{(1)}\\
|
49
|
+
H_{Z} &= \begin{pmatrix}
|
50
|
+
I_{n_{1}}\otimes H_{2} & \,\,H_{1}^{T}\otimes I_{r_{2}}
|
51
|
+
\end{pmatrix}~, \tag*{(2)}
|
52
|
+
\end{align}
|
53
|
+
|
54
|
+
where :math:`H_1` and :math:`H_2` correspond to the parity check matrix of the first and second "seed" codes.
|
55
|
+
|
56
|
+
|
57
|
+
.. [1] J.-P. Tillich and G. Zemor, “Quantum LDPC Codes With Positive Rate and Minimum Distance Proportional to the Square Root of the Blocklength”, IEEE Transactions on Information Theory 60, 1193 (2014)
|
58
|
+
"""
|
59
|
+
|
60
|
+
def __init__(
|
61
|
+
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
|
65
|
+
):
|
66
|
+
|
67
|
+
self.name = name if name else "Hypergraph product code"
|
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.")
|
71
|
+
|
72
|
+
self.seed_matrix_1 = convert_to_binary_scipy_sparse(seed_matrix_1)
|
73
|
+
self.seed_matrix_2 = convert_to_binary_scipy_sparse(seed_matrix_2)
|
74
|
+
|
75
|
+
# maybe move the below to a private _construct_stabilizer_matrices function?
|
76
|
+
# --------------------------------------------------------------------------
|
77
|
+
self._n1 = seed_matrix_1.shape[1]
|
78
|
+
self._n2 = seed_matrix_2.shape[1]
|
79
|
+
|
80
|
+
self._m1 = seed_matrix_1.shape[0]
|
81
|
+
self._m2 = seed_matrix_2.shape[0]
|
82
|
+
|
83
|
+
x_left = scipy.sparse.kron(seed_matrix_1, scipy.sparse.eye(self._n2))
|
84
|
+
x_right = scipy.sparse.kron(scipy.sparse.eye(self._m1), seed_matrix_2.T)
|
85
|
+
self.x_stabilizer_matrix = scipy.sparse.hstack([x_left, x_right])
|
86
|
+
|
87
|
+
z_left = scipy.sparse.kron(scipy.sparse.eye(self._n1), seed_matrix_2)
|
88
|
+
z_right = scipy.sparse.kron(seed_matrix_1.T, scipy.sparse.eye(self._m2))
|
89
|
+
self.z_stabilizer_matrix = scipy.sparse.hstack([z_left, z_right])
|
90
|
+
# --------------------------------------------------------------------------
|
91
|
+
|
92
|
+
super().__init__(self.x_stabilizer_matrix, self.z_stabilizer_matrix, self.name)
|
93
|
+
|
94
|
+
|
95
|
+
def compute_exact_code_distance(self) -> int:
|
96
|
+
"""
|
97
|
+
Computes the exact code distance of the HGP code.
|
98
|
+
|
99
|
+
Returns
|
100
|
+
-------
|
101
|
+
int
|
102
|
+
The distance of the code.
|
103
|
+
|
104
|
+
Notes
|
105
|
+
-----
|
106
|
+
The distance of a HGP code is given as:
|
107
|
+
|
108
|
+
.. math::
|
109
|
+
|
110
|
+
\min(d_1, d_2, d_1^T, d_2^T)
|
111
|
+
|
112
|
+
corresponding to the distance of the seed codes and the distance of their transposes.
|
113
|
+
"""
|
114
|
+
|
115
|
+
rank_seed_m1 = ldpc.mod2.rank(self.seed_matrix_1)
|
116
|
+
rank_seed_m2 = ldpc.mod2.rank(self.seed_matrix_2)
|
117
|
+
|
118
|
+
if self.seed_matrix_1.shape[1] != rank_seed_m1:
|
119
|
+
self.d1 = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_1)
|
120
|
+
else:
|
121
|
+
self.d1 = np.inf
|
122
|
+
|
123
|
+
if self.seed_matrix_2.shape[1] != rank_seed_m2:
|
124
|
+
self.d2 = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_2)
|
125
|
+
else:
|
126
|
+
self.d2 = np.inf
|
127
|
+
|
128
|
+
# note: rank(A) = rank(A^T):
|
129
|
+
if self.seed_matrix_1.shape[0] != rank_seed_m1:
|
130
|
+
self.d1T = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_1.T)
|
131
|
+
else:
|
132
|
+
self.d1T = np.inf
|
133
|
+
|
134
|
+
if self.seed_matrix_2.shape[0] != rank_seed_m2:
|
135
|
+
self.d2T = ldpc.mod2.compute_exact_code_distance(self.seed_matrix_2.T)
|
136
|
+
else:
|
137
|
+
self.d2T = np.inf
|
138
|
+
|
139
|
+
self.x_code_distance = min(self.d1T, self.d2)
|
140
|
+
self.z_code_distance = min(self.d1, self.d2T)
|
141
|
+
self.code_distance = min(self.x_code_distance, self.z_code_distance)
|
142
|
+
|
143
|
+
return self.code_distance
|
144
|
+
|
145
|
+
|
146
|
+
def estimate_min_distance(self, timeout_seconds: float = 0.025) -> int:
|
147
|
+
"""
|
148
|
+
Estimate the minimum X and Z distance of the HGP code. Parameters
|
149
|
+
----------
|
150
|
+
timeout_seconds : float, optional
|
151
|
+
Time limit in seconds for the full search. Default: 0.25
|
152
|
+
|
153
|
+
Returns
|
154
|
+
-------
|
155
|
+
int
|
156
|
+
Best estimate of the (overall) code distance found within time limit.
|
157
|
+
|
158
|
+
"""
|
159
|
+
|
160
|
+
rank_seed_m1 = ldpc.mod2.rank(self.seed_matrix_1)
|
161
|
+
rank_seed_m2 = ldpc.mod2.rank(self.seed_matrix_2)
|
162
|
+
|
163
|
+
|
164
|
+
d1_timeout_seconds = timeout_seconds/4
|
165
|
+
if self.seed_matrix_1.shape[1] != rank_seed_m1:
|
166
|
+
d1_start_time = time.time()
|
167
|
+
d1_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_1, d1_timeout_seconds, 0)
|
168
|
+
d1_run_time = time.time() - d1_start_time
|
169
|
+
else:
|
170
|
+
d1_min_estimate = np.inf
|
171
|
+
d1_run_time = 0
|
172
|
+
|
173
|
+
d1T_timeout_seconds = (d1_timeout_seconds * 4 - d1_run_time)/3 if d1_run_time <= d1_timeout_seconds else timeout_seconds/4
|
174
|
+
if self.seed_matrix_1.shape[0] != rank_seed_m1:
|
175
|
+
d1T_start_time = time.time()
|
176
|
+
d1T_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_1.T, d1T_timeout_seconds, 0)
|
177
|
+
d1T_run_time = time.time() - d1T_start_time
|
178
|
+
else:
|
179
|
+
d1T_min_estimate = np.inf
|
180
|
+
d1T_run_time = 0
|
181
|
+
|
182
|
+
d2_timeout_seconds = (d1T_timeout_seconds * 3 - d1T_run_time)/2 if d1T_run_time <= d1T_timeout_seconds else timeout_seconds/4
|
183
|
+
if self.seed_matrix_2.shape[1] != rank_seed_m2:
|
184
|
+
d2_start_time = time.time()
|
185
|
+
d2_min_estimate, _, _ = ldpc.mod2.estimate_code_distance(self.seed_matrix_2, d2_timeout_seconds, 0)
|
186
|
+
d2_run_time = time.time() - d2_start_time
|
187
|
+
else:
|
188
|
+
d2_min_estimate = np.inf
|
189
|
+
d2_run_time = 0
|
190
|
+
|
191
|
+
|
192
|
+
d2T_timeout_seconds = (d2_timeout_seconds * 2 - d2_run_time) if d2_run_time <= d2_timeout_seconds else timeout_seconds/4
|
193
|
+
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)
|
195
|
+
else:
|
196
|
+
d2T_min_estimate = np.inf
|
197
|
+
|
198
|
+
self.x_code_distance = min(d1T_min_estimate, d2_min_estimate)
|
199
|
+
self.z_code_distance = min(d1_min_estimate, d2T_min_estimate)
|
200
|
+
self.code_distance = min(self.x_code_distance, self.z_code_distance)
|
201
|
+
|
202
|
+
|
203
|
+
return self.code_distance
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
def compute_logical_basis(self) -> Tuple[scipy.sparse.spmatrix, scipy.sparse.spmatrix]:
|
208
|
+
"""
|
209
|
+
Compute the logical operator basis for the given HGP code.
|
210
|
+
|
211
|
+
Returns
|
212
|
+
-------
|
213
|
+
Tuple[scipy.sparse.spmatrix, scipy.sparse.spmatrix]
|
214
|
+
Logical X and Z operator bases (lx, lz).
|
215
|
+
"""
|
216
|
+
|
217
|
+
ker_h1 = ldpc.mod2.kernel(self.seed_matrix_1)
|
218
|
+
ker_h2 = ldpc.mod2.kernel(self.seed_matrix_2)
|
219
|
+
ker_h1T = ldpc.mod2.kernel(self.seed_matrix_1.T)
|
220
|
+
ker_h2T = ldpc.mod2.kernel(self.seed_matrix_2.T)
|
221
|
+
|
222
|
+
row_comp_h1 = ldpc.mod2.row_complement_basis(self.seed_matrix_1)
|
223
|
+
row_comp_h2 = ldpc.mod2.row_complement_basis(self.seed_matrix_2)
|
224
|
+
row_comp_h1T = ldpc.mod2.row_complement_basis(self.seed_matrix_1.T)
|
225
|
+
row_comp_h2T = ldpc.mod2.row_complement_basis(self.seed_matrix_2.T)
|
226
|
+
|
227
|
+
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)])
|
229
|
+
|
230
|
+
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])
|
232
|
+
|
233
|
+
self.z_logical_operator_basis = scipy.sparse.vstack([lz1, lz2], dtype=np.uint8)
|
234
|
+
|
235
|
+
|
236
|
+
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)])
|
238
|
+
|
239
|
+
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
|
+
#----------------------------------------------------------------
|
246
|
+
self.logical_qubit_count = self.x_logical_operator_basis.shape[0]
|
247
|
+
#----------------------------------------------------------------
|
248
|
+
|
249
|
+
return (self.x_logical_operator_basis, self.z_logical_operator_basis)
|
250
|
+
|
251
|
+
|
252
|
+
def __str__(self):
|
253
|
+
"""
|
254
|
+
String representation of the HGP code. Includes the name and [[n, k, d]] properties of the code.
|
255
|
+
|
256
|
+
Returns
|
257
|
+
-------
|
258
|
+
str
|
259
|
+
String representation of the HGP code.
|
260
|
+
"""
|
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
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
from .five_qubit_code import FiveQubitCode
|
@@ -0,0 +1 @@
|
|
1
|
+
from .codetables_de import CodeTablesDE
|
@@ -0,0 +1,146 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: qec
|
3
|
+
Version: 0.2.2
|
4
|
+
Summary: Python Tools for Quantum Error Correction
|
5
|
+
Author-email: Joschka Roffe <joschka@roffe.eu>
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2023 qec.Codes
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
|
28
|
+
Classifier: Development Status :: 4 - Beta
|
29
|
+
Requires-Python: >=3.8
|
30
|
+
Description-Content-Type: text/markdown
|
31
|
+
License-File: LICENSE
|
32
|
+
Requires-Dist: ldpc
|
33
|
+
Requires-Dist: numpy>=1.24.0
|
34
|
+
Requires-Dist: scipy>=1.9.3
|
35
|
+
Requires-Dist: requests
|
36
|
+
Requires-Dist: beautifulsoup4
|
37
|
+
|
38
|
+
<h1>
|
39
|
+
<p align="center">
|
40
|
+
<br>QEC
|
41
|
+
</h1>
|
42
|
+
<p align="center">
|
43
|
+
Python Tools for Quantum Error Correction
|
44
|
+
<br />
|
45
|
+
<a href="https://qec.codes/">Website</a>
|
46
|
+
·
|
47
|
+
<a href="#features">Features</a>
|
48
|
+
·
|
49
|
+
<a href="#installation">Installation</a>
|
50
|
+
·
|
51
|
+
<a href="#examples">Examples</a>
|
52
|
+
</p>
|
53
|
+
</p>
|
54
|
+
|
55
|
+
# Features
|
56
|
+
|
57
|
+
## Code constructions and fundamental analysis
|
58
|
+
We currently provide the construction methods for the stabilizer generators of the QEC code families below, along with optimized methods to obtain their fundamental properties. All the classes allow to:
|
59
|
+
|
60
|
+
- obtain the physical qubit count
|
61
|
+
- obtain the logical qubit count
|
62
|
+
- calculate the exact code distance
|
63
|
+
- estimate the minimum code distance
|
64
|
+
- obtain a logical basis
|
65
|
+
|
66
|
+
The classes (along with their extre methods) are:
|
67
|
+
|
68
|
+
- Hyperprgarph Product (HGP) codes, with methods:
|
69
|
+
- construct the x and z stabiliser matrices from the seed codes
|
70
|
+
- obtain the canonical basis (work in progress)
|
71
|
+
|
72
|
+
- Calderbank-Shor-Steane (CSS) codes
|
73
|
+
- check that the seed codes satisfy the CSS criteria
|
74
|
+
|
75
|
+
- Stabiliser codes
|
76
|
+
- check that the input stabiliser matrix is valid
|
77
|
+
|
78
|
+
## Circuit compilation
|
79
|
+
Work in progress.
|
80
|
+
|
81
|
+
# Installation
|
82
|
+
|
83
|
+
Simply do:
|
84
|
+
```bash
|
85
|
+
pip install qec
|
86
|
+
```
|
87
|
+
|
88
|
+
or obtain a local copy of the package by cloning it, then navigate into the created folder:
|
89
|
+
|
90
|
+
```bash
|
91
|
+
git clone git@github.com:qec-codes/qec.git
|
92
|
+
cd qec
|
93
|
+
```
|
94
|
+
|
95
|
+
Finally, install the package:
|
96
|
+
|
97
|
+
```bash
|
98
|
+
pip install -e .
|
99
|
+
```
|
100
|
+
|
101
|
+
You are all set! To import the package use:
|
102
|
+
|
103
|
+
```python
|
104
|
+
In [1]: import qec
|
105
|
+
|
106
|
+
In [2]: qec.__version__
|
107
|
+
Out [2]: '0.1.0'
|
108
|
+
|
109
|
+
```
|
110
|
+
|
111
|
+
# Examples
|
112
|
+
|
113
|
+
In this example we are going to create the Steane code, and obtain its fundamental code properties. We start by initialising its seed matrices (the [7, 4, 3] Hamming code):
|
114
|
+
```python
|
115
|
+
In [1]: import numpy as np
|
116
|
+
In [2]: from qec.code_constructions import CSSCode
|
117
|
+
|
118
|
+
In [3]: hamming_code = np.array([[1, 0, 0, 1, 0, 1, 1],
|
119
|
+
[0, 1, 0, 1, 1, 0, 1],
|
120
|
+
[0, 0, 1, 0, 1, 1, 1]])
|
121
|
+
```
|
122
|
+
as the Steane code is part of the CSS code family, we can use the `CSSCode` class:
|
123
|
+
|
124
|
+
```python
|
125
|
+
In [4]: steane_code = CSSCode(x_stabilizer_matrix = hamming_code,
|
126
|
+
z_stabilizer_matrix = hamming_code,
|
127
|
+
name = "Steane")
|
128
|
+
In [5]: print(steane_code)
|
129
|
+
Out [6]: Steane Code: [[N=7, K=1, dx<=3, dz<=3]]
|
130
|
+
```
|
131
|
+
|
132
|
+
we can see that all the fundamental properties (N - physical qubit number, K - logical qubit number, dx - X distance, dz - Z distance) are pre-calculated for us. We can continue our analysis by taking a look at the x and z logical basis of the code:
|
133
|
+
|
134
|
+
```python
|
135
|
+
In [7]: print(steane_code.x_logical_operator_basis.toarray())
|
136
|
+
Out [8]: [[1 1 0 1 0 0 0]]
|
137
|
+
In [9]: print(steane_code.z_logical_operator_basis.toarray())
|
138
|
+
Out [10]: [[1 1 0 1 0 0 0]]
|
139
|
+
```
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
qec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
qec/code_constructions/__init__.py,sha256=MWyNUCS5mYcDzjGr_nbr2-ifkJigRJIzsw7sQIQXDfM,119
|
3
|
+
qec/code_constructions/css_code.py,sha256=nIaC24QhQwrmWQNhmX-X4TzlkmNAYoxN0feTdWjhswo,32376
|
4
|
+
qec/code_constructions/hgp_code.py,sha256=VAKU2lfZnDXSmAk6xFZCYT5b0hbtXpEoQUw4qHFcaEk,10419
|
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.2.dist-info/LICENSE,sha256=1b_xwNz1znYBfEaCL6pN2gNBAn8pQIjDRs_UhDp1EJI,1066
|
15
|
+
qec-0.2.2.dist-info/METADATA,sha256=Soh5GrdXcP861-epLVwGnKlk7tVrrtVVc1xKFTowbhA,4509
|
16
|
+
qec-0.2.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
17
|
+
qec-0.2.2.dist-info/top_level.txt,sha256=d8l_7pJ5u9uWdviNp0FUK-j8VPZqywkDek7qa4NDank,4
|
18
|
+
qec-0.2.2.dist-info/RECORD,,
|
qec/quantum_codes/__init__.py
DELETED
qec/stabilizer_code/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
from qec.stabilizer_code.stabilizer_code import StabilizerCode
|
qec-0.2.1.dist-info/METADATA
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.2
|
2
|
-
Name: qec
|
3
|
-
Version: 0.2.1
|
4
|
-
Summary: Python Tools for Quantum Error Correction
|
5
|
-
Author-email: Joschka Roffe <joschka@roffe.eu>
|
6
|
-
License: MIT License
|
7
|
-
|
8
|
-
Copyright (c) 2023 qec.Codes
|
9
|
-
|
10
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
-
of this software and associated documentation files (the "Software"), to deal
|
12
|
-
in the Software without restriction, including without limitation the rights
|
13
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
-
copies of the Software, and to permit persons to whom the Software is
|
15
|
-
furnished to do so, subject to the following conditions:
|
16
|
-
|
17
|
-
The above copyright notice and this permission notice shall be included in all
|
18
|
-
copies or substantial portions of the Software.
|
19
|
-
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
-
SOFTWARE.
|
27
|
-
|
28
|
-
Classifier: Development Status :: 4 - Beta
|
29
|
-
Requires-Python: >=3.8
|
30
|
-
Description-Content-Type: text/markdown
|
31
|
-
License-File: LICENSE
|
32
|
-
Requires-Dist: ldpc
|
33
|
-
Requires-Dist: numpy>=1.24.0
|
34
|
-
Requires-Dist: scipy>=1.9.3
|
35
|
-
Requires-Dist: requests
|
36
|
-
Requires-Dist: beautifulsoup4
|
37
|
-
|
38
|
-
<h1 align="center">QEC </h1>
|
39
|
-
<h3 align="center"> Python Tools for Quantum Error Correction </h3>
|
40
|
-
|
41
|
-
|
42
|
-
- Website: https://qec.codes/
|
43
|
-
|
44
|
-
# Table of contents
|
45
|
-
1. [Features](#features)
|
46
|
-
2. [Installation](#installation)
|
47
|
-
3. [Getting started](#getting-started)
|
48
|
-
|
49
|
-
|
50
|
-
# Features
|
51
|
-
|
52
|
-
Here will go the description of all our fancy features!
|
53
|
-
|
54
|
-
# Installation
|
55
|
-
|
56
|
-
Obtain a local copy of the package by cloning it, then navigate into the created folder:
|
57
|
-
|
58
|
-
```bash
|
59
|
-
git clone git@github.com:qec-codes/qec.git
|
60
|
-
cd qec
|
61
|
-
```
|
62
|
-
|
63
|
-
Finally, install the package:
|
64
|
-
|
65
|
-
```bash
|
66
|
-
pip install -e .
|
67
|
-
```
|
68
|
-
|
69
|
-
You are all set! To import the package use:
|
70
|
-
|
71
|
-
```python
|
72
|
-
In [1]: import qec
|
73
|
-
|
74
|
-
In [2]: qec.__version__
|
75
|
-
Out [2]: '0.1.0'
|
76
|
-
|
77
|
-
```
|
78
|
-
|
79
|
-
# Getting started
|
80
|
-
|
81
|
-
A few simple examples
|
82
|
-
|
qec-0.2.1.dist-info/RECORD
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
qec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
qec/quantum_codes/__init__.py,sha256=DQ1ztrq-vBpTyoehaMWOhals46tRj553Jmkq68bDk-E,117
|
3
|
-
qec/quantum_codes/codetables_de.py,sha256=loBDBOK2cbDJ5moKmIx2MXg6e30XEPrEYau19bbDgac,3623
|
4
|
-
qec/quantum_codes/five_qubit_code.py,sha256=0zrGLyIpfyKwYG7uL00yMcM5PdhQGF17_MiI2qTMhOk,2190
|
5
|
-
qec/stabilizer_code/__init__.py,sha256=L5UMjHBlvfQBhkNlEZYSkyaHvNOcDHjc3oxYibMYHRk,63
|
6
|
-
qec/stabilizer_code/css_code.py,sha256=JhNiBHqfwu4OgMVUsXl6yJ4L5KNW4Dn2Sf0beBdAl2s,24763
|
7
|
-
qec/stabilizer_code/stabilizer_code.py,sha256=I5u8JKZu88ioC4E2nBJ-00xCmnL8nU6kdAvwYOfmNRk,22138
|
8
|
-
qec/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
qec/utils/binary_pauli_utils.py,sha256=BSlngYDdRICu0aVu4u_m0bvLicohORyGxfk5eRER7TQ,13245
|
10
|
-
qec/utils/codetables_de_utils.py,sha256=S1wcVGJkkASQQ5s71QAsYBmpyE-3xTb6UsvgMfQtuiw,9469
|
11
|
-
qec/utils/sparse_binary_utils.py,sha256=Y9xfGKzOGFiVTyhb6iF6N7-5oMY6Ah9oLrnv8HhSBHA,1965
|
12
|
-
qec-0.2.1.dist-info/LICENSE,sha256=1b_xwNz1znYBfEaCL6pN2gNBAn8pQIjDRs_UhDp1EJI,1066
|
13
|
-
qec-0.2.1.dist-info/METADATA,sha256=AbWaMM6fYb65-0lUw6qWuywZigdtHseO-6QAbNZK0QM,2367
|
14
|
-
qec-0.2.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
15
|
-
qec-0.2.1.dist-info/top_level.txt,sha256=d8l_7pJ5u9uWdviNp0FUK-j8VPZqywkDek7qa4NDank,4
|
16
|
-
qec-0.2.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|