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,14 +12,18 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from unittest import TestCase
|
|
16
|
+
from unittest.mock import Mock, patch
|
|
17
|
+
|
|
18
|
+
import pytest
|
|
19
|
+
import sympy
|
|
16
20
|
|
|
17
21
|
import cirq
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit):
|
|
21
25
|
# Ignore differences that would be caught by follow-up optimizations.
|
|
22
|
-
followup_transformers:
|
|
26
|
+
followup_transformers: list[cirq.TRANSFORMER] = [
|
|
23
27
|
cirq.drop_negligible_operations,
|
|
24
28
|
cirq.drop_empty_moments,
|
|
25
29
|
]
|
|
@@ -81,7 +85,7 @@ def test_merge_single_qubit_gates_to_phased_x_and_z_deep():
|
|
|
81
85
|
cirq.testing.assert_same_circuits(c_new, c_expected)
|
|
82
86
|
|
|
83
87
|
|
|
84
|
-
def _phxz(a: float, x: float, z: float):
|
|
88
|
+
def _phxz(a: float | sympy.Symbol, x: float | sympy.Symbol, z: float | sympy.Symbol):
|
|
85
89
|
return cirq.PhasedXZGate(axis_phase_exponent=a, x_exponent=x, z_exponent=z)
|
|
86
90
|
|
|
87
91
|
|
|
@@ -221,13 +225,181 @@ def test_merge_single_qubit_moments_to_phxz_deep():
|
|
|
221
225
|
)
|
|
222
226
|
|
|
223
227
|
|
|
224
|
-
def
|
|
228
|
+
def test_merge_single_qubit_gates_to_phxz_global_phase():
|
|
225
229
|
c = cirq.Circuit(cirq.GlobalPhaseGate(1j).on())
|
|
226
230
|
c2 = cirq.merge_single_qubit_gates_to_phxz(c)
|
|
227
231
|
assert c == c2
|
|
228
232
|
|
|
229
233
|
|
|
230
|
-
def
|
|
234
|
+
def test_merge_single_qubit_gates_to_phased_x_and_z_global_phase():
|
|
231
235
|
c = cirq.Circuit(cirq.GlobalPhaseGate(1j).on())
|
|
232
236
|
c2 = cirq.merge_single_qubit_gates_to_phased_x_and_z(c)
|
|
233
237
|
assert c == c2
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class TestMergeSingleQubitGatesSymbolized(TestCase):
|
|
241
|
+
"""Test suite for merge_single_qubit_gates_to_phxz_symbolized."""
|
|
242
|
+
|
|
243
|
+
def test_case1(self):
|
|
244
|
+
"""Test case diagram.
|
|
245
|
+
Input circuit:
|
|
246
|
+
0: ───X─────────@────────H[ignore]─H──X──PhXZ(a=a0,x=x0,z=z0)──X──PhXZ(a=a1,x=x1,z=z1)───
|
|
247
|
+
│
|
|
248
|
+
1: ───H^h_exp───@^cz_exp─────────────────────────────────────────────────────────────────
|
|
249
|
+
Expected output:
|
|
250
|
+
0: ───PhXZ(a=-1,x=1,z=0)─────@──────────H[ignore]───PhXZ(a=a1,x=x1,z=z1)───
|
|
251
|
+
│
|
|
252
|
+
1: ───PhXZ(a=a0,x=x0,z=z0)───@^cz_exp──────────────────────────────────────
|
|
253
|
+
"""
|
|
254
|
+
a, b = cirq.LineQubit.range(2)
|
|
255
|
+
sa0, sa1 = [sympy.Symbol(a) for a in ["a0", "a1"]]
|
|
256
|
+
sx0, sx1 = [sympy.Symbol(x) for x in ["x0", "x1"]]
|
|
257
|
+
sz0, sz1 = [sympy.Symbol(z) for z in ["z0", "z1"]]
|
|
258
|
+
input_circuit = cirq.Circuit(
|
|
259
|
+
cirq.Moment(cirq.X(a), cirq.H(b) ** sympy.Symbol("h_exp")),
|
|
260
|
+
cirq.Moment(cirq.CZ(a, b) ** sympy.Symbol("cz_exp")),
|
|
261
|
+
cirq.Moment(cirq.H(a).with_tags("ignore")),
|
|
262
|
+
cirq.Moment(cirq.H(a)),
|
|
263
|
+
cirq.Moment(cirq.X(a)),
|
|
264
|
+
cirq.Moment(_phxz(sa0, sx0, sz0).on(a)),
|
|
265
|
+
cirq.Moment(cirq.X(a)),
|
|
266
|
+
cirq.Moment(_phxz(sa1, sx1, sz1).on(a)),
|
|
267
|
+
)
|
|
268
|
+
context = cirq.TransformerContext(tags_to_ignore=["ignore"])
|
|
269
|
+
sweep = cirq.Zip(
|
|
270
|
+
cirq.Points(key="h_exp", points=[0, 1]),
|
|
271
|
+
cirq.Points(key="cz_exp", points=[0, 1]),
|
|
272
|
+
cirq.Points(key="a0", points=[0, 1]),
|
|
273
|
+
cirq.Points(key="x0", points=[0, 1]),
|
|
274
|
+
cirq.Points(key="z0", points=[0, 1]),
|
|
275
|
+
cirq.Points(key="a1", points=[0, 1]),
|
|
276
|
+
cirq.Points(key="x1", points=[0, 1]),
|
|
277
|
+
cirq.Points(key="z1", points=[0, 1]),
|
|
278
|
+
)
|
|
279
|
+
output_circuit, new_sweep = cirq.merge_single_qubit_gates_to_phxz_symbolized(
|
|
280
|
+
input_circuit, context=context, sweep=sweep
|
|
281
|
+
)
|
|
282
|
+
expected = cirq.Circuit(
|
|
283
|
+
cirq.Moment(_phxz(-1, 1, 0).on(a), _phxz(sa0, sx0, sz0).on(b)),
|
|
284
|
+
cirq.Moment(cirq.CZ(a, b) ** sympy.Symbol("cz_exp")),
|
|
285
|
+
cirq.Moment(cirq.H(a).with_tags("ignore")),
|
|
286
|
+
cirq.Moment(_phxz(sa1, sx1, sz1).on(a)),
|
|
287
|
+
)
|
|
288
|
+
assert_optimizes(output_circuit, expected)
|
|
289
|
+
|
|
290
|
+
# Check the unitaries are preserved for each set of sweep parameterization.
|
|
291
|
+
for old_resolver, new_resolver in zip(sweep, new_sweep):
|
|
292
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
293
|
+
cirq.resolve_parameters(input_circuit, old_resolver),
|
|
294
|
+
cirq.resolve_parameters(output_circuit, new_resolver),
|
|
295
|
+
{q: q for q in input_circuit.all_qubits()},
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
def test_with_gauge_compiling_as_sweep_success(self):
|
|
299
|
+
qubits = cirq.LineQubit.range(7)
|
|
300
|
+
c = cirq.Circuit(
|
|
301
|
+
cirq.Moment(cirq.H(qubits[0]), cirq.H(qubits[3])),
|
|
302
|
+
cirq.Moment(cirq.CZ(qubits[0], qubits[2]), cirq.CZ(qubits[3], qubits[5])),
|
|
303
|
+
cirq.Moment(cirq.CZ(qubits[0], qubits[1]), cirq.CZ(qubits[3], qubits[4])),
|
|
304
|
+
cirq.Moment(cirq.CZ(qubits[1], qubits[3]), cirq.CZ(qubits[4], qubits[6])),
|
|
305
|
+
cirq.Moment(cirq.M(*qubits, key='m')),
|
|
306
|
+
)
|
|
307
|
+
old_circuit, old_sweep = cirq.transformers.gauge_compiling.CZGaugeTransformer.as_sweep(
|
|
308
|
+
c, N=50
|
|
309
|
+
)
|
|
310
|
+
new_circuit, new_sweep = cirq.merge_single_qubit_gates_to_phxz_symbolized(
|
|
311
|
+
old_circuit, sweep=old_sweep
|
|
312
|
+
)
|
|
313
|
+
# Check the unitaries are preserved for each set of sweep parameterization.
|
|
314
|
+
for old_resolver, new_resolver in zip(old_sweep, new_sweep):
|
|
315
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
316
|
+
cirq.resolve_parameters(old_circuit[0:-1], old_resolver),
|
|
317
|
+
cirq.resolve_parameters(new_circuit[0:-1], new_resolver),
|
|
318
|
+
{q: q for q in qubits},
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
def test_case_non_parameterized_singles(self):
|
|
322
|
+
"""Test merge_single_qubit_gates_to_phxz_symbolized when all single qubit gates are not
|
|
323
|
+
parameterized."""
|
|
324
|
+
|
|
325
|
+
a, b = cirq.LineQubit.range(2)
|
|
326
|
+
input_circuit = cirq.Circuit(cirq.H(a), cirq.H(a), cirq.CZ(a, b) ** sympy.Symbol("exp"))
|
|
327
|
+
expected_circuit = cirq.merge_single_qubit_gates_to_phxz(input_circuit)
|
|
328
|
+
output_circuit, _ = cirq.merge_single_qubit_gates_to_phxz_symbolized(
|
|
329
|
+
input_circuit, sweep=cirq.Points(key="exp", points=[0.1, 0.2, 0.5])
|
|
330
|
+
)
|
|
331
|
+
assert_optimizes(output_circuit, expected_circuit)
|
|
332
|
+
|
|
333
|
+
def test_fail_different_structures_error(self):
|
|
334
|
+
"""Tests that the function raises a ValueError if merged structures of the circuit differ
|
|
335
|
+
for different parameterizations."""
|
|
336
|
+
q0, q1 = cirq.LineQubit.range(2)
|
|
337
|
+
circuit = cirq.Circuit(cirq.H(q0) ** sympy.Symbol("exp"))
|
|
338
|
+
sweep = cirq.Points(key="exp", points=[0.1, 0.2])
|
|
339
|
+
|
|
340
|
+
with patch(
|
|
341
|
+
"cirq.protocols.resolve_parameters",
|
|
342
|
+
side_effect=[ # Mock the return values of resolve_parameters
|
|
343
|
+
cirq.Circuit(cirq.I(q0).with_tags("_tmp_symbolize_tag")),
|
|
344
|
+
cirq.Circuit(cirq.CZ(q0, q1)),
|
|
345
|
+
],
|
|
346
|
+
):
|
|
347
|
+
with pytest.raises(ValueError, match="Expect a PhasedXZGate or IdentityGate.*"):
|
|
348
|
+
cirq.merge_single_qubit_gates_to_phxz_symbolized(circuit, sweep=sweep)
|
|
349
|
+
|
|
350
|
+
def test_fail_unexpected_gate_error(self):
|
|
351
|
+
"""Tests that the function raises a RuntimeError of unexpected gate."""
|
|
352
|
+
a, b = cirq.LineQubit.range(2)
|
|
353
|
+
circuit = cirq.Circuit(
|
|
354
|
+
cirq.H(a) ** sympy.Symbol("exp1"),
|
|
355
|
+
cirq.X(a),
|
|
356
|
+
cirq.CZ(a, b),
|
|
357
|
+
cirq.Y(a),
|
|
358
|
+
cirq.H(a) ** sympy.Symbol("exp2"),
|
|
359
|
+
)
|
|
360
|
+
sweep = cirq.Points(key="exp1", points=[0.1, 0.2]) * cirq.Points(
|
|
361
|
+
key="exp2", points=[0.1, 0.2]
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
mock_iter = Mock()
|
|
365
|
+
mock_iter.__next__ = Mock(return_value=2)
|
|
366
|
+
|
|
367
|
+
with patch(
|
|
368
|
+
"cirq.transformers.analytical_decompositions"
|
|
369
|
+
".single_qubit_decompositions.single_qubit_matrix_to_phxz",
|
|
370
|
+
return_value=cirq.H,
|
|
371
|
+
):
|
|
372
|
+
with pytest.raises(ValueError, match="Expect a PhasedXZGate or IdentityGate.*"):
|
|
373
|
+
cirq.merge_single_qubit_gates_to_phxz_symbolized(circuit, sweep=sweep)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_first_moment():
|
|
377
|
+
q0 = cirq.LineQubit(0)
|
|
378
|
+
c_orig = cirq.Circuit(
|
|
379
|
+
cirq.Moment(cirq.Y(q0) ** 0.5, cirq.GlobalPhaseGate(1j**0.5).on()), cirq.Moment(cirq.X(q0))
|
|
380
|
+
)
|
|
381
|
+
c_expected = cirq.Circuit(
|
|
382
|
+
cirq.Moment(
|
|
383
|
+
cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=-1.0).on(q0),
|
|
384
|
+
cirq.GlobalPhaseGate(1j**0.5).on(),
|
|
385
|
+
)
|
|
386
|
+
)
|
|
387
|
+
context = cirq.TransformerContext(tags_to_ignore=["ignore"])
|
|
388
|
+
c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context)
|
|
389
|
+
assert c_new == c_expected
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_second_moment():
|
|
393
|
+
q0 = cirq.LineQubit(0)
|
|
394
|
+
c_orig = cirq.Circuit(
|
|
395
|
+
cirq.Moment(cirq.Y(q0) ** 0.5), cirq.Moment(cirq.X(q0), cirq.GlobalPhaseGate(1j**0.5).on())
|
|
396
|
+
)
|
|
397
|
+
c_expected = cirq.Circuit(
|
|
398
|
+
cirq.Moment(
|
|
399
|
+
cirq.PhasedXZGate(axis_phase_exponent=-0.5, x_exponent=0.5, z_exponent=-1.0).on(q0),
|
|
400
|
+
cirq.GlobalPhaseGate(1j**0.5).on(),
|
|
401
|
+
)
|
|
402
|
+
)
|
|
403
|
+
context = cirq.TransformerContext(tags_to_ignore=["ignore"])
|
|
404
|
+
c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context)
|
|
405
|
+
assert c_new == c_expected
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from collections.abc import Mapping
|
|
16
18
|
from typing import cast
|
|
17
19
|
|
|
@@ -34,7 +36,7 @@ class DepolarizingNoiseTransformer:
|
|
|
34
36
|
|
|
35
37
|
Attrs:
|
|
36
38
|
p: The probability with which to add noise.
|
|
37
|
-
target_gate: Add depolarizing
|
|
39
|
+
target_gate: Add depolarizing noise after this type of gate
|
|
38
40
|
"""
|
|
39
41
|
|
|
40
42
|
def __init__(
|
|
@@ -56,7 +58,7 @@ class DepolarizingNoiseTransformer:
|
|
|
56
58
|
if not isinstance(p, (Mapping, float)):
|
|
57
59
|
raise TypeError( # pragma: no cover
|
|
58
60
|
"p must either be a float or a mapping from" # pragma: no cover
|
|
59
|
-
|
|
61
|
+
"sorted qubit pairs to floats" # pragma: no cover
|
|
60
62
|
) # pragma: no cover
|
|
61
63
|
self.p = p
|
|
62
64
|
self.p_func = (
|
|
@@ -86,7 +88,7 @@ class DepolarizingNoiseTransformer:
|
|
|
86
88
|
rng = np.random.default_rng()
|
|
87
89
|
target_gate = self.target_gate
|
|
88
90
|
|
|
89
|
-
# add random Pauli gates with probability p after each
|
|
91
|
+
# add random Pauli gates with probability p after each specified gate
|
|
90
92
|
assert target_gate.num_qubits() == 2, "`target_gate` must be a two-qubit gate."
|
|
91
93
|
paulis = [ops.I, ops.X, ops.Y, ops.Z]
|
|
92
94
|
new_moments = []
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
"""Transformers to rewrite a circuit using gates from a given target gateset."""
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Callable, Hashable, Sequence, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
from cirq import circuits
|
|
20
22
|
from cirq.protocols import decompose_protocol as dp
|
|
@@ -24,8 +26,8 @@ if TYPE_CHECKING:
|
|
|
24
26
|
import cirq
|
|
25
27
|
|
|
26
28
|
|
|
27
|
-
def _create_on_stuck_raise_error(gateset:
|
|
28
|
-
def _value_error_describing_bad_operation(op:
|
|
29
|
+
def _create_on_stuck_raise_error(gateset: cirq.Gateset):
|
|
30
|
+
def _value_error_describing_bad_operation(op: cirq.Operation) -> ValueError:
|
|
29
31
|
return ValueError(f"Unable to convert {op} to target gateset {gateset!r}")
|
|
30
32
|
|
|
31
33
|
return _value_error_describing_bad_operation
|
|
@@ -33,20 +35,20 @@ def _create_on_stuck_raise_error(gateset: 'cirq.Gateset'):
|
|
|
33
35
|
|
|
34
36
|
@transformer_api.transformer
|
|
35
37
|
def _decompose_operations_to_target_gateset(
|
|
36
|
-
circuit:
|
|
38
|
+
circuit: cirq.AbstractCircuit,
|
|
37
39
|
*,
|
|
38
|
-
context:
|
|
39
|
-
gateset:
|
|
40
|
-
decomposer: Callable[[
|
|
40
|
+
context: cirq.TransformerContext | None = None,
|
|
41
|
+
gateset: cirq.Gateset | None = None,
|
|
42
|
+
decomposer: Callable[[cirq.Operation, int], dp.DecomposeResult] = lambda *_: NotImplemented,
|
|
41
43
|
ignore_failures: bool = True,
|
|
42
44
|
tags_to_decompose: Sequence[Hashable] = (),
|
|
43
|
-
) ->
|
|
45
|
+
) -> cirq.Circuit:
|
|
44
46
|
"""Decomposes every operation to `gateset` using `cirq.decompose` and `decomposer`.
|
|
45
47
|
|
|
46
48
|
This transformer attempts to decompose every operation `op` in the given circuit to `gateset`
|
|
47
|
-
using `cirq.decompose` protocol with `decomposer` used as an intercepting decomposer. This
|
|
48
|
-
ensures that `op` is recursively decomposed using implicitly defined known decompositions
|
|
49
|
-
|
|
49
|
+
using the `cirq.decompose` protocol with `decomposer` used as an intercepting decomposer. This
|
|
50
|
+
ensures that `op` is recursively decomposed using implicitly defined known decompositions (e.g.
|
|
51
|
+
in the `_decompose_` magic method on the gate class) until either `decomposer` knows how to
|
|
50
52
|
decompose the given operation or the given operation belongs to `gateset`.
|
|
51
53
|
|
|
52
54
|
Args:
|
|
@@ -68,7 +70,7 @@ def _decompose_operations_to_target_gateset(
|
|
|
68
70
|
ValueError: If any input operation fails to convert and `ignore_failures` is False.
|
|
69
71
|
"""
|
|
70
72
|
|
|
71
|
-
def map_func(op:
|
|
73
|
+
def map_func(op: cirq.Operation, moment_index: int):
|
|
72
74
|
if (
|
|
73
75
|
context
|
|
74
76
|
and context.deep
|
|
@@ -97,13 +99,13 @@ def _decompose_operations_to_target_gateset(
|
|
|
97
99
|
|
|
98
100
|
@transformer_api.transformer
|
|
99
101
|
def optimize_for_target_gateset(
|
|
100
|
-
circuit:
|
|
102
|
+
circuit: cirq.AbstractCircuit,
|
|
101
103
|
*,
|
|
102
|
-
context:
|
|
103
|
-
gateset:
|
|
104
|
+
context: cirq.TransformerContext | None = None,
|
|
105
|
+
gateset: cirq.CompilationTargetGateset | None = None,
|
|
104
106
|
ignore_failures: bool = True,
|
|
105
|
-
max_num_passes:
|
|
106
|
-
) ->
|
|
107
|
+
max_num_passes: int | None = 1,
|
|
108
|
+
) -> cirq.Circuit:
|
|
107
109
|
"""Transforms the given circuit into an equivalent circuit using gates accepted by `gateset`.
|
|
108
110
|
|
|
109
111
|
Repeat max_num_passes times or when `max_num_passes=None` until no further changes can be done
|
|
@@ -12,14 +12,18 @@
|
|
|
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 TYPE_CHECKING
|
|
16
18
|
|
|
17
19
|
import pytest
|
|
18
20
|
|
|
19
21
|
import cirq
|
|
20
|
-
from cirq.protocols.decompose_protocol import DecomposeResult
|
|
21
22
|
from cirq.transformers.optimize_for_target_gateset import _decompose_operations_to_target_gateset
|
|
22
23
|
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from cirq.protocols.decompose_protocol import DecomposeResult
|
|
26
|
+
|
|
23
27
|
|
|
24
28
|
def test_decompose_operations_raises_on_stuck():
|
|
25
29
|
c_orig = cirq.Circuit(cirq.X(cirq.NamedQubit("q")).with_tags("ignore"))
|
|
@@ -37,7 +41,6 @@ def test_decompose_operations_raises_on_stuck():
|
|
|
37
41
|
cirq.testing.assert_same_circuits(c_orig, c_new)
|
|
38
42
|
|
|
39
43
|
|
|
40
|
-
# pylint: disable=line-too-long
|
|
41
44
|
def test_decompose_operations_to_target_gateset_default():
|
|
42
45
|
q = cirq.LineQubit.range(2)
|
|
43
46
|
c_orig = cirq.Circuit(
|
|
@@ -70,7 +73,7 @@ m: ═════════════════════════
|
|
|
70
73
|
1: ───────Y^-0.5───@───Y^0.5────@───Y^-0.5───@───Y^0.5───────×───────────╫───X───T───Y^-0.5───@───Y^0.5────@───Y^-0.5───@───Y^0.5───T───
|
|
71
74
|
║ ║
|
|
72
75
|
m: ══════════════════════════════════════════════════════════════════════@═══^══════════════════════════════════════════════════════════
|
|
73
|
-
''',
|
|
76
|
+
''', # noqa: E501
|
|
74
77
|
)
|
|
75
78
|
|
|
76
79
|
|
|
@@ -121,7 +124,7 @@ class MatrixGateTargetGateset(cirq.CompilationTargetGateset):
|
|
|
121
124
|
def num_qubits(self) -> int:
|
|
122
125
|
return 2
|
|
123
126
|
|
|
124
|
-
def decompose_to_target_gateset(self, op:
|
|
127
|
+
def decompose_to_target_gateset(self, op: cirq.Operation, _) -> DecomposeResult:
|
|
125
128
|
if cirq.num_qubits(op) != 2 or not cirq.has_unitary(op):
|
|
126
129
|
return NotImplemented
|
|
127
130
|
return cirq.MatrixGate(cirq.unitary(op), name="M").on(*op.qubits)
|
|
@@ -188,7 +191,7 @@ m: ═════════════════════@═══^═
|
|
|
188
191
|
║ ║
|
|
189
192
|
m: ═══════════════════════════════════════════════════════════════@═══^═════════════════════════════════════════════════════════
|
|
190
193
|
└────────┘ └────────┘ └────────┘
|
|
191
|
-
''',
|
|
194
|
+
''', # noqa: E501
|
|
192
195
|
)
|
|
193
196
|
|
|
194
197
|
with pytest.raises(ValueError, match="Unable to convert"):
|
|
@@ -249,7 +252,7 @@ def test_optimize_for_target_gateset_deep():
|
|
|
249
252
|
|
|
250
253
|
|
|
251
254
|
@pytest.mark.parametrize('max_num_passes', [2, None])
|
|
252
|
-
def test_optimize_for_target_gateset_multiple_passes(max_num_passes:
|
|
255
|
+
def test_optimize_for_target_gateset_multiple_passes(max_num_passes: int | None):
|
|
253
256
|
gateset = cirq.CZTargetGateset()
|
|
254
257
|
|
|
255
258
|
input_circuit = cirq.Circuit(
|
|
@@ -328,7 +331,7 @@ def test_optimize_for_target_gateset_multiple_passes(max_num_passes: Union[int,
|
|
|
328
331
|
|
|
329
332
|
@pytest.mark.parametrize('max_num_passes', [2, None])
|
|
330
333
|
def test_optimize_for_target_gateset_multiple_passes_dont_preserve_moment_structure(
|
|
331
|
-
max_num_passes:
|
|
334
|
+
max_num_passes: int | None,
|
|
332
335
|
):
|
|
333
336
|
gateset = cirq.CZTargetGateset(preserve_moment_structure=False)
|
|
334
337
|
|
|
@@ -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 TYPE_CHECKING
|
|
16
18
|
|
|
17
19
|
from cirq import circuits, ops
|
|
18
20
|
|
|
@@ -21,8 +23,8 @@ if TYPE_CHECKING:
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
def _get_qubit_mapping_first_and_last_moment(
|
|
24
|
-
circuit:
|
|
25
|
-
) ->
|
|
26
|
+
circuit: cirq.AbstractCircuit,
|
|
27
|
+
) -> dict[cirq.Qid, tuple[int, int]]:
|
|
26
28
|
"""Computes `(first_moment_idx, last_moment_idx)` tuple for each qubit in the input circuit.
|
|
27
29
|
|
|
28
30
|
Args:
|
|
@@ -41,13 +43,13 @@ def _get_qubit_mapping_first_and_last_moment(
|
|
|
41
43
|
return ret
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
def _is_temp(q:
|
|
46
|
+
def _is_temp(q: cirq.Qid) -> bool:
|
|
45
47
|
return isinstance(q, (ops.CleanQubit, ops.BorrowableQubit))
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
def map_clean_and_borrowable_qubits(
|
|
49
|
-
circuit:
|
|
50
|
-
) ->
|
|
51
|
+
circuit: cirq.AbstractCircuit, *, qm: cirq.QubitManager | None = None
|
|
52
|
+
) -> cirq.Circuit:
|
|
51
53
|
"""Uses `qm: QubitManager` to map all `CleanQubit`/`BorrowableQubit`s to system qubits.
|
|
52
54
|
|
|
53
55
|
`CleanQubit` and `BorrowableQubit` are internal qubit types that are used as placeholder qubits
|
|
@@ -56,7 +58,7 @@ def map_clean_and_borrowable_qubits(
|
|
|
56
58
|
This transformer uses the `QubitManager` provided in the input to:
|
|
57
59
|
- Allocate clean ancilla qubits by delegating to `qm.qalloc` for all `CleanQubit`s.
|
|
58
60
|
- Allocate dirty qubits for all `BorrowableQubit` types via the following two steps:
|
|
59
|
-
1. First
|
|
61
|
+
1. First analyze the input circuit and check if there are any suitable system qubits
|
|
60
62
|
that can be borrowed, i.e. ones which do not have any overlapping operations
|
|
61
63
|
between circuit[start_index : end_index] where `(start_index, end_index)` is the
|
|
62
64
|
lifespan of temporary borrowable qubit under consideration. If yes, borrow the system
|
|
@@ -82,7 +84,7 @@ def map_clean_and_borrowable_qubits(
|
|
|
82
84
|
circuit: Input `cirq.Circuit` containing temporarily allocated
|
|
83
85
|
`CleanQubit`/`BorrowableQubit`s.
|
|
84
86
|
qm: An instance of `cirq.QubitManager` specifying the strategy to use for allocating /
|
|
85
|
-
|
|
87
|
+
deallocating new ancilla qubits to replace the temporary qubits.
|
|
86
88
|
|
|
87
89
|
Returns:
|
|
88
90
|
An updated `cirq.Circuit` with all `CleanQubit`/`BorrowableQubit` mapped to either existing
|
|
@@ -97,11 +99,11 @@ def map_clean_and_borrowable_qubits(
|
|
|
97
99
|
trivial_map = {q: q for q in all_qubits}
|
|
98
100
|
# `allocated_map` maintains the mapping of all temporary qubits seen so far, mapping each of
|
|
99
101
|
# them to either a newly allocated managed ancilla or an existing borrowed system qubit.
|
|
100
|
-
allocated_map:
|
|
101
|
-
to_free:
|
|
102
|
+
allocated_map: dict[cirq.Qid, cirq.Qid] = {}
|
|
103
|
+
to_free: set[cirq.Qid] = set()
|
|
102
104
|
last_op_idx = -1
|
|
103
105
|
|
|
104
|
-
def map_func(op:
|
|
106
|
+
def map_func(op: cirq.Operation, idx: int) -> cirq.OP_TREE:
|
|
105
107
|
nonlocal last_op_idx, to_free
|
|
106
108
|
assert isinstance(qm, ops.QubitManager)
|
|
107
109
|
|
|
@@ -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
|
|
|
17
19
|
|
|
@@ -66,7 +68,7 @@ def get_decompose_func(gate_type, qm):
|
|
|
66
68
|
return decompose_func
|
|
67
69
|
|
|
68
70
|
|
|
69
|
-
def test_map_clean_and_borrowable_qubits_greedy_types():
|
|
71
|
+
def test_map_clean_and_borrowable_qubits_greedy_types() -> None:
|
|
70
72
|
qm = cirq.ops.SimpleQubitManager()
|
|
71
73
|
q = cirq.LineQubit.range(2)
|
|
72
74
|
g = GateAllocInDecompose(1)
|
|
@@ -130,7 +132,7 @@ ancilla_1: ───X───X───
|
|
|
130
132
|
)
|
|
131
133
|
|
|
132
134
|
|
|
133
|
-
def test_map_clean_and_borrowable_qubits_borrows():
|
|
135
|
+
def test_map_clean_and_borrowable_qubits_borrows() -> None:
|
|
134
136
|
qm = cirq.ops.SimpleQubitManager()
|
|
135
137
|
op = GateAllocAndBorrowInDecompose(3).on(cirq.NamedQubit("original"))
|
|
136
138
|
extra = cirq.LineQubit.range(3)
|
|
@@ -233,7 +235,7 @@ original: ────@───@───@───@─────@───@
|
|
|
233
235
|
)
|
|
234
236
|
|
|
235
237
|
|
|
236
|
-
def test_map_clean_and_borrowable_qubits_deallocates_only_once():
|
|
238
|
+
def test_map_clean_and_borrowable_qubits_deallocates_only_once() -> None:
|
|
237
239
|
q = [cirq.ops.BorrowableQubit(i) for i in range(2)] + [cirq.q('q')]
|
|
238
240
|
circuit = cirq.Circuit(cirq.X.on_each(*q), cirq.Y(q[1]), cirq.Z(q[1]))
|
|
239
241
|
greedy_mm = cirq.GreedyQubitManager(prefix="a", size=2)
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from collections.abc import Sequence
|
|
16
18
|
from typing import Any
|
|
17
19
|
|
|
@@ -32,23 +34,23 @@ class RandomizedMeasurements:
|
|
|
32
34
|
For more details on the randomized measurement toolbox see https://arxiv.org/abs/2203.11374
|
|
33
35
|
|
|
34
36
|
Args:
|
|
35
|
-
subsystem: The specific subsystem (e.g qubit index) to measure in random basis
|
|
36
|
-
|
|
37
|
+
subsystem: The specific subsystem (e.g., qubit index) to measure in a random basis.
|
|
38
|
+
The rest of the qubits are measured in the computational basis.
|
|
37
39
|
"""
|
|
38
40
|
self.subsystem = subsystem
|
|
39
41
|
|
|
40
42
|
def __call__(
|
|
41
43
|
self,
|
|
42
|
-
circuit:
|
|
44
|
+
circuit: cirq.AbstractCircuit,
|
|
43
45
|
unitary_ensemble: str = "pauli",
|
|
44
46
|
rng: np.random.Generator | None = None,
|
|
45
47
|
*,
|
|
46
48
|
context: transformer_api.TransformerContext | None = None,
|
|
47
|
-
) ->
|
|
49
|
+
) -> cirq.Circuit:
|
|
48
50
|
"""Apply the transformer to the given circuit. Given an input circuit returns
|
|
49
|
-
a new circuit with the pre-measurement unitaries and
|
|
50
|
-
to the qubits in the subsystem provided.If no subsystem is specified in the
|
|
51
|
-
construction of this class it defaults to measuring all the qubits in the
|
|
51
|
+
a new circuit with the pre-measurement unitaries and measurement gates added
|
|
52
|
+
to the qubits in the subsystem provided. If no subsystem is specified in the
|
|
53
|
+
construction of this class, it defaults to measuring all the qubits in the
|
|
52
54
|
randomized bases.
|
|
53
55
|
|
|
54
56
|
Args:
|
|
@@ -80,7 +82,7 @@ class RandomizedMeasurements:
|
|
|
80
82
|
|
|
81
83
|
def random_single_qubit_unitary_moment(
|
|
82
84
|
self, unitary_ensemble: str, qubits: Sequence[Any], rng: np.random.Generator
|
|
83
|
-
) ->
|
|
85
|
+
) -> cirq.Moment:
|
|
84
86
|
"""Outputs the cirq moment associated with the pre-measurement rotations.
|
|
85
87
|
|
|
86
88
|
Args:
|
|
@@ -115,7 +117,7 @@ class RandomizedMeasurements:
|
|
|
115
117
|
return cirq.Moment.from_ops(*op_list)
|
|
116
118
|
|
|
117
119
|
|
|
118
|
-
def _pauli_basis_rotation(rng: np.random.Generator) ->
|
|
120
|
+
def _pauli_basis_rotation(rng: np.random.Generator) -> cirq.Gate:
|
|
119
121
|
"""Randomly generate a Pauli basis rotation.
|
|
120
122
|
|
|
121
123
|
Args:
|
|
@@ -127,7 +129,7 @@ def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
|
|
|
127
129
|
basis_idx = rng.choice(np.arange(3))
|
|
128
130
|
|
|
129
131
|
if basis_idx == 0:
|
|
130
|
-
gate:
|
|
132
|
+
gate: cirq.Gate = cirq.Ry(rads=-np.pi / 2)
|
|
131
133
|
elif basis_idx == 1:
|
|
132
134
|
gate = cirq.Rx(rads=np.pi / 2)
|
|
133
135
|
else:
|
|
@@ -135,8 +137,8 @@ def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
|
|
|
135
137
|
return gate
|
|
136
138
|
|
|
137
139
|
|
|
138
|
-
def _single_qubit_clifford(rng: np.random.Generator) ->
|
|
139
|
-
"""Randomly
|
|
140
|
+
def _single_qubit_clifford(rng: np.random.Generator) -> cirq.Gate:
|
|
141
|
+
"""Randomly generates a single-qubit Clifford rotation.
|
|
140
142
|
|
|
141
143
|
Args:
|
|
142
144
|
rng: Random number generator
|
|
@@ -153,8 +155,8 @@ def _single_qubit_clifford(rng: np.random.Generator) -> "cirq.Gate":
|
|
|
153
155
|
)
|
|
154
156
|
|
|
155
157
|
|
|
156
|
-
def _single_qubit_cue(rng: np.random.Generator) ->
|
|
157
|
-
"""Randomly
|
|
158
|
+
def _single_qubit_cue(rng: np.random.Generator) -> cirq.Gate:
|
|
159
|
+
"""Randomly generates a CUE gate.
|
|
158
160
|
|
|
159
161
|
Args:
|
|
160
162
|
rng: Random number generator
|
|
@@ -12,13 +12,15 @@
|
|
|
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 pytest
|
|
16
18
|
|
|
17
19
|
import cirq
|
|
18
20
|
import cirq.transformers.randomized_measurements as rand_meas
|
|
19
21
|
|
|
20
22
|
|
|
21
|
-
def test_randomized_measurements_appends_two_moments_on_returned_circuit():
|
|
23
|
+
def test_randomized_measurements_appends_two_moments_on_returned_circuit() -> None:
|
|
22
24
|
# Create a 4-qubit circuit
|
|
23
25
|
q0, q1, q2, q3 = cirq.LineQubit.range(4)
|
|
24
26
|
circuit_pre = cirq.Circuit(
|
|
@@ -34,7 +36,9 @@ def test_randomized_measurements_appends_two_moments_on_returned_circuit():
|
|
|
34
36
|
assert num_moments_post == num_moments_pre + 2
|
|
35
37
|
|
|
36
38
|
|
|
37
|
-
def test_append_randomized_measurements_leaves_qubits_not_in_specified_subsystem_unchanged()
|
|
39
|
+
def test_append_randomized_measurements_leaves_qubits_not_in_specified_subsystem_unchanged() -> (
|
|
40
|
+
None
|
|
41
|
+
):
|
|
38
42
|
# Create a 4-qubit circuit
|
|
39
43
|
q0, q1, q2, q3 = cirq.LineQubit.range(4)
|
|
40
44
|
circuit = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q1, q2), cirq.CNOT(q2, q3)])
|
|
@@ -46,7 +50,9 @@ def test_append_randomized_measurements_leaves_qubits_not_in_specified_subsystem
|
|
|
46
50
|
assert circuit.operation_at(q3, 4) is None
|
|
47
51
|
|
|
48
52
|
|
|
49
|
-
def
|
|
53
|
+
def test_append_random_measurements_leaves_qubits_not_in_noncontinuous_subsystem_unchanged() -> (
|
|
54
|
+
None
|
|
55
|
+
):
|
|
50
56
|
# Create a 4-qubit circuit
|
|
51
57
|
q0, q1, q2, q3 = cirq.LineQubit.range(4)
|
|
52
58
|
circuit = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q1, q2), cirq.CNOT(q2, q3)])
|
|
@@ -59,7 +65,7 @@ def test_append_randomized_measurements_leaves_qubits_not_in_noncontinuous_subsy
|
|
|
59
65
|
assert circuit.operation_at(q3, 4) is None
|
|
60
66
|
|
|
61
67
|
|
|
62
|
-
def test_exception():
|
|
68
|
+
def test_exception() -> None:
|
|
63
69
|
q0, q1, q2, q3 = cirq.LineQubit.range(4)
|
|
64
70
|
circuit = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q1, q2), cirq.CNOT(q2, q3)])
|
|
65
71
|
|