cirq-core 1.6.0.dev20250507172716__py3-none-any.whl → 1.6.0.dev20250507225534__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/__init__.py CHANGED
@@ -363,6 +363,7 @@ from cirq.transformers import (
363
363
  eject_z as eject_z,
364
364
  expand_composite as expand_composite,
365
365
  HardCodedInitialMapper as HardCodedInitialMapper,
366
+ index_tags as index_tags,
366
367
  is_negligible_turn as is_negligible_turn,
367
368
  LineInitialMapper as LineInitialMapper,
368
369
  MappingManager as MappingManager,
@@ -385,6 +386,7 @@ from cirq.transformers import (
385
386
  prepare_two_qubit_state_using_sqrt_iswap as prepare_two_qubit_state_using_sqrt_iswap,
386
387
  quantum_shannon_decomposition as quantum_shannon_decomposition,
387
388
  RouteCQC as RouteCQC,
389
+ remove_tags as remove_tags,
388
390
  routed_circuit_with_mapping as routed_circuit_with_mapping,
389
391
  SqrtIswapTargetGateset as SqrtIswapTargetGateset,
390
392
  single_qubit_matrix_to_gates as single_qubit_matrix_to_gates,
cirq/_version.py CHANGED
@@ -28,4 +28,4 @@ if sys.version_info < (3, 10, 0): # pragma: no cover
28
28
  'of cirq (e.g. "python -m pip install cirq==1.1.*")'
29
29
  )
30
30
 
31
- __version__ = "1.6.0.dev20250507172716"
31
+ __version__ = "1.6.0.dev20250507225534"
cirq/_version_test.py CHANGED
@@ -3,4 +3,4 @@ import cirq
3
3
 
4
4
 
5
5
  def test_version():
6
- assert cirq.__version__ == "1.6.0.dev20250507172716"
6
+ assert cirq.__version__ == "1.6.0.dev20250507225534"
@@ -65,7 +65,7 @@ def clifford_optimized_circuit(circuit: circuits.Circuit, atol: float = 1e-8) ->
65
65
  furthest_i = i
66
66
  break
67
67
  if cont_cond == CONTINUE:
68
- modified_op = modified_op.pass_operations_over([op], after_to_before=True)
68
+ modified_op = modified_op.conjugated_by(protocols.inverse(op))
69
69
  num_passed_over += 1
70
70
  if len(modified_op.pauli_string) == 1:
71
71
  furthest_op = modified_op
@@ -122,7 +122,7 @@ def clifford_optimized_circuit(circuit: circuits.Circuit, atol: float = 1e-8) ->
122
122
  all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
123
123
  elif isinstance(other_op, ops.PauliStringPhasor):
124
124
  # Pass over a non-Clifford gate
125
- mod_op = other_op.pass_operations_over([part_cliff_gate(qubit)])
125
+ mod_op = other_op.conjugated_by([part_cliff_gate(qubit)])
126
126
  all_ops[merge_i] = mod_op
127
127
  all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
128
128
  elif merge_i > start_i + 1 and num_passed > 0:
@@ -53,7 +53,7 @@ def _sorted_best_string_placements(
53
53
  ):
54
54
  # This is as far through as this Pauli string can move
55
55
  break
56
- string_op = string_op.pass_operations_over([out_op], after_to_before=True)
56
+ string_op = string_op.conjugated_by(protocols.inverse(out_op))
57
57
  curr = (string_op, i + 1, possible_node)
58
58
  if sort_key(curr) > sort_key(node_max):
59
59
  node_max = curr
@@ -89,8 +89,9 @@ def pauli_string_half(circuit: circuits.Circuit) -> circuits.Circuit:
89
89
 
90
90
 
91
91
  def _pull_non_clifford_before(circuit: circuits.Circuit) -> Iterator[ops.OP_TREE]:
92
- def _iter_ops_range_reversed(moment_end):
93
- for i in reversed(range(moment_end)):
92
+
93
+ def _iter_ops_range(moment_end):
94
+ for i in range(moment_end):
94
95
  moment = circuit[i]
95
96
  for op in moment.operations:
96
97
  if not isinstance(op, ops.PauliStringPhasor):
@@ -99,5 +100,5 @@ def _pull_non_clifford_before(circuit: circuits.Circuit) -> Iterator[ops.OP_TREE
99
100
  for i, moment in enumerate(circuit):
100
101
  for op in moment.operations:
101
102
  if isinstance(op, ops.PauliStringPhasor):
102
- ops_to_cross = _iter_ops_range_reversed(i)
103
- yield op.pass_operations_over(ops_to_cross)
103
+ ops_to_cross = _iter_ops_range(i)
104
+ yield op.conjugated_by(ops_to_cross)
cirq/ops/pauli_string.py CHANGED
@@ -45,6 +45,7 @@ import numpy as np
45
45
  import sympy
46
46
 
47
47
  from cirq import _compat, linalg, protocols, qis, value
48
+ from cirq._compat import deprecated
48
49
  from cirq._doc import document
49
50
  from cirq._import import LazyLoader
50
51
  from cirq.ops import (
@@ -1070,9 +1071,10 @@ class PauliString(raw_types.Operation, Generic[TKey]):
1070
1071
  """
1071
1072
  return self.conjugated_by(ops)
1072
1073
 
1074
+ @deprecated(deadline="v2.0", fix="Use conjuagetd_by()/before()/after() instead.")
1073
1075
  def pass_operations_over(
1074
1076
  self, ops: Iterable[cirq.Operation], after_to_before: bool = False
1075
- ) -> PauliString:
1077
+ ) -> PauliString: # pragma: no cover
1076
1078
  """Determines how the Pauli string changes when conjugated by Cliffords.
1077
1079
 
1078
1080
  The output and input pauli strings are related by a circuit equivalence.
@@ -1099,9 +1101,6 @@ class PauliString(raw_types.Operation, Generic[TKey]):
1099
1101
  pauli string, instead of before (and so are moving in the
1100
1102
  opposite direction).
1101
1103
  """
1102
- # TODO(#6946): deprecate this method.
1103
- # Note: This method is supposed to be replaced by conjugated_by()
1104
- # (see #2351 for details).
1105
1104
  if after_to_before:
1106
1105
  return self.after(ops)
1107
1106
 
@@ -30,7 +30,7 @@ from typing import (
30
30
  import sympy
31
31
 
32
32
  from cirq import protocols, value
33
- from cirq._compat import proper_repr
33
+ from cirq._compat import deprecated, proper_repr
34
34
  from cirq.ops import (
35
35
  common_gates,
36
36
  dense_pauli_string as dps,
@@ -199,9 +199,21 @@ class PauliStringPhasor(gate_operation.GateOperation):
199
199
  syms = tuple(sym(qubit) for qubit in qubits)
200
200
  return protocols.CircuitDiagramInfo(wire_symbols=syms, exponent=self.exponent_relative)
201
201
 
202
+ def conjugated_by(self, clifford: 'cirq.OP_TREE') -> 'PauliStringPhasor':
203
+ r"""Returns the Pauli string conjugated by a clifford operation.
204
+
205
+ The PauliStringPhasor $P$ conjugated by the Clifford operation $C$ is
206
+ $C^\dagger P C$.
207
+ """
208
+ new_pauli_string: ps.PauliString = self.pauli_string.conjugated_by(clifford)
209
+ pp = self.exponent_pos
210
+ pn = self.exponent_neg
211
+ return PauliStringPhasor(new_pauli_string, exponent_pos=pp, exponent_neg=pn)
212
+
213
+ @deprecated(deadline="v2.0", fix="Use conjuagetd_by() instead.")
202
214
  def pass_operations_over(
203
215
  self, ops: Iterable[raw_types.Operation], after_to_before: bool = False
204
- ) -> PauliStringPhasor:
216
+ ) -> PauliStringPhasor: # pragma: no cover
205
217
  """Determines how the Pauli phasor changes when conjugated by Cliffords.
206
218
 
207
219
  The output and input pauli phasors are related by a circuit equivalence.
@@ -228,7 +240,12 @@ class PauliStringPhasor(gate_operation.GateOperation):
228
240
  pauli string, instead of before (and so are moving in the
229
241
  opposite direction).
230
242
  """
231
- new_pauli_string = self.pauli_string.pass_operations_over(ops, after_to_before)
243
+ new_pauli_string: ps.PauliString = ps.PauliString()
244
+ if after_to_before:
245
+ new_pauli_string = self.pauli_string.after(ops)
246
+ else:
247
+ all_ops = list(op_tree.flatten_to_ops(ops))
248
+ new_pauli_string = self.pauli_string.before(all_ops[::-1])
232
249
  pp = self.exponent_pos
233
250
  pn = self.exponent_neg
234
251
  return PauliStringPhasor(new_pauli_string, exponent_pos=pp, exponent_neg=pn)
@@ -155,7 +155,7 @@ def test_consistent():
155
155
  cirq.testing.assert_implements_consistent_protocols(p)
156
156
 
157
157
 
158
- def test_pass_operations_over():
158
+ def test_conjugated_by():
159
159
  q0, q1 = _make_qubits(2)
160
160
  op = cirq.SingleQubitCliffordGate.from_double_map(
161
161
  {cirq.Z: (cirq.X, False), cirq.X: (cirq.Z, False)}
@@ -164,10 +164,7 @@ def test_pass_operations_over():
164
164
  ps_after = cirq.PauliString({q0: cirq.Z, q1: cirq.Y}, -1)
165
165
  before = cirq.PauliStringPhasor(ps_before, exponent_neg=0.1)
166
166
  after = cirq.PauliStringPhasor(ps_after, exponent_neg=0.1)
167
- assert before.pass_operations_over([op]).pauli_string == after.pauli_string
168
- assert (
169
- after.pass_operations_over([op], after_to_before=True).pauli_string == before.pauli_string
170
- )
167
+ assert before.conjugated_by(op).pauli_string == after.pauli_string
171
168
 
172
169
 
173
170
  def test_extrapolate_effect():
@@ -14,7 +14,6 @@
14
14
 
15
15
  import itertools
16
16
  import math
17
- from typing import List
18
17
 
19
18
  import numpy as np
20
19
  import pytest
@@ -723,118 +722,6 @@ def test_to_z_basis_ops_product_state():
723
722
  )
724
723
 
725
724
 
726
- def _assert_pass_over(ops: List[cirq.Operation], before: cirq.PauliString, after: cirq.PauliString):
727
- assert before.pass_operations_over(ops[::-1]) == after
728
- assert after.pass_operations_over(ops, after_to_before=True) == before
729
-
730
-
731
- @pytest.mark.parametrize('shift,sign', itertools.product(range(3), (-1, +1)))
732
- def test_pass_operations_over_single(shift: int, sign: int):
733
- q0, q1 = _make_qubits(2)
734
- X, Y, Z = (cirq.Pauli.by_relative_index(pauli, shift) for pauli in (cirq.X, cirq.Y, cirq.Z))
735
-
736
- op0 = cirq.SingleQubitCliffordGate.from_pauli(Y)(q1)
737
- ps_before: cirq.PauliString[cirq.Qid] = cirq.PauliString({q0: X}, sign)
738
- ps_after = ps_before
739
- _assert_pass_over([op0], ps_before, ps_after)
740
-
741
- op0 = cirq.SingleQubitCliffordGate.from_pauli(X)(q0)
742
- op1 = cirq.SingleQubitCliffordGate.from_pauli(Y)(q1)
743
- ps_before = cirq.PauliString({q0: X, q1: Y}, sign)
744
- ps_after = ps_before
745
- _assert_pass_over([op0, op1], ps_before, ps_after)
746
-
747
- op0 = cirq.SingleQubitCliffordGate.from_double_map({Z: (X, False), X: (Z, False)})(q0)
748
- ps_before = cirq.PauliString({q0: X, q1: Y}, sign)
749
- ps_after = cirq.PauliString({q0: Z, q1: Y}, sign)
750
- _assert_pass_over([op0], ps_before, ps_after)
751
-
752
- op1 = cirq.SingleQubitCliffordGate.from_pauli(X)(q1)
753
- ps_before = cirq.PauliString({q0: X, q1: Y}, sign)
754
- ps_after = -ps_before
755
- _assert_pass_over([op1], ps_before, ps_after)
756
-
757
- ps_after = cirq.PauliString({q0: Z, q1: Y}, -sign)
758
- _assert_pass_over([op0, op1], ps_before, ps_after)
759
-
760
- op0 = cirq.SingleQubitCliffordGate.from_pauli(Z, True)(q0)
761
- op1 = cirq.SingleQubitCliffordGate.from_pauli(X, True)(q0)
762
- ps_before = cirq.PauliString({q0: X}, sign)
763
- ps_after = cirq.PauliString({q0: Y}, -sign)
764
- _assert_pass_over([op0, op1], ps_before, ps_after)
765
-
766
-
767
- @pytest.mark.parametrize(
768
- 'shift,t_or_f1, t_or_f2,neg', itertools.product(range(3), *((True, False),) * 3)
769
- )
770
- def test_pass_operations_over_double(shift: int, t_or_f1: bool, t_or_f2: bool, neg: bool):
771
- sign = -1 if neg else +1
772
- q0, q1, q2 = _make_qubits(3)
773
- X, Y, Z = (cirq.Pauli.by_relative_index(pauli, shift) for pauli in (cirq.X, cirq.Y, cirq.Z))
774
-
775
- op0 = cirq.PauliInteractionGate(Z, t_or_f1, X, t_or_f2)(q0, q1)
776
- ps_before = cirq.PauliString(qubit_pauli_map={q0: Z, q2: Y}, coefficient=sign)
777
- ps_after = cirq.PauliString(qubit_pauli_map={q0: Z, q2: Y}, coefficient=sign)
778
- assert_conjugation(ps_before, op0, ps_after, True)
779
- _assert_pass_over([op0], ps_before, ps_after)
780
-
781
- op0 = cirq.PauliInteractionGate(Y, t_or_f1, X, t_or_f2)(q0, q1)
782
- ps_before = cirq.PauliString({q0: Z, q2: Y}, sign)
783
- ps_after = cirq.PauliString({q0: Z, q2: Y, q1: X}, -sign if t_or_f2 else sign)
784
- assert_conjugation(ps_before, op0, ps_after, True)
785
- _assert_pass_over([op0], ps_before, ps_after)
786
-
787
- op0 = cirq.PauliInteractionGate(Z, t_or_f1, X, t_or_f2)(q0, q1)
788
- ps_before = cirq.PauliString({q0: Z, q1: Y}, sign)
789
- ps_after = cirq.PauliString({q1: Y}, -sign if t_or_f1 else sign)
790
- assert_conjugation(ps_before, op0, ps_after, True)
791
- _assert_pass_over([op0], ps_before, ps_after)
792
-
793
- op0 = cirq.PauliInteractionGate(Y, t_or_f1, X, t_or_f2)(q0, q1)
794
- ps_before = cirq.PauliString({q0: Z, q1: Y}, sign)
795
- ps_after = cirq.PauliString({q0: X, q1: Z}, -1 if neg ^ t_or_f1 ^ t_or_f2 else +1)
796
- assert_conjugation(ps_before, op0, ps_after, True)
797
- _assert_pass_over([op0], ps_before, ps_after)
798
-
799
- op0 = cirq.PauliInteractionGate(X, t_or_f1, X, t_or_f2)(q0, q1)
800
- ps_before = cirq.PauliString({q0: Z, q1: Y}, sign)
801
- ps_after = cirq.PauliString({q0: Y, q1: Z}, +1 if neg ^ t_or_f1 ^ t_or_f2 else -1)
802
- assert_conjugation(ps_before, op0, ps_after, True)
803
- _assert_pass_over([op0], ps_before, ps_after)
804
-
805
-
806
- def test_pass_operations_over_cz():
807
- q0, q1 = _make_qubits(2)
808
- op0 = cirq.CZ(q0, q1)
809
- ps_before = cirq.PauliString({q0: cirq.Z, q1: cirq.Y})
810
- ps_after = cirq.PauliString({q1: cirq.Y})
811
- _assert_pass_over([op0], ps_before, ps_after)
812
-
813
-
814
- def test_pass_operations_over_no_common_qubits():
815
- class ExampleGate(cirq.testing.SingleQubitGate):
816
-
817
- def _decompose_(self, qubits):
818
- return cirq.X(qubits[0])
819
-
820
- q0, q1 = _make_qubits(2)
821
- op0 = ExampleGate()(q1)
822
- ps_before = cirq.PauliString({q0: cirq.Z})
823
- ps_after = cirq.PauliString({q0: cirq.Z})
824
- _assert_pass_over([op0], ps_before, ps_after)
825
-
826
-
827
- def test_pass_unsupported_operations_over():
828
- (q0,) = _make_qubits(1)
829
- pauli_string = cirq.PauliString({q0: cirq.X})
830
- with pytest.raises(
831
- ValueError,
832
- match='Clifford Gate can only be constructed from the operations'
833
- ' that has stabilizer effect.',
834
- ):
835
- pauli_string.pass_operations_over([cirq.T(q0)])
836
-
837
-
838
725
  def test_with_qubits():
839
726
  old_qubits = cirq.LineQubit.range(9)
840
727
  new_qubits = cirq.LineQubit.range(9, 18)
@@ -1637,40 +1524,6 @@ def test_conjugated_by_ordering():
1637
1524
  assert out1 == out2 == cirq.X(a) * cirq.Z(b)
1638
1525
 
1639
1526
 
1640
- def test_pass_operations_over_ordering():
1641
- class OrderSensitiveGate(cirq.Gate):
1642
- def num_qubits(self):
1643
- return 2
1644
-
1645
- def _decompose_(self, qubits):
1646
- return [cirq.Y(qubits[0]) ** -0.5, cirq.CNOT(*qubits)]
1647
-
1648
- a, b = cirq.LineQubit.range(2)
1649
- inp = cirq.Z(b)
1650
- out1 = inp.pass_operations_over(OrderSensitiveGate().on(a, b))
1651
- out2 = inp.pass_operations_over([cirq.CNOT(a, b), cirq.Y(a) ** -0.5])
1652
- out3 = inp.pass_operations_over([cirq.CNOT(a, b)]).pass_operations_over([cirq.Y(a) ** -0.5])
1653
- assert out1 == out2 == out3 == cirq.X(a) * cirq.Z(b)
1654
-
1655
-
1656
- def test_pass_operations_over_ordering_reversed():
1657
- class OrderSensitiveGate(cirq.Gate):
1658
- def num_qubits(self):
1659
- return 2
1660
-
1661
- def _decompose_(self, qubits):
1662
- return [cirq.Y(qubits[0]) ** -0.5, cirq.CNOT(*qubits)]
1663
-
1664
- a, b = cirq.LineQubit.range(2)
1665
- inp = cirq.X(a) * cirq.Z(b)
1666
- out1 = inp.pass_operations_over(OrderSensitiveGate().on(a, b), after_to_before=True)
1667
- out2 = inp.pass_operations_over([cirq.Y(a) ** -0.5, cirq.CNOT(a, b)], after_to_before=True)
1668
- out3 = inp.pass_operations_over([cirq.Y(a) ** -0.5], after_to_before=True).pass_operations_over(
1669
- [cirq.CNOT(a, b)], after_to_before=True
1670
- )
1671
- assert out1 == out2 == out3 == cirq.Z(b)
1672
-
1673
-
1674
1527
  def test_pretty_print():
1675
1528
  a, b, c = cirq.LineQubit.range(3)
1676
1529
  result = cirq.PauliString({a: 'x', b: 'y', c: 'z'})
@@ -119,6 +119,8 @@ from cirq.transformers.transformer_api import (
119
119
  transformer as transformer,
120
120
  )
121
121
 
122
+ from cirq.transformers.tag_transformers import index_tags as index_tags, remove_tags as remove_tags
123
+
122
124
  from cirq.transformers.transformer_primitives import (
123
125
  map_moments as map_moments,
124
126
  map_operations as map_operations,
@@ -0,0 +1,95 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import itertools
16
+ from typing import Callable, Hashable, Optional, TYPE_CHECKING
17
+
18
+ from cirq.transformers import transformer_api, transformer_primitives
19
+
20
+ if TYPE_CHECKING:
21
+ import cirq
22
+
23
+
24
+ @transformer_api.transformer
25
+ def index_tags(
26
+ circuit: 'cirq.AbstractCircuit',
27
+ *,
28
+ context: Optional['cirq.TransformerContext'] = None,
29
+ target_tags: Optional[set[Hashable]] = None,
30
+ ) -> 'cirq.Circuit':
31
+ """Indexes tags in target_tags as tag_0, tag_1, ... per tag.
32
+
33
+ Args:
34
+ circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
35
+ context: `cirq.TransformerContext` storing common configurable options for transformers.
36
+ target_tags: Tags to be indexed.
37
+
38
+ Returns:
39
+ Copy of the transformed input circuit.
40
+ """
41
+ if context and context.tags_to_ignore:
42
+ raise ValueError("index_tags doesn't support tags_to_ignore, use function args instead.")
43
+ if not target_tags:
44
+ return circuit.unfreeze(copy=False)
45
+ tag_iter_by_tags = {tag: itertools.count(start=0, step=1) for tag in target_tags}
46
+
47
+ def _map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
48
+ tag_set = set(op.tags)
49
+ nonlocal tag_iter_by_tags
50
+ for tag in target_tags.intersection(op.tags):
51
+ tag_set.remove(tag)
52
+ tag_set.add(f"{tag}_{next(tag_iter_by_tags[tag])}")
53
+
54
+ return op.untagged.with_tags(*tag_set)
55
+
56
+ return transformer_primitives.map_operations(
57
+ circuit, _map_func, deep=context.deep if context else False
58
+ ).unfreeze(copy=False)
59
+
60
+
61
+ @transformer_api.transformer
62
+ def remove_tags(
63
+ circuit: 'cirq.AbstractCircuit',
64
+ *,
65
+ context: Optional['cirq.TransformerContext'] = None,
66
+ target_tags: Optional[set[Hashable]] = None,
67
+ remove_if: Callable[[Hashable], bool] = lambda _: False,
68
+ ) -> 'cirq.Circuit':
69
+ """Removes tags from the operations based on the input args.
70
+
71
+ Args:
72
+ circuit: Input circuit to apply the transformations on. The input circuit is not mutated.
73
+ context: `cirq.TransformerContext` storing common configurable options for transformers.
74
+ target_tags: Tags to be removed.
75
+ remove_if: A callable(tag) that returns True if the tag should be removed.
76
+ Defaults to False.
77
+
78
+ Returns:
79
+ Copy of the transformed input circuit.
80
+ """
81
+ if context and context.tags_to_ignore:
82
+ raise ValueError("remove_tags doesn't support tags_to_ignore, use function args instead.")
83
+ target_tags = target_tags or set()
84
+
85
+ def _map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
86
+ remaing_tags = set()
87
+ for tag in op.tags:
88
+ if not remove_if(tag) and tag not in target_tags:
89
+ remaing_tags.add(tag)
90
+
91
+ return op.untagged.with_tags(*remaing_tags)
92
+
93
+ return transformer_primitives.map_operations(
94
+ circuit, _map_func, deep=context.deep if context else False
95
+ ).unfreeze(copy=False)
@@ -0,0 +1,101 @@
1
+ # Copyright 2025 The Cirq Developers
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import pytest
16
+
17
+ import cirq
18
+
19
+
20
+ def check_same_circuit_with_same_tag_sets(circuit1, circuit2):
21
+ for op1, op2 in zip(circuit1.all_operations(), circuit2.all_operations()):
22
+ assert set(op1.tags) == set(op2.tags)
23
+ assert op1.untagged == op2.untagged
24
+
25
+
26
+ def test_index_tags():
27
+ q0, q1 = cirq.LineQubit.range(2)
28
+ input_circuit = cirq.Circuit(
29
+ cirq.X(q0).with_tags("tag1", "tag2"),
30
+ cirq.Y(q1).with_tags("tag1"),
31
+ cirq.CZ(q0, q1).with_tags("tag2"),
32
+ )
33
+ expected_circuit = cirq.Circuit(
34
+ cirq.X(q0).with_tags("tag1_0", "tag2_0"),
35
+ cirq.Y(q1).with_tags("tag1_1"),
36
+ cirq.CZ(q0, q1).with_tags("tag2_1"),
37
+ )
38
+ check_same_circuit_with_same_tag_sets(
39
+ cirq.index_tags(input_circuit, target_tags={"tag1", "tag2"}), expected_circuit
40
+ )
41
+
42
+
43
+ def test_index_tags_empty_target_tags():
44
+ q0, q1 = cirq.LineQubit.range(2)
45
+ input_circuit = cirq.Circuit(
46
+ cirq.X(q0).with_tags("tag1", "tag2"),
47
+ cirq.Y(q1).with_tags("tag1"),
48
+ cirq.CZ(q0, q1).with_tags("tag2"),
49
+ )
50
+ check_same_circuit_with_same_tag_sets(
51
+ cirq.index_tags(input_circuit, target_tags={}), input_circuit
52
+ )
53
+
54
+
55
+ def test_remove_tags():
56
+ q0, q1 = cirq.LineQubit.range(2)
57
+ input_circuit = cirq.Circuit(
58
+ cirq.X(q0).with_tags("tag1", "tag2"),
59
+ cirq.Y(q1).with_tags("tag1"),
60
+ cirq.CZ(q0, q1).with_tags("tag2"),
61
+ )
62
+ expected_circuit = cirq.Circuit(
63
+ cirq.X(q0).with_tags("tag2"), cirq.Y(q1), cirq.CZ(q0, q1).with_tags("tag2")
64
+ )
65
+ check_same_circuit_with_same_tag_sets(
66
+ cirq.remove_tags(input_circuit, target_tags={"tag1"}), expected_circuit
67
+ )
68
+
69
+
70
+ def test_remove_tags_via_remove_if():
71
+ q0, q1 = cirq.LineQubit.range(2)
72
+ input_circuit = cirq.Circuit(
73
+ cirq.X(q0).with_tags("tag1", "tag2"),
74
+ cirq.Y(q1).with_tags("not_tag1"),
75
+ cirq.CZ(q0, q1).with_tags("tag2"),
76
+ )
77
+ expected_circuit = cirq.Circuit(cirq.X(q0), cirq.Y(q1).with_tags("not_tag1"), cirq.CZ(q0, q1))
78
+ check_same_circuit_with_same_tag_sets(
79
+ cirq.remove_tags(input_circuit, remove_if=lambda tag: tag.startswith("tag")),
80
+ expected_circuit,
81
+ )
82
+
83
+
84
+ def test_index_tags_with_tags_to_ignore():
85
+ with pytest.raises(
86
+ ValueError, match="index_tags doesn't support tags_to_ignore, use function args instead."
87
+ ):
88
+ cirq.index_tags(
89
+ circuit=cirq.Circuit(),
90
+ target_tags={"tag0"},
91
+ context=cirq.TransformerContext(tags_to_ignore=["tag0"]),
92
+ )
93
+
94
+
95
+ def test_remove_tags_with_tags_to_ignore():
96
+ with pytest.raises(
97
+ ValueError, match="remove_tags doesn't support tags_to_ignore, use function args instead."
98
+ ):
99
+ cirq.remove_tags(
100
+ circuit=cirq.Circuit(), context=cirq.TransformerContext(tags_to_ignore=["tag0"])
101
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cirq-core
3
- Version: 1.6.0.dev20250507172716
3
+ Version: 1.6.0.dev20250507225534
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
@@ -1,11 +1,11 @@
1
- cirq/__init__.py,sha256=rUfvQDtywCak2mJQoihOSyRjGxQahK-YOv909us0w5M,28132
1
+ cirq/__init__.py,sha256=ecDdbOid5m5VpqO4ZPoXQRuWUanrH3Y7lGzzgNPpiyM,28194
2
2
  cirq/_compat.py,sha256=_DknO27XngcjEidNApRsCzLUWDS4QmDk9M12BaqP5Is,29531
3
3
  cirq/_compat_test.py,sha256=t51ZXkEuomg1SMI871Ws-5pk68DGBsAf2TGNjVXtZ8I,34755
4
4
  cirq/_doc.py,sha256=yDyWUD_2JDS0gShfGRb-rdqRt9-WeL7DhkqX7np0Nko,2879
5
5
  cirq/_import.py,sha256=cfocxtT1BJ4HkfZ-VO8YyIhPP-xfqHDkLrzz6eeO5U0,8421
6
6
  cirq/_import_test.py,sha256=6K_v0riZJXOXUphHNkGA8MY-JcmGlezFaGmvrNhm3OQ,1015
7
- cirq/_version.py,sha256=AlgIUe9cSvcXSaC_wG3KpjK_MoYOIokHORQMpjdCAo8,1206
8
- cirq/_version_test.py,sha256=CNrADm0MI1iCUSMW43mxKZgonXXBw4OENMp_s3jqZmw,147
7
+ cirq/_version.py,sha256=hTB6q5KLlQenUB_P9SCUo9H4op-PatyQxgikmCkf8U0,1206
8
+ cirq/_version_test.py,sha256=Yt9Dr26wo6Uhn7hGIoGN0kOoBnN7KUfd5ymMAIBGxCE,147
9
9
  cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
10
10
  cirq/json_resolver_cache.py,sha256=-4KqEEYb6aps-seafnFTHTp3SZc0D8mr4O-pCKIajn8,13653
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -88,7 +88,7 @@ cirq/contrib/noise_models/__init__.py,sha256=O3wvaQ6kyNZzwsCnMMZvr2EyS76LpO9xnVZ
88
88
  cirq/contrib/noise_models/noise_models.py,sha256=i1hCLuI4c6DLMQzBenK1ghAvfnrGKCYgow7tl8Pjf5Q,7674
89
89
  cirq/contrib/noise_models/noise_models_test.py,sha256=nELHWYWbRp6RCurjTSEAumpZPMY2gNN3S4Mhho3pwJ0,10488
90
90
  cirq/contrib/paulistring/__init__.py,sha256=1k2_MYLTMPn8AFoJvSgpN-F-6xgmDjKXRhb-FdDsFoQ,1761
91
- cirq/contrib/paulistring/clifford_optimize.py,sha256=zeap55snqMQZL7GiDHCdQztgsRlVYlEsAFYmPtrEBwo,7849
91
+ cirq/contrib/paulistring/clifford_optimize.py,sha256=bdS4pXjBxcJhFiL_jsVeS4Odcd-D02FtyxLVVsWi4LU,7830
92
92
  cirq/contrib/paulistring/clifford_optimize_test.py,sha256=Q8REpwDRNEHVYl3yxfzxN7c5dsQLhZSkk842xaKvFrw,3889
93
93
  cirq/contrib/paulistring/clifford_target_gateset.py,sha256=7TyfG3ieJluz8AziQKFCT1EgRKLzWu2aoUGAEcLblGw,6369
94
94
  cirq/contrib/paulistring/clifford_target_gateset_test.py,sha256=Q_Zqbfp6yVzLabpKLnhIFCnGBaCgsgiABXCuAixwySQ,8668
@@ -100,9 +100,9 @@ cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py,sha
100
100
  cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py,sha256=yPFWcZiVkUcwwpjQQsT135JPmj9p5KOS9urzNqUWAfQ,35501
101
101
  cirq/contrib/paulistring/pauli_string_optimize.py,sha256=QhowjgeI0vXg_XvF7FmpUgGgDJP9xCbsYS8_womA4Ho,2903
102
102
  cirq/contrib/paulistring/pauli_string_optimize_test.py,sha256=2wSpV7EVwuuK8wI_Pp31V4vCIkq-CEmQz3EjaFWi8fM,2895
103
- cirq/contrib/paulistring/recombine.py,sha256=zm5AJL80Xl4hgTe9U1YUEgWfcHZys_YcWNpnv02DcL0,4355
103
+ cirq/contrib/paulistring/recombine.py,sha256=Q_0RCTfg5i7WaqoynimpYXkuSuE2BIov8jYcan8V1Gk,4343
104
104
  cirq/contrib/paulistring/recombine_test.py,sha256=ClvleI2hVVBOA7sbi3yTth-fErJQYYCw-6ebAvXt-Ns,1915
105
- cirq/contrib/paulistring/separate.py,sha256=clzMvgTUyEW1l-fghk3EYUsKZNOBicy1l2MiuZaoc7o,3960
105
+ cirq/contrib/paulistring/separate.py,sha256=dtGwqXxEiRCxo21wV8uAlA1E3GKQGxr3FuQWqy-jTdM,3926
106
106
  cirq/contrib/paulistring/separate_test.py,sha256=FzR78MSHDhNJxizbXreK6u3BeYhT7xn7W1QyHfEZ34E,1267
107
107
  cirq/contrib/qasm_import/__init__.py,sha256=RKX0vGDC2Pe5rH5rM4ClXdvtrAU16ePFImQpiJtJVNo,744
108
108
  cirq/contrib/qasm_import/_lexer.py,sha256=RkrbOoT5flW_NEzdxRgv4nbmJ1mWJWlENPf7aPAVM9Y,2929
@@ -339,12 +339,12 @@ cirq/ops/pauli_interaction_gate.py,sha256=hGYmC1i8UCDDJ6e3ML6M8GeW-byq_dLoNv5UvB
339
339
  cirq/ops/pauli_interaction_gate_test.py,sha256=adnIIgCvFzO-inNaN77HER-WJ0hg6L63_HfiT60oV3M,4543
340
340
  cirq/ops/pauli_measurement_gate.py,sha256=R64b1zbnwecKTkZHXzOcro21OubDu-wibRk5ppwFfLk,7217
341
341
  cirq/ops/pauli_measurement_gate_test.py,sha256=acKmYvwSQniIX2FtOCVrIPRPmyUBeV4uNUFmyShJixE,6778
342
- cirq/ops/pauli_string.py,sha256=c_9fAJQJR17SZYNCi02AhCdJj5L9zkjZJlgUA1cQv7w,66785
343
- cirq/ops/pauli_string_phasor.py,sha256=OEF2xW5NM0y_4wcL6BLoN_RfBFeQkksh6QcO1qlwyDA,17476
344
- cirq/ops/pauli_string_phasor_test.py,sha256=PT2PmSeXG8JS45gyUrVpXdTifwpNTCmU0ASUZ9WDk1Q,27865
342
+ cirq/ops/pauli_string.py,sha256=OUqhn_gdf3RkYM3G1amiPaHMU89kOUBCSA3AFaWjGnI,66771
343
+ cirq/ops/pauli_string_phasor.py,sha256=WZTsn6ed5H0M3io7ErMrPjFYP9o5huWN63zuabR6PYw,18280
344
+ cirq/ops/pauli_string_phasor_test.py,sha256=R6YLz66Q1Mh2BblMVmXpdR32iNRy_TK1mPENfbzz3G4,27731
345
345
  cirq/ops/pauli_string_raw_types.py,sha256=200Epv_YmR33YVEL8wT198S04GAruyG7I0xVtVk8oqk,2269
346
346
  cirq/ops/pauli_string_raw_types_test.py,sha256=SZPluslZPGffPq93F5apESBygWZ2cj7BEX6dQuawRQE,2648
347
- cirq/ops/pauli_string_test.py,sha256=OcOUSiR-ja1yfEr3GY8Mx3yogmDwr6_yCuXOU2XF3W4,78869
347
+ cirq/ops/pauli_string_test.py,sha256=t4nrqnunT412KzOKac5Wb9NdiZGoR8exWy31GmFXmSk,72831
348
348
  cirq/ops/pauli_sum_exponential.py,sha256=o-OsJ6SfsYNnMdSTpAaL1uauTKh9SLL3oLLoh7y4IV0,4868
349
349
  cirq/ops/pauli_sum_exponential_test.py,sha256=Vi2-0zDUCS4XtFn9dfmkgh9dH2ncuKYOiQLCZPoLMkg,5369
350
350
  cirq/ops/permutation_gate.py,sha256=uLd0qZgT4eDKO22Me9HGSDD7Hnf1Ol3ddkwJ7ZghL3U,4224
@@ -1046,7 +1046,7 @@ cirq/testing/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
1046
1046
  cirq/testing/test_data/test_module_missing_json_test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1047
1047
  cirq/testing/test_data/test_module_missing_testspec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1048
1048
  cirq/testing/test_data/test_module_missing_testspec/json_test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1049
- cirq/transformers/__init__.py,sha256=QjYovkmQHRi7D6nPHkWrszVBM_1__thvOXG4wcYvX_E,6905
1049
+ cirq/transformers/__init__.py,sha256=8k80MycPGQzZdJztV4eDpDAo6qpV7SA7GbG2vFiBAcg,7006
1050
1050
  cirq/transformers/align.py,sha256=XmARu30-wwsWMB-3z0K8WJ7zyErrdsTtgXgMDm4co6A,3355
1051
1051
  cirq/transformers/align_test.py,sha256=AI26PxERbtJDfjKtoz17xVAKn6TSr-9pyImqfr5LJWc,7686
1052
1052
  cirq/transformers/drop_empty_moments.py,sha256=j7zAoEsPs9JQ_zYpQX2yEvfiViDiYejnaOJ9GsXNbx4,1548
@@ -1081,6 +1081,8 @@ cirq/transformers/stratify.py,sha256=jfZEQuKv1YT8RdtcbGNsUNp4cs0WzZoiet-e5zwfLTc
1081
1081
  cirq/transformers/stratify_test.py,sha256=17ic2VAUPEGuPG2o5j98yDxQ2j2J_PN3EsPsfh5xwUk,15220
1082
1082
  cirq/transformers/synchronize_terminal_measurements.py,sha256=uh3u53xLjQLyZvh6KY-oOk_i6j8VveMeOi_zGdi748I,3856
1083
1083
  cirq/transformers/synchronize_terminal_measurements_test.py,sha256=VTiw5S3s_Y31qR7ME8Mzv50LdJ_6M3DOtgwvtziQzPI,7742
1084
+ cirq/transformers/tag_transformers.py,sha256=7Y5w6sKjT5Ccevwu3EysSMLZ4mZvW9jM2wcAFDqBOnU,3510
1085
+ cirq/transformers/tag_transformers_test.py,sha256=qyA9Z6lVk5lRnml6x63EREMUeyCAnxVfRQeA9KN4a0o,3403
1084
1086
  cirq/transformers/transformer_api.py,sha256=zH4suvb0iLPIJ_znCIpJGag4GSiycdPOk2nbbS14C1w,16961
1085
1087
  cirq/transformers/transformer_api_test.py,sha256=YBkIX-R6vYeQz1Y_sqpzDlvNYszEtfvkegoA8dAVVVc,13286
1086
1088
  cirq/transformers/transformer_primitives.py,sha256=q88fl6KGdJvx5mZqnorZv4oR92JK1k6Jm2JZBbjx4Ms,36642
@@ -1212,8 +1214,8 @@ cirq/work/sampler.py,sha256=b7O3B8bc77KQb8ReLx7qeF8owP1Qwb5_I-RwC6-M_C8,19118
1212
1214
  cirq/work/sampler_test.py,sha256=TBJm3gepuOURwklJTXNdqj0thvdqKUvrZwZqdytJxNY,13313
1213
1215
  cirq/work/zeros_sampler.py,sha256=vHCfqkXmUcPkaDuKHlY-UQ71dUHVroEtm_XW51mZpHs,2390
1214
1216
  cirq/work/zeros_sampler_test.py,sha256=TR3AXYSfg3ETpeaEtrmE-GgZsPtfZkUZ36kyH9JquJk,3313
1215
- cirq_core-1.6.0.dev20250507172716.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1216
- cirq_core-1.6.0.dev20250507172716.dist-info/METADATA,sha256=j--9sDJdwJeC6dRf1vf3ir19WZl8FZuOt1RzpsJtJvo,4908
1217
- cirq_core-1.6.0.dev20250507172716.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
1218
- cirq_core-1.6.0.dev20250507172716.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1219
- cirq_core-1.6.0.dev20250507172716.dist-info/RECORD,,
1217
+ cirq_core-1.6.0.dev20250507225534.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1218
+ cirq_core-1.6.0.dev20250507225534.dist-info/METADATA,sha256=t80B3z06_iMsNyOWwLvSh4xNe_TlVBNQ6tOCihY7rkA,4908
1219
+ cirq_core-1.6.0.dev20250507225534.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
1220
+ cirq_core-1.6.0.dev20250507225534.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1221
+ cirq_core-1.6.0.dev20250507225534.dist-info/RECORD,,