cirq-core 1.4.0.dev20240529225110__py3-none-any.whl → 1.5.0__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/__init__.py +587 -569
- cirq/_compat.py +9 -0
- cirq/_compat_test.py +11 -9
- cirq/_import.py +7 -8
- cirq/_version.py +31 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/__init__.py +15 -9
- cirq/circuits/_block_diagram_drawer.py +1 -2
- cirq/circuits/_block_diagram_drawer_test.py +3 -3
- cirq/circuits/_box_drawing_character_data.py +0 -1
- cirq/circuits/_box_drawing_character_data_test.py +2 -2
- cirq/circuits/_bucket_priority_queue.py +0 -1
- cirq/circuits/_bucket_priority_queue_test.py +1 -1
- cirq/circuits/circuit.py +336 -234
- cirq/circuits/circuit_operation.py +102 -52
- cirq/circuits/circuit_operation_test.py +85 -4
- cirq/circuits/circuit_test.py +101 -32
- cirq/circuits/frozen_circuit.py +36 -32
- cirq/circuits/insert_strategy.py +10 -0
- cirq/circuits/insert_strategy_test.py +20 -0
- cirq/circuits/moment.py +79 -80
- cirq/circuits/moment_test.py +105 -2
- cirq/circuits/optimization_pass.py +15 -15
- cirq/circuits/optimization_pass_test.py +8 -9
- cirq/circuits/qasm_output.py +64 -33
- cirq/circuits/qasm_output_test.py +63 -2
- cirq/circuits/text_diagram_drawer.py +26 -56
- cirq/circuits/text_diagram_drawer_test.py +5 -4
- cirq/contrib/__init__.py +2 -2
- cirq/contrib/acquaintance/__init__.py +44 -29
- cirq/contrib/acquaintance/bipartite.py +8 -7
- cirq/contrib/acquaintance/bipartite_test.py +11 -1
- cirq/contrib/acquaintance/devices.py +5 -4
- cirq/contrib/acquaintance/devices_test.py +5 -1
- cirq/contrib/acquaintance/executor.py +18 -21
- cirq/contrib/acquaintance/executor_test.py +3 -2
- cirq/contrib/acquaintance/gates.py +36 -27
- cirq/contrib/acquaintance/gates_test.py +1 -1
- cirq/contrib/acquaintance/inspection_utils.py +10 -9
- cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
- cirq/contrib/acquaintance/mutation_utils.py +10 -10
- cirq/contrib/acquaintance/optimizers.py +7 -6
- cirq/contrib/acquaintance/optimizers_test.py +1 -1
- cirq/contrib/acquaintance/permutation.py +22 -21
- cirq/contrib/acquaintance/permutation_test.py +1 -1
- cirq/contrib/acquaintance/shift.py +8 -6
- cirq/contrib/acquaintance/shift_swap_network.py +6 -4
- cirq/contrib/acquaintance/strategies/__init__.py +9 -3
- cirq/contrib/acquaintance/strategies/complete.py +4 -3
- cirq/contrib/acquaintance/strategies/cubic.py +5 -3
- cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
- cirq/contrib/acquaintance/topological_sort.py +4 -2
- cirq/contrib/bayesian_network/__init__.py +3 -1
- cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
- cirq/contrib/circuitdag/__init__.py +1 -1
- cirq/contrib/circuitdag/circuit_dag.py +24 -24
- cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
- cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
- cirq/contrib/graph_device/__init__.py +8 -8
- cirq/contrib/graph_device/graph_device.py +8 -8
- cirq/contrib/graph_device/graph_device_test.py +0 -1
- cirq/contrib/graph_device/hypergraph_test.py +1 -0
- cirq/contrib/json.py +1 -2
- cirq/contrib/json_test.py +2 -2
- cirq/contrib/noise_models/__init__.py +5 -6
- cirq/contrib/noise_models/noise_models.py +8 -6
- cirq/contrib/paulistring/__init__.py +22 -10
- cirq/contrib/paulistring/clifford_optimize.py +1 -1
- cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
- cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
- cirq/contrib/paulistring/optimize.py +2 -2
- cirq/contrib/paulistring/optimize_test.py +0 -1
- cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
- cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
- cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
- cirq/contrib/paulistring/recombine.py +2 -2
- cirq/contrib/paulistring/recombine_test.py +2 -2
- cirq/contrib/paulistring/separate.py +3 -4
- cirq/contrib/qasm_import/__init__.py +2 -2
- cirq/contrib/qasm_import/_lexer.py +21 -26
- cirq/contrib/qasm_import/_lexer_test.py +90 -6
- cirq/contrib/qasm_import/_parser.py +238 -47
- cirq/contrib/qasm_import/_parser_test.py +514 -59
- cirq/contrib/qasm_import/qasm_test.py +1 -1
- cirq/contrib/qcircuit/__init__.py +6 -4
- cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
- cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
- cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
- cirq/contrib/qcircuit/qcircuit_test.py +1 -1
- cirq/contrib/quantum_volume/__init__.py +7 -7
- cirq/contrib/quantum_volume/quantum_volume.py +6 -11
- cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
- cirq/contrib/quimb/__init__.py +16 -13
- cirq/contrib/quimb/density_matrix.py +1 -1
- cirq/contrib/quimb/mps_simulator.py +27 -28
- cirq/contrib/quimb/mps_simulator_test.py +5 -0
- cirq/contrib/quimb/state_vector.py +3 -10
- cirq/contrib/quirk/__init__.py +1 -1
- cirq/contrib/quirk/export_to_quirk.py +3 -3
- cirq/contrib/routing/__init__.py +12 -9
- cirq/contrib/routing/device.py +1 -1
- cirq/contrib/routing/device_test.py +1 -2
- cirq/contrib/routing/greedy.py +7 -5
- cirq/contrib/routing/greedy_test.py +5 -3
- cirq/contrib/routing/initialization.py +3 -1
- cirq/contrib/routing/initialization_test.py +1 -1
- cirq/contrib/routing/swap_network.py +6 -6
- cirq/contrib/routing/utils.py +6 -4
- cirq/contrib/routing/utils_test.py +1 -2
- cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
- cirq/contrib/svg/__init__.py +1 -1
- cirq/contrib/svg/svg.py +12 -10
- cirq/contrib/svg/svg_test.py +3 -2
- cirq/devices/__init__.py +34 -25
- cirq/devices/device.py +16 -12
- cirq/devices/device_test.py +1 -0
- cirq/devices/grid_device_metadata.py +16 -12
- cirq/devices/grid_device_metadata_test.py +2 -1
- cirq/devices/grid_qubit.py +31 -26
- cirq/devices/grid_qubit_test.py +30 -1
- cirq/devices/insertion_noise_model.py +6 -6
- cirq/devices/insertion_noise_model_test.py +1 -1
- cirq/devices/line_qubit.py +28 -20
- cirq/devices/line_qubit_test.py +26 -0
- cirq/devices/named_topologies.py +12 -10
- cirq/devices/named_topologies_test.py +5 -4
- cirq/devices/noise_model.py +29 -33
- cirq/devices/noise_properties.py +2 -2
- cirq/devices/noise_properties_test.py +2 -2
- cirq/devices/noise_utils.py +3 -3
- cirq/devices/superconducting_qubits_noise_properties.py +2 -2
- cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
- cirq/devices/thermal_noise_model.py +2 -1
- cirq/devices/unconstrained_device.py +1 -1
- cirq/devices/unconstrained_device_test.py +6 -0
- cirq/experiments/__init__.py +51 -34
- cirq/experiments/qubit_characterizations.py +17 -15
- cirq/experiments/qubit_characterizations_test.py +4 -6
- cirq/experiments/random_quantum_circuit_generation.py +10 -9
- cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
- cirq/experiments/readout_confusion_matrix.py +73 -8
- cirq/experiments/readout_confusion_matrix_test.py +104 -1
- cirq/experiments/single_qubit_readout_calibration.py +8 -6
- cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
- cirq/experiments/t1_decay_experiment.py +4 -5
- cirq/experiments/t1_decay_experiment_test.py +1 -2
- cirq/experiments/t2_decay_experiment.py +0 -1
- cirq/experiments/t2_decay_experiment_test.py +1 -2
- cirq/experiments/two_qubit_xeb.py +157 -33
- cirq/experiments/two_qubit_xeb_test.py +38 -22
- cirq/experiments/xeb_fitting.py +99 -19
- cirq/experiments/xeb_fitting_test.py +64 -25
- cirq/experiments/xeb_sampling.py +14 -18
- cirq/experiments/xeb_simulation.py +4 -3
- cirq/experiments/xeb_simulation_test.py +20 -14
- cirq/experiments/z_phase_calibration.py +368 -0
- cirq/experiments/z_phase_calibration_test.py +241 -0
- cirq/interop/__init__.py +4 -1
- cirq/interop/quirk/__init__.py +7 -4
- cirq/interop/quirk/cells/__init__.py +17 -6
- cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
- cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
- cirq/interop/quirk/cells/cell.py +6 -6
- cirq/interop/quirk/cells/composite_cell.py +5 -5
- cirq/interop/quirk/cells/composite_cell_test.py +1 -1
- cirq/interop/quirk/cells/control_cells.py +1 -1
- cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
- cirq/interop/quirk/cells/ignored_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells_test.py +1 -1
- cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
- cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
- cirq/interop/quirk/cells/measurement_cells.py +1 -1
- cirq/interop/quirk/cells/parse.py +8 -7
- cirq/interop/quirk/cells/parse_test.py +2 -2
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
- cirq/interop/quirk/cells/swap_cell_test.py +1 -1
- cirq/interop/quirk/cells/unsupported_cells.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +7 -7
- cirq/interop/quirk/url_to_circuit_test.py +1 -1
- cirq/ion/__init__.py +4 -2
- cirq/json_resolver_cache.py +15 -7
- cirq/linalg/__init__.py +62 -51
- cirq/linalg/combinators.py +4 -4
- cirq/linalg/combinators_test.py +4 -1
- cirq/linalg/decompositions.py +15 -40
- cirq/linalg/decompositions_test.py +16 -22
- cirq/linalg/diagonalize.py +1 -1
- cirq/linalg/diagonalize_test.py +1 -1
- cirq/linalg/operator_spaces.py +20 -4
- cirq/linalg/operator_spaces_test.py +15 -2
- cirq/linalg/predicates.py +3 -3
- cirq/linalg/predicates_test.py +1 -0
- cirq/linalg/tolerance.py +2 -2
- cirq/linalg/transformations.py +30 -12
- cirq/linalg/transformations_test.py +13 -0
- cirq/neutral_atoms/__init__.py +2 -2
- cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
- cirq/ops/__init__.py +172 -132
- cirq/ops/arithmetic_operation.py +2 -2
- cirq/ops/arithmetic_operation_test.py +2 -2
- cirq/ops/boolean_hamiltonian.py +3 -2
- cirq/ops/classically_controlled_operation.py +39 -12
- cirq/ops/classically_controlled_operation_test.py +147 -1
- cirq/ops/clifford_gate.py +38 -36
- cirq/ops/clifford_gate_test.py +75 -1
- cirq/ops/common_channels.py +16 -45
- cirq/ops/common_channels_test.py +10 -0
- cirq/ops/common_gate_families.py +1 -1
- cirq/ops/common_gate_families_test.py +1 -0
- cirq/ops/common_gates.py +48 -49
- cirq/ops/common_gates_test.py +18 -2
- cirq/ops/control_values.py +3 -3
- cirq/ops/control_values_test.py +2 -1
- cirq/ops/controlled_gate.py +36 -23
- cirq/ops/controlled_gate_test.py +70 -3
- cirq/ops/controlled_operation.py +6 -5
- cirq/ops/controlled_operation_test.py +7 -3
- cirq/ops/dense_pauli_string.py +11 -11
- cirq/ops/diagonal_gate.py +2 -2
- cirq/ops/diagonal_gate_test.py +1 -0
- cirq/ops/eigen_gate.py +16 -36
- cirq/ops/eigen_gate_test.py +60 -10
- cirq/ops/fourier_transform.py +1 -3
- cirq/ops/fourier_transform_test.py +2 -1
- cirq/ops/fsim_gate.py +42 -3
- cirq/ops/fsim_gate_test.py +21 -0
- cirq/ops/gate_operation.py +8 -8
- cirq/ops/gate_operation_test.py +4 -2
- cirq/ops/gateset_test.py +11 -2
- cirq/ops/global_phase_op.py +8 -7
- cirq/ops/global_phase_op_test.py +1 -1
- cirq/ops/greedy_qubit_manager_test.py +5 -0
- cirq/ops/identity.py +14 -4
- cirq/ops/identity_test.py +24 -0
- cirq/ops/kraus_channel.py +1 -0
- cirq/ops/kraus_channel_test.py +3 -1
- cirq/ops/linear_combinations.py +27 -21
- cirq/ops/linear_combinations_test.py +23 -4
- cirq/ops/matrix_gates.py +24 -8
- cirq/ops/measure_util.py +2 -2
- cirq/ops/measurement_gate.py +7 -4
- cirq/ops/measurement_gate_test.py +2 -1
- cirq/ops/mixed_unitary_channel.py +1 -0
- cirq/ops/mixed_unitary_channel_test.py +3 -1
- cirq/ops/named_qubit.py +8 -1
- cirq/ops/op_tree.py +3 -30
- cirq/ops/op_tree_test.py +4 -0
- cirq/ops/parallel_gate.py +2 -3
- cirq/ops/parallel_gate_test.py +2 -1
- cirq/ops/parity_gates.py +7 -8
- cirq/ops/parity_gates_test.py +1 -0
- cirq/ops/pauli_gates.py +5 -11
- cirq/ops/pauli_gates_test.py +1 -0
- cirq/ops/pauli_interaction_gate.py +11 -5
- cirq/ops/pauli_interaction_gate_test.py +2 -3
- cirq/ops/pauli_measurement_gate.py +6 -5
- cirq/ops/pauli_measurement_gate_test.py +1 -0
- cirq/ops/pauli_string.py +115 -130
- cirq/ops/pauli_string_phasor.py +21 -20
- cirq/ops/pauli_string_phasor_test.py +13 -3
- cirq/ops/pauli_string_raw_types.py +1 -0
- cirq/ops/pauli_string_test.py +192 -55
- cirq/ops/pauli_sum_exponential.py +3 -4
- cirq/ops/pauli_sum_exponential_test.py +0 -1
- cirq/ops/permutation_gate.py +2 -2
- cirq/ops/permutation_gate_test.py +1 -1
- cirq/ops/phased_iswap_gate.py +6 -7
- cirq/ops/phased_iswap_gate_test.py +21 -5
- cirq/ops/phased_x_gate.py +11 -25
- cirq/ops/phased_x_gate_test.py +19 -3
- cirq/ops/phased_x_z_gate.py +12 -11
- cirq/ops/projector.py +4 -5
- cirq/ops/qubit_manager.py +2 -1
- cirq/ops/qubit_manager_test.py +2 -1
- cirq/ops/qubit_order.py +1 -1
- cirq/ops/random_gate_channel.py +1 -1
- cirq/ops/random_gate_channel_test.py +0 -6
- cirq/ops/raw_types.py +146 -50
- cirq/ops/raw_types_test.py +37 -3
- cirq/ops/state_preparation_channel.py +2 -2
- cirq/ops/state_preparation_channel_test.py +2 -1
- cirq/ops/swap_gates.py +9 -4
- cirq/ops/three_qubit_gates.py +8 -8
- cirq/ops/three_qubit_gates_test.py +1 -0
- cirq/ops/two_qubit_diagonal_gate.py +4 -3
- cirq/ops/uniform_superposition_gate.py +4 -4
- cirq/ops/uniform_superposition_gate_test.py +1 -0
- cirq/ops/wait_gate.py +6 -8
- cirq/protocols/__init__.py +135 -83
- cirq/protocols/act_on_protocol.py +1 -1
- cirq/protocols/act_on_protocol_test.py +1 -1
- cirq/protocols/apply_channel_protocol.py +3 -3
- cirq/protocols/apply_mixture_protocol.py +15 -9
- cirq/protocols/apply_mixture_protocol_test.py +11 -0
- cirq/protocols/apply_unitary_protocol.py +2 -2
- cirq/protocols/apply_unitary_protocol_test.py +2 -1
- cirq/protocols/approximate_equality_protocol.py +7 -8
- cirq/protocols/approximate_equality_protocol_test.py +3 -1
- cirq/protocols/circuit_diagram_info_protocol.py +8 -6
- cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
- cirq/protocols/commutes_protocol.py +6 -6
- cirq/protocols/control_key_protocol.py +1 -1
- cirq/protocols/decompose_protocol.py +4 -5
- cirq/protocols/decompose_protocol_test.py +2 -1
- cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
- cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
- cirq/protocols/has_unitary_protocol.py +1 -1
- cirq/protocols/has_unitary_protocol_test.py +8 -7
- cirq/protocols/hash_from_pickle_test.py +120 -0
- cirq/protocols/inverse_protocol.py +1 -1
- cirq/protocols/json_serialization.py +14 -1
- cirq/protocols/json_serialization_test.py +28 -7
- cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
- cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
- cirq/protocols/json_test_data/Concat.json +19 -0
- cirq/protocols/json_test_data/Concat.repr +1 -0
- cirq/protocols/json_test_data/README.md +4 -2
- cirq/protocols/json_test_data/SympyCondition.json +60 -15
- cirq/protocols/json_test_data/SympyCondition.repr +4 -1
- cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
- cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
- cirq/protocols/json_test_data/__init__.py +1 -1
- cirq/protocols/json_test_data/sympy.And.json +13 -0
- cirq/protocols/json_test_data/sympy.And.repr +1 -0
- cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
- cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
- cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
- cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
- cirq/protocols/json_test_data/sympy.Not.json +9 -0
- cirq/protocols/json_test_data/sympy.Not.repr +1 -0
- cirq/protocols/json_test_data/sympy.Or.json +13 -0
- cirq/protocols/json_test_data/sympy.Or.repr +1 -0
- cirq/protocols/json_test_data/sympy.Xor.json +13 -0
- cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
- cirq/protocols/kraus_protocol.py +8 -8
- cirq/protocols/kraus_protocol_test.py +0 -1
- cirq/protocols/measurement_key_protocol.py +1 -1
- cirq/protocols/measurement_key_protocol_test.py +7 -7
- cirq/protocols/mixture_protocol.py +6 -4
- cirq/protocols/mixture_protocol_test.py +21 -13
- cirq/protocols/pauli_expansion_protocol.py +1 -0
- cirq/protocols/pow_protocol.py +1 -1
- cirq/protocols/qasm.py +25 -6
- cirq/protocols/qasm_test.py +17 -0
- cirq/protocols/qid_shape_protocol.py +2 -2
- cirq/protocols/resolve_parameters.py +2 -3
- cirq/protocols/resolve_parameters_test.py +2 -1
- cirq/protocols/trace_distance_bound.py +1 -1
- cirq/protocols/trace_distance_bound_test.py +1 -0
- cirq/protocols/unitary_protocol.py +3 -3
- cirq/protocols/unitary_protocol_test.py +1 -1
- cirq/qis/__init__.py +48 -35
- cirq/qis/channels_test.py +0 -9
- cirq/qis/clifford_tableau.py +46 -26
- cirq/qis/clifford_tableau_test.py +2 -1
- cirq/qis/entropy.py +115 -0
- cirq/qis/entropy_test.py +43 -0
- cirq/qis/measures.py +5 -4
- cirq/qis/measures_test.py +7 -0
- cirq/qis/noise_utils_test.py +4 -4
- cirq/qis/quantum_state_representation.py +1 -1
- cirq/qis/states.py +7 -7
- cirq/sim/__init__.py +55 -37
- cirq/sim/classical_simulator.py +7 -6
- cirq/sim/classical_simulator_test.py +3 -1
- cirq/sim/clifford/__init__.py +17 -9
- cirq/sim/clifford/clifford_simulator.py +5 -4
- cirq/sim/clifford/clifford_simulator_test.py +32 -9
- cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
- cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
- cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
- cirq/sim/density_matrix_simulator.py +3 -2
- cirq/sim/density_matrix_simulator_test.py +12 -4
- cirq/sim/density_matrix_utils.py +1 -1
- cirq/sim/mux.py +2 -2
- cirq/sim/simulation_state.py +4 -5
- cirq/sim/simulation_state_base.py +2 -2
- cirq/sim/simulation_state_test.py +1 -1
- cirq/sim/simulation_utils.py +3 -1
- cirq/sim/simulation_utils_test.py +2 -3
- cirq/sim/simulator.py +7 -6
- cirq/sim/simulator_base.py +5 -5
- cirq/sim/simulator_test.py +14 -3
- cirq/sim/sparse_simulator.py +4 -3
- cirq/sim/sparse_simulator_test.py +17 -9
- cirq/sim/state_vector.py +2 -2
- cirq/sim/state_vector_simulation_state_test.py +1 -1
- cirq/sim/state_vector_simulator.py +4 -4
- cirq/sim/state_vector_test.py +27 -32
- cirq/study/__init__.py +27 -21
- cirq/study/flatten_expressions.py +5 -6
- cirq/study/flatten_expressions_test.py +1 -1
- cirq/study/resolver.py +14 -11
- cirq/study/resolver_test.py +10 -1
- cirq/study/result.py +3 -3
- cirq/study/sweepable.py +15 -9
- cirq/study/sweepable_test.py +27 -0
- cirq/study/sweeps.py +65 -10
- cirq/study/sweeps_test.py +123 -0
- cirq/testing/__init__.py +86 -57
- cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
- cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
- cirq/testing/circuit_compare.py +3 -4
- cirq/testing/circuit_compare_test.py +7 -8
- cirq/testing/consistent_act_on.py +3 -3
- cirq/testing/consistent_channels_test.py +2 -1
- cirq/testing/consistent_controlled_gate_op.py +3 -2
- cirq/testing/consistent_controlled_gate_op_test.py +2 -3
- cirq/testing/consistent_decomposition.py +1 -1
- cirq/testing/consistent_decomposition_test.py +1 -2
- cirq/testing/consistent_pauli_expansion_test.py +1 -1
- cirq/testing/consistent_phase_by.py +1 -1
- cirq/testing/consistent_phase_by_test.py +1 -2
- cirq/testing/consistent_protocols.py +11 -11
- cirq/testing/consistent_protocols_test.py +4 -5
- cirq/testing/consistent_qasm.py +8 -12
- cirq/testing/consistent_qasm_test.py +1 -1
- cirq/testing/consistent_resolve_parameters.py +2 -1
- cirq/testing/consistent_specified_has_unitary_test.py +1 -1
- cirq/testing/consistent_unitary.py +3 -1
- cirq/testing/consistent_unitary_test.py +3 -3
- cirq/testing/devices.py +1 -1
- cirq/testing/devices_test.py +1 -0
- cirq/testing/equals_tester.py +2 -4
- cirq/testing/equals_tester_test.py +6 -5
- cirq/testing/equivalent_basis_map.py +1 -0
- cirq/testing/equivalent_basis_map_test.py +0 -1
- cirq/testing/gate_features_test.py +5 -0
- cirq/testing/json.py +4 -4
- cirq/testing/lin_alg_utils_test.py +1 -1
- cirq/testing/order_tester.py +1 -1
- cirq/testing/order_tester_test.py +1 -1
- cirq/testing/pytest_utils.py +57 -0
- cirq/testing/pytest_utils_test.py +35 -0
- cirq/testing/random_circuit.py +2 -2
- cirq/testing/random_circuit_test.py +2 -2
- cirq/testing/routing_devices_test.py +2 -1
- cirq/testing/sample_circuits.py +1 -1
- cirq/testing/sample_gates.py +5 -4
- cirq/testing/sample_gates_test.py +2 -2
- cirq/transformers/__init__.py +101 -82
- cirq/transformers/align.py +12 -1
- cirq/transformers/align_test.py +13 -0
- cirq/transformers/analytical_decompositions/__init__.py +27 -24
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
- cirq/transformers/drop_empty_moments.py +1 -0
- cirq/transformers/drop_negligible_operations.py +1 -0
- cirq/transformers/dynamical_decoupling.py +255 -43
- cirq/transformers/dynamical_decoupling_test.py +730 -17
- cirq/transformers/eject_phased_paulis.py +29 -15
- cirq/transformers/eject_phased_paulis_test.py +3 -8
- cirq/transformers/eject_z.py +3 -2
- cirq/transformers/eject_z_test.py +3 -3
- cirq/transformers/gauge_compiling/__init__.py +25 -9
- cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
- cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
- cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
- cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
- cirq/transformers/heuristic_decompositions/__init__.py +3 -3
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
- cirq/transformers/insertion_sort.py +64 -0
- cirq/transformers/insertion_sort_test.py +34 -0
- cirq/transformers/measurement_transformers.py +14 -1
- cirq/transformers/measurement_transformers_test.py +35 -0
- cirq/transformers/merge_k_qubit_gates.py +2 -2
- cirq/transformers/merge_single_qubit_gates.py +1 -1
- cirq/transformers/merge_single_qubit_gates_test.py +1 -1
- cirq/transformers/noise_adding.py +115 -0
- cirq/transformers/noise_adding_test.py +54 -0
- cirq/transformers/optimize_for_target_gateset.py +1 -1
- cirq/transformers/optimize_for_target_gateset_test.py +3 -2
- cirq/transformers/qubit_management_transformers.py +1 -1
- cirq/transformers/randomized_measurements.py +171 -0
- cirq/transformers/randomized_measurements_test.py +68 -0
- cirq/transformers/routing/__init__.py +14 -5
- cirq/transformers/routing/initial_mapper.py +1 -1
- cirq/transformers/routing/initial_mapper_test.py +1 -0
- cirq/transformers/routing/line_initial_mapper.py +3 -2
- cirq/transformers/routing/mapping_manager.py +2 -2
- cirq/transformers/routing/mapping_manager_test.py +2 -2
- cirq/transformers/routing/route_circuit_cqc.py +3 -2
- cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
- cirq/transformers/routing/visualize_routed_circuit.py +1 -0
- cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
- cirq/transformers/stratify.py +2 -2
- cirq/transformers/synchronize_terminal_measurements.py +2 -1
- cirq/transformers/target_gatesets/__init__.py +7 -5
- cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
- cirq/transformers/target_gatesets/cz_gateset.py +5 -1
- cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
- cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
- cirq/transformers/transformer_api.py +5 -4
- cirq/transformers/transformer_api_test.py +11 -3
- cirq/transformers/transformer_primitives.py +9 -31
- cirq/transformers/transformer_primitives_test.py +6 -5
- cirq/value/__init__.py +51 -30
- cirq/value/abc_alt.py +1 -2
- cirq/value/angle.py +2 -0
- cirq/value/classical_data.py +1 -0
- cirq/value/condition.py +149 -3
- cirq/value/condition_test.py +254 -0
- cirq/value/digits.py +1 -1
- cirq/value/duration.py +4 -4
- cirq/value/duration_test.py +2 -1
- cirq/value/linear_dict.py +85 -24
- cirq/value/linear_dict_test.py +94 -3
- cirq/value/measurement_key.py +9 -2
- cirq/value/periodic_value.py +2 -3
- cirq/value/periodic_value_test.py +5 -0
- cirq/value/probability.py +1 -0
- cirq/value/random_state.py +1 -1
- cirq/value/timestamp.py +2 -4
- cirq/value/timestamp_test.py +2 -1
- cirq/value/type_alias.py +2 -2
- cirq/value/value_equality_attr.py +14 -2
- cirq/value/value_equality_attr_test.py +1 -1
- cirq/vis/__init__.py +9 -6
- cirq/vis/density_matrix.py +1 -1
- cirq/vis/density_matrix_test.py +2 -5
- cirq/vis/heatmap.py +49 -12
- cirq/vis/heatmap_test.py +168 -4
- cirq/vis/histogram.py +1 -1
- cirq/vis/histogram_test.py +1 -2
- cirq/vis/state_histogram.py +7 -5
- cirq/vis/state_histogram_test.py +2 -2
- cirq/work/__init__.py +19 -13
- cirq/work/collector.py +2 -2
- cirq/work/observable_grouping.py +2 -2
- cirq/work/observable_measurement.py +3 -3
- cirq/work/observable_measurement_data.py +5 -2
- cirq/work/observable_measurement_test.py +8 -8
- cirq/work/observable_readout_calibration.py +2 -2
- cirq/work/observable_readout_calibration_test.py +2 -1
- cirq/work/observable_settings.py +8 -7
- cirq/work/observable_settings_test.py +3 -2
- cirq/work/pauli_sum_collector.py +1 -1
- cirq/work/sampler.py +8 -20
- cirq/work/sampler_test.py +4 -3
- cirq/work/zeros_sampler.py +1 -1
- cirq_core-1.5.0.dist-info/METADATA +125 -0
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
- cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
- cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
- cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
- cirq_core-1.4.0.dev20240529225110.dist-info/METADATA +0 -50
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
|
@@ -15,11 +15,13 @@
|
|
|
15
15
|
"""Utilities to compute readout confusion matrix and use it for readout error mitigation."""
|
|
16
16
|
|
|
17
17
|
import time
|
|
18
|
-
from typing import Any, Dict,
|
|
19
|
-
|
|
18
|
+
from typing import Any, cast, Dict, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
19
|
+
|
|
20
20
|
import numpy as np
|
|
21
21
|
import scipy.optimize
|
|
22
|
-
|
|
22
|
+
import sympy
|
|
23
|
+
|
|
24
|
+
from cirq import circuits, ops, study, vis
|
|
23
25
|
from cirq._compat import proper_repr
|
|
24
26
|
|
|
25
27
|
if TYPE_CHECKING:
|
|
@@ -31,7 +33,7 @@ class TensoredConfusionMatrices:
|
|
|
31
33
|
|
|
32
34
|
The confusion matrix (CM) for one qubit is:
|
|
33
35
|
|
|
34
|
-
[ Pr(0|0) Pr(1
|
|
36
|
+
[ Pr(0|0) Pr(0|1) ]
|
|
35
37
|
[ Pr(1|0) Pr(1|1) ]
|
|
36
38
|
|
|
37
39
|
where Pr(i | j) = Probability of observing state "i" given state "j" was prepared.
|
|
@@ -71,7 +73,7 @@ class TensoredConfusionMatrices:
|
|
|
71
73
|
confusion_matrices: Sequence of confusion matrices, computed for qubit patterns present
|
|
72
74
|
in `measure_qubits`. A single confusion matrix is also accepted.
|
|
73
75
|
measure_qubits: Sequence of smaller qubit patterns, for which the confusion matrices
|
|
74
|
-
were computed. A single qubit pattern is also accepted. Note that
|
|
76
|
+
were computed. A single qubit pattern is also accepted. Note that
|
|
75
77
|
each qubit pattern is a sequence of qubits used to label the axes of
|
|
76
78
|
the corresponding confusion matrix.
|
|
77
79
|
repetitions: The number of repetitions that were used to estimate the confusion
|
|
@@ -173,13 +175,12 @@ class TensoredConfusionMatrices:
|
|
|
173
175
|
return in_vars + out_vars
|
|
174
176
|
|
|
175
177
|
def _confusion_matrix(self, qubits: Sequence['cirq.Qid']) -> np.ndarray:
|
|
176
|
-
ein_input = []
|
|
178
|
+
ein_input: List[np.ndarray | List[int]] = []
|
|
177
179
|
for qs, cm in zip(self.measure_qubits, self.confusion_matrices):
|
|
178
180
|
ein_input.extend([cm.reshape((2, 2) * len(qs)), self._get_vars(qs)])
|
|
179
181
|
ein_out = self._get_vars(qubits)
|
|
180
182
|
|
|
181
|
-
|
|
182
|
-
ret = np.einsum(*ein_input, ein_out).reshape((2 ** len(qubits),) * 2) # type: ignore
|
|
183
|
+
ret = np.einsum(*ein_input, ein_out).reshape((2 ** len(qubits),) * 2)
|
|
183
184
|
return ret / ret.sum(axis=1)
|
|
184
185
|
|
|
185
186
|
def confusion_matrix(self, qubits: Optional[Sequence['cirq.Qid']] = None) -> np.ndarray:
|
|
@@ -298,6 +299,70 @@ class TensoredConfusionMatrices:
|
|
|
298
299
|
) # pragma: no cover
|
|
299
300
|
return res.x
|
|
300
301
|
|
|
302
|
+
def readout_mitigation_pauli_uncorrelated(
|
|
303
|
+
self, qubits: Sequence['cirq.Qid'], measured_bitstrings: np.ndarray
|
|
304
|
+
) -> tuple[float, float]:
|
|
305
|
+
r"""Uncorrelated readout error mitigation for a multi-qubit Pauli operator.
|
|
306
|
+
|
|
307
|
+
This function scalably performs readout error mitigation on an arbitrary-length Pauli
|
|
308
|
+
operator. It is a reimplementation of https://github.com/eliottrosenberg/correlated_SPAM
|
|
309
|
+
but specialized to the case in which readout is uncorrelated. We require that the confusion
|
|
310
|
+
matrix is a tensor product of single-qubit confusion matrices. We then invert the confusion
|
|
311
|
+
matrix by inverting each of the $C^{(q)}$ Then, in a bit-by-bit fashion, we apply the
|
|
312
|
+
inverses of the single-site confusion matrices to the bits of the measured bitstring,
|
|
313
|
+
contract them with the single-site Pauli operator, and take the product over all of the
|
|
314
|
+
bits. This could be generalized to tensor product spaces that are larger than single qubits,
|
|
315
|
+
but the essential simplification is that each tensor product space is small, so that none of
|
|
316
|
+
the response matrices is exponentially large.
|
|
317
|
+
|
|
318
|
+
This can result in mitigated Pauli operators that are not in the range [-1, 1], but if
|
|
319
|
+
the readout error is indeed uncorrelated and well-characterized, then it should converge
|
|
320
|
+
to being within this range. Results are improved both by a more precise characterization
|
|
321
|
+
of the response matrices (whose statistical uncertainty is not accounted for in the error
|
|
322
|
+
propagation here) and by increasing the number of measured bitstrings.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
qubits: The qubits on which the Pauli operator acts.
|
|
326
|
+
measured_bitstrings: The experimentally measured bitstrings in the eigenbasis of the
|
|
327
|
+
Pauli operator. measured_bitstrings[i,j] is the ith bitstring, qubit j.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
The error-mitigated expectation value of the Pauli operator and its statistical
|
|
331
|
+
uncertainty (not including the uncertainty in the confusion matrices for now).
|
|
332
|
+
|
|
333
|
+
Raises:
|
|
334
|
+
NotImplementedError: If the confusion matrix is not a tensor product of single-qubit
|
|
335
|
+
confusion matrices for all of `qubits`.
|
|
336
|
+
"""
|
|
337
|
+
|
|
338
|
+
# in case given as an array of bools, convert to an array of ints:
|
|
339
|
+
measured_bitstrings = measured_bitstrings.astype(int)
|
|
340
|
+
|
|
341
|
+
# get all of the confusion matrices
|
|
342
|
+
cm_all = []
|
|
343
|
+
for qubit in qubits:
|
|
344
|
+
try:
|
|
345
|
+
idx = self.measure_qubits.index((qubit,))
|
|
346
|
+
except: # pragma: no cover
|
|
347
|
+
raise NotImplementedError(
|
|
348
|
+
"The response matrix must be a tensor product of single-qu"
|
|
349
|
+
+ f"bit response matrices, including that of qubit {qubit}."
|
|
350
|
+
)
|
|
351
|
+
cm_all.append(self.confusion_matrices[idx])
|
|
352
|
+
|
|
353
|
+
# get the correction matrices, assuming uncorrelated readout:
|
|
354
|
+
cminv_all = [np.linalg.inv(cm) for cm in cm_all]
|
|
355
|
+
|
|
356
|
+
# next, contract them with the single-qubit Pauli operators:
|
|
357
|
+
z = np.array([1, -1])
|
|
358
|
+
z_cminv_all = np.array([z @ cminv for cminv in cminv_all])
|
|
359
|
+
|
|
360
|
+
# finally, mitigate each bitstring:
|
|
361
|
+
z_mit_all_shots = np.prod(np.einsum("iji->ij", z_cminv_all[:, measured_bitstrings]), axis=0)
|
|
362
|
+
|
|
363
|
+
# return mean and statistical uncertainty:
|
|
364
|
+
return np.mean(z_mit_all_shots), np.std(z_mit_all_shots) / np.sqrt(len(measured_bitstrings))
|
|
365
|
+
|
|
301
366
|
def __repr__(self) -> str:
|
|
302
367
|
return (
|
|
303
368
|
f"cirq.TensoredConfusionMatrices("
|
|
@@ -13,12 +13,40 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import numpy as np
|
|
16
|
-
import cirq
|
|
17
16
|
import pytest
|
|
18
17
|
|
|
18
|
+
import cirq
|
|
19
|
+
from cirq.experiments.readout_confusion_matrix import TensoredConfusionMatrices
|
|
19
20
|
from cirq.experiments.single_qubit_readout_calibration_test import NoisySingleQubitReadoutSampler
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
def add_readout_error(
|
|
24
|
+
measurements: np.ndarray,
|
|
25
|
+
zero_errors: np.ndarray,
|
|
26
|
+
one_errors: np.ndarray,
|
|
27
|
+
rng: np.random.Generator,
|
|
28
|
+
) -> np.ndarray:
|
|
29
|
+
"""Add readout errors to measured (or simulated) bitstrings.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
measurements: The bitstrings to which we will add readout errors. measurements[i,j] is the
|
|
33
|
+
ith bitstring, qubit j.
|
|
34
|
+
zero_errors: zero_errors[i] is the probability of a 0->1 readout error on qubit i.
|
|
35
|
+
one_errors: one_errors[i] is the probability of a 1->0 readout error on qubit i.
|
|
36
|
+
rng: The pseudorandom number generator to use.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
New measurements but with readout errors added.
|
|
40
|
+
"""
|
|
41
|
+
num_bitstrs, n = measurements.shape
|
|
42
|
+
assert len(zero_errors) == len(one_errors) == n
|
|
43
|
+
# compute the probability that each bit is 1 after adding readout errors:
|
|
44
|
+
p1 = measurements * (1 - one_errors) + (1 - measurements) * zero_errors
|
|
45
|
+
r = rng.random((num_bitstrs, n))
|
|
46
|
+
noisy_measurements = r < p1
|
|
47
|
+
return noisy_measurements.astype(int)
|
|
48
|
+
|
|
49
|
+
|
|
22
50
|
def get_expected_cm(num_qubits: int, p0: float, p1: float):
|
|
23
51
|
expected_cm = np.zeros((2**num_qubits,) * 2)
|
|
24
52
|
for i in range(2**num_qubits):
|
|
@@ -159,3 +187,78 @@ def test_readout_confusion_matrix_repr_and_equality():
|
|
|
159
187
|
eq.add_equality_group(a, a)
|
|
160
188
|
eq.add_equality_group(b, b)
|
|
161
189
|
eq.add_equality_group(c, c)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _sample_ghz(n: int, repetitions: int, rng: np.random.Generator) -> np.ndarray:
|
|
193
|
+
"""Sample a GHZ state in the z basis.
|
|
194
|
+
Args:
|
|
195
|
+
n: The number of qubits.
|
|
196
|
+
repetitions: The number of repetitions.
|
|
197
|
+
rng: The pseudorandom number generator to use.
|
|
198
|
+
Returns:
|
|
199
|
+
An array of the measurement outcomes.
|
|
200
|
+
"""
|
|
201
|
+
return np.tile(rng.integers(0, 2, size=repetitions), (n, 1)).T
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _add_noise_and_mitigate_ghz(
|
|
205
|
+
n: int,
|
|
206
|
+
repetitions: int,
|
|
207
|
+
zero_errors: np.ndarray,
|
|
208
|
+
one_errors: np.ndarray,
|
|
209
|
+
rng: np.random.Generator | None = None,
|
|
210
|
+
) -> tuple[float, float, float, float]:
|
|
211
|
+
"""Add readout error to GHZ-like bitstrings and measure <ZZZ...> with and
|
|
212
|
+
without readout error mitigation.
|
|
213
|
+
Args:
|
|
214
|
+
n: The number of qubits.
|
|
215
|
+
repetitions: The number of repetitions.
|
|
216
|
+
zero_errors: zero_errors[i] is the probability of a 0->1 readout error on qubit i.
|
|
217
|
+
one_errors: one_errors[i] is the probability of a 1->0 readout error on qubit i.
|
|
218
|
+
rng: The pseudorandom number generator to use.
|
|
219
|
+
Returns:
|
|
220
|
+
A tuple of:
|
|
221
|
+
- The mitigated expectation value of <ZZZ...>
|
|
222
|
+
- The statistical uncertainty of the previous output
|
|
223
|
+
- The unmitigated expectation value of <ZZZ...>
|
|
224
|
+
- The statstical uncertainty of the previous output
|
|
225
|
+
"""
|
|
226
|
+
if rng is None:
|
|
227
|
+
rng = np.random.default_rng(0)
|
|
228
|
+
confusion_matrices = [
|
|
229
|
+
np.array([[1 - e0, e1], [e0, 1 - e1]]) for e0, e1 in zip(zero_errors, one_errors)
|
|
230
|
+
]
|
|
231
|
+
qubits = cirq.LineQubit.range(n)
|
|
232
|
+
tcm = TensoredConfusionMatrices(
|
|
233
|
+
confusion_matrices, [[q] for q in qubits], repetitions=0, timestamp=0.0
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
measurements = _sample_ghz(n, repetitions, rng)
|
|
237
|
+
noisy_measurements = add_readout_error(measurements, zero_errors, one_errors, rng)
|
|
238
|
+
# unmitigated:
|
|
239
|
+
p1 = np.mean(np.sum(noisy_measurements, axis=1) % 2)
|
|
240
|
+
z = 1 - 2 * np.mean(p1)
|
|
241
|
+
dz = 2 * np.sqrt(p1 * (1 - p1) / repetitions)
|
|
242
|
+
# return mitigated and unmitigated:
|
|
243
|
+
return (*tcm.readout_mitigation_pauli_uncorrelated(qubits, noisy_measurements), z, dz)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def test_uncorrelated_readout_mitigation_pauli():
|
|
247
|
+
n_all = np.arange(2, 35)
|
|
248
|
+
z_all_mit = []
|
|
249
|
+
dz_all_mit = []
|
|
250
|
+
z_all_raw = []
|
|
251
|
+
dz_all_raw = []
|
|
252
|
+
repetitions = 10_000
|
|
253
|
+
for n in n_all:
|
|
254
|
+
e0 = np.ones(n) * 0.005
|
|
255
|
+
e1 = np.ones(n) * 0.03
|
|
256
|
+
z_mit, dz_mit, z_raw, dz_raw = _add_noise_and_mitigate_ghz(n, repetitions, e0, e1)
|
|
257
|
+
z_all_mit.append(z_mit)
|
|
258
|
+
dz_all_mit.append(dz_mit)
|
|
259
|
+
z_all_raw.append(z_raw)
|
|
260
|
+
dz_all_raw.append(dz_raw)
|
|
261
|
+
|
|
262
|
+
for n, z, dz in zip(n_all, z_all_mit, dz_all_mit):
|
|
263
|
+
ideal = 1.0 if n % 2 == 0 else 0.0
|
|
264
|
+
assert np.isclose(z, ideal, atol=4 * dz)
|
|
@@ -14,15 +14,16 @@
|
|
|
14
14
|
"""Single qubit readout experiments using parallel or isolated statistics."""
|
|
15
15
|
import dataclasses
|
|
16
16
|
import time
|
|
17
|
-
from typing import Any, Dict, Iterable, List, Optional, TYPE_CHECKING
|
|
17
|
+
from typing import Any, cast, Dict, Iterable, List, Optional, TYPE_CHECKING
|
|
18
18
|
|
|
19
|
-
import sympy
|
|
20
|
-
import numpy as np
|
|
21
19
|
import matplotlib.pyplot as plt
|
|
20
|
+
import numpy as np
|
|
21
|
+
import sympy
|
|
22
|
+
|
|
22
23
|
import cirq.vis.heatmap as cirq_heatmap
|
|
23
24
|
import cirq.vis.histogram as cirq_histogram
|
|
24
|
-
from cirq.devices import grid_qubit
|
|
25
25
|
from cirq import circuits, ops, study
|
|
26
|
+
from cirq.devices import grid_qubit
|
|
26
27
|
|
|
27
28
|
if TYPE_CHECKING:
|
|
28
29
|
import cirq
|
|
@@ -77,8 +78,9 @@ class SingleQubitReadoutCalibrationResult:
|
|
|
77
78
|
"""
|
|
78
79
|
|
|
79
80
|
if axs is None:
|
|
80
|
-
_,
|
|
81
|
-
|
|
81
|
+
_, axs_v = plt.subplots(1, 2, dpi=200, facecolor='white', figsize=(12, 4))
|
|
82
|
+
axs_v = cast(np.ndarray, axs_v)
|
|
83
|
+
axs = cast(tuple[plt.Axes, plt.Axes], (axs_v[0], axs_v[1]))
|
|
82
84
|
else:
|
|
83
85
|
if (
|
|
84
86
|
not isinstance(axs, (tuple, list, np.ndarray))
|
|
@@ -12,16 +12,15 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import Any, Optional, Sequence, TYPE_CHECKING, cast
|
|
16
|
-
|
|
17
15
|
import warnings
|
|
16
|
+
from typing import Any, cast, Optional, Sequence, TYPE_CHECKING
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
18
19
|
import pandas as pd
|
|
19
20
|
import sympy
|
|
20
21
|
from matplotlib import pyplot as plt
|
|
21
|
-
import numpy as np
|
|
22
|
-
|
|
23
22
|
|
|
24
|
-
from cirq import circuits, ops, study, value
|
|
23
|
+
from cirq import _import, circuits, ops, study, value
|
|
25
24
|
from cirq._compat import proper_repr
|
|
26
25
|
|
|
27
26
|
if TYPE_CHECKING:
|
|
@@ -13,31 +13,35 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""Provides functions for running and analyzing two-qubit XEB experiments."""
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
import functools
|
|
17
|
+
import itertools
|
|
18
18
|
from dataclasses import dataclass
|
|
19
19
|
from types import MappingProxyType
|
|
20
|
-
import
|
|
21
|
-
import functools
|
|
20
|
+
from typing import Any, cast, Dict, Mapping, Optional, Sequence, Tuple, TYPE_CHECKING
|
|
22
21
|
|
|
23
|
-
from matplotlib import pyplot as plt
|
|
24
22
|
import networkx as nx
|
|
25
23
|
import numpy as np
|
|
26
24
|
import pandas as pd
|
|
25
|
+
from matplotlib import pyplot as plt
|
|
27
26
|
|
|
28
27
|
from cirq import ops, value, vis
|
|
29
|
-
from cirq.
|
|
30
|
-
from cirq.experiments.xeb_fitting import benchmark_2q_xeb_fidelities
|
|
31
|
-
from cirq.experiments.xeb_fitting import fit_exponential_decays, exponential_decay
|
|
28
|
+
from cirq._compat import cached_method
|
|
32
29
|
from cirq.experiments import random_quantum_circuit_generation as rqcg
|
|
33
30
|
from cirq.experiments.qubit_characterizations import (
|
|
34
|
-
ParallelRandomizedBenchmarkingResult,
|
|
35
31
|
parallel_single_qubit_randomized_benchmarking,
|
|
32
|
+
ParallelRandomizedBenchmarkingResult,
|
|
36
33
|
)
|
|
34
|
+
from cirq.experiments.xeb_fitting import (
|
|
35
|
+
benchmark_2q_xeb_fidelities,
|
|
36
|
+
exponential_decay,
|
|
37
|
+
fit_exponential_decays,
|
|
38
|
+
)
|
|
39
|
+
from cirq.experiments.xeb_sampling import sample_2q_xeb_circuits
|
|
37
40
|
from cirq.qis import noise_utils
|
|
38
|
-
from cirq._compat import cached_method
|
|
39
41
|
|
|
40
42
|
if TYPE_CHECKING:
|
|
43
|
+
import multiprocessing
|
|
44
|
+
|
|
41
45
|
import cirq
|
|
42
46
|
|
|
43
47
|
|
|
@@ -52,6 +56,46 @@ def _manhattan_distance(qubit1: 'cirq.GridQubit', qubit2: 'cirq.GridQubit') -> i
|
|
|
52
56
|
return abs(qubit1.row - qubit2.row) + abs(qubit1.col - qubit2.col)
|
|
53
57
|
|
|
54
58
|
|
|
59
|
+
def qubits_and_pairs(
|
|
60
|
+
sampler: 'cirq.Sampler',
|
|
61
|
+
qubits: Optional[Sequence['cirq.GridQubit']] = None,
|
|
62
|
+
pairs: Optional[Sequence[tuple['cirq.GridQubit', 'cirq.GridQubit']]] = None,
|
|
63
|
+
) -> Tuple[Sequence['cirq.GridQubit'], Sequence[tuple['cirq.GridQubit', 'cirq.GridQubit']]]:
|
|
64
|
+
"""Extract qubits and pairs from sampler.
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
If qubits are not provided, then they are extracted from the pairs (if given) or the sampler.
|
|
68
|
+
If pairs are not provided then all pairs of adjacent qubits are used.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
sampler: The quantum engine or simulator to run the circuits.
|
|
72
|
+
qubits: Optional list of qubits.
|
|
73
|
+
pairs: Optional list of pair to use.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
- Qubits to use.
|
|
77
|
+
- Pairs of qubits to use.
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
ValueError: If qubits are not specified and can't be deduced from other arguments.
|
|
81
|
+
"""
|
|
82
|
+
if qubits is None:
|
|
83
|
+
if pairs is None:
|
|
84
|
+
qubits = _grid_qubits_for_sampler(sampler)
|
|
85
|
+
if qubits is None:
|
|
86
|
+
raise ValueError("Couldn't determine qubits from sampler. Please specify them.")
|
|
87
|
+
else:
|
|
88
|
+
qubits_set = set(itertools.chain(*pairs))
|
|
89
|
+
qubits = list(qubits_set)
|
|
90
|
+
|
|
91
|
+
if pairs is None:
|
|
92
|
+
pairs = [
|
|
93
|
+
pair for pair in itertools.combinations(qubits, 2) if _manhattan_distance(*pair) == 1
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
return qubits, pairs
|
|
97
|
+
|
|
98
|
+
|
|
55
99
|
@dataclass(frozen=True)
|
|
56
100
|
class TwoQubitXEBResult:
|
|
57
101
|
"""Results from an XEB experiment."""
|
|
@@ -143,7 +187,9 @@ class TwoQubitXEBResult:
|
|
|
143
187
|
|
|
144
188
|
def xeb_fidelity(self, q0: 'cirq.GridQubit', q1: 'cirq.GridQubit') -> float:
|
|
145
189
|
"""Return the XEB fidelity of a qubit pair."""
|
|
146
|
-
return
|
|
190
|
+
return noise_utils.decay_constant_to_xeb_fidelity(
|
|
191
|
+
self._record(q0, q1).layer_fid, num_qubits=2
|
|
192
|
+
)
|
|
147
193
|
|
|
148
194
|
def xeb_error(self, q0: 'cirq.GridQubit', q1: 'cirq.GridQubit') -> float:
|
|
149
195
|
"""Return the XEB error of a qubit pair."""
|
|
@@ -177,8 +223,7 @@ class TwoQubitXEBResult:
|
|
|
177
223
|
"""Return the Pauli error of all qubit pairs."""
|
|
178
224
|
return {
|
|
179
225
|
pair: noise_utils.decay_constant_to_pauli_error(
|
|
180
|
-
|
|
181
|
-
num_qubits=2,
|
|
226
|
+
self._record(*pair).layer_fid, num_qubits=2
|
|
182
227
|
)
|
|
183
228
|
for pair in self.all_qubit_pairs
|
|
184
229
|
}
|
|
@@ -347,19 +392,23 @@ class InferredXEBResult:
|
|
|
347
392
|
return ax
|
|
348
393
|
|
|
349
394
|
|
|
350
|
-
def
|
|
395
|
+
def parallel_xeb_workflow(
|
|
351
396
|
sampler: 'cirq.Sampler',
|
|
352
397
|
qubits: Optional[Sequence['cirq.GridQubit']] = None,
|
|
353
398
|
entangling_gate: 'cirq.Gate' = ops.CZ,
|
|
354
399
|
n_repetitions: int = 10**4,
|
|
355
400
|
n_combinations: int = 10,
|
|
356
401
|
n_circuits: int = 20,
|
|
357
|
-
cycle_depths: Sequence[int] =
|
|
402
|
+
cycle_depths: Sequence[int] = (5, 25, 50, 100, 200, 300),
|
|
358
403
|
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
|
|
359
404
|
ax: Optional[plt.Axes] = None,
|
|
405
|
+
pairs: Optional[Sequence[tuple['cirq.GridQubit', 'cirq.GridQubit']]] = None,
|
|
406
|
+
pool: Optional['multiprocessing.pool.Pool'] = None,
|
|
407
|
+
batch_size: int = 9,
|
|
408
|
+
tags: Sequence[Any] = (),
|
|
360
409
|
**plot_kwargs,
|
|
361
|
-
) ->
|
|
362
|
-
"""A
|
|
410
|
+
) -> Tuple[pd.DataFrame, Sequence['cirq.Circuit'], pd.DataFrame]:
|
|
411
|
+
"""A utility method that runs the full XEB workflow.
|
|
363
412
|
|
|
364
413
|
Args:
|
|
365
414
|
sampler: The quantum engine or simulator to run the circuits.
|
|
@@ -372,24 +421,29 @@ def parallel_two_qubit_xeb(
|
|
|
372
421
|
random_state: The random state to use.
|
|
373
422
|
ax: the plt.Axes to plot the device layout on. If not given,
|
|
374
423
|
no plot is created.
|
|
424
|
+
pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
|
|
425
|
+
pool: An optional multiprocessing pool.
|
|
426
|
+
batch_size: We call `run_batch` on the sampler, which can speed up execution in certain
|
|
427
|
+
environments. The number of (circuit, cycle_depth) tasks to be run in each batch
|
|
428
|
+
is given by this number.
|
|
429
|
+
tags: Tags to add to two qubit operations.
|
|
375
430
|
**plot_kwargs: Arguments to be passed to 'plt.Axes.plot'.
|
|
376
431
|
|
|
377
432
|
Returns:
|
|
378
|
-
A
|
|
433
|
+
- A DataFrame with columns 'cycle_depth' and 'fidelity'.
|
|
434
|
+
- The circuits used to perform XEB.
|
|
435
|
+
- A pandas dataframe with index given by ['circuit_i', 'cycle_depth'].
|
|
436
|
+
Columns always include "sampled_probs". If `combinations_by_layer` is
|
|
437
|
+
not `None` and you are doing parallel XEB, additional metadata columns
|
|
438
|
+
will be attached to the returned DataFrame.
|
|
379
439
|
|
|
380
440
|
Raises:
|
|
381
441
|
ValueError: If qubits are not specified and the sampler has no device.
|
|
382
442
|
"""
|
|
383
443
|
rs = value.parse_random_state(random_state)
|
|
384
444
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if qubits is None:
|
|
388
|
-
raise ValueError("Couldn't determine qubits from sampler. Please specify them.")
|
|
389
|
-
|
|
390
|
-
graph = nx.Graph(
|
|
391
|
-
pair for pair in itertools.combinations(qubits, 2) if _manhattan_distance(*pair) == 1
|
|
392
|
-
)
|
|
445
|
+
qubits, pairs = qubits_and_pairs(sampler, qubits, pairs)
|
|
446
|
+
graph = nx.Graph(pairs)
|
|
393
447
|
|
|
394
448
|
if ax is not None:
|
|
395
449
|
nx.draw_networkx(graph, pos={q: (q.row, q.col) for q in qubits}, ax=ax)
|
|
@@ -397,7 +451,11 @@ def parallel_two_qubit_xeb(
|
|
|
397
451
|
ax.plot(**plot_kwargs)
|
|
398
452
|
|
|
399
453
|
circuit_library = rqcg.generate_library_of_2q_circuits(
|
|
400
|
-
n_library_circuits=n_circuits,
|
|
454
|
+
n_library_circuits=n_circuits,
|
|
455
|
+
two_qubit_gate=entangling_gate,
|
|
456
|
+
random_state=rs,
|
|
457
|
+
max_cycle_depth=max(cycle_depths),
|
|
458
|
+
tags=tags,
|
|
401
459
|
)
|
|
402
460
|
|
|
403
461
|
combs_by_layer = rqcg.get_random_combinations_for_device(
|
|
@@ -414,12 +472,70 @@ def parallel_two_qubit_xeb(
|
|
|
414
472
|
combinations_by_layer=combs_by_layer,
|
|
415
473
|
shuffle=rs,
|
|
416
474
|
repetitions=n_repetitions,
|
|
475
|
+
batch_size=batch_size,
|
|
417
476
|
)
|
|
418
477
|
|
|
419
478
|
fids = benchmark_2q_xeb_fidelities(
|
|
420
|
-
sampled_df=sampled_df, circuits=circuit_library, cycle_depths=cycle_depths
|
|
479
|
+
sampled_df=sampled_df, circuits=circuit_library, cycle_depths=cycle_depths, pool=pool
|
|
421
480
|
)
|
|
422
481
|
|
|
482
|
+
return fids, circuit_library, sampled_df
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def parallel_two_qubit_xeb(
|
|
486
|
+
sampler: 'cirq.Sampler',
|
|
487
|
+
qubits: Optional[Sequence['cirq.GridQubit']] = None,
|
|
488
|
+
entangling_gate: 'cirq.Gate' = ops.CZ,
|
|
489
|
+
n_repetitions: int = 10**4,
|
|
490
|
+
n_combinations: int = 10,
|
|
491
|
+
n_circuits: int = 20,
|
|
492
|
+
cycle_depths: Sequence[int] = (5, 25, 50, 100, 200, 300),
|
|
493
|
+
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
|
|
494
|
+
ax: Optional[plt.Axes] = None,
|
|
495
|
+
pairs: Optional[Sequence[tuple['cirq.GridQubit', 'cirq.GridQubit']]] = None,
|
|
496
|
+
batch_size: int = 9,
|
|
497
|
+
tags: Sequence[Any] = (),
|
|
498
|
+
**plot_kwargs,
|
|
499
|
+
) -> TwoQubitXEBResult:
|
|
500
|
+
"""A convenience method that runs the full XEB workflow.
|
|
501
|
+
|
|
502
|
+
Args:
|
|
503
|
+
sampler: The quantum engine or simulator to run the circuits.
|
|
504
|
+
qubits: Qubits under test. If none, uses all qubits on the sampler's device.
|
|
505
|
+
entangling_gate: The entangling gate to use.
|
|
506
|
+
n_repetitions: The number of repetitions to use.
|
|
507
|
+
n_combinations: The number of combinations to generate.
|
|
508
|
+
n_circuits: The number of circuits to generate.
|
|
509
|
+
cycle_depths: The cycle depths to use.
|
|
510
|
+
random_state: The random state to use.
|
|
511
|
+
ax: the plt.Axes to plot the device layout on. If not given,
|
|
512
|
+
no plot is created.
|
|
513
|
+
pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
|
|
514
|
+
batch_size: We call `run_batch` on the sampler, which can speed up execution in certain
|
|
515
|
+
environments. The number of (circuit, cycle_depth) tasks to be run in each batch
|
|
516
|
+
is given by this number.
|
|
517
|
+
tags: Tags to add to two qubit operations.
|
|
518
|
+
**plot_kwargs: Arguments to be passed to 'plt.Axes.plot'.
|
|
519
|
+
Returns:
|
|
520
|
+
A TwoQubitXEBResult object representing the results of the experiment.
|
|
521
|
+
Raises:
|
|
522
|
+
ValueError: If qubits are not specified and the sampler has no device.
|
|
523
|
+
"""
|
|
524
|
+
fids, *_ = parallel_xeb_workflow(
|
|
525
|
+
sampler=sampler,
|
|
526
|
+
qubits=qubits,
|
|
527
|
+
pairs=pairs,
|
|
528
|
+
entangling_gate=entangling_gate,
|
|
529
|
+
n_repetitions=n_repetitions,
|
|
530
|
+
n_combinations=n_combinations,
|
|
531
|
+
n_circuits=n_circuits,
|
|
532
|
+
cycle_depths=cycle_depths,
|
|
533
|
+
random_state=random_state,
|
|
534
|
+
ax=ax,
|
|
535
|
+
batch_size=batch_size,
|
|
536
|
+
tags=tags,
|
|
537
|
+
**plot_kwargs,
|
|
538
|
+
)
|
|
423
539
|
return TwoQubitXEBResult(fit_exponential_decays(fids))
|
|
424
540
|
|
|
425
541
|
|
|
@@ -432,9 +548,12 @@ def run_rb_and_xeb(
|
|
|
432
548
|
np.logspace(np.log10(5), np.log10(1000), 5, dtype=int)
|
|
433
549
|
),
|
|
434
550
|
entangling_gate: 'cirq.Gate' = ops.CZ,
|
|
435
|
-
depths_xeb: Sequence[int] =
|
|
551
|
+
depths_xeb: Sequence[int] = (5, 25, 50, 100, 200, 300),
|
|
436
552
|
xeb_combinations: int = 10,
|
|
437
553
|
random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
|
|
554
|
+
pairs: Optional[Sequence[tuple['cirq.GridQubit', 'cirq.GridQubit']]] = None,
|
|
555
|
+
batch_size: int = 9,
|
|
556
|
+
tags: Sequence[Any] = (),
|
|
438
557
|
) -> InferredXEBResult:
|
|
439
558
|
"""A convenience method that runs both RB and XEB workflows.
|
|
440
559
|
|
|
@@ -448,6 +567,11 @@ def run_rb_and_xeb(
|
|
|
448
567
|
depths_xeb: The cycle depths to use for XEB.
|
|
449
568
|
xeb_combinations: The number of combinations to generate for XEB.
|
|
450
569
|
random_state: The random state to use.
|
|
570
|
+
pairs: Pairs to use. If not specified, use all pairs between adjacent qubits.
|
|
571
|
+
batch_size: We call `run_batch` on the sampler, which can speed up execution in certain
|
|
572
|
+
environments. The number of (circuit, cycle_depth) tasks to be run in each batch
|
|
573
|
+
is given by this number.
|
|
574
|
+
tags: Tags to add to two qubit operations.
|
|
451
575
|
|
|
452
576
|
Returns:
|
|
453
577
|
An InferredXEBResult object representing the results of the experiment.
|
|
@@ -456,10 +580,7 @@ def run_rb_and_xeb(
|
|
|
456
580
|
ValueError: If qubits are not specified and the sampler has no device.
|
|
457
581
|
"""
|
|
458
582
|
|
|
459
|
-
|
|
460
|
-
qubits = _grid_qubits_for_sampler(sampler)
|
|
461
|
-
if qubits is None:
|
|
462
|
-
raise ValueError("Couldn't determine qubits from sampler. Please specify them.")
|
|
583
|
+
qubits, pairs = qubits_and_pairs(sampler, qubits, pairs)
|
|
463
584
|
|
|
464
585
|
rb = parallel_single_qubit_randomized_benchmarking(
|
|
465
586
|
sampler=sampler,
|
|
@@ -472,12 +593,15 @@ def run_rb_and_xeb(
|
|
|
472
593
|
xeb = parallel_two_qubit_xeb(
|
|
473
594
|
sampler=sampler,
|
|
474
595
|
qubits=qubits,
|
|
596
|
+
pairs=pairs,
|
|
475
597
|
entangling_gate=entangling_gate,
|
|
476
598
|
n_repetitions=repetitions,
|
|
477
599
|
n_circuits=num_circuits,
|
|
478
600
|
cycle_depths=depths_xeb,
|
|
479
601
|
n_combinations=xeb_combinations,
|
|
480
602
|
random_state=random_state,
|
|
603
|
+
batch_size=batch_size,
|
|
604
|
+
tags=tags,
|
|
481
605
|
)
|
|
482
606
|
|
|
483
607
|
return InferredXEBResult(rb, xeb)
|