cirq-core 1.5.0.dev20250404235631__py3-none-any.whl → 1.5.0.dev20250405050852__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 +1 -1
- cirq/_version_test.py +1 -1
- cirq/ops/common_channels.py +2 -5
- cirq/ops/common_gates.py +0 -12
- cirq/ops/common_gates_test.py +3 -2
- cirq/ops/eigen_gate.py +12 -36
- cirq/ops/eigen_gate_test.py +60 -10
- cirq/ops/parity_gates_test.py +1 -0
- cirq/ops/pauli_gates.py +0 -5
- cirq/ops/pauli_interaction_gate.py +7 -1
- cirq/protocols/apply_mixture_protocol.py +13 -6
- cirq/protocols/apply_mixture_protocol_test.py +11 -0
- cirq/protocols/kraus_protocol.py +4 -1
- cirq/protocols/mixture_protocol.py +4 -3
- cirq/protocols/mixture_protocol_test.py +20 -11
- {cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/METADATA +1 -1
- {cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/RECORD +20 -20
- {cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/LICENSE +0 -0
- {cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/WHEEL +0 -0
- {cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/top_level.txt +0 -0
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
cirq/ops/common_channels.py
CHANGED
|
@@ -1089,15 +1089,12 @@ class BitFlipChannel(raw_types.Gate):
|
|
|
1089
1089
|
ValueError: if p is not a valid probability.
|
|
1090
1090
|
"""
|
|
1091
1091
|
self._p = value.validate_probability(p, 'p')
|
|
1092
|
-
self._delegate = AsymmetricDepolarizingChannel(p, 0.0, 0.0)
|
|
1093
1092
|
|
|
1094
1093
|
def _num_qubits_(self) -> int:
|
|
1095
1094
|
return 1
|
|
1096
1095
|
|
|
1097
|
-
def _mixture_(self) -> Sequence[Tuple[float,
|
|
1098
|
-
|
|
1099
|
-
# just return identity and x term
|
|
1100
|
-
return (mixture[0], mixture[1])
|
|
1096
|
+
def _mixture_(self) -> Sequence[Tuple[float, Any]]:
|
|
1097
|
+
return ((1 - self._p, identity.I), (self._p, pauli_gates.X))
|
|
1101
1098
|
|
|
1102
1099
|
def _has_mixture_(self) -> bool:
|
|
1103
1100
|
return True
|
cirq/ops/common_gates.py
CHANGED
|
@@ -326,12 +326,6 @@ class XPowGate(eigen_gate.EigenGate):
|
|
|
326
326
|
d['dimension'] = self.dimension
|
|
327
327
|
return d
|
|
328
328
|
|
|
329
|
-
def _value_equality_values_(self):
|
|
330
|
-
return (*super()._value_equality_values_(), self._dimension)
|
|
331
|
-
|
|
332
|
-
def _value_equality_approximate_values_(self):
|
|
333
|
-
return (*super()._value_equality_approximate_values_(), self._dimension)
|
|
334
|
-
|
|
335
329
|
|
|
336
330
|
class Rx(XPowGate):
|
|
337
331
|
r"""A gate with matrix $e^{-i X t/2}$ that rotates around the X axis of the Bloch sphere by $t$.
|
|
@@ -862,12 +856,6 @@ class ZPowGate(eigen_gate.EigenGate):
|
|
|
862
856
|
d['dimension'] = self.dimension
|
|
863
857
|
return d
|
|
864
858
|
|
|
865
|
-
def _value_equality_values_(self):
|
|
866
|
-
return (*super()._value_equality_values_(), self._dimension)
|
|
867
|
-
|
|
868
|
-
def _value_equality_approximate_values_(self):
|
|
869
|
-
return (*super()._value_equality_approximate_values_(), self._dimension)
|
|
870
|
-
|
|
871
859
|
|
|
872
860
|
class Rz(ZPowGate):
|
|
873
861
|
r"""A gate with matrix $e^{-i Z t/2}$ that rotates around the Z axis of the Bloch sphere by $t$.
|
cirq/ops/common_gates_test.py
CHANGED
|
@@ -245,11 +245,12 @@ def test_rot_gates_eq():
|
|
|
245
245
|
eq.add_equality_group(cirq.YPowGate(), cirq.YPowGate(exponent=1), cirq.Y)
|
|
246
246
|
eq.add_equality_group(cirq.ZPowGate(), cirq.ZPowGate(exponent=1), cirq.Z)
|
|
247
247
|
eq.add_equality_group(
|
|
248
|
-
cirq.ZPowGate(exponent=1, global_shift=-0.5),
|
|
248
|
+
cirq.ZPowGate(exponent=1, global_shift=-0.5),
|
|
249
|
+
cirq.ZPowGate(exponent=5, global_shift=-0.5),
|
|
250
|
+
cirq.ZPowGate(exponent=5, global_shift=-0.1),
|
|
249
251
|
)
|
|
250
252
|
eq.add_equality_group(cirq.ZPowGate(exponent=3, global_shift=-0.5))
|
|
251
253
|
eq.add_equality_group(cirq.ZPowGate(exponent=1, global_shift=-0.1))
|
|
252
|
-
eq.add_equality_group(cirq.ZPowGate(exponent=5, global_shift=-0.1))
|
|
253
254
|
eq.add_equality_group(
|
|
254
255
|
cirq.CNotPowGate(), cirq.CXPowGate(), cirq.CNotPowGate(exponent=1), cirq.CNOT
|
|
255
256
|
)
|
cirq/ops/eigen_gate.py
CHANGED
|
@@ -34,7 +34,6 @@ import numpy as np
|
|
|
34
34
|
import sympy
|
|
35
35
|
|
|
36
36
|
from cirq import protocols, value
|
|
37
|
-
from cirq.linalg import tolerance
|
|
38
37
|
from cirq.ops import raw_types
|
|
39
38
|
|
|
40
39
|
if TYPE_CHECKING:
|
|
@@ -122,7 +121,6 @@ class EigenGate(raw_types.Gate):
|
|
|
122
121
|
exponent = exponent.real
|
|
123
122
|
self._exponent = exponent
|
|
124
123
|
self._global_shift = global_shift
|
|
125
|
-
self._canonical_exponent_cached = None
|
|
126
124
|
|
|
127
125
|
@property
|
|
128
126
|
def exponent(self) -> value.TParamVal:
|
|
@@ -305,30 +303,19 @@ class EigenGate(raw_types.Gate):
|
|
|
305
303
|
return NotImplemented # pragma: no cover
|
|
306
304
|
return self._with_exponent(exponent=new_exponent)
|
|
307
305
|
|
|
308
|
-
@property
|
|
309
|
-
def _canonical_exponent(self):
|
|
310
|
-
if self._canonical_exponent_cached is None:
|
|
311
|
-
period = self._period()
|
|
312
|
-
if not period:
|
|
313
|
-
self._canonical_exponent_cached = self._exponent
|
|
314
|
-
elif protocols.is_parameterized(self._exponent):
|
|
315
|
-
self._canonical_exponent_cached = self._exponent
|
|
316
|
-
if isinstance(self._exponent, sympy.Number):
|
|
317
|
-
self._canonical_exponent_cached = float(self._exponent)
|
|
318
|
-
else:
|
|
319
|
-
self._canonical_exponent_cached = self._exponent % period
|
|
320
|
-
return self._canonical_exponent_cached
|
|
321
|
-
|
|
322
306
|
def _value_equality_values_(self):
|
|
323
|
-
|
|
307
|
+
"""The phases by which we multiply the eigenspaces.
|
|
324
308
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
309
|
+
The default implementation assumes that the eigenspaces are constant
|
|
310
|
+
for the class, and the eigenphases are the only distinguishing
|
|
311
|
+
characteristics. For gates whose eigenspaces can change, such as
|
|
312
|
+
`PhasedISwapPowGate`, this must be overridden to provide the additional
|
|
313
|
+
fields that affect the eigenspaces.
|
|
314
|
+
"""
|
|
315
|
+
symbolic = lambda x: isinstance(x, sympy.Expr) and x.free_symbols
|
|
316
|
+
f = lambda x: x if symbolic(x) else float(x)
|
|
317
|
+
shifts = (f(self._exponent) * f(self._global_shift + e) for e in self._eigen_shifts())
|
|
318
|
+
return tuple(s if symbolic(s) else value.PeriodicValue(f(s), 2) for s in shifts)
|
|
332
319
|
|
|
333
320
|
def _trace_distance_bound_(self) -> Optional[float]:
|
|
334
321
|
if protocols.is_parameterized(self._exponent):
|
|
@@ -378,20 +365,9 @@ class EigenGate(raw_types.Gate):
|
|
|
378
365
|
return False
|
|
379
366
|
self_without_phase = self._with_exponent(self.exponent)
|
|
380
367
|
self_without_phase._global_shift = 0
|
|
381
|
-
self_without_exp_or_phase = self_without_phase._with_exponent(0)
|
|
382
|
-
self_without_exp_or_phase._global_shift = 0
|
|
383
368
|
other_without_phase = other._with_exponent(other.exponent)
|
|
384
369
|
other_without_phase._global_shift = 0
|
|
385
|
-
|
|
386
|
-
other_without_exp_or_phase._global_shift = 0
|
|
387
|
-
if not protocols.approx_eq(
|
|
388
|
-
self_without_exp_or_phase, other_without_exp_or_phase, atol=atol
|
|
389
|
-
):
|
|
390
|
-
return False
|
|
391
|
-
|
|
392
|
-
period = self_without_phase._period()
|
|
393
|
-
exponents_diff = exponents[0] - exponents[1]
|
|
394
|
-
return tolerance.near_zero_mod(exponents_diff, period, atol=atol)
|
|
370
|
+
return protocols.approx_eq(self_without_phase, other_without_phase, atol=atol)
|
|
395
371
|
|
|
396
372
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
397
373
|
return protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
|
cirq/ops/eigen_gate_test.py
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import re
|
|
16
15
|
from typing import List, Tuple
|
|
17
16
|
|
|
18
17
|
import numpy as np
|
|
@@ -50,7 +49,7 @@ class CExpZinGate(cirq.EigenGate, cirq.testing.TwoQubitGate):
|
|
|
50
49
|
]
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
class ZGateDef(cirq.EigenGate, cirq.testing.
|
|
52
|
+
class ZGateDef(cirq.EigenGate, cirq.testing.SingleQubitGate):
|
|
54
53
|
@property
|
|
55
54
|
def exponent(self):
|
|
56
55
|
return self._exponent
|
|
@@ -97,7 +96,6 @@ def test_eq():
|
|
|
97
96
|
eq.make_equality_group(lambda: CExpZinGate(quarter_turns=0.1))
|
|
98
97
|
eq.add_equality_group(CExpZinGate(0), CExpZinGate(4), CExpZinGate(-4))
|
|
99
98
|
|
|
100
|
-
# Equates by canonicalized period.
|
|
101
99
|
eq.add_equality_group(CExpZinGate(1.5), CExpZinGate(41.5))
|
|
102
100
|
eq.add_equality_group(CExpZinGate(3.5), CExpZinGate(-0.5))
|
|
103
101
|
|
|
@@ -109,6 +107,64 @@ def test_eq():
|
|
|
109
107
|
eq.add_equality_group(ZGateDef(exponent=0.5, global_shift=0.5))
|
|
110
108
|
eq.add_equality_group(ZGateDef(exponent=1.0, global_shift=0.5))
|
|
111
109
|
|
|
110
|
+
# All variants of (0,0) == (0*a,0*a) == (0, 2) == (2, 2)
|
|
111
|
+
a, b = sympy.symbols('a, b')
|
|
112
|
+
eq.add_equality_group(
|
|
113
|
+
WeightedZPowGate(0),
|
|
114
|
+
WeightedZPowGate(0) ** 1.1,
|
|
115
|
+
WeightedZPowGate(0) ** a,
|
|
116
|
+
(WeightedZPowGate(0) ** a) ** 1.2,
|
|
117
|
+
WeightedZPowGate(0) ** (a + 1.3),
|
|
118
|
+
WeightedZPowGate(0) ** b,
|
|
119
|
+
WeightedZPowGate(1) ** 2,
|
|
120
|
+
WeightedZPowGate(0, global_shift=1) ** 2,
|
|
121
|
+
WeightedZPowGate(1, global_shift=1) ** 2,
|
|
122
|
+
WeightedZPowGate(2),
|
|
123
|
+
WeightedZPowGate(0, global_shift=2),
|
|
124
|
+
WeightedZPowGate(2, global_shift=2),
|
|
125
|
+
)
|
|
126
|
+
# WeightedZPowGate(2) is identity, but non-integer exponent would make it different, similar to
|
|
127
|
+
# how we treat (X**2)**0.5==X. So these are in their own equality group. (0, 2*a)
|
|
128
|
+
eq.add_equality_group(
|
|
129
|
+
WeightedZPowGate(2) ** a,
|
|
130
|
+
(WeightedZPowGate(1) ** 2) ** a,
|
|
131
|
+
(WeightedZPowGate(1) ** a) ** 2,
|
|
132
|
+
WeightedZPowGate(1) ** (a * 2),
|
|
133
|
+
WeightedZPowGate(1) ** (a + a),
|
|
134
|
+
)
|
|
135
|
+
# Similarly, these are identity without the exponent, but global_shift affects both phases
|
|
136
|
+
# instead of just the one, so will have a different effect from the above depending on the
|
|
137
|
+
# exponent. (2*a, 0)
|
|
138
|
+
eq.add_equality_group(
|
|
139
|
+
WeightedZPowGate(0, global_shift=2) ** a,
|
|
140
|
+
(WeightedZPowGate(0, global_shift=1) ** 2) ** a,
|
|
141
|
+
(WeightedZPowGate(0, global_shift=1) ** a) ** 2,
|
|
142
|
+
WeightedZPowGate(0, global_shift=1) ** (a * 2),
|
|
143
|
+
WeightedZPowGate(0, global_shift=1) ** (a + a),
|
|
144
|
+
)
|
|
145
|
+
# Symbolic exponents that cancel (0, 1) == (0, a/a)
|
|
146
|
+
eq.add_equality_group(
|
|
147
|
+
WeightedZPowGate(1),
|
|
148
|
+
WeightedZPowGate(a) ** (1 / a),
|
|
149
|
+
WeightedZPowGate(b) ** (1 / b),
|
|
150
|
+
WeightedZPowGate(1 / a) ** a,
|
|
151
|
+
WeightedZPowGate(1 / b) ** b,
|
|
152
|
+
)
|
|
153
|
+
# Symbol in one phase and constant off by period in another (0, a) == (2, a)
|
|
154
|
+
eq.add_equality_group(
|
|
155
|
+
WeightedZPowGate(a),
|
|
156
|
+
WeightedZPowGate(a - 2, global_shift=2),
|
|
157
|
+
WeightedZPowGate(1 - 2 / a, global_shift=2 / a) ** a,
|
|
158
|
+
)
|
|
159
|
+
# Different symbol, different equality group (0, b)
|
|
160
|
+
eq.add_equality_group(WeightedZPowGate(b))
|
|
161
|
+
# Various number types
|
|
162
|
+
eq.add_equality_group(
|
|
163
|
+
WeightedZPowGate(np.int64(3), global_shift=sympy.Number(5)) ** 7.0,
|
|
164
|
+
WeightedZPowGate(sympy.Number(3), global_shift=5.0) ** np.int64(7),
|
|
165
|
+
WeightedZPowGate(3.0, global_shift=np.int64(5)) ** sympy.Number(7),
|
|
166
|
+
)
|
|
167
|
+
|
|
112
168
|
|
|
113
169
|
def test_approx_eq():
|
|
114
170
|
assert cirq.approx_eq(CExpZinGate(1.5), CExpZinGate(1.5), atol=0.1)
|
|
@@ -118,8 +174,7 @@ def test_approx_eq():
|
|
|
118
174
|
assert cirq.approx_eq(ZGateDef(exponent=1.5), ZGateDef(exponent=1.5), atol=0.1)
|
|
119
175
|
assert not cirq.approx_eq(CExpZinGate(1.5), ZGateDef(exponent=1.5), atol=0.1)
|
|
120
176
|
with pytest.raises(
|
|
121
|
-
TypeError,
|
|
122
|
-
match=re.escape("unsupported operand type(s) for -: 'Symbol' and 'PeriodicValue'"),
|
|
177
|
+
TypeError, match="unsupported operand type\\(s\\) for -: '.*' and 'PeriodicValue'"
|
|
123
178
|
):
|
|
124
179
|
cirq.approx_eq(ZGateDef(exponent=1.5), ZGateDef(exponent=sympy.Symbol('a')), atol=0.1)
|
|
125
180
|
assert cirq.approx_eq(CExpZinGate(sympy.Symbol('a')), CExpZinGate(sympy.Symbol('a')), atol=0.1)
|
|
@@ -333,11 +388,6 @@ class WeightedZPowGate(cirq.EigenGate, cirq.testing.SingleQubitGate):
|
|
|
333
388
|
self.weight = weight
|
|
334
389
|
super().__init__(**kwargs)
|
|
335
390
|
|
|
336
|
-
def _value_equality_values_(self):
|
|
337
|
-
return self.weight, self._canonical_exponent, self._global_shift
|
|
338
|
-
|
|
339
|
-
_value_equality_approximate_values_ = _value_equality_values_
|
|
340
|
-
|
|
341
391
|
def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
|
|
342
392
|
return [(0, np.diag([1, 0])), (self.weight, np.diag([0, 1]))]
|
|
343
393
|
|
cirq/ops/parity_gates_test.py
CHANGED
|
@@ -39,6 +39,7 @@ def test_xx_eq():
|
|
|
39
39
|
cirq.XXPowGate(),
|
|
40
40
|
cirq.XXPowGate(exponent=1, global_shift=0),
|
|
41
41
|
cirq.XXPowGate(exponent=3, global_shift=0),
|
|
42
|
+
cirq.XXPowGate(global_shift=100000),
|
|
42
43
|
)
|
|
43
44
|
eq.add_equality_group(cirq.XX**0.5, cirq.XX**2.5, cirq.XX**4.5)
|
|
44
45
|
eq.add_equality_group(cirq.XX**0.25, cirq.XX**2.25, cirq.XX**-1.75)
|
cirq/ops/pauli_gates.py
CHANGED
|
@@ -103,11 +103,6 @@ class Pauli(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
103
103
|
|
|
104
104
|
return pauli_string.SingleQubitPauliStringGateOperation(self, qubits[0])
|
|
105
105
|
|
|
106
|
-
@property
|
|
107
|
-
def _canonical_exponent(self):
|
|
108
|
-
"""Overrides EigenGate._canonical_exponent in subclasses."""
|
|
109
|
-
return 1
|
|
110
|
-
|
|
111
106
|
|
|
112
107
|
class _PauliX(Pauli, common_gates.XPowGate):
|
|
113
108
|
def __init__(self):
|
|
@@ -85,7 +85,13 @@ class PauliInteractionGate(gate_features.InterchangeableQubitsGate, eigen_gate.E
|
|
|
85
85
|
return 2
|
|
86
86
|
|
|
87
87
|
def _value_equality_values_(self):
|
|
88
|
-
return (
|
|
88
|
+
return (
|
|
89
|
+
self.pauli0,
|
|
90
|
+
self.invert0,
|
|
91
|
+
self.pauli1,
|
|
92
|
+
self.invert1,
|
|
93
|
+
value.PeriodicValue(self.exponent, 2),
|
|
94
|
+
)
|
|
89
95
|
|
|
90
96
|
def qubit_index_to_equivalence_group_key(self, index: int) -> int:
|
|
91
97
|
if self.pauli0 == self.pauli1 and self.invert0 == self.invert1:
|
|
@@ -24,7 +24,6 @@ from cirq import linalg
|
|
|
24
24
|
from cirq._doc import doc_private
|
|
25
25
|
from cirq.protocols import qid_shape_protocol
|
|
26
26
|
from cirq.protocols.apply_unitary_protocol import apply_unitary, ApplyUnitaryArgs
|
|
27
|
-
from cirq.protocols.mixture_protocol import mixture
|
|
28
27
|
|
|
29
28
|
# This is a special indicator value used by the apply_mixture method
|
|
30
29
|
# to determine whether or not the caller provided a 'default' argument. It must
|
|
@@ -260,9 +259,9 @@ def apply_mixture(
|
|
|
260
259
|
return result
|
|
261
260
|
|
|
262
261
|
# Fallback to using the object's `_mixture_` matrices. (STEP C)
|
|
263
|
-
|
|
264
|
-
if
|
|
265
|
-
return
|
|
262
|
+
result = _apply_mixture_from_mixture_strat(val, args, is_density_matrix)
|
|
263
|
+
if result is not None:
|
|
264
|
+
return result
|
|
266
265
|
|
|
267
266
|
# Don't know how to apply mixture. Fallback to specified default behavior.
|
|
268
267
|
# (STEP D)
|
|
@@ -359,11 +358,19 @@ def _apply_unitary_from_matrix_strat(
|
|
|
359
358
|
return args.target_tensor
|
|
360
359
|
|
|
361
360
|
|
|
362
|
-
def
|
|
361
|
+
def _apply_mixture_from_mixture_strat(
|
|
362
|
+
val: Any, args: 'ApplyMixtureArgs', is_density_matrix: bool
|
|
363
|
+
) -> Optional[np.ndarray]:
|
|
363
364
|
"""Attempt to use unitary matrices in _mixture_ and return the result."""
|
|
365
|
+
method = getattr(val, '_mixture_', None)
|
|
366
|
+
if method is None:
|
|
367
|
+
return None
|
|
368
|
+
prob_mix = method()
|
|
369
|
+
if prob_mix is NotImplemented or prob_mix is None:
|
|
370
|
+
return None
|
|
364
371
|
args.out_buffer[:] = 0
|
|
365
372
|
np.copyto(dst=args.auxiliary_buffer1, src=args.target_tensor)
|
|
366
|
-
for prob, op in
|
|
373
|
+
for prob, op in prob_mix:
|
|
367
374
|
np.copyto(dst=args.target_tensor, src=args.auxiliary_buffer1)
|
|
368
375
|
right_result = _apply_unitary_strat(op, args, is_density_matrix)
|
|
369
376
|
if right_result is None:
|
|
@@ -237,6 +237,17 @@ def test_apply_mixture_no_protocols_implemented():
|
|
|
237
237
|
assert_apply_mixture_returns(NoProtocols(), rho, left_axes=[1], right_axes=[1])
|
|
238
238
|
|
|
239
239
|
|
|
240
|
+
def test_apply_mixture_mixture_returns_not_implemented():
|
|
241
|
+
class NoMixture:
|
|
242
|
+
def _mixture_(self):
|
|
243
|
+
return NotImplemented
|
|
244
|
+
|
|
245
|
+
rho = np.ones((2, 2, 2, 2), dtype=np.complex128)
|
|
246
|
+
|
|
247
|
+
with pytest.raises(TypeError, match='has no'):
|
|
248
|
+
assert_apply_mixture_returns(NoMixture(), rho, left_axes=[1], right_axes=[1])
|
|
249
|
+
|
|
250
|
+
|
|
240
251
|
def test_apply_mixture_no_protocols_implemented_default():
|
|
241
252
|
class NoProtocols:
|
|
242
253
|
pass
|
cirq/protocols/kraus_protocol.py
CHANGED
|
@@ -24,6 +24,7 @@ from typing_extensions import Protocol
|
|
|
24
24
|
from cirq._doc import doc_private
|
|
25
25
|
from cirq.protocols.decompose_protocol import _try_decompose_into_operations_and_qubits
|
|
26
26
|
from cirq.protocols.mixture_protocol import has_mixture
|
|
27
|
+
from cirq.protocols.unitary_protocol import unitary
|
|
27
28
|
|
|
28
29
|
# This is a special indicator value used by the channel method to determine
|
|
29
30
|
# whether or not the caller provided a 'default' argument. It must be of type
|
|
@@ -145,7 +146,9 @@ def kraus(
|
|
|
145
146
|
mixture_getter = getattr(val, '_mixture_', None)
|
|
146
147
|
mixture_result = NotImplemented if mixture_getter is None else mixture_getter()
|
|
147
148
|
if mixture_result is not NotImplemented and mixture_result is not None:
|
|
148
|
-
return tuple(
|
|
149
|
+
return tuple(
|
|
150
|
+
np.sqrt(p) * (u if isinstance(u, np.ndarray) else unitary(u)) for p, u in mixture_result
|
|
151
|
+
)
|
|
149
152
|
|
|
150
153
|
unitary_getter = getattr(val, '_unitary_', None)
|
|
151
154
|
unitary_result = NotImplemented if unitary_getter is None else unitary_getter()
|
|
@@ -23,6 +23,7 @@ from typing_extensions import Protocol
|
|
|
23
23
|
from cirq._doc import doc_private
|
|
24
24
|
from cirq.protocols.decompose_protocol import _try_decompose_into_operations_and_qubits
|
|
25
25
|
from cirq.protocols.has_unitary_protocol import has_unitary
|
|
26
|
+
from cirq.protocols.unitary_protocol import unitary
|
|
26
27
|
|
|
27
28
|
# This is a special indicator value used by the inverse method to determine
|
|
28
29
|
# whether or not the caller provided a 'default' argument.
|
|
@@ -84,14 +85,14 @@ def mixture(
|
|
|
84
85
|
with that probability in the mixture. The probabilities will sum to 1.0.
|
|
85
86
|
|
|
86
87
|
Raises:
|
|
87
|
-
TypeError: If `val` has no `_mixture_` or `_unitary_`
|
|
88
|
+
TypeError: If `val` has no `_mixture_` or `_unitary_` method, or if it
|
|
88
89
|
does and this method returned `NotImplemented`.
|
|
89
90
|
"""
|
|
90
91
|
|
|
91
92
|
mixture_getter = getattr(val, '_mixture_', None)
|
|
92
93
|
result = NotImplemented if mixture_getter is None else mixture_getter()
|
|
93
|
-
if result is not NotImplemented:
|
|
94
|
-
return result
|
|
94
|
+
if result is not NotImplemented and result is not None:
|
|
95
|
+
return tuple((p, u if isinstance(u, np.ndarray) else unitary(u)) for p, u in result)
|
|
95
96
|
|
|
96
97
|
unitary_getter = getattr(val, '_unitary_', None)
|
|
97
98
|
result = NotImplemented if unitary_getter is None else unitary_getter()
|
|
@@ -17,6 +17,9 @@ import pytest
|
|
|
17
17
|
|
|
18
18
|
import cirq
|
|
19
19
|
|
|
20
|
+
a = np.array([1])
|
|
21
|
+
b = np.array([1j])
|
|
22
|
+
|
|
20
23
|
|
|
21
24
|
class NoMethod:
|
|
22
25
|
pass
|
|
@@ -32,7 +35,7 @@ class ReturnsNotImplemented:
|
|
|
32
35
|
|
|
33
36
|
class ReturnsValidTuple(cirq.SupportsMixture):
|
|
34
37
|
def _mixture_(self):
|
|
35
|
-
return ((0.4,
|
|
38
|
+
return ((0.4, a), (0.6, b))
|
|
36
39
|
|
|
37
40
|
def _has_mixture_(self):
|
|
38
41
|
return True
|
|
@@ -40,27 +43,27 @@ class ReturnsValidTuple(cirq.SupportsMixture):
|
|
|
40
43
|
|
|
41
44
|
class ReturnsNonnormalizedTuple:
|
|
42
45
|
def _mixture_(self):
|
|
43
|
-
return ((0.4,
|
|
46
|
+
return ((0.4, a), (0.4, b))
|
|
44
47
|
|
|
45
48
|
|
|
46
49
|
class ReturnsNegativeProbability:
|
|
47
50
|
def _mixture_(self):
|
|
48
|
-
return ((0.4,
|
|
51
|
+
return ((0.4, a), (-0.4, b))
|
|
49
52
|
|
|
50
53
|
|
|
51
54
|
class ReturnsGreaterThanUnityProbability:
|
|
52
55
|
def _mixture_(self):
|
|
53
|
-
return ((1.2,
|
|
56
|
+
return ((1.2, a), (0.4, b))
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
class ReturnsMixtureButNoHasMixture:
|
|
57
60
|
def _mixture_(self):
|
|
58
|
-
return ((0.4,
|
|
61
|
+
return ((0.4, a), (0.6, b))
|
|
59
62
|
|
|
60
63
|
|
|
61
64
|
class ReturnsUnitary:
|
|
62
65
|
def _unitary_(self):
|
|
63
|
-
return np.
|
|
66
|
+
return np.eye(2)
|
|
64
67
|
|
|
65
68
|
def _has_unitary_(self):
|
|
66
69
|
return True
|
|
@@ -74,12 +77,18 @@ class ReturnsNotImplementedUnitary:
|
|
|
74
77
|
return NotImplemented
|
|
75
78
|
|
|
76
79
|
|
|
80
|
+
class ReturnsMixtureOfReturnsUnitary:
|
|
81
|
+
def _mixture_(self):
|
|
82
|
+
return ((0.4, ReturnsUnitary()), (0.6, ReturnsUnitary()))
|
|
83
|
+
|
|
84
|
+
|
|
77
85
|
@pytest.mark.parametrize(
|
|
78
86
|
'val,mixture',
|
|
79
87
|
(
|
|
80
|
-
(ReturnsValidTuple(), ((0.4,
|
|
81
|
-
(ReturnsNonnormalizedTuple(), ((0.4,
|
|
82
|
-
(ReturnsUnitary(), ((1.0, np.
|
|
88
|
+
(ReturnsValidTuple(), ((0.4, a), (0.6, b))),
|
|
89
|
+
(ReturnsNonnormalizedTuple(), ((0.4, a), (0.4, b))),
|
|
90
|
+
(ReturnsUnitary(), ((1.0, np.eye(2)),)),
|
|
91
|
+
(ReturnsMixtureOfReturnsUnitary(), ((0.4, np.eye(2)), (0.6, np.eye(2)))),
|
|
83
92
|
),
|
|
84
93
|
)
|
|
85
94
|
def test_objects_with_mixture(val, mixture):
|
|
@@ -88,7 +97,7 @@ def test_objects_with_mixture(val, mixture):
|
|
|
88
97
|
np.testing.assert_almost_equal(keys, expected_keys)
|
|
89
98
|
np.testing.assert_equal(values, expected_values)
|
|
90
99
|
|
|
91
|
-
keys, values = zip(*cirq.mixture(val, ((0.3,
|
|
100
|
+
keys, values = zip(*cirq.mixture(val, ((0.3, a), (0.7, b))))
|
|
92
101
|
np.testing.assert_almost_equal(keys, expected_keys)
|
|
93
102
|
np.testing.assert_equal(values, expected_values)
|
|
94
103
|
|
|
@@ -101,7 +110,7 @@ def test_objects_with_no_mixture(val):
|
|
|
101
110
|
_ = cirq.mixture(val)
|
|
102
111
|
assert cirq.mixture(val, None) is None
|
|
103
112
|
assert cirq.mixture(val, NotImplemented) is NotImplemented
|
|
104
|
-
default = ((0.4,
|
|
113
|
+
default = ((0.4, a), (0.6, b))
|
|
105
114
|
assert cirq.mixture(val, default) == default
|
|
106
115
|
|
|
107
116
|
|
{cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cirq-core
|
|
3
|
-
Version: 1.5.0.
|
|
3
|
+
Version: 1.5.0.dev20250405050852
|
|
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
|
{cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/RECORD
RENAMED
|
@@ -4,8 +4,8 @@ cirq/_compat_test.py,sha256=0m3sYIyxRNv9jvAo6rzJ-cnbpny3KGnAByrbU7bApgQ,34720
|
|
|
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=
|
|
8
|
-
cirq/_version_test.py,sha256=
|
|
7
|
+
cirq/_version.py,sha256=rrHncQSD1uha8V-ZVfxjGi97KobvlRJIdilCH7DsjIw,1206
|
|
8
|
+
cirq/_version_test.py,sha256=ZAHy9pdX7FT9NoLH9SJy53S2EU42iikkMzR--NkmMMg,147
|
|
9
9
|
cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
|
|
10
10
|
cirq/json_resolver_cache.py,sha256=YVamU72nCUT5dG0bhAvRKVX5lXcZMNTwP3H36v-cYag,13615
|
|
11
11
|
cirq/py.typed,sha256=VFSlmh_lNwnaXzwY-ZuW-C2Ws5PkuDoVgBdNCs0jXJE,63
|
|
@@ -276,12 +276,12 @@ cirq/ops/classically_controlled_operation.py,sha256=ePhBPrHymodrsztJFk_g2IGI3QSb
|
|
|
276
276
|
cirq/ops/classically_controlled_operation_test.py,sha256=nIYyXfNH4E2IibZSLk6QDVHpfJQbuI_iWwirCH8rhi8,50209
|
|
277
277
|
cirq/ops/clifford_gate.py,sha256=5mE97WQG6kW9ntRcn20hoFip71TFofnNKMx01RHETO4,39488
|
|
278
278
|
cirq/ops/clifford_gate_test.py,sha256=dqghYb7_afYxCLceBarX56Tn9y_dSWCKF75W-Qrzvcw,40341
|
|
279
|
-
cirq/ops/common_channels.py,sha256=
|
|
279
|
+
cirq/ops/common_channels.py,sha256=lGDOSdstoK57DingL-lo2n49-a51MshhJOl4LOcpQfg,37126
|
|
280
280
|
cirq/ops/common_channels_test.py,sha256=nQsSSxu7vtedb3ZUuw4hNKIX7MYI4x8lxvLyWMZNt10,30079
|
|
281
281
|
cirq/ops/common_gate_families.py,sha256=2E31Qr_Yv1zI-r_MNWmr1xJYrEHHU45274iDrt_oKPE,8611
|
|
282
282
|
cirq/ops/common_gate_families_test.py,sha256=bEF6Q6GtEOTc9kHM5WC1UIULPGnMPXdtm8gzLT_aNBI,5276
|
|
283
|
-
cirq/ops/common_gates.py,sha256=
|
|
284
|
-
cirq/ops/common_gates_test.py,sha256=
|
|
283
|
+
cirq/ops/common_gates.py,sha256=nZ5gOd4JPnq7k6jrnNILacMnG-43OzdQQj5W1Vw5JKI,57846
|
|
284
|
+
cirq/ops/common_gates_test.py,sha256=bASPqAkuN92Ij3CCAVwOftL0heIu3J5VPcCtmm6nVU0,46873
|
|
285
285
|
cirq/ops/control_values.py,sha256=Loi_voLNOzPJpjD6AnQz8JrqJLOAUe0jvV3XB_0tTGE,13430
|
|
286
286
|
cirq/ops/control_values_test.py,sha256=K8tbKM6b6PqMEL_lHLFzdrnWF1SkLN0Scft6YMT7FlE,12907
|
|
287
287
|
cirq/ops/controlled_gate.py,sha256=uzQL7scPsKmnu3Kdiw-zF7b4FxdyqvaD6oPkczs1skQ,15234
|
|
@@ -292,8 +292,8 @@ cirq/ops/dense_pauli_string.py,sha256=nQs4lfm9zSGPGE9p9KAJbEhkldpg9krqTwvIkLePs9
|
|
|
292
292
|
cirq/ops/dense_pauli_string_test.py,sha256=duvgzhgTV9wuem4kDSwtL62SEUCThkz1tdP984-C4_s,21504
|
|
293
293
|
cirq/ops/diagonal_gate.py,sha256=NpCGuZpdqMGoM6ya8Q8Jp7UTut2WglMB7DK5oqBRXiE,9021
|
|
294
294
|
cirq/ops/diagonal_gate_test.py,sha256=wsPZWhImVGNrEg1mYnXsO4nJ6VziDBfvEilAFtJJ8b4,6224
|
|
295
|
-
cirq/ops/eigen_gate.py,sha256=
|
|
296
|
-
cirq/ops/eigen_gate_test.py,sha256=
|
|
295
|
+
cirq/ops/eigen_gate.py,sha256=GRtLML2LbTBvVMNlar5SIzdDVK6UHL3lRwAPR6JOPOQ,17494
|
|
296
|
+
cirq/ops/eigen_gate_test.py,sha256=D9ETnoJ4NRcz9EvzQOFra84bonph8optp7zhW57rgWA,16139
|
|
297
297
|
cirq/ops/fourier_transform.py,sha256=_YWqBq7zqRv7rH5oQPPg7zdUSiTp2px8kaaWZZmakZA,7513
|
|
298
298
|
cirq/ops/fourier_transform_test.py,sha256=mtWhiC_Tg60uNh7mhhMb02cckGfNC_Tjte-Q4gRcF8c,6226
|
|
299
299
|
cirq/ops/fsim_gate.py,sha256=Avzlcb_O201K0_tBmNR5m9fWkpBM7Nby0MfJjNJ9g_8,20136
|
|
@@ -329,10 +329,10 @@ cirq/ops/op_tree_test.py,sha256=FzDaDjooimUEYvCvXrTCXbR2Je8QjRTZ0VXoeI7AGyo,5700
|
|
|
329
329
|
cirq/ops/parallel_gate.py,sha256=lkwaatEWd0roRbRKq_fkBz7nmZoMB4hdwFT6LUNxmJ4,6318
|
|
330
330
|
cirq/ops/parallel_gate_test.py,sha256=lWCLnlEhs_LDNgewp7e3uN-23Q513i4G0JMva96_GiE,6299
|
|
331
331
|
cirq/ops/parity_gates.py,sha256=WjuWb69Deym_g22ZJIurrMGY0AWdLQjxNkOFnnrbzAg,14383
|
|
332
|
-
cirq/ops/parity_gates_test.py,sha256=
|
|
333
|
-
cirq/ops/pauli_gates.py,sha256=
|
|
332
|
+
cirq/ops/parity_gates_test.py,sha256=43k4Q6YIm2wOVxaAgp02ki0zpAQ271_lcG2GbWR4TJc,11289
|
|
333
|
+
cirq/ops/pauli_gates.py,sha256=NTt6Jd1WrlkqyvEDNKTLvzSR5pE4Imr-SDTZUs3gPgA,6831
|
|
334
334
|
cirq/ops/pauli_gates_test.py,sha256=3AX2hzr-xeXrZUeSr-yBFYhbLeHK1qEh7_Bq9vGUAgo,7753
|
|
335
|
-
cirq/ops/pauli_interaction_gate.py,sha256=
|
|
335
|
+
cirq/ops/pauli_interaction_gate.py,sha256=2e0VaCO0IE0rdwPb5F50S3rujqOuSWz54r2lNWUDrBA,5603
|
|
336
336
|
cirq/ops/pauli_interaction_gate_test.py,sha256=adnIIgCvFzO-inNaN77HER-WJ0hg6L63_HfiT60oV3M,4543
|
|
337
337
|
cirq/ops/pauli_measurement_gate.py,sha256=ODHQJgy7oEuDb7qOJ2ja_i0w4jvbV202FaO4O_deo6Y,7239
|
|
338
338
|
cirq/ops/pauli_measurement_gate_test.py,sha256=acKmYvwSQniIX2FtOCVrIPRPmyUBeV4uNUFmyShJixE,6778
|
|
@@ -384,8 +384,8 @@ cirq/protocols/act_on_protocol.py,sha256=pRjl2lHqxuYWlJopkWCSPiwrHPggHOdRMb0nu-k
|
|
|
384
384
|
cirq/protocols/act_on_protocol_test.py,sha256=q4vOBfG9-O8CIzmwU8HaB2HZR_U1fk2Vm-q1QhyeEpY,3147
|
|
385
385
|
cirq/protocols/apply_channel_protocol.py,sha256=s5gkjAcAMe_qdPJGPuZnt4r6zZhszpddnK8Ed-wEO90,15678
|
|
386
386
|
cirq/protocols/apply_channel_protocol_test.py,sha256=ETAWrBTVkPuUPUgHsLZo1HUsJnZsO0hD2fQeXlXtvjE,10582
|
|
387
|
-
cirq/protocols/apply_mixture_protocol.py,sha256=
|
|
388
|
-
cirq/protocols/apply_mixture_protocol_test.py,sha256=
|
|
387
|
+
cirq/protocols/apply_mixture_protocol.py,sha256=pYxlpOXxPjMIddyYtEw82_18ioNNvEEcmsImaQ1YiBc,16479
|
|
388
|
+
cirq/protocols/apply_mixture_protocol_test.py,sha256=aWyzK9h9QNmpZJBu0ASaQ8BGYJt5T5KugN4OPMO5pCU,11129
|
|
389
389
|
cirq/protocols/apply_unitary_protocol.py,sha256=giJwec5XCEt5s0_uyNEuhGBlcDeJymPvuoIVx08hszY,29772
|
|
390
390
|
cirq/protocols/apply_unitary_protocol_test.py,sha256=ajjHvcBBv5n8Qh_hMPZkdsOvy1xJ774q4kuC25DJnKM,26136
|
|
391
391
|
cirq/protocols/approximate_equality_protocol.py,sha256=ZqnkoltD8vS1eQjV7Lw3RS49cdjZjGTF0LbdRUlBOCw,6257
|
|
@@ -409,12 +409,12 @@ cirq/protocols/inverse_protocol.py,sha256=aicyqdJVDbd-ZO-wKHA8S_5CcPl3HDhRklSSdo
|
|
|
409
409
|
cirq/protocols/inverse_protocol_test.py,sha256=pqqIU4_G4Npc9Z-SeoM9eCB2T5JRTeI02NCXhP0UtaI,2017
|
|
410
410
|
cirq/protocols/json_serialization.py,sha256=VJCEXB9fkIZh3_d6dkh_QDxwjC3iJAlELGHsCmAMvE4,24779
|
|
411
411
|
cirq/protocols/json_serialization_test.py,sha256=qrh6XTy6k-FCVAd3QvSV_ENHVf9UUgHOt_pzsniI6UM,28144
|
|
412
|
-
cirq/protocols/kraus_protocol.py,sha256=
|
|
412
|
+
cirq/protocols/kraus_protocol.py,sha256=NVzMsIyqxytGAui-avLdq3K0C7UqjckrTDvr0ENmDtQ,9300
|
|
413
413
|
cirq/protocols/kraus_protocol_test.py,sha256=NYVayiCaEpfvelsoR7bP57lUKn2pjFKYOiVOFHeZn9Q,5400
|
|
414
414
|
cirq/protocols/measurement_key_protocol.py,sha256=vqoxjmthtmQ1nWbi7Xd4fdxFNe5y3WL7DZkQ3M_VPnc,13409
|
|
415
415
|
cirq/protocols/measurement_key_protocol_test.py,sha256=W7yWKFVo6fMr7JjTECe8bMh1-NMDOpGMh3S-vmNl_3s,8654
|
|
416
|
-
cirq/protocols/mixture_protocol.py,sha256=
|
|
417
|
-
cirq/protocols/mixture_protocol_test.py,sha256=
|
|
416
|
+
cirq/protocols/mixture_protocol.py,sha256=L6FDIJmYqirVGsNwoUz5sulEDFoRUbhwz4yFL0ML2Po,6448
|
|
417
|
+
cirq/protocols/mixture_protocol_test.py,sha256=5mCh6JjlumMiSwDM818Nvo72AGxttuIYuawyESIQFtY,3818
|
|
418
418
|
cirq/protocols/mul_protocol.py,sha256=ZhkowiHCulggWanjoz6HpMGf0ODqDNIjM32knFKPuJ0,2770
|
|
419
419
|
cirq/protocols/mul_protocol_test.py,sha256=Qv7y17r-HjLXC7e-6t_Y6ht8lD_iiXE6CRyRFb7noGE,2136
|
|
420
420
|
cirq/protocols/pauli_expansion_protocol.py,sha256=vtpVoBlU1pXm4RQf3DDGervXwcW8jqNxs6ETHPSsp1I,3750
|
|
@@ -1209,8 +1209,8 @@ cirq/work/sampler.py,sha256=sW0RhIelGABAKbqTM58shwyyCPgf86JIv9IGdJe__js,19186
|
|
|
1209
1209
|
cirq/work/sampler_test.py,sha256=mdk1J-WrvbPUYhY41VhWf9_te4DnXr_XMPcugWwc4-I,13281
|
|
1210
1210
|
cirq/work/zeros_sampler.py,sha256=8_Ne6dBkDANtTZuql7Eb0Qg_E_P3-_gu-ybFzxTbKAQ,2356
|
|
1211
1211
|
cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
|
|
1212
|
-
cirq_core-1.5.0.
|
|
1213
|
-
cirq_core-1.5.0.
|
|
1214
|
-
cirq_core-1.5.0.
|
|
1215
|
-
cirq_core-1.5.0.
|
|
1216
|
-
cirq_core-1.5.0.
|
|
1212
|
+
cirq_core-1.5.0.dev20250405050852.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
|
1213
|
+
cirq_core-1.5.0.dev20250405050852.dist-info/METADATA,sha256=JbcLAzlUu5jxiad1Wd8Gb9vhve4q05YQnFhfyMBMgLI,4584
|
|
1214
|
+
cirq_core-1.5.0.dev20250405050852.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
1215
|
+
cirq_core-1.5.0.dev20250405050852.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
|
|
1216
|
+
cirq_core-1.5.0.dev20250405050852.dist-info/RECORD,,
|
{cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/LICENSE
RENAMED
|
File without changes
|
{cirq_core-1.5.0.dev20250404235631.dist-info → cirq_core-1.5.0.dev20250405050852.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|