cirq-core 1.7.0.dev20251002223432__py3-none-any.whl → 1.7.0.dev20251007180852__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cirq-core might be problematic. Click here for more details.

Files changed (58) hide show
  1. cirq/_doc.py +4 -3
  2. cirq/_version.py +1 -1
  3. cirq/_version_test.py +1 -1
  4. cirq/linalg/decompositions.py +3 -0
  5. cirq/linalg/decompositions_test.py +1 -0
  6. cirq/ops/fourier_transform_test.py +2 -4
  7. cirq/ops/raw_types.py +3 -0
  8. cirq/protocols/apply_unitary_protocol_test.py +2 -0
  9. cirq/protocols/kraus_protocol.py +3 -3
  10. cirq/protocols/kraus_protocol_test.py +2 -2
  11. cirq/protocols/unitary_protocol.py +1 -1
  12. cirq/testing/consistent_resolve_parameters.py +1 -1
  13. cirq/testing/consistent_unitary.py +1 -1
  14. cirq/testing/consistent_unitary_test.py +1 -1
  15. cirq/testing/equals_tester.py +2 -2
  16. cirq/testing/equivalent_basis_map.py +3 -1
  17. cirq/testing/json.py +1 -1
  18. cirq/testing/op_tree.py +1 -1
  19. cirq/testing/order_tester.py +2 -2
  20. cirq/testing/repr_pretty_tester.py +3 -3
  21. cirq/transformers/align_test.py +13 -13
  22. cirq/transformers/analytical_decompositions/clifford_decomposition.py +8 -8
  23. cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +5 -5
  24. cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +11 -11
  25. cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +6 -6
  26. cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
  27. cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +10 -9
  28. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +5 -5
  29. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +17 -18
  30. cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +32 -26
  31. cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -1
  32. cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +12 -11
  33. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +3 -1
  34. cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +3 -3
  35. cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +2 -2
  36. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +32 -30
  37. cirq/transformers/drop_negligible_operations_test.py +7 -7
  38. cirq/transformers/dynamical_decoupling_test.py +22 -22
  39. cirq/transformers/eject_phased_paulis_test.py +1 -1
  40. cirq/transformers/eject_z.py +2 -2
  41. cirq/transformers/eject_z_test.py +23 -25
  42. cirq/transformers/expand_composite.py +1 -1
  43. cirq/transformers/expand_composite_test.py +14 -14
  44. cirq/transformers/gauge_compiling/gauge_compiling.py +1 -1
  45. cirq/transformers/gauge_compiling/gauge_compiling_test.py +14 -12
  46. cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +3 -3
  47. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +6 -6
  48. cirq/transformers/measurement_transformers_test.py +45 -39
  49. cirq/transformers/merge_k_qubit_gates_test.py +1 -1
  50. cirq/transformers/merge_single_qubit_gates_test.py +22 -22
  51. cirq/transformers/noise_adding_test.py +2 -2
  52. cirq/transformers/optimize_for_target_gateset_test.py +11 -9
  53. cirq/transformers/qubit_management_transformers_test.py +6 -2
  54. {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251007180852.dist-info}/METADATA +1 -1
  55. {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251007180852.dist-info}/RECORD +58 -58
  56. {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251007180852.dist-info}/WHEEL +0 -0
  57. {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251007180852.dist-info}/licenses/LICENSE +0 -0
  58. {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251007180852.dist-info}/top_level.txt +0 -0
cirq/_doc.py CHANGED
@@ -15,12 +15,13 @@
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
- from typing import Any
18
+ from typing import TypeVar
19
19
 
20
+ T = TypeVar('T')
20
21
  RECORDED_CONST_DOCS: dict[int, str] = {}
21
22
 
22
23
 
23
- def document(value: Any, doc_string: str = ''):
24
+ def document(value: T, doc_string: str = '') -> T:
24
25
  """Stores documentation details about the given value.
25
26
 
26
27
  This method is used to associate a docstring with global constants. It is
@@ -64,7 +65,7 @@ def document(value: Any, doc_string: str = ''):
64
65
  _DOC_PRIVATE = "_tf_docs_doc_private"
65
66
 
66
67
 
67
- def doc_private(obj):
68
+ def doc_private(obj: T) -> T:
68
69
  """A decorator: Generates docs for private methods/functions.
