cirq-core 1.6.0.dev20250707183524__py3-none-any.whl → 1.6.0.dev20250708003832__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.dev20250707183524"
32
+ __version__ = "1.6.0.dev20250708003832"
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.dev20250707183524"
6
+ assert cirq.__version__ == "1.6.0.dev20250708003832"
cirq/circuits/moment.py CHANGED
@@ -24,6 +24,7 @@ from typing import (
24
24
  Any,
25
25
  Callable,
26
26
  cast,
27
+ Hashable,
27
28
  Iterable,
28
29
  Iterator,
29
30
  Mapping,
@@ -77,7 +78,12 @@ class Moment:
77
78
  are no such operations, returns an empty Moment.
78
79
  """
79
80
 
80
- def __init__(self, *contents: cirq.OP_TREE, _flatten_contents: bool = True) -> None:
81
+ def __init__(
82
+ self,
83
+ *contents: cirq.OP_TREE,
84
+ _flatten_contents: bool = True,
85
+ tags: tuple[Hashable, ...] = (),
86
+ ) -> None:
81
87
  """Constructs a moment with the given operations.
82
88
 
83
89
  Args:
@@ -88,6 +94,12 @@ class Moment:
88
94
  we skip flattening and assume that contents already consists
89
95
  of individual operations. This is used internally by helper
90
96
  methods to avoid unnecessary validation.
97
+ tags: Optional tags to denote specific Moment objects with meta-data.
98
+ These are a tuple of any Hashable object. Typically, a class
99
+ will be passed. Tags apply only to this specific set of operations
100
+ and will be lost on any transformation of the
101
+ Moment. For instance, if operations are added to the Moment, tags
102
+ will be dropped unless explicitly added back in by the user.
91
103
 
92
104
  Raises:
93
105
  ValueError: A qubit appears more than once.
@@ -110,9 +122,10 @@ class Moment:
110
122
 
111
123
  self._measurement_key_objs: frozenset[cirq.MeasurementKey] | None = None
112
124
  self._control_keys: frozenset[cirq.MeasurementKey] | None = None
125
+ self._tags = tags
113
126
 
114
127
  @classmethod
115
- def from_ops(cls, *ops: cirq.Operation) -> cirq.Moment:
128
+ def from_ops(cls, *ops: cirq.Operation, tags: tuple[Hashable, ...] = ()) -> cirq.Moment:
116
129
  """Construct a Moment from the given operations.
117
130
 
118
131
  This avoids calling `flatten_to_ops` in the moment constructor, which
@@ -122,8 +135,11 @@ class Moment:
122
135
 
123
136
  Args:
124
137
  *ops: Operations to include in the Moment.
138
+ tags: Optional tags to denote specific Moment objects with meta-data.
139
+ These are a tuple of any Hashable object. Tags will be dropped if
140
+ the operations in the Moment are modified or transformed.
125
141
  """
126
- return cls(*ops, _flatten_contents=False)
142
+ return cls(*ops, _flatten_contents=False, tags=tags)
127
143
 
128
144
  @property
129
145
  def operations(self) -> tuple[cirq.Operation, ...]:
@@ -133,6 +149,34 @@ class Moment:
133
149
  def qubits(self) -> frozenset[cirq.Qid]:
134
150
  return frozenset(self._qubit_to_op)
135
151
 
152
+ @property
153
+ def tags(self) -> tuple[Hashable, ...]:
154
+ """Returns a tuple of the operation's tags."""
155
+ return self._tags
156
+
157
+ def with_tags(self, *new_tags: Hashable) -> cirq.Moment:
158
+ """Creates a new Moment with the current ops and the specified tags.
159
+
160
+ If the moment already has tags, this will add the new_tags to the
161
+ preexisting tags.
162
+
163
+ This method can be used to attach meta-data to moments
164
+ without affecting their functionality. The intended usage is to
165
+ attach classes intended for this purpose or strings to mark operations
166
+ for specific usage that will be recognized by consumers.
167
+
168
+ Tags can be a list of any type of object that is useful to identify
169
+ this operation as long as the type is hashable. If you wish the
170
+ resulting operation to be eventually serialized into JSON, you should
171
+ also restrict the operation to be JSON serializable.
172
+
173
+ Please note that tags should be instantiated if classes are
174
+ used. Raw types are not allowed.
175
+ """
176
+ if not new_tags:
177
+ return self
178
+ return Moment(*self._operations, _flatten_contents=False, tags=(*self._tags, *new_tags))
179
+
136
180
  def operates_on_single_qubit(self, qubit: cirq.Qid) -> bool:
137
181
  """Determines if the moment has operations touching the given qubit.
138
182
  Args:
@@ -170,6 +214,8 @@ class Moment:
170
214
  def with_operation(self, operation: cirq.Operation) -> cirq.Moment:
171
215
  """Returns an equal moment, but with the given op added.
172
216
 
217
+ Any tags on the Moment will be dropped.
218
+
173
219
  Args:
174
220
  operation: The operation to append.
175
221
 
@@ -198,6 +244,9 @@ class Moment:
198
244
  def with_operations(self, *contents: cirq.OP_TREE) -> cirq.Moment:
199
245
  """Returns a new moment with the given contents added.
200
246
 
247
+ Any tags on the original Moment object are dropped if the Moment
248
+ is changed.
249
+
201
250
  Args:
202
251
  *contents: New operations to add to this moment.
203
252
 
@@ -235,6 +284,9 @@ class Moment:
235
284
  def without_operations_touching(self, qubits: Iterable[cirq.Qid]) -> cirq.Moment:
236
285
  """Returns an equal moment, but without ops on the given qubits.
237
286
 
287
+ Any tags on the original Moment object are dropped if the Moment
288
+ is changed.
289
+
238
290
  Args:
239
291
  qubits: Operations that touch these will be removed.
240
292
 
@@ -510,11 +562,13 @@ class Moment:
510
562
  return qis.kraus_to_superoperator(self._kraus_())
511
563
 
512
564
  def _json_dict_(self) -> dict[str, Any]:
513
- return protocols.obj_to_dict_helper(self, ['operations'])
565
+ # For backwards compatibility, only output tags if they exist.
566
+ args = ['operations', 'tags'] if self._tags else ['operations']
567
+ return protocols.obj_to_dict_helper(self, args)
514
568
 
515
569
  @classmethod
516
- def _from_json_dict_(cls, operations, **kwargs):
517
- return cls.from_ops(*operations)
570
+ def _from_json_dict_(cls, operations, tags=(), **kwargs):
571
+ return cls(*operations, tags=tags)
518
572
 
519
573
  def __add__(self, other: cirq.OP_TREE) -> cirq.Moment:
520
574
  if isinstance(other, circuit.AbstractCircuit):
@@ -939,3 +939,68 @@ def test_superoperator() -> None:
939
939
  assert m._has_superoperator_()
940
940
  s = m._superoperator_()
941
941
  assert np.allclose(s, np.array([[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0], [1, 0, 0, 1]]) / 2)
942
+
943
+
944
+ def test_moment_with_tags() -> None:
945
+ q0 = cirq.LineQubit(0)
946
+ q1 = cirq.LineQubit(1)
947
+ op1 = cirq.X(q0)
948
+ op2 = cirq.Y(q1)
949
+
950
+ # Test initialization with no tags
951
+ moment_no_tags = cirq.Moment(op1)
952
+ assert moment_no_tags.tags == ()
953
+
954
+ # Test initialization with tags
955
+ moment_with_tags = cirq.Moment(op1, op2, tags=("initial_tag_1", "initial_tag_2"))
956
+ assert moment_with_tags.tags == ("initial_tag_1", "initial_tag_2")
957
+
958
+ # Test with_tags method to add new tags
959
+ new_moment = moment_with_tags.with_tags("new_tag_1", "new_tag_2")
960
+
961
+ # Ensure the original moment's tags are unchanged
962
+ assert moment_with_tags.tags == ("initial_tag_1", "initial_tag_2")
963
+
964
+ # Ensure the new moment has both old and new tags
965
+ assert new_moment.tags == ("initial_tag_1", "initial_tag_2", "new_tag_1", "new_tag_2")
966
+
967
+ # Test with_tags on a moment that initially had no tags
968
+ new_moment_from_no_tags = moment_no_tags.with_tags("single_new_tag")
969
+ assert new_moment_from_no_tags.tags == ("single_new_tag",)
970
+
971
+ # Test adding no new tags
972
+ same_moment_tags = moment_with_tags.with_tags()
973
+ assert same_moment_tags.tags == ("initial_tag_1", "initial_tag_2")
974
+
975
+ class CustomTag:
976
+ """Example Hashable Tag"""
977
+
978
+ def __init__(self, value):
979
+ self.value = value
980
+
981
+ def __hash__(self):
982
+ return hash(self.value) # pragma: nocover
983
+
984
+ def __eq__(self, other):
985
+ return isinstance(other, CustomTag) and self.value == other.value # pragma: nocover
986
+
987
+ def __repr__(self):
988
+ return f"CustomTag({self.value})" # pragma: nocover
989
+
990
+ tag_obj = CustomTag("complex_tag")
991
+ moment_with_custom_tag = cirq.Moment(op1, tags=("string_tag", 123, tag_obj))
992
+ assert moment_with_custom_tag.tags == ("string_tag", 123, tag_obj)
993
+
994
+ new_moment_with_custom_tag = moment_with_custom_tag.with_tags(456)
995
+ assert new_moment_with_custom_tag.tags == ("string_tag", 123, tag_obj, 456)
996
+
997
+ # Test that tags are dropped if the Moment is changed.
998
+ moment = cirq.Moment.from_ops(op1, tags=(tag_obj,))
999
+ assert moment.tags == (tag_obj,)
1000
+ assert moment.with_operation(op2).tags == ()
1001
+ assert moment.with_operations(op2).tags == ()
1002
+ assert moment.without_operations_touching([q0]).tags == ()
1003
+
1004
+ # Test that tags are retained if the Moment is unchanged.
1005
+ assert moment.with_operations().tags == (tag_obj,)
1006
+ assert moment.without_operations_touching([q1]).tags == (tag_obj,)
@@ -39,5 +39,28 @@
39
39
  }
