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/parity_gates.py
CHANGED
|
@@ -14,24 +14,23 @@
|
|
|
14
14
|
|
|
15
15
|
"""Quantum gates that phase with respect to product-of-pauli observables."""
|
|
16
16
|
|
|
17
|
-
from typing import Any, Dict, List, Optional,
|
|
18
|
-
from typing_extensions import Self
|
|
17
|
+
from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
|
|
19
18
|
|
|
20
19
|
import numpy as np
|
|
20
|
+
from typing_extensions import Self
|
|
21
21
|
|
|
22
22
|
from cirq import protocols, value
|
|
23
23
|
from cirq._compat import proper_repr
|
|
24
24
|
from cirq._doc import document
|
|
25
25
|
from cirq.ops import (
|
|
26
|
-
|
|
27
|
-
eigen_gate,
|
|
26
|
+
clifford_gate,
|
|
28
27
|
common_gates,
|
|
28
|
+
eigen_gate,
|
|
29
|
+
gate_features,
|
|
29
30
|
pauli_gates,
|
|
30
|
-
clifford_gate,
|
|
31
31
|
pauli_interaction_gate,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
if TYPE_CHECKING:
|
|
36
35
|
import cirq
|
|
37
36
|
|
|
@@ -118,7 +117,7 @@ class XXPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
|
|
|
118
117
|
def _has_stabilizer_effect_(self) -> bool:
|
|
119
118
|
return self.exponent % 2 in (0, 0.5, 1, 1.5)
|
|
120
119
|
|
|
121
|
-
def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> 'cirq.OP_TREE':
|
|
120
|
+
def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> Iterator['cirq.OP_TREE']:
|
|
122
121
|
yield common_gates.YPowGate(exponent=-0.5).on_each(*qubits)
|
|
123
122
|
yield ZZPowGate(exponent=self.exponent, global_shift=self.global_shift)(*qubits)
|
|
124
123
|
yield common_gates.YPowGate(exponent=0.5).on_each(*qubits)
|
|
@@ -227,7 +226,7 @@ class YYPowGate(gate_features.InterchangeableQubitsGate, eigen_gate.EigenGate):
|
|
|
227
226
|
def _has_stabilizer_effect_(self) -> bool:
|
|
228
227
|
return self.exponent % 2 in (0, 0.5, 1, 1.5)
|
|
229
228
|
|
|
230
|
-
def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> 'cirq.OP_TREE':
|
|
229
|
+
def _decompose_(self, qubits: Tuple['cirq.Qid', ...]) -> Iterator['cirq.OP_TREE']:
|
|
231
230
|
yield common_gates.XPowGate(exponent=0.5).on_each(*qubits)
|
|
232
231
|
yield ZZPowGate(exponent=self.exponent, global_shift=self.global_shift)(*qubits)
|
|
233
232
|
yield common_gates.XPowGate(exponent=-0.5).on_each(*qubits)
|
cirq/ops/parity_gates_test.py
CHANGED
|
@@ -39,6 +39,7 @@ def test_xx_eq():
|
|
|
39
39
|
cirq.XXPowGate(),
|
|
40
40
|
cirq.XXPowGate(exponent=1, global_shift=0),
|
|
41
41
|
cirq.XXPowGate(exponent=3, global_shift=0),
|
|
42
|
+
cirq.XXPowGate(global_shift=100000),
|
|
42
43
|
)
|
|
43
44
|
eq.add_equality_group(cirq.XX**0.5, cirq.XX**2.5, cirq.XX**4.5)
|
|
44
45
|
eq.add_equality_group(cirq.XX**0.25, cirq.XX**2.25, cirq.XX**-1.75)
|
cirq/ops/pauli_gates.py
CHANGED
|
@@ -12,22 +12,21 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
import abc
|
|
15
|
-
from
|
|
15
|
+
from types import NotImplementedType
|
|
16
|
+
from typing import Any, cast, Dict, Tuple, TYPE_CHECKING, Union
|
|
16
17
|
|
|
17
18
|
from cirq._doc import document
|
|
18
19
|
from cirq._import import LazyLoader
|
|
19
|
-
from cirq.ops import common_gates,
|
|
20
|
-
from cirq.type_workarounds import NotImplementedType
|
|
21
|
-
|
|
20
|
+
from cirq.ops import common_gates, identity, raw_types
|
|
22
21
|
|
|
23
22
|
if TYPE_CHECKING:
|
|
24
23
|
import cirq
|
|
25
24
|
from cirq.ops.pauli_string import SingleQubitPauliStringGateOperation
|
|
26
|
-
from cirq.value.product_state import (
|
|
25
|
+
from cirq.value.product_state import ( # pragma: no cover
|
|
27
26
|
_XEigenState,
|
|
28
27
|
_YEigenState,
|
|
29
28
|
_ZEigenState,
|
|
30
|
-
)
|
|
29
|
+
)
|
|
31
30
|
|
|
32
31
|
|
|
33
32
|
pauli_string = LazyLoader("pauli_string", globals(), "cirq.ops.pauli_string")
|
|
@@ -104,11 +103,6 @@ class Pauli(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
104
103
|
|
|
105
104
|
return pauli_string.SingleQubitPauliStringGateOperation(self, qubits[0])
|
|
106
105
|
|
|
107
|
-
@property
|
|
108
|
-
def _canonical_exponent(self):
|
|
109
|
-
"""Overrides EigenGate._canonical_exponent in subclasses."""
|
|
110
|
-
return 1
|
|
111
|
-
|
|
112
106
|
|
|
113
107
|
class _PauliX(Pauli, common_gates.XPowGate):
|
|
114
108
|
def __init__(self):
|
cirq/ops/pauli_gates_test.py
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from typing import Any, Dict, List, Sequence,
|
|
15
|
+
from typing import Any, Dict, Iterator, List, Sequence, Tuple, TYPE_CHECKING
|
|
16
16
|
|
|
17
17
|
import numpy as np
|
|
18
18
|
|
|
19
|
-
from cirq import
|
|
19
|
+
from cirq import protocols, value
|
|
20
20
|
from cirq._compat import proper_repr
|
|
21
|
-
from cirq.ops import
|
|
21
|
+
from cirq.ops import common_gates, eigen_gate, gate_features, pauli_gates
|
|
22
22
|
from cirq.ops.clifford_gate import SingleQubitCliffordGate
|
|
23
23
|
|
|
24
24
|
if TYPE_CHECKING:
|
|
@@ -85,7 +85,13 @@ class PauliInteractionGate(gate_features.InterchangeableQubitsGate, eigen_gate.E
|
|
|
85
85
|
return 2
|
|
86
86
|
|
|
87
87
|
def _value_equality_values_(self):
|
|
88
|
-
return (
|
|
88
|
+
return (
|
|
89
|
+
self.pauli0,
|
|
90
|
+
self.invert0,
|
|
91
|
+
self.pauli1,
|
|
92
|
+
self.invert1,
|
|
93
|
+
value.PeriodicValue(self.exponent, 2),
|
|
94
|
+
)
|
|
89
95
|
|
|
90
96
|
def qubit_index_to_equivalence_group_key(self, index: int) -> int:
|
|
91
97
|
if self.pauli0 == self.pauli1 and self.invert0 == self.invert1:
|
|
@@ -108,7 +114,7 @@ class PauliInteractionGate(gate_features.InterchangeableQubitsGate, eigen_gate.E
|
|
|
108
114
|
comp0 = np.eye(4) - comp1
|
|
109
115
|
return [(0, comp0), (1, comp1)]
|
|
110
116
|
|
|
111
|
-
def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
|
|
117
|
+
def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
|
|
112
118
|
q0, q1 = qubits
|
|
113
119
|
right_gate0 = SingleQubitCliffordGate.from_single_map(z_to=(self.pauli0, self.invert0))
|
|
114
120
|
right_gate1 = SingleQubitCliffordGate.from_single_map(z_to=(self.pauli1, self.invert1))
|
|
@@ -14,25 +14,26 @@
|
|
|
14
14
|
|
|
15
15
|
from typing import (
|
|
16
16
|
Any,
|
|
17
|
+
cast,
|
|
17
18
|
Dict,
|
|
18
19
|
FrozenSet,
|
|
19
20
|
Iterable,
|
|
21
|
+
Iterator,
|
|
20
22
|
Mapping,
|
|
21
|
-
Tuple,
|
|
22
23
|
Sequence,
|
|
24
|
+
Tuple,
|
|
23
25
|
TYPE_CHECKING,
|
|
24
26
|
Union,
|
|
25
|
-
cast,
|
|
26
27
|
)
|
|
27
28
|
|
|
28
29
|
from cirq import protocols, value
|
|
29
30
|
from cirq.ops import (
|
|
30
|
-
|
|
31
|
+
dense_pauli_string as dps,
|
|
31
32
|
measurement_gate,
|
|
32
33
|
op_tree,
|
|
33
|
-
dense_pauli_string as dps,
|
|
34
34
|
pauli_gates,
|
|
35
35
|
pauli_string_phasor,
|
|
36
|
+
raw_types,
|
|
36
37
|
)
|
|
37
38
|
|
|
38
39
|
if TYPE_CHECKING:
|
|
@@ -144,7 +145,7 @@ class PauliMeasurementGate(raw_types.Gate):
|
|
|
144
145
|
|
|
145
146
|
def _decompose_(
|
|
146
147
|
self, qubits: Tuple['cirq.Qid', ...]
|
|
147
|
-
) -> 'protocols.decompose_protocol.DecomposeResult':
|
|
148
|
+
) -> Iterator['protocols.decompose_protocol.DecomposeResult']:
|
|
148
149
|
any_qubit = qubits[0]
|
|
149
150
|
to_z_ops = op_tree.freeze_op_tree(self._observable.on(*qubits).to_z_basis_ops())
|
|
150
151
|
xor_decomp = tuple(pauli_string_phasor.xor_nonlocal_decompose(qubits, any_qubit))
|
cirq/ops/pauli_string.py
CHANGED
|
@@ -14,10 +14,14 @@
|
|
|
14
14
|
import cmath
|
|
15
15
|
import math
|
|
16
16
|
import numbers
|
|
17
|
+
from types import NotImplementedType
|
|
17
18
|
from typing import (
|
|
19
|
+
AbstractSet,
|
|
18
20
|
Any,
|
|
21
|
+
Callable,
|
|
19
22
|
cast,
|
|
20
23
|
Dict,
|
|
24
|
+
Generic,
|
|
21
25
|
ItemsView,
|
|
22
26
|
Iterable,
|
|
23
27
|
Iterator,
|
|
@@ -27,27 +31,23 @@ from typing import (
|
|
|
27
31
|
Optional,
|
|
28
32
|
overload,
|
|
29
33
|
Sequence,
|
|
30
|
-
SupportsComplex,
|
|
31
34
|
Tuple,
|
|
32
35
|
TYPE_CHECKING,
|
|
33
36
|
TypeVar,
|
|
34
37
|
Union,
|
|
35
38
|
ValuesView,
|
|
36
|
-
AbstractSet,
|
|
37
|
-
Callable,
|
|
38
|
-
Generic,
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
import numpy as np
|
|
42
42
|
import sympy
|
|
43
43
|
|
|
44
|
-
import
|
|
45
|
-
from cirq import value, protocols, linalg, qis, _compat
|
|
44
|
+
from cirq import _compat, linalg, protocols, qis, value
|
|
46
45
|
from cirq._doc import document
|
|
47
46
|
from cirq._import import LazyLoader
|
|
48
47
|
from cirq.ops import (
|
|
49
48
|
clifford_gate,
|
|
50
49
|
common_gates,
|
|
50
|
+
dense_pauli_string,
|
|
51
51
|
gate_operation,
|
|
52
52
|
global_phase_op,
|
|
53
53
|
identity,
|
|
@@ -56,7 +56,6 @@ from cirq.ops import (
|
|
|
56
56
|
pauli_interaction_gate,
|
|
57
57
|
raw_types,
|
|
58
58
|
)
|
|
59
|
-
from cirq.type_workarounds import NotImplementedType
|
|
60
59
|
|
|
61
60
|
if TYPE_CHECKING:
|
|
62
61
|
import cirq
|
|
@@ -271,9 +270,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
271
270
|
pass
|
|
272
271
|
|
|
273
272
|
@overload
|
|
274
|
-
def __mul__(
|
|
275
|
-
self, other: Union[complex, int, float, numbers.Number]
|
|
276
|
-
) -> 'cirq.PauliString[TKey]':
|
|
273
|
+
def __mul__(self, other: complex) -> 'cirq.PauliString[TKey]':
|
|
277
274
|
pass
|
|
278
275
|
|
|
279
276
|
def __mul__(self, other):
|
|
@@ -308,23 +305,21 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
308
305
|
)
|
|
309
306
|
|
|
310
307
|
def __rmul__(self, other) -> 'PauliString':
|
|
311
|
-
if isinstance(other, numbers.
|
|
308
|
+
if isinstance(other, numbers.Complex):
|
|
312
309
|
return PauliString(
|
|
313
|
-
qubit_pauli_map=self._qubit_pauli_map,
|
|
314
|
-
coefficient=self._coefficient * complex(cast(SupportsComplex, other)),
|
|
310
|
+
qubit_pauli_map=self._qubit_pauli_map, coefficient=self._coefficient * other
|
|
315
311
|
)
|
|
316
312
|
|
|
317
313
|
if isinstance(other, raw_types.Operation) and isinstance(other.gate, identity.IdentityGate):
|
|
318
|
-
return self
|
|
314
|
+
return self # pragma: no cover
|
|
319
315
|
|
|
320
316
|
# Note: PauliString case handled by __mul__.
|
|
321
317
|
return NotImplemented
|
|
322
318
|
|
|
323
319
|
def __truediv__(self, other):
|
|
324
|
-
if isinstance(other, numbers.
|
|
320
|
+
if isinstance(other, numbers.Complex):
|
|
325
321
|
return PauliString(
|
|
326
|
-
qubit_pauli_map=self._qubit_pauli_map,
|
|
327
|
-
coefficient=self._coefficient / complex(cast(SupportsComplex, other)),
|
|
322
|
+
qubit_pauli_map=self._qubit_pauli_map, coefficient=self._coefficient / other
|
|
328
323
|
)
|
|
329
324
|
return NotImplemented
|
|
330
325
|
|
|
@@ -467,7 +462,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
467
462
|
fused = prefix + '*'.join(factors)
|
|
468
463
|
if len(factors) > 1:
|
|
469
464
|
return f'({fused})'
|
|
470
|
-
return fused
|
|
465
|
+
return fused # pragma: no cover
|
|
471
466
|
|
|
472
467
|
def __str__(self) -> str:
|
|
473
468
|
ordered_qubits = sorted(self.qubits)
|
|
@@ -500,7 +495,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
500
495
|
"""
|
|
501
496
|
qubits = self.qubits if qubits is None else qubits
|
|
502
497
|
factors = [self.get(q, default=identity.I) for q in qubits]
|
|
503
|
-
if
|
|
498
|
+
if protocols.is_parameterized(self):
|
|
504
499
|
raise NotImplementedError('Cannot express as matrix when parameterized')
|
|
505
500
|
assert isinstance(self.coefficient, complex)
|
|
506
501
|
return linalg.kron(self.coefficient, *[protocols.unitary(f) for f in factors])
|
|
@@ -518,7 +513,7 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
518
513
|
def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'):
|
|
519
514
|
if not self._has_unitary_():
|
|
520
515
|
return None
|
|
521
|
-
assert isinstance(self.coefficient,
|
|
516
|
+
assert isinstance(self.coefficient, numbers.Complex)
|
|
522
517
|
if self.coefficient != 1:
|
|
523
518
|
args.target_tensor *= self.coefficient
|
|
524
519
|
return protocols.apply_unitaries([self[q].on(q) for q in self.qubits], self.qubits, args)
|
|
@@ -792,9 +787,11 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
792
787
|
return self
|
|
793
788
|
|
|
794
789
|
def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
|
|
795
|
-
"""Override
|
|
790
|
+
"""Override numpy behavior."""
|
|
796
791
|
if ufunc == np.exp and len(inputs) == 1 and inputs[0] is self:
|
|
797
792
|
return math.e**self
|
|
793
|
+
if ufunc == np.multiply and len(inputs) == 2 and inputs[1] is self:
|
|
794
|
+
return self * inputs[0]
|
|
798
795
|
return NotImplemented
|
|
799
796
|
|
|
800
797
|
def __pow__(self, power):
|
|
@@ -910,14 +907,13 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
910
907
|
Raises:
|
|
911
908
|
ValueError: If the number of qubits is too small.
|
|
912
909
|
"""
|
|
913
|
-
from cirq.ops.dense_pauli_string import DensePauliString
|
|
914
910
|
|
|
915
911
|
if not self.keys() <= set(qubits):
|
|
916
912
|
raise ValueError('not self.keys() <= set(qubits)')
|
|
917
913
|
# pylint: disable=too-many-function-args
|
|
918
914
|
pauli_mask = [self.get(q, identity.I) for q in qubits]
|
|
919
915
|
# pylint: enable=too-many-function-args
|
|
920
|
-
return DensePauliString(pauli_mask, coefficient=self.coefficient)
|
|
916
|
+
return dense_pauli_string.DensePauliString(pauli_mask, coefficient=self.coefficient)
|
|
921
917
|
|
|
922
918
|
def conjugated_by(self, clifford: 'cirq.OP_TREE') -> 'PauliString':
|
|
923
919
|
r"""Returns the Pauli string conjugated by a clifford operation.
|
|
@@ -979,17 +975,65 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
979
975
|
Returns:
|
|
980
976
|
The Pauli string conjugated by the given Clifford operation.
|
|
981
977
|
"""
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
978
|
+
|
|
979
|
+
# Initialize the ps the same as self.
|
|
980
|
+
ps = PauliString(qubit_pauli_map=self._qubit_pauli_map, coefficient=self.coefficient)
|
|
981
|
+
all_ops = list(op_tree.flatten_to_ops(clifford))
|
|
982
|
+
all_qubits = set.union(set(self.qubits), [q for op in all_ops for q in op.qubits])
|
|
983
|
+
# Iteratively calculate the conjugation in reverse order of ops.
|
|
984
|
+
for op in all_ops[::-1]:
|
|
985
|
+
# To calcuate the conjugation of P (`ps`) with respect to C (`op`)
|
|
986
|
+
# Decompose P = Pc⊗R, where Pc acts on the same qubits as C, R acts on the remaining.
|
|
987
|
+
# Then the conjugation = (C^{-1}⊗I·Pc⊗R·C⊗I) = (C^{-1}·Pc·C)⊗R.
|
|
988
|
+
|
|
989
|
+
# Isolate R
|
|
990
|
+
remain: 'cirq.PauliString' = PauliString(
|
|
991
|
+
*(pauli(q) for q in all_qubits - set(op.qubits) if (pauli := ps.get(q)) is not None)
|
|
992
|
+
)
|
|
993
|
+
|
|
994
|
+
# Initialize the conjugation of Pc.
|
|
995
|
+
conjugated: 'cirq.DensePauliString' = (
|
|
996
|
+
dense_pauli_string.DensePauliString(pauli_mask=[identity.I for _ in op.qubits])
|
|
997
|
+
* ps.coefficient
|
|
998
|
+
)
|
|
999
|
+
|
|
1000
|
+
# Calculate the conjugation via CliffordGate's clifford_tableau.
|
|
1001
|
+
# Note the clifford_tableau in CliffordGate represents C·P·C^-1 instead of C^-1·P·C.
|
|
1002
|
+
# So we take the inverse of the tableau to match the definition of the conjugation here.
|
|
1003
|
+
gate_in_clifford: 'cirq.CliffordGate'
|
|
1004
|
+
if isinstance(op.gate, clifford_gate.CliffordGate):
|
|
1005
|
+
gate_in_clifford = op.gate
|
|
1006
|
+
else:
|
|
1007
|
+
# Convert the clifford gate to CliffordGate type.
|
|
1008
|
+
gate_in_clifford = clifford_gate.CliffordGate.from_op_list([op], op.qubits)
|
|
1009
|
+
tableau = gate_in_clifford.clifford_tableau.inverse()
|
|
1010
|
+
|
|
1011
|
+
# Calculate the conjugation by `op` via mutiplying the conjugation of each Pauli:
|
|
1012
|
+
# C^{-1}·(P_1⊗...⊗P_n)·C
|
|
1013
|
+
# = C^{-1}·(P_1⊗I) ...·(P_n⊗I)·C
|
|
1014
|
+
# = (C^{-1}(P_1⊗I)C)·...·(C^{-1}(P_n⊗I)C)
|
|
1015
|
+
# For the Pauli on the kth qubit P_k. The conjugation is calculated as following.
|
|
1016
|
+
# Puali X_k's conjugation is from the destabilzer table;
|
|
1017
|
+
# Puali Z_k's conjugation is from the stabilzer table;
|
|
1018
|
+
# Puali Y_k's conjugation is calcluated according to Y = iXZ. E.g., for the kth qubit,
|
|
1019
|
+
# C^{-1}·Y_k⊗I·C = C^{-1}·(iX_k⊗I·Z_k⊗I)·C = i (C^{-1}·X_k⊗I·C)·(C^{-1}·Z_k⊗I·C).
|
|
1020
|
+
for qid, qubit in enumerate(op.qubits):
|
|
1021
|
+
pauli = ps.get(qubit)
|
|
1022
|
+
match pauli:
|
|
1023
|
+
case None:
|
|
1024
|
+
continue
|
|
1025
|
+
case pauli_gates.X:
|
|
1026
|
+
conjugated *= tableau.destabilizers()[qid]
|
|
1027
|
+
case pauli_gates.Z:
|
|
1028
|
+
conjugated *= tableau.stabilizers()[qid]
|
|
1029
|
+
case pauli_gates.Y:
|
|
1030
|
+
conjugated *= (
|
|
1031
|
+
1j
|
|
1032
|
+
* tableau.destabilizers()[qid] # conj X first
|
|
1033
|
+
* tableau.stabilizers()[qid] # then conj Z
|
|
1034
|
+
)
|
|
1035
|
+
ps = remain * conjugated.on(*op.qubits)
|
|
1036
|
+
return ps
|
|
993
1037
|
|
|
994
1038
|
def after(self, ops: 'cirq.OP_TREE') -> 'cirq.PauliString':
|
|
995
1039
|
r"""Determines the equivalent pauli string after some operations.
|
|
@@ -1052,20 +1096,17 @@ class PauliString(raw_types.Operation, Generic[TKey]):
|
|
|
1052
1096
|
pauli string, instead of before (and so are moving in the
|
|
1053
1097
|
opposite direction).
|
|
1054
1098
|
"""
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
should_negate ^= _pass_operation_over(pauli_map, clifford_op, after_to_before)
|
|
1067
|
-
coef = -self._coefficient if should_negate else self.coefficient
|
|
1068
|
-
return PauliString(qubit_pauli_map=pauli_map, coefficient=coef)
|
|
1099
|
+
# TODO(#6946): deprecate this method.
|
|
1100
|
+
# Note: This method is supposed to be replaced by conjugated_by()
|
|
1101
|
+
# (see #2351 for details).
|
|
1102
|
+
if after_to_before:
|
|
1103
|
+
return self.after(ops)
|
|
1104
|
+
|
|
1105
|
+
if isinstance(ops, gate_operation.GateOperation):
|
|
1106
|
+
return self.before(ops)
|
|
1107
|
+
|
|
1108
|
+
all_ops = list(op_tree.flatten_to_ops(ops))
|
|
1109
|
+
return self.before(all_ops[::-1])
|
|
1069
1110
|
|
|
1070
1111
|
def _is_parameterized_(self) -> bool:
|
|
1071
1112
|
return protocols.is_parameterized(self.coefficient)
|
|
@@ -1120,6 +1161,23 @@ def _validate_qubit_mapping(
|
|
|
1120
1161
|
)
|
|
1121
1162
|
|
|
1122
1163
|
|
|
1164
|
+
def _try_interpret_as_pauli_string(op: Any):
|
|
1165
|
+
"""Return a reprepresentation of an operation as a pauli string, if it is possible."""
|
|
1166
|
+
if isinstance(op, gate_operation.GateOperation):
|
|
1167
|
+
gates = {
|
|
1168
|
+
common_gates.XPowGate: pauli_gates.X,
|
|
1169
|
+
common_gates.YPowGate: pauli_gates.Y,
|
|
1170
|
+
common_gates.ZPowGate: pauli_gates.Z,
|
|
1171
|
+
}
|
|
1172
|
+
if (pauli := gates.get(type(op.gate), None)) is not None:
|
|
1173
|
+
exponent = op.gate.exponent # type: ignore
|
|
1174
|
+
if exponent % 2 == 0:
|
|
1175
|
+
return PauliString()
|
|
1176
|
+
if exponent % 2 == 1:
|
|
1177
|
+
return pauli.on(op.qubits[0])
|
|
1178
|
+
return None
|
|
1179
|
+
|
|
1180
|
+
|
|
1123
1181
|
# Ignoring type because mypy believes `with_qubits` methods are incompatible.
|
|
1124
1182
|
class SingleQubitPauliStringGateOperation( # type: ignore
|
|
1125
1183
|
gate_operation.GateOperation, PauliString
|
|
@@ -1157,13 +1215,17 @@ class SingleQubitPauliStringGateOperation( # type: ignore
|
|
|
1157
1215
|
def __mul__(self, other):
|
|
1158
1216
|
if isinstance(other, SingleQubitPauliStringGateOperation):
|
|
1159
1217
|
return self._as_pauli_string() * other._as_pauli_string()
|
|
1160
|
-
if isinstance(other, (PauliString,
|
|
1218
|
+
if isinstance(other, (PauliString, numbers.Complex)):
|
|
1161
1219
|
return self._as_pauli_string() * other
|
|
1220
|
+
if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
|
|
1221
|
+
return self * as_pauli_string
|
|
1162
1222
|
return NotImplemented
|
|
1163
1223
|
|
|
1164
1224
|
def __rmul__(self, other):
|
|
1165
|
-
if isinstance(other, (PauliString,
|
|
1225
|
+
if isinstance(other, (PauliString, numbers.Complex)):
|
|
1166
1226
|
return other * self._as_pauli_string()
|
|
1227
|
+
if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
|
|
1228
|
+
return as_pauli_string * self
|
|
1167
1229
|
return NotImplemented
|
|
1168
1230
|
|
|
1169
1231
|
def __neg__(self):
|
|
@@ -1409,8 +1471,8 @@ class MutablePauliString(Generic[TKey]):
|
|
|
1409
1471
|
pauli_int = _pauli_like_to_pauli_int(qubit, pauli_gate_like)
|
|
1410
1472
|
phase_log_i += self._imul_atom_helper(cast(TKey, qubit), pauli_int, sign)
|
|
1411
1473
|
self.coefficient *= 1j ** (phase_log_i & 3)
|
|
1412
|
-
elif isinstance(other, numbers.
|
|
1413
|
-
self.coefficient *=
|
|
1474
|
+
elif isinstance(other, numbers.Complex):
|
|
1475
|
+
self.coefficient *= other
|
|
1414
1476
|
elif isinstance(other, raw_types.Operation) and isinstance(
|
|
1415
1477
|
other.gate, identity.IdentityGate
|
|
1416
1478
|
):
|
|
@@ -1584,88 +1646,11 @@ def _decompose_into_cliffords(op: 'cirq.Operation') -> List['cirq.Operation']:
|
|
|
1584
1646
|
if decomposed is not None:
|
|
1585
1647
|
return [out for sub_op in decomposed for out in _decompose_into_cliffords(sub_op)]
|
|
1586
1648
|
|
|
1587
|
-
raise TypeError(
|
|
1649
|
+
raise TypeError( # pragma: no cover
|
|
1588
1650
|
f'Operation is not a known Clifford and did not decompose into known Cliffords: {op!r}'
|
|
1589
1651
|
)
|
|
1590
1652
|
|
|
1591
1653
|
|
|
1592
|
-
def _pass_operation_over(
|
|
1593
|
-
pauli_map: Dict[TKey, pauli_gates.Pauli], op: 'cirq.Operation', after_to_before: bool = False
|
|
1594
|
-
) -> bool:
|
|
1595
|
-
if isinstance(op, gate_operation.GateOperation):
|
|
1596
|
-
gate = op.gate
|
|
1597
|
-
if isinstance(gate, clifford_gate.SingleQubitCliffordGate):
|
|
1598
|
-
return _pass_single_clifford_gate_over(
|
|
1599
|
-
pauli_map, gate, cast(TKey, op.qubits[0]), after_to_before=after_to_before
|
|
1600
|
-
)
|
|
1601
|
-
if isinstance(gate, pauli_interaction_gate.PauliInteractionGate):
|
|
1602
|
-
return _pass_pauli_interaction_gate_over(
|
|
1603
|
-
pauli_map,
|
|
1604
|
-
gate,
|
|
1605
|
-
cast(TKey, op.qubits[0]),
|
|
1606
|
-
cast(TKey, op.qubits[1]),
|
|
1607
|
-
after_to_before=after_to_before,
|
|
1608
|
-
)
|
|
1609
|
-
raise NotImplementedError(f'Unsupported operation: {op!r}')
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
def _pass_single_clifford_gate_over(
|
|
1613
|
-
pauli_map: Dict[TKey, pauli_gates.Pauli],
|
|
1614
|
-
gate: clifford_gate.SingleQubitCliffordGate,
|
|
1615
|
-
qubit: TKey,
|
|
1616
|
-
after_to_before: bool = False,
|
|
1617
|
-
) -> bool:
|
|
1618
|
-
if qubit not in pauli_map:
|
|
1619
|
-
return False # pragma: no cover
|
|
1620
|
-
if not after_to_before:
|
|
1621
|
-
gate **= -1
|
|
1622
|
-
pauli, inv = gate.pauli_tuple(pauli_map[qubit])
|
|
1623
|
-
pauli_map[qubit] = pauli
|
|
1624
|
-
return inv
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
def _pass_pauli_interaction_gate_over(
|
|
1628
|
-
pauli_map: Dict[TKey, pauli_gates.Pauli],
|
|
1629
|
-
gate: pauli_interaction_gate.PauliInteractionGate,
|
|
1630
|
-
qubit0: TKey,
|
|
1631
|
-
qubit1: TKey,
|
|
1632
|
-
after_to_before: bool = False,
|
|
1633
|
-
) -> bool:
|
|
1634
|
-
def merge_and_kickback(
|
|
1635
|
-
qubit: TKey,
|
|
1636
|
-
pauli_left: Optional[pauli_gates.Pauli],
|
|
1637
|
-
pauli_right: Optional[pauli_gates.Pauli],
|
|
1638
|
-
inv: bool,
|
|
1639
|
-
) -> int:
|
|
1640
|
-
assert pauli_left is not None or pauli_right is not None
|
|
1641
|
-
if pauli_left is None or pauli_right is None:
|
|
1642
|
-
pauli_map[qubit] = cast(pauli_gates.Pauli, pauli_left or pauli_right)
|
|
1643
|
-
return 0
|
|
1644
|
-
if pauli_left == pauli_right:
|
|
1645
|
-
del pauli_map[qubit]
|
|
1646
|
-
return 0
|
|
1647
|
-
|
|
1648
|
-
pauli_map[qubit] = pauli_left.third(pauli_right)
|
|
1649
|
-
if (pauli_left < pauli_right) ^ after_to_before:
|
|
1650
|
-
return int(inv) * 2 + 1
|
|
1651
|
-
|
|
1652
|
-
return int(inv) * 2 - 1
|
|
1653
|
-
|
|
1654
|
-
quarter_kickback = 0
|
|
1655
|
-
if qubit0 in pauli_map and not protocols.commutes(pauli_map[qubit0], gate.pauli0):
|
|
1656
|
-
quarter_kickback += merge_and_kickback(
|
|
1657
|
-
qubit1, gate.pauli1, pauli_map.get(qubit1), gate.invert1
|
|
1658
|
-
)
|
|
1659
|
-
if qubit1 in pauli_map and not protocols.commutes(pauli_map[qubit1], gate.pauli1):
|
|
1660
|
-
quarter_kickback += merge_and_kickback(
|
|
1661
|
-
qubit0, pauli_map.get(qubit0), gate.pauli0, gate.invert0
|
|
1662
|
-
)
|
|
1663
|
-
assert (
|
|
1664
|
-
quarter_kickback % 2 == 0
|
|
1665
|
-
), 'Impossible condition. quarter_kickback is either incremented twice or never.'
|
|
1666
|
-
return quarter_kickback % 4 == 2
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
1654
|
# Mypy has extreme difficulty with these constants for some reason.
|
|
1670
1655
|
_i = cast(identity.IdentityGate, identity.I) # type: ignore
|
|
1671
1656
|
_x = cast(pauli_gates.Pauli, pauli_gates.X) # type: ignore
|