Skip to content

Commit

Permalink
Fix order preservation in align_right
Browse files Browse the repository at this point in the history
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 committed Dec 30, 2024
1 parent 686766f commit 8ed9e80
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
10 changes: 9 additions & 1 deletion cirq-core/cirq/transformers/align.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""Transformer passes which align operations to the left or right of the circuit."""

import dataclasses
from locale import currency
from typing import Optional, TYPE_CHECKING
from cirq import circuits, ops
from cirq.transformers import transformer_api
Expand Down Expand Up @@ -73,4 +74,11 @@ 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]
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 8ed9e80

Please sign in to comment.