40
40
  }
41
41
  ]
42
+ },
43
+ {
44
+ "cirq_type": "Moment",
45
+ "operations": [
46
+ {
47
+ "cirq_type": "SingleQubitPauliStringGateOperation",
48
+ "pauli": {
49
+ "cirq_type": "_PauliX",
50
+ "exponent": 1.0,
51
+ "global_shift": 0.0
52
+ },
53
+ "qubit": {
54
+ "cirq_type": "LineQubit",
55
+ "x": 0
56
+ }
57
+ }
58
+ ],
59
+ "tags": [
60
+ {
61
+ "cirq_type": "Duration",
62
+ "picos": 25000
63
+ }
64
+ ]
42
65
  }
43
- ]
66
+ ]
@@ -2,4 +2,9 @@
2
2
  cirq.X(cirq.LineQubit(0)),
3
3
  cirq.Y(cirq.LineQubit(1)),
4
4
  cirq.Z(cirq.LineQubit(2)),
5
- )]
5
+ ),
6
+ cirq.Moment(
7
+ cirq.X(cirq.LineQubit(0)),
8
+ tags=(cirq.Duration(nanos=25),)
9
+ )
10
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cirq-core
3
- Version: 1.6.0.dev20250707183524
3
+ Version: 1.6.0.dev20250708003832
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=9Pv2Pu8YDHvyhqk1PRy5iem8pH4X4yWc6hA6L0cVDGM,1278
8
- cirq/_version_test.py,sha256=OO92frcOSdonTbC0G6BUYoGu95PmU_wkmKd6JphJE0U,155
7
+ cirq/_version.py,sha256=ygmrzn06EPTbFWOVLRny8R883ka_UHuEY_CF9X3Cbwc,1278
8
+ cirq/_version_test.py,sha256=lyEjEDyqrmP9pddMqZ4Vx_G03nha1k2CAOcBde9gnyU,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
@@ -24,8 +24,8 @@ cirq/circuits/frozen_circuit.py,sha256=CwlREZbCCrHJ6zTLLEbER_M7P4IsBEADhM5dbDBTv
24
24
  cirq/circuits/frozen_circuit_test.py,sha256=b-SQdV7KFLt3KCo50eBkGs8q29B2H5PmMevVGk8UCN4,4294
