cirq-core 1.4.1__py3-none-any.whl → 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/__init__.py +587 -569
- cirq/_compat.py +9 -0
- cirq/_compat_test.py +11 -9
- cirq/_import.py +7 -8
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/__init__.py +15 -9
- cirq/circuits/_block_diagram_drawer.py +1 -2
- cirq/circuits/_block_diagram_drawer_test.py +3 -3
- cirq/circuits/_box_drawing_character_data.py +0 -1
- cirq/circuits/_box_drawing_character_data_test.py +2 -2
- cirq/circuits/_bucket_priority_queue.py +0 -1
- cirq/circuits/_bucket_priority_queue_test.py +1 -1
- cirq/circuits/circuit.py +336 -234
- cirq/circuits/circuit_operation.py +102 -52
- cirq/circuits/circuit_operation_test.py +85 -4
- cirq/circuits/circuit_test.py +101 -32
- cirq/circuits/frozen_circuit.py +36 -32
- cirq/circuits/insert_strategy.py +10 -0
- cirq/circuits/insert_strategy_test.py +20 -0
- cirq/circuits/moment.py +79 -80
- cirq/circuits/moment_test.py +105 -2
- cirq/circuits/optimization_pass.py +15 -15
- cirq/circuits/optimization_pass_test.py +8 -9
- cirq/circuits/qasm_output.py +64 -33
- cirq/circuits/qasm_output_test.py +63 -2
- cirq/circuits/text_diagram_drawer.py +26 -56
- cirq/circuits/text_diagram_drawer_test.py +5 -4
- cirq/contrib/__init__.py +2 -2
- cirq/contrib/acquaintance/__init__.py +44 -29
- cirq/contrib/acquaintance/bipartite.py +8 -7
- cirq/contrib/acquaintance/bipartite_test.py +11 -1
- cirq/contrib/acquaintance/devices.py +5 -4
- cirq/contrib/acquaintance/devices_test.py +5 -1
- cirq/contrib/acquaintance/executor.py +18 -21
- cirq/contrib/acquaintance/executor_test.py +3 -2
- cirq/contrib/acquaintance/gates.py +36 -27
- cirq/contrib/acquaintance/gates_test.py +1 -1
- cirq/contrib/acquaintance/inspection_utils.py +10 -9
- cirq/contrib/acquaintance/inspection_utils_test.py +6 -1
- cirq/contrib/acquaintance/mutation_utils.py +10 -10
- cirq/contrib/acquaintance/optimizers.py +7 -6
- cirq/contrib/acquaintance/optimizers_test.py +1 -1
- cirq/contrib/acquaintance/permutation.py +22 -21
- cirq/contrib/acquaintance/permutation_test.py +1 -1
- cirq/contrib/acquaintance/shift.py +8 -6
- cirq/contrib/acquaintance/shift_swap_network.py +6 -4
- cirq/contrib/acquaintance/strategies/__init__.py +9 -3
- cirq/contrib/acquaintance/strategies/complete.py +4 -3
- cirq/contrib/acquaintance/strategies/cubic.py +5 -3
- cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
- cirq/contrib/acquaintance/topological_sort.py +4 -2
- cirq/contrib/bayesian_network/__init__.py +3 -1
- cirq/contrib/bayesian_network/bayesian_network_gate.py +5 -3
- cirq/contrib/circuitdag/__init__.py +1 -1
- cirq/contrib/circuitdag/circuit_dag.py +24 -24
- cirq/contrib/circuitdag/circuit_dag_test.py +1 -1
- cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +15 -11
- cirq/contrib/graph_device/__init__.py +8 -8
- cirq/contrib/graph_device/graph_device.py +8 -8
- cirq/contrib/graph_device/graph_device_test.py +0 -1
- cirq/contrib/graph_device/hypergraph_test.py +1 -0
- cirq/contrib/json.py +1 -2
- cirq/contrib/json_test.py +2 -2
- cirq/contrib/noise_models/__init__.py +5 -6
- cirq/contrib/noise_models/noise_models.py +8 -6
- cirq/contrib/paulistring/__init__.py +22 -10
- cirq/contrib/paulistring/clifford_optimize.py +1 -1
- cirq/contrib/paulistring/clifford_optimize_test.py +0 -1
- cirq/contrib/paulistring/clifford_target_gateset.py +15 -12
- cirq/contrib/paulistring/optimize.py +2 -2
- cirq/contrib/paulistring/optimize_test.py +0 -1
- cirq/contrib/paulistring/pauli_string_dag_test.py +0 -1
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +379 -0
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +523 -0
- cirq/contrib/paulistring/pauli_string_optimize.py +3 -1
- cirq/contrib/paulistring/pauli_string_optimize_test.py +1 -3
- cirq/contrib/paulistring/recombine.py +2 -2
- cirq/contrib/paulistring/recombine_test.py +2 -2
- cirq/contrib/paulistring/separate.py +3 -4
- cirq/contrib/qasm_import/__init__.py +2 -2
- cirq/contrib/qasm_import/_lexer.py +21 -26
- cirq/contrib/qasm_import/_lexer_test.py +90 -6
- cirq/contrib/qasm_import/_parser.py +238 -47
- cirq/contrib/qasm_import/_parser_test.py +514 -59
- cirq/contrib/qasm_import/qasm_test.py +1 -1
- cirq/contrib/qcircuit/__init__.py +6 -4
- cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
- cirq/contrib/qcircuit/qcircuit_pdf.py +1 -2
- cirq/{experiments/grid_parallel_two_qubit_xeb_test.py → contrib/qcircuit/qcircuit_pdf_test.py} +13 -12
- cirq/contrib/qcircuit/qcircuit_test.py +1 -1
- cirq/contrib/quantum_volume/__init__.py +7 -7
- cirq/contrib/quantum_volume/quantum_volume.py +6 -11
- cirq/contrib/quantum_volume/quantum_volume_test.py +3 -1
- cirq/contrib/quimb/__init__.py +16 -13
- cirq/contrib/quimb/density_matrix.py +1 -1
- cirq/contrib/quimb/mps_simulator.py +27 -28
- cirq/contrib/quimb/mps_simulator_test.py +5 -0
- cirq/contrib/quimb/state_vector.py +3 -10
- cirq/contrib/quirk/__init__.py +1 -1
- cirq/contrib/quirk/export_to_quirk.py +3 -3
- cirq/contrib/routing/__init__.py +12 -9
- cirq/contrib/routing/device.py +1 -1
- cirq/contrib/routing/device_test.py +1 -2
- cirq/contrib/routing/greedy.py +7 -5
- cirq/contrib/routing/greedy_test.py +5 -3
- cirq/contrib/routing/initialization.py +3 -1
- cirq/contrib/routing/initialization_test.py +1 -1
- cirq/contrib/routing/swap_network.py +6 -6
- cirq/contrib/routing/utils.py +6 -4
- cirq/contrib/routing/utils_test.py +1 -2
- cirq/{type_workarounds.py → contrib/shuffle_circuits/__init__.py} +5 -10
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +250 -0
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +363 -0
- cirq/contrib/svg/__init__.py +1 -1
- cirq/contrib/svg/svg.py +12 -10
- cirq/contrib/svg/svg_test.py +3 -2
- cirq/devices/__init__.py +34 -25
- cirq/devices/device.py +16 -12
- cirq/devices/device_test.py +1 -0
- cirq/devices/grid_device_metadata.py +16 -12
- cirq/devices/grid_device_metadata_test.py +2 -1
- cirq/devices/grid_qubit.py +31 -26
- cirq/devices/grid_qubit_test.py +30 -1
- cirq/devices/insertion_noise_model.py +6 -6
- cirq/devices/insertion_noise_model_test.py +1 -1
- cirq/devices/line_qubit.py +28 -20
- cirq/devices/line_qubit_test.py +26 -0
- cirq/devices/named_topologies.py +12 -10
- cirq/devices/named_topologies_test.py +5 -4
- cirq/devices/noise_model.py +29 -33
- cirq/devices/noise_properties.py +2 -2
- cirq/devices/noise_properties_test.py +2 -2
- cirq/devices/noise_utils.py +3 -3
- cirq/devices/superconducting_qubits_noise_properties.py +2 -2
- cirq/devices/superconducting_qubits_noise_properties_test.py +3 -3
- cirq/devices/thermal_noise_model.py +2 -1
- cirq/devices/unconstrained_device.py +1 -1
- cirq/devices/unconstrained_device_test.py +6 -0
- cirq/experiments/__init__.py +51 -34
- cirq/experiments/qubit_characterizations.py +17 -15
- cirq/experiments/qubit_characterizations_test.py +4 -6
- cirq/experiments/random_quantum_circuit_generation.py +10 -9
- cirq/experiments/random_quantum_circuit_generation_test.py +21 -4
- cirq/experiments/readout_confusion_matrix.py +73 -8
- cirq/experiments/readout_confusion_matrix_test.py +104 -1
- cirq/experiments/single_qubit_readout_calibration.py +8 -6
- cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
- cirq/experiments/t1_decay_experiment.py +4 -5
- cirq/experiments/t1_decay_experiment_test.py +1 -2
- cirq/experiments/t2_decay_experiment.py +0 -1
- cirq/experiments/t2_decay_experiment_test.py +1 -2
- cirq/experiments/two_qubit_xeb.py +157 -33
- cirq/experiments/two_qubit_xeb_test.py +38 -22
- cirq/experiments/xeb_fitting.py +99 -19
- cirq/experiments/xeb_fitting_test.py +64 -25
- cirq/experiments/xeb_sampling.py +14 -18
- cirq/experiments/xeb_simulation.py +4 -3
- cirq/experiments/xeb_simulation_test.py +20 -14
- cirq/experiments/z_phase_calibration.py +368 -0
- cirq/experiments/z_phase_calibration_test.py +241 -0
- cirq/interop/__init__.py +4 -1
- cirq/interop/quirk/__init__.py +7 -4
- cirq/interop/quirk/cells/__init__.py +17 -6
- cirq/interop/quirk/cells/arithmetic_cells.py +8 -8
- cirq/interop/quirk/cells/arithmetic_cells_test.py +1 -1
- cirq/interop/quirk/cells/cell.py +6 -6
- cirq/interop/quirk/cells/composite_cell.py +5 -5
- cirq/interop/quirk/cells/composite_cell_test.py +1 -1
- cirq/interop/quirk/cells/control_cells.py +1 -1
- cirq/interop/quirk/cells/frequency_space_cells.py +2 -2
- cirq/interop/quirk/cells/ignored_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells_test.py +1 -1
- cirq/interop/quirk/cells/input_rotation_cells.py +1 -1
- cirq/interop/quirk/cells/input_rotation_cells_test.py +1 -1
- cirq/interop/quirk/cells/measurement_cells.py +1 -1
- cirq/interop/quirk/cells/parse.py +8 -7
- cirq/interop/quirk/cells/parse_test.py +2 -2
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +1 -1
- cirq/interop/quirk/cells/swap_cell_test.py +1 -1
- cirq/interop/quirk/cells/unsupported_cells.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +7 -7
- cirq/interop/quirk/url_to_circuit_test.py +1 -1
- cirq/ion/__init__.py +4 -2
- cirq/json_resolver_cache.py +15 -7
- cirq/linalg/__init__.py +62 -51
- cirq/linalg/combinators.py +4 -4
- cirq/linalg/combinators_test.py +4 -1
- cirq/linalg/decompositions.py +15 -40
- cirq/linalg/decompositions_test.py +16 -22
- cirq/linalg/diagonalize.py +1 -1
- cirq/linalg/diagonalize_test.py +1 -1
- cirq/linalg/operator_spaces.py +20 -4
- cirq/linalg/operator_spaces_test.py +15 -2
- cirq/linalg/predicates.py +3 -3
- cirq/linalg/predicates_test.py +1 -0
- cirq/linalg/tolerance.py +2 -2
- cirq/linalg/transformations.py +30 -12
- cirq/linalg/transformations_test.py +13 -0
- cirq/neutral_atoms/__init__.py +2 -2
- cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +0 -1
- cirq/ops/__init__.py +172 -132
- cirq/ops/arithmetic_operation.py +2 -2
- cirq/ops/arithmetic_operation_test.py +2 -2
- cirq/ops/boolean_hamiltonian.py +3 -2
- cirq/ops/classically_controlled_operation.py +39 -12
- cirq/ops/classically_controlled_operation_test.py +147 -1
- cirq/ops/clifford_gate.py +38 -36
- cirq/ops/clifford_gate_test.py +75 -1
- cirq/ops/common_channels.py +16 -45
- cirq/ops/common_channels_test.py +10 -0
- cirq/ops/common_gate_families.py +1 -1
- cirq/ops/common_gate_families_test.py +1 -0
- cirq/ops/common_gates.py +48 -49
- cirq/ops/common_gates_test.py +18 -2
- cirq/ops/control_values.py +3 -3
- cirq/ops/control_values_test.py +2 -1
- cirq/ops/controlled_gate.py +36 -23
- cirq/ops/controlled_gate_test.py +70 -3
- cirq/ops/controlled_operation.py +6 -5
- cirq/ops/controlled_operation_test.py +7 -3
- cirq/ops/dense_pauli_string.py +11 -11
- cirq/ops/diagonal_gate.py +2 -2
- cirq/ops/diagonal_gate_test.py +1 -0
- cirq/ops/eigen_gate.py +16 -36
- cirq/ops/eigen_gate_test.py +60 -10
- cirq/ops/fourier_transform.py +1 -3
- cirq/ops/fourier_transform_test.py +2 -1
- cirq/ops/fsim_gate.py +42 -3
- cirq/ops/fsim_gate_test.py +21 -0
- cirq/ops/gate_operation.py +8 -8
- cirq/ops/gate_operation_test.py +4 -2
- cirq/ops/gateset_test.py +11 -2
- cirq/ops/global_phase_op.py +8 -7
- cirq/ops/global_phase_op_test.py +1 -1
- cirq/ops/greedy_qubit_manager_test.py +5 -0
- cirq/ops/identity.py +14 -4
- cirq/ops/identity_test.py +24 -0
- cirq/ops/kraus_channel.py +1 -0
- cirq/ops/kraus_channel_test.py +3 -1
- cirq/ops/linear_combinations.py +27 -21
- cirq/ops/linear_combinations_test.py +23 -4
- cirq/ops/matrix_gates.py +24 -8
- cirq/ops/measure_util.py +2 -2
- cirq/ops/measurement_gate.py +7 -4
- cirq/ops/measurement_gate_test.py +2 -1
- cirq/ops/mixed_unitary_channel.py +1 -0
- cirq/ops/mixed_unitary_channel_test.py +3 -1
- cirq/ops/named_qubit.py +8 -1
- cirq/ops/op_tree.py +3 -30
- cirq/ops/op_tree_test.py +4 -0
- cirq/ops/parallel_gate.py +2 -3
- cirq/ops/parallel_gate_test.py +2 -1
- cirq/ops/parity_gates.py +7 -8
- cirq/ops/parity_gates_test.py +1 -0
- cirq/ops/pauli_gates.py +5 -11
- cirq/ops/pauli_gates_test.py +1 -0
- cirq/ops/pauli_interaction_gate.py +11 -5
- cirq/ops/pauli_interaction_gate_test.py +2 -3
- cirq/ops/pauli_measurement_gate.py +6 -5
- cirq/ops/pauli_measurement_gate_test.py +1 -0
- cirq/ops/pauli_string.py +115 -130
- cirq/ops/pauli_string_phasor.py +21 -20
- cirq/ops/pauli_string_phasor_test.py +13 -3
- cirq/ops/pauli_string_raw_types.py +1 -0
- cirq/ops/pauli_string_test.py +192 -55
- cirq/ops/pauli_sum_exponential.py +3 -4
- cirq/ops/pauli_sum_exponential_test.py +0 -1
- cirq/ops/permutation_gate.py +2 -2
- cirq/ops/permutation_gate_test.py +1 -1
- cirq/ops/phased_iswap_gate.py +6 -7
- cirq/ops/phased_iswap_gate_test.py +21 -5
- cirq/ops/phased_x_gate.py +11 -25
- cirq/ops/phased_x_gate_test.py +19 -3
- cirq/ops/phased_x_z_gate.py +12 -11
- cirq/ops/projector.py +4 -5
- cirq/ops/qubit_manager.py +2 -1
- cirq/ops/qubit_manager_test.py +2 -1
- cirq/ops/qubit_order.py +1 -1
- cirq/ops/random_gate_channel.py +1 -1
- cirq/ops/random_gate_channel_test.py +0 -6
- cirq/ops/raw_types.py +146 -50
- cirq/ops/raw_types_test.py +37 -3
- cirq/ops/state_preparation_channel.py +2 -2
- cirq/ops/state_preparation_channel_test.py +2 -1
- cirq/ops/swap_gates.py +9 -4
- cirq/ops/three_qubit_gates.py +8 -8
- cirq/ops/three_qubit_gates_test.py +1 -0
- cirq/ops/two_qubit_diagonal_gate.py +4 -3
- cirq/ops/uniform_superposition_gate.py +4 -4
- cirq/ops/uniform_superposition_gate_test.py +1 -0
- cirq/ops/wait_gate.py +6 -8
- cirq/protocols/__init__.py +135 -83
- cirq/protocols/act_on_protocol.py +1 -1
- cirq/protocols/act_on_protocol_test.py +1 -1
- cirq/protocols/apply_channel_protocol.py +3 -3
- cirq/protocols/apply_mixture_protocol.py +15 -9
- cirq/protocols/apply_mixture_protocol_test.py +11 -0
- cirq/protocols/apply_unitary_protocol.py +2 -2
- cirq/protocols/apply_unitary_protocol_test.py +2 -1
- cirq/protocols/approximate_equality_protocol.py +7 -8
- cirq/protocols/approximate_equality_protocol_test.py +3 -1
- cirq/protocols/circuit_diagram_info_protocol.py +8 -6
- cirq/protocols/circuit_diagram_info_protocol_test.py +5 -0
- cirq/protocols/commutes_protocol.py +6 -6
- cirq/protocols/control_key_protocol.py +1 -1
- cirq/protocols/decompose_protocol.py +4 -5
- cirq/protocols/decompose_protocol_test.py +2 -1
- cirq/protocols/equal_up_to_global_phase_protocol.py +3 -3
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +7 -0
- cirq/protocols/has_stabilizer_effect_protocol.py +5 -5
- cirq/protocols/has_unitary_protocol.py +1 -1
- cirq/protocols/has_unitary_protocol_test.py +8 -7
- cirq/protocols/hash_from_pickle_test.py +120 -0
- cirq/protocols/inverse_protocol.py +1 -1
- cirq/protocols/json_serialization.py +14 -1
- cirq/protocols/json_serialization_test.py +28 -7
- cirq/protocols/json_test_data/BitMaskKeyCondition.json +86 -0
- cirq/protocols/json_test_data/BitMaskKeyCondition.repr +7 -0
- cirq/protocols/json_test_data/Concat.json +19 -0
- cirq/protocols/json_test_data/Concat.repr +1 -0
- cirq/protocols/json_test_data/README.md +4 -2
- cirq/protocols/json_test_data/SympyCondition.json +60 -15
- cirq/protocols/json_test_data/SympyCondition.repr +4 -1
- cirq/protocols/json_test_data/_InverseCompositeGate.json +10 -0
- cirq/protocols/json_test_data/_InverseCompositeGate.repr +1 -0
- cirq/protocols/json_test_data/__init__.py +1 -1
- cirq/protocols/json_test_data/sympy.And.json +13 -0
- cirq/protocols/json_test_data/sympy.And.repr +1 -0
- cirq/protocols/json_test_data/sympy.Indexed.json +18 -0
- cirq/protocols/json_test_data/sympy.Indexed.repr +1 -0
- cirq/protocols/json_test_data/sympy.IndexedBase.json +9 -0
- cirq/protocols/json_test_data/sympy.IndexedBase.repr +1 -0
- cirq/protocols/json_test_data/sympy.Not.json +9 -0
- cirq/protocols/json_test_data/sympy.Not.repr +1 -0
- cirq/protocols/json_test_data/sympy.Or.json +13 -0
- cirq/protocols/json_test_data/sympy.Or.repr +1 -0
- cirq/protocols/json_test_data/sympy.Xor.json +13 -0
- cirq/protocols/json_test_data/sympy.Xor.repr +1 -0
- cirq/protocols/kraus_protocol.py +8 -8
- cirq/protocols/kraus_protocol_test.py +0 -1
- cirq/protocols/measurement_key_protocol.py +1 -1
- cirq/protocols/measurement_key_protocol_test.py +7 -7
- cirq/protocols/mixture_protocol.py +6 -4
- cirq/protocols/mixture_protocol_test.py +21 -13
- cirq/protocols/pauli_expansion_protocol.py +1 -0
- cirq/protocols/pow_protocol.py +1 -1
- cirq/protocols/qasm.py +25 -6
- cirq/protocols/qasm_test.py +17 -0
- cirq/protocols/qid_shape_protocol.py +2 -2
- cirq/protocols/resolve_parameters.py +2 -3
- cirq/protocols/resolve_parameters_test.py +2 -1
- cirq/protocols/trace_distance_bound.py +1 -1
- cirq/protocols/trace_distance_bound_test.py +1 -0
- cirq/protocols/unitary_protocol.py +3 -3
- cirq/protocols/unitary_protocol_test.py +1 -1
- cirq/qis/__init__.py +48 -35
- cirq/qis/channels_test.py +0 -9
- cirq/qis/clifford_tableau.py +46 -26
- cirq/qis/clifford_tableau_test.py +2 -1
- cirq/qis/entropy.py +115 -0
- cirq/qis/entropy_test.py +43 -0
- cirq/qis/measures.py +5 -4
- cirq/qis/measures_test.py +7 -0
- cirq/qis/noise_utils_test.py +4 -4
- cirq/qis/quantum_state_representation.py +1 -1
- cirq/qis/states.py +7 -7
- cirq/sim/__init__.py +55 -37
- cirq/sim/classical_simulator.py +7 -6
- cirq/sim/classical_simulator_test.py +3 -1
- cirq/sim/clifford/__init__.py +17 -9
- cirq/sim/clifford/clifford_simulator.py +5 -4
- cirq/sim/clifford/clifford_simulator_test.py +32 -9
- cirq/sim/clifford/clifford_tableau_simulation_state.py +1 -1
- cirq/sim/clifford/stabilizer_simulation_state.py +1 -1
- cirq/sim/clifford/stabilizer_state_ch_form.py +4 -3
- cirq/sim/density_matrix_simulator.py +3 -2
- cirq/sim/density_matrix_simulator_test.py +12 -4
- cirq/sim/density_matrix_utils.py +1 -1
- cirq/sim/mux.py +2 -2
- cirq/sim/simulation_state.py +4 -5
- cirq/sim/simulation_state_base.py +2 -2
- cirq/sim/simulation_state_test.py +1 -1
- cirq/sim/simulation_utils.py +3 -1
- cirq/sim/simulation_utils_test.py +2 -3
- cirq/sim/simulator.py +7 -6
- cirq/sim/simulator_base.py +5 -5
- cirq/sim/simulator_test.py +14 -3
- cirq/sim/sparse_simulator.py +4 -3
- cirq/sim/sparse_simulator_test.py +17 -9
- cirq/sim/state_vector.py +2 -2
- cirq/sim/state_vector_simulation_state_test.py +1 -1
- cirq/sim/state_vector_simulator.py +4 -4
- cirq/sim/state_vector_test.py +27 -32
- cirq/study/__init__.py +27 -21
- cirq/study/flatten_expressions.py +5 -6
- cirq/study/flatten_expressions_test.py +1 -1
- cirq/study/resolver.py +14 -11
- cirq/study/resolver_test.py +10 -1
- cirq/study/result.py +3 -3
- cirq/study/sweepable.py +15 -9
- cirq/study/sweepable_test.py +27 -0
- cirq/study/sweeps.py +65 -10
- cirq/study/sweeps_test.py +123 -0
- cirq/testing/__init__.py +86 -57
- cirq/testing/_compat_test_data/module_a/__init__.py +2 -2
- cirq/testing/_compat_test_data/module_a/sub/subsub/__init__.py +1 -1
- cirq/testing/circuit_compare.py +3 -4
- cirq/testing/circuit_compare_test.py +7 -8
- cirq/testing/consistent_act_on.py +3 -3
- cirq/testing/consistent_channels_test.py +2 -1
- cirq/testing/consistent_controlled_gate_op.py +3 -2
- cirq/testing/consistent_controlled_gate_op_test.py +2 -3
- cirq/testing/consistent_decomposition.py +1 -1
- cirq/testing/consistent_decomposition_test.py +1 -2
- cirq/testing/consistent_pauli_expansion_test.py +1 -1
- cirq/testing/consistent_phase_by.py +1 -1
- cirq/testing/consistent_phase_by_test.py +1 -2
- cirq/testing/consistent_protocols.py +11 -11
- cirq/testing/consistent_protocols_test.py +4 -5
- cirq/testing/consistent_qasm.py +8 -12
- cirq/testing/consistent_qasm_test.py +1 -1
- cirq/testing/consistent_resolve_parameters.py +2 -1
- cirq/testing/consistent_specified_has_unitary_test.py +1 -1
- cirq/testing/consistent_unitary.py +3 -1
- cirq/testing/consistent_unitary_test.py +3 -3
- cirq/testing/devices.py +1 -1
- cirq/testing/devices_test.py +1 -0
- cirq/testing/equals_tester.py +2 -4
- cirq/testing/equals_tester_test.py +6 -5
- cirq/testing/equivalent_basis_map.py +1 -0
- cirq/testing/equivalent_basis_map_test.py +0 -1
- cirq/testing/gate_features_test.py +5 -0
- cirq/testing/json.py +4 -4
- cirq/testing/lin_alg_utils_test.py +1 -1
- cirq/testing/order_tester.py +1 -1
- cirq/testing/order_tester_test.py +1 -1
- cirq/testing/pytest_utils.py +57 -0
- cirq/testing/pytest_utils_test.py +35 -0
- cirq/testing/random_circuit.py +2 -2
- cirq/testing/random_circuit_test.py +2 -2
- cirq/testing/routing_devices_test.py +2 -1
- cirq/testing/sample_circuits.py +1 -1
- cirq/testing/sample_gates.py +5 -4
- cirq/testing/sample_gates_test.py +2 -2
- cirq/transformers/__init__.py +101 -82
- cirq/transformers/align.py +12 -1
- cirq/transformers/align_test.py +13 -0
- cirq/transformers/analytical_decompositions/__init__.py +27 -24
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +2 -1
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +1 -1
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +1 -1
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +1 -1
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +2 -2
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +4 -4
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +99 -24
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +105 -14
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +1 -1
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +1 -1
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +3 -4
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -6
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +1 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -1
- cirq/transformers/drop_empty_moments.py +1 -0
- cirq/transformers/drop_negligible_operations.py +1 -0
- cirq/transformers/dynamical_decoupling.py +255 -43
- cirq/transformers/dynamical_decoupling_test.py +730 -17
- cirq/transformers/eject_phased_paulis.py +29 -15
- cirq/transformers/eject_phased_paulis_test.py +3 -8
- cirq/transformers/eject_z.py +3 -2
- cirq/transformers/eject_z_test.py +3 -3
- cirq/transformers/gauge_compiling/__init__.py +25 -9
- cirq/transformers/gauge_compiling/cphase_gauge.py +146 -0
- cirq/transformers/gauge_compiling/cphase_gauge_test.py +42 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +4 -4
- cirq/transformers/gauge_compiling/gauge_compiling.py +245 -6
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +107 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +39 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +10 -1
- cirq/transformers/gauge_compiling/iswap_gauge.py +2 -2
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -2
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +23 -5
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +3 -2
- cirq/transformers/heuristic_decompositions/__init__.py +3 -3
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +2 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +1 -1
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -4
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +4 -4
- cirq/transformers/insertion_sort.py +64 -0
- cirq/transformers/insertion_sort_test.py +34 -0
- cirq/transformers/measurement_transformers.py +14 -1
- cirq/transformers/measurement_transformers_test.py +35 -0
- cirq/transformers/merge_k_qubit_gates.py +2 -2
- cirq/transformers/merge_single_qubit_gates.py +1 -1
- cirq/transformers/merge_single_qubit_gates_test.py +1 -1
- cirq/transformers/noise_adding.py +115 -0
- cirq/transformers/noise_adding_test.py +54 -0
- cirq/transformers/optimize_for_target_gateset.py +1 -1
- cirq/transformers/optimize_for_target_gateset_test.py +3 -2
- cirq/transformers/qubit_management_transformers.py +1 -1
- cirq/transformers/randomized_measurements.py +171 -0
- cirq/transformers/randomized_measurements_test.py +68 -0
- cirq/transformers/routing/__init__.py +14 -5
- cirq/transformers/routing/initial_mapper.py +1 -1
- cirq/transformers/routing/initial_mapper_test.py +1 -0
- cirq/transformers/routing/line_initial_mapper.py +3 -2
- cirq/transformers/routing/mapping_manager.py +2 -2
- cirq/transformers/routing/mapping_manager_test.py +2 -2
- cirq/transformers/routing/route_circuit_cqc.py +3 -2
- cirq/transformers/routing/route_circuit_cqc_test.py +2 -1
- cirq/transformers/routing/visualize_routed_circuit.py +1 -0
- cirq/transformers/routing/visualize_routed_circuit_test.py +1 -0
- cirq/transformers/stratify.py +2 -2
- cirq/transformers/synchronize_terminal_measurements.py +2 -1
- cirq/transformers/target_gatesets/__init__.py +7 -5
- cirq/transformers/target_gatesets/compilation_target_gateset.py +16 -3
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -0
- cirq/transformers/target_gatesets/cz_gateset.py +5 -1
- cirq/transformers/target_gatesets/cz_gateset_test.py +23 -2
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +1 -1
- cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +3 -2
- cirq/transformers/transformer_api.py +5 -4
- cirq/transformers/transformer_api_test.py +11 -3
- cirq/transformers/transformer_primitives.py +9 -31
- cirq/transformers/transformer_primitives_test.py +6 -5
- cirq/value/__init__.py +51 -30
- cirq/value/abc_alt.py +1 -2
- cirq/value/angle.py +2 -0
- cirq/value/classical_data.py +1 -0
- cirq/value/condition.py +149 -3
- cirq/value/condition_test.py +254 -0
- cirq/value/digits.py +1 -1
- cirq/value/duration.py +4 -4
- cirq/value/duration_test.py +2 -1
- cirq/value/linear_dict.py +85 -24
- cirq/value/linear_dict_test.py +94 -3
- cirq/value/measurement_key.py +9 -2
- cirq/value/periodic_value.py +2 -3
- cirq/value/periodic_value_test.py +5 -0
- cirq/value/probability.py +1 -0
- cirq/value/random_state.py +1 -1
- cirq/value/timestamp.py +2 -4
- cirq/value/timestamp_test.py +2 -1
- cirq/value/type_alias.py +2 -2
- cirq/value/value_equality_attr.py +14 -2
- cirq/value/value_equality_attr_test.py +1 -1
- cirq/vis/__init__.py +9 -6
- cirq/vis/density_matrix.py +1 -1
- cirq/vis/density_matrix_test.py +2 -5
- cirq/vis/heatmap.py +49 -12
- cirq/vis/heatmap_test.py +168 -4
- cirq/vis/histogram.py +1 -1
- cirq/vis/histogram_test.py +1 -2
- cirq/vis/state_histogram.py +7 -5
- cirq/vis/state_histogram_test.py +2 -2
- cirq/work/__init__.py +19 -13
- cirq/work/collector.py +2 -2
- cirq/work/observable_grouping.py +2 -2
- cirq/work/observable_measurement.py +3 -3
- cirq/work/observable_measurement_data.py +5 -2
- cirq/work/observable_measurement_test.py +8 -8
- cirq/work/observable_readout_calibration.py +2 -2
- cirq/work/observable_readout_calibration_test.py +2 -1
- cirq/work/observable_settings.py +8 -7
- cirq/work/observable_settings_test.py +3 -2
- cirq/work/pauli_sum_collector.py +1 -1
- cirq/work/sampler.py +8 -20
- cirq/work/sampler_test.py +4 -3
- cirq/work/zeros_sampler.py +1 -1
- cirq_core-1.5.0.dist-info/METADATA +125 -0
- {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/RECORD +586 -552
- {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/WHEEL +1 -1
- cirq/experiments/grid_parallel_two_qubit_xeb.py +0 -62
- cirq/protocols/json_test_data/GridParallelXEBMetadata.json +0 -119
- cirq/protocols/json_test_data/GridParallelXEBMetadata.repr +0 -1
- cirq_core-1.4.1.dist-info/METADATA +0 -45
- {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/LICENSE +0 -0
- {cirq_core-1.4.1.dist-info → cirq_core-1.5.0.dist-info}/top_level.txt +0 -0
|
@@ -12,19 +12,21 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import re
|
|
16
|
+
import textwrap
|
|
15
17
|
from typing import Callable
|
|
16
18
|
|
|
17
19
|
import numpy as np
|
|
18
20
|
import pytest
|
|
19
21
|
import sympy
|
|
20
22
|
|
|
21
|
-
|
|
22
23
|
import cirq
|
|
23
24
|
import cirq.testing as ct
|
|
24
25
|
from cirq import Circuit
|
|
25
26
|
from cirq.circuits.qasm_output import QasmUGate
|
|
26
27
|
from cirq.contrib.qasm_import import QasmException
|
|
27
28
|
from cirq.contrib.qasm_import._parser import QasmParser
|
|
29
|
+
from cirq.testing import consistent_qasm as cq
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def test_format_header_circuit():
|
|
@@ -185,7 +187,7 @@ def test_CX_gate():
|
|
|
185
187
|
qreg q2[2];
|
|
186
188
|
CX q1[0], q1[1];
|
|
187
189
|
CX q1, q2[0];
|
|
188
|
-
CX q2, q1;
|
|
190
|
+
CX q2, q1;
|
|
189
191
|
"""
|
|
190
192
|
parser = QasmParser()
|
|
191
193
|
|
|
@@ -389,7 +391,7 @@ def test_U_angles():
|
|
|
389
391
|
|
|
390
392
|
def test_U_gate_zero_params_error():
|
|
391
393
|
qasm = """OPENQASM 2.0;
|
|
392
|
-
qreg q[2];
|
|
394
|
+
qreg q[2];
|
|
393
395
|
U q[1];"""
|
|
394
396
|
|
|
395
397
|
parser = QasmParser()
|
|
@@ -400,7 +402,7 @@ def test_U_gate_zero_params_error():
|
|
|
400
402
|
|
|
401
403
|
def test_U_gate_too_much_params_error():
|
|
402
404
|
qasm = """OPENQASM 2.0;
|
|
403
|
-
qreg q[2];
|
|
405
|
+
qreg q[2];
|
|
404
406
|
U(pi, pi, pi, pi) q[1];"""
|
|
405
407
|
|
|
406
408
|
parser = QasmParser()
|
|
@@ -519,9 +521,9 @@ def test_rotation_gates(qasm_gate: str, cirq_gate: Callable[[float], cirq.Gate])
|
|
|
519
521
|
def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
|
|
520
522
|
qasm = f"""
|
|
521
523
|
OPENQASM 2.0;
|
|
522
|
-
include "qelib1.inc";
|
|
523
|
-
qreg q[2];
|
|
524
|
-
{qasm_gate}(pi) q[0], q[1];
|
|
524
|
+
include "qelib1.inc";
|
|
525
|
+
qreg q[2];
|
|
526
|
+
{qasm_gate}(pi) q[0], q[1];
|
|
525
527
|
"""
|
|
526
528
|
|
|
527
529
|
parser = QasmParser()
|
|
@@ -533,9 +535,9 @@ def test_rotation_gates_wrong_number_of_args(qasm_gate: str):
|
|
|
533
535
|
@pytest.mark.parametrize('qasm_gate', [g[0] for g in rotation_gates])
|
|
534
536
|
def test_rotation_gates_zero_params_error(qasm_gate: str):
|
|
535
537
|
qasm = f"""OPENQASM 2.0;
|
|
536
|
-
include "qelib1.inc";
|
|
537
|
-
qreg q[2];
|
|
538
|
-
{qasm_gate} q[1];
|
|
538
|
+
include "qelib1.inc";
|
|
539
|
+
qreg q[2];
|
|
540
|
+
{qasm_gate} q[1];
|
|
539
541
|
"""
|
|
540
542
|
|
|
541
543
|
parser = QasmParser()
|
|
@@ -583,7 +585,7 @@ def test_measure_individual_bits():
|
|
|
583
585
|
OPENQASM 2.0;
|
|
584
586
|
include "qelib1.inc";
|
|
585
587
|
qreg q1[2];
|
|
586
|
-
creg c1[2];
|
|
588
|
+
creg c1[2];
|
|
587
589
|
measure q1[0] -> c1[0];
|
|
588
590
|
measure q1[1] -> c1[1];
|
|
589
591
|
"""
|
|
@@ -611,8 +613,8 @@ def test_measure_registers():
|
|
|
611
613
|
qasm = """OPENQASM 2.0;
|
|
612
614
|
include "qelib1.inc";
|
|
613
615
|
qreg q1[3];
|
|
614
|
-
creg c1[3];
|
|
615
|
-
measure q1 -> c1;
|
|
616
|
+
creg c1[3];
|
|
617
|
+
measure q1 -> c1;
|
|
616
618
|
"""
|
|
617
619
|
parser = QasmParser()
|
|
618
620
|
|
|
@@ -638,10 +640,10 @@ def test_measure_registers():
|
|
|
638
640
|
|
|
639
641
|
def test_measure_mismatched_register_size():
|
|
640
642
|
qasm = """OPENQASM 2.0;
|
|
641
|
-
include "qelib1.inc";
|
|
643
|
+
include "qelib1.inc";
|
|
642
644
|
qreg q1[2];
|
|
643
|
-
creg c1[3];
|
|
644
|
-
measure q1 -> c1;
|
|
645
|
+
creg c1[3];
|
|
646
|
+
measure q1 -> c1;
|
|
645
647
|
"""
|
|
646
648
|
|
|
647
649
|
parser = QasmParser()
|
|
@@ -652,11 +654,11 @@ def test_measure_mismatched_register_size():
|
|
|
652
654
|
|
|
653
655
|
def test_measure_to_quantum_register():
|
|
654
656
|
qasm = """OPENQASM 2.0;
|
|
655
|
-
include "qelib1.inc";
|
|
657
|
+
include "qelib1.inc";
|
|
656
658
|
qreg q1[3];
|
|
657
659
|
qreg q2[3];
|
|
658
|
-
creg c1[3];
|
|
659
|
-
measure q2 -> q1;
|
|
660
|
+
creg c1[3];
|
|
661
|
+
measure q2 -> q1;
|
|
660
662
|
"""
|
|
661
663
|
|
|
662
664
|
parser = QasmParser()
|
|
@@ -667,10 +669,10 @@ def test_measure_to_quantum_register():
|
|
|
667
669
|
|
|
668
670
|
def test_measure_undefined_classical_bit():
|
|
669
671
|
qasm = """OPENQASM 2.0;
|
|
670
|
-
include "qelib1.inc";
|
|
671
|
-
qreg q1[3];
|
|
672
|
-
creg c1[3];
|
|
673
|
-
measure q1[1] -> c2[1];
|
|
672
|
+
include "qelib1.inc";
|
|
673
|
+
qreg q1[3];
|
|
674
|
+
creg c1[3];
|
|
675
|
+
measure q1[1] -> c2[1];
|
|
674
676
|
"""
|
|
675
677
|
|
|
676
678
|
parser = QasmParser()
|
|
@@ -681,11 +683,11 @@ def test_measure_undefined_classical_bit():
|
|
|
681
683
|
|
|
682
684
|
def test_measure_from_classical_register():
|
|
683
685
|
qasm = """OPENQASM 2.0;
|
|
684
|
-
include "qelib1.inc";
|
|
686
|
+
include "qelib1.inc";
|
|
685
687
|
qreg q1[2];
|
|
686
|
-
creg c1[3];
|
|
687
|
-
creg c2[3];
|
|
688
|
-
measure c1 -> c2;
|
|
688
|
+
creg c1[3];
|
|
689
|
+
creg c2[3];
|
|
690
|
+
measure c1 -> c2;
|
|
689
691
|
"""
|
|
690
692
|
|
|
691
693
|
parser = QasmParser()
|
|
@@ -697,8 +699,8 @@ def test_measure_from_classical_register():
|
|
|
697
699
|
def test_measurement_bounds():
|
|
698
700
|
qasm = """OPENQASM 2.0;
|
|
699
701
|
qreg q1[3];
|
|
700
|
-
creg c1[3];
|
|
701
|
-
measure q1[0] -> c1[4];
|
|
702
|
+
creg c1[3];
|
|
703
|
+
measure q1[0] -> c1[4];
|
|
702
704
|
"""
|
|
703
705
|
parser = QasmParser()
|
|
704
706
|
|
|
@@ -706,12 +708,41 @@ def test_measurement_bounds():
|
|
|
706
708
|
parser.parse(qasm)
|
|
707
709
|
|
|
708
710
|
|
|
711
|
+
def test_reset():
|
|
712
|
+
qasm = textwrap.dedent(
|
|
713
|
+
"""\
|
|
714
|
+
OPENQASM 2.0;
|
|
715
|
+
include "qelib1.inc";
|
|
716
|
+
qreg q[1];
|
|
717
|
+
creg c[1];
|
|
718
|
+
x q[0];
|
|
719
|
+
reset q[0];
|
|
720
|
+
measure q[0] -> c[0];
|
|
721
|
+
"""
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
parser = QasmParser()
|
|
725
|
+
|
|
726
|
+
q_0 = cirq.NamedQubit('q_0')
|
|
727
|
+
|
|
728
|
+
expected_circuit = Circuit([cirq.X(q_0), cirq.reset(q_0), cirq.measure(q_0, key='c_0')])
|
|
729
|
+
|
|
730
|
+
parsed_qasm = parser.parse(qasm)
|
|
731
|
+
|
|
732
|
+
assert parsed_qasm.supportedFormat
|
|
733
|
+
assert parsed_qasm.qelib1Include
|
|
734
|
+
|
|
735
|
+
ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
|
|
736
|
+
assert parsed_qasm.qregs == {'q': 1}
|
|
737
|
+
assert parsed_qasm.cregs == {'c': 1}
|
|
738
|
+
|
|
739
|
+
|
|
709
740
|
def test_u1_gate():
|
|
710
741
|
qasm = """
|
|
711
742
|
OPENQASM 2.0;
|
|
712
743
|
include "qelib1.inc";
|
|
713
744
|
qreg q[1];
|
|
714
|
-
u1(pi / 3.0) q[0];
|
|
745
|
+
u1(pi / 3.0) q[0];
|
|
715
746
|
"""
|
|
716
747
|
parser = QasmParser()
|
|
717
748
|
|
|
@@ -734,7 +765,7 @@ def test_u2_gate():
|
|
|
734
765
|
OPENQASM 2.0;
|
|
735
766
|
include "qelib1.inc";
|
|
736
767
|
qreg q[1];
|
|
737
|
-
u2(2 * pi, pi / 3.0) q[0];
|
|
768
|
+
u2(2 * pi, pi / 3.0) q[0];
|
|
738
769
|
"""
|
|
739
770
|
parser = QasmParser()
|
|
740
771
|
|
|
@@ -757,7 +788,7 @@ def test_id_gate():
|
|
|
757
788
|
OPENQASM 2.0;
|
|
758
789
|
include "qelib1.inc";
|
|
759
790
|
qreg q[2];
|
|
760
|
-
id q;
|
|
791
|
+
id q;
|
|
761
792
|
"""
|
|
762
793
|
parser = QasmParser()
|
|
763
794
|
|
|
@@ -816,7 +847,7 @@ def test_r_gate():
|
|
|
816
847
|
OPENQASM 2.0;
|
|
817
848
|
include "qelib1.inc";
|
|
818
849
|
qreg q[1];
|
|
819
|
-
r(pi, pi / 2.0) q[0];
|
|
850
|
+
r(pi, pi / 2.0) q[0];
|
|
820
851
|
"""
|
|
821
852
|
parser = QasmParser()
|
|
822
853
|
|
|
@@ -841,9 +872,9 @@ def test_r_gate():
|
|
|
841
872
|
def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate):
|
|
842
873
|
qasm = f"""
|
|
843
874
|
OPENQASM 2.0;
|
|
844
|
-
include "qelib1.inc";
|
|
845
|
-
qreg q[2];
|
|
846
|
-
{qasm_gate} q[0], q[1];
|
|
875
|
+
include "qelib1.inc";
|
|
876
|
+
qreg q[2];
|
|
877
|
+
{qasm_gate} q[0], q[1];
|
|
847
878
|
"""
|
|
848
879
|
|
|
849
880
|
parser = QasmParser()
|
|
@@ -859,9 +890,9 @@ def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate):
|
|
|
859
890
|
)
|
|
860
891
|
def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
|
|
861
892
|
qasm = f"""OPENQASM 2.0;
|
|
862
|
-
include "qelib1.inc";
|
|
863
|
-
qreg q[2];
|
|
864
|
-
{qasm_gate}(pi, 2*pi, 3*pi, 4*pi, 5*pi) q[1];
|
|
893
|
+
include "qelib1.inc";
|
|
894
|
+
qreg q[2];
|
|
895
|
+
{qasm_gate}(pi, 2*pi, 3*pi, 4*pi, 5*pi) q[1];
|
|
865
896
|
"""
|
|
866
897
|
|
|
867
898
|
parser = QasmParser()
|
|
@@ -873,9 +904,9 @@ def test_standard_gates_wrong_params_error(qasm_gate: str, num_params: int):
|
|
|
873
904
|
return
|
|
874
905
|
|
|
875
906
|
qasm = f"""OPENQASM 2.0;
|
|
876
|
-
include "qelib1.inc";
|
|
877
|
-
qreg q[2];
|
|
878
|
-
{qasm_gate} q[1];
|
|
907
|
+
include "qelib1.inc";
|
|
908
|
+
qreg q[2];
|
|
909
|
+
{qasm_gate} q[1];
|
|
879
910
|
"""
|
|
880
911
|
|
|
881
912
|
parser = QasmParser()
|
|
@@ -894,16 +925,24 @@ two_qubit_gates = [
|
|
|
894
925
|
]
|
|
895
926
|
|
|
896
927
|
|
|
928
|
+
# Mapping of two-qubit gates and `num_params`
|
|
929
|
+
two_qubit_param_gates = {
|
|
930
|
+
('cu1', cirq.ControlledGate(QasmUGate(0, 0, 0.1 / np.pi))): 1,
|
|
931
|
+
('cu3', cirq.ControlledGate(QasmUGate(0.1 / np.pi, 0.2 / np.pi, 0.3 / np.pi))): 3,
|
|
932
|
+
('crz', cirq.ControlledGate(cirq.rz(0.1))): 1,
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
|
|
897
936
|
@pytest.mark.parametrize('qasm_gate,cirq_gate', two_qubit_gates)
|
|
898
937
|
def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
|
|
899
938
|
qasm = f"""
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
939
|
+
OPENQASM 2.0;
|
|
940
|
+
include "qelib1.inc";
|
|
941
|
+
qreg q1[2];
|
|
942
|
+
qreg q2[2];
|
|
943
|
+
{qasm_gate} q1[0], q1[1];
|
|
944
|
+
{qasm_gate} q1, q2[0];
|
|
945
|
+
{qasm_gate} q2, q1;
|
|
907
946
|
"""
|
|
908
947
|
parser = QasmParser()
|
|
909
948
|
|
|
@@ -931,11 +970,85 @@ def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate):
|
|
|
931
970
|
assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
|
|
932
971
|
|
|
933
972
|
|
|
934
|
-
@pytest.mark.parametrize(
|
|
973
|
+
@pytest.mark.parametrize(
|
|
974
|
+
'qasm_gate,cirq_gate,num_params',
|
|
975
|
+
[
|
|
976
|
+
(gate_map[0], gate_map[1], num_param)
|
|
977
|
+
for gate_map, num_param in two_qubit_param_gates.items()
|
|
978
|
+
],
|
|
979
|
+
)
|
|
980
|
+
def test_two_qubit_param_gates(
|
|
981
|
+
qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate, num_params: int
|
|
982
|
+
):
|
|
983
|
+
params = '(0.1, 0.2, 0.3)' if num_params == 3 else '(0.1)'
|
|
984
|
+
qasm = f"""
|
|
985
|
+
OPENQASM 2.0;
|
|
986
|
+
include "qelib1.inc";
|
|
987
|
+
qreg q1[2];
|
|
988
|
+
qreg q2[2];
|
|
989
|
+
{qasm_gate}{params} q1[0], q1[1];
|
|
990
|
+
{qasm_gate}{params} q1, q2[0];
|
|
991
|
+
{qasm_gate}{params} q2, q1;
|
|
992
|
+
"""
|
|
993
|
+
parser = QasmParser()
|
|
994
|
+
|
|
995
|
+
q1_0 = cirq.NamedQubit('q1_0')
|
|
996
|
+
q1_1 = cirq.NamedQubit('q1_1')
|
|
997
|
+
q2_0 = cirq.NamedQubit('q2_0')
|
|
998
|
+
q2_1 = cirq.NamedQubit('q2_1')
|
|
999
|
+
|
|
1000
|
+
expected_circuit = cirq.Circuit()
|
|
1001
|
+
expected_circuit.append(cirq_gate.on(q1_0, q1_1))
|
|
1002
|
+
expected_circuit.append(cirq_gate.on(q1_0, q2_0))
|
|
1003
|
+
expected_circuit.append(cirq_gate.on(q1_1, q2_0))
|
|
1004
|
+
expected_circuit.append(cirq_gate.on(q2_0, q1_0))
|
|
1005
|
+
expected_circuit.append(cirq_gate.on(q2_1, q1_1))
|
|
1006
|
+
parsed_qasm = parser.parse(qasm)
|
|
1007
|
+
|
|
1008
|
+
assert parsed_qasm.supportedFormat
|
|
1009
|
+
assert parsed_qasm.qelib1Include
|
|
1010
|
+
|
|
1011
|
+
ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
|
|
1012
|
+
assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
@pytest.mark.parametrize(
|
|
1016
|
+
'qasm_gate', [g[0] for g in two_qubit_gates] + [g[0] for g in two_qubit_param_gates.keys()]
|
|
1017
|
+
)
|
|
1018
|
+
def test_two_qubit_gates_not_enough_qubits(qasm_gate: str):
|
|
1019
|
+
if qasm_gate in ('cu1', 'crz'):
|
|
1020
|
+
qasm = f"""
|
|
1021
|
+
OPENQASM 2.0;
|
|
1022
|
+
include "qelib1.inc";
|
|
1023
|
+
qreg q[2];
|
|
1024
|
+
{qasm_gate}(0.1) q[0];
|
|
1025
|
+
"""
|
|
1026
|
+
elif qasm_gate == 'cu3':
|
|
1027
|
+
qasm = f"""
|
|
1028
|
+
OPENQASM 2.0;
|
|
1029
|
+
include "qelib1.inc";
|
|
1030
|
+
qreg q[2];
|
|
1031
|
+
{qasm_gate}(0.1, 0.2, 0.3) q[0];
|
|
1032
|
+
"""
|
|
1033
|
+
else:
|
|
1034
|
+
qasm = f"""
|
|
1035
|
+
OPENQASM 2.0;
|
|
1036
|
+
include "qelib1.inc";
|
|
1037
|
+
qreg q[2];
|
|
1038
|
+
{qasm_gate} q[0];
|
|
1039
|
+
"""
|
|
1040
|
+
|
|
1041
|
+
parser = QasmParser()
|
|
1042
|
+
|
|
1043
|
+
with pytest.raises(QasmException, match=rf".*{qasm_gate}.* takes 2 arg\(s\).*got.*1.*line 5"):
|
|
1044
|
+
parser.parse(qasm)
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
@pytest.mark.parametrize('qasm_gate', [g[0] for g in two_qubit_param_gates.keys()])
|
|
935
1048
|
def test_two_qubit_gates_not_enough_args(qasm_gate: str):
|
|
936
1049
|
qasm = f"""
|
|
937
|
-
OPENQASM 2.0;
|
|
938
|
-
include "qelib1.inc";
|
|
1050
|
+
OPENQASM 2.0;
|
|
1051
|
+
include "qelib1.inc";
|
|
939
1052
|
qreg q[2];
|
|
940
1053
|
{qasm_gate} q[0];
|
|
941
1054
|
"""
|
|
@@ -946,19 +1059,27 @@ def test_two_qubit_gates_not_enough_args(qasm_gate: str):
|
|
|
946
1059
|
parser.parse(qasm)
|
|
947
1060
|
|
|
948
1061
|
|
|
949
|
-
@pytest.mark.parametrize(
|
|
1062
|
+
@pytest.mark.parametrize(
|
|
1063
|
+
'qasm_gate', [g[0] for g in two_qubit_gates] + [g[0] for g in two_qubit_param_gates.keys()]
|
|
1064
|
+
)
|
|
950
1065
|
def test_two_qubit_gates_with_too_much_parameters(qasm_gate: str):
|
|
1066
|
+
if qasm_gate in ('cu1', 'cu3', 'crz'):
|
|
1067
|
+
num_params_needed = 3 if qasm_gate == 'cu3' else 1
|
|
1068
|
+
else:
|
|
1069
|
+
num_params_needed = 0
|
|
1070
|
+
|
|
951
1071
|
qasm = f"""
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
"""
|
|
1072
|
+
OPENQASM 2.0;
|
|
1073
|
+
include "qelib1.inc";
|
|
1074
|
+
qreg q[2];
|
|
1075
|
+
{qasm_gate}(pi, pi/2, pi/3, pi/4) q[0],q[1];
|
|
1076
|
+
"""
|
|
957
1077
|
|
|
958
1078
|
parser = QasmParser()
|
|
959
1079
|
|
|
960
1080
|
with pytest.raises(
|
|
961
|
-
QasmException,
|
|
1081
|
+
QasmException,
|
|
1082
|
+
match=rf".*{qasm_gate}*. takes {num_params_needed} parameter\(s\).*got.*4.*line 5",
|
|
962
1083
|
):
|
|
963
1084
|
parser.parse(qasm)
|
|
964
1085
|
|
|
@@ -1057,3 +1178,337 @@ def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.Gate):
|
|
|
1057
1178
|
|
|
1058
1179
|
ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
|
|
1059
1180
|
assert parsed_qasm.qregs == {'q': 2}
|
|
1181
|
+
|
|
1182
|
+
|
|
1183
|
+
def test_openqasm_3_0_qubits():
|
|
1184
|
+
qasm = """OPENQASM 3.0;
|
|
1185
|
+
include "stdgates.inc";
|
|
1186
|
+
qubit[2] q;
|
|
1187
|
+
bit[2] b;
|
|
1188
|
+
|
|
1189
|
+
x q[0];
|
|
1190
|
+
|
|
1191
|
+
b[0] = measure q[0];
|
|
1192
|
+
reset q[0];
|
|
1193
|
+
"""
|
|
1194
|
+
parser = QasmParser()
|
|
1195
|
+
|
|
1196
|
+
q0 = cirq.NamedQubit('q_0')
|
|
1197
|
+
|
|
1198
|
+
expected_circuit = Circuit([cirq.X.on(q0), cirq.measure(q0, key='b_0'), cirq.reset(q0)])
|
|
1199
|
+
|
|
1200
|
+
parsed_qasm = parser.parse(qasm)
|
|
1201
|
+
|
|
1202
|
+
assert parsed_qasm.supportedFormat
|
|
1203
|
+
|
|
1204
|
+
ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
|
|
1205
|
+
assert parsed_qasm.qregs == {'q': 2}
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
def test_openqasm_3_0_scalar_qubit():
|
|
1209
|
+
qasm = """OPENQASM 3.0;
|
|
1210
|
+
include "stdgates.inc";
|
|
1211
|
+
qubit q;
|
|
1212
|
+
bit b;
|
|
1213
|
+
|
|
1214
|
+
x q;
|
|
1215
|
+
|
|
1216
|
+
b = measure q;
|
|
1217
|
+
reset q;
|
|
1218
|
+
"""
|
|
1219
|
+
parser = QasmParser()
|
|
1220
|
+
|
|
1221
|
+
q0 = cirq.NamedQubit('q_0')
|
|
1222
|
+
|
|
1223
|
+
expected_circuit = Circuit([cirq.X.on(q0), cirq.measure(q0, key='b_0'), cirq.reset(q0)])
|
|
1224
|
+
|
|
1225
|
+
parsed_qasm = parser.parse(qasm)
|
|
1226
|
+
|
|
1227
|
+
assert parsed_qasm.supportedFormat
|
|
1228
|
+
|
|
1229
|
+
ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit)
|
|
1230
|
+
assert parsed_qasm.qregs == {'q': 1}
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
def test_custom_gate():
|
|
1234
|
+
qasm = """OPENQASM 2.0;
|
|
1235
|
+
include "qelib1.inc";
|
|
1236
|
+
qreg q[2];
|
|
1237
|
+
gate g q0, q1 {
|
|
1238
|
+
x q0;
|
|
1239
|
+
y q0;
|
|
1240
|
+
z q1;
|
|
1241
|
+
}
|
|
1242
|
+
g q[0], q[1];
|
|
1243
|
+
g q[1], q[0];
|
|
1244
|
+
"""
|
|
1245
|
+
|
|
1246
|
+
# The gate definition should translate to this
|
|
1247
|
+
q0, q1 = cirq.NamedQubit.range(2, prefix='q')
|
|
1248
|
+
g = cirq.FrozenCircuit(cirq.X(q0), cirq.Y(q0), cirq.Z(q1))
|
|
1249
|
+
|
|
1250
|
+
# The outer circuit should then translate to this
|
|
1251
|
+
q_0, q_1 = cirq.NamedQubit.range(2, prefix='q_') # The outer qreg array
|
|
1252
|
+
expected = cirq.Circuit(
|
|
1253
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_0, q1: q_1}),
|
|
1254
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_1, q1: q_0}),
|
|
1255
|
+
)
|
|
1256
|
+
|
|
1257
|
+
# Verify
|
|
1258
|
+
parser = QasmParser()
|
|
1259
|
+
parsed_qasm = parser.parse(qasm)
|
|
1260
|
+
assert parsed_qasm.circuit == expected
|
|
1261
|
+
|
|
1262
|
+
# Sanity check that this unrolls to a valid circuit
|
|
1263
|
+
unrolled_expected = cirq.Circuit(
|
|
1264
|
+
cirq.X(q_0), cirq.Y(q_0), cirq.Z(q_1), cirq.X(q_1), cirq.Y(q_1), cirq.Z(q_0)
|
|
1265
|
+
)
|
|
1266
|
+
unrolled = cirq.align_left(cirq.unroll_circuit_op(parsed_qasm.circuit, tags_to_check=None))
|
|
1267
|
+
assert unrolled == unrolled_expected
|
|
1268
|
+
|
|
1269
|
+
# Sanity check that these have the same unitaries as the QASM.
|
|
1270
|
+
cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(parsed_qasm.circuit))
|
|
1271
|
+
cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
def test_custom_gate_parameterized():
|
|
1275
|
+
qasm = """OPENQASM 2.0;
|
|
1276
|
+
include "qelib1.inc";
|
|
1277
|
+
qreg q[2];
|
|
1278
|
+
gate g(p0, p1) q0, q1 {
|
|
1279
|
+
rx(p0) q0;
|
|
1280
|
+
ry(p0+p1+3) q0;
|
|
1281
|
+
rz(p1) q1;
|
|
1282
|
+
}
|
|
1283
|
+
g(1,2) q[0], q[1];
|
|
1284
|
+
g(0,4) q[1], q[0];
|
|
1285
|
+
"""
|
|
1286
|
+
|
|
1287
|
+
# The gate definition should translate to this
|
|
1288
|
+
p0, p1 = sympy.symbols('p0, p1')
|
|
1289
|
+
q0, q1 = cirq.NamedQubit.range(2, prefix='q')
|
|
1290
|
+
g = cirq.FrozenCircuit(
|
|
1291
|
+
cirq.Rx(rads=p0).on(q0), cirq.Ry(rads=p0 + p1 + 3).on(q0), cirq.Rz(rads=p1).on(q1)
|
|
1292
|
+
)
|
|
1293
|
+
|
|
1294
|
+
# The outer circuit should then translate to this
|
|
1295
|
+
q_0, q_1 = cirq.NamedQubit.range(2, prefix='q_') # The outer qreg array
|
|
1296
|
+
expected = cirq.Circuit(
|
|
1297
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_0, q1: q_1}, param_resolver={'p0': 1, 'p1': 2}),
|
|
1298
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_1, q1: q_0}, param_resolver={'p0': 0, 'p1': 4}),
|
|
1299
|
+
)
|
|
1300
|
+
|
|
1301
|
+
# Verify
|
|
1302
|
+
parser = QasmParser()
|
|
1303
|
+
parsed_qasm = parser.parse(qasm)
|
|
1304
|
+
assert parsed_qasm.circuit == expected
|
|
1305
|
+
|
|
1306
|
+
# Sanity check that this unrolls to a valid circuit
|
|
1307
|
+
unrolled_expected = cirq.Circuit(
|
|
1308
|
+
cirq.Rx(rads=1).on(q_0),
|
|
1309
|
+
cirq.Ry(rads=6).on(q_0),
|
|
1310
|
+
cirq.Rz(rads=2).on(q_1),
|
|
1311
|
+
cirq.Rx(rads=0).on(q_1),
|
|
1312
|
+
cirq.Ry(rads=7).on(q_1),
|
|
1313
|
+
cirq.Rz(rads=4).on(q_0),
|
|
1314
|
+
)
|
|
1315
|
+
unrolled = cirq.align_left(cirq.unroll_circuit_op(parsed_qasm.circuit, tags_to_check=None))
|
|
1316
|
+
assert unrolled == unrolled_expected
|
|
1317
|
+
|
|
1318
|
+
# Sanity check that these have the same unitaries as the QASM.
|
|
1319
|
+
cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(parsed_qasm.circuit))
|
|
1320
|
+
cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
def test_custom_gate_broadcast():
|
|
1324
|
+
qasm = """OPENQASM 2.0;
|
|
1325
|
+
include "qelib1.inc";
|
|
1326
|
+
qreg q[3];
|
|
1327
|
+
gate g q0 {
|
|
1328
|
+
x q0;
|
|
1329
|
+
y q0;
|
|
1330
|
+
z q0;
|
|
1331
|
+
}
|
|
1332
|
+
g q; // broadcast to all qubits in register
|
|
1333
|
+
"""
|
|
1334
|
+
|
|
1335
|
+
# The gate definition should translate to this
|
|
1336
|
+
q0 = cirq.NamedQubit('q0')
|
|
1337
|
+
g = cirq.FrozenCircuit(cirq.X(q0), cirq.Y(q0), cirq.Z(q0))
|
|
1338
|
+
|
|
1339
|
+
# The outer circuit should then translate to this
|
|
1340
|
+
q_0, q_1, q_2 = cirq.NamedQubit.range(3, prefix='q_') # The outer qreg array
|
|
1341
|
+
expected = cirq.Circuit(
|
|
1342
|
+
# It is broadcast to all qubits in the qreg
|
|
1343
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_0}),
|
|
1344
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_1}),
|
|
1345
|
+
cirq.CircuitOperation(g, qubit_map={q0: q_2}),
|
|
1346
|
+
)
|
|
1347
|
+
|
|
1348
|
+
# Verify
|
|
1349
|
+
parser = QasmParser()
|
|
1350
|
+
parsed_qasm = parser.parse(qasm)
|
|
1351
|
+
assert parsed_qasm.circuit == expected
|
|
1352
|
+
|
|
1353
|
+
# Sanity check that this unrolls to a valid circuit
|
|
1354
|
+
unrolled_expected = cirq.Circuit(
|
|
1355
|
+
cirq.X(q_0),
|
|
1356
|
+
cirq.Y(q_0),
|
|
1357
|
+
cirq.Z(q_0),
|
|
1358
|
+
cirq.X(q_1),
|
|
1359
|
+
cirq.Y(q_1),
|
|
1360
|
+
cirq.Z(q_1),
|
|
1361
|
+
cirq.X(q_2),
|
|
1362
|
+
cirq.Y(q_2),
|
|
1363
|
+
cirq.Z(q_2),
|
|
1364
|
+
)
|
|
1365
|
+
unrolled = cirq.align_left(cirq.unroll_circuit_op(parsed_qasm.circuit, tags_to_check=None))
|
|
1366
|
+
assert unrolled == unrolled_expected
|
|
1367
|
+
|
|
1368
|
+
# Sanity check that these have the same unitaries as the QASM.
|
|
1369
|
+
cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(parsed_qasm.circuit))
|
|
1370
|
+
cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq.unitary(unrolled))
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
def test_custom_gate_undefined_qubit_error():
|
|
1374
|
+
qasm = """OPENQASM 2.0;
|
|
1375
|
+
include "qelib1.inc";
|
|
1376
|
+
qreg q[1];
|
|
1377
|
+
gate g q0 { x q1; }
|
|
1378
|
+
g q
|
|
1379
|
+
"""
|
|
1380
|
+
_test_parse_exception(
|
|
1381
|
+
qasm,
|
|
1382
|
+
cirq_err="Undefined qubit 'q1' at line 4",
|
|
1383
|
+
qiskit_err="4,19: 'q1' is not defined in this scope",
|
|
1384
|
+
)
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
def test_custom_gate_qubit_scope_closure_error():
|
|
1388
|
+
qasm = """OPENQASM 2.0;
|
|
1389
|
+
include "qelib1.inc";
|
|
1390
|
+
qreg q[1];
|
|
1391
|
+
gate g q0 { x q; }
|
|
1392
|
+
g q
|
|
1393
|
+
"""
|
|
1394
|
+
_test_parse_exception(
|
|
1395
|
+
qasm,
|
|
1396
|
+
cirq_err="'q' is a register, not a qubit at line 4",
|
|
1397
|
+
qiskit_err="4,19: 'q' is a quantum register, not a qubit",
|
|
1398
|
+
)
|
|
1399
|
+
|
|
1400
|
+
|
|
1401
|
+
def test_custom_gate_qubit_index_error():
|
|
1402
|
+
qasm = """OPENQASM 2.0;
|
|
1403
|
+
include "qelib1.inc";
|
|
1404
|
+
qreg q[1];
|
|
1405
|
+
gate g q0 { x q0[0]; }
|
|
1406
|
+
g q
|
|
1407
|
+
"""
|
|
1408
|
+
_test_parse_exception(
|
|
1409
|
+
qasm,
|
|
1410
|
+
cirq_err="Unsupported indexed qreg 'q0[0]' at line 4",
|
|
1411
|
+
qiskit_err="4,21: needed ';', but instead saw [",
|
|
1412
|
+
)
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
def test_custom_gate_qreg_count_error():
|
|
1416
|
+
qasm = """OPENQASM 2.0;
|
|
1417
|
+
include "qelib1.inc";
|
|
1418
|
+
qreg q[2];
|
|
1419
|
+
gate g q0 { x q0; }
|
|
1420
|
+
g q[0], q[1];
|
|
1421
|
+
"""
|
|
1422
|
+
_test_parse_exception(
|
|
1423
|
+
qasm,
|
|
1424
|
+
cirq_err="Wrong number of qregs for 'g' at line 5",
|
|
1425
|
+
qiskit_err="5,5: 'g' takes 1 quantum argument, but got 2",
|
|
1426
|
+
)
|
|
1427
|
+
|
|
1428
|
+
|
|
1429
|
+
def test_custom_gate_missing_param_error():
|
|
1430
|
+
qasm = """OPENQASM 2.0;
|
|
1431
|
+
include "qelib1.inc";
|
|
1432
|
+
qreg q[1];
|
|
1433
|
+
gate g(p) q0 { rx(p) q0; }
|
|
1434
|
+
g q;
|
|
1435
|
+
"""
|
|
1436
|
+
_test_parse_exception(
|
|
1437
|
+
qasm,
|
|
1438
|
+
cirq_err="Wrong number of params for 'g' at line 5",
|
|
1439
|
+
qiskit_err=None, # Qiskit bug? It's an invalid circuit that won't simulate.
|
|
1440
|
+
)
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
def test_custom_gate_extra_param_error():
|
|
1444
|
+
qasm = """OPENQASM 2.0;
|
|
1445
|
+
include "qelib1.inc";
|
|
1446
|
+
qreg q[1];
|
|
1447
|
+
gate g q0 { x q0; }
|
|
1448
|
+
g(3) q;
|
|
1449
|
+
"""
|
|
1450
|
+
_test_parse_exception(
|
|
1451
|
+
qasm,
|
|
1452
|
+
cirq_err="Wrong number of params for 'g' at line 5",
|
|
1453
|
+
qiskit_err="5,5: 'g' takes 0 parameters, but got 1",
|
|
1454
|
+
)
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
def test_custom_gate_undefined_param_error():
|
|
1458
|
+
qasm = """OPENQASM 2.0;
|
|
1459
|
+
include "qelib1.inc";
|
|
1460
|
+
qreg q[1];
|
|
1461
|
+
gate g q0 { rx(p) q0; }
|
|
1462
|
+
g q;
|
|
1463
|
+
"""
|
|
1464
|
+
_test_parse_exception(
|
|
1465
|
+
qasm,
|
|
1466
|
+
cirq_err="Undefined parameter 'p' in line 4",
|
|
1467
|
+
qiskit_err="4,20: 'p' is not a parameter",
|
|
1468
|
+
)
|
|
1469
|
+
|
|
1470
|
+
|
|
1471
|
+
def test_top_level_param_error():
|
|
1472
|
+
qasm = """OPENQASM 2.0;
|
|
1473
|
+
include "qelib1.inc";
|
|
1474
|
+
qreg q[1];
|
|
1475
|
+
rx(p) q;
|
|
1476
|
+
"""
|
|
1477
|
+
_test_parse_exception(
|
|
1478
|
+
qasm,
|
|
1479
|
+
cirq_err="Parameter 'p' in line 4 not supported",
|
|
1480
|
+
qiskit_err="4,8: 'p' is not a parameter",
|
|
1481
|
+
)
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
def _test_parse_exception(qasm: str, cirq_err: str, qiskit_err: str | None):
|
|
1485
|
+
parser = QasmParser()
|
|
1486
|
+
with pytest.raises(QasmException, match=re.escape(cirq_err)):
|
|
1487
|
+
parser.parse(qasm)
|
|
1488
|
+
pytest.importorskip("qiskit")
|
|
1489
|
+
import qiskit.qasm2
|
|
1490
|
+
|
|
1491
|
+
if qiskit_err is None:
|
|
1492
|
+
qiskit.QuantumCircuit.from_qasm_str(qasm)
|
|
1493
|
+
return
|
|
1494
|
+
with pytest.raises(qiskit.qasm2.exceptions.QASM2ParseError, match=re.escape(qiskit_err)):
|
|
1495
|
+
qiskit.QuantumCircuit.from_qasm_str(qasm)
|
|
1496
|
+
|
|
1497
|
+
|
|
1498
|
+
def test_nested_custom_gate_has_keyword_in_name():
|
|
1499
|
+
qasm = """OPENQASM 2.0;
|
|
1500
|
+
include "qelib1.inc";
|
|
1501
|
+
qreg q[1];
|
|
1502
|
+
gate gateGate qb { x qb; }
|
|
1503
|
+
gate qregGate qa { gateGate qa; }
|
|
1504
|
+
qregGate q;
|
|
1505
|
+
"""
|
|
1506
|
+
qb = cirq.NamedQubit('qb')
|
|
1507
|
+
inner = cirq.FrozenCircuit(cirq.X(qb))
|
|
1508
|
+
qa = cirq.NamedQubit('qa')
|
|
1509
|
+
middle = cirq.FrozenCircuit(cirq.CircuitOperation(inner, qubit_map={qb: qa}))
|
|
1510
|
+
q_0 = cirq.NamedQubit('q_0')
|
|
1511
|
+
expected = cirq.Circuit(cirq.CircuitOperation(middle, qubit_map={qa: q_0}))
|
|
1512
|
+
parser = QasmParser()
|
|
1513
|
+
parsed_qasm = parser.parse(qasm)
|
|
1514
|
+
assert parsed_qasm.circuit == expected
|