cirq-core 1.6.0.dev20250722041606__py3-none-any.whl → 1.6.0.dev20250722170817__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.dev20250722041606"
31
+ __version__ = "1.6.0.dev20250722170817"
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.dev20250722041606"
6
+ assert cirq.__version__ == "1.6.0.dev20250722170817"
cirq/ops/matrix_gates.py CHANGED
@@ -22,7 +22,7 @@ import numpy as np
22
22
 
23
23
  from cirq import _import, linalg, protocols
24
24
  from cirq._compat import proper_repr
25
- from cirq.ops import global_phase_op, identity, phased_x_z_gate, raw_types
25
+ from cirq.ops import global_phase_op, phased_x_z_gate, raw_types
26
26
 
27
27
  if TYPE_CHECKING:
28
28
  import cirq
@@ -170,8 +170,8 @@ class MatrixGate(raw_types.Gate):
170
170
  return NotImplemented
171
171
  # The above algorithms ignore phase, but phase is important to maintain if the gate is
172
172
  # controlled. Here, we add it back in with a global phase op.
173
- ident = identity.IdentityGate(qid_shape=self._qid_shape).on(*qubits) # Preserve qid order
174
- u = protocols.unitary(Circuit(ident, *decomposed)).reshape(self._matrix.shape)
173
+ circuit = Circuit(*decomposed)
174
+ u = circuit.unitary(qubit_order=qubits, qubits_that_should_be_present=qubits)
175
175
  phase_delta = linalg.phase_delta(u, self._matrix)
176
176
  # Phase delta is on the complex unit circle, so if real(phase_delta) >= 1, that means
177
177
  # no phase delta. (>1 is rounding error).
@@ -413,3 +413,16 @@ def test_matrixgate_name_serialization():
413
413
  gate_after_serialization3 = cirq.read_json(json_text=cirq.to_json(gate3))
414
414
  assert gate3._name == ''
415
415
  assert gate_after_serialization3._name == ''
416
+
417
+
418
+ def test_decompose_when_qubits_not_in_ascending_order():
419
+ # Previous code for preserving global phase would misorder qubits
420
+ q0, q1 = cirq.LineQubit.range(2)
421
+ circuit1 = cirq.Circuit()
422
+ matrix = cirq.testing.random_unitary(4, random_state=0)
423
+ circuit1.append(cirq.MatrixGate(matrix).on(q1, q0))
424
+ u1 = cirq.unitary(circuit1)
425
+ decomposed = cirq.decompose(circuit1)
426
+ circuit2 = cirq.Circuit(decomposed)
427
+ u2 = cirq.unitary(circuit2)
428
+ np.testing.assert_allclose(u1, u2, atol=1e-14)
@@ -23,6 +23,7 @@ from typing import Any, Sequence, TypeVar
23
23
  import numpy as np
24
24
  from typing_extensions import Protocol
25
25
 
26
+ from cirq import protocols, qis
26
27
  from cirq._doc import doc_private
27
28
  from cirq.protocols.decompose_protocol import _try_decompose_into_operations_and_qubits
28
29
  from cirq.protocols.mixture_protocol import has_mixture
