cirq-core 1.6.0.dev20250625011740__py3-none-any.whl → 1.6.0.dev20250625152617__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
@@ -28,4 +28,4 @@ if sys.version_info < (3, 11, 0): # pragma: no cover
28
28
  'of cirq (e.g. "python -m pip install cirq==1.5.0")'
29
29
  )
30
30
 
31
- __version__ = "1.6.0.dev20250625011740"
31
+ __version__ = "1.6.0.dev20250625152617"
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.dev20250625011740"
6
+ assert cirq.__version__ == "1.6.0.dev20250625152617"
cirq/ops/common_gates.py CHANGED
@@ -37,7 +37,14 @@ import cirq
37
37
  from cirq import protocols, value
38
38
  from cirq._compat import proper_repr
39
39
  from cirq._doc import document
40
- from cirq.ops import control_values as cv, controlled_gate, eigen_gate, gate_features, raw_types
40
+ from cirq.ops import (
41
+ control_values as cv,
42
+ controlled_gate,
43
+ eigen_gate,
44
+ gate_features,
45
+ global_phase_op,
46
+ raw_types,
47
+ )
41
48
  from cirq.ops.measurement_gate import MeasurementGate
42
49
  from cirq.ops.swap_gates import ISWAP, ISwapPowGate, SWAP, SwapPowGate
43
50
 
@@ -235,6 +242,11 @@ class XPowGate(eigen_gate.EigenGate):
235
242
  return cirq.CCXPowGate(exponent=self._exponent)
236
243
  return result
237
244
 
245
+ def _decompose_with_context_(
246
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
247
+ ) -> list[cirq.Operation] | NotImplementedType:
248
+ return _extract_phase(self, XPowGate, qubits, context)
249
+
238
250
  def _pauli_expansion_(self) -> value.LinearDict[str]:
239
251
  if self._dimension != 2:
240
252
  return NotImplemented # pragma: no cover
@@ -487,6 +499,11 @@ class YPowGate(eigen_gate.EigenGate):
487
499
  f'global_shift={self._global_shift!r})'
488
500
  )
489
501
 
502
+ def _decompose_with_context_(
503
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
504
+ ) -> list[cirq.Operation] | NotImplementedType:
505
+ return _extract_phase(self, YPowGate, qubits, context)
506
+
490
507
 
491
508
  class Ry(YPowGate):