69
70
 
70
71
  For example:
cirq/_version.py CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 11, 0): # pragma: no cover
28
28
  'of Cirq (e.g. "python -m pip install cirq==1.5.0")'
29
29
  )
30
30
 
31
- __version__ = "1.7.0.dev20251002223432"
31
+ __version__ = "1.7.0.dev20251007180852"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version() -> None:
6
- assert cirq.__version__ == "1.7.0.dev20251002223432"
6
+ assert cirq.__version__ == "1.7.0.dev20251007180852"
@@ -472,6 +472,9 @@ class KakDecomposition:
472
472
  f' global_phase={self.global_phase!r})'
473
473
  )
474
474
 
475
+ def _has_unitary_(self) -> bool:
476
+ return True
477
+
475
478
  def _unitary_(self) -> np.ndarray:
476
479
  """Returns the decomposition's two-qubit unitary matrix.
477
480
 
@@ -259,6 +259,7 @@ def test_kak_plot_empty() -> None:
259
259
  )
260
260
  def test_kak_decomposition(target) -> None:
261
261
  kak = cirq.kak_decomposition(target)
262
+ assert cirq.has_unitary(kak)
262
263
  np.testing.assert_allclose(cirq.unitary(kak), target, atol=1e-8)
263
264
 
264
265
 
@@ -107,9 +107,7 @@ def test_qft() -> None:
107
107
 
108
108
  arr = np.array([[1, 1, 1, 1], [1, -1j, -1, 1j], [1, -1, 1, -1], [1, 1j, -1, -1j]]) / 2
109
109
  np.testing.assert_allclose(
110
- cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1), # type: ignore[operator]
111
- arr, # type: ignore[arg-type]
112
- atol=1e-8,
110
+ cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1), arr, atol=1e-8
113
111
  )
114
112
 
115
113
  for k in range(4):
@@ -121,7 +119,7 @@ def test_qft() -> None:
121
119
 
122
120
  def test_inverse() -> None:
123
121
  a, b, c = cirq.LineQubit.range(3)
124
- assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c) ** -1 # type: ignore[operator]
122
+ assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c) ** -1
125
123
  assert cirq.qft(a, b, c, inverse=True, without_reverse=True) == cirq.inverse(
126
124
  cirq.qft(a, b, c, without_reverse=True)
127
125
  )
cirq/ops/raw_types.py CHANGED
@@ -528,6 +528,9 @@ class Operation(metaclass=abc.ABCMeta):
528
528
  def _qid_shape_(self) -> tuple[int, ...]:
529
529
  return protocols.qid_shape(self.qubits)
530
530
 
531
+ def __pow__(self, exponent: Any) -> Operation:
532
+ return NotImplemented # pragma: no cover
533
+
531
534
  @abc.abstractmethod
532
535
  def with_qubits(self, *new_qubits: cirq.Qid) -> cirq.Operation:
533
536
  """Returns the same operation, but applied to different qubits.
@@ -240,6 +240,7 @@ def test_apply_unitary_args_tensor_manipulation() -> None:
240
240
  op_indices, tuple(qid_shape[i] for i in op_indices)
241
241
  )
242
242
  sub_result = val._apply_unitary_(sub_args)
243
+ assert isinstance(sub_result, np.ndarray)
243
244
  result = _incorporate_result_into_target(args, sub_args, sub_result)
244
245
  np.testing.assert_allclose(result, expected, atol=1e-8)
245
246
 
@@ -258,6 +259,7 @@ def test_apply_unitary_args_tensor_manipulation() -> None:
258
259
  op_indices, tuple(qid_shape[i] for i in op_indices)
259
260
  )
260
261
  sub_result = val._apply_unitary_(sub_args)
262
+ assert isinstance(sub_result, np.ndarray)
261
263
  result = _incorporate_result_into_target(args, sub_args, sub_result)
262
264
  np.testing.assert_allclose(result, expected, atol=1e-8, verbose=True)
263
265
 
@@ -18,7 +18,7 @@ from __future__ import annotations
18
18
 
19
19
  import warnings
20
20
  from types import NotImplementedType
21
- from typing import Any, Protocol, Sequence, TypeVar
21
+ from typing import Any, Iterable, Protocol, TypeVar
22
22
 
23
23
  import numpy as np
24
24
 
