cirq-core 1.5.0.dev20250409222543__py3-none-any.whl → 1.6.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 +16 -17
- cirq/_compat.py +21 -20
- cirq/_compat_test.py +14 -34
- cirq/_doc.py +4 -2
- cirq/_import.py +8 -6
- cirq/_import_test.py +4 -2
- cirq/_version.py +6 -6
- cirq/_version_test.py +2 -2
- cirq/circuits/_block_diagram_drawer.py +11 -10
- cirq/circuits/_block_diagram_drawer_test.py +8 -6
- cirq/circuits/_box_drawing_character_data.py +8 -8
- cirq/circuits/_box_drawing_character_data_test.py +3 -1
- cirq/circuits/_bucket_priority_queue.py +9 -7
- cirq/circuits/_bucket_priority_queue_test.py +22 -20
- cirq/circuits/circuit.py +248 -172
- cirq/circuits/circuit_operation.py +73 -83
- cirq/circuits/circuit_operation_test.py +128 -90
- cirq/circuits/circuit_test.py +211 -151
- cirq/circuits/frozen_circuit.py +23 -60
- cirq/circuits/frozen_circuit_test.py +31 -8
- cirq/circuits/insert_strategy.py +7 -5
- cirq/circuits/insert_strategy_test.py +4 -2
- cirq/circuits/moment.py +88 -40
- cirq/circuits/moment_test.py +128 -51
- cirq/circuits/optimization_pass.py +5 -5
- cirq/circuits/optimization_pass_test.py +10 -10
- cirq/circuits/qasm_output.py +11 -11
- cirq/circuits/qasm_output_test.py +25 -22
- cirq/circuits/text_diagram_drawer.py +23 -38
- cirq/circuits/text_diagram_drawer_test.py +19 -17
- cirq/conftest.py +4 -3
- cirq/contrib/__init__.py +4 -4
- cirq/contrib/acquaintance/__init__.py +1 -1
- cirq/contrib/acquaintance/bipartite.py +5 -8
- cirq/contrib/acquaintance/bipartite_test.py +18 -13
- cirq/contrib/acquaintance/devices.py +2 -2
- cirq/contrib/acquaintance/devices_test.py +5 -3
- cirq/contrib/acquaintance/executor.py +5 -5
- cirq/contrib/acquaintance/executor_test.py +13 -9
- cirq/contrib/acquaintance/gates.py +18 -28
- cirq/contrib/acquaintance/gates_test.py +24 -20
- cirq/contrib/acquaintance/inspection_utils.py +8 -4
- cirq/contrib/acquaintance/inspection_utils_test.py +4 -2
- cirq/contrib/acquaintance/mutation_utils.py +4 -4
- cirq/contrib/acquaintance/mutation_utils_test.py +4 -2
- cirq/contrib/acquaintance/optimizers.py +4 -4
- cirq/contrib/acquaintance/optimizers_test.py +4 -1
- cirq/contrib/acquaintance/permutation.py +15 -27
- cirq/contrib/acquaintance/permutation_test.py +26 -17
- cirq/contrib/acquaintance/shift.py +4 -4
- cirq/contrib/acquaintance/shift_swap_network.py +4 -4
- cirq/contrib/acquaintance/shift_swap_network_test.py +9 -6
- cirq/contrib/acquaintance/shift_test.py +8 -6
- cirq/contrib/acquaintance/strategies/cubic.py +2 -2
- cirq/contrib/acquaintance/strategies/cubic_test.py +4 -2
- cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
- cirq/contrib/acquaintance/strategies/quartic_paired_test.py +10 -6
- cirq/contrib/acquaintance/testing.py +2 -0
- cirq/contrib/acquaintance/topological_sort.py +2 -2
- cirq/contrib/acquaintance/topological_sort_test.py +3 -1
- cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
- cirq/contrib/bayesian_network/bayesian_network_gate_test.py +14 -9
- cirq/contrib/circuitdag/circuit_dag.py +4 -4
- cirq/contrib/circuitdag/circuit_dag_test.py +17 -15
- cirq/contrib/custom_simulators/custom_state_simulator.py +5 -5
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +22 -17
- cirq/contrib/graph_device/graph_device.py +12 -11
- cirq/contrib/graph_device/graph_device_test.py +18 -14
- cirq/contrib/graph_device/hypergraph.py +16 -14
- cirq/contrib/graph_device/hypergraph_test.py +13 -11
- cirq/contrib/graph_device/uniform_graph_device.py +6 -4
- cirq/contrib/graph_device/uniform_graph_device_test.py +11 -3
- cirq/contrib/hacks/disable_validation.py +6 -1
- cirq/contrib/hacks/disable_validation_test.py +3 -1
- cirq/contrib/json.py +31 -5
- cirq/contrib/json_test.py +6 -3
- cirq/contrib/json_test_data/DampedReadoutNoiseModel.json +12 -0
- cirq/contrib/json_test_data/DampedReadoutNoiseModel.repr +4 -0
- cirq/contrib/json_test_data/DepolarizingNoiseModel.json +12 -0
- cirq/contrib/json_test_data/DepolarizingNoiseModel.repr +4 -0
- cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.json +6 -0
- cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.repr +1 -0
- cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.json +5 -0
- cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.repr +1 -0
- cirq/contrib/json_test_data/ReadoutNoiseModel.json +12 -0
- cirq/contrib/json_test_data/ReadoutNoiseModel.repr +4 -0
- cirq/contrib/json_test_data/__init__.py +17 -0
- cirq/contrib/json_test_data/spec.py +32 -0
- cirq/contrib/noise_models/noise_models.py +119 -5
- cirq/contrib/noise_models/noise_models_test.py +37 -9
- cirq/contrib/paulistring/clifford_optimize.py +6 -4
- cirq/contrib/paulistring/clifford_optimize_test.py +6 -5
- cirq/contrib/paulistring/clifford_target_gateset.py +10 -10
- cirq/contrib/paulistring/clifford_target_gateset_test.py +13 -11
- cirq/contrib/paulistring/optimize.py +2 -0
- cirq/contrib/paulistring/optimize_test.py +4 -3
- cirq/contrib/paulistring/pauli_string_dag.py +2 -0
- cirq/contrib/paulistring/pauli_string_dag_test.py +3 -1
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +255 -120
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +398 -19
- cirq/contrib/paulistring/pauli_string_optimize.py +7 -1
- cirq/contrib/paulistring/pauli_string_optimize_test.py +5 -3
- cirq/contrib/paulistring/recombine.py +6 -4
- cirq/contrib/paulistring/recombine_test.py +3 -1
- cirq/contrib/paulistring/separate.py +9 -6
- cirq/contrib/paulistring/separate_test.py +3 -1
- cirq/contrib/qasm_import/_lexer.py +3 -2
- cirq/contrib/qasm_import/_lexer_test.py +49 -13
- cirq/contrib/qasm_import/_parser.py +547 -83
- cirq/contrib/qasm_import/_parser_test.py +988 -97
- cirq/contrib/qasm_import/exception.py +2 -0
- cirq/contrib/qasm_import/qasm.py +8 -2
- cirq/contrib/qasm_import/qasm_test.py +7 -4
- cirq/contrib/qcircuit/qcircuit_diagram_info.py +5 -5
- cirq/contrib/qcircuit/qcircuit_diagram_info_test.py +4 -1
- cirq/contrib/qcircuit/qcircuit_pdf.py +7 -3
- cirq/contrib/qcircuit/qcircuit_pdf_test.py +3 -1
- cirq/contrib/qcircuit/qcircuit_test.py +10 -8
- cirq/contrib/quantum_volume/quantum_volume.py +31 -27
- cirq/contrib/quantum_volume/quantum_volume_test.py +19 -16
- cirq/contrib/quimb/density_matrix.py +15 -14
- cirq/contrib/quimb/density_matrix_test.py +10 -7
- cirq/contrib/quimb/grid_circuits.py +5 -2
- cirq/contrib/quimb/grid_circuits_test.py +3 -0
- cirq/contrib/quimb/mps_simulator.py +20 -20
- cirq/contrib/quimb/mps_simulator_test.py +3 -0
- cirq/contrib/quimb/state_vector.py +12 -11
- cirq/contrib/quimb/state_vector_test.py +3 -0
- cirq/contrib/quirk/export_to_quirk.py +5 -3
- cirq/contrib/quirk/export_to_quirk_test.py +18 -16
- cirq/contrib/quirk/linearize_circuit.py +2 -0
- cirq/contrib/quirk/quirk_gate.py +18 -17
- cirq/contrib/routing/device.py +5 -3
- cirq/contrib/routing/device_test.py +2 -0
- cirq/contrib/routing/greedy.py +10 -21
- cirq/contrib/routing/greedy_test.py +4 -2
- cirq/contrib/routing/initialization.py +2 -2
- cirq/contrib/routing/initialization_test.py +5 -3
- cirq/contrib/routing/router.py +9 -5
- cirq/contrib/routing/router_test.py +2 -0
- cirq/contrib/routing/swap_network.py +3 -3
- cirq/contrib/routing/swap_network_test.py +3 -1
- cirq/contrib/routing/utils.py +2 -2
- cirq/contrib/routing/utils_test.py +3 -0
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +15 -9
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +3 -0
- cirq/contrib/svg/svg.py +3 -3
- cirq/contrib/svg/svg_test.py +8 -5
- cirq/devices/device.py +4 -4
- cirq/devices/device_test.py +7 -4
- cirq/devices/grid_device_metadata.py +10 -10
- cirq/devices/grid_device_metadata_test.py +3 -0
- cirq/devices/grid_qubit.py +29 -21
- cirq/devices/grid_qubit_test.py +3 -0
- cirq/devices/insertion_noise_model.py +7 -7
- cirq/devices/insertion_noise_model_test.py +7 -5
- cirq/devices/line_qubit.py +13 -13
- cirq/devices/line_qubit_test.py +2 -0
- cirq/devices/named_topologies.py +18 -29
- cirq/devices/named_topologies_test.py +13 -10
- cirq/devices/noise_model.py +3 -3
- cirq/devices/noise_model_test.py +19 -15
- cirq/devices/noise_properties.py +15 -6
- cirq/devices/noise_properties_test.py +34 -3
- cirq/devices/noise_utils.py +11 -9
- cirq/devices/noise_utils_test.py +2 -0
- cirq/devices/superconducting_qubits_noise_properties.py +23 -22
- cirq/devices/superconducting_qubits_noise_properties_test.py +6 -6
- cirq/devices/thermal_noise_model.py +107 -37
- cirq/devices/thermal_noise_model_test.py +21 -0
- cirq/devices/unconstrained_device.py +5 -3
- cirq/devices/unconstrained_device_test.py +2 -0
- cirq/experiments/__init__.py +4 -2
- cirq/experiments/benchmarking/__init__.py +17 -0
- cirq/experiments/benchmarking/parallel_xeb.py +677 -0
- cirq/experiments/benchmarking/parallel_xeb_test.py +447 -0
- cirq/experiments/fidelity_estimation.py +14 -8
- cirq/experiments/fidelity_estimation_test.py +3 -0
- cirq/experiments/n_qubit_tomography.py +17 -16
- cirq/experiments/n_qubit_tomography_test.py +8 -5
- cirq/experiments/purity_estimation.py +2 -0
- cirq/experiments/purity_estimation_test.py +2 -0
- cirq/experiments/qubit_characterizations.py +207 -103
- cirq/experiments/qubit_characterizations_test.py +40 -12
- cirq/experiments/random_quantum_circuit_generation.py +56 -70
- cirq/experiments/random_quantum_circuit_generation_test.py +11 -8
- cirq/experiments/readout_confusion_matrix.py +24 -22
- cirq/experiments/readout_confusion_matrix_test.py +2 -0
- cirq/experiments/single_qubit_readout_calibration.py +30 -15
- cirq/experiments/single_qubit_readout_calibration_test.py +5 -2
- cirq/experiments/t1_decay_experiment.py +9 -7
- cirq/experiments/t1_decay_experiment_test.py +13 -11
- cirq/experiments/t2_decay_experiment.py +16 -13
- cirq/experiments/t2_decay_experiment_test.py +2 -0
- cirq/experiments/two_qubit_xeb.py +64 -57
- cirq/experiments/two_qubit_xeb_test.py +10 -6
- cirq/experiments/xeb_fitting.py +39 -35
- cirq/experiments/xeb_sampling.py +37 -44
- cirq/experiments/xeb_sampling_test.py +3 -0
- cirq/experiments/xeb_simulation.py +14 -10
- cirq/experiments/xeb_simulation_test.py +5 -5
- cirq/experiments/z_phase_calibration.py +32 -29
- cirq/experiments/z_phase_calibration_test.py +3 -4
- cirq/interop/quirk/cells/__init__.py +1 -1
- cirq/interop/quirk/cells/all_cells.py +7 -2
- cirq/interop/quirk/cells/arithmetic_cells.py +29 -41
- cirq/interop/quirk/cells/arithmetic_cells_test.py +17 -14
- cirq/interop/quirk/cells/cell.py +19 -28
- cirq/interop/quirk/cells/cell_test.py +3 -0
- cirq/interop/quirk/cells/composite_cell.py +13 -28
- cirq/interop/quirk/cells/composite_cell_test.py +2 -0
- cirq/interop/quirk/cells/control_cells.py +15 -15
- cirq/interop/quirk/cells/control_cells_test.py +7 -5
- cirq/interop/quirk/cells/frequency_space_cells.py +4 -3
- cirq/interop/quirk/cells/frequency_space_cells_test.py +3 -1
- cirq/interop/quirk/cells/ignored_cells.py +3 -0
- cirq/interop/quirk/cells/ignored_cells_test.py +3 -1
- cirq/interop/quirk/cells/input_cells.py +7 -5
- cirq/interop/quirk/cells/input_cells_test.py +7 -5
- cirq/interop/quirk/cells/input_rotation_cells.py +15 -13
- cirq/interop/quirk/cells/input_rotation_cells_test.py +9 -7
- cirq/interop/quirk/cells/measurement_cells.py +5 -2
- cirq/interop/quirk/cells/measurement_cells_test.py +3 -1
- cirq/interop/quirk/cells/parse.py +22 -23
- cirq/interop/quirk/cells/parse_test.py +12 -10
- cirq/interop/quirk/cells/qubit_permutation_cells.py +5 -3
- cirq/interop/quirk/cells/qubit_permutation_cells_test.py +9 -7
- cirq/interop/quirk/cells/scalar_cells.py +4 -1
- cirq/interop/quirk/cells/scalar_cells_test.py +3 -1
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +5 -2
- cirq/interop/quirk/cells/single_qubit_rotation_cells_test.py +5 -3
- cirq/interop/quirk/cells/swap_cell.py +8 -6
- cirq/interop/quirk/cells/swap_cell_test.py +6 -4
- cirq/interop/quirk/cells/testing.py +6 -6
- cirq/interop/quirk/cells/testing_test.py +8 -6
- cirq/interop/quirk/cells/unsupported_cells.py +3 -0
- cirq/interop/quirk/cells/unsupported_cells_test.py +4 -2
- cirq/interop/quirk/url_to_circuit.py +23 -36
- cirq/interop/quirk/url_to_circuit_test.py +4 -1
- cirq/json_resolver_cache.py +14 -12
- cirq/linalg/__init__.py +4 -6
- cirq/linalg/combinators.py +7 -5
- cirq/linalg/combinators_test.py +10 -7
- cirq/linalg/decompositions.py +24 -35
- cirq/linalg/decompositions_test.py +3 -1
- cirq/linalg/diagonalize.py +6 -4
- cirq/linalg/diagonalize_test.py +15 -14
- cirq/linalg/operator_spaces.py +14 -14
- cirq/linalg/operator_spaces_test.py +13 -11
- cirq/linalg/predicates.py +18 -9
- cirq/linalg/predicates_test.py +5 -0
- cirq/linalg/tolerance.py +6 -3
- cirq/linalg/tolerance_test.py +6 -4
- cirq/linalg/transformations.py +23 -20
- cirq/linalg/transformations_test.py +73 -43
- cirq/neutral_atoms/convert_to_neutral_atom_gates.py +9 -3
- cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +3 -1
- cirq/neutral_atoms/neutral_atom_devices.py +2 -0
- cirq/ops/__init__.py +2 -0
- cirq/ops/arithmetic_operation.py +21 -21
- cirq/ops/arithmetic_operation_test.py +7 -8
- cirq/ops/boolean_hamiltonian.py +23 -22
- cirq/ops/boolean_hamiltonian_test.py +12 -9
- cirq/ops/classically_controlled_operation.py +31 -36
- cirq/ops/classically_controlled_operation_test.py +121 -117
- cirq/ops/clifford_gate.py +98 -81
- cirq/ops/clifford_gate_test.py +72 -57
- cirq/ops/common_channels.py +44 -44
- cirq/ops/common_channels_test.py +83 -81
- cirq/ops/common_gate_families.py +9 -7
- cirq/ops/common_gate_families_test.py +11 -7
- cirq/ops/common_gates.py +164 -183
- cirq/ops/common_gates_test.py +135 -95
- cirq/ops/control_values.py +23 -26
- cirq/ops/control_values_test.py +22 -20
- cirq/ops/controlled_gate.py +64 -112
- cirq/ops/controlled_gate_test.py +130 -35
- cirq/ops/controlled_operation.py +24 -35
- cirq/ops/controlled_operation_test.py +8 -6
- cirq/ops/dense_pauli_string.py +38 -49
- cirq/ops/dense_pauli_string_test.py +4 -2
- cirq/ops/diagonal_gate.py +18 -31
- cirq/ops/diagonal_gate_test.py +13 -13
- cirq/ops/eigen_gate.py +29 -29
- cirq/ops/eigen_gate_test.py +45 -28
- cirq/ops/fourier_transform.py +14 -20
- cirq/ops/fourier_transform_test.py +15 -12
- cirq/ops/fsim_gate.py +43 -42
- cirq/ops/fsim_gate_test.py +29 -29
- cirq/ops/gate_features.py +2 -0
- cirq/ops/gate_features_test.py +5 -3
- cirq/ops/gate_operation.py +43 -65
- cirq/ops/gate_operation_test.py +46 -42
- cirq/ops/gateset.py +28 -40
- cirq/ops/gateset_test.py +4 -2
- cirq/ops/global_phase_op.py +45 -20
- cirq/ops/global_phase_op_test.py +44 -20
- cirq/ops/greedy_qubit_manager.py +10 -8
- cirq/ops/greedy_qubit_manager_test.py +5 -3
- cirq/ops/identity.py +14 -12
- cirq/ops/identity_test.py +24 -20
- cirq/ops/kraus_channel.py +11 -8
- cirq/ops/kraus_channel_test.py +14 -11
- cirq/ops/linear_combinations.py +65 -77
- cirq/ops/linear_combinations_test.py +14 -9
- cirq/ops/matrix_gates.py +21 -18
- cirq/ops/matrix_gates_test.py +16 -0
- cirq/ops/measure_util.py +15 -20
- cirq/ops/measure_util_test.py +2 -0
- cirq/ops/measurement_gate.py +26 -37
- cirq/ops/measurement_gate_test.py +2 -0
- cirq/ops/mixed_unitary_channel.py +12 -9
- cirq/ops/mixed_unitary_channel_test.py +14 -11
- cirq/ops/named_qubit.py +16 -13
- cirq/ops/named_qubit_test.py +15 -13
- cirq/ops/op_tree.py +9 -7
- cirq/ops/op_tree_test.py +22 -19
- cirq/ops/parallel_gate.py +15 -17
- cirq/ops/parallel_gate_test.py +18 -16
- cirq/ops/parity_gates.py +23 -25
- cirq/ops/parity_gates_test.py +36 -32
- cirq/ops/pauli_gates.py +22 -21
- cirq/ops/pauli_gates_test.py +29 -20
- cirq/ops/pauli_interaction_gate.py +15 -19
- cirq/ops/pauli_interaction_gate_test.py +10 -8
- cirq/ops/pauli_measurement_gate.py +23 -35
- cirq/ops/pauli_measurement_gate_test.py +2 -0
- cirq/ops/pauli_string.py +92 -120
- cirq/ops/pauli_string_phasor.py +52 -45
- cirq/ops/pauli_string_phasor_test.py +4 -5
- cirq/ops/pauli_string_raw_types.py +9 -7
- cirq/ops/pauli_string_raw_types_test.py +2 -0
- cirq/ops/pauli_string_test.py +31 -154
- cirq/ops/pauli_sum_exponential.py +12 -12
- cirq/ops/pauli_sum_exponential_test.py +12 -10
- cirq/ops/permutation_gate.py +8 -6
- cirq/ops/permutation_gate_test.py +10 -8
- cirq/ops/phased_iswap_gate.py +16 -16
- cirq/ops/phased_iswap_gate_test.py +17 -15
- cirq/ops/phased_x_gate.py +16 -17
- cirq/ops/phased_x_gate_test.py +18 -16
- cirq/ops/phased_x_z_gate.py +24 -22
- cirq/ops/phased_x_z_gate_test.py +17 -11
- cirq/ops/projector.py +16 -11
- cirq/ops/projector_test.py +19 -16
- cirq/ops/qid_util.py +7 -5
- cirq/ops/qid_util_test.py +2 -0
- cirq/ops/qubit_manager.py +11 -9
- cirq/ops/qubit_manager_test.py +6 -4
- cirq/ops/qubit_order.py +11 -14
- cirq/ops/qubit_order_or_list.py +4 -2
- cirq/ops/qubit_order_test.py +12 -10
- cirq/ops/random_gate_channel.py +12 -10
- cirq/ops/random_gate_channel_test.py +14 -11
- cirq/ops/raw_types.py +109 -129
- cirq/ops/raw_types_test.py +63 -57
- cirq/ops/state_preparation_channel.py +7 -7
- cirq/ops/state_preparation_channel_test.py +11 -9
- cirq/ops/swap_gates.py +13 -15
- cirq/ops/swap_gates_test.py +19 -17
- cirq/ops/tags.py +5 -3
- cirq/ops/tags_test.py +4 -2
- cirq/ops/three_qubit_gates.py +43 -76
- cirq/ops/three_qubit_gates_test.py +19 -17
- cirq/ops/two_qubit_diagonal_gate.py +13 -13
- cirq/ops/two_qubit_diagonal_gate_test.py +10 -8
- cirq/ops/uniform_superposition_gate.py +5 -3
- cirq/ops/uniform_superposition_gate_test.py +5 -3
- cirq/ops/wait_gate.py +17 -14
- cirq/ops/wait_gate_test.py +9 -6
- cirq/protocols/__init__.py +0 -3
- cirq/protocols/act_on_protocol.py +8 -6
- cirq/protocols/act_on_protocol_test.py +15 -12
- cirq/protocols/apply_channel_protocol.py +10 -14
- cirq/protocols/apply_channel_protocol_test.py +2 -0
- cirq/protocols/apply_mixture_protocol.py +13 -42
- cirq/protocols/apply_mixture_protocol_test.py +7 -5
- cirq/protocols/apply_unitary_protocol.py +39 -34
- cirq/protocols/apply_unitary_protocol_test.py +4 -1
- cirq/protocols/approximate_equality_protocol.py +2 -0
- cirq/protocols/approximate_equality_protocol_test.py +2 -0
- cirq/protocols/circuit_diagram_info_protocol.py +58 -42
- cirq/protocols/circuit_diagram_info_protocol_test.py +70 -12
- cirq/protocols/commutes_protocol.py +8 -7
- cirq/protocols/commutes_protocol_test.py +2 -0
- cirq/protocols/control_key_protocol.py +6 -4
- cirq/protocols/control_key_protocol_test.py +3 -1
- cirq/protocols/decompose_protocol.py +49 -48
- cirq/protocols/decompose_protocol_test.py +27 -16
- cirq/protocols/equal_up_to_global_phase_protocol.py +2 -0
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +9 -6
- cirq/protocols/has_stabilizer_effect_protocol.py +7 -5
- cirq/protocols/has_stabilizer_effect_protocol_test.py +7 -5
- cirq/protocols/has_unitary_protocol.py +10 -6
- cirq/protocols/has_unitary_protocol_test.py +13 -8
- cirq/protocols/hash_from_pickle_test.py +2 -11
- cirq/protocols/inverse_protocol.py +13 -16
- cirq/protocols/inverse_protocol_test.py +5 -3
- cirq/protocols/json_serialization.py +35 -54
- cirq/protocols/json_serialization_test.py +14 -21
- cirq/protocols/json_test_data/CXSWAP.json +46 -0
- cirq/protocols/json_test_data/CXSWAP.repr +13 -0
- cirq/protocols/json_test_data/CZSWAP.json +46 -0
- cirq/protocols/json_test_data/CZSWAP.repr +13 -0
- cirq/protocols/json_test_data/CircuitOperation.json +6 -3
- cirq/protocols/json_test_data/CircuitOperation.repr_inward +4 -2
- cirq/protocols/json_test_data/Moment.json +24 -1
- cirq/protocols/json_test_data/Moment.repr +6 -1
- cirq/protocols/json_test_data/ThermalNoiseModel.json +32 -0
- cirq/protocols/json_test_data/ThermalNoiseModel.repr +1 -0
- cirq/protocols/json_test_data/spec.py +6 -2
- cirq/protocols/kraus_protocol.py +47 -7
- cirq/protocols/kraus_protocol_test.py +86 -12
- cirq/protocols/measurement_key_protocol.py +15 -16
- cirq/protocols/measurement_key_protocol_test.py +13 -11
- cirq/protocols/mixture_protocol.py +7 -5
- cirq/protocols/mixture_protocol_test.py +4 -2
- cirq/protocols/mul_protocol.py +2 -3
- cirq/protocols/mul_protocol_test.py +2 -0
- cirq/protocols/pauli_expansion_protocol.py +6 -3
- cirq/protocols/pauli_expansion_protocol_test.py +5 -3
- cirq/protocols/phase_protocol.py +2 -0
- cirq/protocols/phase_protocol_test.py +3 -1
- cirq/protocols/pow_protocol.py +11 -16
- cirq/protocols/pow_protocol_test.py +2 -0
- cirq/protocols/qasm.py +14 -20
- cirq/protocols/qasm_test.py +6 -3
- cirq/protocols/qid_shape_protocol.py +8 -8
- cirq/protocols/qid_shape_protocol_test.py +3 -1
- cirq/protocols/resolve_parameters.py +5 -3
- cirq/protocols/resolve_parameters_test.py +8 -7
- cirq/protocols/trace_distance_bound.py +6 -4
- cirq/protocols/trace_distance_bound_test.py +3 -1
- cirq/protocols/unitary_protocol.py +17 -7
- cirq/protocols/unitary_protocol_test.py +12 -2
- cirq/qis/channels.py +6 -2
- cirq/qis/channels_test.py +20 -16
- cirq/qis/clifford_tableau.py +21 -19
- cirq/qis/clifford_tableau_test.py +2 -2
- cirq/qis/entropy.py +14 -3
- cirq/qis/entropy_test.py +3 -1
- cirq/qis/measures.py +13 -13
- cirq/qis/measures_test.py +20 -14
- cirq/qis/noise_utils.py +2 -0
- cirq/qis/noise_utils_test.py +9 -7
- cirq/qis/quantum_state_representation.py +7 -8
- cirq/qis/states.py +58 -56
- cirq/qis/states_test.py +2 -0
- cirq/sim/classical_simulator.py +23 -22
- cirq/sim/classical_simulator_test.py +2 -0
- cirq/sim/clifford/clifford_simulator.py +23 -21
- cirq/sim/clifford/clifford_simulator_test.py +7 -4
- cirq/sim/clifford/clifford_tableau_simulation_state.py +10 -7
- cirq/sim/clifford/clifford_tableau_simulation_state_test.py +5 -5
- cirq/sim/clifford/stabilizer_ch_form_simulation_state.py +8 -6
- cirq/sim/clifford/stabilizer_ch_form_simulation_state_test.py +8 -6
- cirq/sim/clifford/stabilizer_sampler.py +9 -7
- cirq/sim/clifford/stabilizer_sampler_test.py +4 -2
- cirq/sim/clifford/stabilizer_simulation_state.py +14 -13
- cirq/sim/clifford/stabilizer_simulation_state_test.py +6 -4
- cirq/sim/clifford/stabilizer_state_ch_form.py +13 -11
- cirq/sim/clifford/stabilizer_state_ch_form_test.py +4 -2
- cirq/sim/density_matrix_simulation_state.py +26 -27
- cirq/sim/density_matrix_simulation_state_test.py +10 -8
- cirq/sim/density_matrix_simulator.py +30 -28
- cirq/sim/density_matrix_simulator_test.py +48 -48
- cirq/sim/density_matrix_utils.py +13 -11
- cirq/sim/density_matrix_utils_test.py +38 -36
- cirq/sim/mux.py +33 -31
- cirq/sim/mux_test.py +3 -0
- cirq/sim/simulation_product_state.py +15 -15
- cirq/sim/simulation_product_state_test.py +29 -26
- cirq/sim/simulation_state.py +29 -38
- cirq/sim/simulation_state_base.py +21 -32
- cirq/sim/simulation_state_test.py +15 -13
- cirq/sim/simulation_utils.py +5 -2
- cirq/sim/simulation_utils_test.py +5 -2
- cirq/sim/simulator.py +90 -106
- cirq/sim/simulator_base.py +33 -45
- cirq/sim/simulator_base_test.py +20 -15
- cirq/sim/simulator_test.py +23 -14
- cirq/sim/sparse_simulator.py +19 -17
- cirq/sim/sparse_simulator_test.py +41 -40
- cirq/sim/state_vector.py +15 -12
- cirq/sim/state_vector_simulation_state.py +31 -31
- cirq/sim/state_vector_simulation_state_test.py +16 -14
- cirq/sim/state_vector_simulator.py +17 -14
- cirq/sim/state_vector_simulator_test.py +2 -0
- cirq/sim/state_vector_test.py +6 -3
- cirq/study/flatten_expressions.py +16 -15
- cirq/study/flatten_expressions_test.py +13 -11
- cirq/study/resolver.py +18 -17
- cirq/study/resolver_test.py +22 -20
- cirq/study/result.py +17 -27
- cirq/study/result_test.py +2 -0
- cirq/study/sweepable.py +12 -10
- cirq/study/sweepable_test.py +3 -0
- cirq/study/sweeps.py +42 -61
- cirq/study/sweeps_test.py +33 -0
- cirq/testing/__init__.py +7 -11
- cirq/testing/_compat_test_data/module_a/__init__.py +1 -0
- cirq/testing/_compat_test_data/module_a/module_b/__init__.py +1 -0
- cirq/testing/_compat_test_data/module_a/sub/__init__.py +1 -0
- cirq/testing/circuit_compare.py +8 -17
- cirq/testing/circuit_compare_test.py +2 -0
- cirq/testing/consistent_act_on.py +13 -11
- cirq/testing/consistent_act_on_test.py +5 -3
- cirq/testing/consistent_channels.py +2 -0
- cirq/testing/consistent_channels_test.py +10 -8
- cirq/testing/consistent_controlled_gate_op.py +5 -5
- cirq/testing/consistent_controlled_gate_op_test.py +18 -18
- cirq/testing/consistent_decomposition.py +2 -2
- cirq/testing/consistent_decomposition_test.py +4 -2
- cirq/testing/consistent_pauli_expansion.py +2 -0
- cirq/testing/consistent_pauli_expansion_test.py +3 -1
- cirq/testing/consistent_phase_by.py +2 -0
- cirq/testing/consistent_phase_by_test.py +3 -1
- cirq/testing/consistent_protocols.py +14 -20
- cirq/testing/consistent_protocols_test.py +13 -11
- cirq/testing/consistent_qasm.py +6 -4
- cirq/testing/consistent_qasm_test.py +7 -7
- cirq/testing/consistent_resolve_parameters.py +2 -0
- cirq/testing/consistent_specified_has_unitary.py +2 -2
- cirq/testing/consistent_specified_has_unitary_test.py +6 -4
- cirq/testing/consistent_unitary.py +1 -0
- cirq/testing/consistent_unitary_test.py +4 -2
- cirq/testing/deprecation.py +5 -2
- cirq/testing/deprecation_test.py +5 -2
- cirq/testing/devices.py +7 -4
- cirq/testing/devices_test.py +7 -4
- cirq/testing/equals_tester.py +4 -2
- cirq/testing/equals_tester_test.py +21 -17
- cirq/testing/equivalent_basis_map.py +6 -4
- cirq/testing/equivalent_basis_map_test.py +6 -4
- cirq/testing/equivalent_repr_eval.py +6 -4
- cirq/testing/equivalent_repr_eval_test.py +5 -3
- cirq/testing/gate_features.py +2 -0
- cirq/testing/gate_features_test.py +7 -5
- cirq/testing/json.py +19 -15
- cirq/testing/json_test.py +5 -3
- cirq/testing/lin_alg_utils.py +10 -11
- cirq/testing/lin_alg_utils_test.py +14 -12
- cirq/testing/logs.py +7 -6
- cirq/testing/logs_test.py +9 -7
- cirq/testing/no_identifier_qubit.py +4 -2
- cirq/testing/no_identifier_qubit_test.py +5 -3
- cirq/testing/op_tree.py +2 -0
- cirq/testing/op_tree_test.py +4 -1
- cirq/testing/order_tester.py +2 -0
- cirq/testing/order_tester_test.py +8 -6
- cirq/testing/pytest_utils.py +2 -0
- cirq/testing/pytest_utils_test.py +4 -2
- cirq/testing/random_circuit.py +21 -20
- cirq/testing/random_circuit_test.py +12 -9
- cirq/testing/repr_pretty_tester.py +1 -0
- cirq/testing/repr_pretty_tester_test.py +5 -3
- cirq/testing/routing_devices.py +4 -1
- cirq/testing/routing_devices_test.py +9 -6
- cirq/testing/sample_circuits.py +4 -1
- cirq/testing/sample_circuits_test.py +3 -1
- cirq/testing/sample_gates.py +3 -0
- cirq/testing/sample_gates_test.py +5 -2
- cirq/transformers/__init__.py +11 -4
- cirq/transformers/align.py +9 -7
- cirq/transformers/align_test.py +2 -0
- cirq/transformers/analytical_decompositions/__init__.py +3 -6
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +18 -16
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +19 -16
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +11 -9
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +5 -3
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +5 -3
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +5 -3
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +141 -44
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +35 -1
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +8 -7
- cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +2 -0
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +7 -4
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +3 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +11 -19
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +8 -33
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +9 -11
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -0
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +91 -27
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +36 -7
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +20 -21
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +8 -6
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +13 -15
- cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +3 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +39 -41
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -0
- cirq/transformers/drop_empty_moments.py +5 -3
- cirq/transformers/drop_empty_moments_test.py +4 -2
- cirq/transformers/drop_negligible_operations.py +7 -5
- cirq/transformers/drop_negligible_operations_test.py +2 -0
- cirq/transformers/dynamical_decoupling.py +49 -42
- cirq/transformers/dynamical_decoupling_test.py +223 -205
- cirq/transformers/eject_phased_paulis.py +28 -26
- cirq/transformers/eject_phased_paulis_test.py +12 -9
- cirq/transformers/eject_z.py +12 -12
- cirq/transformers/eject_z_test.py +2 -2
- cirq/transformers/expand_composite.py +6 -4
- cirq/transformers/expand_composite_test.py +3 -1
- cirq/transformers/gauge_compiling/__init__.py +3 -1
- cirq/transformers/gauge_compiling/cphase_gauge.py +2 -0
- cirq/transformers/gauge_compiling/cphase_gauge_test.py +2 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +2 -0
- cirq/transformers/gauge_compiling/cz_gauge_test.py +1 -0
- cirq/transformers/gauge_compiling/gauge_compiling.py +45 -41
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +2 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +1 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +5 -1
- cirq/transformers/gauge_compiling/iswap_gauge.py +2 -0
- cirq/transformers/gauge_compiling/iswap_gauge_test.py +1 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +2 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +7 -6
- cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +2 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +2 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +2 -0
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +6 -3
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +3 -0
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +12 -9
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +9 -7
- cirq/transformers/insertion_sort.py +8 -6
- cirq/transformers/insertion_sort_test.py +3 -1
- cirq/transformers/measurement_transformers.py +29 -29
- cirq/transformers/measurement_transformers_test.py +2 -0
- cirq/transformers/merge_k_qubit_gates.py +12 -10
- cirq/transformers/merge_k_qubit_gates_test.py +18 -18
- cirq/transformers/merge_single_qubit_gates.py +197 -20
- cirq/transformers/merge_single_qubit_gates_test.py +177 -5
- cirq/transformers/noise_adding.py +5 -3
- cirq/transformers/noise_adding_test.py +2 -0
- cirq/transformers/optimize_for_target_gateset.py +19 -17
- cirq/transformers/optimize_for_target_gateset_test.py +11 -8
- cirq/transformers/qubit_management_transformers.py +13 -11
- cirq/transformers/qubit_management_transformers_test.py +5 -3
- cirq/transformers/randomized_measurements.py +16 -14
- cirq/transformers/randomized_measurements_test.py +10 -4
- cirq/transformers/routing/initial_mapper.py +6 -4
- cirq/transformers/routing/initial_mapper_test.py +2 -0
- cirq/transformers/routing/line_initial_mapper.py +16 -14
- cirq/transformers/routing/line_initial_mapper_test.py +9 -7
- cirq/transformers/routing/mapping_manager.py +10 -10
- cirq/transformers/routing/mapping_manager_test.py +2 -0
- cirq/transformers/routing/route_circuit_cqc.py +33 -31
- cirq/transformers/routing/route_circuit_cqc_test.py +15 -13
- cirq/transformers/routing/visualize_routed_circuit.py +8 -7
- cirq/transformers/routing/visualize_routed_circuit_test.py +4 -2
- cirq/transformers/stratify.py +17 -15
- cirq/transformers/stratify_test.py +3 -0
- cirq/transformers/symbolize.py +103 -0
- cirq/transformers/symbolize_test.py +62 -0
- cirq/transformers/synchronize_terminal_measurements.py +10 -10
- cirq/transformers/synchronize_terminal_measurements_test.py +12 -10
- cirq/transformers/tag_transformers.py +97 -0
- cirq/transformers/tag_transformers_test.py +103 -0
- cirq/transformers/target_gatesets/compilation_target_gateset.py +21 -19
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +20 -16
- cirq/transformers/target_gatesets/cz_gateset.py +7 -5
- cirq/transformers/target_gatesets/cz_gateset_test.py +21 -19
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +9 -7
- cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +25 -25
- cirq/transformers/transformer_api.py +34 -47
- cirq/transformers/transformer_api_test.py +9 -8
- cirq/transformers/transformer_primitives.py +39 -49
- cirq/transformers/transformer_primitives_test.py +10 -17
- cirq/value/abc_alt.py +6 -4
- cirq/value/abc_alt_test.py +5 -3
- cirq/value/angle.py +11 -12
- cirq/value/angle_test.py +5 -3
- cirq/value/classical_data.py +27 -27
- cirq/value/classical_data_test.py +11 -8
- cirq/value/condition.py +26 -24
- cirq/value/condition_test.py +2 -0
- cirq/value/digits.py +14 -11
- cirq/value/digits_test.py +2 -0
- cirq/value/duration.py +23 -20
- cirq/value/duration_test.py +2 -0
- cirq/value/linear_dict.py +25 -30
- cirq/value/linear_dict_test.py +10 -8
- cirq/value/measurement_key.py +12 -12
- cirq/value/measurement_key_test.py +2 -0
- cirq/value/periodic_value.py +4 -4
- cirq/value/periodic_value_test.py +11 -7
- cirq/value/probability.py +3 -1
- cirq/value/probability_test.py +4 -2
- cirq/value/product_state.py +15 -13
- cirq/value/product_state_test.py +4 -1
- cirq/value/random_state.py +2 -0
- cirq/value/random_state_test.py +5 -3
- cirq/value/timestamp.py +11 -7
- cirq/value/timestamp_test.py +14 -12
- cirq/value/type_alias.py +4 -4
- cirq/value/value_equality_attr.py +8 -9
- cirq/value/value_equality_attr_test.py +14 -11
- cirq/vis/density_matrix.py +3 -3
- cirq/vis/density_matrix_test.py +20 -17
- cirq/vis/heatmap.py +24 -37
- cirq/vis/heatmap_test.py +3 -0
- cirq/vis/histogram.py +9 -6
- cirq/vis/histogram_test.py +5 -2
- cirq/vis/state_histogram.py +10 -8
- cirq/vis/state_histogram_test.py +7 -5
- cirq/vis/vis_utils.py +4 -1
- cirq/vis/vis_utils_test.py +4 -1
- cirq/work/collector.py +12 -18
- cirq/work/collector_test.py +15 -10
- cirq/work/observable_grouping.py +6 -7
- cirq/work/observable_grouping_test.py +10 -9
- cirq/work/observable_measurement.py +47 -45
- cirq/work/observable_measurement_data.py +22 -17
- cirq/work/observable_measurement_data_test.py +4 -1
- cirq/work/observable_measurement_test.py +48 -29
- cirq/work/observable_readout_calibration.py +5 -2
- cirq/work/observable_readout_calibration_test.py +5 -2
- cirq/work/observable_settings.py +13 -22
- cirq/work/observable_settings_test.py +9 -7
- cirq/work/pauli_sum_collector.py +12 -10
- cirq/work/pauli_sum_collector_test.py +9 -9
- cirq/work/sampler.py +42 -43
- cirq/work/sampler_test.py +31 -24
- cirq/work/zeros_sampler.py +6 -4
- cirq/work/zeros_sampler_test.py +7 -5
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/METADATA +7 -8
- cirq_core-1.6.0.dist-info/RECORD +1241 -0
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
- cirq_core-1.5.0.dev20250409222543.dist-info/RECORD +0 -1216
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
|
@@ -12,15 +12,21 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import itertools
|
|
15
18
|
import random
|
|
16
|
-
from typing import
|
|
19
|
+
from typing import Sequence
|
|
17
20
|
|
|
18
21
|
import numpy as np
|
|
19
22
|
import pytest
|
|
20
23
|
|
|
21
24
|
import cirq
|
|
22
25
|
from cirq.contrib.paulistring import measure_pauli_strings
|
|
23
|
-
from cirq.
|
|
26
|
+
from cirq.contrib.paulistring.pauli_string_measurement_with_readout_mitigation import (
|
|
27
|
+
_process_pauli_measurement_results,
|
|
28
|
+
)
|
|
29
|
+
from cirq.experiments.single_qubit_readout_calibration import SingleQubitReadoutCalibrationResult
|
|
24
30
|
from cirq.experiments.single_qubit_readout_calibration_test import NoisySingleQubitReadoutSampler
|
|
25
31
|
|
|
26
32
|
|
|
@@ -32,9 +38,14 @@ def _create_ghz(number_of_qubits: int, qubits: Sequence[cirq.Qid]) -> cirq.Circu
|
|
|
32
38
|
return ghz_circuit
|
|
33
39
|
|
|
34
40
|
|
|
35
|
-
def _generate_random_pauli_string(
|
|
41
|
+
def _generate_random_pauli_string(
|
|
42
|
+
qubits: Sequence[cirq.Qid], enable_coeff: bool = False, allow_pauli_i: bool = True
|
|
43
|
+
):
|
|
36
44
|
pauli_ops = [cirq.I, cirq.X, cirq.Y, cirq.Z]
|
|
37
45
|
|
|
46
|
+
if not allow_pauli_i:
|
|
47
|
+
pauli_ops = [cirq.X, cirq.Y, cirq.Z]
|
|
48
|
+
|
|
38
49
|
operators = {q: random.choice(pauli_ops) for q in qubits}
|
|
39
50
|
# Ensure at least one non-identity.
|
|
40
51
|
operators[random.choice(qubits)] = random.choice(pauli_ops[1:])
|
|
@@ -45,6 +56,49 @@ def _generate_random_pauli_string(qubits: Sequence[cirq.Qid], enable_coeff: bool
|
|
|
45
56
|
return cirq.PauliString(operators)
|
|
46
57
|
|
|
47
58
|
|
|
59
|
+
def _generate_qwc_paulis(
|
|
60
|
+
input_pauli: cirq.PauliString, num_output: int, exclude_input_pauli: bool = False
|
|
61
|
+
) -> list[cirq.PauliString]:
|
|
62
|
+
"""Generates PauliStrings that are Qubit-Wise Commuting (QWC)
|
|
63
|
+
with the input_pauli.
|
|
64
|
+
|
|
65
|
+
All operations in input_pauli must not be pauli I.
|
|
66
|
+
"""
|
|
67
|
+
allowed_paulis_per_qubit = []
|
|
68
|
+
qubits = input_pauli.qubits
|
|
69
|
+
|
|
70
|
+
for qubit in qubits:
|
|
71
|
+
pauli_op = input_pauli.get(qubit, cirq.I)
|
|
72
|
+
|
|
73
|
+
allowed_pauli_op = []
|
|
74
|
+
if pauli_op == cirq.I:
|
|
75
|
+
allowed_pauli_op = [cirq.I, cirq.X, cirq.Y, cirq.Z] # pragma: no cover
|
|
76
|
+
elif pauli_op == cirq.X:
|
|
77
|
+
allowed_pauli_op = [cirq.I, cirq.X]
|
|
78
|
+
elif pauli_op == cirq.Y:
|
|
79
|
+
allowed_pauli_op = [cirq.I, cirq.Y]
|
|
80
|
+
elif pauli_op == cirq.Z:
|
|
81
|
+
allowed_pauli_op = [cirq.I, cirq.Z]
|
|
82
|
+
|
|
83
|
+
allowed_paulis_per_qubit.append(allowed_pauli_op)
|
|
84
|
+
|
|
85
|
+
qwc_paulis: list[cirq.PauliString] = []
|
|
86
|
+
|
|
87
|
+
for pauli_combination in itertools.product(*allowed_paulis_per_qubit):
|
|
88
|
+
pauli_dict = {}
|
|
89
|
+
for i, qid in enumerate(qubits):
|
|
90
|
+
pauli_dict[qid] = pauli_combination[i]
|
|
91
|
+
|
|
92
|
+
qwc_pauli: cirq.PauliString = cirq.PauliString(pauli_dict)
|
|
93
|
+
if exclude_input_pauli and qwc_pauli == input_pauli:
|
|
94
|
+
continue # pragma: no cover
|
|
95
|
+
if all(q == cirq.I for q in qwc_pauli):
|
|
96
|
+
continue
|
|
97
|
+
qwc_paulis.append(qwc_pauli)
|
|
98
|
+
|
|
99
|
+
return qwc_paulis if num_output > len(qwc_paulis) else random.sample(qwc_paulis, num_output)
|
|
100
|
+
|
|
101
|
+
|
|
48
102
|
def _ideal_expectation_based_on_pauli_string(
|
|
49
103
|
pauli_string: cirq.PauliString, final_state_vector: np.ndarray
|
|
50
104
|
) -> float:
|
|
@@ -61,7 +115,7 @@ def test_pauli_string_measurement_errors_no_noise() -> None:
|
|
|
61
115
|
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
62
116
|
sampler = cirq.Simulator()
|
|
63
117
|
|
|
64
|
-
circuits_to_pauli:
|
|
118
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
65
119
|
circuits_to_pauli[circuit] = [_generate_random_pauli_string(qubits) for _ in range(3)]
|
|
66
120
|
|
|
67
121
|
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
@@ -109,7 +163,7 @@ def test_pauli_string_measurement_errors_with_coefficient_no_noise() -> None:
|
|
|
109
163
|
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
110
164
|
sampler = cirq.Simulator()
|
|
111
165
|
|
|
112
|
-
circuits_to_pauli:
|
|
166
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
113
167
|
circuits_to_pauli[circuit] = [_generate_random_pauli_string(qubits, True) for _ in range(3)]
|
|
114
168
|
|
|
115
169
|
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
@@ -149,6 +203,60 @@ def test_pauli_string_measurement_errors_with_coefficient_no_noise() -> None:
|
|
|
149
203
|
}
|
|
150
204
|
|
|
151
205
|
|
|
206
|
+
def test_group_pauli_string_measurement_errors_no_noise_with_coefficient() -> None:
|
|
207
|
+
"""Test that the mitigated expectation is close to the ideal expectation
|
|
208
|
+
based on the group of Pauli strings"""
|
|
209
|
+
|
|
210
|
+
qubits = cirq.LineQubit.range(5)
|
|
211
|
+
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
212
|
+
sampler = cirq.Simulator()
|
|
213
|
+
|
|
214
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[list[cirq.PauliString]]] = {}
|
|
215
|
+
circuits_to_pauli[circuit] = [
|
|
216
|
+
_generate_qwc_paulis(
|
|
217
|
+
_generate_random_pauli_string(qubits, enable_coeff=True, allow_pauli_i=False), 100, True
|
|
218
|
+
)
|
|
219
|
+
for _ in range(3)
|
|
220
|
+
]
|
|
221
|
+
circuits_to_pauli[circuit].append([cirq.PauliString({q: cirq.X for q in qubits})])
|
|
222
|
+
|
|
223
|
+
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
224
|
+
circuits_to_pauli, sampler, 100, 100, 100, 100
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
|
|
228
|
+
assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
|
|
229
|
+
|
|
230
|
+
expected_val_simulation = sampler.simulate(
|
|
231
|
+
circuit_with_pauli_expectations.circuit.unfreeze()
|
|
232
|
+
)
|
|
233
|
+
final_state_vector = expected_val_simulation.final_state_vector
|
|
234
|
+
|
|
235
|
+
for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
|
|
236
|
+
# Since there is no noise, the mitigated and unmitigated expectations should be the same
|
|
237
|
+
assert np.isclose(
|
|
238
|
+
pauli_string_measurement_results.mitigated_expectation,
|
|
239
|
+
pauli_string_measurement_results.unmitigated_expectation,
|
|
240
|
+
)
|
|
241
|
+
assert np.isclose(
|
|
242
|
+
pauli_string_measurement_results.mitigated_expectation,
|
|
243
|
+
_ideal_expectation_based_on_pauli_string(
|
|
244
|
+
pauli_string_measurement_results.pauli_string, final_state_vector
|
|
245
|
+
),
|
|
246
|
+
atol=4 * pauli_string_measurement_results.mitigated_stddev,
|
|
247
|
+
)
|
|
248
|
+
assert isinstance(
|
|
249
|
+
pauli_string_measurement_results.calibration_result,
|
|
250
|
+
SingleQubitReadoutCalibrationResult,
|
|
251
|
+
)
|
|
252
|
+
assert pauli_string_measurement_results.calibration_result.zero_state_errors == {
|
|
253
|
+
q: 0 for q in pauli_string_measurement_results.pauli_string.qubits
|
|
254
|
+
}
|
|
255
|
+
assert pauli_string_measurement_results.calibration_result.one_state_errors == {
|
|
256
|
+
q: 0 for q in pauli_string_measurement_results.pauli_string.qubits
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
152
260
|
def test_pauli_string_measurement_errors_with_noise() -> None:
|
|
153
261
|
"""Test that the mitigated expectation is close to the ideal expectation
|
|
154
262
|
based on the Pauli string"""
|
|
@@ -157,7 +265,7 @@ def test_pauli_string_measurement_errors_with_noise() -> None:
|
|
|
157
265
|
sampler = NoisySingleQubitReadoutSampler(p0=0.1, p1=0.005, seed=1234)
|
|
158
266
|
simulator = cirq.Simulator()
|
|
159
267
|
|
|
160
|
-
circuits_to_pauli:
|
|
268
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
161
269
|
circuits_to_pauli[circuit] = [_generate_random_pauli_string(qubits) for _ in range(3)]
|
|
162
270
|
|
|
163
271
|
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
@@ -196,6 +304,57 @@ def test_pauli_string_measurement_errors_with_noise() -> None:
|
|
|
196
304
|
assert 0.0045 < error < 0.0055
|
|
197
305
|
|
|
198
306
|
|
|
307
|
+
def test_group_pauli_string_measurement_errors_with_noise() -> None:
|
|
308
|
+
"""Test that the mitigated expectation is close to the ideal expectation
|
|
309
|
+
based on the group Pauli strings"""
|
|
310
|
+
qubits = cirq.LineQubit.range(7)
|
|
311
|
+
circuit = cirq.FrozenCircuit(_create_ghz(7, qubits))
|
|
312
|
+
sampler = NoisySingleQubitReadoutSampler(p0=0.1, p1=0.005, seed=1234)
|
|
313
|
+
simulator = cirq.Simulator()
|
|
314
|
+
|
|
315
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[list[cirq.PauliString]]] = {}
|
|
316
|
+
circuits_to_pauli[circuit] = [
|
|
317
|
+
_generate_qwc_paulis(
|
|
318
|
+
_generate_random_pauli_string(qubits, enable_coeff=True, allow_pauli_i=False), 5
|
|
319
|
+
)
|
|
320
|
+
]
|
|
321
|
+
|
|
322
|
+
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
323
|
+
circuits_to_pauli, sampler, 800, 1000, 800, np.random.default_rng()
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
|
|
327
|
+
assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
|
|
328
|
+
|
|
329
|
+
expected_val_simulation = simulator.simulate(
|
|
330
|
+
circuit_with_pauli_expectations.circuit.unfreeze()
|
|
331
|
+
)
|
|
332
|
+
final_state_vector = expected_val_simulation.final_state_vector
|
|
333
|
+
|
|
334
|
+
for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
|
|
335
|
+
assert np.isclose(
|
|
336
|
+
pauli_string_measurement_results.mitigated_expectation,
|
|
337
|
+
_ideal_expectation_based_on_pauli_string(
|
|
338
|
+
pauli_string_measurement_results.pauli_string, final_state_vector
|
|
339
|
+
),
|
|
340
|
+
atol=4 * pauli_string_measurement_results.mitigated_stddev,
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
assert isinstance(
|
|
344
|
+
pauli_string_measurement_results.calibration_result,
|
|
345
|
+
SingleQubitReadoutCalibrationResult,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
for (
|
|
349
|
+
error
|
|
350
|
+
) in pauli_string_measurement_results.calibration_result.zero_state_errors.values():
|
|
351
|
+
assert 0.08 < error < 0.12
|
|
352
|
+
for (
|
|
353
|
+
error
|
|
354
|
+
) in pauli_string_measurement_results.calibration_result.one_state_errors.values():
|
|
355
|
+
assert 0.0045 < error < 0.0055
|
|
356
|
+
|
|
357
|
+
|
|
199
358
|
def test_many_circuits_input_measurement_with_noise() -> None:
|
|
200
359
|
"""Test that the mitigated expectation is close to the ideal expectation
|
|
201
360
|
based on the Pauli string for multiple circuits"""
|
|
@@ -213,7 +372,7 @@ def test_many_circuits_input_measurement_with_noise() -> None:
|
|
|
213
372
|
circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
|
|
214
373
|
circuit_3 = cirq.FrozenCircuit(_create_ghz(8, qubits_3))
|
|
215
374
|
|
|
216
|
-
circuits_to_pauli:
|
|
375
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
217
376
|
circuits_to_pauli[circuit_1] = [_generate_random_pauli_string(qubits_1) for _ in range(3)]
|
|
218
377
|
circuits_to_pauli[circuit_2] = [_generate_random_pauli_string(qubits_2) for _ in range(3)]
|
|
219
378
|
circuits_to_pauli[circuit_3] = [_generate_random_pauli_string(qubits_3) for _ in range(3)]
|
|
@@ -261,7 +420,7 @@ def test_allow_measurement_without_readout_mitigation() -> None:
|
|
|
261
420
|
circuit = cirq.FrozenCircuit(_create_ghz(7, qubits))
|
|
262
421
|
sampler = NoisySingleQubitReadoutSampler(p0=0.1, p1=0.005, seed=1234)
|
|
263
422
|
|
|
264
|
-
circuits_to_pauli:
|
|
423
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
265
424
|
circuits_to_pauli[circuit] = [
|
|
266
425
|
_generate_random_pauli_string(qubits, True),
|
|
267
426
|
_generate_random_pauli_string(qubits),
|
|
@@ -285,6 +444,36 @@ def test_allow_measurement_without_readout_mitigation() -> None:
|
|
|
285
444
|
assert pauli_string_measurement_results.calibration_result is None
|
|
286
445
|
|
|
287
446
|
|
|
447
|
+
def test_allow_group_pauli_measurement_without_readout_mitigation() -> None:
|
|
448
|
+
"""Test that the function allows to measure without error mitigation"""
|
|
449
|
+
qubits = cirq.LineQubit.range(7)
|
|
450
|
+
circuit = cirq.FrozenCircuit(_create_ghz(7, qubits))
|
|
451
|
+
sampler = NoisySingleQubitReadoutSampler(p0=0.1, p1=0.005, seed=1234)
|
|
452
|
+
|
|
453
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[list[cirq.PauliString]]] = {}
|
|
454
|
+
circuits_to_pauli[circuit] = [
|
|
455
|
+
_generate_qwc_paulis(_generate_random_pauli_string(qubits, True), 2, True),
|
|
456
|
+
_generate_qwc_paulis(_generate_random_pauli_string(qubits), 4),
|
|
457
|
+
_generate_qwc_paulis(_generate_random_pauli_string(qubits), 6),
|
|
458
|
+
]
|
|
459
|
+
|
|
460
|
+
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
461
|
+
circuits_to_pauli, sampler, 100, 100, 0, np.random.default_rng()
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
|
|
465
|
+
assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
|
|
466
|
+
|
|
467
|
+
for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
|
|
468
|
+
# Since there's no mitigation, the mitigated and unmitigated expectations
|
|
469
|
+
# should be the same
|
|
470
|
+
assert np.isclose(
|
|
471
|
+
pauli_string_measurement_results.mitigated_expectation,
|
|
472
|
+
pauli_string_measurement_results.unmitigated_expectation,
|
|
473
|
+
)
|
|
474
|
+
assert pauli_string_measurement_results.calibration_result is None
|
|
475
|
+
|
|
476
|
+
|
|
288
477
|
def test_many_circuits_with_coefficient() -> None:
|
|
289
478
|
"""Test that the mitigated expectation is close to the ideal expectation
|
|
290
479
|
based on the Pauli string for multiple circuits"""
|
|
@@ -302,7 +491,7 @@ def test_many_circuits_with_coefficient() -> None:
|
|
|
302
491
|
circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
|
|
303
492
|
circuit_3 = cirq.FrozenCircuit(_create_ghz(8, qubits_3))
|
|
304
493
|
|
|
305
|
-
circuits_to_pauli:
|
|
494
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
306
495
|
circuits_to_pauli[circuit_1] = [_generate_random_pauli_string(qubits_1, True) for _ in range(3)]
|
|
307
496
|
circuits_to_pauli[circuit_2] = [_generate_random_pauli_string(qubits_2, True) for _ in range(3)]
|
|
308
497
|
circuits_to_pauli[circuit_3] = [_generate_random_pauli_string(qubits_3, True) for _ in range(3)]
|
|
@@ -344,6 +533,77 @@ def test_many_circuits_with_coefficient() -> None:
|
|
|
344
533
|
assert 0.0045 < error < 0.0055
|
|
345
534
|
|
|
346
535
|
|
|
536
|
+
def test_many_group_pauli_in_circuits_with_coefficient() -> None:
|
|
537
|
+
"""Test that the mitigated expectation is close to the ideal expectation
|
|
538
|
+
based on the Pauli string for multiple circuits"""
|
|
539
|
+
qubits_1 = cirq.LineQubit.range(3)
|
|
540
|
+
qubits_2 = [
|
|
541
|
+
cirq.GridQubit(0, 1),
|
|
542
|
+
cirq.GridQubit(1, 1),
|
|
543
|
+
cirq.GridQubit(1, 0),
|
|
544
|
+
cirq.GridQubit(1, 2),
|
|
545
|
+
cirq.GridQubit(2, 1),
|
|
546
|
+
]
|
|
547
|
+
qubits_3 = cirq.LineQubit.range(8)
|
|
548
|
+
|
|
549
|
+
circuit_1 = cirq.FrozenCircuit(_create_ghz(3, qubits_1))
|
|
550
|
+
circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
|
|
551
|
+
circuit_3 = cirq.FrozenCircuit(_create_ghz(8, qubits_3))
|
|
552
|
+
|
|
553
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[list[cirq.PauliString]]] = {}
|
|
554
|
+
circuits_to_pauli[circuit_1] = [
|
|
555
|
+
_generate_qwc_paulis(
|
|
556
|
+
_generate_random_pauli_string(qubits_1, enable_coeff=True, allow_pauli_i=False), 4
|
|
557
|
+
)
|
|
558
|
+
]
|
|
559
|
+
circuits_to_pauli[circuit_2] = [
|
|
560
|
+
_generate_qwc_paulis(
|
|
561
|
+
_generate_random_pauli_string(qubits_2, enable_coeff=True, allow_pauli_i=False), 5
|
|
562
|
+
)
|
|
563
|
+
]
|
|
564
|
+
circuits_to_pauli[circuit_3] = [
|
|
565
|
+
_generate_qwc_paulis(
|
|
566
|
+
_generate_random_pauli_string(qubits_3, enable_coeff=True, allow_pauli_i=False), 6
|
|
567
|
+
)
|
|
568
|
+
]
|
|
569
|
+
|
|
570
|
+
sampler = NoisySingleQubitReadoutSampler(p0=0.03, p1=0.005, seed=1234)
|
|
571
|
+
simulator = cirq.Simulator()
|
|
572
|
+
|
|
573
|
+
circuits_with_pauli_expectations = measure_pauli_strings(
|
|
574
|
+
circuits_to_pauli, sampler, 1000, 1000, 1000, np.random.default_rng()
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
for circuit_with_pauli_expectations in circuits_with_pauli_expectations:
|
|
578
|
+
assert isinstance(circuit_with_pauli_expectations.circuit, cirq.FrozenCircuit)
|
|
579
|
+
|
|
580
|
+
expected_val_simulation = simulator.simulate(
|
|
581
|
+
circuit_with_pauli_expectations.circuit.unfreeze()
|
|
582
|
+
)
|
|
583
|
+
final_state_vector = expected_val_simulation.final_state_vector
|
|
584
|
+
|
|
585
|
+
for pauli_string_measurement_results in circuit_with_pauli_expectations.results:
|
|
586
|
+
assert np.isclose(
|
|
587
|
+
pauli_string_measurement_results.mitigated_expectation,
|
|
588
|
+
_ideal_expectation_based_on_pauli_string(
|
|
589
|
+
pauli_string_measurement_results.pauli_string, final_state_vector
|
|
590
|
+
),
|
|
591
|
+
atol=4 * pauli_string_measurement_results.mitigated_stddev,
|
|
592
|
+
)
|
|
593
|
+
assert isinstance(
|
|
594
|
+
pauli_string_measurement_results.calibration_result,
|
|
595
|
+
SingleQubitReadoutCalibrationResult,
|
|
596
|
+
)
|
|
597
|
+
for (
|
|
598
|
+
error
|
|
599
|
+
) in pauli_string_measurement_results.calibration_result.zero_state_errors.values():
|
|
600
|
+
assert 0.025 < error < 0.035
|
|
601
|
+
for (
|
|
602
|
+
error
|
|
603
|
+
) in pauli_string_measurement_results.calibration_result.one_state_errors.values():
|
|
604
|
+
assert 0.0045 < error < 0.0055
|
|
605
|
+
|
|
606
|
+
|
|
347
607
|
def test_coefficient_not_real_number() -> None:
|
|
348
608
|
"""Test that the coefficient of input pauli string is not real.
|
|
349
609
|
Should return error in this case"""
|
|
@@ -351,7 +611,7 @@ def test_coefficient_not_real_number() -> None:
|
|
|
351
611
|
random_pauli_string = _generate_random_pauli_string(qubits_1, True) * (3 + 4j)
|
|
352
612
|
circuit_1 = cirq.FrozenCircuit(_create_ghz(3, qubits_1))
|
|
353
613
|
|
|
354
|
-
circuits_to_pauli:
|
|
614
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
355
615
|
circuits_to_pauli[circuit_1] = [
|
|
356
616
|
random_pauli_string,
|
|
357
617
|
_generate_random_pauli_string(qubits_1, True),
|
|
@@ -386,7 +646,7 @@ def test_invalid_input_circuit_type() -> None:
|
|
|
386
646
|
"""Test that the input circuit type is not frozen circuit"""
|
|
387
647
|
qubits = cirq.LineQubit.range(5)
|
|
388
648
|
|
|
389
|
-
qubits_to_pauli:
|
|
649
|
+
qubits_to_pauli: dict[tuple, list[cirq.PauliString]] = {}
|
|
390
650
|
qubits_to_pauli[tuple(qubits)] = [cirq.PauliString({q: cirq.X for q in qubits})]
|
|
391
651
|
with pytest.raises(
|
|
392
652
|
TypeError, match="All keys in 'circuits_to_pauli' must be FrozenCircuit instances."
|
|
@@ -415,13 +675,14 @@ def test_invalid_input_pauli_string_type() -> None:
|
|
|
415
675
|
circuit_1 = cirq.FrozenCircuit(_create_ghz(5, qubits_1))
|
|
416
676
|
circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
|
|
417
677
|
|
|
418
|
-
circuits_to_pauli:
|
|
419
|
-
circuits_to_pauli[circuit_1] =
|
|
678
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, cirq.FrozenCircuit] = {}
|
|
679
|
+
circuits_to_pauli[circuit_1] = [_generate_random_pauli_string(qubits_1)] # type: ignore
|
|
680
|
+
circuits_to_pauli[circuit_2] = [circuit_1, circuit_2] # type: ignore
|
|
420
681
|
|
|
421
682
|
with pytest.raises(
|
|
422
683
|
TypeError,
|
|
423
684
|
match="All elements in the Pauli string lists must be cirq.PauliString "
|
|
424
|
-
"instances, got <class 'cirq.circuits.
|
|
685
|
+
"instances, got <class 'cirq.circuits.frozen_circuit.FrozenCircuit'>.",
|
|
425
686
|
):
|
|
426
687
|
measure_pauli_strings(
|
|
427
688
|
circuits_to_pauli, # type: ignore[arg-type]
|
|
@@ -447,7 +708,7 @@ def test_all_pauli_strings_are_pauli_i() -> None:
|
|
|
447
708
|
circuit_1 = cirq.FrozenCircuit(_create_ghz(5, qubits_1))
|
|
448
709
|
circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
|
|
449
710
|
|
|
450
|
-
circuits_to_pauli:
|
|
711
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
451
712
|
circuits_to_pauli[circuit_1] = [
|
|
452
713
|
cirq.PauliString({q: cirq.I for q in qubits_1}),
|
|
453
714
|
cirq.PauliString({q: cirq.X for q in qubits_1}),
|
|
@@ -471,7 +732,7 @@ def test_zero_pauli_repetitions() -> None:
|
|
|
471
732
|
|
|
472
733
|
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
473
734
|
|
|
474
|
-
circuits_to_pauli:
|
|
735
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
475
736
|
circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
|
|
476
737
|
with pytest.raises(ValueError, match="Must provide non-zero pauli_repetitions."):
|
|
477
738
|
measure_pauli_strings(
|
|
@@ -485,7 +746,7 @@ def test_negative_num_random_bitstrings() -> None:
|
|
|
485
746
|
|
|
486
747
|
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
487
748
|
|
|
488
|
-
circuits_to_pauli:
|
|
749
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
489
750
|
circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
|
|
490
751
|
with pytest.raises(ValueError, match="Must provide zero or more num_random_bitstrings."):
|
|
491
752
|
measure_pauli_strings(
|
|
@@ -499,7 +760,7 @@ def test_zero_readout_repetitions() -> None:
|
|
|
499
760
|
|
|
500
761
|
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
501
762
|
|
|
502
|
-
circuits_to_pauli:
|
|
763
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
503
764
|
circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
|
|
504
765
|
with pytest.raises(
|
|
505
766
|
ValueError, match="Must provide non-zero readout_repetitions for readout" + " calibration."
|
|
@@ -515,9 +776,127 @@ def test_rng_type_mismatch() -> None:
|
|
|
515
776
|
|
|
516
777
|
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
517
778
|
|
|
518
|
-
circuits_to_pauli:
|
|
779
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
519
780
|
circuits_to_pauli[circuit] = [cirq.PauliString({q: cirq.X for q in qubits})]
|
|
520
781
|
with pytest.raises(ValueError, match="Must provide a numpy random generator or a seed"):
|
|
521
782
|
measure_pauli_strings(
|
|
522
783
|
circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, "test" # type: ignore[arg-type]
|
|
523
784
|
)
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
def test_pauli_type_mismatch() -> None:
|
|
788
|
+
"""Test that the input paulis are not a sequence of PauliStrings."""
|
|
789
|
+
qubits = cirq.LineQubit.range(5)
|
|
790
|
+
|
|
791
|
+
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
792
|
+
|
|
793
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, int] = {}
|
|
794
|
+
circuits_to_pauli[circuit] = 1
|
|
795
|
+
with pytest.raises(
|
|
796
|
+
TypeError,
|
|
797
|
+
match="Expected all elements to be either a sequence of PauliStrings or sequences of"
|
|
798
|
+
" ops.PauliStrings. Got <class 'int'> instead.",
|
|
799
|
+
):
|
|
800
|
+
measure_pauli_strings(
|
|
801
|
+
circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, "test" # type: ignore[arg-type]
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
def test_group_paulis_are_not_qwc() -> None:
|
|
806
|
+
"""Test that the group paulis are not qwc."""
|
|
807
|
+
qubits = cirq.LineQubit.range(5)
|
|
808
|
+
|
|
809
|
+
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
810
|
+
|
|
811
|
+
pauli_str1: cirq.PauliString = cirq.PauliString({qubits[0]: cirq.X, qubits[1]: cirq.Y})
|
|
812
|
+
pauli_str2: cirq.PauliString = cirq.PauliString({qubits[0]: cirq.Y})
|
|
813
|
+
|
|
814
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
815
|
+
circuits_to_pauli[circuit] = [[pauli_str1, pauli_str2]] # type: ignore
|
|
816
|
+
with pytest.raises(
|
|
817
|
+
ValueError, match="The group of Pauli strings are not Qubit-Wise Commuting with each other."
|
|
818
|
+
):
|
|
819
|
+
measure_pauli_strings(
|
|
820
|
+
circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, np.random.default_rng()
|
|
821
|
+
)
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
def test_empty_group_paulis_not_allowed() -> None:
|
|
825
|
+
"""Test that the group paulis are empty"""
|
|
826
|
+
qubits = cirq.LineQubit.range(5)
|
|
827
|
+
|
|
828
|
+
circuit = cirq.FrozenCircuit(_create_ghz(5, qubits))
|
|
829
|
+
|
|
830
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[cirq.PauliString]] = {}
|
|
831
|
+
circuits_to_pauli[circuit] = [[]] # type: ignore
|
|
832
|
+
with pytest.raises(ValueError, match="Empty group of Pauli strings is not allowed"):
|
|
833
|
+
measure_pauli_strings(
|
|
834
|
+
circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, np.random.default_rng()
|
|
835
|
+
)
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def test_group_paulis_type_mismatch() -> None:
|
|
839
|
+
"""Test that the group paulis type is not correct"""
|
|
840
|
+
qubits_1 = cirq.LineQubit.range(3)
|
|
841
|
+
qubits_2 = [
|
|
842
|
+
cirq.GridQubit(0, 1),
|
|
843
|
+
cirq.GridQubit(1, 1),
|
|
844
|
+
cirq.GridQubit(1, 0),
|
|
845
|
+
cirq.GridQubit(1, 2),
|
|
846
|
+
cirq.GridQubit(2, 1),
|
|
847
|
+
]
|
|
848
|
+
qubits_3 = cirq.LineQubit.range(8)
|
|
849
|
+
|
|
850
|
+
circuit_1 = cirq.FrozenCircuit(_create_ghz(3, qubits_1))
|
|
851
|
+
circuit_2 = cirq.FrozenCircuit(_create_ghz(5, qubits_2))
|
|
852
|
+
circuit_3 = cirq.FrozenCircuit(_create_ghz(8, qubits_3))
|
|
853
|
+
|
|
854
|
+
circuits_to_pauli: dict[cirq.FrozenCircuit, list[list[cirq.PauliString]]] = {}
|
|
855
|
+
circuits_to_pauli[circuit_1] = [
|
|
856
|
+
_generate_qwc_paulis(
|
|
857
|
+
_generate_random_pauli_string(qubits_1, enable_coeff=True, allow_pauli_i=False), 6
|
|
858
|
+
)
|
|
859
|
+
for _ in range(3)
|
|
860
|
+
]
|
|
861
|
+
circuits_to_pauli[circuit_2] = [_generate_random_pauli_string(qubits_2, True) for _ in range(3)]
|
|
862
|
+
circuits_to_pauli[circuit_3] = [_generate_random_pauli_string(qubits_3, True) for _ in range(3)]
|
|
863
|
+
|
|
864
|
+
with pytest.raises(
|
|
865
|
+
TypeError,
|
|
866
|
+
match="Expected all elements to be sequences of ops.PauliString, "
|
|
867
|
+
"but found <class 'cirq.ops.pauli_string.PauliString'>.",
|
|
868
|
+
):
|
|
869
|
+
measure_pauli_strings(
|
|
870
|
+
circuits_to_pauli, cirq.Simulator(), 1000, 1000, 1000, np.random.default_rng()
|
|
871
|
+
)
|
|
872
|
+
|
|
873
|
+
|
|
874
|
+
def test_process_pauli_measurement_results_raises_error_on_missing_calibration() -> None:
|
|
875
|
+
"""Test that the function raises an error if the calibration result is missing."""
|
|
876
|
+
qubits: Sequence[cirq.Qid] = cirq.LineQubit.range(5)
|
|
877
|
+
|
|
878
|
+
measurement_op = cirq.measure(*qubits, key='m')
|
|
879
|
+
test_circuits: list[cirq.Circuit] = [_create_ghz(5, qubits) + measurement_op for _ in range(3)]
|
|
880
|
+
|
|
881
|
+
pauli_strings = [_generate_random_pauli_string(qubits, True) for _ in range(3)]
|
|
882
|
+
sampler = cirq.Simulator()
|
|
883
|
+
|
|
884
|
+
circuit_results = sampler.run_batch(test_circuits, repetitions=1000)
|
|
885
|
+
|
|
886
|
+
pauli_strings_qubits = sorted(
|
|
887
|
+
set(itertools.chain.from_iterable(ps.qubits for ps in pauli_strings))
|
|
888
|
+
)
|
|
889
|
+
empty_calibration_result_dict = {tuple(pauli_strings_qubits): None}
|
|
890
|
+
|
|
891
|
+
with pytest.raises(
|
|
892
|
+
ValueError,
|
|
893
|
+
match="Readout mitigation is enabled, but no calibration result was found for qubits",
|
|
894
|
+
):
|
|
895
|
+
_process_pauli_measurement_results(
|
|
896
|
+
qubits,
|
|
897
|
+
[pauli_strings],
|
|
898
|
+
circuit_results[0], # type: ignore[arg-type]
|
|
899
|
+
empty_calibration_result_dict, # type: ignore[arg-type]
|
|
900
|
+
1000,
|
|
901
|
+
1.0,
|
|
902
|
+
)
|
|
@@ -12,15 +12,21 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
18
|
+
|
|
15
19
|
import networkx
|
|
16
20
|
|
|
17
21
|
from cirq import circuits, linalg
|
|
18
|
-
from cirq.contrib import circuitdag
|
|
19
22
|
from cirq.contrib.paulistring.pauli_string_dag import pauli_string_dag_from_circuit
|
|
20
23
|
from cirq.contrib.paulistring.recombine import move_pauli_strings_into_circuit
|
|
21
24
|
from cirq.contrib.paulistring.separate import convert_and_separate_circuit
|
|
22
25
|
from cirq.ops import PauliStringGateOperation
|
|
23
26
|
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from cirq.contrib import circuitdag
|
|
29
|
+
|
|
24
30
|
|
|
25
31
|
def pauli_string_optimized_circuit(
|
|
26
32
|
circuit: circuits.Circuit, move_cliffords: bool = True, atol: float = 1e-8
|
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import cirq
|
|
16
18
|
from cirq.contrib.paulistring import CliffordTargetGateset, pauli_string_optimized_circuit
|
|
17
19
|
|
|
18
20
|
|
|
19
|
-
def test_optimize():
|
|
21
|
+
def test_optimize() -> None:
|
|
20
22
|
q0, q1 = cirq.LineQubit.range(2)
|
|
21
23
|
c_orig = cirq.Circuit(
|
|
22
24
|
cirq.X(q0) ** 0.25, cirq.H(q0), cirq.CZ(q0, q1), cirq.H(q0), cirq.X(q0) ** 0.125
|
|
@@ -50,7 +52,7 @@ def test_optimize():
|
|
|
50
52
|
)
|
|
51
53
|
|
|
52
54
|
|
|
53
|
-
def test_handles_measurement_gate():
|
|
55
|
+
def test_handles_measurement_gate() -> None:
|
|
54
56
|
q0, q1 = cirq.LineQubit.range(2)
|
|
55
57
|
c_orig = cirq.Circuit(
|
|
56
58
|
cirq.X(q0) ** 0.25,
|
|
@@ -75,7 +77,7 @@ def test_handles_measurement_gate():
|
|
|
75
77
|
)
|
|
76
78
|
|
|
77
79
|
|
|
78
|
-
def test_optimize_large_circuit():
|
|
80
|
+
def test_optimize_large_circuit() -> None:
|
|
79
81
|
q0, q1, q2 = cirq.LineQubit.range(3)
|
|
80
82
|
c_orig = cirq.testing.nonoptimal_toffoli_circuit(q0, q1, q2)
|
|
81
83
|
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Any, Callable, cast, Iterable, Sequence
|
|
16
18
|
|
|
17
19
|
from cirq import circuits, ops, protocols
|
|
18
20
|
from cirq.contrib import circuitdag
|
|
@@ -26,7 +28,7 @@ def _sorted_best_string_placements(
|
|
|
26
28
|
possible_nodes: Iterable[Any],
|
|
27
29
|
output_ops: Sequence[ops.Operation],
|
|
28
30
|
key: Callable[[Any], ops.PauliStringPhasor] = lambda node: node.val,
|
|
29
|
-
) ->
|
|
31
|
+
) -> list[tuple[ops.PauliStringPhasor, int, circuitdag.Unique[ops.PauliStringPhasor]]]:
|
|
30
32
|
sort_key = lambda placement: (-len(placement[0].pauli_string), placement[1])
|
|
31
33
|
|
|
32
34
|
node_maxes = []
|
|
@@ -53,7 +55,7 @@ def _sorted_best_string_placements(
|
|
|
53
55
|
):
|
|
54
56
|
# This is as far through as this Pauli string can move
|
|
55
57
|
break
|
|
56
|
-
string_op = string_op.
|
|
58
|
+
string_op = string_op.conjugated_by(protocols.inverse(out_op))
|
|
57
59
|
curr = (string_op, i + 1, possible_node)
|
|
58
60
|
if sort_key(curr) > sort_key(node_max):
|
|
59
61
|
node_max = curr
|
|
@@ -64,7 +66,7 @@ def _sorted_best_string_placements(
|
|
|
64
66
|
|
|
65
67
|
|
|
66
68
|
def move_pauli_strings_into_circuit(
|
|
67
|
-
circuit_left:
|
|
69
|
+
circuit_left: circuits.Circuit | circuitdag.CircuitDag, circuit_right: circuits.Circuit
|
|
68
70
|
) -> circuits.Circuit:
|
|
69
71
|
if isinstance(circuit_left, circuitdag.CircuitDag):
|
|
70
72
|
string_dag = circuitdag.CircuitDag(pauli_string_reorder_pred, circuit_left)
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import cirq
|
|
16
18
|
from cirq.contrib.paulistring import (
|
|
17
19
|
convert_and_separate_circuit,
|
|
@@ -26,7 +28,7 @@ def _assert_no_multi_qubit_pauli_strings(circuit: cirq.Circuit) -> None:
|
|
|
26
28
|
assert len(op.pauli_string) == 1 # pragma: no cover
|
|
27
29
|
|
|
28
30
|
|
|
29
|
-
def test_move_non_clifford_into_clifford():
|
|
31
|
+
def test_move_non_clifford_into_clifford() -> None:
|
|
30
32
|
q0, q1, q2 = cirq.LineQubit.range(3)
|
|
31
33
|
c_orig = cirq.testing.nonoptimal_toffoli_circuit(q0, q1, q2)
|
|
32
34
|
|