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
|
@@ -18,9 +18,14 @@ A CircuitOperation is an Operation object that wraps a FrozenCircuit. When
|
|
|
18
18
|
applied as part of a larger circuit, a CircuitOperation will execute all
|
|
19
19
|
component operations in order, including any nested CircuitOperations.
|
|
20
20
|
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
21
24
|
import math
|
|
25
|
+
import warnings
|
|
22
26
|
from functools import cached_property
|
|
23
27
|
from typing import (
|
|
28
|
+
Any,
|
|
24
29
|
Callable,
|
|
25
30
|
cast,
|
|
26
31
|
Dict,
|
|
@@ -38,13 +43,12 @@ from typing import (
|
|
|
38
43
|
import numpy as np
|
|
39
44
|
import sympy
|
|
40
45
|
|
|
41
|
-
from cirq import circuits, ops, protocols,
|
|
46
|
+
from cirq import circuits, ops, protocols, study, value
|
|
42
47
|
from cirq._compat import proper_repr
|
|
43
48
|
|
|
44
49
|
if TYPE_CHECKING:
|
|
45
50
|
import cirq
|
|
46
51
|
|
|
47
|
-
|
|
48
52
|
INT_CLASSES = (int, np.integer)
|
|
49
53
|
INT_TYPE = Union[int, np.integer]
|
|
50
54
|
IntParam = Union[INT_TYPE, sympy.Expr]
|
|
@@ -80,16 +84,16 @@ class CircuitOperation(ops.Operation):
|
|
|
80
84
|
|
|
81
85
|
def __init__(
|
|
82
86
|
self,
|
|
83
|
-
circuit:
|
|
87
|
+
circuit: cirq.FrozenCircuit,
|
|
84
88
|
repetitions: INT_TYPE = 1,
|
|
85
|
-
qubit_map: Optional[Dict[
|
|
89
|
+
qubit_map: Optional[Dict[cirq.Qid, cirq.Qid]] = None,
|
|
86
90
|
measurement_key_map: Optional[Dict[str, str]] = None,
|
|
87
91
|
param_resolver: Optional[study.ParamResolverOrSimilarType] = None,
|
|
88
92
|
repetition_ids: Optional[Sequence[str]] = None,
|
|
89
93
|
parent_path: Tuple[str, ...] = (),
|
|
90
|
-
extern_keys: FrozenSet[
|
|
91
|
-
use_repetition_ids: bool =
|
|
92
|
-
repeat_until: Optional[
|
|
94
|
+
extern_keys: FrozenSet[cirq.MeasurementKey] = frozenset(),
|
|
95
|
+
use_repetition_ids: Optional[bool] = None,
|
|
96
|
+
repeat_until: Optional[cirq.Condition] = None,
|
|
93
97
|
):
|
|
94
98
|
"""Initializes a CircuitOperation.
|
|
95
99
|
|
|
@@ -119,7 +123,9 @@ class CircuitOperation(ops.Operation):
|
|
|
119
123
|
use_repetition_ids: When True, any measurement key in the subcircuit
|
|
120
124
|
will have its path prepended with the repetition id for each
|
|
121
125
|
repetition. When False, this will not happen and the measurement
|
|
122
|
-
key will be repeated.
|
|
126
|
+
key will be repeated. The default is True, but it will be changed
|
|
127
|
+
to False in the next release. Please pass an explicit argument
|
|
128
|
+
``use_repetition_ids=True`` to preserve the current behavior.
|
|
123
129
|
repeat_until: A condition that will be tested after each iteration of
|
|
124
130
|
the subcircuit. The subcircuit will repeat until condition returns
|
|
125
131
|
True, but will always run at least once, and the measurement key
|
|
@@ -155,7 +161,19 @@ class CircuitOperation(ops.Operation):
|
|
|
155
161
|
# Ensure that the circuit is invertible if the repetitions are negative.
|
|
156
162
|
self._repetitions = repetitions
|
|
157
163
|
self._repetition_ids = None if repetition_ids is None else list(repetition_ids)
|
|
158
|
-
|
|
164
|
+
if use_repetition_ids is None:
|
|
165
|
+
if repetition_ids is None:
|
|
166
|
+
msg = (
|
|
167
|
+
"In cirq 1.6 the default value of `use_repetition_ids` will change to\n"
|
|
168
|
+
"`use_repetition_ids=False`. To make this warning go away, please pass\n"
|
|
169
|
+
"explicit `use_repetition_ids`, e.g., to preserve current behavior, use\n"
|
|
170
|
+
"\n"
|
|
171
|
+
" CircuitOperations(..., use_repetition_ids=True)"
|
|
172
|
+
)
|
|
173
|
+
warnings.warn(msg, FutureWarning)
|
|
174
|
+
self._use_repetition_ids = True
|
|
175
|
+
else:
|
|
176
|
+
self._use_repetition_ids = use_repetition_ids
|
|
159
177
|
if isinstance(self._repetitions, float):
|
|
160
178
|
if math.isclose(self._repetitions, round(self._repetitions)):
|
|
161
179
|
self._repetitions = round(self._repetitions)
|
|
@@ -200,16 +218,17 @@ class CircuitOperation(ops.Operation):
|
|
|
200
218
|
)
|
|
201
219
|
|
|
202
220
|
self._repeat_until = repeat_until
|
|
203
|
-
|
|
221
|
+
mapped_repeat_until = self._mapped_repeat_until
|
|
222
|
+
if mapped_repeat_until:
|
|
204
223
|
if self._use_repetition_ids or self._repetitions != 1:
|
|
205
224
|
raise ValueError('Cannot use repetitions with repeat_until')
|
|
206
225
|
if protocols.measurement_key_objs(self._mapped_single_loop()).isdisjoint(
|
|
207
|
-
|
|
226
|
+
mapped_repeat_until.keys
|
|
208
227
|
):
|
|
209
228
|
raise ValueError('Infinite loop: condition is not modified in subcircuit.')
|
|
210
229
|
|
|
211
230
|
@property
|
|
212
|
-
def circuit(self) ->
|
|
231
|
+
def circuit(self) -> cirq.FrozenCircuit:
|
|
213
232
|
return self._circuit
|
|
214
233
|
|
|
215
234
|
@property
|
|
@@ -225,11 +244,11 @@ class CircuitOperation(ops.Operation):
|
|
|
225
244
|
return self._use_repetition_ids
|
|
226
245
|
|
|
227
246
|
@property
|
|
228
|
-
def repeat_until(self) -> Optional[
|
|
247
|
+
def repeat_until(self) -> Optional[cirq.Condition]:
|
|
229
248
|
return self._repeat_until
|
|
230
249
|
|
|
231
250
|
@property
|
|
232
|
-
def qubit_map(self) -> Mapping[
|
|
251
|
+
def qubit_map(self) -> Mapping[cirq.Qid, cirq.Qid]:
|
|
233
252
|
return self._qubit_map
|
|
234
253
|
|
|
235
254
|
@property
|
|
@@ -244,14 +263,14 @@ class CircuitOperation(ops.Operation):
|
|
|
244
263
|
def parent_path(self) -> Tuple[str, ...]:
|
|
245
264
|
return self._parent_path
|
|
246
265
|
|
|
247
|
-
def base_operation(self) ->
|
|
266
|
+
def base_operation(self) -> cirq.CircuitOperation:
|
|
248
267
|
"""Returns a copy of this operation with only the wrapped circuit.
|
|
249
268
|
|
|
250
269
|
Key and qubit mappings, parameter values, and repetitions are not copied.
|
|
251
270
|
"""
|
|
252
271
|
return CircuitOperation(self.circuit)
|
|
253
272
|
|
|
254
|
-
def replace(self, **changes) ->
|
|
273
|
+
def replace(self, **changes) -> cirq.CircuitOperation:
|
|
255
274
|
"""Returns a copy of this operation with the specified changes."""
|
|
256
275
|
kwargs = {
|
|
257
276
|
'circuit': self.circuit,
|
|
@@ -266,7 +285,7 @@ class CircuitOperation(ops.Operation):
|
|
|
266
285
|
'repeat_until': self.repeat_until,
|
|
267
286
|
**changes,
|
|
268
287
|
}
|
|
269
|
-
return CircuitOperation(**kwargs)
|
|
288
|
+
return CircuitOperation(**kwargs)
|
|
270
289
|
|
|
271
290
|
def __eq__(self, other) -> bool:
|
|
272
291
|
if not isinstance(other, type(self)):
|
|
@@ -286,7 +305,7 @@ class CircuitOperation(ops.Operation):
|
|
|
286
305
|
# Methods for getting post-mapping properties of the contained circuit.
|
|
287
306
|
|
|
288
307
|
@property
|
|
289
|
-
def qubits(self) -> Tuple[
|
|
308
|
+
def qubits(self) -> Tuple[cirq.Qid, ...]:
|
|
290
309
|
"""Returns the qubits operated on by this object."""
|
|
291
310
|
ordered_qubits = ops.QubitOrder.DEFAULT.order_for(self.circuit.all_qubits())
|
|
292
311
|
return tuple(self.qubit_map.get(q, q) for q in ordered_qubits)
|
|
@@ -312,7 +331,7 @@ class CircuitOperation(ops.Operation):
|
|
|
312
331
|
raise ValueError('Cannot unroll circuit due to nondeterministic repetitions')
|
|
313
332
|
|
|
314
333
|
@cached_property
|
|
315
|
-
def _measurement_key_objs(self) -> FrozenSet[
|
|
334
|
+
def _measurement_key_objs(self) -> FrozenSet[cirq.MeasurementKey]:
|
|
316
335
|
circuit_keys = protocols.measurement_key_objs(self.circuit)
|
|
317
336
|
if circuit_keys and self.use_repetition_ids:
|
|
318
337
|
self._ensure_deterministic_loop_count()
|
|
@@ -330,24 +349,25 @@ class CircuitOperation(ops.Operation):
|
|
|
330
349
|
for key in circuit_keys
|
|
331
350
|
)
|
|
332
351
|
|
|
333
|
-
def _measurement_key_objs_(self) -> FrozenSet[
|
|
352
|
+
def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
|
|
334
353
|
return self._measurement_key_objs
|
|
335
354
|
|
|
336
355
|
def _measurement_key_names_(self) -> FrozenSet[str]:
|
|
337
356
|
return frozenset(str(key) for key in self._measurement_key_objs_())
|
|
338
357
|
|
|
339
358
|
@cached_property
|
|
340
|
-
def _control_keys(self) -> FrozenSet[
|
|
359
|
+
def _control_keys(self) -> FrozenSet[cirq.MeasurementKey]:
|
|
341
360
|
keys = (
|
|
342
361
|
frozenset()
|
|
343
362
|
if not protocols.control_keys(self.circuit)
|
|
344
363
|
else protocols.control_keys(self._mapped_single_loop())
|
|
345
364
|
)
|
|
346
|
-
|
|
347
|
-
|
|
365
|
+
mapped_repeat_until = self._mapped_repeat_until
|
|
366
|
+
if mapped_repeat_until is not None:
|
|
367
|
+
keys |= frozenset(mapped_repeat_until.keys) - self._measurement_key_objs_()
|
|
348
368
|
return keys
|
|
349
369
|
|
|
350
|
-
def _control_keys_(self) -> FrozenSet[
|
|
370
|
+
def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
|
|
351
371
|
return self._control_keys
|
|
352
372
|
|
|
353
373
|
def _is_parameterized_(self) -> bool:
|
|
@@ -358,14 +378,11 @@ class CircuitOperation(ops.Operation):
|
|
|
358
378
|
|
|
359
379
|
def _parameter_names_generator(self) -> Iterator[str]:
|
|
360
380
|
yield from protocols.parameter_names(self.repetitions)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
protocols.resolve_parameters(symbol, self.param_resolver, recursive=False)
|
|
364
|
-
):
|
|
365
|
-
yield name
|
|
381
|
+
yield from protocols.parameter_names(self._mapped_repeat_until)
|
|
382
|
+
yield from protocols.parameter_names(self._mapped_any_loop)
|
|
366
383
|
|
|
367
384
|
@cached_property
|
|
368
|
-
def _mapped_any_loop(self) ->
|
|
385
|
+
def _mapped_any_loop(self) -> cirq.Circuit:
|
|
369
386
|
circuit = self.circuit.unfreeze()
|
|
370
387
|
if self.qubit_map:
|
|
371
388
|
circuit = circuit.transform_qubits(lambda q: self.qubit_map.get(q, q))
|
|
@@ -377,7 +394,7 @@ class CircuitOperation(ops.Operation):
|
|
|
377
394
|
circuit = protocols.resolve_parameters(circuit, self.param_resolver, recursive=False)
|
|
378
395
|
return circuit.unfreeze(copy=False)
|
|
379
396
|
|
|
380
|
-
def _mapped_single_loop(self, repetition_id: Optional[str] = None) ->
|
|
397
|
+
def _mapped_single_loop(self, repetition_id: Optional[str] = None) -> cirq.Circuit:
|
|
381
398
|
circuit = self._mapped_any_loop
|
|
382
399
|
if repetition_id:
|
|
383
400
|
circuit = protocols.with_rescoped_keys(circuit, (repetition_id,))
|
|
@@ -385,7 +402,27 @@ class CircuitOperation(ops.Operation):
|
|
|
385
402
|
circuit, self.parent_path, bindable_keys=self._extern_keys
|
|
386
403
|
)
|
|
387
404
|
|
|
388
|
-
|
|
405
|
+
@cached_property
|
|
406
|
+
def _mapped_repeat_until(self) -> Optional[cirq.Condition]:
|
|
407
|
+
"""Applies measurement_key_map, param_resolver, and current scope to repeat_until."""
|
|
408
|
+
repeat_until = self.repeat_until
|
|
409
|
+
if not repeat_until:
|
|
410
|
+
return repeat_until
|
|
411
|
+
if self.measurement_key_map:
|
|
412
|
+
repeat_until = protocols.with_measurement_key_mapping(
|
|
413
|
+
repeat_until, self.measurement_key_map
|
|
414
|
+
)
|
|
415
|
+
if self.param_resolver:
|
|
416
|
+
repeat_until = protocols.resolve_parameters(
|
|
417
|
+
repeat_until, self.param_resolver, recursive=False
|
|
418
|
+
)
|
|
419
|
+
return protocols.with_rescoped_keys(
|
|
420
|
+
repeat_until,
|
|
421
|
+
self.parent_path,
|
|
422
|
+
bindable_keys=self._extern_keys | self._measurement_key_objs,
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
def mapped_circuit(self, deep: bool = False) -> cirq.Circuit:
|
|
389
426
|
"""Applies all maps to the contained circuit and returns the result.
|
|
390
427
|
|
|
391
428
|
Args:
|
|
@@ -413,20 +450,21 @@ class CircuitOperation(ops.Operation):
|
|
|
413
450
|
)
|
|
414
451
|
return circuit
|
|
415
452
|
|
|
416
|
-
def mapped_op(self, deep: bool = False) ->
|
|
453
|
+
def mapped_op(self, deep: bool = False) -> cirq.CircuitOperation:
|
|
417
454
|
"""As `mapped_circuit`, but wraps the result in a CircuitOperation."""
|
|
418
455
|
return CircuitOperation(circuit=self.mapped_circuit(deep=deep).freeze())
|
|
419
456
|
|
|
420
|
-
def _decompose_(self) -> Iterator[
|
|
457
|
+
def _decompose_(self) -> Iterator[cirq.Operation]:
|
|
421
458
|
return self.mapped_circuit(deep=False).all_operations()
|
|
422
459
|
|
|
423
|
-
def _act_on_(self, sim_state:
|
|
424
|
-
|
|
460
|
+
def _act_on_(self, sim_state: cirq.SimulationStateBase) -> bool:
|
|
461
|
+
mapped_repeat_until = self._mapped_repeat_until
|
|
462
|
+
if mapped_repeat_until:
|
|
425
463
|
circuit = self._mapped_single_loop()
|
|
426
464
|
while True:
|
|
427
465
|
for op in circuit.all_operations():
|
|
428
466
|
protocols.act_on(op, sim_state)
|
|
429
|
-
if
|
|
467
|
+
if mapped_repeat_until.resolve(sim_state.classical_data):
|
|
430
468
|
break
|
|
431
469
|
else:
|
|
432
470
|
for op in self._decompose_():
|
|
@@ -508,6 +546,16 @@ class CircuitOperation(ops.Operation):
|
|
|
508
546
|
def __hash__(self) -> int:
|
|
509
547
|
return self._hash
|
|
510
548
|
|
|
549
|
+
def __getstate__(self) -> Dict[str, Any]:
|
|
550
|
+
# clear cached hash value when pickling, see #6674
|
|
551
|
+
state = self.__dict__
|
|
552
|
+
# cached_property stores value in the property-named attribute
|
|
553
|
+
hash_attr = "_hash"
|
|
554
|
+
if hash_attr in state:
|
|
555
|
+
state = state.copy()
|
|
556
|
+
del state[hash_attr]
|
|
557
|
+
return state
|
|
558
|
+
|
|
511
559
|
def _json_dict_(self):
|
|
512
560
|
resp = {
|
|
513
561
|
'circuit': self.circuit,
|
|
@@ -556,7 +604,7 @@ class CircuitOperation(ops.Operation):
|
|
|
556
604
|
|
|
557
605
|
def repeat(
|
|
558
606
|
self, repetitions: Optional[IntParam] = None, repetition_ids: Optional[Sequence[str]] = None
|
|
559
|
-
) ->
|
|
607
|
+
) -> CircuitOperation:
|
|
560
608
|
"""Returns a copy of this operation repeated 'repetitions' times.
|
|
561
609
|
Each repetition instance will be identified by a single repetition_id.
|
|
562
610
|
|
|
@@ -608,7 +656,7 @@ class CircuitOperation(ops.Operation):
|
|
|
608
656
|
final_repetitions = protocols.mul(self.repetitions, repetitions)
|
|
609
657
|
return self.replace(repetitions=final_repetitions, repetition_ids=repetition_ids)
|
|
610
658
|
|
|
611
|
-
def __pow__(self, power: IntParam) ->
|
|
659
|
+
def __pow__(self, power: IntParam) -> cirq.CircuitOperation:
|
|
612
660
|
return self.repeat(power)
|
|
613
661
|
|
|
614
662
|
def _with_key_path_(self, path: Tuple[str, ...]):
|
|
@@ -618,7 +666,7 @@ class CircuitOperation(ops.Operation):
|
|
|
618
666
|
return self.replace(parent_path=prefix + self.parent_path)
|
|
619
667
|
|
|
620
668
|
def _with_rescoped_keys_(
|
|
621
|
-
self, path: Tuple[str, ...], bindable_keys: FrozenSet[
|
|
669
|
+
self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
|
|
622
670
|
):
|
|
623
671
|
# The following line prevents binding to measurement keys in previous repeated subcircuits
|
|
624
672
|
# "just because their repetition ids matched". If we eventually decide to change that
|
|
@@ -642,7 +690,7 @@ class CircuitOperation(ops.Operation):
|
|
|
642
690
|
"""
|
|
643
691
|
return self._with_key_path_(path)
|
|
644
692
|
|
|
645
|
-
def with_repetition_ids(self, repetition_ids: List[str]) ->
|
|
693
|
+
def with_repetition_ids(self, repetition_ids: List[str]) -> cirq.CircuitOperation:
|
|
646
694
|
"""Returns a copy of this `CircuitOperation` with the given repetition IDs.
|
|
647
695
|
|
|
648
696
|
Args:
|
|
@@ -655,8 +703,8 @@ class CircuitOperation(ops.Operation):
|
|
|
655
703
|
return self.replace(repetition_ids=repetition_ids)
|
|
656
704
|
|
|
657
705
|
def with_qubit_mapping(
|
|
658
|
-
self, qubit_map: Union[Mapping[
|
|
659
|
-
) ->
|
|
706
|
+
self, qubit_map: Union[Mapping[cirq.Qid, cirq.Qid], Callable[[cirq.Qid], cirq.Qid]]
|
|
707
|
+
) -> cirq.CircuitOperation:
|
|
660
708
|
"""Returns a copy of this operation with an updated qubit mapping.
|
|
661
709
|
|
|
662
710
|
Users should pass either 'qubit_map' or 'transform' to this method.
|
|
@@ -677,7 +725,7 @@ class CircuitOperation(ops.Operation):
|
|
|
677
725
|
if callable(qubit_map):
|
|
678
726
|
transform = qubit_map
|
|
679
727
|
elif isinstance(qubit_map, dict):
|
|
680
|
-
transform = lambda q: qubit_map.get(q, q)
|
|
728
|
+
transform = lambda q: qubit_map.get(q, q)
|
|
681
729
|
else:
|
|
682
730
|
raise TypeError('qubit_map must be a function or dict mapping qubits to qubits.')
|
|
683
731
|
new_map = {}
|
|
@@ -695,7 +743,7 @@ class CircuitOperation(ops.Operation):
|
|
|
695
743
|
)
|
|
696
744
|
return new_op
|
|
697
745
|
|
|
698
|
-
def with_qubits(self, *new_qubits:
|
|
746
|
+
def with_qubits(self, *new_qubits: cirq.Qid) -> cirq.CircuitOperation:
|
|
699
747
|
"""Returns a copy of this operation with an updated qubit mapping.
|
|
700
748
|
|
|
701
749
|
Args:
|
|
@@ -715,7 +763,7 @@ class CircuitOperation(ops.Operation):
|
|
|
715
763
|
raise ValueError(f'Expected {expected} qubits, got {len(new_qubits)}.')
|
|
716
764
|
return self.with_qubit_mapping(dict(zip(self.qubits, new_qubits)))
|
|
717
765
|
|
|
718
|
-
def with_measurement_key_mapping(self, key_map: Mapping[str, str]) ->
|
|
766
|
+
def with_measurement_key_mapping(self, key_map: Mapping[str, str]) -> cirq.CircuitOperation:
|
|
719
767
|
"""Returns a copy of this operation with an updated key mapping.
|
|
720
768
|
|
|
721
769
|
Args:
|
|
@@ -749,12 +797,12 @@ class CircuitOperation(ops.Operation):
|
|
|
749
797
|
)
|
|
750
798
|
return new_op
|
|
751
799
|
|
|
752
|
-
def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]) ->
|
|
800
|
+
def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]) -> cirq.CircuitOperation:
|
|
753
801
|
return self.with_measurement_key_mapping(key_map)
|
|
754
802
|
|
|
755
803
|
def with_params(
|
|
756
|
-
self, param_values:
|
|
757
|
-
) ->
|
|
804
|
+
self, param_values: cirq.ParamResolverOrSimilarType, recursive: bool = False
|
|
805
|
+
) -> cirq.CircuitOperation:
|
|
758
806
|
"""Returns a copy of this operation with an updated ParamResolver.
|
|
759
807
|
|
|
760
808
|
Any existing parameter mappings will have their values updated given
|
|
@@ -780,7 +828,9 @@ class CircuitOperation(ops.Operation):
|
|
|
780
828
|
by param_values.
|
|
781
829
|
"""
|
|
782
830
|
new_params = {}
|
|
783
|
-
for k in protocols.parameter_symbols(self.circuit)
|
|
831
|
+
for k in protocols.parameter_symbols(self.circuit) | protocols.parameter_symbols(
|
|
832
|
+
self.repeat_until
|
|
833
|
+
):
|
|
784
834
|
v = self.param_resolver.value_of(k, recursive=False)
|
|
785
835
|
v = protocols.resolve_parameters(v, param_values, recursive=recursive)
|
|
786
836
|
if v != k:
|
|
@@ -788,8 +838,8 @@ class CircuitOperation(ops.Operation):
|
|
|
788
838
|
return self.replace(param_resolver=new_params)
|
|
789
839
|
|
|
790
840
|
def _resolve_parameters_(
|
|
791
|
-
self, resolver:
|
|
792
|
-
) ->
|
|
841
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
842
|
+
) -> cirq.CircuitOperation:
|
|
793
843
|
resolved = self.with_params(resolver.param_dict, recursive)
|
|
794
844
|
# repetitions can resolve to a float, but this is ok since constructor converts to
|
|
795
845
|
# nearby int.
|
|
@@ -168,7 +168,7 @@ def test_with_qubits():
|
|
|
168
168
|
|
|
169
169
|
assert op_base.with_qubit_mapping({a: d, b: c, d: a}) == op_with_qubits
|
|
170
170
|
|
|
171
|
-
def map_fn(qubit:
|
|
171
|
+
def map_fn(qubit: cirq.Qid) -> cirq.Qid:
|
|
172
172
|
if qubit == a:
|
|
173
173
|
return d
|
|
174
174
|
if qubit == b:
|
|
@@ -327,9 +327,33 @@ def test_repeat(add_measurements: bool, use_default_ids_for_initial_rep: bool) -
|
|
|
327
327
|
_ = op_base.repeat()
|
|
328
328
|
|
|
329
329
|
with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
|
|
330
|
-
_ = op_base.repeat(1.3)
|
|
331
|
-
assert op_base.repeat(3.00000000001).repetitions == 3
|
|
332
|
-
assert op_base.repeat(2.99999999999).repetitions == 3
|
|
330
|
+
_ = op_base.repeat(1.3)
|
|
331
|
+
assert op_base.repeat(3.00000000001).repetitions == 3
|
|
332
|
+
assert op_base.repeat(2.99999999999).repetitions == 3
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# TODO: #7232 - enable and fix immediately after the 1.5.0 release
|
|
336
|
+
@pytest.mark.xfail(reason='broken by rollback of use_repetition_ids for #7232')
|
|
337
|
+
def test_replace_repetition_ids() -> None:
|
|
338
|
+
a, b = cirq.LineQubit.range(2)
|
|
339
|
+
circuit = cirq.Circuit(cirq.H(a), cirq.CX(a, b), cirq.M(b, key='mb'), cirq.M(a, key='ma'))
|
|
340
|
+
op = cirq.CircuitOperation(circuit.freeze())
|
|
341
|
+
assert op.repetitions == 1
|
|
342
|
+
assert not op.use_repetition_ids
|
|
343
|
+
|
|
344
|
+
op2 = op.replace(repetitions=2)
|
|
345
|
+
assert op2.repetitions == 2
|
|
346
|
+
assert not op2.use_repetition_ids
|
|
347
|
+
|
|
348
|
+
op3 = op.replace(repetitions=3, repetition_ids=None)
|
|
349
|
+
assert op3.repetitions == 3
|
|
350
|
+
assert not op3.use_repetition_ids
|
|
351
|
+
|
|
352
|
+
# Passing `repetition_ids` will also enable `use_repetition_ids`
|
|
353
|
+
op4 = op.replace(repetitions=4, repetition_ids=['a', 'b', 'c', 'd'])
|
|
354
|
+
assert op4.repetitions == 4
|
|
355
|
+
assert op4.use_repetition_ids
|
|
356
|
+
assert op4.repetition_ids == ['a', 'b', 'c', 'd']
|
|
333
357
|
|
|
334
358
|
|
|
335
359
|
@pytest.mark.parametrize('add_measurements', [True, False])
|
|
@@ -1204,4 +1228,61 @@ def test_repeat_until_error():
|
|
|
1204
1228
|
)
|
|
1205
1229
|
|
|
1206
1230
|
|
|
1231
|
+
def test_repeat_until_protocols():
|
|
1232
|
+
q = cirq.LineQubit(0)
|
|
1233
|
+
op = cirq.CircuitOperation(
|
|
1234
|
+
cirq.FrozenCircuit(cirq.H(q) ** sympy.Symbol('p'), cirq.measure(q, key='a')),
|
|
1235
|
+
repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('a'), 0)),
|
|
1236
|
+
# TODO: #7232 - remove immediately after the 1.5.0 release
|
|
1237
|
+
use_repetition_ids=False,
|
|
1238
|
+
)
|
|
1239
|
+
scoped = cirq.with_rescoped_keys(op, ('0',))
|
|
1240
|
+
# Ensure the _repeat_until has been mapped, the measurement has been mapped to the same key,
|
|
1241
|
+
# and the control keys of the subcircuit is empty (because the control key of the condition is
|
|
1242
|
+
# bound to the measurement).
|
|
1243
|
+
assert scoped._mapped_repeat_until.keys == (cirq.MeasurementKey('a', ('0',)),)
|
|
1244
|
+
assert cirq.measurement_key_objs(scoped) == {cirq.MeasurementKey('a', ('0',))}
|
|
1245
|
+
assert not cirq.control_keys(scoped)
|
|
1246
|
+
mapped = cirq.with_measurement_key_mapping(scoped, {'a': 'b'})
|
|
1247
|
+
assert mapped._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('0',)),)
|
|
1248
|
+
assert cirq.measurement_key_objs(mapped) == {cirq.MeasurementKey('b', ('0',))}
|
|
1249
|
+
assert not cirq.control_keys(mapped)
|
|
1250
|
+
prefixed = cirq.with_key_path_prefix(mapped, ('1',))
|
|
1251
|
+
assert prefixed._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('1', '0')),)
|
|
1252
|
+
assert cirq.measurement_key_objs(prefixed) == {cirq.MeasurementKey('b', ('1', '0'))}
|
|
1253
|
+
assert not cirq.control_keys(prefixed)
|
|
1254
|
+
setpath = cirq.with_key_path(prefixed, ('2',))
|
|
1255
|
+
assert setpath._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
|
|
1256
|
+
assert cirq.measurement_key_objs(setpath) == {cirq.MeasurementKey('b', ('2',))}
|
|
1257
|
+
assert not cirq.control_keys(setpath)
|
|
1258
|
+
resolved = cirq.resolve_parameters(setpath, {'p': 1})
|
|
1259
|
+
assert resolved._mapped_repeat_until.keys == (cirq.MeasurementKey('b', ('2',)),)
|
|
1260
|
+
assert cirq.measurement_key_objs(resolved) == {cirq.MeasurementKey('b', ('2',))}
|
|
1261
|
+
assert not cirq.control_keys(resolved)
|
|
1262
|
+
|
|
1263
|
+
|
|
1264
|
+
def test_inner_repeat_until_simulate():
|
|
1265
|
+
sim = cirq.Simulator()
|
|
1266
|
+
q = cirq.LineQubit(0)
|
|
1267
|
+
inner_loop = cirq.CircuitOperation(
|
|
1268
|
+
cirq.FrozenCircuit(cirq.H(q), cirq.measure(q, key="inner_loop")),
|
|
1269
|
+
repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol("inner_loop"), 0)),
|
|
1270
|
+
# TODO: #7232 - remove immediately after the 1.5.0 release
|
|
1271
|
+
use_repetition_ids=False,
|
|
1272
|
+
)
|
|
1273
|
+
outer_loop = cirq.Circuit(inner_loop, cirq.X(q), cirq.measure(q, key="outer_loop"))
|
|
1274
|
+
circuit = cirq.Circuit(
|
|
1275
|
+
cirq.CircuitOperation(
|
|
1276
|
+
cirq.FrozenCircuit(outer_loop), repetitions=2, use_repetition_ids=True
|
|
1277
|
+
)
|
|
1278
|
+
)
|
|
1279
|
+
result = sim.run(circuit, repetitions=1)
|
|
1280
|
+
assert all(len(v) == 1 and v[0] == 1 for v in result.records['0:inner_loop'][0][:-1])
|
|
1281
|
+
assert result.records['0:inner_loop'][0][-1] == [0]
|
|
1282
|
+
assert result.records['0:outer_loop'] == [[[1]]]
|
|
1283
|
+
assert all(len(v) == 1 and v[0] == 1 for v in result.records['1:inner_loop'][0][:-1])
|
|
1284
|
+
assert result.records['1:inner_loop'][0][-1] == [0]
|
|
1285
|
+
assert result.records['1:outer_loop'] == [[[1]]]
|
|
1286
|
+
|
|
1287
|
+
|
|
1207
1288
|
# TODO: Operation has a "gate" property. What is this for a CircuitOperation?
|