-
Notifications
You must be signed in to change notification settings - Fork 5
98 create x yz decomposer for quantify scheduler #214
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
Merged
juanboschero
merged 26 commits into
develop
from
98-create-x-yz-decomposer-for-quantify-scheduler
Jun 26, 2024
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
6845628
Merge pull request #213 from QuTech-Delft/develop
juanboschero cd6c838
Add XYX decomposition
juanboschero b1ab2f5
Fix isort & black
juanboschero 3b0aea7
Add ABADecomposer class.
rturrado f87717a
Merge branch 'develop' into 98-create-x-yz-decomposer-for-quantify-sc…
juanboschero 918bc2a
Introduce general ABAdecomposer class
juanboschero b425c52
Merge remote-tracking branch 'origin/98-create-x-yz-decomposer-for-qu…
rturrado a7f3fc8
Fix ABADecomposer.
rturrado 99d21d2
Run isort and black.
rturrado 6383173
Run mypy.
rturrado 76c9312
Update CONTRIBUTING.md.
rturrado 0f962c5
Remove unused imports.
rturrado 413586d
Trying to fix Python 3.8 errors.
rturrado e1515b7
Fix imports in integration and remove deprecated files
juanboschero a621401
Fix imports in integration
juanboschero b334b61
Fix mypy errors in decomposer
juanboschero 6fbd4e0
Merge pull request #231 from QuTech-Delft/98-fix-aba-decomposer
juanboschero d852265
Modify aba_decomposer init and modify CONTRIBUTING.md
juanboschero 3eb92f5
Add docstrings to aba_decompose
juanboschero aa39451
Fix mypy issues
juanboschero 6ee9335
Fix docstrings and type hinting
juanboschero 366ed0d
Modify Self import in circuit_builder
juanboschero 2a74a85
Modify Self import in circuit_builder
juanboschero f0ce3c1
Update opensquirrel/decomposer/aba_decomposer.py
juanboschero 4b98ead
Update opensquirrel/decomposer/aba_decomposer.py
juanboschero f8fa823
Merge branch 'develop' into 98-create-x-yz-decomposer-for-quantify-sc…
juanboschero 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,184 @@ | ||
| """ Module containing classes that inherit from the ABADecomposer class to decompose a circuit into one of the Pauli | ||
| ABA decompositions.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import math | ||
| from abc import ABC, abstractmethod | ||
| from collections.abc import Callable | ||
|
|
||
| from opensquirrel.common import ATOL | ||
| from opensquirrel.decomposer.general_decomposer import Decomposer | ||
| from opensquirrel.default_gates import Rx, Ry, Rz | ||
| from opensquirrel.ir import Axis, AxisLike, BlochSphereRotation, Float, Gate | ||
| from opensquirrel.utils.identity_filter import filter_out_identities | ||
|
|
||
|
|
||
| class ABADecomposer(Decomposer, ABC): | ||
| @property | ||
| @abstractmethod | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: ... | ||
|
|
||
| @property | ||
| @abstractmethod | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: ... | ||
|
|
||
| _gate_list: list[Callable[..., BlochSphereRotation]] = [Rx, Ry, Rz] | ||
|
|
||
| def __init__(self) -> None: | ||
| self.index_a = self._gate_list.index(self.ra) | ||
| self.index_b = self._gate_list.index(self.rb) | ||
|
|
||
| def get_decomposition_angles(self, alpha: float, axis: AxisLike) -> tuple[float, float, float]: | ||
| """Gives the angles used in the A-B-A decomposition of the Bloch sphere rotation | ||
| characterized by a rotation around `axis` of angle `alpha`. | ||
|
|
||
| Parameters: | ||
| alpha: angle of the Bloch sphere rotation | ||
| axis: _normalized_ axis of the Bloch sphere rotation | ||
|
|
||
| Returns: | ||
| A triple (theta1, theta2, theta3) corresponding to the decomposition of the | ||
| arbitrary Bloch sphere rotation into U = Ra(theta3) Rb(theta2) Ra(theta1) | ||
|
|
||
| """ | ||
| axis = Axis(axis) | ||
| a_axis_value = axis[self.index_a] | ||
| b_axis_value = axis[self.index_b] | ||
| if not (-math.pi + ATOL < alpha <= math.pi + ATOL): | ||
| raise ValueError("Angle needs to be normalized") | ||
|
|
||
| if abs(alpha - math.pi) < ATOL: | ||
| # alpha == pi, math.tan(alpha / 2) is not defined. | ||
|
|
||
| if abs(a_axis_value) < ATOL: | ||
| theta2 = math.pi | ||
| p = 0.0 | ||
| m = 2 * math.acos(b_axis_value) | ||
|
|
||
| else: | ||
| p = math.pi | ||
| theta2 = 2 * math.acos(a_axis_value) | ||
|
|
||
| if abs(a_axis_value - 1) < ATOL or abs(a_axis_value + 1) < ATOL: | ||
| m = p # This can be anything, but setting m = p means theta3 == 0, which is better for gate count. | ||
| else: | ||
| m = 2 * math.acos(b_axis_value / math.sqrt(1 - a_axis_value**2)) | ||
|
|
||
| else: | ||
| p = 2 * math.atan2(a_axis_value * math.sin(alpha / 2), math.cos(alpha / 2)) | ||
|
|
||
| acos_argument = math.cos(alpha / 2) * math.sqrt(1 + (a_axis_value * math.tan(alpha / 2)) ** 2) | ||
|
|
||
| # This fixes float approximations like 1.0000000000002 which acos doesn't like. | ||
| acos_argument = max(min(acos_argument, 1.0), -1.0) | ||
|
|
||
| theta2 = 2 * math.acos(acos_argument) | ||
| theta2 = math.copysign(theta2, alpha) | ||
|
|
||
| if abs(math.sin(theta2 / 2)) < ATOL: | ||
| m = p # This can be anything, but setting m = p means theta3 == 0, which is better for gate count. | ||
| else: | ||
| acos_argument = float(b_axis_value) * math.sin(alpha / 2) / math.sin(theta2 / 2) | ||
|
|
||
| # This fixes float approximations like 1.0000000000002 which acos doesn't like. | ||
| acos_argument = max(min(acos_argument, 1.0), -1.0) | ||
|
|
||
| m = 2 * math.acos(acos_argument) | ||
|
|
||
| theta1 = (p + m) / 2 | ||
|
|
||
| theta3 = p - theta1 | ||
| return theta1, theta2, theta3 | ||
|
|
||
| def decompose(self, g: Gate) -> list[Gate]: | ||
S-Linde marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| """General A-B-A decomposition function for a single gate. | ||
|
|
||
| Args: | ||
| g: gate to decompose. | ||
|
|
||
| Returns: | ||
| Three gates, following the A-B-A convention, corresponding to the decomposition of the input gate. | ||
| """ | ||
| if not isinstance(g, BlochSphereRotation): | ||
| # We only decompose Bloch sphere rotations. | ||
| return [g] | ||
|
|
||
| theta1, theta2, theta3 = self.get_decomposition_angles(g.angle, g.axis) | ||
| a1 = self.ra(g.qubit, Float(theta1)) | ||
| b = self.rb(g.qubit, Float(theta2)) | ||
| a2 = self.ra(g.qubit, Float(theta3)) | ||
|
|
||
| return filter_out_identities([a1, b, a2]) | ||
|
|
||
|
|
||
| class XYXDecomposer(ABADecomposer): | ||
| """Class responsible for the X-Y-X decomposition.""" | ||
|
|
||
| @property | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rx | ||
|
|
||
| @property | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: | ||
| return Ry | ||
|
|
||
|
|
||
| class XZXDecomposer(ABADecomposer): | ||
| """Class responsible for the X-Z-X decomposition.""" | ||
|
|
||
| @property | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rx | ||
|
|
||
| @property | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rz | ||
|
|
||
|
|
||
| class YXYDecomposer(ABADecomposer): | ||
| """Class responsible for the Y-X-Y decomposition.""" | ||
|
|
||
| @property | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: | ||
| return Ry | ||
|
|
||
| @property | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rx | ||
|
|
||
|
|
||
| class YZYDecomposer(ABADecomposer): | ||
| """Class responsible for the Y-Z-Y decomposition.""" | ||
|
|
||
| @property | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: | ||
| return Ry | ||
|
|
||
| @property | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rz | ||
|
|
||
|
|
||
| class ZXZDecomposer(ABADecomposer): | ||
| """Class responsible for the Z-X-Z decomposition.""" | ||
|
|
||
| @property | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rz | ||
|
|
||
| @property | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rx | ||
|
|
||
|
|
||
| class ZYZDecomposer(ABADecomposer): | ||
| """Class responsible for the Z-Y-Z decomposition.""" | ||
|
|
||
| @property | ||
| def ra(self) -> Callable[..., BlochSphereRotation]: | ||
| return Rz | ||
|
|
||
| @property | ||
| def rb(self) -> Callable[..., BlochSphereRotation]: | ||
| return Ry | ||
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 was deleted.
Oops, something went wrong.
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,44 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import math | ||
|
|
||
| import pytest | ||
|
|
||
| from opensquirrel.decomposer.aba_decomposer import XYXDecomposer | ||
| from opensquirrel.default_gates import CNOT, CR, H, I, Rx, Ry, S, X, Y | ||
| from opensquirrel.ir import BlochSphereRotation, Float, Gate, Qubit | ||
|
|
||
|
|
||
| @pytest.fixture(name="decomposer") | ||
| def decomposer_fixture() -> XYXDecomposer: | ||
| return XYXDecomposer() | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "gate, expected_result", | ||
| [ | ||
| (CNOT(Qubit(0), Qubit(1)), [CNOT(Qubit(0), Qubit(1))]), | ||
| (CR(Qubit(2), Qubit(3), Float(2.123)), [CR(Qubit(2), Qubit(3), Float(2.123))]), | ||
| (I(Qubit(0)), []), | ||
| ( | ||
| S(Qubit(0)), | ||
| [Rx(Qubit(0), Float(math.pi / 2)), Ry(Qubit(0), Float(math.pi / 2)), Rx(Qubit(0), Float(-math.pi / 2))], | ||
| ), | ||
| (Y(Qubit(0)), [Ry(Qubit(0), Float(math.pi))]), | ||
| (Ry(Qubit(0), Float(0.9)), [Ry(Qubit(0), Float(0.9))]), | ||
| (X(Qubit(0)), [Rx(Qubit(0), Float(math.pi))]), | ||
| (Rx(Qubit(0), Float(0.123)), [Rx(Qubit(0), Float(0.123))]), | ||
| (H(Qubit(0)), [Rx(Qubit(0), Float(math.pi)), Ry(Qubit(0), Float(math.pi / 2))]), | ||
| ( | ||
| BlochSphereRotation(qubit=Qubit(0), angle=5.21, axis=(1, 2, 3), phase=0.324), | ||
| [ | ||
| Rx(Qubit(0), Float(0.8251439260060653)), | ||
| Ry(Qubit(0), Float(-1.030183660156084)), | ||
| Rx(Qubit(0), Float(-1.140443520488592)), | ||
| ], | ||
| ), | ||
| ], | ||
| ids=["CNOT", "CR", "I", "S", "Y", "Ry", "X", "Rx", "H", "arbitrary"], | ||
| ) | ||
| def test_xyx_decomposer(decomposer: XYXDecomposer, gate: Gate, expected_result: list[Gate]) -> None: | ||
| assert decomposer.decompose(gate) == expected_result |
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.
Uh oh!
There was an error while loading. Please reload this page.