@@ -31,7 +31,7 @@ from cirq.protocols.unitary_protocol import unitary
31
31
 
32
32
  # This is a special indicator value used by the channel method to determine
33
33
  # whether or not the caller provided a 'default' argument. It must be of type
34
- # Sequence[np.ndarray] to ensure the method has the correct type signature in
34
+ # Iterable[np.ndarray] to ensure the method has the correct type signature in
35
35
  # that case. It is checked for using `is`, so it won't have a false positive
36
36
  # if the user provides a different (np.array([]),) value.
37
37
  RaiseTypeErrorIfNotProvided: tuple[np.ndarray] = (np.array([]),)
@@ -44,7 +44,7 @@ class SupportsKraus(Protocol):
44
44
  """An object that may be describable as a quantum channel."""
45
45
 
46
46
  @doc_private
47
- def _kraus_(self) -> Sequence[np.ndarray] | NotImplementedType:
47
+ def _kraus_(self) -> Iterable[np.ndarray] | NotImplementedType:
48
48
  r"""A list of Kraus matrices describing the quantum channel.
49
49
 
50
50
  These matrices are the terms in the operator sum representation of a
@@ -16,7 +16,7 @@
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- from typing import Iterable, Sequence
19
+ from typing import Iterable
20
20
 
21
21
  import numpy as np
22
22
  import pytest
@@ -89,7 +89,7 @@ def test_explicit_kraus() -> None:
89
89
  c = (a0, a1)
90
90
 
91
91
  class ReturnsKraus:
92
- def _kraus_(self) -> Sequence[np.ndarray]:
92
+ def _kraus_(self) -> Iterable[np.ndarray]:
93
93
  return c
94
94
 
95
95
  assert cirq.kraus(ReturnsKraus()) is c
@@ -38,7 +38,7 @@ class SupportsUnitary(Protocol):
38
38
  """An object that may be describable by a unitary matrix."""
39
39
 
40
40
  @doc_private
41
- def _unitary_(self) -> np.ndarray | NotImplementedType:
41
+ def _unitary_(self) -> np.ndarray | NotImplementedType | None:
42
42
  """A unitary matrix describing this value, e.g. the matrix of a gate.
43
43
 
44
44
  This method is used by the global `cirq.unitary` method. If this method
@@ -21,7 +21,7 @@ import sympy
21
21
  import cirq
22
22
 
23
23
 
24
- def assert_consistent_resolve_parameters(val: Any):
24
+ def assert_consistent_resolve_parameters(val: Any) -> None:
25
25
  names = cirq.parameter_names(val)
26
26
  symbols = cirq.parameter_symbols(val)
27
27
 
@@ -21,7 +21,7 @@ import numpy as np
21
21
  import cirq
22
22
 
23
23
 
24
- def assert_unitary_is_consistent(val: Any, ignoring_global_phase: bool = False):
24
+ def assert_unitary_is_consistent(val: Any, ignoring_global_phase: bool = False) -> None:
25
25
  if not isinstance(val, (cirq.Operation, cirq.Gate)):
26
26
  return
27
27
 
@@ -95,4 +95,4 @@ def test_failed_decomposition() -> None:
95
95
  with pytest.raises(ValueError):
96
96
  cirq.testing.assert_unitary_is_consistent(FailsOnDecompostion())
97
97
 
98
- _ = cirq.testing.assert_unitary_is_consistent(cirq.Circuit())
98
+ cirq.testing.assert_unitary_is_consistent(cirq.Circuit())
@@ -93,7 +93,7 @@ class EqualsTester:
93
93
  "Common problem: returning NotImplementedError instead of NotImplemented. "
94
94
  )
95
95
 
96
- def add_equality_group(self, *group_items: Any):
96
+ def add_equality_group(self, *group_items: Any) -> None:
97
97
  """Tries to add a disjoint equivalence group to the equality tester.
98
98
 
99
99
  This methods asserts that items within the group must all be equal to
@@ -114,7 +114,7 @@ class EqualsTester:
114
114
  # Remember this group, to enable disjoint checks vs later groups.
115
115
  self._groups.append(group_items)
116
116
 
117
- def make_equality_group(self, *factories: Callable[[], Any]):
117
+ def make_equality_group(self, *factories: Callable[[], Any]) -> None:
118
118
  """Tries to add a disjoint equivalence group to the equality tester.
