-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create data classes used by the Azure physical costing model #356
Changes from all commits
6645514
933b662
aa76406
1c65f14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# 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 attr | ||
import numpy as np | ||
from attrs import frozen | ||
|
||
from qualtran.surface_code.physical_parameters import PhysicalParameters | ||
|
||
|
||
@frozen | ||
class QuantumErrorCorrectionScheme: | ||
"""QuantumErrorCorrectionScheme represents a quantum error correction scheme. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is an unhelpful line. A full quantum error correction scheme would include a particular code, decoder, way of doing gates, and many more things. As I understand it: this class captures a small slice of the relevant characteristics of an error correcting code. Consider a more helpful name for this class. And/or consider making this abstract and giving it a concise name (and meaningful names to the implementations). |
||
|
||
QuantumErrorCorrectionScheme provides estimates for the logical error rate, | ||
number of physical qubits and the logical time step given a code distance and | ||
physical assumptions. | ||
Comment on lines
+26
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't indent the body of the docstring |
||
|
||
Attributes: | ||
error_rate_scaler: Logical error rate coefficient. | ||
error_rate_threshold: Logical error rate threshold. | ||
Comment on lines
+31
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please document these constants in terms of the mathematical formula in which they appear. I don't think "error_rate_scaler" is a common term and "error_rate_threshold" would imply that this is a property of the code whereas in reality this is yet another fuzzy parameter that captures the empirical behavior of the error suppression. Note that we measure/target/think about the parameter There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The definition of lambda definitely includes the physical error rate you can use https://arxiv.org/abs/2207.06431 as a reference for lambda. It's the error at d divided by the error at d+2; i.e. how much suppression you get by increasing the code distance. |
||
reference: source of the estimates. | ||
""" | ||
|
||
error_rate_scaler = attr.ib(type=float, default=0.1, repr=lambda x: f'{x:g}') | ||
error_rate_threshold = attr.ib(type=float, default=0.01, repr=lambda x: f'{x:g}') | ||
reference = attr.ib(type=str, default='') | ||
|
||
def logical_error_rate( | ||
self, code_distance: int | np.ndarray, physical_error_rate: float | np.ndarray | ||
) -> float | np.ndarray: | ||
"""Computes the logical error rate.""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to say something in addition to the method name """The logical error rate for a given code distance and physical error rate using this scheme""" |
||
return self.error_rate_scaler * np.power( | ||
physical_error_rate / self.error_rate_threshold, (code_distance + 1) / 2 | ||
) | ||
|
||
def physical_qubits(self, code_distance: int | np.ndarray) -> int | np.ndarray: | ||
"""Computes number of physical qubits""" | ||
Comment on lines
+48
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. """The number of physical qubits for the given code distance using this scheme. also: this needs an |
||
|
||
def logical_time_step( | ||
self, code_distance: int | np.ndarray, physical_parameters: PhysicalParameters | ||
) -> float: | ||
"""Computes the logical time step.""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what |
||
|
||
|
||
class GateBasedSurfaceCode(QuantumErrorCorrectionScheme): | ||
"""Gate 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: | ||
return (4 * physical_parameters.t_gate + 2 * physical_parameters.t_meas) * code_distance | ||
|
||
|
||
class MeasurementBasedSurfaceCode(QuantumErrorCorrectionScheme): | ||
"""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: | ||
return 20 * physical_parameters.t_meas * code_distance | ||
|
||
|
||
class MeasurementBasedHastingsHaahCode(QuantumErrorCorrectionScheme): | ||
"""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: | ||
return 3 * physical_parameters.t_meas * code_distance |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# 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 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.QuantumErrorCorrectionScheme, 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.QuantumErrorCorrectionScheme, 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), 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.QuantumErrorCorrectionScheme, want: float): | ||
assert qec.logical_time_step( | ||
12, physical_parameters=PhysicalParameters(50e-9, 100e-9, 1e-4) | ||
) == pytest.approx(want) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# 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 attr | ||
import numpy as np | ||
from attrs import frozen | ||
|
||
_PRETTY_FLOAT = attr.ib(type=float, repr=lambda x: f'{x:g}') | ||
|
||
|
||
class RotationCostModel(abc.ABC): | ||
"""Analytical estimate of number of T gates needed to approximate a rotation given an error budget.""" | ||
|
||
@abc.abstractmethod | ||
def mean_cost(self, error_budge: float | np.ndarray) -> float: | ||
"""Returns the mean number of T gates needed to approx a rotation.""" | ||
|
||
@abc.abstractmethod | ||
def max_cost(self, error_budge: float | np.ndarray) -> float: | ||
"""Returns the max number of T gates needed to approx a rotation.""" | ||
|
||
|
||
@frozen | ||
class RotationCostLinearModel(RotationCostModel): | ||
r"""RotationCostLinearModel is a linear model in the log of the error budget. | ||
|
||
#T gates = $-A \log_2{budget} + B$ | ||
|
||
Attributes: | ||
A_mean: Mean value of the coefficient of $log_2{budget}$. | ||
B_mean: Mean value of the offset/overhead. | ||
A_max: Max value of the coefficient of $log_2{budget}$. | ||
B_max: Max value of the offset/overhead. | ||
""" | ||
A_mean = _PRETTY_FLOAT | ||
B_mean = _PRETTY_FLOAT | ||
A_max = _PRETTY_FLOAT | ||
B_max = _PRETTY_FLOAT | ||
|
||
gateset = attr.ib(type=str, default='') | ||
approximation_protocol = attr.ib(type=str, default='') | ||
reference = attr.ib(type=str, default='') | ||
|
||
def mean_cost(self, error_budge: float | np.ndarray) -> float: | ||
return self.A_mean * np.log2(1.0 / error_budge) + self.B_mean | ||
|
||
def max_cost(self, error_budge: float | np.ndarray) -> float: | ||
return self.A_max * np.log2(1.0 / error_budge) + self.B_max | ||
|
||
|
||
MixedFallBackCliffordT = RotationCostLinearModel( | ||
A_mean=0.53, | ||
B_mean=4.86, | ||
A_max=0.57, | ||
B_max=8.83, | ||
gateset='Clifford+T', | ||
approximation_protocol='Mixed fallback', | ||
reference='https://arxiv.org/abs/2203.10064:Table1', | ||
) | ||
|
||
BeverlandEtAl = RotationCostLinearModel( | ||
A_mean=0.53, | ||
B_mean=5.3, | ||
A_max=0.53, | ||
B_max=5.3, | ||
gateset='Clifford+T', | ||
approximation_protocol='Mixed fallback', | ||
reference='https://arxiv.org/abs/2211.07629:D2', | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# 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. | ||
|
||
from qualtran.surface_code.rotation_cost_model import RotationCostLinearModel | ||
|
||
|
||
def test_linear_model(): | ||
model = RotationCostLinearModel(1, 2, 3, 4) | ||
assert model.mean_cost(0.5) == 3 | ||
assert model.max_cost(0.5) == 7 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# 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 attr | ||
from attrs import frozen | ||
|
||
from qualtran.surface_code.magic_state_factory import MagicStateCount, MagicStateFactory | ||
|
||
_PRETTY_FLOAT = attr.ib(type=float, default=0.0, repr=lambda x: f'{x:g}') | ||
|
||
|
||
@frozen | ||
class TFactory(MagicStateFactory): | ||
"""TFactory represents a magic state factory for T states. | ||
|
||
Attributes: | ||
num_qubits: Number of qubits used by the factory. | ||
duration: Time taken by the factory to produce T states. | ||
t_states_rate: Number of T states per production cycle. | ||
reference: Source of these estimates. | ||
""" | ||
|
||
num_qubits = attr.ib(type=int, default=0) | ||
duration = _PRETTY_FLOAT | ||
t_states_rate = _PRETTY_FLOAT | ||
error_rate = attr.ib(type=float, default=1e-9, repr=lambda x: f'{x:g}') | ||
reference = attr.ib(type=str, default='') | ||
|
||
def footprint(self) -> int: | ||
return self.num_qubits | ||
|
||
def n_cycles(self, n_magic: MagicStateCount) -> int: | ||
return n_magic.all_t_count() / self.t_states_rate * self.duration | ||
|
||
def distillation_error(self, n_magic: MagicStateCount, phys_err: float) -> float: | ||
return n_magic.all_t_count() / self.t_states_rate * phys_err |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# 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. | ||
|
||
|
||
from qualtran.surface_code.t_factory import MagicStateCount, TFactory | ||
|
||
|
||
def test_footprint(): | ||
factory = TFactory(num_qubits=5, duration=1, t_states_rate=0.1) | ||
magic_count = MagicStateCount(t_count=1, ccz_count=1) | ||
assert factory.footprint() == 5 | ||
assert factory.n_cycles(magic_count) == 50 | ||
assert factory.distillation_error(magic_count, 0.5) == 25 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this abstract?