Skip to content
29 changes: 19 additions & 10 deletions qiskit/circuit/add_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,18 @@ def control(operation: Union[Gate, ControlledGate],
operation.base_gate.name == 'x'):
qc.mct(q_control[:] + q_target[:-1], q_target[-1], q_ancillae)
elif operation.name == 'rx':
qc.mcrx(operation.definition[0][0].params[0], q_control, q_target[0],
qc.mcrx(operation.definition.data[0][0].params[0], q_control, q_target[0],
use_basis_gates=True)
elif operation.name == 'ry':
qc.mcry(operation.definition[0][0].params[0], q_control, q_target[0],
qc.mcry(operation.definition.data[0][0].params[0], q_control, q_target[0],
q_ancillae, mode='noancilla', use_basis_gates=True)
elif operation.name == 'rz':
qc.mcrz(operation.definition[0][0].params[0], q_control, q_target[0],
qc.mcrz(operation.definition.data[0][0].params[0], q_control, q_target[0],
use_basis_gates=True)
else:
bgate = _unroll_gate(operation, ['u1', 'u3', 'cx'])
# now we have a bunch of single qubit rotation gates and cx
for rule in bgate.definition:
for rule in bgate.definition.data:
if rule[0].name == 'u3':
theta, phi, lamb = rule[0].params
if phi == -pi / 2 and lamb == pi / 2:
Expand All @@ -150,7 +150,6 @@ def control(operation: Union[Gate, ControlledGate],
else:
raise CircuitError('gate contains non-controllable instructions')

instr = qc.to_instruction()
if isinstance(operation, controlledgate.ControlledGate):
new_num_ctrl_qubits = num_ctrl_qubits + operation.num_ctrl_qubits
new_ctrl_state = operation.ctrl_state << num_ctrl_qubits | ctrl_state
Expand All @@ -171,11 +170,11 @@ def control(operation: Union[Gate, ControlledGate],
ctrl_substr = ('{0}' * new_num_ctrl_qubits).format('c')
new_name = '{0}{1}'.format(ctrl_substr, base_name)
cgate = controlledgate.ControlledGate(new_name,
instr.num_qubits,
qc.num_qubits,
operation.params,
label=label,
num_ctrl_qubits=new_num_ctrl_qubits,
definition=instr.definition,
definition=qc,
ctrl_state=new_ctrl_state)
cgate.base_gate = base_gate
return cgate
Expand All @@ -185,7 +184,7 @@ def _gate_to_circuit(operation):
qr = QuantumRegister(operation.num_qubits)
qc = QuantumCircuit(qr, name=operation.name)
if hasattr(operation, 'definition') and operation.definition:
for rule in operation.definition:
for rule in operation.definition.data:
if rule[0].name in {'id', 'barrier', 'measure', 'snapshot'}:
raise CircuitError('Cannot make controlled gate with {} instruction'.format(
rule[0].name))
Expand All @@ -195,11 +194,21 @@ def _gate_to_circuit(operation):
return qc


def _unroll_gate(operation, basis_gates):
def _gate_to_dag(operation):
from qiskit.converters.circuit_to_dag import circuit_to_dag
if hasattr(operation, 'definition') and operation.definition:
return circuit_to_dag(operation.definition)
else:
qr = QuantumRegister(operation.num_qubits)
qc = QuantumCircuit(qr, name=operation.name)
qc.append(operation, qr)
return circuit_to_dag(qc)


def _unroll_gate(operation, basis_gates):
from qiskit.converters.dag_to_circuit import dag_to_circuit
from qiskit.transpiler.passes import Unroller
unroller = Unroller(basis_gates)
dag = circuit_to_dag(_gate_to_circuit(operation))
dag = _gate_to_dag(operation)
qc = dag_to_circuit(unroller.run(dag))
return qc.to_gate()
35 changes: 18 additions & 17 deletions qiskit/circuit/controlledgate.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@

"""Controlled unitary gate."""

from typing import Tuple, List, Optional, Union
from typing import List, Optional, Union
from qiskit.circuit.exceptions import CircuitError

# pylint: disable=cyclic-import
from .quantumcircuit import QuantumCircuit
from .gate import Gate
from .quantumregister import QuantumRegister
from .quantumregister import Qubit
from .classicalregister import Clbit

# pylint: disable=missing-return-doc

Expand All @@ -30,7 +30,7 @@ class ControlledGate(Gate):

def __init__(self, name: str, num_qubits: int, params: List,
label: Optional[str] = None, num_ctrl_qubits: Optional[int] = 1,
definition: Optional[List[Tuple[Gate, List[Qubit], List[Clbit]]]] = None,
definition: Optional['QuantumCircuit'] = None,
ctrl_state: Optional[Union[int, str]] = None):
"""Create a new ControlledGate. In the new gate the first ``num_ctrl_qubits``
of the gate are the controls.
Expand Down Expand Up @@ -90,8 +90,8 @@ def __init__(self, name: str, num_qubits: int, params: List,
self.base_gate = None
if definition:
self.definition = definition
if len(definition) == 1:
base_gate = definition[0][0]
if len(definition.data) == 1:
base_gate = definition.data[0][0]
if isinstance(base_gate, ControlledGate):
self.base_gate = base_gate.base_gate
else:
Expand All @@ -109,25 +109,26 @@ def definition(self) -> List:
if self._open_ctrl:
closed_gate = self.copy()
closed_gate.ctrl_state = None
# pylint: disable=cyclic-import
from qiskit.circuit.library.standard_gates import XGate
bit_ctrl_state = bin(self.ctrl_state)[2:].zfill(self.num_ctrl_qubits)
qreg = QuantumRegister(self.num_qubits, 'q')
definition = [(closed_gate, qreg, [])]
open_rules = []
qc_open_ctrl = QuantumCircuit(qreg)
for qind, val in enumerate(bit_ctrl_state[::-1]):
if val == '0':
open_rules.append([XGate(), [qreg[qind]], []])
if open_rules:
return open_rules + definition + open_rules
else:
return self._definition
qc_open_ctrl.x(qind)
qc_open_ctrl.append(closed_gate, qargs=qreg[:])
for qind, val in enumerate(bit_ctrl_state[::-1]):
if val == '0':
qc_open_ctrl.x(qind)
return qc_open_ctrl
else:
return super().definition

@definition.setter
def definition(self, excited_def: List):
"""Set controlled gate definition with closed controls."""
def definition(self, excited_def: 'QuantumCircuit'):
"""Set controlled gate definition with closed controls.

Args:
excited_def: The circuit with all closed controls."""
super(Gate, self.__class__).definition.fset(self, excited_def)

@property
Expand Down
23 changes: 16 additions & 7 deletions qiskit/circuit/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def definition(self):

@definition.setter
def definition(self, array):
"""Set matrix representation"""
"""Set gate representation"""
self._definition = array

@property
Expand Down Expand Up @@ -246,9 +246,9 @@ def reverse_ops(self):
return self.copy()

reverse_inst = self.copy(name=self.name + '_reverse')
reverse_inst.definition = []
reverse_inst.definition.data = []
for inst, qargs, cargs in reversed(self._definition):
reverse_inst._definition.append((inst.reverse_ops(), qargs, cargs))
reverse_inst._definition.data.append((inst.reverse_ops(), qargs, cargs))
return reverse_inst

def inverse(self):
Expand All @@ -270,9 +270,9 @@ def inverse(self):
if self.definition is None:
raise CircuitError("inverse() not implemented for %s." % self.name)
inverse_gate = self.copy(name=self.name + '_dg')
inverse_gate._definition = []
for inst, qargs, cargs in reversed(self._definition):
inverse_gate._definition.append((inst.inverse(), qargs, cargs))
inverse_gate._definition.data = []
for inst, qargs, cargs in reversed(self._definition.data):
inverse_gate._definition.data.append((inst.inverse(), qargs, cargs))
return inverse_gate

def c_if(self, classical, val):
Expand Down Expand Up @@ -377,5 +377,14 @@ def repeat(self, n):
qargs = [] if self.num_qubits == 0 else QuantumRegister(self.num_qubits, 'q')
cargs = [] if self.num_clbits == 0 else ClassicalRegister(self.num_clbits, 'c')

instruction.definition = [(self, qargs[:], cargs[:])] * n
if instruction.definition is None:
# pylint: disable=cyclic-import
from qiskit import QuantumCircuit
qc = QuantumCircuit()
if qargs:
qc.add_register(qargs)
if cargs:
qc.add_register(cargs)
qc.data = [(self, qargs[:], cargs[:])] * n
instruction.definition = qc
return instruction
7 changes: 6 additions & 1 deletion qiskit/circuit/library/standard_gates/dcx.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,17 @@ def _define(self):
"""
gate dcx a, b { cx a, b; cx a, b; }
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .x import CXGate
q = QuantumRegister(2, 'q')
self.definition = [
qc = QuantumCircuit(q, name=self.name)
rules = [
(CXGate(), [q[0], q[1]], []),
(CXGate(), [q[1], q[0]], [])
]
qc.data = rules
self.definition = qc

def to_matrix(self):
"""Return a numpy.array for the DCX gate."""
Expand Down
22 changes: 12 additions & 10 deletions qiskit/circuit/library/standard_gates/h.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,16 @@ def _define(self):
"""
gate h a { u2(0,pi) a; }
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .u2 import U2Gate
definition = []
q = QuantumRegister(1, 'q')
rule = [
qc = QuantumCircuit(q, name=self.name)
rules = [
(U2Gate(0, pi), [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-H gate.
Expand Down Expand Up @@ -181,10 +182,12 @@ def _define(self):
sdg b;
}
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .x import CXGate # pylint: disable=cyclic-import
definition = []
q = QuantumRegister(2, 'q')
rule = [
qc = QuantumCircuit(q, name=self.name)
rules = [
(SGate(), [q[1]], []),
(HGate(), [q[1]], []),
(TGate(), [q[1]], []),
Expand All @@ -193,9 +196,8 @@ def _define(self):
(HGate(), [q[1]], []),
(SdgGate(), [q[1]], [])
]
for inst in rule:
definition.append(inst)
self.definition = definition
qc.data = rules
self.definition = qc

def inverse(self):
"""Return inverted CH gate (itself)."""
Expand Down
7 changes: 6 additions & 1 deletion qiskit/circuit/library/standard_gates/iswap.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,23 @@ def _define(self):
h q[1];
}
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .h import HGate
from .s import SGate
from .x import CXGate
q = QuantumRegister(2, 'q')
self.definition = [
qc = QuantumCircuit(q, name=self.name)
rules = [
(SGate(), [q[0]], []),
(SGate(), [q[1]], []),
(HGate(), [q[0]], []),
(CXGate(), [q[0], q[1]], []),
(CXGate(), [q[1], q[0]], []),
(HGate(), [q[1]], [])
]
qc.data = rules
self.definition = qc

def to_matrix(self):
"""Return a numpy.array for the iSWAP gate."""
Expand Down
14 changes: 7 additions & 7 deletions qiskit/circuit/library/standard_gates/ms.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ def __init__(self, num_qubits, theta, *, n_qubits=None, # pylint:disable=unused
super().__init__('ms', num_qubits, [theta], label=label)

def _define(self):
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .rxx import RXXGate
definition = []
q = QuantumRegister(self.num_qubits, 'q')
rule = []
qc = QuantumCircuit(q, name=self.name)
rules = []
for i in range(self.num_qubits):
for j in range(i + 1, self.num_qubits):
rule += [(RXXGate(self.params[0]), [q[i], q[j]], [])]

for inst in rule:
definition.append(inst)
self.definition = definition
rules += [(RXXGate(self.params[0]), [q[i], q[j]], [])]
qc.data = rules
self.definition = qc
11 changes: 6 additions & 5 deletions qiskit/circuit/library/standard_gates/r.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,18 @@ def _define(self):
"""
gate r(θ, φ) a {u3(θ, φ - π/2, -φ + π/2) a;}
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .u3 import U3Gate
definition = []
q = QuantumRegister(1, 'q')
qc = QuantumCircuit(q, name=self.name)
theta = self.params[0]
phi = self.params[1]
rule = [
rules = [
(U3Gate(theta, phi - pi / 2, -phi + pi / 2), [q[0]], [])
]
for inst in rule:
definition.append(inst)
self.definition = definition
qc.data = rules
self.definition = qc

def inverse(self):
"""Invert this gate.
Expand Down
22 changes: 12 additions & 10 deletions qiskit/circuit/library/standard_gates/rx.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,16 @@ def _define(self):
"""
gate rx(theta) a {r(theta, 0) a;}
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .r import RGate
definition = []
q = QuantumRegister(1, 'q')
rule = [
qc = QuantumCircuit(q, name=self.name)
rules = [
(RGate(self.params[0], 0), [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 (mutli-)controlled-RX gate.
Expand Down Expand Up @@ -178,21 +179,22 @@ def _define(self):
u3(theta/2,-pi/2,0) t;
}
"""
# pylint: disable=cyclic-import
from qiskit.circuit.quantumcircuit import QuantumCircuit
from .u1 import U1Gate
from .u3 import U3Gate
from .x import CXGate
definition = []
q = QuantumRegister(2, 'q')
rule = [
qc = QuantumCircuit(q, name=self.name)
rules = [
(U1Gate(pi / 2), [q[1]], []),
(CXGate(), [q[0], q[1]], []),
(U3Gate(-self.params[0] / 2, 0, 0), [q[1]], []),
(CXGate(), [q[0], q[1]], []),
(U3Gate(self.params[0] / 2, -pi / 2, 0), [q[1]], [])
]
for inst in rule:
definition.append(inst)
self.definition = definition
qc.data = rules
self.definition = qc

def inverse(self):
"""Return inverse RX gate (i.e. with the negative rotation angle)."""
Expand Down
Loading