119
119
 
120
120
  Uses the factory methods to produce two different objects with the same
@@ -22,7 +22,9 @@ import cirq
22
22
  from cirq import circuits
23
23
 
24
24
 
25
- def assert_equivalent_computational_basis_map(maps: dict[int, int], circuit: circuits.Circuit):
25
+ def assert_equivalent_computational_basis_map(
26
+ maps: dict[int, int], circuit: circuits.Circuit
27
+ ) -> None:
26
28
  """Ensure equivalence of basis state mapping.
27
29
 
28
30
  Args:
cirq/testing/json.py CHANGED
@@ -149,7 +149,7 @@ def spec_for(module_name: str) -> ModuleJsonTestSpec:
149
149
  return getattr(test_module, "TestSpec")
150
150
 
151
151
 
152
- def assert_json_roundtrip_works(obj, text_should_be=None, resolvers=None):
152
+ def assert_json_roundtrip_works(obj, text_should_be=None, resolvers=None) -> None:
153
153
  """Tests that the given object can serialized and de-serialized
154
154
 
155
155
  Args:
cirq/testing/op_tree.py CHANGED
@@ -17,7 +17,7 @@ from __future__ import annotations
17
17
  from cirq import ops
18
18
 
19
19
 
20
- def assert_equivalent_op_tree(x: ops.OP_TREE, y: ops.OP_TREE):
20
+ def assert_equivalent_op_tree(x: ops.OP_TREE, y: ops.OP_TREE) -> None:
21
21
  """Ensures that the two OP_TREEs are equivalent.
22
22
 
23
23
  Args:
@@ -78,7 +78,7 @@ class OrderTester:
78
78
  f"That rule is being violated by this value: {item!r}"
79
79
  ) from ex
80
80
 
81
- def add_ascending(self, *items: Any):
81
+ def add_ascending(self, *items: Any) -> None:
82
82
  """Tries to add a sequence of ascending items to the order tester.
83
83
 
84
84
  This methods asserts that items must all be ascending
@@ -98,7 +98,7 @@ class OrderTester:
98
98
  for item in items:
99
99
  self.add_ascending_equivalence_group(item)
100
100
 
101
- def add_ascending_equivalence_group(self, *group_items: Any):
101
+ def add_ascending_equivalence_group(self, *group_items: Any) -> None:
102
102
  """Tries to add an ascending equivalence group to the order tester.
103
103
 
104
104
  Asserts that the group items are equal to each other, but strictly
@@ -34,11 +34,11 @@ class FakePrinter:
34
34
  def __init__(self):
35
35
  self.text_pretty = ""
36
36
 
37
- def text(self, to_print):
37
+ def text(self, to_print) -> None:
38
38
  self.text_pretty += to_print
39
39
 
40
40
 
41
- def assert_repr_pretty(val: Any, text: str, cycle: bool = False):
41
+ def assert_repr_pretty(val: Any, text: str, cycle: bool = False) -> None:
42
42
  """Assert that the given object has a `_repr_pretty_` method that produces the given text.
43
43
 
44
44
  Args:
@@ -57,7 +57,7 @@ def assert_repr_pretty(val: Any, text: str, cycle: bool = False):
57
57
  assert p.text_pretty == text, f"{p.text_pretty} != {text}"
58
58
 
59
59
 
