# Transpilation into custom gate set in qiskit

In qiskit, I can transpile a given circuit into a some predefined gate set as follows (just an example)

from qiskit import QuantumCircuit
from qiskit.compiler import transpile
from qiskit.circuit.random import random_circuit

basis_gates = ['id', 'u3', 'cx']

qc = random_circuit(3, 1, seed=0)
qc_trans = transpile(qc, basis_gates=basis_gates)


I have several related questions.

1. Where can I find an exhaustive list of operators allowed as basis_gates?
2. For any operator label from the list of allowed basis gates, how can I find the precise meaning of the corresponding gate, say as a matrix representation?
3. Most importantly, can I add my own custom gates to use as basis gates? Can I add parametric gates? For examples as far as I can tell qiskit standard tools include Rxz and Ryz gates but no Rxy gate. Can I make one?

Example of a (trivial) transpilation into custom gate set failing

from qiskit import QuantumCircuit
from qiskit.compiler import transpile

qc = QuantumCircuit(2, name='mycx')
qc.cx(0, 1)
mycx = qc.to_gate()
qc = QuantumCircuit(2)
qc.cx(0, 1)

transpile(qc, basis_gates=['id','mycx'])


gives me a TranspileError.

• in your mycx example, you probably mean qc.append(mycx, [0, 1]) instead of qc.cx(0, 1). With that change, it works. Jun 8, 2021 at 11:39
• @luciano Nono, the whole point is that although cx is essential the same as mycx I would like the transpiler to find that out. More generally, I would like to get the transpilation into any custom universal gate set. Jun 8, 2021 at 11:40
• I added the section Your custom gate as basis target of a circuit that is not using it as part of my answer. Let me know if that makes it. Jun 9, 2021 at 8:18
• Also, check this youtube video: Unitary matrix to 1Q, 2QGates
– RSW
Aug 13, 2022 at 8:15

### The Qiskit standard gate list

You can find the full list of Qiskit standard gates in the module qiskit.circuit.library.standard_gates (documentation).

### The matrix representation of a standard gate

For each gate, you can see its matrix representation with the to_matrix method. For example:

from qiskit.circuit.library import standard_gates
standard_gates.HGate().to_matrix()

array([[ 0.70710678+0.j,  0.70710678+0.j],
[ 0.70710678+0.j, -0.70710678+0.j]])


Or, its latex representation:

from qiskit.visualization import array_to_latex
array_to_latex(standard_gates.HGate().to_matrix())


### Creating your own custom gate

You can create your own gates from a circuit. For example:

from qiskit import QuantumCircuit

custom_circuit = QuantumCircuit(2, name='bell')
custom_circuit.h(0)
custom_circuit.cx(0, 1)

custom_gate = custom_circuit.to_gate()


You can create a circuit using that custom gate:

circuit = QuantumCircuit(3)
circuit.h(0)
circuit.append(custom_gate, [0,1])
circuit.cx(1, 2)
circuit.draw()

     ┌───┐┌───────┐
q_0: ┤ H ├┤0      ├─────
└───┘│  bell │
q_1: ─────┤1      ├──■──
└───────┘┌─┴─┐
q_2: ──────────────┤ X ├
└───┘


### Telling the transpiler not to decompose your custom gate

Following the previous example, you can transpile that circuit using the custom gate name in the target basis list:

from qiskit.compiler import transpile

basis_gates = ['bell', 'u3', 'cx']

qc_trans = transpile(circuit, basis_gates=basis_gates)
qc_trans.draw()

     ┌─────────────┐┌───────┐
q_0: ┤ U3(π/2,0,π) ├┤0      ├─────
└─────────────┘│  bell │
q_1: ───────────────┤1      ├──■──
└───────┘┌─┴─┐
q_2: ────────────────────────┤ X ├
└───┘


### Your custom gate as basis target of a circuit that is not using it

You can basis-target your own custom in some cases. That requires to extend the equivalence library. Following your mycx example:

1. Create a circuit definition with your custom gate
mycx = QuantumCircuit(2, name='mycx')
mycx.cx(0, 1)

mycx_def = QuantumCircuit(2)
mycx_def.append(mycx.to_gate(), [0, 1])

1. Add an equivalence to the library where a gate (CXGate in this case) is equivalent to that definition.
StandardEquivalenceLibrary.add_equivalence(CXGate(), mycx_def)

1. Create a circuit that uses the domain gate (CXGate in this case).
from qiskit.compiler import transpile

qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)

1. Transpile using the parameter translation_method='translator'. This will tell the transpiler to use the equivalence library for basis translation. In the basis_gate parameter you can refer to your custom gate name (mycx in this case):
result = transpile(qc, basis_gates=['mycx', 'u3'], translation_method='translator')
result.draw()

     ┌─────────────┐┌───────┐
q_0: ┤ U3(π/2,0,π) ├┤0      ├─────────
└─────────────┘│  mycx │┌───────┐
q_1: ───────────────┤1      ├┤0      ├
└───────┘│  mycx │
q_2: ────────────────────────┤1      ├
└───────┘

• Hi, thanks a lot for your answer! I have several follow up questions though. (1) If I just have a label from basis_gates list like 'u3' or 'cx', can I do something like Gate.from_label('cx') instead of looking up the documentation to get the gate? Jun 8, 2021 at 11:11
• (2) Your example of transpilation is a bit trivial because you use the custom 'bell' gate both in the original circuit and in the transpiled circuit. In a more practical situation the transpilation seems to fail. Please see updated question. Jun 8, 2021 at 11:19
• It is not possible to make a from_label. But it looks like a great feature request candidate: github.com/Qiskit/qiskit-terra/issues/… Jun 8, 2021 at 11:29
• Your mycx example fails because qc includes cx which is not in the basis. (and you probably forgot to append mycx to qc? Jun 8, 2021 at 11:31
• Thanks a lot for further elaboration! Still, it seems that we have different goals in mind. Ideally, I would like to transpile an arbitrary circuit into any custom gate set which is universal. Theorems like Solovay-Kitaev's guarantee that this is possible. Perhaps I am interested whether there is some general-purpose algorithm under the hood in qiskit that does that. From your new amendment I gather that I need to set the rules for decomposing into my custom gate set by hands. So I would guess that current qiskit traspiler can only target gates native to IBM machines? Jun 9, 2021 at 8:34

You can use BQSKit to accomplish this very easily. BQSKit is a powerful and portable quantum compiler/transpiler. You will need to calculate the unitary of your gate and you can just plug that into BQSKit.

You can accomplish this with the following:

from bqskit import compile, MachineModel, Circuit
from bqskit.ir.gates import IdentityGate, ConstantUnitaryGate
mycx = ConstantUnitaryGate([...]) # Fill in unitary here
model = MachineModel(gate_set={mycx, IdentityGate(1)})
output_circuit = compile(circuit, model)