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
5.03k stars 2.32k forks source link

QPY loses scheduling information #10582

Open apateonas opened 1 year ago

apateonas commented 1 year ago

Environment

What is happening?

I want to generate a dataset of scheduled Quantum Circuits to run analysis on. I want to save these circuits to a file, so I found the qpy functionality qiskit provides to write circuits to bytes. However, I am seeing that when I load the circuit from the bytes, I am losing scheduling information. Specifically, I can use timeline_drawer before I write to bytes, but when I load the circuit back, I get VisualizationError: 'Input circuit bv is not scheduled and it contains operations with unknown delays. This cannot be visualized.' The circuitop_start_times, qubit start/end times, and duration are also undefined.

How can we reproduce the issue?

import io
from qiskit import qpy, compiler
from qiskit.circuit.library import QFT
from qiskit.providers.fake_provider import FakeProviderForBackendV2

def to_bytes(circuit: QuantumCircuit):
    buf = io.BytesIO()
    qpy.dump(circuit, buf)
    val = buf.getvalue()
    buf.close()
    return val

def from_bytes(qpy_bytes):
    buf = io.BytesIO(qpy_bytes)
    circuit = qpy.load(buf)[0]
    buf.close()
    return circuit

# Build circuit
circuit = QFT(
    name="qft",
    num_qubits=7,
    approximation_degree=0,
    do_swaps=True,
    inverse=False,
    insert_barriers=False,
)
provider = FakeProviderForBackendV2()
backend = provider.get_backend("fake_perth")
transpiled = compiler.transpile(
    circuit,
    backend=backend,
    optimization_level=3,
    seed_transpiler=0,
    layout_method="sabre",
    routing_method="sabre",
    scheduling_method="alap",
)

# Dump and load from Bytes with QPY
circuit_bytes = to_bytes(transpiled)
loaded_circuit = from_bytes(circuit_bytes)

print(transpiled.op_start_times)
print(loaded_circuit.op_start_times)

What should happen?

QPY serialization should not lose any information in the QuantumCircuit, including any scheduling details.

Any suggestions?

No response

Abhiraj-Shrotriya commented 1 year ago

@jakelishman @apateonas

I would like to have a look at this bug. Can you please assign me?

Thank you

And, a simpler and error-free way of reproducing this issue would be as follows:

import io
from qiskit import qpy, transpile, QuantumCircuit
from qiskit.providers.fake_provider import FakePerth

def to_bytes(circuit):
    buf = io.BytesIO()
    qpy.dump(circuit, buf)
    val = buf.getvalue()
    buf.close()
    return val

def from_bytes(qpy_bytes):
    buf = io.BytesIO(qpy_bytes)
    circuit = qpy.load(buf)[0]
    buf.close()
    return circuit

# Build circuit
quantum_circuit = QuantumCircuit(4, 2)
quantum_circuit.x(0)

backend = FakePerth()
transpiled_circuit = transpile(
    quantum_circuit,
    backend=backend,
    optimization_level=2,
    seed_transpiler=0,
    scheduling_method="alap",
)

# Dump and load from Bytes with QPY
circuit_bytes = to_bytes(transpiled_circuit)
loaded_circuit = from_bytes(circuit_bytes)

print(transpiled_circuit.op_start_times)
print(loaded_circuit.op_start_times)
jakelishman commented 1 year ago

@Abhiraj-Shrotriya, you're welcome to have a look, but just be warned that it's quite possible that this issue will not be simple, if there's significant changes to QPY serialisation required. I think / hope that that's not the case, but it could be quite a significant chunk of work.

Abhiraj-Shrotriya commented 1 year ago

@jakelishman, Hi, I took a look at it. Yes, this fix will take some time. I will try my best to solve this as soon as possible. If required, of course I will take your reviews. Thank you