2
$\begingroup$

I'm trying to get used to the qiskit module and quantum circuits in general, before tackling a QML project. So I'm going through the tutorial on the documentation page regarding gates. I've gotten as far as the controlled Hadamard gate. I can create the circuit and print it out, but once I try to run the job, I get an error:

q0_0: ──■──
      ┌─┴─┐
q0_1: ┤ H ├
      └───┘
Simulation failed and returned the following error message:
ERROR:  [Experiment 0] Circuit contains invalid instructions {"gates": {ch}} for "unitary" method

I had to modify the sample code a little because it threw a few deprecation errors and I couldn't get it to display the circuit or the matrix as it stood. The example code (gathered into 1 from the tutorial):

import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
from math import pi

from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute
from qiskit.tools.visualization import circuit_drawer
from qiskit.quantum_info import state_fidelity
from qiskit import BasicAer

backend = BasicAer.get_backend('unitary_simulator')

q = QuantumRegister(2)
qc = QuantumCircuit(q)
qc.ch(q[0],q[1])
qc.draw()

job = execute(qc, backend)
job.result().get_unitary(qc, decimals=3)

The main change I had to make, was irt. the .draw() and execute() functions. I got some errors there when importing. Since I couldn't find a provider called BasicAer I went with the Aer provider. for all single-qubit states, this worked as well as for controlled X Y and Z gates.

from qiskit import \
        QuantumCircuit,\
        QuantumRegister,\
        ClassicalRegister
from qiskit.providers.aer import UnitarySimulator

import numpy as np

backend = UnitarySimulator()
n = 2
q = QuantumRegister(n)

qc = QuantumCircuit(q)
qc.ch(q[0], q[1]) # LSB first
print(qc)
job = backend.run(qc)

I tried to google the error message, but I couldn't find any previous issues regarding this, nor any particular error message like it.

The error refers to a "Unitary" method. This could be the unitary_simulator/UnitarySimulator the tutorial used versus the one I imported. Testing it, the code seems to run, though I struggle to see the output. In addition, an error is then thrown at the decimal bit in the tutorial. It seems like I could make it work if I changed the import method, but I don't quite understand why. There were also some deprecation warnings for the tutorial in earlier parts, which my previous methods avoided, in particular regarding the Unitary operator and the decomposition into u3, u2 and u1.

Is the BasicAer.get_backend('unitary_simulator')method in the process of phasing out, or is it an either or situation? is there a particular reason for the difference in the functionality between the 2?

>>> qiskit.__qiskit_version__
{'qiskit-terra': '0.17.0', 'qiskit-aer': '0.8.0', 'qiskit-ignis': '0.6.0', 'qiskit-ibmq-provider': '0.12.2', 'qiskit-aqua': '0.9.0', 'qiskit': '0.25.0'}

Edit: I got a tip from a TA regarding the use of execute() which does let the program run. From a quick look at the documentation, it seems like there are few differences between the execute() and backend.run(), though according to this it could be that the execute() transpiles the circuit first? but I don't quite see why that would allow for unitary operations.

Another thing, I have tested the same type of imports on singular bit gates such as the U gate, and on 2-qubit gates such as the CX gate, which both work with the unitary operator from what I understand. And there are no new function calls for the CH gate. I guess part of it is that I don't see why it fails for the CH and not for H, U or CX or others.

$\endgroup$
3
$\begingroup$

As it is written in the error message, it is here because the CH gate is not in the basis gates of UnitarySimulator, therefore the backend doesn't understand it and can't do anything with it ; check this line of code :

'ch' in UnitarySimulator().configuration().basis_gates

It returns False.

Now I believe it has the error with the run method and not the execute function because in the execute function, there is a step called the transpiler that does this translation step into gates the backend knows. It is a vital step when you are running on actual devices that have basis gates equal to ['x', 'sx', 'rz', 'id', 'cx']. Nothing needs to change when you use the execute function, but with the run method you could do something like this :

qc = QuantumCircuit(q)
qc.ch(q[0], q[1]) # LSB first
qc = transpile(qc, backend)
qobj = assemble(qc, backend)
print(qc)
job = backend.run(qobj)
$\endgroup$
2
$\begingroup$

The reason for your error is that you are running on a backend that does not support CH. The function execute works because it runs transpile before, adapting the basis.

However, if I understand the spirit of your question, you can quickly get the unitary of any circuit using kaleidoscope, a very nice 3rd-party Qiskit extension. It can be installed with pip install kaleidoscope.

Then, you just do:

import kaleidoscope.qiskit
qc.unitary()
Operator([[ 1.        +0.j,  0.        +0.j,  0.        +0.j,
            0.        +0.j],
          [ 0.        +0.j,  0.70710678+0.j,  0.        +0.j,
            0.70710678+0.j],
          [ 0.        +0.j,  0.        +0.j,  1.        +0.j,
            0.        +0.j],
          [ 0.        +0.j,  0.70710678+0.j,  0.        +0.j,
           -0.70710678+0.j]],
         input_dims=(2, 2), output_dims=(2, 2))

If you want to display your matrix more nicely, you can get back to regular Qiskit and use qiskit.visualization.array_to_latex:

import kaleidoscope.qiskit
from qiskit.visualization import array_to_latex
array_to_latex(qc.unitary())

$$ \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \tfrac{1}{\sqrt{2}} & 0 & \tfrac{1}{\sqrt{2}} \\ 0 & 0 & 1 & 0 \\ 0 & \tfrac{1}{\sqrt{2}} & 0 & -\tfrac{1}{\sqrt{2}} \\ \end{bmatrix} $$

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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