cirq-core 1.6.0.dev20250501173104__py3-none-any.whl → 1.6.0.dev20250501192724__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/transformers/analytical_decompositions/two_qubit_to_cz.py +18 -18
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +18 -19
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +8 -10
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +26 -28
- cirq/transformers/drop_empty_moments.py +4 -2
- cirq/transformers/drop_negligible_operations.py +6 -4
- cirq/transformers/dynamical_decoupling.py +6 -4
- cirq/transformers/dynamical_decoupling_test.py +8 -6
- cirq/transformers/eject_phased_paulis.py +14 -12
- cirq/transformers/eject_z.py +8 -6
- cirq/transformers/expand_composite.py +5 -3
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +3 -1
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -1
- cirq/transformers/insertion_sort.py +6 -4
- cirq/transformers/measurement_transformers.py +21 -21
- cirq/transformers/merge_k_qubit_gates.py +11 -9
- cirq/transformers/merge_k_qubit_gates_test.py +5 -3
- cirq/transformers/merge_single_qubit_gates.py +15 -13
- cirq/transformers/optimize_for_target_gateset.py +14 -12
- cirq/transformers/optimize_for_target_gateset_test.py +7 -3
- cirq/transformers/qubit_management_transformers.py +10 -8
- cirq/transformers/randomized_measurements.py +9 -7
- cirq/transformers/routing/initial_mapper.py +5 -3
- cirq/transformers/routing/line_initial_mapper.py +15 -13
- cirq/transformers/routing/mapping_manager.py +9 -9
- cirq/transformers/routing/route_circuit_cqc.py +17 -15
- cirq/transformers/routing/visualize_routed_circuit.py +7 -6
- cirq/transformers/stratify.py +13 -11
- cirq/transformers/synchronize_terminal_measurements.py +9 -9
- cirq/transformers/target_gatesets/compilation_target_gateset.py +19 -17
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +11 -7
- cirq/transformers/target_gatesets/cz_gateset.py +4 -2
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -3
- cirq/transformers/transformer_api.py +17 -15
- cirq/transformers/transformer_primitives.py +22 -20
- cirq/transformers/transformer_primitives_test.py +3 -1
- cirq/value/classical_data.py +26 -26
- cirq/value/condition.py +23 -21
- cirq/value/duration.py +11 -8
- cirq/value/linear_dict.py +22 -20
- cirq/value/periodic_value.py +4 -4
- cirq/value/probability.py +3 -1
- cirq/value/product_state.py +14 -12
- cirq/work/collector.py +7 -5
- cirq/work/observable_measurement.py +24 -22
- cirq/work/observable_measurement_data.py +9 -7
- cirq/work/observable_readout_calibration.py +4 -1
- cirq/work/observable_readout_calibration_test.py +4 -1
- cirq/work/observable_settings.py +4 -2
- cirq/work/pauli_sum_collector.py +8 -6
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/RECORD +57 -57
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/top_level.txt +0 -0
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Utility methods for decomposing two-qubit unitaries into CZ gates."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import cast, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
@@ -31,8 +33,8 @@ if TYPE_CHECKING:
|
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
def _remove_partial_czs_or_fail(
|
|
34
|
-
operations: Iterable[
|
|
35
|
-
) -> List[
|
|
36
|
+
operations: Iterable[cirq.Operation], atol: float
|
|
37
|
+
) -> List[cirq.Operation]:
|
|
36
38
|
result = []
|
|
37
39
|
for op in operations:
|
|
38
40
|
if isinstance(op.gate, ops.CZPowGate):
|
|
@@ -49,8 +51,8 @@ def _remove_partial_czs_or_fail(
|
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
def two_qubit_matrix_to_cz_operations(
|
|
52
|
-
q0:
|
|
53
|
-
q1:
|
|
54
|
+
q0: cirq.Qid,
|
|
55
|
+
q1: cirq.Qid,
|
|
54
56
|
mat: np.ndarray,
|
|
55
57
|
allow_partial_czs: bool,
|
|
56
58
|
atol: float = 1e-8,
|
|
@@ -85,13 +87,13 @@ def two_qubit_matrix_to_cz_operations(
|
|
|
85
87
|
|
|
86
88
|
|
|
87
89
|
def two_qubit_matrix_to_diagonal_and_cz_operations(
|
|
88
|
-
q0:
|
|
89
|
-
q1:
|
|
90
|
+
q0: cirq.Qid,
|
|
91
|
+
q1: cirq.Qid,
|
|
90
92
|
mat: np.ndarray,
|
|
91
93
|
allow_partial_czs: bool = False,
|
|
92
94
|
atol: float = 1e-8,
|
|
93
95
|
clean_operations: bool = True,
|
|
94
|
-
) -> Tuple[np.ndarray, List[
|
|
96
|
+
) -> Tuple[np.ndarray, List[cirq.Operation]]:
|
|
95
97
|
"""Decomposes a 2-qubit unitary to a diagonal and the remaining operations.
|
|
96
98
|
|
|
97
99
|
For a 2-qubit unitary V, return ops, a list of operations and
|
|
@@ -136,7 +138,7 @@ def two_qubit_matrix_to_diagonal_and_cz_operations(
|
|
|
136
138
|
)
|
|
137
139
|
|
|
138
140
|
|
|
139
|
-
def _xx_interaction_via_full_czs(q0:
|
|
141
|
+
def _xx_interaction_via_full_czs(q0: cirq.Qid, q1: cirq.Qid, x: float):
|
|
140
142
|
a = x * -2 / np.pi
|
|
141
143
|
yield ops.H(q1)
|
|
142
144
|
yield ops.CZ(q0, q1)
|
|
@@ -145,7 +147,7 @@ def _xx_interaction_via_full_czs(q0: 'cirq.Qid', q1: 'cirq.Qid', x: float):
|
|
|
145
147
|
yield ops.H(q1)
|
|
146
148
|
|
|
147
149
|
|
|
148
|
-
def _xx_yy_interaction_via_full_czs(q0:
|
|
150
|
+
def _xx_yy_interaction_via_full_czs(q0: cirq.Qid, q1: cirq.Qid, x: float, y: float):
|
|
149
151
|
a = x * -2 / np.pi
|
|
150
152
|
b = y * -2 / np.pi
|
|
151
153
|
yield ops.X(q0) ** 0.5
|
|
@@ -160,9 +162,7 @@ def _xx_yy_interaction_via_full_czs(q0: 'cirq.Qid', q1: 'cirq.Qid', x: float, y:
|
|
|
160
162
|
yield ops.X(q0) ** -0.5
|
|
161
163
|
|
|
162
164
|
|
|
163
|
-
def _xx_yy_zz_interaction_via_full_czs(
|
|
164
|
-
q0: 'cirq.Qid', q1: 'cirq.Qid', x: float, y: float, z: float
|
|
165
|
-
):
|
|
165
|
+
def _xx_yy_zz_interaction_via_full_czs(q0: cirq.Qid, q1: cirq.Qid, x: float, y: float, z: float):
|
|
166
166
|
a = x * -2 / np.pi + 0.5
|
|
167
167
|
b = y * -2 / np.pi + 0.5
|
|
168
168
|
c = z * -2 / np.pi + 0.5
|
|
@@ -192,8 +192,8 @@ def cleanup_operations(operations: Sequence[ops.Operation]):
|
|
|
192
192
|
|
|
193
193
|
|
|
194
194
|
def _kak_decomposition_to_operations(
|
|
195
|
-
q0:
|
|
196
|
-
q1:
|
|
195
|
+
q0: cirq.Qid,
|
|
196
|
+
q1: cirq.Qid,
|
|
197
197
|
kak: linalg.KakDecomposition,
|
|
198
198
|
allow_partial_czs: bool,
|
|
199
199
|
atol: float = 1e-8,
|
|
@@ -232,7 +232,7 @@ def _is_trivial_angle(rad: float, atol: float) -> bool:
|
|
|
232
232
|
|
|
233
233
|
|
|
234
234
|
def _parity_interaction(
|
|
235
|
-
q0:
|
|
235
|
+
q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: Optional[ops.Gate] = None
|
|
236
236
|
):
|
|
237
237
|
"""Yields a ZZ interaction framed by the given operation."""
|
|
238
238
|
if abs(rads) < atol:
|
|
@@ -255,14 +255,14 @@ def _parity_interaction(
|
|
|
255
255
|
yield g.on(q0), g.on(q1)
|
|
256
256
|
|
|
257
257
|
|
|
258
|
-
def _do_single_on(u: np.ndarray, q:
|
|
258
|
+
def _do_single_on(u: np.ndarray, q: cirq.Qid, atol: float = 1e-8):
|
|
259
259
|
for gate in single_qubit_decompositions.single_qubit_matrix_to_gates(u, atol):
|
|
260
260
|
yield gate(q)
|
|
261
261
|
|
|
262
262
|
|
|
263
263
|
def _non_local_part(
|
|
264
|
-
q0:
|
|
265
|
-
q1:
|
|
264
|
+
q0: cirq.Qid,
|
|
265
|
+
q1: cirq.Qid,
|
|
266
266
|
interaction_coefficients: Tuple[float, float, float],
|
|
267
267
|
allow_partial_czs: bool,
|
|
268
268
|
atol: float = 1e-8,
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Utility methods for decomposing two-qubit unitaries into FSim gates."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Iterable, Iterator, List, Optional, Sequence, TYPE_CHECKING, Union
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
@@ -25,11 +27,11 @@ if TYPE_CHECKING:
|
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
def decompose_two_qubit_interaction_into_four_fsim_gates(
|
|
28
|
-
interaction: Union[
|
|
30
|
+
interaction: Union[cirq.SupportsUnitary, np.ndarray],
|
|
29
31
|
*,
|
|
30
|
-
fsim_gate: Union[
|
|
31
|
-
qubits: Optional[Sequence[
|
|
32
|
-
) ->
|
|
32
|
+
fsim_gate: Union[cirq.FSimGate, cirq.ISwapPowGate],
|
|
33
|
+
qubits: Optional[Sequence[cirq.Qid]] = None,
|
|
34
|
+
) -> cirq.Circuit:
|
|
33
35
|
"""Decomposes operations into an FSimGate near theta=pi/2, phi=0.
|
|
34
36
|
|
|
35
37
|
This decomposition is guaranteed to use exactly four of the given FSim
|
|
@@ -110,12 +112,12 @@ def _sticky_0_to_1(v: float, *, atol: float) -> Optional[float]:
|
|
|
110
112
|
|
|
111
113
|
def _decompose_xx_yy_into_two_fsims_ignoring_single_qubit_ops(
|
|
112
114
|
*,
|
|
113
|
-
qubits: Sequence[
|
|
114
|
-
fsim_gate:
|
|
115
|
+
qubits: Sequence[cirq.Qid],
|
|
116
|
+
fsim_gate: cirq.FSimGate,
|
|
115
117
|
canonical_x_kak_coefficient: float,
|
|
116
118
|
canonical_y_kak_coefficient: float,
|
|
117
119
|
atol: float = 1e-8,
|
|
118
|
-
) -> List[
|
|
120
|
+
) -> List[cirq.Operation]:
|
|
119
121
|
x = canonical_x_kak_coefficient
|
|
120
122
|
y = canonical_y_kak_coefficient
|
|
121
123
|
assert 0 <= y <= x <= np.pi / 4
|
|
@@ -174,10 +176,10 @@ _B = _BGate()
|
|
|
174
176
|
|
|
175
177
|
|
|
176
178
|
def _decompose_two_qubit_interaction_into_two_b_gates(
|
|
177
|
-
interaction: Union[
|
|
179
|
+
interaction: Union[cirq.SupportsUnitary, np.ndarray, cirq.KakDecomposition],
|
|
178
180
|
*,
|
|
179
|
-
qubits: Sequence[
|
|
180
|
-
) -> List[
|
|
181
|
+
qubits: Sequence[cirq.Qid],
|
|
182
|
+
) -> List[cirq.Operation]:
|
|
181
183
|
kak = linalg.kak_decomposition(interaction)
|
|
182
184
|
|
|
183
185
|
result = _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
|
|
@@ -192,8 +194,8 @@ def _decompose_two_qubit_interaction_into_two_b_gates(
|
|
|
192
194
|
|
|
193
195
|
|
|
194
196
|
def _decompose_b_gate_into_two_fsims(
|
|
195
|
-
*, fsim_gate:
|
|
196
|
-
) -> List[
|
|
197
|
+
*, fsim_gate: cirq.FSimGate, qubits: Sequence[cirq.Qid]
|
|
198
|
+
) -> List[cirq.Operation]:
|
|
197
199
|
kak = linalg.kak_decomposition(_B)
|
|
198
200
|
|
|
199
201
|
result = _decompose_xx_yy_into_two_fsims_ignoring_single_qubit_ops(
|
|
@@ -211,8 +213,8 @@ def _decompose_b_gate_into_two_fsims(
|
|
|
211
213
|
|
|
212
214
|
|
|
213
215
|
def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
|
|
214
|
-
qubits: Sequence[
|
|
215
|
-
) -> List[
|
|
216
|
+
qubits: Sequence[cirq.Qid], kak_interaction_coefficients: Iterable[float]
|
|
217
|
+
) -> List[cirq.Operation]:
|
|
216
218
|
"""Decompose using a minimal construction of two-qubit operations.
|
|
217
219
|
|
|
218
220
|
References:
|
|
@@ -236,11 +238,8 @@ def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
|
|
|
236
238
|
|
|
237
239
|
|
|
238
240
|
def _fix_single_qubit_gates_around_kak_interaction(
|
|
239
|
-
*,
|
|
240
|
-
|
|
241
|
-
operations: List['cirq.Operation'],
|
|
242
|
-
qubits: Sequence['cirq.Qid'],
|
|
243
|
-
) -> Iterator['cirq.Operation']:
|
|
241
|
+
*, desired: cirq.KakDecomposition, operations: List[cirq.Operation], qubits: Sequence[cirq.Qid]
|
|
242
|
+
) -> Iterator[cirq.Operation]:
|
|
244
243
|
"""Adds single qubit operations to complete a desired interaction.
|
|
245
244
|
|
|
246
245
|
Args:
|
|
@@ -19,6 +19,8 @@ Gate compilation methods implemented here are following the paper below:
|
|
|
19
19
|
arXiv:1603.07678
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
22
24
|
from typing import cast, Iterable, List, Optional, Tuple, TYPE_CHECKING
|
|
23
25
|
|
|
24
26
|
import numpy as np
|
|
@@ -31,11 +33,7 @@ if TYPE_CHECKING:
|
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
def two_qubit_matrix_to_ion_operations(
|
|
34
|
-
q0:
|
|
35
|
-
q1: 'cirq.Qid',
|
|
36
|
-
mat: np.ndarray,
|
|
37
|
-
atol: float = 1e-8,
|
|
38
|
-
clean_operations: bool = True,
|
|
36
|
+
q0: cirq.Qid, q1: cirq.Qid, mat: np.ndarray, atol: float = 1e-8, clean_operations: bool = True
|
|
39
37
|
) -> List[ops.Operation]:
|
|
40
38
|
"""Decomposes a two-qubit operation into MS/single-qubit rotation gates.
|
|
41
39
|
|
|
@@ -56,7 +54,7 @@ def two_qubit_matrix_to_ion_operations(
|
|
|
56
54
|
|
|
57
55
|
|
|
58
56
|
def _kak_decomposition_to_operations(
|
|
59
|
-
q0:
|
|
57
|
+
q0: cirq.Qid, q1: cirq.Qid, kak: linalg.KakDecomposition, atol: float = 1e-8
|
|
60
58
|
) -> List[ops.Operation]:
|
|
61
59
|
"""Assumes that the decomposition is canonical."""
|
|
62
60
|
b0, b1 = kak.single_qubit_operations_before
|
|
@@ -74,13 +72,13 @@ def _kak_decomposition_to_operations(
|
|
|
74
72
|
)
|
|
75
73
|
|
|
76
74
|
|
|
77
|
-
def _do_single_on(u: np.ndarray, q:
|
|
75
|
+
def _do_single_on(u: np.ndarray, q: cirq.Qid, atol: float = 1e-8):
|
|
78
76
|
for gate in single_qubit_decompositions.single_qubit_matrix_to_gates(u, atol):
|
|
79
77
|
yield gate(q)
|
|
80
78
|
|
|
81
79
|
|
|
82
80
|
def _parity_interaction(
|
|
83
|
-
q0:
|
|
81
|
+
q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: Optional[ops.Gate] = None
|
|
84
82
|
):
|
|
85
83
|
"""Yields an XX interaction framed by the given operation."""
|
|
86
84
|
|
|
@@ -98,8 +96,8 @@ def _parity_interaction(
|
|
|
98
96
|
|
|
99
97
|
|
|
100
98
|
def _non_local_part(
|
|
101
|
-
q0:
|
|
102
|
-
q1:
|
|
99
|
+
q0: cirq.Qid,
|
|
100
|
+
q1: cirq.Qid,
|
|
103
101
|
interaction_coefficients: Tuple[float, float, float],
|
|
104
102
|
atol: float = 1e-8,
|
|
105
103
|
):
|
|
@@ -20,6 +20,8 @@ References:
|
|
|
20
20
|
https://arxiv.org/abs/2105.06074
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
23
25
|
from typing import Optional, Sequence, Tuple, TYPE_CHECKING
|
|
24
26
|
|
|
25
27
|
import numpy as np
|
|
@@ -34,7 +36,7 @@ if TYPE_CHECKING:
|
|
|
34
36
|
|
|
35
37
|
|
|
36
38
|
def parameterized_2q_op_to_sqrt_iswap_operations(
|
|
37
|
-
op:
|
|
39
|
+
op: cirq.Operation, *, use_sqrt_iswap_inv: bool = False
|
|
38
40
|
) -> protocols.decompose_protocol.DecomposeResult:
|
|
39
41
|
"""Tries to decompose a parameterized 2q operation into √iSWAP's + parameterized 1q rotations.
|
|
40
42
|
|
|
@@ -68,9 +70,7 @@ def parameterized_2q_op_to_sqrt_iswap_operations(
|
|
|
68
70
|
return NotImplemented
|
|
69
71
|
|
|
70
72
|
|
|
71
|
-
def _sqrt_iswap_inv(
|
|
72
|
-
a: 'cirq.Qid', b: 'cirq.Qid', use_sqrt_iswap_inv: bool = True
|
|
73
|
-
) -> 'cirq.OP_TREE':
|
|
73
|
+
def _sqrt_iswap_inv(a: cirq.Qid, b: cirq.Qid, use_sqrt_iswap_inv: bool = True) -> cirq.OP_TREE:
|
|
74
74
|
"""Optree implementing `cirq.SQRT_ISWAP_INV(a, b)` using √iSWAPs.
|
|
75
75
|
|
|
76
76
|
Args:
|
|
@@ -89,7 +89,7 @@ def _sqrt_iswap_inv(
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
def _cphase_symbols_to_sqrt_iswap(
|
|
92
|
-
a:
|
|
92
|
+
a: cirq.Qid, b: cirq.Qid, turns: cirq.TParamVal, use_sqrt_iswap_inv: bool = True
|
|
93
93
|
):
|
|
94
94
|
"""Implements `cirq.CZ(a, b) ** turns` using two √iSWAPs and single qubit rotations.
|
|
95
95
|
|
|
@@ -136,7 +136,7 @@ def _cphase_symbols_to_sqrt_iswap(
|
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
def _swap_symbols_to_sqrt_iswap(
|
|
139
|
-
a:
|
|
139
|
+
a: cirq.Qid, b: cirq.Qid, turns: cirq.TParamVal, use_sqrt_iswap_inv: bool = True
|
|
140
140
|
):
|
|
141
141
|
"""Implements `cirq.SWAP(a, b) ** turns` using two √iSWAPs and single qubit rotations.
|
|
142
142
|
|
|
@@ -170,7 +170,7 @@ def _swap_symbols_to_sqrt_iswap(
|
|
|
170
170
|
|
|
171
171
|
|
|
172
172
|
def _iswap_symbols_to_sqrt_iswap(
|
|
173
|
-
a:
|
|
173
|
+
a: cirq.Qid, b: cirq.Qid, turns: cirq.TParamVal, use_sqrt_iswap_inv: bool = True
|
|
174
174
|
):
|
|
175
175
|
"""Implements `cirq.ISWAP(a, b) ** turns` using two √iSWAPs and single qubit rotations.
|
|
176
176
|
|
|
@@ -202,10 +202,10 @@ def _iswap_symbols_to_sqrt_iswap(
|
|
|
202
202
|
|
|
203
203
|
|
|
204
204
|
def _fsim_symbols_to_sqrt_iswap(
|
|
205
|
-
a:
|
|
206
|
-
b:
|
|
207
|
-
theta:
|
|
208
|
-
phi:
|
|
205
|
+
a: cirq.Qid,
|
|
206
|
+
b: cirq.Qid,
|
|
207
|
+
theta: cirq.TParamVal,
|
|
208
|
+
phi: cirq.TParamVal,
|
|
209
209
|
use_sqrt_iswap_inv: bool = True,
|
|
210
210
|
):
|
|
211
211
|
"""Implements `cirq.FSimGate(theta, phi)(a, b)` using two √iSWAPs and single qubit rotations.
|
|
@@ -229,8 +229,8 @@ def _fsim_symbols_to_sqrt_iswap(
|
|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
def two_qubit_matrix_to_sqrt_iswap_operations(
|
|
232
|
-
q0:
|
|
233
|
-
q1:
|
|
232
|
+
q0: cirq.Qid,
|
|
233
|
+
q1: cirq.Qid,
|
|
234
234
|
mat: np.ndarray,
|
|
235
235
|
*,
|
|
236
236
|
required_sqrt_iswap_count: Optional[int] = None,
|
|
@@ -238,7 +238,7 @@ def two_qubit_matrix_to_sqrt_iswap_operations(
|
|
|
238
238
|
atol: float = 1e-8,
|
|
239
239
|
check_preconditions: bool = True,
|
|
240
240
|
clean_operations: bool = False,
|
|
241
|
-
) -> Sequence[
|
|
241
|
+
) -> Sequence[cirq.Operation]:
|
|
242
242
|
"""Decomposes a two-qubit operation into ZPow/XPow/YPow/sqrt-iSWAP gates.
|
|
243
243
|
|
|
244
244
|
This method uses the KAK decomposition of the matrix to determine how many
|
|
@@ -300,13 +300,13 @@ def two_qubit_matrix_to_sqrt_iswap_operations(
|
|
|
300
300
|
|
|
301
301
|
|
|
302
302
|
def _kak_decomposition_to_sqrt_iswap_operations(
|
|
303
|
-
q0:
|
|
304
|
-
q1:
|
|
303
|
+
q0: cirq.Qid,
|
|
304
|
+
q1: cirq.Qid,
|
|
305
305
|
kak: linalg.KakDecomposition,
|
|
306
306
|
required_sqrt_iswap_count: Optional[int] = None,
|
|
307
307
|
use_sqrt_iswap_inv: bool = False,
|
|
308
308
|
atol: float = 1e-8,
|
|
309
|
-
) -> Sequence[
|
|
309
|
+
) -> Sequence[cirq.Operation]:
|
|
310
310
|
single_qubit_operations, _ = _single_qubit_matrices_with_sqrt_iswap(
|
|
311
311
|
kak, required_sqrt_iswap_count, atol=atol
|
|
312
312
|
)
|
|
@@ -325,14 +325,14 @@ def _kak_decomposition_to_sqrt_iswap_operations(
|
|
|
325
325
|
|
|
326
326
|
|
|
327
327
|
def _decomp_to_operations(
|
|
328
|
-
q0:
|
|
329
|
-
q1:
|
|
330
|
-
two_qubit_gate:
|
|
328
|
+
q0: cirq.Qid,
|
|
329
|
+
q1: cirq.Qid,
|
|
330
|
+
two_qubit_gate: cirq.Gate,
|
|
331
331
|
single_qubit_operations: Sequence[Tuple[np.ndarray, np.ndarray]],
|
|
332
332
|
u0_before: np.ndarray = np.eye(2),
|
|
333
333
|
u0_after: np.ndarray = np.eye(2),
|
|
334
334
|
atol: float = 1e-8,
|
|
335
|
-
) -> Sequence[
|
|
335
|
+
) -> Sequence[cirq.Operation]:
|
|
336
336
|
"""Converts a sequence of single-qubit unitary matrices on two qubits into a
|
|
337
337
|
list of operations with interleaved two-qubit gates."""
|
|
338
338
|
two_qubit_op = two_qubit_gate(q0, q1)
|
|
@@ -401,9 +401,7 @@ def _decomp_to_operations(
|
|
|
401
401
|
|
|
402
402
|
|
|
403
403
|
def _single_qubit_matrices_with_sqrt_iswap(
|
|
404
|
-
kak:
|
|
405
|
-
required_sqrt_iswap_count: Optional[int] = None,
|
|
406
|
-
atol: float = 1e-8,
|
|
404
|
+
kak: cirq.KakDecomposition, required_sqrt_iswap_count: Optional[int] = None, atol: float = 1e-8
|
|
407
405
|
) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
|
|
408
406
|
"""Computes the sequence of interleaved single-qubit unitary matrices in the
|
|
409
407
|
sqrt-iSWAP decomposition."""
|
|
@@ -476,7 +474,7 @@ def _in_3sqrt_iswap_region(
|
|
|
476
474
|
|
|
477
475
|
|
|
478
476
|
def _decomp_0_matrices(
|
|
479
|
-
kak:
|
|
477
|
+
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
480
478
|
) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
|
|
481
479
|
"""Returns the single-qubit matrices for the 0-SQRT_ISWAP decomposition.
|
|
482
480
|
|
|
@@ -494,7 +492,7 @@ def _decomp_0_matrices(
|
|
|
494
492
|
|
|
495
493
|
|
|
496
494
|
def _decomp_1sqrt_iswap_matrices(
|
|
497
|
-
kak:
|
|
495
|
+
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
498
496
|
) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
|
|
499
497
|
"""Returns the single-qubit matrices for the 1-SQRT_ISWAP decomposition.
|
|
500
498
|
|
|
@@ -507,7 +505,7 @@ def _decomp_1sqrt_iswap_matrices(
|
|
|
507
505
|
|
|
508
506
|
|
|
509
507
|
def _decomp_2sqrt_iswap_matrices(
|
|
510
|
-
kak:
|
|
508
|
+
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
511
509
|
) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
|
|
512
510
|
"""Returns the single-qubit matrices for the 2-SQRT_ISWAP decomposition.
|
|
513
511
|
|
|
@@ -570,7 +568,7 @@ def _decomp_2sqrt_iswap_matrices(
|
|
|
570
568
|
|
|
571
569
|
|
|
572
570
|
def _decomp_3sqrt_iswap_matrices(
|
|
573
|
-
kak:
|
|
571
|
+
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
574
572
|
) -> Tuple[Sequence[Tuple[np.ndarray, np.ndarray]], complex]:
|
|
575
573
|
"""Returns the single-qubit matrices for the 3-SQRT_ISWAP decomposition.
|
|
576
574
|
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer pass that removes empty moments from a circuit."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Optional, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
from cirq.transformers import transformer_api, transformer_primitives
|
|
@@ -24,8 +26,8 @@ if TYPE_CHECKING:
|
|
|
24
26
|
|
|
25
27
|
@transformer_api.transformer
|
|
26
28
|
def drop_empty_moments(
|
|
27
|
-
circuit:
|
|
28
|
-
) ->
|
|
29
|
+
circuit: cirq.AbstractCircuit, *, context: Optional[cirq.TransformerContext] = None
|
|
30
|
+
) -> cirq.Circuit:
|
|
29
31
|
"""Removes empty moments from a circuit.
|
|
30
32
|
|
|
31
33
|
Args:
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer pass that removes operations with tiny effects."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Optional, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
from cirq import protocols
|
|
@@ -25,11 +27,11 @@ if TYPE_CHECKING:
|
|
|
25
27
|
|
|
26
28
|
@transformer_api.transformer
|
|
27
29
|
def drop_negligible_operations(
|
|
28
|
-
circuit:
|
|
30
|
+
circuit: cirq.AbstractCircuit,
|
|
29
31
|
*,
|
|
30
|
-
context: Optional[
|
|
32
|
+
context: Optional[cirq.TransformerContext] = None,
|
|
31
33
|
atol: float = 1e-8,
|
|
32
|
-
) ->
|
|
34
|
+
) -> cirq.Circuit:
|
|
33
35
|
"""Removes operations with tiny effects.
|
|
34
36
|
|
|
35
37
|
An operation `op` is considered to have a tiny effect if
|
|
@@ -47,7 +49,7 @@ def drop_negligible_operations(
|
|
|
47
49
|
if context is None:
|
|
48
50
|
context = transformer_api.TransformerContext()
|
|
49
51
|
|
|
50
|
-
def map_func(op:
|
|
52
|
+
def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
|
|
51
53
|
return (
|
|
52
54
|
op
|
|
53
55
|
if protocols.num_qubits(op) > 10
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer pass that adds dynamical decoupling operations to a circuit."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from functools import reduce
|
|
18
20
|
from itertools import cycle
|
|
19
21
|
from typing import Dict, Optional, Tuple, TYPE_CHECKING, Union
|
|
@@ -204,12 +206,12 @@ def _need_merge_pulled_through(op_at_q: ops.Operation, is_at_last_busy_moment: b
|
|
|
204
206
|
|
|
205
207
|
@transformer_api.transformer
|
|
206
208
|
def add_dynamical_decoupling(
|
|
207
|
-
circuit:
|
|
209
|
+
circuit: cirq.AbstractCircuit,
|
|
208
210
|
*,
|
|
209
|
-
context: Optional[
|
|
211
|
+
context: Optional[cirq.TransformerContext] = None,
|
|
210
212
|
schema: Union[str, Tuple[ops.Gate, ...]] = 'DEFAULT',
|
|
211
213
|
single_qubit_gate_moments_only: bool = True,
|
|
212
|
-
) ->
|
|
214
|
+
) -> cirq.Circuit:
|
|
213
215
|
"""Adds dynamical decoupling gate operations to a given circuit.
|
|
214
216
|
This transformer might add new moments thus change structure of the original circuit.
|
|
215
217
|
|
|
@@ -284,7 +286,7 @@ def add_dynamical_decoupling(
|
|
|
284
286
|
transformed_moments.extend(moments_to_be_appended)
|
|
285
287
|
|
|
286
288
|
# Step 2, calc updated_moment with insertions / merges.
|
|
287
|
-
updated_moment_ops: set[
|
|
289
|
+
updated_moment_ops: set[cirq.Operation] = set()
|
|
288
290
|
for q in orig_circuit.all_qubits():
|
|
289
291
|
op_at_q = moment.operation_at(q)
|
|
290
292
|
remaining_pulled_through_gate = pulled_through.get(q)
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import Sequence, Tuple, Union
|
|
16
18
|
|
|
17
19
|
import numpy as np
|
|
@@ -21,7 +23,7 @@ import cirq
|
|
|
21
23
|
from cirq import add_dynamical_decoupling
|
|
22
24
|
|
|
23
25
|
|
|
24
|
-
def assert_sim_eq(circuit1:
|
|
26
|
+
def assert_sim_eq(circuit1: cirq.AbstractCircuit, circuit2: cirq.AbstractCircuit):
|
|
25
27
|
# Simulate 2 circuits and compare final states.
|
|
26
28
|
sampler = cirq.Simulator(dtype=np.complex128)
|
|
27
29
|
psi0 = sampler.simulate(cirq.drop_terminal_measurements(circuit1)).final_state_vector
|
|
@@ -31,9 +33,9 @@ def assert_sim_eq(circuit1: 'cirq.AbstractCircuit', circuit2: 'cirq.AbstractCirc
|
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
def assert_dd(
|
|
34
|
-
input_circuit:
|
|
35
|
-
expected_circuit: Union[str,
|
|
36
|
-
schema: Union[str, Tuple[
|
|
36
|
+
input_circuit: cirq.AbstractCircuit,
|
|
37
|
+
expected_circuit: Union[str, cirq.AbstractCircuit],
|
|
38
|
+
schema: Union[str, Tuple[cirq.Gate, ...]] = 'DEFAULT',
|
|
37
39
|
single_qubit_gate_moments_only: bool = True,
|
|
38
40
|
):
|
|
39
41
|
transformed_circuit = add_dynamical_decoupling(
|
|
@@ -86,7 +88,7 @@ def test_no_insertion():
|
|
|
86
88
|
('Y_YINV', (cirq.Y, cirq.Y**-1)),
|
|
87
89
|
],
|
|
88
90
|
)
|
|
89
|
-
def test_insert_provided_schema(schema: str, inserted_gates: Sequence[
|
|
91
|
+
def test_insert_provided_schema(schema: str, inserted_gates: Sequence[cirq.Gate]):
|
|
90
92
|
"""Test case diagrams.
|
|
91
93
|
Input:
|
|
92
94
|
a: ───H───@───────────M───
|
|
@@ -252,7 +254,7 @@ def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool):
|
|
|
252
254
|
),
|
|
253
255
|
],
|
|
254
256
|
)
|
|
255
|
-
def test_invalid_dd_schema(schema: Union[str, Tuple[
|
|
257
|
+
def test_invalid_dd_schema(schema: Union[str, Tuple[cirq.Gate, ...]], error_msg_regex):
|
|
256
258
|
a = cirq.NamedQubit('a')
|
|
257
259
|
input_circuit = cirq.Circuit(cirq.H(a))
|
|
258
260
|
with pytest.raises(ValueError, match=error_msg_regex):
|