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.08k stars 2.34k forks source link

QPY serialization of empty gates yields ``None`` definitions #7429

Closed Cryoris closed 2 years ago

Cryoris commented 2 years ago

Environment

What is happening?

Serializing + deserializing a circuit containing an empty gate (i.e. no operations) with QPY yields a gate where the definition is None instead of an empty circuit. If the definition is None the transpiler cannot decompose the gate, unless the gate is in the basis set (like e.g. x or cx are).

This is a problem in particular for Qiskit runtime as users might unintentionally construct circuits that contain empty gates, as e.g. was the case in Qiskit/qiskit-nature#449.

How can we reproduce the issue?

import io
from qiskit import Aer, transpile, QuantumCircuit
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.qpy_serialization import dump, load

empty = QuantumCircuit(1, name="empty")
circuit = QuantumCircuit(1)
circuit.append(empty, [0])

qpy_file = io.BytesIO()
dump(circuit, qpy_file)
qpy_file.seek(0)
new_circuit = load(qpy_file)[0]

sim = Aer.get_backend("aer_simulator")
transpile(new_circuit, sim)

produces

qiskit.exceptions.QiskitError: "Cannot unroll the circuit to the given basis, ['ccx', 'cp', 'cswap', 'csx', 'cu', 'cu1', 'cu2', 'cu3', 'cx', 'cy', 'cz', 'delay', 'diagonal', 'h', 'id', 'initialize', 'mcp', 'mcphase', 'mcr', 'mcrx', 'mcry', 'mcrz', 'mcswap', 'mcsx', 'mcu', 'mcu1', 'mcu2', 'mcu3', 'mcx', 'mcx_gray', 'mcy', 'mcz', 'multiplexer', 'p', 'pauli', 'r', 'roerror', 'rx', 'rxx', 'ry', 'ryy', 'rz', 'rzx', 'rzz', 's', 'sdg', 'swap', 'sx', 'sxdg', 't', 'tdg', 'u', 'u1', 'u2', 'u3', 'unitary', 'x', 'y', 'z', 'kraus', 'roerror', 'save_amplitudes', 'save_amplitudes_sq', 'save_density_matrix', 'save_expval', 'save_expval_var', 'save_matrix_product_state', 'save_probabilities', 'save_probabilities_dict', 'save_stabilizer', 'save_state', 'save_statevector', 'save_statevector_dict', 'save_superop', 'save_unitary', 'set_density_matrix', 'set_matrix_product_state', 'set_stabilizer', 'set_statevector', 'set_superop', 'set_unitary', 'snapshot', 'superop']. Instruction empty not found in equivalence library and no rule found to expand."

What should happen?

The gate should have a definition which is an empty circuit instead of being just None.

Any suggestions?

No response

jakelishman commented 2 years ago

This seems pretty fixable without a QPY format bump. It's our old friend bool causing problems here: QPY decides if it needs to output a definition based on bool(instruction.definition), but bool(empty) is False because QuantumCircuit defines __len__ as a pass through to the number of operations, and bool essentially tries len(x) != 0.

Pretty sure I can fix this no problems, and it'll be stable for backport.