492
509
  r"""A gate with matrix $e^{-i Y t/2}$ that rotates around the Y axis of the Bloch sphere by $t$.
@@ -699,6 +716,11 @@ class ZPowGate(eigen_gate.EigenGate):
699
716
  return cirq.CCZPowGate(exponent=self._exponent)
700
717
  return result
701
718
 
719
+ def _decompose_with_context_(
720
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
721
+ ) -> list[cirq.Operation] | NotImplementedType:
722
+ return _extract_phase(self, ZPowGate, qubits, context)
723
+
702
724
  def _qid_shape_(self) -> tuple[int, ...]:
703
725
  return (self._dimension,)
704
726
 
@@ -1131,6 +1153,11 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
1131
1153
  control_qid_shape=result.control_qid_shape + (2,),
1132
1154
  )
1133
1155
 
1156
+ def _decompose_with_context_(
1157
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
1158
+ ) -> list[cirq.Operation] | NotImplementedType:
1159
+ return _extract_phase(self, CZPowGate, qubits, context)
1160
+
1134
1161
  def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
1135
1162
  return protocols.CircuitDiagramInfo(
1136
1163
  wire_symbols=('@', '@'), exponent=self._diagram_exponent(args)
@@ -1486,3 +1513,25 @@ def _phased_x_or_pauli_gate(
1486
1513
  case 0.5:
1487
1514
  return YPowGate(exponent=exponent)
1488
1515
  return cirq.ops.PhasedXPowGate(exponent=exponent, phase_exponent=phase_exponent)
1516
+
1517
+
1518
+ def _extract_phase(
1519
+ gate: cirq.EigenGate,
1520
+ gate_class: type,
1521
+ qubits: tuple[cirq.Qid, ...],
1522
+ context: cirq.DecompositionContext,
1523
+ ) -> list[cirq.Operation] | NotImplementedType:
1524
+ """Extracts the global phase field to its own gate, or absorbs it if it has no effect.
1525
+
1526
+ This is for use within the decompose handlers, and will return `NotImplemented` if there is no
1527
+ global phase, implying it is already in its simplest form. It will return a list, with the
1528
+ original op minus any global phase first, and the global phase op second. If the resulting
1529
+ global phase is empty (can happen for example in `XPowGate(global_phase=2/3)**3`), then it is
1530
+ excluded from the return value."""
1531
+ if not context.extract_global_phases or gate.global_shift == 0:
1532
+ return NotImplemented
1533
+ result = [gate_class(exponent=gate.exponent).on(*qubits)]
1534
+ phase_gate = global_phase_op.from_phase_and_exponent(gate.global_shift, gate.exponent)
1535
+ if not phase_gate.is_identity():
1536
+ result.append(phase_gate())
1537
+ return result
@@ -1322,3 +1322,37 @@ def test_parameterized_pauli_expansion(gate_type, exponent) -> None:
1322
1322
  gate_resolved = cirq.resolve_parameters(gate, {'s': 0.5})
1323
1323
  pauli_resolved = cirq.resolve_parameters(pauli, {'s': 0.5})
1324
1324
  assert cirq.approx_eq(pauli_resolved, cirq.pauli_expansion(gate_resolved))
1325
+
1326
+
1327
+ @pytest.mark.parametrize('gate_type', [cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZPowGate])
1328
+ @pytest.mark.parametrize('exponent', [0, 0.5, 2, 3, -0.5, -2, -3, sympy.Symbol('s')])
1329
+ def test_decompose_with_extracted_phases(gate_type: type, exponent: cirq.TParamVal) -> None:
1330
+ context = cirq.DecompositionContext(cirq.SimpleQubitManager(), extract_global_phases=True)
1331
+ test_shift = 2 / 3 # Interesting because e.g. X(shift=2/3) ** 3 == X with no phase
1332
+ gate = gate_type(exponent=exponent, global_shift=test_shift)
1333
+ op = gate.on(*cirq.LineQubit.range(cirq.num_qubits(gate)))
1334
+ decomposed = cirq.decompose(op, context=context)
1335
+
1336
+ # The first gate should be the original gate, but with shift removed.
1337
+ gate0 = decomposed[0].gate
1338
+ assert isinstance(gate0, gate_type)
1339
+ assert isinstance(gate0, cirq.EigenGate)
1340
+ assert gate0.global_shift == 0
1341
+ assert gate0.exponent == exponent
1342
+ if exponent % 3 == 0:
1343
+ # Since test_shift == 2/3, gate**3 nullifies the phase, leaving only the unphased gate.
1344
+ assert len(decomposed) == 1
1345
+ else:
1346
+ # Other exponents emit a global phase gate to compensate.
1347
+ assert len(decomposed) == 2
1348
+ gate1 = decomposed[1].gate
1349
+ assert isinstance(gate1, cirq.GlobalPhaseGate)
1350
+ assert gate1.coefficient == 1j ** (2 * exponent * test_shift)
1351
+
1352
+ # Sanity check that the decomposition is equivalent to the original.
1353
+ decomposed_circuit = cirq.Circuit(decomposed)
1354
+ if cirq.is_parameterized(exponent):
1355
+ resolver = {'s': -1.234} # arbitrary
1356
+ op = cirq.resolve_parameters(op, resolver)
1357
+ decomposed_circuit = cirq.resolve_parameters(decomposed_circuit, resolver)
1358
+ np.testing.assert_allclose(cirq.unitary(op), cirq.unitary(decomposed_circuit), atol=1e-10)
@@ -24,7 +24,6 @@ from cirq.ops import (
24
24
  control_values as cv,
25
25
  controlled_operation as cop,
26
26
  diagonal_gate as dg,
27
- global_phase_op as gp,
28
27
  op_tree,
29
28
  raw_types,
30
29
  )
@@ -139,12 +138,9 @@ class ControlledGate(raw_types.Gate):
139
138
  def _qid_shape_(self) -> tuple[int, ...]:
140
139
  return self.control_qid_shape + protocols.qid_shape(self.sub_gate)
141
140
 
142
- def _decompose_(self, qubits: tuple[cirq.Qid, ...]) -> None | NotImplementedType | cirq.OP_TREE:
143
- return self._decompose_with_context_(qubits)
144
-
145
141
  def _decompose_with_context_(
146
- self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext | None = None
147
- ) -> None | NotImplementedType | cirq.OP_TREE:
142
+ self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
143
+ ) -> NotImplementedType | cirq.OP_TREE:
148
144
  control_qubits = list(qubits[: self.num_controls()])
149
145
  controlled_sub_gate = self.sub_gate.controlled(
150
146
  self.num_controls(), self.control_values, self.control_qid_shape
@@ -152,6 +148,25 @@ class ControlledGate(raw_types.Gate):
152
148
  # Prefer the subgate controlled version if available
153
149
  if self != controlled_sub_gate:
154
150
  return controlled_sub_gate.on(*qubits)
151
+
152
+ # Try decomposing the subgate next.
153
+ result = protocols.decompose_once_with_qubits(
154
+ self.sub_gate,
155
+ qubits[self.num_controls() :],
156
+ NotImplemented,
157
+ flatten=False,
158
+ # Extract global phases from decomposition, as controlled phases decompose easily.
159
+ context=context.extracting_global_phases(),
160
+ )
161
+ if result is not NotImplemented:
162
+ return op_tree.transform_op_tree(
163
+ result,
164
+ lambda op: op.controlled_by(
165
+ *qubits[: self.num_controls()], control_values=self.control_values
166
+ ),
167
+ )
168
+
169
+ # Finally try brute-force on the unitary.
155
170
  if protocols.has_unitary(self.sub_gate) and all(q.dimension == 2 for q in qubits):
156
171
  n_qubits = protocols.num_qubits(self.sub_gate)
157
172
  # Case 1: Global Phase (1x1 Matrix)
@@ -173,54 +188,9 @@ class ControlledGate(raw_types.Gate):
173
188
  protocols.unitary(self.sub_gate), control_qubits, qubits[-1]
174
189
  )
175
190
  return invert_ops + decomposed_ops + invert_ops
176
- if isinstance(self.sub_gate, common_gates.CZPowGate):
177
- z_sub_gate = common_gates.ZPowGate(exponent=self.sub_gate.exponent)
178
- num_controls = self.num_controls() + 1
179
- control_values = self.control_values & cv.ProductOfSums(((1,),))
180
- control_qid_shape = self.control_qid_shape + (2,)
181
- controlled_z = (
182
- z_sub_gate.controlled(
183
- num_controls=num_controls,
184
- control_values=control_values,
185
- control_qid_shape=control_qid_shape,
186
- )
187
- if protocols.is_parameterized(self)
188
- else ControlledGate(
189
- z_sub_gate,
190
- num_controls=num_controls,
191
- control_values=control_values,
192
- control_qid_shape=control_qid_shape,
193
- )
194
- )
195
- if self != controlled_z:
196
- result = controlled_z.on(*qubits)
197
- if self.sub_gate.global_shift == 0:
198
- return result
199
- # Reconstruct the controlled global shift of the subgate.
200
- total_shift = self.sub_gate.exponent * self.sub_gate.global_shift
201
- phase_gate = gp.GlobalPhaseGate(1j ** (2 * total_shift))
202
- controlled_phase_op = phase_gate.controlled(
203
- num_controls=self.num_controls(),
204
- control_values=self.control_values,
205
- control_qid_shape=self.control_qid_shape,
206
- ).on(*control_qubits)
207
- return [result, controlled_phase_op]
208
- result = protocols.decompose_once_with_qubits(
209
- self.sub_gate,
210
- qubits[self.num_controls() :],
211
- NotImplemented,
212
- flatten=False,
213
- context=context,
214
- )
215
- if result is NotImplemented:
216
- return NotImplemented
217
191
 
218
- return op_tree.transform_op_tree(
219
- result,
220
- lambda op: op.controlled_by(
221
- *qubits[: self.num_controls()], control_values=self.control_values
222
- ),
223
- )
192
+ # If nothing works, return `NotImplemented`.
193
+ return NotImplemented
224
194
 
225
195
  def on(self, *qubits: cirq.Qid) -> cop.ControlledOperation:
226
196
  if len(qubits) == 0:
@@ -804,3 +804,31 @@ def test_controlled_global_phase_matrix_gate_decomposes(
804
804
  decomposed = cirq.decompose(cg_matrix(*all_qubits))
805
805
  assert not any(isinstance(op.gate, cirq.MatrixGate) for op in decomposed)
806
806
  np.testing.assert_allclose(cirq.unitary(cirq.Circuit(decomposed)), cirq.unitary(cg_matrix))
807
+
808
+
809
+ @pytest.mark.parametrize('gate_type', [cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZPowGate])
810
+ @pytest.mark.parametrize('test_shift', np.pi * (np.random.default_rng(324).random(10) * 2 - 1))
811
+ def test_controlled_phase_extracted_before_decomposition(gate_type, test_shift) -> None:
812
+ test_shift = 0.123 # arbitrary
813
+
814
+ shifted_gate = gate_type(global_shift=test_shift).controlled()
815
+ unshifted_gate = gate_type().controlled()
816
+ qs = cirq.LineQubit.range(cirq.num_qubits(shifted_gate))
817
+ shifted_op = shifted_gate.on(*qs)
818
+ unshifted_op = unshifted_gate.on(*qs)
819
+ shifted_decomposition = cirq.decompose(shifted_op)
820
+ unshifted_decomposition = cirq.decompose(unshifted_op)
821
+
822
+ # No brute-force calculation. It's the standard decomposition plus Z for the controlled shift.
823
+ assert shifted_decomposition[:-1] == unshifted_decomposition
824
+ z_op = shifted_decomposition[-1]
825
+ assert z_op.qubits == (qs[0],)
826
+ z = z_op.gate
827
+ assert isinstance(z, cirq.ZPowGate)
828
+ np.testing.assert_approx_equal(z.exponent, test_shift)
829
+ assert z.global_shift == 0
830
+
831
+ # Sanity check that the decomposition is equivalent
832
+ np.testing.assert_allclose(
833
+ cirq.unitary(cirq.Circuit(shifted_decomposition)), cirq.unitary(shifted_op), atol=1e-10
834
+ )
@@ -92,6 +92,13 @@ class GlobalPhaseGate(raw_types.Gate):
92
92
  coefficient = protocols.resolve_parameters(self.coefficient, resolver, recursive)
93
93
  return GlobalPhaseGate(coefficient=coefficient)
94
94
 
95
+ def is_identity(self) -> bool:
96
+ """Checks if gate is equivalent to an identity.
97
+
98
+ Returns: True if the coefficient is within rounding error of 1.
99
+ """
100
+ return not protocols.is_parameterized(self._coefficient) and np.isclose(self.coefficient, 1)
101
+
95
102
  def controlled(
96
103
  self,
97
104
  num_controls: int | None = None,
@@ -122,3 +129,23 @@ def global_phase_operation(
122
129
  ) -> cirq.GateOperation:
123
130
  """Creates an operation that represents a global phase on the state."""
124
131
  return GlobalPhaseGate(coefficient, atol)()
132
+
133
+
134
+ def from_phase_and_exponent(
135
+ half_turns: cirq.TParamVal, exponent: cirq.TParamVal
136
+ ) -> cirq.GlobalPhaseGate:
137
+ """Creates a GlobalPhaseGate from the global phase and exponent.
138
+
139
+ Args:
140
+ half_turns: The number of half turns to rotate by.
141
+ exponent: The power to raise the phase to.
142
+
143
+ Returns: A `GlobalPhaseGate` with the corresponding coefficient.
144
+ """
145
+ coefficient = 1j ** (2 * half_turns * exponent)
146
+ coefficient = (
147
+ complex(coefficient)
148
+ if isinstance(coefficient, sympy.Expr) and coefficient.is_complex
149
+ else coefficient
150
+ )
151
+ return GlobalPhaseGate(coefficient)
@@ -19,6 +19,7 @@ import pytest
19
19
  import sympy
20
20
 
21
21
  import cirq
22
+ from cirq.ops import global_phase_op
22
23
 
23
24
 
24
25
  def test_init() -> None:
@@ -304,3 +305,22 @@ def test_global_phase_gate_controlled(coeff, exp) -> None:
304
305
  assert g.controlled(control_values=xor_control_values) == cirq.ControlledGate(
305
306
  g, control_values=xor_control_values
306
307
  )
308
+
309
+
310
+ def test_is_identity() -> None:
311
+ g = cirq.GlobalPhaseGate(1)
312
+ assert g.is_identity()
313
+ g = cirq.GlobalPhaseGate(1j)
314
+ assert not g.is_identity()
315
+ g = cirq.GlobalPhaseGate(-1)
316
+ assert not g.is_identity()
317
+
318
+
319
+ def test_from_phase_and_exponent() -> None:
320
+ g = global_phase_op.from_phase_and_exponent(2.5, 0.5)
321
+ assert g.coefficient == np.exp(1.25j * np.pi)
322
+ a, b = sympy.symbols('a, b')
323
+ g = global_phase_op.from_phase_and_exponent(a, b)
324
+ assert g.coefficient == 1j ** (2 * a * b)
325
+ g = global_phase_op.from_phase_and_exponent(1 / a, a)
326
+ assert g.coefficient == -1
@@ -106,19 +106,11 @@ class CCZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
106
106
  elif not b.is_adjacent(c):
107
107
  a, b = b, a
108
108
 
109
- p = common_gates.T**self._exponent
109
+ exp = self._exponent
110
+ p = common_gates.T**exp
110
111
  sweep_abc = [common_gates.CNOT(a, b), common_gates.CNOT(b, c)]
111
- global_phase = 1j ** (2 * self.global_shift * self._exponent)
112
- global_phase = (
113
- complex(global_phase)
114
- if protocols.is_parameterized(global_phase) and global_phase.is_complex
115
- else global_phase
116
- )
117
- global_phase_operation = (
118
- [global_phase_op.global_phase_operation(global_phase)]
119
- if protocols.is_parameterized(global_phase) or abs(global_phase - 1.0) > 0
120
- else []
121
- )
112
+ global_phase_gate = global_phase_op.from_phase_and_exponent(self.global_shift, exp)
113
+ global_phase_operation = [] if global_phase_gate.is_identity() else [global_phase_gate()]
122
114
  return global_phase_operation + [
123
115
  p(a),
124
116
  p(b),
@@ -81,9 +81,16 @@ class DecompositionContext:
81
81
  Args:
82
82
  qubit_manager: A `cirq.QubitManager` instance to allocate clean / dirty ancilla qubits as
83
83
  part of the decompose protocol.
84
+ extract_global_phases: If set, will extract the global phases from
85
+ `DECOMPOSE_TARGET_GATESET` into independent global phase operations.
84
86
  """