@@ -94,6 +95,37 @@ class SupportsKraus(Protocol):
94
95
  """
95
96
 
96
97
 
98
+ def _strat_kraus_from_apply_channel(val: Any) -> tuple[np.ndarray, ...] | None:
99
+ """Attempts to compute a value's Kraus operators via its _apply_channel_ method.
100
+ This is very expensive (O(16^N)), so only do this as a last resort."""
101
+ method = getattr(val, '_apply_channel_', None)
102
+ if method is None:
103
+ return None
104
+
105
+ qid_shape = protocols.qid_shape(val)
106
+
107
+ eye = qis.eye_tensor(qid_shape * 2, dtype=np.complex128)
108
+ buffer = np.empty_like(eye)
109
+ buffer.fill(float('nan'))
110
+ superop = protocols.apply_channel(
111
+ val=val,
112
+ args=protocols.ApplyChannelArgs(
113
+ target_tensor=eye,
114
+ out_buffer=buffer,
115
+ auxiliary_buffer0=buffer.copy(),
116
+ auxiliary_buffer1=buffer.copy(),
117
+ left_axes=list(range(len(qid_shape))),
118
+ right_axes=list(range(len(qid_shape), len(qid_shape) * 2)),
119
+ ),
120
+ default=None,
121
+ )
122
+ if superop is None or superop is NotImplemented:
123
+ return None
124
+ n = np.prod(qid_shape) ** 2
125
+ kraus_ops = qis.superoperator_to_kraus(superop.reshape((n, n)))
126
+ return tuple(kraus_ops)
127
+
128
+
97
129
  def kraus(
98
130
  val: Any, default: Any = RaiseTypeErrorIfNotProvided
99
131
  ) -> tuple[np.ndarray, ...] | TDefault:
@@ -159,6 +191,14 @@ def kraus(
159
191
  if channel_result is not NotImplemented:
160
192
  return tuple(channel_result) # pragma: no cover
161
193
 
194
+ # Last-resort fallback: try to derive Kraus from _apply_channel_.
195
+ # Note: _apply_channel can lead to kraus being called again, so if default
196
+ # is None, this can trigger an infinite loop.
197
+ if default is not None:
198
+ result = _strat_kraus_from_apply_channel(val)
199
+ if result is not None:
200
+ return result
201
+
162
202
  if default is not RaiseTypeErrorIfNotProvided:
163
203
  return default
164
204
 
@@ -22,6 +22,7 @@ import numpy as np
22
22
  import pytest
23
23
 
24
24
  import cirq
25
+ from cirq.protocols.apply_channel_protocol import _apply_kraus
25
26
 
26
27
  LOCAL_DEFAULT: list[np.ndarray] = [np.array([])]
27
28
 
@@ -171,3 +172,74 @@ def test_has_kraus_when_decomposed(decomposed_cls) -> None:
171
172
  op = HasKrausWhenDecomposed(decomposed_cls).on(cirq.NamedQubit('test'))
172
173
  assert cirq.has_kraus(op)
173
174
  assert not cirq.has_kraus(op, allow_decompose=False)
175
+
176
+
177
+ def test_strat_kraus_from_apply_channel_returns_none():
178
+ # Remove _kraus_ and _apply_channel_ methods
179
+ class NoApplyChannelReset(cirq.ResetChannel):
180
+ def _kraus_(self):
181
+ return NotImplemented
182
+
183
+ def _apply_channel_(self, args):
184
+ return NotImplemented
185
+
186
+ gate_no_apply = NoApplyChannelReset()
187
+ with pytest.raises(
188
+ TypeError,
189
+ match="does have a _kraus_, _mixture_ or _unitary_ method, but it returned NotImplemented",
190
+ ):
191
+ cirq.kraus(gate_no_apply)
192
+
193
+
194
+ @pytest.mark.parametrize(
195
+ 'channel_cls,params',
196
+ [
197
+ (cirq.BitFlipChannel, (0.5,)),
198
+ (cirq.PhaseFlipChannel, (0.3,)),
199
+ (cirq.DepolarizingChannel, (0.2,)),
200
+ (cirq.AmplitudeDampingChannel, (0.4,)),
201
+ (cirq.PhaseDampingChannel, (0.25,)),
202
+ ],
203
+ )
204
+ def test_kraus_fallback_to_apply_channel(channel_cls, params) -> None:
205
+ """Kraus protocol falls back to _apply_channel_ when no _kraus_, _mixture_, or _unitary_."""
206
+ # Create the expected channel and get its Kraus operators
207
+ expected_channel = channel_cls(*params)
208
+ expected_kraus = cirq.kraus(expected_channel)
209
+
210
+ class TestChannel:
211
+ def __init__(self, channel_cls, params):
212
+ self.channel_cls = channel_cls
213
+ self.params = params
214
+ self.expected_kraus = cirq.kraus(channel_cls(*params))
215
+
216
+ def _num_qubits_(self):
217
+ return 1
218
+
219
+ def _apply_channel_(self, args: cirq.ApplyChannelArgs):
220
+ return _apply_kraus(self.expected_kraus, args)
221
+
222
+ chan = TestChannel(channel_cls, params)
223
+ kraus_ops = cirq.kraus(chan)
224
+
225
+ # Compare the superoperator matrices for equivalence
226
+ expected_super = sum(np.kron(k, k.conj()) for k in expected_kraus)
227
+ actual_super = sum(np.kron(k, k.conj()) for k in kraus_ops)
228
+ np.testing.assert_allclose(actual_super, expected_super, atol=1e-8)
229
+
230
+
231
+ def test_reset_channel_kraus_apply_channel_consistency():
232
+ Reset = cirq.ResetChannel
233
+ # Original gate
234
+ gate = Reset()
235
+ cirq.testing.assert_has_consistent_apply_channel(gate)
236
+ cirq.testing.assert_consistent_channel(gate)
237
+
238
+ # Remove _kraus_ method
239
+ class NoKrausReset(Reset):
240
+ def _kraus_(self):
241
+ return NotImplemented
242
+
243
+ gate_no_kraus = NoKrausReset()
244
+ # Should still match the original superoperator
245
+ np.testing.assert_allclose(cirq.kraus(gate), cirq.kraus(gate_no_kraus), atol=1e-8)
@@ -336,6 +336,7 @@ def assert_has_consistent_apply_channel(val: Any, *, atol: float = 1e-8) -> None
336
336
  atol: Absolute error tolerance.
337
337
  """
