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
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import re
|
|
16
16
|
from typing import Optional
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
import ply.lex as lex
|
|
19
19
|
|
|
20
20
|
from cirq.contrib.qasm_import.exception import QasmException
|
|
@@ -24,20 +24,30 @@ class QasmLexer:
|
|
|
24
24
|
def __init__(self):
|
|
25
25
|
self.lex = lex.lex(object=self, debug=False)
|
|
26
26
|
|
|
27
|
-
literals = "{}[]()
|
|
27
|
+
literals = "{}[]();,+/*-^="
|
|
28
28
|
|
|
29
29
|
reserved = {
|
|
30
|
+
'qubit': 'QUBIT',
|
|
30
31
|
'qreg': 'QREG',
|
|
32
|
+
'bit': 'BIT',
|
|
31
33
|
'creg': 'CREG',
|
|
32
34
|
'measure': 'MEASURE',
|
|
35
|
+
'reset': 'RESET',
|
|
36
|
+
'gate': 'GATE',
|
|
33
37
|
'if': 'IF',
|
|
34
|
-
'
|
|
35
|
-
'==': 'EQ',
|
|
38
|
+
'pi': 'PI',
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
tokens = [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
tokens = [
|
|
42
|
+
'FORMAT_SPEC',
|
|
43
|
+
'NUMBER',
|
|
44
|
+
'NATURAL_NUMBER',
|
|
45
|
+
'STDGATESINC',
|
|
46
|
+
'QELIBINC',
|
|
47
|
+
'ID',
|
|
48
|
+
'ARROW',
|
|
49
|
+
'EQ',
|
|
50
|
+
] + list(reserved.values())
|
|
41
51
|
|
|
42
52
|
def t_newline(self, t):
|
|
43
53
|
r"""\n+"""
|
|
@@ -45,11 +55,6 @@ class QasmLexer:
|
|
|
45
55
|
|
|
46
56
|
t_ignore = ' \t'
|
|
47
57
|
|
|
48
|
-
def t_PI(self, t):
|
|
49
|
-
r"""pi"""
|
|
50
|
-
t.value = np.pi
|
|
51
|
-
return t
|
|
52
|
-
|
|
53
58
|
# all numbers except NATURAL_NUMBERs:
|
|
54
59
|
# it's useful to have this separation to be able to handle indices
|
|
55
60
|
# separately. In case of the parameter expressions, we are "OR"-ing
|
|
@@ -83,20 +88,8 @@ class QasmLexer:
|
|
|
83
88
|
r"""include(\s+)"qelib1.inc";"""
|
|
84
89
|
return t
|
|
85
90
|
|
|
86
|
-
def
|
|
87
|
-
r"""
|
|
88
|
-
return t
|
|
89
|
-
|
|
90
|
-
def t_CREG(self, t):
|
|
91
|
-
r"""creg"""
|
|
92
|
-
return t
|
|
93
|
-
|
|
94
|
-
def t_MEASURE(self, t):
|
|
95
|
-
r"""measure"""
|
|
96
|
-
return t
|
|
97
|
-
|
|
98
|
-
def t_IF(self, t):
|
|
99
|
-
r"""if"""
|
|
91
|
+
def t_STDGATESINC(self, t):
|
|
92
|
+
r"""include(\s+)"stdgates.inc";"""
|
|
100
93
|
return t
|
|
101
94
|
|
|
102
95
|
def t_ARROW(self, t):
|
|
@@ -109,6 +102,8 @@ class QasmLexer:
|
|
|
109
102
|
|
|
110
103
|
def t_ID(self, t):
|
|
111
104
|
r"""[a-zA-Z][a-zA-Z\d_]*"""
|
|
105
|
+
if t.value in QasmLexer.reserved:
|
|
106
|
+
t.type = QasmLexer.reserved[t.value]
|
|
112
107
|
return t
|
|
113
108
|
|
|
114
109
|
def t_COMMENT(self, t):
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import pytest
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
from cirq.contrib.qasm_import import QasmException
|
|
18
18
|
from cirq.contrib.qasm_import._lexer import QasmLexer
|
|
19
19
|
|
|
@@ -103,12 +103,28 @@ def test_numbers(number: str):
|
|
|
103
103
|
assert token.value == float(number)
|
|
104
104
|
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
@pytest.mark.parametrize('token', QasmLexer.reserved.keys())
|
|
107
|
+
def test_keywords(token):
|
|
107
108
|
lexer = QasmLexer()
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
assert
|
|
109
|
+
identifier = f'{token} {token}'
|
|
110
|
+
lexer.input(identifier)
|
|
111
|
+
t = lexer.token()
|
|
112
|
+
assert t.type == QasmLexer.reserved[token]
|
|
113
|
+
assert t.value == token
|
|
114
|
+
t2 = lexer.token()
|
|
115
|
+
assert t2.type == QasmLexer.reserved[token]
|
|
116
|
+
assert t2.value == token
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@pytest.mark.parametrize('token', QasmLexer.reserved.keys())
|
|
120
|
+
@pytest.mark.parametrize('separator', ['', '_'])
|
|
121
|
+
def test_identifier_starts_or_ends_with_keyword(token, separator):
|
|
122
|
+
lexer = QasmLexer()
|
|
123
|
+
identifier = f'{token}{separator}{token}'
|
|
124
|
+
lexer.input(identifier)
|
|
125
|
+
t = lexer.token()
|
|
126
|
+
assert t.type == "ID"
|
|
127
|
+
assert t.value == identifier
|
|
112
128
|
|
|
113
129
|
|
|
114
130
|
def test_qreg():
|
|
@@ -159,6 +175,74 @@ def test_creg():
|
|
|
159
175
|
assert token.value == ";"
|
|
160
176
|
|
|
161
177
|
|
|
178
|
+
def test_custom_gate():
|
|
179
|
+
lexer = QasmLexer()
|
|
180
|
+
lexer.input('gate name(param1,param2) q1, q2 {X(q1)}')
|
|
181
|
+
token = lexer.token()
|
|
182
|
+
assert token.type == "GATE"
|
|
183
|
+
assert token.value == "gate"
|
|
184
|
+
|
|
185
|
+
token = lexer.token()
|
|
186
|
+
assert token.type == "ID"
|
|
187
|
+
assert token.value == "name"
|
|
188
|
+
|
|
189
|
+
token = lexer.token()
|
|
190
|
+
assert token.type == "("
|
|
191
|
+
assert token.value == "("
|
|
192
|
+
|
|
193
|
+
token = lexer.token()
|
|
194
|
+
assert token.type == "ID"
|
|
195
|
+
assert token.value == "param1"
|
|
196
|
+
|
|
197
|
+
token = lexer.token()
|
|
198
|
+
assert token.type == ","
|
|
199
|
+
assert token.value == ","
|
|
200
|
+
|
|
201
|
+
token = lexer.token()
|
|
202
|
+
assert token.type == "ID"
|
|
203
|
+
assert token.value == "param2"
|
|
204
|
+
|
|
205
|
+
token = lexer.token()
|
|
206
|
+
assert token.type == ")"
|
|
207
|
+
assert token.value == ")"
|
|
208
|
+
|
|
209
|
+
token = lexer.token()
|
|
210
|
+
assert token.type == "ID"
|
|
211
|
+
assert token.value == "q1"
|
|
212
|
+
|
|
213
|
+
token = lexer.token()
|
|
214
|
+
assert token.type == ","
|
|
215
|
+
assert token.value == ","
|
|
216
|
+
|
|
217
|
+
token = lexer.token()
|
|
218
|
+
assert token.type == "ID"
|
|
219
|
+
assert token.value == "q2"
|
|
220
|
+
|
|
221
|
+
token = lexer.token()
|
|
222
|
+
assert token.type == "{"
|
|
223
|
+
assert token.value == "{"
|
|
224
|
+
|
|
225
|
+
token = lexer.token()
|
|
226
|
+
assert token.type == "ID"
|
|
227
|
+
assert token.value == "X"
|
|
228
|
+
|
|
229
|
+
token = lexer.token()
|
|
230
|
+
assert token.type == "("
|
|
231
|
+
assert token.value == "("
|
|
232
|
+
|
|
233
|
+
token = lexer.token()
|
|
234
|
+
assert token.type == "ID"
|
|
235
|
+
assert token.value == "q1"
|
|
236
|
+
|
|
237
|
+
token = lexer.token()
|
|
238
|
+
assert token.type == ")"
|
|
239
|
+
assert token.value == ")"
|
|
240
|
+
|
|
241
|
+
token = lexer.token()
|
|
242
|
+
assert token.type == "}"
|
|
243
|
+
assert token.value == "}"
|
|
244
|
+
|
|
245
|
+
|
|
162
246
|
def test_error():
|
|
163
247
|
lexer = QasmLexer()
|
|
164
248
|
lexer.input('θ')
|
|
@@ -12,20 +12,32 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import dataclasses
|
|
15
16
|
import functools
|
|
16
17
|
import operator
|
|
17
|
-
from typing import
|
|
18
|
+
from typing import (
|
|
19
|
+
Any,
|
|
20
|
+
Callable,
|
|
21
|
+
cast,
|
|
22
|
+
Dict,
|
|
23
|
+
Iterable,
|
|
24
|
+
List,
|
|
25
|
+
Optional,
|
|
26
|
+
Set,
|
|
27
|
+
Tuple,
|
|
28
|
+
TYPE_CHECKING,
|
|
29
|
+
Union,
|
|
30
|
+
)
|
|
18
31
|
|
|
19
32
|
import numpy as np
|
|
20
33
|
import sympy
|
|
21
34
|
from ply import yacc
|
|
22
35
|
|
|
23
|
-
from cirq import
|
|
36
|
+
from cirq import Circuit, CircuitOperation, CX, FrozenCircuit, NamedQubit, ops, value
|
|
24
37
|
from cirq.circuits.qasm_output import QasmUGate
|
|
25
38
|
from cirq.contrib.qasm_import._lexer import QasmLexer
|
|
26
39
|
from cirq.contrib.qasm_import.exception import QasmException
|
|
27
40
|
|
|
28
|
-
|
|
29
41
|
if TYPE_CHECKING:
|
|
30
42
|
import cirq
|
|
31
43
|
|
|
@@ -47,6 +59,31 @@ class Qasm:
|
|
|
47
59
|
self.circuit = c
|
|
48
60
|
|
|
49
61
|
|
|
62
|
+
def _generate_op_qubits(args: List[List[ops.Qid]], lineno: int) -> List[List[ops.Qid]]:
|
|
63
|
+
"""Generates the Cirq qubits for an operation from the OpenQASM qregs.
|
|
64
|
+
|
|
65
|
+
OpenQASM gates can be applied on single qubits and qubit registers.
|
|
66
|
+
We represent single qubits as registers of size 1.
|
|
67
|
+
Based on the OpenQASM spec (https://arxiv.org/abs/1707.03429),
|
|
68
|
+
single qubit arguments can be mixed with qubit registers.
|
|
69
|
+
Given quantum registers of length reg_size and single qubits are both
|
|
70
|
+
used as arguments, we generate reg_size GateOperations via iterating
|
|
71
|
+
through each qubit of the registers 0 to n-1 and use the same one
|
|
72
|
+
qubit from the "single-qubit registers" for each operation."""
|
|
73
|
+
reg_sizes = np.unique([len(reg) for reg in args])
|
|
74
|
+
if len(reg_sizes) > 2 or (len(reg_sizes) > 1 and reg_sizes[0] != 1):
|
|
75
|
+
raise QasmException(
|
|
76
|
+
f"Non matching quantum registers of length {reg_sizes} at line {lineno}"
|
|
77
|
+
)
|
|
78
|
+
op_qubits_gen = functools.reduce(
|
|
79
|
+
cast(Callable[[List['cirq.Qid'], List['cirq.Qid']], List['cirq.Qid']], np.broadcast), args
|
|
80
|
+
)
|
|
81
|
+
op_qubits = [[q] if isinstance(q, ops.Qid) else q for q in op_qubits_gen]
|
|
82
|
+
if any(len(set(q)) < len(q) for q in op_qubits):
|
|
83
|
+
raise QasmException(f"Overlapping qubits in arguments at line {lineno}")
|
|
84
|
+
return op_qubits
|
|
85
|
+
|
|
86
|
+
|
|
50
87
|
class QasmGateStatement:
|
|
51
88
|
"""Specifies how to convert a call to an OpenQASM gate
|
|
52
89
|
to a list of `cirq.GateOperation`s.
|
|
@@ -87,7 +124,7 @@ class QasmGateStatement:
|
|
|
87
124
|
f"got: {len(args)}, at line {lineno}"
|
|
88
125
|
)
|
|
89
126
|
|
|
90
|
-
def _validate_params(self, params: List[
|
|
127
|
+
def _validate_params(self, params: List[value.TParamVal], lineno: int):
|
|
91
128
|
if len(params) != self.num_params:
|
|
92
129
|
raise QasmException(
|
|
93
130
|
f"{self.qasm_gate} takes {self.num_params} parameter(s), "
|
|
@@ -95,41 +132,47 @@ class QasmGateStatement:
|
|
|
95
132
|
)
|
|
96
133
|
|
|
97
134
|
def on(
|
|
98
|
-
self, params: List[
|
|
135
|
+
self, params: List[value.TParamVal], args: List[List[ops.Qid]], lineno: int
|
|
99
136
|
) -> Iterable[ops.Operation]:
|
|
100
137
|
self._validate_args(args, lineno)
|
|
101
138
|
self._validate_params(params, lineno)
|
|
102
139
|
|
|
103
|
-
reg_sizes = np.unique([len(reg) for reg in args])
|
|
104
|
-
if len(reg_sizes) > 2 or (len(reg_sizes) > 1 and reg_sizes[0] != 1):
|
|
105
|
-
raise QasmException(
|
|
106
|
-
f"Non matching quantum registers of length {reg_sizes} at line {lineno}"
|
|
107
|
-
)
|
|
108
|
-
|
|
109
140
|
# the actual gate we'll apply the arguments to might be a parameterized
|
|
110
141
|
# or non-parameterized gate
|
|
111
142
|
final_gate: ops.Gate = (
|
|
112
143
|
self.cirq_gate if isinstance(self.cirq_gate, ops.Gate) else self.cirq_gate(params)
|
|
113
144
|
)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
145
|
+
for qubits in _generate_op_qubits(args, lineno):
|
|
146
|
+
yield final_gate.on(*qubits)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@dataclasses.dataclass
|
|
150
|
+
class CustomGate:
|
|
151
|
+
"""Represents an invocation of a user-defined gate.
|
|
152
|
+
|
|
153
|
+
The custom gate definition is encoded here as a `FrozenCircuit`, and the
|
|
154
|
+
arguments (params and qubits) of the specific invocation of that gate are
|
|
155
|
+
stored here too. When `on` is called, we create a CircuitOperation, mapping
|
|
156
|
+
the qubits and params to the values provided."""
|
|
157
|
+
|
|
158
|
+
name: str
|
|
159
|
+
circuit: FrozenCircuit
|
|
160
|
+
params: Tuple[str, ...]
|
|
161
|
+
qubits: Tuple[ops.Qid, ...]
|
|
162
|
+
|
|
163
|
+
def on(
|
|
164
|
+
self, params: List[value.TParamVal], args: List[List[ops.Qid]], lineno: int
|
|
165
|
+
) -> Iterable[ops.Operation]:
|
|
166
|
+
if len(params) != len(self.params):
|
|
167
|
+
raise QasmException(f"Wrong number of params for '{self.name}' at line {lineno}")
|
|
168
|
+
if len(args) != len(self.qubits):
|
|
169
|
+
raise QasmException(f"Wrong number of qregs for '{self.name}' at line {lineno}")
|
|
170
|
+
for qubits in _generate_op_qubits(args, lineno):
|
|
171
|
+
yield CircuitOperation(
|
|
172
|
+
self.circuit,
|
|
173
|
+
param_resolver={k: v for k, v in zip(self.params, params)},
|
|
174
|
+
qubit_map={k: v for k, v in zip(self.qubits, qubits)},
|
|
175
|
+
)
|
|
133
176
|
|
|
134
177
|
|
|
135
178
|
class QasmParser:
|
|
@@ -146,6 +189,18 @@ class QasmParser:
|
|
|
146
189
|
self.circuit = Circuit()
|
|
147
190
|
self.qregs: Dict[str, int] = {}
|
|
148
191
|
self.cregs: Dict[str, int] = {}
|
|
192
|
+
self.gate_set: Dict[str, Union[CustomGate, QasmGateStatement]] = {**self.basic_gates}
|
|
193
|
+
"""The gates available to use in the circuit, including those from libraries, and
|
|
194
|
+
user-defined ones."""
|
|
195
|
+
self.in_custom_gate_scope = False
|
|
196
|
+
"""This is set to True when the parser is in the middle of parsing a custom gate
|
|
197
|
+
definition."""
|
|
198
|
+
self.custom_gate_scoped_params: Set[str] = set()
|
|
199
|
+
"""The params declared within the current custom gate definition. Empty if not in
|
|
200
|
+
custom gate scope."""
|
|
201
|
+
self.custom_gate_scoped_qubits: Dict[str, ops.Qid] = {}
|
|
202
|
+
"""The qubits declared within the current custom gate definition. Empty if not in
|
|
203
|
+
custom gate scope."""
|
|
149
204
|
self.qelibinc = False
|
|
150
205
|
self.lexer = QasmLexer()
|
|
151
206
|
self.supported_format = False
|
|
@@ -243,6 +298,24 @@ class QasmParser:
|
|
|
243
298
|
'ch': QasmGateStatement(
|
|
244
299
|
qasm_gate='ch', cirq_gate=ops.ControlledGate(ops.H), num_params=0, num_args=2
|
|
245
300
|
),
|
|
301
|
+
'cu1': QasmGateStatement(
|
|
302
|
+
qasm_gate='cu1',
|
|
303
|
+
num_params=1,
|
|
304
|
+
num_args=2,
|
|
305
|
+
cirq_gate=(lambda params: ops.ControlledGate(QasmUGate(0, 0, params[0] / np.pi))),
|
|
306
|
+
),
|
|
307
|
+
'cu3': QasmGateStatement(
|
|
308
|
+
qasm_gate='cu3',
|
|
309
|
+
num_params=3,
|
|
310
|
+
num_args=2,
|
|
311
|
+
cirq_gate=(lambda params: ops.ControlledGate(QasmUGate(*[p / np.pi for p in params]))),
|
|
312
|
+
),
|
|
313
|
+
'crz': QasmGateStatement(
|
|
314
|
+
qasm_gate='crz',
|
|
315
|
+
num_params=1,
|
|
316
|
+
num_args=2,
|
|
317
|
+
cirq_gate=(lambda params: ops.ControlledGate(ops.rz(params[0]))),
|
|
318
|
+
),
|
|
246
319
|
'swap': QasmGateStatement(qasm_gate='swap', cirq_gate=ops.SWAP, num_params=0, num_args=2),
|
|
247
320
|
'cswap': QasmGateStatement(
|
|
248
321
|
qasm_gate='cswap', num_params=0, num_args=3, cirq_gate=ops.CSWAP
|
|
@@ -252,8 +325,6 @@ class QasmParser:
|
|
|
252
325
|
'tdg': QasmGateStatement(qasm_gate='tdg', num_params=0, num_args=1, cirq_gate=ops.T**-1),
|
|
253
326
|
}
|
|
254
327
|
|
|
255
|
-
all_gates = {**basic_gates, **qelib_gates}
|
|
256
|
-
|
|
257
328
|
tokens = QasmLexer.tokens
|
|
258
329
|
start = 'start'
|
|
259
330
|
|
|
@@ -270,6 +341,7 @@ class QasmParser:
|
|
|
270
341
|
|
|
271
342
|
def p_qasm_no_format_specified_error(self, p):
|
|
272
343
|
"""qasm : QELIBINC
|
|
344
|
+
| STDGATESINC
|
|
273
345
|
| circuit"""
|
|
274
346
|
if self.supported_format is False:
|
|
275
347
|
raise QasmException("Missing 'OPENQASM 2.0;' statement")
|
|
@@ -277,6 +349,13 @@ class QasmParser:
|
|
|
277
349
|
def p_qasm_include(self, p):
|
|
278
350
|
"""qasm : qasm QELIBINC"""
|
|
279
351
|
self.qelibinc = True
|
|
352
|
+
self.gate_set |= self.qelib_gates
|
|
353
|
+
p[0] = Qasm(self.supported_format, self.qelibinc, self.qregs, self.cregs, self.circuit)
|
|
354
|
+
|
|
355
|
+
def p_qasm_include_stdgates(self, p):
|
|
356
|
+
"""qasm : qasm STDGATESINC"""
|
|
357
|
+
self.qelibinc = True
|
|
358
|
+
self.gate_set |= self.qelib_gates
|
|
280
359
|
p[0] = Qasm(self.supported_format, self.qelibinc, self.qregs, self.cregs, self.circuit)
|
|
281
360
|
|
|
282
361
|
def p_qasm_circuit(self, p):
|
|
@@ -285,14 +364,16 @@ class QasmParser:
|
|
|
285
364
|
|
|
286
365
|
def p_format(self, p):
|
|
287
366
|
"""format : FORMAT_SPEC"""
|
|
288
|
-
if p[1]
|
|
367
|
+
if p[1] not in ["2.0", "3.0"]:
|
|
289
368
|
raise QasmException(
|
|
290
|
-
f"Unsupported OpenQASM version: {p[1]},
|
|
369
|
+
f"Unsupported OpenQASM version: {p[1]}, "
|
|
370
|
+
"only 2.0 and 3.0 are supported currently by Cirq"
|
|
291
371
|
)
|
|
292
372
|
|
|
293
373
|
# circuit : new_reg circuit
|
|
294
374
|
# | gate_op circuit
|
|
295
375
|
# | measurement circuit
|
|
376
|
+
# | reset circuit
|
|
296
377
|
# | if circuit
|
|
297
378
|
# | empty
|
|
298
379
|
|
|
@@ -303,6 +384,7 @@ class QasmParser:
|
|
|
303
384
|
def p_circuit_gate_or_measurement_or_if(self, p):
|
|
304
385
|
"""circuit : circuit gate_op
|
|
305
386
|
| circuit measurement
|
|
387
|
+
| circuit reset
|
|
306
388
|
| circuit if"""
|
|
307
389
|
self.circuit.append(p[2])
|
|
308
390
|
p[0] = self.circuit
|
|
@@ -311,17 +393,36 @@ class QasmParser:
|
|
|
311
393
|
"""circuit : empty"""
|
|
312
394
|
p[0] = self.circuit
|
|
313
395
|
|
|
396
|
+
def p_circuit_gate_def(self, p):
|
|
397
|
+
"""circuit : gate_def"""
|
|
398
|
+
p[0] = self.circuit
|
|
399
|
+
|
|
314
400
|
# qreg and creg
|
|
315
401
|
|
|
316
402
|
def p_new_reg(self, p):
|
|
317
403
|
"""new_reg : QREG ID '[' NATURAL_NUMBER ']' ';'
|
|
318
|
-
|
|
|
319
|
-
|
|
404
|
+
| QUBIT '[' NATURAL_NUMBER ']' ID ';'
|
|
405
|
+
| QUBIT ID ';'
|
|
406
|
+
| CREG ID '[' NATURAL_NUMBER ']' ';'
|
|
407
|
+
| BIT '[' NATURAL_NUMBER ']' ID ';'
|
|
408
|
+
| BIT ID ';'
|
|
409
|
+
"""
|
|
410
|
+
if p[1] == "qreg" or p[1] == "creg":
|
|
411
|
+
# QREG ID '[' NATURAL_NUMBER ']' ';'
|
|
412
|
+
name, length = p[2], p[4]
|
|
413
|
+
else:
|
|
414
|
+
if len(p) < 5:
|
|
415
|
+
# QUBIT ID ';' | BIT ID ';'
|
|
416
|
+
name = p[2]
|
|
417
|
+
length = 1
|
|
418
|
+
else:
|
|
419
|
+
# QUBIT '[' NATURAL_NUMBER ']' ID ';'
|
|
420
|
+
name, length = p[5], p[3]
|
|
320
421
|
if name in self.qregs.keys() or name in self.cregs.keys():
|
|
321
422
|
raise QasmException(f"{name} is already defined at line {p.lineno(2)}")
|
|
322
423
|
if length == 0:
|
|
323
424
|
raise QasmException(f"Illegal, zero-length register '{name}' at line {p.lineno(4)}")
|
|
324
|
-
if p[1] == "qreg":
|
|
425
|
+
if p[1] == "qreg" or p[1] == "qubit":
|
|
325
426
|
self.qregs[name] = length
|
|
326
427
|
else:
|
|
327
428
|
self.cregs[name] = length
|
|
@@ -340,14 +441,13 @@ class QasmParser:
|
|
|
340
441
|
self._resolve_gate_operation(args=p[5], gate=p[1], p=p, params=p[3])
|
|
341
442
|
|
|
342
443
|
def _resolve_gate_operation(
|
|
343
|
-
self, args: List[List[ops.Qid]], gate: str, p: Any, params: List[
|
|
444
|
+
self, args: List[List[ops.Qid]], gate: str, p: Any, params: List[value.TParamVal]
|
|
344
445
|
):
|
|
345
|
-
|
|
346
|
-
if gate not in gate_set.keys():
|
|
446
|
+
if gate not in self.gate_set:
|
|
347
447
|
tip = ", did you forget to include qelib1.inc?" if not self.qelibinc else ""
|
|
348
448
|
msg = f'Unknown gate "{gate}" at line {p.lineno(1)}{tip}'
|
|
349
449
|
raise QasmException(msg)
|
|
350
|
-
p[0] = gate_set[gate].on(args=args, params=params, lineno=p.lineno(1))
|
|
450
|
+
p[0] = self.gate_set[gate].on(args=args, params=params, lineno=p.lineno(1))
|
|
351
451
|
|
|
352
452
|
# params : parameter ',' params
|
|
353
453
|
# | parameter
|
|
@@ -362,7 +462,8 @@ class QasmParser:
|
|
|
362
462
|
p[0] = [p[1]]
|
|
363
463
|
|
|
364
464
|
# expr : term
|
|
365
|
-
# |
|
|
465
|
+
# | ID
|
|
466
|
+
# | func '(' expression ')'
|
|
366
467
|
# | binary_op
|
|
367
468
|
# | unary_op
|
|
368
469
|
|
|
@@ -370,6 +471,14 @@ class QasmParser:
|
|
|
370
471
|
"""expr : term"""
|
|
371
472
|
p[0] = p[1]
|
|
372
473
|
|
|
474
|
+
def p_expr_identifier(self, p):
|
|
475
|
+
"""expr : ID"""
|
|
476
|
+
if not self.in_custom_gate_scope:
|
|
477
|
+
raise QasmException(f"Parameter '{p[1]}' in line {p.lineno(1)} not supported")
|
|
478
|
+
if p[1] not in self.custom_gate_scoped_params:
|
|
479
|
+
raise QasmException(f"Undefined parameter '{p[1]}' in line {p.lineno(1)}'")
|
|
480
|
+
p[0] = sympy.Symbol(p[1])
|
|
481
|
+
|
|
373
482
|
def p_expr_parens(self, p):
|
|
374
483
|
"""expr : '(' expr ')'"""
|
|
375
484
|
p[0] = p[2]
|
|
@@ -400,10 +509,13 @@ class QasmParser:
|
|
|
400
509
|
|
|
401
510
|
def p_term(self, p):
|
|
402
511
|
"""term : NUMBER
|
|
403
|
-
| NATURAL_NUMBER
|
|
404
|
-
| PI"""
|
|
512
|
+
| NATURAL_NUMBER"""
|
|
405
513
|
p[0] = p[1]
|
|
406
514
|
|
|
515
|
+
def p_pi(self, p):
|
|
516
|
+
"""term : PI"""
|
|
517
|
+
p[0] = np.pi
|
|
518
|
+
|
|
407
519
|
# qargs : qarg ',' qargs
|
|
408
520
|
# | qarg ';'
|
|
409
521
|
|
|
@@ -422,6 +534,15 @@ class QasmParser:
|
|
|
422
534
|
def p_quantum_arg_register(self, p):
|
|
423
535
|
"""qarg : ID"""
|
|
424
536
|
reg = p[1]
|
|
537
|
+
if self.in_custom_gate_scope:
|
|
538
|
+
if reg not in self.custom_gate_scoped_qubits:
|
|
539
|
+
if reg not in self.qregs:
|
|
540
|
+
msg = f"Undefined qubit '{reg}'"
|
|
541
|
+
else:
|
|
542
|
+
msg = f"'{reg}' is a register, not a qubit"
|
|
543
|
+
raise QasmException(f"{msg} at line {p.lineno(1)}")
|
|
544
|
+
p[0] = [self.custom_gate_scoped_qubits[reg]]
|
|
545
|
+
return
|
|
425
546
|
if reg not in self.qregs.keys():
|
|
426
547
|
raise QasmException(f'Undefined quantum register "{reg}" at line {p.lineno(1)}')
|
|
427
548
|
qubits = []
|
|
@@ -450,6 +571,8 @@ class QasmParser:
|
|
|
450
571
|
"""qarg : ID '[' NATURAL_NUMBER ']'"""
|
|
451
572
|
reg = p[1]
|
|
452
573
|
idx = p[3]
|
|
574
|
+
if self.in_custom_gate_scope:
|
|
575
|
+
raise QasmException(f"Unsupported indexed qreg '{reg}[{idx}]' at line {p.lineno(1)}")
|
|
453
576
|
arg_name = self.make_name(idx, reg)
|
|
454
577
|
if reg not in self.qregs.keys():
|
|
455
578
|
raise QasmException(f'Undefined quantum register "{reg}" at line {p.lineno(1)}')
|
|
@@ -485,9 +608,14 @@ class QasmParser:
|
|
|
485
608
|
# measurement : MEASURE qarg ARROW carg
|
|
486
609
|
|
|
487
610
|
def p_measurement(self, p):
|
|
488
|
-
"""measurement : MEASURE qarg ARROW carg ';'
|
|
489
|
-
|
|
490
|
-
|
|
611
|
+
"""measurement : MEASURE qarg ARROW carg ';'
|
|
612
|
+
| carg '=' MEASURE qarg ';'"""
|
|
613
|
+
if p[1] == 'measure':
|
|
614
|
+
qreg = p[2]
|
|
615
|
+
creg = p[4]
|
|
616
|
+
else:
|
|
617
|
+
qreg = p[4]
|
|
618
|
+
creg = p[1]
|
|
491
619
|
|
|
492
620
|
if len(qreg) != len(creg):
|
|
493
621
|
raise QasmException(
|
|
@@ -499,6 +627,15 @@ class QasmParser:
|
|
|
499
627
|
ops.MeasurementGate(num_qubits=1, key=creg[i]).on(qreg[i]) for i in range(len(qreg))
|
|
500
628
|
]
|
|
501
629
|
|
|
630
|
+
# reset operations
|
|
631
|
+
# reset : RESET qarg
|
|
632
|
+
|
|
633
|
+
def p_reset(self, p):
|
|
634
|
+
"""reset : RESET qarg ';'"""
|
|
635
|
+
qreg = p[2]
|
|
636
|
+
|
|
637
|
+
p[0] = [ops.ResetChannel().on(qreg[i]) for i in range(len(qreg))]
|
|
638
|
+
|
|
502
639
|
# if operations
|
|
503
640
|
# if : IF '(' carg EQ NATURAL_NUMBER ')' ID qargs
|
|
504
641
|
|
|
@@ -514,6 +651,60 @@ class QasmParser:
|
|
|
514
651
|
ops.ClassicallyControlledOperation(conditions=conditions, sub_operation=tuple(p[7])[0])
|
|
515
652
|
]
|
|
516
653
|
|
|
654
|
+
def p_gate_params_multiple(self, p):
|
|
655
|
+
"""gate_params : ID ',' gate_params"""
|
|
656
|
+
self.p_gate_params_single(p)
|
|
657
|
+
p[0] += p[3]
|
|
658
|
+
|
|
659
|
+
def p_gate_params_single(self, p):
|
|
660
|
+
"""gate_params : ID"""
|
|
661
|
+
self.in_custom_gate_scope = True
|
|
662
|
+
self.custom_gate_scoped_params.add(p[1])
|
|
663
|
+
p[0] = [p[1]]
|
|
664
|
+
|
|
665
|
+
def p_gate_qubits_multiple(self, p):
|
|
666
|
+
"""gate_qubits : ID ',' gate_qubits"""
|
|
667
|
+
self.p_gate_qubits_single(p)
|
|
668
|
+
p[0] += p[3]
|
|
669
|
+
|
|
670
|
+
def p_gate_qubits_single(self, p):
|
|
671
|
+
"""gate_qubits : ID"""
|
|
672
|
+
self.in_custom_gate_scope = True
|
|
673
|
+
q = NamedQubit(p[1])
|
|
674
|
+
self.custom_gate_scoped_qubits[p[1]] = q
|
|
675
|
+
p[0] = [q]
|
|
676
|
+
|
|
677
|
+
def p_gate_ops(self, p):
|
|
678
|
+
"""gate_ops : gate_op gate_ops"""
|
|
679
|
+
p[0] = [p[1]] + p[2]
|
|
680
|
+
|
|
681
|
+
def p_gate_ops_empty(self, p):
|
|
682
|
+
"""gate_ops : empty"""
|
|
683
|
+
self.in_custom_gate_scope = True
|
|
684
|
+
p[0] = []
|
|
685
|
+
|
|
686
|
+
def p_gate_def_parameterized(self, p):
|
|
687
|
+
"""gate_def : GATE ID '(' gate_params ')' gate_qubits '{' gate_ops '}'"""
|
|
688
|
+
self._gate_def(p, has_params=True)
|
|
689
|
+
|
|
690
|
+
def p_gate_def(self, p):
|
|
691
|
+
"""gate_def : GATE ID gate_qubits '{' gate_ops '}'"""
|
|
692
|
+
self._gate_def(p, has_params=False)
|
|
693
|
+
|
|
694
|
+
def _gate_def(self, p: List[Any], *, has_params: bool):
|
|
695
|
+
name = p[2]
|
|
696
|
+
gate_params = tuple(p[4]) if has_params else ()
|
|
697
|
+
offset = 3 if has_params else 0
|
|
698
|
+
gate_qubits = tuple(p[3 + offset])
|
|
699
|
+
gate_ops = p[5 + offset]
|
|
700
|
+
circuit = Circuit(gate_ops).freeze()
|
|
701
|
+
gate_def = CustomGate(name, circuit, gate_params, gate_qubits)
|
|
702
|
+
self.gate_set[name] = gate_def
|
|
703
|
+
self.custom_gate_scoped_params.clear()
|
|
704
|
+
self.custom_gate_scoped_qubits.clear()
|
|
705
|
+
self.in_custom_gate_scope = False
|
|
706
|
+
p[0] = gate_def
|
|
707
|
+
|
|
517
708
|
def p_error(self, p):
|
|
518
709
|
if p is None:
|
|
519
710
|
raise QasmException('Unexpected end of file')
|