Skip to content

Commit

Permalink
add rxx gate (Qiskit#3113)
Browse files Browse the repository at this point in the history
Co-authored-by: ma5x <[email protected]>
Co-authored-by: strickroman <[email protected]>
  • Loading branch information
3 people authored and ajavadia committed Sep 19, 2019
1 parent 1cf95cc commit 5195991
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 2 deletions.
1 change: 1 addition & 0 deletions qiskit/extensions/standard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@
from .crz import CrzGate
from .cu3 import Cu3Gate
from .rzz import RZZGate
from .rxx import RXXGate
9 changes: 9 additions & 0 deletions qiskit/extensions/standard/rx.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"""
Rotation around the x-axis.
"""
import math
import numpy
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
Expand Down Expand Up @@ -51,6 +53,13 @@ def inverse(self):
"""
return RXGate(-self.params[0])

def to_matrix(self):
"""Return a Numpy.array for the RX gate."""
cos = math.cos(self.params[0] / 2)
sin = math.sin(self.params[0] / 2)
return numpy.array([[cos, -1j * sin],
[-1j * sin, cos]], dtype=complex)


def rx(self, theta, q):
"""Apply Rx to q."""
Expand Down
80 changes: 80 additions & 0 deletions qiskit/extensions/standard/rxx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2019.
#
# 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.

"""
Two-qubit XX-rotation gate.
"""
import numpy as np
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.extensions.standard.cx import CnotGate
from qiskit.extensions.standard.u1 import U1Gate
from qiskit.extensions.standard.u2 import U2Gate
from qiskit.extensions.standard.u3 import U3Gate
from qiskit.extensions.standard.h import HGate


class RXXGate(Gate):
"""Two-qubit XX-rotation gate.
This gate corresponds to the rotation U(θ) = exp(-1j * θ * X⊗X / 2)
"""

def __init__(self, theta):
"""Create new rxx gate."""
super().__init__("rxx", 2, [theta])

def _define(self):
"""Calculate a subcircuit that implements this unitary."""
definition = []
q = QuantumRegister(2, "q")
theta = self.params[0]
rule = [
(U3Gate(np.pi / 2, theta, 0), [q[0]], []),
(HGate(), [q[1]], []),
(CnotGate(), [q[0], q[1]], []),
(U1Gate(-theta), [q[1]], []),
(CnotGate(), [q[0], q[1]], []),
(HGate(), [q[1]], []),
(U2Gate(-np.pi, np.pi - theta), [q[0]], []),
]
for inst in rule:
definition.append(inst)
self.definition = definition

def inverse(self):
"""Invert this gate."""
return RXXGate(-self.params[0])

# NOTE: we should use the following as the canonical matrix
# definition but we don't include it yet since it differs from
# the circuit decomposition matrix by a global phase
# def to_matrix(self):
# """Return a Numpy.array for the RXX gate."""
# theta = float(self.params[0])
# return np.array([
# [np.cos(theta / 2), 0, 0, -1j * np.sin(theta / 2)],
# [0, np.cos(theta / 2), -1j * np.sin(theta / 2), 0],
# [0, -1j * np.sin(theta / 2), np.cos(theta / 2), 0],
# [-1j * np.sin(theta / 2), 0, 0, np.cos(theta / 2)]], dtype=complex)


def rxx(self, theta, qubit1, qubit2):
"""Apply RXX to circuit."""
return self.append(RXXGate(theta), [qubit1, qubit2], [])


# Add to QuantumCircuit class
QuantumCircuit.rxx = rxx
9 changes: 9 additions & 0 deletions qiskit/extensions/standard/ry.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"""
Rotation around the y-axis.
"""
import math
import numpy
from qiskit.circuit import Gate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
Expand Down Expand Up @@ -50,6 +52,13 @@ def inverse(self):
"""
return RYGate(-self.params[0])

def to_matrix(self):
"""Return a Numpy.array for the RY gate."""
cos = math.cos(self.params[0] / 2)
sin = math.sin(self.params[0] / 2)
return numpy.array([[cos, -sin],
[sin, cos]], dtype=complex)


def ry(self, theta, q):
"""Apply Ry to q."""
Expand Down
59 changes: 59 additions & 0 deletions qiskit/quantum_info/synthesis/ion_decompose.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2019.
#
# 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.

# pylint: disable=invalid-name

"""
Decomposition methods for trapped-ion basis gates RXXGate, RXGate, RYGate.
"""

import numpy as np

from qiskit.circuit.quantumcircuit import QuantumCircuit
from qiskit.extensions.standard.ry import RYGate
from qiskit.extensions.standard.rx import RXGate
from qiskit.extensions.standard.rxx import RXXGate


def cnot_rxx_decompose(plus_ry=True, plus_rxx=True):
"""Decomposition of CNOT gate.
NOTE: this differs to CNOT by a global phase.
The matrix returned is given by exp(1j * pi/4) * CNOT
Args:
plus_ry (bool): positive initial RY rotation
plus_rxx (bool): positive RXX rotation.
Returns:
QuantumCircuit: The decomposed circuit for CNOT gate (up to
global phase).
"""
# Convert boolean args to +/- 1 signs
if plus_ry:
sgn_ry = 1
else:
sgn_ry = -1
if plus_rxx:
sgn_rxx = 1
else:
sgn_rxx = -1

circuit = QuantumCircuit(2)
circuit.append(RYGate(sgn_ry * np.pi / 2), [0])
circuit.append(RXXGate(sgn_rxx * np.pi / 2), [0, 1])
circuit.append(RXGate(-sgn_rxx * np.pi / 2), [0])
circuit.append(RXGate(-sgn_rxx * sgn_ry * np.pi / 2), [1])
circuit.append(RYGate(-sgn_ry * np.pi / 2), [0])
return circuit
16 changes: 14 additions & 2 deletions test/python/quantum_info/test_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
from qiskit import execute
from qiskit.circuit import QuantumCircuit, QuantumRegister
from qiskit.extensions import UnitaryGate
from qiskit.providers.basicaer import UnitarySimulatorPy
from qiskit.extensions.standard import (HGate, IdGate, SdgGate, SGate, U3Gate,
XGate, YGate, ZGate)
XGate, YGate, ZGate, CnotGate)
from qiskit.providers.basicaer import UnitarySimulatorPy
from qiskit.quantum_info.operators import Operator, Pauli
from qiskit.quantum_info.random import random_unitary
from qiskit.quantum_info.synthesis.one_qubit_decompose import OneQubitEulerDecomposer
Expand All @@ -32,6 +32,7 @@
TwoQubitBasisDecomposer,
Ud,
euler_angles_1q)
from qiskit.quantum_info.synthesis.ion_decompose import cnot_rxx_decompose
from qiskit.test import QiskitTestCase


Expand Down Expand Up @@ -377,6 +378,17 @@ def check_exact_decomposition(self, target_unitary, decomposer, tolerance=1.e-7)
maxdist = np.min(maxdists)
self.assertTrue(np.abs(maxdist) < tolerance, "Worst distance {}".format(maxdist))

def test_cnot_rxx_decompose(self):
"""Verify CNOT decomposition into RXX gate is correct"""
cnot = Operator(CnotGate())
decomps = [cnot_rxx_decompose(),
cnot_rxx_decompose(plus_ry=True, plus_rxx=True),
cnot_rxx_decompose(plus_ry=True, plus_rxx=False),
cnot_rxx_decompose(plus_ry=False, plus_rxx=True),
cnot_rxx_decompose(plus_ry=False, plus_rxx=False)]
for decomp in decomps:
self.assertTrue(cnot.equiv(decomp))

def test_exact_two_qubit_cnot_decompose_random(self, nsamples=10):
"""Verify exact CNOT decomposition for random Haar 4x4 unitaries.
"""
Expand Down

0 comments on commit 5195991

Please sign in to comment.