85
87
 
86
88
  qubit_manager: cirq.QubitManager
89
+ extract_global_phases: bool = False
90
+
91
+ def extracting_global_phases(self) -> DecompositionContext:
92
+ """Returns a copy with the `extract_global_phases` field set."""
93
+ return dataclasses.replace(self, extract_global_phases=True)
87
94
 
88
95
 
89
96
  class SupportsDecompose(Protocol):
@@ -445,3 +445,12 @@ def test_decompose_without_context_succeed() -> None:
445
445
  cirq.ops.CleanQubit(1, prefix='_decompose_protocol'),
446
446
  )
447
447
  ]
448
+
449
+
450
+ def test_extracting_global_phases() -> None:
451
+ qm = cirq.SimpleQubitManager()
452
+ context = cirq.DecompositionContext(qm)
453
+ new_context = context.extracting_global_phases()
454
+ assert not context.extract_global_phases
455
+ assert new_context.extract_global_phases
456
+ assert new_context.qubit_manager is qm
@@ -21,26 +21,31 @@ https://arxiv.org/abs/quant-ph/0406176
21
21
 
22
22
  from __future__ import annotations
23
23
 
24
- from typing import Callable, Iterable, TYPE_CHECKING
24
+ from typing import Callable, cast, Iterable, TYPE_CHECKING
25
25
 
26
26
  import numpy as np
27
+ from attr import define
27
28
  from scipy.linalg import cossin
28
29
 
29
30
  from cirq import ops
30
31
  from cirq.circuits.frozen_circuit import FrozenCircuit
31
32
  from cirq.linalg import decompositions, predicates
32
33
  from cirq.protocols import unitary_protocol
33
- from cirq.transformers.analytical_decompositions.three_qubit_decomposition import (
34
- three_qubit_matrix_to_operations,
35
- )
36
34
  from cirq.transformers.analytical_decompositions.two_qubit_to_cz import (
37
35
  two_qubit_matrix_to_cz_operations,
36
+ two_qubit_matrix_to_diagonal_and_cz_operations,
38
37
  )
39
38
 
40
39
  if TYPE_CHECKING:
41
40
  import cirq
42
41
 
43
42
 
