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/ops/control_values.py
CHANGED
|
@@ -11,10 +11,13 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import abc
|
|
15
18
|
import itertools
|
|
16
19
|
from functools import cached_property
|
|
17
|
-
from typing import Any, Collection,
|
|
20
|
+
from typing import Any, Collection, Iterator, Sequence, TYPE_CHECKING
|
|
18
21
|
|
|
19
22
|
from cirq import protocols, value
|
|
20
23
|
|
|
@@ -47,7 +50,7 @@ class AbstractControlValues(abc.ABC):
|
|
|
47
50
|
"""Validates that all control values for ith qubit are in range [0, qid_shaped[i])"""
|
|
48
51
|
|
|
49
52
|
@abc.abstractmethod
|
|
50
|
-
def expand(self) ->
|
|
53
|
+
def expand(self) -> SumOfProducts:
|
|
51
54
|
"""Returns an expanded `cirq.SumOfProduct` representation of this control values."""
|
|
52
55
|
|
|
53
56
|
@property
|
|
@@ -64,17 +67,15 @@ class AbstractControlValues(abc.ABC):
|
|
|
64
67
|
"""Returns the number of qubits for which control values are stored by this object."""
|
|
65
68
|
|
|
66
69
|
@abc.abstractmethod
|
|
67
|
-
def _json_dict_(self) ->
|
|
70
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
68
71
|
"""Returns a dictionary used for serializing this object."""
|
|
69
72
|
|
|
70
73
|
@abc.abstractmethod
|
|
71
|
-
def _circuit_diagram_info_(
|
|
72
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
73
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
74
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
74
75
|
"""Returns information used to draw this object in circuit diagrams."""
|
|
75
76
|
|
|
76
77
|
@abc.abstractmethod
|
|
77
|
-
def __iter__(self) -> Iterator[
|
|
78
|
+
def __iter__(self) -> Iterator[tuple[int, ...]]:
|
|
78
79
|
"""Iterator on internal representation of control values used by the derived classes.
|
|
79
80
|
|
|
80
81
|
Note: Be careful that the terms iterated upon by this iterator will have different
|
|
@@ -88,7 +89,7 @@ class AbstractControlValues(abc.ABC):
|
|
|
88
89
|
def _value_equality_values_(self) -> Any:
|
|
89
90
|
return tuple(v for v in self.expand())
|
|
90
91
|
|
|
91
|
-
def __and__(self, other:
|
|
92
|
+
def __and__(self, other: AbstractControlValues) -> AbstractControlValues:
|
|
92
93
|
"""Returns a cartesian product of all control values predicates in `self` x `other`.
|
|
93
94
|
|
|
94
95
|
The `and` of two control values `cv1` and `cv2` represents a control value object
|
|
@@ -109,7 +110,7 @@ class AbstractControlValues(abc.ABC):
|
|
|
109
110
|
tuple(x + y for (x, y) in itertools.product(self.expand(), other.expand()))
|
|
110
111
|
)
|
|
111
112
|
|
|
112
|
-
def __or__(self, other:
|
|
113
|
+
def __or__(self, other: AbstractControlValues) -> AbstractControlValues:
|
|
113
114
|
"""Returns a union of all control values predicates in `self` + `other`.
|
|
114
115
|
|
|
115
116
|
Both `self` and `other` must represent control values for the same set of qubits and
|
|
@@ -140,8 +141,8 @@ class AbstractControlValues(abc.ABC):
|
|
|
140
141
|
class ProductOfSums(AbstractControlValues):
|
|
141
142
|
"""Represents control values as N OR (sum) clauses, each of which applies to one qubit."""
|
|
142
143
|
|
|
143
|
-
def __init__(self, data: Sequence[
|
|
144
|
-
self._qubit_sums:
|
|
144
|
+
def __init__(self, data: Sequence[int | Collection[int]]):
|
|
145
|
+
self._qubit_sums: tuple[tuple[int, ...], ...] = tuple(
|
|
145
146
|
(cv,) if isinstance(cv, int) else tuple(sorted(set(cv))) for cv in data
|
|
146
147
|
)
|
|
147
148
|
|
|
@@ -149,10 +150,10 @@ class ProductOfSums(AbstractControlValues):
|
|
|
149
150
|
def is_trivial(self) -> bool:
|
|
150
151
|
return self._qubit_sums == ((1,),) * self._num_qubits_()
|
|
151
152
|
|
|
152
|
-
def __iter__(self) -> Iterator[
|
|
153
|
+
def __iter__(self) -> Iterator[tuple[int, ...]]:
|
|
153
154
|
return iter(self._qubit_sums)
|
|
154
155
|
|
|
155
|
-
def expand(self) ->
|
|
156
|
+
def expand(self) -> SumOfProducts:
|
|
156
157
|
return SumOfProducts(tuple(itertools.product(*self._qubit_sums)))
|
|
157
158
|
|
|
158
159
|
def __repr__(self) -> str:
|
|
@@ -161,7 +162,7 @@ class ProductOfSums(AbstractControlValues):
|
|
|
161
162
|
def _num_qubits_(self) -> int:
|
|
162
163
|
return len(self._qubit_sums)
|
|
163
164
|
|
|
164
|
-
def __getitem__(self, key:
|
|
165
|
+
def __getitem__(self, key: int | slice) -> ProductOfSums | tuple[int, ...]:
|
|
165
166
|
if isinstance(key, slice):
|
|
166
167
|
return ProductOfSums(self._qubit_sums[key])
|
|
167
168
|
return self._qubit_sums[key]
|
|
@@ -175,9 +176,7 @@ class ProductOfSums(AbstractControlValues):
|
|
|
175
176
|
)
|
|
176
177
|
raise ValueError(message)
|
|
177
178
|
|
|
178
|
-
def _circuit_diagram_info_(
|
|
179
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
180
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
179
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
181
180
|
"""Returns a string representation to be used in circuit diagrams."""
|
|
182
181
|
|
|
183
182
|
def get_symbol(vals):
|
|
@@ -195,7 +194,7 @@ class ProductOfSums(AbstractControlValues):
|
|
|
195
194
|
|
|
196
195
|
return ''.join(get_prefix(t) for t in self._qubit_sums)
|
|
197
196
|
|
|
198
|
-
def _json_dict_(self) ->
|
|
197
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
199
198
|
return {"data": self._qubit_sums}
|
|
200
199
|
|
|
201
200
|
def __and__(self, other: AbstractControlValues) -> AbstractControlValues:
|
|
@@ -242,8 +241,8 @@ class SumOfProducts(AbstractControlValues):
|
|
|
242
241
|
>>> nand_cop = cirq.X(q2).controlled_by(q0, q1, control_values=nand_control_values)
|
|
243
242
|
"""
|
|
244
243
|
|
|
245
|
-
def __init__(self, data: Collection[Sequence[int]], *, name:
|
|
246
|
-
self._conjunctions:
|
|
244
|
+
def __init__(self, data: Collection[Sequence[int]], *, name: str | None = None):
|
|
245
|
+
self._conjunctions: tuple[tuple[int, ...], ...] = tuple(
|
|
247
246
|
sorted(set(tuple(cv) for cv in data))
|
|
248
247
|
)
|
|
249
248
|
self._name = name
|
|
@@ -257,16 +256,14 @@ class SumOfProducts(AbstractControlValues):
|
|
|
257
256
|
def is_trivial(self) -> bool:
|
|
258
257
|
return self._conjunctions == ((1,) * self._num_qubits_(),)
|
|
259
258
|
|
|
260
|
-
def expand(self) ->
|
|
259
|
+
def expand(self) -> SumOfProducts:
|
|
261
260
|
return self
|
|
262
261
|
|
|
263
|
-
def __iter__(self) -> Iterator[
|
|
262
|
+
def __iter__(self) -> Iterator[tuple[int, ...]]:
|
|
264
263
|
"""Returns the combinations tracked by the object."""
|
|
265
264
|
return iter(self._conjunctions)
|
|
266
265
|
|
|
267
|
-
def _circuit_diagram_info_(
|
|
268
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
269
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
266
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
270
267
|
"""Returns a string representation to be used in circuit diagrams."""
|
|
271
268
|
if self._name is not None:
|
|
272
269
|
wire_symbols = ['@'] * self._num_qubits_()
|
|
@@ -316,5 +313,5 @@ class SumOfProducts(AbstractControlValues):
|
|
|
316
313
|
f' of range [0, {qid_shapes[q_i]}) for control qubit number <{q_i}>.'
|
|
317
314
|
)
|
|
318
315
|
|
|
319
|
-
def _json_dict_(self) ->
|
|
316
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
320
317
|
return {'data': self._conjunctions, 'name': self._name}
|
cirq/ops/control_values_test.py
CHANGED
|
@@ -12,12 +12,14 @@
|
|
|
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
|
|
|
19
21
|
|
|
20
|
-
def test_init_sum_of_products_raises():
|
|
22
|
+
def test_init_sum_of_products_raises() -> None:
|
|
21
23
|
# data shouldn't be empty.
|
|
22
24
|
with pytest.raises(ValueError):
|
|
23
25
|
_ = cirq.SumOfProducts([])
|
|
@@ -27,7 +29,7 @@ def test_init_sum_of_products_raises():
|
|
|
27
29
|
_ = cirq.SumOfProducts([[1], [1, 0]])
|
|
28
30
|
|
|
29
31
|
|
|
30
|
-
def test_init_product_of_sums():
|
|
32
|
+
def test_init_product_of_sums() -> None:
|
|
31
33
|
eq = cirq.testing.EqualsTester()
|
|
32
34
|
# 0. Trivial case of 1 control and 1 qubit.
|
|
33
35
|
eq.add_equality_group(cirq.ProductOfSums([1]), cirq.ProductOfSums(((1,),)))
|
|
@@ -57,7 +59,7 @@ def test_init_product_of_sums():
|
|
|
57
59
|
eq.add_equality_group([(1, 2), (0, 1)])
|
|
58
60
|
|
|
59
61
|
|
|
60
|
-
def test_init_sum_of_products():
|
|
62
|
+
def test_init_sum_of_products() -> None:
|
|
61
63
|
eq = cirq.testing.EqualsTester()
|
|
62
64
|
# 0. Trivial case of 1 control and 1 qubit
|
|
63
65
|
eq.add_equality_group(cirq.SumOfProducts([[1]]), cirq.SumOfProducts(((1,),)))
|
|
@@ -88,7 +90,7 @@ def test_init_sum_of_products():
|
|
|
88
90
|
eq.add_equality_group(cirq.SumOfProducts([(1, 0), (2, 0), (1, 1), (2, 1)]))
|
|
89
91
|
|
|
90
92
|
|
|
91
|
-
def test_equality_across_types():
|
|
93
|
+
def test_equality_across_types() -> None:
|
|
92
94
|
eq = cirq.testing.EqualsTester()
|
|
93
95
|
# Trivial case of 1 control and 1 qubit
|
|
94
96
|
eq.add_equality_group(
|
|
@@ -122,7 +124,7 @@ def test_equality_across_types():
|
|
|
122
124
|
eq.add_equality_group(cirq.ProductOfSums([(0, 1), (1, 0)])) # or control
|
|
123
125
|
|
|
124
126
|
|
|
125
|
-
def test_and_operation():
|
|
127
|
+
def test_and_operation() -> None:
|
|
126
128
|
eq = cirq.testing.EqualsTester()
|
|
127
129
|
|
|
128
130
|
eq.add_equality_group(
|
|
@@ -169,12 +171,12 @@ def test_and_operation():
|
|
|
169
171
|
[cirq.SumOfProducts([(0, 0), (1, 1)]), cirq.ProductOfSums([0, 1, 2]), cirq.SumOfProducts],
|
|
170
172
|
],
|
|
171
173
|
)
|
|
172
|
-
def test_and_operation_adds_qubits(cv1, cv2, expected_type):
|
|
174
|
+
def test_and_operation_adds_qubits(cv1, cv2, expected_type) -> None:
|
|
173
175
|
assert isinstance(cv1 & cv2, expected_type)
|
|
174
176
|
assert cirq.num_qubits(cv1 & cv2) == cirq.num_qubits(cv1) + cirq.num_qubits(cv2)
|
|
175
177
|
|
|
176
178
|
|
|
177
|
-
def test_or_operation():
|
|
179
|
+
def test_or_operation() -> None:
|
|
178
180
|
eq = cirq.testing.EqualsTester()
|
|
179
181
|
|
|
180
182
|
eq.add_equality_group(
|
|
@@ -212,7 +214,7 @@ def test_or_operation():
|
|
|
212
214
|
[cirq.SumOfProducts([[0], [1], [2]]), cirq.SumOfProducts([[1, 0]]), None],
|
|
213
215
|
],
|
|
214
216
|
)
|
|
215
|
-
def test_or_operation_acts_on_same_qubits(cv1, cv2, expected_type):
|
|
217
|
+
def test_or_operation_acts_on_same_qubits(cv1, cv2, expected_type) -> None:
|
|
216
218
|
if cirq.num_qubits(cv1) == cirq.num_qubits(cv2):
|
|
217
219
|
assert cirq.num_qubits(cv1 | cv2) == cirq.num_qubits(cv1)
|
|
218
220
|
assert expected_type is not None
|
|
@@ -224,31 +226,31 @@ def test_or_operation_acts_on_same_qubits(cv1, cv2, expected_type):
|
|
|
224
226
|
|
|
225
227
|
|
|
226
228
|
@pytest.mark.parametrize('data', [((1,),), ((0, 1), (1,)), [(0, 1), (1, 0)]])
|
|
227
|
-
def test_product_of_sums_repr(data):
|
|
229
|
+
def test_product_of_sums_repr(data) -> None:
|
|
228
230
|
cirq.testing.assert_equivalent_repr(cirq.ProductOfSums(data))
|
|
229
231
|
|
|
230
232
|
|
|
231
233
|
@pytest.mark.parametrize('data', [((1,),), ((0, 1),), ((0, 0), (0, 1), (1, 0))])
|
|
232
|
-
def test_sum_of_products_repr(data):
|
|
234
|
+
def test_sum_of_products_repr(data) -> None:
|
|
233
235
|
cirq.testing.assert_equivalent_repr(cirq.SumOfProducts(data))
|
|
234
236
|
cirq.testing.assert_equivalent_repr(cirq.SumOfProducts(data, name="CustomName"))
|
|
235
237
|
|
|
236
238
|
|
|
237
|
-
def test_sum_of_products_validate():
|
|
239
|
+
def test_sum_of_products_validate() -> None:
|
|
238
240
|
control_val = cirq.SumOfProducts(((1, 2), (0, 1)))
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
control_val.validate([2, 3])
|
|
241
243
|
|
|
242
244
|
with pytest.raises(ValueError):
|
|
243
|
-
|
|
245
|
+
control_val.validate([2, 2])
|
|
244
246
|
|
|
245
247
|
# number of qubits != number of control values.
|
|
246
248
|
with pytest.raises(ValueError):
|
|
247
|
-
|
|
249
|
+
control_val.validate([2])
|
|
248
250
|
|
|
249
251
|
|
|
250
252
|
@pytest.mark.parametrize('data', [((1,),), ((0, 1),), ((0, 0), (0, 1), (1, 0))])
|
|
251
|
-
def test_sum_of_products_num_qubits(data):
|
|
253
|
+
def test_sum_of_products_num_qubits(data) -> None:
|
|
252
254
|
assert cirq.num_qubits(cirq.SumOfProducts(data)) == len(data[0])
|
|
253
255
|
|
|
254
256
|
|
|
@@ -261,7 +263,7 @@ def test_sum_of_products_num_qubits(data):
|
|
|
261
263
|
[((1, 1, 1, 1),), True],
|
|
262
264
|
],
|
|
263
265
|
)
|
|
264
|
-
def test_sum_of_products_is_trivial(data, is_trivial):
|
|
266
|
+
def test_sum_of_products_is_trivial(data, is_trivial) -> None:
|
|
265
267
|
assert cirq.SumOfProducts(data).is_trivial == is_trivial
|
|
266
268
|
|
|
267
269
|
|
|
@@ -269,16 +271,16 @@ def test_sum_of_products_is_trivial(data, is_trivial):
|
|
|
269
271
|
'data, is_trivial',
|
|
270
272
|
[[((1,),), True], [((0, 1),), False], [([2], [1], [2]), False], [([1], [1], [1], [1]), True]],
|
|
271
273
|
)
|
|
272
|
-
def test_product_of_sum_is_trivial(data, is_trivial):
|
|
274
|
+
def test_product_of_sum_is_trivial(data, is_trivial) -> None:
|
|
273
275
|
assert cirq.ProductOfSums(data).is_trivial == is_trivial
|
|
274
276
|
|
|
275
277
|
|
|
276
|
-
def test_product_of_sums_str():
|
|
278
|
+
def test_product_of_sums_str() -> None:
|
|
277
279
|
c = cirq.ProductOfSums([(0, 1), 1, 0, (0, 2)])
|
|
278
280
|
assert str(c) == 'C01C1C0C02'
|
|
279
281
|
|
|
280
282
|
|
|
281
|
-
def test_sum_of_products_str():
|
|
283
|
+
def test_sum_of_products_str() -> None:
|
|
282
284
|
c = cirq.SumOfProducts(((1, 0), (0, 1)))
|
|
283
285
|
assert str(c) == 'C_01_10'
|
|
284
286
|
|
|
@@ -286,7 +288,7 @@ def test_sum_of_products_str():
|
|
|
286
288
|
assert str(c) == 'C_xor'
|
|
287
289
|
|
|
288
290
|
|
|
289
|
-
def test_control_values_diagrams():
|
|
291
|
+
def test_control_values_diagrams() -> None:
|
|
290
292
|
q = cirq.LineQubit.range(3)
|
|
291
293
|
ccx = cirq.X(q[0]).controlled_by(*q[1:])
|
|
292
294
|
ccx_sop = cirq.X(q[0]).controlled_by(*q[1:], control_values=cirq.SumOfProducts([[1, 1]]))
|
cirq/ops/controlled_gate.py
CHANGED
|
@@ -12,19 +12,10 @@
|
|
|
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 types import NotImplementedType
|
|
16
|
-
from typing import
|
|
17
|
-
AbstractSet,
|
|
18
|
-
Any,
|
|
19
|
-
Collection,
|
|
20
|
-
Dict,
|
|
21
|
-
List,
|
|
22
|
-
Optional,
|
|
23
|
-
Sequence,
|
|
24
|
-
Tuple,
|
|
25
|
-
TYPE_CHECKING,
|
|
26
|
-
Union,
|
|
27
|
-
)
|
|
18
|
+
from typing import AbstractSet, Any, Collection, Sequence, TYPE_CHECKING
|
|
28
19
|
|
|
29
20
|
import numpy as np
|
|
30
21
|
|
|
@@ -33,7 +24,6 @@ from cirq.ops import (
|
|
|
33
24
|
control_values as cv,
|
|
34
25
|
controlled_operation as cop,
|
|
35
26
|
diagonal_gate as dg,
|
|
36
|
-
global_phase_op as gp,
|
|
37
27
|
op_tree,
|
|
38
28
|
raw_types,
|
|
39
29
|
)
|
|
@@ -57,12 +47,10 @@ class ControlledGate(raw_types.Gate):
|
|
|
57
47
|
|
|
58
48
|
def __init__(
|
|
59
49
|
self,
|
|
60
|
-
sub_gate:
|
|
61
|
-
num_controls:
|
|
62
|
-
control_values:
|
|
63
|
-
|
|
64
|
-
] = None,
|
|
65
|
-
control_qid_shape: Optional[Sequence[int]] = None,
|
|
50
|
+
sub_gate: cirq.Gate,
|
|
51
|
+
num_controls: int | None = None,
|
|
52
|
+
control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
|
|
53
|
+
control_qid_shape: Sequence[int] | None = None,
|
|
66
54
|
) -> None:
|
|
67
55
|
"""Initializes the controlled gate. If no arguments are specified for
|
|
68
56
|
the controls, defaults to a single qubit control.
|
|
@@ -133,7 +121,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
133
121
|
self._sub_gate = sub_gate
|
|
134
122
|
|
|
135
123
|
@property
|
|
136
|
-
def control_qid_shape(self) ->
|
|
124
|
+
def control_qid_shape(self) -> tuple[int, ...]:
|
|
137
125
|
return self._control_qid_shape
|
|
138
126
|
|
|
139
127
|
@property
|
|
@@ -141,102 +129,70 @@ class ControlledGate(raw_types.Gate):
|
|
|
141
129
|
return self._control_values
|
|
142
130
|
|
|
143
131
|
@property
|
|
144
|
-
def sub_gate(self) ->
|
|
132
|
+
def sub_gate(self) -> cirq.Gate:
|
|
145
133
|
return self._sub_gate
|
|
146
134
|
|
|
147
135
|
def num_controls(self) -> int:
|
|
148
136
|
return len(self.control_qid_shape)
|
|
149
137
|
|
|
150
|
-
def _qid_shape_(self) ->
|
|
138
|
+
def _qid_shape_(self) -> tuple[int, ...]:
|
|
151
139
|
return self.control_qid_shape + protocols.qid_shape(self.sub_gate)
|
|
152
140
|
|
|
153
|
-
def _decompose_(
|
|
154
|
-
self, qubits: Tuple['cirq.Qid', ...]
|
|
155
|
-
) -> Union[None, NotImplementedType, 'cirq.OP_TREE']:
|
|
156
|
-
return self._decompose_with_context_(qubits)
|
|
157
|
-
|
|
158
141
|
def _decompose_with_context_(
|
|
159
|
-
self, qubits:
|
|
160
|
-
) ->
|
|
142
|
+
self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext
|
|
143
|
+
) -> NotImplementedType | cirq.OP_TREE:
|
|
161
144
|
control_qubits = list(qubits[: self.num_controls()])
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if set(cvals) == {0}:
|
|
171
|
-
invert_ops.append(common_gates.X(cqbit))
|
|
172
|
-
elif set(cvals) == {0, 1}:
|
|
173
|
-
control_qubits.remove(cqbit)
|
|
174
|
-
decomposed_ops = controlled_gate_decomposition.decompose_multi_controlled_rotation(
|
|
175
|
-
protocols.unitary(self.sub_gate), control_qubits, qubits[-1]
|
|
176
|
-
)
|
|
177
|
-
return invert_ops + decomposed_ops + invert_ops
|
|
178
|
-
if isinstance(self.sub_gate, gp.GlobalPhaseGate):
|
|
179
|
-
# A controlled global phase is a diagonal gate, where each active control value index
|
|
180
|
-
# is set equal to the phase angle.
|
|
181
|
-
shape = self.control_qid_shape
|
|
182
|
-
if protocols.is_parameterized(self.sub_gate) or set(shape) != {2}:
|
|
183
|
-
# Could work in theory, but DiagonalGate decompose does not support them.
|
|
184
|
-
return NotImplemented
|
|
185
|
-
angle = np.angle(complex(self.sub_gate.coefficient))
|
|
186
|
-
rads = np.zeros(shape=shape)
|
|
187
|
-
for hot in self.control_values.expand():
|
|
188
|
-
rads[hot] = angle
|
|
189
|
-
return dg.DiagonalGate(diag_angles_radians=[*rads.flatten()]).on(*qubits)
|
|
190
|
-
if isinstance(self.sub_gate, common_gates.CZPowGate):
|
|
191
|
-
z_sub_gate = common_gates.ZPowGate(exponent=self.sub_gate.exponent)
|
|
192
|
-
num_controls = self.num_controls() + 1
|
|
193
|
-
control_values = self.control_values & cv.ProductOfSums(((1,),))
|
|
194
|
-
control_qid_shape = self.control_qid_shape + (2,)
|
|
195
|
-
controlled_z = (
|
|
196
|
-
z_sub_gate.controlled(
|
|
197
|
-
num_controls=num_controls,
|
|
198
|
-
control_values=control_values,
|
|
199
|
-
control_qid_shape=control_qid_shape,
|
|
200
|
-
)
|
|
201
|
-
if protocols.is_parameterized(self)
|
|
202
|
-
else ControlledGate(
|
|
203
|
-
z_sub_gate,
|
|
204
|
-
num_controls=num_controls,
|
|
205
|
-
control_values=control_values,
|
|
206
|
-
control_qid_shape=control_qid_shape,
|
|
207
|
-
)
|
|
208
|
-
)
|
|
209
|
-
if self != controlled_z:
|
|
210
|
-
result = controlled_z.on(*qubits)
|
|
211
|
-
if self.sub_gate.global_shift == 0:
|
|
212
|
-
return result
|
|
213
|
-
# Reconstruct the controlled global shift of the subgate.
|
|
214
|
-
total_shift = self.sub_gate.exponent * self.sub_gate.global_shift
|
|
215
|
-
phase_gate = gp.GlobalPhaseGate(1j ** (2 * total_shift))
|
|
216
|
-
controlled_phase_op = phase_gate.controlled(
|
|
217
|
-
num_controls=self.num_controls(),
|
|
218
|
-
control_values=self.control_values,
|
|
219
|
-
control_qid_shape=self.control_qid_shape,
|
|
220
|
-
).on(*control_qubits)
|
|
221
|
-
return [result, controlled_phase_op]
|
|
145
|
+
controlled_sub_gate = self.sub_gate.controlled(
|
|
146
|
+
self.num_controls(), self.control_values, self.control_qid_shape
|
|
147
|
+
)
|
|
148
|
+
# Prefer the subgate controlled version if available
|
|
149
|
+
if self != controlled_sub_gate:
|
|
150
|
+
return controlled_sub_gate.on(*qubits)
|
|
151
|
+
|
|
152
|
+
# Try decomposing the subgate next.
|
|
222
153
|
result = protocols.decompose_once_with_qubits(
|
|
223
154
|
self.sub_gate,
|
|
224
155
|
qubits[self.num_controls() :],
|
|
225
156
|
NotImplemented,
|
|
226
157
|
flatten=False,
|
|
227
|
-
|
|
158
|
+
# Extract global phases from decomposition, as controlled phases decompose easily.
|
|
159
|
+
context=context.extracting_global_phases(),
|
|
228
160
|
)
|
|
229
|
-
if result is NotImplemented:
|
|
230
|
-
return
|
|
161
|
+
if result is not NotImplemented:
|
|
162
|
+
return op_tree.transform_op_tree(
|
|
163
|
+
result,
|
|
164
|
+
lambda op: op.controlled_by(
|
|
165
|
+
*qubits[: self.num_controls()], control_values=self.control_values
|
|
166
|
+
),
|
|
167
|
+
)
|
|
231
168
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
169
|
+
# Finally try brute-force on the unitary.
|
|
170
|
+
if protocols.has_unitary(self.sub_gate) and all(q.dimension == 2 for q in qubits):
|
|
171
|
+
n_qubits = protocols.num_qubits(self.sub_gate)
|
|
172
|
+
# Case 1: Global Phase (1x1 Matrix)
|
|
173
|
+
if n_qubits == 0:
|
|
174
|
+
angle = np.angle(protocols.unitary(self.sub_gate)[0, 0])
|
|
175
|
+
rads = np.zeros(shape=self.control_qid_shape)
|
|
176
|
+
for hot in self.control_values.expand():
|
|
177
|
+
rads[hot] = angle
|
|
178
|
+
return dg.DiagonalGate(diag_angles_radians=[*rads.flatten()]).on(*qubits)
|
|
179
|
+
# Case 2: Multi-controlled single-qubit gate decomposition
|
|
180
|
+
if n_qubits == 1 and isinstance(self.control_values, cv.ProductOfSums):
|
|
181
|
+
invert_ops: list[cirq.Operation] = []
|
|
182
|
+
for cvals, cqbit in zip(self.control_values, qubits[: self.num_controls()]):
|
|
183
|
+
if set(cvals) == {0}:
|
|
184
|
+
invert_ops.append(common_gates.X(cqbit))
|
|
185
|
+
elif set(cvals) == {0, 1}:
|
|
186
|
+
control_qubits.remove(cqbit)
|
|
187
|
+
decomposed_ops = controlled_gate_decomposition.decompose_multi_controlled_rotation(
|
|
188
|
+
protocols.unitary(self.sub_gate), control_qubits, qubits[-1]
|
|
189
|
+
)
|
|
190
|
+
return invert_ops + decomposed_ops + invert_ops
|
|
191
|
+
|
|
192
|
+
# If nothing works, return `NotImplemented`.
|
|
193
|
+
return NotImplemented
|
|
238
194
|
|
|
239
|
-
def on(self, *qubits:
|
|
195
|
+
def on(self, *qubits: cirq.Qid) -> cop.ControlledOperation:
|
|
240
196
|
if len(qubits) == 0:
|
|
241
197
|
raise ValueError(f"Applied a gate to an empty set of qubits. Gate: {self!r}")
|
|
242
198
|
self.validate_args(qubits)
|
|
@@ -249,7 +205,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
249
205
|
def _value_equality_values_(self):
|
|
250
206
|
return (self.sub_gate, self.num_controls(), self.control_values, self.control_qid_shape)
|
|
251
207
|
|
|
252
|
-
def _apply_unitary_(self, args:
|
|
208
|
+
def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray:
|
|
253
209
|
qubits = line_qubit.LineQid.for_gate(self)
|
|
254
210
|
op = self.sub_gate.on(*qubits[self.num_controls() :])
|
|
255
211
|
c_op = cop.ControlledOperation(qubits[: self.num_controls()], op, self.control_values)
|
|
@@ -258,7 +214,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
258
214
|
def _has_unitary_(self) -> bool:
|
|
259
215
|
return protocols.has_unitary(self.sub_gate)
|
|
260
216
|
|
|
261
|
-
def _unitary_(self) ->
|
|
217
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
262
218
|
qubits = line_qubit.LineQid.for_gate(self)
|
|
263
219
|
op = self.sub_gate.on(*qubits[self.num_controls() :])
|
|
264
220
|
c_op = cop.ControlledOperation(qubits[: self.num_controls()], op, self.control_values)
|
|
@@ -268,13 +224,13 @@ class ControlledGate(raw_types.Gate):
|
|
|
268
224
|
def _has_mixture_(self) -> bool:
|
|
269
225
|
return protocols.has_mixture(self.sub_gate)
|
|
270
226
|
|
|
271
|
-
def _mixture_(self) ->
|
|
227
|
+
def _mixture_(self) -> Sequence[tuple[float, np.ndarray]] | NotImplementedType:
|
|
272
228
|
qubits = line_qubit.LineQid.for_gate(self)
|
|
273
229
|
op = self.sub_gate.on(*qubits[self.num_controls() :])
|
|
274
230
|
c_op = cop.ControlledOperation(qubits[: self.num_controls()], op, self.control_values)
|
|
275
231
|
return protocols.mixture(c_op, default=NotImplemented)
|
|
276
232
|
|
|
277
|
-
def __pow__(self, exponent: Any) ->
|
|
233
|
+
def __pow__(self, exponent: Any) -> ControlledGate:
|
|
278
234
|
new_sub_gate = protocols.pow(self.sub_gate, exponent, NotImplemented)
|
|
279
235
|
if new_sub_gate is NotImplemented:
|
|
280
236
|
return NotImplemented
|
|
@@ -291,9 +247,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
291
247
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
292
248
|
return protocols.parameter_names(self.sub_gate)
|
|
293
249
|
|
|
294
|
-
def _resolve_parameters_(
|
|
295
|
-
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
296
|
-
) -> 'ControlledGate':
|
|
250
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> ControlledGate:
|
|
297
251
|
new_sub_gate = protocols.resolve_parameters(self.sub_gate, resolver, recursive)
|
|
298
252
|
return ControlledGate(
|
|
299
253
|
new_sub_gate,
|
|
@@ -302,7 +256,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
302
256
|
control_qid_shape=self.control_qid_shape,
|
|
303
257
|
)
|
|
304
258
|
|
|
305
|
-
def _trace_distance_bound_(self) ->
|
|
259
|
+
def _trace_distance_bound_(self) -> float | None:
|
|
306
260
|
if self._is_parameterized_():
|
|
307
261
|
return None
|
|
308
262
|
u = protocols.unitary(self.sub_gate, default=None)
|
|
@@ -311,9 +265,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
311
265
|
angle_list = np.append(np.angle(np.linalg.eigvals(u)), 0)
|
|
312
266
|
return protocols.trace_distance_from_angle_list(angle_list)
|
|
313
267
|
|
|
314
|
-
def _circuit_diagram_info_(
|
|
315
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
316
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
268
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
317
269
|
sub_args = protocols.CircuitDiagramInfoArgs(
|
|
318
270
|
known_qubit_count=(
|
|
319
271
|
args.known_qubit_count - self.num_controls()
|
|
@@ -355,7 +307,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
355
307
|
f'control_qid_shape={self.control_qid_shape!r})'
|
|
356
308
|
)
|
|
357
309
|
|
|
358
|
-
def _json_dict_(self) ->
|
|
310
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
359
311
|
return {
|
|
360
312
|
'control_values': self.control_values,
|
|
361
313
|
'control_qid_shape': self.control_qid_shape,
|
|
@@ -363,7 +315,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
363
315
|
}
|
|
364
316
|
|
|
365
317
|
|
|
366
|
-
def _validate_sub_object(sub_object:
|
|
318
|
+
def _validate_sub_object(sub_object: cirq.Gate | cirq.Operation):
|
|
367
319
|
if protocols.is_measurement(sub_object):
|
|
368
320
|
raise ValueError(f'Cannot control measurement {sub_object}')
|
|
369
321
|
if not protocols.has_mixture(sub_object) and not protocols.is_parameterized(sub_object):
|