338
338
  __tracebackhide__ = True
339
+ assert hasattr(val, '_apply_channel_')
339
340
 
340
341
  kraus = protocols.kraus(val, default=None)
341
342
  expected = qis.kraus_to_superoperator(kraus) if kraus is not None else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cirq-core
3
- Version: 1.6.0.dev20250722041606
3
+ Version: 1.6.0.dev20250722170817
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=9nRK75OBSnRLgvqZx_6GZra2OeWGWSqAmRTkenzHHTc,1206
8
- cirq/_version_test.py,sha256=txKPsk8dyJHomB1i-2VhHX7-RZHtL8rgxBb-gVZ3nhk,155
7
+ cirq/_version.py,sha256=_kMl3JRDUx0uWereGzzxnl55QCVAISV1PjAdpb9UIdc,1206
8
+ cirq/_version_test.py,sha256=YPglnCVZk8K6xjmYv-Tp-eC0-Es2CnNotUVN2i0kXAE,155
9
9
  cirq/conftest.py,sha256=wSDKNdIQRDfLnXvOCWD3erheOw8JHRhdfQ53EyTUIXg,1239
10
10
  cirq/json_resolver_cache.py,sha256=A5DIgFAY1hUNt9vai_C3-gGBv24116CJMzQxMcXOax4,13726
11
11
  cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
@@ -319,8 +319,8 @@ cirq/ops/kraus_channel.py,sha256=uSLq2AG72zbwzcbiEETFOAZ35KNR9U9KIFO31HYzLKA,507
319
319
  cirq/ops/kraus_channel_test.py,sha256=FhgCyCKa4bIgGc4yAQbqDKB80910TEVVWRknyyGbILg,4955
320
320
  cirq/ops/linear_combinations.py,sha256=AQA0aFDuHXks44fFtevrc2Zl1chleSlf1A0LkmrZrW8,39883
321
321
  cirq/ops/linear_combinations_test.py,sha256=EYqrWlFFThv8dl5B_9yIckEn_z3-Nfzh7rdVzGpIVWM,67351
322
- cirq/ops/matrix_gates.py,sha256=w-yDz2ZmIDiSTLO6Qhp6NrJJFJOJIjrt3okK7rRcZ68,10309
323
- cirq/ops/matrix_gates_test.py,sha256=5ZVdkTODOXKv5fi3xDqJA0gc9cYBMTd-KuKHyK-dxHI,14261
322
+ cirq/ops/matrix_gates.py,sha256=or8Kc3kP1NFjLbAHemmrZIqYFgEeeteMogNVEzYjosk,10238
323
+ cirq/ops/matrix_gates_test.py,sha256=MEK1VsaAv2Li_aYhFIfD53gytCNo854l5-BXL9yZBFs,14770
324
324
  cirq/ops/measure_util.py,sha256=iT7vrYLTo6L4z4_Zdm-8e8iiiKyQgF2v9Ui74Tg52aw,7261
325
325
  cirq/ops/measure_util_test.py,sha256=WrbR2jr_bFXxpQe8n3ANLAKYo1hcf-SlgsFOi-ULRXU,5343
326
326
  cirq/ops/measurement_gate.py,sha256=i7ThYTd1xdzOG274jzFnzqEz5Qmv6wggcubWa-3FDZE,11874
@@ -414,8 +414,8 @@ cirq/protocols/inverse_protocol.py,sha256=tHaY8-dfd0SD59v3DZ_zpwz7lwFrraPExEnIgn
414
414
  cirq/protocols/inverse_protocol_test.py,sha256=5RoZfSRzBvpGpLdg1XKYdB6qy-GkDvZsATUvxdFrLJ0,2067
415
415
  cirq/protocols/json_serialization.py,sha256=z7Yu2vsNabRkdeYyIuNCoXATHkrOGreTRShNyN0Fjuc,24520
416
416
  cirq/protocols/json_serialization_test.py,sha256=An57W8eBWaUF4kKOCos2UlHzNiILnUJvqmZLmwZ_6MA,27872
