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

override control of standard gates where possible #3631

Merged
merged 27 commits into from
Jan 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c69356e
move controlled gate class definitions into base gate module.
ewinston Dec 18, 2019
34eec02
fix cyclic imports
ewinston Dec 19, 2019
27bb3a4
Merge branch 'master' into gateconsolidate
ewinston Dec 19, 2019
93e6570
update for new crx and cry
ewinston Dec 19, 2019
bb525e5
linting
ewinston Dec 19, 2019
0f16d69
linting
ewinston Dec 19, 2019
832b10f
Merge branch 'master' into gateconsolidate
ewinston Dec 20, 2019
082e012
Merge branch 'master' into gateconsolidate
ewinston Jan 7, 2020
52bbd25
Merge branch 'master' into gateconsolidate
ewinston Jan 13, 2020
9cff62a
linting
ewinston Jan 14, 2020
32e99e7
minor
ewinston Jan 14, 2020
f090bae
wrong import of U3Gate
ewinston Jan 14, 2020
0369b1b
Merge branch 'master' into gateconsolidate
ewinston Jan 14, 2020
6c5e91d
module level pylint cyclic-import disable
ewinston Jan 15, 2020
1f122dc
Merge branch 'gateconsolidate_cyclic' into gateconsolidate
ewinston Jan 15, 2020
170a332
update mapper ground truth
ewinston Jan 15, 2020
9e9ba78
hack to get tox to work
ewinston Jan 15, 2020
79f575e
solve bug associated with ToffoliGate import.
ewinston Jan 17, 2020
b02a0e5
avoid multiple definitions
ewinston Jan 17, 2020
4884d07
Merge branch 'master' into gateconsolidate
ewinston Jan 17, 2020
3ef227a
Merge branch 'master' into gateconsolidate
ewinston Jan 21, 2020
be5e03a
update warning category.
ewinston Jan 27, 2020
907ec76
Merge branch 'master' into gateconsolidate
mergify[bot] Jan 27, 2020
da6311f
change stack level
ewinston Jan 27, 2020
b116ea5
Merge branch 'gateconsolidate' of github.com:ewinston/qiskit-terra in…
ewinston Jan 27, 2020
82388a6
Merge branch 'master' into gateconsolidate
ewinston Jan 28, 2020
c1b4cb3
Merge branch 'master' into gateconsolidate
mergify[bot] Jan 30, 2020
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
73 changes: 8 additions & 65 deletions qiskit/circuit/add_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,77 +31,20 @@ def add_control(operation, num_ctrl_qubits, label):
uses num_ctrl_qubits-1 ancillae qubits so returns a gate of size
num_qubits + 2*num_ctrl_qubits - 1.
"""
import qiskit.extensions.standard as standard
if isinstance(operation, standard.RZGate) or operation.name == 'rz':
# num_ctrl_qubits > 1
# the condition matching 'name' above is to catch a test case,
# 'TestControlledGate.test_rotation_gates', where the rz gate
# gets converted to a circuit before becoming a generic Gate object.
cgate = standard.CrzGate(*operation.params)
return cgate.control(num_ctrl_qubits - 1)
if isinstance(operation, UnitaryGate):
# attempt decomposition
operation._define()
if _control_definition_known(operation, num_ctrl_qubits):
return _control_predefined(operation, num_ctrl_qubits)
return control(operation, num_ctrl_qubits=num_ctrl_qubits, label=label)


def _control_definition_known(operation, num_ctrl_qubits):
if num_ctrl_qubits == 2 and operation.name == 'x':
return True
elif num_ctrl_qubits == 1:
return operation.name in {'x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 'swap', 'u1', 'u3', 'cx'}
elif operation.name == 'rz' and num_ctrl_qubits > 1:
return True
else:
return False


def _control_predefined(operation, num_ctrl_qubits):
"""Returns controlled gates with hard-coded definitions in
the standard extensions."""
if operation.name == 'x' and num_ctrl_qubits in [1, 2]:
if num_ctrl_qubits == 1:
import qiskit.extensions.standard.cx
cgate = qiskit.extensions.standard.cx.CnotGate()
else:
import qiskit.extensions.standard.ccx
cgate = qiskit.extensions.standard.ccx.ToffoliGate()
elif operation.name == 'y':
import qiskit.extensions.standard.cy
cgate = qiskit.extensions.standard.cy.CyGate()
elif operation.name == 'z':
import qiskit.extensions.standard.cz
cgate = qiskit.extensions.standard.cz.CzGate()
elif operation.name == 'h':
import qiskit.extensions.standard.ch
cgate = qiskit.extensions.standard.ch.CHGate()
elif operation.name in {'rx', 'ry', 'rz'}:
if operation.name == 'rx':
import qiskit.extensions.standard.crx
cgate = qiskit.extensions.standard.crx.CrxGate(*operation.params)
elif operation.name == 'ry':
import qiskit.extensions.standard.cry
cgate = qiskit.extensions.standard.cry.CryGate(*operation.params)
else: # operation.name == 'rz'
import qiskit.extensions.standard.crz
cgate = qiskit.extensions.standard.crz.CrzGate(*operation.params)
if num_ctrl_qubits == 1:
return cgate
else:
# only predefined for one control qubit
return cgate.control(num_ctrl_qubits - 1)
elif operation.name == 'swap':
import qiskit.extensions.standard.cswap
cgate = qiskit.extensions.standard.cswap.FredkinGate()
elif operation.name == 'u1':
import qiskit.extensions.standard.cu1
cgate = qiskit.extensions.standard.cu1.Cu1Gate(*operation.params)
elif operation.name == 'u3':
import qiskit.extensions.standard.cu3
cgate = qiskit.extensions.standard.cu3.Cu3Gate(*operation.params)
elif operation.name == 'cx':
import qiskit.extensions.standard.ccx
cgate = qiskit.extensions.standard.ccx.ToffoliGate()
else:
raise QiskitError('No standard controlled gate for "{}"'.format(
operation.name))
return cgate


def control(operation, num_ctrl_qubits=1, label=None):
"""Return controlled version of gate using controlled rotations

