-
Notifications
You must be signed in to change notification settings - Fork 161
Various models for custom RE Python API #2742
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
Draft
msoeken
wants to merge
4
commits into
main
Choose a base branch
from
msoeken/re-models
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| from typing import Any, Dict | ||
| from ._utils import extract_qubit_metric | ||
|
|
||
|
|
||
| class RoundBasedFactory: | ||
| """ | ||
| Factory for generating magic states using round-based distillation protocols. | ||
|
|
||
| This class implements magic state distillation using round-based protocols. | ||
| It generates distillation units that can operate at both physical and logical levels. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| *, | ||
| with_physical: bool = True, | ||
| gate_time: str = "gate_time", | ||
| gate_error: str = "gate_error", | ||
| clifford_error: str = "clifford_error", | ||
| use_max_qubits_per_round: bool = False, | ||
| max_rounds: int = 3, | ||
| max_extra_rounds: int = 5 | ||
| ): | ||
| """ | ||
| Initialize the round-based magic state factory. | ||
|
|
||
| :param with_physical: Whether to include physical-level distillation units | ||
| (default: True) | ||
| :param gate_time: Key name (or list of key names) for extracting gate time | ||
| from qubit metrics. If a list is provided, the sum of all corresponding | ||
| times is used (default: "gate_time") | ||
| :param gate_error: Key name (or list of key names) for extracting gate | ||
| error rate from qubit metrics. If a list is provided, the maximum of | ||
| all corresponding error rates is used (default: "gate_error") | ||
| :param clifford_error: Key name (or list of key names) for extracting | ||
| Clifford gate error rate from qubit metrics. If a list is provided, | ||
| the maximum of all corresponding error rates is used | ||
| (default: "clifford_error") | ||
| :param use_max_qubits_per_round: Whether to maximize qubits used per round | ||
| (default: False) | ||
| :param max_rounds: Maximum number of distillation rounds (default: 3) | ||
| :param max_extra_rounds: Maximum number of additional rounds beyond | ||
| max_rounds (default: 5) | ||
| """ | ||
| self.with_physical = with_physical | ||
| self.gate_time = gate_time | ||
| self.gate_error = gate_error | ||
| self.clifford_error = clifford_error | ||
| self.use_max_qubits_per_round = use_max_qubits_per_round | ||
| self.max_rounds = max_rounds | ||
| self.max_extra_rounds = max_extra_rounds | ||
|
|
||
| def distillation_units( | ||
| self, code: Any, qubit: Dict[str, Any], max_code_parameter: int | ||
| ): | ||
| """ | ||
| Generate a list of distillation units for magic state production. | ||
|
|
||
| Creates distillation units using 15-to-1 protocols (RM prep and space | ||
| efficient variants) at both physical level (if enabled) and across | ||
| all valid code parameters up to the maximum. | ||
|
|
||
| :param code: QEC code object that provides code parameters and metrics | ||
| :param qubit: Dictionary containing physical qubit characteristics | ||
| :param max_code_parameter: Maximum code parameter (distance) to consider | ||
| :return: List of distillation unit dictionaries, each containing | ||
| configuration and callable functions for resource calculations | ||
| """ | ||
| units = [] | ||
|
|
||
| gate_time = extract_qubit_metric(qubit, self.gate_time) | ||
| clifford_error = extract_qubit_metric(qubit, self.clifford_error) | ||
|
|
||
| if self.with_physical: | ||
| units.append( | ||
| _create_unit( | ||
| "15-to-1 RM prep", | ||
| 1, | ||
| 24, | ||
| gate_time, | ||
| 1, | ||
| 31, | ||
| clifford_error, | ||
| ) | ||
| ) | ||
| units.append( | ||
| _create_unit( | ||
| "15-to-1 space efficient", | ||
| 1, | ||
| 45, | ||
| gate_time, | ||
| 1, | ||
| 12, | ||
| clifford_error, | ||
| ) | ||
| ) | ||
|
|
||
| for code_parameter in code.code_parameter_range(): | ||
| if code.code_parameter_cmp(qubit, code_parameter, max_code_parameter) == 1: | ||
| break | ||
|
|
||
| units.append( | ||
| _create_unit( | ||
| "15-to-1 RM prep", | ||
| code_parameter, | ||
| 11, | ||
| code.logical_cycle_time(qubit, code_parameter), | ||
| code.physical_qubits(code_parameter), | ||
| 31, | ||
| code.logical_error_rate(qubit, code_parameter), | ||
| ) | ||
| ) | ||
| units.append( | ||
| _create_unit( | ||
| "15-to-1 space efficient", | ||
| code_parameter, | ||
| 13, | ||
| code.logical_cycle_time(qubit, code_parameter), | ||
| code.physical_qubits(code_parameter), | ||
| 20, | ||
| code.logical_error_rate(qubit, code_parameter), | ||
| ) | ||
| ) | ||
|
|
||
| return units | ||
|
|
||
| def trivial_distillation_unit( | ||
| self, code: Any, qubit: Dict[str, Any], code_parameter: Any | ||
| ): | ||
| """ | ||
| Creates this 1-to-1 distillation unit in the case where the target error | ||
| rate is already met by the physical qubit. | ||
|
|
||
| :param code: QEC code object that provides code parameters and metrics | ||
| :param qubit: Dictionary containing physical qubit characteristics | ||
| :param code_parameter: Code parameter chosen to run the algorithm | ||
| """ | ||
|
|
||
| return { | ||
| "name": "trivial 1-to-1", | ||
| "code_parameter": code_parameter, | ||
| "num_input_states": 1, | ||
| "num_output_states": 1, | ||
| "physical_qubits": lambda _: code.physical_qubits(code_parameter), | ||
| "duration": lambda _: code.logical_cycle_time(qubit, code_parameter), | ||
| "output_error_rate": lambda input_error_rate: input_error_rate, | ||
| "failure_probability": lambda _: 0.0, | ||
| } | ||
|
|
||
|
|
||
| def _create_unit( | ||
| name: str, | ||
| code_parameter: Any, | ||
| num_cycles: int, | ||
| cycle_time: int, | ||
| physical_qubits_factor: int, | ||
| physical_qubits: int, | ||
| clifford_error_rate: float, | ||
| ): | ||
| """ | ||
| Create a distillation unit configuration dictionary. | ||
|
|
||
| :param name: Name of the distillation protocol | ||
| :param code_parameter: Code parameter (distance) for this unit | ||
| :param num_cycles: Number of cycles required for distillation | ||
| :param cycle_time: Time per cycle | ||
| :param physical_qubits_factor: Multiplier for physical qubit count | ||
| :param physical_qubits: Base number of physical qubits | ||
| :param clifford_error_rate: Error rate for Clifford operations | ||
| :return: Dictionary containing unit configuration and callable functions | ||
| for calculating physical qubits, duration, output error rate, and | ||
| failure probability | ||
| """ | ||
|
|
||
| return { | ||
| "name": name, | ||
| "code_parameter": code_parameter, | ||
| "num_input_states": 15, | ||
| "num_output_states": 1, | ||
| "physical_qubits": lambda _: physical_qubits * physical_qubits_factor, | ||
| "duration": lambda _: num_cycles * cycle_time, | ||
| "output_error_rate": lambda input_error_rate: 35 * input_error_rate**3 | ||
| + 7.1 * clifford_error_rate, | ||
| "failure_probability": lambda input_error_rate: 15 * input_error_rate | ||
| + 356 * clifford_error_rate, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
| import math | ||
| from typing import Union, List, Optional | ||
|
|
||
| from ._estimator import LogicalCounts | ||
|
|
||
|
|
||
| NUM_MEASUREMENTS_PER_R = 1 | ||
| NUM_MEASUREMENTS_PER_TOF = 3 | ||
|
|
||
|
|
||
| class PSSPCEstimator: | ||
| """ | ||
| Computes post-layout logical resources based on the Parallel Synthesis | ||
| Sequential Pauli Computation (PSSPC) layout method. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| source: Union[List[str], str, LogicalCounts], | ||
| expression: Optional[str] = None, | ||
| ): | ||
| """ | ||
| Constructor for PSSPC layout method. The source can be a list of Q# | ||
| source files (use a list even if there is only one file), a path to a Q# | ||
| project (directory with a qsharp.json file), or a LogicalCounts object. | ||
|
|
||
| :param source: The Q# source files, project path, or LogicalCounts | ||
| object. | ||
| :param expression: An entry point expression that must only be used when | ||
| the source is a list of Q# files or a project path. | ||
| """ | ||
|
|
||
| if isinstance(source, LogicalCounts): | ||
| if expression is not None: | ||
| raise ValueError( | ||
| "Cannot specify entry point expression when source is LogicalCounts" | ||
| ) | ||
| self._counts = source | ||
| else: | ||
| if expression is None: | ||
| raise ValueError( | ||
| "Must specify entry point expression when source is not LogicalCounts" | ||
| ) | ||
| self._counts = self._compute_counts(source, expression) | ||
|
|
||
| def logical_qubits(self): | ||
| """ | ||
| Calculates the number of logical qubits required for the PSSPC layout | ||
| according to Eq. (D1) in [arXiv:2211.07629](https://arxiv.org/pdf/2211.07629) | ||
| """ | ||
|
|
||
| num_qubits = self._counts["numQubits"] | ||
|
|
||
| qubit_padding = math.ceil(math.sqrt(8 * num_qubits)) + 1 | ||
| return 2 * num_qubits + qubit_padding | ||
|
|
||
| def logical_depth(self, budget): | ||
| """ | ||
| Calculates the number of multi-qubit Pauli measurements executed in | ||
| sequence according to Eq. (D3) in | ||
| [arXiv:2211.07629](https://arxiv.org/pdf/2211.07629) | ||
| """ | ||
|
|
||
| budget_rotations = budget["rotations"] | ||
| tof_count = self._counts.get("cczCount", 0) + self._counts.get("ccixCount", 0) | ||
| num_ts_per_rotation = self._num_ts_per_rotation(budget_rotations) | ||
|
|
||
| return ( | ||
| ( | ||
| self._counts.get("measurementCount", 0) | ||
| + self._counts.get("rotationCount", 0) | ||
| + self._counts.get("tCount", 0) | ||
| ) | ||
| * NUM_MEASUREMENTS_PER_R | ||
| + tof_count * NUM_MEASUREMENTS_PER_TOF | ||
| + ( | ||
| num_ts_per_rotation | ||
| * self._counts.get("rotationDepth", 0) | ||
| * NUM_MEASUREMENTS_PER_R | ||
| ) | ||
| ) | ||
|
|
||
| def num_magic_states(self, budget, index): | ||
| """ | ||
| Calculates the number of T magic states that are consumbed by | ||
| multi-qubit Pauli measurements executed by PSSPC according to Eq. (D4) | ||
| in [arXiv:2211.07629](https://arxiv.org/pdf/2211.07629) | ||
| """ | ||
|
|
||
| # Only works for one kind of magic states, which is assumed to be T | ||
| # magic states | ||
| assert index == 0 | ||
|
|
||
| budget_rotations = budget["rotations"] | ||
| tof_count = self._counts.get("cczCount", 0) + self._counts.get("ccixCount", 0) | ||
| num_ts_per_rotation = self._num_ts_per_rotation(budget_rotations) | ||
|
|
||
| return ( | ||
| 4 * tof_count | ||
| + self._counts.get("tCount", 0) | ||
| + num_ts_per_rotation * self._counts.get("rotationCount", 0) | ||
| ) | ||
|
|
||
| def algorithm_overhead(self, budget): | ||
| """ | ||
| Returns the pre-layout logical resources as algorithm overhead, which | ||
| can be accessed from the estimation result. | ||
| """ | ||
| return self._counts | ||
|
|
||
| def prune_error_budget(self, budget, strategy): | ||
| if self._counts.get("rotationCount", 0) == 0: | ||
| budget_rotations = budget.get("rotations", 0) | ||
| budget["rotations"] = 0 | ||
| budget["logical"] += budget_rotations / 2 | ||
| budget["magic_states"] += budget_rotations / 2 | ||
|
|
||
| def _compute_counts(self, source: Union[List[str], str], expression): | ||
| # NOTE: Importing qsharp here to avoid circular dependency | ||
| import qsharp | ||
|
|
||
| if isinstance(source, list): | ||
| qsharp.init() | ||
| for file in source: | ||
| qsharp.eval(qsharp._fs.read_file(file)[1]) | ||
| elif isinstance(source, str): | ||
| qsharp.init(project_root=source) | ||
| else: | ||
| raise ValueError("Invalid source type for PSSPCEstimator") | ||
|
|
||
| return qsharp.logical_counts(expression) | ||
|
|
||
| def _num_ts_per_rotation(self, rotation_budget): | ||
| rotation_count = self._counts.get("rotationCount", 0) | ||
|
|
||
| if rotation_count > 0: | ||
| return math.ceil(0.53 * math.log2(rotation_count / rotation_budget) + 4.86) | ||
|
|
||
| else: | ||
| return 0 | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check notice
Code scanning / devskim
If untrusted data (data from HTTP requests, user submitted files, etc.) is included in an eval statement it can allow an attacker to inject their own code. Note