cirq-core 1.7.0.dev20250915211227__py3-none-any.whl → 1.7.0.dev20250917023732__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/circuits/circuit_operation_test.py +5 -0
- cirq/ops/classically_controlled_operation.py +3 -7
- cirq/ops/measure_util.py +7 -6
- cirq/ops/pauli_string_test.py +2 -2
- cirq/ops/raw_types.py +19 -2
- cirq/protocols/has_stabilizer_effect_protocol_test.py +11 -9
- cirq/protocols/has_unitary_protocol_test.py +3 -3
- cirq/protocols/json_serialization.py +3 -3
- cirq/protocols/json_serialization_test.py +31 -31
- cirq/protocols/kraus_protocol_test.py +5 -5
- cirq/protocols/measurement_key_protocol.py +31 -8
- cirq/protocols/mixture_protocol.py +1 -1
- cirq/protocols/mixture_protocol_test.py +7 -7
- cirq/protocols/mul_protocol_test.py +4 -4
- cirq/protocols/phase_protocol.py +13 -4
- cirq/protocols/pow_protocol_test.py +5 -5
- cirq/protocols/resolve_parameters.py +1 -1
- cirq/protocols/unitary_protocol_test.py +31 -19
- cirq/qis/clifford_tableau.py +14 -14
- cirq/qis/clifford_tableau_test.py +17 -17
- cirq/qis/entropy.py +1 -1
- cirq/qis/entropy_test.py +1 -1
- cirq/qis/states_test.py +54 -54
- cirq/sim/classical_simulator_test.py +56 -28
- cirq/sim/clifford/clifford_simulator.py +5 -5
- cirq/sim/clifford/clifford_simulator_test.py +50 -49
- cirq/sim/clifford/stabilizer_state_ch_form.py +9 -9
- cirq/sim/density_matrix_simulation_state.py +6 -6
- cirq/sim/density_matrix_simulator.py +1 -1
- cirq/sim/density_matrix_simulator_test.py +94 -84
- cirq/sim/density_matrix_utils_test.py +1 -1
- cirq/sim/mux_test.py +26 -26
- cirq/sim/simulation_product_state_test.py +7 -7
- cirq/sim/simulation_state.py +4 -4
- cirq/sim/simulation_state_base.py +1 -1
- cirq/sim/simulation_state_test.py +5 -5
- cirq/sim/simulator.py +2 -2
- cirq/sim/simulator_base_test.py +49 -35
- cirq/sim/simulator_test.py +39 -35
- cirq/sim/sparse_simulator.py +1 -1
- cirq/sim/sparse_simulator_test.py +92 -82
- cirq/sim/state_vector.py +1 -1
- cirq/sim/state_vector_simulation_state.py +7 -7
- cirq/sim/state_vector_simulator_test.py +9 -9
- cirq/sim/state_vector_test.py +37 -37
- cirq/study/result_test.py +20 -20
- cirq/study/sweepable_test.py +20 -20
- cirq/study/sweeps_test.py +43 -43
- cirq/testing/circuit_compare_test.py +16 -14
- cirq/testing/consistent_channels.py +2 -2
- cirq/testing/consistent_controlled_gate_op.py +1 -1
- cirq/testing/consistent_decomposition.py +4 -2
- cirq/testing/consistent_phase_by.py +1 -1
- cirq/testing/consistent_qasm.py +2 -2
- cirq/testing/consistent_qasm_test.py +3 -3
- cirq/transformers/eject_z.py +1 -0
- cirq/transformers/gauge_compiling/__init__.py +5 -0
- cirq/transformers/gauge_compiling/idle_moments_gauge.py +222 -0
- cirq/transformers/gauge_compiling/idle_moments_gauge_test.py +193 -0
- {cirq_core-1.7.0.dev20250915211227.dist-info → cirq_core-1.7.0.dev20250917023732.dist-info}/METADATA +1 -1
- {cirq_core-1.7.0.dev20250915211227.dist-info → cirq_core-1.7.0.dev20250917023732.dist-info}/RECORD +66 -64
- {cirq_core-1.7.0.dev20250915211227.dist-info → cirq_core-1.7.0.dev20250917023732.dist-info}/WHEEL +0 -0
- {cirq_core-1.7.0.dev20250915211227.dist-info → cirq_core-1.7.0.dev20250917023732.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.7.0.dev20250915211227.dist-info → cirq_core-1.7.0.dev20250917023732.dist-info}/top_level.txt +0 -0
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
from types import NotImplementedType
|
|
20
|
-
from typing import Any, Mapping, Protocol, TYPE_CHECKING
|
|
20
|
+
from typing import Any, Mapping, overload, Protocol, TYPE_CHECKING, TypeVar
|
|
21
21
|
|
|
22
22
|
from cirq import value
|
|
23
23
|
from cirq._doc import doc_private
|
|
@@ -25,6 +25,9 @@ from cirq._doc import doc_private
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
26
|
import cirq
|
|
27
27
|
|
|
28
|
+
T = TypeVar('T')
|
|
29
|
+
TDefault = TypeVar('TDefault')
|
|
30
|
+
|
|
28
31
|
# This is a special indicator value used by the inverse method to determine
|
|
29
32
|
# whether or not the caller provided a 'default' argument.
|
|
30
33
|
RaiseTypeErrorIfNotProvided: Any = ([],)
|
|
@@ -104,7 +107,17 @@ class SupportsMeasurementKey(Protocol):
|
|
|
104
107
|
"""
|
|
105
108
|
|
|
106
109
|
|
|
107
|
-
|
|
110
|
+
@overload
|
|
111
|
+
def measurement_key_obj(val: Any) -> cirq.MeasurementKey:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@overload
|
|
116
|
+
def measurement_key_obj(val: Any, default: TDefault) -> cirq.MeasurementKey | TDefault:
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def measurement_key_obj(val, default=RaiseTypeErrorIfNotProvided):
|
|
108
121
|
"""Get the single measurement key object for the given value.
|
|
109
122
|
|
|
110
123
|
Args:
|
|
@@ -138,7 +151,17 @@ def measurement_key_obj(val: Any, default: Any = RaiseTypeErrorIfNotProvided):
|
|
|
138
151
|
raise TypeError(f"Object of type '{type(val)}' had no measurement keys.")
|
|
139
152
|
|
|
140
153
|
|
|
141
|
-
|
|
154
|
+
@overload
|
|
155
|
+
def measurement_key_name(val: Any) -> str:
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@overload
|
|
160
|
+
def measurement_key_name(val: Any, default: TDefault) -> str | TDefault:
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def measurement_key_name(val, default=RaiseTypeErrorIfNotProvided):
|
|
142
165
|
"""Get the single measurement key for the given value.
|
|
143
166
|
|
|
144
167
|
Args:
|
|
@@ -278,7 +301,7 @@ def is_measurement(val: Any) -> bool:
|
|
|
278
301
|
return keys is not NotImplemented and bool(keys)
|
|
279
302
|
|
|
280
303
|
|
|
281
|
-
def with_measurement_key_mapping(val:
|
|
304
|
+
def with_measurement_key_mapping(val: T, key_map: Mapping[str, str]) -> T:
|
|
282
305
|
"""Remaps the target's measurement keys according to the provided key_map.
|
|
283
306
|
|
|
284
307
|
This method can be used to reassign measurement keys at runtime, or to
|
|
@@ -288,7 +311,7 @@ def with_measurement_key_mapping(val: Any, key_map: Mapping[str, str]):
|
|
|
288
311
|
return NotImplemented if getter is None else getter(key_map)
|
|
289
312
|
|
|
290
313
|
|
|
291
|
-
def with_key_path(val:
|
|
314
|
+
def with_key_path(val: T, path: tuple[str, ...]) -> T:
|
|
292
315
|
"""Adds the path to the target's measurement keys.
|
|
293
316
|
|
|
294
317
|
The path usually refers to an identifier or a list of identifiers from a subcircuit that
|
|
@@ -299,7 +322,7 @@ def with_key_path(val: Any, path: tuple[str, ...]):
|
|
|
299
322
|
return NotImplemented if getter is None else getter(path)
|
|
300
323
|
|
|
301
324
|
|
|
302
|
-
def with_key_path_prefix(val:
|
|
325
|
+
def with_key_path_prefix(val: T, prefix: tuple[str, ...]) -> T:
|
|
303
326
|
"""Prefixes the path to the target's measurement keys.
|
|
304
327
|
|
|
305
328
|
The path usually refers to an identifier or a list of identifiers from a subcircuit that
|
|
@@ -315,8 +338,8 @@ def with_key_path_prefix(val: Any, prefix: tuple[str, ...]):
|
|
|
315
338
|
|
|
316
339
|
|
|
317
340
|
def with_rescoped_keys(
|
|
318
|
-
val:
|
|
319
|
-
):
|
|
341
|
+
val: T, path: tuple[str, ...], bindable_keys: frozenset[cirq.MeasurementKey] | None = None
|
|
342
|
+
) -> T:
|
|
320
343
|
"""Rescopes any measurement and control keys to the provided path, given the existing keys.
|
|
321
344
|
|
|
322
345
|
The path usually refers to an identifier or a list of identifiers from a subcircuit that
|
|
@@ -148,7 +148,7 @@ def has_mixture(val: Any, *, allow_decompose: bool = True) -> bool:
|
|
|
148
148
|
return mixture(val, None) is not None
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
def validate_mixture(supports_mixture: SupportsMixture):
|
|
151
|
+
def validate_mixture(supports_mixture: SupportsMixture) -> None:
|
|
152
152
|
"""Validates that the mixture's tuple are valid probabilities."""
|
|
153
153
|
mixture_tuple = mixture(supports_mixture, None)
|
|
154
154
|
if mixture_tuple is None:
|
|
@@ -93,7 +93,7 @@ class ReturnsMixtureOfReturnsUnitary:
|
|
|
93
93
|
(ReturnsMixtureOfReturnsUnitary(), ((0.4, np.eye(2)), (0.6, np.eye(2)))),
|
|
94
94
|
),
|
|
95
95
|
)
|
|
96
|
-
def test_objects_with_mixture(val, mixture):
|
|
96
|
+
def test_objects_with_mixture(val, mixture) -> None:
|
|
97
97
|
expected_keys, expected_values = zip(*mixture)
|
|
98
98
|
keys, values = zip(*cirq.mixture(val))
|
|
99
99
|
np.testing.assert_almost_equal(keys, expected_keys)
|
|
@@ -107,7 +107,7 @@ def test_objects_with_mixture(val, mixture):
|
|
|
107
107
|
@pytest.mark.parametrize(
|
|
108
108
|
'val', (NoMethod(), ReturnsNotImplemented(), ReturnsNotImplementedUnitary())
|
|
109
109
|
)
|
|
110
|
-
def test_objects_with_no_mixture(val):
|
|
110
|
+
def test_objects_with_no_mixture(val) -> None:
|
|
111
111
|
with pytest.raises(TypeError, match="mixture"):
|
|
112
112
|
_ = cirq.mixture(val)
|
|
113
113
|
assert cirq.mixture(val, None) is None
|
|
@@ -116,7 +116,7 @@ def test_objects_with_no_mixture(val):
|
|
|
116
116
|
assert cirq.mixture(val, default) == default
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
def test_has_mixture():
|
|
119
|
+
def test_has_mixture() -> None:
|
|
120
120
|
assert cirq.has_mixture(ReturnsValidTuple())
|
|
121
121
|
assert not cirq.has_mixture(ReturnsNotImplemented())
|
|
122
122
|
assert cirq.has_mixture(ReturnsMixtureButNoHasMixture())
|
|
@@ -124,7 +124,7 @@ def test_has_mixture():
|
|
|
124
124
|
assert not cirq.has_mixture(ReturnsNotImplementedUnitary())
|
|
125
125
|
|
|
126
126
|
|
|
127
|
-
def test_valid_mixture():
|
|
127
|
+
def test_valid_mixture() -> None:
|
|
128
128
|
cirq.validate_mixture(ReturnsValidTuple())
|
|
129
129
|
|
|
130
130
|
|
|
@@ -136,11 +136,11 @@ def test_valid_mixture():
|
|
|
136
136
|
(ReturnsGreaterThanUnityProbability(), 'greater than 1'),
|
|
137
137
|
),
|
|
138
138
|
)
|
|
139
|
-
def test_invalid_mixture(val, message):
|
|
139
|
+
def test_invalid_mixture(val, message) -> None:
|
|
140
140
|
with pytest.raises(ValueError, match=message):
|
|
141
141
|
cirq.validate_mixture(val)
|
|
142
142
|
|
|
143
143
|
|
|
144
|
-
def test_missing_mixture():
|
|
144
|
+
def test_missing_mixture() -> None:
|
|
145
145
|
with pytest.raises(TypeError, match='_mixture_'):
|
|
146
|
-
cirq.validate_mixture(NoMethod)
|
|
146
|
+
cirq.validate_mixture(NoMethod) # type: ignore[arg-type]
|
|
@@ -52,7 +52,7 @@ class MulSevenRMulEight:
|
|
|
52
52
|
return 8
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def test_equivalent_to_builtin_mul():
|
|
55
|
+
def test_equivalent_to_builtin_mul() -> None:
|
|
56
56
|
test_vals = [
|
|
57
57
|
0,
|
|
58
58
|
1,
|
|
@@ -76,14 +76,14 @@ def test_equivalent_to_builtin_mul():
|
|
|
76
76
|
c = cirq.mul(a, b, default=None)
|
|
77
77
|
if c is None:
|
|
78
78
|
with pytest.raises(TypeError):
|
|
79
|
-
_ = a * b
|
|
79
|
+
_ = a * b # type: ignore[operator]
|
|
80
80
|
with pytest.raises(TypeError):
|
|
81
81
|
_ = cirq.mul(a, b)
|
|
82
82
|
else:
|
|
83
|
-
assert c == a * b
|
|
83
|
+
assert c == a * b # type: ignore[operator]
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def test_symbol_special_case():
|
|
86
|
+
def test_symbol_special_case() -> None:
|
|
87
87
|
x = sympy.Symbol('x')
|
|
88
88
|
assert cirq.mul(x, 1.0) is x
|
|
89
89
|
assert cirq.mul(1.0, x) is x
|
cirq/protocols/phase_protocol.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import Any, Protocol, TypeVar
|
|
17
|
+
from typing import Any, overload, Protocol, TypeVar
|
|
18
18
|
|
|
19
19
|
# This is a special value to indicate that a type error should be returned.
|
|
20
20
|
# This is used within phase_by to raise an error if no underlying
|
|
@@ -24,6 +24,7 @@ from cirq._doc import doc_private
|
|
|
24
24
|
RaiseTypeErrorIfNotProvided: Any = ([],)
|
|
25
25
|
|
|
26
26
|
TDefault = TypeVar('TDefault')
|
|
27
|
+
T = TypeVar('T')
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class SupportsPhase(Protocol):
|
|
@@ -47,9 +48,17 @@ class SupportsPhase(Protocol):
|
|
|
47
48
|
"""
|
|
48
49
|
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
@overload
|
|
52
|
+
def phase_by(val: T, phase_turns: float, qubit_index: int) -> T:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@overload
|
|
57
|
+
def phase_by(val: T, phase_turns: float, qubit_index: int, default: TDefault) -> T | TDefault:
|
|
58
|
+
pass
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def phase_by(val, phase_turns, qubit_index, default=RaiseTypeErrorIfNotProvided):
|
|
53
62
|
"""Returns a phased version of the effect.
|
|
54
63
|
|
|
55
64
|
For example, an X gate phased by 90 degrees would be a Y gate.
|
|
@@ -34,7 +34,7 @@ class ReturnsExponent:
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
@pytest.mark.parametrize('val', (NoMethod(), 'text', object(), ReturnsNotImplemented()))
|
|
37
|
-
def test_powerless(val):
|
|
37
|
+
def test_powerless(val) -> None:
|
|
38
38
|
assert cirq.pow(val, 5, None) is None
|
|
39
39
|
assert cirq.pow(val, 2, NotImplemented) is NotImplemented
|
|
40
40
|
|
|
@@ -42,13 +42,13 @@ def test_powerless(val):
|
|
|
42
42
|
assert cirq.pow(val, 1, None) is None
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
def test_pow_error():
|
|
45
|
+
def test_pow_error() -> None:
|
|
46
46
|
with pytest.raises(TypeError, match="returned NotImplemented"):
|
|
47
|
-
_ = cirq.pow(ReturnsNotImplemented(), 3)
|
|
47
|
+
_ = cirq.pow(ReturnsNotImplemented(), 3) # type: ignore[call-overload]
|
|
48
48
|
with pytest.raises(TypeError, match="no __pow__ method"):
|
|
49
|
-
_ = cirq.pow(NoMethod(), 3)
|
|
49
|
+
_ = cirq.pow(NoMethod(), 3) # type: ignore[call-overload]
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
@pytest.mark.parametrize('val,exponent,out', ((ReturnsExponent(), 2, 2), (1, 2, 1), (2, 3, 8)))
|
|
53
|
-
def test_pow_with_result(val, exponent, out):
|
|
53
|
+
def test_pow_with_result(val, exponent, out) -> None:
|
|
54
54
|
assert cirq.pow(val, exponent) == cirq.pow(val, exponent, default=None) == val**exponent == out
|
|
@@ -196,6 +196,6 @@ def resolve_parameters(
|
|
|
196
196
|
return val
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
def resolve_parameters_once(val:
|
|
199
|
+
def resolve_parameters_once(val: T, param_resolver: cirq.ParamResolverOrSimilarType) -> T:
|
|
200
200
|
"""Performs a single parameter resolution step using the param resolver."""
|
|
201
201
|
return resolve_parameters(val, param_resolver, False)
|
|
@@ -56,7 +56,7 @@ class ReturnsNotImplemented(cirq.Gate):
|
|
|
56
56
|
def _unitary_(self):
|
|
57
57
|
return NotImplemented
|
|
58
58
|
|
|
59
|
-
def num_qubits(self):
|
|
59
|
+
def num_qubits(self) -> int:
|
|
60
60
|
return 1
|
|
61
61
|
|
|
62
62
|
|
|
@@ -64,7 +64,7 @@ class ReturnsMatrix(cirq.Gate):
|
|
|
64
64
|
def _unitary_(self) -> np.ndarray:
|
|
65
65
|
return m1
|
|
66
66
|
|
|
67
|
-
def num_qubits(self):
|
|
67
|
+
def num_qubits(self) -> int:
|
|
68
68
|
return 1 # pragma: no cover
|
|
69
69
|
|
|
70
70
|
|
|
@@ -80,7 +80,7 @@ class FullyImplemented(cirq.Gate):
|
|
|
80
80
|
return None
|
|
81
81
|
return m1
|
|
82
82
|
|
|
83
|
-
def num_qubits(self):
|
|
83
|
+
def num_qubits(self) -> int:
|
|
84
84
|
return 1
|
|
85
85
|
|
|
86
86
|
|
|
@@ -88,7 +88,7 @@ class DecomposableGate(cirq.Gate):
|
|
|
88
88
|
def __init__(self, unitary_value):
|
|
89
89
|
self.unitary_value = unitary_value
|
|
90
90
|
|
|
91
|
-
def num_qubits(self):
|
|
91
|
+
def num_qubits(self) -> int:
|
|
92
92
|
return 1
|
|
93
93
|
|
|
94
94
|
def _decompose_(self, qubits):
|
|
@@ -154,7 +154,7 @@ class OtherComposite:
|
|
|
154
154
|
yield cirq.X(cirq.LineQubit(3))
|
|
155
155
|
|
|
156
156
|
|
|
157
|
-
def test_unitary():
|
|
157
|
+
def test_unitary() -> None:
|
|
158
158
|
with pytest.raises(TypeError, match='unitary effect'):
|
|
159
159
|
_ = cirq.unitary(NoMethod())
|
|
160
160
|
with pytest.raises(TypeError, match='unitary effect'):
|
|
@@ -186,7 +186,7 @@ def test_unitary():
|
|
|
186
186
|
assert cirq.unitary(FullyImplemented(False), default=None) is None
|
|
187
187
|
|
|
188
188
|
|
|
189
|
-
def test_has_unitary():
|
|
189
|
+
def test_has_unitary() -> None:
|
|
190
190
|
assert not cirq.has_unitary(NoMethod())
|
|
191
191
|
assert not cirq.has_unitary(ReturnsNotImplemented())
|
|
192
192
|
assert cirq.has_unitary(ReturnsMatrix())
|
|
@@ -215,7 +215,7 @@ def _test_gate_that_allocates_qubits(gate):
|
|
|
215
215
|
@pytest.mark.parametrize('ancilla_bitsize', [1, 4])
|
|
216
216
|
def test_decompose_gate_that_allocates_clean_qubits(
|
|
217
217
|
theta: float, phase_state: int, target_bitsize: int, ancilla_bitsize: int
|
|
218
|
-
):
|
|
218
|
+
) -> None:
|
|
219
219
|
gate = testing.PhaseUsingCleanAncilla(theta, phase_state, target_bitsize, ancilla_bitsize)
|
|
220
220
|
_test_gate_that_allocates_qubits(gate)
|
|
221
221
|
|
|
@@ -225,26 +225,38 @@ def test_decompose_gate_that_allocates_clean_qubits(
|
|
|
225
225
|
@pytest.mark.parametrize('ancilla_bitsize', [1, 4])
|
|
226
226
|
def test_decompose_gate_that_allocates_dirty_qubits(
|
|
227
227
|
phase_state: int, target_bitsize: int, ancilla_bitsize: int
|
|
228
|
-
):
|
|
228
|
+
) -> None:
|
|
229
229
|
gate = testing.PhaseUsingDirtyAncilla(phase_state, target_bitsize, ancilla_bitsize)
|
|
230
230
|
_test_gate_that_allocates_qubits(gate)
|
|
231
231
|
|
|
232
232
|
|
|
233
|
-
def test_decompose_and_get_unitary():
|
|
233
|
+
def test_decompose_and_get_unitary() -> None:
|
|
234
234
|
from cirq.protocols.unitary_protocol import _strat_unitary_from_decompose
|
|
235
235
|
|
|
236
|
-
np.testing.assert_allclose(_strat_unitary_from_decompose(DecomposableOperation((a,), True)), m1)
|
|
237
236
|
np.testing.assert_allclose(
|
|
238
|
-
_strat_unitary_from_decompose(DecomposableOperation((a,
|
|
237
|
+
_strat_unitary_from_decompose(DecomposableOperation((a,), True)), m1 # type: ignore[arg-type]
|
|
238
|
+
)
|
|
239
|
+
np.testing.assert_allclose(
|
|
240
|
+
_strat_unitary_from_decompose(DecomposableOperation((a, b), True)), m2 # type: ignore[arg-type]
|
|
241
|
+
)
|
|
242
|
+
np.testing.assert_allclose(
|
|
243
|
+
_strat_unitary_from_decompose(DecomposableOrder((a, b, c))), m3 # type: ignore[arg-type]
|
|
244
|
+
)
|
|
245
|
+
np.testing.assert_allclose(
|
|
246
|
+
_strat_unitary_from_decompose(ExampleOperation((a,))), np.eye(2) # type: ignore[arg-type]
|
|
247
|
+
)
|
|
248
|
+
np.testing.assert_allclose(
|
|
249
|
+
_strat_unitary_from_decompose(ExampleOperation((a, b))), np.eye(4) # type: ignore[arg-type]
|
|
250
|
+
)
|
|
251
|
+
np.testing.assert_allclose(
|
|
252
|
+
_strat_unitary_from_decompose(ExampleComposite()), np.eye(1) # type: ignore[arg-type]
|
|
253
|
+
)
|
|
254
|
+
np.testing.assert_allclose(
|
|
255
|
+
_strat_unitary_from_decompose(OtherComposite()), m2 # type: ignore[arg-type]
|
|
239
256
|
)
|
|
240
|
-
np.testing.assert_allclose(_strat_unitary_from_decompose(DecomposableOrder((a, b, c))), m3)
|
|
241
|
-
np.testing.assert_allclose(_strat_unitary_from_decompose(ExampleOperation((a,))), np.eye(2))
|
|
242
|
-
np.testing.assert_allclose(_strat_unitary_from_decompose(ExampleOperation((a, b))), np.eye(4))
|
|
243
|
-
np.testing.assert_allclose(_strat_unitary_from_decompose(ExampleComposite()), np.eye(1))
|
|
244
|
-
np.testing.assert_allclose(_strat_unitary_from_decompose(OtherComposite()), m2)
|
|
245
257
|
|
|
246
258
|
|
|
247
|
-
def test_decomposed_has_unitary():
|
|
259
|
+
def test_decomposed_has_unitary() -> None:
|
|
248
260
|
# Gates
|
|
249
261
|
assert cirq.has_unitary(DecomposableGate(True))
|
|
250
262
|
assert not cirq.has_unitary(DecomposableGate(False))
|
|
@@ -263,7 +275,7 @@ def test_decomposed_has_unitary():
|
|
|
263
275
|
assert cirq.has_unitary(OtherComposite())
|
|
264
276
|
|
|
265
277
|
|
|
266
|
-
def test_decomposed_unitary():
|
|
278
|
+
def test_decomposed_unitary() -> None:
|
|
267
279
|
# Gates
|
|
268
280
|
np.testing.assert_allclose(cirq.unitary(DecomposableGate(True)), m1)
|
|
269
281
|
|
|
@@ -283,7 +295,7 @@ def test_decomposed_unitary():
|
|
|
283
295
|
np.testing.assert_allclose(cirq.unitary(OtherComposite()), m2)
|
|
284
296
|
|
|
285
297
|
|
|
286
|
-
def test_unitary_from_apply_unitary():
|
|
298
|
+
def test_unitary_from_apply_unitary() -> None:
|
|
287
299
|
class ApplyGate(cirq.Gate):
|
|
288
300
|
def num_qubits(self):
|
|
289
301
|
return 1
|
cirq/qis/clifford_tableau.py
CHANGED
|
@@ -38,7 +38,7 @@ class StabilizerState(
|
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
@abc.abstractmethod
|
|
41
|
-
def apply_x(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
41
|
+
def apply_x(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
42
42
|
"""Apply an X operation to the state.
|
|
43
43
|
|
|
44
44
|
Args:
|
|
@@ -51,7 +51,7 @@ class StabilizerState(
|
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
53
|
@abc.abstractmethod
|
|
54
|
-
def apply_y(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
54
|
+
def apply_y(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
55
55
|
"""Apply an Y operation to the state.
|
|
56
56
|
|
|
57
57
|
Args:
|
|
@@ -64,7 +64,7 @@ class StabilizerState(
|
|
|
64
64
|
"""
|
|
65
65
|
|
|
66
66
|
@abc.abstractmethod
|
|
67
|
-
def apply_z(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
67
|
+
def apply_z(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
68
68
|
"""Apply a Z operation to the state.
|
|
69
69
|
|
|
70
70
|
Args:
|
|
@@ -77,7 +77,7 @@ class StabilizerState(
|
|
|
77
77
|
"""
|
|
78
78
|
|
|
79
79
|
@abc.abstractmethod
|
|
80
|
-
def apply_h(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
80
|
+
def apply_h(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
81
81
|
"""Apply an H operation to the state.
|
|
82
82
|
|
|
83
83
|
Args:
|
|
@@ -92,7 +92,7 @@ class StabilizerState(
|
|
|
92
92
|
@abc.abstractmethod
|
|
93
93
|
def apply_cz(
|
|
94
94
|
self, control_axis: int, target_axis: int, exponent: float = 1, global_shift: float = 0
|
|
95
|
-
):
|
|
95
|
+
) -> None:
|
|
96
96
|
"""Apply a CZ operation to the state.
|
|
97
97
|
|
|
98
98
|
Args:
|
|
@@ -108,7 +108,7 @@ class StabilizerState(
|
|
|
108
108
|
@abc.abstractmethod
|
|
109
109
|
def apply_cx(
|
|
110
110
|
self, control_axis: int, target_axis: int, exponent: float = 1, global_shift: float = 0
|
|
111
|
-
):
|
|
111
|
+
) -> None:
|
|
112
112
|
"""Apply a CX operation to the state.
|
|
113
113
|
|
|
114
114
|
Args:
|
|
@@ -122,7 +122,7 @@ class StabilizerState(
|
|
|
122
122
|
"""
|
|
123
123
|
|
|
124
124
|
@abc.abstractmethod
|
|
125
|
-
def apply_global_phase(self, coefficient: linear_dict.Scalar):
|
|
125
|
+
def apply_global_phase(self, coefficient: linear_dict.Scalar) -> None:
|
|
126
126
|
"""Apply a global phase to the state.
|
|
127
127
|
|
|
128
128
|
Args:
|
|
@@ -561,7 +561,7 @@ class CliffordTableau(StabilizerState):
|
|
|
561
561
|
|
|
562
562
|
return int(self.rs[p])
|
|
563
563
|
|
|
564
|
-
def apply_x(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
564
|
+
def apply_x(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
565
565
|
if exponent % 2 == 0:
|
|
566
566
|
return
|
|
567
567
|
if exponent % 0.5 != 0.0:
|
|
@@ -576,7 +576,7 @@ class CliffordTableau(StabilizerState):
|
|
|
576
576
|
self.rs[:] ^= self.xs[:, axis] & self.zs[:, axis]
|
|
577
577
|
self.xs[:, axis] ^= self.zs[:, axis]
|
|
578
578
|
|
|
579
|
-
def apply_y(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
579
|
+
def apply_y(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
580
580
|
if exponent % 2 == 0:
|
|
581
581
|
return
|
|
582
582
|
if exponent % 0.5 != 0.0:
|
|
@@ -597,7 +597,7 @@ class CliffordTableau(StabilizerState):
|
|
|
597
597
|
self.xs[:, axis].copy(),
|
|
598
598
|
)
|
|
599
599
|
|
|
600
|
-
def apply_z(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
600
|
+
def apply_z(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
601
601
|
if exponent % 2 == 0:
|
|
602
602
|
return
|
|
603
603
|
if exponent % 0.5 != 0.0:
|
|
@@ -612,7 +612,7 @@ class CliffordTableau(StabilizerState):
|
|
|
612
612
|
self.rs[:] ^= self.xs[:, axis] & (~self.zs[:, axis])
|
|
613
613
|
self.zs[:, axis] ^= self.xs[:, axis]
|
|
614
614
|
|
|
615
|
-
def apply_h(self, axis: int, exponent: float = 1, global_shift: float = 0):
|
|
615
|
+
def apply_h(self, axis: int, exponent: float = 1, global_shift: float = 0) -> None:
|
|
616
616
|
if exponent % 2 == 0:
|
|
617
617
|
return
|
|
618
618
|
if exponent % 1 != 0:
|
|
@@ -622,7 +622,7 @@ class CliffordTableau(StabilizerState):
|
|
|
622
622
|
|
|
623
623
|
def apply_cz(
|
|
624
624
|
self, control_axis: int, target_axis: int, exponent: float = 1, global_shift: float = 0
|
|
625
|
-
):
|
|
625
|
+
) -> None:
|
|
626
626
|
if exponent % 2 == 0:
|
|
627
627
|
return
|
|
628
628
|
if exponent % 1 != 0:
|
|
@@ -647,7 +647,7 @@ class CliffordTableau(StabilizerState):
|
|
|
647
647
|
|
|
648
648
|
def apply_cx(
|
|
649
649
|
self, control_axis: int, target_axis: int, exponent: float = 1, global_shift: float = 0
|
|
650
|
-
):
|
|
650
|
+
) -> None:
|
|
651
651
|
if exponent % 2 == 0:
|
|
652
652
|
return
|
|
653
653
|
if exponent % 1 != 0:
|
|
@@ -660,7 +660,7 @@ class CliffordTableau(StabilizerState):
|
|
|
660
660
|
self.xs[:, target_axis] ^= self.xs[:, control_axis]
|
|
661
661
|
self.zs[:, control_axis] ^= self.zs[:, target_axis]
|
|
662
662
|
|
|
663
|
-
def apply_global_phase(self, coefficient: linear_dict.Scalar):
|
|
663
|
+
def apply_global_phase(self, coefficient: linear_dict.Scalar) -> None:
|
|
664
664
|
pass
|
|
665
665
|
|
|
666
666
|
def measure(
|
|
@@ -47,7 +47,7 @@ def _CNOT(table, q1, q2):
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
@pytest.mark.parametrize('num_qubits', range(1, 4))
|
|
50
|
-
def test_tableau_initial_state_string(num_qubits):
|
|
50
|
+
def test_tableau_initial_state_string(num_qubits) -> None:
|
|
51
51
|
for i in range(2**num_qubits):
|
|
52
52
|
t = cirq.CliffordTableau(initial_state=i, num_qubits=num_qubits)
|
|
53
53
|
splitted_represent_string = str(t).split('\n')
|
|
@@ -58,7 +58,7 @@ def test_tableau_initial_state_string(num_qubits):
|
|
|
58
58
|
assert splitted_represent_string[n] == expected_string
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
def test_tableau_invalid_initial_state():
|
|
61
|
+
def test_tableau_invalid_initial_state() -> None:
|
|
62
62
|
with pytest.raises(ValueError, match="2*num_qubits columns and of type bool."):
|
|
63
63
|
cirq.CliffordTableau(1, rs=np.zeros(1, dtype=bool))
|
|
64
64
|
|
|
@@ -73,7 +73,7 @@ def test_tableau_invalid_initial_state():
|
|
|
73
73
|
cirq.CliffordTableau(1, zs=np.zeros(1, dtype=bool))
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
def test_stabilizers():
|
|
76
|
+
def test_stabilizers() -> None:
|
|
77
77
|
# Note: the stabilizers are not unique for one state. We just use the one
|
|
78
78
|
# produced by the tableau algorithm.
|
|
79
79
|
# 1. Final state is |1>: Stabalized by -Z.
|
|
@@ -101,7 +101,7 @@ def test_stabilizers():
|
|
|
101
101
|
assert stabilizers[1] == cirq.DensePauliString('IX', coefficient=1)
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
def test_destabilizers():
|
|
104
|
+
def test_destabilizers() -> None:
|
|
105
105
|
# Note: Like stablizers, the destabilizers are not unique for one state, too.
|
|
106
106
|
# We just use the one produced by the tableau algorithm.
|
|
107
107
|
# Under the clifford tableau algorithm, there are several properties that the
|
|
@@ -135,7 +135,7 @@ def test_destabilizers():
|
|
|
135
135
|
assert destabilizers[1] == cirq.DensePauliString('IZ', coefficient=1)
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-
def test_measurement():
|
|
138
|
+
def test_measurement() -> None:
|
|
139
139
|
repetitions = 500
|
|
140
140
|
prng = np.random.RandomState(seed=123456)
|
|
141
141
|
|
|
@@ -195,7 +195,7 @@ def test_measurement():
|
|
|
195
195
|
assert sum(np.asarray(res) == 3) >= (repetitions / 4 * 0.9)
|
|
196
196
|
|
|
197
197
|
|
|
198
|
-
def test_validate_tableau():
|
|
198
|
+
def test_validate_tableau() -> None:
|
|
199
199
|
num_qubits = 4
|
|
200
200
|
for i in range(2**num_qubits):
|
|
201
201
|
t = cirq.CliffordTableau(initial_state=i, num_qubits=num_qubits)
|
|
@@ -218,7 +218,7 @@ def test_validate_tableau():
|
|
|
218
218
|
assert not t._validate()
|
|
219
219
|
|
|
220
220
|
|
|
221
|
-
def test_rowsum():
|
|
221
|
+
def test_rowsum() -> None:
|
|
222
222
|
# Note: rowsum should not apply on two rows that anti-commute each other.
|
|
223
223
|
t = cirq.CliffordTableau(num_qubits=2)
|
|
224
224
|
# XI * IX ==> XX
|
|
@@ -246,7 +246,7 @@ def test_rowsum():
|
|
|
246
246
|
assert t.stabilizers()[1] == cirq.DensePauliString('YX', coefficient=1)
|
|
247
247
|
|
|
248
248
|
|
|
249
|
-
def test_json_dict():
|
|
249
|
+
def test_json_dict() -> None:
|
|
250
250
|
t = cirq.CliffordTableau._from_json_dict_(n=1, rs=[0, 0], xs=[[1], [0]], zs=[[0], [1]])
|
|
251
251
|
assert t.destabilizers()[0] == cirq.DensePauliString('X', coefficient=1)
|
|
252
252
|
assert t.stabilizers()[0] == cirq.DensePauliString('Z', coefficient=1)
|
|
@@ -266,7 +266,7 @@ def test_json_dict():
|
|
|
266
266
|
assert json_dict[k] == v
|
|
267
267
|
|
|
268
268
|
|
|
269
|
-
def test_str():
|
|
269
|
+
def test_str() -> None:
|
|
270
270
|
t = cirq.CliffordTableau(num_qubits=2)
|
|
271
271
|
splitted_represent_string = str(t).split('\n')
|
|
272
272
|
assert len(splitted_represent_string) == 2
|
|
@@ -288,11 +288,11 @@ def test_str():
|
|
|
288
288
|
assert splitted_represent_string[1] == '+ I Y '
|
|
289
289
|
|
|
290
290
|
|
|
291
|
-
def test_repr():
|
|
291
|
+
def test_repr() -> None:
|
|
292
292
|
cirq.testing.assert_equivalent_repr(cirq.CliffordTableau(num_qubits=1))
|
|
293
293
|
|
|
294
294
|
|
|
295
|
-
def test_str_full():
|
|
295
|
+
def test_str_full() -> None:
|
|
296
296
|
t = cirq.CliffordTableau(num_qubits=1)
|
|
297
297
|
expected_str = r"""stable | destable
|
|
298
298
|
-------+----------
|
|
@@ -317,7 +317,7 @@ def test_str_full():
|
|
|
317
317
|
assert t._str_full_() == expected_str
|
|
318
318
|
|
|
319
319
|
|
|
320
|
-
def test_copy():
|
|
320
|
+
def test_copy() -> None:
|
|
321
321
|
t = cirq.CliffordTableau(num_qubits=3, initial_state=3)
|
|
322
322
|
new_t = t.copy()
|
|
323
323
|
|
|
@@ -340,7 +340,7 @@ def _three_identical_table(num_qubits):
|
|
|
340
340
|
return t1, t2, t3
|
|
341
341
|
|
|
342
342
|
|
|
343
|
-
def test_tableau_then():
|
|
343
|
+
def test_tableau_then() -> None:
|
|
344
344
|
|
|
345
345
|
t1, t2, expected_t = _three_identical_table(1)
|
|
346
346
|
assert expected_t == t1.then(t2)
|
|
@@ -427,7 +427,7 @@ def test_tableau_then():
|
|
|
427
427
|
assert expected_t == t1.then(t2)
|
|
428
428
|
|
|
429
429
|
|
|
430
|
-
def test_tableau_matmul():
|
|
430
|
+
def test_tableau_matmul() -> None:
|
|
431
431
|
t1, t2, expected_t = _three_identical_table(1)
|
|
432
432
|
_ = [_H(t, 0) for t in (t1, expected_t)]
|
|
433
433
|
_ = [_H(t, 0) for t in (t2, expected_t)]
|
|
@@ -443,17 +443,17 @@ def test_tableau_matmul():
|
|
|
443
443
|
t1 @ 21
|
|
444
444
|
|
|
445
445
|
|
|
446
|
-
def test_tableau_then_with_bad_input():
|
|
446
|
+
def test_tableau_then_with_bad_input() -> None:
|
|
447
447
|
t1 = cirq.CliffordTableau(1)
|
|
448
448
|
t2 = cirq.CliffordTableau(2)
|
|
449
449
|
with pytest.raises(ValueError, match="Mismatched number of qubits of two tableaux: 1 vs 2."):
|
|
450
450
|
t1.then(t2)
|
|
451
451
|
|
|
452
452
|
with pytest.raises(TypeError):
|
|
453
|
-
t1.then(cirq.X)
|
|
453
|
+
t1.then(cirq.X) # type: ignore[arg-type]
|
|
454
454
|
|
|
455
455
|
|
|
456
|
-
def test_inverse():
|
|
456
|
+
def test_inverse() -> None:
|
|
457
457
|
t = cirq.CliffordTableau(num_qubits=1)
|
|
458
458
|
assert t.inverse() == t
|
|
459
459
|
|
cirq/qis/entropy.py
CHANGED
|
@@ -93,7 +93,7 @@ def _compute_bitstrings_contribution_to_purity(bitstrings: npt.NDArray[np.int8])
|
|
|
93
93
|
|
|
94
94
|
def process_renyi_entropy_from_bitstrings(
|
|
95
95
|
measured_bitstrings: npt.NDArray[np.int8],
|
|
96
|
-
subsystem: tuple[int] | None = None,
|
|
96
|
+
subsystem: tuple[int, ...] | None = None,
|
|
97
97
|
pool: ThreadPoolExecutor | None = None,
|
|
98
98
|
) -> float:
|
|
99
99
|
"""Compute the Rényi entropy of an array of bitstrings.
|
cirq/qis/entropy_test.py
CHANGED
|
@@ -23,7 +23,7 @@ from cirq.qis.entropy import process_renyi_entropy_from_bitstrings
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
@pytest.mark.parametrize('pool', [None, ThreadPoolExecutor(max_workers=1)])
|
|
26
|
-
def test_process_renyi_entropy_from_bitstrings(pool):
|
|
26
|
+
def test_process_renyi_entropy_from_bitstrings(pool) -> None:
|
|
27
27
|
bitstrings = np.array(
|
|
28
28
|
[
|
|
29
29
|
[[0, 1, 1, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 1, 1, 1]],
|