From c3ffd19c2dfaefef3cff312c0e1b00745629b9b7 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 16:16:01 -0700 Subject: [PATCH 01/20] Add a summary of QEC algorithms class --- ...quantum_error_correction_scheme_summary.py | 105 ++++++++++++++++++ ...um_error_correction_scheme_summary_test.py | 84 ++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 qualtran/surface_code/quantum_error_correction_scheme_summary.py create mode 100644 qualtran/surface_code/quantum_error_correction_scheme_summary_test.py diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py new file mode 100644 index 000000000..e7c3bca12 --- /dev/null +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -0,0 +1,105 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import abc +import enum + +import numpy as np +from attrs import field, frozen + +from qualtran.surface_code.physical_parameters import PhysicalParameters + + +@frozen +class QuantumErrorCorrectionSchemeSummary(abc.ABC): + """QuantumErrorCorrectionSchemeSummary represents a high level view of a QEC scheme. + + QuantumErrorCorrectionSchemeSummary provides estimates for the logical error rate, + number of physical qubits and the logical time step given a code distance and + physical assumptions. + + Attributes: + error_rate_scaler: Logical error rate coefficient. + error_rate_threshold: Logical error rate threshold. + reference: source of the estimates. + """ + + error_rate_scaler: float = field(default=0.1, repr=lambda x: f'{x:g}') + error_rate_threshold: float = field(default=0.01, repr=lambda x: f'{x:g}') + reference: str | None = None + + def logical_error_rate( + self, code_distance: int | np.ndarray, physical_error_rate: float | np.ndarray + ) -> float | np.ndarray: + """The logical error rate for the given code distance using this scheme.""" + return self.error_rate_scaler * np.power( + physical_error_rate / self.error_rate_threshold, (code_distance + 1) / 2 + ) + + @abc.abstractmethod + def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: + """The number of physical qubits for the given code distance using this scheme.""" + + @abc.abstractmethod + def logical_time_step( + self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters + ) -> float | np.ndarray: + """The duration of a logical time step for the given code distance using this scheme.""" + + +class GateBasedSurfaceCodeSource(enum.Enum): + arXiv12080928 = 0 # Folwer Model. + arXiv221107629 = 1 # Azure Model. + + +@frozen +class GateBasedSurfaceCode(QuantumErrorCorrectionSchemeSummary): + """Gate Based Surface Code.""" + + source: GateBasedSurfaceCodeSource = GateBasedSurfaceCodeSource.arXiv12080928 + + def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: + return 2 * code_distance**2 + + def logical_time_step( + self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters + ) -> float | np.ndarray: + measurement_coef = 1 if self.source is GateBasedSurfaceCodeSource.arXiv12080928 else 2 + return ( + 4 * physical_parameters.t_gate_ns + measurement_coef * physical_parameters.t_meas_ns + ) * code_distance + + +class MeasurementBasedSurfaceCode(QuantumErrorCorrectionSchemeSummary): + """Measurement Based Surface Code.""" + + def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: + return 2 * code_distance**2 + + def logical_time_step( + self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters + ) -> float | np.ndarray: + return 20 * physical_parameters.t_meas_ns * code_distance + + +class MeasurementBasedHastingsHaahCode(QuantumErrorCorrectionSchemeSummary): + """Measurement Based Hastings&Haah Code.""" + + def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: + return 4 * code_distance**2 + 8 * (code_distance - 1) + + def logical_time_step( + self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters + ) -> float | np.ndarray: + return 3 * physical_parameters.t_meas_ns * code_distance diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py new file mode 100644 index 000000000..a45257c3f --- /dev/null +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -0,0 +1,84 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +from qualtran.surface_code import quantum_error_correction_scheme_summary as qecs +from qualtran.surface_code.physical_parameters import PhysicalParameters + + +@pytest.mark.parametrize( + 'qec,want', + [ + [qecs.GateBasedSurfaceCode(error_rate_scaler=0.03, error_rate_threshold=0.01), 3e-7], + [ + qecs.MeasurementBasedSurfaceCode(error_rate_scaler=0.04, error_rate_threshold=0.09), + 6.77e-12, + ], + [ + qecs.MeasurementBasedHastingsHaahCode( + error_rate_scaler=0.05, error_rate_threshold=0.06 + ), + 6.43e-11, + ], + ], +) +def test_logical_error_rate(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): + assert qec.logical_error_rate(9, 1e-3) == pytest.approx(want) + + +@pytest.mark.parametrize( + 'qec,want', + [ + [qecs.GateBasedSurfaceCode(error_rate_scaler=0.03, error_rate_threshold=0.01), 242], + [qecs.MeasurementBasedSurfaceCode(error_rate_scaler=0.04, error_rate_threshold=0.09), 242], + [ + qecs.MeasurementBasedHastingsHaahCode( + error_rate_scaler=0.05, error_rate_threshold=0.06 + ), + 564, + ], + ], +) +def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: int): + assert qec.physical_qubits(11) == want + + +@pytest.mark.parametrize( + 'qec,want', + [ + [ + qecs.GateBasedSurfaceCode( + error_rate_scaler=0.03, + error_rate_threshold=0.01, + source=qecs.GateBasedSurfaceCodeSource.arXiv221107629, + ), + 4.8e-6, + ], + [ + qecs.MeasurementBasedSurfaceCode(error_rate_scaler=0.04, error_rate_threshold=0.09), + 2.4e-5, + ], + [ + qecs.MeasurementBasedHastingsHaahCode( + error_rate_scaler=0.05, error_rate_threshold=0.06 + ), + 3.6e-6, + ], + ], +) +def test_logical_time_step(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): + assert qec.logical_time_step( + 12, physical_parameters=PhysicalParameters(50e-9, 100e-9, 1e-4) + ) == pytest.approx(want) From e1f9b4f272b04991ea4577bd9c4d0c245c6fd312 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 16:30:44 -0700 Subject: [PATCH 02/20] improve docstring --- .../quantum_error_correction_scheme_summary.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index e7c3bca12..5d675b286 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -29,6 +29,14 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): number of physical qubits and the logical time step given a code distance and physical assumptions. + The logical error rate as a function of code distance $d$ and physical error rate $p$ + is given by + $$ + $$ + a \left ( \frac{p}{p^*} \right )^\frac{d + 1}{2} + $$ + Where $a$ is the error_rate_scaler and $p^*$ is the error_rate_threshold. + Attributes: error_rate_scaler: Logical error rate coefficient. error_rate_threshold: Logical error rate threshold. From 310c0dcdee96d132fdf097532de5452a47fa5b04 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 16:31:35 -0700 Subject: [PATCH 03/20] nit --- qualtran/surface_code/quantum_error_correction_scheme_summary.py | 1 - 1 file changed, 1 deletion(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 5d675b286..963fbebec 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -32,7 +32,6 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): The logical error rate as a function of code distance $d$ and physical error rate $p$ is given by $$ - $$ a \left ( \frac{p}{p^*} \right )^\frac{d + 1}{2} $$ Where $a$ is the error_rate_scaler and $p^*$ is the error_rate_threshold. From cf1cde34fe7e3ee52867d0379d7af33e26ca5ec5 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 16:31:48 -0700 Subject: [PATCH 04/20] nit --- .../surface_code/quantum_error_correction_scheme_summary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 963fbebec..0fe6fb169 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -29,7 +29,7 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): number of physical qubits and the logical time step given a code distance and physical assumptions. - The logical error rate as a function of code distance $d$ and physical error rate $p$ + The logical error rate as a function of code distance $d$ and physical error rate $p$ is given by $$ a \left ( \frac{p}{p^*} \right )^\frac{d + 1}{2} From 4cab32306f790b5f8d36b2ad1c423d8c1a3a8cff Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 16:35:20 -0700 Subject: [PATCH 05/20] nit --- .../surface_code/quantum_error_correction_scheme_summary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 0fe6fb169..4bd4c8983 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -23,7 +23,7 @@ @frozen class QuantumErrorCorrectionSchemeSummary(abc.ABC): - """QuantumErrorCorrectionSchemeSummary represents a high level view of a QEC scheme. + r"""QuantumErrorCorrectionSchemeSummary represents a high level view of a QEC scheme. QuantumErrorCorrectionSchemeSummary provides estimates for the logical error rate, number of physical qubits and the logical time step given a code distance and From a24c06fe3d0e4a65e0d8c6af4c56a2450d100697 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 17:37:42 -0700 Subject: [PATCH 06/20] nit --- .../surface_code/quantum_error_correction_scheme_summary.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 4bd4c8983..951be466f 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -36,6 +36,8 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): $$ Where $a$ is the error_rate_scaler and $p^*$ is the error_rate_threshold. + Note: The logical error-suppression factor $\Lambda = \frac{p^*}{p}$ + Attributes: error_rate_scaler: Logical error rate coefficient. error_rate_threshold: Logical error rate threshold. From 174c239095bd0e13d012eb05383bdcc98321e999 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Fri, 6 Oct 2023 18:22:52 +0000 Subject: [PATCH 07/20] fix docstring indentation --- ...quantum_error_correction_scheme_summary.py | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 951be466f..956a62d5a 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -25,18 +25,18 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): r"""QuantumErrorCorrectionSchemeSummary represents a high level view of a QEC scheme. - QuantumErrorCorrectionSchemeSummary provides estimates for the logical error rate, - number of physical qubits and the logical time step given a code distance and - physical assumptions. - - The logical error rate as a function of code distance $d$ and physical error rate $p$ - is given by - $$ - a \left ( \frac{p}{p^*} \right )^\frac{d + 1}{2} - $$ - Where $a$ is the error_rate_scaler and $p^*$ is the error_rate_threshold. - - Note: The logical error-suppression factor $\Lambda = \frac{p^*}{p}$ + QuantumErrorCorrectionSchemeSummary provides estimates for the logical error rate, + number of physical qubits and the logical time step given a code distance and + physical assumptions. + + The logical error rate as a function of code distance $d$ and physical error rate $p$ + is given by + $$ + a \left ( \frac{p}{p^*} \right )^\frac{d + 1}{2} + $$ + Where $a$ is the error_rate_scaler and $p^*$ is the error_rate_threshold. + + Note: The logical error-suppression factor $\Lambda = \frac{p^*}{p}$ Attributes: error_rate_scaler: Logical error rate coefficient. From 885f7325ea53b0fa8a6df9fd17a60f3065d6731f Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 25 Oct 2023 16:09:35 -0700 Subject: [PATCH 08/20] will be back --- ...quantum_error_correction_scheme_summary.py | 102 +++++++++--------- ...um_error_correction_scheme_summary_test.py | 56 +--------- 2 files changed, 58 insertions(+), 100 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 956a62d5a..1e05ff2f2 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -26,8 +26,7 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): r"""QuantumErrorCorrectionSchemeSummary represents a high level view of a QEC scheme. QuantumErrorCorrectionSchemeSummary provides estimates for the logical error rate, - number of physical qubits and the logical time step given a code distance and - physical assumptions. + number of physical qubits and the time of an error detection cycle. The logical error rate as a function of code distance $d$ and physical error rate $p$ is given by @@ -49,66 +48,71 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): reference: str | None = None def logical_error_rate( - self, code_distance: int | np.ndarray, physical_error_rate: float | np.ndarray + self, code_distance: int, physical_error_rate: float | np.ndarray ) -> float | np.ndarray: - """The logical error rate for the given code distance using this scheme.""" + """The logical error rate given the physical error rate.""" return self.error_rate_scaler * np.power( physical_error_rate / self.error_rate_threshold, (code_distance + 1) / 2 ) @abc.abstractmethod - def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: - """The number of physical qubits for the given code distance using this scheme.""" + def physical_qubits(self, code_distance: int) -> int: + """The number of physical qubits used by the error correction circuit.""" @abc.abstractmethod - def logical_time_step( - self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters - ) -> float | np.ndarray: - """The duration of a logical time step for the given code distance using this scheme.""" - - -class GateBasedSurfaceCodeSource(enum.Enum): - arXiv12080928 = 0 # Folwer Model. - arXiv221107629 = 1 # Azure Model. + def error_detection_cycle_time(self, code_distance: int) -> float: + """The time of a quantum error correction cycle in seconds.""" -@frozen -class GateBasedSurfaceCode(QuantumErrorCorrectionSchemeSummary): - """Gate Based Surface Code.""" - - source: GateBasedSurfaceCodeSource = GateBasedSurfaceCodeSource.arXiv12080928 +class SurfaceCode(QuantumErrorCorrectionSchemeSummary): + """A Surface Code Quantum Error Correction Scheme.""" - def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: + def physical_qubits(self, code_distance: int) -> int | np.ndarray: return 2 * code_distance**2 - def logical_time_step( - self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters - ) -> float | np.ndarray: - measurement_coef = 1 if self.source is GateBasedSurfaceCodeSource.arXiv12080928 else 2 - return ( - 4 * physical_parameters.t_gate_ns + measurement_coef * physical_parameters.t_meas_ns - ) * code_distance - - -class MeasurementBasedSurfaceCode(QuantumErrorCorrectionSchemeSummary): - """Measurement Based Surface Code.""" - def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: - return 2 * code_distance**2 - - def logical_time_step( - self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters - ) -> float | np.ndarray: - return 20 * physical_parameters.t_meas_ns * code_distance - - -class MeasurementBasedHastingsHaahCode(QuantumErrorCorrectionSchemeSummary): - """Measurement Based Hastings&Haah Code.""" +@frozen +class SimpliedSurfaceCode(SurfaceCode): + """SimpliedSurfaceCode assumes the error detection time is a linear function in code distance.""" - def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: - return 4 * code_distance**2 + 8 * (code_distance - 1) + error_detection_cycle_time_slope_us: float + error_detection_cycle_time_intercept_us: float - def logical_time_step( - self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters - ) -> float | np.ndarray: - return 3 * physical_parameters.t_meas_ns * code_distance + def error_detection_cycle_time(self, code_distance: int) -> float: + return ( + self.error_detection_cycle_time_slope_us * code_distance + + self.error_detection_cycle_time_intercept_us + ) * 1e-6 + + +Fowler = SimpliedSurfaceCode( + error_rate_scaler=0.1, + error_rate_threshold=0.01, + # The Fowler model assumes an error detection time of 1us regardless of the code distance. + error_detection_cycle_time_slope_us=0, + error_detection_cycle_time_intercept_us=1, + reference='https://arxiv.org/pdf/1808.06709.pdf,https://arxiv.org/pdf/1208.0928.pdf', +) + +# The Beverland model assumes an error detection time equal to a*d, where slope a depends only on the hardware. +BeverlandTrappedIonQubits = SimpliedSurfaceCode( + error_rate_scaler=0.03, + error_rate_threshold=0.01, + error_detection_cycle_time_slope_us=600, + error_detection_cycle_time_intercept_us=0, + reference='https://arxiv.org/pdf/2211.07629.pdf', +) +BeverlandSuperConductingQubits = SimpliedSurfaceCode( + error_rate_scaler=0.03, + error_rate_threshold=0.01, + error_detection_cycle_time_slope_us=0.4, + error_detection_cycle_time_intercept_us=0, + reference='https://arxiv.org/pdf/2211.07629.pdf', +) +BeverlandMajoranaQubits = SimpliedSurfaceCode( + error_rate_scaler=0.03, + error_rate_threshold=0.01, + error_detection_cycle_time_slope_us=0.6, + error_detection_cycle_time_intercept_us=0, + reference='https://arxiv.org/pdf/2211.07629.pdf', +) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index a45257c3f..21d85a60b 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -15,70 +15,24 @@ import pytest from qualtran.surface_code import quantum_error_correction_scheme_summary as qecs -from qualtran.surface_code.physical_parameters import PhysicalParameters @pytest.mark.parametrize( - 'qec,want', - [ - [qecs.GateBasedSurfaceCode(error_rate_scaler=0.03, error_rate_threshold=0.01), 3e-7], - [ - qecs.MeasurementBasedSurfaceCode(error_rate_scaler=0.04, error_rate_threshold=0.09), - 6.77e-12, - ], - [ - qecs.MeasurementBasedHastingsHaahCode( - error_rate_scaler=0.05, error_rate_threshold=0.06 - ), - 6.43e-11, - ], - ], + 'qec,want', [(qecs.Fowler, 3e-7), (qecs.BeverlandSuperConductingQubits, 0)] ) def test_logical_error_rate(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): assert qec.logical_error_rate(9, 1e-3) == pytest.approx(want) @pytest.mark.parametrize( - 'qec,want', - [ - [qecs.GateBasedSurfaceCode(error_rate_scaler=0.03, error_rate_threshold=0.01), 242], - [qecs.MeasurementBasedSurfaceCode(error_rate_scaler=0.04, error_rate_threshold=0.09), 242], - [ - qecs.MeasurementBasedHastingsHaahCode( - error_rate_scaler=0.05, error_rate_threshold=0.06 - ), - 564, - ], - ], + 'qec,want', [[qecs.BeverlandSuperConductingQubits, 242], [qecs.Fowler, 242]] ) def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: int): assert qec.physical_qubits(11) == want @pytest.mark.parametrize( - 'qec,want', - [ - [ - qecs.GateBasedSurfaceCode( - error_rate_scaler=0.03, - error_rate_threshold=0.01, - source=qecs.GateBasedSurfaceCodeSource.arXiv221107629, - ), - 4.8e-6, - ], - [ - qecs.MeasurementBasedSurfaceCode(error_rate_scaler=0.04, error_rate_threshold=0.09), - 2.4e-5, - ], - [ - qecs.MeasurementBasedHastingsHaahCode( - error_rate_scaler=0.05, error_rate_threshold=0.06 - ), - 3.6e-6, - ], - ], + 'qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8e-6], [qecs.Fowler, 2.4e-5]] ) -def test_logical_time_step(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): - assert qec.logical_time_step( - 12, physical_parameters=PhysicalParameters(50e-9, 100e-9, 1e-4) - ) == pytest.approx(want) +def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): + assert qec.error_detection_cycle_time(12) == pytest.approx(want) From 8fa32723c43783181dd5767fb28d169b2a537d6b Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 25 Oct 2023 16:20:30 -0700 Subject: [PATCH 09/20] ready for review --- .../quantum_error_correction_scheme_summary.py | 11 ++++------- .../quantum_error_correction_scheme_summary_test.py | 6 +++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 1e05ff2f2..783007bc7 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -13,13 +13,10 @@ # limitations under the License. import abc -import enum import numpy as np from attrs import field, frozen -from qualtran.surface_code.physical_parameters import PhysicalParameters - @frozen class QuantumErrorCorrectionSchemeSummary(abc.ABC): @@ -43,9 +40,9 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): reference: source of the estimates. """ - error_rate_scaler: float = field(default=0.1, repr=lambda x: f'{x:g}') - error_rate_threshold: float = field(default=0.01, repr=lambda x: f'{x:g}') - reference: str | None = None + error_rate_scaler: float = field(repr=lambda x: f'{x:g}') + error_rate_threshold: float = field(repr=lambda x: f'{x:g}') + reference: str | None def logical_error_rate( self, code_distance: int, physical_error_rate: float | np.ndarray @@ -67,7 +64,7 @@ def error_detection_cycle_time(self, code_distance: int) -> float: class SurfaceCode(QuantumErrorCorrectionSchemeSummary): """A Surface Code Quantum Error Correction Scheme.""" - def physical_qubits(self, code_distance: int) -> int | np.ndarray: + def physical_qubits(self, code_distance: int) -> int: return 2 * code_distance**2 diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index 21d85a60b..f3d19d015 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -18,10 +18,10 @@ @pytest.mark.parametrize( - 'qec,want', [(qecs.Fowler, 3e-7), (qecs.BeverlandSuperConductingQubits, 0)] + 'qec,want', [(qecs.Fowler, 1e-3), (qecs.BeverlandSuperConductingQubits, 3e-4)] ) def test_logical_error_rate(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): - assert qec.logical_error_rate(9, 1e-3) == pytest.approx(want) + assert qec.logical_error_rate(3, 1e-3) == pytest.approx(want) @pytest.mark.parametrize( @@ -32,7 +32,7 @@ def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: in @pytest.mark.parametrize( - 'qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8e-6], [qecs.Fowler, 2.4e-5]] + 'qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8e-6], [qecs.Fowler, 1e-6]] ) def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): assert qec.error_detection_cycle_time(12) == pytest.approx(want) From ea9edc7bea6d4590aaaaf4450f87b592bcc825a1 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 25 Oct 2023 16:27:05 -0700 Subject: [PATCH 10/20] doc --- .../quantum_error_correction_scheme_summary.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 783007bc7..2a061bea7 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -70,7 +70,19 @@ def physical_qubits(self, code_distance: int) -> int: @frozen class SimpliedSurfaceCode(SurfaceCode): - """SimpliedSurfaceCode assumes the error detection time is a linear function in code distance.""" + r"""SimpliedSurfaceCode assumes the error detection time is a linear function in code distance. + + The error detection time $\tau(d)$ is assumed to be given by a linear function + $$ + \tau(d) = a*d + b + $$ + Where $a$ is the `error_detection_cycle_time_slope_us` and $b$ is `error_detection_cycle_time_intercept_us` + both of which depend only on the hardware. + + Attributes: + error_detection_cycle_time_slope_us: + error_detection_cycle_time_intercept_us: float + """ error_detection_cycle_time_slope_us: float error_detection_cycle_time_intercept_us: float From 5a14ec60a212c865ab4fd4856d8c82196aa11438 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 25 Oct 2023 17:06:32 -0700 Subject: [PATCH 11/20] address comments --- .../quantum_error_correction_scheme_summary.py | 18 +++++++++--------- ...tum_error_correction_scheme_summary_test.py | 6 ++---- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 2a061bea7..68ca9b39b 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -37,7 +37,7 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): Attributes: error_rate_scaler: Logical error rate coefficient. error_rate_threshold: Logical error rate threshold. - reference: source of the estimates. + reference: source of the estimates in human readable format. """ error_rate_scaler: float = field(repr=lambda x: f'{x:g}') @@ -57,7 +57,7 @@ def physical_qubits(self, code_distance: int) -> int: """The number of physical qubits used by the error correction circuit.""" @abc.abstractmethod - def error_detection_cycle_time(self, code_distance: int) -> float: + def error_detection_cycle_time_us(self, code_distance: int) -> float: """The time of a quantum error correction cycle in seconds.""" @@ -70,7 +70,7 @@ def physical_qubits(self, code_distance: int) -> int: @frozen class SimpliedSurfaceCode(SurfaceCode): - r"""SimpliedSurfaceCode assumes the error detection time is a linear function in code distance. + r"""Assumes the error detection time is a linear function in code distance. The error detection time $\tau(d)$ is assumed to be given by a linear function $$ @@ -87,11 +87,11 @@ class SimpliedSurfaceCode(SurfaceCode): error_detection_cycle_time_slope_us: float error_detection_cycle_time_intercept_us: float - def error_detection_cycle_time(self, code_distance: int) -> float: + def error_detection_cycle_time_us(self, code_distance: int) -> float: return ( self.error_detection_cycle_time_slope_us * code_distance + self.error_detection_cycle_time_intercept_us - ) * 1e-6 + ) Fowler = SimpliedSurfaceCode( @@ -100,7 +100,7 @@ def error_detection_cycle_time(self, code_distance: int) -> float: # The Fowler model assumes an error detection time of 1us regardless of the code distance. error_detection_cycle_time_slope_us=0, error_detection_cycle_time_intercept_us=1, - reference='https://arxiv.org/pdf/1808.06709.pdf,https://arxiv.org/pdf/1208.0928.pdf', + reference='https://arxiv.org/abs/1808.06709,https://arxiv.org/abs/1208.0928', ) # The Beverland model assumes an error detection time equal to a*d, where slope a depends only on the hardware. @@ -109,19 +109,19 @@ def error_detection_cycle_time(self, code_distance: int) -> float: error_rate_threshold=0.01, error_detection_cycle_time_slope_us=600, error_detection_cycle_time_intercept_us=0, - reference='https://arxiv.org/pdf/2211.07629.pdf', + reference='https://arxiv.org/abs/2211.07629', ) BeverlandSuperConductingQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, error_detection_cycle_time_slope_us=0.4, error_detection_cycle_time_intercept_us=0, - reference='https://arxiv.org/pdf/2211.07629.pdf', + reference='https://arxiv.org/abs/2211.07629', ) BeverlandMajoranaQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, error_detection_cycle_time_slope_us=0.6, error_detection_cycle_time_intercept_us=0, - reference='https://arxiv.org/pdf/2211.07629.pdf', + reference='https://arxiv.org/abs/2211.07629', ) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index f3d19d015..802a6022c 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -31,8 +31,6 @@ def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: in assert qec.physical_qubits(11) == want -@pytest.mark.parametrize( - 'qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8e-6], [qecs.Fowler, 1e-6]] -) +@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8], [qecs.Fowler, 1]]) def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): - assert qec.error_detection_cycle_time(12) == pytest.approx(want) + assert qec.error_detection_cycle_time_us(12) == pytest.approx(want) From 30092d77f4a3008dc14c1cad76c5f8ded1b3d5fe Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 16 Nov 2023 15:58:07 -0800 Subject: [PATCH 12/20] tmp --- ...quantum_error_correction_scheme_summary.py | 50 ++++++------------- ...um_error_correction_scheme_summary_test.py | 2 +- 2 files changed, 16 insertions(+), 36 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 68ca9b39b..083597bbe 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -57,49 +57,32 @@ def physical_qubits(self, code_distance: int) -> int: """The number of physical qubits used by the error correction circuit.""" @abc.abstractmethod - def error_detection_cycle_time_us(self, code_distance: int) -> float: + def syndrome_detection_time_us(self, code_distance: int) -> float: """The time of a quantum error correction cycle in seconds.""" -class SurfaceCode(QuantumErrorCorrectionSchemeSummary): - """A Surface Code Quantum Error Correction Scheme.""" - - def physical_qubits(self, code_distance: int) -> int: - return 2 * code_distance**2 - - @frozen -class SimpliedSurfaceCode(SurfaceCode): - r"""Assumes the error detection time is a linear function in code distance. - - The error detection time $\tau(d)$ is assumed to be given by a linear function - $$ - \tau(d) = a*d + b - $$ - Where $a$ is the `error_detection_cycle_time_slope_us` and $b$ is `error_detection_cycle_time_intercept_us` - both of which depend only on the hardware. +class SimpliedSurfaceCode(QuantumErrorCorrectionSchemeSummary): + """A Surface Code Quantum Error Correction Scheme. Attributes: - error_detection_cycle_time_slope_us: - error_detection_cycle_time_intercept_us: float + single_stabilizer_measurement_time_us: Max time of a single X or Z stabilizer measurement. """ - error_detection_cycle_time_slope_us: float - error_detection_cycle_time_intercept_us: float + single_stabilizer_measurement_time_us: float - def error_detection_cycle_time_us(self, code_distance: int) -> float: - return ( - self.error_detection_cycle_time_slope_us * code_distance - + self.error_detection_cycle_time_intercept_us - ) + def physical_qubits(self, code_distance: int) -> int: + return 2 * code_distance**2 + + def syndrome_detection_time_us(self, code_distance: int) -> float: + """Equals the time to measure a stabilizer times the depth of the circuit.""" + return self.single_stabilizer_measurement_time_us * code_distance Fowler = SimpliedSurfaceCode( error_rate_scaler=0.1, error_rate_threshold=0.01, - # The Fowler model assumes an error detection time of 1us regardless of the code distance. - error_detection_cycle_time_slope_us=0, - error_detection_cycle_time_intercept_us=1, + single_stabilizer_measurement_time_us=1, reference='https://arxiv.org/abs/1808.06709,https://arxiv.org/abs/1208.0928', ) @@ -107,21 +90,18 @@ def error_detection_cycle_time_us(self, code_distance: int) -> float: BeverlandTrappedIonQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, - error_detection_cycle_time_slope_us=600, - error_detection_cycle_time_intercept_us=0, + single_stabilizer_measurement_time_us=600, reference='https://arxiv.org/abs/2211.07629', ) BeverlandSuperConductingQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, - error_detection_cycle_time_slope_us=0.4, - error_detection_cycle_time_intercept_us=0, + single_stabilizer_measurement_time_us=0.4, reference='https://arxiv.org/abs/2211.07629', ) BeverlandMajoranaQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, - error_detection_cycle_time_slope_us=0.6, - error_detection_cycle_time_intercept_us=0, + single_stabilizer_measurement_time_us=0.6, reference='https://arxiv.org/abs/2211.07629', ) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index 802a6022c..48fae8c67 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -33,4 +33,4 @@ def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: in @pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8], [qecs.Fowler, 1]]) def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): - assert qec.error_detection_cycle_time_us(12) == pytest.approx(want) + assert qec.syndrome_detection_time_us(12) == pytest.approx(want) From 3cc5d90926246a7be79870e571c20810d98b5ebe Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 16 Nov 2023 16:49:52 -0800 Subject: [PATCH 13/20] update terminalogy --- ...quantum_error_correction_scheme_summary.py | 32 ++++--------------- ...um_error_correction_scheme_summary_test.py | 12 +++---- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 083597bbe..6b1541579 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -57,7 +57,7 @@ def physical_qubits(self, code_distance: int) -> int: """The number of physical qubits used by the error correction circuit.""" @abc.abstractmethod - def syndrome_detection_time_us(self, code_distance: int) -> float: + def error_detection_circuit_time_us(self, code_distance: int) -> float: """The time of a quantum error correction cycle in seconds.""" @@ -66,42 +66,22 @@ class SimpliedSurfaceCode(QuantumErrorCorrectionSchemeSummary): """A Surface Code Quantum Error Correction Scheme. Attributes: - single_stabilizer_measurement_time_us: Max time of a single X or Z stabilizer measurement. + single_stabilizer_time_us: Max time of a single X or Z stabilizer measurement. """ - single_stabilizer_measurement_time_us: float + single_stabilizer_time_us: float def physical_qubits(self, code_distance: int) -> int: return 2 * code_distance**2 - def syndrome_detection_time_us(self, code_distance: int) -> float: + def error_detection_circuit_time_us(self, code_distance: int) -> float: """Equals the time to measure a stabilizer times the depth of the circuit.""" - return self.single_stabilizer_measurement_time_us * code_distance + return self.single_stabilizer_time_us * code_distance -Fowler = SimpliedSurfaceCode( - error_rate_scaler=0.1, - error_rate_threshold=0.01, - single_stabilizer_measurement_time_us=1, - reference='https://arxiv.org/abs/1808.06709,https://arxiv.org/abs/1208.0928', -) - -# The Beverland model assumes an error detection time equal to a*d, where slope a depends only on the hardware. -BeverlandTrappedIonQubits = SimpliedSurfaceCode( - error_rate_scaler=0.03, - error_rate_threshold=0.01, - single_stabilizer_measurement_time_us=600, - reference='https://arxiv.org/abs/2211.07629', -) BeverlandSuperConductingQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, - single_stabilizer_measurement_time_us=0.4, - reference='https://arxiv.org/abs/2211.07629', -) -BeverlandMajoranaQubits = SimpliedSurfaceCode( - error_rate_scaler=0.03, - error_rate_threshold=0.01, - single_stabilizer_measurement_time_us=0.6, + single_stabilizer_time_us=0.4, # Equals 4*t_gate+2*t_meas where t_gate=50ns and t_meas=100ns. reference='https://arxiv.org/abs/2211.07629', ) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index 48fae8c67..fd4a500dd 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -17,20 +17,16 @@ from qualtran.surface_code import quantum_error_correction_scheme_summary as qecs -@pytest.mark.parametrize( - 'qec,want', [(qecs.Fowler, 1e-3), (qecs.BeverlandSuperConductingQubits, 3e-4)] -) +@pytest.mark.parametrize('qec,want', [(qecs.BeverlandSuperConductingQubits, 3e-4)]) def test_logical_error_rate(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): assert qec.logical_error_rate(3, 1e-3) == pytest.approx(want) -@pytest.mark.parametrize( - 'qec,want', [[qecs.BeverlandSuperConductingQubits, 242], [qecs.Fowler, 242]] -) +@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 242]]) def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: int): assert qec.physical_qubits(11) == want -@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8], [qecs.Fowler, 1]]) +@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8]]) def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): - assert qec.syndrome_detection_time_us(12) == pytest.approx(want) + assert qec.error_detection_circuit_time_us(12) == pytest.approx(want) From 6c79a339cb2f206916812eaa25f684312bac670e Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 16 Nov 2023 16:51:28 -0800 Subject: [PATCH 14/20] nit --- .../surface_code/quantum_error_correction_scheme_summary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 6b1541579..4c9f73498 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -54,11 +54,11 @@ def logical_error_rate( @abc.abstractmethod def physical_qubits(self, code_distance: int) -> int: - """The number of physical qubits used by the error correction circuit.""" + """The number of physical qubits used by the error detection circuit.""" @abc.abstractmethod def error_detection_circuit_time_us(self, code_distance: int) -> float: - """The time of a quantum error correction cycle in seconds.""" + """The time of a quantum error detection cycle in seconds.""" @frozen From 5d5e7e4e588ab262dc49027a955b4709fa8d8894 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 30 Nov 2023 14:29:24 -0800 Subject: [PATCH 15/20] nit --- .../surface_code/quantum_error_correction_scheme_summary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 4c9f73498..9caefa25f 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -37,7 +37,7 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): Attributes: error_rate_scaler: Logical error rate coefficient. error_rate_threshold: Logical error rate threshold. - reference: source of the estimates in human readable format. + reference: source of the estimates in human-readable format. """ error_rate_scaler: float = field(repr=lambda x: f'{x:g}') From ac1ee47fbbf83c067e91c13cb4eeb9e9b05d9652 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 30 Nov 2023 15:07:39 -0800 Subject: [PATCH 16/20] remove formulae.py --- qualtran/surface_code/ccz2t_cost_model.py | 37 +++++++++---- qualtran/surface_code/data_block.py | 11 ++-- qualtran/surface_code/formulae.py | 50 ------------------ qualtran/surface_code/formulae_test.py | 28 ---------- ...quantum_error_correction_scheme_summary.py | 52 ++++++++++++++++--- ...um_error_correction_scheme_summary_test.py | 24 +++++++++ 6 files changed, 102 insertions(+), 100 deletions(-) delete mode 100644 qualtran/surface_code/formulae.py delete mode 100644 qualtran/surface_code/formulae_test.py diff --git a/qualtran/surface_code/ccz2t_cost_model.py b/qualtran/surface_code/ccz2t_cost_model.py index d5c5cc286..9a793fba4 100644 --- a/qualtran/surface_code/ccz2t_cost_model.py +++ b/qualtran/surface_code/ccz2t_cost_model.py @@ -17,9 +17,9 @@ from attrs import frozen +import qualtran.surface_code.quantum_error_correction_scheme_summary as qec from qualtran.surface_code.algorithm_summary import AlgorithmSummary from qualtran.surface_code.data_block import DataBlock, SimpleDataBlock -from qualtran.surface_code.formulae import code_distance_from_budget, error_at from qualtran.surface_code.magic_state_factory import MagicStateFactory from qualtran.surface_code.physical_cost import PhysicalCost @@ -39,6 +39,7 @@ class CCZ2TFactory(MagicStateFactory): distillation_l1_d: int = 15 distillation_l2_d: int = 31 + qec_scheme: qec.QuantumErrorCorrectionSchemeSummary = qec.FowlerSuperConductingQubits # ------------------------------------------------------------------------------- # ---- Level 0 --------- @@ -61,7 +62,9 @@ def l0_topo_error_t_gate(self, phys_err: float) -> float: # The chance of a logical error occurring within a lattice surgery unit cell at # code distance d1*0.5. - topo_error_per_unit_cell = error_at(phys_err, d=self.distillation_l1_d // 2) + topo_error_per_unit_cell = self.qec_scheme.logical_error_rate( + physical_error_rate=phys_err, code_distance=self.distillation_l1_d // 2 + ) # It takes approximately 100 L0 unit cells to get the injected state where # it needs to be and perform the T gate. @@ -83,12 +86,16 @@ def l1_topo_error_factory(self, phys_err: float) -> float: """Topological error associated with a L1 T factory.""" # The L1 T factory uses approximately 1000 L1 unit cells. - return 1000 * error_at(phys_err, d=self.distillation_l1_d) + return 1000 * self.qec_scheme.logical_error_rate( + physical_error_rate=phys_err, code_distance=self.distillation_l1_d + ) def l1_topo_error_t_gate(self, phys_err: float) -> float: # It takes approximately 100 L1 unit cells to get the L1 state produced by the # factory to where it needs to be and perform the T gate. - return 100 * error_at(phys_err, d=self.distillation_l1_d) + return 100 * self.qec_scheme.logical_error_rate( + physical_error_rate=phys_err, code_distance=self.distillation_l1_d + ) def l1_distillation_error(self, phys_err: float) -> float: """The error due to level-0 faulty T states making it through distillation undetected. @@ -117,7 +124,9 @@ def l2_error(self, phys_err: float) -> float: """ # The L2 CCZ factory and catalyzed T factory both use approximately 1000 L2 unit cells. - l2_topo_error_factory = 1000 * error_at(phys_err, d=self.distillation_l2_d) + l2_topo_error_factory = 1000 * self.qec_scheme.logical_error_rate( + physical_error_rate=phys_err, code_distance=self.distillation_l2_d + ) # Distillation error for this level. l2_distillation_error = 28 * self.l1_error(phys_err) ** 2 @@ -156,11 +165,11 @@ def get_ccz2t_costs( n_magic: AlgorithmSummary, n_algo_qubits: int, phys_err: float = 1e-3, - error_budget: Optional[float] = 1e-2, + error_budget: float = 1e-2, cycle_time_us: float = 1.0, - routing_overhead: Optional[float] = 0.5, - factory: MagicStateFactory = None, - data_block: DataBlock = None, + routing_overhead: float = 0.5, + factory: Optional[MagicStateFactory] = None, + data_block: Optional[DataBlock] = None, ) -> PhysicalCost: """Physical costs using the model from catalyzed CCZ to 2T paper. @@ -201,8 +210,14 @@ def get_ccz2t_costs( n_logical_qubits = math.ceil((1 + routing_overhead) * n_algo_qubits) data_unit_cells = n_logical_qubits * n_cycles target_err_per_round = err_budget / data_unit_cells - data_d = code_distance_from_budget(phys_err=phys_err, budget=target_err_per_round) - data_block = SimpleDataBlock(data_d=data_d, routing_overhead=routing_overhead) + data_d = qec.FowlerSuperConductingQubits.code_distance_from_budget( + physical_error_rate=phys_err, budget=target_err_per_round + ) + data_block = SimpleDataBlock( + data_d=data_d, + routing_overhead=routing_overhead, + qec_scheme=qec.FowlerSuperConductingQubits, + ) data_error = data_block.data_error( n_algo_qubits=n_algo_qubits, n_cycles=n_cycles, phys_err=phys_err diff --git a/qualtran/surface_code/data_block.py b/qualtran/surface_code/data_block.py index fb482abda..23aee958c 100644 --- a/qualtran/surface_code/data_block.py +++ b/qualtran/surface_code/data_block.py @@ -17,7 +17,7 @@ from attrs import frozen -from qualtran.surface_code.formulae import error_at +import qualtran.surface_code.quantum_error_correction_scheme_summary as qec class DataBlock(metaclass=abc.ABCMeta): @@ -28,6 +28,7 @@ class DataBlock(metaclass=abc.ABCMeta): called the data block, and we provide its costs here. """ + @abc.abstractmethod def footprint(self, n_algo_qubits: int) -> int: """The number of physical qubits used by the data block. @@ -36,6 +37,7 @@ def footprint(self, n_algo_qubits: int) -> int: accessed. """ + @abc.abstractmethod def data_error(self, n_algo_qubits: int, n_cycles: int, phys_err: float) -> float: """The error associated with storing data on `n_algo_qubits` for `n_cycles`.""" @@ -52,6 +54,7 @@ class SimpleDataBlock(DataBlock): data_d: int routing_overhead: float = 0.5 + qec_scheme: qec.QuantumErrorCorrectionSchemeSummary = qec.FowlerSuperConductingQubits def n_logical_qubits(self, n_algo_qubits: int) -> int: """Number of logical qubits including overhead. @@ -64,10 +67,12 @@ def n_logical_qubits(self, n_algo_qubits: int) -> int: def footprint(self, n_algo_qubits: int) -> int: """The number of physical qubits used by the data block.""" - n_phys_per_logical = 2 * self.data_d**2 + n_phys_per_logical = self.qec_scheme.physical_qubits(self.data_d) return self.n_logical_qubits(n_algo_qubits) * n_phys_per_logical def data_error(self, n_algo_qubits: int, n_cycles: int, phys_err: float) -> float: """The error associated with storing data on `n_algo_qubits` for `n_cycles`.""" data_cells = self.n_logical_qubits(n_algo_qubits) * n_cycles - return data_cells * error_at(phys_err, d=self.data_d) + return data_cells * self.qec_scheme.logical_error_rate( + physical_error_rate=phys_err, code_distance=self.data_d + ) diff --git a/qualtran/surface_code/formulae.py b/qualtran/surface_code/formulae.py deleted file mode 100644 index 6283f20ae..000000000 --- a/qualtran/surface_code/formulae.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import math - - -def error_at(phys_err: float, *, d: int) -> float: - """Logical error suppressed with code distance `d` for this physical error rate. - - This is an estimate, see the references section. - - The formula was originally expressed as $p_l = a (b * p_p)^((d+1)/2)$ physical - error rate $p_p$ and parameters $a$ and $b$. This can alternatively be expressed with - $p_th = (1/b)$ roughly corresponding to the code threshold. This is sometimes also - expressed with $lambda = p_th / p_p$. A lambda of 10, for example, would be p_p = 1e-3 - and p_th = 0.01. The pre-factor $a$ has no clear provenance. - - References: - Low overhead quantum computation using lattice surgery. Fowler and Gidney (2018). - https://arxiv.org/abs/1808.06709. - See section XV for introduction of this formula, with citation to below. - - Surface code quantum error correction incorporating accurate error propagation. - Fowler et. al. (2010). https://arxiv.org/abs/1004.0255. - Note: this doesn't actually contain the formula from the above reference. - """ - return 0.1 * (100 * phys_err) ** ((d + 1) / 2) - - -def code_distance_from_budget(phys_err: float, budget: float) -> int: - """Get the code distance that keeps one below the logical error `budget`.""" - - # See: `error_at()`. p_l = a Λ^(-r) where r = (d+1)/2 - # Which we invert: r = ln(p_l/a) / ln(1/Λ) - r = math.log(10 * budget) / math.log(100 * phys_err) - d = 2 * math.ceil(r) - 1 - if d < 3: - return 3 - return d diff --git a/qualtran/surface_code/formulae_test.py b/qualtran/surface_code/formulae_test.py deleted file mode 100644 index bb237a72f..000000000 --- a/qualtran/surface_code/formulae_test.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import numpy as np - -from qualtran.surface_code.formulae import code_distance_from_budget, error_at - - -def test_invert_error_at(): - phys_err = 1e-3 - budgets = np.logspace(-1, -18) - for budget in budgets: - d = code_distance_from_budget(phys_err=phys_err, budget=budget) - assert d % 2 == 1 - assert error_at(phys_err=phys_err, d=d) <= budget - if d > 3: - assert error_at(phys_err=phys_err, d=d - 2) > budget diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 9caefa25f..071b95cbc 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -13,14 +13,14 @@ # limitations under the License. import abc +import math -import numpy as np from attrs import field, frozen @frozen class QuantumErrorCorrectionSchemeSummary(abc.ABC): - r"""QuantumErrorCorrectionSchemeSummary represents a high level view of a QEC scheme. + r"""QuantumErrorCorrectionSchemeSummary represents a high-level view of a QEC scheme. QuantumErrorCorrectionSchemeSummary provides estimates for the logical error rate, number of physical qubits and the time of an error detection cycle. @@ -37,21 +37,50 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): Attributes: error_rate_scaler: Logical error rate coefficient. error_rate_threshold: Logical error rate threshold. - reference: source of the estimates in human-readable format. + reference: source of the estimates in a human-readable format. """ error_rate_scaler: float = field(repr=lambda x: f'{x:g}') error_rate_threshold: float = field(repr=lambda x: f'{x:g}') reference: str | None - def logical_error_rate( - self, code_distance: int, physical_error_rate: float | np.ndarray - ) -> float | np.ndarray: - """The logical error rate given the physical error rate.""" - return self.error_rate_scaler * np.power( + def logical_error_rate(self, code_distance: int, physical_error_rate: float) -> float: + """Logical error suppressed with code distance for this physical error rate. + + This is an estimate, see the references section. + + The formula was originally expressed as $p_l = a (b * p_p)^((d+1)/2)$ physical + error rate $p_p$ and parameters $a$ and $b$. This can alternatively be expressed with + $p_th = (1/b)$ roughly corresponding to the code threshold. This is sometimes also + expressed with $lambda = p_th / p_p$. A lambda of 10, for example, would be p_p = 1e-3 + and p_th = 0.01. The pre-factor $a$ has no clear provenance. + + References: + Low overhead quantum computation using lattice surgery. Fowler and Gidney (2018). + https://arxiv.org/abs/1808.06709. + See section XV for introduction of this formula, with citation to below. + + Surface code quantum error correction incorporating accurate error propagation. + Fowler et. al. (2010). https://arxiv.org/abs/1004.0255. + Note: this doesn't actually contain the formula from the above reference. + """ + return self.error_rate_scaler * math.pow( physical_error_rate / self.error_rate_threshold, (code_distance + 1) / 2 ) + def code_distance_from_budget(self, physical_error_rate: float, budget: float) -> int: + """Get the code distance that keeps one below the logical error `budget`.""" + + # See: `error_at()`. p_l = a Λ^(-r) where r = (d+1)/2 + # Which we invert: r = ln(p_l/a) / ln(1/Λ) + r = math.log(budget / self.error_rate_scaler) / math.log( + physical_error_rate / self.error_rate_threshold + ) + d = 2 * math.ceil(r) - 1 + if d < 3: + return 3 + return d + @abc.abstractmethod def physical_qubits(self, code_distance: int) -> int: """The number of physical qubits used by the error detection circuit.""" @@ -85,3 +114,10 @@ def error_detection_circuit_time_us(self, code_distance: int) -> float: single_stabilizer_time_us=0.4, # Equals 4*t_gate+2*t_meas where t_gate=50ns and t_meas=100ns. reference='https://arxiv.org/abs/2211.07629', ) + +FowlerSuperConductingQubits = SimpliedSurfaceCode( + error_rate_scaler=0.1, + error_rate_threshold=0.01, + single_stabilizer_time_us=1, + reference='https://arxiv.org/abs/1808.06709', +) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index fd4a500dd..20a411079 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import numpy as np import pytest from qualtran.surface_code import quantum_error_correction_scheme_summary as qecs @@ -30,3 +31,26 @@ def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: in @pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8]]) def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): assert qec.error_detection_circuit_time_us(12) == pytest.approx(want) + + +def test_invert_error_at(): + phys_err = 1e-3 + budgets = np.logspace(-1, -18) + for budget in budgets: + d = qecs.FowlerSuperConductingQubits.code_distance_from_budget( + physical_error_rate=phys_err, budget=budget + ) + assert d % 2 == 1 + assert ( + qecs.FowlerSuperConductingQubits.logical_error_rate( + physical_error_rate=phys_err, code_distance=d + ) + <= budget + ) + if d > 3: + assert ( + qecs.FowlerSuperConductingQubits.logical_error_rate( + physical_error_rate=phys_err, code_distance=d - 2 + ) + > budget + ) From 234338ab1af073d9596087f2e850209003083543 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 30 Nov 2023 15:12:09 -0800 Subject: [PATCH 17/20] nit --- .../surface_code/quantum_error_correction_scheme_summary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 071b95cbc..06494e8d6 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -42,7 +42,7 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): error_rate_scaler: float = field(repr=lambda x: f'{x:g}') error_rate_threshold: float = field(repr=lambda x: f'{x:g}') - reference: str | None + reference: str | None = None def logical_error_rate(self, code_distance: int, physical_error_rate: float) -> float: """Logical error suppressed with code distance for this physical error rate. @@ -98,7 +98,7 @@ class SimpliedSurfaceCode(QuantumErrorCorrectionSchemeSummary): single_stabilizer_time_us: Max time of a single X or Z stabilizer measurement. """ - single_stabilizer_time_us: float + single_stabilizer_time_us: float = 1 def physical_qubits(self, code_distance: int) -> int: return 2 * code_distance**2 From 28b2a8b4ac62fb35adc33496a4f23d9e2ad3bac5 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 30 Nov 2023 15:23:33 -0800 Subject: [PATCH 18/20] also fix #535 --- qualtran/surface_code/ccz2t_cost_model.py | 4 ++++ qualtran/surface_code/ccz2t_cost_model_test.py | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/qualtran/surface_code/ccz2t_cost_model.py b/qualtran/surface_code/ccz2t_cost_model.py index 9a793fba4..a29b79286 100644 --- a/qualtran/surface_code/ccz2t_cost_model.py +++ b/qualtran/surface_code/ccz2t_cost_model.py @@ -207,6 +207,10 @@ def get_ccz2t_costs( if data_block is None: # Use "left over" budget for data qubits. err_budget = error_budget - distillation_error + if err_budget < 0: + raise ValueError( + f'distillation error {distillation_error} is larger than the error budget {error_budget}' + ) n_logical_qubits = math.ceil((1 + routing_overhead) * n_algo_qubits) data_unit_cells = n_logical_qubits * n_cycles target_err_per_round = err_budget / data_unit_cells diff --git a/qualtran/surface_code/ccz2t_cost_model_test.py b/qualtran/surface_code/ccz2t_cost_model_test.py index 329ebc626..6e984a1da 100644 --- a/qualtran/surface_code/ccz2t_cost_model_test.py +++ b/qualtran/surface_code/ccz2t_cost_model_test.py @@ -13,6 +13,7 @@ # limitations under the License. import numpy as np +import pytest from qualtran.surface_code.algorithm_summary import AlgorithmSummary from qualtran.surface_code.ccz2t_cost_model import get_ccz2t_costs @@ -30,3 +31,8 @@ def test_vs_spreadsheet(): np.testing.assert_allclose(re.failure_prob, 0.0084, rtol=1e-3) np.testing.assert_allclose(re.footprint, 4.00e5, rtol=1e-3) np.testing.assert_allclose(re.duration_hr, 7.53, rtol=1e-3) + + +def test_invalid_input(): + with pytest.raises(ValueError): + _ = get_ccz2t_costs(n_magic=AlgorithmSummary(toffoli_gates=3.2e10), n_algo_qubits=2196) From b4e924002169fee3b67e6b360d0b3b1a768f7770 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Fri, 1 Dec 2023 22:54:59 +0000 Subject: [PATCH 19/20] address comments --- qualtran/surface_code/ccz2t_cost_model.py | 6 +++--- qualtran/surface_code/data_block.py | 2 +- .../quantum_error_correction_scheme_summary.py | 10 +++++----- .../quantum_error_correction_scheme_summary_test.py | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/qualtran/surface_code/ccz2t_cost_model.py b/qualtran/surface_code/ccz2t_cost_model.py index a29b79286..fab5e9f13 100644 --- a/qualtran/surface_code/ccz2t_cost_model.py +++ b/qualtran/surface_code/ccz2t_cost_model.py @@ -39,7 +39,7 @@ class CCZ2TFactory(MagicStateFactory): distillation_l1_d: int = 15 distillation_l2_d: int = 31 - qec_scheme: qec.QuantumErrorCorrectionSchemeSummary = qec.FowlerSuperConductingQubits + qec_scheme: qec.QuantumErrorCorrectionSchemeSummary = qec.FowlerSuperconductingQubits # ------------------------------------------------------------------------------- # ---- Level 0 --------- @@ -214,13 +214,13 @@ def get_ccz2t_costs( n_logical_qubits = math.ceil((1 + routing_overhead) * n_algo_qubits) data_unit_cells = n_logical_qubits * n_cycles target_err_per_round = err_budget / data_unit_cells - data_d = qec.FowlerSuperConductingQubits.code_distance_from_budget( + data_d = qec.FowlerSuperconductingQubits.code_distance_from_budget( physical_error_rate=phys_err, budget=target_err_per_round ) data_block = SimpleDataBlock( data_d=data_d, routing_overhead=routing_overhead, - qec_scheme=qec.FowlerSuperConductingQubits, + qec_scheme=qec.FowlerSuperconductingQubits, ) data_error = data_block.data_error( diff --git a/qualtran/surface_code/data_block.py b/qualtran/surface_code/data_block.py index 23aee958c..319e7592b 100644 --- a/qualtran/surface_code/data_block.py +++ b/qualtran/surface_code/data_block.py @@ -54,7 +54,7 @@ class SimpleDataBlock(DataBlock): data_d: int routing_overhead: float = 0.5 - qec_scheme: qec.QuantumErrorCorrectionSchemeSummary = qec.FowlerSuperConductingQubits + qec_scheme: qec.QuantumErrorCorrectionSchemeSummary = qec.FowlerSuperconductingQubits def n_logical_qubits(self, n_algo_qubits: int) -> int: """Number of logical qubits including overhead. diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 06494e8d6..35ea696d2 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -71,7 +71,7 @@ def logical_error_rate(self, code_distance: int, physical_error_rate: float) -> def code_distance_from_budget(self, physical_error_rate: float, budget: float) -> int: """Get the code distance that keeps one below the logical error `budget`.""" - # See: `error_at()`. p_l = a Λ^(-r) where r = (d+1)/2 + # See: `logical_error_rate()`. p_l = a Λ^(-r) where r = (d+1)/2 # Which we invert: r = ln(p_l/a) / ln(1/Λ) r = math.log(budget / self.error_rate_scaler) / math.log( physical_error_rate / self.error_rate_threshold @@ -83,11 +83,11 @@ def code_distance_from_budget(self, physical_error_rate: float, budget: float) - @abc.abstractmethod def physical_qubits(self, code_distance: int) -> int: - """The number of physical qubits used by the error detection circuit.""" + """The number of physical qubits per logical qubit used by the error detection circuit.""" @abc.abstractmethod def error_detection_circuit_time_us(self, code_distance: int) -> float: - """The time of a quantum error detection cycle in seconds.""" + """The time of a quantum error detection cycle in microseconds.""" @frozen @@ -108,14 +108,14 @@ def error_detection_circuit_time_us(self, code_distance: int) -> float: return self.single_stabilizer_time_us * code_distance -BeverlandSuperConductingQubits = SimpliedSurfaceCode( +BeverlandSuperconductingQubits = SimpliedSurfaceCode( error_rate_scaler=0.03, error_rate_threshold=0.01, single_stabilizer_time_us=0.4, # Equals 4*t_gate+2*t_meas where t_gate=50ns and t_meas=100ns. reference='https://arxiv.org/abs/2211.07629', ) -FowlerSuperConductingQubits = SimpliedSurfaceCode( +FowlerSuperconductingQubits = SimpliedSurfaceCode( error_rate_scaler=0.1, error_rate_threshold=0.01, single_stabilizer_time_us=1, diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py index 20a411079..77e98bea8 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary_test.py @@ -18,17 +18,17 @@ from qualtran.surface_code import quantum_error_correction_scheme_summary as qecs -@pytest.mark.parametrize('qec,want', [(qecs.BeverlandSuperConductingQubits, 3e-4)]) +@pytest.mark.parametrize('qec,want', [(qecs.BeverlandSuperconductingQubits, 3e-4)]) def test_logical_error_rate(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): assert qec.logical_error_rate(3, 1e-3) == pytest.approx(want) -@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 242]]) +@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperconductingQubits, 242]]) def test_physical_qubits(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: int): assert qec.physical_qubits(11) == want -@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperConductingQubits, 4.8]]) +@pytest.mark.parametrize('qec,want', [[qecs.BeverlandSuperconductingQubits, 4.8]]) def test_error_detection_cycle_time(qec: qecs.QuantumErrorCorrectionSchemeSummary, want: float): assert qec.error_detection_circuit_time_us(12) == pytest.approx(want) @@ -37,19 +37,19 @@ def test_invert_error_at(): phys_err = 1e-3 budgets = np.logspace(-1, -18) for budget in budgets: - d = qecs.FowlerSuperConductingQubits.code_distance_from_budget( + d = qecs.FowlerSuperconductingQubits.code_distance_from_budget( physical_error_rate=phys_err, budget=budget ) assert d % 2 == 1 assert ( - qecs.FowlerSuperConductingQubits.logical_error_rate( + qecs.FowlerSuperconductingQubits.logical_error_rate( physical_error_rate=phys_err, code_distance=d ) <= budget ) if d > 3: assert ( - qecs.FowlerSuperConductingQubits.logical_error_rate( + qecs.FowlerSuperconductingQubits.logical_error_rate( physical_error_rate=phys_err, code_distance=d - 2 ) > budget From b61d688e0f43f8a3f90f7c2d08da80b04408ba5c Mon Sep 17 00:00:00 2001 From: Noureldin Date: Fri, 1 Dec 2023 22:59:55 +0000 Subject: [PATCH 20/20] style --- .../surface_code/quantum_error_correction_scheme_summary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qualtran/surface_code/quantum_error_correction_scheme_summary.py b/qualtran/surface_code/quantum_error_correction_scheme_summary.py index 35ea696d2..3e54522db 100644 --- a/qualtran/surface_code/quantum_error_correction_scheme_summary.py +++ b/qualtran/surface_code/quantum_error_correction_scheme_summary.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - import abc import math +from typing import Optional from attrs import field, frozen @@ -42,7 +42,7 @@ class QuantumErrorCorrectionSchemeSummary(abc.ABC): error_rate_scaler: float = field(repr=lambda x: f'{x:g}') error_rate_threshold: float = field(repr=lambda x: f'{x:g}') - reference: str | None = None + reference: Optional[str] = None def logical_error_rate(self, code_distance: int, physical_error_rate: float) -> float: """Logical error suppressed with code distance for this physical error rate.