From c3ffd19c2dfaefef3cff312c0e1b00745629b9b7 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 5 Oct 2023 16:16:01 -0700 Subject: [PATCH 01/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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/33] 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. From 5422c86b9b8c70a85db7b565f51c3753d278c62f Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Tue, 5 Dec 2023 16:16:06 -0800 Subject: [PATCH 21/33] add azure model --- qualtran/surface_code/azure_cost_model.py | 98 ++++++++++++++ .../surface_code/azure_cost_model_test.py | 120 ++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 qualtran/surface_code/azure_cost_model.py create mode 100644 qualtran/surface_code/azure_cost_model_test.py diff --git a/qualtran/surface_code/azure_cost_model.py b/qualtran/surface_code/azure_cost_model.py new file mode 100644 index 000000000..51c4d1894 --- /dev/null +++ b/qualtran/surface_code/azure_cost_model.py @@ -0,0 +1,98 @@ +# 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 + +from qualtran.surface_code.algorithm_summary import AlgorithmSummary +from qualtran.surface_code.quantum_error_correction_scheme_summary import ( + QuantumErrorCorrectionSchemeSummary, +) +from qualtran.surface_code.rotation_cost_model import RotationCostModel + + +def logical_qubits(algorithm_specs: AlgorithmSummary) -> int: + """Number of logical qubits needed for the algorithm. + + Source: Equation D1 in https://arxiv.org/abs/2211.07629. + + Args: + algorithm_specs: A summary of an algorithm/circuit. + """ + q_alg = algorithm_specs.algorithm_qubits + return 2 * q_alg + math.ceil(math.sqrt(8 * q_alg)) + 1 + + +def minimum_time_steps( + error_budget: float, alg: AlgorithmSummary, rotation_model: RotationCostModel +) -> int: + """Minimum number of time steps needed for the algorithm. + + Source: Equation D3 in https://arxiv.org/abs/2211.07629. + + Args: + error_budget: Error Budget. + alg: A summary of an algorithm/circuit. + rotation_model: Cost model used to compute the number of T gates + needed to approximate rotations. + """ + c_min = alg.measurements + alg.rotation_gates + alg.t_gates + 3 * alg.toffoli_gates + eps_syn = error_budget / 3 + c_min += ( + alg.rotation_circuit_depth + * rotation_model.rotation_cost(eps_syn / alg.rotation_gates).t_gates + ) + return c_min + + +def code_distance( + error_budget: float, + time_steps: float, + alg: AlgorithmSummary, + qec: QuantumErrorCorrectionSchemeSummary, + physical_error_rate: float, +) -> int: + """Minimum code distance needed to run the algorithm within the error budget. + + Source: -Corrected- E2 from https://arxiv.org/abs/2211.07629. + + Args: + error_budget: Error Budget. + time_steps: Number of time steps used to run the algorithm. + alg: A summary of an algorithm/circuit. + qec: Quantum Error Correction Scheme. + physical_parameters: Physical Assumptions. + """ + q = logical_qubits(alg) + return qec.code_distance_from_budget(physical_error_rate, error_budget / (3 * q * time_steps)) + + +def t_states( + error_budget: float, alg: AlgorithmSummary, rotation_model: RotationCostModel +) -> float: + """Total number of T states consumed by the algorithm. + + Source: D4 in https://arxiv.org/abs/2211.07629. + + Args: + error_budget: Error Budget. + alg: A summary of an algorithm/circuit. + rotation_model: Cost model used to compute the number of T gates + needed to approximate rotations. + """ + eps_syn = error_budget / 3 + return ( + alg.t_gates + + 4 * alg.toffoli_gates + + alg.rotation_gates * rotation_model.rotation_cost(eps_syn / alg.rotation_gates).t_gates + ) diff --git a/qualtran/surface_code/azure_cost_model_test.py b/qualtran/surface_code/azure_cost_model_test.py new file mode 100644 index 000000000..f213649da --- /dev/null +++ b/qualtran/surface_code/azure_cost_model_test.py @@ -0,0 +1,120 @@ +# 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 +import pytest +from attrs import frozen + +from qualtran.surface_code import azure_cost_model +from qualtran.surface_code.algorithm_summary import AlgorithmSummary +from qualtran.surface_code.quantum_error_correction_scheme_summary import ( + BeverlandSuperconductingQubits, +) +from qualtran.surface_code.rotation_cost_model import BeverlandEtAlRotationCost + + +@frozen +class Test: + alg: AlgorithmSummary + q_alg: float + + error_budget: float + c_min: float + + time_steps: float + code_distance: float + + t_states: float + +_TESTS = [ + Test( + alg=AlgorithmSummary( + algorithm_qubits=100, + rotation_gates=30100, + measurements=1.4 * 10**6, + rotation_circuit_depth=501, + ), + q_alg=230, + error_budget=1e-3, + c_min=1.5e6, + time_steps=1.5e5, + code_distance=9, + t_states=6e5, + ), + Test( + alg=AlgorithmSummary( + algorithm_qubits=1318, + rotation_gates=2.06e8, + measurements=1.37e9, + rotation_circuit_depth=2.05e8, + toffoli_gates=1.35e11, + t_gates=5.53e7, + ), + q_alg=2740, + error_budget=1e-2, + c_min=4.1e11, + time_steps=4.1e11, + code_distance=17, + t_states=5.44e11, + ), + Test( + alg=AlgorithmSummary( + algorithm_qubits=12581, + rotation_gates=12, + measurements=1.08e9, + rotation_circuit_depth=12, + toffoli_gates=3.73e10, + t_gates=12, + ), + q_alg=25481, + error_budget=1 / 3, + c_min=1.23e11, + time_steps=1.23e10, + code_distance=13, + t_states=1.49e11, + ), +] + + +@pytest.mark.parametrize('test', _TESTS) +def test_logical_qubits(test: Test): + assert azure_cost_model.logical_qubits(test.alg) == test.q_alg + + +@pytest.mark.parametrize('test', _TESTS) +def test_minimum_time_step(test: Test): + got = azure_cost_model.minimum_time_steps( + test.error_budget, test.alg, rotation_model=BeverlandEtAlRotationCost + ) + assert got == pytest.approx(test.c_min, rel=1e-1) + + +@pytest.mark.parametrize('test', _TESTS) +def test_code_distance(test: Test): + got = azure_cost_model.code_distance( + test.error_budget, + test.time_steps, + test.alg, + qec=BeverlandSuperconductingQubits, + physical_error_rate=1e-4, + ) + assert got == test.code_distance + + +@pytest.mark.parametrize('test', _TESTS) +def test_t_states(test: Test): + got = azure_cost_model.t_states( + test.error_budget, test.alg, rotation_model=BeverlandEtAlRotationCost + ) + assert got == pytest.approx(test.t_states, rel=1e-2) From f87a73fb5e8a444030e1fbd7e3cfb4828c4bde41 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 6 Dec 2023 16:00:26 -0800 Subject: [PATCH 22/33] Add Azure model --- qualtran/surface_code/azure_cost_model.ipynb | 714 ++++++++++++++++++ qualtran/surface_code/azure_cost_model.py | 8 +- .../surface_code/azure_cost_model_test.py | 26 +- 3 files changed, 731 insertions(+), 17 deletions(-) create mode 100644 qualtran/surface_code/azure_cost_model.ipynb diff --git a/qualtran/surface_code/azure_cost_model.ipynb b/qualtran/surface_code/azure_cost_model.ipynb new file mode 100644 index 000000000..f93a10a0e --- /dev/null +++ b/qualtran/surface_code/azure_cost_model.ipynb @@ -0,0 +1,714 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Azure Cost Model\n", + "In this notebook, we go through the cost model in \"Assessing requirements to scale to practical quantum advantage\" by [Beverland et al](https://arxiv.org/abs/2211.07629) to reproduce the estimated costs in Appendix F." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Azure cost model has 5 inputs:\n", + "1. The physical assumptions about the hardware (e.g. error rate, the latency of Clifford and measurement operations, ...etc).\n", + "1. A summary of the circuit/algorithm to execute (e.g. number of T gates, ..etc).\n", + "1. The magic state factory (e.g. number of qubits consumed by it, its error rate, ...etc)\n", + "1. Cost model of Approximating rotations using T operations up to error $\\epsilon$\n", + "1. The quantum error correction scheme.\n", + "\n", + "We take a look at each of these and then reproduce the results of Appendix F." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The Inputs\n", + "### Physical Parameters\n", + "These are assumptions about the quantum hardware and are:\n", + "- `t_gate`: Latency of Clifford gates. \n", + "- `t_meas`: Latency of Measurement operations.\n", + "- `physical_error_rate`: Physical error rate ($p$).\n", + "\n", + "These parameters are used to compute other quantities such as the time for a single stabilizer round. In Qualtran these are represented by the `PhysicalParameters` dataclass." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.surface_code.physical_parameters import BeverlandEtAl\n", + "\n", + "BeverlandEtAl" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Algorithm Summary\n", + "This is a summary of the circuit or algorithm to execute. This summary is several simple counts:\n", + "- `algorithm_qubits`: Number of algorithm qubits.\n", + "- `measurements`: Number of Clifford measurements ($M_R$).\n", + "- `t_gates`: Number of T gates ($M_T$).\n", + "- `toffoli_gates`: Number of Toffoli gates ($M_{Tof}$).\n", + "- `rotation_gates`: Number of Rotations ($M_R$).\n", + "- `rotation_circuit_depth`: Depth of rotation circuit ($D_R$).\n", + "\n", + "Note: where we add the symbol used to refer to the quantity in the paper in parentheses.\n", + "\n", + "In Qualtran the algorithm specs are represented by the data class `qualtran.surface_code.AlgorithmSummary`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.surface_code.algorithm_summary import AlgorithmSummary\n", + "\n", + "shor_specs = AlgorithmSummary(\n", + " algorithm_qubits=12581,\n", + " rotation_gates=12,\n", + " measurements=1.08e9,\n", + " rotation_circuit_depth=12,\n", + " toffoli_gates=3.73e10,\n", + " t_gates=12,\n", + ")\n", + "shor_specs" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Magic State Factory\n", + "\n", + "The magic state factory in our case is a T-state factory. The paper describes 15-to-1 factories in Appendix C, but only the overall summary in Table VII in terms of physical qubits count and generation time is used in estimation in Appendix F." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Rotation Approximation Model\n", + "\n", + "This is a model that approximates the number of T gates needed to implement a rotation up to error $\\epsilon$. [Beverland et al](https://arxiv.org/abs/2211.07629) use the approximation model from [Kliuchnikov et al](https://arxiv.org/abs/2203.10064). The formula for the number of T gates used to approximate an angle up to error $\\epsilon$ is given by:\n", + "$$\n", + "a \\log_2{\\frac{1}{\\epsilon}} + b\n", + "$$\n", + "\n", + "Where $a$ and $b$ are constants that depend on the gate set and the approximation protocol. Table 1 of [Kliuchnikov et al](https://arxiv.org/abs/2203.10064) gives estimates for those constants for different combinations of gate sets and protocols.\n", + "\n", + "In [Beverland et al](https://arxiv.org/abs/2211.07629), Although they don't specify the approximation algorithm their constants of $a=0.53, b=5.3$ are closest to the mixed fallback approximation protocol with a Clifford+T gate set constants of $a=0.53, b=4.86$. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.surface_code.rotation_cost_model import BeverlandEtAlRotationCost\n", + "\n", + "BeverlandEtAlRotationCost" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quantum Error Correction Scheme\n", + "The quantum error correction scheme determines three things:\n", + "1. The logical error rate given a code distance and physical error rate $P(d)$.\n", + "1. The number of physical qubits needed per logical qubit $n(d)$.\n", + "1. The number of logical time steps $\\tau(d)$.\n", + "\n", + "Tabel V of [Beverland et al](https://arxiv.org/abs/2211.07629) lists how these are computed from the QEC scheme.\n", + "\n", + "In [Beverland et al](https://arxiv.org/abs/2211.07629), they use a gate-based QEC that has $P(d), n(d), \\tau(d)$ as:\n", + "$$\n", + "P(d) = 0.03 \\left ( \\frac{p}{0.01} \\right) ^ \\frac{d+1}{2}\\\\\n", + "n(d) = 2 d^2\\\\\n", + "\\tau(d) = \\textrm{\\{error detection circuit time\\}} \\cdot d\\\\\n", + "$$\n", + "\n", + "The error detection circuit time depends on several factors including the time to apply a Clifford, measurement and reset operations as well as classical processing.\n", + "\n", + "In [Beverland et al](https://arxiv.org/abs/2211.07629) Table V they don't take into account the classical processing part and assume that a reset takes the same time as a measurement leading to the formula:\n", + "$$\n", + "\\textrm{\\{error detection circuit time\\}} = 4t_\\textrm{gate} + 2t_\\textrm{meas}\n", + "$$\n", + "\n", + "Other authors (e.g. [Fowler, Gidney](https://arxiv.org/abs/1808.06709)) assume that the entire process takes a specific time (e.g. $\\approx 1\\mu s$).\n", + "\n", + "In Qualtran, we use \"error detection circuit time\" rather than fall to the low level hardware parameters. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.surface_code.quantum_error_correction_scheme_summary import (\n", + " BeverlandSuperconductingQubits,\n", + ")\n", + "\n", + "qec = BeverlandSuperconductingQubits\n", + "qec" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Resource Estimation\n", + "Now we move to reproduce the results in Appendix F." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quantum Dynamics\n", + "The algorithm specs of this circuit are given as:\n", + "- number of algorithm qubits: 100\n", + "- number of rotation gates: $30100$\n", + "- number of measurements: $1.4 \\times 10^6$\n", + "- number of T gates: $0$\n", + "- number of Toffoli gates: $0$\n", + "- depth of rotation circuit: $501$\n", + "\n", + "with an error budget $\\epsilon$ of 0.001" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "quantum_dynamics_specs = AlgorithmSummary(\n", + " algorithm_qubits=100,\n", + " rotation_gates=30100,\n", + " # Note in the paper the number of measurements\n", + " # has an extra zero which we assume to be a typo.\n", + " measurements=1.4e5,\n", + " rotation_circuit_depth=501,\n", + ")\n", + "quantum_dynamics_specs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.surface_code import azure_cost_model\n", + "\n", + "# First calculate the number of logical qubits (Eq. D1)\n", + "logical_qubits = azure_cost_model.logical_qubits(quantum_dynamics_specs)\n", + "print('Q =', logical_qubits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Calculate the minimum number of logical time steps (Eq D3)\n", + "error_budget = 0.001\n", + "c_min = azure_cost_model.minimum_time_steps(\n", + " error_budget=error_budget, alg=quantum_dynamics_specs, rotation_model=BeverlandEtAlRotationCost\n", + ")\n", + "print('C_min = %e' % c_min)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# And the number of needed T operations (Eq D4)\n", + "t_operations = azure_cost_model.t_states(\n", + " error_budget=error_budget, alg=quantum_dynamics_specs, rotation_model=BeverlandEtAlRotationCost\n", + ")\n", + "print('M = %e' % t_operations)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Comparing our esimates of $Q = 230, C_{min} = 1.8 \\times 10^5, M = 6 \\times 10^5$ to the paper estimates of \n", + "$Q = 230, C_{min} = 1.5 \\times 10^5, M = 2.4 \\times 10^6$. We find a match for $Q$ and $C_{min}$ however we are off by 4x for the number of T gates $M$.\n", + "\n", + "D4 gives the formula for $M$ as $$M = M_T + 4 M_{Tof} + M_R \\lceil A \\log_2{M_R/\\epsilon_{syn}} + B\\rceil$$\n", + "\n", + "Since $M_T = M_{Tof} = 0$, the only contribution to $M$ comes from rotations where $M_R = 30100, \\epsilon_{syn} = \\frac{10^{-3}}{3} , A = 0.53, B = 5.3$ which give our value of 6.02e5." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we estimate the code distance $d$. $d$ satisfies \n", + "$$\n", + "P(d) = a \\left ( \\frac{p}{p^*} \\right )^\\frac{d+1}{2} \n", + "$$\n", + "subject ot the constraint on the logical error rate of $QCP(d) = \\frac{\\epsilon}{3}$. Where $p$ is the physical error rate. $a$ and $p^*$ are constants determined by the QEC scheme." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = azure_cost_model.code_distance(\n", + " error_budget=error_budget,\n", + " time_steps=c_min,\n", + " alg=quantum_dynamics_specs,\n", + " qec=BeverlandSuperconductingQubits,\n", + " physical_error_rate=BeverlandEtAl.physical_error_rate,\n", + ")\n", + "print(f'{d=}')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Matching the surface code of $d = 9$. This leads to a total run time (Eq. E3) of 0.65s which is close to the time in the paper of 0.55s" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "'algorithm run time of %g seconds' % (qec.error_detection_circuit_time_us(d) * 1e-6 * c_min)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we examine the magic state factories. In [Beverland et al](https://arxiv.org/abs/2211.07629) for the quantum dynamics example we are given 199 factories each producing one T state every 46.8us at an error rate of 5.6e-11 while consuming 3240 qubits. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "num_factories = 199\n", + "factory_qubits = 3240" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Leading to a total number of physical qubits (from E6)\n", + "distillation_qubits = num_factories * factory_qubits\n", + "q = distillation_qubits + logical_qubits * qec.physical_qubits(d)\n", + "print('total number of physical qubits:', q)\n", + "print('percentage of distillation qubits: {}%'.format(round(distillation_qubits / q * 100, 1)))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our estimate of 0.68M physical qubits with 94.5% of them being consumed by the T states factories match exactly with the numbers in the paper." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quantum Chemistry\n", + "The algorithm specs of this circuit are given as:\n", + "- number of algorithm qubits: 1318\n", + "- number of rotation gates: $2.06 \\times 10^8$\n", + "- number of measurements: $1.37 \\times 10^9$\n", + "- number of T gates: $5.53 \\times 10^7$\n", + "- number of Toffoli gates: $1.35 \\times 10^{11}$\n", + "- depth of rotation circuit: $2.05 \\times 10^8$\n", + "\n", + "with an error budget of 0.01" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "quantum_chemistry_specs = AlgorithmSummary(\n", + " algorithm_qubits=1318,\n", + " rotation_gates=2.06e8,\n", + " measurements=1.37e9,\n", + " toffoli_gates=1.35e11,\n", + " t_gates=5.53e7,\n", + " rotation_circuit_depth=2.05e8,\n", + ")\n", + "quantum_chemistry_specs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "logical_qubits = azure_cost_model.logical_qubits(quantum_chemistry_specs)\n", + "print('Q =', logical_qubits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Calculate the minimum number of logical time steps (Eq D3)\n", + "error_budget = 0.01\n", + "c_min = azure_cost_model.minimum_time_steps(\n", + " error_budget=error_budget, alg=quantum_chemistry_specs, rotation_model=BeverlandEtAlRotationCost\n", + ")\n", + "print('C_{min} = %g' % c_min)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# And the number of needed T operations (Eq D4)\n", + "t_operations = azure_cost_model.t_states(\n", + " error_budget=error_budget, alg=quantum_chemistry_specs, rotation_model=BeverlandEtAlRotationCost\n", + ")\n", + "print('M = %g' % t_operations)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that our estimates match nicely to the paper estimates of \n", + "$$Q = 2740\\\\\n", + "C_{min} = 4.10 \\times 10^{11}\\\\\n", + "M = 5.44 \\times 10^{11}$$" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we estimate the code distance." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = azure_cost_model.code_distance(\n", + " error_budget=error_budget,\n", + " time_steps=c_min,\n", + " alg=quantum_chemistry_specs,\n", + " qec=qec,\n", + " physical_error_rate=BeverlandEtAl.physical_error_rate,\n", + ")\n", + "print(f'{d=}')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Again we match the code distance from the paper of $d = 17$. This leads to a total run time (Eq. E3) of" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_seconds = qec.error_detection_circuit_time_us(d) * 1e-6 * c_min\n", + "total_days = total_seconds / 3600 / 24\n", + "'algorithm run time of %g days' % (total_days)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We get a run time estimate of 32.4 days. In the paper, it says the run time is 1 month and 1 day." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we examine the magic state factories. In [Beverland et al](https://arxiv.org/abs/2211.07629) for the quantum chemistry example we are given 17 factories each producing one T state every 83.2us at an error rate of 2.13e-15 while consuming 16000 qubits. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "num_factories = 17\n", + "factory_qubits = 16000" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Leading to a total number of physical qubits (from E6)\n", + "distillation_qubits = num_factories * factory_qubits\n", + "q = distillation_qubits + logical_qubits * qec.physical_qubits(d)\n", + "print('total number of physical qubits: %g M' % round(q * 1e-6, 2))\n", + "print('percentage of distillation qubits: {}%'.format(round(distillation_qubits / q * 100, 1)))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our estimate of 1.86M physical qubits matches exactly with the paper's." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Shor Factoring\n", + "The algorithm specs of this circuit are given as:\n", + "- number of algorithm qubits: 12581\n", + "- number of rotation gates: $12$\n", + "- number of measurements: $1.08 \\times 10^9$\n", + "- number of T gates: 12\n", + "- number of Toffoli gates: $3.73 \\times 10^{10}$\n", + "- depth of rotation circuit: $12$\n", + "\n", + "with an error budget of 1/3" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "shor_specs = AlgorithmSummary(\n", + " algorithm_qubits=12581,\n", + " rotation_gates=12,\n", + " measurements=1.08e9,\n", + " rotation_circuit_depth=12,\n", + " # Note in the paper the number of Toffoli operations is 3.73e10.\n", + " # However we assume that the exponent has a typo and that the number is 3.73e9.\n", + " toffoli_gates=3.73e9,\n", + " t_gates=12,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "logical_qubits = azure_cost_model.logical_qubits(shor_specs)\n", + "print('Q =', logical_qubits)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Calculate the minimum number of logical time steps (Eq D3)\n", + "error_budget = 1 / 3\n", + "c_min = azure_cost_model.minimum_time_steps(\n", + " error_budget=error_budget, alg=shor_specs, rotation_model=BeverlandEtAlRotationCost\n", + ")\n", + "print('C_min = %e' % c_min)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# And the number of needed T operations (Eq D4)\n", + "t_operations = azure_cost_model.t_states(\n", + " error_budget=error_budget, alg=shor_specs, rotation_model=BeverlandEtAlRotationCost\n", + ")\n", + "print('M = %e' % t_operations)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our estimates of $Q = 25481, C_{min} = 1.23 \\cdot 10^{10}, M = 1.49 \\cdot 10^{10}$ match exactly with the estimates of the paper." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "d = azure_cost_model.code_distance(\n", + " error_budget=error_budget,\n", + " time_steps=c_min,\n", + " alg=shor_specs,\n", + " qec=qec,\n", + " physical_error_rate=BeverlandEtAl.physical_error_rate,\n", + ")\n", + "print(f'{d=}')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Matching the surface code of $d = 13$ in the paper." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_seconds = qec.error_detection_circuit_time_us(d) * 1e-6 * c_min\n", + "total_hours = total_seconds / 3600\n", + "h = int(total_hours)\n", + "m = (total_hours - h) * 60\n", + "'algorithm run time of %d hours %d' % (h, m)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our estimate runtime of 17h43m matches exactly with the estimate of the paper." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we examine the magic state factories. In [Beverland et al](https://arxiv.org/abs/2211.07629) for the quantum chemistry example we are given 18 factories each producing one T state every 72.8us at an error rate of 5.51e-13 while consuming 5760 qubits. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "num_factories = 18\n", + "factory_qubits = 5760" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Leading to a total number of physical qubits (from E6)\n", + "distillation_qubits = num_factories * factory_qubits\n", + "q = distillation_qubits + logical_qubits * qec.physical_qubits(d)\n", + "print('total number of physical qubits: %g M' % round(q * 1e-6, 2))\n", + "print('percentage of distillation qubits: {}%'.format(round(distillation_qubits / q * 100, 1)))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Our estimate of 8.72M physical qubits matches exactly with the paper." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "qualtran", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/qualtran/surface_code/azure_cost_model.py b/qualtran/surface_code/azure_cost_model.py index 51c4d1894..a8577ad93 100644 --- a/qualtran/surface_code/azure_cost_model.py +++ b/qualtran/surface_code/azure_cost_model.py @@ -30,7 +30,7 @@ def logical_qubits(algorithm_specs: AlgorithmSummary) -> int: algorithm_specs: A summary of an algorithm/circuit. """ q_alg = algorithm_specs.algorithm_qubits - return 2 * q_alg + math.ceil(math.sqrt(8 * q_alg)) + 1 + return math.ceil(2 * q_alg + math.sqrt(8 * q_alg) + 1) def minimum_time_steps( @@ -46,9 +46,9 @@ def minimum_time_steps( rotation_model: Cost model used to compute the number of T gates needed to approximate rotations. """ - c_min = alg.measurements + alg.rotation_gates + alg.t_gates + 3 * alg.toffoli_gates + c_min = math.ceil(alg.measurements + alg.rotation_gates + alg.t_gates + 3 * alg.toffoli_gates) eps_syn = error_budget / 3 - c_min += ( + c_min += math.ceil( alg.rotation_circuit_depth * rotation_model.rotation_cost(eps_syn / alg.rotation_gates).t_gates ) @@ -71,7 +71,7 @@ def code_distance( time_steps: Number of time steps used to run the algorithm. alg: A summary of an algorithm/circuit. qec: Quantum Error Correction Scheme. - physical_parameters: Physical Assumptions. + physical_error_rate: The physical error rate of the device. """ q = logical_qubits(alg) return qec.code_distance_from_budget(physical_error_rate, error_budget / (3 * q * time_steps)) diff --git a/qualtran/surface_code/azure_cost_model_test.py b/qualtran/surface_code/azure_cost_model_test.py index f213649da..3800cdc69 100644 --- a/qualtran/surface_code/azure_cost_model_test.py +++ b/qualtran/surface_code/azure_cost_model_test.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import numpy as np import pytest from attrs import frozen @@ -34,9 +33,10 @@ class Test: time_steps: float code_distance: float - + t_states: float + _TESTS = [ Test( alg=AlgorithmSummary( @@ -50,16 +50,16 @@ class Test: c_min=1.5e6, time_steps=1.5e5, code_distance=9, - t_states=6e5, + t_states=602000, ), Test( alg=AlgorithmSummary( algorithm_qubits=1318, - rotation_gates=2.06e8, - measurements=1.37e9, + t_gates=5.53e7, rotation_circuit_depth=2.05e8, + rotation_gates=2.06e8, toffoli_gates=1.35e11, - t_gates=5.53e7, + measurements=1.37e9, ), q_alg=2740, error_budget=1e-2, @@ -71,18 +71,18 @@ class Test: Test( alg=AlgorithmSummary( algorithm_qubits=12581, + t_gates=12, + rotation_circuit_depth=12, rotation_gates=12, + toffoli_gates=3.73e9, measurements=1.08e9, - rotation_circuit_depth=12, - toffoli_gates=3.73e10, - t_gates=12, ), q_alg=25481, error_budget=1 / 3, - c_min=1.23e11, + c_min=1.23e10, time_steps=1.23e10, code_distance=13, - t_states=1.49e11, + t_states=1.49e10, ), ] @@ -97,7 +97,7 @@ def test_minimum_time_step(test: Test): got = azure_cost_model.minimum_time_steps( test.error_budget, test.alg, rotation_model=BeverlandEtAlRotationCost ) - assert got == pytest.approx(test.c_min, rel=1e-1) + assert got == pytest.approx(test.c_min, rel=0.1) @pytest.mark.parametrize('test', _TESTS) @@ -117,4 +117,4 @@ def test_t_states(test: Test): got = azure_cost_model.t_states( test.error_budget, test.alg, rotation_model=BeverlandEtAlRotationCost ) - assert got == pytest.approx(test.t_states, rel=1e-2) + assert got == pytest.approx(test.t_states, rel=0.1) From 8d42dc5a0805ce51c8bd0e90e1da43abf64eae5e Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 6 Dec 2023 16:07:53 -0800 Subject: [PATCH 23/33] nit --- qualtran/surface_code/azure_cost_model.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/qualtran/surface_code/azure_cost_model.py b/qualtran/surface_code/azure_cost_model.py index a8577ad93..a80157866 100644 --- a/qualtran/surface_code/azure_cost_model.py +++ b/qualtran/surface_code/azure_cost_model.py @@ -24,7 +24,7 @@ def logical_qubits(algorithm_specs: AlgorithmSummary) -> int: """Number of logical qubits needed for the algorithm. - Source: Equation D1 in https://arxiv.org/abs/2211.07629. + Source: Equation D1 in https://arxiv.org/abs/2211.07629. Args: algorithm_specs: A summary of an algorithm/circuit. @@ -38,7 +38,7 @@ def minimum_time_steps( ) -> int: """Minimum number of time steps needed for the algorithm. - Source: Equation D3 in https://arxiv.org/abs/2211.07629. + Source: Equation D3 in https://arxiv.org/abs/2211.07629. Args: error_budget: Error Budget. @@ -62,9 +62,13 @@ def code_distance( qec: QuantumErrorCorrectionSchemeSummary, physical_error_rate: float, ) -> int: - """Minimum code distance needed to run the algorithm within the error budget. + r"""Minimum code distance needed to run the algorithm within the error budget. - Source: -Corrected- E2 from https://arxiv.org/abs/2211.07629. + This is the code distance $d$ that satisfies $QCP = \epsilon/3$. Where: + $\epsilon$ is the error budget. + Q is the number of logical qubits. + C is the number of time steps. + P(d) is the logical error rate. Args: error_budget: Error Budget. @@ -82,7 +86,7 @@ def t_states( ) -> float: """Total number of T states consumed by the algorithm. - Source: D4 in https://arxiv.org/abs/2211.07629. + Source: D4 in https://arxiv.org/abs/2211.07629. Args: error_budget: Error Budget. From 61c56a2270f67a86b8abd23ccdd55de6ca0b0495 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 6 Dec 2023 16:23:25 -0800 Subject: [PATCH 24/33] docs --- qualtran/surface_code/azure_cost_model.py | 35 +++++++++++++++++++---- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/qualtran/surface_code/azure_cost_model.py b/qualtran/surface_code/azure_cost_model.py index a80157866..afa18b99d 100644 --- a/qualtran/surface_code/azure_cost_model.py +++ b/qualtran/surface_code/azure_cost_model.py @@ -22,7 +22,12 @@ def logical_qubits(algorithm_specs: AlgorithmSummary) -> int: - """Number of logical qubits needed for the algorithm. + r"""Number of logical qubits needed for the algorithm. + + Equals: + $$ + 2 Q_\mathrm{alg} + \lceil \sqrt{8 Q_\mathrm{alg}} \rceil + 1 + $$ Source: Equation D1 in https://arxiv.org/abs/2211.07629. @@ -36,8 +41,19 @@ def logical_qubits(algorithm_specs: AlgorithmSummary) -> int: def minimum_time_steps( error_budget: float, alg: AlgorithmSummary, rotation_model: RotationCostModel ) -> int: - """Minimum number of time steps needed for the algorithm. - + r"""Minimum number of time steps needed for the algorithm. + + Equals + $$ + M_\mathrm{meas} + M_R + M_T + 3 M_\mathrm{Tof} + D_R \textrm{rotation cost} + $$ + Where: + $M_\mathrm{meas}$ is the number of measurements. + $M_R$ is the number of rotations. + $M_T$ is the number of T operations. + $M_mathrm{Tof}$ is the number of toffoli operations. + $D_R$ is the depth of the rotation circuit. + $\textrm{rotation cost}$ is the number of T operations needed to approximate a rotation to $\epsilon/(3*M_R)$. Source: Equation D3 in https://arxiv.org/abs/2211.07629. Args: @@ -84,8 +100,17 @@ def code_distance( def t_states( error_budget: float, alg: AlgorithmSummary, rotation_model: RotationCostModel ) -> float: - """Total number of T states consumed by the algorithm. - + r"""Total number of T states consumed by the algorithm. + + Equals + $$ + M_T + 4 M_\mathrm{Tof} + M_R \textrm{rotation cost} + $$ + Where: + $M_R$ is the number of rotations. + $M_T$ is the number of T operations. + $M_mathrm{Tof}$ is the number of toffoli operations. + $\textrm{rotation cost}$ is the number of T operations needed to approximate a rotation to $\epsilon/(3*M_R)$. Source: D4 in https://arxiv.org/abs/2211.07629. Args: From 23a8fbb667362fe7f9231af86dbb90b04559bcc8 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Wed, 6 Dec 2023 16:32:14 -0800 Subject: [PATCH 25/33] docs --- qualtran/surface_code/azure_cost_model.ipynb | 26 ++++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/qualtran/surface_code/azure_cost_model.ipynb b/qualtran/surface_code/azure_cost_model.ipynb index f93a10a0e..2b9b488ce 100644 --- a/qualtran/surface_code/azure_cost_model.ipynb +++ b/qualtran/surface_code/azure_cost_model.ipynb @@ -57,14 +57,14 @@ "source": [ "### Algorithm Summary\n", "This is a summary of the circuit or algorithm to execute. This summary is several simple counts:\n", - "- `algorithm_qubits`: Number of algorithm qubits.\n", - "- `measurements`: Number of Clifford measurements ($M_R$).\n", - "- `t_gates`: Number of T gates ($M_T$).\n", - "- `toffoli_gates`: Number of Toffoli gates ($M_{Tof}$).\n", - "- `rotation_gates`: Number of Rotations ($M_R$).\n", - "- `rotation_circuit_depth`: Depth of rotation circuit ($D_R$).\n", + "- `algorithm_qubits` is the number of algorithm qubits.\n", + "- `measurements` is the umber of Clifford measurements ($M_R$).\n", + "- `t_gates` is the number of T gates ($M_T$).\n", + "- `toffoli_gates` is the number of Toffoli gates ($M_{Tof}$).\n", + "- `rotation_gates` is the number of Rotations ($M_R$).\n", + "- `rotation_circuit_depth` is the depth of rotation circuit ($D_R$).\n", "\n", - "Note: where we add the symbol used to refer to the quantity in the paper in parentheses.\n", + "Note: The symbol in parentheses corresponds to the notation in the paper\n", "\n", "In Qualtran the algorithm specs are represented by the data class `qualtran.surface_code.AlgorithmSummary`." ] @@ -77,15 +77,9 @@ "source": [ "from qualtran.surface_code.algorithm_summary import AlgorithmSummary\n", "\n", - "shor_specs = AlgorithmSummary(\n", - " algorithm_qubits=12581,\n", - " rotation_gates=12,\n", - " measurements=1.08e9,\n", - " rotation_circuit_depth=12,\n", - " toffoli_gates=3.73e10,\n", - " t_gates=12,\n", - ")\n", - "shor_specs" + "# A circuit that applies a T then measures the qubit.\n", + "circuit_summary = AlgorithmSummary(algorithm_qubits=1, t_gates=1, measurements=1)\n", + "circuit_summary" ] }, { From 66dcc24ccc8c5e9a0706a14d97a51d447a1fcacb Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 7 Dec 2023 11:30:16 -0800 Subject: [PATCH 26/33] add notebook to index --- docs/index.rst | 10 ++++++++++ docs/surface_code/index.rst | 14 ++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 docs/surface_code/index.rst diff --git a/docs/index.rst b/docs/index.rst index 2f605403b..9bf1d332f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -58,3 +58,13 @@ This section of the docs includes an API reference for all symbols in the librar :hidden: reference/index.rst + +:ref: `surface_code` +``qualtran.surface_code`` contains implementations of classes and routines useful for estimating +the cost of running fault-tolerant quantum algorithms using surface codes for error correction. + +.. toctree:: + :maxdepth: 2 + :hidden: + + surface_code/index.rst \ No newline at end of file diff --git a/docs/surface_code/index.rst b/docs/surface_code/index.rst new file mode 100644 index 000000000..7f21d3842 --- /dev/null +++ b/docs/surface_code/index.rst @@ -0,0 +1,14 @@ +.. surface_code: + +Surface Code +============= + +``qualtran.surface_code`` contains implementations of classes and routines useful for estimating +the cost of running fault-tolerant quantum algorithms using surface codes for error correction. + + +.. toctree:: + :maxdepth: 1 + :caption: Estimation Models: + + azure_model.ipynb \ No newline at end of file From effcc8c76bc4b772b3238d3cae08f5be35d59f64 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 7 Dec 2023 11:33:39 -0800 Subject: [PATCH 27/33] nit --- docs/index.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 9bf1d332f..6837cccc9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -48,23 +48,24 @@ and high-level quantum programs. :ref:`Read more... ` bloqs/index.rst -:ref:`reference` -------------------------------- - -This section of the docs includes an API reference for all symbols in the library. -:ref:`Go to Reference... ` +:ref: `surface_code` +``qualtran.surface_code`` contains implementations of classes and routines useful for estimating +the cost of running fault-tolerant quantum algorithms using surface codes for error correction. .. toctree:: + :maxdepth: 1 :hidden: - reference/index.rst + surface_code/index.rst -:ref: `surface_code` -``qualtran.surface_code`` contains implementations of classes and routines useful for estimating -the cost of running fault-tolerant quantum algorithms using surface codes for error correction. + +:ref:`reference` +------------------------------- + +This section of the docs includes an API reference for all symbols in the library. +:ref:`Go to Reference... ` .. toctree:: - :maxdepth: 2 :hidden: - surface_code/index.rst \ No newline at end of file + reference/index.rst \ No newline at end of file From 8e8a7f4be713f51704cac420debcaf2e914cd16b Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 7 Dec 2023 11:37:32 -0800 Subject: [PATCH 28/33] nit --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 6837cccc9..c290499a2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -68,4 +68,4 @@ This section of the docs includes an API reference for all symbols in the librar .. toctree:: :hidden: - reference/index.rst \ No newline at end of file + reference/index.rst From c8fa6148aa4fd90aeeea77916b8be7e08759a0e4 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 7 Dec 2023 11:39:35 -0800 Subject: [PATCH 29/33] nit --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index c290499a2..56d241edd 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -48,7 +48,7 @@ and high-level quantum programs. :ref:`Read more... ` bloqs/index.rst -:ref: `surface_code` +:ref:`surface_code` ``qualtran.surface_code`` contains implementations of classes and routines useful for estimating the cost of running fault-tolerant quantum algorithms using surface codes for error correction. From 5e843ee151c380fbdc61efc1c6998b15388fc94a Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Thu, 7 Dec 2023 11:40:34 -0800 Subject: [PATCH 30/33] nit --- docs/index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 56d241edd..472f1c997 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -49,6 +49,8 @@ and high-level quantum programs. :ref:`Read more... ` :ref:`surface_code` +------------------------------ + ``qualtran.surface_code`` contains implementations of classes and routines useful for estimating the cost of running fault-tolerant quantum algorithms using surface codes for error correction. From 9eaea79993158fedeacc82f9559a592753ff2c63 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Fri, 8 Dec 2023 17:07:14 -0800 Subject: [PATCH 31/33] address comments --- qualtran/surface_code/azure_cost_model.ipynb | 95 ++++++++++---------- qualtran/surface_code/physical_parameters.py | 2 +- 2 files changed, 50 insertions(+), 47 deletions(-) diff --git a/qualtran/surface_code/azure_cost_model.ipynb b/qualtran/surface_code/azure_cost_model.ipynb index 2b9b488ce..ef6bc60ab 100644 --- a/qualtran/surface_code/azure_cost_model.ipynb +++ b/qualtran/surface_code/azure_cost_model.ipynb @@ -6,7 +6,9 @@ "metadata": {}, "source": [ "# Azure Cost Model\n", - "In this notebook, we go through the cost model in \"Assessing requirements to scale to practical quantum advantage\" by [Beverland et al](https://arxiv.org/abs/2211.07629) to reproduce the estimated costs in Appendix F." + "In this notebook, we go through the cost model in \"Assessing requirements to scale to practical quantum advantage\" by [Beverland et al](https://arxiv.org/abs/2211.07629) to reproduce the estimated costs in Appendix F.\n", + "\n", + "The paper describes the formulas used for estimating cost in the various appendices. The final estimation procedure is put together in Appendix E. Throughout, we reproduce the costs from the paper; in particular Appendix F." ] }, { @@ -15,10 +17,10 @@ "metadata": {}, "source": [ "The Azure cost model has 5 inputs:\n", - "1. The physical assumptions about the hardware (e.g. error rate, the latency of Clifford and measurement operations, ...etc).\n", - "1. A summary of the circuit/algorithm to execute (e.g. number of T gates, ..etc).\n", - "1. The magic state factory (e.g. number of qubits consumed by it, its error rate, ...etc)\n", - "1. Cost model of Approximating rotations using T operations up to error $\\epsilon$\n", + "1. The physical assumptions about the hardware (e.g. error rate, the latency of Clifford and measurement operations, etc).\n", + "1. A summary of the circuit/algorithm to execute (e.g. number of T gates, etc).\n", + "1. The magic state factory (e.g. number of qubits consumed by it, its error rate, etc).\n", + "1. Cost model of Approximating rotations using T operations up to error $\\epsilon$.\n", "1. The quantum error correction scheme.\n", "\n", "We take a look at each of these and then reproduce the results of Appendix F." @@ -32,11 +34,11 @@ "## The Inputs\n", "### Physical Parameters\n", "These are assumptions about the quantum hardware and are:\n", - "- `t_gate`: Latency of Clifford gates. \n", - "- `t_meas`: Latency of Measurement operations.\n", + "- `t_gate_us`: Latency time of Clifford gates. \n", + "- `t_meas_us`: Latency time of Measurement operations.\n", "- `physical_error_rate`: Physical error rate ($p$).\n", "\n", - "These parameters are used to compute other quantities such as the time for a single stabilizer round. In Qualtran these are represented by the `PhysicalParameters` dataclass." + "In Qualtran these are represented by the `PhysicalParameters` dataclass." ] }, { @@ -45,9 +47,9 @@ "metadata": {}, "outputs": [], "source": [ - "from qualtran.surface_code.physical_parameters import BeverlandEtAl\n", + "from qualtran.surface_code.physical_parameters import BEVERLAND_PARAMS\n", "\n", - "BeverlandEtAl" + "BEVERLAND_PARAMS" ] }, { @@ -58,10 +60,10 @@ "### Algorithm Summary\n", "This is a summary of the circuit or algorithm to execute. This summary is several simple counts:\n", "- `algorithm_qubits` is the number of algorithm qubits.\n", - "- `measurements` is the umber of Clifford measurements ($M_R$).\n", + "- `measurements` is the number of Clifford measurements ($M_R$).\n", "- `t_gates` is the number of T gates ($M_T$).\n", "- `toffoli_gates` is the number of Toffoli gates ($M_{Tof}$).\n", - "- `rotation_gates` is the number of Rotations ($M_R$).\n", + "- `rotation_gates` is the number of rotations ($M_R$).\n", "- `rotation_circuit_depth` is the depth of rotation circuit ($D_R$).\n", "\n", "Note: The symbol in parentheses corresponds to the notation in the paper\n", @@ -89,7 +91,7 @@ "source": [ "### Magic State Factory\n", "\n", - "The magic state factory in our case is a T-state factory. The paper describes 15-to-1 factories in Appendix C, but only the overall summary in Table VII in terms of physical qubits count and generation time is used in estimation in Appendix F." + "The magic state factory in our case is a T-state factory. The paper describes 15-to-1 factories in Appendix C, but only the overall summary in Table VII in terms of physical qubit count and generation time is used in estimation in Appendix F." ] }, { @@ -99,14 +101,14 @@ "source": [ "### Rotation Approximation Model\n", "\n", - "This is a model that approximates the number of T gates needed to implement a rotation up to error $\\epsilon$. [Beverland et al](https://arxiv.org/abs/2211.07629) use the approximation model from [Kliuchnikov et al](https://arxiv.org/abs/2203.10064). The formula for the number of T gates used to approximate an angle up to error $\\epsilon$ is given by:\n", + "This is a model that approximates the number of T gates needed to implement a rotation up to error $\\epsilon$. In the paper they use the approximation model from [Kliuchnikov et al](https://arxiv.org/abs/2203.10064). The formula for the number of T gates used to approximate an angle up to error $\\epsilon$ is given by:\n", "$$\n", "a \\log_2{\\frac{1}{\\epsilon}} + b\n", "$$\n", "\n", "Where $a$ and $b$ are constants that depend on the gate set and the approximation protocol. Table 1 of [Kliuchnikov et al](https://arxiv.org/abs/2203.10064) gives estimates for those constants for different combinations of gate sets and protocols.\n", "\n", - "In [Beverland et al](https://arxiv.org/abs/2211.07629), Although they don't specify the approximation algorithm their constants of $a=0.53, b=5.3$ are closest to the mixed fallback approximation protocol with a Clifford+T gate set constants of $a=0.53, b=4.86$. " + "In the paper, they use $a=0.53, b=5.3$" ] }, { @@ -127,29 +129,29 @@ "source": [ "### Quantum Error Correction Scheme\n", "The quantum error correction scheme determines three things:\n", - "1. The logical error rate given a code distance and physical error rate $P(d)$.\n", - "1. The number of physical qubits needed per logical qubit $n(d)$.\n", - "1. The number of logical time steps $\\tau(d)$.\n", + "1. The logical error rate given a code distance and physical error rate: $P(d)$.\n", + "1. The number of physical qubits needed per logical qubit: $n(d)$.\n", + "1. The number of logical time steps: $\\tau(d)$.\n", "\n", - "Tabel V of [Beverland et al](https://arxiv.org/abs/2211.07629) lists how these are computed from the QEC scheme.\n", + "Table V of the paper lists how these are related to the QEC scheme.\n", "\n", - "In [Beverland et al](https://arxiv.org/abs/2211.07629), they use a gate-based QEC that has $P(d), n(d), \\tau(d)$ as:\n", + "In the paper, they use gate-based QEC which has $P(d), n(d), \\tau(d)$ as:\n", "$$\n", "P(d) = 0.03 \\left ( \\frac{p}{0.01} \\right) ^ \\frac{d+1}{2}\\\\\n", "n(d) = 2 d^2\\\\\n", - "\\tau(d) = \\textrm{\\{error detection circuit time\\}} \\cdot d\\\\\n", + "\\tau(d) = \\textrm{\\{single stabilizer time\\}} \\cdot d\\\\\n", "$$\n", "\n", - "The error detection circuit time depends on several factors including the time to apply a Clifford, measurement and reset operations as well as classical processing.\n", + "The error detection circuit time depends on several factors physical factors including the time to apply a Clifford, measurement and reset operations as well as classical processing.\n", "\n", - "In [Beverland et al](https://arxiv.org/abs/2211.07629) Table V they don't take into account the classical processing part and assume that a reset takes the same time as a measurement leading to the formula:\n", + "In Table V they don't take into account the classical processing part and assume that a reset takes the same time as a measurement leading to the formula:\n", "$$\n", - "\\textrm{\\{error detection circuit time\\}} = 4t_\\textrm{gate} + 2t_\\textrm{meas}\n", + "\\textrm{\\{single stabilizer time\\}} = 4t_\\textrm{gate} + 2t_\\textrm{meas}\n", "$$\n", "\n", "Other authors (e.g. [Fowler, Gidney](https://arxiv.org/abs/1808.06709)) assume that the entire process takes a specific time (e.g. $\\approx 1\\mu s$).\n", "\n", - "In Qualtran, we use \"error detection circuit time\" rather than fall to the low level hardware parameters. " + "In Qualtran, we use \"single stabilizer time\" rather than fall to the low-level hardware parameters. We also default to the Fowler, Gidney parameters (i.e. `FowlerSuperconductingQubits`) when none are given." ] }, { @@ -182,14 +184,14 @@ "source": [ "### Quantum Dynamics\n", "The algorithm specs of this circuit are given as:\n", - "- number of algorithm qubits: 100\n", - "- number of rotation gates: $30100$\n", + "- number of algorithm qubits: $100$\n", + "- number of rotation gates: $30,100$\n", "- number of measurements: $1.4 \\times 10^6$\n", "- number of T gates: $0$\n", "- number of Toffoli gates: $0$\n", "- depth of rotation circuit: $501$\n", "\n", - "with an error budget $\\epsilon$ of 0.001" + "with an error budget $\\epsilon$ of $0.001$" ] }, { @@ -259,7 +261,7 @@ "\n", "D4 gives the formula for $M$ as $$M = M_T + 4 M_{Tof} + M_R \\lceil A \\log_2{M_R/\\epsilon_{syn}} + B\\rceil$$\n", "\n", - "Since $M_T = M_{Tof} = 0$, the only contribution to $M$ comes from rotations where $M_R = 30100, \\epsilon_{syn} = \\frac{10^{-3}}{3} , A = 0.53, B = 5.3$ which give our value of 6.02e5." + "Since $M_T = M_{Tof} = 0$, the only contribution to $M$ comes from rotations where $M_R = 30100, \\epsilon_{syn} = \\frac{10^{-3}}{3} , A = 0.53, B = 5.3$ which give our value of $6.02e5$." ] }, { @@ -271,7 +273,7 @@ "$$\n", "P(d) = a \\left ( \\frac{p}{p^*} \\right )^\\frac{d+1}{2} \n", "$$\n", - "subject ot the constraint on the logical error rate of $QCP(d) = \\frac{\\epsilon}{3}$. Where $p$ is the physical error rate. $a$ and $p^*$ are constants determined by the QEC scheme." + "subject ot the constraint on the logical error rate of $Q \\cdot C \\cdot P(d) = \\frac{\\epsilon}{3}$. Where $p$ is the physical error rate. $a$ and $p^*$ are constants determined by the QEC scheme." ] }, { @@ -285,7 +287,7 @@ " time_steps=c_min,\n", " alg=quantum_dynamics_specs,\n", " qec=BeverlandSuperconductingQubits,\n", - " physical_error_rate=BeverlandEtAl.physical_error_rate,\n", + " physical_error_rate=BEVERLAND_PARAMS.physical_error_rate,\n", ")\n", "print(f'{d=}')" ] @@ -295,7 +297,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Matching the surface code of $d = 9$. This leads to a total run time (Eq. E3) of 0.65s which is close to the time in the paper of 0.55s" + "Matching the paper's code distance of $d = 9$. This leads to a total run time (Eq. E3) of 0.65s which is close to the time in the paper of 0.55s" ] }, { @@ -304,7 +306,8 @@ "metadata": {}, "outputs": [], "source": [ - "'algorithm run time of %g seconds' % (qec.error_detection_circuit_time_us(d) * 1e-6 * c_min)" + "t_s = qec.error_detection_circuit_time_us(d) * 1e-6 * c_min\n", + "f'algorithm run time of {t_s:g} seconds'.format()" ] }, { @@ -312,7 +315,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Next we examine the magic state factories. In [Beverland et al](https://arxiv.org/abs/2211.07629) for the quantum dynamics example we are given 199 factories each producing one T state every 46.8us at an error rate of 5.6e-11 while consuming 3240 qubits. " + "Next, we examine the magic state factories. In the paper, for the quantum dynamics example, we are given $199$ factories each producing one T state every $46.8 \\mu s$ at an error rate of $5.6e-11$ while consuming $3,240$ qubits. " ] }, { @@ -343,7 +346,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Our estimate of 0.68M physical qubits with 94.5% of them being consumed by the T states factories match exactly with the numbers in the paper." + "Our estimate of 0.68M physical qubits with 94.5% of them being consumed by the T states factories match the numbers in the paper." ] }, { @@ -447,7 +450,7 @@ " time_steps=c_min,\n", " alg=quantum_chemistry_specs,\n", " qec=qec,\n", - " physical_error_rate=BeverlandEtAl.physical_error_rate,\n", + " physical_error_rate=BEVERLAND_PARAMS.physical_error_rate,\n", ")\n", "print(f'{d=}')" ] @@ -484,7 +487,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Next we examine the magic state factories. In [Beverland et al](https://arxiv.org/abs/2211.07629) for the quantum chemistry example we are given 17 factories each producing one T state every 83.2us at an error rate of 2.13e-15 while consuming 16000 qubits. " + "Next we examine the magic state factories. In the paper, for the quantum chemistry example, we are given $17$ factories each producing one T state every $83.2\\mu s$ at an error rate of $2.13e-15$ while consuming $16,000$ qubits. " ] }, { @@ -515,7 +518,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Our estimate of 1.86M physical qubits matches exactly with the paper's." + "Our estimate of 1.86M physical qubits matches the paper's estimate." ] }, { @@ -525,14 +528,14 @@ "source": [ "### Shor Factoring\n", "The algorithm specs of this circuit are given as:\n", - "- number of algorithm qubits: 12581\n", + "- number of algorithm qubits: $12,581$\n", "- number of rotation gates: $12$\n", "- number of measurements: $1.08 \\times 10^9$\n", "- number of T gates: 12\n", "- number of Toffoli gates: $3.73 \\times 10^{10}$\n", "- depth of rotation circuit: $12$\n", "\n", - "with an error budget of 1/3" + "with an error budget of $1/3$" ] }, { @@ -595,7 +598,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Our estimates of $Q = 25481, C_{min} = 1.23 \\cdot 10^{10}, M = 1.49 \\cdot 10^{10}$ match exactly with the estimates of the paper." + "Our estimates of $Q = 25481, C_{min} = 1.23 \\cdot 10^{10}, M = 1.49 \\cdot 10^{10}$ match the estimates of the paper." ] }, { @@ -609,7 +612,7 @@ " time_steps=c_min,\n", " alg=shor_specs,\n", " qec=qec,\n", - " physical_error_rate=BeverlandEtAl.physical_error_rate,\n", + " physical_error_rate=BEVERLAND_PARAMS.physical_error_rate,\n", ")\n", "print(f'{d=}')" ] @@ -619,7 +622,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Matching the surface code of $d = 13$ in the paper." + "Matching the code distance of $d = 13$ in the paper." ] }, { @@ -640,7 +643,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Our estimate runtime of 17h43m matches exactly with the estimate of the paper." + "Our estimate runtime of 17h43m matches with the estimate of the paper." ] }, { @@ -648,7 +651,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Next we examine the magic state factories. In [Beverland et al](https://arxiv.org/abs/2211.07629) for the quantum chemistry example we are given 18 factories each producing one T state every 72.8us at an error rate of 5.51e-13 while consuming 5760 qubits. " + "Next we examine the magic state factories. In the paper, for the quantum chemistry example, we are given $18$ factories each producing one T state every $72.8 \\mu s$ at an error rate of $5.51e-13$ while consuming $5,760$ qubits. " ] }, { @@ -679,7 +682,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Our estimate of 8.72M physical qubits matches exactly with the paper." + "Our estimate of 8.72M physical qubits matches the paper's estimate." ] } ], diff --git a/qualtran/surface_code/physical_parameters.py b/qualtran/surface_code/physical_parameters.py index 1d4f8a745..9944de8af 100644 --- a/qualtran/surface_code/physical_parameters.py +++ b/qualtran/surface_code/physical_parameters.py @@ -35,7 +35,7 @@ class PhysicalParameters: reference: Optional[str] = None -BeverlandEtAl = PhysicalParameters( +BEVERLAND_PARAMS = PhysicalParameters( t_gate_ns=50, # 50ns t_meas_ns=100, # 100ns physical_error_rate=1e-4, From dfe5db65779ac906ca39a47ce0c8539db12c0f4c Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Mon, 11 Dec 2023 13:14:34 -0800 Subject: [PATCH 32/33] nit --- qualtran/surface_code/azure_cost_model.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qualtran/surface_code/azure_cost_model.ipynb b/qualtran/surface_code/azure_cost_model.ipynb index ef6bc60ab..7b9423d12 100644 --- a/qualtran/surface_code/azure_cost_model.ipynb +++ b/qualtran/surface_code/azure_cost_model.ipynb @@ -34,8 +34,8 @@ "## The Inputs\n", "### Physical Parameters\n", "These are assumptions about the quantum hardware and are:\n", - "- `t_gate_us`: Latency time of Clifford gates. \n", - "- `t_meas_us`: Latency time of Measurement operations.\n", + "- `t_gate_ns`: Latency time of Clifford gates. \n", + "- `t_meas_ns`: Latency time of Measurement operations.\n", "- `physical_error_rate`: Physical error rate ($p$).\n", "\n", "In Qualtran these are represented by the `PhysicalParameters` dataclass." From 27a131322c947fb059cbf0d63330c39799e4d426 Mon Sep 17 00:00:00 2001 From: Nour Yosri Date: Fri, 15 Dec 2023 11:55:12 -0800 Subject: [PATCH 33/33] ditch rst file changes --- docs/index.rst | 13 ------------- docs/surface_code/index.rst | 14 -------------- 2 files changed, 27 deletions(-) delete mode 100644 docs/surface_code/index.rst diff --git a/docs/index.rst b/docs/index.rst index 472f1c997..2f605403b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -48,19 +48,6 @@ and high-level quantum programs. :ref:`Read more... ` bloqs/index.rst -:ref:`surface_code` ------------------------------- - -``qualtran.surface_code`` contains implementations of classes and routines useful for estimating -the cost of running fault-tolerant quantum algorithms using surface codes for error correction. - -.. toctree:: - :maxdepth: 1 - :hidden: - - surface_code/index.rst - - :ref:`reference` ------------------------------- diff --git a/docs/surface_code/index.rst b/docs/surface_code/index.rst deleted file mode 100644 index 7f21d3842..000000000 --- a/docs/surface_code/index.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. surface_code: - -Surface Code -============= - -``qualtran.surface_code`` contains implementations of classes and routines useful for estimating -the cost of running fault-tolerant quantum algorithms using surface codes for error correction. - - -.. toctree:: - :maxdepth: 1 - :caption: Estimation Models: - - azure_model.ipynb \ No newline at end of file