417
- cirq/protocols/kraus_protocol.py,sha256=ptiRkEnDgBnEdxobs6wZdZsOAhVzF6bhhSHuNqLKFJo,9250
418
- cirq/protocols/kraus_protocol_test.py,sha256=51eJ3r3Kx10rG-1hPjcfcODeUO3PFQmwU9ATMnhTWDw,5495
417
+ cirq/protocols/kraus_protocol.py,sha256=xNcjUBjxLOcsWRDkv7wdJ51iUvDhtHpxy_vXhhc2Gyw,10735
418
+ cirq/protocols/kraus_protocol_test.py,sha256=yw0WEXYNEOgA7xJB9UMIGbHRn2HJwPa88LKOoOuvRWc,7959
419
419
  cirq/protocols/measurement_key_protocol.py,sha256=JU7XbZfR7o6Wcv5qRJisp3ZAWwW9Fx7OHtxNMrWtZoQ,13351
420
420
  cirq/protocols/measurement_key_protocol_test.py,sha256=PqSU9uB4t2yvPz9hZBLby2mZnZo-DOLlx3HIicyPeLo,8768
421
421
  cirq/protocols/mixture_protocol.py,sha256=A8J-kkwUqiQphw6d3DK3QZ-lP31DTWv475ZzdeqYA0w,6428
@@ -976,7 +976,7 @@ cirq/study/sweepable_test.py,sha256=gMKkCoy8JxaCDeMTiDLdmcbBrioWs-teYOnqrri_2rI,
976
976
  cirq/study/sweeps.py,sha256=VhGc1Q4qJHF9QQlCpGh-X5rF3tKp0esUvWCy1y22S9M,21403
977
977
  cirq/study/sweeps_test.py,sha256=fiOKKnDyD-Ju7xeQM7A9pKkfR58VHXKdc0qw9d0MwRA,17231
978
978
  cirq/testing/__init__.py,sha256=QNkOC_QdYkiNrIxYuNjPsB_iWmTW8zUrUwOSiz_8LPg,6171
979
- cirq/testing/circuit_compare.py,sha256=3vgAfXZoqfpR58dGDzYTfkitzW7zs7wVq4OsW5LrBUU,18723
979
+ cirq/testing/circuit_compare.py,sha256=vWgMVa-TVwTRUMyEvNV6Ah3CMRlZYVo1xn41MsCTHzo,18766
980
980
  cirq/testing/circuit_compare_test.py,sha256=4ov58dOiez9HSQUJDP5hW1Li2tL75Gkevts2PiyyfSU,19738
981
981
  cirq/testing/consistent_act_on.py,sha256=hE_6fRPcmlvgRf2bHkB0XS4jnh_cR2PVS-g9YyNIijo,7670
982
982
  cirq/testing/consistent_act_on_test.py,sha256=UR-1RMhF88wlG3cFnbR0i8khrWFEuWg75WF5lnoXWWM,3571
@@ -1224,8 +1224,8 @@ cirq/work/sampler.py,sha256=rxbMWvrhu3gfNSBjZKozw28lLKVvBAS_1EGyPdYe8Xg,19041
1224
1224
  cirq/work/sampler_test.py,sha256=SsMrRvLDYELyOAWLKISjkdEfrBwLYWRsT6D8WrsLM3Q,13533
1225
1225
  cirq/work/zeros_sampler.py,sha256=Fs2JWwq0n9zv7_G5Rm-9vPeHUag7uctcMOHg0JTkZpc,2371
1226
1226
  cirq/work/zeros_sampler_test.py,sha256=lQLgQDGBLtfImryys2HzQ2jOSGxHgc7-koVBUhv8qYk,3345
1227
- cirq_core-1.6.0.dev20250722041606.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1228
- cirq_core-1.6.0.dev20250722041606.dist-info/METADATA,sha256=tXjfxPgW07rxp87WIlM7PZj2tL8MT6GzE4te6h8HnS4,4857
1229
- cirq_core-1.6.0.dev20250722041606.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1230
- cirq_core-1.6.0.dev20250722041606.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1231
- cirq_core-1.6.0.dev20250722041606.dist-info/RECORD,,
1227
+ cirq_core-1.6.0.dev20250722170817.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
1228
+ cirq_core-1.6.0.dev20250722170817.dist-info/METADATA,sha256=YO4I5RwXxcwxk32N6ggIh0zSFCIzfT7DAN-NQdSDyC0,4857
1229
+ cirq_core-1.6.0.dev20250722170817.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
1230
+ cirq_core-1.6.0.dev20250722170817.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
1231
+ cirq_core-1.6.0.dev20250722170817.dist-info/RECORD,,