cirq-core 1.7.0.dev20251002223432__py3-none-any.whl → 1.7.0.dev20251003181338__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/_doc.py +4 -3
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/linalg/decompositions.py +3 -0
- cirq/linalg/decompositions_test.py +1 -0
- cirq/ops/fourier_transform_test.py +2 -4
- cirq/ops/raw_types.py +3 -0
- cirq/protocols/apply_unitary_protocol_test.py +2 -0
- cirq/protocols/kraus_protocol.py +3 -3
- cirq/protocols/kraus_protocol_test.py +2 -2
- cirq/protocols/unitary_protocol.py +1 -1
- cirq/testing/consistent_resolve_parameters.py +1 -1
- cirq/testing/consistent_unitary.py +1 -1
- cirq/testing/consistent_unitary_test.py +1 -1
- cirq/testing/equals_tester.py +2 -2
- cirq/testing/equivalent_basis_map.py +3 -1
- cirq/testing/json.py +1 -1
- cirq/testing/op_tree.py +1 -1
- cirq/testing/order_tester.py +2 -2
- cirq/testing/repr_pretty_tester.py +3 -3
- cirq/transformers/align_test.py +13 -13
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +8 -8
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +5 -5
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +11 -11
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +6 -6
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +10 -9
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +5 -5
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +17 -18
- cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +32 -26
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +12 -11
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +3 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +3 -3
- cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +32 -30
- cirq/transformers/drop_negligible_operations_test.py +7 -7
- cirq/transformers/dynamical_decoupling_test.py +22 -22
- cirq/transformers/eject_phased_paulis_test.py +1 -1
- cirq/transformers/eject_z.py +2 -2
- cirq/transformers/eject_z_test.py +23 -25
- cirq/transformers/expand_composite.py +1 -1
- cirq/transformers/expand_composite_test.py +14 -14
- cirq/transformers/gauge_compiling/gauge_compiling.py +1 -1
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +14 -12
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +3 -3
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +6 -6
- cirq/transformers/measurement_transformers_test.py +45 -39
- cirq/transformers/merge_k_qubit_gates_test.py +1 -1
- cirq/transformers/merge_single_qubit_gates_test.py +22 -22
- cirq/transformers/noise_adding_test.py +2 -2
- cirq/transformers/optimize_for_target_gateset_test.py +11 -9
- cirq/transformers/qubit_management_transformers_test.py +6 -2
- {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251003181338.dist-info}/METADATA +1 -1
- {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251003181338.dist-info}/RECORD +58 -58
- {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251003181338.dist-info}/WHEEL +0 -0
- {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251003181338.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.7.0.dev20251002223432.dist-info → cirq_core-1.7.0.dev20251003181338.dist-info}/top_level.txt +0 -0
cirq/_doc.py
CHANGED
|
@@ -15,12 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import TypeVar
|
|
19
19
|
|
|
20
|
+
T = TypeVar('T')
|
|
20
21
|
RECORDED_CONST_DOCS: dict[int, str] = {}
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def document(value:
|
|
24
|
+
def document(value: T, doc_string: str = '') -> T:
|
|
24
25
|
"""Stores documentation details about the given value.
|
|
25
26
|
|
|
26
27
|
This method is used to associate a docstring with global constants. It is
|
|
@@ -64,7 +65,7 @@ def document(value: Any, doc_string: str = ''):
|
|
|
64
65
|
_DOC_PRIVATE = "_tf_docs_doc_private"
|
|
65
66
|
|
|
66
67
|
|
|
67
|
-
def doc_private(obj):
|
|
68
|
+
def doc_private(obj: T) -> T:
|
|
68
69
|
"""A decorator: Generates docs for private methods/functions.
|
|
69
70
|
|
|
70
71
|
For example:
|
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
cirq/linalg/decompositions.py
CHANGED
|
@@ -107,9 +107,7 @@ def test_qft() -> None:
|
|
|
107
107
|
|
|
108
108
|
arr = np.array([[1, 1, 1, 1], [1, -1j, -1, 1j], [1, -1, 1, -1], [1, 1j, -1, -1j]]) / 2
|
|
109
109
|
np.testing.assert_allclose(
|
|
110
|
-
cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1),
|
|
111
|
-
arr, # type: ignore[arg-type]
|
|
112
|
-
atol=1e-8,
|
|
110
|
+
cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1), arr, atol=1e-8
|
|
113
111
|
)
|
|
114
112
|
|
|
115
113
|
for k in range(4):
|
|
@@ -121,7 +119,7 @@ def test_qft() -> None:
|
|
|
121
119
|
|
|
122
120
|
def test_inverse() -> None:
|
|
123
121
|
a, b, c = cirq.LineQubit.range(3)
|
|
124
|
-
assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c) ** -1
|
|
122
|
+
assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c) ** -1
|
|
125
123
|
assert cirq.qft(a, b, c, inverse=True, without_reverse=True) == cirq.inverse(
|
|
126
124
|
cirq.qft(a, b, c, without_reverse=True)
|
|
127
125
|
)
|
cirq/ops/raw_types.py
CHANGED
|
@@ -528,6 +528,9 @@ class Operation(metaclass=abc.ABCMeta):
|
|
|
528
528
|
def _qid_shape_(self) -> tuple[int, ...]:
|
|
529
529
|
return protocols.qid_shape(self.qubits)
|
|
530
530
|
|
|
531
|
+
def __pow__(self, exponent: Any) -> Operation:
|
|
532
|
+
return NotImplemented # pragma: no cover
|
|
533
|
+
|
|
531
534
|
@abc.abstractmethod
|
|
532
535
|
def with_qubits(self, *new_qubits: cirq.Qid) -> cirq.Operation:
|
|
533
536
|
"""Returns the same operation, but applied to different qubits.
|
|
@@ -240,6 +240,7 @@ def test_apply_unitary_args_tensor_manipulation() -> None:
|
|
|
240
240
|
op_indices, tuple(qid_shape[i] for i in op_indices)
|
|
241
241
|
)
|
|
242
242
|
sub_result = val._apply_unitary_(sub_args)
|
|
243
|
+
assert isinstance(sub_result, np.ndarray)
|
|
243
244
|
result = _incorporate_result_into_target(args, sub_args, sub_result)
|
|
244
245
|
np.testing.assert_allclose(result, expected, atol=1e-8)
|
|
245
246
|
|
|
@@ -258,6 +259,7 @@ def test_apply_unitary_args_tensor_manipulation() -> None:
|
|
|
258
259
|
op_indices, tuple(qid_shape[i] for i in op_indices)
|
|
259
260
|
)
|
|
260
261
|
sub_result = val._apply_unitary_(sub_args)
|
|
262
|
+
assert isinstance(sub_result, np.ndarray)
|
|
261
263
|
result = _incorporate_result_into_target(args, sub_args, sub_result)
|
|
262
264
|
np.testing.assert_allclose(result, expected, atol=1e-8, verbose=True)
|
|
263
265
|
|
cirq/protocols/kraus_protocol.py
CHANGED
|
@@ -18,7 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import warnings
|
|
20
20
|
from types import NotImplementedType
|
|
21
|
-
from typing import Any,
|
|
21
|
+
from typing import Any, Iterable, Protocol, TypeVar
|
|
22
22
|
|
|
23
23
|
import numpy as np
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ from cirq.protocols.unitary_protocol import unitary
|
|
|
31
31
|
|
|
32
32
|
# This is a special indicator value used by the channel method to determine
|
|
33
33
|
# whether or not the caller provided a 'default' argument. It must be of type
|
|
34
|
-
#
|
|
34
|
+
# Iterable[np.ndarray] to ensure the method has the correct type signature in
|
|
35
35
|
# that case. It is checked for using `is`, so it won't have a false positive
|
|
36
36
|
# if the user provides a different (np.array([]),) value.
|
|
37
37
|
RaiseTypeErrorIfNotProvided: tuple[np.ndarray] = (np.array([]),)
|
|
@@ -44,7 +44,7 @@ class SupportsKraus(Protocol):
|
|
|
44
44
|
"""An object that may be describable as a quantum channel."""
|
|
45
45
|
|
|
46
46
|
@doc_private
|
|
47
|
-
def _kraus_(self) ->
|
|
47
|
+
def _kraus_(self) -> Iterable[np.ndarray] | NotImplementedType:
|
|
48
48
|
r"""A list of Kraus matrices describing the quantum channel.
|
|
49
49
|
|
|
50
50
|
These matrices are the terms in the operator sum representation of a
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import Iterable
|
|
19
|
+
from typing import Iterable
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
import pytest
|
|
@@ -89,7 +89,7 @@ def test_explicit_kraus() -> None:
|
|
|
89
89
|
c = (a0, a1)
|
|
90
90
|
|
|
91
91
|
class ReturnsKraus:
|
|
92
|
-
def _kraus_(self) ->
|
|
92
|
+
def _kraus_(self) -> Iterable[np.ndarray]:
|
|
93
93
|
return c
|
|
94
94
|
|
|
95
95
|
assert cirq.kraus(ReturnsKraus()) is c
|
|
@@ -38,7 +38,7 @@ class SupportsUnitary(Protocol):
|
|
|
38
38
|
"""An object that may be describable by a unitary matrix."""
|
|
39
39
|
|
|
40
40
|
@doc_private
|
|
41
|
-
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
41
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType | None:
|
|
42
42
|
"""A unitary matrix describing this value, e.g. the matrix of a gate.
|
|
43
43
|
|
|
44
44
|
This method is used by the global `cirq.unitary` method. If this method
|
|
@@ -21,7 +21,7 @@ import numpy as np
|
|
|
21
21
|
import cirq
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def assert_unitary_is_consistent(val: Any, ignoring_global_phase: bool = False):
|
|
24
|
+
def assert_unitary_is_consistent(val: Any, ignoring_global_phase: bool = False) -> None:
|
|
25
25
|
if not isinstance(val, (cirq.Operation, cirq.Gate)):
|
|
26
26
|
return
|
|
27
27
|
|
|
@@ -95,4 +95,4 @@ def test_failed_decomposition() -> None:
|
|
|
95
95
|
with pytest.raises(ValueError):
|
|
96
96
|
cirq.testing.assert_unitary_is_consistent(FailsOnDecompostion())
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
cirq.testing.assert_unitary_is_consistent(cirq.Circuit())
|
cirq/testing/equals_tester.py
CHANGED
|
@@ -93,7 +93,7 @@ class EqualsTester:
|
|
|
93
93
|
"Common problem: returning NotImplementedError instead of NotImplemented. "
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
-
def add_equality_group(self, *group_items: Any):
|
|
96
|
+
def add_equality_group(self, *group_items: Any) -> None:
|
|
97
97
|
"""Tries to add a disjoint equivalence group to the equality tester.
|
|
98
98
|
|
|
99
99
|
This methods asserts that items within the group must all be equal to
|
|
@@ -114,7 +114,7 @@ class EqualsTester:
|
|
|
114
114
|
# Remember this group, to enable disjoint checks vs later groups.
|
|
115
115
|
self._groups.append(group_items)
|
|
116
116
|
|
|
117
|
-
def make_equality_group(self, *factories: Callable[[], Any]):
|
|
117
|
+
def make_equality_group(self, *factories: Callable[[], Any]) -> None:
|
|
118
118
|
"""Tries to add a disjoint equivalence group to the equality tester.
|
|
119
119
|
|
|
120
120
|
Uses the factory methods to produce two different objects with the same
|
|
@@ -22,7 +22,9 @@ import cirq
|
|
|
22
22
|
from cirq import circuits
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
def assert_equivalent_computational_basis_map(
|
|
25
|
+
def assert_equivalent_computational_basis_map(
|
|
26
|
+
maps: dict[int, int], circuit: circuits.Circuit
|
|
27
|
+
) -> None:
|
|
26
28
|
"""Ensure equivalence of basis state mapping.
|
|
27
29
|
|
|
28
30
|
Args:
|
cirq/testing/json.py
CHANGED
|
@@ -149,7 +149,7 @@ def spec_for(module_name: str) -> ModuleJsonTestSpec:
|
|
|
149
149
|
return getattr(test_module, "TestSpec")
|
|
150
150
|
|
|
151
151
|
|
|
152
|
-
def assert_json_roundtrip_works(obj, text_should_be=None, resolvers=None):
|
|
152
|
+
def assert_json_roundtrip_works(obj, text_should_be=None, resolvers=None) -> None:
|
|
153
153
|
"""Tests that the given object can serialized and de-serialized
|
|
154
154
|
|
|
155
155
|
Args:
|
cirq/testing/op_tree.py
CHANGED
|
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
from cirq import ops
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def assert_equivalent_op_tree(x: ops.OP_TREE, y: ops.OP_TREE):
|
|
20
|
+
def assert_equivalent_op_tree(x: ops.OP_TREE, y: ops.OP_TREE) -> None:
|
|
21
21
|
"""Ensures that the two OP_TREEs are equivalent.
|
|
22
22
|
|
|
23
23
|
Args:
|
cirq/testing/order_tester.py
CHANGED
|
@@ -78,7 +78,7 @@ class OrderTester:
|
|
|
78
78
|
f"That rule is being violated by this value: {item!r}"
|
|
79
79
|
) from ex
|
|
80
80
|
|
|
81
|
-
def add_ascending(self, *items: Any):
|
|
81
|
+
def add_ascending(self, *items: Any) -> None:
|
|
82
82
|
"""Tries to add a sequence of ascending items to the order tester.
|
|
83
83
|
|
|
84
84
|
This methods asserts that items must all be ascending
|
|
@@ -98,7 +98,7 @@ class OrderTester:
|
|
|
98
98
|
for item in items:
|
|
99
99
|
self.add_ascending_equivalence_group(item)
|
|
100
100
|
|
|
101
|
-
def add_ascending_equivalence_group(self, *group_items: Any):
|
|
101
|
+
def add_ascending_equivalence_group(self, *group_items: Any) -> None:
|
|
102
102
|
"""Tries to add an ascending equivalence group to the order tester.
|
|
103
103
|
|
|
104
104
|
Asserts that the group items are equal to each other, but strictly
|
|
@@ -34,11 +34,11 @@ class FakePrinter:
|
|
|
34
34
|
def __init__(self):
|
|
35
35
|
self.text_pretty = ""
|
|
36
36
|
|
|
37
|
-
def text(self, to_print):
|
|
37
|
+
def text(self, to_print) -> None:
|
|
38
38
|
self.text_pretty += to_print
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
def assert_repr_pretty(val: Any, text: str, cycle: bool = False):
|
|
41
|
+
def assert_repr_pretty(val: Any, text: str, cycle: bool = False) -> None:
|
|
42
42
|
"""Assert that the given object has a `_repr_pretty_` method that produces the given text.
|
|
43
43
|
|
|
44
44
|
Args:
|
|
@@ -57,7 +57,7 @@ def assert_repr_pretty(val: Any, text: str, cycle: bool = False):
|
|
|
57
57
|
assert p.text_pretty == text, f"{p.text_pretty} != {text}"
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def assert_repr_pretty_contains(val: Any, substr: str, cycle: bool = False):
|
|
60
|
+
def assert_repr_pretty_contains(val: Any, substr: str, cycle: bool = False) -> None:
|
|
61
61
|
"""Assert that the given object has a `_repr_pretty_` output that contains the given text.
|
|
62
62
|
|
|
63
63
|
Args:
|
cirq/transformers/align_test.py
CHANGED
|
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
import cirq
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def test_align_basic_no_context():
|
|
20
|
+
def test_align_basic_no_context() -> None:
|
|
21
21
|
q1 = cirq.NamedQubit('q1')
|
|
22
22
|
q2 = cirq.NamedQubit('q2')
|
|
23
23
|
c = cirq.Circuit(
|
|
@@ -45,7 +45,7 @@ def test_align_basic_no_context():
|
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def test_align_left_no_compile_context():
|
|
48
|
+
def test_align_left_no_compile_context() -> None:
|
|
49
49
|
q1 = cirq.NamedQubit('q1')
|
|
50
50
|
q2 = cirq.NamedQubit('q2')
|
|
51
51
|
cirq.testing.assert_same_circuits(
|
|
@@ -59,7 +59,7 @@ def test_align_left_no_compile_context():
|
|
|
59
59
|
cirq.measure(*[q1, q2], key='a'),
|
|
60
60
|
]
|
|
61
61
|
),
|
|
62
|
-
context=cirq.TransformerContext(tags_to_ignore=
|
|
62
|
+
context=cirq.TransformerContext(tags_to_ignore=("nocompile",)),
|
|
63
63
|
),
|
|
64
64
|
cirq.Circuit(
|
|
65
65
|
[
|
|
@@ -73,7 +73,7 @@ def test_align_left_no_compile_context():
|
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
def test_align_left_deep():
|
|
76
|
+
def test_align_left_deep() -> None:
|
|
77
77
|
q1, q2 = cirq.LineQubit.range(2)
|
|
78
78
|
c_nested = cirq.FrozenCircuit(
|
|
79
79
|
[
|
|
@@ -104,11 +104,11 @@ def test_align_left_deep():
|
|
|
104
104
|
c_nested_aligned,
|
|
105
105
|
cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"),
|
|
106
106
|
)
|
|
107
|
-
context = cirq.TransformerContext(tags_to_ignore=
|
|
107
|
+
context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True)
|
|
108
108
|
cirq.testing.assert_same_circuits(cirq.align_left(c_orig, context=context), c_expected)
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
def test_align_left_subset_of_operations():
|
|
111
|
+
def test_align_left_subset_of_operations() -> None:
|
|
112
112
|
q1 = cirq.NamedQubit('q1')
|
|
113
113
|
q2 = cirq.NamedQubit('q2')
|
|
114
114
|
tag = "op_to_align"
|
|
@@ -134,7 +134,7 @@ def test_align_left_subset_of_operations():
|
|
|
134
134
|
cirq.toggle_tags(
|
|
135
135
|
cirq.align_left(
|
|
136
136
|
cirq.toggle_tags(c_orig, [tag]),
|
|
137
|
-
context=cirq.TransformerContext(tags_to_ignore=
|
|
137
|
+
context=cirq.TransformerContext(tags_to_ignore=(tag,)),
|
|
138
138
|
),
|
|
139
139
|
[tag],
|
|
140
140
|
),
|
|
@@ -142,7 +142,7 @@ def test_align_left_subset_of_operations():
|
|
|
142
142
|
)
|
|
143
143
|
|
|
144
144
|
|
|
145
|
-
def test_align_right_no_compile_context():
|
|
145
|
+
def test_align_right_no_compile_context() -> None:
|
|
146
146
|
q1 = cirq.NamedQubit('q1')
|
|
147
147
|
q2 = cirq.NamedQubit('q2')
|
|
148
148
|
cirq.testing.assert_same_circuits(
|
|
@@ -156,7 +156,7 @@ def test_align_right_no_compile_context():
|
|
|
156
156
|
cirq.measure(*[q1, q2], key='a'),
|
|
157
157
|
]
|
|
158
158
|
),
|
|
159
|
-
context=cirq.TransformerContext(tags_to_ignore=
|
|
159
|
+
context=cirq.TransformerContext(tags_to_ignore=("nocompile",)),
|
|
160
160
|
),
|
|
161
161
|
cirq.Circuit(
|
|
162
162
|
[
|
|
@@ -170,7 +170,7 @@ def test_align_right_no_compile_context():
|
|
|
170
170
|
)
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
def test_align_right_deep():
|
|
173
|
+
def test_align_right_deep() -> None:
|
|
174
174
|
q1, q2 = cirq.LineQubit.range(2)
|
|
175
175
|
c_nested = cirq.FrozenCircuit(
|
|
176
176
|
cirq.Moment([cirq.X(q1)]),
|
|
@@ -199,11 +199,11 @@ def test_align_right_deep():
|
|
|
199
199
|
c_nested_aligned,
|
|
200
200
|
cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"),
|
|
201
201
|
)
|
|
202
|
-
context = cirq.TransformerContext(tags_to_ignore=
|
|
202
|
+
context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True)
|
|
203
203
|
cirq.testing.assert_same_circuits(cirq.align_right(c_orig, context=context), c_expected)
|
|
204
204
|
|
|
205
205
|
|
|
206
|
-
def test_classical_control():
|
|
206
|
+
def test_classical_control() -> None:
|
|
207
207
|
q0, q1 = cirq.LineQubit.range(2)
|
|
208
208
|
circuit = cirq.Circuit(
|
|
209
209
|
cirq.H(q0), cirq.measure(q0, key='m'), cirq.X(q1).with_classical_controls('m')
|
|
@@ -212,7 +212,7 @@ def test_classical_control():
|
|
|
212
212
|
cirq.testing.assert_same_circuits(cirq.align_right(circuit), circuit)
|
|
213
213
|
|
|
214
214
|
|
|
215
|
-
def test_measurement_and_classical_control_same_moment_preserve_order():
|
|
215
|
+
def test_measurement_and_classical_control_same_moment_preserve_order() -> None:
|
|
216
216
|
q0, q1 = cirq.LineQubit.range(2)
|
|
217
217
|
circuit = cirq.Circuit()
|
|
218
218
|
op_measure = cirq.measure(q0, key='m')
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import functools
|
|
20
|
-
from typing import TYPE_CHECKING
|
|
20
|
+
from typing import Sequence, TYPE_CHECKING
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
|
|
@@ -31,7 +31,7 @@ def _X(
|
|
|
31
31
|
q: int,
|
|
32
32
|
args: sim.CliffordTableauSimulationState,
|
|
33
33
|
operations: list[ops.Operation],
|
|
34
|
-
qubits:
|
|
34
|
+
qubits: Sequence[cirq.Qid],
|
|
35
35
|
):
|
|
36
36
|
protocols.act_on(ops.X, args, qubits=[qubits[q]], allow_decompose=False)
|
|
37
37
|
operations.append(ops.X(qubits[q]))
|
|
@@ -41,7 +41,7 @@ def _Z(
|
|
|
41
41
|
q: int,
|
|
42
42
|
args: sim.CliffordTableauSimulationState,
|
|
43
43
|
operations: list[ops.Operation],
|
|
44
|
-
qubits:
|
|
44
|
+
qubits: Sequence[cirq.Qid],
|
|
45
45
|
):
|
|
46
46
|
protocols.act_on(ops.Z, args, qubits=[qubits[q]], allow_decompose=False)
|
|
47
47
|
operations.append(ops.Z(qubits[q]))
|
|
@@ -51,7 +51,7 @@ def _Sdg(
|
|
|
51
51
|
q: int,
|
|
52
52
|
args: sim.CliffordTableauSimulationState,
|
|
53
53
|
operations: list[ops.Operation],
|
|
54
|
-
qubits:
|
|
54
|
+
qubits: Sequence[cirq.Qid],
|
|
55
55
|
):
|
|
56
56
|
# Apply the tableau with S^\{dagger}
|
|
57
57
|
protocols.act_on(ops.S**-1, args, qubits=[qubits[q]], allow_decompose=False)
|
|
@@ -62,7 +62,7 @@ def _H(
|
|
|
62
62
|
q: int,
|
|
63
63
|
args: sim.CliffordTableauSimulationState,
|
|
64
64
|
operations: list[ops.Operation],
|
|
65
|
-
qubits:
|
|
65
|
+
qubits: Sequence[cirq.Qid],
|
|
66
66
|
):
|
|
67
67
|
protocols.act_on(ops.H, args, qubits=[qubits[q]], allow_decompose=False)
|
|
68
68
|
operations.append(ops.H(qubits[q]))
|
|
@@ -73,7 +73,7 @@ def _CNOT(
|
|
|
73
73
|
q2: int,
|
|
74
74
|
args: sim.CliffordTableauSimulationState,
|
|
75
75
|
operations: list[ops.Operation],
|
|
76
|
-
qubits:
|
|
76
|
+
qubits: Sequence[cirq.Qid],
|
|
77
77
|
):
|
|
78
78
|
protocols.act_on(ops.CNOT, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False)
|
|
79
79
|
operations.append(ops.CNOT(qubits[q1], qubits[q2]))
|
|
@@ -84,14 +84,14 @@ def _SWAP(
|
|
|
84
84
|
q2: int,
|
|
85
85
|
args: sim.CliffordTableauSimulationState,
|
|
86
86
|
operations: list[ops.Operation],
|
|
87
|
-
qubits:
|
|
87
|
+
qubits: Sequence[cirq.Qid],
|
|
88
88
|
):
|
|
89
89
|
protocols.act_on(ops.SWAP, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False)
|
|
90
90
|
operations.append(ops.SWAP(qubits[q1], qubits[q2]))
|
|
91
91
|
|
|
92
92
|
|
|
93
93
|
def decompose_clifford_tableau_to_operations(
|
|
94
|
-
qubits:
|
|
94
|
+
qubits: Sequence[cirq.Qid], clifford_tableau: qis.CliffordTableau
|
|
95
95
|
) -> list[ops.Operation]:
|
|
96
96
|
"""Decompose an n-qubit Clifford Tableau into a list of one/two qubit operations.
|
|
97
97
|
|
|
@@ -21,14 +21,14 @@ import cirq
|
|
|
21
21
|
from cirq.testing import assert_allclose_up_to_global_phase
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def test_misaligned_qubits():
|
|
24
|
+
def test_misaligned_qubits() -> None:
|
|
25
25
|
qubits = cirq.LineQubit.range(1)
|
|
26
26
|
tableau = cirq.CliffordTableau(num_qubits=2)
|
|
27
27
|
with pytest.raises(ValueError):
|
|
28
28
|
cirq.decompose_clifford_tableau_to_operations(qubits, tableau)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def test_clifford_decompose_one_qubit():
|
|
31
|
+
def test_clifford_decompose_one_qubit() -> None:
|
|
32
32
|
"""Two random instance for one qubit decomposition."""
|
|
33
33
|
qubits = cirq.LineQubit.range(1)
|
|
34
34
|
args = cirq.CliffordTableauSimulationState(
|
|
@@ -63,7 +63,7 @@ def test_clifford_decompose_one_qubit():
|
|
|
63
63
|
assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def test_clifford_decompose_two_qubits():
|
|
66
|
+
def test_clifford_decompose_two_qubits() -> None:
|
|
67
67
|
"""Two random instance for two qubits decomposition."""
|
|
68
68
|
qubits = cirq.LineQubit.range(2)
|
|
69
69
|
args = cirq.CliffordTableauSimulationState(
|
|
@@ -98,7 +98,7 @@ def test_clifford_decompose_two_qubits():
|
|
|
98
98
|
assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def test_clifford_decompose_by_unitary():
|
|
101
|
+
def test_clifford_decompose_by_unitary() -> None:
|
|
102
102
|
"""Validate the decomposition of random Clifford Tableau by unitary matrix.
|
|
103
103
|
|
|
104
104
|
Due to the exponential growth in dimension, it cannot validate very large number of qubits.
|
|
@@ -125,7 +125,7 @@ def test_clifford_decompose_by_unitary():
|
|
|
125
125
|
assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
def test_clifford_decompose_by_reconstruction():
|
|
128
|
+
def test_clifford_decompose_by_reconstruction() -> None:
|
|
129
129
|
"""Validate the decomposition of random Clifford Tableau by reconstruction.
|
|
130
130
|
|
|
131
131
|
This approach can validate large number of qubits compared with the unitary one.
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import itertools
|
|
18
|
-
from typing import TYPE_CHECKING
|
|
18
|
+
from typing import Sequence, TYPE_CHECKING
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
|
|
@@ -114,7 +114,7 @@ def _ccnot_congruent(c0: cirq.Qid, c1: cirq.Qid, target: cirq.Qid) -> list[cirq.
|
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
def decompose_multi_controlled_x(
|
|
117
|
-
controls:
|
|
117
|
+
controls: Sequence[cirq.Qid], target: cirq.Qid, free_qubits: Sequence[cirq.Qid]
|
|
118
118
|
) -> list[cirq.Operation]:
|
|
119
119
|
"""Implements action of multi-controlled Pauli X gate.
|
|
120
120
|
|
|
@@ -152,11 +152,11 @@ def decompose_multi_controlled_x(
|
|
|
152
152
|
elif len(free_qubits) >= 1:
|
|
153
153
|
# See [1], Lemma 7.3.
|
|
154
154
|
m1 = n // 2
|
|
155
|
-
free1 = controls[m1:]
|
|
155
|
+
free1 = [*controls[m1:], target, *free_qubits[1:]]
|
|
156
156
|
ctrl1 = controls[:m1]
|
|
157
157
|
part1 = decompose_multi_controlled_x(ctrl1, free_qubits[0], free1)
|
|
158
|
-
free2 = controls[:m1]
|
|
159
|
-
ctrl2 = controls[m1:]
|
|
158
|
+
free2 = [*controls[:m1], *free_qubits[1:]]
|
|
159
|
+
ctrl2 = [*controls[m1:], free_qubits[0]]
|
|
160
160
|
part2 = decompose_multi_controlled_x(ctrl2, target, free2)
|
|
161
161
|
return [*part1, *part2, *part1, *part2]
|
|
162
162
|
else:
|
|
@@ -167,7 +167,7 @@ def decompose_multi_controlled_x(
|
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
def _decompose_su(
|
|
170
|
-
matrix: np.ndarray, controls:
|
|
170
|
+
matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid
|
|
171
171
|
) -> list[cirq.Operation]:
|
|
172
172
|
"""Decomposes controlled special unitary gate into elementary gates.
|
|
173
173
|
|
|
@@ -193,9 +193,9 @@ def _decompose_su(
|
|
|
193
193
|
def _decompose_recursive(
|
|
194
194
|
matrix: np.ndarray,
|
|
195
195
|
power: float,
|
|
196
|
-
controls:
|
|
196
|
+
controls: Sequence[cirq.Qid],
|
|
197
197
|
target: cirq.Qid,
|
|
198
|
-
free_qubits:
|
|
198
|
+
free_qubits: Sequence[cirq.Qid],
|
|
199
199
|
) -> list[cirq.Operation]:
|
|
200
200
|
"""Decomposes controlled unitary gate into elementary gates.
|
|
201
201
|
|
|
@@ -205,20 +205,20 @@ def _decompose_recursive(
|
|
|
205
205
|
if len(controls) == 1:
|
|
206
206
|
return _decompose_single_ctrl(_unitary_power(matrix, power), controls[0], target)
|
|
207
207
|
|
|
208
|
-
cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], free_qubits
|
|
208
|
+
cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], [*free_qubits, target])
|
|
209
209
|
return [
|
|
210
210
|
*_decompose_single_ctrl(_unitary_power(matrix, 0.5 * power), controls[-1], target),
|
|
211
211
|
*cnots,
|
|
212
212
|
*_decompose_single_ctrl(_unitary_power(matrix, -0.5 * power), controls[-1], target),
|
|
213
213
|
*cnots,
|
|
214
214
|
*_decompose_recursive(
|
|
215
|
-
matrix, 0.5 * power, controls[:-1], target, [controls[-1]
|
|
215
|
+
matrix, 0.5 * power, controls[:-1], target, [controls[-1], *free_qubits]
|
|
216
216
|
),
|
|
217
217
|
]
|
|
218
218
|
|
|
219
219
|
|
|
220
220
|
def decompose_multi_controlled_rotation(
|
|
221
|
-
matrix: np.ndarray, controls:
|
|
221
|
+
matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid
|
|
222
222
|
) -> list[cirq.Operation]:
|
|
223
223
|
"""Implements action of multi-controlled unitary gate.
|
|
224
224
|
|
|
@@ -20,7 +20,7 @@ import scipy.stats
|
|
|
20
20
|
import cirq
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def test_decompose_x():
|
|
23
|
+
def test_decompose_x() -> None:
|
|
24
24
|
"""Verifies correctness of multi-controlled X decomposition."""
|
|
25
25
|
for total_qubits_count in range(1, 8):
|
|
26
26
|
qubits = cirq.LineQubit.range(total_qubits_count)
|
|
@@ -83,14 +83,14 @@ def _test_decompose(matrix, controls_count):
|
|
|
83
83
|
cirq.testing.assert_allclose_up_to_global_phase(expected_matrix, result_matrix, atol=1e-8)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def test_decompose_specific_matrices():
|
|
86
|
+
def test_decompose_specific_matrices() -> None:
|
|
87
87
|
for gate in [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.I, cirq.T, cirq.S]:
|
|
88
88
|
for controls_count in range(7):
|
|
89
89
|
_test_decompose(cirq.unitary(gate), controls_count)
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
@cirq.testing.retry_once_with_later_random_values
|
|
93
|
-
def test_decompose_random_unitary():
|
|
93
|
+
def test_decompose_random_unitary() -> None:
|
|
94
94
|
for controls_count in range(5):
|
|
95
95
|
for _ in range(10):
|
|
96
96
|
_test_decompose(_random_unitary(), controls_count)
|
|
@@ -99,7 +99,7 @@ def test_decompose_random_unitary():
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
@cirq.testing.retry_once_with_later_random_values
|
|
102
|
-
def test_decompose_random_special_unitary():
|
|
102
|
+
def test_decompose_random_special_unitary() -> None:
|
|
103
103
|
for controls_count in range(5):
|
|
104
104
|
for _ in range(10):
|
|
105
105
|
_test_decompose(_random_special_unitary(), controls_count)
|
|
@@ -113,7 +113,7 @@ def _decomposition_size(U, controls_count):
|
|
|
113
113
|
return _count_operations(operations)
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
def test_decompose_size_special_unitary():
|
|
116
|
+
def test_decompose_size_special_unitary() -> None:
|
|
117
117
|
np.random.seed(0)
|
|
118
118
|
u = _random_special_unitary()
|
|
119
119
|
assert _decomposition_size(u, 0) == (1, 0, 0)
|
|
@@ -126,7 +126,7 @@ def test_decompose_size_special_unitary():
|
|
|
126
126
|
assert _decomposition_size(u, i) == (64 * i - 312, 48 * i - 234, 16)
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
def test_decompose_size_unitary():
|
|
129
|
+
def test_decompose_size_unitary() -> None:
|
|
130
130
|
np.random.seed(0)
|
|
131
131
|
u = _random_unitary()
|
|
132
132
|
assert _decomposition_size(u, 0) == (1, 0, 0)
|
|
@@ -100,7 +100,7 @@ def decompose_cphase_into_two_fsim(
|
|
|
100
100
|
fsim_gate: cirq.FSimGate,
|
|
101
101
|
qubits: Sequence[cirq.Qid] | None = None,
|
|
102
102
|
atol: float = 1e-8,
|
|
103
|
-
) -> cirq.
|
|
103
|
+
) -> Sequence[cirq.Operation]:
|
|
104
104
|
"""Decomposes CZPowGate into two FSimGates.
|
|
105
105
|
|
|
106
106
|
This function implements the decomposition described in section VII F I
|