Expand Down
22 changes: 11 additions & 11 deletions qiskit/converters/ast_to_dag.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
from qiskit.circuit.measure import Measure
from qiskit.circuit.reset import Reset
from qiskit.extensions.standard.barrier import Barrier
from qiskit.extensions.standard.ccx import ToffoliGate
from qiskit.extensions.standard.cswap import FredkinGate
from qiskit.extensions.standard.cx import CnotGate
from qiskit.extensions.standard.cy import CyGate
from qiskit.extensions.standard.cz import CzGate
from qiskit.extensions.standard.x import ToffoliGate
from qiskit.extensions.standard.swap import FredkinGate
from qiskit.extensions.standard.x import CnotGate
from qiskit.extensions.standard.y import CyGate
from qiskit.extensions.standard.z import CzGate
from qiskit.extensions.standard.swap import SwapGate
from qiskit.extensions.standard.h import HGate
from qiskit.extensions.standard.iden import IdGate
Expand All @@ -46,12 +46,12 @@
from qiskit.extensions.standard.rx import RXGate
from qiskit.extensions.standard.ry import RYGate
from qiskit.extensions.standard.rz import RZGate
from qiskit.extensions.standard.cu1 import Cu1Gate
from qiskit.extensions.standard.ch import CHGate
from qiskit.extensions.standard.crx import CrxGate
from qiskit.extensions.standard.cry import CryGate
from qiskit.extensions.standard.crz import CrzGate
from qiskit.extensions.standard.cu3 import Cu3Gate
from qiskit.extensions.standard.u1 import Cu1Gate
from qiskit.extensions.standard.h import CHGate
from qiskit.extensions.standard.rx import CrxGate
from qiskit.extensions.standard.ry import CryGate
from qiskit.extensions.standard.rz import CrzGate
from qiskit.extensions.standard.u3 import Cu3Gate
from qiskit.extensions.standard.rxx import RXXGate
from qiskit.extensions.standard.rzz import RZZGate

Expand Down
2 changes: 1 addition & 1 deletion qiskit/extensions/quantum_initializer/initializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.circuit import Instruction
from qiskit.extensions.standard.cx import CnotGate
from qiskit.extensions.standard.x import CnotGate
from qiskit.extensions.standard.ry import RYGate
from qiskit.extensions.standard.rz import RZGate
from qiskit.circuit.reset import Reset
Expand Down
43 changes: 15 additions & 28 deletions qiskit/extensions/standard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,21 @@