60
- def assert_repr_pretty_contains(val: Any, substr: str, cycle: bool = False):
60
+ def assert_repr_pretty_contains(val: Any, substr: str, cycle: bool = False) -> None:
61
61
  """Assert that the given object has a `_repr_pretty_` output that contains the given text.
62
62
 
63
63
  Args:
@@ -17,7 +17,7 @@ from __future__ import annotations
17
17
  import cirq
18
18
 
19
19
 
20
- def test_align_basic_no_context():
20
+ def test_align_basic_no_context() -> None:
21
21
  q1 = cirq.NamedQubit('q1')
22
22
  q2 = cirq.NamedQubit('q2')
23
23
  c = cirq.Circuit(
@@ -45,7 +45,7 @@ def test_align_basic_no_context():
45
45
  )
46
46
 
47
47
 
48
- def test_align_left_no_compile_context():
48
+ def test_align_left_no_compile_context() -> None:
49
49
  q1 = cirq.NamedQubit('q1')
50
50
  q2 = cirq.NamedQubit('q2')
51
51
  cirq.testing.assert_same_circuits(
@@ -59,7 +59,7 @@ def test_align_left_no_compile_context():
59
59
  cirq.measure(*[q1, q2], key='a'),
60
60
  ]
61
61
  ),
62
- context=cirq.TransformerContext(tags_to_ignore=["nocompile"]),
62
+ context=cirq.TransformerContext(tags_to_ignore=("nocompile",)),
63
63
  ),
64
64
  cirq.Circuit(
65
65
  [
@@ -73,7 +73,7 @@ def test_align_left_no_compile_context():
73
73
  )
74
74
 
75
75
 
76
- def test_align_left_deep():
76
+ def test_align_left_deep() -> None:
77
77
  q1, q2 = cirq.LineQubit.range(2)
78
78
  c_nested = cirq.FrozenCircuit(
79
79
  [
@@ -104,11 +104,11 @@ def test_align_left_deep():
104
104
  c_nested_aligned,
105
105
  cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"),
106
106
  )
107
- context = cirq.TransformerContext(tags_to_ignore=["nocompile"], deep=True)
107
+ context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True)
108
108
  cirq.testing.assert_same_circuits(cirq.align_left(c_orig, context=context), c_expected)
109
109
 
110
110
 
111
- def test_align_left_subset_of_operations():
111
+ def test_align_left_subset_of_operations() -> None:
112
112
  q1 = cirq.NamedQubit('q1')
113
113
  q2 = cirq.NamedQubit('q2')
114
114
  tag = "op_to_align"
@@ -134,7 +134,7 @@ def test_align_left_subset_of_operations():
134
134
  cirq.toggle_tags(
135
135
  cirq.align_left(
136
136
  cirq.toggle_tags(c_orig, [tag]),
137
- context=cirq.TransformerContext(tags_to_ignore=[tag]),
137
+ context=cirq.TransformerContext(tags_to_ignore=(tag,)),
138
138
  ),
139
139
  [tag],
140
140
  ),
@@ -142,7 +142,7 @@ def test_align_left_subset_of_operations():
142
142
  )
143
143
 
144
144
 
145
- def test_align_right_no_compile_context():
145
+ def test_align_right_no_compile_context() -> None:
146
146
  q1 = cirq.NamedQubit('q1')
147
147
  q2 = cirq.NamedQubit('q2')
148
148
  cirq.testing.assert_same_circuits(
@@ -156,7 +156,7 @@ def test_align_right_no_compile_context():
156
156
  cirq.measure(*[q1, q2], key='a'),
157
157
  ]
158
158
  ),
159
- context=cirq.TransformerContext(tags_to_ignore=["nocompile"]),
159
+ context=cirq.TransformerContext(tags_to_ignore=("nocompile",)),
160
160
  ),
161
161
  cirq.Circuit(
162
162
  [
@@ -170,7 +170,7 @@ def test_align_right_no_compile_context():
170
170
  )
171
171
 
172
172
 
173
- def test_align_right_deep():
173
+ def test_align_right_deep() -> None:
174
174
  q1, q2 = cirq.LineQubit.range(2)
175
175
  c_nested = cirq.FrozenCircuit(
176
176
  cirq.Moment([cirq.X(q1)]),
@@ -199,11 +199,11 @@ def test_align_right_deep():
199
199
  c_nested_aligned,
200
200
  cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"),
201
201
  )
202
- context = cirq.TransformerContext(tags_to_ignore=["nocompile"], deep=True)
202
+ context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True)
203
203
  cirq.testing.assert_same_circuits(cirq.align_right(c_orig, context=context), c_expected)
204
204
 
205
205
 
206
- def test_classical_control():
206
+ def test_classical_control() -> None:
207
207
  q0, q1 = cirq.LineQubit.range(2)
208
208
  circuit = cirq.Circuit(
209
209
  cirq.H(q0), cirq.measure(q0, key='m'), cirq.X(q1).with_classical_controls('m')
@@ -212,7 +212,7 @@ def test_classical_control():
212
212
  cirq.testing.assert_same_circuits(cirq.align_right(circuit), circuit)
213
213
 
214
214
 
215
- def test_measurement_and_classical_control_same_moment_preserve_order():
215
+ def test_measurement_and_classical_control_same_moment_preserve_order() -> None:
216
216
  q0, q1 = cirq.LineQubit.range(2)
217
217
  circuit = cirq.Circuit()
218
218
  op_measure = cirq.measure(q0, key='m')
@@ -17,7 +17,7 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import functools
20
- from typing import TYPE_CHECKING
20
+ from typing import Sequence, TYPE_CHECKING
21
21
 
22
22
  import numpy as np
23
23
 
@@ -31,7 +31,7 @@ def _X(
31
31
  q: int,
32
32
  args: sim.CliffordTableauSimulationState,
33
33
  operations: list[ops.Operation],
34
- qubits: list[cirq.Qid],
34
+ qubits: Sequence[cirq.Qid],
35
35
  ):
36
36
  protocols.act_on(ops.X, args, qubits=[qubits[q]], allow_decompose=False)
37
37
  operations.append(ops.X(qubits[q]))
@@ -41,7 +41,7 @@ def _Z(
41
41
  q: int,
42
42
  args: sim.CliffordTableauSimulationState,
43
43
  operations: list[ops.Operation],
44
- qubits: list[cirq.Qid],
44
+ qubits: Sequence[cirq.Qid],
45
45
  ):
46
46
  protocols.act_on(ops.Z, args, qubits=[qubits[q]], allow_decompose=False)
47
47
  operations.append(ops.Z(qubits[q]))
@@ -51,7 +51,7 @@ def _Sdg(
51
51
  q: int,
52
52
  args: sim.CliffordTableauSimulationState,
53
53
  operations: list[ops.Operation],
54
- qubits: list[cirq.Qid],
54
+ qubits: Sequence[cirq.Qid],
55
55
  ):
56
56
  # Apply the tableau with S^\{dagger}
57
57
  protocols.act_on(ops.S**-1, args, qubits=[qubits[q]], allow_decompose=False)
@@ -62,7 +62,7 @@ def _H(
62
62
  q: int,
63
63
  args: sim.CliffordTableauSimulationState,
64
64
  operations: list[ops.Operation],
65
- qubits: list[cirq.Qid],
65
+ qubits: Sequence[cirq.Qid],
66
66
  ):
67
67
  protocols.act_on(ops.H, args, qubits=[qubits[q]], allow_decompose=False)
68
68
  operations.append(ops.H(qubits[q]))
@@ -73,7 +73,7 @@ def _CNOT(
73
73
  q2: int,
74
74
  args: sim.CliffordTableauSimulationState,
75
75
  operations: list[ops.Operation],
76
- qubits: list[cirq.Qid],
76
+ qubits: Sequence[cirq.Qid],
77
77
  ):
78
78
  protocols.act_on(ops.CNOT, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False)
79
79
  operations.append(ops.CNOT(qubits[q1], qubits[q2]))
@@ -84,14 +84,14 @@ def _SWAP(
84
84
  q2: int,
85
85
  args: sim.CliffordTableauSimulationState,
86
86
  operations: list[ops.Operation],
87
- qubits: list[cirq.Qid],
87
+ qubits: Sequence[cirq.Qid],
88
88
  ):
89
89
  protocols.act_on(ops.SWAP, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False)
90
90
  operations.append(ops.SWAP(qubits[q1], qubits[q2]))
91
91
 
92
92
 
93
93
  def decompose_clifford_tableau_to_operations(
94
- qubits: list[cirq.Qid], clifford_tableau: qis.CliffordTableau
94
+ qubits: Sequence[cirq.Qid], clifford_tableau: qis.CliffordTableau
95
95
  ) -> list[ops.Operation]:
96
96
  """Decompose an n-qubit Clifford Tableau into a list of one/two qubit operations.
