Skip to content

Commit 284c3e6

Browse files
authored
Support decomposition of parameterized gates in cirq.PhasedXPowGate (quantumlib#5083)
- Adds support for decomposing parameterized `cirq.PhasedXPowGate`s. - Also modifies the decomposition to respect global phase, so that the decomposition is valid for controlled variants as well. - Part of quantumlib#4858
1 parent fc35a4f commit 284c3e6

File tree

2 files changed

+24
-19
lines changed

2 files changed

+24
-19
lines changed

cirq/ops/phased_x_gate.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
8080
assert len(qubits) == 1
8181
q = qubits[0]
8282
z = cirq.Z(q) ** self._phase_exponent
83-
x = cirq.X(q) ** self._exponent
84-
if protocols.is_parameterized(z):
85-
return NotImplemented
83+
x = cirq.XPowGate(exponent=self._exponent, global_shift=self.global_shift).on(q)
8684
return z ** -1, x, z
8785

8886
@property

cirq/ops/phased_x_gate_test.py

+23-16
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,11 @@
3535
],
3636
)
3737
def test_phased_x_consistent_protocols(phase_exponent):
38-
# If there is no global_shift, the gate is global phase insensitive.
3938
cirq.testing.assert_implements_consistent_protocols(
4039
cirq.PhasedXPowGate(phase_exponent=phase_exponent, exponent=1.0),
41-
ignoring_global_phase=False,
4240
)
4341
cirq.testing.assert_implements_consistent_protocols(
4442
cirq.PhasedXPowGate(phase_exponent=phase_exponent, exponent=1.0, global_shift=0.1),
45-
ignoring_global_phase=True,
4643
)
4744

4845

@@ -171,26 +168,36 @@ def test_str_repr():
171168
)
172169

173170

174-
@pytest.mark.parametrize('resolve_fn', [cirq.resolve_parameters, cirq.resolve_parameters_once])
175-
def test_parameterize(resolve_fn):
171+
@pytest.mark.parametrize(
172+
'resolve_fn, global_shift', [(cirq.resolve_parameters, 0), (cirq.resolve_parameters_once, 0.1)]
173+
)
174+
def test_parameterize(resolve_fn, global_shift):
176175
parameterized_gate = cirq.PhasedXPowGate(
177-
exponent=sympy.Symbol('a'), phase_exponent=sympy.Symbol('b')
176+
exponent=sympy.Symbol('a'), phase_exponent=sympy.Symbol('b'), global_shift=global_shift
178177
)
179178
assert cirq.pow(parameterized_gate, 5) == cirq.PhasedXPowGate(
180-
exponent=sympy.Symbol('a') * 5, phase_exponent=sympy.Symbol('b')
181-
)
182-
assert (
183-
cirq.decompose_once_with_qubits(parameterized_gate, [cirq.LineQubit(0)], NotImplemented)
184-
is NotImplemented
179+
exponent=sympy.Symbol('a') * 5, phase_exponent=sympy.Symbol('b'), global_shift=global_shift
185180
)
186181
assert cirq.unitary(parameterized_gate, default=None) is None
187182
assert cirq.is_parameterized(parameterized_gate)
183+
q = cirq.NamedQubit("q")
184+
parameterized_decomposed_circuit = cirq.Circuit(cirq.decompose(parameterized_gate(q)))
185+
for resolver in cirq.Linspace('a', 0, 2, 10) * cirq.Linspace('b', 0, 2, 10):
186+
resolved_gate = resolve_fn(parameterized_gate, resolver)
187+
assert resolved_gate == cirq.PhasedXPowGate(
188+
exponent=resolver.value_of('a'),
189+
phase_exponent=resolver.value_of('b'),
190+
global_shift=global_shift,
191+
)
192+
np.testing.assert_allclose(
193+
cirq.unitary(resolved_gate(q)),
194+
cirq.unitary(resolve_fn(parameterized_decomposed_circuit, resolver)),
195+
atol=1e-8,
196+
)
188197

189-
resolver = cirq.ParamResolver({'a': 0.1, 'b': 0.2})
190-
resolved_gate = resolve_fn(parameterized_gate, resolver)
191-
assert resolved_gate == cirq.PhasedXPowGate(exponent=0.1, phase_exponent=0.2)
192-
193-
unparameterized_gate = cirq.PhasedXPowGate(exponent=0.1, phase_exponent=0.2)
198+
unparameterized_gate = cirq.PhasedXPowGate(
199+
exponent=0.1, phase_exponent=0.2, global_shift=global_shift
200+
)
194201
assert not cirq.is_parameterized(unparameterized_gate)
195202
assert cirq.is_parameterized(unparameterized_gate ** sympy.Symbol('a'))
196203
assert cirq.is_parameterized(unparameterized_gate ** (sympy.Symbol('a') + 1))

0 commit comments

Comments
 (0)