Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix order preservation in align_right #6899

Merged
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