10
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ in your mycx example, you probably mean qc.append(mycx, [0, 1]) instead of qc.cx(0, 1). With that change, it works. $\endgroup$
    – luciano
    Commented Jun 8, 2021 at 11:39
  • $\begingroup$ @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. $\endgroup$ Commented Jun 8, 2021 at 11:40
  • $\begingroup$ 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. $\endgroup$
    – luciano
    Commented Jun 9, 2021 at 8:18
  • $\begingroup$ Also, check this youtube video: Unitary matrix to 1Q, 2QGates $\endgroup$
    – RSW
    Commented Aug 13, 2022 at 8:15

2 Answers 2

12
$\begingroup$

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())

matrix output in latex

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      ├
                             └───────┘
$\endgroup$
8
  • $\begingroup$ 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? $\endgroup$ Commented Jun 8, 2021 at 11:11
  • $\begingroup$ (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. $\endgroup$ Commented Jun 8, 2021 at 11:19
  • $\begingroup$ It is not possible to make a from_label. But it looks like a great feature request candidate: github.com/Qiskit/qiskit-terra/issues/… $\endgroup$
    – luciano
    Commented Jun 8, 2021 at 11:29
  • $\begingroup$ Your mycx example fails because qc includes cx which is not in the basis. (and you probably forgot to append mycx to qc? $\endgroup$
    – luciano
    Commented Jun 8, 2021 at 11:31
  • $\begingroup$ 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? $\endgroup$ Commented Jun 9, 2021 at 8:34
2
$\begingroup$

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)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.