cirq-core 1.6.0.dev20250520054601__py3-none-any.whl → 1.6.0.dev20250520181654__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/_compat.py +15 -17
- cirq/_compat_test.py +6 -9
- cirq/_doc.py +2 -2
- cirq/_import.py +6 -6
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/_block_diagram_drawer.py +9 -10
- cirq/circuits/_box_drawing_character_data.py +6 -8
- cirq/circuits/_bucket_priority_queue.py +7 -7
- cirq/circuits/circuit.py +118 -125
- cirq/circuits/circuit_operation.py +38 -52
- cirq/circuits/circuit_test.py +4 -4
- cirq/circuits/frozen_circuit.py +13 -23
- cirq/circuits/moment.py +23 -29
- cirq/circuits/optimization_pass.py +4 -4
- cirq/circuits/optimization_pass_test.py +4 -6
- cirq/circuits/qasm_output.py +11 -11
- cirq/circuits/text_diagram_drawer.py +21 -36
- cirq/contrib/acquaintance/bipartite.py +5 -8
- cirq/contrib/acquaintance/executor.py +5 -5
- cirq/contrib/acquaintance/executor_test.py +3 -3
- cirq/contrib/acquaintance/gates.py +16 -26
- cirq/contrib/acquaintance/gates_test.py +3 -3
- cirq/contrib/acquaintance/mutation_utils.py +4 -4
- cirq/contrib/acquaintance/optimizers.py +4 -4
- cirq/contrib/acquaintance/permutation.py +15 -27
- cirq/contrib/acquaintance/shift.py +3 -3
- cirq/contrib/acquaintance/shift_swap_network.py +4 -4
- cirq/contrib/acquaintance/strategies/cubic.py +2 -2
- cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
- cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
- cirq/contrib/circuitdag/circuit_dag.py +2 -2
- cirq/contrib/custom_simulators/custom_state_simulator.py +3 -3
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +4 -4
- cirq/contrib/graph_device/graph_device.py +5 -5
- cirq/contrib/graph_device/hypergraph.py +12 -12
- cirq/contrib/graph_device/uniform_graph_device.py +4 -4
- cirq/contrib/paulistring/clifford_optimize.py +2 -2
- cirq/contrib/paulistring/clifford_target_gateset.py +7 -7
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +31 -31
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +23 -23
- cirq/contrib/paulistring/recombine.py +3 -3
- cirq/contrib/paulistring/separate.py +2 -2
- cirq/contrib/qasm_import/_parser.py +20 -32
- cirq/contrib/qcircuit/qcircuit_diagram_info.py +3 -5
- cirq/contrib/quantum_volume/quantum_volume.py +24 -24
- cirq/contrib/quimb/density_matrix.py +12 -14
- cirq/contrib/quimb/mps_simulator.py +20 -20
- cirq/contrib/quimb/state_vector.py +6 -10
- cirq/contrib/quirk/export_to_quirk.py +3 -3
- cirq/contrib/quirk/quirk_gate.py +15 -15
- cirq/contrib/routing/device.py +3 -3
- cirq/contrib/routing/greedy.py +10 -21
- cirq/contrib/routing/initialization.py +2 -2
- cirq/contrib/routing/swap_network.py +3 -3
- cirq/contrib/routing/utils.py +2 -2
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +8 -8
- cirq/contrib/svg/svg.py +3 -3
- cirq/devices/grid_device_metadata.py +10 -10
- cirq/devices/grid_qubit.py +20 -20
- cirq/devices/insertion_noise_model.py +5 -5
- cirq/devices/line_qubit.py +13 -13
- cirq/devices/named_topologies.py +18 -29
- cirq/devices/noise_model.py +3 -3
- cirq/devices/noise_properties.py +2 -2
- cirq/devices/noise_properties_test.py +1 -3
- cirq/devices/noise_utils.py +7 -7
- cirq/devices/superconducting_qubits_noise_properties.py +21 -21
- cirq/devices/superconducting_qubits_noise_properties_test.py +5 -7
- cirq/devices/thermal_noise_model.py +14 -14
- cirq/devices/unconstrained_device.py +2 -2
- cirq/experiments/benchmarking/parallel_xeb.py +29 -31
- cirq/experiments/n_qubit_tomography.py +5 -7
- cirq/experiments/qubit_characterizations.py +29 -40
- cirq/experiments/qubit_characterizations_test.py +1 -1
- cirq/experiments/random_quantum_circuit_generation.py +19 -33
- cirq/experiments/random_quantum_circuit_generation_test.py +6 -6
- cirq/experiments/readout_confusion_matrix.py +14 -14
- cirq/experiments/single_qubit_readout_calibration.py +12 -12
- cirq/experiments/t2_decay_experiment.py +7 -7
- cirq/experiments/two_qubit_xeb.py +32 -32
- cirq/experiments/two_qubit_xeb_test.py +5 -5
- cirq/experiments/xeb_fitting.py +25 -25
- cirq/experiments/xeb_sampling.py +22 -33
- cirq/experiments/xeb_simulation.py +5 -5
- cirq/experiments/xeb_simulation_test.py +3 -3
- cirq/experiments/z_phase_calibration.py +19 -19
- cirq/interop/quirk/cells/arithmetic_cells.py +23 -36
- cirq/interop/quirk/cells/cell.py +9 -21
- cirq/interop/quirk/cells/composite_cell.py +7 -22
- cirq/interop/quirk/cells/control_cells.py +8 -8
- cirq/interop/quirk/cells/input_cells.py +4 -4
- cirq/interop/quirk/cells/input_rotation_cells.py +5 -5
- cirq/interop/quirk/cells/parse.py +20 -23
- cirq/interop/quirk/cells/qubit_permutation_cells.py +3 -3
- cirq/interop/quirk/cells/swap_cell.py +3 -3
- cirq/interop/quirk/cells/testing.py +5 -7
- cirq/interop/quirk/url_to_circuit.py +17 -33
- cirq/json_resolver_cache.py +6 -6
- cirq/linalg/decompositions.py +20 -31
- cirq/linalg/diagonalize.py +4 -4
- cirq/linalg/diagonalize_test.py +3 -4
- cirq/linalg/operator_spaces.py +5 -5
- cirq/linalg/predicates.py +7 -7
- cirq/linalg/transformations.py +20 -20
- cirq/ops/arithmetic_operation.py +13 -15
- cirq/ops/boolean_hamiltonian.py +17 -17
- cirq/ops/classically_controlled_operation.py +13 -25
- cirq/ops/clifford_gate.py +31 -35
- cirq/ops/clifford_gate_test.py +2 -3
- cirq/ops/common_channels.py +30 -32
- cirq/ops/common_gates.py +64 -74
- cirq/ops/control_values.py +12 -12
- cirq/ops/controlled_gate.py +15 -30
- cirq/ops/controlled_gate_test.py +5 -5
- cirq/ops/controlled_operation.py +12 -25
- cirq/ops/controlled_operation_test.py +5 -5
- cirq/ops/dense_pauli_string.py +23 -34
- cirq/ops/dense_pauli_string_test.py +1 -2
- cirq/ops/diagonal_gate.py +9 -20
- cirq/ops/diagonal_gate_test.py +1 -3
- cirq/ops/eigen_gate.py +11 -23
- cirq/ops/eigen_gate_test.py +6 -8
- cirq/ops/fourier_transform.py +5 -5
- cirq/ops/fsim_gate.py +14 -14
- cirq/ops/gate_operation.py +23 -44
- cirq/ops/gateset.py +23 -37
- cirq/ops/gateset_test.py +2 -2
- cirq/ops/global_phase_op.py +8 -10
- cirq/ops/greedy_qubit_manager.py +6 -6
- cirq/ops/identity.py +9 -9
- cirq/ops/kraus_channel.py +7 -7
- cirq/ops/linear_combinations.py +29 -48
- cirq/ops/matrix_gates.py +8 -8
- cirq/ops/measure_util.py +13 -14
- cirq/ops/measurement_gate.py +18 -29
- cirq/ops/mixed_unitary_channel.py +8 -8
- cirq/ops/named_qubit.py +10 -10
- cirq/ops/op_tree.py +7 -7
- cirq/ops/parallel_gate.py +5 -5
- cirq/ops/parity_gates.py +14 -14
- cirq/ops/pauli_gates.py +8 -10
- cirq/ops/pauli_interaction_gate.py +6 -6
- cirq/ops/pauli_measurement_gate.py +11 -23
- cirq/ops/pauli_string.py +35 -52
- cirq/ops/pauli_string_phasor.py +4 -14
- cirq/ops/pauli_string_raw_types.py +3 -3
- cirq/ops/pauli_sum_exponential.py +2 -2
- cirq/ops/permutation_gate.py +4 -4
- cirq/ops/phased_iswap_gate.py +9 -9
- cirq/ops/phased_x_gate.py +10 -10
- cirq/ops/phased_x_z_gate.py +11 -11
- cirq/ops/projector.py +6 -6
- cirq/ops/qubit_manager.py +6 -6
- cirq/ops/qubit_order.py +3 -3
- cirq/ops/random_gate_channel.py +4 -4
- cirq/ops/raw_types.py +48 -70
- cirq/ops/state_preparation_channel.py +3 -3
- cirq/ops/swap_gates.py +9 -9
- cirq/ops/tags.py +2 -4
- cirq/ops/three_qubit_gates.py +20 -38
- cirq/ops/two_qubit_diagonal_gate.py +5 -5
- cirq/ops/uniform_superposition_gate.py +2 -2
- cirq/ops/wait_gate.py +5 -5
- cirq/protocols/act_on_protocol_test.py +3 -3
- cirq/protocols/apply_channel_protocol.py +8 -14
- cirq/protocols/apply_mixture_protocol.py +14 -16
- cirq/protocols/apply_mixture_protocol_test.py +5 -6
- cirq/protocols/apply_unitary_protocol.py +17 -19
- cirq/protocols/circuit_diagram_info_protocol.py +19 -30
- cirq/protocols/decompose_protocol.py +30 -34
- cirq/protocols/inverse_protocol.py +7 -7
- cirq/protocols/json_serialization.py +32 -51
- cirq/protocols/json_serialization_test.py +9 -10
- cirq/protocols/kraus_protocol.py +4 -4
- cirq/protocols/kraus_protocol_test.py +3 -3
- cirq/protocols/measurement_key_protocol.py +11 -13
- cirq/protocols/mixture_protocol.py +4 -4
- cirq/protocols/qasm.py +11 -13
- cirq/protocols/qid_shape_protocol.py +6 -8
- cirq/qis/clifford_tableau.py +12 -12
- cirq/qis/measures.py +7 -7
- cirq/qis/quantum_state_representation.py +3 -3
- cirq/qis/states.py +51 -51
- cirq/sim/classical_simulator.py +10 -10
- cirq/sim/clifford/clifford_simulator.py +6 -6
- cirq/sim/clifford/clifford_tableau_simulation_state_test.py +1 -3
- cirq/sim/clifford/stabilizer_sampler.py +4 -4
- cirq/sim/clifford/stabilizer_state_ch_form.py +3 -3
- cirq/sim/density_matrix_simulation_state.py +15 -15
- cirq/sim/density_matrix_simulator.py +11 -11
- cirq/sim/density_matrix_utils.py +9 -9
- cirq/sim/mux.py +9 -9
- cirq/sim/simulation_product_state.py +9 -9
- cirq/sim/simulation_product_state_test.py +2 -2
- cirq/sim/simulation_state.py +14 -27
- cirq/sim/simulation_state_base.py +8 -24
- cirq/sim/simulation_utils.py +3 -4
- cirq/sim/simulator.py +28 -43
- cirq/sim/simulator_base.py +12 -25
- cirq/sim/simulator_base_test.py +6 -6
- cirq/sim/simulator_test.py +7 -7
- cirq/sim/sparse_simulator.py +8 -8
- cirq/sim/state_vector.py +8 -8
- cirq/sim/state_vector_simulation_state.py +17 -17
- cirq/sim/state_vector_simulator.py +4 -4
- cirq/study/flatten_expressions.py +12 -14
- cirq/study/resolver.py +9 -11
- cirq/study/result.py +11 -24
- cirq/study/sweepable.py +5 -5
- cirq/study/sweeps.py +27 -40
- cirq/testing/circuit_compare.py +5 -5
- cirq/testing/consistent_controlled_gate_op_test.py +7 -11
- cirq/testing/consistent_protocols.py +10 -10
- cirq/testing/consistent_protocols_test.py +7 -7
- cirq/testing/consistent_qasm.py +4 -4
- cirq/testing/consistent_qasm_test.py +2 -3
- cirq/testing/devices.py +4 -5
- cirq/testing/equals_tester.py +2 -2
- cirq/testing/equivalent_basis_map.py +4 -4
- cirq/testing/equivalent_repr_eval.py +3 -3
- cirq/testing/json.py +14 -14
- cirq/testing/logs.py +3 -3
- cirq/testing/no_identifier_qubit.py +2 -3
- cirq/testing/random_circuit.py +7 -7
- cirq/testing/random_circuit_test.py +3 -3
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +16 -16
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +13 -13
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +5 -5
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +3 -3
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +3 -3
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +4 -4
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +6 -7
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +2 -2
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +7 -7
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +4 -4
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +7 -7
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +11 -11
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +5 -5
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +14 -14
- cirq/transformers/dynamical_decoupling.py +13 -13
- cirq/transformers/dynamical_decoupling_test.py +4 -4
- cirq/transformers/eject_phased_paulis.py +16 -16
- cirq/transformers/eject_z.py +5 -7
- cirq/transformers/gauge_compiling/gauge_compiling.py +38 -38
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +2 -2
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +8 -8
- cirq/transformers/insertion_sort.py +5 -5
- cirq/transformers/measurement_transformers.py +14 -14
- cirq/transformers/merge_k_qubit_gates_test.py +1 -3
- cirq/transformers/merge_single_qubit_gates_test.py +1 -3
- cirq/transformers/qubit_management_transformers.py +5 -5
- cirq/transformers/routing/initial_mapper.py +4 -4
- cirq/transformers/routing/line_initial_mapper.py +9 -9
- cirq/transformers/routing/mapping_manager.py +7 -7
- cirq/transformers/routing/route_circuit_cqc.py +27 -27
- cirq/transformers/routing/visualize_routed_circuit.py +4 -4
- cirq/transformers/stratify.py +8 -8
- cirq/transformers/synchronize_terminal_measurements.py +6 -6
- cirq/transformers/target_gatesets/compilation_target_gateset.py +8 -8
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -2
- cirq/transformers/target_gatesets/cz_gateset.py +4 -4
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -5
- cirq/transformers/transformer_api.py +11 -26
- cirq/transformers/transformer_primitives.py +24 -36
- cirq/transformers/transformer_primitives_test.py +3 -3
- cirq/value/classical_data.py +18 -18
- cirq/value/condition.py +8 -8
- cirq/value/digits.py +7 -7
- cirq/value/duration.py +12 -12
- cirq/value/linear_dict.py +8 -12
- cirq/value/measurement_key.py +8 -8
- cirq/value/product_state.py +9 -9
- cirq/value/value_equality_attr.py +4 -4
- cirq/vis/heatmap.py +23 -35
- cirq/work/collector.py +9 -17
- cirq/work/observable_grouping.py +4 -7
- cirq/work/observable_measurement.py +29 -41
- cirq/work/observable_measurement_data.py +14 -14
- cirq/work/observable_measurement_test.py +2 -2
- cirq/work/observable_settings.py +9 -10
- cirq/work/pauli_sum_collector.py +5 -5
- cirq/work/sampler.py +17 -17
- cirq/work/zeros_sampler.py +3 -3
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/RECORD +289 -289
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/WHEEL +1 -1
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/top_level.txt +0 -0
|
@@ -17,21 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
import dataclasses
|
|
19
19
|
import itertools
|
|
20
|
-
from typing import
|
|
21
|
-
Any,
|
|
22
|
-
Callable,
|
|
23
|
-
cast,
|
|
24
|
-
Container,
|
|
25
|
-
Dict,
|
|
26
|
-
Iterable,
|
|
27
|
-
Iterator,
|
|
28
|
-
List,
|
|
29
|
-
Optional,
|
|
30
|
-
Sequence,
|
|
31
|
-
Tuple,
|
|
32
|
-
TYPE_CHECKING,
|
|
33
|
-
Union,
|
|
34
|
-
)
|
|
20
|
+
from typing import Any, Callable, cast, Container, Iterable, Iterator, Sequence, TYPE_CHECKING
|
|
35
21
|
|
|
36
22
|
import numpy as np
|
|
37
23
|
|
|
@@ -43,8 +29,8 @@ if TYPE_CHECKING:
|
|
|
43
29
|
|
|
44
30
|
import cirq
|
|
45
31
|
|
|
46
|
-
QidPairT =
|
|
47
|
-
GridQubitPairT =
|
|
32
|
+
QidPairT = tuple['cirq.Qid', 'cirq.Qid']
|
|
33
|
+
GridQubitPairT = tuple['cirq.GridQubit', 'cirq.GridQubit']
|
|
48
34
|
|
|
49
35
|
|
|
50
36
|
@dataclasses.dataclass(frozen=True)
|
|
@@ -117,7 +103,7 @@ class GridInteractionLayer(Container[GridQubitPairT]):
|
|
|
117
103
|
pos = a.row % 2, (a.col - self.col_offset) % 2
|
|
118
104
|
return pos == (0, 0) or pos == (1, self.stagger)
|
|
119
105
|
|
|
120
|
-
def _json_dict_(self) ->
|
|
106
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
121
107
|
return protocols.obj_to_dict_helper(self, ['col_offset', 'vertical', 'stagger'])
|
|
122
108
|
|
|
123
109
|
def __repr__(self) -> str:
|
|
@@ -253,7 +239,7 @@ def generate_library_of_2q_circuits(
|
|
|
253
239
|
q1: cirq.Qid = devices.LineQubit(1),
|
|
254
240
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
255
241
|
tags: Sequence[Any] = (),
|
|
256
|
-
) ->
|
|
242
|
+
) -> list[cirq.Circuit]:
|
|
257
243
|
"""Generate a library of two-qubit Circuits.
|
|
258
244
|
|
|
259
245
|
For single-qubit gates, this uses PhasedXZGates where the axis-in-XY-plane is one
|
|
@@ -309,18 +295,18 @@ class CircuitLibraryCombination:
|
|
|
309
295
|
`get_random_combinations_for_pairs`.
|
|
310
296
|
"""
|
|
311
297
|
|
|
312
|
-
layer:
|
|
298
|
+
layer: Any | None
|
|
313
299
|
combinations: np.ndarray
|
|
314
|
-
pairs:
|
|
300
|
+
pairs: list[QidPairT]
|
|
315
301
|
|
|
316
302
|
|
|
317
303
|
def _get_random_combinations(
|
|
318
304
|
n_library_circuits: int,
|
|
319
305
|
n_combinations: int,
|
|
320
306
|
*,
|
|
321
|
-
pair_gen: Iterator[
|
|
307
|
+
pair_gen: Iterator[tuple[list[QidPairT], Any]],
|
|
322
308
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
323
|
-
) ->
|
|
309
|
+
) -> list[CircuitLibraryCombination]:
|
|
324
310
|
"""For qubit pairs, prepare a set of combinations to efficiently sample
|
|
325
311
|
parallel two-qubit XEB circuits.
|
|
326
312
|
|
|
@@ -370,7 +356,7 @@ def get_random_combinations_for_device(
|
|
|
370
356
|
*,
|
|
371
357
|
pattern: Sequence[GridInteractionLayer] = HALF_GRID_STAGGERED_PATTERN,
|
|
372
358
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
373
|
-
) ->
|
|
359
|
+
) -> list[CircuitLibraryCombination]:
|
|
374
360
|
"""For a given device, prepare a set of combinations to efficiently sample
|
|
375
361
|
parallel two-qubit XEB circuits.
|
|
376
362
|
|
|
@@ -422,9 +408,9 @@ def get_random_combinations_for_device(
|
|
|
422
408
|
def get_random_combinations_for_pairs(
|
|
423
409
|
n_library_circuits: int,
|
|
424
410
|
n_combinations: int,
|
|
425
|
-
all_pairs:
|
|
411
|
+
all_pairs: list[list[QidPairT]],
|
|
426
412
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
427
|
-
) ->
|
|
413
|
+
) -> list[CircuitLibraryCombination]:
|
|
428
414
|
"""For an explicit nested list of pairs, prepare a set of combinations to efficiently sample
|
|
429
415
|
parallel two-qubit XEB circuits.
|
|
430
416
|
|
|
@@ -463,12 +449,12 @@ def get_random_combinations_for_pairs(
|
|
|
463
449
|
)
|
|
464
450
|
|
|
465
451
|
|
|
466
|
-
def _pairs_from_moment(moment: cirq.Moment) ->
|
|
452
|
+
def _pairs_from_moment(moment: cirq.Moment) -> list[QidPairT]:
|
|
467
453
|
"""Helper function in `get_random_combinations_for_layer_circuit` pair generator.
|
|
468
454
|
|
|
469
455
|
The moment should contain only two qubit operations, which define a list of qubit pairs.
|
|
470
456
|
"""
|
|
471
|
-
pairs:
|
|
457
|
+
pairs: list[QidPairT] = []
|
|
472
458
|
for op in moment.operations:
|
|
473
459
|
if len(op.qubits) != 2:
|
|
474
460
|
raise ValueError("Layer circuit contains non-2-qubit operations.")
|
|
@@ -482,7 +468,7 @@ def get_random_combinations_for_layer_circuit(
|
|
|
482
468
|
n_combinations: int,
|
|
483
469
|
layer_circuit: cirq.Circuit,
|
|
484
470
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
485
|
-
) ->
|
|
471
|
+
) -> list[CircuitLibraryCombination]:
|
|
486
472
|
"""For a layer circuit, prepare a set of combinations to efficiently sample
|
|
487
473
|
parallel two-qubit XEB circuits.
|
|
488
474
|
|
|
@@ -622,7 +608,7 @@ def random_rotations_between_grid_interaction_layers_circuit(
|
|
|
622
608
|
return circuit
|
|
623
609
|
|
|
624
610
|
|
|
625
|
-
def _coupled_qubit_pairs(qubits:
|
|
611
|
+
def _coupled_qubit_pairs(qubits: list[cirq.GridQubit]) -> list[GridQubitPairT]:
|
|
626
612
|
pairs = []
|
|
627
613
|
qubit_set = set(qubits)
|
|
628
614
|
for qubit in qubits:
|
|
@@ -661,14 +647,14 @@ class _RandomSingleQubitLayerFactory:
|
|
|
661
647
|
|
|
662
648
|
|
|
663
649
|
class _FixedSingleQubitLayerFactory:
|
|
664
|
-
def __init__(self, fixed_single_qubit_layer:
|
|
650
|
+
def __init__(self, fixed_single_qubit_layer: dict[cirq.Qid, cirq.Gate]) -> None:
|
|
665
651
|
self.fixed_single_qubit_layer = fixed_single_qubit_layer
|
|
666
652
|
|
|
667
653
|
def new_layer(self, previous_single_qubit_layer: cirq.Moment) -> cirq.Moment:
|
|
668
654
|
return circuits.Moment(v.on(q) for q, v in self.fixed_single_qubit_layer.items())
|
|
669
655
|
|
|
670
656
|
|
|
671
|
-
_SingleQubitLayerFactory =
|
|
657
|
+
_SingleQubitLayerFactory = _FixedSingleQubitLayerFactory | _RandomSingleQubitLayerFactory
|
|
672
658
|
|
|
673
659
|
|
|
674
660
|
def _single_qubit_gates_arg_to_factory(
|
|
@@ -687,7 +673,7 @@ def _single_qubit_gates_arg_to_factory(
|
|
|
687
673
|
|
|
688
674
|
|
|
689
675
|
def _two_qubit_layer(
|
|
690
|
-
coupled_qubit_pairs:
|
|
676
|
+
coupled_qubit_pairs: list[GridQubitPairT],
|
|
691
677
|
two_qubit_op_factory: Callable[
|
|
692
678
|
[cirq.GridQubit, cirq.GridQubit, np.random.RandomState], cirq.OP_TREE
|
|
693
679
|
],
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import itertools
|
|
18
|
-
from typing import Callable, cast,
|
|
18
|
+
from typing import Callable, cast, Iterable, Sequence
|
|
19
19
|
|
|
20
20
|
import networkx as nx
|
|
21
21
|
import numpy as np
|
|
@@ -35,7 +35,7 @@ from cirq.experiments.random_quantum_circuit_generation import (
|
|
|
35
35
|
random_rotations_between_two_qubit_circuit,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
-
SINGLE_QUBIT_LAYER =
|
|
38
|
+
SINGLE_QUBIT_LAYER = dict[cirq.GridQubit, cirq.Gate | None]
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def test_random_rotation_between_two_qubit_circuit():
|
|
@@ -404,7 +404,7 @@ def test_grid_interaction_layer_repr():
|
|
|
404
404
|
|
|
405
405
|
|
|
406
406
|
def _validate_single_qubit_layers(
|
|
407
|
-
qubits:
|
|
407
|
+
qubits: set[cirq.GridQubit], moments: Sequence[cirq.Moment], non_repeating_layers: bool = True
|
|
408
408
|
) -> None:
|
|
409
409
|
previous_single_qubit_gates: SINGLE_QUBIT_LAYER = {q: None for q in qubits}
|
|
410
410
|
|
|
@@ -422,7 +422,7 @@ def _validate_single_qubit_layers(
|
|
|
422
422
|
|
|
423
423
|
|
|
424
424
|
def _validate_two_qubit_layers(
|
|
425
|
-
qubits:
|
|
425
|
+
qubits: set[cirq.GridQubit],
|
|
426
426
|
moments: Sequence[cirq.Moment],
|
|
427
427
|
pattern: Sequence[cirq.experiments.GridInteractionLayer],
|
|
428
428
|
) -> None:
|
|
@@ -447,8 +447,8 @@ def _validate_two_qubit_layers(
|
|
|
447
447
|
|
|
448
448
|
|
|
449
449
|
def _coupled_qubit_pairs(
|
|
450
|
-
qubits:
|
|
451
|
-
) ->
|
|
450
|
+
qubits: set[cirq.GridQubit],
|
|
451
|
+
) -> list[tuple[cirq.GridQubit, cirq.GridQubit]]:
|
|
452
452
|
pairs = []
|
|
453
453
|
for qubit in qubits:
|
|
454
454
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import time
|
|
20
|
-
from typing import Any, cast,
|
|
20
|
+
from typing import Any, cast, Sequence, TYPE_CHECKING
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
import scipy.optimize
|
|
@@ -61,8 +61,8 @@ class TensoredConfusionMatrices:
|
|
|
61
61
|
|
|
62
62
|
def __init__(
|
|
63
63
|
self,
|
|
64
|
-
confusion_matrices:
|
|
65
|
-
measure_qubits:
|
|
64
|
+
confusion_matrices: np.ndarray | Sequence[np.ndarray],
|
|
65
|
+
measure_qubits: Sequence[cirq.Qid] | Sequence[Sequence[cirq.Qid]],
|
|
66
66
|
*,
|
|
67
67
|
repetitions: int,
|
|
68
68
|
timestamp: float,
|
|
@@ -114,7 +114,7 @@ class TensoredConfusionMatrices:
|
|
|
114
114
|
self._measure_qubits = tuple(tuple(q) for q in measure_qubits)
|
|
115
115
|
self._qubits = tuple(sorted(set(q for ql in measure_qubits for q in ql)))
|
|
116
116
|
self._qubits_to_idx = {q: i for i, q in enumerate(self._qubits)}
|
|
117
|
-
self._cache:
|
|
117
|
+
self._cache: dict[tuple[cirq.Qid, ...], np.ndarray] = {}
|
|
118
118
|
if sum(len(q) for q in self._measure_qubits) != len(self._qubits):
|
|
119
119
|
raise ValueError(f"Repeated qubits not allowed in measure_qubits: {measure_qubits}.")
|
|
120
120
|
|
|
@@ -157,27 +157,27 @@ class TensoredConfusionMatrices:
|
|
|
157
157
|
return self._timestamp
|
|
158
158
|
|
|
159
159
|
@property
|
|
160
|
-
def confusion_matrices(self) ->
|
|
160
|
+
def confusion_matrices(self) -> tuple[np.ndarray, ...]:
|
|
161
161
|
"""List of confusion matrices corresponding to `measure_qubits` qubit pattern."""
|
|
162
162
|
return self._confusion_matrices
|
|
163
163
|
|
|
164
164
|
@property
|
|
165
|
-
def measure_qubits(self) ->
|
|
165
|
+
def measure_qubits(self) -> tuple[tuple[cirq.Qid, ...], ...]:
|
|
166
166
|
"""Calibrated qubit pattern for which individual confusion matrices were computed."""
|
|
167
167
|
return self._measure_qubits
|
|
168
168
|
|
|
169
169
|
@property
|
|
170
|
-
def qubits(self) ->
|
|
170
|
+
def qubits(self) -> tuple[cirq.Qid, ...]:
|
|
171
171
|
"""Sorted list of all calibrated qubits."""
|
|
172
172
|
return self._qubits
|
|
173
173
|
|
|
174
|
-
def _get_vars(self, qubit_pattern: Sequence[cirq.Qid]) ->
|
|
174
|
+
def _get_vars(self, qubit_pattern: Sequence[cirq.Qid]) -> list[int]:
|
|
175
175
|
in_vars = [2 * self._qubits_to_idx[q] for q in qubit_pattern]
|
|
176
176
|
out_vars = [2 * self._qubits_to_idx[q] + 1 for q in qubit_pattern]
|
|
177
177
|
return in_vars + out_vars
|
|
178
178
|
|
|
179
179
|
def _confusion_matrix(self, qubits: Sequence[cirq.Qid]) -> np.ndarray:
|
|
180
|
-
ein_input:
|
|
180
|
+
ein_input: list[np.ndarray | list[int]] = []
|
|
181
181
|
for qs, cm in zip(self.measure_qubits, self.confusion_matrices):
|
|
182
182
|
ein_input.extend([cm.reshape((2, 2) * len(qs)), self._get_vars(qs)])
|
|
183
183
|
ein_out = self._get_vars(qubits)
|
|
@@ -185,7 +185,7 @@ class TensoredConfusionMatrices:
|
|
|
185
185
|
ret = np.einsum(*ein_input, ein_out).reshape((2 ** len(qubits),) * 2)
|
|
186
186
|
return ret / ret.sum(axis=1)
|
|
187
187
|
|
|
188
|
-
def confusion_matrix(self, qubits:
|
|
188
|
+
def confusion_matrix(self, qubits: Sequence[cirq.Qid] | None = None) -> np.ndarray:
|
|
189
189
|
"""Returns a single confusion matrix constructed for the given set of qubits.
|
|
190
190
|
|
|
191
191
|
The single `2 ** len(qubits) x 2 ** len(qubits)` confusion matrix is constructed
|
|
@@ -213,7 +213,7 @@ class TensoredConfusionMatrices:
|
|
|
213
213
|
self._cache[key] = self._confusion_matrix(qubits)
|
|
214
214
|
return self._cache[key]
|
|
215
215
|
|
|
216
|
-
def correction_matrix(self, qubits:
|
|
216
|
+
def correction_matrix(self, qubits: Sequence[cirq.Qid] | None = None) -> np.ndarray:
|
|
217
217
|
"""Returns a single correction matrix constructed for the given set of qubits.
|
|
218
218
|
|
|
219
219
|
A correction matrix is the inverse of confusion matrix and can be used to apply corrections
|
|
@@ -242,7 +242,7 @@ class TensoredConfusionMatrices:
|
|
|
242
242
|
def apply(
|
|
243
243
|
self,
|
|
244
244
|
result: np.ndarray,
|
|
245
|
-
qubits:
|
|
245
|
+
qubits: Sequence[cirq.Qid] | None = None,
|
|
246
246
|
*,
|
|
247
247
|
method='least_squares',
|
|
248
248
|
) -> np.ndarray:
|
|
@@ -375,7 +375,7 @@ class TensoredConfusionMatrices:
|
|
|
375
375
|
f")"
|
|
376
376
|
)
|
|
377
377
|
|
|
378
|
-
def _json_dict_(self) ->
|
|
378
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
379
379
|
return {
|
|
380
380
|
'confusion_matrices': self.confusion_matrices,
|
|
381
381
|
'measure_qubits': self.measure_qubits,
|
|
@@ -426,7 +426,7 @@ class TensoredConfusionMatrices:
|
|
|
426
426
|
|
|
427
427
|
def measure_confusion_matrix(
|
|
428
428
|
sampler: cirq.Sampler,
|
|
429
|
-
qubits:
|
|
429
|
+
qubits: Sequence[cirq.Qid] | Sequence[Sequence[cirq.Qid]],
|
|
430
430
|
repetitions: int = 1000,
|
|
431
431
|
) -> TensoredConfusionMatrices:
|
|
432
432
|
"""Prepares `TensoredConfusionMatrices` for the n qubits in the input.
|
|
@@ -18,7 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import dataclasses
|
|
20
20
|
import time
|
|
21
|
-
from typing import Any, cast,
|
|
21
|
+
from typing import Any, cast, Iterable, TYPE_CHECKING
|
|
22
22
|
|
|
23
23
|
import matplotlib.pyplot as plt
|
|
24
24
|
import numpy as np
|
|
@@ -47,12 +47,12 @@ class SingleQubitReadoutCalibrationResult:
|
|
|
47
47
|
timestamp: The time the data was taken, in seconds since the epoch.
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
|
-
zero_state_errors:
|
|
51
|
-
one_state_errors:
|
|
50
|
+
zero_state_errors: dict[cirq.Qid, float]
|
|
51
|
+
one_state_errors: dict[cirq.Qid, float]
|
|
52
52
|
repetitions: int
|
|
53
53
|
timestamp: float
|
|
54
54
|
|
|
55
|
-
def _json_dict_(self) ->
|
|
55
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
56
56
|
return {
|
|
57
57
|
'zero_state_errors': list(self.zero_state_errors.items()),
|
|
58
58
|
'one_state_errors': list(self.one_state_errors.items()),
|
|
@@ -62,7 +62,7 @@ class SingleQubitReadoutCalibrationResult:
|
|
|
62
62
|
|
|
63
63
|
def plot_heatmap(
|
|
64
64
|
self,
|
|
65
|
-
axs:
|
|
65
|
+
axs: tuple[plt.Axes, plt.Axes] | None = None,
|
|
66
66
|
annotation_format: str = '0.1%',
|
|
67
67
|
**plot_kwargs: Any,
|
|
68
68
|
) -> tuple[plt.Axes, plt.Axes]:
|
|
@@ -110,16 +110,16 @@ class SingleQubitReadoutCalibrationResult:
|
|
|
110
110
|
|
|
111
111
|
def plot_integrated_histogram(
|
|
112
112
|
self,
|
|
113
|
-
ax:
|
|
113
|
+
ax: plt.Axes | None = None,
|
|
114
114
|
cdf_on_x: bool = False,
|
|
115
115
|
axis_label: str = 'Readout error rate',
|
|
116
116
|
semilog: bool = True,
|
|
117
117
|
median_line: bool = True,
|
|
118
|
-
median_label:
|
|
118
|
+
median_label: str | None = 'median',
|
|
119
119
|
mean_line: bool = False,
|
|
120
|
-
mean_label:
|
|
120
|
+
mean_label: str | None = 'mean',
|
|
121
121
|
show_zero: bool = False,
|
|
122
|
-
title:
|
|
122
|
+
title: str | None = None,
|
|
123
123
|
**kwargs,
|
|
124
124
|
) -> plt.Axes:
|
|
125
125
|
"""Plot the readout errors using cirq.integrated_histogram().
|
|
@@ -238,8 +238,8 @@ def estimate_parallel_single_qubit_readout_errors(
|
|
|
238
238
|
qubits: Iterable[cirq.Qid],
|
|
239
239
|
trials: int = 20,
|
|
240
240
|
repetitions: int = 1000,
|
|
241
|
-
trials_per_batch:
|
|
242
|
-
bit_strings:
|
|
241
|
+
trials_per_batch: int | None = None,
|
|
242
|
+
bit_strings: np.ndarray | None = None,
|
|
243
243
|
) -> SingleQubitReadoutCalibrationResult:
|
|
244
244
|
"""Estimate single qubit readout error using parallel operations.
|
|
245
245
|
|
|
@@ -300,7 +300,7 @@ def estimate_parallel_single_qubit_readout_errors(
|
|
|
300
300
|
if trials_per_batch <= 0:
|
|
301
301
|
raise ValueError("Must provide non-zero trials_per_batch for readout calibration.")
|
|
302
302
|
|
|
303
|
-
all_sweeps:
|
|
303
|
+
all_sweeps: list[study.Sweepable] = []
|
|
304
304
|
num_batches = (trials + trials_per_batch - 1) // trials_per_batch
|
|
305
305
|
|
|
306
306
|
# Initialize circuits
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import enum
|
|
18
|
-
from typing import Any,
|
|
18
|
+
from typing import Any, TYPE_CHECKING
|
|
19
19
|
|
|
20
20
|
import pandas as pd
|
|
21
21
|
import sympy
|
|
@@ -46,9 +46,9 @@ def t2_decay(
|
|
|
46
46
|
max_delay: cirq.DURATION_LIKE,
|
|
47
47
|
min_delay: cirq.DURATION_LIKE = None,
|
|
48
48
|
repetitions: int = 1000,
|
|
49
|
-
delay_sweep:
|
|
50
|
-
num_pulses:
|
|
51
|
-
) ->
|
|
49
|
+
delay_sweep: study.Sweep | None = None,
|
|
50
|
+
num_pulses: list[int] | None = None,
|
|
51
|
+
) -> cirq.experiments.T2DecayResult | list[cirq.experiments.T2DecayResult]:
|
|
52
52
|
"""Runs a t2 transverse relaxation experiment.
|
|
53
53
|
|
|
54
54
|
Initializes a qubit into a superposition state, evolves the system using
|
|
@@ -259,7 +259,7 @@ def _cpmg_circuit(qubit: cirq.Qid, delay_var: sympy.Symbol, max_pulses: int) ->
|
|
|
259
259
|
return circuit
|
|
260
260
|
|
|
261
261
|
|
|
262
|
-
def _cpmg_sweep(num_pulses:
|
|
262
|
+
def _cpmg_sweep(num_pulses: list[int]):
|
|
263
263
|
"""Returns a sweep for a circuit created by _cpmg_circuit.
|
|
264
264
|
|
|
265
265
|
The circuit in _cpmg_circuit parameterizes the pulses, so this function
|
|
@@ -354,7 +354,7 @@ class T2DecayResult:
|
|
|
354
354
|
"""
|
|
355
355
|
return self._expectation_pauli_y
|
|
356
356
|
|
|
357
|
-
def plot_expectations(self, ax:
|
|
357
|
+
def plot_expectations(self, ax: plt.Axes | None = None, **plot_kwargs: Any) -> plt.Axes:
|
|
358
358
|
"""Plots the expectation values of Pauli operators versus delay time.
|
|
359
359
|
|
|
360
360
|
Args:
|
|
@@ -395,7 +395,7 @@ class T2DecayResult:
|
|
|
395
395
|
fig.show()
|
|
396
396
|
return ax
|
|
397
397
|
|
|
398
|
-
def plot_bloch_vector(self, ax:
|
|
398
|
+
def plot_bloch_vector(self, ax: plt.Axes | None = None, **plot_kwargs: Any) -> plt.Axes:
|
|
399
399
|
"""Plots the estimated length of the Bloch vector versus time.
|
|
400
400
|
|
|
401
401
|
This plot estimates the Bloch Vector by squaring the Pauli expectation
|
|
@@ -20,7 +20,7 @@ import functools
|
|
|
20
20
|
import itertools
|
|
21
21
|
from dataclasses import dataclass
|
|
22
22
|
from types import MappingProxyType
|
|
23
|
-
from typing import Any, cast,
|
|
23
|
+
from typing import Any, cast, Mapping, Sequence, TYPE_CHECKING
|
|
24
24
|
|
|
25
25
|
import networkx as nx
|
|
26
26
|
import numpy as np
|
|
@@ -49,7 +49,7 @@ if TYPE_CHECKING:
|
|
|
49
49
|
import cirq
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def _grid_qubits_for_sampler(sampler: cirq.Sampler) ->
|
|
52
|
+
def _grid_qubits_for_sampler(sampler: cirq.Sampler) -> Sequence[cirq.GridQubit] | None:
|
|
53
53
|
if hasattr(sampler, 'processor'):
|
|
54
54
|
device = sampler.processor.get_device()
|
|
55
55
|
return sorted(device.metadata.qubit_set)
|
|
@@ -62,9 +62,9 @@ def _manhattan_distance(qubit1: cirq.GridQubit, qubit2: cirq.GridQubit) -> int:
|
|
|
62
62
|
|
|
63
63
|
def qubits_and_pairs(
|
|
64
64
|
sampler: cirq.Sampler,
|
|
65
|
-
qubits:
|
|
66
|
-
pairs:
|
|
67
|
-
) ->
|
|
65
|
+
qubits: Sequence[cirq.GridQubit] | None = None,
|
|
66
|
+
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
|
|
67
|
+
) -> tuple[Sequence[cirq.GridQubit], Sequence[tuple[cirq.GridQubit, cirq.GridQubit]]]:
|
|
68
68
|
"""Extract qubits and pairs from sampler.
|
|
69
69
|
|
|
70
70
|
|
|
@@ -107,7 +107,7 @@ class TwoQubitXEBResult:
|
|
|
107
107
|
fidelities: pd.DataFrame
|
|
108
108
|
|
|
109
109
|
@functools.cached_property
|
|
110
|
-
def _qubit_pair_map(self) ->
|
|
110
|
+
def _qubit_pair_map(self) -> dict[tuple[cirq.GridQubit, cirq.GridQubit], int]:
|
|
111
111
|
if isinstance(self.fidelities.index[0][0], ops.Qid):
|
|
112
112
|
return {
|
|
113
113
|
(min(q0, q1), max(q0, q1)): i for i, (q0, q1) in enumerate(self.fidelities.index)
|
|
@@ -118,10 +118,10 @@ class TwoQubitXEBResult:
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
@functools.cached_property
|
|
121
|
-
def all_qubit_pairs(self) ->
|
|
121
|
+
def all_qubit_pairs(self) -> tuple[tuple[cirq.GridQubit, cirq.GridQubit], ...]:
|
|
122
122
|
return tuple(sorted(self._qubit_pair_map.keys()))
|
|
123
123
|
|
|
124
|
-
def plot_heatmap(self, ax:
|
|
124
|
+
def plot_heatmap(self, ax: plt.Axes | None = None, **plot_kwargs) -> plt.Axes:
|
|
125
125
|
"""plot the heatmap of XEB errors.
|
|
126
126
|
|
|
127
127
|
Args:
|
|
@@ -135,7 +135,7 @@ class TwoQubitXEBResult:
|
|
|
135
135
|
show_plot = not ax
|
|
136
136
|
if not isinstance(ax, plt.Axes):
|
|
137
137
|
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
|
|
138
|
-
heatmap_data:
|
|
138
|
+
heatmap_data: dict[tuple[cirq.GridQubit, ...], float] = {
|
|
139
139
|
pair: self.xeb_error(*pair) for pair in self.all_qubit_pairs
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -147,7 +147,7 @@ class TwoQubitXEBResult:
|
|
|
147
147
|
return ax
|
|
148
148
|
|
|
149
149
|
def plot_fitted_exponential(
|
|
150
|
-
self, q0: cirq.GridQubit, q1: cirq.GridQubit, ax:
|
|
150
|
+
self, q0: cirq.GridQubit, q1: cirq.GridQubit, ax: plt.Axes | None = None, **plot_kwargs
|
|
151
151
|
) -> plt.Axes:
|
|
152
152
|
"""plot the fitted model to for xeb error of a qubit pair.
|
|
153
153
|
|
|
@@ -199,11 +199,11 @@ class TwoQubitXEBResult:
|
|
|
199
199
|
"""Return the XEB error of a qubit pair."""
|
|
200
200
|
return 1 - self.xeb_fidelity(q0, q1)
|
|
201
201
|
|
|
202
|
-
def all_errors(self) ->
|
|
202
|
+
def all_errors(self) -> dict[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
203
203
|
"""Return the XEB error of all qubit pairs."""
|
|
204
204
|
return {(q0, q1): self.xeb_error(q0, q1) for q0, q1 in self.all_qubit_pairs}
|
|
205
205
|
|
|
206
|
-
def plot_histogram(self, ax:
|
|
206
|
+
def plot_histogram(self, ax: plt.Axes | None = None, **plot_kwargs) -> plt.Axes:
|
|
207
207
|
"""plot a histogram of all xeb errors.
|
|
208
208
|
|
|
209
209
|
Args:
|
|
@@ -223,7 +223,7 @@ class TwoQubitXEBResult:
|
|
|
223
223
|
return ax
|
|
224
224
|
|
|
225
225
|
@cached_method
|
|
226
|
-
def pauli_error(self) ->
|
|
226
|
+
def pauli_error(self) -> dict[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
227
227
|
"""Return the Pauli error of all qubit pairs."""
|
|
228
228
|
return {
|
|
229
229
|
pair: noise_utils.decay_constant_to_pauli_error(
|
|
@@ -246,7 +246,7 @@ class InferredXEBResult:
|
|
|
246
246
|
xeb_result: TwoQubitXEBResult
|
|
247
247
|
|
|
248
248
|
@property
|
|
249
|
-
def all_qubit_pairs(self) -> Sequence[
|
|
249
|
+
def all_qubit_pairs(self) -> Sequence[tuple[cirq.GridQubit, cirq.GridQubit]]:
|
|
250
250
|
return self.xeb_result.all_qubit_pairs
|
|
251
251
|
|
|
252
252
|
@cached_method
|
|
@@ -255,12 +255,12 @@ class InferredXEBResult:
|
|
|
255
255
|
return self.rb_result.pauli_error()
|
|
256
256
|
|
|
257
257
|
@cached_method
|
|
258
|
-
def two_qubit_pauli_error(self) -> Mapping[
|
|
258
|
+
def two_qubit_pauli_error(self) -> Mapping[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
259
259
|
"""Return the two-qubit Pauli error for all pairs."""
|
|
260
260
|
return MappingProxyType(self.xeb_result.pauli_error())
|
|
261
261
|
|
|
262
262
|
@cached_method
|
|
263
|
-
def inferred_pauli_error(self) -> Mapping[
|
|
263
|
+
def inferred_pauli_error(self) -> Mapping[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
264
264
|
"""Return the inferred Pauli error for all pairs."""
|
|
265
265
|
single_q_paulis = self.rb_result.pauli_error()
|
|
266
266
|
xeb = self.xeb_result.pauli_error()
|
|
@@ -272,7 +272,7 @@ class InferredXEBResult:
|
|
|
272
272
|
return MappingProxyType({pair: _pauli_error(*pair) for pair in self.all_qubit_pairs})
|
|
273
273
|
|
|
274
274
|
@cached_method
|
|
275
|
-
def inferred_decay_constant(self) -> Mapping[
|
|
275
|
+
def inferred_decay_constant(self) -> Mapping[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
276
276
|
"""Return the inferred decay constant for all pairs."""
|
|
277
277
|
return MappingProxyType(
|
|
278
278
|
{
|
|
@@ -282,7 +282,7 @@ class InferredXEBResult:
|
|
|
282
282
|
)
|
|
283
283
|
|
|
284
284
|
@cached_method
|
|
285
|
-
def inferred_xeb_error(self) -> Mapping[
|
|
285
|
+
def inferred_xeb_error(self) -> Mapping[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
286
286
|
"""Return the inferred XEB error for all pairs."""
|
|
287
287
|
return MappingProxyType(
|
|
288
288
|
{
|
|
@@ -293,7 +293,7 @@ class InferredXEBResult:
|
|
|
293
293
|
|
|
294
294
|
def _target_errors(
|
|
295
295
|
self, target_error: str
|
|
296
|
-
) -> Mapping[
|
|
296
|
+
) -> Mapping[tuple[cirq.GridQubit, cirq.GridQubit], float]:
|
|
297
297
|
"""Returns requested error.
|
|
298
298
|
|
|
299
299
|
The requested error must be one of 'pauli', 'decay_constant', or 'xeb'.
|
|
@@ -315,7 +315,7 @@ class InferredXEBResult:
|
|
|
315
315
|
return error_funcs[target_error]()
|
|
316
316
|
|
|
317
317
|
def plot_heatmap(
|
|
318
|
-
self, target_error: str = 'pauli', ax:
|
|
318
|
+
self, target_error: str = 'pauli', ax: plt.Axes | None = None, **plot_kwargs
|
|
319
319
|
) -> plt.Axes:
|
|
320
320
|
"""plot the heatmap of the target errors.
|
|
321
321
|
|
|
@@ -329,7 +329,7 @@ class InferredXEBResult:
|
|
|
329
329
|
if not isinstance(ax, plt.Axes):
|
|
330
330
|
fig, ax = plt.subplots(1, 1, figsize=(8, 8))
|
|
331
331
|
heatmap_data = cast(
|
|
332
|
-
Mapping[
|
|
332
|
+
Mapping[tuple['cirq.GridQubit', ...], float], self._target_errors(target_error)
|
|
333
333
|
)
|
|
334
334
|
|
|
335
335
|
name = f'{target_error} error' if target_error != 'decay_constant' else 'decay constant'
|
|
@@ -343,7 +343,7 @@ class InferredXEBResult:
|
|
|
343
343
|
def plot_histogram(
|
|
344
344
|
self,
|
|
345
345
|
target_error: str = 'pauli',
|
|
346
|
-
ax:
|
|
346
|
+
ax: plt.Axes | None = None,
|
|
347
347
|
kind: str = 'two_qubit',
|
|
348
348
|
**plot_kwargs,
|
|
349
349
|
) -> plt.Axes:
|
|
@@ -398,20 +398,20 @@ class InferredXEBResult:
|
|
|
398
398
|
|
|
399
399
|
def parallel_xeb_workflow(
|
|
400
400
|
sampler: cirq.Sampler,
|
|
401
|
-
qubits:
|
|
401
|
+
qubits: Sequence[cirq.GridQubit] | None = None,
|
|
402
402
|
entangling_gate: cirq.Gate = ops.CZ,
|
|
403
403
|
n_repetitions: int = 10**4,
|
|
404
404
|
n_combinations: int = 10,
|
|
405
405
|
n_circuits: int = 20,
|
|
406
406
|
cycle_depths: Sequence[int] = (5, 25, 50, 100, 200, 300),
|
|
407
407
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
408
|
-
ax:
|
|
409
|
-
pairs:
|
|
410
|
-
pool:
|
|
408
|
+
ax: plt.Axes | None = None,
|
|
409
|
+
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
|
|
410
|
+
pool: multiprocessing.pool.Pool | None = None,
|
|
411
411
|
batch_size: int = 9,
|
|
412
412
|
tags: Sequence[Any] = (),
|
|
413
413
|
**plot_kwargs,
|
|
414
|
-
) ->
|
|
414
|
+
) -> tuple[pd.DataFrame, Sequence[cirq.Circuit], pd.DataFrame]:
|
|
415
415
|
"""A utility method that runs the full XEB workflow.
|
|
416
416
|
|
|
417
417
|
Args:
|
|
@@ -488,15 +488,15 @@ def parallel_xeb_workflow(
|
|
|
488
488
|
|
|
489
489
|
def parallel_two_qubit_xeb(
|
|
490
490
|
sampler: cirq.Sampler,
|
|
491
|
-
qubits:
|
|
491
|
+
qubits: Sequence[cirq.GridQubit] | None = None,
|
|
492
492
|
entangling_gate: cirq.Gate = ops.CZ,
|
|
493
493
|
n_repetitions: int = 10**4,
|
|
494
494
|
n_combinations: int = 10,
|
|
495
495
|
n_circuits: int = 20,
|
|
496
496
|
cycle_depths: Sequence[int] = (5, 25, 50, 100, 200, 300),
|
|
497
497
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
498
|
-
ax:
|
|
499
|
-
pairs:
|
|
498
|
+
ax: plt.Axes | None = None,
|
|
499
|
+
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
|
|
500
500
|
batch_size: int = 9,
|
|
501
501
|
tags: Sequence[Any] = (),
|
|
502
502
|
**plot_kwargs,
|
|
@@ -545,7 +545,7 @@ def parallel_two_qubit_xeb(
|
|
|
545
545
|
|
|
546
546
|
def run_rb_and_xeb(
|
|
547
547
|
sampler: cirq.Sampler,
|
|
548
|
-
qubits:
|
|
548
|
+
qubits: Sequence[cirq.GridQubit] | None = None,
|
|
549
549
|
repetitions: int = 10**3,
|
|
550
550
|
num_circuits: int = 20,
|
|
551
551
|
num_clifford_range: Sequence[int] = tuple(
|
|
@@ -555,7 +555,7 @@ def run_rb_and_xeb(
|
|
|
555
555
|
depths_xeb: Sequence[int] = (5, 25, 50, 100, 200, 300),
|
|
556
556
|
xeb_combinations: int = 10,
|
|
557
557
|
random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
558
|
-
pairs:
|
|
558
|
+
pairs: Sequence[tuple[cirq.GridQubit, cirq.GridQubit]] | None = None,
|
|
559
559
|
batch_size: int = 9,
|
|
560
560
|
tags: Sequence[Any] = (),
|
|
561
561
|
) -> InferredXEBResult:
|