cirq-core 1.4.1__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 +1 -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.1.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
- {cirq_core-1.4.1.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.1.dist-info/METADATA +0 -45
- {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
cirq/circuits/moment.py
CHANGED
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
|
|
15
15
|
"""A simplified time-slice of operations within a sequenced circuit."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
import itertools
|
|
20
|
+
from functools import cached_property
|
|
21
|
+
from types import NotImplementedType
|
|
18
22
|
from typing import (
|
|
19
23
|
AbstractSet,
|
|
20
24
|
Any,
|
|
@@ -26,35 +30,34 @@ from typing import (
|
|
|
26
30
|
Iterator,
|
|
27
31
|
List,
|
|
28
32
|
Mapping,
|
|
29
|
-
overload,
|
|
30
33
|
Optional,
|
|
34
|
+
overload,
|
|
31
35
|
Sequence,
|
|
32
36
|
Tuple,
|
|
33
37
|
TYPE_CHECKING,
|
|
34
38
|
Union,
|
|
35
39
|
)
|
|
36
|
-
from typing_extensions import Self
|
|
37
40
|
|
|
38
41
|
import numpy as np
|
|
42
|
+
from typing_extensions import Self
|
|
39
43
|
|
|
40
|
-
from cirq import
|
|
44
|
+
from cirq import _compat, ops, protocols, qis
|
|
41
45
|
from cirq._import import LazyLoader
|
|
42
|
-
from cirq.ops import
|
|
46
|
+
from cirq.ops import op_tree, raw_types
|
|
43
47
|
from cirq.protocols import circuit_diagram_info_protocol
|
|
44
|
-
from cirq.type_workarounds import NotImplementedType
|
|
45
48
|
|
|
46
49
|
if TYPE_CHECKING:
|
|
47
50
|
import cirq
|
|
48
51
|
|
|
49
52
|
# Lazy imports to break circular dependencies.
|
|
50
|
-
|
|
53
|
+
circuit = LazyLoader("circuit", globals(), "cirq.circuits.circuit")
|
|
51
54
|
op_tree = LazyLoader("op_tree", globals(), "cirq.ops.op_tree")
|
|
52
55
|
text_diagram_drawer = LazyLoader(
|
|
53
56
|
"text_diagram_drawer", globals(), "cirq.circuits.text_diagram_drawer"
|
|
54
57
|
)
|
|
55
58
|
|
|
56
59
|
|
|
57
|
-
def _default_breakdown(qid:
|
|
60
|
+
def _default_breakdown(qid: cirq.Qid) -> Tuple[Any, Any]:
|
|
58
61
|
# Attempt to convert into a position on the complex plane.
|
|
59
62
|
try:
|
|
60
63
|
plane_pos = complex(qid) # type: ignore
|
|
@@ -81,7 +84,7 @@ class Moment:
|
|
|
81
84
|
are no such operations, returns an empty Moment.
|
|
82
85
|
"""
|
|
83
86
|
|
|
84
|
-
def __init__(self, *contents:
|
|
87
|
+
def __init__(self, *contents: cirq.OP_TREE, _flatten_contents: bool = True) -> None:
|
|
85
88
|
"""Constructs a moment with the given operations.
|
|
86
89
|
|
|
87
90
|
Args:
|
|
@@ -101,10 +104,10 @@ class Moment:
|
|
|
101
104
|
if _flatten_contents
|
|
102
105
|
else cast(Tuple['cirq.Operation'], contents)
|
|
103
106
|
)
|
|
104
|
-
self._sorted_operations: Optional[Tuple[
|
|
107
|
+
self._sorted_operations: Optional[Tuple[cirq.Operation, ...]] = None
|
|
105
108
|
|
|
106
109
|
# An internal dictionary to support efficient operation access by qubit.
|
|
107
|
-
self._qubit_to_op: Dict[
|
|
110
|
+
self._qubit_to_op: Dict[cirq.Qid, cirq.Operation] = {}
|
|
108
111
|
for op in self.operations:
|
|
109
112
|
for q in op.qubits:
|
|
110
113
|
# Check that operations don't overlap.
|
|
@@ -112,12 +115,11 @@ class Moment:
|
|
|
112
115
|
raise ValueError(f'Overlapping operations: {self.operations}')
|
|
113
116
|
self._qubit_to_op[q] = op
|
|
114
117
|
|
|
115
|
-
self.
|
|
116
|
-
self.
|
|
117
|
-
self._control_keys: Optional[FrozenSet['cirq.MeasurementKey']] = None
|
|
118
|
+
self._measurement_key_objs: Optional[FrozenSet[cirq.MeasurementKey]] = None
|
|
119
|
+
self._control_keys: Optional[FrozenSet[cirq.MeasurementKey]] = None
|
|
118
120
|
|
|
119
121
|
@classmethod
|
|
120
|
-
def from_ops(cls, *ops:
|
|
122
|
+
def from_ops(cls, *ops: cirq.Operation) -> cirq.Moment:
|
|
121
123
|
"""Construct a Moment from the given operations.
|
|
122
124
|
|
|
123
125
|
This avoids calling `flatten_to_ops` in the moment constructor, which
|
|
@@ -131,14 +133,14 @@ class Moment:
|
|
|
131
133
|
return cls(*ops, _flatten_contents=False)
|
|
132
134
|
|
|
133
135
|
@property
|
|
134
|
-
def operations(self) -> Tuple[
|
|
136
|
+
def operations(self) -> Tuple[cirq.Operation, ...]:
|
|
135
137
|
return self._operations
|
|
136
138
|
|
|
137
|
-
@
|
|
138
|
-
def qubits(self) -> FrozenSet[
|
|
139
|
-
return self.
|
|
139
|
+
@cached_property
|
|
140
|
+
def qubits(self) -> FrozenSet[cirq.Qid]:
|
|
141
|
+
return frozenset(self._qubit_to_op)
|
|
140
142
|
|
|
141
|
-
def operates_on_single_qubit(self, qubit:
|
|
143
|
+
def operates_on_single_qubit(self, qubit: cirq.Qid) -> bool:
|
|
142
144
|
"""Determines if the moment has operations touching the given qubit.
|
|
143
145
|
Args:
|
|
144
146
|
qubit: The qubit that may or may not be touched by operations.
|
|
@@ -147,7 +149,7 @@ class Moment:
|
|
|
147
149
|
"""
|
|
148
150
|
return qubit in self._qubit_to_op
|
|
149
151
|
|
|
150
|
-
def operates_on(self, qubits: Iterable[
|
|
152
|
+
def operates_on(self, qubits: Iterable[cirq.Qid]) -> bool:
|
|
151
153
|
"""Determines if the moment has operations touching the given qubits.
|
|
152
154
|
|
|
153
155
|
Args:
|
|
@@ -156,9 +158,9 @@ class Moment:
|
|
|
156
158
|
Returns:
|
|
157
159
|
Whether this moment has operations involving the qubits.
|
|
158
160
|
"""
|
|
159
|
-
return not self.
|
|
161
|
+
return not self._qubit_to_op.keys().isdisjoint(qubits)
|
|
160
162
|
|
|
161
|
-
def operation_at(self, qubit: raw_types.Qid) -> Optional[
|
|
163
|
+
def operation_at(self, qubit: raw_types.Qid) -> Optional[cirq.Operation]:
|
|
162
164
|
"""Returns the operation on a certain qubit for the moment.
|
|
163
165
|
|
|
164
166
|
Args:
|
|
@@ -172,7 +174,7 @@ class Moment:
|
|
|
172
174
|
return self.__getitem__(qubit)
|
|
173
175
|
return None
|
|
174
176
|
|
|
175
|
-
def with_operation(self, operation:
|
|
177
|
+
def with_operation(self, operation: cirq.Operation) -> cirq.Moment:
|
|
176
178
|
"""Returns an equal moment, but with the given op added.
|
|
177
179
|
|
|
178
180
|
Args:
|
|
@@ -184,14 +186,13 @@ class Moment:
|
|
|
184
186
|
Raises:
|
|
185
187
|
ValueError: If the operation given overlaps a current operation in the moment.
|
|
186
188
|
"""
|
|
187
|
-
if any(q in self.
|
|
189
|
+
if any(q in self._qubit_to_op for q in operation.qubits):
|
|
188
190
|
raise ValueError(f'Overlapping operations: {operation}')
|
|
189
191
|
|
|
190
192
|
# Use private variables to facilitate a quick copy.
|
|
191
193
|
m = Moment(_flatten_contents=False)
|
|
192
194
|
m._operations = self._operations + (operation,)
|
|
193
195
|
m._sorted_operations = None
|
|
194
|
-
m._qubits = self._qubits.union(operation.qubits)
|
|
195
196
|
m._qubit_to_op = {**self._qubit_to_op, **{q: operation for q in operation.qubits}}
|
|
196
197
|
|
|
197
198
|
m._measurement_key_objs = self._measurement_key_objs_().union(
|
|
@@ -201,7 +202,7 @@ class Moment:
|
|
|
201
202
|
|
|
202
203
|
return m
|
|
203
204
|
|
|
204
|
-
def with_operations(self, *contents:
|
|
205
|
+
def with_operations(self, *contents: cirq.OP_TREE) -> cirq.Moment:
|
|
205
206
|
"""Returns a new moment with the given contents added.
|
|
206
207
|
|
|
207
208
|
Args:
|
|
@@ -221,14 +222,11 @@ class Moment:
|
|
|
221
222
|
m = Moment(_flatten_contents=False)
|
|
222
223
|
# Use private variables to facilitate a quick copy.
|
|
223
224
|
m._qubit_to_op = self._qubit_to_op.copy()
|
|
224
|
-
qubits = set(self._qubits)
|
|
225
225
|
for op in flattened_contents:
|
|
226
|
-
if any(q in
|
|
226
|
+
if any(q in m._qubit_to_op for q in op.qubits):
|
|
227
227
|
raise ValueError(f'Overlapping operations: {op}')
|
|
228
|
-
qubits.update(op.qubits)
|
|
229
228
|
for q in op.qubits:
|
|
230
229
|
m._qubit_to_op[q] = op
|
|
231
|
-
m._qubits = frozenset(qubits)
|
|
232
230
|
|
|
233
231
|
m._operations = self._operations + flattened_contents
|
|
234
232
|
m._sorted_operations = None
|
|
@@ -241,7 +239,7 @@ class Moment:
|
|
|
241
239
|
|
|
242
240
|
return m
|
|
243
241
|
|
|
244
|
-
def without_operations_touching(self, qubits: Iterable[
|
|
242
|
+
def without_operations_touching(self, qubits: Iterable[cirq.Qid]) -> cirq.Moment:
|
|
245
243
|
"""Returns an equal moment, but without ops on the given qubits.
|
|
246
244
|
|
|
247
245
|
Args:
|
|
@@ -267,15 +265,16 @@ class Moment:
|
|
|
267
265
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
268
266
|
return {name for op in self for name in protocols.parameter_names(op)}
|
|
269
267
|
|
|
270
|
-
def _resolve_parameters_(
|
|
271
|
-
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
272
|
-
) -> 'cirq.Moment':
|
|
268
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> cirq.Moment:
|
|
273
269
|
changed = False
|
|
274
|
-
resolved_ops: List[
|
|
270
|
+
resolved_ops: List[cirq.Operation] = []
|
|
275
271
|
for op in self:
|
|
276
272
|
resolved_op = protocols.resolve_parameters(op, resolver, recursive)
|
|
277
|
-
|
|
278
|
-
changed
|
|
273
|
+
changed = (
|
|
274
|
+
changed
|
|
275
|
+
or resolved_op != op
|
|
276
|
+
or (protocols.is_parameterized(op) and not protocols.is_parameterized(resolved_op))
|
|
277
|
+
)
|
|
279
278
|
resolved_ops.append(resolved_op)
|
|
280
279
|
if not changed:
|
|
281
280
|
return self
|
|
@@ -295,21 +294,21 @@ class Moment:
|
|
|
295
294
|
def _measurement_key_names_(self) -> FrozenSet[str]:
|
|
296
295
|
return frozenset(str(key) for key in self._measurement_key_objs_())
|
|
297
296
|
|
|
298
|
-
def _measurement_key_objs_(self) -> FrozenSet[
|
|
297
|
+
def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
|
|
299
298
|
if self._measurement_key_objs is None:
|
|
300
299
|
self._measurement_key_objs = frozenset(
|
|
301
300
|
key for op in self.operations for key in protocols.measurement_key_objs(op)
|
|
302
301
|
)
|
|
303
302
|
return self._measurement_key_objs
|
|
304
303
|
|
|
305
|
-
def _control_keys_(self) -> FrozenSet[
|
|
304
|
+
def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
|
|
306
305
|
if self._control_keys is None:
|
|
307
306
|
self._control_keys = frozenset(
|
|
308
307
|
k for op in self.operations for k in protocols.control_keys(op)
|
|
309
308
|
)
|
|
310
309
|
return self._control_keys
|
|
311
310
|
|
|
312
|
-
def _sorted_operations_(self) -> Tuple[
|
|
311
|
+
def _sorted_operations_(self) -> Tuple[cirq.Operation, ...]:
|
|
313
312
|
if self._sorted_operations is None:
|
|
314
313
|
self._sorted_operations = tuple(sorted(self._operations, key=lambda op: op.qubits))
|
|
315
314
|
return self._sorted_operations
|
|
@@ -331,7 +330,7 @@ class Moment:
|
|
|
331
330
|
)
|
|
332
331
|
|
|
333
332
|
def _with_rescoped_keys_(
|
|
334
|
-
self, path: Tuple[str, ...], bindable_keys: FrozenSet[
|
|
333
|
+
self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
|
|
335
334
|
):
|
|
336
335
|
return Moment(
|
|
337
336
|
protocols.with_rescoped_keys(op, path, bindable_keys) for op in self.operations
|
|
@@ -349,7 +348,7 @@ class Moment:
|
|
|
349
348
|
|
|
350
349
|
return self is other or self._sorted_operations_() == other._sorted_operations_()
|
|
351
350
|
|
|
352
|
-
def _approx_eq_(self, other: Any, atol:
|
|
351
|
+
def _approx_eq_(self, other: Any, atol: float) -> bool:
|
|
353
352
|
"""See `cirq.protocols.SupportsApproximateEquality`."""
|
|
354
353
|
if not isinstance(other, type(self)):
|
|
355
354
|
return NotImplemented
|
|
@@ -365,7 +364,16 @@ class Moment:
|
|
|
365
364
|
def __hash__(self):
|
|
366
365
|
return hash((Moment, self._sorted_operations_()))
|
|
367
366
|
|
|
368
|
-
def
|
|
367
|
+
def __getstate__(self) -> Dict[str, Any]:
|
|
368
|
+
# clear cached hash value when pickling, see #6674
|
|
369
|
+
state = self.__dict__
|
|
370
|
+
hash_attr = _compat._method_cache_name(self.__hash__)
|
|
371
|
+
if hash_attr in state:
|
|
372
|
+
state = state.copy()
|
|
373
|
+
del state[hash_attr]
|
|
374
|
+
return state
|
|
375
|
+
|
|
376
|
+
def __iter__(self) -> Iterator[cirq.Operation]:
|
|
369
377
|
return iter(self.operations)
|
|
370
378
|
|
|
371
379
|
def __pow__(self, power):
|
|
@@ -394,12 +402,12 @@ class Moment:
|
|
|
394
402
|
def __str__(self) -> str:
|
|
395
403
|
return self.to_text_diagram()
|
|
396
404
|
|
|
397
|
-
def _decompose_(self) ->
|
|
405
|
+
def _decompose_(self) -> cirq.OP_TREE:
|
|
398
406
|
"""See `cirq.SupportsDecompose`."""
|
|
399
407
|
return self._operations
|
|
400
408
|
|
|
401
409
|
def transform_qubits(
|
|
402
|
-
self, qubit_map: Union[Dict[
|
|
410
|
+
self, qubit_map: Union[Dict[cirq.Qid, cirq.Qid], Callable[[cirq.Qid], cirq.Qid]]
|
|
403
411
|
) -> Self:
|
|
404
412
|
"""Returns the same moment, but with different qubits.
|
|
405
413
|
|
|
@@ -413,7 +421,7 @@ class Moment:
|
|
|
413
421
|
"""
|
|
414
422
|
return self.__class__(op.transform_qubits(qubit_map) for op in self.operations)
|
|
415
423
|
|
|
416
|
-
def expand_to(self, qubits: Iterable[
|
|
424
|
+
def expand_to(self, qubits: Iterable[cirq.Qid]) -> cirq.Moment:
|
|
417
425
|
"""Returns self expanded to given superset of qubits by making identities explicit.
|
|
418
426
|
|
|
419
427
|
Args:
|
|
@@ -437,7 +445,9 @@ class Moment:
|
|
|
437
445
|
@_compat.cached_method()
|
|
438
446
|
def _has_kraus_(self) -> bool:
|
|
439
447
|
"""Returns True if self has a Kraus representation and self uses <= 10 qubits."""
|
|
440
|
-
return
|
|
448
|
+
return (
|
|
449
|
+
all(protocols.has_kraus(op) for op in self.operations) and len(self._qubit_to_op) <= 10
|
|
450
|
+
)
|
|
441
451
|
|
|
442
452
|
def _kraus_(self) -> Sequence[np.ndarray]:
|
|
443
453
|
r"""Returns Kraus representation of self.
|
|
@@ -462,7 +472,7 @@ class Moment:
|
|
|
462
472
|
if not self._has_kraus_():
|
|
463
473
|
return NotImplemented
|
|
464
474
|
|
|
465
|
-
qubits = sorted(self.
|
|
475
|
+
qubits = sorted(self._qubit_to_op)
|
|
466
476
|
n = len(qubits)
|
|
467
477
|
if n < 1:
|
|
468
478
|
return (np.array([[1 + 0j]]),)
|
|
@@ -470,13 +480,13 @@ class Moment:
|
|
|
470
480
|
qubit_to_row_subscript = dict(zip(qubits, 'abcdefghij'))
|
|
471
481
|
qubit_to_col_subscript = dict(zip(qubits, 'ABCDEFGHIJ'))
|
|
472
482
|
|
|
473
|
-
def row_subscripts(qs: Sequence[
|
|
483
|
+
def row_subscripts(qs: Sequence[cirq.Qid]) -> str:
|
|
474
484
|
return ''.join(qubit_to_row_subscript[q] for q in qs)
|
|
475
485
|
|
|
476
|
-
def col_subscripts(qs: Sequence[
|
|
486
|
+
def col_subscripts(qs: Sequence[cirq.Qid]) -> str:
|
|
477
487
|
return ''.join(qubit_to_col_subscript[q] for q in qs)
|
|
478
488
|
|
|
479
|
-
def kraus_tensors(op:
|
|
489
|
+
def kraus_tensors(op: cirq.Operation) -> Sequence[np.ndarray]:
|
|
480
490
|
return tuple(np.reshape(k, (2, 2) * len(op.qubits)) for k in protocols.kraus(op))
|
|
481
491
|
|
|
482
492
|
input_subscripts = ','.join(
|
|
@@ -513,12 +523,12 @@ class Moment:
|
|
|
513
523
|
def _from_json_dict_(cls, operations, **kwargs):
|
|
514
524
|
return cls.from_ops(*operations)
|
|
515
525
|
|
|
516
|
-
def __add__(self, other:
|
|
517
|
-
if isinstance(other,
|
|
526
|
+
def __add__(self, other: cirq.OP_TREE) -> cirq.Moment:
|
|
527
|
+
if isinstance(other, circuit.AbstractCircuit):
|
|
518
528
|
return NotImplemented # Delegate to Circuit.__radd__.
|
|
519
529
|
return self.with_operations(other)
|
|
520
530
|
|
|
521
|
-
def __sub__(self, other:
|
|
531
|
+
def __sub__(self, other: cirq.OP_TREE) -> cirq.Moment:
|
|
522
532
|
must_remove = set(op_tree.flatten_to_ops(other))
|
|
523
533
|
new_ops = []
|
|
524
534
|
for op in self.operations:
|
|
@@ -536,11 +546,11 @@ class Moment:
|
|
|
536
546
|
|
|
537
547
|
# pylint: disable=function-redefined
|
|
538
548
|
@overload
|
|
539
|
-
def __getitem__(self, key: raw_types.Qid) ->
|
|
549
|
+
def __getitem__(self, key: raw_types.Qid) -> cirq.Operation:
|
|
540
550
|
pass
|
|
541
551
|
|
|
542
552
|
@overload
|
|
543
|
-
def __getitem__(self, key: Iterable[raw_types.Qid]) ->
|
|
553
|
+
def __getitem__(self, key: Iterable[raw_types.Qid]) -> cirq.Moment:
|
|
544
554
|
pass
|
|
545
555
|
|
|
546
556
|
def __getitem__(self, key):
|
|
@@ -557,10 +567,10 @@ class Moment:
|
|
|
557
567
|
return Moment(frozenset(ops_to_keep))
|
|
558
568
|
|
|
559
569
|
def to_text_diagram(
|
|
560
|
-
self:
|
|
570
|
+
self: cirq.Moment,
|
|
561
571
|
*,
|
|
562
|
-
xy_breakdown_func: Callable[[
|
|
563
|
-
extra_qubits: Iterable[
|
|
572
|
+
xy_breakdown_func: Callable[[cirq.Qid], Tuple[Any, Any]] = _default_breakdown,
|
|
573
|
+
extra_qubits: Iterable[cirq.Qid] = (),
|
|
564
574
|
use_unicode_characters: bool = True,
|
|
565
575
|
precision: Optional[int] = None,
|
|
566
576
|
include_tags: bool = True,
|
|
@@ -589,7 +599,7 @@ class Moment:
|
|
|
589
599
|
"""
|
|
590
600
|
|
|
591
601
|
# Figure out where to place everything.
|
|
592
|
-
qs =
|
|
602
|
+
qs = self._qubit_to_op.keys() | set(extra_qubits)
|
|
593
603
|
points = {xy_breakdown_func(q) for q in qs}
|
|
594
604
|
x_keys = sorted({pt[0] for pt in points}, key=_SortByValFallbackToType)
|
|
595
605
|
y_keys = sorted({pt[1] for pt in points}, key=_SortByValFallbackToType)
|
|
@@ -648,37 +658,26 @@ class Moment:
|
|
|
648
658
|
return diagram.render()
|
|
649
659
|
|
|
650
660
|
def _commutes_(self, other: Any, *, atol: float = 1e-8) -> Union[bool, NotImplementedType]:
|
|
651
|
-
"""Determines whether Moment commutes with the Operation.
|
|
661
|
+
"""Determines whether Moment commutes with the other Moment or Operation.
|
|
652
662
|
|
|
653
663
|
Args:
|
|
654
|
-
other: An Operation
|
|
655
|
-
In case a different type is specified, NotImplemented is
|
|
656
|
-
returned.
|
|
664
|
+
other: An Operation or Moment object to test for commutativity.
|
|
657
665
|
atol: Absolute error tolerance. If all entries in v1@v2 - v2@v1
|
|
658
666
|
have a magnitude less than this tolerance, v1 and v2 can be
|
|
659
667
|
reported as commuting. Defaults to 1e-8.
|
|
660
668
|
|
|
661
669
|
Returns:
|
|
662
|
-
True: The Moment
|
|
663
|
-
|
|
670
|
+
True: The Moment commutes with Moment or Operation OR they don't
|
|
671
|
+
have shared qubits.
|
|
664
672
|
False: The two values do not commute.
|
|
665
673
|
NotImplemented: In case we don't know how to check this, e.g.
|
|
666
|
-
the parameter type is not supported
|
|
674
|
+
the parameter type is not supported or commutativity cannot be
|
|
675
|
+
determined.
|
|
667
676
|
"""
|
|
668
|
-
if not isinstance(other, ops.Operation):
|
|
677
|
+
if not isinstance(other, (ops.Operation, Moment)):
|
|
669
678
|
return NotImplemented
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
for op in self.operations:
|
|
673
|
-
if not other_qubits.intersection(set(op.qubits)):
|
|
674
|
-
continue
|
|
675
|
-
|
|
676
|
-
commutes = protocols.commutes(op, other, atol=atol, default=NotImplemented)
|
|
677
|
-
|
|
678
|
-
if not commutes or commutes is NotImplemented:
|
|
679
|
-
return commutes
|
|
680
|
-
|
|
681
|
-
return True
|
|
679
|
+
other_operations = other.operations if isinstance(other, Moment) else (other,)
|
|
680
|
+
return raw_types._operations_commutes_impl(self.operations, other_operations, atol=atol)
|
|
682
681
|
|
|
683
682
|
|
|
684
683
|
class _SortByValFallbackToType:
|
cirq/circuits/moment_test.py
CHANGED
|
@@ -294,6 +294,14 @@ def test_resolve_parameters():
|
|
|
294
294
|
moment = cirq.Moment(cirq.X(a) ** sympy.Symbol('v'), cirq.Y(b) ** sympy.Symbol('w'))
|
|
295
295
|
resolved_moment = cirq.resolve_parameters(moment, cirq.ParamResolver({'v': 0.1, 'w': 0.2}))
|
|
296
296
|
assert resolved_moment == cirq.Moment(cirq.X(a) ** 0.1, cirq.Y(b) ** 0.2)
|
|
297
|
+
# sympy constant is resolved to a Python number
|
|
298
|
+
moment = cirq.Moment(cirq.Rz(rads=sympy.pi).on(a))
|
|
299
|
+
resolved_moment = cirq.resolve_parameters(moment, {'pi': np.pi})
|
|
300
|
+
assert resolved_moment == cirq.Moment(cirq.Rz(rads=np.pi).on(a))
|
|
301
|
+
resolved_gate = resolved_moment.operations[0].gate
|
|
302
|
+
assert not isinstance(resolved_gate.exponent, sympy.Basic)
|
|
303
|
+
assert isinstance(resolved_gate.exponent, float)
|
|
304
|
+
assert not cirq.is_parameterized(resolved_moment)
|
|
297
305
|
|
|
298
306
|
|
|
299
307
|
def test_resolve_parameters_no_change():
|
|
@@ -672,7 +680,7 @@ def test_text_diagram_does_not_depend_on_insertion_order():
|
|
|
672
680
|
assert str(m1) == str(m2)
|
|
673
681
|
|
|
674
682
|
|
|
675
|
-
def
|
|
683
|
+
def test_commutes_moment_and_operation():
|
|
676
684
|
a = cirq.NamedQubit('a')
|
|
677
685
|
b = cirq.NamedQubit('b')
|
|
678
686
|
c = cirq.NamedQubit('c')
|
|
@@ -680,7 +688,7 @@ def test_commutes():
|
|
|
680
688
|
|
|
681
689
|
moment = cirq.Moment([cirq.X(a), cirq.Y(b), cirq.H(c)])
|
|
682
690
|
|
|
683
|
-
assert
|
|
691
|
+
assert cirq.commutes(moment, a, default=None) is None
|
|
684
692
|
|
|
685
693
|
assert cirq.commutes(moment, cirq.X(a))
|
|
686
694
|
assert cirq.commutes(moment, cirq.Y(b))
|
|
@@ -692,6 +700,101 @@ def test_commutes():
|
|
|
692
700
|
assert not cirq.commutes(moment, cirq.H(b))
|
|
693
701
|
assert not cirq.commutes(moment, cirq.X(c))
|
|
694
702
|
|
|
703
|
+
# Empty moment commutes with everything
|
|
704
|
+
moment = cirq.Moment()
|
|
705
|
+
assert cirq.commutes(moment, cirq.X(a))
|
|
706
|
+
assert cirq.commutes(moment, cirq.measure(b))
|
|
707
|
+
|
|
708
|
+
# Two qubit operation
|
|
709
|
+
moment = cirq.Moment(cirq.Z(a), cirq.Z(b))
|
|
710
|
+
assert cirq.commutes(moment, cirq.XX(a, b))
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def test_commutes_moment_and_moment():
|
|
714
|
+
a = cirq.NamedQubit('a')
|
|
715
|
+
b = cirq.NamedQubit('b')
|
|
716
|
+
c = cirq.NamedQubit('c')
|
|
717
|
+
|
|
718
|
+
# Test cases where individual operations don't commute but moments do
|
|
719
|
+
# Two Z gates (Z⊗Z) commutes with RXX even though individual Z's don't
|
|
720
|
+
assert not cirq.commutes(cirq.Moment(cirq.Z(a)), cirq.Moment(cirq.XX(a, b)))
|
|
721
|
+
assert cirq.commutes(cirq.Moment(cirq.Z(a), cirq.Z(b)), cirq.Moment(cirq.XX(a, b)))
|
|
722
|
+
|
|
723
|
+
# Moments that do not commute if acting on same qubits
|
|
724
|
+
assert cirq.commutes(cirq.Moment(cirq.X(a)), cirq.Moment(cirq.Y(b)))
|
|
725
|
+
assert not cirq.commutes(cirq.Moment(cirq.X(a)), cirq.Moment(cirq.Y(a)))
|
|
726
|
+
|
|
727
|
+
# Moments commute with themselves
|
|
728
|
+
assert cirq.commutes(
|
|
729
|
+
cirq.Moment([cirq.X(a), cirq.Y(b), cirq.H(c)]),
|
|
730
|
+
cirq.Moment([cirq.X(a), cirq.Y(b), cirq.H(c)]),
|
|
731
|
+
)
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def test_commutes_moment_with_controls():
|
|
735
|
+
a, b = cirq.LineQubit.range(2)
|
|
736
|
+
assert cirq.commutes(
|
|
737
|
+
cirq.Moment(cirq.measure(a, key='k0')), cirq.Moment(cirq.X(b).with_classical_controls('k1'))
|
|
738
|
+
)
|
|
739
|
+
assert cirq.commutes(
|
|
740
|
+
cirq.Moment(cirq.X(b).with_classical_controls('k1')), cirq.Moment(cirq.measure(a, key='k0'))
|
|
741
|
+
)
|
|
742
|
+
assert cirq.commutes(
|
|
743
|
+
cirq.Moment(cirq.X(a).with_classical_controls('k0')),
|
|
744
|
+
cirq.Moment(cirq.H(b).with_classical_controls('k0')),
|
|
745
|
+
)
|
|
746
|
+
assert cirq.commutes(
|
|
747
|
+
cirq.Moment(cirq.X(a).with_classical_controls('k0')),
|
|
748
|
+
cirq.Moment(cirq.X(a).with_classical_controls('k0')),
|
|
749
|
+
)
|
|
750
|
+
assert not cirq.commutes(
|
|
751
|
+
cirq.Moment(cirq.measure(a, key='k0')), cirq.Moment(cirq.X(b).with_classical_controls('k0'))
|
|
752
|
+
)
|
|
753
|
+
assert not cirq.commutes(
|
|
754
|
+
cirq.Moment(cirq.X(b).with_classical_controls('k0')), cirq.Moment(cirq.measure(a, key='k0'))
|
|
755
|
+
)
|
|
756
|
+
assert not cirq.commutes(
|
|
757
|
+
cirq.Moment(cirq.X(a).with_classical_controls('k0')),
|
|
758
|
+
cirq.Moment(cirq.H(a).with_classical_controls('k0')),
|
|
759
|
+
)
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def test_commutes_moment_and_moment_comprehensive():
|
|
763
|
+
a, b, c, d = cirq.LineQubit.range(4)
|
|
764
|
+
|
|
765
|
+
# Basic Z⊗Z commuting with XX at different angles
|
|
766
|
+
m1 = cirq.Moment([cirq.Z(a), cirq.Z(b)])
|
|
767
|
+
m2 = cirq.Moment([cirq.XXPowGate(exponent=0.5)(a, b)])
|
|
768
|
+
assert cirq.commutes(m1, m2)
|
|
769
|
+
|
|
770
|
+
# Disjoint qubit sets
|
|
771
|
+
m1 = cirq.Moment([cirq.X(a), cirq.Y(b)])
|
|
772
|
+
m2 = cirq.Moment([cirq.Z(c), cirq.H(d)])
|
|
773
|
+
assert cirq.commutes(m1, m2)
|
|
774
|
+
|
|
775
|
+
# Mixed case - some commute individually, some as group
|
|
776
|
+
m1 = cirq.Moment([cirq.Z(a), cirq.Z(b), cirq.X(c)])
|
|
777
|
+
m2 = cirq.Moment([cirq.XXPowGate(exponent=0.5)(a, b), cirq.X(c)])
|
|
778
|
+
assert cirq.commutes(m1, m2)
|
|
779
|
+
|
|
780
|
+
# Non-commuting case: X on first qubit, Z on second with XX gate
|
|
781
|
+
m1 = cirq.Moment([cirq.X(a), cirq.Z(b)])
|
|
782
|
+
m2 = cirq.Moment([cirq.XX(a, b)])
|
|
783
|
+
assert not cirq.commutes(m1, m2)
|
|
784
|
+
|
|
785
|
+
# Complex case requiring unitary calculation - non-commuting case
|
|
786
|
+
m1 = cirq.Moment([cirq.Z(a), cirq.Z(b), cirq.Z(c)])
|
|
787
|
+
m2 = cirq.Moment([cirq.XXPowGate(exponent=0.5)(a, b), cirq.X(c)])
|
|
788
|
+
assert not cirq.commutes(m1, m2) # Z⊗Z⊗Z doesn't commute with XX⊗X
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
def test_commutes_handles_non_unitary_operation():
|
|
792
|
+
a = cirq.NamedQubit('a')
|
|
793
|
+
op_damp_a = cirq.AmplitudeDampingChannel(gamma=0.1).on(a)
|
|
794
|
+
assert cirq.commutes(cirq.Moment(cirq.X(a)), op_damp_a, default=None) is None
|
|
795
|
+
assert cirq.commutes(cirq.Moment(cirq.X(a)), cirq.Moment(op_damp_a), default=None) is None
|
|
796
|
+
assert cirq.commutes(cirq.Moment(op_damp_a), cirq.Moment(op_damp_a))
|
|
797
|
+
|
|
695
798
|
|
|
696
799
|
def test_transform_qubits():
|
|
697
800
|
a, b = cirq.LineQubit.range(2)
|
|
@@ -13,15 +13,17 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
"""Defines the OptimizationPass type."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
16
19
|
import abc
|
|
17
20
|
from collections import defaultdict
|
|
18
|
-
from typing import
|
|
21
|
+
from typing import Callable, cast, Dict, Iterable, Optional, Sequence, Tuple, TYPE_CHECKING
|
|
19
22
|
|
|
20
23
|
from cirq import ops
|
|
21
24
|
|
|
22
25
|
if TYPE_CHECKING:
|
|
23
26
|
import cirq
|
|
24
|
-
from cirq.ops import Qid
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
class PointOptimizationSummary:
|
|
@@ -30,8 +32,8 @@ class PointOptimizationSummary:
|
|
|
30
32
|
def __init__(
|
|
31
33
|
self,
|
|
32
34
|
clear_span: int,
|
|
33
|
-
clear_qubits: Iterable[
|
|
34
|
-
new_operations:
|
|
35
|
+
clear_qubits: Iterable[cirq.Qid],
|
|
36
|
+
new_operations: cirq.OP_TREE,
|
|
35
37
|
preserve_moments: bool = False,
|
|
36
38
|
) -> None:
|
|
37
39
|
"""Inits PointOptimizationSummary.
|
|
@@ -87,9 +89,7 @@ class PointOptimizer:
|
|
|
87
89
|
|
|
88
90
|
def __init__(
|
|
89
91
|
self,
|
|
90
|
-
post_clean_up: Callable[
|
|
91
|
-
[Sequence['cirq.Operation']], 'cirq.OP_TREE'
|
|
92
|
-
] = lambda op_list: op_list,
|
|
92
|
+
post_clean_up: Callable[[Sequence[cirq.Operation]], cirq.OP_TREE] = lambda op_list: op_list,
|
|
93
93
|
) -> None:
|
|
94
94
|
"""Inits PointOptimizer.
|
|
95
95
|
|
|
@@ -100,13 +100,13 @@ class PointOptimizer:
|
|
|
100
100
|
"""
|
|
101
101
|
self.post_clean_up = post_clean_up
|
|
102
102
|
|
|
103
|
-
def __call__(self, circuit:
|
|
103
|
+
def __call__(self, circuit: cirq.Circuit):
|
|
104
104
|
return self.optimize_circuit(circuit)
|
|
105
105
|
|
|
106
106
|
@abc.abstractmethod
|
|
107
107
|
def optimization_at(
|
|
108
|
-
self, circuit:
|
|
109
|
-
) -> Optional[
|
|
108
|
+
self, circuit: cirq.Circuit, index: int, op: cirq.Operation
|
|
109
|
+
) -> Optional[cirq.PointOptimizationSummary]:
|
|
110
110
|
"""Describes how to change operations near the given location.
|
|
111
111
|
|
|
112
112
|
For example, this method could realize that the given operation is an
|
|
@@ -126,8 +126,8 @@ class PointOptimizer:
|
|
|
126
126
|
change should be made.
|
|
127
127
|
"""
|
|
128
128
|
|
|
129
|
-
def optimize_circuit(self, circuit:
|
|
130
|
-
frontier: Dict[
|
|
129
|
+
def optimize_circuit(self, circuit: cirq.Circuit):
|
|
130
|
+
frontier: Dict[cirq.Qid, int] = defaultdict(lambda: 0)
|
|
131
131
|
i = 0
|
|
132
132
|
while i < len(circuit): # Note: circuit may mutate as we go.
|
|
133
133
|
for op in circuit[i].operations:
|
|
@@ -137,14 +137,14 @@ class PointOptimizer:
|
|
|
137
137
|
|
|
138
138
|
# Skip if an optimization removed the circuit underneath us.
|
|
139
139
|
if i >= len(circuit):
|
|
140
|
-
continue
|
|
140
|
+
continue # pragma: no cover
|
|
141
141
|
# Skip if an optimization removed the op we're considering.
|
|
142
142
|
if op not in circuit[i].operations:
|
|
143
|
-
continue
|
|
143
|
+
continue # pragma: no cover
|
|
144
144
|
opt = self.optimization_at(circuit, i, op)
|
|
145
145
|
# Skip if the optimization did nothing.
|
|
146
146
|
if opt is None:
|
|
147
|
-
continue
|
|
147
|
+
continue # pragma: no cover
|
|
148
148
|
|
|
149
149
|
# Clear target area, and insert new operations.
|
|
150
150
|
circuit.clear_operations_touching(
|