# Custom Gate/Instruction with classical bits in Qiskit

In Qiskit, I need to define a custom gate or instruction that, once decomposed, turns into a series of basis gates, including measurements and classically controlled gates (this is the part that I can't get around).

I already tried using QuantumCircuit.to_gate(), but it does not work, maybe there is a way to it with the Instruction class?

Edit 1

I tried to do something like this:

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

def mygate():
qr = QuantumRegister(4)
cr1 = ClassicalRegister(1)
cr2 = ClassicalRegister(1)
qc = QuantumCircuit(qr, cr1, cr2, name='mygate')
qc.measure(qr[0], cr1[0])
qc.measure(qr[1], cr2[0])
qc.x(qr[-2]).c_if(cr1, 1)
qc.x(qr[-1]).c_if(cr2, 1)

return qc.to_instruction()

big = QuantumCircuit(5, 4)
big.append(mygate(), range(4), range(2))


But it does not work.

qiskit.exceptions.QiskitError: 'Cannot convert condition in circuit with multiple classical registers to instruction'

• I'm sorry, I don't really understand the question - do you want to algorithmically decompose a custom gate? Commented Sep 17, 2020 at 23:10

You need to convert a circuit into an instruction, not a gate. A gate is assumed to be invertible, which is not the case if you have measurements and classical conditionals. Therefore, you need to create a custom instruction. Here is a short tutorial for that:

First, create a circuit will all your gates and instructions, with measurements and conditionals. This will be the custom instruction:

from qiskit import *
from qiskit.circuit.library import *

qr = QuantumRegister(2)
cr = ClassicalRegister(2)
circuit = QuantumCircuit(qr, cr, name='my_inst')
circuit.h(qr[0])
circuit.cx(qr[0], qr[1])
circuit.measure(qr[1], cr[0])
circuit.append(XGate(), [qr[0]]).c_if(cr,2)
circuit.draw('text')

      ┌───┐         ┌───┐
q4_0: ┤ H ├──■──────┤ X ├─
└───┘┌─┴─┐┌─┐ └─┬─┘
q4_1: ─────┤ X ├┤M├───┼───
└───┘└╥┘┌──┴──┐
c4: 2/═══════════╩═╡ = 2 ╞
0 └─────┘


Then, you need to convert this circuit into an instruction:

my_inst = circuit.to_instruction()


This instruction can be append to another super circuit:

big_circuit = QuantumCircuit(5, 2)
big_circuit.h(range(5))
big_circuit.append(my_inst, range(2), range(2))
big_circuit.h(range(5))
big_circuit.draw('text')

     ┌───┐┌──────────┐┌───┐
q_0: ┤ H ├┤0         ├┤ H ├
├───┤│          │├───┤
q_1: ┤ H ├┤1         ├┤ H ├
├───┤│          │├───┤
q_2: ┤ H ├┤          ├┤ H ├
├───┤│          │├───┤
q_3: ┤ H ├┤  my_inst ├┤ H ├
├───┤│          │├───┤
q_4: ┤ H ├┤          ├┤ H ├
└───┘│          │└───┘
c_0: ═════╡0         ╞═════
│          │
c_1: ═════╡1         ╞═════
└──────────┘


There it is. If you decompose the instructions in this circuit, you will see the internal operations:

big_circuit.decompose().draw('text')

     ┌──────────┐   ┌───┐                         ┌───┐ ┌──────────┐
q_0: ┤ U2(0,pi) ├───┤ H ├──────■──────────────────┤ X ├─┤ U2(0,pi) ├
├──────────┤   └───┘    ┌─┴─┐┌─┐┌──────────┐ └─┬─┘ └──────────┘
q_1: ┤ U2(0,pi) ├────────────┤ X ├┤M├┤ U2(0,pi) ├───┼───────────────
├──────────┤┌──────────┐└───┘└╥┘└──────────┘   │
q_2: ┤ U2(0,pi) ├┤ U2(0,pi) ├──────╫────────────────┼───────────────
├──────────┤├──────────┤      ║                │
q_3: ┤ U2(0,pi) ├┤ U2(0,pi) ├──────╫────────────────┼───────────────
├──────────┤├──────────┤      ║                │
q_4: ┤ U2(0,pi) ├┤ U2(0,pi) ├──────╫────────────────┼───────────────
└──────────┘└──────────┘      ║             ┌──┴──┐
c: 2/══════════════════════════════╩═════════════╡ = 2 ╞════════════
0             └─────┘


If you want to decompose the circuit to a particular base, you can use the transpiler for that:

decomposed = transpile(big_circuit, basis_gates=['cx', 'u3'], optimization_level=0)
decomposed.draw('text', fold=-1)

     ┌───────────────┐┌───────────────┐                         ┌─────────────┐┌───────────────┐
q_0: ┤ U3(pi/2,0,pi) ├┤ U3(pi/2,0,pi) ├──■──────────────────────┤ U3(pi,0,pi) ├┤ U3(pi/2,0,pi) ├
├───────────────┤└───────────────┘┌─┴─┐┌─┐┌───────────────┐└──────┬──────┘└───────────────┘
q_1: ┤ U3(pi/2,0,pi) ├─────────────────┤ X ├┤M├┤ U3(pi/2,0,pi) ├───────┼────────────────────────
├───────────────┤┌───────────────┐└───┘└╥┘└───────────────┘       │
q_2: ┤ U3(pi/2,0,pi) ├┤ U3(pi/2,0,pi) ├──────╫─────────────────────────┼────────────────────────
├───────────────┤├───────────────┤      ║                         │
q_3: ┤ U3(pi/2,0,pi) ├┤ U3(pi/2,0,pi) ├──────╫─────────────────────────┼────────────────────────
├───────────────┤├───────────────┤      ║                         │
q_4: ┤ U3(pi/2,0,pi) ├┤ U3(pi/2,0,pi) ├──────╫─────────────────────────┼────────────────────────
└───────────────┘└───────────────┘      ║                      ┌──┴──┐
c: 2/════════════════════════════════════════╩══════════════════════╡ = 2 ╞═════════════════════
0                      └─────┘

• Thanks for the reply, I updated my question with a slightly more complex example. Commented Sep 18, 2020 at 6:14
• I see. The reason for Edit 1 failer is because registers get flatten as part of the conversion. Because classical conditional depends on the names of classical registers, converting a circuit with more than a classical register creates a condition on a partial register, which is not supported. Therefore that situation is not allowed. Commented Sep 18, 2020 at 12:19
• So there is no way to do it? Commented Sep 19, 2020 at 14:40
• No. You can request the feature here github.com/Qiskit/qiskit-terra/issues/new/choose. Commented Sep 19, 2020 at 17:42

I don't see a way to avoid the error you are getting as an Instruction can't handle multiple classical registers but here is a workaround.

def mygate():

qr = QuantumRegister(4)
cr1 = ClassicalRegister(1)
cr2 = ClassicalRegister(1)

qc = QuantumCircuit(qr, cr1, cr2,
name='mygate')

qc.measure(qr[0], cr1[0])
qc.measure(qr[1], cr2[0])

qc.x(qr[-2]).c_if(cr1, 1)
qc.x(qr[-1]).c_if(cr2, 1)

return qc

big = QuantumCircuit(5, 4)
big.compose(mygate(),
qubits=range(4), clbits=range(2),
inplace=True)

• This will not create a custom instruction but will concatenate two circuits (big and mygate). The "encapsulation" of mygate happens at Python level, not at circuit level. Depending on your usecase, it's a possibility. Commented Sep 18, 2020 at 17:21