-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Sqrt(X) and C-Sqrt(X) gates #4638
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
Changes from 18 commits
214d880
f958aae
e32cc98
8826707
7a60a5e
8dd8b78
2fd9221
e3f600a
ea0a329
6d62d0e
25452ce
be6221b
22b84e1
df9269c
c575589
fe5c2d5
7b3876a
6cb5812
621d781
010e50c
30c5074
faa28a9
caa95c8
5481928
8d6c200
7cd4b71
b5e291d
d4279e9
575702f
5483125
f4cd163
58e897a
117f16d
03d0945
36067ad
872123b
54836c0
3359e4e
ad7b92a
8fce279
ec40da9
f50d47e
76329f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,258 @@ | ||||||
| # -*- 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 \\ | ||||||
| 1 - 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='√X'): | ||||||
| """Create new SX gate.""" | ||||||
| super().__init__('sx', 1, [], label=label) | ||||||
|
|
||||||
| 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 | ||||||
| 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 | ||||||
|
|
||||||
| def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): | ||||||
| """Return a (multi-)controlled-SX gate. | ||||||
|
|
||||||
| One control returns a CSX 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) | ||||||
|
|
||||||
| # 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 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'): | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be similar to how sdg and tdg are rendered.
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also I noticed this will draw as two columns in the mpl drawer, but you can fix that by adding it to the list of standard gates on line 704 of visualization/matplotlib.py
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also it would be good to have some consistency between this and other "daggered" gates in the text drawer. Also since text-drawer doesn't have math mode the exponent doesn't show well. What's the best way to fix this? I'm being nit-picky on these because they will end up being shown very prominently when we translate to these basis.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about the text drawer, maybe it is really
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Turns out that the dagger sign causes a test to fail, which says that only Code page 437 symbols are allowed. @1ucian0 is that because other symbols might not get rendered on different machines or what's the reason for this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at the available symbols from this page I switched back to
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @1ucian0 why can't we support symbols outside of that list? |
||||||
| """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. | ||||||
|
|
||||||
| **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 { 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 | ||||||
| q = QuantumRegister(2, 'q') | ||||||
| qc = QuantumCircuit(q, name=self.name) | ||||||
| rules = [ | ||||||
| (HGate(), [q[1]], []), | ||||||
| (CU1Gate(pi/2), [q[0], q[1]], []), | ||||||
| (HGate(), [q[1]], []) | ||||||
| ] | ||||||
| qc.data = rules | ||||||
| self.definition = qc | ||||||
|
|
||||||
| def to_matrix(self): | ||||||
| """Return a numpy.array for the CSX gate.""" | ||||||
| if self.ctrl_state: | ||||||
| return self._matrix1 | ||||||
| else: | ||||||
| return self._matrix0 | ||||||

Uh oh!
There was an error while loading. Please reload this page.