From 214d88012c6c8ccbdf577da5ca66db3300e6f78d Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 11:52:38 +0200 Subject: [PATCH 01/28] add sqrt x and controlled version --- qiskit/circuit/library/standard_gates/sx.py | 193 ++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 qiskit/circuit/library/standard_gates/sx.py diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py new file mode 100644 index 000000000000..1a34bda63035 --- /dev/null +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2017. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Sqrt(X) and C-Sqrt(X) gates.""" + +import numpy +from qiskit.qasm import pi +from qiskit.circuit.controlledgate import ControlledGate +from qiskit.circuit.gate import Gate +from qiskit.circuit.quantumregister import QuantumRegister + + +class SXGate(Gate): + r"""The single-qubit Sqrt(X) gate (:math:`\sqrt{X}`). + + **Matrix Representation:** + + .. math:: + + \sqrt{X} = \frac{1}{2} \begin{pmatrix} + 1 + i & 1 - i \\ + i - i & 1 + i + \end{pmatrix} + + **Circuit symbol:** + + .. parsed-literal:: + + ┌────┐ + q_0: ┤ √X ├ + └────┘ + + .. note:: + + A global phase difference exists between the definitions of + :math:`RX(\pi/2)` and :math:`\sqrt{X}`. + + .. math:: + + RX(\pi/2) = \frac{1}{\sqrt{2}} \begin{pmatrix} + 1 & -i \\ + -i & 1 + \end{pmatrix} + = e^{-i pi/4} \sqrt{X} + + """ + + def __init__(self, label=None): + """Create new SX gate.""" + super().__init__('sx', 1, [], label=label) + + def _define(self): + from .u1 import U1Gate + from .h import HGate + definition = [] + q = QuantumRegister(1, 'q') + rule = [ + (HGate(), [q[0]], []), + (U1Gate(pi / 2), [q[0]], []), + (HGate(), [q[0]], []) + ] + for inst in rule: + definition.append(inst) + self.definition = definition + + def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): + """Return a (mutli-)controlled-Y gate. + + One control returns a CY gate. + + Args: + num_ctrl_qubits (int): number of control qubits. + label (str or None): An optional label for the gate [Default: None] + ctrl_state (int or str or None): control state expressed as integer, + string (e.g. '110'), or None. If None, use all 1s. + + Returns: + ControlledGate: controlled version of this gate. + """ + if num_ctrl_qubits == 1: + gate = CSXGate(label=label, ctrl_state=ctrl_state) + gate.base_gate.label = self.label + return gate + return super().control(num_ctrl_qubits=num_ctrl_qubits, label=label, ctrl_state=ctrl_state) + + def to_matrix(self): + """Return a numpy.array for the SX gate.""" + return numpy.array([[1 + 1j, 1 - 1j], + [1 - 1j, 1 + 1j]], dtype=complex) / 2 + + +class CSXGate(ControlledGate): + r"""Controlled-√X gate. + + **Circuit symbol:** + + .. parsed-literal:: + + q_0: ──■── + ┌─┴──┐ + q_1: ┤ √X ├ + └────┘ + + **Matrix representation:** + + .. math:: + + C\sqrt{X} \ q_0, q_1 = + I \otimes |0 \rangle\langle 0| + \sqrt{X} \otimes |1 \rangle\langle 1| = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & (1 + i) / 2 & 0 & (1 - i) / 2 \\ + 0 & 0 & 1 & 0 \\ + 0 & (1 - i) / 2 & 0 & (1 + i) / 2 + \end{pmatrix} + + + .. note:: + + In Qiskit's convention, higher qubit indices are more significant + (little endian convention). In many textbooks, controlled gates are + presented with the assumption of more significant qubits as control, + which in our case would be `q_1`. Thus a textbook matrix for this + gate will be: + + .. parsed-literal:: + ┌────┐ + q_0: ┤ √X ├ + └─┬──┘ + q_1: ──■── + + .. math:: + + C\sqrt{X}\ q_1, q_0 = + |0 \rangle\langle 0| \otimes I + |1 \rangle\langle 1| \otimes \sqrt{X} = + \begin{pmatrix} + 1 & 0 & 0 & 0 \\ + 0 & 1 & 0 & 0 \\ + 0 & 0 & (1 + i) / 2 & (1 - i) / 2 \\ + 0 & 0 & (1 - i) / 2 & (1 + i) / 2 + \end{pmatrix} + + """ + # Define class constants. This saves future allocation time. + _matrix1 = numpy.array([[1, 0, 0, 0], + [0, (1 + 1j) / 2, 0, (1 - 1j) / 2], + [0, 0, 1, 0], + [0, (1 - 1j) / 2, 0, (1 + 1j) / 2]], dtype=complex) + _matrix0 = numpy.array([[(1 + 1j) / 2, 0, (1 - 1j) / 2, 0], + [0, 1, 0, 0], + [(1 - 1j) / 2, 0, (1 + 1j) / 2, 0], + [0, 0, 0, 1]], dtype=complex) + + def __init__(self, label=None, ctrl_state=None): + """Create new CSX gate.""" + super().__init__('csx', 2, [], num_ctrl_qubits=1, label=label, + ctrl_state=ctrl_state) + self.base_gate = SXGate() + + def _define(self): + """ + gate csx a,b { sdg b; cx a,b; s b; } + """ + from .h import HGate + from .u1 import CU1Gate + definition = [] + q = QuantumRegister(2, 'q') + rule = [ + (HGate(), [q[1]], []), + (CU1Gate(pi/2), [q[0], q[1]], []), + (HGate(), [q[1]], []) + ] + for inst in rule: + definition.append(inst) + self.definition = definition + + def to_matrix(self): + """Return a numpy.array for the CSX gate.""" + if self.ctrl_state: + return self._matrix1 + else: + return self._matrix0 From f958aaeb6c45ccf453306066a1516f262e466836 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 11:52:46 +0200 Subject: [PATCH 02/28] add to inits --- qiskit/circuit/library/__init__.py | 2 ++ qiskit/circuit/library/standard_gates/__init__.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/qiskit/circuit/library/__init__.py b/qiskit/circuit/library/__init__.py index 58691fd0072f..3f4e92412d21 100644 --- a/qiskit/circuit/library/__init__.py +++ b/qiskit/circuit/library/__init__.py @@ -35,6 +35,7 @@ CRYGate CRZGate CSwapGate + CSXGate CU1Gate CU3Gate CXGate @@ -58,6 +59,7 @@ SdgGate SwapGate iSwapGate + SXGate TGate TdgGate U1Gate diff --git a/qiskit/circuit/library/standard_gates/__init__.py b/qiskit/circuit/library/standard_gates/__init__.py index 99c09d32db31..153dd550d9a6 100644 --- a/qiskit/circuit/library/standard_gates/__init__.py +++ b/qiskit/circuit/library/standard_gates/__init__.py @@ -29,6 +29,7 @@ CRYGate CRZGate CSwapGate + CSXGate CU1Gate CU3Gate CXGate @@ -50,6 +51,7 @@ SdgGate SwapGate iSwapGate + SXGate TGate TdgGate U1Gate @@ -75,6 +77,7 @@ from .s import SGate, SdgGate from .swap import SwapGate, CSwapGate from .iswap import iSwapGate +from .sx import SXGate, CSXGate from .dcx import DCXGate from .t import TGate, TdgGate from .u1 import U1Gate, CU1Gate, MCU1Gate From e32cc987ac921c3b897dee4c1819ef871a5863cb Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 11:56:35 +0200 Subject: [PATCH 03/28] add to equivalence lib --- .../standard_gates/equivalence_library.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index c019fa3f3e2d..b01ef91ee6b6 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -41,6 +41,8 @@ SwapGate, CSwapGate, iSwapGate, + SXGate, + CSXGate, DCXGate, TGate, TdgGate, @@ -289,6 +291,30 @@ def_iswap.append(inst, qargs, cargs) _sel.add_equivalence(iSwapGate(), def_iswap) +# SXGate + +q = QuantumRegister(1, 'q') +def_sx = QuantumCircuit(q) +for inst, qargs, cargs in [ + (HGate(), [q[0]], []), + (U1Gate(pi / 2), [q[0]], []), + (HGate(), [q[0]], []) +]: + def_sx.append(inst, qargs, cargs) +_sel.add_equivalence(SXGate(), def_sx) + +# CSXGate + +q = QuantumRegister(2, 'q') +def_csx = QuantumCircuit(q) +for inst, qargs, cargs in [ + (HGate(), [q[1]], []), + (CU1Gate(pi / 2), [q[0], q[1]], []), + (HGate(), [q[1]], []) +]: + def_csx.append(inst, qargs, cargs) +_sel.add_equivalence(CSXGate(), def_csx) + # DCXGate q = QuantumRegister(2, 'q') From 8826707e554c9f3751a9b9d545478c6b707dd7c4 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 12:06:10 +0200 Subject: [PATCH 04/28] add to qelib --- qiskit/circuit/library/standard_gates/sx.py | 5 ++++- qiskit/qasm/libs/qelib1.inc | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 1a34bda63035..f1559ac65621 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -61,6 +61,9 @@ def __init__(self, label=None): super().__init__('sx', 1, [], label=label) def _define(self): + """ + gate sx a { h a; u1(pi/2) a; h a ;} + """ from .u1 import U1Gate from .h import HGate definition = [] @@ -170,7 +173,7 @@ def __init__(self, label=None, ctrl_state=None): def _define(self): """ - gate csx a,b { sdg b; cx a,b; s b; } + gate csx a,b { h b; cu1(pi/2) a,b; h b; } """ from .h import HGate from .u1 import CU1Gate diff --git a/qiskit/qasm/libs/qelib1.inc b/qiskit/qasm/libs/qelib1.inc index 68c41d4786b4..9c1392379990 100644 --- a/qiskit/qasm/libs/qelib1.inc +++ b/qiskit/qasm/libs/qelib1.inc @@ -45,6 +45,8 @@ gate rz(phi) a { u1(phi) a; } // --- QE Standard User-Defined Gates --- +// sqrt(X) +gate sx a { h a; u1(pi/2) a; h a; } // controlled-Phase gate cz a,b { h b; cx a,b; h b; } // controlled-Y @@ -122,6 +124,8 @@ gate cu3(theta,phi,lambda) c, t cx c,t; u3(theta/2,phi,0) t; } +// controlled-sqrt(X) +gate csx a { h b; cu1(pi/2) a,b; h b; } // two-qubit XX rotation gate rxx(theta) a,b { From 7a60a5ef7b39f22bd6e7fad0b962dd79c88f19e0 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 12:12:02 +0200 Subject: [PATCH 05/28] add circuit methods --- qiskit/circuit/quantumcircuit.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index 5c14807f8357..e5a84b19d699 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -1908,6 +1908,17 @@ def fredkin(self, control_qubit, target_qubit1, target_qubit2, """Apply :class:`~qiskit.circuit.library.CSwapGate`.""" return self.cswap(control_qubit, target_qubit1, target_qubit2) + def sx(self, qubit): + """Apply :class:`~qiskit.circuit.library.SXGate`.""" + from .library.standard_gates.sx import SXGate + return self.append(SXGate(), [qubit], []) + + def csx(self, control_qubit, target_qubit, label=None, ctrl_state=None): + """Apply :class:`~qiskit.circuit.library.CSXGate`.""" + from .library.standard_gates.sx import CSXGate + return self.append(CSXGate(label=label, ctrl_state=ctrl_state), + [control_qubit, target_qubit], []) + @deprecate_arguments({'q': 'qubit'}) def t(self, qubit, *, q=None): # pylint: disable=invalid-name,unused-argument """Apply :class:`~qiskit.circuit.library.TGate`.""" From 8dd8b783f7ed0e84dbbe09907cc042740c2b201a Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 12:12:34 +0200 Subject: [PATCH 06/28] add to label test --- test/python/circuit/test_controlled_gate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index 9de8c2bc281e..d682c722b251 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -34,7 +34,7 @@ from qiskit.converters.dag_to_circuit import dag_to_circuit from qiskit.quantum_info import Operator from qiskit.circuit.library import (CXGate, XGate, YGate, ZGate, U1Gate, - CYGate, CZGate, CU1Gate, SwapGate, + CYGate, CZGate, CU1Gate, SwapGate, SXGate, CSXGate, CCXGate, HGate, RZGate, RXGate, RYGate, CRYGate, CRXGate, CSwapGate, U3Gate, CHGate, CRZGate, CU3Gate, @@ -1147,6 +1147,8 @@ class TestControlledGateLabel(QiskitTestCase): (CZGate, []), (CU1Gate, [0.1]), (SwapGate, []), + (SXGate, []), + (CSXGate, []), (CCXGate, []), (RZGate, [0.1]), (RXGate, [0.1]), From e3f600ac153e7e2f49fb9a34e47331f28ddd9a3c Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 12:18:48 +0200 Subject: [PATCH 07/28] add reno --- releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml diff --git a/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml b/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml new file mode 100644 index 000000000000..bc4b17580ccc --- /dev/null +++ b/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Added the sqrt(X) and controlled-sqrt(X) gates as circuit methods. + They are available as ``QuantumCircuit.sx`` and ``QuantumCircuit.csx``, + with the respective gate classes ``SXGate`` and ``CSXGate``. From ea0a32940d7d68cdfedfcf6ee0b023f6b6625ff9 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Thu, 2 Jul 2020 12:27:56 +0200 Subject: [PATCH 08/28] fix missing qubit in qelub --- qiskit/qasm/libs/qelib1.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/qasm/libs/qelib1.inc b/qiskit/qasm/libs/qelib1.inc index 9c1392379990..0646612590bd 100644 --- a/qiskit/qasm/libs/qelib1.inc +++ b/qiskit/qasm/libs/qelib1.inc @@ -125,7 +125,7 @@ gate cu3(theta,phi,lambda) c, t u3(theta/2,phi,0) t; } // controlled-sqrt(X) -gate csx a { h b; cu1(pi/2) a,b; h b; } +gate csx a b { h b; cu1(pi/2) a,b; h b; } // two-qubit XX rotation gate rxx(theta) a,b { From 6d62d0ee36371f3f126e47f828aeeb43010299fd Mon Sep 17 00:00:00 2001 From: Cryoris Date: Fri, 3 Jul 2020 11:51:58 +0200 Subject: [PATCH 09/28] change SX definition to use only one H --- .../standard_gates/equivalence_library.py | 4 ++-- qiskit/circuit/library/standard_gates/sx.py | 16 +++++++++------- qiskit/qasm/libs/qelib1.inc | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index b01ef91ee6b6..6c3a8d37c1fb 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -296,9 +296,9 @@ q = QuantumRegister(1, 'q') def_sx = QuantumCircuit(q) for inst, qargs, cargs in [ + (RZGate(-pi / 2), [q[0]], []), (HGate(), [q[0]], []), - (U1Gate(pi / 2), [q[0]], []), - (HGate(), [q[0]], []) + (RZGate(-pi / 2), [q[0]], []) ]: def_sx.append(inst, qargs, cargs) _sel.add_equivalence(SXGate(), def_sx) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index f1559ac65621..ac1799cea828 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -62,7 +62,7 @@ def __init__(self, label=None): def _define(self): """ - gate sx a { h a; u1(pi/2) a; h a ;} + gate sx a { rz(-pi/2) a; h a; rz(-pi/2); } """ from .u1 import U1Gate from .h import HGate @@ -78,9 +78,9 @@ def _define(self): self.definition = definition def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): - """Return a (mutli-)controlled-Y gate. + """Return a (multi-)controlled-SX gate. - One control returns a CY gate. + One control returns a CSX gate. Args: num_ctrl_qubits (int): number of control qubits. @@ -97,10 +97,12 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): return gate return super().control(num_ctrl_qubits=num_ctrl_qubits, label=label, ctrl_state=ctrl_state) - def to_matrix(self): - """Return a numpy.array for the SX gate.""" - return numpy.array([[1 + 1j, 1 - 1j], - [1 - 1j, 1 + 1j]], dtype=complex) / 2 + # Differs by global phase of exp(-i pi/4) with correct RZ. + # If the RZ == U1, then the global phase difference is exp(i pi/4) + # def to_matrix(self): + # """Return a numpy.array for the SX gate.""" + # return numpy.array([[1 + 1j, 1 - 1j], + # [1 - 1j, 1 + 1j]], dtype=complex) / 2 class CSXGate(ControlledGate): diff --git a/qiskit/qasm/libs/qelib1.inc b/qiskit/qasm/libs/qelib1.inc index 0646612590bd..ae98e5a93985 100644 --- a/qiskit/qasm/libs/qelib1.inc +++ b/qiskit/qasm/libs/qelib1.inc @@ -46,7 +46,7 @@ gate rz(phi) a { u1(phi) a; } // --- QE Standard User-Defined Gates --- // sqrt(X) -gate sx a { h a; u1(pi/2) a; h a; } +gate sx a { rz(-pi/2) a; h a; rz(-pi/2) a; } // controlled-Phase gate cz a,b { h b; cx a,b; h b; } // controlled-Y @@ -125,7 +125,7 @@ gate cu3(theta,phi,lambda) c, t u3(theta/2,phi,0) t; } // controlled-sqrt(X) -gate csx a b { h b; cu1(pi/2) a,b; h b; } +gate csx a,b { h b; cu1(pi/2) a,b; h b; } // two-qubit XX rotation gate rxx(theta) a,b { From 25452ce19e9636ba5a56b66274979a70759cca2b Mon Sep 17 00:00:00 2001 From: Cryoris Date: Fri, 3 Jul 2020 11:58:37 +0200 Subject: [PATCH 10/28] update decomp in gate and add default label --- qiskit/circuit/library/standard_gates/sx.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index ac1799cea828..6e2c66cd41b6 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -56,7 +56,7 @@ class SXGate(Gate): """ - def __init__(self, label=None): + def __init__(self, label='√X'): """Create new SX gate.""" super().__init__('sx', 1, [], label=label) @@ -64,14 +64,14 @@ def _define(self): """ gate sx a { rz(-pi/2) a; h a; rz(-pi/2); } """ - from .u1 import U1Gate + from .rz import RZGate from .h import HGate definition = [] q = QuantumRegister(1, 'q') rule = [ + (RZGate(-pi / 2), [q[0]], []), (HGate(), [q[0]], []), - (U1Gate(pi / 2), [q[0]], []), - (HGate(), [q[0]], []) + (RZGate(-pi / 2), [q[0]], []) ] for inst in rule: definition.append(inst) From be6221b970fed7bb084bc6df5a8bd25644d9729b Mon Sep 17 00:00:00 2001 From: Cryoris Date: Fri, 3 Jul 2020 12:26:20 +0200 Subject: [PATCH 11/28] fix test by accounting for global phase diff --- qiskit/circuit/library/standard_gates/sx.py | 1 + test/python/circuit/test_controlled_gate.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 6e2c66cd41b6..021835adea49 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -99,6 +99,7 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): # Differs by global phase of exp(-i pi/4) with correct RZ. # If the RZ == U1, then the global phase difference is exp(i pi/4) + # TODO: Restore after allowing phase on circuits. # def to_matrix(self): # """Return a numpy.array for the SX gate.""" # return numpy.array([[1 + 1j, 1 - 1j], diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index d682c722b251..80b27c6710fa 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -1033,6 +1033,8 @@ def test_controlled_standard_gates(self, num_ctrl_qubits, gate_class): iden = Operator.from_label('I') zgen = Operator.from_label('Z') base_mat = (np.cos(0.5 * theta) * iden - 1j * np.sin(0.5 * theta) * zgen).data + elif gate.name == 'sx': # account for global phase diff + base_mat = Operator(gate).data * np.exp(0.25j * np.pi) else: base_mat = Operator(gate).data target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, From 22b84e133d21a7d1becb557f22d3f22642d93fe9 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Fri, 3 Jul 2020 13:36:00 +0200 Subject: [PATCH 12/28] handle case of 1 ctrl qubit separately --- test/python/circuit/test_controlled_gate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index 80b27c6710fa..455f057e7ec7 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -1033,7 +1033,8 @@ def test_controlled_standard_gates(self, num_ctrl_qubits, gate_class): iden = Operator.from_label('I') zgen = Operator.from_label('Z') base_mat = (np.cos(0.5 * theta) * iden - 1j * np.sin(0.5 * theta) * zgen).data - elif gate.name == 'sx': # account for global phase diff + # account for global phase diff, CSX is exact + elif gate.name == 'sx' and num_ctrl_qubits == 1: base_mat = Operator(gate).data * np.exp(0.25j * np.pi) else: base_mat = Operator(gate).data From df9269cfd46b669168877c5dd7927e1812801cb3 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Mon, 6 Jul 2020 10:34:06 +0200 Subject: [PATCH 13/28] account for global phase in CSX test --- test/python/circuit/test_controlled_gate.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index 455f057e7ec7..39c24d1d9de5 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -913,6 +913,8 @@ def test_open_controlled_to_matrix(self, gate_class, ctrl_state): cgate = gate_class(*free_params) cgate.ctrl_state = ctrl_state base_mat = Operator(cgate.base_gate).data + if gate_class == CSXGate: + base_mat *= np.exp(0.25j * np.pi) # SX has a global phase, must be accounted for in CSX target = _compute_control_matrix(base_mat, cgate.num_ctrl_qubits, ctrl_state=ctrl_state) try: From fe5c2d560799957de6129c4c30b04c1d04af27a6 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Mon, 6 Jul 2020 12:22:42 +0200 Subject: [PATCH 14/28] change to new gate def --- qiskit/circuit/library/standard_gates/sx.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 021835adea49..3b4ecd43d3d3 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -64,18 +64,18 @@ def _define(self): """ gate sx a { rz(-pi/2) a; h a; rz(-pi/2); } """ + from qiskit.circuit.quantumcircuit import QuantumCircuit from .rz import RZGate from .h import HGate - definition = [] q = QuantumRegister(1, 'q') - rule = [ + qc = QuantumCircuit(q, name=self.name) + rules = [ (RZGate(-pi / 2), [q[0]], []), (HGate(), [q[0]], []), (RZGate(-pi / 2), [q[0]], []) ] - for inst in rule: - definition.append(inst) - self.definition = definition + qc.data = rules + self.definition = qc def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): """Return a (multi-)controlled-SX gate. @@ -178,18 +178,18 @@ def _define(self): """ gate csx a,b { h b; cu1(pi/2) a,b; h b; } """ + from qiskit.circuit.quantumcircuit import QuantumCircuit from .h import HGate from .u1 import CU1Gate - definition = [] q = QuantumRegister(2, 'q') - rule = [ + qc = QuantumCircuit(q, name=self.name) + rules = [ (HGate(), [q[1]], []), (CU1Gate(pi/2), [q[0], q[1]], []), (HGate(), [q[1]], []) ] - for inst in rule: - definition.append(inst) - self.definition = definition + qc.data = rules + self.definition = qc def to_matrix(self): """Return a numpy.array for the CSX gate.""" From 7b3876aa0f965460b8a9c4e2aeedd3690b8365b2 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Mon, 6 Jul 2020 13:50:17 +0200 Subject: [PATCH 15/28] ignore cyclic import --- qiskit/circuit/library/standard_gates/sx.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 3b4ecd43d3d3..7848a3bdb8ba 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -64,6 +64,7 @@ def _define(self): """ gate sx a { rz(-pi/2) a; h a; rz(-pi/2); } """ + # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .rz import RZGate from .h import HGate @@ -178,6 +179,7 @@ def _define(self): """ gate csx a,b { h b; cu1(pi/2) a,b; h b; } """ + # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .h import HGate from .u1 import CU1Gate From 6cb5812c6fa9724defe4dd4dcbbf282f3d311b45 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Mon, 13 Jul 2020 09:24:32 +0200 Subject: [PATCH 16/28] add SXdg gate --- qiskit/circuit/library/__init__.py | 1 + .../library/standard_gates/__init__.py | 3 +- .../standard_gates/equivalence_library.py | 12 ++++ qiskit/circuit/library/standard_gates/sx.py | 59 ++++++++++++++++++- qiskit/circuit/quantumcircuit.py | 5 ++ qiskit/qasm/libs/qelib1.inc | 2 + 6 files changed, 80 insertions(+), 2 deletions(-) diff --git a/qiskit/circuit/library/__init__.py b/qiskit/circuit/library/__init__.py index 3f4e92412d21..88472a50d494 100644 --- a/qiskit/circuit/library/__init__.py +++ b/qiskit/circuit/library/__init__.py @@ -60,6 +60,7 @@ SwapGate iSwapGate SXGate + SXdgGate TGate TdgGate U1Gate diff --git a/qiskit/circuit/library/standard_gates/__init__.py b/qiskit/circuit/library/standard_gates/__init__.py index 153dd550d9a6..d29b42dafde7 100644 --- a/qiskit/circuit/library/standard_gates/__init__.py +++ b/qiskit/circuit/library/standard_gates/__init__.py @@ -52,6 +52,7 @@ SwapGate iSwapGate SXGate + SXdgGate TGate TdgGate U1Gate @@ -77,7 +78,7 @@ from .s import SGate, SdgGate from .swap import SwapGate, CSwapGate from .iswap import iSwapGate -from .sx import SXGate, CSXGate +from .sx import SXGate, SXdgGate, CSXGate from .dcx import DCXGate from .t import TGate, TdgGate from .u1 import U1Gate, CU1Gate, MCU1Gate diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index 6c3a8d37c1fb..ecffa90080ad 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -410,6 +410,18 @@ u3_qasm_def.rz(phi+3*pi, 0) _sel.add_equivalence(U3Gate(theta, phi, lam), u3_qasm_def) +q = QuantumRegister(1, 'q') +theta = Parameter('theta') +phi = Parameter('phi') +lam = Parameter('lam') +u3_qasm_def = QuantumCircuit(q) +u3_qasm_def.rz(lam, 0) +u3_qasm_def.sxdg(0) +u3_qasm_def.rz(theta+pi, 0) +u3_qasm_def.sxdg(0) +u3_qasm_def.rz(phi+3*pi, 0) +_sel.add_equivalence(U3Gate(theta, phi, lam), u3_qasm_def) + # CU3Gate q = QuantumRegister(2, 'q') diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 7848a3bdb8ba..fa9c9029f4a6 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -30,7 +30,7 @@ class SXGate(Gate): \sqrt{X} = \frac{1}{2} \begin{pmatrix} 1 + i & 1 - i \\ - i - i & 1 + i + 1 - i & 1 + i \end{pmatrix} **Circuit symbol:** @@ -107,6 +107,63 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): # [1 - 1j, 1 + 1j]], dtype=complex) / 2 +class SXdgGate(Gate): + r"""The inverse single-qubit Sqrt(X) gate. + + .. math:: + + \sqrt{X}^{\dagger} = \frac{1}{2} \begin{pmatrix} + 1 - i & 1 + i \\ + 1 + i & 1 - i + \end{pmatrix} + + + .. note:: + + A global phase difference exists between the definitions of + :math:`RX(-\pi/2)` and :math:`\sqrt{X}^{\dagger}`. + + .. math:: + + RX(-\pi/2) = \frac{1}{\sqrt{2}} \begin{pmatrix} + 1 & i \\ + i & 1 + \end{pmatrix} + = e^{-i pi/4} \sqrt{X}^{\dagger} + + """ + + def __init__(self, label='√X_dg'): + """Create new SXdg gate.""" + super().__init__('sxdg', 1, [], label=label) + + def _define(self): + """ + gate sxdg a { rz(pi/2) a; h a; rz(pi/2); } + """ + # pylint: disable=cyclic-import + from qiskit.circuit.quantumcircuit import QuantumCircuit + from .rz import RZGate + from .h import HGate + q = QuantumRegister(1, 'q') + qc = QuantumCircuit(q, name=self.name) + rules = [ + (RZGate(pi / 2), [q[0]], []), + (HGate(), [q[0]], []), + (RZGate(pi / 2), [q[0]], []) + ] + qc.data = rules + self.definition = qc + + # Differs by global phase of exp(-i pi/4) with correct RZ. + # If the RZ == U1, then the global phase difference is exp(i pi/4) + # TODO: Restore after allowing phase on circuits. + # def to_matrix(self): + # """Return a numpy.array for the SX gate.""" + # return numpy.array([[1 - 1j, 1 + 1j], + # [1 + 1j, 1 - 1j]], dtype=complex) / 2 + + class CSXGate(ControlledGate): r"""Controlled-√X gate. diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index e5a84b19d699..d7633f58c260 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -1913,6 +1913,11 @@ def sx(self, qubit): from .library.standard_gates.sx import SXGate return self.append(SXGate(), [qubit], []) + def sxdg(self, qubit): + """Apply :class:`~qiskit.circuit.library.SXdgGate`.""" + from .library.standard_gates.sx import SXdgGate + return self.append(SXdgGate(), [qubit], []) + def csx(self, control_qubit, target_qubit, label=None, ctrl_state=None): """Apply :class:`~qiskit.circuit.library.CSXGate`.""" from .library.standard_gates.sx import CSXGate diff --git a/qiskit/qasm/libs/qelib1.inc b/qiskit/qasm/libs/qelib1.inc index ae98e5a93985..bfa7df86058e 100644 --- a/qiskit/qasm/libs/qelib1.inc +++ b/qiskit/qasm/libs/qelib1.inc @@ -47,6 +47,8 @@ gate rz(phi) a { u1(phi) a; } // sqrt(X) gate sx a { rz(-pi/2) a; h a; rz(-pi/2) a; } +// inverse sqrt(X) +gate sxdg a { rz(pi/2) a; h a; rz(pi/2) a; } // controlled-Phase gate cz a,b { h b; cx a,b; h b; } // controlled-Y From 621d781e2628fbf7cf70ade17f0dbad5f7bd4393 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 14 Jul 2020 13:51:26 +0200 Subject: [PATCH 17/28] fix U3 equivalence, add rz to sx ry --- .../library/standard_gates/equivalence_library.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index ecffa90080ad..191d8456e396 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -42,6 +42,7 @@ CSwapGate, iSwapGate, SXGate, + SXdgGate, CSXGate, DCXGate, TGate, @@ -223,6 +224,13 @@ rz_to_rxry.append(RXGate(-pi/2), [q[0]], []) _sel.add_equivalence(RZGate(theta), rz_to_rxry) +q = QuantumRegister(1, 'q') +rz_to_sxry = QuantumCircuit(q) +rz_to_sxry.append(SXGate(), [q[0]], []) +rz_to_sxry.append(RYGate(-theta), [q[0]], []) +rz_to_sxry.append(SXdgGate(), [q[0]], []) +_sel.add_equivalence(RZGate(theta), rz_to_sxry) + # CRZGate q = QuantumRegister(2, 'q') @@ -416,9 +424,9 @@ lam = Parameter('lam') u3_qasm_def = QuantumCircuit(q) u3_qasm_def.rz(lam, 0) -u3_qasm_def.sxdg(0) +u3_qasm_def.sx(0) u3_qasm_def.rz(theta+pi, 0) -u3_qasm_def.sxdg(0) +u3_qasm_def.sx(0) u3_qasm_def.rz(phi+3*pi, 0) _sel.add_equivalence(U3Gate(theta, phi, lam), u3_qasm_def) From 010e50c447b5d5ba98b96ea80ab859492899c6be Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 15 Jul 2020 12:42:30 +0200 Subject: [PATCH 18/28] equivalences: replace RX by SX, add SX->RX --- .../standard_gates/equivalence_library.py | 48 ++++++++++--------- test/python/circuit/test_gate_definitions.py | 4 +- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index 191d8456e396..9553a83c7bca 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -216,19 +216,11 @@ def_rz.append(U1Gate(theta), [q[0]], []) _sel.add_equivalence(RZGate(theta), def_rz) -q = QuantumRegister(1, 'q') -theta = Parameter('theta') -rz_to_rxry = QuantumCircuit(q) -rz_to_rxry.append(RXGate(pi/2), [q[0]], []) -rz_to_rxry.append(RYGate(-theta), [q[0]], []) -rz_to_rxry.append(RXGate(-pi/2), [q[0]], []) -_sel.add_equivalence(RZGate(theta), rz_to_rxry) - q = QuantumRegister(1, 'q') rz_to_sxry = QuantumCircuit(q) -rz_to_sxry.append(SXGate(), [q[0]], []) -rz_to_sxry.append(RYGate(-theta), [q[0]], []) -rz_to_sxry.append(SXdgGate(), [q[0]], []) +rz_to_sxry.sx(0) +rz_to_sxry.ry(-theta, 0) +rz_to_sxry.sxdg(0) _sel.add_equivalence(RZGate(theta), rz_to_sxry) # CRZGate @@ -311,6 +303,28 @@ def_sx.append(inst, qargs, cargs) _sel.add_equivalence(SXGate(), def_sx) +q = QuantumRegister(1, 'q') +sx_to_rx = QuantumCircuit(q) +sx_to_rx.rx(pi / 2, 0) +_sel.add_equivalence(SXGate(), sx_to_rx) + +# SXdgGate + +q = QuantumRegister(1, 'q') +def_sxdg = QuantumCircuit(q) +for inst, qargs, cargs in [ + (RZGate(pi / 2), [q[0]], []), + (HGate(), [q[0]], []), + (RZGate(pi / 2), [q[0]], []) +]: + def_sxdg.append(inst, qargs, cargs) +_sel.add_equivalence(SXdgGate(), def_sxdg) + +q = QuantumRegister(1, 'q') +sxdg_to_rx = QuantumCircuit(q) +sxdg_to_rx.rx(-pi / 2, 0) +_sel.add_equivalence(SXdgGate(), sxdg_to_rx) + # CSXGate q = QuantumRegister(2, 'q') @@ -406,18 +420,6 @@ # U3Gate -q = QuantumRegister(1, 'q') -theta = Parameter('theta') -phi = Parameter('phi') -lam = Parameter('lam') -u3_qasm_def = QuantumCircuit(q) -u3_qasm_def.rz(lam, 0) -u3_qasm_def.rx(pi/2, 0) -u3_qasm_def.rz(theta+pi, 0) -u3_qasm_def.rx(pi/2, 0) -u3_qasm_def.rz(phi+3*pi, 0) -_sel.add_equivalence(U3Gate(theta, phi, lam), u3_qasm_def) - q = QuantumRegister(1, 'q') theta = Parameter('theta') phi = Parameter('phi') diff --git a/test/python/circuit/test_gate_definitions.py b/test/python/circuit/test_gate_definitions.py index 7fd98d9ff5b3..a8cf6f45df12 100644 --- a/test/python/circuit/test_gate_definitions.py +++ b/test/python/circuit/test_gate_definitions.py @@ -27,7 +27,7 @@ HGate, CHGate, IGate, RGate, RXGate, CRXGate, RYGate, CRYGate, RZGate, CRZGate, SGate, SdgGate, CSwapGate, TGate, TdgGate, U1Gate, CU1Gate, U2Gate, U3Gate, CU3Gate, XGate, CXGate, CCXGate, YGate, CYGate, - ZGate, CZGate, RYYGate + ZGate, CZGate, RYYGate, SXGate, SXdgGate ) from qiskit.circuit.library.standard_gates.equivalence_library import ( @@ -122,7 +122,7 @@ class TestStandardEquivalenceLibrary(QiskitTestCase): HGate, CHGate, IGate, RGate, RXGate, CRXGate, RYGate, CRYGate, RZGate, CRZGate, SGate, SdgGate, CSwapGate, TGate, TdgGate, U1Gate, CU1Gate, U2Gate, U3Gate, CU3Gate, XGate, CXGate, CCXGate, YGate, CYGate, - ZGate, CZGate, RYYGate + ZGate, CZGate, RYYGate, SXGate, SXdgGate ) def test_definition_parameters(self, gate_class): """Verify decompositions from standard equivalence library match definitions.""" From faa28a9a6978830ee0df90abf4eacafb6319e3fb Mon Sep 17 00:00:00 2001 From: Julien Gacon Date: Sat, 25 Jul 2020 10:24:24 +0200 Subject: [PATCH 19/28] Apply suggestions from code review Co-authored-by: Ali Javadi-Abhari --- .../circuit/library/standard_gates/equivalence_library.py | 8 ++++---- qiskit/circuit/library/standard_gates/sx.py | 2 +- qiskit/qasm/libs/qelib1.inc | 6 +++--- test/python/circuit/test_gate_definitions.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index 9553a83c7bca..1e1987888767 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -296,9 +296,9 @@ q = QuantumRegister(1, 'q') def_sx = QuantumCircuit(q) for inst, qargs, cargs in [ - (RZGate(-pi / 2), [q[0]], []), + (SdgGate(), [q[0]], []), (HGate(), [q[0]], []), - (RZGate(-pi / 2), [q[0]], []) + (SdgGate(), [q[0]], []) ]: def_sx.append(inst, qargs, cargs) _sel.add_equivalence(SXGate(), def_sx) @@ -313,9 +313,9 @@ q = QuantumRegister(1, 'q') def_sxdg = QuantumCircuit(q) for inst, qargs, cargs in [ - (RZGate(pi / 2), [q[0]], []), + (SGate(), [q[0]], []), (HGate(), [q[0]], []), - (RZGate(pi / 2), [q[0]], []) + (SGate(), [q[0]], []) ]: def_sxdg.append(inst, qargs, cargs) _sel.add_equivalence(SXdgGate(), def_sxdg) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index fa9c9029f4a6..76ffe26657f3 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -133,7 +133,7 @@ class SXdgGate(Gate): """ - def __init__(self, label='√X_dg'): + def __init__(self, label='√X^†'): """Create new SXdg gate.""" super().__init__('sxdg', 1, [], label=label) diff --git a/qiskit/qasm/libs/qelib1.inc b/qiskit/qasm/libs/qelib1.inc index bfa7df86058e..dab7357f8f9c 100644 --- a/qiskit/qasm/libs/qelib1.inc +++ b/qiskit/qasm/libs/qelib1.inc @@ -46,9 +46,9 @@ gate rz(phi) a { u1(phi) a; } // --- QE Standard User-Defined Gates --- // sqrt(X) -gate sx a { rz(-pi/2) a; h a; rz(-pi/2) a; } +gate sx a { sdg a; h a; sdg a; } // inverse sqrt(X) -gate sxdg a { rz(pi/2) a; h a; rz(pi/2) a; } +gate sxdg a { s a; h a; s a; } // controlled-Phase gate cz a,b { h b; cx a,b; h b; } // controlled-Y @@ -223,4 +223,4 @@ gate c4x a,b,c,d,e h d; cu1(pi/4) d,e; h d; c3x a,b,c,d; c3sqrtx a,b,c,e; -} \ No newline at end of file +} diff --git a/test/python/circuit/test_gate_definitions.py b/test/python/circuit/test_gate_definitions.py index a8cf6f45df12..7f9d9e8c001e 100644 --- a/test/python/circuit/test_gate_definitions.py +++ b/test/python/circuit/test_gate_definitions.py @@ -122,7 +122,7 @@ class TestStandardEquivalenceLibrary(QiskitTestCase): HGate, CHGate, IGate, RGate, RXGate, CRXGate, RYGate, CRYGate, RZGate, CRZGate, SGate, SdgGate, CSwapGate, TGate, TdgGate, U1Gate, CU1Gate, U2Gate, U3Gate, CU3Gate, XGate, CXGate, CCXGate, YGate, CYGate, - ZGate, CZGate, RYYGate, SXGate, SXdgGate + ZGate, CZGate, RYYGate, SXGate, SXdgGate, CSXGate ) def test_definition_parameters(self, gate_class): """Verify decompositions from standard equivalence library match definitions.""" From 54819288894110526eee93758988d47adfad4488 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Sat, 25 Jul 2020 11:08:03 +0200 Subject: [PATCH 20/28] update to accomodate global phases --- .../standard_gates/equivalence_library.py | 10 ++--- qiskit/circuit/library/standard_gates/sx.py | 38 ++++++++----------- test/python/circuit/test_controlled_gate.py | 5 --- test/python/circuit/test_gate_definitions.py | 2 +- 4 files changed, 22 insertions(+), 33 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index decdaffee083..639c9b8a50ab 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -311,7 +311,7 @@ # SXGate q = QuantumRegister(1, 'q') -def_sx = QuantumCircuit(q) +def_sx = QuantumCircuit(q, global_phase=pi / 4) for inst, qargs, cargs in [ (SdgGate(), [q[0]], []), (HGate(), [q[0]], []), @@ -321,14 +321,14 @@ _sel.add_equivalence(SXGate(), def_sx) q = QuantumRegister(1, 'q') -sx_to_rx = QuantumCircuit(q) +sx_to_rx = QuantumCircuit(q, global_phase=pi / 4) sx_to_rx.rx(pi / 2, 0) _sel.add_equivalence(SXGate(), sx_to_rx) # SXdgGate q = QuantumRegister(1, 'q') -def_sxdg = QuantumCircuit(q) +def_sxdg = QuantumCircuit(q, global_phase=-pi / 4) for inst, qargs, cargs in [ (SGate(), [q[0]], []), (HGate(), [q[0]], []), @@ -338,7 +338,7 @@ _sel.add_equivalence(SXdgGate(), def_sxdg) q = QuantumRegister(1, 'q') -sxdg_to_rx = QuantumCircuit(q) +sxdg_to_rx = QuantumCircuit(q, global_phase=-pi / 4) sxdg_to_rx.rx(-pi / 2, 0) _sel.add_equivalence(SXdgGate(), sxdg_to_rx) @@ -441,7 +441,7 @@ theta = Parameter('theta') phi = Parameter('phi') lam = Parameter('lam') -u3_qasm_def = QuantumCircuit(q, global_phase=(lam + phi) / 2) +u3_qasm_def = QuantumCircuit(q, global_phase=(lam + phi - pi) / 2) u3_qasm_def.rz(lam, 0) u3_qasm_def.sx(0) u3_qasm_def.rz(theta+pi, 0) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 76ffe26657f3..18288dfa1366 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -66,14 +66,14 @@ def _define(self): """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit - from .rz import RZGate + from .s import SdgGate from .h import HGate q = QuantumRegister(1, 'q') - qc = QuantumCircuit(q, name=self.name) + qc = QuantumCircuit(q, name=self.name, global_phase=pi / 4) rules = [ - (RZGate(-pi / 2), [q[0]], []), + (SdgGate(), [q[0]], []), (HGate(), [q[0]], []), - (RZGate(-pi / 2), [q[0]], []) + (SdgGate(), [q[0]], []) ] qc.data = rules self.definition = qc @@ -98,13 +98,10 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): return gate return super().control(num_ctrl_qubits=num_ctrl_qubits, label=label, ctrl_state=ctrl_state) - # Differs by global phase of exp(-i pi/4) with correct RZ. - # If the RZ == U1, then the global phase difference is exp(i pi/4) - # TODO: Restore after allowing phase on circuits. - # def to_matrix(self): - # """Return a numpy.array for the SX gate.""" - # return numpy.array([[1 + 1j, 1 - 1j], - # [1 - 1j, 1 + 1j]], dtype=complex) / 2 + def to_matrix(self): + """Return a numpy.array for the SX gate.""" + return numpy.array([[1 + 1j, 1 - 1j], + [1 - 1j, 1 + 1j]], dtype=complex) / 2 class SXdgGate(Gate): @@ -143,25 +140,22 @@ def _define(self): """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit - from .rz import RZGate + from .s import SGate from .h import HGate q = QuantumRegister(1, 'q') - qc = QuantumCircuit(q, name=self.name) + qc = QuantumCircuit(q, name=self.name, global_phase=-pi / 4) rules = [ - (RZGate(pi / 2), [q[0]], []), + (SGate(), [q[0]], []), (HGate(), [q[0]], []), - (RZGate(pi / 2), [q[0]], []) + (SGate(), [q[0]], []) ] qc.data = rules self.definition = qc - # Differs by global phase of exp(-i pi/4) with correct RZ. - # If the RZ == U1, then the global phase difference is exp(i pi/4) - # TODO: Restore after allowing phase on circuits. - # def to_matrix(self): - # """Return a numpy.array for the SX gate.""" - # return numpy.array([[1 - 1j, 1 + 1j], - # [1 + 1j, 1 - 1j]], dtype=complex) / 2 + def to_matrix(self): + """Return a numpy.array for the SXdg gate.""" + return numpy.array([[1 - 1j, 1 + 1j], + [1 + 1j, 1 - 1j]], dtype=complex) / 2 class CSXGate(ControlledGate): diff --git a/test/python/circuit/test_controlled_gate.py b/test/python/circuit/test_controlled_gate.py index fa958e85ea4f..7c78171df882 100644 --- a/test/python/circuit/test_controlled_gate.py +++ b/test/python/circuit/test_controlled_gate.py @@ -970,8 +970,6 @@ def test_open_controlled_to_matrix(self, gate_class, ctrl_state): cgate = gate_class(*free_params) cgate.ctrl_state = ctrl_state base_mat = Operator(cgate.base_gate).data - if gate_class == CSXGate: - base_mat *= np.exp(0.25j * np.pi) # SX has a global phase, must be accounted for in CSX target = _compute_control_matrix(base_mat, cgate.num_ctrl_qubits, ctrl_state=ctrl_state) try: @@ -1093,9 +1091,6 @@ def test_controlled_standard_gates(self, num_ctrl_qubits, gate_class): iden = Operator.from_label('I') zgen = Operator.from_label('Z') base_mat = (np.cos(0.5 * theta) * iden - 1j * np.sin(0.5 * theta) * zgen).data - # account for global phase diff, CSX is exact - elif gate.name == 'sx' and num_ctrl_qubits == 1: - base_mat = Operator(gate).data * np.exp(0.25j * np.pi) else: base_mat = Operator(gate).data target_mat = _compute_control_matrix(base_mat, num_ctrl_qubits, diff --git a/test/python/circuit/test_gate_definitions.py b/test/python/circuit/test_gate_definitions.py index c3a017a66b80..912c1911583a 100644 --- a/test/python/circuit/test_gate_definitions.py +++ b/test/python/circuit/test_gate_definitions.py @@ -28,7 +28,7 @@ HGate, CHGate, IGate, RGate, RXGate, CRXGate, RYGate, CRYGate, RZGate, CRZGate, SGate, SdgGate, CSwapGate, TGate, TdgGate, U1Gate, CU1Gate, U2Gate, U3Gate, CU3Gate, XGate, CXGate, CCXGate, YGate, CYGate, - ZGate, CZGate, RYYGate, SXGate, SXdgGate + ZGate, CZGate, RYYGate, SXGate, SXdgGate, CSXGate ) from qiskit.circuit.library.standard_gates.equivalence_library import ( From 8d6c2000591c91c1e22e9faf5816a0e0330e1e18 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Sat, 25 Jul 2020 12:30:52 +0200 Subject: [PATCH 21/28] change to case where phase is not 1 --- test/python/circuit/test_extensions_standard.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/python/circuit/test_extensions_standard.py b/test/python/circuit/test_extensions_standard.py index 50d09b6df71e..7a7de13e1d29 100644 --- a/test/python/circuit/test_extensions_standard.py +++ b/test/python/circuit/test_extensions_standard.py @@ -1354,7 +1354,7 @@ def test_to_matrix(self): definition.""" from qiskit.circuit.library.standard_gates.ms import MSGate - params = [0.1 * i for i in range(10)] + params = [0.1 * (i + 1) for i in range(10)] gate_class_list = Gate.__subclasses__() + ControlledGate.__subclasses__() simulator = BasicAer.get_backend('unitary_simulator') for gate_class in gate_class_list: @@ -1385,8 +1385,10 @@ def test_to_matrix(self): gate.name) continue definition_unitary = execute([circ], simulator).result().get_unitary() - self.assertTrue(matrix_equal(definition_unitary, gate_matrix)) - self.assertTrue(is_unitary_matrix(gate_matrix)) + + with self.subTest(gate_class): + self.assertTrue(matrix_equal(definition_unitary, gate_matrix)) + self.assertTrue(is_unitary_matrix(gate_matrix)) def test_to_matrix_op(self): """test gates implementing to_matrix generate matrix which matches From 7cd4b7125ff247c18438e308bfa9b4ae0a2a3abf Mon Sep 17 00:00:00 2001 From: Cryoris Date: Sat, 25 Jul 2020 12:33:35 +0200 Subject: [PATCH 22/28] mention SXdg in the reno --- releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml b/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml index bc4b17580ccc..b831fc3e2933 100644 --- a/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml +++ b/releasenotes/notes/sqrt-x-gates-3aba219f0efd8900.yaml @@ -1,6 +1,7 @@ --- features: - | - Added the sqrt(X) and controlled-sqrt(X) gates as circuit methods. - They are available as ``QuantumCircuit.sx`` and ``QuantumCircuit.csx``, - with the respective gate classes ``SXGate`` and ``CSXGate``. + Added the sqrt(X), its adjoint and controlled-sqrt(X) gates as circuit methods. + They are available as ``QuantumCircuit.sx``, ``QuantumCircuit.sxdg`` + and ``QuantumCircuit.csx``, with the respective gate classes ``SXGate``, + ``SXdgGate`` and ``CSXGate``. From 575702f9c339bb141683db02dd361027aafe0764 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 28 Jul 2020 17:22:32 +0200 Subject: [PATCH 23/28] ignore global phase for now --- test/python/circuit/test_extensions_standard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/python/circuit/test_extensions_standard.py b/test/python/circuit/test_extensions_standard.py index 7a7de13e1d29..c4e1c720d16a 100644 --- a/test/python/circuit/test_extensions_standard.py +++ b/test/python/circuit/test_extensions_standard.py @@ -1387,7 +1387,8 @@ def test_to_matrix(self): definition_unitary = execute([circ], simulator).result().get_unitary() with self.subTest(gate_class): - self.assertTrue(matrix_equal(definition_unitary, gate_matrix)) + # TODO check for exact equality once BasicAer can handle global phase + self.assertTrue(matrix_equal(definition_unitary, gate_matrix, ignore_phase=True)) self.assertTrue(is_unitary_matrix(gate_matrix)) def test_to_matrix_op(self): From f4cd163ad245ee28f413db30b0e171066d3707d9 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 28 Jul 2020 21:22:13 +0200 Subject: [PATCH 24/28] update text and mpl drawer --- qiskit/circuit/library/standard_gates/s.py | 2 +- qiskit/circuit/library/standard_gates/t.py | 2 +- qiskit/visualization/qcstyle.py | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/s.py b/qiskit/circuit/library/standard_gates/s.py index c022bd90dd84..32b16ef7a912 100644 --- a/qiskit/circuit/library/standard_gates/s.py +++ b/qiskit/circuit/library/standard_gates/s.py @@ -103,7 +103,7 @@ class SdgGate(Gate): Equivalent to a :math:`\pi/2` radian rotation about the Z axis. """ - def __init__(self, label=None): + def __init__(self, label='S^†'): """Create new Sdg gate.""" super().__init__('sdg', 1, [], label=label) diff --git a/qiskit/circuit/library/standard_gates/t.py b/qiskit/circuit/library/standard_gates/t.py index 9dfa263bb982..837fbefb7e9b 100644 --- a/qiskit/circuit/library/standard_gates/t.py +++ b/qiskit/circuit/library/standard_gates/t.py @@ -104,7 +104,7 @@ class TdgGate(Gate): Equivalent to a :math:`\pi/2` radian rotation about the Z axis. """ - def __init__(self, label=None): + def __init__(self, label='T^†'): """Create new Tdg gate.""" super().__init__('tdg', 1, [], label=label) diff --git a/qiskit/visualization/qcstyle.py b/qiskit/visualization/qcstyle.py index f3b993dad2a5..d70add371c92 100644 --- a/qiskit/visualization/qcstyle.py +++ b/qiskit/visualization/qcstyle.py @@ -57,6 +57,8 @@ def __init__(self): 'h': 'H', 's': 'S', 'sdg': 'S^\\dagger', + 'sx': '\\sqrt{X}', + 'sxdg': '\\sqrt{X}^\\dagger', 't': 'T', 'tdg': 'T^\\dagger', 'iswap': 'Iswap', From 58e897a4fdd5bf26c50fbca2119fb34c57d9fdd7 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Tue, 28 Jul 2020 21:27:41 +0200 Subject: [PATCH 25/28] add sx and sxdg to standard gates in matplotlib.py --- qiskit/visualization/matplotlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/visualization/matplotlib.py b/qiskit/visualization/matplotlib.py index b5907d212a22..ebb1f76c26e3 100644 --- a/qiskit/visualization/matplotlib.py +++ b/qiskit/visualization/matplotlib.py @@ -702,7 +702,7 @@ def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False): def _draw_ops(self, verbose=False): _standard_gates = ['x', 'y', 'z', 'id', 'h', 'r', 's', 'sdg', 't', 'tdg', 'rx', 'ry', 'rz', - 'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'swap', 'reset'] + 'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'swap', 'reset', 'sx', 'sxdg'] _barrier_gates = ['barrier', 'snapshot', 'load', 'save', 'noise'] _barriers = {'coord': [], 'group': []} From 03d094540f2270a7d0caae7714c19abb750dcc77 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 29 Jul 2020 09:10:55 +0200 Subject: [PATCH 26/28] dagger is unsupported ascii char --- qiskit/circuit/library/standard_gates/s.py | 2 +- qiskit/circuit/library/standard_gates/sx.py | 2 +- qiskit/circuit/library/standard_gates/t.py | 2 +- .../references/circuit_text_ref.txt | 26 +++++++++---------- .../test_circuit_visualization_output.py | 6 +++-- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/qiskit/circuit/library/standard_gates/s.py b/qiskit/circuit/library/standard_gates/s.py index 32b16ef7a912..8c85fe472741 100644 --- a/qiskit/circuit/library/standard_gates/s.py +++ b/qiskit/circuit/library/standard_gates/s.py @@ -103,7 +103,7 @@ class SdgGate(Gate): Equivalent to a :math:`\pi/2` radian rotation about the Z axis. """ - def __init__(self, label='S^†'): + def __init__(self, label='S_dg'): """Create new Sdg gate.""" super().__init__('sdg', 1, [], label=label) diff --git a/qiskit/circuit/library/standard_gates/sx.py b/qiskit/circuit/library/standard_gates/sx.py index 18288dfa1366..b0c8630ceed5 100644 --- a/qiskit/circuit/library/standard_gates/sx.py +++ b/qiskit/circuit/library/standard_gates/sx.py @@ -130,7 +130,7 @@ class SXdgGate(Gate): """ - def __init__(self, label='√X^†'): + def __init__(self, label='√X_dg'): """Create new SXdg gate.""" super().__init__('sxdg', 1, [], label=label) diff --git a/qiskit/circuit/library/standard_gates/t.py b/qiskit/circuit/library/standard_gates/t.py index 837fbefb7e9b..cbbd733c188b 100644 --- a/qiskit/circuit/library/standard_gates/t.py +++ b/qiskit/circuit/library/standard_gates/t.py @@ -104,7 +104,7 @@ class TdgGate(Gate): Equivalent to a :math:`\pi/2` radian rotation about the Z axis. """ - def __init__(self, label='T^†'): + def __init__(self, label='T_dg'): """Create new Tdg gate.""" super().__init__('tdg', 1, [], label=label) diff --git a/test/python/visualization/references/circuit_text_ref.txt b/test/python/visualization/references/circuit_text_ref.txt index cc0c1036cd9a..209138526c6a 100644 --- a/test/python/visualization/references/circuit_text_ref.txt +++ b/test/python/visualization/references/circuit_text_ref.txt @@ -1,13 +1,13 @@ - ┌───┐┌───┐┌───┐ ░ ┌───┐┌───┐┌─────┐┌───┐┌─────┐┌───┐ ┌────────┐┌────────┐┌────────┐┌────────┐┌───────────┐┌──────────────┐ ┌─┐ -q_0: |0>┤ X ├┤ Y ├┤ Z ├─░─┤ H ├┤ S ├┤ SDG ├┤ T ├┤ TDG ├┤ I ├─|0>─┤ RX(pi) ├┤ RY(pi) ├┤ RZ(pi) ├┤ U1(pi) ├┤ U2(pi,pi) ├┤ U3(pi,pi,pi) ├─X───■────■───■───■───■──────────■────────────■─────────■─────────■───────■───■─┤M├────── - └─░─┘└───┘└───┘ ░ └───┘└───┘└─────┘└───┘└─────┘└───┘ └────────┘└────────┘└────────┘└────────┘└───────────┘└──────────────┘ │ ┌─┴─┐┌─┴─┐ │ ┌─┴─┐ │pi ┌──────┴───────┐┌───┴────┐┌───┴────┐┌───┴────┐ │ │ └╥┘┌─┐ -q_1: |0>──░────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────X─┤ X ├┤ Y ├─■─┤ H ├─■───┤ U3(pi,pi,pi) ├┤ RZ(pi) ├┤ RY(pi) ├┤ RX(pi) ├──■───X──╫─┤M├─── - ░ └───┘└───┘ └───┘ └──────────────┘└────────┘└────────┘└────────┘┌─┴─┐ │ ║ └╥┘┌─┐ -q_2: |0>──░───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ X ├─X──╫──╫─┤M├ - ░ └───┘ ║ ║ └╥┘ - c_0: 0 ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩══╬══╬═ - ║ ║ - c_1: 0 ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩══╬═ - ║ - c_2: 0 ═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩═ - \ No newline at end of file + ┌───┐┌───┐┌───┐ ░ ┌───┐┌───┐┌──────┐┌───┐┌──────┐┌────┐┌───────┐┌───┐ ┌────────┐┌────────┐┌────────┐┌────────┐┌───────────┐┌──────────────┐ ┌─┐ +q_0: |0>┤ X ├┤ Y ├┤ Z ├─░─┤ H ├┤ S ├┤ S_dg ├┤ T ├┤ T_dg ├┤ √X ├┤ √X_dg ├┤ I ├─|0>─┤ RX(pi) ├┤ RY(pi) ├┤ RZ(pi) ├┤ U1(pi) ├┤ U2(pi,pi) ├┤ U3(pi,pi,pi) ├─X───■────■───■───■───■──────────■────────────■─────────■─────────■───────■───■─┤M├────── + └─░─┘└───┘└───┘ ░ └───┘└───┘└──────┘└───┘└──────┘└────┘└───────┘└───┘ └────────┘└────────┘└────────┘└────────┘└───────────┘└──────────────┘ │ ┌─┴─┐┌─┴─┐ │ ┌─┴─┐ │pi ┌──────┴───────┐┌───┴────┐┌───┴────┐┌───┴────┐ │ │ └╥┘┌─┐ +q_1: |0>──░─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────X─┤ X ├┤ Y ├─■─┤ H ├─■───┤ U3(pi,pi,pi) ├┤ RZ(pi) ├┤ RY(pi) ├┤ RX(pi) ├──■───X──╫─┤M├─── + ░ └───┘└───┘ └───┘ └──────────────┘└────────┘└────────┘└────────┘┌─┴─┐ │ ║ └╥┘┌─┐ +q_2: |0>──░────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ X ├─X──╫──╫─┤M├ + ░ └───┘ ║ ║ └╥┘ + c_0: 0 ════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩══╬══╬═ + ║ ║ + c_1: 0 ═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩══╬═ + ║ + c_2: 0 ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╩═ + \ No newline at end of file diff --git a/test/python/visualization/test_circuit_visualization_output.py b/test/python/visualization/test_circuit_visualization_output.py index 6e4938fa5288..ac6e9446d60c 100644 --- a/test/python/visualization/test_circuit_visualization_output.py +++ b/test/python/visualization/test_circuit_visualization_output.py @@ -52,6 +52,8 @@ def sample_circuit(self): circuit.sdg(qr[0]) circuit.t(qr[0]) circuit.tdg(qr[0]) + circuit.sx(qr[0]) + circuit.sxdg(qr[0]) circuit.i(qr[0]) circuit.reset(qr[0]) circuit.rx(pi, qr[0]) @@ -102,12 +104,12 @@ def test_text_drawer(self): qc = self.sample_circuit() output = circuit_drawer(qc, filename=filename, output="text", fold=-1, initial_state=True, cregbundle=False) - self.assertFilesAreEqual(filename, self.text_reference) - os.remove(filename) try: encode(str(output), encoding='cp437') except UnicodeEncodeError: self.fail("_text_circuit_drawer() should only use extended ascii (aka code page 437).") + self.assertFilesAreEqual(filename, self.text_reference) + os.remove(filename) if __name__ == '__main__': From 54836c00b5c3fb2cc7e4958deb64d7121ce08939 Mon Sep 17 00:00:00 2001 From: Cryoris Date: Wed, 29 Jul 2020 14:18:08 +0200 Subject: [PATCH 27/28] use mathmode in qcstyle --- qiskit/visualization/qcstyle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiskit/visualization/qcstyle.py b/qiskit/visualization/qcstyle.py index a4f1243da2af..bf68ec8d4ac2 100644 --- a/qiskit/visualization/qcstyle.py +++ b/qiskit/visualization/qcstyle.py @@ -57,8 +57,8 @@ def __init__(self): 'h': 'H', 's': 'S', 'sdg': '$\\mathrm{S}^\\dagger$', - 'sx': '\\sqrt{X}', - 'sxdg': '\\sqrt{X}^\\dagger', + 'sx': '$\\sqrt{X}$', + 'sxdg': '$\\sqrt{X}^\\dagger$', 't': 'T', 'tdg': '$\\mathrm{T}^\\dagger$', 'iswap': 'Iswap', From ad7b92a9049aac68fb494ed88f688fc3f494433e Mon Sep 17 00:00:00 2001 From: Cryoris Date: Fri, 31 Jul 2020 12:14:48 +0200 Subject: [PATCH 28/28] add u2 to u1/sx equivalence --- .../library/standard_gates/equivalence_library.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py index 639c9b8a50ab..a8ec44a475a7 100644 --- a/qiskit/circuit/library/standard_gates/equivalence_library.py +++ b/qiskit/circuit/library/standard_gates/equivalence_library.py @@ -427,7 +427,7 @@ def_cu1.append(inst, qargs, cargs) _sel.add_equivalence(CU1Gate(theta), def_cu1) -# U2Gate +# U1Gate q = QuantumRegister(1, 'q') theta = Parameter('theta') @@ -435,6 +435,17 @@ def_u1.append(U3Gate(0, 0, theta), [q[0]], []) _sel.add_equivalence(U1Gate(theta), def_u1) +# U2Gate + +q = QuantumRegister(1, 'q') +phi = Parameter('phi') +lam = Parameter('lam') +u2_to_u1sx = QuantumCircuit(q, global_phase=-pi / 4) +u2_to_u1sx.u1(lam - pi/2, 0) +u2_to_u1sx.sx(0) +u2_to_u1sx.u1(phi + pi/2, 0) +_sel.add_equivalence(U2Gate(phi, lam), u2_to_u1sx) + # U3Gate q = QuantumRegister(1, 'q')