25
25
  cirq/circuits/insert_strategy.py,sha256=3995vK4U6O9RV4BXMoFl9Tf3ekxIiqxv71IuX80JtYo,3237
26
26
  cirq/circuits/insert_strategy_test.py,sha256=pBFgsylgRG1CS1h4JyzZQFP-xvh6fSbgpiZgxXfbpr4,1237
27
- cirq/circuits/moment.py,sha256=H6PRIo6HajNjeP-Wx5c2xiF31id56fr0FywelO3KZwY,25900
28
- cirq/circuits/moment_test.py,sha256=4zLOOyF-ckx_gKJMJI4ylugcqQDf7Sy2_FQgmdG-L5c,31770
27
+ cirq/circuits/moment.py,sha256=MK8H9YUQ44ofLdM1E_zOrJ4Sh5Ayh4ezDtwZkx1O-1E,28363
28
+ cirq/circuits/moment_test.py,sha256=-RXBe4ZkWTz1n4n5Hdna5HHslAfAn-gqdreMhuZP508,34233
29
29
  cirq/circuits/optimization_pass.py,sha256=W_YYo_9uy5h4ijU_In5n7gG3EvCVp1cJbE1pHD9ci74,6481
30
30
  cirq/circuits/optimization_pass_test.py,sha256=FvCCOZrqVQLYrf_BUAZ6M-sm6dMv00_xsvpN25Op1BA,5914