43
+ @define
44
+ class _TwoQubitGate:
45
+ location: int
46
+ matrix: np.ndarray
47
+
48
+
44
49
  def quantum_shannon_decomposition(
45
50
  qubits: list[cirq.Qid], u: np.ndarray, atol: float = 1e-8
46
51
  ) -> Iterable[cirq.Operation]:
@@ -67,14 +72,12 @@ def quantum_shannon_decomposition(
67
72
  1. _single_qubit_decomposition
68
73
  OR
69
74
  (Recursive Case)
70
- 1. _msb_demuxer
71
- 2. _multiplexed_cossin
72
- 3. _msb_demuxer
75
+ 1. _recursive_decomposition
73
76
 
74
77
  Yields:
75
78
  A single 2-qubit or 1-qubit operations from OP TREE
76
79
  composed from the set
77
- { CNOT, rz, ry, ZPowGate }
80
+ { CNOT, CZ, rz, ry, ZPowGate }
78
81
 
79
82
  Raises:
80
83
  ValueError: If the u matrix is non-unitary
@@ -98,30 +101,92 @@ def quantum_shannon_decomposition(
98
101
  yield from _single_qubit_decomposition(qubits[0], u)
99
102
  return
100
103
 
101
- if n == 4:
102
- operations = tuple(
103
- two_qubit_matrix_to_cz_operations(
104
- qubits[0], qubits[1], u, allow_partial_czs=True, clean_operations=True, atol=atol
105
- )
104
+ # Collect all operations from the recursive decomposition
105
+ shannon_decomp: list[cirq.Operation | list[cirq.Operation]] = [
106
+ *_recursive_decomposition(qubits, u)
107
+ ]
108
+ # Separate all 2-qubit generic gates while keeping track of location
109
+ two_qubit_gates = [
110
+ _TwoQubitGate(location=loc, matrix=unitary_protocol.unitary(o))
111
+ for loc, o in enumerate(cast(list[ops.Operation], shannon_decomp))
112
+ if isinstance(o.gate, ops.MatrixGate)
113
+ ]
114
+ # Apply case A.2 from Shende et al.
115
+ q0 = qubits[-2]
116
+ q1 = qubits[-1]
117
+ for idx in range(len(two_qubit_gates) - 1, 0, -1):
118
+ diagonal, operations = two_qubit_matrix_to_diagonal_and_cz_operations(
119
+ q0,
120
+ q1,
121
+ two_qubit_gates[idx].matrix,
122
+ allow_partial_czs=True,
123
+ clean_operations=True,
124
+ atol=atol,
106
125
  )
107
- yield from operations
108
- i, j = np.unravel_index(np.argmax(np.abs(u)), u.shape)
109
- new_unitary = unitary_protocol.unitary(FrozenCircuit.from_moments(*operations))
110
- global_phase = np.angle(u[i, j]) - np.angle(new_unitary[i, j])
111
- if np.abs(global_phase) > 1e-9:
112
- yield ops.global_phase_operation(np.exp(1j * global_phase))
113
- return
126
+ global_phase = _global_phase_difference(
127
+ two_qubit_gates[idx].matrix, [ops.MatrixGate(diagonal)(q0, q1), *operations]
128
+ )
129
+ if not np.isclose(global_phase, 0, atol=atol):
130
+ operations.append(ops.global_phase_operation(np.exp(1j * global_phase)))
131
+ # Replace the generic gate with ops from OP TREE
132
+ shannon_decomp[two_qubit_gates[idx].location] = operations
133
+ # Join the diagonal with the unitary to be decomposed in the next step
134
+ two_qubit_gates[idx - 1].matrix = diagonal @ two_qubit_gates[idx - 1].matrix
135
+ if len(two_qubit_gates) > 0:
136
+ operations = two_qubit_matrix_to_cz_operations(
137
+ q0,
138
+ q1,
139
+ two_qubit_gates[0].matrix,
140
+ allow_partial_czs=True,
141
+ clean_operations=True,
142
+ atol=atol,
143
+ )
144
+ global_phase = _global_phase_difference(two_qubit_gates[0].matrix, operations)
145
+ if not np.isclose(global_phase, 0, atol=atol):
146
+ operations.append(ops.global_phase_operation(np.exp(1j * global_phase)))
147
+ shannon_decomp[two_qubit_gates[0].location] = operations
148
+ # Yield the final operations in order
149
+ yield from cast(Iterable[ops.Operation], ops.flatten_op_tree(shannon_decomp))
150
+
151
+
152
+ def _recursive_decomposition(qubits: list[cirq.Qid], u: np.ndarray) -> Iterable[cirq.Operation]:
153
+ """Recursive step in the quantum shannon decomposition.
154
+
155
+ Decomposes n-qubit unitary into generic 2-qubit gates, CNOT, CZ and 1-qubit gates.
156
+ All generic 2-qubit gates are applied to the two least significant qubits and
157
+ are not decomposed further here.
158
+
159
+ Args:
160
+ qubits: List of qubits in order of significance
161
+ u: Numpy array for unitary matrix representing gate to be decomposed
162
+
163
+ Calls:
164
+ 1. _msb_demuxer
165
+ 2. _multiplexed_cossin
166
+ 3. _msb_demuxer
167
+
168
+ Yields:
169
+ Generic 2-qubit gates or operations from {ry,rz,CNOT,CZ}.
114
170
 
115
- if n == 8:
116
- operations = tuple(
117
- three_qubit_matrix_to_operations(qubits[0], qubits[1], qubits[2], u, atol=atol)
171
+ Raises:
172
+ ValueError: If the u matrix is not of shape (2^n,2^n)
173
+ ValueError: If the u matrix is not of size at least 4
174
+ """
175
+ n = u.shape[0]
176
+ if n & (n - 1):
177
+ raise ValueError(
178
+ f"Expected input matrix u to be a (2^n x 2^n) shaped numpy array, \
179
+ but instead got shape {u.shape}"
118
180
  )
119
- yield from operations
120
- i, j = np.unravel_index(np.argmax(np.abs(u)), u.shape)
121
- new_unitary = unitary_protocol.unitary(FrozenCircuit.from_moments(*operations))
122
- global_phase = np.angle(u[i, j]) - np.angle(new_unitary[i, j])
123
- if np.abs(global_phase) > 1e-9:
124
- yield ops.global_phase_operation(np.exp(1j * global_phase))
181
+
182
+ if n <= 2:
183
+ raise ValueError(
184
+ f"Expected input matrix u for recursive step to have size at least 4, \
185
+ but it has size {n}"
186
+ )
187
+
188
+ if n == 4:
189
+ yield ops.MatrixGate(u).on(*qubits)
125
190
  return
126
191
 
127
192
  # Perform a cosine-sine (linalg) decomposition on u
@@ -137,10 +202,30 @@ def quantum_shannon_decomposition(
137
202
  # Yield ops from multiplexed Ry part
138
203
  yield from _multiplexed_cossin(qubits, theta, ops.ry)
139
204
 
205
+ # Optimization A.1 in Shende et al. - the last CZ gate in the multiplexed Ry part
206
+ # is merged into the generic multiplexor (u1, u2)
207
+ # This gate is CZ(qubits[1], qubits[0]) = CZ(qubits[0], qubits[1])
208
+ # as CZ is symmetric.
209
+ # For the u1⊕u2 multiplexor operator:
210
+ # as u1 is the operator in case qubits[0] = |0>,
211
+ # and u2 is the operator in case qubits[0] = |1>
212
+ # we can represent the merge by phasing u2 with Z ⊗ I
213
+ cz_diag = np.concatenate((np.ones(n >> 2), np.full(n >> 2, -1)))
214
+ u2 = u2 @ np.diag(cz_diag)
215
+
140
216
  # Yield ops from decomposition of multiplexed u1/u2 part
141
217
  yield from _msb_demuxer(qubits, u1, u2)
142
218
 
143
219
 
220
+ def _global_phase_difference(u: np.ndarray, ops: list[cirq.Operation]) -> float:
221
+ """Returns the difference in global phase between unitary u and
222
+ a list of operations computing u.
223
+ """
224
+ i, j = np.unravel_index(np.argmax(np.abs(u)), u.shape)
225
+ new_unitary = unitary_protocol.unitary(FrozenCircuit.from_moments(*ops))
226
+ return np.angle(u[i, j]) - np.angle(new_unitary[i, j])
227
+
228
+
144
229
  def _single_qubit_decomposition(qubit: cirq.Qid, u: np.ndarray) -> Iterable[cirq.Operation]:
145
230
  """Decomposes single-qubit gate, and returns list of operations, keeping phase invariant.
146
231
 
@@ -202,11 +287,14 @@ def _msb_demuxer(
202
287
  u2: Lower-right quadrant of total unitary to be decomposed (see diagram)
203
288
 
204
289
  Calls:
205
- 1. quantum_shannon_decomposition
290
+ 1. _recursive_decomposition
206
291
  2. _multiplexed_cossin
207
- 3. quantum_shannon_decomposition
292
+ 3. _recursive_decomposition
208
293
 
209
- Yields: Single operation from OP TREE of 2-qubit and 1-qubit operations
294
+ Yields:
295
+ Generic 2-qubit gates on the two least significant qubits,
296
+ CNOT gates with the target not on the two least significant qubits,
297
+ ry or rz
210
298
  """
211
299
  # Perform a diagonalization to find values
212
300
  u1 = u1.astype(np.complex128)
@@ -231,7 +319,7 @@ def _msb_demuxer(
231
319
  # Last term is given by ( I ⊗ W ), demultiplexed
232
320
  # Remove most-significant (demuxed) control-qubit
233
321
  # Yield operations for QSD on W
234
- yield from quantum_shannon_decomposition(demux_qubits[1:], W, atol=1e-6)
322
+ yield from _recursive_decomposition(demux_qubits[1:], W)
235
323
 
236
324
  # Use complex phase of d_i to give theta_i (so d_i* gives -theta_i)
237
325
  # Observe that middle part looks like Σ_i( Rz(theta_i)⊗|i><i| )
@@ -239,7 +327,7 @@ def _msb_demuxer(
239
327
  yield from _multiplexed_cossin(demux_qubits, -np.angle(d), ops.rz)
240
328
 
241
329
  # Yield operations for QSD on V
242
- yield from quantum_shannon_decomposition(demux_qubits[1:], V, atol=1e-6)
330
+ yield from _recursive_decomposition(demux_qubits[1:], V)
243
331
 
244
332
 
245
333
  def _nth_gray(n: int) -> int:
@@ -263,7 +351,7 @@ def _multiplexed_cossin(
263
351
  Calls:
264
352
  No major calls
265
353
 
266
- Yields: Single operation from OP TREE from set 1- and 2-qubit gates: {ry,rz,CNOT}
354
+ Yields: Single operation from OP TREE from set 1- and 2-qubit gates: {ry,rz,CNOT,CZ}
267
355
  """
268
356
  # Most significant qubit is main qubit with rotation function applied
269
357
  main_qubit = cossin_qubits[0]
@@ -304,4 +392,11 @@ def _multiplexed_cossin(
304
392
  yield rot_func(rotation).on(main_qubit)
305
393
 
306
394
  # Add a CNOT from the select qubit to the main qubit
307
- yield ops.CNOT(control_qubits[select_qubit], main_qubit)
395
+ # Optimization A.1 in Shende et al. - use CZ instead of CNOT for ry rotations
396
+ if rot_func == ops.ry:
397
+ # Don't emit the last gate, as it will be merged into the generic multiplexor
398
+ # in the cosine-sine decomposition
399
+ if j < len(angles) - 1:
400
+ yield ops.CZ(control_qubits[select_qubit], main_qubit)
401
+ else:
402
+ yield ops.CNOT(control_qubits[select_qubit], main_qubit)
@@ -20,10 +20,12 @@ from scipy.stats import unitary_group
20
20
 
21
21
  import cirq
22
22
  from cirq.ops import common_gates
23
+ from cirq.testing import random_two_qubit_circuit_with_czs
23
24
  from cirq.transformers.analytical_decompositions.quantum_shannon_decomposition import (
24
25
  _msb_demuxer,
25
26
  _multiplexed_cossin,
26
27
  _nth_gray,
28
+ _recursive_decomposition,
27
29
  _single_qubit_decomposition,
28
30
  quantum_shannon_decomposition,
29
31
  )
@@ -49,6 +51,14 @@ def test_qsd_n_qubit_errors():
49
51
  cirq.Circuit(quantum_shannon_decomposition(qubits, np.ones((8, 8))))
50
52
 
51
53
 
54
+ def test_recursive_decomposition_n_qubit_errors():
55
+ qubits = [cirq.NamedQubit(f'q{i}') for i in range(3)]
56
+ with pytest.raises(ValueError, match="shaped numpy array"):
57
+ cirq.Circuit(_recursive_decomposition(qubits, np.eye(9)))
58
+ with pytest.raises(ValueError, match="size at least 4"):
59
+ cirq.Circuit(_recursive_decomposition(qubits, np.eye(2)))
60
+
61
+
52
62
  def test_random_single_qubit_decomposition():
53
63
  U = unitary_group.rvs(2)
54
64
  qubit = cirq.NamedQubit('q0')
@@ -80,10 +90,18 @@ def test_multiplexed_cossin():
80
90
  multiplexed_ry = np.array(multiplexed_ry)
81
91
  qubits = [cirq.NamedQubit(f'q{i}') for i in range(2)]
82
92
  circuit = cirq.Circuit(_multiplexed_cossin(qubits, [angle_1, angle_2]))
93
+ # Add back the CZ gate removed by the A.1 optimization
94
+ circuit += cirq.CZ(qubits[1], qubits[0])
83
95
  # Test return is equal to inital unitary
84
96
  assert cirq.approx_eq(multiplexed_ry, circuit.unitary(), atol=1e-9)
85
97
  # Test all operations in gate set
86
- gates = (common_gates.Rz, common_gates.Ry, common_gates.ZPowGate, common_gates.CXPowGate)
98
+ gates = (
99
+ common_gates.Rz,
100
+ common_gates.Ry,
101
+ common_gates.ZPowGate,
102
+ common_gates.CXPowGate,
103
+ common_gates.CZPowGate,
104
+ )
87
105
  assert all(isinstance(op.gate, gates) for op in circuit.all_operations())
88
106
 
89
107
 
@@ -203,3 +221,17 @@ def test_qft5():
203
221
  )
204
222
  new_unitary = cirq.unitary(shannon_circuit)
205
223
  np.testing.assert_allclose(new_unitary, desired_unitary, atol=1e-6)
224
+
225
+
226
+ def test_random_circuit_decomposition():
227
+ qubits = cirq.LineQubit.range(3)
228
+ test_circuit = (
229
+ random_two_qubit_circuit_with_czs(3, qubits[0], qubits[1])
230
+ + random_two_qubit_circuit_with_czs(3, qubits[1], qubits[2])
231
+ + random_two_qubit_circuit_with_czs(3, qubits[0], qubits[2])
232
+ )
233
+ circuit = cirq.Circuit(quantum_shannon_decomposition(qubits, test_circuit.unitary()))
234
+ # Test return is equal to initial unitary
235
+ assert cirq.approx_eq(test_circuit.unitary(), circuit.unitary(), atol=1e-9)
236
+ # Test all operations have at most 2 qubits.
237
+ assert all(cirq.num_qubits(op) <= 2 for op in circuit.all_operations())
@@ -26,7 +26,6 @@ from cirq.linalg.decompositions import extract_right_diag, num_cnots_required
26
26
  from cirq.transformers.analytical_decompositions import single_qubit_decompositions
27
27
  from cirq.transformers.eject_phased_paulis import eject_phased_paulis
28
28
  from cirq.transformers.eject_z import eject_z
29
- from cirq.transformers.merge_single_qubit_gates import merge_single_qubit_gates_to_phased_x_and_z
30
29
 
31
30
  if TYPE_CHECKING:
32
31
  import cirq
@@ -81,8 +80,8 @@ def two_qubit_matrix_to_cz_operations(
81
80
  if clean_operations:
82
81
  if not allow_partial_czs:
83
82
  # CZ^t is not allowed for any $t$ except $t=1$.
84
- return _remove_partial_czs_or_fail(cleanup_operations(operations), atol=atol)
85
- return cleanup_operations(operations)
83
+ return _remove_partial_czs_or_fail(cleanup_operations(operations, atol=atol), atol=atol)
84
+ return cleanup_operations(operations, atol=atol)
86
85
  return operations
87
86
 
88
87
 
@@ -182,15 +181,75 @@ def _xx_yy_zz_interaction_via_full_czs(q0: cirq.Qid, q1: cirq.Qid, x: float, y:
182
181
  yield ops.H(q1)
183
182
 
184
183
 
185
- def cleanup_operations(operations: Sequence[ops.Operation]):
184
+ def cleanup_operations(operations: Sequence[ops.Operation], atol: float = 1e-8):
185
+ operations = _merge_single_qubit_gates(operations, atol=atol)
186
186
  circuit = circuits.Circuit(operations)
187
- circuit = merge_single_qubit_gates_to_phased_x_and_z(circuit)
188
187
  circuit = eject_phased_paulis(circuit)
189
188
  circuit = eject_z(circuit)
190
189
  circuit = circuits.Circuit(circuit.all_operations(), strategy=circuits.InsertStrategy.EARLIEST)
191
190
  return list(circuit.all_operations())
192
191
 
193
192
 
193
+ def _transform_single_qubit_operations_to_phased_x_and_z(
194
+ operations: Sequence[ops.Operation], atol: float
195
+ ) -> Sequence[ops.Operation]:
196
+ """Transforms operations on the same qubit to a PhasedXPowGate followed by a Z gate.
197
+
198
+ Args:
199
+ operations: sequence of operations on the same qubit
200
+ atol: a limit on the amount of absolute error introduced by the
201
+ transformation.
202
+ Returns:
203
+ A PhasedXPowGate followed by a Z gate. If one the gates is not needed, it will be omitted.
204
+ """
205
+ u = np.eye(2)
206
+ for op in operations:
207
+ u = protocols.unitary(op) @ u
208
+ return [
209
+ g(op.qubits[0])
210
+ for g in single_qubit_decompositions.single_qubit_matrix_to_phased_x_z(u, atol=atol)
211
+ ]
212
+
213
+
214
+ def _merge_single_qubit_gates(
215
+ operations: Sequence[ops.Operation], atol: float
216
+ ) -> Sequence[ops.Operation]:
217
+ """Merge consecutive single qubit gates.
218
+
219
+ Traverses the sequence of operations maintaining a list of consecutive single qubit
220
+ operations for each qubit. When a 2-qubit gate is encountered, it transforms pending
221
+ operations to a PhasedXPowGate followed by a Z gate.
222
+
223
+ Args:
224
+ operations: sequence of operations
225
+ atol: a limit on the amount of absolute error introduced by the
226
+ transformation.
227
+ Returns:
228
+ new sequence of operations after merging gates
229
+ """
230
+ merged_ops: list[ops.Operation] = []
231
+ pending_ops: dict[tuple[cirq.Qid, ...], list[ops.Operation]] = dict()
232
+ for op in operations:
233
+ if protocols.num_qubits(op) == 2:
234
+ for _, qubit_ops in pending_ops.items():
235
+ merged_ops.extend(
236
+ _transform_single_qubit_operations_to_phased_x_and_z(qubit_ops, atol=atol)
237
+ )
238
+ pending_ops.clear()
239
+ # Add the 2-qubit gate
240
+ merged_ops.append(op)
241
+ elif protocols.num_qubits(op) == 1:
242
+ if op.qubits not in pending_ops:
243
+ pending_ops[op.qubits] = []
244
+ pending_ops[op.qubits].append(op)
245
+ # Merge remaining pending operations
246
+ for _, qubit_ops in pending_ops.items():
247
+ merged_ops.extend(
248
+ _transform_single_qubit_operations_to_phased_x_and_z(qubit_ops, atol=atol)
249
+ )
250
+ return merged_ops
251
+
252
+
194
253
  def _kak_decomposition_to_operations(
195
254
  q0: cirq.Qid,
196
255
  q1: cirq.Qid,
@@ -261,6 +261,24 @@ def test_decompose_to_diagonal_and_circuit(v) -> None:
261
261
  cirq.testing.assert_allclose_up_to_global_phase(circuit_unitary, v, atol=2e-6)
262
262
 
263
263
 
264
+ @pytest.mark.parametrize(
265
+ "mat, num_czs",
266
+ [
267
+ (cirq.unitary(random_two_qubit_circuit_with_czs(3)), 2),
268
+ (cirq.unitary(random_two_qubit_circuit_with_czs(2)), 2),
269
+ (cirq.unitary(random_two_qubit_circuit_with_czs(1)), 1),
270
+ (cirq.unitary(random_two_qubit_circuit_with_czs(0)), 0),
271
+ ],
272
+ )
273
+ def test_decompose_to_diagonal_and_circuit_returns_circuit_with_expected_number_of_czs(
274
+ mat, num_czs
275
+ ):
276
+ b, c = cirq.LineQubit.range(2)
277
+ _, ops = two_qubit_matrix_to_diagonal_and_cz_operations(b, c, mat, atol=1e-8)
278
+ circuit = cirq.Circuit(ops)
279
+ assert len(list(circuit.findall_operations_with_gate_type(cirq.CZPowGate))) == num_czs
280
+
281
+
264
282
  def test_remove_partial_czs_or_fail() -> None:
265
283
  CZ = cirq.CZ(*cirq.LineQubit.range(2))
266
284
  assert (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cirq-core
3
- Version: 1.6.0.dev20250625011740
3
+ Version: 1.6.0.dev20250625152617
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=IH_yywLC2DP2aoKRwaMc-SSgj8xtbawI_twNVETqkKo,1206
8
- cirq/_version_test.py,sha256=U7bVhNAYqNObqaCFrE56cK-cTnxPKD87NR_9rSy22eY,155
7
+ cirq/_version.py,sha256=WaS6yXNBrQkWyNLtZioFkSEnew96llAnYDIuKKhPb-4,1206
8
+ cirq/_version_test.py,sha256=LhXcrh_kn28Wi96pK1rtGPJU3q_VGDIJsTcF1OWhgYg,155
9
9
  cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
10
10
  cirq/json_resolver_cache.py,sha256=hYyG53VJeV61X0oukK5ndZYega8lkL2FyaL1m0j6h5M,13556
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -283,12 +283,12 @@ cirq/ops/common_channels.py,sha256=BD8-qJDGITOSP0bJVcWGgjbI5dj2dwFkSzzWb-qgfcc,3
283
283
  cirq/ops/common_channels_test.py,sha256=Qzw7nDrWgO1GDB7qkN2YUZi3NDswvvBJ9TEnSNakJX4,30755
284
284
  cirq/ops/common_gate_families.py,sha256=trK4ZXCKqYahZkyuwaAn-TcjUu7gmI9n9geO8PYiRGE,8606
285
285
  cirq/ops/common_gate_families_test.py,sha256=SfIKolQhVIof0uOHljY1QKT9Tu_4WzUsoeCNR2jIOPg,5441
286
- cirq/ops/common_gates.py,sha256=uNDMUj3mru-WsfLPJrxtiXfKfsZ5y8y3Ngha0AsZaXs,56206
287
- cirq/ops/common_gates_test.py,sha256=sTkAbPvfVf9p3N1lqnwkI9gJmTwQfIXPAbyVXFTP0NM,47979
286
+ cirq/ops/common_gates.py,sha256=pnyLK2FurjE6idejtAzgRaawiW-AqiM22w7xMkEpxVs,58221
287
+ cirq/ops/common_gates_test.py,sha256=IcUWxDTTTbis0efXz2Kn0zAdclp9R31fZAfCx3E-BOo,49758
288
288
  cirq/ops/control_values.py,sha256=GrNi8YJZSZDCl8Su6Ocimvd1R1SejFJjVu2thcJ8VLI,13346
289
289
  cirq/ops/control_values_test.py,sha256=Wyn0nwtcpnJvcPVRHmFGb3PtYxvsbpluA5UbPrG7tIo,13067
290
- cirq/ops/controlled_gate.py,sha256=WaimPh4J5tNGf65t6LLylx8l_RBCnqgQhz8DmUPCN5I,15077
291
- cirq/ops/controlled_gate_test.py,sha256=_iXDPtWdRkpTi_zgcY9J9c0gDx35pOmlW7HmT6DSzSw,28039
290
+ cirq/ops/controlled_gate.py,sha256=3Hex9AdY6c_DedKoCqqpS4gx9rAgm9KZITbwUBXsoYg,13562
291
+ cirq/ops/controlled_gate_test.py,sha256=jmIOlCx8dC3VId4NynX1ZYy7s7tkLav_d-fjiIZyVh0,29308
292
292
  cirq/ops/controlled_operation.py,sha256=l0pjUfru39HBuAbBkRCqJmrJDxah0JOFxXXILcUt0v8,13978
293
293
  cirq/ops/controlled_operation_test.py,sha256=qXpnUoeWmOQaTMZPAuuICtX9Idf-JWtdARTsTENv54g,16546
294
294
  cirq/ops/dense_pauli_string.py,sha256=1TijNu1D2HIbbnwLbT_f546R2L4OCQtm1bKjqhno1Kg,24234
@@ -307,8 +307,8 @@ cirq/ops/gate_operation.py,sha256=MF8JIYEM6bQu6ft9Eb19hSOillzu8MmaIoXSlmwbm5U,13
307
307
  cirq/ops/gate_operation_test.py,sha256=4QwWxCjGXNM__6QGw1kYSbBMh_4783jBZVBJD1ERGPk,18020
308
308
  cirq/ops/gateset.py,sha256=9HFW5Sg_jPpao8SEd7XgLdc_6xgUwZfvb6f7pfVPIF8,21492
309
309
  cirq/ops/gateset_test.py,sha256=_dpKTEwXuOY-jpev9rBPEcMy4KZ7zd6GmJ5JkvZAeog,16580
310
- cirq/ops/global_phase_op.py,sha256=Q5GrvuNgpSafUrcYUqEibt8hFoh3ZNeYJ9cp_nJ5PR4,4804
311
- cirq/ops/global_phase_op_test.py,sha256=cJDGmWlo3qAnW65Y9uCNMxuiOSTO6I1T3cC65ylaCfk,10087
310
+ cirq/ops/global_phase_op.py,sha256=GcERs4X5h5_at6tvJc8-AcM0cVsLCRPlpPkAWMINm54,5711
311
+ cirq/ops/global_phase_op_test.py,sha256=9BBnPZLLmBzHsMoRPMFTAShx87TJnhTLvvgLpHJF4wc,10721
312
312
  cirq/ops/greedy_qubit_manager.py,sha256=UTd9cTRbl4GQmf6ai6zqVBn5TR3-Vg84jJu4AN-0cxc,4050
313
313
  cirq/ops/greedy_qubit_manager_test.py,sha256=5vSKWsO0q8LwaKJSnOqr0bVQooKt0cwcO7zmPArHRRs,3464
314
314
  cirq/ops/identity.py,sha256=jWPE3jWLduXF5JgA0qol2blHXRvFUndClukG6nwGvUE,5862
@@ -374,7 +374,7 @@ cirq/ops/swap_gates.py,sha256=mEDVB4pdBsbenaOahrNtAcE2B1ZPW-4vGq079rECxf4,11743
374
374
  cirq/ops/swap_gates_test.py,sha256=8Yee6RgkQahsnB92ZD-rTb9dNqMLXdBKlgWC8qWd2uo,7624
375
375
  cirq/ops/tags.py,sha256=nBKqDnPHunxABIOqSAHsVb2hByRAJSfGCJjTC6-AbTY,2307
376
376
  cirq/ops/tags_test.py,sha256=EUCAjFYsQ98r6eo8XUNJoQCKMRCc4KvcqXUZAzfPqiE,1210
377
- cirq/ops/three_qubit_gates.py,sha256=DTxExMVcWRW8mmZnQrW6HQLUYbty0I_INAGaFxUh5DY,28175
377
+ cirq/ops/three_qubit_gates.py,sha256=yPzu3xYz9_bKQCzuRyH3YnB8KHEI1qtdH8whBgHhMkU,27911
378
378
  cirq/ops/three_qubit_gates_test.py,sha256=r9bO7noLCUIGhSprE-KUTlnrf16IEoAhy93Obi6oL18,11951
379
379
  cirq/ops/two_qubit_diagonal_gate.py,sha256=m2wnFpi0sHA9cxMa2cqwRYGQIlbyTGohMTLdVVQZ2-U,5377
380
380
  cirq/ops/two_qubit_diagonal_gate_test.py,sha256=pv24VMf2yQ-2gaHg_EUwWx5tAFvXo47_sKzdbdCPhRY,4100
@@ -399,8 +399,8 @@ cirq/protocols/commutes_protocol.py,sha256=6cJNba3aEsCh_XHIeNTHb0LRzws6ZbxOrKL_r
399
399
  cirq/protocols/commutes_protocol_test.py,sha256=9YhBFYAwc-XpU7HrQp-GarKwmwmbgyadUYqlkiG10A8,5885
400
400
  cirq/protocols/control_key_protocol.py,sha256=uGgfahCHzsFpUGq6flgTMuqPh20zUSB2AOkSrhyoqwQ,2621
401
401
  cirq/protocols/control_key_protocol_test.py,sha256=fNDDkf4mQpA_tKuhX1e2BJN72v9HdGftgd79sOqREJE,1014
402
- cirq/protocols/decompose_protocol.py,sha256=uNptw0F1SxJRE8TDdcuoLdxd-B50brbJ8S5bQUPzRCs,18729
403
- cirq/protocols/decompose_protocol_test.py,sha256=sSiycmk4kMYC32IKuTjAoQBzfmM5sE3hzhZd1Dzd6rE,16144
402
+ cirq/protocols/decompose_protocol.py,sha256=zwmrlFmBggInx1u1xZEeBDxaLGRWMGHCp87F7RRQPH4,19129
403
+ cirq/protocols/decompose_protocol_test.py,sha256=s5ELgra5UKExKCjDHUtMOwTZrGmYwxAphCRryRLMM_Q,16456
404
404
  cirq/protocols/equal_up_to_global_phase_protocol.py,sha256=y-GPOImHgdjVqXF-qE3SUmlekF6-zI0tgi0E2nTdW1M,4106
405
405
  cirq/protocols/equal_up_to_global_phase_protocol_test.py,sha256=EDfWnCuYAVfcvBXHYoZ0lDukNEGG2c53vzP7s8jHLKA,6050
406
406
  cirq/protocols/has_stabilizer_effect_protocol.py,sha256=T_CVVpvckp3ZTsWi089mPqbmwOPLlF6GalEKrVK7Hvs,4309
@@ -1102,8 +1102,8 @@ cirq/transformers/analytical_decompositions/cphase_to_fsim.py,sha256=jFWTFjCQ76c
1102
1102
  cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py,sha256=6ZDfSTL7aWSXXfM5DToeX8VxMalWirrCGKKg7QKBGFc,5591
1103
1103
  cirq/transformers/analytical_decompositions/pauli_string_decomposition.py,sha256=7GKdVnN5jvpjABudB0zE1kUn0BPZmuvRZcM2yLMUoWs,4540
1104
1104
  cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py,sha256=yWHkXXErOxLmnp5t65WUsY9e9iN6L950MZRw5OY3QW0,2172
1105
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py,sha256=JF2q79HEK5ZScMlqvnq17j7jAq0RFKpLPkKPnWiwN0c,11798
1106
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py,sha256=7oGMrh-ZBVaHmjZjfLI4N_P8aJhxKasu59R8-Uy2G-E,7721
1105
+ cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py,sha256=EIrK1PbHRMMhT5wei6rYk8diPEaqEZ0B-9M1chhCfCo,15450
1106
+ cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py,sha256=Bk94HEm9a-cywM_Q2TBF6eUYkSJB1GWwJ5QO1J-rMoA,9006
1107
1107
  cirq/transformers/analytical_decompositions/single_qubit_decompositions.py,sha256=6kaQfcXY7je42o-pVprSwgPXCDJXraDXQ9mHyR_BaBk,8428
1108
1108
  cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py,sha256=oh96QXddCm1v8CrYA5mEnnx_ENXwZi89W6paVZU273I,12344
1109
1109
  cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py,sha256=CRZylmI8nA_aq6vXj0WmMce8PIe8OFCjq4_bqYfkenk,2464
@@ -1112,8 +1112,8 @@ cirq/transformers/analytical_decompositions/three_qubit_decomposition.py,sha256=
1112
1112
  cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py,sha256=a21HU4BE82AG2UJU4hUVqymUU7Lw4CLw4-NChX4OpLI,6808
1113
1113
  cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py,sha256=2bIpZOHBHxH2mdbJfDpo6nQgpitOI0ZmoH_5l_nA1nU,6167
1114
1114
  cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py,sha256=c-vFBZnybd-Ez4rcs13THGGthzEZ0qw9Iw9sAKbE6yc,4494
1115
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py,sha256=XwDkm7l8DnRoKcQVgm2X64mmUS16iVDsMFV-35KYHfo,9305
1116
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py,sha256=5sSL80lYWquh7fcE6nbYVekEpxLNrHhj0T6G93IOZ7w,10033
1115
+ cirq/transformers/analytical_decompositions/two_qubit_to_cz.py,sha256=L2ScuiYW5tbNSc9_DJ4S6Lr_0mpmurVKUzlwLmGdJmw,11513
1116
+ cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py,sha256=PLPQRsBCVwGCgtL7nBY6xdI_CG1zxTdIj7fFGpxjU2U,10704
1117
1117
  cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py,sha256=8tYGV41gQBRzJSNUB3bsTMI8vil0TNE4TgqWlEw8BhE,9656
1118
1118
  cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py,sha256=bX8ap8VskN-gKxn3F4A8_vhgWO0AErOpP1QVVEtBjmY,7073
1119
1119
  cirq/transformers/analytical_decompositions/two_qubit_to_ms.py,sha256=dP9umZJBgNJ8FbDFFZVgMSyO-NjWJqXmoWyQuTo--0g,3751
@@ -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.dev20250625011740.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1224
- cirq_core-1.6.0.dev20250625011740.dist-info/METADATA,sha256=_q1W3S0aAsqVZyyOY0-P7nQH4q_XAWi4lBx0luZmBqs,4857
1225
- cirq_core-1.6.0.dev20250625011740.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1226
- cirq_core-1.6.0.dev20250625011740.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1227
- cirq_core-1.6.0.dev20250625011740.dist-info/RECORD,,
1223
+ cirq_core-1.6.0.dev20250625152617.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1224
+ cirq_core-1.6.0.dev20250625152617.dist-info/METADATA,sha256=fnk4EUEjwRjeZxmyGn_W7MpZMYIIs5bO1ox35RYjOZ0,4857
1225
+ cirq_core-1.6.0.dev20250625152617.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1226
+ cirq_core-1.6.0.dev20250625152617.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1227
+ cirq_core-1.6.0.dev20250625152617.dist-info/RECORD,,