Skip to content

Commit

Permalink
Fix order preservation in align_right (#6899)
Browse files Browse the repository at this point in the history
* Fix order preservation in align_right

Order was not preserved for non-commutable measurements and controls in the same moment. Reversing the circuit's moments did not reverse the ops within those moments. The subsequent `align_left` could split those ops into separate moments. Then reversing the moments again would have the end result of reversing the order of those operations in the final circuit.

This PR makes sure to reverse the order of ops within the moment prior to the call to `align_left`.
  • Loading branch information
daxfohl authored Jan 15, 2025
1 parent ede4124 commit 0b796d1
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
12 changes: 11 additions & 1 deletion cirq-core/cirq/transformers/align.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,14 @@ def align_right(
"""
if context is not None and context.deep is True:
context = dataclasses.replace(context, deep=False)
return align_left(circuit[::-1], context=context)[::-1]
# Reverse the circuit, align left, and reverse again. Note each moment also has to have its ops
# reversed internally, to avoid edge conditions where non-commuting but can-be-in-same-moment
# ops (measurements and classical controls, particularly) could end up getting swapped.
backwards = []
for moment in circuit[::-1]:
backwards.append(circuits.Moment(reversed(moment.operations)))
aligned_backwards = align_left(circuits.Circuit(backwards), context=context)
forwards = []
for moment in aligned_backwards[::-1]:
forwards.append(circuits.Moment(reversed(moment.operations)))
return circuits.Circuit(forwards)
13 changes: 13 additions & 0 deletions cirq-core/cirq/transformers/align_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,16 @@ def test_classical_control():
)
cirq.testing.assert_same_circuits(cirq.align_left(circuit), circuit)
cirq.testing.assert_same_circuits(cirq.align_right(circuit), circuit)


def test_measurement_and_classical_control_same_moment_preserve_order():
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit()
op_measure = cirq.measure(q0, key='m')
op_controlled = cirq.X(q1).with_classical_controls('m')
circuit.append(op_measure)
circuit.append(op_controlled, cirq.InsertStrategy.INLINE)
circuit = cirq.align_right(circuit)
ops_in_order = list(circuit.all_operations())
assert ops_in_order[0] == op_measure
assert ops_in_order[1] == op_controlled

0 comments on commit 0b796d1

Please sign in to comment.