97
97
 
@@ -21,14 +21,14 @@ import cirq
21
21
  from cirq.testing import assert_allclose_up_to_global_phase
22
22
 
23
23
 
24
- def test_misaligned_qubits():
24
+ def test_misaligned_qubits() -> None:
25
25
  qubits = cirq.LineQubit.range(1)
26
26
  tableau = cirq.CliffordTableau(num_qubits=2)
27
27
  with pytest.raises(ValueError):
28
28
  cirq.decompose_clifford_tableau_to_operations(qubits, tableau)
29
29
 
30
30
 
31
- def test_clifford_decompose_one_qubit():
31
+ def test_clifford_decompose_one_qubit() -> None:
32
32
  """Two random instance for one qubit decomposition."""
33
33
  qubits = cirq.LineQubit.range(1)
34
34
  args = cirq.CliffordTableauSimulationState(
@@ -63,7 +63,7 @@ def test_clifford_decompose_one_qubit():
63
63
  assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
64
64
 
65
65
 
66
- def test_clifford_decompose_two_qubits():
66
+ def test_clifford_decompose_two_qubits() -> None:
67
67
  """Two random instance for two qubits decomposition."""
68
68
  qubits = cirq.LineQubit.range(2)
69
69
  args = cirq.CliffordTableauSimulationState(
@@ -98,7 +98,7 @@ def test_clifford_decompose_two_qubits():
98
98
  assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
99
99
 
100
100
 
101
- def test_clifford_decompose_by_unitary():
101
+ def test_clifford_decompose_by_unitary() -> None:
102
102
  """Validate the decomposition of random Clifford Tableau by unitary matrix.
103
103
 
104
104
  Due to the exponential growth in dimension, it cannot validate very large number of qubits.
@@ -125,7 +125,7 @@ def test_clifford_decompose_by_unitary():
125
125
  assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
126
126
 
127
127
 
128
- def test_clifford_decompose_by_reconstruction():
128
+ def test_clifford_decompose_by_reconstruction() -> None:
129
129
  """Validate the decomposition of random Clifford Tableau by reconstruction.
130
130
 
131
131
  This approach can validate large number of qubits compared with the unitary one.
@@ -15,7 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import itertools
18
- from typing import TYPE_CHECKING
18
+ from typing import Sequence, TYPE_CHECKING
19
19
 
20
20
  import numpy as np
21
21
 
@@ -114,7 +114,7 @@ def _ccnot_congruent(c0: cirq.Qid, c1: cirq.Qid, target: cirq.Qid) -> list[cirq.
114
114
 
115
115
 
116
116
  def decompose_multi_controlled_x(
117
- controls: list[cirq.Qid], target: cirq.Qid, free_qubits: list[cirq.Qid]
117
+ controls: Sequence[cirq.Qid], target: cirq.Qid, free_qubits: Sequence[cirq.Qid]
118
118
  ) -> list[cirq.Operation]:
119
119
  """Implements action of multi-controlled Pauli X gate.
120
120
 
@@ -152,11 +152,11 @@ def decompose_multi_controlled_x(
152
152
  elif len(free_qubits) >= 1:
153
153
  # See [1], Lemma 7.3.
154
154
  m1 = n // 2
155
- free1 = controls[m1:] + [target] + free_qubits[1:]
155
+ free1 = [*controls[m1:], target, *free_qubits[1:]]
156
156
  ctrl1 = controls[:m1]
157
157
  part1 = decompose_multi_controlled_x(ctrl1, free_qubits[0], free1)
158
- free2 = controls[:m1] + free_qubits[1:]
159
- ctrl2 = controls[m1:] + [free_qubits[0]]
158
+ free2 = [*controls[:m1], *free_qubits[1:]]
159
+ ctrl2 = [*controls[m1:], free_qubits[0]]
160
160
  part2 = decompose_multi_controlled_x(ctrl2, target, free2)
161
161
  return [*part1, *part2, *part1, *part2]
162
162
  else:
@@ -167,7 +167,7 @@ def decompose_multi_controlled_x(
167
167
 
168
168
 
169
169
  def _decompose_su(
170
- matrix: np.ndarray, controls: list[cirq.Qid], target: cirq.Qid
170
+ matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid
171
171
  ) -> list[cirq.Operation]:
172
172
  """Decomposes controlled special unitary gate into elementary gates.
173
173
 
@@ -193,9 +193,9 @@ def _decompose_su(
193
193
  def _decompose_recursive(
194
194
  matrix: np.ndarray,
195
195
  power: float,
196
- controls: list[cirq.Qid],
196
+ controls: Sequence[cirq.Qid],
197
197
  target: cirq.Qid,
198
- free_qubits: list[cirq.Qid],
198
+ free_qubits: Sequence[cirq.Qid],
199
199
  ) -> list[cirq.Operation]:
200
200
  """Decomposes controlled unitary gate into elementary gates.
201
201
 
@@ -205,20 +205,20 @@ def _decompose_recursive(
205
205
  if len(controls) == 1:
206
206
  return _decompose_single_ctrl(_unitary_power(matrix, power), controls[0], target)
207
207
 
208
- cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], free_qubits + [target])
208
+ cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], [*free_qubits, target])
209
209
  return [
210
210
  *_decompose_single_ctrl(_unitary_power(matrix, 0.5 * power), controls[-1], target),
211
211
  *cnots,
212
212
  *_decompose_single_ctrl(_unitary_power(matrix, -0.5 * power), controls[-1], target),
213
213
  *cnots,
214
214
  *_decompose_recursive(
215
- matrix, 0.5 * power, controls[:-1], target, [controls[-1]] + free_qubits
215
+ matrix, 0.5 * power, controls[:-1], target, [controls[-1], *free_qubits]
216
216
  ),
217
217
  ]
218
218
 
219
219
 
220
220
  def decompose_multi_controlled_rotation(
221
- matrix: np.ndarray, controls: list[cirq.Qid], target: cirq.Qid
221
+ matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid
222
222
  ) -> list[cirq.Operation]:
223
223
  """Implements action of multi-controlled unitary gate.
224
224
 
@@ -20,7 +20,7 @@ import scipy.stats
20
20
  import cirq
21
21
 
22
22
 
23
- def test_decompose_x():
23
+ def test_decompose_x() -> None:
24
24
  """Verifies correctness of multi-controlled X decomposition."""
25
25
  for total_qubits_count in range(1, 8):
26
26
  qubits = cirq.LineQubit.range(total_qubits_count)
@@ -83,14 +83,14 @@ def _test_decompose(matrix, controls_count):
83
83
  cirq.testing.assert_allclose_up_to_global_phase(expected_matrix, result_matrix, atol=1e-8)
84
84
 
85
85
 
86
- def test_decompose_specific_matrices():
86
+ def test_decompose_specific_matrices() -> None:
87
87
  for gate in [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.I, cirq.T, cirq.S]:
88
88
  for controls_count in range(7):
89
89
  _test_decompose(cirq.unitary(gate), controls_count)
90
90
 
91
91
 
92
92
  @cirq.testing.retry_once_with_later_random_values
93
- def test_decompose_random_unitary():
93
+ def test_decompose_random_unitary() -> None:
94
94
  for controls_count in range(5):
95
95
  for _ in range(10):
96
96
  _test_decompose(_random_unitary(), controls_count)
@@ -99,7 +99,7 @@ def test_decompose_random_unitary():
99
99
 
100
100
 
101
101
  @cirq.testing.retry_once_with_later_random_values
102
- def test_decompose_random_special_unitary():
102
+ def test_decompose_random_special_unitary() -> None:
103
103
  for controls_count in range(5):
104
104
  for _ in range(10):
105
105
  _test_decompose(_random_special_unitary(), controls_count)
@@ -113,7 +113,7 @@ def _decomposition_size(U, controls_count):
113
113
  return _count_operations(operations)
114
114
 
115
115
 
116
- def test_decompose_size_special_unitary():
116
+ def test_decompose_size_special_unitary() -> None:
117
117
  np.random.seed(0)
118
118
  u = _random_special_unitary()
119
119
  assert _decomposition_size(u, 0) == (1, 0, 0)
@@ -126,7 +126,7 @@ def test_decompose_size_special_unitary():
126
126
  assert _decomposition_size(u, i) == (64 * i - 312, 48 * i - 234, 16)
127
127
 
128
128
 
129
- def test_decompose_size_unitary():
129
+ def test_decompose_size_unitary() -> None:
130
130
  np.random.seed(0)
131
131
  u = _random_unitary()
132
132
  assert _decomposition_size(u, 0) == (1, 0, 0)
@@ -100,7 +100,7 @@ def decompose_cphase_into_two_fsim(
100
100
  fsim_gate: cirq.FSimGate,
101
101
  qubits: Sequence[cirq.Qid] | None = None,
102
102
  atol: float = 1e-8,
103
- ) -> cirq.OP_TREE:
103
+ ) -> Sequence[cirq.Operation]:
104
104
  """Decomposes CZPowGate into two FSimGates.
105
105
 
106
106
  This function implements the decomposition described in section VII F I