cirq-core 1.4.0.dev20240529225110__py3-none-any.whl → 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/__init__.py +587 -569
- cirq/_compat.py +9 -0
- cirq/_compat_test.py +11 -9
- cirq/_import.py +7 -8
- cirq/_version.py +31 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/__init__.py +15 -9
- cirq/circuits/_block_diagram_drawer.py +1 -2
- cirq/circuits/_block_diagram_drawer_test.py +3 -3
- cirq/circuits/_box_drawing_character_data.py +0 -1
- cirq/circuits/_box_drawing_character_data_test.py +2 -2
- cirq/circuits/_bucket_priority_queue.py +0 -1
- cirq/circuits/_bucket_priority_queue_test.py +1 -1
- cirq/circuits/circuit.py +336 -234
- cirq/circuits/circuit_operation.py +102 -52
- cirq/circuits/circuit_operation_test.py +85 -4
- cirq/circuits/circuit_test.py +101 -32
- cirq/circuits/frozen_circuit.py +36 -32
- cirq/circuits/insert_strategy.py +10 -0
- cirq/circuits/insert_strategy_test.py +20 -0
- cirq/circuits/moment.py +79 -80
- cirq/circuits/moment_test.py +105 -2
- cirq/circuits/optimization_pass.py +15 -15
- cirq/circuits/optimization_pass_test.py +8 -9
- cirq/circuits/qasm_output.py +64 -33
- cirq/circuits/qasm_output_test.py +63 -2
- cirq/circuits/text_diagram_drawer.py +26 -56
- cirq/circuits/text_diagram_drawer_test.py +5 -4
- cirq/contrib/__init__.py +2 -2
- cirq/contrib/acquaintance/__init__.py +44 -29
- cirq/contrib/acquaintance/bipartite.py +8 -7
- cirq/contrib/acquaintance/bipartite_test.py +11 -1
- cirq/contrib/acquaintance/devices.py +5 -4
- cirq/contrib/acquaintance/devices_test.py +5 -1
- cirq/contrib/acquaintance/executor.py +18 -21
- cirq/contrib/acquaintance/executor_test.py +3 -2
- cirq/contrib/acquaintance/gates.py +36 -27
- cirq/contrib/acquaintance/gates_test.py +1 -1
- cirq/contrib/acquaintance/inspection_utils.py +10 -9
- cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
- cirq/contrib/acquaintance/mutation_utils.py +10 -10
- cirq/contrib/acquaintance/optimizers.py +7 -6
- cirq/contrib/acquaintance/optimizers_test.py +1 -1
- cirq/contrib/acquaintance/permutation.py +22 -21
- cirq/contrib/acquaintance/permutation_test.py +1 -1
- cirq/contrib/acquaintance/shift.py +8 -6
- cirq/contrib/acquaintance/shift_swap_network.py +6 -4
- cirq/contrib/acquaintance/strategies/__init__.py +9 -3
- cirq/contrib/acquaintance/strategies/complete.py +4 -3
- cirq/contrib/acquaintance/strategies/cubic.py +5 -3
- cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
- cirq/contrib/acquaintance/topological_sort.py +4 -2
- cirq/contrib/bayesian_network/__init__.py +3 -1
- cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
- cirq/contrib/circuitdag/__init__.py +1 -1
- cirq/contrib/circuitdag/circuit_dag.py +24 -24
- cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
- cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
- cirq/contrib/graph_device/__init__.py +8 -8
- cirq/contrib/graph_device/graph_device.py +8 -8
- cirq/contrib/graph_device/graph_device_test.py +0 -1
- cirq/contrib/graph_device/hypergraph_test.py +1 -0
- cirq/contrib/json.py +1 -2
- cirq/contrib/json_test.py +2 -2
- cirq/contrib/noise_models/__init__.py +5 -6
- cirq/contrib/noise_models/noise_models.py +8 -6
- cirq/contrib/paulistring/__init__.py +22 -10
- cirq/contrib/paulistring/clifford_optimize.py +1 -1
- cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
- cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
- cirq/contrib/paulistring/optimize.py +2 -2
- cirq/contrib/paulistring/optimize_test.py +0 -1
- cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
- cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
- cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
- cirq/contrib/paulistring/recombine.py +2 -2
- cirq/contrib/paulistring/recombine_test.py +2 -2
- cirq/contrib/paulistring/separate.py +3 -4
- cirq/contrib/qasm_import/__init__.py +2 -2
- cirq/contrib/qasm_import/_lexer.py +21 -26
- cirq/contrib/qasm_import/_lexer_test.py +90 -6
- cirq/contrib/qasm_import/_parser.py +238 -47
- cirq/contrib/qasm_import/_parser_test.py +514 -59
- cirq/contrib/qasm_import/qasm_test.py +1 -1
- cirq/contrib/qcircuit/__init__.py +6 -4
- cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
- cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
- cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
- cirq/contrib/qcircuit/qcircuit_test.py +1 -1
- cirq/contrib/quantum_volume/__init__.py +7 -7
- cirq/contrib/quantum_volume/quantum_volume.py +6 -11
- cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
- cirq/contrib/quimb/__init__.py +16 -13
- cirq/contrib/quimb/density_matrix.py +1 -1
- cirq/contrib/quimb/mps_simulator.py +27 -28
- cirq/contrib/quimb/mps_simulator_test.py +5 -0
- cirq/contrib/quimb/state_vector.py +3 -10
- cirq/contrib/quirk/__init__.py +1 -1
- cirq/contrib/quirk/export_to_quirk.py +3 -3
- cirq/contrib/routing/__init__.py +12 -9
- cirq/contrib/routing/device.py +1 -1
- cirq/contrib/routing/device_test.py +1 -2
- cirq/contrib/routing/greedy.py +7 -5
- cirq/contrib/routing/greedy_test.py +5 -3
- cirq/contrib/routing/initialization.py +3 -1
- cirq/contrib/routing/initialization_test.py +1 -1
- cirq/contrib/routing/swap_network.py +6 -6
- cirq/contrib/routing/utils.py +6 -4
- cirq/contrib/routing/utils_test.py +1 -2
- cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
- cirq/contrib/svg/__init__.py +1 -1
- cirq/contrib/svg/svg.py +12 -10
- cirq/contrib/svg/svg_test.py +3 -2
- cirq/devices/__init__.py +34 -25
- cirq/devices/device.py +16 -12
- cirq/devices/device_test.py +1 -0
- cirq/devices/grid_device_metadata.py +16 -12
- cirq/devices/grid_device_metadata_test.py +2 -1
- cirq/devices/grid_qubit.py +31 -26
- cirq/devices/grid_qubit_test.py +30 -1
- cirq/devices/insertion_noise_model.py +6 -6
- cirq/devices/insertion_noise_model_test.py +1 -1
- cirq/devices/line_qubit.py +28 -20
- cirq/devices/line_qubit_test.py +26 -0
- cirq/devices/named_topologies.py +12 -10
- cirq/devices/named_topologies_test.py +5 -4
- cirq/devices/noise_model.py +29 -33
- cirq/devices/noise_properties.py +2 -2
- cirq/devices/noise_properties_test.py +2 -2
- cirq/devices/noise_utils.py +3 -3
- cirq/devices/superconducting_qubits_noise_properties.py +2 -2
- cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
- cirq/devices/thermal_noise_model.py +2 -1
- cirq/devices/unconstrained_device.py +1 -1
- cirq/devices/unconstrained_device_test.py +6 -0
- cirq/experiments/__init__.py +51 -34
- cirq/experiments/qubit_characterizations.py +17 -15
- cirq/experiments/qubit_characterizations_test.py +4 -6
- cirq/experiments/random_quantum_circuit_generation.py +10 -9
- cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
- cirq/experiments/readout_confusion_matrix.py +73 -8
- cirq/experiments/readout_confusion_matrix_test.py +104 -1
- cirq/experiments/single_qubit_readout_calibration.py +8 -6
- cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
- cirq/experiments/t1_decay_experiment.py +4 -5
- cirq/experiments/t1_decay_experiment_test.py +1 -2
- cirq/experiments/t2_decay_experiment.py +0 -1
- cirq/experiments/t2_decay_experiment_test.py +1 -2
- cirq/experiments/two_qubit_xeb.py +157 -33
- cirq/experiments/two_qubit_xeb_test.py +38 -22
- cirq/experiments/xeb_fitting.py +99 -19
- cirq/experiments/xeb_fitting_test.py +64 -25
- cirq/experiments/xeb_sampling.py +14 -18
- cirq/experiments/xeb_simulation.py +4 -3
- cirq/experiments/xeb_simulation_test.py +20 -14
- cirq/experiments/z_phase_calibration.py +368 -0
- cirq/experiments/z_phase_calibration_test.py +241 -0
- cirq/interop/__init__.py +4 -1
- cirq/interop/quirk/__init__.py +7 -4
- cirq/interop/quirk/cells/__init__.py +17 -6
- cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
- cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
- cirq/interop/quirk/cells/cell.py +6 -6
- cirq/interop/quirk/cells/composite_cell.py +5 -5
- cirq/interop/quirk/cells/composite_cell_test.py +1 -1
- cirq/interop/quirk/cells/control_cells.py +1 -1
- cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
- cirq/interop/quirk/cells/ignored_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells_test.py +1 -1
- cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
- cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
- cirq/interop/quirk/cells/measurement_cells.py +1 -1
- cirq/interop/quirk/cells/parse.py +8 -7
- cirq/interop/quirk/cells/parse_test.py +2 -2
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
- cirq/interop/quirk/cells/swap_cell_test.py +1 -1
- cirq/interop/quirk/cells/unsupported_cells.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +7 -7
- cirq/interop/quirk/url_to_circuit_test.py +1 -1
- cirq/ion/__init__.py +4 -2
- cirq/json_resolver_cache.py +15 -7
- cirq/linalg/__init__.py +62 -51
- cirq/linalg/combinators.py +4 -4
- cirq/linalg/combinators_test.py +4 -1
- cirq/linalg/decompositions.py +15 -40
- cirq/linalg/decompositions_test.py +16 -22
- cirq/linalg/diagonalize.py +1 -1
- cirq/linalg/diagonalize_test.py +1 -1
- cirq/linalg/operator_spaces.py +20 -4
- cirq/linalg/operator_spaces_test.py +15 -2
- cirq/linalg/predicates.py +3 -3
- cirq/linalg/predicates_test.py +1 -0
- cirq/linalg/tolerance.py +2 -2
- cirq/linalg/transformations.py +30 -12
- cirq/linalg/transformations_test.py +13 -0
- cirq/neutral_atoms/__init__.py +2 -2
- cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
- cirq/ops/__init__.py +172 -132
- cirq/ops/arithmetic_operation.py +2 -2
- cirq/ops/arithmetic_operation_test.py +2 -2
- cirq/ops/boolean_hamiltonian.py +3 -2
- cirq/ops/classically_controlled_operation.py +39 -12
- cirq/ops/classically_controlled_operation_test.py +147 -1
- cirq/ops/clifford_gate.py +38 -36
- cirq/ops/clifford_gate_test.py +75 -1
- cirq/ops/common_channels.py +16 -45
- cirq/ops/common_channels_test.py +10 -0
- cirq/ops/common_gate_families.py +1 -1
- cirq/ops/common_gate_families_test.py +1 -0
- cirq/ops/common_gates.py +48 -49
- cirq/ops/common_gates_test.py +18 -2
- cirq/ops/control_values.py +3 -3
- cirq/ops/control_values_test.py +2 -1
- cirq/ops/controlled_gate.py +36 -23
- cirq/ops/controlled_gate_test.py +70 -3
- cirq/ops/controlled_operation.py +6 -5
- cirq/ops/controlled_operation_test.py +7 -3
- cirq/ops/dense_pauli_string.py +11 -11
- cirq/ops/diagonal_gate.py +2 -2
- cirq/ops/diagonal_gate_test.py +1 -0
- cirq/ops/eigen_gate.py +16 -36
- cirq/ops/eigen_gate_test.py +60 -10
- cirq/ops/fourier_transform.py +1 -3
- cirq/ops/fourier_transform_test.py +2 -1
- cirq/ops/fsim_gate.py +42 -3
- cirq/ops/fsim_gate_test.py +21 -0
- cirq/ops/gate_operation.py +8 -8
- cirq/ops/gate_operation_test.py +4 -2
- cirq/ops/gateset_test.py +11 -2
- cirq/ops/global_phase_op.py +8 -7
- cirq/ops/global_phase_op_test.py +1 -1
- cirq/ops/greedy_qubit_manager_test.py +5 -0
- cirq/ops/identity.py +14 -4
- cirq/ops/identity_test.py +24 -0
- cirq/ops/kraus_channel.py +1 -0
- cirq/ops/kraus_channel_test.py +3 -1
- cirq/ops/linear_combinations.py +27 -21
- cirq/ops/linear_combinations_test.py +23 -4
- cirq/ops/matrix_gates.py +24 -8
- cirq/ops/measure_util.py +2 -2
- cirq/ops/measurement_gate.py +7 -4
- cirq/ops/measurement_gate_test.py +2 -1
- cirq/ops/mixed_unitary_channel.py +1 -0
- cirq/ops/mixed_unitary_channel_test.py +3 -1
- cirq/ops/named_qubit.py +8 -1
- cirq/ops/op_tree.py +3 -30
- cirq/ops/op_tree_test.py +4 -0
- cirq/ops/parallel_gate.py +2 -3
- cirq/ops/parallel_gate_test.py +2 -1
- cirq/ops/parity_gates.py +7 -8
- cirq/ops/parity_gates_test.py +1 -0
- cirq/ops/pauli_gates.py +5 -11
- cirq/ops/pauli_gates_test.py +1 -0
- cirq/ops/pauli_interaction_gate.py +11 -5
- cirq/ops/pauli_interaction_gate_test.py +2 -3
- cirq/ops/pauli_measurement_gate.py +6 -5
- cirq/ops/pauli_measurement_gate_test.py +1 -0
- cirq/ops/pauli_string.py +115 -130
- cirq/ops/pauli_string_phasor.py +21 -20
- cirq/ops/pauli_string_phasor_test.py +13 -3
- cirq/ops/pauli_string_raw_types.py +1 -0
- cirq/ops/pauli_string_test.py +192 -55
- cirq/ops/pauli_sum_exponential.py +3 -4
- cirq/ops/pauli_sum_exponential_test.py +0 -1
- cirq/ops/permutation_gate.py +2 -2
- cirq/ops/permutation_gate_test.py +1 -1
- cirq/ops/phased_iswap_gate.py +6 -7
- cirq/ops/phased_iswap_gate_test.py +21 -5
- cirq/ops/phased_x_gate.py +11 -25
- cirq/ops/phased_x_gate_test.py +19 -3
- cirq/ops/phased_x_z_gate.py +12 -11
- cirq/ops/projector.py +4 -5
- cirq/ops/qubit_manager.py +2 -1
- cirq/ops/qubit_manager_test.py +2 -1
- cirq/ops/qubit_order.py +1 -1
- cirq/ops/random_gate_channel.py +1 -1
- cirq/ops/random_gate_channel_test.py +0 -6
- cirq/ops/raw_types.py +146 -50
- cirq/ops/raw_types_test.py +37 -3
- cirq/ops/state_preparation_channel.py +2 -2
- cirq/ops/state_preparation_channel_test.py +2 -1
- cirq/ops/swap_gates.py +9 -4
- cirq/ops/three_qubit_gates.py +8 -8
- cirq/ops/three_qubit_gates_test.py +1 -0
- cirq/ops/two_qubit_diagonal_gate.py +4 -3
- cirq/ops/uniform_superposition_gate.py +4 -4
- cirq/ops/uniform_superposition_gate_test.py +1 -0
- cirq/ops/wait_gate.py +6 -8
- cirq/protocols/__init__.py +135 -83
- cirq/protocols/act_on_protocol.py +1 -1
- cirq/protocols/act_on_protocol_test.py +1 -1
- cirq/protocols/apply_channel_protocol.py +3 -3
- cirq/protocols/apply_mixture_protocol.py +15 -9
- cirq/protocols/apply_mixture_protocol_test.py +11 -0
- cirq/protocols/apply_unitary_protocol.py +2 -2
- cirq/protocols/apply_unitary_protocol_test.py +2 -1
- cirq/protocols/approximate_equality_protocol.py +7 -8
- cirq/protocols/approximate_equality_protocol_test.py +3 -1
- cirq/protocols/circuit_diagram_info_protocol.py +8 -6
- cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
- cirq/protocols/commutes_protocol.py +6 -6
- cirq/protocols/control_key_protocol.py +1 -1
- cirq/protocols/decompose_protocol.py +4 -5
- cirq/protocols/decompose_protocol_test.py +2 -1
- cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
- cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
- cirq/protocols/has_unitary_protocol.py +1 -1
- cirq/protocols/has_unitary_protocol_test.py +8 -7
- cirq/protocols/hash_from_pickle_test.py +120 -0
- cirq/protocols/inverse_protocol.py +1 -1
- cirq/protocols/json_serialization.py +14 -1
- cirq/protocols/json_serialization_test.py +28 -7
- cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
- cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
- cirq/protocols/json_test_data/Concat.json +19 -0
- cirq/protocols/json_test_data/Concat.repr +1 -0
- cirq/protocols/json_test_data/README.md +4 -2
- cirq/protocols/json_test_data/SympyCondition.json +60 -15
- cirq/protocols/json_test_data/SympyCondition.repr +4 -1
- cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
- cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
- cirq/protocols/json_test_data/__init__.py +1 -1
- cirq/protocols/json_test_data/sympy.And.json +13 -0
- cirq/protocols/json_test_data/sympy.And.repr +1 -0
- cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
- cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
- cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
- cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
- cirq/protocols/json_test_data/sympy.Not.json +9 -0
- cirq/protocols/json_test_data/sympy.Not.repr +1 -0
- cirq/protocols/json_test_data/sympy.Or.json +13 -0
- cirq/protocols/json_test_data/sympy.Or.repr +1 -0
- cirq/protocols/json_test_data/sympy.Xor.json +13 -0
- cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
- cirq/protocols/kraus_protocol.py +8 -8
- cirq/protocols/kraus_protocol_test.py +0 -1
- cirq/protocols/measurement_key_protocol.py +1 -1
- cirq/protocols/measurement_key_protocol_test.py +7 -7
- cirq/protocols/mixture_protocol.py +6 -4
- cirq/protocols/mixture_protocol_test.py +21 -13
- cirq/protocols/pauli_expansion_protocol.py +1 -0
- cirq/protocols/pow_protocol.py +1 -1
- cirq/protocols/qasm.py +25 -6
- cirq/protocols/qasm_test.py +17 -0
- cirq/protocols/qid_shape_protocol.py +2 -2
- cirq/protocols/resolve_parameters.py +2 -3
- cirq/protocols/resolve_parameters_test.py +2 -1
- cirq/protocols/trace_distance_bound.py +1 -1
- cirq/protocols/trace_distance_bound_test.py +1 -0
- cirq/protocols/unitary_protocol.py +3 -3
- cirq/protocols/unitary_protocol_test.py +1 -1
- cirq/qis/__init__.py +48 -35
- cirq/qis/channels_test.py +0 -9
- cirq/qis/clifford_tableau.py +46 -26
- cirq/qis/clifford_tableau_test.py +2 -1
- cirq/qis/entropy.py +115 -0
- cirq/qis/entropy_test.py +43 -0
- cirq/qis/measures.py +5 -4
- cirq/qis/measures_test.py +7 -0
- cirq/qis/noise_utils_test.py +4 -4
- cirq/qis/quantum_state_representation.py +1 -1
- cirq/qis/states.py +7 -7
- cirq/sim/__init__.py +55 -37
- cirq/sim/classical_simulator.py +7 -6
- cirq/sim/classical_simulator_test.py +3 -1
- cirq/sim/clifford/__init__.py +17 -9
- cirq/sim/clifford/clifford_simulator.py +5 -4
- cirq/sim/clifford/clifford_simulator_test.py +32 -9
- cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
- cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
- cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
- cirq/sim/density_matrix_simulator.py +3 -2
- cirq/sim/density_matrix_simulator_test.py +12 -4
- cirq/sim/density_matrix_utils.py +1 -1
- cirq/sim/mux.py +2 -2
- cirq/sim/simulation_state.py +4 -5
- cirq/sim/simulation_state_base.py +2 -2
- cirq/sim/simulation_state_test.py +1 -1
- cirq/sim/simulation_utils.py +3 -1
- cirq/sim/simulation_utils_test.py +2 -3
- cirq/sim/simulator.py +7 -6
- cirq/sim/simulator_base.py +5 -5
- cirq/sim/simulator_test.py +14 -3
- cirq/sim/sparse_simulator.py +4 -3
- cirq/sim/sparse_simulator_test.py +17 -9
- cirq/sim/state_vector.py +2 -2
- cirq/sim/state_vector_simulation_state_test.py +1 -1
- cirq/sim/state_vector_simulator.py +4 -4
- cirq/sim/state_vector_test.py +27 -32
- cirq/study/__init__.py +27 -21
- cirq/study/flatten_expressions.py +5 -6
- cirq/study/flatten_expressions_test.py +1 -1
- cirq/study/resolver.py +14 -11
- cirq/study/resolver_test.py +10 -1
- cirq/study/result.py +3 -3
- cirq/study/sweepable.py +15 -9
- cirq/study/sweepable_test.py +27 -0
- cirq/study/sweeps.py +65 -10
- cirq/study/sweeps_test.py +123 -0
- cirq/testing/__init__.py +86 -57
- cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
- cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
- cirq/testing/circuit_compare.py +3 -4
- cirq/testing/circuit_compare_test.py +7 -8
- cirq/testing/consistent_act_on.py +3 -3
- cirq/testing/consistent_channels_test.py +2 -1
- cirq/testing/consistent_controlled_gate_op.py +3 -2
- cirq/testing/consistent_controlled_gate_op_test.py +2 -3
- cirq/testing/consistent_decomposition.py +1 -1
- cirq/testing/consistent_decomposition_test.py +1 -2
- cirq/testing/consistent_pauli_expansion_test.py +1 -1
- cirq/testing/consistent_phase_by.py +1 -1
- cirq/testing/consistent_phase_by_test.py +1 -2
- cirq/testing/consistent_protocols.py +11 -11
- cirq/testing/consistent_protocols_test.py +4 -5
- cirq/testing/consistent_qasm.py +8 -12
- cirq/testing/consistent_qasm_test.py +1 -1
- cirq/testing/consistent_resolve_parameters.py +2 -1
- cirq/testing/consistent_specified_has_unitary_test.py +1 -1
- cirq/testing/consistent_unitary.py +3 -1
- cirq/testing/consistent_unitary_test.py +3 -3
- cirq/testing/devices.py +1 -1
- cirq/testing/devices_test.py +1 -0
- cirq/testing/equals_tester.py +2 -4
- cirq/testing/equals_tester_test.py +6 -5
- cirq/testing/equivalent_basis_map.py +1 -0
- cirq/testing/equivalent_basis_map_test.py +0 -1
- cirq/testing/gate_features_test.py +5 -0
- cirq/testing/json.py +4 -4
- cirq/testing/lin_alg_utils_test.py +1 -1
- cirq/testing/order_tester.py +1 -1
- cirq/testing/order_tester_test.py +1 -1
- cirq/testing/pytest_utils.py +57 -0
- cirq/testing/pytest_utils_test.py +35 -0
- cirq/testing/random_circuit.py +2 -2
- cirq/testing/random_circuit_test.py +2 -2
- cirq/testing/routing_devices_test.py +2 -1
- cirq/testing/sample_circuits.py +1 -1
- cirq/testing/sample_gates.py +5 -4
- cirq/testing/sample_gates_test.py +2 -2
- cirq/transformers/__init__.py +101 -82
- cirq/transformers/align.py +12 -1
- cirq/transformers/align_test.py +13 -0
- cirq/transformers/analytical_decompositions/__init__.py +27 -24
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
- cirq/transformers/drop_empty_moments.py +1 -0
- cirq/transformers/drop_negligible_operations.py +1 -0
- cirq/transformers/dynamical_decoupling.py +255 -43
- cirq/transformers/dynamical_decoupling_test.py +730 -17
- cirq/transformers/eject_phased_paulis.py +29 -15
- cirq/transformers/eject_phased_paulis_test.py +3 -8
- cirq/transformers/eject_z.py +3 -2
- cirq/transformers/eject_z_test.py +3 -3
- cirq/transformers/gauge_compiling/__init__.py +25 -9
- cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
- cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
- cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
- cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
- cirq/transformers/heuristic_decompositions/__init__.py +3 -3
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
- cirq/transformers/insertion_sort.py +64 -0
- cirq/transformers/insertion_sort_test.py +34 -0
- cirq/transformers/measurement_transformers.py +14 -1
- cirq/transformers/measurement_transformers_test.py +35 -0
- cirq/transformers/merge_k_qubit_gates.py +2 -2
- cirq/transformers/merge_single_qubit_gates.py +1 -1
- cirq/transformers/merge_single_qubit_gates_test.py +1 -1
- cirq/transformers/noise_adding.py +115 -0
- cirq/transformers/noise_adding_test.py +54 -0
- cirq/transformers/optimize_for_target_gateset.py +1 -1
- cirq/transformers/optimize_for_target_gateset_test.py +3 -2
- cirq/transformers/qubit_management_transformers.py +1 -1
- cirq/transformers/randomized_measurements.py +171 -0
- cirq/transformers/randomized_measurements_test.py +68 -0
- cirq/transformers/routing/__init__.py +14 -5
- cirq/transformers/routing/initial_mapper.py +1 -1
- cirq/transformers/routing/initial_mapper_test.py +1 -0
- cirq/transformers/routing/line_initial_mapper.py +3 -2
- cirq/transformers/routing/mapping_manager.py +2 -2
- cirq/transformers/routing/mapping_manager_test.py +2 -2
- cirq/transformers/routing/route_circuit_cqc.py +3 -2
- cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
- cirq/transformers/routing/visualize_routed_circuit.py +1 -0
- cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
- cirq/transformers/stratify.py +2 -2
- cirq/transformers/synchronize_terminal_measurements.py +2 -1
- cirq/transformers/target_gatesets/__init__.py +7 -5
- cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
- cirq/transformers/target_gatesets/cz_gateset.py +5 -1
- cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
- cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
- cirq/transformers/transformer_api.py +5 -4
- cirq/transformers/transformer_api_test.py +11 -3
- cirq/transformers/transformer_primitives.py +9 -31
- cirq/transformers/transformer_primitives_test.py +6 -5
- cirq/value/__init__.py +51 -30
- cirq/value/abc_alt.py +1 -2
- cirq/value/angle.py +2 -0
- cirq/value/classical_data.py +1 -0
- cirq/value/condition.py +149 -3
- cirq/value/condition_test.py +254 -0
- cirq/value/digits.py +1 -1
- cirq/value/duration.py +4 -4
- cirq/value/duration_test.py +2 -1
- cirq/value/linear_dict.py +85 -24
- cirq/value/linear_dict_test.py +94 -3
- cirq/value/measurement_key.py +9 -2
- cirq/value/periodic_value.py +2 -3
- cirq/value/periodic_value_test.py +5 -0
- cirq/value/probability.py +1 -0
- cirq/value/random_state.py +1 -1
- cirq/value/timestamp.py +2 -4
- cirq/value/timestamp_test.py +2 -1
- cirq/value/type_alias.py +2 -2
- cirq/value/value_equality_attr.py +14 -2
- cirq/value/value_equality_attr_test.py +1 -1
- cirq/vis/__init__.py +9 -6
- cirq/vis/density_matrix.py +1 -1
- cirq/vis/density_matrix_test.py +2 -5
- cirq/vis/heatmap.py +49 -12
- cirq/vis/heatmap_test.py +168 -4
- cirq/vis/histogram.py +1 -1
- cirq/vis/histogram_test.py +1 -2
- cirq/vis/state_histogram.py +7 -5
- cirq/vis/state_histogram_test.py +2 -2
- cirq/work/__init__.py +19 -13
- cirq/work/collector.py +2 -2
- cirq/work/observable_grouping.py +2 -2
- cirq/work/observable_measurement.py +3 -3
- cirq/work/observable_measurement_data.py +5 -2
- cirq/work/observable_measurement_test.py +8 -8
- cirq/work/observable_readout_calibration.py +2 -2
- cirq/work/observable_readout_calibration_test.py +2 -1
- cirq/work/observable_settings.py +8 -7
- cirq/work/observable_settings_test.py +3 -2
- cirq/work/pauli_sum_collector.py +1 -1
- cirq/work/sampler.py +8 -20
- cirq/work/sampler_test.py +4 -3
- cirq/work/zeros_sampler.py +1 -1
- cirq_core-1.5.0.dist-info/METADATA +125 -0
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
- cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
- cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
- cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
- cirq_core-1.4.0.dev20240529225110.dist-info/METADATA +0 -50
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.4.0.dev20240529225110.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
cirq/ops/common_gates.py
CHANGED
|
@@ -25,12 +25,13 @@ Each of these are implemented as EigenGates, which means that they can be
|
|
|
25
25
|
raised to a power (i.e. cirq.H**0.5). See the definition in EigenGate.
|
|
26
26
|
"""
|
|
27
27
|
|
|
28
|
+
from types import NotImplementedType
|
|
28
29
|
from typing import (
|
|
29
30
|
Any,
|
|
30
31
|
cast,
|
|
31
32
|
Collection,
|
|
32
|
-
List,
|
|
33
33
|
Dict,
|
|
34
|
+
List,
|
|
34
35
|
Optional,
|
|
35
36
|
Sequence,
|
|
36
37
|
Tuple,
|
|
@@ -45,12 +46,9 @@ import cirq
|
|
|
45
46
|
from cirq import protocols, value
|
|
46
47
|
from cirq._compat import proper_repr
|
|
47
48
|
from cirq._doc import document
|
|
48
|
-
from cirq.ops import controlled_gate, eigen_gate, gate_features, raw_types
|
|
49
|
-
|
|
50
|
-
from cirq.type_workarounds import NotImplementedType
|
|
51
|
-
|
|
52
|
-
from cirq.ops.swap_gates import ISWAP, SWAP, ISwapPowGate, SwapPowGate
|
|
49
|
+
from cirq.ops import control_values as cv, controlled_gate, eigen_gate, gate_features, raw_types
|
|
53
50
|
from cirq.ops.measurement_gate import MeasurementGate
|
|
51
|
+
from cirq.ops.swap_gates import ISWAP, ISwapPowGate, SWAP, SwapPowGate
|
|
54
52
|
|
|
55
53
|
if TYPE_CHECKING:
|
|
56
54
|
import cirq
|
|
@@ -179,7 +177,7 @@ class XPowGate(eigen_gate.EigenGate):
|
|
|
179
177
|
return SingleQubitCliffordGate.X.on(*qubits)
|
|
180
178
|
if self.exponent % 2 == 1.5:
|
|
181
179
|
return SingleQubitCliffordGate.X_nsqrt.on(*qubits)
|
|
182
|
-
return NotImplemented
|
|
180
|
+
return NotImplemented # pragma: no cover
|
|
183
181
|
|
|
184
182
|
def _trace_distance_bound_(self) -> Optional[float]:
|
|
185
183
|
if self._is_parameterized_() or self._dimension != 2:
|
|
@@ -260,11 +258,12 @@ class XPowGate(eigen_gate.EigenGate):
|
|
|
260
258
|
return result
|
|
261
259
|
|
|
262
260
|
def _pauli_expansion_(self) -> value.LinearDict[str]:
|
|
263
|
-
if
|
|
264
|
-
return NotImplemented
|
|
261
|
+
if self._dimension != 2:
|
|
262
|
+
return NotImplemented # pragma: no cover
|
|
265
263
|
phase = 1j ** (2 * self._exponent * (self._global_shift + 0.5))
|
|
266
|
-
|
|
267
|
-
|
|
264
|
+
lib = sympy if protocols.is_parameterized(self) else np
|
|
265
|
+
angle = lib.pi * self._exponent / 2
|
|
266
|
+
return value.LinearDict({'I': phase * lib.cos(angle), 'X': -1j * phase * lib.sin(angle)})
|
|
268
267
|
|
|
269
268
|
def _circuit_diagram_info_(
|
|
270
269
|
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
@@ -274,7 +273,7 @@ class XPowGate(eigen_gate.EigenGate):
|
|
|
274
273
|
)
|
|
275
274
|
|
|
276
275
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
277
|
-
args.validate_version('2.0')
|
|
276
|
+
args.validate_version('2.0', '3.0')
|
|
278
277
|
if self._global_shift == 0:
|
|
279
278
|
if self._exponent == 1:
|
|
280
279
|
return args.format('x {0};\n', qubits[0])
|
|
@@ -290,9 +289,7 @@ class XPowGate(eigen_gate.EigenGate):
|
|
|
290
289
|
|
|
291
290
|
def _phase_by_(self, phase_turns, qubit_index):
|
|
292
291
|
"""See `cirq.SupportsPhase`."""
|
|
293
|
-
return
|
|
294
|
-
exponent=self._exponent, phase_exponent=phase_turns * 2
|
|
295
|
-
)
|
|
292
|
+
return _phased_x_or_pauli_gate(exponent=self._exponent, phase_exponent=phase_turns * 2)
|
|
296
293
|
|
|
297
294
|
def _has_stabilizer_effect_(self) -> Optional[bool]:
|
|
298
295
|
if self._is_parameterized_() or self._dimension != 2:
|
|
@@ -327,12 +324,6 @@ class XPowGate(eigen_gate.EigenGate):
|
|
|
327
324
|
d['dimension'] = self.dimension
|
|
328
325
|
return d
|
|
329
326
|
|
|
330
|
-
def _value_equality_values_(self):
|
|
331
|
-
return (*super()._value_equality_values_(), self._dimension)
|
|
332
|
-
|
|
333
|
-
def _value_equality_approximate_values_(self):
|
|
334
|
-
return (*super()._value_equality_approximate_values_(), self._dimension)
|
|
335
|
-
|
|
336
327
|
|
|
337
328
|
class Rx(XPowGate):
|
|
338
329
|
r"""A gate with matrix $e^{-i X t/2}$ that rotates around the X axis of the Bloch sphere by $t$.
|
|
@@ -376,7 +367,7 @@ class Rx(XPowGate):
|
|
|
376
367
|
return f'cirq.Rx(rads={proper_repr(self._rads)})'
|
|
377
368
|
|
|
378
369
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
379
|
-
args.validate_version('2.0')
|
|
370
|
+
args.validate_version('2.0', '3.0')
|
|
380
371
|
return args.format('rx({0:half_turns}) {1};\n', self._exponent, qubits[0])
|
|
381
372
|
|
|
382
373
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
@@ -452,7 +443,7 @@ class YPowGate(eigen_gate.EigenGate):
|
|
|
452
443
|
return SingleQubitCliffordGate.Y.on(*qubits)
|
|
453
444
|
if self.exponent % 2 == 1.5:
|
|
454
445
|
return SingleQubitCliffordGate.Y_nsqrt.on(*qubits)
|
|
455
|
-
return NotImplemented
|
|
446
|
+
return NotImplemented # pragma: no cover
|
|
456
447
|
|
|
457
448
|
def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
|
|
458
449
|
return [
|
|
@@ -466,11 +457,10 @@ class YPowGate(eigen_gate.EigenGate):
|
|
|
466
457
|
return abs(np.sin(self._exponent * 0.5 * np.pi))
|
|
467
458
|
|
|
468
459
|
def _pauli_expansion_(self) -> value.LinearDict[str]:
|
|
469
|
-
if protocols.is_parameterized(self):
|
|
470
|
-
return NotImplemented
|
|
471
460
|
phase = 1j ** (2 * self._exponent * (self._global_shift + 0.5))
|
|
472
|
-
|
|
473
|
-
|
|
461
|
+
lib = sympy if protocols.is_parameterized(self) else np
|
|
462
|
+
angle = lib.pi * self._exponent / 2
|
|
463
|
+
return value.LinearDict({'I': phase * lib.cos(angle), 'Y': -1j * phase * lib.sin(angle)})
|
|
474
464
|
|
|
475
465
|
def _circuit_diagram_info_(
|
|
476
466
|
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
@@ -480,7 +470,7 @@ class YPowGate(eigen_gate.EigenGate):
|
|
|
480
470
|
)
|
|
481
471
|
|
|
482
472
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
483
|
-
args.validate_version('2.0')
|
|
473
|
+
args.validate_version('2.0', '3.0')
|
|
484
474
|
if self._exponent == 1 and self.global_shift != -0.5:
|
|
485
475
|
return args.format('y {0};\n', qubits[0])
|
|
486
476
|
|
|
@@ -492,7 +482,7 @@ class YPowGate(eigen_gate.EigenGate):
|
|
|
492
482
|
|
|
493
483
|
def _phase_by_(self, phase_turns, qubit_index):
|
|
494
484
|
"""See `cirq.SupportsPhase`."""
|
|
495
|
-
return
|
|
485
|
+
return _phased_x_or_pauli_gate(
|
|
496
486
|
exponent=self._exponent, phase_exponent=0.5 + phase_turns * 2
|
|
497
487
|
)
|
|
498
488
|
|
|
@@ -562,7 +552,7 @@ class Ry(YPowGate):
|
|
|
562
552
|
return f'cirq.Ry(rads={proper_repr(self._rads)})'
|
|
563
553
|
|
|
564
554
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
565
|
-
args.validate_version('2.0')
|
|
555
|
+
args.validate_version('2.0', '3.0')
|
|
566
556
|
return args.format('ry({0:half_turns}) {1};\n', self._exponent, qubits[0])
|
|
567
557
|
|
|
568
558
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
@@ -658,7 +648,7 @@ class ZPowGate(eigen_gate.EigenGate):
|
|
|
658
648
|
return SingleQubitCliffordGate.Z.on(*qubits)
|
|
659
649
|
if self.exponent % 2 == 1.5:
|
|
660
650
|
return SingleQubitCliffordGate.Z_nsqrt.on(*qubits)
|
|
661
|
-
return NotImplemented
|
|
651
|
+
return NotImplemented # pragma: no cover
|
|
662
652
|
|
|
663
653
|
def in_su2(self) -> 'Rz':
|
|
664
654
|
"""Returns an equal-up-global-phase gate from the group SU2."""
|
|
@@ -766,11 +756,12 @@ class ZPowGate(eigen_gate.EigenGate):
|
|
|
766
756
|
return abs(np.sin(self._exponent * 0.5 * np.pi))
|
|
767
757
|
|
|
768
758
|
def _pauli_expansion_(self) -> value.LinearDict[str]:
|
|
769
|
-
if
|
|
770
|
-
return NotImplemented
|
|
759
|
+
if self._dimension != 2:
|
|
760
|
+
return NotImplemented # pragma: no cover
|
|
771
761
|
phase = 1j ** (2 * self._exponent * (self._global_shift + 0.5))
|
|
772
|
-
|
|
773
|
-
|
|
762
|
+
lib = sympy if protocols.is_parameterized(self) else np
|
|
763
|
+
angle = lib.pi * self._exponent / 2
|
|
764
|
+
return value.LinearDict({'I': phase * lib.cos(angle), 'Z': -1j * phase * lib.sin(angle)})
|
|
774
765
|
|
|
775
766
|
def _phase_by_(self, phase_turns: float, qubit_index: int):
|
|
776
767
|
return self
|
|
@@ -793,7 +784,7 @@ class ZPowGate(eigen_gate.EigenGate):
|
|
|
793
784
|
return protocols.CircuitDiagramInfo(wire_symbols=('Z',), exponent=e)
|
|
794
785
|
|
|
795
786
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
796
|
-
args.validate_version('2.0')
|
|
787
|
+
args.validate_version('2.0', '3.0')
|
|
797
788
|
|
|
798
789
|
if self.global_shift == 0:
|
|
799
790
|
if self._exponent == 1:
|
|
@@ -863,12 +854,6 @@ class ZPowGate(eigen_gate.EigenGate):
|
|
|
863
854
|
d['dimension'] = self.dimension
|
|
864
855
|
return d
|
|
865
856
|
|
|
866
|
-
def _value_equality_values_(self):
|
|
867
|
-
return (*super()._value_equality_values_(), self._dimension)
|
|
868
|
-
|
|
869
|
-
def _value_equality_approximate_values_(self):
|
|
870
|
-
return (*super()._value_equality_approximate_values_(), self._dimension)
|
|
871
|
-
|
|
872
857
|
|
|
873
858
|
class Rz(ZPowGate):
|
|
874
859
|
r"""A gate with matrix $e^{-i Z t/2}$ that rotates around the Z axis of the Bloch sphere by $t$.
|
|
@@ -912,7 +897,7 @@ class Rz(ZPowGate):
|
|
|
912
897
|
return f'cirq.Rz(rads={proper_repr(self._rads)})'
|
|
913
898
|
|
|
914
899
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
915
|
-
args.validate_version('2.0')
|
|
900
|
+
args.validate_version('2.0', '3.0')
|
|
916
901
|
return args.format('rz({0:half_turns}) {1};\n', self._exponent, qubits[0])
|
|
917
902
|
|
|
918
903
|
def _json_dict_(self) -> Dict[str, Any]:
|
|
@@ -983,7 +968,7 @@ class HPowGate(eigen_gate.EigenGate):
|
|
|
983
968
|
return SingleQubitCliffordGate.H.on(*qubits)
|
|
984
969
|
if self.exponent % 2 == 0:
|
|
985
970
|
return []
|
|
986
|
-
return NotImplemented
|
|
971
|
+
return NotImplemented # pragma: no cover
|
|
987
972
|
|
|
988
973
|
def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
|
|
989
974
|
if self._exponent != 1:
|
|
@@ -1018,7 +1003,7 @@ class HPowGate(eigen_gate.EigenGate):
|
|
|
1018
1003
|
)
|
|
1019
1004
|
|
|
1020
1005
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
1021
|
-
args.validate_version('2.0')
|
|
1006
|
+
args.validate_version('2.0', '3.0')
|
|
1022
1007
|
if self._exponent == 0:
|
|
1023
1008
|
return args.format('id {0};\n', qubits[0])
|
|
1024
1009
|
elif self._exponent == 1 and self._global_shift == 0:
|
|
@@ -1081,7 +1066,7 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
|
|
|
1081
1066
|
return PauliInteractionGate.CZ.on(*qubits)
|
|
1082
1067
|
if self.exponent % 2 == 0:
|
|
1083
1068
|
return []
|
|
1084
|
-
return NotImplemented
|
|
1069
|
+
return NotImplemented # pragma: no cover
|
|
1085
1070
|
|
|
1086
1071
|
def _eigen_components(self) -> List[Tuple[float, np.ndarray]]:
|
|
1087
1072
|
return [(0, np.diag([1, 1, 1, 0])), (1, np.diag([0, 0, 0, 1]))]
|
|
@@ -1206,7 +1191,7 @@ class CZPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
|
|
|
1206
1191
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
1207
1192
|
if self._exponent != 1:
|
|
1208
1193
|
return None # Don't have an equivalent gate in QASM
|
|
1209
|
-
args.validate_version('2.0')
|
|
1194
|
+
args.validate_version('2.0', '3.0')
|
|
1210
1195
|
return args.format('cz {0},{1};\n', qubits[0], qubits[1])
|
|
1211
1196
|
|
|
1212
1197
|
def _has_stabilizer_effect_(self) -> Optional[bool]:
|
|
@@ -1276,7 +1261,7 @@ class CXPowGate(eigen_gate.EigenGate):
|
|
|
1276
1261
|
return PauliInteractionGate.CNOT.on(*qubits)
|
|
1277
1262
|
if self.exponent % 2 == 0:
|
|
1278
1263
|
return []
|
|
1279
|
-
return NotImplemented
|
|
1264
|
+
return NotImplemented # pragma: no cover
|
|
1280
1265
|
|
|
1281
1266
|
def _decompose_(self, qubits):
|
|
1282
1267
|
c, t = qubits
|
|
@@ -1407,7 +1392,7 @@ class CXPowGate(eigen_gate.EigenGate):
|
|
|
1407
1392
|
def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
|
|
1408
1393
|
if self._exponent != 1:
|
|
1409
1394
|
return None # Don't have an equivalent gate in QASM
|
|
1410
|
-
args.validate_version('2.0')
|
|
1395
|
+
args.validate_version('2.0', '3.0')
|
|
1411
1396
|
return args.format('cx {0},{1};\n', qubits[0], qubits[1])
|
|
1412
1397
|
|
|
1413
1398
|
def _has_stabilizer_effect_(self) -> Optional[bool]:
|
|
@@ -1555,3 +1540,17 @@ document(
|
|
|
1555
1540
|
$$
|
|
1556
1541
|
""",
|
|
1557
1542
|
)
|
|
1543
|
+
|
|
1544
|
+
|
|
1545
|
+
def _phased_x_or_pauli_gate(
|
|
1546
|
+
exponent: Union[float, sympy.Expr], phase_exponent: Union[float, sympy.Expr]
|
|
1547
|
+
) -> Union['cirq.PhasedXPowGate', 'cirq.XPowGate', 'cirq.YPowGate']:
|
|
1548
|
+
"""Return PhasedXPowGate or X or Y gate if equivalent at the given phase_exponent."""
|
|
1549
|
+
if not isinstance(phase_exponent, sympy.Expr) or phase_exponent.is_constant():
|
|
1550
|
+
half_turns = value.canonicalize_half_turns(float(phase_exponent))
|
|
1551
|
+
match half_turns:
|
|
1552
|
+
case 0.0:
|
|
1553
|
+
return XPowGate(exponent=exponent)
|
|
1554
|
+
case 0.5:
|
|
1555
|
+
return YPowGate(exponent=exponent)
|
|
1556
|
+
return cirq.ops.PhasedXPowGate(exponent=exponent, phase_exponent=phase_exponent)
|
cirq/ops/common_gates_test.py
CHANGED
|
@@ -245,11 +245,12 @@ def test_rot_gates_eq():
|
|
|
245
245
|
eq.add_equality_group(cirq.YPowGate(), cirq.YPowGate(exponent=1), cirq.Y)
|
|
246
246
|
eq.add_equality_group(cirq.ZPowGate(), cirq.ZPowGate(exponent=1), cirq.Z)
|
|
247
247
|
eq.add_equality_group(
|
|
248
|
-
cirq.ZPowGate(exponent=1, global_shift=-0.5),
|
|
248
|
+
cirq.ZPowGate(exponent=1, global_shift=-0.5),
|
|
249
|
+
cirq.ZPowGate(exponent=5, global_shift=-0.5),
|
|
250
|
+
cirq.ZPowGate(exponent=5, global_shift=-0.1),
|
|
249
251
|
)
|
|
250
252
|
eq.add_equality_group(cirq.ZPowGate(exponent=3, global_shift=-0.5))
|
|
251
253
|
eq.add_equality_group(cirq.ZPowGate(exponent=1, global_shift=-0.1))
|
|
252
|
-
eq.add_equality_group(cirq.ZPowGate(exponent=5, global_shift=-0.1))
|
|
253
254
|
eq.add_equality_group(
|
|
254
255
|
cirq.CNotPowGate(), cirq.CXPowGate(), cirq.CNotPowGate(exponent=1), cirq.CNOT
|
|
255
256
|
)
|
|
@@ -307,6 +308,11 @@ def test_h_str():
|
|
|
307
308
|
assert str(cirq.H**0.5) == 'H**0.5'
|
|
308
309
|
|
|
309
310
|
|
|
311
|
+
def test_phase_exponent():
|
|
312
|
+
assert cirq.XPowGate(exponent=0.5).phase_exponent == 0.0
|
|
313
|
+
assert cirq.YPowGate(exponent=0.5).phase_exponent == 0.5
|
|
314
|
+
|
|
315
|
+
|
|
310
316
|
def test_x_act_on_tableau():
|
|
311
317
|
with pytest.raises(TypeError, match="Failed to act"):
|
|
312
318
|
cirq.act_on(cirq.X, ExampleSimulationState(), qubits=())
|
|
@@ -1300,3 +1306,13 @@ def test_wrong_dims():
|
|
|
1300
1306
|
|
|
1301
1307
|
with pytest.raises(ValueError, match='Wrong shape'):
|
|
1302
1308
|
_ = cirq.Z.on(cirq.LineQid(0, dimension=3))
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
@pytest.mark.parametrize('gate_type', [cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate])
|
|
1312
|
+
@pytest.mark.parametrize('exponent', [sympy.Symbol('s'), sympy.Symbol('s') * 2])
|
|
1313
|
+
def test_parameterized_pauli_expansion(gate_type, exponent):
|
|
1314
|
+
gate = gate_type(exponent=exponent)
|
|
1315
|
+
pauli = cirq.pauli_expansion(gate)
|
|
1316
|
+
gate_resolved = cirq.resolve_parameters(gate, {'s': 0.5})
|
|
1317
|
+
pauli_resolved = cirq.resolve_parameters(pauli, {'s': 0.5})
|
|
1318
|
+
assert cirq.approx_eq(pauli_resolved, cirq.pauli_expansion(gate_resolved))
|
cirq/ops/control_values.py
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import abc
|
|
15
|
-
from functools import cached_property
|
|
16
|
-
from typing import Collection, Tuple, TYPE_CHECKING, Any, Dict, Iterator, Optional, Sequence, Union
|
|
17
15
|
import itertools
|
|
16
|
+
from functools import cached_property
|
|
17
|
+
from typing import Any, Collection, Dict, Iterator, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
18
18
|
|
|
19
19
|
from cirq import protocols, value
|
|
20
20
|
|
|
@@ -275,7 +275,7 @@ class SumOfProducts(AbstractControlValues):
|
|
|
275
275
|
|
|
276
276
|
if len(self._conjunctions) == 1:
|
|
277
277
|
# Use a simpler diagram if there's only 1 term.
|
|
278
|
-
return protocols.CircuitDiagramInfo(
|
|
278
|
+
return protocols.CircuitDiagramInfo( # pragma: no cover
|
|
279
279
|
wire_symbols=["@" if x == 1 else f"({x})" for x in self._conjunctions[0]]
|
|
280
280
|
)
|
|
281
281
|
|
cirq/ops/control_values_test.py
CHANGED
cirq/ops/controlled_gate.py
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from types import NotImplementedType
|
|
15
16
|
from typing import (
|
|
16
17
|
AbstractSet,
|
|
17
18
|
Any,
|
|
@@ -21,21 +22,21 @@ from typing import (
|
|
|
21
22
|
Optional,
|
|
22
23
|
Sequence,
|
|
23
24
|
Tuple,
|
|
24
|
-
Union,
|
|
25
25
|
TYPE_CHECKING,
|
|
26
|
+
Union,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
import numpy as np
|
|
29
30
|
|
|
30
|
-
from cirq import protocols, value
|
|
31
|
+
from cirq import _import, protocols, value
|
|
31
32
|
from cirq.ops import (
|
|
32
|
-
|
|
33
|
+
control_values as cv,
|
|
33
34
|
controlled_operation as cop,
|
|
35
|
+
diagonal_gate as dg,
|
|
36
|
+
global_phase_op as gp,
|
|
34
37
|
op_tree,
|
|
35
|
-
|
|
36
|
-
control_values as cv,
|
|
38
|
+
raw_types,
|
|
37
39
|
)
|
|
38
|
-
from cirq.type_workarounds import NotImplementedType
|
|
39
40
|
|
|
40
41
|
if TYPE_CHECKING:
|
|
41
42
|
import cirq
|
|
@@ -157,13 +158,13 @@ class ControlledGate(raw_types.Gate):
|
|
|
157
158
|
def _decompose_with_context_(
|
|
158
159
|
self, qubits: Tuple['cirq.Qid', ...], context: Optional['cirq.DecompositionContext'] = None
|
|
159
160
|
) -> Union[None, NotImplementedType, 'cirq.OP_TREE']:
|
|
161
|
+
control_qubits = list(qubits[: self.num_controls()])
|
|
160
162
|
if (
|
|
161
163
|
protocols.has_unitary(self.sub_gate)
|
|
162
164
|
and protocols.num_qubits(self.sub_gate) == 1
|
|
163
165
|
and self._qid_shape_() == (2,) * len(self._qid_shape_())
|
|
164
166
|
and isinstance(self.control_values, cv.ProductOfSums)
|
|
165
167
|
):
|
|
166
|
-
control_qubits = list(qubits[: self.num_controls()])
|
|
167
168
|
invert_ops: List['cirq.Operation'] = []
|
|
168
169
|
for cvals, cqbit in zip(self.control_values, qubits[: self.num_controls()]):
|
|
169
170
|
if set(cvals) == {0}:
|
|
@@ -174,11 +175,20 @@ class ControlledGate(raw_types.Gate):
|
|
|
174
175
|
protocols.unitary(self.sub_gate), control_qubits, qubits[-1]
|
|
175
176
|
)
|
|
176
177
|
return invert_ops + decomposed_ops + invert_ops
|
|
177
|
-
|
|
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)
|
|
178
190
|
if isinstance(self.sub_gate, common_gates.CZPowGate):
|
|
179
|
-
z_sub_gate = common_gates.ZPowGate(
|
|
180
|
-
exponent=self.sub_gate.exponent, global_shift=self.sub_gate.global_shift
|
|
181
|
-
)
|
|
191
|
+
z_sub_gate = common_gates.ZPowGate(exponent=self.sub_gate.exponent)
|
|
182
192
|
num_controls = self.num_controls() + 1
|
|
183
193
|
control_values = self.control_values & cv.ProductOfSums(((1,),))
|
|
184
194
|
control_qid_shape = self.control_qid_shape + (2,)
|
|
@@ -197,15 +207,18 @@ class ControlledGate(raw_types.Gate):
|
|
|
197
207
|
)
|
|
198
208
|
)
|
|
199
209
|
if self != controlled_z:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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]
|
|
209
222
|
result = protocols.decompose_once_with_qubits(
|
|
210
223
|
self.sub_gate,
|
|
211
224
|
qubits[self.num_controls() :],
|
|
@@ -255,7 +268,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
255
268
|
def _has_mixture_(self) -> bool:
|
|
256
269
|
return protocols.has_mixture(self.sub_gate)
|
|
257
270
|
|
|
258
|
-
def _mixture_(self) -> Union[np.ndarray, NotImplementedType]:
|
|
271
|
+
def _mixture_(self) -> Union[Sequence[tuple[float, np.ndarray]], NotImplementedType]:
|
|
259
272
|
qubits = line_qubit.LineQid.for_gate(self)
|
|
260
273
|
op = self.sub_gate.on(*qubits[self.num_controls() :])
|
|
261
274
|
c_op = cop.ControlledOperation(qubits[: self.num_controls()], op, self.control_values)
|
|
@@ -294,7 +307,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
294
307
|
return None
|
|
295
308
|
u = protocols.unitary(self.sub_gate, default=None)
|
|
296
309
|
if u is None:
|
|
297
|
-
return NotImplemented
|
|
310
|
+
return NotImplemented # pragma: no cover
|
|
298
311
|
angle_list = np.append(np.angle(np.linalg.eigvals(u)), 0)
|
|
299
312
|
return protocols.trace_distance_from_angle_list(angle_list)
|
|
300
313
|
|
|
@@ -328,7 +341,7 @@ class ControlledGate(raw_types.Gate):
|
|
|
328
341
|
return str(self.control_values) + str(self.sub_gate)
|
|
329
342
|
|
|
330
343
|
def __repr__(self) -> str:
|
|
331
|
-
if self.
|
|
344
|
+
if self.control_qid_shape == (2,) and self.control_values.is_trivial:
|
|
332
345
|
return f'cirq.ControlledGate(sub_gate={self.sub_gate!r})'
|
|
333
346
|
|
|
334
347
|
if self.control_values.is_trivial and set(self.control_qid_shape) == {2}:
|
cirq/ops/controlled_gate_test.py
CHANGED
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from types import NotImplementedType
|
|
16
|
+
from typing import Any, cast, Optional, Sequence, Tuple, Union
|
|
16
17
|
|
|
17
18
|
import numpy as np
|
|
18
19
|
import pytest
|
|
19
20
|
import sympy
|
|
20
21
|
|
|
21
22
|
import cirq
|
|
22
|
-
from cirq.type_workarounds import NotImplementedType
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class GateUsingWorkspaceForApplyUnitary(cirq.testing.SingleQubitGate):
|
|
@@ -408,6 +408,11 @@ def test_unitary():
|
|
|
408
408
|
),
|
|
409
409
|
True,
|
|
410
410
|
),
|
|
411
|
+
(cirq.GlobalPhaseGate(-1), True),
|
|
412
|
+
(cirq.GlobalPhaseGate(1j**0.7), True),
|
|
413
|
+
(cirq.GlobalPhaseGate(sympy.Symbol("s")), False),
|
|
414
|
+
(cirq.CZPowGate(exponent=1.2, global_shift=0.3), True),
|
|
415
|
+
(cirq.CZPowGate(exponent=sympy.Symbol("s"), global_shift=0.3), False),
|
|
411
416
|
# Single qudit gate with dimension 4.
|
|
412
417
|
(cirq.MatrixGate(np.kron(*(cirq.unitary(cirq.H),) * 2), qid_shape=(4,)), False),
|
|
413
418
|
(cirq.MatrixGate(cirq.testing.random_unitary(4, random_state=1234)), False),
|
|
@@ -420,11 +425,73 @@ def test_unitary():
|
|
|
420
425
|
],
|
|
421
426
|
)
|
|
422
427
|
def test_controlled_gate_is_consistent(gate: cirq.Gate, should_decompose_to_target):
|
|
423
|
-
|
|
428
|
+
_test_controlled_gate_is_consistent(gate, should_decompose_to_target)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
@pytest.mark.parametrize(
|
|
432
|
+
'gate',
|
|
433
|
+
[
|
|
434
|
+
cirq.I,
|
|
435
|
+
cirq.GlobalPhaseGate(1),
|
|
436
|
+
cirq.GlobalPhaseGate(-1),
|
|
437
|
+
cirq.GlobalPhaseGate(1j),
|
|
438
|
+
cirq.GlobalPhaseGate(1j**0.7),
|
|
439
|
+
cirq.Z,
|
|
440
|
+
cirq.ZPowGate(exponent=1.2, global_shift=0.3),
|
|
441
|
+
cirq.CZ,
|
|
442
|
+
cirq.CZPowGate(exponent=1.2, global_shift=0.3),
|
|
443
|
+
cirq.CCZ,
|
|
444
|
+
cirq.CCZPowGate(exponent=1.2, global_shift=0.3),
|
|
445
|
+
cirq.X,
|
|
446
|
+
cirq.XPowGate(exponent=1.2, global_shift=0.3),
|
|
447
|
+
cirq.CX,
|
|
448
|
+
cirq.CXPowGate(exponent=1.2, global_shift=0.3),
|
|
449
|
+
cirq.CCX,
|
|
450
|
+
cirq.CCXPowGate(exponent=1.2, global_shift=0.3),
|
|
451
|
+
],
|
|
452
|
+
)
|
|
453
|
+
@pytest.mark.parametrize(
|
|
454
|
+
'control_qid_shape, control_values, should_decompose_to_target',
|
|
455
|
+
[
|
|
456
|
+
([2, 2], None, True),
|
|
457
|
+
([2, 2], xor_control_values, False),
|
|
458
|
+
([3], None, False),
|
|
459
|
+
([3, 4], xor_control_values, False),
|
|
460
|
+
],
|
|
461
|
+
)
|
|
462
|
+
def test_nontrivial_controlled_gate_is_consistent(
|
|
463
|
+
gate: cirq.Gate,
|
|
464
|
+
control_qid_shape: Sequence[int],
|
|
465
|
+
control_values: Any,
|
|
466
|
+
should_decompose_to_target: bool,
|
|
467
|
+
):
|
|
468
|
+
_test_controlled_gate_is_consistent(
|
|
469
|
+
gate, should_decompose_to_target, control_qid_shape, control_values
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def _test_controlled_gate_is_consistent(
|
|
474
|
+
gate: cirq.Gate,
|
|
475
|
+
should_decompose_to_target: bool,
|
|
476
|
+
control_qid_shape: Optional[Sequence[int]] = None,
|
|
477
|
+
control_values: Any = None,
|
|
478
|
+
):
|
|
479
|
+
cgate = cirq.ControlledGate(
|
|
480
|
+
gate, control_qid_shape=control_qid_shape, control_values=control_values
|
|
481
|
+
)
|
|
424
482
|
cirq.testing.assert_implements_consistent_protocols(cgate)
|
|
425
483
|
cirq.testing.assert_decompose_ends_at_default_gateset(
|
|
426
484
|
cgate, ignore_known_gates=not should_decompose_to_target
|
|
427
485
|
)
|
|
486
|
+
# The above only decompose once, which doesn't check that the sub-gate's phase is handled.
|
|
487
|
+
# We need to check full decomposition here.
|
|
488
|
+
if not cirq.is_parameterized(gate):
|
|
489
|
+
shape = cirq.qid_shape(cgate)
|
|
490
|
+
qids = cirq.LineQid.for_qid_shape(shape)
|
|
491
|
+
decomposed = cirq.decompose(cgate.on(*qids))
|
|
492
|
+
first_op = cirq.IdentityGate(qid_shape=shape).on(*qids) # To ensure same qid order
|
|
493
|
+
circuit = cirq.Circuit(first_op, *decomposed)
|
|
494
|
+
np.testing.assert_allclose(cirq.unitary(cgate), cirq.unitary(circuit), atol=1e-13)
|
|
428
495
|
|
|
429
496
|
|
|
430
497
|
def test_pow_inverse():
|
cirq/ops/controlled_operation.py
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from types import NotImplementedType
|
|
15
16
|
from typing import (
|
|
16
17
|
AbstractSet,
|
|
17
18
|
Any,
|
|
@@ -21,24 +22,23 @@ from typing import (
|
|
|
21
22
|
Optional,
|
|
22
23
|
Sequence,
|
|
23
24
|
Tuple,
|
|
24
|
-
Union,
|
|
25
25
|
TYPE_CHECKING,
|
|
26
|
+
Union,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
import numpy as np
|
|
29
30
|
|
|
30
31
|
from cirq import protocols, qis, value
|
|
31
32
|
from cirq.ops import (
|
|
32
|
-
controlled_gate,
|
|
33
33
|
common_gates,
|
|
34
|
+
control_values as cv,
|
|
35
|
+
controlled_gate,
|
|
34
36
|
eigen_gate,
|
|
35
37
|
gate_operation,
|
|
36
38
|
matrix_gates,
|
|
37
39
|
op_tree,
|
|
38
40
|
raw_types,
|
|
39
|
-
control_values as cv,
|
|
40
41
|
)
|
|
41
|
-
from cirq.type_workarounds import NotImplementedType
|
|
42
42
|
|
|
43
43
|
if TYPE_CHECKING:
|
|
44
44
|
import cirq
|
|
@@ -212,6 +212,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
212
212
|
hasattr(self._sub_operation, "gate")
|
|
213
213
|
and len(self._controls) == 1
|
|
214
214
|
and self.control_values == cv.ProductOfSums(((1,),))
|
|
215
|
+
and all(q.dimension == 2 for q in self.qubits)
|
|
215
216
|
):
|
|
216
217
|
gate = self.sub_operation.gate
|
|
217
218
|
if (
|
|
@@ -296,7 +297,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
296
297
|
return None
|
|
297
298
|
u = protocols.unitary(self.sub_operation, default=None)
|
|
298
299
|
if u is None:
|
|
299
|
-
return NotImplemented
|
|
300
|
+
return NotImplemented # pragma: no cover
|
|
300
301
|
angle_list = np.append(np.angle(np.linalg.eigvals(u)), 0)
|
|
301
302
|
return protocols.trace_distance_from_angle_list(angle_list)
|
|
302
303
|
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import itertools
|
|
16
16
|
import re
|
|
17
|
+
from types import NotImplementedType
|
|
17
18
|
from typing import cast, Tuple, Union
|
|
18
19
|
|
|
19
20
|
import numpy as np
|
|
@@ -22,7 +23,6 @@ import sympy
|
|
|
22
23
|
|
|
23
24
|
import cirq
|
|
24
25
|
from cirq import protocols
|
|
25
|
-
from cirq.type_workarounds import NotImplementedType
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class GateUsingWorkspaceForApplyUnitary(cirq.testing.SingleQubitGate):
|
|
@@ -159,7 +159,7 @@ def test_str():
|
|
|
159
159
|
return ()
|
|
160
160
|
|
|
161
161
|
def with_qubits(self, *new_qubits: cirq.Qid):
|
|
162
|
-
|
|
162
|
+
return self
|
|
163
163
|
|
|
164
164
|
def __str__(self):
|
|
165
165
|
return "Op(q2)"
|
|
@@ -170,7 +170,11 @@ def test_str():
|
|
|
170
170
|
assert str(cirq.ControlledOperation([c1, c2], SingleQubitOp())) == "CC(c1, c2, Op(q2))"
|
|
171
171
|
|
|
172
172
|
assert (
|
|
173
|
-
str(
|
|
173
|
+
str(
|
|
174
|
+
cirq.ControlledOperation(
|
|
175
|
+
[c1, c2.with_dimension(3)], SingleQubitOp().with_qubits(cirq.q(1))
|
|
176
|
+
)
|
|
177
|
+
)
|
|
174
178
|
== "CC(c1, c2 (d=3), Op(q2))"
|
|
175
179
|
)
|
|
176
180
|
|