Skip to content
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

Implement the relative phase Toffoli gates #3761

Merged
merged 21 commits into from
Feb 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions qiskit/extensions/standard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from .iden import IdGate
from .ms import MSGate
from .r import RGate
from .rccx import RCCXGate
from .rcccx import RCCCXGate
from .rx import RXGate, CrxGate
from .rxx import RXXGate
from .ry import RYGate, CryGate
Expand Down
2 changes: 0 additions & 2 deletions qiskit/extensions/standard/multi_control_toffoli_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit

from qiskit import QiskitError
# pylint: disable=unused-import
from .relative_phase_toffoli import rccx

logger = logging.getLogger(__name__)

Expand Down
117 changes: 117 additions & 0 deletions qiskit/extensions/standard/rcccx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-

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

"""The simplified 3-controlled Toffoli gate."""

import numpy

from qiskit.circuit import QuantumCircuit, Gate, QuantumRegister
from qiskit.extensions.standard.u1 import U1Gate
from qiskit.extensions.standard.u2 import U2Gate
from qiskit.extensions.standard.x import CnotGate
from qiskit.qasm import pi


class RCCCXGate(Gate):
"""The simplified 3-controlled Toffoli gate.

The simplified Toffoli gate implements the Toffoli gate up to relative phases.
Note, that the simplified Toffoli is not equivalent to the Toffoli. But can be used in places
where the Toffoli gate is uncomputed again.

This concrete implementation is from https://arxiv.org/abs/1508.03273, the complete circuit
of Fig. 4.
"""

def __init__(self):
"""Create a new RCCCX gate."""
super().__init__('rcccx', 4, [])

def _define(self):
"""
gate rcccx a,b,c,d
{ u2(0,pi) d;
u1(pi/4) d;
cx c,d;
u1(-pi/4) d;
u2(0,pi) d;
cx a,d;
u1(pi/4) d;
cx b,d;
u1(-pi/4) d;
cx a,d;
u1(pi/4) d;
cx b,d;
u1(-pi/4) d;
u2(0,pi) d;
u1(pi/4) d;
cx c,d;
u1(-pi/4) d;
u2(0,pi) d;
}
"""
definition = []
q = QuantumRegister(4, 'q')

rule = [
(U2Gate(0, pi), [q[3]], []), # H gate
(U1Gate(pi / 4), [q[3]], []), # T gate
(CnotGate(), [q[2], q[3]], []),
(U1Gate(-pi / 4), [q[3]], []), # inverse T gate
(U2Gate(0, pi), [q[3]], []),
(CnotGate(), [q[0], q[3]], []),
(U1Gate(pi / 4), [q[3]], []),
(CnotGate(), [q[1], q[3]], []),
(U1Gate(-pi / 4), [q[3]], []),
(CnotGate(), [q[0], q[3]], []),
(U1Gate(pi / 4), [q[3]], []),
(CnotGate(), [q[1], q[3]], []),
(U1Gate(-pi / 4), [q[3]], []),
(U2Gate(0, pi), [q[3]], []),
(U1Gate(pi / 4), [q[3]], []),
(CnotGate(), [q[2], q[3]], []),
(U1Gate(-pi / 4), [q[3]], []),
(U2Gate(0, pi), [q[3]], []),
]
for inst in rule:
definition.append(inst)
self.definition = definition

def to_matrix(self):
"""Return a numpy.array for the RCCCX gate."""
return numpy.array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1j, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1j, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=complex)


def rcccx(self, control_qubit1, control_qubit2, control_qubit3, target_qubit):
"""Apply the simplified, relative-phase 3-control Toffoli gate."""
return self.append(RCCCXGate(), [control_qubit1, control_qubit2, control_qubit3, target_qubit],
[])


QuantumCircuit.rcccx = rcccx
91 changes: 91 additions & 0 deletions qiskit/extensions/standard/rccx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-

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

"""The simplified Toffoli gate."""

import numpy

from qiskit.circuit import QuantumCircuit, Gate, QuantumRegister
from qiskit.extensions.standard.u1 import U1Gate
from qiskit.extensions.standard.u2 import U2Gate
from qiskit.extensions.standard.x import CnotGate
from qiskit.qasm import pi


class RCCXGate(Gate):
"""The simplified Toffoli gate, also referred to as Margolus gate.

The simplified Toffoli gate implements the Toffoli gate up to relative phases.
This implementation requires three CX gates which is the minimal amount possible,
as shown in https://arxiv.org/abs/quant-ph/0312225.
Note, that the simplified Toffoli is not equivalent to the Toffoli. But can be used in places
where the Toffoli gate is uncomputed again.

This concrete implementation is from https://arxiv.org/abs/1508.03273, the dashed box
of Fig. 3.
"""

def __init__(self):
"""Create a new simplified CCX gate."""
super().__init__('rccx', 3, [])

def _define(self):
"""
gate rccx a,b,c
{ u2(0,pi) c;
u1(pi/4) c;
cx b, c;
u1(-pi/4) c;
cx a, c;
u1(pi/4) c;
cx b, c;
u1(-pi/4) c;
u2(0,pi) c;
}
"""
definition = []
q = QuantumRegister(3, 'q')
rule = [
(U2Gate(0, pi), [q[2]], []), # H gate
(U1Gate(pi / 4), [q[2]], []), # T gate
(CnotGate(), [q[1], q[2]], []),
(U1Gate(-pi / 4), [q[2]], []), # inverse T gate
(CnotGate(), [q[0], q[2]], []),
(U1Gate(pi / 4), [q[2]], []),
(CnotGate(), [q[1], q[2]], []),
(U1Gate(-pi / 4), [q[2]], []), # inverse T gate
(U2Gate(0, pi), [q[2]], []), # H gate
]
for inst in rule:
definition.append(inst)
self.definition = definition

def to_matrix(self):
"""Return a numpy.array for the simplified CCX gate."""
return numpy.array([[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, -1j],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, -1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 1j, 0, 0, 0, 0]], dtype=complex)


def rccx(self, control_qubit1, control_qubit2, target_qubit):
"""Apply the simplified, relative-phase Toffoli gate."""
return self.append(RCCXGate(), [control_qubit1, control_qubit2, target_qubit], [])


QuantumCircuit.rccx = rccx
133 changes: 0 additions & 133 deletions qiskit/extensions/standard/relative_phase_toffoli.py

This file was deleted.

Loading