Skip to content

Commit 0993b36

Browse files
authored
Add assert_decompose_ends_at_default_gateset to consistent protocols test to ensure all cirq gates decompose to default gateset (quantumlib#5107)
1 parent 5ade5ef commit 0993b36

File tree

5 files changed

+29
-11
lines changed

5 files changed

+29
-11
lines changed

cirq/ops/dense_pauli_string_test.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,11 @@ def test_protocols():
376376
cirq.testing.assert_implements_consistent_protocols(-cirq.DensePauliString('Z'))
377377
cirq.testing.assert_implements_consistent_protocols(1j * cirq.DensePauliString('X'))
378378
cirq.testing.assert_implements_consistent_protocols(2 * cirq.DensePauliString('X'))
379-
cirq.testing.assert_implements_consistent_protocols(t * cirq.DensePauliString('XYIZ'))
380379
cirq.testing.assert_implements_consistent_protocols(
381-
cirq.DensePauliString('XYIZ', coefficient=t + 2)
380+
t * cirq.DensePauliString('XYIZ'), ignore_decompose_to_default_gateset=True
381+
)
382+
cirq.testing.assert_implements_consistent_protocols(
383+
cirq.DensePauliString('XYIZ', coefficient=t + 2), ignore_decompose_to_default_gateset=True
382384
)
383385
cirq.testing.assert_implements_consistent_protocols(-cirq.DensePauliString('XYIZ'))
384386
cirq.testing.assert_implements_consistent_protocols(

cirq/ops/random_gate_channel_test.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,20 @@ def test_eq():
8080

8181
def test_consistent_protocols():
8282
cirq.testing.assert_implements_consistent_protocols(
83-
cirq.RandomGateChannel(sub_gate=cirq.X, probability=1)
83+
cirq.RandomGateChannel(sub_gate=cirq.X, probability=1),
84+
ignore_decompose_to_default_gateset=True,
8485
)
8586
cirq.testing.assert_implements_consistent_protocols(
86-
cirq.RandomGateChannel(sub_gate=cirq.X, probability=0)
87+
cirq.RandomGateChannel(sub_gate=cirq.X, probability=0),
88+
ignore_decompose_to_default_gateset=True,
8789
)
8890
cirq.testing.assert_implements_consistent_protocols(
89-
cirq.RandomGateChannel(sub_gate=cirq.X, probability=sympy.Symbol('x') / 2)
91+
cirq.RandomGateChannel(sub_gate=cirq.X, probability=sympy.Symbol('x') / 2),
92+
ignore_decompose_to_default_gateset=True,
9093
)
9194
cirq.testing.assert_implements_consistent_protocols(
92-
cirq.RandomGateChannel(sub_gate=cirq.X, probability=0.5)
95+
cirq.RandomGateChannel(sub_gate=cirq.X, probability=0.5),
96+
ignore_decompose_to_default_gateset=True,
9397
)
9498

9599

cirq/testing/consistent_decomposition.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ def _known_gate_with_no_decomposition(val: Any):
5353
"""Checks whether `val` is a known gate with no default decomposition to default gateset."""
5454
if isinstance(val, ops.MatrixGate):
5555
return protocols.qid_shape(val) not in [(2,), (2,) * 2, (2,) * 3]
56+
if isinstance(val, ops.BaseDensePauliString) and not protocols.has_unitary(val):
57+
return True
5658
if isinstance(val, ops.ControlledGate):
5759
if protocols.is_parameterized(val):
5860
return True

cirq/testing/consistent_protocols.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
)
2727
from cirq.testing.consistent_decomposition import (
2828
assert_decompose_is_consistent_with_unitary,
29+
assert_decompose_ends_at_default_gateset,
2930
)
3031
from cirq.testing.consistent_phase_by import (
3132
assert_phase_by_is_consistent_with_unitary,
@@ -55,6 +56,7 @@ def assert_implements_consistent_protocols(
5556
setup_code: str = 'import cirq\nimport numpy as np\nimport sympy',
5657
global_vals: Optional[Dict[str, Any]] = None,
5758
local_vals: Optional[Dict[str, Any]] = None,
59+
ignore_decompose_to_default_gateset: bool = False,
5860
) -> None:
5961
"""Checks that a value is internally consistent and has a good __repr__."""
6062
global_vals = global_vals or {}
@@ -66,6 +68,7 @@ def assert_implements_consistent_protocols(
6668
setup_code=setup_code,
6769
global_vals=global_vals,
6870
local_vals=local_vals,
71+
ignore_decompose_to_default_gateset=ignore_decompose_to_default_gateset,
6972
)
7073

7174
for exponent in exponents:
@@ -77,6 +80,7 @@ def assert_implements_consistent_protocols(
7780
setup_code=setup_code,
7881
global_vals=global_vals,
7982
local_vals=local_vals,
83+
ignore_decompose_to_default_gateset=ignore_decompose_to_default_gateset,
8084
)
8185

8286

@@ -90,6 +94,7 @@ def assert_eigengate_implements_consistent_protocols(
9094
setup_code: str = 'import cirq\nimport numpy as np\nimport sympy',
9195
global_vals: Optional[Dict[str, Any]] = None,
9296
local_vals: Optional[Dict[str, Any]] = None,
97+
ignore_decompose_to_default_gateset: bool = False,
9398
) -> None:
9499
"""Checks that an EigenGate subclass is internally consistent and has a
95100
good __repr__."""
@@ -105,6 +110,7 @@ def assert_eigengate_implements_consistent_protocols(
105110
setup_code=setup_code,
106111
global_vals=global_vals,
107112
local_vals=local_vals,
113+
ignore_decompose_to_default_gateset=ignore_decompose_to_default_gateset,
108114
)
109115

110116

@@ -143,6 +149,7 @@ def _assert_meets_standards_helper(
143149
setup_code: str,
144150
global_vals: Optional[Dict[str, Any]],
145151
local_vals: Optional[Dict[str, Any]],
152+
ignore_decompose_to_default_gateset: bool,
146153
) -> None:
147154
__tracebackhide__ = True # pylint: disable=unused-variable
148155

@@ -154,6 +161,8 @@ def _assert_meets_standards_helper(
154161
assert_qasm_is_consistent_with_unitary(val)
155162
assert_has_consistent_trace_distance_bound(val)
156163
assert_decompose_is_consistent_with_unitary(val, ignoring_global_phase=ignoring_global_phase)
164+
if not ignore_decompose_to_default_gateset:
165+
assert_decompose_ends_at_default_gateset(val)
157166
assert_phase_by_is_consistent_with_unitary(val)
158167
assert_pauli_expansion_is_consistent_with_unitary(val)
159168
assert_equivalent_repr(

cirq/testing/consistent_protocols_test.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
6565
q = qubits[0]
6666
z = cirq.Z(q) ** self.phase_exponent
6767
x = cirq.X(q) ** self.exponent
68-
if cirq.is_parameterized(z):
69-
# coverage: ignore
70-
return NotImplemented
7168
return z ** -1, x, z
7269

7370
def _pauli_expansion_(self) -> cirq.LinearDict[str]:
@@ -260,12 +257,16 @@ def test_assert_implements_consistent_protocols():
260257

261258
def test_assert_eigengate_implements_consistent_protocols():
262259
cirq.testing.assert_eigengate_implements_consistent_protocols(
263-
GoodEigenGate, global_vals={'GoodEigenGate': GoodEigenGate}
260+
GoodEigenGate,
261+
global_vals={'GoodEigenGate': GoodEigenGate},
262+
ignore_decompose_to_default_gateset=True,
264263
)
265264

266265
with pytest.raises(AssertionError):
267266
cirq.testing.assert_eigengate_implements_consistent_protocols(
268-
BadEigenGate, global_vals={'BadEigenGate': BadEigenGate}
267+
BadEigenGate,
268+
global_vals={'BadEigenGate': BadEigenGate},
269+
ignore_decompose_to_default_gateset=True,
269270
)
270271

271272

0 commit comments

Comments
 (0)