cirq-core 1.1.0.dev20221220224914__py3-none-any.whl → 1.2.0__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.
Files changed (228) hide show
  1. cirq/__init__.py +8 -0
  2. cirq/_compat.py +29 -4
  3. cirq/_compat_test.py +24 -26
  4. cirq/_version.py +32 -1
  5. cirq/_version_test.py +1 -1
  6. cirq/circuits/_block_diagram_drawer_test.py +4 -3
  7. cirq/circuits/circuit.py +109 -63
  8. cirq/circuits/circuit_operation.py +2 -3
  9. cirq/circuits/circuit_operation_test.py +4 -4
  10. cirq/circuits/circuit_test.py +11 -0
  11. cirq/circuits/frozen_circuit.py +13 -1
  12. cirq/circuits/frozen_circuit_test.py +5 -1
  13. cirq/circuits/moment.py +39 -14
  14. cirq/circuits/moment_test.py +7 -0
  15. cirq/circuits/text_diagram_drawer.py +1 -1
  16. cirq/circuits/text_diagram_drawer_test.py +3 -7
  17. cirq/contrib/acquaintance/bipartite.py +1 -1
  18. cirq/contrib/acquaintance/devices.py +2 -2
  19. cirq/contrib/acquaintance/executor.py +5 -2
  20. cirq/contrib/acquaintance/gates.py +3 -2
  21. cirq/contrib/acquaintance/permutation.py +13 -2
  22. cirq/contrib/acquaintance/testing.py +3 -5
  23. cirq/contrib/paulistring/recombine.py +3 -6
  24. cirq/contrib/qasm_import/_parser.py +17 -21
  25. cirq/contrib/qasm_import/_parser_test.py +30 -45
  26. cirq/contrib/qcircuit/qcircuit_test.py +3 -7
  27. cirq/contrib/quantum_volume/quantum_volume.py +3 -3
  28. cirq/contrib/quimb/mps_simulator.py +1 -1
  29. cirq/contrib/quimb/state_vector.py +2 -0
  30. cirq/contrib/quirk/quirk_gate.py +1 -0
  31. cirq/contrib/svg/svg.py +4 -7
  32. cirq/contrib/svg/svg_test.py +29 -1
  33. cirq/devices/grid_qubit.py +26 -28
  34. cirq/devices/grid_qubit_test.py +21 -5
  35. cirq/devices/line_qubit.py +10 -12
  36. cirq/devices/line_qubit_test.py +9 -2
  37. cirq/devices/named_topologies.py +1 -1
  38. cirq/devices/noise_model.py +4 -1
  39. cirq/devices/superconducting_qubits_noise_properties.py +1 -3
  40. cirq/experiments/n_qubit_tomography.py +1 -1
  41. cirq/experiments/qubit_characterizations.py +2 -2
  42. cirq/experiments/single_qubit_readout_calibration.py +1 -1
  43. cirq/experiments/t2_decay_experiment.py +1 -1
  44. cirq/experiments/xeb_simulation_test.py +2 -2
  45. cirq/interop/quirk/cells/testing.py +1 -1
  46. cirq/json_resolver_cache.py +1 -0
  47. cirq/linalg/__init__.py +2 -0
  48. cirq/linalg/decompositions_test.py +4 -4
  49. cirq/linalg/diagonalize_test.py +5 -6
  50. cirq/linalg/transformations.py +72 -9
  51. cirq/linalg/transformations_test.py +23 -7
  52. cirq/ops/__init__.py +4 -0
  53. cirq/ops/arithmetic_operation.py +4 -6
  54. cirq/ops/classically_controlled_operation.py +10 -3
  55. cirq/ops/clifford_gate.py +1 -7
  56. cirq/ops/common_channels.py +21 -15
  57. cirq/ops/common_gate_families.py +2 -3
  58. cirq/ops/common_gates.py +48 -11
  59. cirq/ops/common_gates_test.py +4 -0
  60. cirq/ops/controlled_gate.py +44 -18
  61. cirq/ops/controlled_operation.py +13 -5
  62. cirq/ops/dense_pauli_string.py +14 -19
  63. cirq/ops/diagonal_gate.py +3 -4
  64. cirq/ops/eigen_gate.py +8 -10
  65. cirq/ops/eigen_gate_test.py +6 -0
  66. cirq/ops/gate_operation.py +11 -6
  67. cirq/ops/gate_operation_test.py +11 -2
  68. cirq/ops/gateset.py +2 -1
  69. cirq/ops/gateset_test.py +38 -5
  70. cirq/ops/global_phase_op.py +28 -2
  71. cirq/ops/global_phase_op_test.py +21 -0
  72. cirq/ops/identity.py +1 -1
  73. cirq/ops/kraus_channel_test.py +2 -2
  74. cirq/ops/linear_combinations.py +7 -6
  75. cirq/ops/linear_combinations_test.py +26 -10
  76. cirq/ops/matrix_gates.py +8 -4
  77. cirq/ops/matrix_gates_test.py +25 -3
  78. cirq/ops/measure_util.py +13 -5
  79. cirq/ops/measure_util_test.py +8 -2
  80. cirq/ops/measurement_gate.py +1 -1
  81. cirq/ops/measurement_gate_test.py +9 -4
  82. cirq/ops/mixed_unitary_channel_test.py +4 -4
  83. cirq/ops/named_qubit.py +2 -4
  84. cirq/ops/parity_gates.py +5 -1
  85. cirq/ops/parity_gates_test.py +6 -0
  86. cirq/ops/pauli_gates.py +9 -9
  87. cirq/ops/pauli_string.py +4 -2
  88. cirq/ops/pauli_string_raw_types.py +4 -11
  89. cirq/ops/pauli_string_test.py +13 -13
  90. cirq/ops/pauli_sum_exponential.py +6 -1
  91. cirq/ops/qubit_manager.py +97 -0
  92. cirq/ops/qubit_manager_test.py +66 -0
  93. cirq/ops/raw_types.py +75 -33
  94. cirq/ops/raw_types_test.py +34 -0
  95. cirq/ops/three_qubit_gates.py +16 -10
  96. cirq/ops/three_qubit_gates_test.py +4 -2
  97. cirq/ops/two_qubit_diagonal_gate.py +3 -3
  98. cirq/ops/wait_gate.py +1 -1
  99. cirq/protocols/__init__.py +1 -0
  100. cirq/protocols/act_on_protocol.py +3 -3
  101. cirq/protocols/act_on_protocol_test.py +5 -5
  102. cirq/protocols/apply_channel_protocol.py +9 -8
  103. cirq/protocols/apply_mixture_protocol.py +8 -8
  104. cirq/protocols/apply_mixture_protocol_test.py +1 -1
  105. cirq/protocols/apply_unitary_protocol.py +66 -19
  106. cirq/protocols/apply_unitary_protocol_test.py +50 -0
  107. cirq/protocols/circuit_diagram_info_protocol.py +7 -9
  108. cirq/protocols/decompose_protocol.py +167 -125
  109. cirq/protocols/decompose_protocol_test.py +132 -2
  110. cirq/protocols/has_stabilizer_effect_protocol.py +2 -1
  111. cirq/protocols/inverse_protocol.py +2 -2
  112. cirq/protocols/json_serialization_test.py +3 -3
  113. cirq/protocols/json_test_data/Linspace.json +20 -7
  114. cirq/protocols/json_test_data/Linspace.repr +4 -1
  115. cirq/protocols/json_test_data/Points.json +19 -8
  116. cirq/protocols/json_test_data/Points.repr +4 -1
  117. cirq/protocols/json_test_data/Result.repr_inward +1 -1
  118. cirq/protocols/json_test_data/ResultDict.repr +1 -1
  119. cirq/protocols/json_test_data/ResultDict.repr_inward +1 -1
  120. cirq/protocols/json_test_data/TrialResult.repr_inward +1 -1
  121. cirq/protocols/json_test_data/XPowGate.json +13 -5
  122. cirq/protocols/json_test_data/XPowGate.repr +1 -1
  123. cirq/protocols/json_test_data/ZPowGate.json +13 -5
  124. cirq/protocols/json_test_data/ZPowGate.repr +1 -1
  125. cirq/protocols/json_test_data/ZipLongest.json +19 -0
  126. cirq/protocols/json_test_data/ZipLongest.repr +1 -0
  127. cirq/protocols/json_test_data/spec.py +1 -0
  128. cirq/protocols/kraus_protocol.py +3 -4
  129. cirq/protocols/measurement_key_protocol.py +3 -1
  130. cirq/protocols/mixture_protocol.py +3 -2
  131. cirq/protocols/phase_protocol.py +3 -3
  132. cirq/protocols/pow_protocol.py +1 -2
  133. cirq/protocols/qasm.py +4 -4
  134. cirq/protocols/qid_shape_protocol.py +8 -8
  135. cirq/protocols/resolve_parameters.py +8 -3
  136. cirq/protocols/resolve_parameters_test.py +3 -3
  137. cirq/protocols/unitary_protocol.py +19 -11
  138. cirq/protocols/unitary_protocol_test.py +37 -0
  139. cirq/qis/channels.py +1 -1
  140. cirq/qis/clifford_tableau.py +4 -5
  141. cirq/qis/quantum_state_representation.py +7 -9
  142. cirq/qis/states.py +21 -13
  143. cirq/qis/states_test.py +7 -0
  144. cirq/sim/clifford/clifford_simulator.py +3 -3
  145. cirq/sim/density_matrix_simulation_state.py +2 -1
  146. cirq/sim/density_matrix_simulator.py +1 -1
  147. cirq/sim/density_matrix_simulator_test.py +9 -5
  148. cirq/sim/density_matrix_utils.py +7 -32
  149. cirq/sim/mux.py +2 -2
  150. cirq/sim/simulation_state.py +58 -18
  151. cirq/sim/simulation_state_base.py +5 -2
  152. cirq/sim/simulation_state_test.py +121 -9
  153. cirq/sim/simulation_utils.py +59 -0
  154. cirq/sim/simulation_utils_test.py +32 -0
  155. cirq/sim/simulator.py +2 -1
  156. cirq/sim/simulator_base_test.py +3 -3
  157. cirq/sim/sparse_simulator.py +1 -1
  158. cirq/sim/sparse_simulator_test.py +5 -5
  159. cirq/sim/state_vector.py +7 -36
  160. cirq/sim/state_vector_simulation_state.py +18 -1
  161. cirq/sim/state_vector_simulator.py +3 -2
  162. cirq/sim/state_vector_simulator_test.py +24 -2
  163. cirq/sim/state_vector_test.py +46 -15
  164. cirq/study/__init__.py +1 -0
  165. cirq/study/flatten_expressions.py +2 -2
  166. cirq/study/resolver.py +2 -0
  167. cirq/study/resolver_test.py +1 -1
  168. cirq/study/result.py +1 -1
  169. cirq/study/sweeps.py +103 -9
  170. cirq/study/sweeps_test.py +64 -0
  171. cirq/testing/__init__.py +4 -0
  172. cirq/testing/circuit_compare.py +15 -18
  173. cirq/testing/consistent_act_on.py +4 -4
  174. cirq/testing/consistent_controlled_gate_op_test.py +1 -1
  175. cirq/testing/consistent_decomposition.py +11 -2
  176. cirq/testing/consistent_decomposition_test.py +8 -1
  177. cirq/testing/consistent_protocols.py +2 -0
  178. cirq/testing/consistent_protocols_test.py +8 -4
  179. cirq/testing/consistent_qasm.py +8 -15
  180. cirq/testing/consistent_specified_has_unitary.py +1 -1
  181. cirq/testing/consistent_unitary.py +85 -0
  182. cirq/testing/consistent_unitary_test.py +96 -0
  183. cirq/testing/equivalent_repr_eval.py +10 -10
  184. cirq/testing/json.py +3 -3
  185. cirq/testing/logs.py +1 -1
  186. cirq/testing/order_tester.py +4 -5
  187. cirq/testing/random_circuit.py +3 -5
  188. cirq/testing/sample_gates.py +79 -0
  189. cirq/testing/sample_gates_test.py +59 -0
  190. cirq/transformers/__init__.py +2 -0
  191. cirq/transformers/analytical_decompositions/__init__.py +8 -0
  192. cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +130 -0
  193. cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +58 -0
  194. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +230 -0
  195. cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +112 -0
  196. cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -3
  197. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
  198. cirq/transformers/expand_composite.py +1 -1
  199. cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +4 -4
  200. cirq/transformers/measurement_transformers.py +4 -4
  201. cirq/transformers/merge_single_qubit_gates.py +17 -4
  202. cirq/transformers/routing/route_circuit_cqc.py +2 -2
  203. cirq/transformers/stratify.py +125 -62
  204. cirq/transformers/stratify_test.py +20 -16
  205. cirq/transformers/transformer_api.py +1 -1
  206. cirq/transformers/transformer_primitives.py +3 -2
  207. cirq/transformers/transformer_primitives_test.py +11 -0
  208. cirq/value/abc_alt.py +3 -2
  209. cirq/value/abc_alt_test.py +1 -0
  210. cirq/value/classical_data.py +10 -10
  211. cirq/value/digits.py +2 -2
  212. cirq/value/linear_dict.py +18 -19
  213. cirq/value/product_state.py +7 -6
  214. cirq/value/value_equality_attr.py +2 -2
  215. cirq/vis/heatmap.py +1 -1
  216. cirq/vis/heatmap_test.py +2 -2
  217. cirq/work/collector.py +2 -2
  218. cirq/work/observable_measurement_data.py +5 -5
  219. cirq/work/observable_readout_calibration.py +3 -1
  220. cirq/work/observable_settings.py +1 -1
  221. cirq/work/pauli_sum_collector.py +9 -8
  222. cirq/work/sampler.py +2 -0
  223. cirq/work/zeros_sampler.py +2 -2
  224. {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/METADATA +7 -15
  225. {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/RECORD +228 -214
  226. {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/WHEEL +1 -1
  227. {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/LICENSE +0 -0
  228. {cirq_core-1.1.0.dev20221220224914.dist-info → cirq_core-1.2.0.dist-info}/top_level.txt +0 -0
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  """An immutable version of the Circuit data structure."""
15
- from typing import FrozenSet, Iterable, Iterator, Sequence, Tuple, TYPE_CHECKING, Union
15
+ from typing import AbstractSet, FrozenSet, Iterable, Iterator, Sequence, Tuple, TYPE_CHECKING, Union
16
16
 
17
17
  import numpy as np
18
18
 
@@ -83,6 +83,10 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
83
83
  def _qid_shape_(self) -> Tuple[int, ...]:
84
84
  return super()._qid_shape_()
85
85
 
86
+ @_compat.cached_method
87
+ def _has_unitary_(self) -> bool:
88
+ return super()._has_unitary_()
89
+
86
90
  @_compat.cached_method
87
91
  def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
88
92
  return super()._unitary_()
@@ -124,6 +128,14 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
124
128
  def all_measurement_key_names(self) -> FrozenSet[str]:
125
129
  return frozenset(str(key) for key in self.all_measurement_key_objs())
126
130
 
131
+ @_compat.cached_method
132
+ def _is_parameterized_(self) -> bool:
133
+ return super()._is_parameterized_()
134
+
135
+ @_compat.cached_method
136
+ def _parameter_names_(self) -> AbstractSet[str]:
137
+ return super()._parameter_names_()
138
+
127
139
  def _measurement_key_names_(self) -> FrozenSet[str]:
128
140
  return self.all_measurement_key_names()
129
141
 
@@ -68,5 +68,9 @@ def test_immutable():
68
68
  q = cirq.LineQubit(0)
69
69
  c = cirq.FrozenCircuit(cirq.X(q), cirq.H(q))
70
70
 
71
- with pytest.raises(AttributeError, match="can't set attribute"):
71
+ # Match one of two strings. The second one is message returned since python 3.11.
72
+ with pytest.raises(
73
+ AttributeError,
74
+ match="(can't set attribute)|(property 'moments' of 'FrozenCircuit' object has no setter)",
75
+ ):
72
76
  c.moments = (cirq.Moment(cirq.H(q)), cirq.Moment(cirq.X(q)))
cirq/circuits/moment.py CHANGED
@@ -19,6 +19,7 @@ from typing import (
19
19
  AbstractSet,
20
20
  Any,
21
21
  Callable,
22
+ cast,
22
23
  Dict,
23
24
  FrozenSet,
24
25
  Iterable,
@@ -30,13 +31,13 @@ from typing import (
30
31
  Sequence,
31
32
  Tuple,
32
33
  TYPE_CHECKING,
33
- TypeVar,
34
34
  Union,
35
35
  )
36
+ from typing_extensions import Self
36
37
 
37
38
  import numpy as np
38
39
 
39
- from cirq import protocols, ops, qis
40
+ from cirq import protocols, ops, qis, _compat
40
41
  from cirq._import import LazyLoader
41
42
  from cirq.ops import raw_types, op_tree
42
43
  from cirq.protocols import circuit_diagram_info_protocol
@@ -52,8 +53,6 @@ text_diagram_drawer = LazyLoader(
52
53
  "text_diagram_drawer", globals(), "cirq.circuits.text_diagram_drawer"
53
54
  )
54
55
 
55
- TSelf_Moment = TypeVar('TSelf_Moment', bound='Moment')
56
-
57
56
 
58
57
  def _default_breakdown(qid: 'cirq.Qid') -> Tuple[Any, Any]:
59
58
  # Attempt to convert into a position on the complex plane.
@@ -82,17 +81,26 @@ class Moment:
82
81
  are no such operations, returns an empty Moment.
83
82
  """
84
83
 
85
- def __init__(self, *contents: 'cirq.OP_TREE') -> None:
84
+ def __init__(self, *contents: 'cirq.OP_TREE', _flatten_contents: bool = True) -> None:
86
85
  """Constructs a moment with the given operations.
87
86
 
88
87
  Args:
89
88
  contents: The operations applied within the moment.
90
89
  Will be flattened and frozen into a tuple before storing.
90
+ _flatten_contents: If True, use flatten_to_ops to convert
91
+ the OP_TREE of contents into a tuple of Operation. If False,
92
+ we skip flattening and assume that contents already consists
93
+ of individual operations. This is used internally by helper
94
+ methods to avoid unnecessary validation.
91
95
 
92
96
  Raises:
93
97
  ValueError: A qubit appears more than once.
94
98
  """
95
- self._operations = tuple(op_tree.flatten_to_ops(contents))
99
+ self._operations = (
100
+ tuple(op_tree.flatten_to_ops(contents))
101
+ if _flatten_contents
102
+ else cast(Tuple['cirq.Operation'], contents)
103
+ )
96
104
  self._sorted_operations: Optional[Tuple['cirq.Operation', ...]] = None
97
105
 
98
106
  # An internal dictionary to support efficient operation access by qubit.
@@ -108,6 +116,20 @@ class Moment:
108
116
  self._measurement_key_objs: Optional[FrozenSet['cirq.MeasurementKey']] = None
109
117
  self._control_keys: Optional[FrozenSet['cirq.MeasurementKey']] = None
110
118
 
119
+ @classmethod
120
+ def from_ops(cls, *ops: 'cirq.Operation') -> 'cirq.Moment':
121
+ """Construct a Moment from the given operations.
122
+
123
+ This avoids calling `flatten_to_ops` in the moment constructor, which
124
+ results in better performance in cases where the contents of the moment
125
+ are already in the form of a sequence of operations rather than an
126
+ arbitrary OP_TREE.
127
+
128
+ Args:
129
+ *ops: Operations to include in the Moment.
130
+ """
131
+ return cls(*ops, _flatten_contents=False)
132
+
111
133
  @property
112
134
  def operations(self) -> Tuple['cirq.Operation', ...]:
113
135
  return self._operations
@@ -148,8 +170,7 @@ class Moment:
148
170
  """
149
171
  if self.operates_on([qubit]):
150
172
  return self.__getitem__(qubit)
151
- else:
152
- return None
173
+ return None
153
174
 
154
175
  def with_operation(self, operation: 'cirq.Operation') -> 'cirq.Moment':
155
176
  """Returns an equal moment, but with the given op added.
@@ -167,7 +188,7 @@ class Moment:
167
188
  raise ValueError(f'Overlapping operations: {operation}')
168
189
 
169
190
  # Use private variables to facilitate a quick copy.
170
- m = Moment()
191
+ m = Moment(_flatten_contents=False)
171
192
  m._operations = self._operations + (operation,)
172
193
  m._sorted_operations = None
173
194
  m._qubits = self._qubits.union(operation.qubits)
@@ -197,7 +218,7 @@ class Moment:
197
218
  if not flattened_contents:
198
219
  return self
199
220
 
200
- m = Moment()
221
+ m = Moment(_flatten_contents=False)
201
222
  # Use private variables to facilitate a quick copy.
202
223
  m._qubit_to_op = self._qubit_to_op.copy()
203
224
  qubits = set(self._qubits)
@@ -238,9 +259,11 @@ class Moment:
238
259
  if qubits.isdisjoint(frozenset(operation.qubits))
239
260
  )
240
261
 
262
+ @_compat.cached_method()
241
263
  def _is_parameterized_(self) -> bool:
242
264
  return any(protocols.is_parameterized(op) for op in self)
243
265
 
266
+ @_compat.cached_method()
244
267
  def _parameter_names_(self) -> AbstractSet[str]:
245
268
  return {name for op in self for name in protocols.parameter_names(op)}
246
269
 
@@ -266,6 +289,7 @@ class Moment:
266
289
  for op in self.operations
267
290
  )
268
291
 
292
+ @_compat.cached_method()
269
293
  def _measurement_key_names_(self) -> FrozenSet[str]:
270
294
  return frozenset(str(key) for key in self._measurement_key_objs_())
271
295
 
@@ -333,6 +357,7 @@ class Moment:
333
357
  def __ne__(self, other) -> bool:
334
358
  return not self == other
335
359
 
360
+ @_compat.cached_method()
336
361
  def __hash__(self):
337
362
  return hash((Moment, self._sorted_operations_()))
338
363
 
@@ -370,9 +395,8 @@ class Moment:
370
395
  return self._operations
371
396
 
372
397
  def transform_qubits(
373
- self: TSelf_Moment,
374
- qubit_map: Union[Dict['cirq.Qid', 'cirq.Qid'], Callable[['cirq.Qid'], 'cirq.Qid']],
375
- ) -> TSelf_Moment:
398
+ self, qubit_map: Union[Dict['cirq.Qid', 'cirq.Qid'], Callable[['cirq.Qid'], 'cirq.Qid']]
399
+ ) -> Self:
376
400
  """Returns the same moment, but with different qubits.
377
401
 
378
402
  Args:
@@ -406,6 +430,7 @@ class Moment:
406
430
  operations.append(ops.I(q))
407
431
  return Moment(*operations)
408
432
 
433
+ @_compat.cached_method()
409
434
  def _has_kraus_(self) -> bool:
410
435
  """Returns True if self has a Kraus representation and self uses <= 10 qubits."""
411
436
  return all(protocols.has_kraus(op) for op in self.operations) and len(self.qubits) <= 10
@@ -482,7 +507,7 @@ class Moment:
482
507
 
483
508
  @classmethod
484
509
  def _from_json_dict_(cls, operations, **kwargs):
485
- return Moment(operations)
510
+ return cls.from_ops(*operations)
486
511
 
487
512
  def __add__(self, other: 'cirq.OP_TREE') -> 'cirq.Moment':
488
513
 
@@ -170,6 +170,13 @@ def test_operation_at():
170
170
  assert cirq.Moment([cirq.CZ(a, b), cirq.X(c)]).operation_at(a) == cirq.CZ(a, b)
171
171
 
172
172
 
173
+ def test_from_ops():
174
+ a = cirq.NamedQubit('a')
175
+ b = cirq.NamedQubit('b')
176
+
177
+ assert cirq.Moment.from_ops(cirq.X(a), cirq.Y(b)) == cirq.Moment(cirq.X(a), cirq.Y(b))
178
+
179
+
173
180
  def test_with_operation():
174
181
  a = cirq.NamedQubit('a')
175
182
  b = cirq.NamedQubit('b')
@@ -292,7 +292,7 @@ class TextDiagramDrawer:
292
292
  self,
293
293
  horizontal_spacing: int = 1,
294
294
  vertical_spacing: int = 1,
295
- crossing_char: str = None,
295
+ crossing_char: Optional[str] = None,
296
296
  use_unicode_characters: bool = True,
297
297
  ) -> str:
298
298
  """Outputs text containing the diagram."""
@@ -46,17 +46,13 @@ def assert_has_rendering(actual: TextDiagramDrawer, desired: str, **kwargs) -> N
46
46
  "Diagram's rendering differs from the desired rendering.\n"
47
47
  '\n'
48
48
  'Actual rendering:\n'
49
- '{}\n'
49
+ f'{actual_diagram}\n'
50
50
  '\n'
51
51
  'Desired rendering:\n'
52
- '{}\n'
52
+ f'{desired_diagram}\n'
53
53
  '\n'
54
54
  'Highlighted differences:\n'
55
- '{}\n'.format(
56
- actual_diagram,
57
- desired_diagram,
58
- ct.highlight_text_differences(actual_diagram, desired_diagram),
59
- )
55
+ f'{ct.highlight_text_differences(actual_diagram, desired_diagram)}\n'
60
56
  )
61
57
 
62
58
 
@@ -133,7 +133,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
133
133
  if self.subgraph == BipartiteGraphType.MATCHING:
134
134
  name = 'Matching'
135
135
  elif self.subgraph == BipartiteGraphType.COMPLETE:
136
- name = 'K_{{{0}, {0}}}'.format(self.part_size)
136
+ name = f'K_{{{self.part_size}, {self.part_size}}}'
137
137
  # NB: self.subgraph not in BipartiteGraphType caught by self.permutation
138
138
  arrow = '↦' if args.use_unicode_characters else '->'
139
139
 
@@ -36,8 +36,8 @@ class AcquaintanceDevice(devices.Device, metaclass=abc.ABCMeta):
36
36
  isinstance(operation, ops.GateOperation) and isinstance(operation.gate, self.gate_types)
37
37
  ):
38
38
  raise ValueError(
39
- 'not (isinstance({0!r}, {1!r}) and '
40
- 'ininstance({0!r}.gate, {2!r})'.format(operation, ops.Operation, self.gate_types)
39
+ f'not (isinstance({operation!r}, {ops.Operation!r}) and '
40
+ f'ininstance({operation!r}.gate, {self.gate_types!r})'
41
41
  )
42
42
 
43
43
 
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
34
34
 
35
35
 
36
36
  class ExecutionStrategy(metaclass=abc.ABCMeta):
37
- """Tells `StrategyExecutorTransormer` how to execute an acquaintance strategy.
37
+ """Tells `StrategyExecutorTransformer` how to execute an acquaintance strategy.
38
38
 
39
39
  An execution strategy tells `StrategyExecutorTransformer` how to execute
40
40
  an acquaintance strategy, i.e. what gates to implement at the available
@@ -174,7 +174,10 @@ class GreedyExecutionStrategy(ExecutionStrategy):
174
174
  """
175
175
 
176
176
  def __init__(
177
- self, gates: LogicalGates, initial_mapping: LogicalMapping, device: 'cirq.Device' = None
177
+ self,
178
+ gates: LogicalGates,
179
+ initial_mapping: LogicalMapping,
180
+ device: Optional['cirq.Device'] = None,
178
181
  ) -> None:
179
182
  """Inits GreedyExecutionStrategy.
180
183
 
@@ -347,8 +347,9 @@ class SwapNetworkGate(PermutationGate):
347
347
  return {i: j for i, j in enumerate(reversed(range(sum(self.part_lens))))}
348
348
 
349
349
  def __repr__(self) -> str:
350
- return 'cirq.contrib.acquaintance.SwapNetworkGate({!r}, {!r})'.format(
351
- self.part_lens, self.acquaintance_size
350
+ return (
351
+ 'cirq.contrib.acquaintance.SwapNetworkGate('
352
+ f'{self.part_lens!r}, {self.acquaintance_size!r})'
352
353
  )
353
354
 
354
355
  def _value_equality_values_(self):
@@ -13,7 +13,18 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import abc
16
- from typing import Any, cast, Dict, Iterable, Sequence, Tuple, TypeVar, Union, TYPE_CHECKING
16
+ from typing import (
17
+ Any,
18
+ cast,
19
+ Dict,
20
+ Iterable,
21
+ Optional,
22
+ Sequence,
23
+ Tuple,
24
+ TypeVar,
25
+ Union,
26
+ TYPE_CHECKING,
27
+ )
17
28
 
18
29
  from cirq import circuits, ops, protocols, transformers, value
19
30
  from cirq.type_workarounds import NotImplementedType
@@ -72,7 +83,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
72
83
  mapping[new_key] = old_element
73
84
 
74
85
  @staticmethod
75
- def validate_permutation(permutation: Dict[int, int], n_elements: int = None) -> None:
86
+ def validate_permutation(permutation: Dict[int, int], n_elements: Optional[int] = None) -> None:
76
87
  if not permutation:
77
88
  return
78
89
  if set(permutation.values()) != set(permutation):
@@ -29,13 +29,11 @@ def assert_permutation_decomposition_equivalence(gate: PermutationGate, n_qubits
29
29
  update_mapping(mapping, operations)
30
30
  expected_mapping = {qubits[j]: i for i, j in gate.permutation().items()}
31
31
  assert mapping == expected_mapping, (
32
- "{!r}.permutation({}) doesn't match decomposition.\n"
32
+ f"{gate!r}.permutation({n_qubits}) doesn't match decomposition.\n"
33
33
  '\n'
34
34
  'Actual mapping:\n'
35
- '{}\n'
35
+ f'{[mapping[q] for q in qubits]}\n'
36
36
  '\n'
37
37
  'Expected mapping:\n'
38
- '{}\n'.format(
39
- gate, n_qubits, [mapping[q] for q in qubits], [expected_mapping[q] for q in qubits]
40
- )
38
+ f'{[expected_mapping[q] for q in qubits]}\n'
41
39
  )
@@ -27,7 +27,6 @@ def _sorted_best_string_placements(
27
27
  output_ops: Sequence[ops.Operation],
28
28
  key: Callable[[Any], ops.PauliStringPhasor] = lambda node: node.val,
29
29
  ) -> List[Tuple[ops.PauliStringPhasor, int, circuitdag.Unique[ops.PauliStringPhasor]]]:
30
-
31
30
  sort_key = lambda placement: (-len(placement[0].pauli_string), placement[1])
32
31
 
33
32
  node_maxes = []
@@ -84,11 +83,9 @@ def move_pauli_strings_into_circuit(
84
83
  # Pick the Pauli string that can be moved furthest through
85
84
  # the Clifford circuit
86
85
  for best_string_op, best_index, best_node in placements:
87
-
88
- assert (
89
- best_index <= last_index
90
- ), "Unexpected insertion index order, {} >= {}, len: {}".format(
91
- best_index, last_index, len(output_ops)
86
+ assert best_index <= last_index, (
87
+ "Unexpected insertion index order, "
88
+ f"{best_index} >= {last_index}, len: {len(output_ops)}"
92
89
  )
93
90
 
94
91
  last_index = best_index
@@ -11,6 +11,7 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
14
15
  import functools
15
16
  import operator
16
17
  from typing import Any, Callable, cast, Dict, Iterable, List, Optional, Union, TYPE_CHECKING
@@ -82,16 +83,15 @@ class QasmGateStatement:
82
83
  def _validate_args(self, args: List[List[ops.Qid]], lineno: int):
83
84
  if len(args) != self.num_args:
84
85
  raise QasmException(
85
- "{} only takes {} arg(s) (qubits and/or registers), "
86
- "got: {}, at line {}".format(self.qasm_gate, self.num_args, len(args), lineno)
86
+ f"{self.qasm_gate} only takes {self.num_args} arg(s) (qubits and/or registers), "
87
+ f"got: {len(args)}, at line {lineno}"
87
88
  )
88
89
 
89
90
  def _validate_params(self, params: List[float], lineno: int):
90
91
  if len(params) != self.num_params:
91
92
  raise QasmException(
92
- "{} takes {} parameter(s), got: {}, at line {}".format(
93
- self.qasm_gate, self.num_params, len(params), lineno
94
- )
93
+ f"{self.qasm_gate} takes {self.num_params} parameter(s), "
94
+ f"got: {len(params)}, at line {lineno}"
95
95
  )
96
96
 
97
97
  def on(
@@ -141,7 +141,7 @@ class QasmParser:
141
141
  parsedQasm = QasmParser().parse(qasm)
142
142
  """
143
143
 
144
- def __init__(self):
144
+ def __init__(self) -> None:
145
145
  self.parser = yacc.yacc(module=self, debug=False, write_tables=False)
146
146
  self.circuit = Circuit()
147
147
  self.qregs: Dict[str, int] = {}
@@ -287,8 +287,7 @@ class QasmParser:
287
287
  """format : FORMAT_SPEC"""
288
288
  if p[1] != "2.0":
289
289
  raise QasmException(
290
- "Unsupported OpenQASM version: {}, "
291
- "only 2.0 is supported currently by Cirq".format(p[1])
290
+ f"Unsupported OpenQASM version: {p[1]}, only 2.0 is supported currently by Cirq"
292
291
  )
293
292
 
294
293
  # circuit : new_reg circuit
@@ -345,11 +344,8 @@ class QasmParser:
345
344
  ):
346
345
  gate_set = self.basic_gates if not self.qelibinc else self.all_gates
347
346
  if gate not in gate_set.keys():
348
- msg = 'Unknown gate "{}" at line {}{}'.format(
349
- gate,
350
- p.lineno(1),
351
- ", did you forget to include qelib1.inc?" if not self.qelibinc else "",
352
- )
347
+ tip = ", did you forget to include qelib1.inc?" if not self.qelibinc else ""
348
+ msg = f'Unknown gate "{gate}" at line {p.lineno(1)}{tip}'
353
349
  raise QasmException(msg)
354
350
  p[0] = gate_set[gate].on(args=args, params=params, lineno=p.lineno(1))
355
351
 
@@ -460,9 +456,9 @@ class QasmParser:
460
456
  size = self.qregs[reg]
461
457
  if idx >= size:
462
458
  raise QasmException(
463
- 'Out of bounds qubit index {} '
464
- 'on register {} of size {} '
465
- 'at line {}'.format(idx, reg, size, p.lineno(1))
459
+ f'Out of bounds qubit index {idx} '
460
+ f'on register {reg} of size {size} '
461
+ f'at line {p.lineno(1)}'
466
462
  )
467
463
  if arg_name not in self.qubits.keys():
468
464
  self.qubits[arg_name] = NamedQubit(arg_name)
@@ -479,9 +475,9 @@ class QasmParser:
479
475
  size = self.cregs[reg]
480
476
  if idx >= size:
481
477
  raise QasmException(
482
- 'Out of bounds bit index {} '
483
- 'on classical register {} of size {} '
484
- 'at line {}'.format(idx, reg, size, p.lineno(1))
478
+ f'Out of bounds bit index {idx} '
479
+ f'on classical register {reg} of size {size} '
480
+ f'at line {p.lineno(1)}'
485
481
  )
486
482
  p[0] = [arg_name]
487
483
 
@@ -495,8 +491,8 @@ class QasmParser:
495
491
 
496
492
  if len(qreg) != len(creg):
497
493
  raise QasmException(
498
- 'mismatched register sizes {} -> {} for measurement '
499
- 'at line {}'.format(len(qreg), len(creg), p.lineno(1))
494
+ f'mismatched register sizes {len(qreg)} -> {len(creg)} for measurement '
495
+ f'at line {p.lineno(1)}'
500
496
  )
501
497
 
502
498
  p[0] = [
@@ -11,6 +11,7 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
14
15
  from typing import Callable
15
16
 
16
17
  import numpy as np
@@ -489,14 +490,12 @@ single_qubit_gates = [
489
490
 
490
491
  @pytest.mark.parametrize('qasm_gate,cirq_gate', rotation_gates)
491
492
  def test_rotation_gates(qasm_gate: str, cirq_gate: Callable[[float], cirq.Gate]):
492
- qasm = """OPENQASM 2.0;
493
+ qasm = f"""OPENQASM 2.0;
493
494
  include "qelib1.inc";
494
495
  qreg q[2];
495
- {0}(pi/2) q[0];
496
- {0}(pi) q;
497
- """.format(
498
- qasm_gate
499
- )
496
+ {qasm_gate}(pi/2) q[0];
497
+ {qasm_gate}(pi) q;
498
+ """
500
499
 
501
500
  parser = QasmParser()
502
501
 
@@ -527,7 +526,7 @@ def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
527
526
 
528
527
  parser = QasmParser()
529
528
 
530
- with pytest.raises(QasmException, match=r".*{}.* takes 1.*got.*2.*line 5".format(qasm_gate)):
529
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.* takes 1.*got.*2.*line 5"):
531
530
  parser.parse(qasm)
532
531
 
533
532
 
@@ -541,7 +540,7 @@ def test_rotation_gates_zero_params_error(qasm_gate: str):
541
540
 
542
541
  parser = QasmParser()
543
542
 
544
- with pytest.raises(QasmException, match=r".*{}.* takes 1.*got.*0.*line 4".format(qasm_gate)):
543
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.* takes 1.*got.*0.*line 4"):
545
544
  parser.parse(qasm)
546
545
 
547
546
 
@@ -867,9 +866,7 @@ def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
867
866
 
868
867
  parser = QasmParser()
869
868
 
870
- with pytest.raises(
871
- QasmException, match=r".*{}.* takes {}.*got.*5.*line 4".format(qasm_gate, num_params)
872
- ):
869
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.* takes {num_params}.*got.*5.*line 4"):
873
870
  parser.parse(qasm)
874
871
 
875
872
  if num_params == 0:
@@ -883,9 +880,7 @@ def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
883
880
 
884
881
  parser = QasmParser()
885
882
 
886
- with pytest.raises(
887
- QasmException, match=r".*{}.* takes {}.*got.*0.*line 4".format(qasm_gate, num_params)
888
- ):
883
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.* takes {num_params}.*got.*0.*line 4"):
889
884
  parser.parse(qasm)
890
885
 
891
886
 
@@ -901,17 +896,15 @@ two_qubit_gates = [
901
896
 
902
897
  @pytest.mark.parametrize('qasm_gate,cirq_gate', two_qubit_gates)
903
898
  def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
904
- qasm = """
905
- OPENQASM 2.0;
906
- include "qelib1.inc";
899
+ qasm = f"""
900
+ OPENQASM 2.0;
901
+ include "qelib1.inc";
907
902
  qreg q1[2];
908
903
  qreg q2[2];
909
- {0} q1[0], q1[1];
910
- {0} q1, q2[0];
911
- {0} q2, q1;
912
- """.format(
913
- qasm_gate
914
- )
904
+ {qasm_gate} q1[0], q1[1];
905
+ {qasm_gate} q1, q2[0];
906
+ {qasm_gate} q2, q1;
907
+ """
915
908
  parser = QasmParser()
916
909
 
917
910
  q1_0 = cirq.NamedQubit('q1_0')
@@ -949,9 +942,7 @@ def test_two_qubit_gates_not_enough_args(qasm_gate: str):
949
942
 
950
943
  parser = QasmParser()
951
944
 
952
- with pytest.raises(
953
- QasmException, match=r".*{}.* takes 2 arg\(s\).*got.*1.*line 5".format(qasm_gate)
954
- ):
945
+ with pytest.raises(QasmException, match=rf".*{qasm_gate}.* takes 2 arg\(s\).*got.*1.*line 5"):
955
946
  parser.parse(qasm)
956
947
 
957
948
 
@@ -967,7 +958,7 @@ def test_two_qubit_gates_with_too_much_parameters(qasm_gate: str):
967
958
  parser = QasmParser()
968
959
 
969
960
  with pytest.raises(
970
- QasmException, match=r".*{}.* takes 0 parameter\(s\).*got.*1.*line 5".format(qasm_gate)
961
+ QasmException, match=rf".*{qasm_gate}.* takes 0 parameter\(s\).*got.*1.*line 5"
971
962
  ):
972
963
  parser.parse(qasm)
973
964
 
@@ -977,18 +968,16 @@ three_qubit_gates = [('ccx', cirq.TOFFOLI), ('cswap', cirq.CSWAP)]
977
968
 
978
969
  @pytest.mark.parametrize('qasm_gate,cirq_gate', three_qubit_gates)
979
970
  def test_three_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
980
- qasm = """
971
+ qasm = f"""
981
972
  OPENQASM 2.0;
982
- include "qelib1.inc";
973
+ include "qelib1.inc";
983
974
  qreg q1[2];
984
975
  qreg q2[2];
985
976
  qreg q3[2];
986
- {0} q1[0], q1[1], q2[0];
987
- {0} q1, q2[0], q3[0];
988
- {0} q1, q2, q3;
989
- """.format(
990
- qasm_gate
991
- )
977
+ {qasm_gate} q1[0], q1[1], q2[0];
978
+ {qasm_gate} q1, q2[0], q3[0];
979
+ {qasm_gate} q1, q2, q3;
980
+ """
992
981
  parser = QasmParser()
993
982
 
994
983
  q1_0 = cirq.NamedQubit('q1_0')
@@ -1027,9 +1016,7 @@ def test_three_qubit_gates_not_enough_args(qasm_gate: str):
1027
1016
 
1028
1017
  parser = QasmParser()
1029
1018
 
1030
- with pytest.raises(
1031
- QasmException, match=r""".*{}.* takes 3 arg\(s\).*got.*1.*line 4""".format(qasm_gate)
1032
- ):
1019
+ with pytest.raises(QasmException, match=rf".*{qasm_gate}.* takes 3 arg\(s\).*got.*1.*line 4"):
1033
1020
  parser.parse(qasm)
1034
1021
 
1035
1022
 
@@ -1043,20 +1030,18 @@ def test_three_qubit_gates_with_too_much_parameters(qasm_gate: str):
1043
1030
 
1044
1031
  parser = QasmParser()
1045
1032
 
1046
- with pytest.raises(QasmException, match=r""".*{}.*parameter.*line 4.*""".format(qasm_gate)):
1033
+ with pytest.raises(QasmException, match=f".*{qasm_gate}.*parameter.*line 4.*"):
1047
1034
  parser.parse(qasm)
1048
1035
 
1049
1036
 
1050
1037
  @pytest.mark.parametrize('qasm_gate,cirq_gate', single_qubit_gates)
1051
1038
  def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate):
1052
- qasm = """OPENQASM 2.0;
1039
+ qasm = f"""OPENQASM 2.0;
1053
1040
  include "qelib1.inc";
1054
1041
  qreg q[2];
1055
- {0} q[0];
1056
- {0} q;
1057
- """.format(
1058
- qasm_gate
1059
- )
1042
+ {qasm_gate} q[0];
1043
+ {qasm_gate} q;
1044
+ """
1060
1045
 
1061
1046
  parser = QasmParser()
1062
1047