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,17 +14,24 @@
|
|
|
14
14
|
|
|
15
15
|
"""Creates the abstraction for gauge compiling as a cirq transformer."""
|
|
16
16
|
|
|
17
|
-
from typing import Callable, Tuple, Optional, Sequence, Union, List
|
|
18
17
|
import abc
|
|
19
|
-
import itertools
|
|
20
18
|
import functools
|
|
21
|
-
|
|
19
|
+
import itertools
|
|
22
20
|
from dataclasses import dataclass
|
|
23
|
-
from
|
|
24
|
-
import
|
|
21
|
+
from numbers import Real
|
|
22
|
+
from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union
|
|
25
23
|
|
|
24
|
+
import numpy as np
|
|
25
|
+
import sympy
|
|
26
|
+
from attrs import field, frozen
|
|
27
|
+
|
|
28
|
+
from cirq import circuits, ops
|
|
29
|
+
from cirq.protocols import unitary_protocol
|
|
30
|
+
from cirq.protocols.has_unitary_protocol import has_unitary
|
|
31
|
+
from cirq.study import sweepable
|
|
32
|
+
from cirq.study.sweeps import Points, Zip
|
|
26
33
|
from cirq.transformers import transformer_api
|
|
27
|
-
from cirq import
|
|
34
|
+
from cirq.transformers.analytical_decompositions import single_qubit_decompositions
|
|
28
35
|
|
|
29
36
|
|
|
30
37
|
class Gauge(abc.ABC):
|
|
@@ -122,6 +129,43 @@ class SameGateGauge(Gauge):
|
|
|
122
129
|
)
|
|
123
130
|
|
|
124
131
|
|
|
132
|
+
@frozen
|
|
133
|
+
class TwoQubitGateSymbolizer:
|
|
134
|
+
"""Parameterizes two qubit gates with symbols.
|
|
135
|
+
|
|
136
|
+
Attributes:
|
|
137
|
+
symbolizer: A callable that takes a two-qubit gate and a sequence of symbols,
|
|
138
|
+
and returns a tuple containing the parameterized gate and a dictionary
|
|
139
|
+
mapping symbol names to their values.
|
|
140
|
+
n_symbols: The number of symbols to use for parameterization.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
symbolizer_fn: Callable[[ops.Gate, Sequence[sympy.Symbol]], Tuple[ops.Gate, Dict[str, Real]]]
|
|
144
|
+
n_symbols: int
|
|
145
|
+
|
|
146
|
+
def __call__(
|
|
147
|
+
self, two_qubit_gate: ops.Gate, symbols: Sequence[sympy.Symbol]
|
|
148
|
+
) -> Tuple[ops.Gate, Dict[str, Real]]:
|
|
149
|
+
"""Symbolizes a two qubit gate to a parameterized gate.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
two_qubit_gate: The 2 qubit gate to be symbolized.
|
|
153
|
+
symbols: A sequence of sympy symbols to use for parameterization.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
A tuple containing the parameterized gate and a dictionary mapping
|
|
157
|
+
symbol names to their values.
|
|
158
|
+
|
|
159
|
+
Raises:
|
|
160
|
+
ValueError: If the provided symbols do not match the expected number.
|
|
161
|
+
"""
|
|
162
|
+
if len(symbols) != self.n_symbols:
|
|
163
|
+
raise ValueError(
|
|
164
|
+
f"Expect {self.n_symbols} symbols, but got {len(symbols)} symbols in {symbols}"
|
|
165
|
+
)
|
|
166
|
+
return self.symbolizer_fn(two_qubit_gate, symbols)
|
|
167
|
+
|
|
168
|
+
|
|
125
169
|
def _select(choices: Sequence[Gauge], probabilites: np.ndarray, prng: np.random.Generator) -> Gauge:
|
|
126
170
|
return choices[prng.choice(len(choices), p=probabilites)]
|
|
127
171
|
|
|
@@ -144,12 +188,14 @@ class GaugeSelector:
|
|
|
144
188
|
|
|
145
189
|
@transformer_api.transformer
|
|
146
190
|
class GaugeTransformer:
|
|
191
|
+
|
|
147
192
|
def __init__(
|
|
148
193
|
self,
|
|
149
194
|
# target can be either a specific gate, gatefamily or gateset
|
|
150
195
|
# which allows matching parametric gates.
|
|
151
196
|
target: Union[ops.Gate, ops.Gateset, ops.GateFamily],
|
|
152
197
|
gauge_selector: Callable[[np.random.Generator], Gauge],
|
|
198
|
+
two_qubit_gate_symbolizer: Optional[TwoQubitGateSymbolizer] = None,
|
|
153
199
|
) -> None:
|
|
154
200
|
"""Constructs a GaugeTransformer.
|
|
155
201
|
|
|
@@ -157,9 +203,11 @@ class GaugeTransformer:
|
|
|
157
203
|
target: Target two-qubit gate, a gate-family or a gate-set of two-qubit gates.
|
|
158
204
|
gauge_selector: A callable that takes a numpy random number generator
|
|
159
205
|
as an argument and returns a Gauge.
|
|
206
|
+
two_qubit_gate_symbolizer: A symbolizer to symbolize 2 qubit gates.
|
|
160
207
|
"""
|
|
161
208
|
self.target = ops.GateFamily(target) if isinstance(target, ops.Gate) else target
|
|
162
209
|
self.gauge_selector = gauge_selector
|
|
210
|
+
self.two_qubit_gate_symbolizer = two_qubit_gate_symbolizer
|
|
163
211
|
|
|
164
212
|
def __call__(
|
|
165
213
|
self,
|
|
@@ -201,6 +249,148 @@ class GaugeTransformer:
|
|
|
201
249
|
new_moments.extend(_build_moments(right))
|
|
202
250
|
return circuits.Circuit.from_moments(*new_moments)
|
|
203
251
|
|
|
252
|
+
def as_sweep(
|
|
253
|
+
self,
|
|
254
|
+
circuit: circuits.AbstractCircuit,
|
|
255
|
+
*,
|
|
256
|
+
N: int,
|
|
257
|
+
context: Optional[transformer_api.TransformerContext] = None,
|
|
258
|
+
prng: Optional[np.random.Generator] = None,
|
|
259
|
+
) -> Tuple[circuits.AbstractCircuit, sweepable.Sweepable]:
|
|
260
|
+
"""Generates a parameterized circuit with *N* sets of sweepable parameters.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
circuit: The input circuit to be processed by gauge compiling.
|
|
264
|
+
N: The number of parameter sets to generate.
|
|
265
|
+
context: A `cirq.TransformerContext` storing common configurable options for
|
|
266
|
+
the transformers.
|
|
267
|
+
prng: A pseudo-random number generator to select a gauge within a gauge cluster.
|
|
268
|
+
"""
|
|
269
|
+
|
|
270
|
+
rng = np.random.default_rng() if prng is None else prng
|
|
271
|
+
if context is None:
|
|
272
|
+
context = transformer_api.TransformerContext(deep=False)
|
|
273
|
+
if context.deep:
|
|
274
|
+
raise ValueError('GaugeTransformer cannot be used with deep=True')
|
|
275
|
+
new_moments: List[List[ops.Operation]] = [] # Store parameterized circuits.
|
|
276
|
+
phxz_sid = itertools.count()
|
|
277
|
+
two_qubit_gate_sid = itertools.count()
|
|
278
|
+
# Map from "((pre|post),$qid,$moment_id)" to gate parameters.
|
|
279
|
+
# E.g., {(post,q1,2): {"x_exponent": "x1", "z_exponent": "z1", "axis_phase": "a1"}}
|
|
280
|
+
phxz_symbols_by_locs: Dict[Tuple[str, ops.Qid, int], Dict[str, sympy.Symbol]] = {}
|
|
281
|
+
# Map from "($q0,$q1,$moment_id)" to gate parameters.
|
|
282
|
+
# E.g., {(q0,q1,0): ["s0"]}.
|
|
283
|
+
two_qubit_gate_symbols_by_locs: Dict[Tuple[ops.Qid, ops.Qid, int], List[sympy.Symbol]] = {}
|
|
284
|
+
|
|
285
|
+
def single_qubit_next_symbol() -> Dict[str, sympy.Symbol]:
|
|
286
|
+
sid = next(phxz_sid)
|
|
287
|
+
return _parameterize_to_phxz(sid)
|
|
288
|
+
|
|
289
|
+
def two_qubit_gate_next_symbol_list(n: int) -> List[sympy.Symbol]:
|
|
290
|
+
"""Returns symbols for 2 qubit gate parameterization."""
|
|
291
|
+
sid = next(two_qubit_gate_sid)
|
|
292
|
+
symbols: List[sympy.Symbol] = [sympy.Symbol(f"s{sid}_{sub}") for sub in range(n)]
|
|
293
|
+
return symbols
|
|
294
|
+
|
|
295
|
+
# Build parameterized circuit.
|
|
296
|
+
for moment_id, moment in enumerate(circuit):
|
|
297
|
+
center_moment: List[ops.Operation] = []
|
|
298
|
+
left_moment: List[ops.Operation] = []
|
|
299
|
+
right_moment: List[ops.Operation] = []
|
|
300
|
+
for op in moment:
|
|
301
|
+
if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
|
|
302
|
+
context.tags_to_ignore
|
|
303
|
+
):
|
|
304
|
+
center_moment.append(op)
|
|
305
|
+
continue
|
|
306
|
+
if op.gate is not None and op in self.target:
|
|
307
|
+
random_gauge = self.gauge_selector(rng).sample(op.gate, rng)
|
|
308
|
+
# Build symbols for 2-qubit-gates if the transformer might transform it,
|
|
309
|
+
# otherwise, keep it as it is.
|
|
310
|
+
if self.two_qubit_gate_symbolizer is not None:
|
|
311
|
+
symbols: list[sympy.Symbol] = two_qubit_gate_next_symbol_list(
|
|
312
|
+
self.two_qubit_gate_symbolizer.n_symbols
|
|
313
|
+
)
|
|
314
|
+
two_qubit_gate_symbols_by_locs[(op.qubits[0], op.qubits[1], moment_id)] = (
|
|
315
|
+
symbols
|
|
316
|
+
)
|
|
317
|
+
parameterized_2_qubit_gate, _ = self.two_qubit_gate_symbolizer(
|
|
318
|
+
random_gauge.two_qubit_gate, symbols
|
|
319
|
+
)
|
|
320
|
+
center_moment.append(parameterized_2_qubit_gate.on(*op.qubits))
|
|
321
|
+
else:
|
|
322
|
+
center_moment.append(op)
|
|
323
|
+
# Build symbols for the gauge, for a 2-qubit gauge, symbols will be built for
|
|
324
|
+
# pre/post q0/q1 and the new 2-qubit gate if the 2-qubit gate is updated in
|
|
325
|
+
# the gauge compiling.
|
|
326
|
+
for prefix, q in itertools.product(["pre", "post"], op.qubits):
|
|
327
|
+
xza_by_symbols = single_qubit_next_symbol() # xza in phased xz gate.
|
|
328
|
+
phxz_symbols_by_locs[(prefix, q, moment_id)] = xza_by_symbols
|
|
329
|
+
new_op = ops.PhasedXZGate(**xza_by_symbols).on(q)
|
|
330
|
+
if prefix == "pre":
|
|
331
|
+
left_moment.append(new_op)
|
|
332
|
+
else:
|
|
333
|
+
right_moment.append(new_op)
|
|
334
|
+
else:
|
|
335
|
+
center_moment.append(op)
|
|
336
|
+
new_moments.extend(
|
|
337
|
+
[moment for moment in [left_moment, center_moment, right_moment] if moment]
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
# Initialize the map from symbol names to their N values.
|
|
341
|
+
values_by_params: Dict[str, List[float]] = {
|
|
342
|
+
**{
|
|
343
|
+
str(symbol): []
|
|
344
|
+
for symbols_by_names in phxz_symbols_by_locs.values()
|
|
345
|
+
for symbol in symbols_by_names.values()
|
|
346
|
+
},
|
|
347
|
+
**{
|
|
348
|
+
str(symbol): []
|
|
349
|
+
for symbols in two_qubit_gate_symbols_by_locs.values()
|
|
350
|
+
for symbol in symbols
|
|
351
|
+
},
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
# Assign values for parameters via randomly chosen GaugeSelector.
|
|
355
|
+
for _ in range(N):
|
|
356
|
+
for moment_id, moment in enumerate(circuit):
|
|
357
|
+
for op in moment:
|
|
358
|
+
if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
|
|
359
|
+
context.tags_to_ignore
|
|
360
|
+
):
|
|
361
|
+
continue
|
|
362
|
+
if op.gate is not None and len(op.qubits) == 2 and op in self.target:
|
|
363
|
+
gauge = self.gauge_selector(rng).sample(op.gate, rng)
|
|
364
|
+
|
|
365
|
+
# Get the params for 2 qubit gates.
|
|
366
|
+
if self.two_qubit_gate_symbolizer is not None:
|
|
367
|
+
_, vals_by_symbols = self.two_qubit_gate_symbolizer(
|
|
368
|
+
gauge.two_qubit_gate,
|
|
369
|
+
[
|
|
370
|
+
*two_qubit_gate_symbols_by_locs[
|
|
371
|
+
(op.qubits[0], op.qubits[1], moment_id)
|
|
372
|
+
]
|
|
373
|
+
],
|
|
374
|
+
)
|
|
375
|
+
for symbol_str, val in vals_by_symbols.items():
|
|
376
|
+
values_by_params[symbol_str].append(float(val))
|
|
377
|
+
|
|
378
|
+
# Get the params of pre/post q0/q1 gates.
|
|
379
|
+
for pre_or_post, idx in itertools.product(["pre", "post"], [0, 1]):
|
|
380
|
+
gates = getattr(gauge, f"{pre_or_post}_q{idx}")
|
|
381
|
+
phxz_params = _gate_sequence_to_phxz_params(
|
|
382
|
+
gates,
|
|
383
|
+
phxz_symbols_by_locs[(pre_or_post, op.qubits[idx], moment_id)],
|
|
384
|
+
)
|
|
385
|
+
for key, value in phxz_params.items():
|
|
386
|
+
values_by_params[key].append(float(value))
|
|
387
|
+
|
|
388
|
+
sweeps: List[Points] = [
|
|
389
|
+
Points(key=key, points=values) for key, values in values_by_params.items()
|
|
390
|
+
]
|
|
391
|
+
|
|
392
|
+
return circuits.Circuit.from_moments(*new_moments), Zip(*sweeps)
|
|
393
|
+
|
|
204
394
|
|
|
205
395
|
def _build_moments(operation_by_qubits: List[List[ops.Operation]]) -> List[List[ops.Operation]]:
|
|
206
396
|
"""Builds moments from a list of operations grouped by qubits.
|
|
@@ -212,3 +402,52 @@ def _build_moments(operation_by_qubits: List[List[ops.Operation]]) -> List[List[
|
|
|
212
402
|
for moment in itertools.zip_longest(*operation_by_qubits):
|
|
213
403
|
moments.append([op for op in moment if op is not None])
|
|
214
404
|
return moments
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def _parameterize_to_phxz(symbol_id: int) -> Dict[str, sympy.Symbol]:
|
|
408
|
+
"""Returns symbolized parameters for the gate."""
|
|
409
|
+
|
|
410
|
+
# Parameterize single qubit gate to parameterized PhasedXZGate.
|
|
411
|
+
phased_xz_params = {
|
|
412
|
+
"x_exponent": sympy.Symbol(f"x{symbol_id}"),
|
|
413
|
+
"z_exponent": sympy.Symbol(f"z{symbol_id}"),
|
|
414
|
+
"axis_phase_exponent": sympy.Symbol(f"a{symbol_id}"),
|
|
415
|
+
}
|
|
416
|
+
return phased_xz_params
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def _gate_sequence_to_phxz_params(
|
|
420
|
+
gates: Tuple[ops.Gate, ...], xza_by_symbols: Dict[str, sympy.Symbol]
|
|
421
|
+
) -> Dict[str, float]:
|
|
422
|
+
identity_gate_in_phxz = {
|
|
423
|
+
str(xza_by_symbols["x_exponent"]): 0.0,
|
|
424
|
+
str(xza_by_symbols["z_exponent"]): 0.0,
|
|
425
|
+
str(xza_by_symbols["axis_phase_exponent"]): 0.0,
|
|
426
|
+
}
|
|
427
|
+
if not gates:
|
|
428
|
+
return identity_gate_in_phxz
|
|
429
|
+
for gate in gates:
|
|
430
|
+
if not has_unitary(gate) or gate.num_qubits() != 1:
|
|
431
|
+
raise ValueError(
|
|
432
|
+
"Invalid gate sequence to be converted to PhasedXZGate."
|
|
433
|
+
f"Found incompatiable gate {gate} in sequence."
|
|
434
|
+
)
|
|
435
|
+
phxz = (
|
|
436
|
+
single_qubit_decompositions.single_qubit_matrix_to_phxz(
|
|
437
|
+
functools.reduce(
|
|
438
|
+
np.matmul, [unitary_protocol.unitary(gate) for gate in reversed(gates)]
|
|
439
|
+
)
|
|
440
|
+
)
|
|
441
|
+
or ops.I
|
|
442
|
+
)
|
|
443
|
+
if phxz is ops.I: # Identity gate
|
|
444
|
+
return identity_gate_in_phxz
|
|
445
|
+
# Check the gate type, needs to be a PhasedXZ gate.
|
|
446
|
+
if not isinstance(phxz, ops.PhasedXZGate):
|
|
447
|
+
raise ValueError("Failed to convert the gate sequence to a PhasedXZ gate.")
|
|
448
|
+
if phxz is not None:
|
|
449
|
+
return {
|
|
450
|
+
str(xza_by_symbols["x_exponent"]): phxz.x_exponent,
|
|
451
|
+
str(xza_by_symbols["z_exponent"]): phxz.z_exponent,
|
|
452
|
+
str(xza_by_symbols["axis_phase_exponent"]): phxz.axis_phase_exponent,
|
|
453
|
+
}
|
|
@@ -12,10 +12,23 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import
|
|
15
|
+
import unittest.mock
|
|
16
|
+
|
|
16
17
|
import numpy as np
|
|
18
|
+
import pytest
|
|
19
|
+
import sympy
|
|
20
|
+
|
|
17
21
|
import cirq
|
|
18
|
-
from cirq.transformers.
|
|
22
|
+
from cirq.transformers.analytical_decompositions import single_qubit_decompositions
|
|
23
|
+
from cirq.transformers.gauge_compiling import (
|
|
24
|
+
ConstantGauge,
|
|
25
|
+
CZGaugeTransformer,
|
|
26
|
+
GaugeSelector,
|
|
27
|
+
GaugeTransformer,
|
|
28
|
+
SqrtCZGaugeTransformer,
|
|
29
|
+
TwoQubitGateSymbolizer,
|
|
30
|
+
)
|
|
31
|
+
from cirq.transformers.gauge_compiling.sqrt_cz_gauge import SqrtCZGauge
|
|
19
32
|
|
|
20
33
|
|
|
21
34
|
def test_deep_transformation_not_supported():
|
|
@@ -25,10 +38,19 @@ def test_deep_transformation_not_supported():
|
|
|
25
38
|
cirq.Circuit(), context=cirq.TransformerContext(deep=True)
|
|
26
39
|
)
|
|
27
40
|
|
|
41
|
+
with pytest.raises(ValueError, match="cannot be used with deep=True"):
|
|
42
|
+
_ = GaugeTransformer(target=cirq.CZ, gauge_selector=lambda _: None).as_sweep(
|
|
43
|
+
cirq.Circuit(), context=cirq.TransformerContext(deep=True), N=1
|
|
44
|
+
)
|
|
45
|
+
|
|
28
46
|
|
|
29
47
|
def test_ignore_tags():
|
|
30
48
|
c = cirq.Circuit(cirq.CZ(*cirq.LineQubit.range(2)).with_tags('foo'))
|
|
31
49
|
assert c == CZGaugeTransformer(c, context=cirq.TransformerContext(tags_to_ignore={"foo"}))
|
|
50
|
+
parameterized_circuit, _ = CZGaugeTransformer.as_sweep(
|
|
51
|
+
c, context=cirq.TransformerContext(tags_to_ignore={"foo"}), N=1
|
|
52
|
+
)
|
|
53
|
+
assert c == parameterized_circuit
|
|
32
54
|
|
|
33
55
|
|
|
34
56
|
def test_target_can_be_gateset():
|
|
@@ -39,3 +61,86 @@ def test_target_can_be_gateset():
|
|
|
39
61
|
)
|
|
40
62
|
want = cirq.Circuit(cirq.Y.on_each(qs), cirq.CZ(*qs), cirq.X.on_each(qs))
|
|
41
63
|
assert transformer(c, prng=np.random.default_rng(0)) == want
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_as_sweep_multi_pre_or_multi_post():
|
|
67
|
+
transformer = GaugeTransformer(
|
|
68
|
+
target=cirq.CZ,
|
|
69
|
+
gauge_selector=GaugeSelector(
|
|
70
|
+
gauges=[
|
|
71
|
+
ConstantGauge(
|
|
72
|
+
two_qubit_gate=cirq.CZ,
|
|
73
|
+
pre_q0=[cirq.X, cirq.X],
|
|
74
|
+
post_q0=[cirq.Z],
|
|
75
|
+
pre_q1=[cirq.Y],
|
|
76
|
+
post_q1=[cirq.Y, cirq.Y, cirq.Y],
|
|
77
|
+
)
|
|
78
|
+
]
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
qs = cirq.LineQubit.range(2)
|
|
82
|
+
input_circuit = cirq.Circuit(cirq.CZ(*qs))
|
|
83
|
+
parameterized_circuit, sweeps = transformer.as_sweep(input_circuit, N=1)
|
|
84
|
+
|
|
85
|
+
for params in sweeps:
|
|
86
|
+
compiled_circuit = cirq.resolve_parameters(parameterized_circuit, params)
|
|
87
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
88
|
+
input_circuit, compiled_circuit, qubit_map={q: q for q in input_circuit.all_qubits()}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def test_as_sweep_invalid_gauge_sequence():
|
|
93
|
+
transfomer = GaugeTransformer(
|
|
94
|
+
target=cirq.CZ,
|
|
95
|
+
gauge_selector=GaugeSelector(
|
|
96
|
+
gauges=[
|
|
97
|
+
ConstantGauge(
|
|
98
|
+
two_qubit_gate=cirq.CZ,
|
|
99
|
+
pre_q0=[cirq.measure],
|
|
100
|
+
post_q0=[cirq.Z],
|
|
101
|
+
pre_q1=[cirq.X],
|
|
102
|
+
post_q1=[cirq.Z],
|
|
103
|
+
)
|
|
104
|
+
]
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
qs = cirq.LineQubit.range(2)
|
|
108
|
+
c = cirq.Circuit(cirq.CZ(*qs))
|
|
109
|
+
with pytest.raises(ValueError, match="Invalid gate sequence to be converted to PhasedXZGate."):
|
|
110
|
+
transfomer.as_sweep(c, N=1)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_as_sweep_convert_to_phxz_failed():
|
|
114
|
+
qs = cirq.LineQubit.range(2)
|
|
115
|
+
c = cirq.Circuit(cirq.CZ(*qs))
|
|
116
|
+
|
|
117
|
+
with unittest.mock.patch.object(
|
|
118
|
+
single_qubit_decompositions,
|
|
119
|
+
"single_qubit_matrix_to_phxz",
|
|
120
|
+
# Return an non PhasedXZ gate, so we expect errors from as_sweep().
|
|
121
|
+
return_value=cirq.X,
|
|
122
|
+
):
|
|
123
|
+
with pytest.raises(
|
|
124
|
+
ValueError, match="Failed to convert the gate sequence to a PhasedXZ gate."
|
|
125
|
+
):
|
|
126
|
+
_ = CZGaugeTransformer.as_sweep(c, context=cirq.TransformerContext(), N=1)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_symbolize_2_qubits_gate_failed():
|
|
130
|
+
qs = cirq.LineQubit.range(2)
|
|
131
|
+
c = cirq.Circuit(cirq.CZPowGate(exponent=0.5).on(*qs))
|
|
132
|
+
|
|
133
|
+
with unittest.mock.patch.object(
|
|
134
|
+
SqrtCZGauge,
|
|
135
|
+
"sample",
|
|
136
|
+
# ISWAP gate is not a CZPowGate; errors are expected when symbolizing the 2-qubit gate.
|
|
137
|
+
return_value=ConstantGauge(two_qubit_gate=cirq.ISWAP),
|
|
138
|
+
):
|
|
139
|
+
with pytest.raises(ValueError, match="Can't symbolize non-CZPowGate as CZ\\*\\*symbol."):
|
|
140
|
+
_ = SqrtCZGaugeTransformer.as_sweep(c, N=1)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_symbolize_2_qubits_gate_failed_unmatched_symbol_length():
|
|
144
|
+
symbolizer = TwoQubitGateSymbolizer(symbolizer_fn=lambda gate, _: (gate, {}), n_symbols=2)
|
|
145
|
+
with pytest.raises(ValueError, match="Expect 2 symbols, but got 1 symbols"):
|
|
146
|
+
symbolizer(cirq.CZ, [sympy.Symbol('x')])
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
from unittest.mock import patch
|
|
17
|
-
import pytest
|
|
18
17
|
|
|
19
18
|
import numpy as np
|
|
19
|
+
import pytest
|
|
20
20
|
|
|
21
21
|
import cirq
|
|
22
|
-
from cirq.transformers.gauge_compiling import
|
|
22
|
+
from cirq.transformers.gauge_compiling import GaugeSelector, GaugeTransformer
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class GaugeTester:
|
|
@@ -73,6 +73,43 @@ class GaugeTester:
|
|
|
73
73
|
else:
|
|
74
74
|
_check_equivalent_with_error_message(c, nc, gauge)
|
|
75
75
|
|
|
76
|
+
def test_sweep(self):
|
|
77
|
+
qubits = cirq.LineQubit.range(3)
|
|
78
|
+
|
|
79
|
+
input_circuit = cirq.Circuit(
|
|
80
|
+
cirq.Moment(cirq.H(qubits[0])),
|
|
81
|
+
cirq.Moment(self.two_qubit_gate(*qubits[:2])),
|
|
82
|
+
cirq.Moment(self.two_qubit_gate(*qubits[1:])),
|
|
83
|
+
cirq.Moment([cirq.H(q) for q in qubits]),
|
|
84
|
+
cirq.Moment([cirq.measure(q) for q in qubits]),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
n_samples = 5
|
|
88
|
+
parameterized_circuit, sweeps = self.gauge_transformer.as_sweep(input_circuit, N=n_samples)
|
|
89
|
+
|
|
90
|
+
# Check the parameterized circuit and N set of parameters.
|
|
91
|
+
assert cirq.is_parameterized(parameterized_circuit)
|
|
92
|
+
simulator = cirq.Simulator()
|
|
93
|
+
results = simulator.run_sweep(parameterized_circuit, sweeps)
|
|
94
|
+
assert len(results) == n_samples
|
|
95
|
+
|
|
96
|
+
# Check compilied circuits have the same unitary as the orig circuit.
|
|
97
|
+
for params in sweeps:
|
|
98
|
+
compiled_circuit = cirq.resolve_parameters(parameterized_circuit, params)
|
|
99
|
+
if self.must_fail:
|
|
100
|
+
with pytest.raises(AssertionError):
|
|
101
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
102
|
+
input_circuit[:-1],
|
|
103
|
+
compiled_circuit[:-1],
|
|
104
|
+
qubit_map={q: q for q in input_circuit.all_qubits()},
|
|
105
|
+
)
|
|
106
|
+
break
|
|
107
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
108
|
+
input_circuit[:-1],
|
|
109
|
+
compiled_circuit[:-1],
|
|
110
|
+
qubit_map={q: q for q in input_circuit.all_qubits()},
|
|
111
|
+
)
|
|
112
|
+
|
|
76
113
|
|
|
77
114
|
def _check_equivalent_with_error_message(c: cirq.AbstractCircuit, nc: cirq.AbstractCircuit, gauge):
|
|
78
115
|
try:
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
import numpy as np
|
|
17
|
+
|
|
17
18
|
import cirq
|
|
19
|
+
from cirq.transformers import ConstantGauge, GaugeSelector, GaugeTransformer
|
|
18
20
|
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
19
|
-
from cirq.transformers import GaugeTransformer, GaugeSelector, ConstantGauge
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class ExampleGate(cirq.testing.TwoQubitGate):
|
|
@@ -26,7 +27,15 @@ class ExampleGate(cirq.testing.TwoQubitGate):
|
|
|
26
27
|
return self.unitary
|
|
27
28
|
|
|
28
29
|
|
|
30
|
+
class ExampleSweepGate(cirq.testing.TwoQubitGate):
|
|
31
|
+
unitary = cirq.unitary(cirq.CZ)
|
|
32
|
+
|
|
33
|
+
def _unitary_(self) -> np.ndarray:
|
|
34
|
+
return self.unitary # pragma: no cover
|
|
35
|
+
|
|
36
|
+
|
|
29
37
|
_EXAMPLE_TARGET = ExampleGate()
|
|
38
|
+
_EXAMPLE_SWEEP_TARGET = ExampleSweepGate()
|
|
30
39
|
|
|
31
40
|
_GOOD_TRANSFORMER = GaugeTransformer(
|
|
32
41
|
target=_EXAMPLE_TARGET,
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
|
|
17
17
|
import numpy as np
|
|
18
18
|
|
|
19
|
+
from cirq import ops
|
|
19
20
|
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
20
21
|
ConstantGauge,
|
|
21
22
|
Gauge,
|
|
22
|
-
GaugeTransformer,
|
|
23
23
|
GaugeSelector,
|
|
24
|
+
GaugeTransformer,
|
|
24
25
|
)
|
|
25
|
-
from cirq import ops
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class RZRotation(Gauge):
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
"""The spin inversion gauge transformer."""
|
|
16
16
|
|
|
17
|
+
from cirq import ops
|
|
17
18
|
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
18
|
-
GaugeTransformer,
|
|
19
19
|
GaugeSelector,
|
|
20
|
+
GaugeTransformer,
|
|
20
21
|
SameGateGauge,
|
|
21
22
|
)
|
|
22
|
-
from cirq import ops
|
|
23
23
|
|
|
24
24
|
SpinInversionGaugeSelector = GaugeSelector(
|
|
25
25
|
gauges=[
|
|
@@ -15,16 +15,20 @@
|
|
|
15
15
|
"""A Gauge transformer for CZ**0.5 and CZ**-0.5 gates."""
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
from
|
|
18
|
+
from numbers import Real
|
|
19
|
+
from typing import Dict, Sequence, Tuple, TYPE_CHECKING
|
|
20
|
+
|
|
19
21
|
import numpy as np
|
|
22
|
+
import sympy
|
|
20
23
|
|
|
24
|
+
from cirq.ops import CZ, CZPowGate, Gate, Gateset, S, X
|
|
21
25
|
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
22
|
-
GaugeTransformer,
|
|
23
|
-
GaugeSelector,
|
|
24
26
|
ConstantGauge,
|
|
25
27
|
Gauge,
|
|
28
|
+
GaugeSelector,
|
|
29
|
+
GaugeTransformer,
|
|
30
|
+
TwoQubitGateSymbolizer,
|
|
26
31
|
)
|
|
27
|
-
from cirq.ops import CZ, S, X, Gateset
|
|
28
32
|
|
|
29
33
|
if TYPE_CHECKING:
|
|
30
34
|
import cirq
|
|
@@ -59,6 +63,20 @@ class SqrtCZGauge(Gauge):
|
|
|
59
63
|
)
|
|
60
64
|
|
|
61
65
|
|
|
66
|
+
def _symbolize_as_cz_pow(
|
|
67
|
+
two_qubit_gate: Gate, symbols: Sequence[sympy.Symbol]
|
|
68
|
+
) -> Tuple[Gate, Dict[str, Real]]:
|
|
69
|
+
"""Symbolizes a CZPowGate to a parameterized CZPowGate."""
|
|
70
|
+
|
|
71
|
+
if not isinstance(two_qubit_gate, CZPowGate) or not isinstance(two_qubit_gate.exponent, Real):
|
|
72
|
+
raise ValueError("Can't symbolize non-CZPowGate as CZ**symbol.")
|
|
73
|
+
return (CZ ** symbols[0], {str(symbols[0]): two_qubit_gate.exponent})
|
|
74
|
+
|
|
75
|
+
|
|
62
76
|
SqrtCZGaugeTransformer = GaugeTransformer(
|
|
63
|
-
target=Gateset(_SQRT_CZ, _SQRT_CZ**-1),
|
|
77
|
+
target=Gateset(_SQRT_CZ, _SQRT_CZ**-1),
|
|
78
|
+
gauge_selector=GaugeSelector(gauges=[SqrtCZGauge()]),
|
|
79
|
+
two_qubit_gate_symbolizer=TwoQubitGateSymbolizer(
|
|
80
|
+
symbolizer_fn=_symbolize_as_cz_pow, n_symbols=1
|
|
81
|
+
),
|
|
64
82
|
)
|
|
@@ -15,13 +15,14 @@
|
|
|
15
15
|
"""A Gauge transformer for SQRT_ISWAP gate."""
|
|
16
16
|
|
|
17
17
|
import numpy as np
|
|
18
|
+
|
|
19
|
+
from cirq import ops
|
|
18
20
|
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
19
21
|
ConstantGauge,
|
|
20
22
|
Gauge,
|
|
21
|
-
GaugeTransformer,
|
|
22
23
|
GaugeSelector,
|
|
24
|
+
GaugeTransformer,
|
|
23
25
|
)
|
|
24
|
-
from cirq import ops
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class RZRotation(Gauge):
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"""Utilities for heuristic decomposition of cirq gates."""
|
|
16
16
|
|
|
17
17
|
from cirq.transformers.heuristic_decompositions.two_qubit_gate_tabulation import (
|
|
18
|
-
TwoQubitGateTabulation,
|
|
19
|
-
TwoQubitGateTabulationResult,
|
|
20
|
-
two_qubit_gate_product_tabulation,
|
|
18
|
+
TwoQubitGateTabulation as TwoQubitGateTabulation,
|
|
19
|
+
TwoQubitGateTabulationResult as TwoQubitGateTabulationResult,
|
|
20
|
+
two_qubit_gate_product_tabulation as two_qubit_gate_product_tabulation,
|
|
21
21
|
)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# pylint: disable=wrong-or-nonexistent-copyright-notice
|
|
2
2
|
import itertools
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Optional, Sequence, Union
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
|
+
|
|
6
7
|
from cirq.value import random_state
|
|
7
8
|
|
|
8
9
|
_RealArraylike = Union[np.ndarray, float]
|
|
@@ -14,21 +14,21 @@
|
|
|
14
14
|
|
|
15
15
|
"""Attempt to tabulate single qubit gates required to generate a target 2Q gate
|
|
16
16
|
with a product A k A."""
|
|
17
|
+
from dataclasses import dataclass
|
|
17
18
|
from functools import reduce
|
|
18
19
|
from typing import List, NamedTuple, Sequence, Tuple
|
|
19
20
|
|
|
20
|
-
from dataclasses import dataclass
|
|
21
21
|
import numpy as np
|
|
22
22
|
|
|
23
23
|
import cirq
|
|
24
24
|
from cirq import value
|
|
25
|
-
from cirq._compat import
|
|
25
|
+
from cirq._compat import proper_eq, proper_repr
|
|
26
26
|
from cirq.transformers.heuristic_decompositions.gate_tabulation_math_utils import (
|
|
27
27
|
kak_vector_infidelity,
|
|
28
|
+
kak_vector_to_unitary,
|
|
29
|
+
random_qubit_unitary,
|
|
28
30
|
vector_kron,
|
|
29
31
|
weyl_chamber_mesh,
|
|
30
|
-
random_qubit_unitary,
|
|
31
|
-
kak_vector_to_unitary,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
_SingleQubitGatePair = Tuple[np.ndarray, np.ndarray]
|