Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
4.84k stars 2.29k forks source link

Dump and load with qpy does not seem to return the same circuit #9509

Closed AGaliciaMartinez closed 1 year ago

AGaliciaMartinez commented 1 year ago

Environment

What is happening?

We obtain different circuits once dumped into a qpy an loaded again from a qpy.

How can we reproduce the issue?

from qiskit import QuantumCircuit
from qiskit import qpy
from io import BytesIO

circuit = QuantumCircuit(1)
circuit.h(0)
circuit.data
# Out[62]: [CircuitInstruction(operation=Instruction(name='h', num_qubits=1, num_clbits=0, params=[]), qubits=(Qubit(QuantumRegister(1, 'q'), 0),), clbits=())]
bytes = BytesIO()
qpy.dump(programs=circuit, file_obj=bytes)
qpy_loaded_circuit = qpy.load(BytesIO(bytes.getvalue()))
qpy_loaded_circuit[0].data
# Out[61]: [CircuitInstruction(operation=Instruction(name='h', num_qubits=1, num_clbits=0, params=[]), qubits=(<qiskit.circuit.quantumregister.Qubit object at 0x7f33fbae4f40>,), clbits=())]

The difference between the outputs seems to lie in the qubits attribute from CircuitInstruction.

Context in which this error arises

We are trying to access the index of the qubit for the instruction in the following way: circuit.data[0].qubit[0].index. This works for the circuit but it does not work with qpy_loaded_circuit (raises error). This error started appearing in the last version of qiskit but we noticed that there is a deprecation when using circuit.data[0].qubit[0].index. I assume that this is not the intended way of retrieving the information about the qubit index for a given instruction. Is there any other way we can use to retrieve this information without the deprecation warning and the error from the loaded qpy circuit?

UPDATE: We found that the following works:

qreg = qpy_loaded_circuit[0].qregs[0]
instruction = qpy_loaded_circuit[0].data[0]
qreg.index(instruction.qubits[0])

Is this the intended way?

Thank you in advance for the help!

What should happen?

We would like to obtain the index information for a CircuitInstruction

Any suggestions?

No response

jakelishman commented 1 year ago

You likely shouldn't ever be using Bit.index - it's been deprecated for a lot longer than the most recent version of Terra, and it's not representative of the Qiskit data model. Is this mitiq? I remember one of us mentioned to the team something like a year ago that its code playing with the internals of QuantumCircuit was very fragile because of stuff like this, but I don't remember much more than that.

What do you need the index of the bit in the circuit for? You can use the actual Bit object anywhere that builds gates (e.g. QuantumCircuit.h, .append, etc). If you really need the index for something, then you might want QuantumCircuit.find_bit. edit: the indices used by each instruction should be the same after QPY roundtrip - i.e. if you did h(0) on the first circuit, the equivalent instruction on the output circuit will be on its 0th qubit.

jakelishman commented 1 year ago

Also, when you say it's "different": you should find that circuit == qpy_loaded_circuits[0] - it's circuit equivalence up to qubit object identity.

AGaliciaMartinez commented 1 year ago

Hi Jake, thanks for the quick reply! find_bit is indeed what we should be using. This is not mitiq, we (PGI-13, Juelich FZ) are working on a qiskit compatible interface to execute circuits in our quantum computers. We hence need to iterate the instructions to translate them into the low level pulses we use. The information about the qubit index in which the circuit is executed is also necessary for our translation layer.

I am going to close the issue as being solved since this was a problem caused by us not using QuantumCircuit properly. Thanks again Jake!

jakelishman commented 1 year ago

Fair enough, that sounds sensible! Yeah, find_bit is good, but also if you knew the qubit indices for each instruction before the QPY roundtrip, they should be the same on the way out as well. But QuantumCircuit.find_bit(bit).index should give you the info you need too.

Sounds cool! If you make a custom backend for your computer and on the off chance there's some degree of public accessibility to it, you can even make a full "provider" package and add it to https://github.com/Qiskit-Partners. I'm guessing probably you're not making that sort of thing public, though, haha.