From dd6e31ac4011bb39030b5dc440cfbbb1a3c71d16 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sat, 3 Feb 2024 13:10:18 +0400 Subject: [PATCH 1/6] initial commit --- src/qibo/transpiler/decompositions.py | 50 ++++++++++++++++++--------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index cb106d423b..cbefc02dc9 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -116,7 +116,7 @@ def _u3_to_gpi2(t, p, l): # Decompose single qubit gates using U3 u3_dec = GateDecompositions() -u3_dec.add(gates.H, [gates.U3(0, 7 * np.pi / 2, np.pi, 0)]) +u3_dec.add(gates.H, [gates.U3(0, -np.pi / 2, np.pi, 0)]) u3_dec.add(gates.X, [gates.U3(0, np.pi, 0, np.pi)]) u3_dec.add(gates.Y, [gates.U3(0, np.pi, 0, 0)]) u3_dec.add(gates.Z, [gates.Z(0)]) @@ -159,28 +159,28 @@ def _u3_to_gpi2(t, p, l): gates.CNOT, [ gates.U3(0, 3 * np.pi / 2, np.pi, 0), - gates.U3(1, np.pi / 2, -np.pi, -np.pi), + gates.U3(1, np.pi / 2, np.pi, np.pi), gates.iSWAP(0, 1), gates.U3(0, np.pi, 0, np.pi), - gates.U3(1, np.pi / 2, -np.pi, -np.pi), + gates.U3(1, np.pi / 2, np.pi, np.pi), gates.iSWAP(0, 1), - gates.U3(0, np.pi / 2, np.pi / 2, -np.pi), - gates.U3(1, np.pi / 2, -np.pi, -np.pi / 2), + gates.U3(0, np.pi / 2, np.pi / 2, np.pi), + gates.U3(1, np.pi / 2, np.pi, -np.pi / 2), ], ) iswap_dec.add( gates.CZ, [ - gates.U3(0, 7 * np.pi / 2, np.pi, 0), - gates.U3(1, 7 * np.pi / 2, np.pi, 0), - gates.U3(1, np.pi / 2, -np.pi, -np.pi), + gates.U3(0, -np.pi / 2, np.pi, 0), + gates.U3(1, -np.pi / 2, np.pi, 0), + gates.U3(1, np.pi / 2, np.pi, np.pi), gates.iSWAP(0, 1), gates.U3(0, np.pi, 0, np.pi), - gates.U3(1, np.pi / 2, -np.pi, -np.pi), + gates.U3(1, np.pi / 2, np.pi, np.pi), gates.iSWAP(0, 1), - gates.U3(0, np.pi / 2, np.pi / 2, -np.pi), - gates.U3(1, np.pi / 2, -np.pi, -np.pi / 2), - gates.U3(1, 7 * np.pi / 2, np.pi, 0), + gates.U3(0, np.pi / 2, np.pi / 2, np.pi), + gates.U3(1, np.pi / 2, np.pi, -np.pi / 2), + gates.U3(1, -np.pi / 2, np.pi, 0), ], ) iswap_dec.add( @@ -304,14 +304,14 @@ def _u3_to_gpi2(t, p, l): cz_dec.add( gates.FSWAP, [ - gates.U3(0, np.pi / 2, -np.pi / 2, -np.pi), + gates.U3(0, np.pi / 2, -np.pi / 2, np.pi), gates.U3(1, np.pi / 2, np.pi / 2, np.pi / 2), gates.CZ(0, 1), gates.U3(0, np.pi / 2, 0, -np.pi / 2), gates.U3(1, np.pi / 2, 0, np.pi / 2), gates.CZ(0, 1), - gates.U3(0, np.pi / 2, np.pi / 2, -np.pi), - gates.U3(1, np.pi / 2, 0, -np.pi), + gates.U3(0, np.pi / 2, np.pi / 2, np.pi), + gates.U3(1, np.pi / 2, 0, np.pi), ], ) cz_dec.add( @@ -328,7 +328,7 @@ def _u3_to_gpi2(t, p, l): gates.RYY, lambda gate: [ gates.RX(0, np.pi / 2), - gates.U3(1, np.pi / 2, np.pi / 2, -np.pi), + gates.U3(1, np.pi / 2, np.pi / 2, np.pi), gates.CZ(0, 1), gates.RX(1, gate.parameters[0]), gates.CZ(0, 1), @@ -392,3 +392,21 @@ def _u3_to_gpi2(t, p, l): gates.H(1), ], ) + + +# standard gate decompositions used by :meth:`qibo.gates.gates.Gate.decompose` +standard = GateDecompositions() +standard.add(gates.SX, [gates.RX(0, np.pi / 2, trainable=False)]) +standard.add(gates.SXDG, [gates.RX(0, -np.pi / 2, trainable=False)]) +standard.add(gates.U3, [gates.RZ, gates.SX, gates.RZ, gates.SX, gates.RZ]) +standard.add(gates.CY, [gates.SDG, gates.CNOT, gates.S]) +standard.add(gates.CZ, [gates.H, gates.CNOT, gates.H]) +standard.add(gates.CSX, []) +standard.add(gates.CSXDG, []) +standard.add(gates.FSWAP, []) +standard.add(gates.RZX, []) +standard.add(gates.RXXYY, []) +standard.add(gates.GIVENS, []) +standard.add(gates.RBS, []) +standard.add(gates.ECR, []) +standard.add(gates.TOFFOLI, []) From 645e6f1eec20cc8f5c59db6d7a1309334019dc6b Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sun, 4 Feb 2024 08:36:46 +0400 Subject: [PATCH 2/6] testing function --- src/qibo/transpiler/decompositions.py | 34 +++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index cbefc02dc9..56901c8920 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -1,3 +1,4 @@ +#%% import numpy as np from qibo import gates @@ -395,18 +396,21 @@ def _u3_to_gpi2(t, p, l): # standard gate decompositions used by :meth:`qibo.gates.gates.Gate.decompose` -standard = GateDecompositions() -standard.add(gates.SX, [gates.RX(0, np.pi / 2, trainable=False)]) -standard.add(gates.SXDG, [gates.RX(0, -np.pi / 2, trainable=False)]) -standard.add(gates.U3, [gates.RZ, gates.SX, gates.RZ, gates.SX, gates.RZ]) -standard.add(gates.CY, [gates.SDG, gates.CNOT, gates.S]) -standard.add(gates.CZ, [gates.H, gates.CNOT, gates.H]) -standard.add(gates.CSX, []) -standard.add(gates.CSXDG, []) -standard.add(gates.FSWAP, []) -standard.add(gates.RZX, []) -standard.add(gates.RXXYY, []) -standard.add(gates.GIVENS, []) -standard.add(gates.RBS, []) -standard.add(gates.ECR, []) -standard.add(gates.TOFFOLI, []) +standard_decompositions = GateDecompositions() +standard_decompositions.add(gates.SX, [gates.RX(0, np.pi / 2, trainable=False)]) +standard_decompositions.add(gates.SXDG, [gates.RX(0, -np.pi / 2, trainable=False)]) +standard_decompositions.add( + gates.U3, + lambda gate: [gates.RZ(0, gate.parameters[2]), gates.SX(0), gates.RZ(0, gate.parameters[0] + np.pi), gates.SX(0), gates.RZ(0, gate.parameters[1] + np.pi)], +) +standard_decompositions.add(gates.CY, [gates.SDG, gates.CNOT, gates.S]) +standard_decompositions.add(gates.CZ, [gates.H, gates.CNOT, gates.H]) +standard_decompositions.add(gates.CSX, []) +standard_decompositions.add(gates.CSXDG, []) +standard_decompositions.add(gates.FSWAP, []) +standard_decompositions.add(gates.RZX, []) +standard_decompositions.add(gates.RXXYY, []) +standard_decompositions.add(gates.GIVENS, []) +standard_decompositions.add(gates.RBS, []) +standard_decompositions.add(gates.ECR, []) +standard_decompositions.add(gates.TOFFOLI, []) From 62971ea411e7f29cbcc3a79a2b03d7b4899d5554 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 4 Feb 2024 04:37:13 +0000 Subject: [PATCH 3/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/qibo/transpiler/decompositions.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index 56901c8920..72e49154fd 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -1,4 +1,4 @@ -#%% +# %% import numpy as np from qibo import gates @@ -400,8 +400,14 @@ def _u3_to_gpi2(t, p, l): standard_decompositions.add(gates.SX, [gates.RX(0, np.pi / 2, trainable=False)]) standard_decompositions.add(gates.SXDG, [gates.RX(0, -np.pi / 2, trainable=False)]) standard_decompositions.add( - gates.U3, - lambda gate: [gates.RZ(0, gate.parameters[2]), gates.SX(0), gates.RZ(0, gate.parameters[0] + np.pi), gates.SX(0), gates.RZ(0, gate.parameters[1] + np.pi)], + gates.U3, + lambda gate: [ + gates.RZ(0, gate.parameters[2]), + gates.SX(0), + gates.RZ(0, gate.parameters[0] + np.pi), + gates.SX(0), + gates.RZ(0, gate.parameters[1] + np.pi), + ], ) standard_decompositions.add(gates.CY, [gates.SDG, gates.CNOT, gates.S]) standard_decompositions.add(gates.CZ, [gates.H, gates.CNOT, gates.H]) From a7ac562498f5678679659944dc18303ae46066d2 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sun, 4 Feb 2024 09:43:36 +0400 Subject: [PATCH 4/6] implement refactoring --- src/qibo/gates/gates.py | 124 +++++++++++++------------- src/qibo/transpiler/decompositions.py | 69 +++++++++++--- 2 files changed, 118 insertions(+), 75 deletions(-) diff --git a/src/qibo/gates/gates.py b/src/qibo/gates/gates.py index aa0e0d5ede..588145a5dc 100644 --- a/src/qibo/gates/gates.py +++ b/src/qibo/gates/gates.py @@ -271,7 +271,11 @@ def decompose(self): being the :class:`qibo.gates.RX` gate. More precisely, :math:`\\sqrt{X} = e^{i \\pi / 4} \\, \\text{RX}(\\pi / 2)`. """ - return [RX(self.init_args[0], np.pi / 2, trainable=False)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) def _dagger(self): """""" @@ -314,7 +318,11 @@ def decompose(self): being the :class:`qibo.gates.RX` gate. More precisely, :math:`(\\sqrt{X})^{\\dagger} = e^{-i \\pi / 4} \\, \\text{RX}(-\\pi / 2)`. """ - return [RX(self.init_args[0], -np.pi / 2, trainable=False)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) def _dagger(self): """""" @@ -892,14 +900,11 @@ def decompose(self) -> List[Gate]: where :math:`\\text{RZ}` and :math:`\\sqrt{X}` are, respectively, :class:`qibo.gates.RZ` and :class`qibo.gates.SX`. """ - q = self.init_args[0] - return [ - RZ(q, self.init_kwargs["lam"]), - SX(q), - RZ(q, self.init_kwargs["theta"] + math.pi), - SX(q), - RZ(q, self.init_kwargs["phi"] + math.pi), - ] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class U1q(_Un_): @@ -1020,8 +1025,11 @@ def decompose(self) -> List[Gate]: the target qubit, followed by :class:`qibo.gates.CNOT`, followed by a :class:`qibo.gates.S` in the target qubit. """ - q0, q1 = self.init_args - return [SDG(q1), CNOT(q0, q1), S(q1)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class CZ(Gate): @@ -1063,8 +1071,11 @@ def decompose(self) -> List[Gate]: the target qubit, followed by :class:`qibo.gates.CNOT`, followed by another :class:`qibo.gates.H` in the target qubit """ - q0, q1 = self.init_args - return [H(q1), CNOT(q0, q1), H(q1)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class CSX(Gate): @@ -1100,8 +1111,11 @@ def qasm_label(self): def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: """""" - q0, q1 = self.init_args - return [H(q1), CU1(q0, q1, np.pi / 2), H(q1)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) def _dagger(self): """""" @@ -1141,8 +1155,11 @@ def qasm_label(self): def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: """""" - q0, q1 = self.init_args - return [H(q1), CU1(q0, q1, -np.pi / 2), H(q1)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) def _dagger(self): """""" @@ -1868,9 +1885,11 @@ def __init__(self, q0, q1, theta, trainable=True): def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: """""" - q0, q1 = self.target_qubits - theta = self.init_kwargs["theta"] - return [H(q1), CNOT(q0, q1), RZ(q1, theta), CNOT(q0, q1), H(q1)] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class RXXYY(_Rnn_): @@ -1909,22 +1928,11 @@ def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: the original gate due to a phase difference in :math:`\\left(\\sqrt{X}\\right)^{\\dagger}`. """ - q0, q1 = self.target_qubits - theta = self.init_kwargs["theta"] - return [ - RZ(q1, -np.pi / 2), - S(q0), - SX(q1), - RZ(q1, np.pi / 2), - CNOT(q1, q0), - RY(q0, -theta / 2), - RY(q1, -theta / 2), - CNOT(q1, q0), - SDG(q0), - RZ(q1, -np.pi / 2), - SX(q1).dagger(), - RZ(q1, np.pi / 2), - ] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class MS(ParametrizedGate): @@ -2029,18 +2037,13 @@ def _dagger(self) -> "Gate": return self.__class__(*self.target_qubits, -self.parameters[0]) def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: - """Decomposition of Givens gate according to `ArXiv:2106.13839 - `_.""" - q0, q1 = self.target_qubits - theta = self.init_kwargs["theta"] - return [ - CNOT(q0, q1), - RY(q0, theta), - CNOT(q1, q0), - RY(q0, -theta), - CNOT(q1, q0), - CNOT(q0, q1), - ] + """Decomposition of RBS gate according to `ArXiv:2109.09685 + `_.""" + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class RBS(ParametrizedGate): @@ -2090,18 +2093,11 @@ def _dagger(self) -> "Gate": def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: """Decomposition of RBS gate according to `ArXiv:2109.09685 `_.""" - q0, q1 = self.target_qubits - theta = self.init_kwargs["theta"] - return [ - H(q0), - CNOT(q0, q1), - H(q1), - RY(q0, theta), - RY(q1, -theta), - H(q1), - CNOT(q0, q1), - H(q0), - ] + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) + + return standard_decompositions(self) class ECR(Gate): @@ -2142,9 +2138,11 @@ def decompose(self, *free, use_toffolis: bool = True) -> List[Gate]: \\textup{ECR} = e^{i 7 \\pi / 4} \\, S(q_{0}) \\, \\sqrt{X}(q_{1}) \\, \\textup{CNOT}(q_{0}, q_{1}) \\, X(q_{0}) """ + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) - q0, q1 = self.target_qubits - return [S(q0), SX(q1), CNOT(q0, q1), X(q0)] + return standard_decompositions(self) class TOFFOLI(Gate): diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index 72e49154fd..813549e046 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -1,4 +1,3 @@ -# %% import numpy as np from qibo import gates @@ -409,14 +408,60 @@ def _u3_to_gpi2(t, p, l): gates.RZ(0, gate.parameters[1] + np.pi), ], ) -standard_decompositions.add(gates.CY, [gates.SDG, gates.CNOT, gates.S]) -standard_decompositions.add(gates.CZ, [gates.H, gates.CNOT, gates.H]) -standard_decompositions.add(gates.CSX, []) -standard_decompositions.add(gates.CSXDG, []) -standard_decompositions.add(gates.FSWAP, []) -standard_decompositions.add(gates.RZX, []) -standard_decompositions.add(gates.RXXYY, []) -standard_decompositions.add(gates.GIVENS, []) -standard_decompositions.add(gates.RBS, []) -standard_decompositions.add(gates.ECR, []) -standard_decompositions.add(gates.TOFFOLI, []) +standard_decompositions.add(gates.CY, [gates.SDG(1), gates.CNOT(0, 1), gates.S(1)]) +standard_decompositions.add(gates.CZ, [gates.H(1), gates.CNOT(0, 1), gates.H(1)]) +standard_decompositions.add( + gates.CSX, [gates.H(1), gates.CU1(0, 1, np.pi / 2), gates.H(1)] +) +standard_decompositions.add( + gates.CSXDG, [gates.H(1), gates.CU1(0, 1, -np.pi / 2), gates.H(1)] +) +standard_decompositions.add( + gates.FSWAP, [gates.X(1)] + gates.GIVENS(0, 1, np.pi / 2).decompose() + [gates.X(0)] +) +standard_decompositions.add( + gates.RZX, + lambda gate: [ + gates.H(1), + gates.CNOT(0, 1), + gates.RZ(1, gate.parameters[0]), + gates.CNOT(0, 1), + gates.H(1), + ], +) +standard_decompositions.add( + gates.RXXYY, + lambda gate: [ + gates.RZ(1, -np.pi / 2), + gates.S(0), + gates.SX(1), + gates.RZ(1, np.pi / 2), + gates.CNOT(1, 0), + gates.RY(0, -gate.parameters[0] / 2), + gates.RY(1, -gate.parameters[0] / 2), + gates.CNOT(1, 0), + gates.SDG(0), + gates.RZ(1, -np.pi / 2), + gates.SX(1).dagger(), + gates.RZ(1, np.pi / 2), + ], +) +standard_decompositions.add( + gates.GIVENS, lambda gate: gates.RBS(0, 1, -gate.parameters[1]).decompose() +) +standard_decompositions.add( + gates.RBS, + lambda gate: [ + gates.H(0), + gates.CNOT(0, 1), + gates.H(1), + gates.RY(0, gate.parameters[0]), + gates.RY(1, -gate.parameters[0]), + gates.H(1), + gates.CNOT(0, 1), + gates.H(0), + ], +) +standard_decompositions.add( + gates.ECR, [gates.S(0), gates.SX(1), gates.CNOT(0, 1), gates.X(0)] +) From a86e2acab1488fcadd254a5ca059c8f481cfd71e Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sun, 4 Feb 2024 10:17:53 +0400 Subject: [PATCH 5/6] fix order --- src/qibo/transpiler/decompositions.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index 813549e046..b36ff1c139 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -416,9 +416,6 @@ def _u3_to_gpi2(t, p, l): standard_decompositions.add( gates.CSXDG, [gates.H(1), gates.CU1(0, 1, -np.pi / 2), gates.H(1)] ) -standard_decompositions.add( - gates.FSWAP, [gates.X(1)] + gates.GIVENS(0, 1, np.pi / 2).decompose() + [gates.X(0)] -) standard_decompositions.add( gates.RZX, lambda gate: [ @@ -446,9 +443,6 @@ def _u3_to_gpi2(t, p, l): gates.RZ(1, np.pi / 2), ], ) -standard_decompositions.add( - gates.GIVENS, lambda gate: gates.RBS(0, 1, -gate.parameters[1]).decompose() -) standard_decompositions.add( gates.RBS, lambda gate: [ @@ -462,6 +456,12 @@ def _u3_to_gpi2(t, p, l): gates.H(0), ], ) +standard_decompositions.add( + gates.GIVENS, lambda gate: gates.RBS(0, 1, -gate.parameters[1]).decompose() +) +standard_decompositions.add( + gates.FSWAP, [gates.X(1)] + gates.GIVENS(0, 1, np.pi / 2).decompose() + [gates.X(0)] +) standard_decompositions.add( gates.ECR, [gates.S(0), gates.SX(1), gates.CNOT(0, 1), gates.X(0)] ) From 2a7b55b479c6fb7a98fa9521017752424df04052 Mon Sep 17 00:00:00 2001 From: Renato Mello Date: Sun, 4 Feb 2024 10:31:46 +0400 Subject: [PATCH 6/6] fix bug --- src/qibo/transpiler/decompositions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index b36ff1c139..f559f0088a 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -457,7 +457,7 @@ def _u3_to_gpi2(t, p, l): ], ) standard_decompositions.add( - gates.GIVENS, lambda gate: gates.RBS(0, 1, -gate.parameters[1]).decompose() + gates.GIVENS, lambda gate: gates.RBS(0, 1, -gate.parameters[0]).decompose() ) standard_decompositions.add( gates.FSWAP, [gates.X(1)] + gates.GIVENS(0, 1, np.pi / 2).decompose() + [gates.X(0)]