Skip to content

Commit 0b796d1

Browse files
authored
Fix order preservation in align_right (#6899)
* 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`.
1 parent ede4124 commit 0b796d1

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

cirq-core/cirq/transformers/align.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,14 @@ def align_right(
7373
"""
7474
if context is not None and context.deep is True:
7575
context = dataclasses.replace(context, deep=False)
76-
return align_left(circuit[::-1], context=context)[::-1]
76+
# Reverse the circuit, align left, and reverse again. Note each moment also has to have its ops
77+
# reversed internally, to avoid edge conditions where non-commuting but can-be-in-same-moment
78+
# ops (measurements and classical controls, particularly) could end up getting swapped.
79+
backwards = []
80+
for moment in circuit[::-1]:
81+
backwards.append(circuits.Moment(reversed(moment.operations)))
82+
aligned_backwards = align_left(circuits.Circuit(backwards), context=context)
83+
forwards = []
84+
for moment in aligned_backwards[::-1]:
85+
forwards.append(circuits.Moment(reversed(moment.operations)))
86+
return circuits.Circuit(forwards)

cirq-core/cirq/transformers/align_test.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,16 @@ def test_classical_control():
208208
)
209209
cirq.testing.assert_same_circuits(cirq.align_left(circuit), circuit)
210210
cirq.testing.assert_same_circuits(cirq.align_right(circuit), circuit)
211+
212+
213+
def test_measurement_and_classical_control_same_moment_preserve_order():
214+
q0, q1 = cirq.LineQubit.range(2)
215+
circuit = cirq.Circuit()
216+
op_measure = cirq.measure(q0, key='m')
217+
op_controlled = cirq.X(q1).with_classical_controls('m')
218+
circuit.append(op_measure)
219+
circuit.append(op_controlled, cirq.InsertStrategy.INLINE)
220+
circuit = cirq.align_right(circuit)
221+
ops_in_order = list(circuit.all_operations())
222+
assert ops_in_order[0] == op_measure
223+
assert ops_in_order[1] == op_controlled

0 commit comments

Comments
 (0)