"""Standard gates."""
from .barrier import Barrier
from .ccx import ToffoliGate
from .cswap import FredkinGate
from .cx import CnotGate
from .cy import CyGate
from .cz import CzGate
from .swap import SwapGate
from .h import HGate
from .h import HGate, CHGate
from .iden import IdGate
from .s import SGate
from .s import SdgGate
from .t import TGate
from .t import TdgGate
from .u1 import U1Gate
from .u2 import U2Gate
from .u3 import U3Gate
from .x import XGate
from .y import YGate
from .z import ZGate
from .ms import MSGate
from .r import RGate
from .rx import RXGate
from .ry import RYGate
from .rz import RZGate
from .cu1 import Cu1Gate
from .ch import CHGate
from .crx import CrxGate
from .cry import CryGate
from .crz import CrzGate
from .cu3 import Cu3Gate
from .rzz import RZZGate
from .rx import RXGate, CrxGate
from .rxx import RXXGate
from .ms import MSGate
from .ry import RYGate, CryGate
from .rz import RZGate, CrzGate
from .rzz import RZZGate
from .s import SGate, SdgGate
from .swap import SwapGate, FredkinGate
from .t import TGate, TdgGate
from .u1 import U1Gate, Cu1Gate
from .u2 import U2Gate
from .u3 import U3Gate, Cu3Gate
from .x import XGate, CnotGate, ToffoliGate
from .y import YGate, CyGate
from .z import ZGate, CzGate
80 changes: 5 additions & 75 deletions qiskit/extensions/standard/ccx.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,79 +16,9 @@
Toffoli gate. Controlled-Controlled-X.
"""

import numpy
import warnings
# pylint: disable=unused-import
from qiskit.extensions.standard.x import ToffoliGate, ccx

from qiskit.circuit import ControlledGate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.extensions.standard.x import XGate
from qiskit.extensions.standard.h import HGate
from qiskit.extensions.standard.cx import CnotGate
from qiskit.extensions.standard.t import TGate
from qiskit.extensions.standard.t import TdgGate


class ToffoliGate(ControlledGate):
"""Toffoli gate."""

def __init__(self):
"""Create new Toffoli gate."""
super().__init__("ccx", 3, [], num_ctrl_qubits=2)
self.base_gate = XGate
self.base_gate_name = "x"

def _define(self):
"""
gate ccx a,b,c
{
h c; cx b,c; tdg c; cx a,c;
t c; cx b,c; tdg c; cx a,c;
t b; t c; h c; cx a,b;
t a; tdg b; cx a,b;}
"""
definition = []
q = QuantumRegister(3, "q")
rule = [
(HGate(), [q[2]], []),
(CnotGate(), [q[1], q[2]], []),
(TdgGate(), [q[2]], []),
(CnotGate(), [q[0], q[2]], []),
(TGate(), [q[2]], []),
(CnotGate(), [q[1], q[2]], []),
(TdgGate(), [q[2]], []),
(CnotGate(), [q[0], q[2]], []),
(TGate(), [q[1]], []),
(TGate(), [q[2]], []),
(HGate(), [q[2]], []),
(CnotGate(), [q[0], q[1]], []),
(TGate(), [q[0]], []),
(TdgGate(), [q[1]], []),
(CnotGate(), [q[0], q[1]], [])
]
for inst in rule:
definition.append(inst)
self.definition = definition

def inverse(self):
"""Invert this gate."""
return ToffoliGate() # self-inverse

def to_matrix(self):
"""Return a Numpy.array for the Toffoli 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, 1],
[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, 1, 0, 0, 0, 0]], dtype=complex)


def ccx(self, ctl1, ctl2, tgt):
"""Apply Toffoli to ctl1 and ctl2 to tgt."""
return self.append(ToffoliGate(), [ctl1, ctl2, tgt], [])


QuantumCircuit.ccx = ccx
QuantumCircuit.toffoli = ccx
warnings.warn('This module is deprecated. The ToffoliGate can now be found in x.py',
category=DeprecationWarning, stacklevel=2)
69 changes: 5 additions & 64 deletions qiskit/extensions/standard/ch.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,68 +15,9 @@
"""
controlled-H gate.
"""
import numpy as np
import warnings
# pylint: disable=unused-import
from qiskit.extensions.standard.h import HGate, ch

from qiskit.circuit import ControlledGate
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.extensions.standard.h import HGate
from qiskit.extensions.standard.cx import CnotGate
from qiskit.extensions.standard.t import TGate, TdgGate
from qiskit.extensions.standard.s import SGate, SdgGate


class CHGate(ControlledGate):
"""controlled-H gate."""

def __init__(self):
"""Create new CH gate."""
super().__init__("ch", 2, [], num_ctrl_qubits=1)
self.base_gate = HGate
self.base_gate_name = "h"

def _define(self):
"""
gate ch a,b {
s b;
h b;
t b;
cx a, b;
tdg b;
h b;
sdg b;
}
"""
definition = []
q = QuantumRegister(2, "q")
rule = [
(SGate(), [q[1]], []),
(HGate(), [q[1]], []),
(TGate(), [q[1]], []),
(CnotGate(), [q[0], q[1]], []),
(TdgGate(), [q[1]], []),
(HGate(), [q[1]], []),
(SdgGate(), [q[1]], [])
]
for inst in rule:
definition.append(inst)
self.definition = definition

def inverse(self):
"""Invert this gate."""
return CHGate() # self-inverse

def to_matrix(self):
"""Return a Numpy.array for the Ch gate."""
return np.array([[1, 0, 0, 0],
[0, 1/np.sqrt(2), 0, 1/np.sqrt(2)],
[0, 0, 1, 0],
[0, 1/np.sqrt(2), 0, -1/np.sqrt(2)]], dtype=complex)


def ch(self, ctl, tgt): # pylint: disable=invalid-name
"""Apply CH from ctl to tgt."""
return self.append(CHGate(), [ctl, tgt], [])


QuantumCircuit.ch = ch
warnings.warn('This module is deprecated. The CHGate can now be found in h.py',
category=DeprecationWarning, stacklevel=2)
Loading