From 500dbdf366d133d202e1999f766eb0c76b79339e Mon Sep 17 00:00:00 2001 From: SeanvdMeer <18538762+minisean@users.noreply.github.com> Date: Fri, 6 Dec 2024 16:17:51 +0100 Subject: [PATCH 1/3] Fixes bug with odd-weight parity computations. Added corresponding test-case --- .../intrf_error_identifier.py | 2 +- .../test_error_identifier.py | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/qce_interp/interface_definitions/intrf_error_identifier.py b/src/qce_interp/interface_definitions/intrf_error_identifier.py index 8e7e906..50b3982 100644 --- a/src/qce_interp/interface_definitions/intrf_error_identifier.py +++ b/src/qce_interp/interface_definitions/intrf_error_identifier.py @@ -934,7 +934,7 @@ def calculate_computational_parity(array: np.ndarray, parity_index_lookup: Dict[ subarray = array[:, indices] # Calculate the parity: +1 if even number of 0's, -1 if odd number of 0's - parity = np.sum(subarray == 0, axis=1) % 2 # This gives 0 for even, 1 for odd + parity = np.sum(subarray, axis=1) % 2 # This gives 0 for even, 1 for odd result[:, i] = np.where(parity == 0, 1, -1) # Map 0 to +1 and 1 to -1 return result diff --git a/tests/interface_definitions/test_error_identifier.py b/tests/interface_definitions/test_error_identifier.py index 631c611..a63bf5d 100644 --- a/tests/interface_definitions/test_error_identifier.py +++ b/tests/interface_definitions/test_error_identifier.py @@ -807,6 +807,43 @@ def test_single_weight_four_computed_parties(self): defect_array, np.asarray([[[1], [1], [1], [1], [1], [1]]]) ) + + def test_odd_data_computed_parity(self): + """Tests computed parity when there are an odd number of data-qubits per ancilla qubit.""" + computed_parity: np.ndarray = ErrorDetectionIdentifier.calculate_computational_parity( + array=np.asarray([ + [0, 0, 0], + [0, 0, 1], + [0, 1, 1], + [1, 1, 1], + ]), + parity_index_lookup={ + QubitIDObj('X1'): np.asarray([0]), + QubitIDObj('X2'): np.asarray([0, 1]), + QubitIDObj('X3'): np.asarray([1, 2]), + QubitIDObj('X4'): np.asarray([2]), + }, + involved_ancilla_qubit_ids=[ + QubitIDObj('X1'), + QubitIDObj('X2'), + QubitIDObj('X3'), + QubitIDObj('X4'), + ] + ) + + expected_computed_parity = np.asarray([ + [+1, +1, +1, +1], + [+1, +1, -1, -1], + [+1, -1, +1, -1], + [-1, +1, +1, -1], + ]) + + assert_array_equal( + computed_parity, + expected_computed_parity, + err_msg=f"Expects single-qubit parity to be equal to the state-parity. 0 -> +1, 1 -> -1." + ) + # endregion # region Teardown From 9a5c28a89ef8ebb6bdcabe578e535f05d392bc4e Mon Sep 17 00:00:00 2001 From: SeanvdMeer <18538762+minisean@users.noreply.github.com> Date: Tue, 10 Dec 2024 17:08:11 +0100 Subject: [PATCH 2/3] Updated removed limitation for continues qec-rounds --- src/qce_interp/decoder_examples/mwpm_decoders.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/qce_interp/decoder_examples/mwpm_decoders.py b/src/qce_interp/decoder_examples/mwpm_decoders.py index 9fce3d9..c7bcb38 100644 --- a/src/qce_interp/decoder_examples/mwpm_decoders.py +++ b/src/qce_interp/decoder_examples/mwpm_decoders.py @@ -382,8 +382,6 @@ def __init__( self.all_defects.append(defects) self.all_data_qubit_outcomes.append(data_qubit_outcomes) - assert not (len(self.all_data_qubit_outcomes) != (self.qec_rounds[-1] + 1)), "Only support step size = 1 starting at 0 round!" - self.distance = len(self.all_data_qubit_outcomes[0][0]) # args for decoder self.H = csc_matrix(create_diagonal_matrix_corrected(self.distance).tolist()) @@ -407,7 +405,7 @@ def get_fidelity(self, cycle_stabilizer_count: int, target_state: np.ndarray = N """ # by default step size = 1, starting from 0. if qec_round_idx is None: - qec_round_idx = cycle_stabilizer_count + qec_round_idx = list(self.qec_rounds).index(cycle_stabilizer_count) num_shots = len(self.all_defects[qec_round_idx]) if (max_shots is not None) and (num_shots > max_shots): num_shots = max_shots From 122b42a8d9a7d400b573b0eaece781267b179cec Mon Sep 17 00:00:00 2001 From: SeanvdMeer <18538762+minisean@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:12:51 +0100 Subject: [PATCH 3/3] Refactored AssignmentFidelityMatrix to AssignmentProbabilityMatrix naming --- .../intrf_state_classification.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/qce_interp/interface_definitions/intrf_state_classification.py b/src/qce_interp/interface_definitions/intrf_state_classification.py index 6c35258..f7025ae 100644 --- a/src/qce_interp/interface_definitions/intrf_state_classification.py +++ b/src/qce_interp/interface_definitions/intrf_state_classification.py @@ -454,30 +454,30 @@ def get_threshold_estimate(shots_0: NDArray[np.complex128], shots_1: NDArray[np. @dataclass(frozen=True) -class AssignmentFidelityMatrix: - """Data class, containing assignment fidelity matrix and array-like of state-key.""" +class AssignmentProbabilityMatrix: + """Data class, containing assignment probability matrix and array-like of state-key.""" state_keys: List[StateKey] matrix: NDArray[np.float64] # region Class Methods @classmethod - def from_acquisition_container(cls, acquisition_container: IStateAcquisitionContainer) -> 'AssignmentFidelityMatrix': + def from_acquisition_container(cls, acquisition_container: IStateAcquisitionContainer) -> 'AssignmentProbabilityMatrix': """:return: Class method constructor based on decision boundaries.""" # Data allocation decision_boundaries: DecisionBoundaries = acquisition_container.classification_boundaries states: List[StateKey] = list(acquisition_container.contained_states) - fidelity_matrix: np.ndarray = np.zeros(shape=(len(states), len(states))) + probability_matrix: np.ndarray = np.zeros(shape=(len(states), len(states))) for i, _state_key in enumerate(states): state_acquisition = acquisition_container.get_state_acquisition(state=_state_key) for j, state in enumerate(states): - fidelity_matrix[i][j] = decision_boundaries.get_fidelity( + probability_matrix[i][j] = decision_boundaries.get_fidelity( shots=state_acquisition.shots, assigned_state=state, ) - return AssignmentFidelityMatrix( + return AssignmentProbabilityMatrix( state_keys=states, - matrix=fidelity_matrix, + matrix=probability_matrix, ) # endregion