quantumlib / Cirq

A Python framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
Apache License 2.0
4.23k stars 1.01k forks source link

Incorrect Classical Register Size in `to_qasm` with Inhomogeneous Measurements #6508

Open p51lee opened 5 months ago

p51lee commented 5 months ago

Description of the issue

When a Circuit contains multiple measurements under the same key but with varying sizes, the to_qasm method improperly assigns the classical register size, resulting in a smaller than required register. A potential solution includes fixing this behavior directly or, throwing an exception for circuits with measurements of differing sizes being translated to OpenQASM, to prevent incorrect translations.

How to reproduce the issue

import cirq

qubits = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.measure(qubits[0], key='c'),
    cirq.measure(qubits, key='c'),
)
# No issue
# circuit = cirq.Circuit(
#    cirq.measure(qubits, key='c'),
#    cirq.measure(qubits[0], key='c'),
# )

print(circuit.to_qasm())

Result:

// Generated from Cirq v1.3.0

OPENQASM 2.0;
include "qelib1.inc";

// Qubits: [q(0), q(1)]
qreg q[2];
creg m_c[1];  // Incorrectly suggests a single-bit register, expected size is 2

measure q[0] -> m_c[0];

// Gate: cirq.MeasurementGate(2, cirq.MeasurementKey(name='c'), ())
measure q[0] -> m_c[0];
measure q[1] -> m_c[1]; 

Cirq version 1.3.0

verult commented 5 months ago

Thank you for the bug report. From the Cirq sync: to help make a decision regarding whether a fix or an exception is more appropriate, @p51lee do you have concrete use cases in mind where two qubit registers with the same name and different lengths are measured with the same key?

In either case, we should also consider adding documentation about the expected behavior where appropriate.

p51lee commented 5 months ago

Thank you for following up. The issue occurs even when using qubits with different names:

qubits_1 = [cirq.NamedQubit("p")]
qubits_2 = [cirq.NamedQubit("q"), cirq.NamedQubit("r")]
circuit = cirq.Circuit(
    cirq.measure(qubits_1, key='c'),
    cirq.measure(qubits_2, key='c'),
)
print(circuit.to_qasm())

For a use case, I considered circuits with classically conditioned gates. However, since Cirq doesn’t support conditional QASM output, an exception for measurements with different sizes but the same key seems appropriate. This would prevent confusion and incorrect QASM translations.