quantumlib / Cirq

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

`synchronize_terminal_measurements()` misorders measurements with the same key #6329

Open richrines1 opened 10 months ago

richrines1 commented 10 months ago

Description of the issue

(not 100% sure this isn't intended behavior)

when two measurements have the same key, reordering them results in a logically different circuit. Transformers like align_left() and align_right() correctly account for this by preventing the reordering of measurements with the same key, but synchronize_terminal_measurements() does not (see below)

How to reproduce the issue

circuit = cirq.Circuit(
    cirq.X(cirq.q(1)),
    cirq.measure(cirq.q(0), key="key1"),
    cirq.measure(cirq.q(1), key="key1"),
    cirq.measure(cirq.q(1), key="key2"),
)

print(circuit)
print(cirq.align_right(circuit))  # no change, as it would require reordering the two measurements with `key="key1"`
print(cirq.synchronize_terminal_measurements(circuit))

prints:

0: ───M('key1')───────────────────────────

1: ───X───────────M('key1')───M('key2')───
0: ───M('key1')───────────────────────────

1: ───X───────────M('key1')───M('key2')───
0: ───────────────────M('key1')───

1: ───X───M('key1')───M('key2')───

where the final circuit is not logically equivalent (the expected measurement outcome for "key1" is flipped)

Cirq version

1.3.0.dev20230830191034
tanujkhattar commented 9 months ago

@richrines1 This is a subtle issue, thanks for raising this! Do you have a real world scenario where this becomes a problem?

Specifically, in Cirq we do not have explicit wires corresponding to classical measurement results. So two operations op1 and op2 have an ordering dependency b/w each other if (a) they either share a qubit (i.e. a quantum wire) or (b) op2 is a classically controlled operation controlled on measurement outcome of op1 (i.e. a hacky version of a classical wire).

In this case, we've run into the scenario where both op1 and op2 are both independent measurement operations but they overwrite their results to the same classical register named "key1". And we don't add an (implicit) edge dependency b/w these two operations by design right now. Whether we should start doing that is a feature request that we can consider but I'm curious to know more about the use case where this came up.

@mpharrigan If we were to do support this use case in Qualtran, I'd imagine the measurement gate would have a RIGHT register for measurement outcome and not a THRU register. In that case as well, op1 and op2 would not have an edge in the explicit compute graph. However, if measurement gates end up having THRU registers for classical outputs, then op1 and op2 would have an explicit edge b/w them. This subtlety is worth keeping in mind when designing for adding support for classical registers in Qualtran.

richrines1 commented 8 months ago

thanks for the response @tanujkhattar! admittedly this came up as a corner case in a test, for which i don't really have a (non-contrived) application. so definitely not a blocking issue

mostly i was surprised by the inconsistency between align_right and synchronize_terminal_measurements:

(but probably in any realistic application i'd just make sure the keys weren't the same, so afaict this isn't likely to ever be an issue in practice)

github-actions[bot] commented 7 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days

github-actions[bot] commented 5 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days

github-actions[bot] commented 4 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days

github-actions[bot] commented 3 months ago

Issue closed due to inactivity.

github-actions[bot] commented 2 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days

github-actions[bot] commented 1 month ago

Issue closed due to inactivity.

github-actions[bot] commented 2 weeks ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days