31
31
  cirq/circuits/qasm_output.py,sha256=qclnyiEnRzkcr0JqzzABuiHD3INkiALmhl1jCW0AYNk,13079
@@ -632,8 +632,8 @@ cirq/protocols/json_test_data/MeasurementType.json,sha256=OjFtbTIm-EweRuREf6jV_Y
632
632
  cirq/protocols/json_test_data/MeasurementType.repr,sha256=GKWPv9INNDbe8VHe-Ef3i1ykQ9aGIxaom-8Q3E4ptYc,64
633
633
  cirq/protocols/json_test_data/MixedUnitaryChannel.json,sha256=S44Yl3LDXyPuvCs_8oU0iA4hXvm4k11_FnQ-FwrE11A,2890
634
634
  cirq/protocols/json_test_data/MixedUnitaryChannel.repr,sha256=btyHCJZOc0KUvNHOCYqvsDkPi352tjy9O7Zf4XI5zL8,486
635
- cirq/protocols/json_test_data/Moment.json,sha256=iTcMbe_lKBpAKmcQT62y9CDwORvkoUgk_oob71CAKe0,897
636
- cirq/protocols/json_test_data/Moment.repr,sha256=6nuVloJ1MBxO-mWnLHymjO1Ylqsi39RrOpf_S95ccl0,109
635
+ cirq/protocols/json_test_data/Moment.json,sha256=XkNGe04dogNVHWwAPUVFyGJZWHKmFggWoy2-gU6Hm9U,1336
636
+ cirq/protocols/json_test_data/Moment.repr,sha256=zmD-5J0nOIrJzqDxxfKDnhc8RvVghIcJUk8pNTCyyOg,194
637
637
  cirq/protocols/json_test_data/MultiAsymmetricDepolarizingChannel.json,sha256=FQ68e4brRCsjN_5CL53DeF14QgCqO4V2mjV6HoGMX2c,115
638
638
  cirq/protocols/json_test_data/MultiAsymmetricDepolarizingChannel.repr,sha256=nqLmF-C4XmYAfQ6-uV70uPnHj4fWmiP1axVyWb6DrJA,68
639
639
  cirq/protocols/json_test_data/MultiDepolarizingChannel.json,sha256=Iyhfj1Te8kmiohUbYDliUgq8eSoYmAd2flDtq1UopBU,69
@@ -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.dev20250707183524.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1224
- cirq_core-1.6.0.dev20250707183524.dist-info/METADATA,sha256=pV7QD-hP8acoFCJZyJWCcvZn1hnsSBIGY1Mwvdgoy0s,4857
1225
- cirq_core-1.6.0.dev20250707183524.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1226
- cirq_core-1.6.0.dev20250707183524.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1227
- cirq_core-1.6.0.dev20250707183524.dist-info/RECORD,,
1223
+ cirq_core-1.6.0.dev20250708003832.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1224
+ cirq_core-1.6.0.dev20250708003832.dist-info/METADATA,sha256=VMbtjwjbwGyd4SMU1VaROP5loZQ0AQnbXXrKoEdTX5Y,4857
1225
+ cirq_core-1.6.0.dev20250708003832.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1226
+ cirq_core-1.6.0.dev20250708003832.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1227
+ cirq_core-1.6.0.dev20250708003832.dist-info/RECORD,,