cirq-core 1.5.0.dev20250409225226__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.dev20250409225226.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.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
- cirq_core-1.5.0.dev20250409225226.dist-info/RECORD +0 -1216
- {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.5.0.dev20250409225226.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
cirq/circuits/circuit.py
CHANGED
|
@@ -33,19 +33,13 @@ from typing import (
|
|
|
33
33
|
Any,
|
|
34
34
|
Callable,
|
|
35
35
|
cast,
|
|
36
|
-
|
|
37
|
-
FrozenSet,
|
|
36
|
+
Hashable,
|
|
38
37
|
Iterable,
|
|
39
38
|
Iterator,
|
|
40
|
-
List,
|
|
41
39
|
Mapping,
|
|
42
40
|
MutableSequence,
|
|
43
|
-
Optional,
|
|
44
41
|
overload,
|
|
45
42
|
Sequence,
|
|
46
|
-
Set,
|
|
47
|
-
Tuple,
|
|
48
|
-
Type,
|
|
49
43
|
TYPE_CHECKING,
|
|
50
44
|
TypeVar,
|
|
51
45
|
Union,
|
|
@@ -93,7 +87,7 @@ document(
|
|
|
93
87
|
""",
|
|
94
88
|
)
|
|
95
89
|
|
|
96
|
-
_INT_TYPE =
|
|
90
|
+
_INT_TYPE = int | np.integer
|
|
97
91
|
|
|
98
92
|
|
|
99
93
|
class Alignment(enum.Enum):
|
|
@@ -148,7 +142,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
148
142
|
"""
|
|
149
143
|
|
|
150
144
|
@classmethod
|
|
151
|
-
def from_moments(
|
|
145
|
+
def from_moments(
|
|
146
|
+
cls: type[CIRCUIT_TYPE], *moments: cirq.OP_TREE | None, tags: Sequence[Hashable] = ()
|
|
147
|
+
) -> CIRCUIT_TYPE:
|
|
152
148
|
"""Create a circuit from moment op trees.
|
|
153
149
|
|
|
154
150
|
Args:
|
|
@@ -162,11 +158,15 @@ class AbstractCircuit(abc.ABC):
|
|
|
162
158
|
which is then included in the new circuit. Note that in this
|
|
163
159
|
case we have the normal restriction that operations in a
|
|
164
160
|
moment must be applied to disjoint sets of qubits.
|
|
161
|
+
tags: A sequence of any type of object that is useful to attach metadata
|
|
162
|
+
to this circuit as long as the type is hashable. If you wish the
|
|
163
|
+
resulting circuit to be eventually serialized into JSON, you should
|
|
164
|
+
also restrict the tags to be JSON serializable.
|
|
165
165
|
"""
|
|
166
|
-
return cls._from_moments(cls._make_moments(moments))
|
|
166
|
+
return cls._from_moments(cls._make_moments(moments), tags=tags)
|
|
167
167
|
|
|
168
168
|
@staticmethod
|
|
169
|
-
def _make_moments(moments: Iterable[
|
|
169
|
+
def _make_moments(moments: Iterable[cirq.OP_TREE | None]) -> Iterator[cirq.Moment]:
|
|
170
170
|
for m in moments:
|
|
171
171
|
if isinstance(m, Moment):
|
|
172
172
|
yield m
|
|
@@ -177,7 +177,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
177
177
|
|
|
178
178
|
@classmethod
|
|
179
179
|
@abc.abstractmethod
|
|
180
|
-
def _from_moments(
|
|
180
|
+
def _from_moments(
|
|
181
|
+
cls: type[CIRCUIT_TYPE], moments: Iterable[cirq.Moment], tags: Sequence[Hashable]
|
|
182
|
+
) -> CIRCUIT_TYPE:
|
|
181
183
|
"""Create a circuit from moments.
|
|
182
184
|
|
|
183
185
|
This must be implemented by subclasses. It provides a more efficient way
|
|
@@ -208,6 +210,20 @@ class AbstractCircuit(abc.ABC):
|
|
|
208
210
|
copy: If True and 'self' is a Circuit, returns a copy that circuit.
|
|
209
211
|
"""
|
|
210
212
|
|
|
213
|
+
@property
|
|
214
|
+
@abc.abstractmethod
|
|
215
|
+
def tags(self) -> tuple[Hashable, ...]:
|
|
216
|
+
"""Returns a tuple of the Circuit's tags."""
|
|
217
|
+
|
|
218
|
+
@abc.abstractmethod
|
|
219
|
+
def with_tags(self, *new_tags: Hashable) -> Self:
|
|
220
|
+
"""Creates a new tagged Circuit with `self.tags` and `new_tags` combined."""
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def untagged(self) -> Self:
|
|
224
|
+
"""Returns the underlying Circuit without any tags."""
|
|
225
|
+
return self._from_moments(self.moments, tags=()) if self.tags else self
|
|
226
|
+
|
|
211
227
|
def __bool__(self) -> bool:
|
|
212
228
|
return bool(self.moments)
|
|
213
229
|
|
|
@@ -217,14 +233,16 @@ class AbstractCircuit(abc.ABC):
|
|
|
217
233
|
return other is self or (
|
|
218
234
|
len(self.moments) == len(other.moments)
|
|
219
235
|
and all(m0 == m1 for m0, m1 in zip(self.moments, other.moments))
|
|
236
|
+
and self.tags == other.tags
|
|
220
237
|
)
|
|
221
238
|
|
|
222
239
|
def _approx_eq_(self, other: Any, atol: float) -> bool:
|
|
223
240
|
"""See `cirq.protocols.SupportsApproximateEquality`."""
|
|
224
241
|
if not isinstance(other, AbstractCircuit):
|
|
225
242
|
return NotImplemented
|
|
226
|
-
return other is self or
|
|
227
|
-
|
|
243
|
+
return other is self or (
|
|
244
|
+
self.tags == other.tags
|
|
245
|
+
and cirq.protocols.approx_eq(tuple(self.moments), tuple(other.moments), atol=atol)
|
|
228
246
|
)
|
|
229
247
|
|
|
230
248
|
def __ne__(self, other) -> bool:
|
|
@@ -240,17 +258,16 @@ class AbstractCircuit(abc.ABC):
|
|
|
240
258
|
"""See `cirq.SupportsDecompose`."""
|
|
241
259
|
return self.all_operations()
|
|
242
260
|
|
|
243
|
-
# pylint: disable=function-redefined
|
|
244
261
|
@overload
|
|
245
262
|
def __getitem__(self, key: int) -> cirq.Moment:
|
|
246
263
|
pass
|
|
247
264
|
|
|
248
265
|
@overload
|
|
249
|
-
def __getitem__(self, key:
|
|
266
|
+
def __getitem__(self, key: tuple[int, cirq.Qid]) -> cirq.Operation:
|
|
250
267
|
pass
|
|
251
268
|
|
|
252
269
|
@overload
|
|
253
|
-
def __getitem__(self, key:
|
|
270
|
+
def __getitem__(self, key: tuple[int, Iterable[cirq.Qid]]) -> cirq.Moment:
|
|
254
271
|
pass
|
|
255
272
|
|
|
256
273
|
@overload
|
|
@@ -258,16 +275,16 @@ class AbstractCircuit(abc.ABC):
|
|
|
258
275
|
pass
|
|
259
276
|
|
|
260
277
|
@overload
|
|
261
|
-
def __getitem__(self, key:
|
|
278
|
+
def __getitem__(self, key: tuple[slice, cirq.Qid]) -> Self:
|
|
262
279
|
pass
|
|
263
280
|
|
|
264
281
|
@overload
|
|
265
|
-
def __getitem__(self, key:
|
|
282
|
+
def __getitem__(self, key: tuple[slice, Iterable[cirq.Qid]]) -> Self:
|
|
266
283
|
pass
|
|
267
284
|
|
|
268
285
|
def __getitem__(self, key):
|
|
269
286
|
if isinstance(key, slice):
|
|
270
|
-
return self._from_moments(self.moments[key])
|
|
287
|
+
return self._from_moments(self.moments[key], tags=self.tags)
|
|
271
288
|
if hasattr(key, '__index__'):
|
|
272
289
|
return self.moments[key]
|
|
273
290
|
if isinstance(key, tuple):
|
|
@@ -280,12 +297,12 @@ class AbstractCircuit(abc.ABC):
|
|
|
280
297
|
return selected_moments[qubit_idx]
|
|
281
298
|
if isinstance(qubit_idx, ops.Qid):
|
|
282
299
|
qubit_idx = [qubit_idx]
|
|
283
|
-
return self._from_moments(
|
|
300
|
+
return self._from_moments(
|
|
301
|
+
(moment[qubit_idx] for moment in selected_moments), tags=self.tags
|
|
302
|
+
)
|
|
284
303
|
|
|
285
304
|
raise TypeError('__getitem__ called with key not of type slice, int, or tuple.')
|
|
286
305
|
|
|
287
|
-
# pylint: enable=function-redefined
|
|
288
|
-
|
|
289
306
|
def __str__(self) -> str:
|
|
290
307
|
return self.to_text_diagram()
|
|
291
308
|
|
|
@@ -293,7 +310,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
293
310
|
args = []
|
|
294
311
|
if self.moments:
|
|
295
312
|
args.append(_list_repr_with_indented_item_lines(self.moments))
|
|
296
|
-
|
|
313
|
+
moments_repr = f'{", ".join(args)}'
|
|
314
|
+
tag_repr = ','.join(_compat.proper_repr(t) for t in self.tags)
|
|
315
|
+
return f'{moments_repr}, tags=[{tag_repr}]' if self.tags else moments_repr
|
|
297
316
|
|
|
298
317
|
def __repr__(self) -> str:
|
|
299
318
|
cls_name = self.__class__.__name__
|
|
@@ -318,7 +337,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
318
337
|
|
|
319
338
|
def _first_moment_operating_on(
|
|
320
339
|
self, qubits: Iterable[cirq.Qid], indices: Iterable[int]
|
|
321
|
-
) ->
|
|
340
|
+
) -> int | None:
|
|
322
341
|
qubits = frozenset(qubits)
|
|
323
342
|
for m in indices:
|
|
324
343
|
if self._has_op_at(m, qubits):
|
|
@@ -329,8 +348,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
329
348
|
self,
|
|
330
349
|
qubits: Iterable[cirq.Qid],
|
|
331
350
|
start_moment_index: int = 0,
|
|
332
|
-
max_distance:
|
|
333
|
-
) ->
|
|
351
|
+
max_distance: int | None = None,
|
|
352
|
+
) -> int | None:
|
|
334
353
|
"""Finds the index of the next moment that touches the given qubits.
|
|
335
354
|
|
|
336
355
|
Args:
|
|
@@ -360,7 +379,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
360
379
|
|
|
361
380
|
def next_moments_operating_on(
|
|
362
381
|
self, qubits: Iterable[cirq.Qid], start_moment_index: int = 0
|
|
363
|
-
) ->
|
|
382
|
+
) -> dict[cirq.Qid, int]:
|
|
364
383
|
"""Finds the index of the next moment that touches each qubit.
|
|
365
384
|
|
|
366
385
|
Args:
|
|
@@ -383,9 +402,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
383
402
|
def prev_moment_operating_on(
|
|
384
403
|
self,
|
|
385
404
|
qubits: Sequence[cirq.Qid],
|
|
386
|
-
end_moment_index:
|
|
387
|
-
max_distance:
|
|
388
|
-
) ->
|
|
405
|
+
end_moment_index: int | None = None,
|
|
406
|
+
max_distance: int | None = None,
|
|
407
|
+
) -> int | None:
|
|
389
408
|
"""Finds the index of the previous moment that touches the given qubits.
|
|
390
409
|
|
|
391
410
|
Args:
|
|
@@ -427,10 +446,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
427
446
|
|
|
428
447
|
def reachable_frontier_from(
|
|
429
448
|
self,
|
|
430
|
-
start_frontier:
|
|
449
|
+
start_frontier: dict[cirq.Qid, int],
|
|
431
450
|
*,
|
|
432
451
|
is_blocker: Callable[[cirq.Operation], bool] = lambda op: False,
|
|
433
|
-
) ->
|
|
452
|
+
) -> dict[cirq.Qid, int]:
|
|
434
453
|
"""Determines how far can be reached into a circuit under certain rules.
|
|
435
454
|
|
|
436
455
|
The location L = (qubit, moment_index) is *reachable* if and only if the
|
|
@@ -566,7 +585,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
566
585
|
where i is the moment index, q is the qubit, and end_frontier is the
|
|
567
586
|
result of this method.
|
|
568
587
|
"""
|
|
569
|
-
active:
|
|
588
|
+
active: set[cirq.Qid] = set()
|
|
570
589
|
end_frontier = {}
|
|
571
590
|
queue = BucketPriorityQueue[ops.Operation](drop_duplicate_entries=True)
|
|
572
591
|
|
|
@@ -610,10 +629,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
610
629
|
|
|
611
630
|
def findall_operations_between(
|
|
612
631
|
self,
|
|
613
|
-
start_frontier:
|
|
614
|
-
end_frontier:
|
|
632
|
+
start_frontier: dict[cirq.Qid, int],
|
|
633
|
+
end_frontier: dict[cirq.Qid, int],
|
|
615
634
|
omit_crossing_operations: bool = False,
|
|
616
|
-
) ->
|
|
635
|
+
) -> list[tuple[int, cirq.Operation]]:
|
|
617
636
|
"""Finds operations between the two given frontiers.
|
|
618
637
|
|
|
619
638
|
If a qubit is in `start_frontier` but not `end_frontier`, its end index
|
|
@@ -658,9 +677,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
658
677
|
|
|
659
678
|
def findall_operations_until_blocked(
|
|
660
679
|
self,
|
|
661
|
-
start_frontier:
|
|
680
|
+
start_frontier: dict[cirq.Qid, int],
|
|
662
681
|
is_blocker: Callable[[cirq.Operation], bool] = lambda op: False,
|
|
663
|
-
) ->
|
|
682
|
+
) -> list[tuple[int, cirq.Operation]]:
|
|
664
683
|
"""Finds all operations until a blocking operation is hit.
|
|
665
684
|
|
|
666
685
|
An operation is considered blocking if both of the following hold:
|
|
@@ -746,11 +765,11 @@ class AbstractCircuit(abc.ABC):
|
|
|
746
765
|
and the second item is the operation itself.
|
|
747
766
|
|
|
748
767
|
"""
|
|
749
|
-
op_list:
|
|
768
|
+
op_list: list[tuple[int, ops.Operation]] = []
|
|
750
769
|
if not start_frontier:
|
|
751
770
|
return op_list
|
|
752
771
|
start_index = min(start_frontier.values())
|
|
753
|
-
blocked_qubits:
|
|
772
|
+
blocked_qubits: set[cirq.Qid] = set()
|
|
754
773
|
for index, moment in enumerate(self[start_index:], start_index):
|
|
755
774
|
active_qubits = set(q for q, s in start_frontier.items() if s <= index)
|
|
756
775
|
for op in moment.operations:
|
|
@@ -762,7 +781,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
762
781
|
break
|
|
763
782
|
return op_list
|
|
764
783
|
|
|
765
|
-
def operation_at(self, qubit: cirq.Qid, moment_index: int) ->
|
|
784
|
+
def operation_at(self, qubit: cirq.Qid, moment_index: int) -> cirq.Operation | None:
|
|
766
785
|
"""Finds the operation on a qubit within a moment, if any.
|
|
767
786
|
|
|
768
787
|
Args:
|
|
@@ -780,7 +799,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
780
799
|
|
|
781
800
|
def findall_operations(
|
|
782
801
|
self, predicate: Callable[[cirq.Operation], bool]
|
|
783
|
-
) -> Iterable[
|
|
802
|
+
) -> Iterable[tuple[int, cirq.Operation]]:
|
|
784
803
|
"""Find the locations of all operations that satisfy a given condition.
|
|
785
804
|
|
|
786
805
|
This returns an iterator of (index, operation) tuples where each
|
|
@@ -800,8 +819,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
800
819
|
yield index, op
|
|
801
820
|
|
|
802
821
|
def findall_operations_with_gate_type(
|
|
803
|
-
self, gate_type:
|
|
804
|
-
) -> Iterable[
|
|
822
|
+
self, gate_type: type[_TGate]
|
|
823
|
+
) -> Iterable[tuple[int, cirq.GateOperation, _TGate]]:
|
|
805
824
|
"""Find the locations of all gate operations of a given type.
|
|
806
825
|
|
|
807
826
|
Args:
|
|
@@ -817,7 +836,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
817
836
|
gate_op = cast(ops.GateOperation, op)
|
|
818
837
|
yield index, gate_op, cast(_TGate, gate_op.gate)
|
|
819
838
|
|
|
820
|
-
def has_measurements(self):
|
|
839
|
+
def has_measurements(self) -> bool:
|
|
821
840
|
"""Returns whether or not this circuit has measurements.
|
|
822
841
|
|
|
823
842
|
Returns: True if `cirq.is_measurement(self)` is True otherwise False.
|
|
@@ -922,10 +941,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
922
941
|
qubits
|
|
923
942
|
)
|
|
924
943
|
|
|
925
|
-
def all_qubits(self) ->
|
|
944
|
+
def all_qubits(self) -> frozenset[cirq.Qid]:
|
|
926
945
|
"""Returns the qubits acted upon by Operations in this circuit.
|
|
927
946
|
|
|
928
|
-
Returns:
|
|
947
|
+
Returns: frozenset of `cirq.Qid` objects acted on by all operations
|
|
929
948
|
in this circuit.
|
|
930
949
|
"""
|
|
931
950
|
return frozenset(q for m in self.moments for q in m.qubits)
|
|
@@ -952,11 +971,13 @@ class AbstractCircuit(abc.ABC):
|
|
|
952
971
|
"""Apply func to expand each op into a circuit, then zip up the circuits."""
|
|
953
972
|
return Circuit.zip(*[Circuit(func(op)) for op in moment])
|
|
954
973
|
|
|
955
|
-
return self._from_moments(
|
|
974
|
+
return self._from_moments(
|
|
975
|
+
(m for moment in self for m in map_moment(moment)), tags=self.tags
|
|
976
|
+
)
|
|
956
977
|
|
|
957
978
|
def qid_shape(
|
|
958
979
|
self, qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT
|
|
959
|
-
) ->
|
|
980
|
+
) -> tuple[int, ...]:
|
|
960
981
|
"""Get the qubit shapes of all qubits in this circuit.
|
|
961
982
|
|
|
962
983
|
Returns: A tuple containing the dimensions (shape) of all qudits
|
|
@@ -965,56 +986,60 @@ class AbstractCircuit(abc.ABC):
|
|
|
965
986
|
qids = ops.QubitOrder.as_qubit_order(qubit_order).order_for(self.all_qubits())
|
|
966
987
|
return protocols.qid_shape(qids)
|
|
967
988
|
|
|
968
|
-
def all_measurement_key_objs(self) ->
|
|
989
|
+
def all_measurement_key_objs(self) -> frozenset[cirq.MeasurementKey]:
|
|
969
990
|
return frozenset(
|
|
970
991
|
key for op in self.all_operations() for key in protocols.measurement_key_objs(op)
|
|
971
992
|
)
|
|
972
993
|
|
|
973
|
-
def _measurement_key_objs_(self) ->
|
|
994
|
+
def _measurement_key_objs_(self) -> frozenset[cirq.MeasurementKey]:
|
|
974
995
|
"""Returns the set of all measurement keys in this circuit.
|
|
975
996
|
|
|
976
|
-
Returns:
|
|
997
|
+
Returns: frozenset of `cirq.MeasurementKey` objects that are
|
|
977
998
|
in this circuit.
|
|
978
999
|
"""
|
|
979
1000
|
return self.all_measurement_key_objs()
|
|
980
1001
|
|
|
981
|
-
def all_measurement_key_names(self) ->
|
|
1002
|
+
def all_measurement_key_names(self) -> frozenset[str]:
|
|
982
1003
|
"""Returns the set of all measurement key names in this circuit.
|
|
983
1004
|
|
|
984
|
-
Returns:
|
|
1005
|
+
Returns: frozenset of strings that are the measurement key
|
|
985
1006
|
names in this circuit.
|
|
986
1007
|
"""
|
|
987
1008
|
return frozenset(
|
|
988
1009
|
key for op in self.all_operations() for key in protocols.measurement_key_names(op)
|
|
989
1010
|
)
|
|
990
1011
|
|
|
991
|
-
def _measurement_key_names_(self) ->
|
|
1012
|
+
def _measurement_key_names_(self) -> frozenset[str]:
|
|
992
1013
|
return self.all_measurement_key_names()
|
|
993
1014
|
|
|
994
1015
|
def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]):
|
|
995
1016
|
return self._from_moments(
|
|
996
|
-
protocols.with_measurement_key_mapping(moment, key_map) for moment in self.moments
|
|
1017
|
+
(protocols.with_measurement_key_mapping(moment, key_map) for moment in self.moments),
|
|
1018
|
+
tags=self.tags,
|
|
997
1019
|
)
|
|
998
1020
|
|
|
999
|
-
def _with_key_path_(self, path:
|
|
1000
|
-
return self._from_moments(
|
|
1021
|
+
def _with_key_path_(self, path: tuple[str, ...]):
|
|
1022
|
+
return self._from_moments(
|
|
1023
|
+
(protocols.with_key_path(moment, path) for moment in self.moments), tags=self.tags
|
|
1024
|
+
)
|
|
1001
1025
|
|
|
1002
|
-
def _with_key_path_prefix_(self, prefix:
|
|
1026
|
+
def _with_key_path_prefix_(self, prefix: tuple[str, ...]):
|
|
1003
1027
|
return self._from_moments(
|
|
1004
|
-
protocols.with_key_path_prefix(moment, prefix) for moment in self.moments
|
|
1028
|
+
(protocols.with_key_path_prefix(moment, prefix) for moment in self.moments),
|
|
1029
|
+
tags=self.tags,
|
|
1005
1030
|
)
|
|
1006
1031
|
|
|
1007
1032
|
def _with_rescoped_keys_(
|
|
1008
|
-
self, path:
|
|
1033
|
+
self, path: tuple[str, ...], bindable_keys: frozenset[cirq.MeasurementKey]
|
|
1009
1034
|
):
|
|
1010
1035
|
moments = []
|
|
1011
1036
|
for moment in self.moments:
|
|
1012
1037
|
new_moment = protocols.with_rescoped_keys(moment, path, bindable_keys)
|
|
1013
1038
|
moments.append(new_moment)
|
|
1014
1039
|
bindable_keys |= protocols.measurement_key_objs(new_moment)
|
|
1015
|
-
return self._from_moments(moments)
|
|
1040
|
+
return self._from_moments(moments, tags=self.tags)
|
|
1016
1041
|
|
|
1017
|
-
def _qid_shape_(self) ->
|
|
1042
|
+
def _qid_shape_(self) -> tuple[int, ...]:
|
|
1018
1043
|
return self.qid_shape()
|
|
1019
1044
|
|
|
1020
1045
|
def _has_unitary_(self) -> bool:
|
|
@@ -1029,7 +1054,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1029
1054
|
)
|
|
1030
1055
|
return all(protocols.has_unitary(e) for e in unitary_ops)
|
|
1031
1056
|
|
|
1032
|
-
def _unitary_(self) ->
|
|
1057
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
1033
1058
|
"""Converts the circuit into a unitary matrix, if possible.
|
|
1034
1059
|
|
|
1035
1060
|
If the circuit contains any non-terminal measurements, the conversion
|
|
@@ -1047,7 +1072,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1047
1072
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1048
1073
|
qubits_that_should_be_present: Iterable[cirq.Qid] = (),
|
|
1049
1074
|
ignore_terminal_measurements: bool = True,
|
|
1050
|
-
dtype:
|
|
1075
|
+
dtype: type[np.complexfloating] = np.complex128,
|
|
1051
1076
|
) -> np.ndarray:
|
|
1052
1077
|
"""Converts the circuit into a unitary matrix, if possible.
|
|
1053
1078
|
|
|
@@ -1124,7 +1149,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1124
1149
|
initial_state: cirq.STATE_VECTOR_LIKE = 0,
|
|
1125
1150
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1126
1151
|
ignore_terminal_measurements: bool = False,
|
|
1127
|
-
dtype:
|
|
1152
|
+
dtype: type[np.complexfloating] = np.complex128,
|
|
1128
1153
|
param_resolver: cirq.ParamResolverOrSimilarType = None,
|
|
1129
1154
|
seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
1130
1155
|
) -> np.ndarray:
|
|
@@ -1182,8 +1207,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
1182
1207
|
*,
|
|
1183
1208
|
use_unicode_characters: bool = True,
|
|
1184
1209
|
transpose: bool = False,
|
|
1185
|
-
include_tags: bool = True,
|
|
1186
|
-
precision:
|
|
1210
|
+
include_tags: bool | Iterable[type] = True,
|
|
1211
|
+
precision: int | None = 3,
|
|
1187
1212
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1188
1213
|
) -> str:
|
|
1189
1214
|
"""Returns text containing a diagram describing the circuit.
|
|
@@ -1192,7 +1217,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
1192
1217
|
use_unicode_characters: Determines if unicode characters are
|
|
1193
1218
|
allowed (as opposed to ascii-only diagrams).
|
|
1194
1219
|
transpose: Arranges qubit wires vertically instead of horizontally.
|
|
1195
|
-
include_tags:
|
|
1220
|
+
include_tags: Controls which tags attached to operations are
|
|
1221
|
+
included. ``True`` includes all tags, ``False`` includes none,
|
|
1222
|
+
or a collection of tag classes may be specified to include only
|
|
1223
|
+
those tags.
|
|
1196
1224
|
precision: Number of digits to display in text diagram
|
|
1197
1225
|
qubit_order: Determines how qubits are ordered in the diagram.
|
|
1198
1226
|
|
|
@@ -1217,15 +1245,15 @@ class AbstractCircuit(abc.ABC):
|
|
|
1217
1245
|
self,
|
|
1218
1246
|
*,
|
|
1219
1247
|
use_unicode_characters: bool = True,
|
|
1220
|
-
qubit_namer:
|
|
1248
|
+
qubit_namer: Callable[[cirq.Qid], str] | None = None,
|
|
1221
1249
|
transpose: bool = False,
|
|
1222
|
-
include_tags: bool = True,
|
|
1250
|
+
include_tags: bool | Iterable[type] = True,
|
|
1223
1251
|
draw_moment_groups: bool = True,
|
|
1224
|
-
precision:
|
|
1252
|
+
precision: int | None = 3,
|
|
1225
1253
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1226
|
-
get_circuit_diagram_info:
|
|
1227
|
-
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo]
|
|
1228
|
-
|
|
1254
|
+
get_circuit_diagram_info: (
|
|
1255
|
+
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo] | None
|
|
1256
|
+
) = None,
|
|
1229
1257
|
) -> cirq.TextDiagramDrawer:
|
|
1230
1258
|
"""Returns a TextDiagramDrawer with the circuit drawn into it.
|
|
1231
1259
|
|
|
@@ -1234,7 +1262,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
1234
1262
|
allowed (as opposed to ascii-only diagrams).
|
|
1235
1263
|
qubit_namer: Names qubits in diagram. Defaults to using _circuit_diagram_info_ or str.
|
|
1236
1264
|
transpose: Arranges qubit wires vertically instead of horizontally.
|
|
1237
|
-
include_tags:
|
|
1265
|
+
include_tags: Controls which tags attached to operations are
|
|
1266
|
+
included. ``True`` includes all tags, ``False`` includes none,
|
|
1267
|
+
or a collection of tag classes may be specified to include only
|
|
1268
|
+
those tags.
|
|
1238
1269
|
draw_moment_groups: Whether to draw moment symbol or not
|
|
1239
1270
|
precision: Number of digits to use when representing numbers.
|
|
1240
1271
|
qubit_order: Determines how qubits are ordered in the diagram.
|
|
@@ -1276,7 +1307,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1276
1307
|
diagram.write(0, max(label_map.values(), default=0) + 1, 'global phase:')
|
|
1277
1308
|
first_annotation_row += 1
|
|
1278
1309
|
|
|
1279
|
-
moment_groups:
|
|
1310
|
+
moment_groups: list[tuple[int, int]] = []
|
|
1280
1311
|
for moment in self.moments:
|
|
1281
1312
|
_draw_moment_in_diagram(
|
|
1282
1313
|
moment=moment,
|
|
@@ -1304,24 +1335,35 @@ class AbstractCircuit(abc.ABC):
|
|
|
1304
1335
|
return diagram
|
|
1305
1336
|
|
|
1306
1337
|
def _is_parameterized_(self) -> bool:
|
|
1307
|
-
return any(protocols.is_parameterized(op) for op in self.all_operations())
|
|
1338
|
+
return any(protocols.is_parameterized(op) for op in self.all_operations()) or any(
|
|
1339
|
+
protocols.is_parameterized(tag) for tag in self.tags
|
|
1340
|
+
)
|
|
1308
1341
|
|
|
1309
1342
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
1310
|
-
|
|
1343
|
+
op_params = {name for op in self.all_operations() for name in protocols.parameter_names(op)}
|
|
1344
|
+
tag_params = {name for tag in self.tags for name in protocols.parameter_names(tag)}
|
|
1345
|
+
return op_params | tag_params
|
|
1311
1346
|
|
|
1312
1347
|
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> Self:
|
|
1313
1348
|
changed = False
|
|
1314
|
-
resolved_moments:
|
|
1349
|
+
resolved_moments: list[cirq.Moment] = []
|
|
1350
|
+
resolved_tags: list[Hashable] = []
|
|
1315
1351
|
for moment in self:
|
|
1316
1352
|
resolved_moment = protocols.resolve_parameters(moment, resolver, recursive)
|
|
1317
1353
|
if resolved_moment is not moment:
|
|
1318
1354
|
changed = True
|
|
1319
1355
|
resolved_moments.append(resolved_moment)
|
|
1320
|
-
|
|
1356
|
+
for tag in self.tags:
|
|
1357
|
+
resolved_tag = protocols.resolve_parameters(tag, resolver, recursive)
|
|
1358
|
+
if resolved_tag is not tag:
|
|
1359
|
+
changed = True
|
|
1360
|
+
resolved_tags.append(resolved_tag)
|
|
1361
|
+
if changed:
|
|
1362
|
+
return self._from_moments(resolved_moments, tags=resolved_tags)
|
|
1363
|
+
else:
|
|
1321
1364
|
return self # pragma: no cover
|
|
1322
|
-
return self._from_moments(resolved_moments)
|
|
1323
1365
|
|
|
1324
|
-
def _qasm_(self, args:
|
|
1366
|
+
def _qasm_(self, args: cirq.QasmArgs | None = None) -> str:
|
|
1325
1367
|
if args is None:
|
|
1326
1368
|
output = self._to_qasm_output()
|
|
1327
1369
|
else:
|
|
@@ -1330,7 +1372,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1330
1372
|
|
|
1331
1373
|
def _to_qasm_output(
|
|
1332
1374
|
self,
|
|
1333
|
-
header:
|
|
1375
|
+
header: str | None = None,
|
|
1334
1376
|
precision: int = 10,
|
|
1335
1377
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1336
1378
|
version: str = '2.0',
|
|
@@ -1359,7 +1401,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1359
1401
|
|
|
1360
1402
|
def to_qasm(
|
|
1361
1403
|
self,
|
|
1362
|
-
header:
|
|
1404
|
+
header: str | None = None,
|
|
1363
1405
|
precision: int = 10,
|
|
1364
1406
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1365
1407
|
version: str = '2.0',
|
|
@@ -1380,8 +1422,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
1380
1422
|
|
|
1381
1423
|
def save_qasm(
|
|
1382
1424
|
self,
|
|
1383
|
-
file_path:
|
|
1384
|
-
header:
|
|
1425
|
+
file_path: str | bytes | int,
|
|
1426
|
+
header: str | None = None,
|
|
1385
1427
|
precision: int = 10,
|
|
1386
1428
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1387
1429
|
) -> None:
|
|
@@ -1398,14 +1440,16 @@ class AbstractCircuit(abc.ABC):
|
|
|
1398
1440
|
self._to_qasm_output(header, precision, qubit_order).save(file_path)
|
|
1399
1441
|
|
|
1400
1442
|
def _json_dict_(self):
|
|
1401
|
-
|
|
1443
|
+
attribute_names = ['moments', 'tags'] if self.tags else ['moments']
|
|
1444
|
+
ret = protocols.obj_to_dict_helper(self, attribute_names)
|
|
1445
|
+
return ret
|
|
1402
1446
|
|
|
1403
1447
|
@classmethod
|
|
1404
|
-
def _from_json_dict_(cls, moments, **kwargs):
|
|
1405
|
-
return cls(moments, strategy=InsertStrategy.EARLIEST)
|
|
1448
|
+
def _from_json_dict_(cls, moments, tags=(), **kwargs):
|
|
1449
|
+
return cls(moments, tags=tags, strategy=InsertStrategy.EARLIEST)
|
|
1406
1450
|
|
|
1407
1451
|
def zip(
|
|
1408
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
1452
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
1409
1453
|
) -> cirq.AbstractCircuit:
|
|
1410
1454
|
"""Combines operations from circuits in a moment-by-moment fashion.
|
|
1411
1455
|
|
|
@@ -1466,7 +1510,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1466
1510
|
if isinstance(align, str):
|
|
1467
1511
|
align = Alignment[align.upper()]
|
|
1468
1512
|
|
|
1469
|
-
result = cirq.Circuit()
|
|
1513
|
+
result = cirq.Circuit(tags=circuits[0].tags if circuits else ())
|
|
1470
1514
|
for k in range(n):
|
|
1471
1515
|
try:
|
|
1472
1516
|
if align == Alignment.LEFT:
|
|
@@ -1481,7 +1525,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1481
1525
|
return result
|
|
1482
1526
|
|
|
1483
1527
|
def concat_ragged(
|
|
1484
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
1528
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
1485
1529
|
) -> cirq.AbstractCircuit:
|
|
1486
1530
|
"""Concatenates circuits, overlapping them if possible due to ragged edges.
|
|
1487
1531
|
|
|
@@ -1535,9 +1579,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
1535
1579
|
for k in range(1, len(circuits)):
|
|
1536
1580
|
offset, n_acc = _concat_ragged_helper(offset, n_acc, buffer, circuits[k].moments, align)
|
|
1537
1581
|
|
|
1538
|
-
return cirq.Circuit(buffer[offset : offset + n_acc])
|
|
1582
|
+
return cirq.Circuit(buffer[offset : offset + n_acc], tags=circuits[0].tags)
|
|
1539
1583
|
|
|
1540
|
-
def get_independent_qubit_sets(self) ->
|
|
1584
|
+
def get_independent_qubit_sets(self) -> list[set[cirq.Qid]]:
|
|
1541
1585
|
"""Divide circuit's qubits into independent qubit sets.
|
|
1542
1586
|
|
|
1543
1587
|
Independent qubit sets are the qubit sets such that there are
|
|
@@ -1614,9 +1658,12 @@ class AbstractCircuit(abc.ABC):
|
|
|
1614
1658
|
# the qubits from one factor belong to a specific independent qubit set.
|
|
1615
1659
|
# This makes it possible to create independent circuits based on these
|
|
1616
1660
|
# moments.
|
|
1617
|
-
return (
|
|
1661
|
+
return (
|
|
1662
|
+
self._from_moments([m[qubits] for m in self.moments], tags=self.tags)
|
|
1663
|
+
for qubits in qubit_factors
|
|
1664
|
+
)
|
|
1618
1665
|
|
|
1619
|
-
def _control_keys_(self) ->
|
|
1666
|
+
def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
|
|
1620
1667
|
controls = frozenset(k for op in self.all_operations() for k in protocols.control_keys(op))
|
|
1621
1668
|
return controls - protocols.measurement_key_objs(self)
|
|
1622
1669
|
|
|
@@ -1626,7 +1673,7 @@ def _overlap_collision_time(
|
|
|
1626
1673
|
) -> int:
|
|
1627
1674
|
# Tracks the first used moment index for each qubit in c2.
|
|
1628
1675
|
# Tracks the complementary last used moment index for each qubit in c1.
|
|
1629
|
-
seen_times:
|
|
1676
|
+
seen_times: dict[cirq.Qid, int] = {}
|
|
1630
1677
|
|
|
1631
1678
|
# Start scanning from end of first and start of second.
|
|
1632
1679
|
if align == Alignment.LEFT:
|
|
@@ -1667,7 +1714,7 @@ def _concat_ragged_helper(
|
|
|
1667
1714
|
buf: MutableSequence[cirq.Moment],
|
|
1668
1715
|
c2: Sequence[cirq.Moment],
|
|
1669
1716
|
align: cirq.Alignment,
|
|
1670
|
-
) ->
|
|
1717
|
+
) -> tuple[int, int]:
|
|
1671
1718
|
n2 = len(c2)
|
|
1672
1719
|
shift = _overlap_collision_time(buf[c1_offset : c1_offset + n1], c2, align)
|
|
1673
1720
|
c2_offset = c1_offset + n1 - shift
|
|
@@ -1757,7 +1804,10 @@ class Circuit(AbstractCircuit):
|
|
|
1757
1804
|
"""
|
|
1758
1805
|
|
|
1759
1806
|
def __init__(
|
|
1760
|
-
self,
|
|
1807
|
+
self,
|
|
1808
|
+
*contents: cirq.OP_TREE,
|
|
1809
|
+
strategy: cirq.InsertStrategy = InsertStrategy.EARLIEST,
|
|
1810
|
+
tags: Sequence[Hashable] = (),
|
|
1761
1811
|
) -> None:
|
|
1762
1812
|
"""Initializes a circuit.
|
|
1763
1813
|
|
|
@@ -1771,18 +1821,23 @@ class Circuit(AbstractCircuit):
|
|
|
1771
1821
|
from `contents`, this determines how the operations are packed
|
|
1772
1822
|
together. This option does not affect later insertions into the
|
|
1773
1823
|
circuit.
|
|
1824
|
+
tags: A sequence of any type of object that is useful to attach metadata
|
|
1825
|
+
to this circuit as long as the type is hashable. If you wish the
|
|
1826
|
+
resulting circuit to be eventually serialized into JSON, you should
|
|
1827
|
+
also restrict the tags to be JSON serializable.
|
|
1774
1828
|
"""
|
|
1775
|
-
self._placement_cache:
|
|
1776
|
-
self._moments:
|
|
1829
|
+
self._placement_cache: _PlacementCache | None = _PlacementCache()
|
|
1830
|
+
self._moments: list[cirq.Moment] = []
|
|
1831
|
+
self._tags = tuple(tags)
|
|
1777
1832
|
|
|
1778
1833
|
# Implementation note: the following cached properties are set lazily and then
|
|
1779
1834
|
# invalidated and reset to None in `self._mutated()`, which is called any time
|
|
1780
1835
|
# `self._moments` is changed.
|
|
1781
|
-
self._all_qubits:
|
|
1782
|
-
self._frozen:
|
|
1783
|
-
self._is_measurement:
|
|
1784
|
-
self._is_parameterized:
|
|
1785
|
-
self._parameter_names:
|
|
1836
|
+
self._all_qubits: frozenset[cirq.Qid] | None = None
|
|
1837
|
+
self._frozen: cirq.FrozenCircuit | None = None
|
|
1838
|
+
self._is_measurement: bool | None = None
|
|
1839
|
+
self._is_parameterized: bool | None = None
|
|
1840
|
+
self._parameter_names: AbstractSet[str] | None = None
|
|
1786
1841
|
if not contents:
|
|
1787
1842
|
return
|
|
1788
1843
|
flattened_contents = tuple(ops.flatten_to_ops_or_moments(contents))
|
|
@@ -1807,10 +1862,11 @@ class Circuit(AbstractCircuit):
|
|
|
1807
1862
|
self._placement_cache = None
|
|
1808
1863
|
|
|
1809
1864
|
@classmethod
|
|
1810
|
-
def _from_moments(cls, moments: Iterable[cirq.Moment]) -> Circuit:
|
|
1865
|
+
def _from_moments(cls, moments: Iterable[cirq.Moment], tags: Sequence[Hashable]) -> Circuit:
|
|
1811
1866
|
new_circuit = Circuit()
|
|
1812
1867
|
new_circuit._moments[:] = moments
|
|
1813
1868
|
new_circuit._placement_cache = None
|
|
1869
|
+
new_circuit._tags = tuple(tags)
|
|
1814
1870
|
return new_circuit
|
|
1815
1871
|
|
|
1816
1872
|
def _load_contents_with_earliest_strategy(self, contents: cirq.OP_TREE):
|
|
@@ -1837,8 +1893,8 @@ class Circuit(AbstractCircuit):
|
|
|
1837
1893
|
|
|
1838
1894
|
# We also maintain the dict from moment index to moments/ops that go into it, for use when
|
|
1839
1895
|
# building the actual moments at the end.
|
|
1840
|
-
op_lists_by_index:
|
|
1841
|
-
moments_by_index:
|
|
1896
|
+
op_lists_by_index: dict[int, list[cirq.Operation]] = defaultdict(list)
|
|
1897
|
+
moments_by_index: dict[int, cirq.Moment] = {}
|
|
1842
1898
|
|
|
1843
1899
|
# "mop" means current moment-or-operation
|
|
1844
1900
|
for mop in ops.flatten_to_ops_or_moments(contents):
|
|
@@ -1869,13 +1925,13 @@ class Circuit(AbstractCircuit):
|
|
|
1869
1925
|
from cirq.circuits.frozen_circuit import FrozenCircuit
|
|
1870
1926
|
|
|
1871
1927
|
if self._frozen is None:
|
|
1872
|
-
self._frozen = FrozenCircuit._from_moments(self._moments)
|
|
1928
|
+
self._frozen = FrozenCircuit._from_moments(self._moments, tags=self.tags)
|
|
1873
1929
|
return self._frozen
|
|
1874
1930
|
|
|
1875
1931
|
def unfreeze(self, copy: bool = True) -> cirq.Circuit:
|
|
1876
1932
|
return self.copy() if copy else self
|
|
1877
1933
|
|
|
1878
|
-
def all_qubits(self) ->
|
|
1934
|
+
def all_qubits(self) -> frozenset[cirq.Qid]:
|
|
1879
1935
|
if self._all_qubits is None:
|
|
1880
1936
|
self._all_qubits = super().all_qubits()
|
|
1881
1937
|
return self._all_qubits
|
|
@@ -1898,11 +1954,11 @@ class Circuit(AbstractCircuit):
|
|
|
1898
1954
|
def copy(self) -> Circuit:
|
|
1899
1955
|
"""Return a copy of this circuit."""
|
|
1900
1956
|
copied_circuit = Circuit()
|
|
1901
|
-
copied_circuit._moments = self._moments
|
|
1957
|
+
copied_circuit._moments[:] = self._moments
|
|
1902
1958
|
copied_circuit._placement_cache = None
|
|
1959
|
+
copied_circuit._tags = self.tags
|
|
1903
1960
|
return copied_circuit
|
|
1904
1961
|
|
|
1905
|
-
# pylint: disable=function-redefined
|
|
1906
1962
|
@overload
|
|
1907
1963
|
def __setitem__(self, key: int, value: cirq.Moment):
|
|
1908
1964
|
pass
|
|
@@ -1923,9 +1979,7 @@ class Circuit(AbstractCircuit):
|
|
|
1923
1979
|
self._moments[key] = value
|
|
1924
1980
|
self._mutated()
|
|
1925
1981
|
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
def __delitem__(self, key: Union[int, slice]):
|
|
1982
|
+
def __delitem__(self, key: int | slice):
|
|
1929
1983
|
del self._moments[key]
|
|
1930
1984
|
self._mutated()
|
|
1931
1985
|
|
|
@@ -1962,7 +2016,7 @@ class Circuit(AbstractCircuit):
|
|
|
1962
2016
|
def __mul__(self, repetitions: _INT_TYPE):
|
|
1963
2017
|
if not isinstance(repetitions, (int, np.integer)):
|
|
1964
2018
|
return NotImplemented
|
|
1965
|
-
return Circuit(self._moments * int(repetitions))
|
|
2019
|
+
return Circuit(self._moments * int(repetitions), tags=self.tags)
|
|
1966
2020
|
|
|
1967
2021
|
def __rmul__(self, repetitions: _INT_TYPE):
|
|
1968
2022
|
if not isinstance(repetitions, (int, np.integer)):
|
|
@@ -1988,26 +2042,26 @@ class Circuit(AbstractCircuit):
|
|
|
1988
2042
|
return NotImplemented
|
|
1989
2043
|
inv_moments.append(inv_moment)
|
|
1990
2044
|
|
|
1991
|
-
return cirq.Circuit(inv_moments)
|
|
2045
|
+
return cirq.Circuit(inv_moments, tags=self.tags)
|
|
1992
2046
|
|
|
1993
2047
|
__hash__ = None # type: ignore
|
|
1994
2048
|
|
|
1995
2049
|
def concat_ragged(
|
|
1996
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
2050
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
1997
2051
|
) -> cirq.Circuit:
|
|
1998
2052
|
return AbstractCircuit.concat_ragged(*circuits, align=align).unfreeze(copy=False)
|
|
1999
2053
|
|
|
2000
2054
|
concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__
|
|
2001
2055
|
|
|
2002
2056
|
def zip(
|
|
2003
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
2057
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
2004
2058
|
) -> cirq.Circuit:
|
|
2005
2059
|
return AbstractCircuit.zip(*circuits, align=align).unfreeze(copy=False)
|
|
2006
2060
|
|
|
2007
2061
|
zip.__doc__ = AbstractCircuit.zip.__doc__
|
|
2008
2062
|
|
|
2009
2063
|
def transform_qubits(
|
|
2010
|
-
self, qubit_map:
|
|
2064
|
+
self, qubit_map: dict[cirq.Qid, cirq.Qid] | Callable[[cirq.Qid], cirq.Qid]
|
|
2011
2065
|
) -> cirq.Circuit:
|
|
2012
2066
|
"""Returns the same circuit, but with different qubits.
|
|
2013
2067
|
|
|
@@ -2055,7 +2109,7 @@ class Circuit(AbstractCircuit):
|
|
|
2055
2109
|
return Circuit(op_list)
|
|
2056
2110
|
|
|
2057
2111
|
def earliest_available_moment(
|
|
2058
|
-
self, op: cirq.Operation, *, end_moment_index:
|
|
2112
|
+
self, op: cirq.Operation, *, end_moment_index: int | None = None
|
|
2059
2113
|
) -> int:
|
|
2060
2114
|
"""Finds the index of the earliest (i.e. left most) moment which can accommodate `op`.
|
|
2061
2115
|
|
|
@@ -2148,7 +2202,7 @@ class Circuit(AbstractCircuit):
|
|
|
2148
2202
|
and not all(
|
|
2149
2203
|
(strategy is InsertStrategy.EARLIEST and self._can_add_op_at(k, op))
|
|
2150
2204
|
or (k > 0 and self._can_add_op_at(k - 1, op))
|
|
2151
|
-
for op in cast(
|
|
2205
|
+
for op in cast(list[cirq.Operation], batch)
|
|
2152
2206
|
)
|
|
2153
2207
|
):
|
|
2154
2208
|
self._moments.insert(k, Moment())
|
|
@@ -2227,10 +2281,10 @@ class Circuit(AbstractCircuit):
|
|
|
2227
2281
|
|
|
2228
2282
|
def _push_frontier(
|
|
2229
2283
|
self,
|
|
2230
|
-
early_frontier:
|
|
2231
|
-
late_frontier:
|
|
2232
|
-
update_qubits:
|
|
2233
|
-
) ->
|
|
2284
|
+
early_frontier: dict[cirq.Qid, int],
|
|
2285
|
+
late_frontier: dict[cirq.Qid, int],
|
|
2286
|
+
update_qubits: Iterable[cirq.Qid] | None = None,
|
|
2287
|
+
) -> tuple[int, int]:
|
|
2234
2288
|
"""Inserts moments to separate two frontiers.
|
|
2235
2289
|
|
|
2236
2290
|
After insertion n_new moments, the following holds:
|
|
@@ -2292,15 +2346,15 @@ class Circuit(AbstractCircuit):
|
|
|
2292
2346
|
raise ValueError('operations and insertion_indices must have the same length.')
|
|
2293
2347
|
self._moments += [Moment() for _ in range(1 + max(insertion_indices) - len(self))]
|
|
2294
2348
|
self._mutated()
|
|
2295
|
-
moment_to_ops:
|
|
2349
|
+
moment_to_ops: dict[int, list[cirq.Operation]] = defaultdict(list)
|
|
2296
2350
|
for op_index, moment_index in enumerate(insertion_indices):
|
|
2297
2351
|
moment_to_ops[moment_index].append(operations[op_index])
|
|
2298
2352
|
for moment_index, new_ops in moment_to_ops.items():
|
|
2299
2353
|
self._moments[moment_index] = self._moments[moment_index].with_operations(*new_ops)
|
|
2300
2354
|
|
|
2301
2355
|
def insert_at_frontier(
|
|
2302
|
-
self, operations: cirq.OP_TREE, start: int, frontier:
|
|
2303
|
-
) ->
|
|
2356
|
+
self, operations: cirq.OP_TREE, start: int, frontier: dict[cirq.Qid, int] | None = None
|
|
2357
|
+
) -> dict[cirq.Qid, int]:
|
|
2304
2358
|
"""Inserts operations inline at frontier.
|
|
2305
2359
|
|
|
2306
2360
|
Args:
|
|
@@ -2334,7 +2388,7 @@ class Circuit(AbstractCircuit):
|
|
|
2334
2388
|
|
|
2335
2389
|
return frontier
|
|
2336
2390
|
|
|
2337
|
-
def batch_remove(self, removals: Iterable[
|
|
2391
|
+
def batch_remove(self, removals: Iterable[tuple[int, cirq.Operation]]) -> None:
|
|
2338
2392
|
"""Removes several operations from a circuit.
|
|
2339
2393
|
|
|
2340
2394
|
Args:
|
|
@@ -2358,7 +2412,7 @@ class Circuit(AbstractCircuit):
|
|
|
2358
2412
|
self._mutated()
|
|
2359
2413
|
|
|
2360
2414
|
def batch_replace(
|
|
2361
|
-
self, replacements: Iterable[
|
|
2415
|
+
self, replacements: Iterable[tuple[int, cirq.Operation, cirq.Operation]]
|
|
2362
2416
|
) -> None:
|
|
2363
2417
|
"""Replaces several operations in a circuit with new operations.
|
|
2364
2418
|
|
|
@@ -2382,7 +2436,7 @@ class Circuit(AbstractCircuit):
|
|
|
2382
2436
|
self._moments = copy._moments
|
|
2383
2437
|
self._mutated()
|
|
2384
2438
|
|
|
2385
|
-
def batch_insert_into(self, insert_intos: Iterable[
|
|
2439
|
+
def batch_insert_into(self, insert_intos: Iterable[tuple[int, cirq.OP_TREE]]) -> None:
|
|
2386
2440
|
"""Inserts operations into empty spaces in existing moments.
|
|
2387
2441
|
|
|
2388
2442
|
If any of the insertions fails (due to colliding with an existing
|
|
@@ -2403,7 +2457,7 @@ class Circuit(AbstractCircuit):
|
|
|
2403
2457
|
self._moments = copy._moments
|
|
2404
2458
|
self._mutated()
|
|
2405
2459
|
|
|
2406
|
-
def batch_insert(self, insertions: Iterable[
|
|
2460
|
+
def batch_insert(self, insertions: Iterable[tuple[int, cirq.OP_TREE]]) -> None:
|
|
2407
2461
|
"""Applies a batched insert operation to the circuit.
|
|
2408
2462
|
|
|
2409
2463
|
Transparently handles the fact that earlier insertions may shift
|
|
@@ -2453,7 +2507,9 @@ class Circuit(AbstractCircuit):
|
|
|
2453
2507
|
"""
|
|
2454
2508
|
self.insert(len(self._moments), moment_or_operation_tree, strategy)
|
|
2455
2509
|
|
|
2456
|
-
def clear_operations_touching(
|
|
2510
|
+
def clear_operations_touching(
|
|
2511
|
+
self, qubits: Iterable[cirq.Qid], moment_indices: Iterable[int]
|
|
2512
|
+
) -> None:
|
|
2457
2513
|
"""Clears operations that are touching given qubits at given moments.
|
|
2458
2514
|
|
|
2459
2515
|
Args:
|
|
@@ -2471,6 +2527,18 @@ class Circuit(AbstractCircuit):
|
|
|
2471
2527
|
def moments(self) -> Sequence[cirq.Moment]:
|
|
2472
2528
|
return self._moments
|
|
2473
2529
|
|
|
2530
|
+
@property
|
|
2531
|
+
def tags(self) -> tuple[Hashable, ...]:
|
|
2532
|
+
return self._tags
|
|
2533
|
+
|
|
2534
|
+
def with_tags(self, *new_tags: Hashable) -> cirq.Circuit:
|
|
2535
|
+
"""Creates a new tagged `Circuit` with `self.tags` and `new_tags` combined."""
|
|
2536
|
+
if not new_tags:
|
|
2537
|
+
return self
|
|
2538
|
+
new_circuit = Circuit(tags=self.tags + new_tags)
|
|
2539
|
+
new_circuit._moments[:] = self._moments
|
|
2540
|
+
return new_circuit
|
|
2541
|
+
|
|
2474
2542
|
def with_noise(self, noise: cirq.NOISE_MODEL_LIKE) -> cirq.Circuit:
|
|
2475
2543
|
"""Make a noisy version of the circuit.
|
|
2476
2544
|
|
|
@@ -2485,7 +2553,7 @@ class Circuit(AbstractCircuit):
|
|
|
2485
2553
|
"""
|
|
2486
2554
|
noise_model = devices.NoiseModel.from_noise_model_like(noise)
|
|
2487
2555
|
qubits = sorted(self.all_qubits())
|
|
2488
|
-
c_noisy = Circuit()
|
|
2556
|
+
c_noisy = Circuit(tags=self.tags)
|
|
2489
2557
|
for op_tree in noise_model.noisy_moments(self, qubits):
|
|
2490
2558
|
# Keep moments aligned
|
|
2491
2559
|
c_noisy += Circuit(op_tree)
|
|
@@ -2495,8 +2563,8 @@ class Circuit(AbstractCircuit):
|
|
|
2495
2563
|
def _pick_inserted_ops_moment_indices(
|
|
2496
2564
|
operations: Sequence[cirq.Operation],
|
|
2497
2565
|
start: int = 0,
|
|
2498
|
-
frontier:
|
|
2499
|
-
) ->
|
|
2566
|
+
frontier: dict[cirq.Qid, int] | None = None,
|
|
2567
|
+
) -> tuple[Sequence[int], dict[cirq.Qid, int]]:
|
|
2500
2568
|
"""Greedily assigns operations to moments.
|
|
2501
2569
|
|
|
2502
2570
|
Args:
|
|
@@ -2541,13 +2609,13 @@ def _draw_moment_annotations(
|
|
|
2541
2609
|
moment: cirq.Moment,
|
|
2542
2610
|
col: int,
|
|
2543
2611
|
use_unicode_characters: bool,
|
|
2544
|
-
label_map:
|
|
2612
|
+
label_map: dict[cirq.LabelEntity, int],
|
|
2545
2613
|
out_diagram: cirq.TextDiagramDrawer,
|
|
2546
|
-
precision:
|
|
2614
|
+
precision: int | None,
|
|
2547
2615
|
get_circuit_diagram_info: Callable[
|
|
2548
2616
|
[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo
|
|
2549
2617
|
],
|
|
2550
|
-
include_tags: bool,
|
|
2618
|
+
include_tags: bool | Iterable[type],
|
|
2551
2619
|
first_annotation_row: int,
|
|
2552
2620
|
transpose: bool,
|
|
2553
2621
|
):
|
|
@@ -2572,14 +2640,14 @@ def _draw_moment_in_diagram(
|
|
|
2572
2640
|
*,
|
|
2573
2641
|
moment: cirq.Moment,
|
|
2574
2642
|
use_unicode_characters: bool,
|
|
2575
|
-
label_map:
|
|
2643
|
+
label_map: dict[cirq.LabelEntity, int],
|
|
2576
2644
|
out_diagram: cirq.TextDiagramDrawer,
|
|
2577
|
-
precision:
|
|
2578
|
-
moment_groups:
|
|
2579
|
-
get_circuit_diagram_info:
|
|
2580
|
-
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo]
|
|
2581
|
-
|
|
2582
|
-
include_tags: bool,
|
|
2645
|
+
precision: int | None,
|
|
2646
|
+
moment_groups: list[tuple[int, int]],
|
|
2647
|
+
get_circuit_diagram_info: (
|
|
2648
|
+
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo] | None
|
|
2649
|
+
),
|
|
2650
|
+
include_tags: bool | Iterable[type],
|
|
2583
2651
|
first_annotation_row: int,
|
|
2584
2652
|
transpose: bool,
|
|
2585
2653
|
):
|
|
@@ -2650,8 +2718,16 @@ def _draw_moment_in_diagram(
|
|
|
2650
2718
|
desc = _formatted_phase(global_phase, use_unicode_characters, precision)
|
|
2651
2719
|
if desc:
|
|
2652
2720
|
y = max(label_map.values(), default=0) + 1
|
|
2653
|
-
|
|
2654
|
-
|
|
2721
|
+
visible_tags = protocols.CircuitDiagramInfoArgs(
|
|
2722
|
+
known_qubits=None,
|
|
2723
|
+
known_qubit_count=None,
|
|
2724
|
+
use_unicode_characters=True,
|
|
2725
|
+
precision=None,
|
|
2726
|
+
label_map=None,
|
|
2727
|
+
include_tags=include_tags,
|
|
2728
|
+
).tags_to_include(tags)
|
|
2729
|
+
if visible_tags:
|
|
2730
|
+
desc = desc + f"[{', '.join(map(str, visible_tags))}]"
|
|
2655
2731
|
out_diagram.write(x0, y, desc)
|
|
2656
2732
|
|
|
2657
2733
|
if not non_global_ops:
|
|
@@ -2662,7 +2738,7 @@ def _draw_moment_in_diagram(
|
|
|
2662
2738
|
moment_groups.append((x0, max_x))
|
|
2663
2739
|
|
|
2664
2740
|
|
|
2665
|
-
def _get_global_phase_and_tags_for_op(op: cirq.Operation) ->
|
|
2741
|
+
def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> tuple[complex | None, list[Any]]:
|
|
2666
2742
|
if isinstance(op.gate, ops.GlobalPhaseGate):
|
|
2667
2743
|
return complex(op.gate.coefficient), list(op.tags)
|
|
2668
2744
|
elif isinstance(op.untagged, CircuitOperation):
|
|
@@ -2671,9 +2747,9 @@ def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> Tuple[Optional[comp
|
|
|
2671
2747
|
return None, []
|
|
2672
2748
|
|
|
2673
2749
|
|
|
2674
|
-
def _get_global_phase_and_tags_for_ops(op_list: Any) ->
|
|
2675
|
-
global_phase:
|
|
2676
|
-
tags:
|
|
2750
|
+
def _get_global_phase_and_tags_for_ops(op_list: Any) -> tuple[complex | None, list[Any]]:
|
|
2751
|
+
global_phase: complex | None = None
|
|
2752
|
+
tags: list[Any] = []
|
|
2677
2753
|
for op in op_list:
|
|
2678
2754
|
op_phase, op_tags = _get_global_phase_and_tags_for_op(op)
|
|
2679
2755
|
if op_phase:
|
|
@@ -2685,7 +2761,7 @@ def _get_global_phase_and_tags_for_ops(op_list: Any) -> Tuple[Optional[complex],
|
|
|
2685
2761
|
return global_phase, tags
|
|
2686
2762
|
|
|
2687
2763
|
|
|
2688
|
-
def _formatted_phase(coefficient: complex, unicode: bool, precision:
|
|
2764
|
+
def _formatted_phase(coefficient: complex, unicode: bool, precision: int | None) -> str:
|
|
2689
2765
|
h = math.atan2(coefficient.imag, coefficient.real) / math.pi
|
|
2690
2766
|
unit = 'π' if unicode else 'pi'
|
|
2691
2767
|
if h == 1:
|
|
@@ -2694,7 +2770,7 @@ def _formatted_phase(coefficient: complex, unicode: bool, precision: Optional[in
|
|
|
2694
2770
|
|
|
2695
2771
|
|
|
2696
2772
|
def _draw_moment_groups_in_diagram(
|
|
2697
|
-
moment_groups:
|
|
2773
|
+
moment_groups: list[tuple[int, int]],
|
|
2698
2774
|
use_unicode_characters: bool,
|
|
2699
2775
|
out_diagram: cirq.TextDiagramDrawer,
|
|
2700
2776
|
):
|
|
@@ -2728,8 +2804,8 @@ def _draw_moment_groups_in_diagram(
|
|
|
2728
2804
|
def _apply_unitary_circuit(
|
|
2729
2805
|
circuit: cirq.AbstractCircuit,
|
|
2730
2806
|
state: np.ndarray,
|
|
2731
|
-
qubits:
|
|
2732
|
-
dtype:
|
|
2807
|
+
qubits: tuple[cirq.Qid, ...],
|
|
2808
|
+
dtype: type[np.complexfloating],
|
|
2733
2809
|
) -> np.ndarray:
|
|
2734
2810
|
"""Applies a circuit's unitary effect to the given vector or matrix.
|
|
2735
2811
|
|
|
@@ -2792,14 +2868,14 @@ _TKey = TypeVar('_TKey')
|
|
|
2792
2868
|
@overload
|
|
2793
2869
|
def _group_until_different(
|
|
2794
2870
|
items: Iterable[_TIn], key: Callable[[_TIn], _TKey]
|
|
2795
|
-
) -> Iterable[
|
|
2871
|
+
) -> Iterable[tuple[_TKey, list[_TIn]]]:
|
|
2796
2872
|
pass
|
|
2797
2873
|
|
|
2798
2874
|
|
|
2799
2875
|
@overload
|
|
2800
2876
|
def _group_until_different(
|
|
2801
2877
|
items: Iterable[_TIn], key: Callable[[_TIn], _TKey], val: Callable[[_TIn], _TOut]
|
|
2802
|
-
) -> Iterable[
|
|
2878
|
+
) -> Iterable[tuple[_TKey, list[_TOut]]]:
|
|
2803
2879
|
pass
|
|
2804
2880
|
|
|
2805
2881
|
|
|
@@ -2829,7 +2905,7 @@ def _group_until_different(items: Iterable[_TIn], key: Callable[[_TIn], _TKey],
|
|
|
2829
2905
|
return ((k, [val(i) for i in v]) for (k, v) in itertools.groupby(items, key))
|
|
2830
2906
|
|
|
2831
2907
|
|
|
2832
|
-
def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[
|
|
2908
|
+
def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[list[_MOMENT_OR_OP]]:
|
|
2833
2909
|
"""Groups sequential ops into those that can coexist in a single moment.
|
|
2834
2910
|
|
|
2835
2911
|
This function will go through the input sequence in order, emitting lists of sequential
|
|
@@ -2844,8 +2920,8 @@ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[L
|
|
|
2844
2920
|
[X(a), X(a), X(b)] -> [[X(a)], [X(a), X(b)]]
|
|
2845
2921
|
[X(a), Moment(X(b)), X(c)] -> [[X(a)], [Moment(X(b))], [X(c)]]
|
|
2846
2922
|
"""
|
|
2847
|
-
batch:
|
|
2848
|
-
batch_qubits:
|
|
2923
|
+
batch: list[_MOMENT_OR_OP] = []
|
|
2924
|
+
batch_qubits: set[cirq.Qid] = set()
|
|
2849
2925
|
for mop in inputs:
|
|
2850
2926
|
is_moment = isinstance(mop, cirq.Moment)
|
|
2851
2927
|
if (is_moment and batch) or not batch_qubits.isdisjoint(mop.qubits):
|
|
@@ -2863,10 +2939,10 @@ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[L
|
|
|
2863
2939
|
|
|
2864
2940
|
def get_earliest_accommodating_moment_index(
|
|
2865
2941
|
moment_or_operation: _MOMENT_OR_OP,
|
|
2866
|
-
qubit_indices:
|
|
2867
|
-
mkey_indices:
|
|
2868
|
-
ckey_indices:
|
|
2869
|
-
length:
|
|
2942
|
+
qubit_indices: dict[cirq.Qid, int],
|
|
2943
|
+
mkey_indices: dict[cirq.MeasurementKey, int],
|
|
2944
|
+
ckey_indices: dict[cirq.MeasurementKey, int],
|
|
2945
|
+
length: int | None = None,
|
|
2870
2946
|
) -> int:
|
|
2871
2947
|
"""Get the index of the earliest moment that can accommodate the given moment or operation.
|
|
2872
2948
|
|
|
@@ -2951,9 +3027,9 @@ class _PlacementCache:
|
|
|
2951
3027
|
|
|
2952
3028
|
def __init__(self) -> None:
|
|
2953
3029
|
# These are dicts from the qubit/key to the greatest moment index that has it.
|
|
2954
|
-
self._qubit_indices:
|
|
2955
|
-
self._mkey_indices:
|
|
2956
|
-
self._ckey_indices:
|
|
3030
|
+
self._qubit_indices: dict[cirq.Qid, int] = {}
|
|
3031
|
+
self._mkey_indices: dict[cirq.MeasurementKey, int] = {}
|
|
3032
|
+
self._ckey_indices: dict[cirq.MeasurementKey, int] = {}
|
|
2957
3033
|
|
|
2958
3034
|
# For keeping track of length of the circuit thus far.
|
|
2959
3035
|
self._length = 0
|