cirq-core 1.6.0.dev20250708194540__py3-none-any.whl → 1.6.0.dev20250710201614__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.

cirq/_version.py CHANGED
@@ -29,4 +29,4 @@ if sys.version_info < (3, 11 - 1, 0): # pragma: no cover
29
29
  'of cirq (e.g. "python -m pip install cirq==1.5.0")'
30
30
  )
31
31
 
32
- __version__ = "1.6.0.dev20250708194540"
32
+ __version__ = "1.6.0.dev20250710201614"
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.6.0.dev20250708194540"
6
+ assert cirq.__version__ == "1.6.0.dev20250710201614"
cirq/circuits/circuit.py CHANGED
@@ -33,6 +33,7 @@ from typing import (
33
33
  Any,
34
34
  Callable,
35
35
  cast,
36
+ Hashable,
36
37
  Iterable,
37
38
  Iterator,
38
39
  Mapping,
@@ -141,7 +142,9 @@ class AbstractCircuit(abc.ABC):
141
142
  """
142
143
 
143
144
  @classmethod
144
- def from_moments(cls: type[CIRCUIT_TYPE], *moments: cirq.OP_TREE | None) -> CIRCUIT_TYPE:
145
+ def from_moments(
146
+ cls: type[CIRCUIT_TYPE], *moments: cirq.OP_TREE | None, tags: Sequence[Hashable] = ()
147
+ ) -> CIRCUIT_TYPE:
145
148
  """Create a circuit from moment op trees.
146
149
 
147
150
  Args:
@@ -155,8 +158,12 @@ class AbstractCircuit(abc.ABC):
155
158
  which is then included in the new circuit. Note that in this
156
159
  case we have the normal restriction that operations in a
157
160
  moment must be applied to disjoint sets of qubits.
161
+ tags: A sequence of any type of object that is useful to attach metadata
162
+ to this circuit as long as the type is hashable. If you wish the
163
+ resulting circuit to be eventually serialized into JSON, you should
164
+ also restrict the tags to be JSON serializable.
158
165
  """
159
- return cls._from_moments(cls._make_moments(moments))
166
+ return cls._from_moments(cls._make_moments(moments), tags=tags)
160
167
 
161
168
  @staticmethod
162
169
  def _make_moments(moments: Iterable[cirq.OP_TREE | None]) -> Iterator[cirq.Moment]:
@@ -170,7 +177,9 @@ class AbstractCircuit(abc.ABC):
170
177
 
171
178
  @classmethod
172
179
  @abc.abstractmethod
173
- def _from_moments(cls: type[CIRCUIT_TYPE], moments: Iterable[cirq.Moment]) -> CIRCUIT_TYPE:
180
+ def _from_moments(
181
+ cls: type[CIRCUIT_TYPE], moments: Iterable[cirq.Moment], tags: Sequence[Hashable]
182
+ ) -> CIRCUIT_TYPE:
174
183
  """Create a circuit from moments.
175
184
 
176
185
  This must be implemented by subclasses. It provides a more efficient way
@@ -201,6 +210,20 @@ class AbstractCircuit(abc.ABC):
201
210
  copy: If True and 'self' is a Circuit, returns a copy that circuit.
202
211
  """
203
212
 
213
+ @property
214
+ @abc.abstractmethod
215
+ def tags(self) -> tuple[Hashable, ...]:
216
+ """Returns a tuple of the Circuit's tags."""
217
+
218
+ @abc.abstractmethod
219
+ def with_tags(self, *new_tags: Hashable) -> Self:
220
+ """Creates a new tagged Circuit with `self.tags` and `new_tags` combined."""
221
+
222
+ @property
223
+ def untagged(self) -> Self:
224
+ """Returns the underlying Circuit without any tags."""
225
+ return self._from_moments(self.moments, tags=()) if self.tags else self
226
+
204
227
  def __bool__(self) -> bool:
205
228
  return bool(self.moments)
206
229
 
@@ -210,14 +233,16 @@ class AbstractCircuit(abc.ABC):
210
233
  return other is self or (
211
234
  len(self.moments) == len(other.moments)
212
235
  and all(m0 == m1 for m0, m1 in zip(self.moments, other.moments))
236
+ and self.tags == other.tags
213
237
  )
214
238
 
215
239
  def _approx_eq_(self, other: Any, atol: float) -> bool:
216
240
  """See `cirq.protocols.SupportsApproximateEquality`."""
217
241
  if not isinstance(other, AbstractCircuit):
218
242
  return NotImplemented
219
- return other is self or cirq.protocols.approx_eq(
220
- tuple(self.moments), tuple(other.moments), atol=atol
243
+ return other is self or (
244
+ self.tags == other.tags
245
+ and cirq.protocols.approx_eq(tuple(self.moments), tuple(other.moments), atol=atol)
221
246
  )
222
247
 
223
248
  def __ne__(self, other) -> bool:
@@ -259,7 +284,7 @@ class AbstractCircuit(abc.ABC):
259
284
 
260
285
  def __getitem__(self, key):
261
286
  if isinstance(key, slice):
262
- return self._from_moments(self.moments[key])
287
+ return self._from_moments(self.moments[key], tags=self.tags)
263
288
  if hasattr(key, '__index__'):
264
289
  return self.moments[key]
265
290
  if isinstance(key, tuple):
@@ -272,7 +297,9 @@ class AbstractCircuit(abc.ABC):
272
297
  return selected_moments[qubit_idx]
273
298
  if isinstance(qubit_idx, ops.Qid):
274
299
  qubit_idx = [qubit_idx]
275
- return self._from_moments(moment[qubit_idx] for moment in selected_moments)
300
+ return self._from_moments(
301
+ (moment[qubit_idx] for moment in selected_moments), tags=self.tags
302
+ )
276
303
 
277
304
  raise TypeError('__getitem__ called with key not of type slice, int, or tuple.')
278
305
 
@@ -283,7 +310,9 @@ class AbstractCircuit(abc.ABC):
283
310
  args = []
284
311
  if self.moments:
285
312
  args.append(_list_repr_with_indented_item_lines(self.moments))
286
- return f'{", ".join(args)}'
313
+ moments_repr = f'{", ".join(args)}'
314
+ tag_repr = ','.join(_compat.proper_repr(t) for t in self.tags)
315
+ return f'{moments_repr}, tags=[{tag_repr}]' if self.tags else moments_repr
287
316
 
288
317
  def __repr__(self) -> str:
289
318
  cls_name = self.__class__.__name__
@@ -942,7 +971,9 @@ class AbstractCircuit(abc.ABC):
942
971
  """Apply func to expand each op into a circuit, then zip up the circuits."""
943
972
  return Circuit.zip(*[Circuit(func(op)) for op in moment])
944
973
 
945
- return self._from_moments(m for moment in self for m in map_moment(moment))
974
+ return self._from_moments(
975
+ (m for moment in self for m in map_moment(moment)), tags=self.tags
976
+ )
946
977
 
947
978
  def qid_shape(
948
979
  self, qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT
@@ -983,15 +1014,19 @@ class AbstractCircuit(abc.ABC):
983
1014
 
984
1015
  def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]):
985
1016
  return self._from_moments(
986
- protocols.with_measurement_key_mapping(moment, key_map) for moment in self.moments
1017
+ (protocols.with_measurement_key_mapping(moment, key_map) for moment in self.moments),
1018
+ tags=self.tags,
987
1019
  )
988
1020
 
989
1021
  def _with_key_path_(self, path: tuple[str, ...]):
990
- return self._from_moments(protocols.with_key_path(moment, path) for moment in self.moments)
1022
+ return self._from_moments(
1023
+ (protocols.with_key_path(moment, path) for moment in self.moments), tags=self.tags
1024
+ )
991
1025
 
992
1026
  def _with_key_path_prefix_(self, prefix: tuple[str, ...]):
993
1027
  return self._from_moments(
994
- protocols.with_key_path_prefix(moment, prefix) for moment in self.moments
1028
+ (protocols.with_key_path_prefix(moment, prefix) for moment in self.moments),
1029
+ tags=self.tags,
995
1030
  )
996
1031
 
997
1032
  def _with_rescoped_keys_(
@@ -1002,7 +1037,7 @@ class AbstractCircuit(abc.ABC):
1002
1037
  new_moment = protocols.with_rescoped_keys(moment, path, bindable_keys)
1003
1038
  moments.append(new_moment)
1004
1039
  bindable_keys |= protocols.measurement_key_objs(new_moment)
1005
- return self._from_moments(moments)
1040
+ return self._from_moments(moments, tags=self.tags)
1006
1041
 
1007
1042
  def _qid_shape_(self) -> tuple[int, ...]:
1008
1043
  return self.qid_shape()
@@ -1300,22 +1335,33 @@ class AbstractCircuit(abc.ABC):
1300
1335
  return diagram
1301
1336
 
1302
1337
  def _is_parameterized_(self) -> bool:
1303
- return any(protocols.is_parameterized(op) for op in self.all_operations())
1338
+ return any(protocols.is_parameterized(op) for op in self.all_operations()) or any(
1339
+ protocols.is_parameterized(tag) for tag in self.tags
1340
+ )
1304
1341
 
1305
1342
  def _parameter_names_(self) -> AbstractSet[str]:
1306
- return {name for op in self.all_operations() for name in protocols.parameter_names(op)}
1343
+ op_params = {name for op in self.all_operations() for name in protocols.parameter_names(op)}
1344
+ tag_params = {name for tag in self.tags for name in protocols.parameter_names(tag)}
1345
+ return op_params | tag_params
1307
1346
 
1308
1347
  def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> Self:
1309
1348
  changed = False
1310
1349
  resolved_moments: list[cirq.Moment] = []
1350
+ resolved_tags: list[Hashable] = []
1311
1351
  for moment in self:
1312
1352
  resolved_moment = protocols.resolve_parameters(moment, resolver, recursive)
1313
1353
  if resolved_moment is not moment:
1314
1354
  changed = True
1315
1355
  resolved_moments.append(resolved_moment)
1316
- if not changed:
1356
+ for tag in self.tags:
1357
+ resolved_tag = protocols.resolve_parameters(tag, resolver, recursive)
1358
+ if resolved_tag is not tag:
1359
+ changed = True
1360
+ resolved_tags.append(resolved_tag)
1361
+ if changed:
1362
+ return self._from_moments(resolved_moments, tags=resolved_tags)
1363
+ else:
1317
1364
  return self # pragma: no cover
1318
- return self._from_moments(resolved_moments)
1319
1365
 
1320
1366
  def _qasm_(self, args: cirq.QasmArgs | None = None) -> str:
1321
1367
  if args is None:
@@ -1394,11 +1440,13 @@ class AbstractCircuit(abc.ABC):
1394
1440
  self._to_qasm_output(header, precision, qubit_order).save(file_path)
1395
1441
 
1396
1442
  def _json_dict_(self):
1397
- return protocols.obj_to_dict_helper(self, ['moments'])
1443
+ attribute_names = ['moments', 'tags'] if self.tags else ['moments']
1444
+ ret = protocols.obj_to_dict_helper(self, attribute_names)
1445
+ return ret
1398
1446
 
1399
1447
  @classmethod
1400
- def _from_json_dict_(cls, moments, **kwargs):
1401
- return cls(moments, strategy=InsertStrategy.EARLIEST)
1448
+ def _from_json_dict_(cls, moments, tags=(), **kwargs):
1449
+ return cls(moments, tags=tags, strategy=InsertStrategy.EARLIEST)
1402
1450
 
1403
1451
  def zip(
1404
1452
  *circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
@@ -1462,7 +1510,7 @@ class AbstractCircuit(abc.ABC):
1462
1510
  if isinstance(align, str):
1463
1511
  align = Alignment[align.upper()]
1464
1512
 
1465
- result = cirq.Circuit()
1513
+ result = cirq.Circuit(tags=circuits[0].tags if circuits else ())
1466
1514
  for k in range(n):
1467
1515
  try:
1468
1516
  if align == Alignment.LEFT:
@@ -1531,7 +1579,7 @@ class AbstractCircuit(abc.ABC):
1531
1579
  for k in range(1, len(circuits)):
1532
1580
  offset, n_acc = _concat_ragged_helper(offset, n_acc, buffer, circuits[k].moments, align)
1533
1581
 
1534
- return cirq.Circuit(buffer[offset : offset + n_acc])
1582
+ return cirq.Circuit(buffer[offset : offset + n_acc], tags=circuits[0].tags)
1535
1583
 
1536
1584
  def get_independent_qubit_sets(self) -> list[set[cirq.Qid]]:
1537
1585
  """Divide circuit's qubits into independent qubit sets.
@@ -1610,7 +1658,10 @@ class AbstractCircuit(abc.ABC):
1610
1658
  # the qubits from one factor belong to a specific independent qubit set.
1611
1659
  # This makes it possible to create independent circuits based on these
1612
1660
  # moments.
1613
- return (self._from_moments(m[qubits] for m in self.moments) for qubits in qubit_factors)
1661
+ return (
1662
+ self._from_moments([m[qubits] for m in self.moments], tags=self.tags)
1663
+ for qubits in qubit_factors
1664
+ )
1614
1665
 
1615
1666
  def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
1616
1667
  controls = frozenset(k for op in self.all_operations() for k in protocols.control_keys(op))
@@ -1753,7 +1804,10 @@ class Circuit(AbstractCircuit):
1753
1804
  """
1754
1805
 
1755
1806
  def __init__(
1756
- self, *contents: cirq.OP_TREE, strategy: cirq.InsertStrategy = InsertStrategy.EARLIEST
1807
+ self,
1808
+ *contents: cirq.OP_TREE,
1809
+ strategy: cirq.InsertStrategy = InsertStrategy.EARLIEST,
1810
+ tags: Sequence[Hashable] = (),
1757
1811
  ) -> None:
1758
1812
  """Initializes a circuit.
1759
1813
 
@@ -1767,9 +1821,14 @@ class Circuit(AbstractCircuit):
1767
1821
  from `contents`, this determines how the operations are packed
1768
1822
  together. This option does not affect later insertions into the
1769
1823
  circuit.
1824
+ tags: A sequence of any type of object that is useful to attach metadata
1825
+ to this circuit as long as the type is hashable. If you wish the
1826
+ resulting circuit to be eventually serialized into JSON, you should
1827
+ also restrict the tags to be JSON serializable.
1770
1828
  """
1771
1829
  self._placement_cache: _PlacementCache | None = _PlacementCache()
1772
1830
  self._moments: list[cirq.Moment] = []
1831
+ self._tags = tuple(tags)
1773
1832
 
1774
1833
  # Implementation note: the following cached properties are set lazily and then
1775
1834
  # invalidated and reset to None in `self._mutated()`, which is called any time
@@ -1803,10 +1862,11 @@ class Circuit(AbstractCircuit):
1803
1862
  self._placement_cache = None
1804
1863
 
1805
1864
  @classmethod
1806
- def _from_moments(cls, moments: Iterable[cirq.Moment]) -> Circuit:
1865
+ def _from_moments(cls, moments: Iterable[cirq.Moment], tags: Sequence[Hashable]) -> Circuit:
1807
1866
  new_circuit = Circuit()
1808
1867
  new_circuit._moments[:] = moments
1809
1868
  new_circuit._placement_cache = None
1869
+ new_circuit._tags = tuple(tags)
1810
1870
  return new_circuit
1811
1871
 
1812
1872
  def _load_contents_with_earliest_strategy(self, contents: cirq.OP_TREE):
@@ -1865,7 +1925,7 @@ class Circuit(AbstractCircuit):
1865
1925
  from cirq.circuits.frozen_circuit import FrozenCircuit
1866
1926
 
1867
1927
  if self._frozen is None:
1868
- self._frozen = FrozenCircuit._from_moments(self._moments)
1928
+ self._frozen = FrozenCircuit._from_moments(self._moments, tags=self.tags)
1869
1929
  return self._frozen
1870
1930
 
1871
1931
  def unfreeze(self, copy: bool = True) -> cirq.Circuit:
@@ -1894,8 +1954,9 @@ class Circuit(AbstractCircuit):
1894
1954
  def copy(self) -> Circuit:
1895
1955
  """Return a copy of this circuit."""
1896
1956
  copied_circuit = Circuit()
1897
- copied_circuit._moments = self._moments[:]
1957
+ copied_circuit._moments[:] = self._moments
1898
1958
  copied_circuit._placement_cache = None
1959
+ copied_circuit._tags = self.tags
1899
1960
  return copied_circuit
1900
1961
 
1901
1962
  @overload
@@ -1955,7 +2016,7 @@ class Circuit(AbstractCircuit):
1955
2016
  def __mul__(self, repetitions: _INT_TYPE):
1956
2017
  if not isinstance(repetitions, (int, np.integer)):
1957
2018
  return NotImplemented
1958
- return Circuit(self._moments * int(repetitions))
2019
+ return Circuit(self._moments * int(repetitions), tags=self.tags)
1959
2020
 
1960
2021
  def __rmul__(self, repetitions: _INT_TYPE):
1961
2022
  if not isinstance(repetitions, (int, np.integer)):
@@ -1981,7 +2042,7 @@ class Circuit(AbstractCircuit):
1981
2042
  return NotImplemented
1982
2043
  inv_moments.append(inv_moment)
1983
2044
 
1984
- return cirq.Circuit(inv_moments)
2045
+ return cirq.Circuit(inv_moments, tags=self.tags)
1985
2046
 
1986
2047
  __hash__ = None # type: ignore
1987
2048
 
@@ -2466,6 +2527,18 @@ class Circuit(AbstractCircuit):
2466
2527
  def moments(self) -> Sequence[cirq.Moment]:
2467
2528
  return self._moments
2468
2529
 
2530
+ @property
2531
+ def tags(self) -> tuple[Hashable, ...]:
2532
+ return self._tags
2533
+
2534
+ def with_tags(self, *new_tags: Hashable) -> cirq.Circuit:
2535
+ """Creates a new tagged `Circuit` with `self.tags` and `new_tags` combined."""
2536
+ if not new_tags:
2537
+ return self
2538
+ new_circuit = Circuit(tags=self.tags + new_tags)
2539
+ new_circuit._moments[:] = self._moments
2540
+ return new_circuit
2541
+
2469
2542
  def with_noise(self, noise: cirq.NOISE_MODEL_LIKE) -> cirq.Circuit:
2470
2543
  """Make a noisy version of the circuit.
2471
2544
 
@@ -2480,7 +2553,7 @@ class Circuit(AbstractCircuit):
2480
2553
  """
2481
2554
  noise_model = devices.NoiseModel.from_noise_model_like(noise)
2482
2555
  qubits = sorted(self.all_qubits())
2483
- c_noisy = Circuit()
2556
+ c_noisy = Circuit(tags=self.tags)
2484
2557
  for op_tree in noise_model.noisy_moments(self, qubits):
2485
2558
  # Keep moments aligned
2486
2559
  c_noisy += Circuit(op_tree)
@@ -4919,3 +4919,52 @@ def test_append_speed() -> None:
4919
4919
  duration = time.perf_counter() - t
4920
4920
  assert len(c) == moments
4921
4921
  assert duration < 5
4922
+
4923
+
4924
+ def test_tagged_circuits() -> None:
4925
+ q = cirq.LineQubit(0)
4926
+ ops = [cirq.X(q), cirq.H(q)]
4927
+ tags = (sympy.Symbol("a"), "b")
4928
+ circuit = cirq.Circuit(ops)
4929
+ tagged_circuit = cirq.Circuit(ops, tags=tags)
4930
+ # Test equality
4931
+ assert tagged_circuit.tags == tags
4932
+ assert circuit != tagged_circuit
4933
+ assert not cirq.approx_eq(circuit, tagged_circuit)
4934
+ # Test _repr_ and _json_ round trips.
4935
+ cirq.testing.assert_equivalent_repr(tagged_circuit)
4936
+ cirq.testing.assert_json_roundtrip_works(tagged_circuit)
4937
+ # Test utility methods and constructors
4938
+ assert tagged_circuit.with_tags() is tagged_circuit
4939
+ assert circuit.with_tags(*tags) == tagged_circuit
4940
+ assert tagged_circuit.with_tags("c") == cirq.Circuit(ops, tags=[*tags, "c"])
4941
+ assert tagged_circuit.untagged == circuit
4942
+ assert circuit.untagged is circuit
4943
+ assert tagged_circuit.freeze().tags == tags
4944
+ assert tagged_circuit.unfreeze(copy=True).tags == tags
4945
+ assert tagged_circuit.unfreeze(copy=False).tags == tags
4946
+ # Test parameterized protocols
4947
+ assert cirq.is_parameterized(circuit) is False
4948
+ assert cirq.is_parameterized(tagged_circuit) is True
4949
+ assert cirq.parameter_names(tagged_circuit) == {"a"}
4950
+ assert cirq.resolve_parameters(tagged_circuit, {"a": 1}).tags == (1, "b")
4951
+ # Tags are not propagated to diagrams yet.
4952
+ assert str(circuit) == str(tagged_circuit)
4953
+ # Test tags are preserved through operations
4954
+ assert (tagged_circuit + circuit).tags == tags
4955
+ assert (circuit + tagged_circuit).tags == () # We only preserve the tags for the first one
4956
+ assert (2 * tagged_circuit).tags == tags
4957
+ assert (tagged_circuit * 2).tags == tags
4958
+ assert (tagged_circuit**-1).tags == tags
4959
+ assert tagged_circuit.with_noise(cirq.X).tags == tags
4960
+ for c in tagged_circuit.factorize():
4961
+ assert tagged_circuit.tags == tags
4962
+
4963
+ q2 = cirq.LineQubit(1)
4964
+ circuit2 = cirq.Circuit(cirq.X(q2), cirq.H(q2))
4965
+ assert tagged_circuit.zip(circuit2).tags == tags
4966
+ assert circuit2.zip(tagged_circuit).tags == () # We only preserve the tags for the first one
4967
+ assert tagged_circuit.concat_ragged(circuit2).tags == tags
4968
+ assert (
4969
+ circuit2.concat_ragged(tagged_circuit).tags == ()
4970
+ ) # We only preserve the tags for the first one
@@ -65,9 +65,12 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
65
65
  self._tags = tuple(tags)
66
66
 
67
67
  @classmethod
68
- def _from_moments(cls, moments: Iterable[cirq.Moment]) -> FrozenCircuit:
68
+ def _from_moments(
69
+ cls, moments: Iterable[cirq.Moment], tags: Sequence[Hashable]
70
+ ) -> FrozenCircuit:
69
71
  new_circuit = FrozenCircuit()
70
72
  new_circuit._moments = tuple(moments)
73
+ new_circuit._tags = tuple(tags)
71
74
  return new_circuit
72
75
 
73
76
  @property
@@ -78,7 +81,7 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
78
81
  return self
79
82
 
80
83
  def unfreeze(self, copy: bool = True) -> cirq.Circuit:
81
- return Circuit._from_moments(self._moments)
84
+ return Circuit._from_moments(self._moments, tags=self.tags)
82
85
 
83
86
  @property
84
87
  def tags(self) -> tuple[Hashable, ...]:
@@ -87,8 +90,7 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
87
90
 
88
91
  @cached_property
89
92
  def untagged(self) -> cirq.FrozenCircuit:
90
- """Returns the underlying FrozenCircuit without any tags."""
91
- return self._from_moments(self._moments) if self.tags else self
93
+ return super().untagged
92
94
 
93
95
  def with_tags(self, *new_tags: Hashable) -> cirq.FrozenCircuit:
94
96
  """Creates a new tagged `FrozenCircuit` with `self.tags` and `new_tags` combined."""
@@ -103,13 +105,6 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
103
105
  # Explicitly cached for performance
104
106
  return hash((self.moments, self.tags))
105
107
 
106
- def __eq__(self, other):
107
- super_eq = super().__eq__(other)
108
- if super_eq is not True:
109
- return super_eq
110
- other_tags = other.tags if isinstance(other, FrozenCircuit) else ()
111
- return self.tags == other_tags
112
-
113
108
  def __getstate__(self):
114
109
  # Don't save hash when pickling; see #3777.
115
110
  state = self.__dict__
@@ -174,23 +169,11 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
174
169
 
175
170
  @_compat.cached_method
176
171
  def _is_parameterized_(self) -> bool:
177
- return super()._is_parameterized_() or any(
178
- protocols.is_parameterized(tag) for tag in self.tags
179
- )
172
+ return super()._is_parameterized_()
180
173
 
181
174
  @_compat.cached_method
182
175
  def _parameter_names_(self) -> AbstractSet[str]:
183
- tag_params = {name for tag in self.tags for name in protocols.parameter_names(tag)}
184
- return super()._parameter_names_() | tag_params
185
-
186
- def _resolve_parameters_(
187
- self, resolver: cirq.ParamResolver, recursive: bool
188
- ) -> cirq.FrozenCircuit:
189
- resolved_circuit = super()._resolve_parameters_(resolver, recursive)
190
- resolved_tags = [
191
- protocols.resolve_parameters(tag, resolver, recursive) for tag in self.tags
192
- ]
193
- return resolved_circuit.with_tags(*resolved_tags)
176
+ return super()._parameter_names_()
194
177
 
195
178
  def _measurement_key_names_(self) -> frozenset[str]:
196
179
  return self.all_measurement_key_names()
@@ -217,16 +200,6 @@ class FrozenCircuit(AbstractCircuit, protocols.SerializableByKey):
217
200
  except:
218
201
  return NotImplemented
219
202
 
220
- def _repr_args(self) -> str:
221
- moments_repr = super()._repr_args()
222
- tag_repr = ','.join(_compat.proper_repr(t) for t in self._tags)
223
- return f'{moments_repr}, tags=[{tag_repr}]' if self.tags else moments_repr
224
-
225
- def _json_dict_(self):
226
- attribute_names = ['moments', 'tags'] if self.tags else ['moments']
227
- ret = protocols.obj_to_dict_helper(self, attribute_names)
228
- return ret
229
-
230
203
  @classmethod
231
204
  def _from_json_dict_(cls, moments, *, tags=(), **kwargs):
232
205
  return cls(moments, strategy=InsertStrategy.EARLIEST, tags=tags)
@@ -96,15 +96,15 @@ def test_immutable() -> None:
96
96
  def test_tagged_circuits() -> None:
97
97
  q = cirq.LineQubit(0)
98
98
  ops = [cirq.X(q), cirq.H(q)]
99
- tags = [sympy.Symbol("a"), "b"]
99
+ tags = (sympy.Symbol("a"), "b")
100
100
  circuit = cirq.Circuit(ops)
101
101
  frozen_circuit = cirq.FrozenCircuit(ops)
102
102
  tagged_circuit = cirq.FrozenCircuit(ops, tags=tags)
103
103
  # Test equality
104
- assert tagged_circuit.tags == tuple(tags)
104
+ assert tagged_circuit.tags == tags
105
105
  assert circuit == frozen_circuit != tagged_circuit
106
+ assert not cirq.approx_eq(frozen_circuit, tagged_circuit)
106
107
  assert cirq.approx_eq(circuit, frozen_circuit)
107
- assert cirq.approx_eq(frozen_circuit, tagged_circuit)
108
108
  # Test hash
109
109
  assert hash(frozen_circuit) != hash(tagged_circuit)
110
110
  # Test _repr_ and _json_ round trips.
@@ -116,9 +116,29 @@ def test_tagged_circuits() -> None:
116
116
  assert tagged_circuit.with_tags("c") == cirq.FrozenCircuit(ops, tags=[*tags, "c"])
117
117
  assert tagged_circuit.untagged == frozen_circuit
118
118
  assert frozen_circuit.untagged is frozen_circuit
119
+ assert tagged_circuit.unfreeze(copy=True).tags == tags
120
+ assert tagged_circuit.unfreeze(copy=False).tags == tags
119
121
  # Test parameterized protocols
120
122
  assert cirq.is_parameterized(frozen_circuit) is False
121
123
  assert cirq.is_parameterized(tagged_circuit) is True
122
124
  assert cirq.parameter_names(tagged_circuit) == {"a"}
125
+ assert cirq.resolve_parameters(tagged_circuit, {"a": 1}).tags == (1, "b")
123
126
  # Tags are not propagated to diagrams yet.
124
127
  assert str(frozen_circuit) == str(tagged_circuit)
128
+ # Test tags are preserved through operations
129
+ assert (tagged_circuit + circuit).tags == tags
130
+ assert (circuit + tagged_circuit).tags == () # We only preserve the tags for the first one
131
+ assert (2 * tagged_circuit).tags == tags
132
+ assert (tagged_circuit * 2).tags == tags
133
+ assert (tagged_circuit**-1).tags == tags
134
+ for c in tagged_circuit.factorize():
135
+ assert tagged_circuit.tags == tags
136
+
137
+ q2 = cirq.LineQubit(1)
138
+ circuit2 = cirq.Circuit(cirq.X(q2), cirq.H(q2))
139
+ assert tagged_circuit.zip(circuit2).tags == tags
140
+ assert circuit2.zip(tagged_circuit).tags == () # We only preserve the tags for the first one
141
+ assert tagged_circuit.concat_ragged(circuit2).tags == tags
142
+ assert (
143
+ circuit2.concat_ragged(tagged_circuit).tags == ()
144
+ ) # We only preserve the tags for the first one
@@ -15,12 +15,15 @@
15
15
 
16
16
  from cirq.experiments.qubit_characterizations import (
17
17
  RandomizedBenchMarkResult as RandomizedBenchMarkResult,
18
+ RBParameters as RBParameters,
18
19
  single_qubit_randomized_benchmarking as single_qubit_randomized_benchmarking,
20
+ single_qubit_rb as single_qubit_rb,
19
21
  single_qubit_state_tomography as single_qubit_state_tomography,
20
22
  TomographyResult as TomographyResult,
21
23
  two_qubit_randomized_benchmarking as two_qubit_randomized_benchmarking,
22
24
  two_qubit_state_tomography as two_qubit_state_tomography,
23
25
  parallel_single_qubit_randomized_benchmarking as parallel_single_qubit_randomized_benchmarking,
26
+ parallel_single_qubit_rb as parallel_single_qubit_rb,
24
27
  )
25
28
 
26
29
  from cirq.experiments.fidelity_estimation import (
@@ -19,6 +19,7 @@ import functools
19
19
  import itertools
20
20
  from typing import Any, cast, Iterator, Mapping, Sequence, TYPE_CHECKING
21
21
 
22
+ import attrs
22
23
  import numpy as np
23
24
  from matplotlib import pyplot as plt
24
25
 
@@ -28,6 +29,7 @@ from scipy.optimize import curve_fit
28
29
  import cirq.vis.heatmap as cirq_heatmap
29
30
  import cirq.vis.histogram as cirq_histogram
30
31
  from cirq import circuits, ops, protocols
32
+ from cirq._compat import deprecated
31
33
  from cirq.devices import grid_qubit
32
34
 
33
35
  if TYPE_CHECKING:
@@ -36,6 +38,12 @@ if TYPE_CHECKING:
36
38
  import cirq
37
39
 
38
40
 
41
+ def _canonize_clifford_sequences(
42
+ sequences: list[list[ops.SingleQubitCliffordGate]],
43
+ ) -> list[list[ops.SingleQubitCliffordGate]]:
44
+ return [[_reduce_gate_seq(seq)] for seq in sequences]
45
+
46
+
39
47
  @dataclasses.dataclass
40
48
  class Cliffords:
41
49
  """The single-qubit Clifford group, decomposed into elementary gates.
@@ -134,7 +142,7 @@ class RandomizedBenchMarkResult:
134
142
  xdata=self._num_cfds_seq,
135
143
  ydata=self._gnd_state_probs,
136
144
  p0=[0.5, 0.5, 1.0 - 1e-3],
137
- bounds=([0, 0.25, 0], [0.5, 0.75, 1]),
145
+ bounds=([0, -1, 0], [1, 1, 1]),
138
146
  )
139
147
 
140
148
 
@@ -333,6 +341,44 @@ class TomographyResult:
333
341
  return axes
334
342
 
335
343
 
344
+ @attrs.frozen
345
+ class RBParameters:
346
+ r"""Parameters for running randomized benchmarking.
347
+
348
+ Arguments:
349
+ num_clifford_range: The different numbers of Cliffords in the RB study.
350
+ num_circuits: The number of random circuits generated for each
351
+ number of Cliffords.
352
+ repetitions: The number of repetitions of each circuit.
353
+ use_xy_basis: Determines if the Clifford gates are built with x and y
354
+ rotations (True) or x and z rotations (False).
355
+ strict_basis: whether to use only cliffords that can be represented by at
356
+ most 2 gates of the choses basis. For example,
357
+ if True and use_xy_basis is True, this excludes $I, Z, \sqrt(Z), \-sqrt(Z)^\dagger$.
358
+ if True and use_xy_basis is False, this excludes $I, Y, \sqrt(Y), -\sqrt(Y)^\dagger$.
359
+ """
360
+
361
+ num_clifford_range: Sequence[int] = tuple(np.logspace(np.log10(5), 3, 5, dtype=int))
362
+ num_circuits: int = 10
363
+ repetitions: int = 600
364
+ use_xy_basis: bool = False
365
+ strict_basis: bool = True
366
+
367
+ def gateset(self) -> list[list[ops.SingleQubitCliffordGate]]:
368
+ clifford_group = _single_qubit_cliffords()
369
+ sequences = clifford_group.c1_in_xy if self.use_xy_basis else clifford_group.c1_in_xz
370
+ sequences = _canonize_clifford_sequences(sequences)
371
+ if self.strict_basis:
372
+ if self.use_xy_basis:
373
+ excluded_gates = ops.Gateset(ops.I, ops.Z, ops.Z**0.5, ops.Z**-0.5)
374
+ else:
375
+ excluded_gates = ops.Gateset(ops.I, ops.Y, ops.Y**0.5, ops.Y**-0.5)
376
+
377
+ sequences = [[g] for (g,) in sequences if g not in excluded_gates]
378
+ return sequences
379
+
380
+
381
+ @deprecated(deadline='v2.0', fix='please use single_qubit_rb instead')
336
382
  def single_qubit_randomized_benchmarking(
337
383
  sampler: cirq.Sampler,
338
384
  qubit: cirq.Qid,
@@ -376,17 +422,20 @@ def single_qubit_randomized_benchmarking(
376
422
  A RandomizedBenchMarkResult object that stores and plots the result.
377
423
  """
378
424
 
379
- result = parallel_single_qubit_randomized_benchmarking(
425
+ return single_qubit_rb(
380
426
  sampler,
381
- (qubit,),
382
- use_xy_basis,
383
- num_clifford_range=num_clifford_range,
384
- num_circuits=num_circuits,
385
- repetitions=repetitions,
427
+ qubit,
428
+ RBParameters(
429
+ num_clifford_range=num_clifford_range,
430
+ num_circuits=num_circuits,
431
+ repetitions=repetitions,
432
+ use_xy_basis=use_xy_basis,
433
+ strict_basis=False,
434
+ ),
386
435
  )
387
- return result.results_dictionary[qubit]
388
436
 
389
437
 
438
+ @deprecated(deadline='v2.0', fix='please use parallel_single_qubit_rb instead')
390
439
  def parallel_single_qubit_randomized_benchmarking(
391
440
  sampler: cirq.Sampler,
392
441
  qubits: Sequence[cirq.Qid],
@@ -413,35 +462,90 @@ def parallel_single_qubit_randomized_benchmarking(
413
462
  num_circuits: The number of random circuits generated for each
414
463
  number of Cliffords.
415
464
  repetitions: The number of repetitions of each circuit.
465
+ Returns:
466
+ A dictionary from qubits to RandomizedBenchMarkResult objects.
467
+ """
468
+ return parallel_single_qubit_rb(
469
+ sampler,
470
+ qubits,
471
+ RBParameters(
472
+ num_clifford_range=num_clifford_range,
473
+ num_circuits=num_circuits,
474
+ repetitions=repetitions,
475
+ use_xy_basis=use_xy_basis,
476
+ strict_basis=False,
477
+ ),
478
+ )
479
+
480
+
481
+ def single_qubit_rb(
482
+ sampler: cirq.Sampler,
483
+ qubit: cirq.Qid,
484
+ parameters: RBParameters = RBParameters(),
485
+ rng_or_seed: np.random.Generator | int | None = None,
486
+ ) -> RandomizedBenchMarkResult:
487
+ """Clifford-based randomized benchmarking (RB) on a single qubit.
488
+
489
+ Args:
490
+ sampler: The quantum engine or simulator to run the circuits.
491
+ qubit: The qubit(s) to benchmark.
492
+ parameters: The parameters of the experiment.
493
+ rng_or_seed: A np.random.Generator object or seed.
494
+ Returns:
495
+ A dictionary from qubits to RandomizedBenchMarkResult objects.
496
+ """
497
+ return parallel_single_qubit_rb(sampler, [qubit], parameters, rng_or_seed).results_dictionary[
498
+ qubit
499
+ ]
500
+
501
+
502
+ def parallel_single_qubit_rb(
503
+ sampler: cirq.Sampler,
504
+ qubits: Sequence[cirq.Qid],
505
+ parameters: RBParameters = RBParameters(),
506
+ rng_or_seed: np.random.Generator | int | None = None,
507
+ ) -> ParallelRandomizedBenchmarkingResult:
508
+ """Clifford-based randomized benchmarking (RB) single qubits in parallel.
416
509
 
510
+ Args:
511
+ sampler: The quantum engine or simulator to run the circuits.
512
+ qubits: The qubit(s) to benchmark.
513
+ parameters: The parameters of the experiment.
514
+ rng_or_seed: A np.random.Generator object or seed.
417
515
  Returns:
418
516
  A dictionary from qubits to RandomizedBenchMarkResult objects.
419
517
  """
420
518
 
421
- clifford_group = _single_qubit_cliffords()
422
- c1 = clifford_group.c1_in_xy if use_xy_basis else clifford_group.c1_in_xz
519
+ rng_or_seed = (
520
+ rng_or_seed
521
+ if isinstance(rng_or_seed, np.random.Generator)
522
+ else np.random.default_rng(rng_or_seed)
523
+ )
524
+
525
+ c1 = parameters.gateset()
423
526
 
424
527
  # create circuits
425
528
  circuits_all: list[cirq.AbstractCircuit] = []
426
- for num_cliffords in num_clifford_range:
427
- for _ in range(num_circuits):
428
- circuits_all.append(_create_parallel_rb_circuit(qubits, num_cliffords, c1))
529
+ for num_cliffords in parameters.num_clifford_range:
530
+ for _ in range(parameters.num_circuits):
531
+ circuits_all.append(_create_parallel_rb_circuit(qubits, num_cliffords, c1, rng_or_seed))
429
532
 
430
533
  # run circuits
431
- results = sampler.run_batch(circuits_all, repetitions=repetitions)
534
+ results = sampler.run_batch(circuits_all, repetitions=parameters.repetitions)
432
535
  gnd_probs: dict = {q: [] for q in qubits}
433
536
  idx = 0
434
- for num_cliffords in num_clifford_range:
537
+ for num_cliffords in parameters.num_clifford_range:
435
538
  excited_probs: dict[cirq.Qid, list[float]] = {q: [] for q in qubits}
436
- for _ in range(num_circuits):
539
+ for _ in range(parameters.num_circuits):
437
540
  result = results[idx][0]
438
541
  for qubit in qubits:
439
542
  excited_probs[qubit].append(np.mean(result.measurements[str(qubit)]))
440
543
  idx += 1
441
544
  for qubit in qubits:
442
545
  gnd_probs[qubit].append(1.0 - np.mean(excited_probs[qubit]))
546
+
443
547
  return ParallelRandomizedBenchmarkingResult(
444
- {q: RandomizedBenchMarkResult(num_clifford_range, gnd_probs[q]) for q in qubits}
548
+ {q: RandomizedBenchMarkResult(parameters.num_clifford_range, gnd_probs[q]) for q in qubits}
445
549
  )
446
550
 
447
551
 
@@ -677,9 +781,14 @@ def two_qubit_state_tomography(
677
781
 
678
782
 
679
783
  def _create_parallel_rb_circuit(
680
- qubits: Sequence[cirq.Qid], num_cliffords: int, c1: list
784
+ qubits: Sequence[cirq.Qid],
785
+ num_cliffords: int,
786
+ c1: list[list[ops.SingleQubitCliffordGate]],
787
+ rng: np.random.Generator | None = None,
681
788
  ) -> cirq.Circuit:
682
- sequences_to_zip = [_random_single_q_clifford(qubit, num_cliffords, c1) for qubit in qubits]
789
+ sequences_to_zip = [
790
+ _random_single_q_clifford(qubit, num_cliffords, c1, rng) for qubit in qubits
791
+ ]
683
792
  # Ensure each sequence has the same number of moments.
684
793
  num_moments = max(len(sequence) for sequence in sequences_to_zip)
685
794
  for q, sequence in zip(qubits, sequences_to_zip):
@@ -730,11 +839,14 @@ def _two_qubit_clifford_matrices(q_0: cirq.Qid, q_1: cirq.Qid, cliffords: Cliffo
730
839
 
731
840
 
732
841
  def _random_single_q_clifford(
733
- qubit: cirq.Qid, num_cfds: int, cfds: Sequence[Sequence[cirq.ops.SingleQubitCliffordGate]]
842
+ qubit: cirq.Qid,
843
+ num_cfds: int,
844
+ cfds: Sequence[Sequence[cirq.ops.SingleQubitCliffordGate]],
845
+ rng: np.random.Generator | None = None,
734
846
  ) -> list[cirq.Operation]:
735
- clifford_group_size = 24
736
847
  operations = [[gate.to_phased_xz_gate()(qubit) for gate in gates] for gates in cfds]
737
- gate_ids = np.random.choice(clifford_group_size, num_cfds).tolist()
848
+ choice_fn = rng.choice if rng else np.random.choice
849
+ gate_ids = choice_fn(len(cfds), num_cfds).tolist()
738
850
  adjoint = _reduce_gate_seq([gate for gate_id in gate_ids for gate in cfds[gate_id]]) ** -1
739
851
  return [op for gate_id in gate_ids for op in operations[gate_id]] + [
740
852
  adjoint.to_phased_xz_gate()(qubit)
@@ -14,6 +14,9 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ import os
18
+ from unittest import mock
19
+
17
20
  import matplotlib.pyplot as plt
18
21
  import numpy as np
19
22
  import pytest
@@ -104,6 +107,7 @@ def test_single_qubit_cliffords():
104
107
  assert num_x <= 1
105
108
 
106
109
 
110
+ @mock.patch.dict(os.environ, clear='CIRQ_TESTING')
107
111
  def test_single_qubit_randomized_benchmarking():
108
112
  # Check that the ground state population at the end of the Clifford
109
113
  # sequences is always unity.
@@ -116,7 +120,8 @@ def test_single_qubit_randomized_benchmarking():
116
120
  assert np.isclose(results.pauli_error(), 0.0, atol=1e-7) # warning is expected
117
121
 
118
122
 
119
- def test_parallel_single_qubit_randomized_benchmarking():
123
+ @mock.patch.dict(os.environ, clear='CIRQ_TESTING')
124
+ def test_parallel_single_qubit_parallel_single_qubit_randomized_benchmarking():
120
125
  # Check that the ground state population at the end of the Clifford
121
126
  # sequences is always unity.
122
127
  simulator = sim.Simulator()
@@ -229,13 +234,24 @@ def test_tomography_plot_raises_for_incorrect_number_of_axes():
229
234
  result.plot(axes)
230
235
 
231
236
 
232
- def test_single_qubit_cliffords_gateset():
237
+ @pytest.mark.parametrize('num_cliffords', range(5, 10))
238
+ @pytest.mark.parametrize('use_xy_basis', [False, True])
239
+ @pytest.mark.parametrize('strict_basis', [False, True])
240
+ def test_single_qubit_cliffords_gateset(num_cliffords, use_xy_basis, strict_basis):
233
241
  qubits = [GridQubit(0, i) for i in range(4)]
234
- clifford_group = cirq.experiments.qubit_characterizations._single_qubit_cliffords()
242
+ c1_in_xy = cirq.experiments.qubit_characterizations.RBParameters(
243
+ use_xy_basis=use_xy_basis, strict_basis=strict_basis
244
+ ).gateset()
245
+ if strict_basis:
246
+ assert len(c1_in_xy) == 20
247
+ else:
248
+ assert len(c1_in_xy) == 24
235
249
  c = cirq.experiments.qubit_characterizations._create_parallel_rb_circuit(
236
- qubits, 5, clifford_group.c1_in_xy
250
+ qubits, num_cliffords, c1_in_xy
237
251
  )
238
252
  device = cirq.testing.ValidatingTestDevice(
239
253
  qubits=qubits, allowed_gates=(cirq.ops.PhasedXZGate, cirq.MeasurementGate)
240
254
  )
241
255
  device.validate_circuit(c)
256
+
257
+ assert len(c) == num_cliffords + 2
@@ -30,8 +30,9 @@ from cirq import ops, value, vis
30
30
  from cirq._compat import cached_method
31
31
  from cirq.experiments import random_quantum_circuit_generation as rqcg
32
32
  from cirq.experiments.qubit_characterizations import (
33
- parallel_single_qubit_randomized_benchmarking,
33
+ parallel_single_qubit_rb,
34
34
  ParallelRandomizedBenchmarkingResult,
35
+ RBParameters,
35
36
  )
36
37
  from cirq.experiments.xeb_fitting import (
37
38
  benchmark_2q_xeb_fidelities,
@@ -586,12 +587,14 @@ def run_rb_and_xeb(
586
587
 
587
588
  qubits, pairs = qubits_and_pairs(sampler, qubits, pairs)
588
589
 
589
- rb = parallel_single_qubit_randomized_benchmarking(
590
+ rb = parallel_single_qubit_rb(
590
591
  sampler=sampler,
591
592
  qubits=qubits,
592
- repetitions=repetitions,
593
- num_circuits=num_circuits,
594
- num_clifford_range=num_clifford_range,
593
+ parameters=RBParameters(
594
+ num_circuits=num_circuits,
595
+ repetitions=repetitions,
596
+ num_clifford_range=num_clifford_range,
597
+ ),
595
598
  )
596
599
 
597
600
  xeb = parallel_two_qubit_xeb(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cirq-core
3
- Version: 1.6.0.dev20250708194540
3
+ Version: 1.6.0.dev20250710201614
4
4
  Summary: A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
5
5
  Home-page: http://github.com/quantumlib/cirq
6
6
  Author: The Cirq Developers
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=emXpdD5ZvwLRlFAoQB8YatmZyU3b4e9jg6FppMTUhkU,33900
4
4
  cirq/_doc.py,sha256=BrnoABo1hk5RgB3Cgww4zLHUfiyFny0F1V-tOMCbdaU,2909
5
5
  cirq/_import.py,sha256=ixBu4EyGl46Ram2cP3p5eZVEFDW5L2DS-VyTjz4N9iw,8429
6
6
  cirq/_import_test.py,sha256=oF4izzOVZLc7NZ0aZHFcGv-r01eiFFt_JORx_x7_D4s,1089
7
- cirq/_version.py,sha256=5oG9gU9cqqdiqs3o6hGtmfEJR4EziOoYF4cif-v8BhY,1278
8
- cirq/_version_test.py,sha256=zwK3BOP8XiYHsxdC8GpFR_cbti8p18KAdZJEX8uF1m8,155
7
+ cirq/_version.py,sha256=m4hvsoxwoTZW7nkIKNqyHusG5pkALz-3Xdvl2rSL-1A,1278
8
+ cirq/_version_test.py,sha256=M_J_DJkVg3XLVn4B7SC8WbPAqgWw3TF6OpKiEmr774U,155
9
9
  cirq/conftest.py,sha256=wSDKNdIQRDfLnXvOCWD3erheOw8JHRhdfQ53EyTUIXg,1239
10
10
  cirq/json_resolver_cache.py,sha256=hYyG53VJeV61X0oukK5ndZYega8lkL2FyaL1m0j6h5M,13556
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -16,12 +16,12 @@ cirq/circuits/_box_drawing_character_data.py,sha256=hExbMJHm9LGORhlhNiUvPiHquv4p
16
16
  cirq/circuits/_box_drawing_character_data_test.py,sha256=GyiNQDtiu_drzEe_y8DOXCFRYDKr2k8KetXN5RVDp18,1668
17
17
  cirq/circuits/_bucket_priority_queue.py,sha256=U564r2mou4aZsOlpVYiZCgirqS6mVznG3ESyawBt4gE,6749
18
18
  cirq/circuits/_bucket_priority_queue_test.py,sha256=MOby-UKYZQMe2n4KhqkfDCPrz-T_3eBbWDEa0_nadJQ,5627
19
- cirq/circuits/circuit.py,sha256=qrqB_dxLSOBOL39NP9yEibApEPtZc8AiHx71GJK6aWM,119540
19
+ cirq/circuits/circuit.py,sha256=pdRVuMGfCAjoBn5bh01IBR6EoiB8oOtChX_HvI6vBqk,122669
20
20
  cirq/circuits/circuit_operation.py,sha256=Bkmf3rY0QYwS8UC1c1rJpvfbSrQcYVkvSX45Hv059uQ,36302
21
21
  cirq/circuits/circuit_operation_test.py,sha256=JqRjSqt--Weceog4CAl4iZW8CNy0qJ_2svUyeAR6D-s,49411
22
- cirq/circuits/circuit_test.py,sha256=onltKv_LnYK9qqqUpIYgitVtoGyBIDA1LqgLAPT0JdI,164304
23
- cirq/circuits/frozen_circuit.py,sha256=CwlREZbCCrHJ6zTLLEbER_M7P4IsBEADhM5dbDBTvvM,9152
24
- cirq/circuits/frozen_circuit_test.py,sha256=b-SQdV7KFLt3KCo50eBkGs8q29B2H5PmMevVGk8UCN4,4294
22
+ cirq/circuits/circuit_test.py,sha256=Q1ywfvVp6ThmtkAKTk-5bq0cVKctncL0d1qoWxTL_r4,166579
23
+ cirq/circuits/frozen_circuit.py,sha256=UXwABQqBSnSKqSWmRluQPD09xZU0orSW3b3IHvDqxUw,7903
24
+ cirq/circuits/frozen_circuit_test.py,sha256=1Uk3g9St_nJFmu3IJ5hAcXWJjLfWFUXTCKQU1b0JJrE,5321
25
25
  cirq/circuits/insert_strategy.py,sha256=3995vK4U6O9RV4BXMoFl9Tf3ekxIiqxv71IuX80JtYo,3237
26
26
  cirq/circuits/insert_strategy_test.py,sha256=pBFgsylgRG1CS1h4JyzZQFP-xvh6fSbgpiZgxXfbpr4,1237
27
27
  cirq/circuits/moment.py,sha256=MK8H9YUQ44ofLdM1E_zOrJ4Sh5Ayh4ezDtwZkx1O-1E,28363
@@ -180,15 +180,15 @@ cirq/devices/thermal_noise_model.py,sha256=LIGlA6ikYWqbh-759RqXPMDMpCV2uKHT_pRLf
180
180
  cirq/devices/thermal_noise_model_test.py,sha256=vgloNkmkNes_pn0D50-LD2RUcsMJey7EN8Wm6Nc-d5U,12282
181
181
  cirq/devices/unconstrained_device.py,sha256=wa94uVzaCPb1jmG3h6hSGJQggSuCvEK8wekkGXCOx_Q,1551
182
182
  cirq/devices/unconstrained_device_test.py,sha256=J8vABVWWywQuX6Jlo5Y0pWTh6VZRatdmjdBL6u0kZKk,1083
183
- cirq/experiments/__init__.py,sha256=Pl86-y9EoQuz8_XkzYGUcaiBJQKsWwVE4oG_sCORIb0,3645
183
+ cirq/experiments/__init__.py,sha256=3y8FX6Edh_mEFJ7AWjhDurnSLxuEt0_edqL7CitCrTQ,3777
184
184
  cirq/experiments/fidelity_estimation.py,sha256=2wq4gFZ6XYzk3NUGbyNn7EZT911XEHcZot1RD4825mc,9264
185
185
  cirq/experiments/fidelity_estimation_test.py,sha256=On0O1StB6Fo85xuK6BWo-zZWb2at-GqhAgpSrNRBn3I,4955
186
186
  cirq/experiments/n_qubit_tomography.py,sha256=16u0Tv14SyUM9WCk-ZxbBit9cl93MbZodGrj16XiBuo,8436
187
187
  cirq/experiments/n_qubit_tomography_test.py,sha256=8wIgs0O8DtlCGOyC0MZA_d3tLNoURX1ARcqnnp1360g,4439
188
188
  cirq/experiments/purity_estimation.py,sha256=0F5uWh0pqNJ9RZQtNBzGeF8OUpapGFeqPWWVsdpEA7k,2503
189
189
  cirq/experiments/purity_estimation_test.py,sha256=OF3EtFBg7ZqPSBfRJK_-1ji2-xrNVEuD77lHO8Sm3Jc,959
190
- cirq/experiments/qubit_characterizations.py,sha256=1ly0iYWcXVxOicsZehIOukHZQtqtNrlad44MIDdJdXU,36617
191
- cirq/experiments/qubit_characterizations_test.py,sha256=A0_BjQnjeOxXlR2kC7gEwtmssTnv8kR0ljAQA4hOGoQ,9752
190
+ cirq/experiments/qubit_characterizations.py,sha256=BKvi1_A7nOT24lxT8zsTWdqeORMUIV_yhQFUS5gy6bE,40673
191
+ cirq/experiments/qubit_characterizations_test.py,sha256=RZzyuQwYm9tHtQSZLigJnQcyhZdCzE7OiuyETQSiHxo,10319
192
192
  cirq/experiments/random_quantum_circuit_generation.py,sha256=pV6ubukLLdfPXLvJD2t979rVDCOTM32X6SB65vExeE4,28012
193
193
  cirq/experiments/random_quantum_circuit_generation_test.py,sha256=4GSfUK2hw2r90JAO7R2zSBqjtwWi8vXuAhw-iK6quwY,16512
194
194
  cirq/experiments/readout_confusion_matrix.py,sha256=ro3miCMr8K-EDW918PHKL_QcqrDUT-_uTXUvJ1PPzEI,20666
@@ -199,7 +199,7 @@ cirq/experiments/t1_decay_experiment.py,sha256=ojtmkQ5mgiQ-cK389YrvlRXotzHon83HN
199
199
  cirq/experiments/t1_decay_experiment_test.py,sha256=vjm-zV0a2yrFrFhzq03GOMBy5U_XnvX1Ga3NN4FiT3k,9262
200
200
  cirq/experiments/t2_decay_experiment.py,sha256=w4W7QvdIPW5LO9KeREpMFJpFpz0F0wA9T9qPs1t4Mzw,19135
201
201
  cirq/experiments/t2_decay_experiment_test.py,sha256=b2ikIWTctvAp66GZftmVJ1z0mgS-eN0FsUU7bErG7Cg,15066
202
- cirq/experiments/two_qubit_xeb.py,sha256=JKv6B5iH3HXhiJQ4qG2BldVzWu1kinZNHpxJeZdDHVA,22771
202
+ cirq/experiments/two_qubit_xeb.py,sha256=7CXYU1W-qijnp-1831zT-lEXCx6GeEJoCf6QOBvBChw,22803
203
203
  cirq/experiments/two_qubit_xeb_test.py,sha256=MSwdIOcfFy9d-GZUzz4f-2_gblleR89dPIyC8pt_AsQ,10689
204
204
  cirq/experiments/xeb_fitting.py,sha256=SaiamG0gc36bC6ilecZwJou-taEh3REWJAwg5F47DEA,30306
205
205
  cirq/experiments/xeb_fitting_test.py,sha256=q4d-6dPnnN_E9Qw9laip-opsfhdftJuY3QZfEh_u7Wo,15483
@@ -1220,8 +1220,8 @@ cirq/work/sampler.py,sha256=rxbMWvrhu3gfNSBjZKozw28lLKVvBAS_1EGyPdYe8Xg,19041
1220
1220
  cirq/work/sampler_test.py,sha256=SsMrRvLDYELyOAWLKISjkdEfrBwLYWRsT6D8WrsLM3Q,13533
1221
1221
  cirq/work/zeros_sampler.py,sha256=Fs2JWwq0n9zv7_G5Rm-9vPeHUag7uctcMOHg0JTkZpc,2371
1222
1222
  cirq/work/zeros_sampler_test.py,sha256=lQLgQDGBLtfImryys2HzQ2jOSGxHgc7-koVBUhv8qYk,3345
1223
- cirq_core-1.6.0.dev20250708194540.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1224
- cirq_core-1.6.0.dev20250708194540.dist-info/METADATA,sha256=nQaHL2Zt5HnbS80R-g9r6ZzzwW2OLtXlbaIdbhitiks,4857
1225
- cirq_core-1.6.0.dev20250708194540.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1226
- cirq_core-1.6.0.dev20250708194540.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1227
- cirq_core-1.6.0.dev20250708194540.dist-info/RECORD,,
1223
+ cirq_core-1.6.0.dev20250710201614.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1224
+ cirq_core-1.6.0.dev20250710201614.dist-info/METADATA,sha256=dH62aYT8Qf5VpA7jOWI5gAcL9yT-duDKmBy5905yxUg,4857
1225
+ cirq_core-1.6.0.dev20250710201614.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1226
+ cirq_core-1.6.0.dev20250710201614.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1227
+ cirq_core-1.6.0.dev20250710201614.dist-info/RECORD,,