cirq-core 1.6.0.dev20250501173104__py3-none-any.whl → 1.6.0.dev20250501231232__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/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +211 -107
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +347 -3
- 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.dev20250501231232.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/RECORD +59 -59
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/top_level.txt +0 -0
|
@@ -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):
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer pass that pushes 180° rotations around axes in the XY plane later in the circuit."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import cast, Dict, Iterable, Iterator, Optional, Tuple, TYPE_CHECKING, Union
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
@@ -29,12 +31,12 @@ if TYPE_CHECKING:
|
|
|
29
31
|
|
|
30
32
|
@transformer_api.transformer(add_deep_support=True)
|
|
31
33
|
def eject_phased_paulis(
|
|
32
|
-
circuit:
|
|
34
|
+
circuit: cirq.AbstractCircuit,
|
|
33
35
|
*,
|
|
34
|
-
context: Optional[
|
|
36
|
+
context: Optional[cirq.TransformerContext] = None,
|
|
35
37
|
atol: float = 1e-8,
|
|
36
38
|
eject_parameterized: bool = False,
|
|
37
|
-
) ->
|
|
39
|
+
) -> cirq.Circuit:
|
|
38
40
|
"""Transformer pass to push X, Y, PhasedX & (certain) PhasedXZ gates to the end of the circuit.
|
|
39
41
|
|
|
40
42
|
As the gates get pushed, they may absorb Z gates, cancel against other
|
|
@@ -60,7 +62,7 @@ def eject_phased_paulis(
|
|
|
60
62
|
held_w_phases: Dict[ops.Qid, value.TParamVal] = {}
|
|
61
63
|
tags_to_ignore = set(context.tags_to_ignore) if context else set()
|
|
62
64
|
|
|
63
|
-
def map_func(op:
|
|
65
|
+
def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
|
|
64
66
|
# Dump if `op` marked with a no compile tag.
|
|
65
67
|
if set(op.tags) & tags_to_ignore:
|
|
66
68
|
return [_dump_held(op.qubits, held_w_phases, atol), op]
|
|
@@ -107,7 +109,7 @@ def eject_phased_paulis(
|
|
|
107
109
|
|
|
108
110
|
def _absorb_z_into_w(
|
|
109
111
|
op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal]
|
|
110
|
-
) ->
|
|
112
|
+
) -> cirq.OP_TREE:
|
|
111
113
|
"""Absorbs a Z^t gate into a W(a) flip.
|
|
112
114
|
|
|
113
115
|
[Where W(a) is shorthand for PhasedX(phase_exponent=a).]
|
|
@@ -128,7 +130,7 @@ def _absorb_z_into_w(
|
|
|
128
130
|
|
|
129
131
|
def _dump_held(
|
|
130
132
|
qubits: Iterable[ops.Qid], held_w_phases: Dict[ops.Qid, value.TParamVal], atol: float
|
|
131
|
-
) -> Iterator[
|
|
133
|
+
) -> Iterator[cirq.OP_TREE]:
|
|
132
134
|
# Note: sorting is to avoid non-determinism in the insertion order.
|
|
133
135
|
for q in sorted(qubits):
|
|
134
136
|
p = held_w_phases.get(q)
|
|
@@ -140,7 +142,7 @@ def _dump_held(
|
|
|
140
142
|
|
|
141
143
|
def _dump_into_measurement(
|
|
142
144
|
op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal]
|
|
143
|
-
) ->
|
|
145
|
+
) -> cirq.OP_TREE:
|
|
144
146
|
measurement = cast(ops.MeasurementGate, cast(ops.GateOperation, op).gate)
|
|
145
147
|
new_measurement = measurement.with_bits_flipped(
|
|
146
148
|
*[i for i, q in enumerate(op.qubits) if q in held_w_phases]
|
|
@@ -152,7 +154,7 @@ def _dump_into_measurement(
|
|
|
152
154
|
|
|
153
155
|
def _potential_cross_whole_w(
|
|
154
156
|
op: ops.Operation, atol: float, held_w_phases: Dict[ops.Qid, value.TParamVal]
|
|
155
|
-
) ->
|
|
157
|
+
) -> cirq.OP_TREE:
|
|
156
158
|
"""Grabs or cancels a held W gate against an existing W gate.
|
|
157
159
|
|
|
158
160
|
[Where W(a) is shorthand for PhasedX(phase_exponent=a).]
|
|
@@ -185,7 +187,7 @@ def _potential_cross_whole_w(
|
|
|
185
187
|
|
|
186
188
|
def _potential_cross_partial_w(
|
|
187
189
|
op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal], atol: float
|
|
188
|
-
) ->
|
|
190
|
+
) -> cirq.OP_TREE:
|
|
189
191
|
"""Cross the held W over a partial W gate.
|
|
190
192
|
|
|
191
193
|
[Where W(a) is shorthand for PhasedX(phase_exponent=a).]
|
|
@@ -210,7 +212,7 @@ def _potential_cross_partial_w(
|
|
|
210
212
|
return gate.on(op.qubits[0])
|
|
211
213
|
|
|
212
214
|
|
|
213
|
-
def _single_cross_over_cz(op: ops.Operation, qubit_with_w:
|
|
215
|
+
def _single_cross_over_cz(op: ops.Operation, qubit_with_w: cirq.Qid) -> cirq.OP_TREE:
|
|
214
216
|
"""Crosses exactly one W flip over a partial CZ.
|
|
215
217
|
|
|
216
218
|
[Where W(a) is shorthand for PhasedX(phase_exponent=a).]
|
|
@@ -251,7 +253,7 @@ def _single_cross_over_cz(op: ops.Operation, qubit_with_w: 'cirq.Qid') -> 'cirq.
|
|
|
251
253
|
|
|
252
254
|
def _double_cross_over_cz(
|
|
253
255
|
op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal]
|
|
254
|
-
) ->
|
|
256
|
+
) -> cirq.OP_TREE:
|
|
255
257
|
"""Crosses two W flips over a partial CZ.
|
|
256
258
|
|
|
257
259
|
[Where W(a) is shorthand for PhasedX(phase_exponent=a).]
|
|
@@ -355,7 +357,7 @@ def _try_get_known_z_half_turns(
|
|
|
355
357
|
|
|
356
358
|
def _phased_x_or_pauli_gate(
|
|
357
359
|
exponent: Union[float, sympy.Expr], phase_exponent: Union[float, sympy.Expr], atol: float
|
|
358
|
-
) -> Union[
|
|
360
|
+
) -> Union[cirq.PhasedXPowGate, cirq.XPowGate, cirq.YPowGate]:
|
|
359
361
|
"""Return PhasedXPowGate or X or Y gate if equivalent within atol in z-axis turns."""
|
|
360
362
|
if not isinstance(phase_exponent, sympy.Expr) or phase_exponent.is_constant():
|
|
361
363
|
half_turns = value.canonicalize_half_turns(float(phase_exponent))
|
cirq/transformers/eject_z.py
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer pass that pushes Z gates later and later in the circuit."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from collections import defaultdict
|
|
18
20
|
from typing import Dict, Iterable, Iterator, Optional, Tuple, TYPE_CHECKING
|
|
19
21
|
|
|
@@ -31,7 +33,7 @@ def _is_integer(n):
|
|
|
31
33
|
return np.isclose(n, np.round(n))
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
def _is_swaplike(gate:
|
|
36
|
+
def _is_swaplike(gate: cirq.Gate):
|
|
35
37
|
if isinstance(gate, ops.SwapPowGate):
|
|
36
38
|
return gate.exponent == 1
|
|
37
39
|
|
|
@@ -46,12 +48,12 @@ def _is_swaplike(gate: 'cirq.Gate'):
|
|
|
46
48
|
|
|
47
49
|
@transformer_api.transformer(add_deep_support=True)
|
|
48
50
|
def eject_z(
|
|
49
|
-
circuit:
|
|
51
|
+
circuit: cirq.AbstractCircuit,
|
|
50
52
|
*,
|
|
51
|
-
context: Optional[
|
|
53
|
+
context: Optional[cirq.TransformerContext] = None,
|
|
52
54
|
atol: float = 0.0,
|
|
53
55
|
eject_parameterized: bool = False,
|
|
54
|
-
) ->
|
|
56
|
+
) -> cirq.Circuit:
|
|
55
57
|
"""Pushes Z gates towards the end of the circuit.
|
|
56
58
|
|
|
57
59
|
As the Z gates get pushed they may absorb other Z gates, get absorbed into
|
|
@@ -77,7 +79,7 @@ def eject_z(
|
|
|
77
79
|
lambda: None
|
|
78
80
|
)
|
|
79
81
|
|
|
80
|
-
def dump_tracked_phase(qubits: Iterable[ops.Qid]) -> Iterator[
|
|
82
|
+
def dump_tracked_phase(qubits: Iterable[ops.Qid]) -> Iterator[cirq.OP_TREE]:
|
|
81
83
|
"""Zeroes qubit_phase entries by emitting Z gates."""
|
|
82
84
|
for q in qubits:
|
|
83
85
|
p, key = qubit_phase[q], last_phased_xz_op[q]
|
|
@@ -87,7 +89,7 @@ def eject_z(
|
|
|
87
89
|
elif key:
|
|
88
90
|
phased_xz_replacements[key] = phased_xz_replacements[key].with_z_exponent(p * 2)
|
|
89
91
|
|
|
90
|
-
def map_func(op:
|
|
92
|
+
def map_func(op: cirq.Operation, moment_index: int) -> cirq.OP_TREE:
|
|
91
93
|
last_phased_xz_op.update({q: None for q in op.qubits})
|
|
92
94
|
|
|
93
95
|
if tags_to_ignore & set(op.tags):
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer pass that expands composite operations via `cirq.decompose`."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Callable, Optional, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
from cirq import circuits, ops, protocols
|
|
@@ -25,9 +27,9 @@ if TYPE_CHECKING:
|
|
|
25
27
|
|
|
26
28
|
@transformer_api.transformer
|
|
27
29
|
def expand_composite(
|
|
28
|
-
circuit:
|
|
30
|
+
circuit: cirq.AbstractCircuit,
|
|
29
31
|
*,
|
|
30
|
-
context: Optional[
|
|
32
|
+
context: Optional[cirq.TransformerContext] = None,
|
|
31
33
|
no_decomp: Callable[[ops.Operation], bool] = (lambda _: False),
|
|
32
34
|
):
|
|
33
35
|
"""A transformer that expands composite operations via `cirq.decompose`.
|
|
@@ -48,7 +50,7 @@ def expand_composite(
|
|
|
48
50
|
Copy of the transformed input circuit.
|
|
49
51
|
"""
|
|
50
52
|
|
|
51
|
-
def map_func(op:
|
|
53
|
+
def map_func(op: cirq.Operation, _) -> cirq.OP_TREE:
|
|
52
54
|
if context and context.deep and isinstance(op.untagged, circuits.CircuitOperation):
|
|
53
55
|
return op
|
|
54
56
|
return protocols.decompose(op, keep=no_decomp, on_stuck_raise=None)
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"""A Gauge transformer for CZ**0.5 and CZ**-0.5 gates."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
18
20
|
from numbers import Real
|
|
19
21
|
from typing import Dict, Sequence, Tuple, TYPE_CHECKING
|
|
20
22
|
|
|
@@ -42,7 +44,7 @@ class SqrtCZGauge(Gauge):
|
|
|
42
44
|
def weight(self) -> float:
|
|
43
45
|
return 3.0
|
|
44
46
|
|
|
45
|
-
def sample(self, gate:
|
|
47
|
+
def sample(self, gate: cirq.Gate, prng: np.random.Generator) -> ConstantGauge:
|
|
46
48
|
if prng.choice([True, False]):
|
|
47
49
|
return ConstantGauge(two_qubit_gate=gate)
|
|
48
50
|
swap_qubits = prng.choice([True, False])
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
"""Attempt to tabulate single qubit gates required to generate a target 2Q gate
|
|
16
16
|
with a product A k A."""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
17
20
|
from dataclasses import dataclass
|
|
18
21
|
from functools import reduce
|
|
19
22
|
from typing import List, NamedTuple, Sequence, Tuple
|
|
@@ -316,7 +319,7 @@ def two_qubit_gate_product_tabulation(
|
|
|
316
319
|
*,
|
|
317
320
|
sample_scaling: int = 50,
|
|
318
321
|
allow_missed_points: bool = True,
|
|
319
|
-
random_state:
|
|
322
|
+
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
320
323
|
) -> TwoQubitGateTabulation:
|
|
321
324
|
r"""Generate a TwoQubitGateTabulation for a base two qubit unitary.
|
|
322
325
|
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformer that sorts commuting operations in increasing order of their `.qubits` tuple."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Dict, List, Optional, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
from cirq import circuits, protocols
|
|
@@ -25,8 +27,8 @@ if TYPE_CHECKING:
|
|
|
25
27
|
|
|
26
28
|
@transformer_api.transformer(add_deep_support=True)
|
|
27
29
|
def insertion_sort_transformer(
|
|
28
|
-
circuit:
|
|
29
|
-
) ->
|
|
30
|
+
circuit: cirq.AbstractCircuit, *, context: Optional[cirq.TransformerContext] = None
|
|
31
|
+
) -> cirq.Circuit:
|
|
30
32
|
"""Sorts the operations using their sorted `.qubits` property as comparison key.
|
|
31
33
|
|
|
32
34
|
Operations are swapped only if they commute.
|
|
@@ -35,8 +37,8 @@ def insertion_sort_transformer(
|
|
|
35
37
|
circuit: input circuit.
|
|
36
38
|
context: optional TransformerContext (not used),
|
|
37
39
|
"""
|
|
38
|
-
final_operations: List[
|
|
39
|
-
qubit_index: Dict[
|
|
40
|
+
final_operations: List[cirq.Operation] = []
|
|
41
|
+
qubit_index: Dict[cirq.Qid, int] = {
|
|
40
42
|
q: idx for idx, q in enumerate(sorted(circuit.all_qubits()))
|
|
41
43
|
}
|
|
42
44
|
cached_qubit_indices: Dict[int, List[int]] = {}
|