Skip to content

Commit a839837

Browse files
authored
Change merge_single_qubit_moments_to_phxz to support global phase. (#7405)
This addresses an issue I found while working on #7291 Currently `merge_single_qubit_moments_to_phxz` will not merge moments that have a global phase, meaning that moments that could theoretically be merged are not. I updated it so that global phase is also supported. I added two tests to show the issue. Perhaps this situation is not common right now, but if #7383 is committed and the flag is used, it may become more common. @daxfohl Note that I'm not merging the global phase operations in a single one, because I'm thinking some phases could be parametrized; should I attempt to do this?
1 parent be1b527 commit a839837

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

cirq-core/cirq/transformers/merge_single_qubit_gates.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def merge_single_qubit_moments_to_phxz(
118118

119119
def can_merge_moment(m: cirq.Moment):
120120
return all(
121-
protocols.num_qubits(op) == 1
121+
protocols.num_qubits(op) <= 1
122122
and protocols.has_unitary(op)
123123
and tags_to_ignore.isdisjoint(op.tags)
124124
for op in m
@@ -146,6 +146,10 @@ def merge_func(m1: cirq.Moment, m2: cirq.Moment) -> cirq.Moment | None:
146146
)
147147
if gate:
148148
ret_ops.append(gate(q))
149+
# Transfer global phase
150+
for op in m1.operations + m2.operations:
151+
if protocols.num_qubits(op) == 0:
152+
ret_ops.append(op)
149153
return circuits.Moment(ret_ops)
150154

151155
return transformer_primitives.merge_moments(

cirq-core/cirq/transformers/merge_single_qubit_gates_test.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,35 @@ def test_merge_single_qubit_gates_to_phased_x_and_z_global_phase():
231231
c = cirq.Circuit(cirq.GlobalPhaseGate(1j).on())
232232
c2 = cirq.merge_single_qubit_gates_to_phased_x_and_z(c)
233233
assert c == c2
234+
235+
236+
def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_first_moment():
237+
q0 = cirq.LineQubit(0)
238+
c_orig = cirq.Circuit(
239+
cirq.Moment(cirq.Y(q0) ** 0.5, cirq.GlobalPhaseGate(1j**0.5).on()), cirq.Moment(cirq.X(q0))
240+
)
241+
c_expected = cirq.Circuit(
242+
cirq.Moment(
243+
cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=-1.0).on(q0),
244+
cirq.GlobalPhaseGate(1j**0.5).on(),
245+
)
246+
)
247+
context = cirq.TransformerContext(tags_to_ignore=["ignore"])
248+
c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context)
249+
assert c_new == c_expected
250+
251+
252+
def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_second_moment():
253+
q0 = cirq.LineQubit(0)
254+
c_orig = cirq.Circuit(
255+
cirq.Moment(cirq.Y(q0) ** 0.5), cirq.Moment(cirq.X(q0), cirq.GlobalPhaseGate(1j**0.5).on())
256+
)
257+
c_expected = cirq.Circuit(
258+
cirq.Moment(
259+
cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=-1.0).on(q0),
260+
cirq.GlobalPhaseGate(1j**0.5).on(),
261+
)
262+
)
263+
context = cirq.TransformerContext(tags_to_ignore=["ignore"])
264+
c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context)
265+
assert c_new == c_expected

0 commit comments

Comments
 (0)