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
|
@@ -12,14 +12,13 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Wraps Parallel Two Qubit XEB into a few convenience methods."""
|
|
15
|
-
from typing import Optional, Sequence, Dict
|
|
16
|
-
import itertools
|
|
17
15
|
import io
|
|
16
|
+
import itertools
|
|
17
|
+
from typing import Dict, Optional, Sequence
|
|
18
18
|
|
|
19
19
|
import matplotlib.pyplot as plt
|
|
20
|
-
|
|
21
|
-
import numpy as np
|
|
22
20
|
import networkx as nx
|
|
21
|
+
import numpy as np
|
|
23
22
|
import pandas as pd
|
|
24
23
|
import pytest
|
|
25
24
|
|
|
@@ -148,10 +147,10 @@ _TEST_RESULT = cirq.experiments.TwoQubitXEBResult(
|
|
|
148
147
|
@pytest.mark.parametrize(
|
|
149
148
|
'q0,q1,pauli',
|
|
150
149
|
[
|
|
151
|
-
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4),
|
|
152
|
-
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3),
|
|
153
|
-
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.
|
|
154
|
-
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4),
|
|
150
|
+
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4), 0.09374999999999997),
|
|
151
|
+
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3), 0.18749999999999994),
|
|
152
|
+
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.65625),
|
|
153
|
+
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4), 0.46875),
|
|
155
154
|
],
|
|
156
155
|
)
|
|
157
156
|
def test_pauli_error(q0: cirq.GridQubit, q1: cirq.GridQubit, pauli: float):
|
|
@@ -174,10 +173,10 @@ class MockParallelRandomizedBenchmarkingResult(ParallelRandomizedBenchmarkingRes
|
|
|
174
173
|
@pytest.mark.parametrize(
|
|
175
174
|
'q0,q1,pauli',
|
|
176
175
|
[
|
|
177
|
-
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4),
|
|
178
|
-
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3),
|
|
179
|
-
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.
|
|
180
|
-
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4),
|
|
176
|
+
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4), 0.09374999999999997 - 0.03),
|
|
177
|
+
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3), 0.18749999999999994 - 0.09),
|
|
178
|
+
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.65625 - 0.08),
|
|
179
|
+
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4), 0.46875 - 0.13),
|
|
181
180
|
],
|
|
182
181
|
)
|
|
183
182
|
def test_inferred_pauli_error(q0: cirq.GridQubit, q1: cirq.GridQubit, pauli: float):
|
|
@@ -191,10 +190,10 @@ def test_inferred_pauli_error(q0: cirq.GridQubit, q1: cirq.GridQubit, pauli: flo
|
|
|
191
190
|
@pytest.mark.parametrize(
|
|
192
191
|
'q0,q1,xeb',
|
|
193
192
|
[
|
|
194
|
-
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4), 0.
|
|
195
|
-
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3), 0.
|
|
196
|
-
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.
|
|
197
|
-
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4), 0.
|
|
193
|
+
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4), 0.050999999999999934),
|
|
194
|
+
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3), 0.07799999999999996),
|
|
195
|
+
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.46099999999999997),
|
|
196
|
+
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4), 0.2709999999999999),
|
|
198
197
|
],
|
|
199
198
|
)
|
|
200
199
|
def test_inferred_xeb_error(q0: cirq.GridQubit, q1: cirq.GridQubit, xeb: float):
|
|
@@ -224,10 +223,10 @@ def test_inferred_single_qubit_pauli():
|
|
|
224
223
|
@pytest.mark.parametrize(
|
|
225
224
|
'q0,q1,pauli',
|
|
226
225
|
[
|
|
227
|
-
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4),
|
|
228
|
-
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3),
|
|
229
|
-
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.
|
|
230
|
-
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4),
|
|
226
|
+
(cirq.GridQubit(4, 4), cirq.GridQubit(5, 4), 0.09374999999999997),
|
|
227
|
+
(cirq.GridQubit(5, 3), cirq.GridQubit(6, 3), 0.18749999999999994),
|
|
228
|
+
(cirq.GridQubit(4, 3), cirq.GridQubit(5, 3), 0.65625),
|
|
229
|
+
(cirq.GridQubit(6, 3), cirq.GridQubit(6, 4), 0.46875),
|
|
231
230
|
],
|
|
232
231
|
)
|
|
233
232
|
def test_inferred_two_qubit_pauli(q0: cirq.GridQubit, q1: cirq.GridQubit, pauli: float):
|
|
@@ -261,26 +260,43 @@ def test_inferred_plots(ax, target_error, kind):
|
|
|
261
260
|
|
|
262
261
|
|
|
263
262
|
@pytest.mark.parametrize(
|
|
264
|
-
'sampler,qubits',
|
|
263
|
+
'sampler,qubits,pairs',
|
|
265
264
|
[
|
|
266
265
|
(
|
|
267
266
|
cirq.DensityMatrixSimulator(
|
|
268
267
|
seed=0, noise=cirq.ConstantQubitNoiseModel(cirq.amplitude_damp(0.1))
|
|
269
268
|
),
|
|
270
269
|
cirq.GridQubit.rect(3, 2, 4, 3),
|
|
270
|
+
None,
|
|
271
|
+
),
|
|
272
|
+
(
|
|
273
|
+
cirq.DensityMatrixSimulator(
|
|
274
|
+
seed=0, noise=cirq.ConstantQubitNoiseModel(cirq.amplitude_damp(0.1))
|
|
275
|
+
),
|
|
276
|
+
None,
|
|
277
|
+
[
|
|
278
|
+
(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)),
|
|
279
|
+
(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)),
|
|
280
|
+
],
|
|
271
281
|
),
|
|
272
282
|
(
|
|
273
283
|
DensityMatrixSimulatorWithProcessor(
|
|
274
284
|
seed=0, noise=cirq.ConstantQubitNoiseModel(cirq.amplitude_damp(0.1))
|
|
275
285
|
),
|
|
276
286
|
None,
|
|
287
|
+
None,
|
|
277
288
|
),
|
|
278
289
|
],
|
|
279
290
|
)
|
|
280
|
-
def test_run_rb_and_xeb(
|
|
291
|
+
def test_run_rb_and_xeb(
|
|
292
|
+
sampler: cirq.Sampler,
|
|
293
|
+
qubits: Optional[Sequence[cirq.GridQubit]],
|
|
294
|
+
pairs: Optional[Sequence[tuple[cirq.GridQubit, cirq.GridQubit]]],
|
|
295
|
+
):
|
|
281
296
|
res = cirq.experiments.run_rb_and_xeb(
|
|
282
297
|
sampler=sampler,
|
|
283
298
|
qubits=qubits,
|
|
299
|
+
pairs=pairs,
|
|
284
300
|
repetitions=100,
|
|
285
301
|
num_clifford_range=tuple(np.arange(3, 10, 1)),
|
|
286
302
|
xeb_combinations=1,
|
cirq/experiments/xeb_fitting.py
CHANGED
|
@@ -13,20 +13,23 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Estimation of fidelity associated with experimental circuit executions."""
|
|
15
15
|
import dataclasses
|
|
16
|
-
from abc import
|
|
16
|
+
from abc import ABC, abstractmethod
|
|
17
17
|
from typing import Dict, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
import pandas as pd
|
|
21
21
|
import sympy
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
from cirq import _import, circuits, ops, protocols
|
|
23
24
|
from cirq.experiments.xeb_simulation import simulate_2q_xeb_circuits
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
26
|
-
import cirq
|
|
27
27
|
import multiprocessing
|
|
28
|
+
|
|
28
29
|
import scipy.optimize
|
|
29
30
|
|
|
31
|
+
import cirq
|
|
32
|
+
|
|
30
33
|
# We initialize these lazily, otherwise they slow global import speed.
|
|
31
34
|
optimize = _import.LazyLoader("optimize", globals(), "scipy.optimize")
|
|
32
35
|
stats = _import.LazyLoader("stats", globals(), "scipy.stats")
|
|
@@ -95,6 +98,11 @@ def benchmark_2q_xeb_fidelities(
|
|
|
95
98
|
df['e_u'] = np.sum(pure_probs**2, axis=1)
|
|
96
99
|
df['u_u'] = np.sum(pure_probs, axis=1) / D
|
|
97
100
|
df['m_u'] = np.sum(pure_probs * sampled_probs, axis=1)
|
|
101
|
+
# Var[m_u] = Var[sum p(x) * p_sampled(x)]
|
|
102
|
+
# = sum p(x)^2 Var[p_sampled(x)]
|
|
103
|
+
# = sum p(x)^2 p(x) (1 - p(x))
|
|
104
|
+
# = sum p(x)^3 (1 - p(x))
|
|
105
|
+
df['var_m_u'] = np.sum(pure_probs**3 * (1 - pure_probs), axis=1)
|
|
98
106
|
df['y'] = df['m_u'] - df['u_u']
|
|
99
107
|
df['x'] = df['e_u'] - df['u_u']
|
|
100
108
|
df['numerator'] = df['x'] * df['y']
|
|
@@ -103,7 +111,11 @@ def benchmark_2q_xeb_fidelities(
|
|
|
103
111
|
def per_cycle_depth(df):
|
|
104
112
|
"""This function is applied per cycle_depth in the following groupby aggregation."""
|
|
105
113
|
fid_lsq = df['numerator'].sum() / df['denominator'].sum()
|
|
106
|
-
|
|
114
|
+
# Note: both df['denominator'] and df['x'] are constants.
|
|
115
|
+
# Var[f] = Var[df['numerator']] / (sum df['denominator'])^2
|
|
116
|
+
# = sum (df['x']^2 * df['var_m_u']) / (sum df['denominator'])^2
|
|
117
|
+
var_fid = (df['var_m_u'] * df['x'] ** 2).sum() / df['denominator'].sum() ** 2
|
|
118
|
+
ret = {'fidelity': fid_lsq, 'fidelity_variance': var_fid}
|
|
107
119
|
|
|
108
120
|
def _try_keep(k):
|
|
109
121
|
"""If all the values for a key `k` are the same in this group, we can keep it."""
|
|
@@ -126,7 +138,7 @@ def benchmark_2q_xeb_fidelities(
|
|
|
126
138
|
else:
|
|
127
139
|
groupby_names = ['cycle_depth']
|
|
128
140
|
|
|
129
|
-
return df.groupby(groupby_names).apply(per_cycle_depth).reset_index()
|
|
141
|
+
return df.groupby(groupby_names).apply(per_cycle_depth, include_groups=False).reset_index()
|
|
130
142
|
|
|
131
143
|
|
|
132
144
|
class XEBCharacterizationOptions(ABC):
|
|
@@ -146,6 +158,69 @@ class XEBCharacterizationOptions(ABC):
|
|
|
146
158
|
"""Return an initial Nelder-Mead simplex and the names for each parameter."""
|
|
147
159
|
|
|
148
160
|
|
|
161
|
+
def _try_defaults_from_unitary(gate: 'cirq.Gate') -> Optional[Dict[str, 'cirq.TParamVal']]:
|
|
162
|
+
r"""Try to figure out the PhasedFSim angles from the unitary of the gate.
|
|
163
|
+
|
|
164
|
+
The unitary of a PhasedFSimGate has the form:
|
|
165
|
+
$$
|
|
166
|
+
\begin{bmatrix}
|
|
167
|
+
1 & 0 & 0 & 0 \\
|
|
168
|
+
0 & e^{-i \gamma - i \zeta} \cos(\theta) & -i e^{-i \gamma + i\chi} \sin(\theta) & 0 \\
|
|
169
|
+
0 & -i e^{-i \gamma - i \chi} \sin(\theta) & e^{-i \gamma + i \zeta} \cos(\theta) & 0 \\
|
|
170
|
+
0 & 0 & 0 & e^{-2i \gamma - i \phi}
|
|
171
|
+
\end{bmatrix}
|
|
172
|
+
$$
|
|
173
|
+
That's the information about the five angles $\theta, \phi, \gamma, \zeta, \chi$ is encoded in
|
|
174
|
+
the submatrix unitary[1:3, 1:3] and the element u[3][3]. With some algebra, we can isolate each
|
|
175
|
+
of the angles as an argument of a combination of those elements (and potentially other angles).
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
A cirq gate.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
A dictionary mapping angles to values or None if the gate doesn't have a unitary or if it
|
|
182
|
+
can't be represented by a PhasedFSimGate.
|
|
183
|
+
"""
|
|
184
|
+
u = protocols.unitary(gate, default=None)
|
|
185
|
+
if u is None:
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
gamma = np.angle(u[1, 1] * u[2, 2] - u[1, 2] * u[2, 1]) / -2
|
|
189
|
+
phi = -np.angle(u[3, 3]) - 2 * gamma
|
|
190
|
+
phased_cos_theta_2 = u[1, 1] * u[2, 2]
|
|
191
|
+
if phased_cos_theta_2 == 0:
|
|
192
|
+
# The zeta phase is multiplied with cos(theta),
|
|
193
|
+
# so if cos(theta) is zero then any value is possible.
|
|
194
|
+
zeta = 0
|
|
195
|
+
else:
|
|
196
|
+
zeta = np.angle(u[2, 2] / u[1, 1]) / 2
|
|
197
|
+
|
|
198
|
+
phased_sin_theta_2 = u[1, 2] * u[2, 1]
|
|
199
|
+
if phased_sin_theta_2 == 0:
|
|
200
|
+
# The chi phase is multiplied with sin(theta),
|
|
201
|
+
# so if sin(theta) is zero then any value is possible.
|
|
202
|
+
chi = 0
|
|
203
|
+
else:
|
|
204
|
+
chi = np.angle(u[1, 2] / u[2, 1]) / 2
|
|
205
|
+
|
|
206
|
+
theta = np.angle(np.exp(1j * (gamma + zeta)) * u[1, 1] - np.exp(1j * (gamma - chi)) * u[1, 2])
|
|
207
|
+
|
|
208
|
+
if np.allclose(
|
|
209
|
+
u,
|
|
210
|
+
protocols.unitary(
|
|
211
|
+
ops.PhasedFSimGate(theta=theta, phi=phi, chi=chi, zeta=zeta, gamma=gamma)
|
|
212
|
+
),
|
|
213
|
+
):
|
|
214
|
+
return {
|
|
215
|
+
'theta_default': theta,
|
|
216
|
+
'phi_default': phi,
|
|
217
|
+
'gamma_default': gamma,
|
|
218
|
+
'zeta_default': zeta,
|
|
219
|
+
'chi_default': chi,
|
|
220
|
+
}
|
|
221
|
+
return None
|
|
222
|
+
|
|
223
|
+
|
|
149
224
|
def phased_fsim_angles_from_gate(gate: 'cirq.Gate') -> Dict[str, 'cirq.TParamVal']:
|
|
150
225
|
"""For a given gate, return a dictionary mapping '{angle}_default' to its noiseless value
|
|
151
226
|
for the five PhasedFSim angles."""
|
|
@@ -175,6 +250,11 @@ def phased_fsim_angles_from_gate(gate: 'cirq.Gate') -> Dict[str, 'cirq.TParamVal
|
|
|
175
250
|
'phi_default': gate.phi,
|
|
176
251
|
}
|
|
177
252
|
|
|
253
|
+
# Handle all gates that can be represented using an FSimGate.
|
|
254
|
+
from_unitary = _try_defaults_from_unitary(gate)
|
|
255
|
+
if from_unitary is not None:
|
|
256
|
+
return from_unitary
|
|
257
|
+
|
|
178
258
|
raise ValueError(f"Unknown default angles for {gate}.")
|
|
179
259
|
|
|
180
260
|
|
|
@@ -317,16 +397,21 @@ def SqrtISwapXEBOptions(*args, **kwargs):
|
|
|
317
397
|
|
|
318
398
|
|
|
319
399
|
def parameterize_circuit(
|
|
320
|
-
circuit: 'cirq.Circuit',
|
|
400
|
+
circuit: 'cirq.Circuit',
|
|
401
|
+
options: XEBCharacterizationOptions,
|
|
402
|
+
target_gatefamily: Optional[ops.GateFamily] = None,
|
|
321
403
|
) -> 'cirq.Circuit':
|
|
322
404
|
"""Parameterize PhasedFSim-like gates in a given circuit according to
|
|
323
405
|
`phased_fsim_options`.
|
|
324
406
|
"""
|
|
407
|
+
if isinstance(target_gatefamily, ops.GateFamily):
|
|
408
|
+
should_parameterize = lambda op: op in target_gatefamily or options.should_parameterize(op)
|
|
409
|
+
else:
|
|
410
|
+
should_parameterize = options.should_parameterize
|
|
325
411
|
gate = options.get_parameterized_gate()
|
|
326
412
|
return circuits.Circuit(
|
|
327
413
|
circuits.Moment(
|
|
328
|
-
gate.on(*op.qubits) if
|
|
329
|
-
for op in moment.operations
|
|
414
|
+
gate.on(*op.qubits) if should_parameterize(op) else op for op in moment.operations
|
|
330
415
|
)
|
|
331
416
|
for moment in circuit.moments
|
|
332
417
|
)
|
|
@@ -572,6 +657,7 @@ def _fit_exponential_decay(
|
|
|
572
657
|
fidelities,
|
|
573
658
|
p0=(a_0, layer_fid_0),
|
|
574
659
|
bounds=((0, 0), (1, 1)),
|
|
660
|
+
maxfev=1000,
|
|
575
661
|
)
|
|
576
662
|
except ValueError: # pragma: no cover
|
|
577
663
|
return 0, 0, np.inf, np.inf
|
|
@@ -580,15 +666,6 @@ def _fit_exponential_decay(
|
|
|
580
666
|
return a, layer_fid, a_std, layer_fid_std
|
|
581
667
|
|
|
582
668
|
|
|
583
|
-
def _one_unique(df, name, default):
|
|
584
|
-
"""Helper function to assert that there's one unique value in a column and return it."""
|
|
585
|
-
if name not in df.columns:
|
|
586
|
-
return default
|
|
587
|
-
vals = df[name].unique()
|
|
588
|
-
assert len(vals) == 1, name
|
|
589
|
-
return vals[0]
|
|
590
|
-
|
|
591
|
-
|
|
592
669
|
def fit_exponential_decays(fidelities_df: pd.DataFrame) -> pd.DataFrame:
|
|
593
670
|
"""Fit exponential decay curves to a fidelities DataFrame.
|
|
594
671
|
|
|
@@ -608,13 +685,16 @@ def fit_exponential_decays(fidelities_df: pd.DataFrame) -> pd.DataFrame:
|
|
|
608
685
|
a, layer_fid, a_std, layer_fid_std = _fit_exponential_decay(
|
|
609
686
|
f1['cycle_depth'], f1['fidelity']
|
|
610
687
|
)
|
|
688
|
+
fidelity_variance = 0
|
|
689
|
+
if 'fidelity_variance' in f1:
|
|
690
|
+
fidelity_variance = f1['fidelity_variance'].values
|
|
611
691
|
record = {
|
|
612
692
|
'a': a,
|
|
613
693
|
'layer_fid': layer_fid,
|
|
614
694
|
'cycle_depths': f1['cycle_depth'].values,
|
|
615
695
|
'fidelities': f1['fidelity'].values,
|
|
616
696
|
'a_std': a_std,
|
|
617
|
-
'layer_fid_std': layer_fid_std,
|
|
697
|
+
'layer_fid_std': np.sqrt(layer_fid_std**2 + fidelity_variance),
|
|
618
698
|
}
|
|
619
699
|
return pd.Series(record)
|
|
620
700
|
|
|
@@ -622,7 +702,7 @@ def fit_exponential_decays(fidelities_df: pd.DataFrame) -> pd.DataFrame:
|
|
|
622
702
|
groupby = ['layer_i', 'pair_i', 'pair']
|
|
623
703
|
else:
|
|
624
704
|
groupby = ['pair']
|
|
625
|
-
return fidelities_df.groupby(groupby).apply(_per_pair)
|
|
705
|
+
return fidelities_df.groupby(groupby).apply(_per_pair, include_groups=False)
|
|
626
706
|
|
|
627
707
|
|
|
628
708
|
def before_and_after_characterization(
|
|
@@ -11,9 +11,12 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import itertools
|
|
15
18
|
import multiprocessing
|
|
16
|
-
from typing import Iterable
|
|
19
|
+
from typing import Iterable, Iterator
|
|
17
20
|
|
|
18
21
|
import networkx as nx
|
|
19
22
|
import numpy as np
|
|
@@ -23,18 +26,28 @@ import pytest
|
|
|
23
26
|
import cirq
|
|
24
27
|
import cirq.experiments.random_quantum_circuit_generation as rqcg
|
|
25
28
|
from cirq.experiments.xeb_fitting import (
|
|
29
|
+
_fit_exponential_decay,
|
|
30
|
+
before_and_after_characterization,
|
|
26
31
|
benchmark_2q_xeb_fidelities,
|
|
27
|
-
parameterize_circuit,
|
|
28
|
-
SqrtISwapXEBOptions,
|
|
29
32
|
characterize_phased_fsim_parameters_with_xeb,
|
|
30
33
|
characterize_phased_fsim_parameters_with_xeb_by_pair,
|
|
31
|
-
_fit_exponential_decay,
|
|
32
34
|
fit_exponential_decays,
|
|
33
|
-
|
|
35
|
+
parameterize_circuit,
|
|
36
|
+
phased_fsim_angles_from_gate,
|
|
37
|
+
SqrtISwapXEBOptions,
|
|
34
38
|
XEBPhasedFSimCharacterizationOptions,
|
|
35
39
|
)
|
|
36
40
|
from cirq.experiments.xeb_sampling import sample_2q_xeb_circuits
|
|
37
41
|
|
|
42
|
+
_POOL_NUM_PROCESSES = min(4, multiprocessing.cpu_count())
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@pytest.fixture
|
|
46
|
+
def pool() -> Iterator[multiprocessing.pool.Pool]:
|
|
47
|
+
ctx = multiprocessing.get_context()
|
|
48
|
+
with ctx.Pool(_POOL_NUM_PROCESSES) as pool:
|
|
49
|
+
yield pool
|
|
50
|
+
|
|
38
51
|
|
|
39
52
|
@pytest.fixture(scope='module')
|
|
40
53
|
def circuits_cycle_depths_sampled_df():
|
|
@@ -203,7 +216,7 @@ def test_get_initial_simplex():
|
|
|
203
216
|
assert simplex.shape[1] == len(names)
|
|
204
217
|
|
|
205
218
|
|
|
206
|
-
def test_characterize_phased_fsim_parameters_with_xeb():
|
|
219
|
+
def test_characterize_phased_fsim_parameters_with_xeb(pool):
|
|
207
220
|
q0, q1 = cirq.LineQubit.range(2)
|
|
208
221
|
rs = np.random.RandomState(52)
|
|
209
222
|
circuits = [
|
|
@@ -228,17 +241,16 @@ def test_characterize_phased_fsim_parameters_with_xeb():
|
|
|
228
241
|
characterize_phi=False,
|
|
229
242
|
)
|
|
230
243
|
p_circuits = [parameterize_circuit(circuit, options) for circuit in circuits]
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
)
|
|
244
|
+
result = characterize_phased_fsim_parameters_with_xeb(
|
|
245
|
+
sampled_df=sampled_df,
|
|
246
|
+
parameterized_circuits=p_circuits,
|
|
247
|
+
cycle_depths=cycle_depths,
|
|
248
|
+
options=options,
|
|
249
|
+
# speed up with looser tolerances:
|
|
250
|
+
fatol=1e-2,
|
|
251
|
+
xatol=1e-2,
|
|
252
|
+
pool=pool,
|
|
253
|
+
)
|
|
242
254
|
opt_res = result.optimization_results[(q0, q1)]
|
|
243
255
|
assert np.abs(opt_res.x[0] + np.pi / 4) < 0.1
|
|
244
256
|
assert np.abs(opt_res.fun) < 0.1 # noiseless simulator
|
|
@@ -248,7 +260,7 @@ def test_characterize_phased_fsim_parameters_with_xeb():
|
|
|
248
260
|
|
|
249
261
|
|
|
250
262
|
@pytest.mark.parametrize('use_pool', (True, False))
|
|
251
|
-
def test_parallel_full_workflow(use_pool):
|
|
263
|
+
def test_parallel_full_workflow(request, use_pool):
|
|
252
264
|
circuits = rqcg.generate_library_of_2q_circuits(
|
|
253
265
|
n_library_circuits=5,
|
|
254
266
|
two_qubit_gate=cirq.ISWAP**0.5,
|
|
@@ -268,10 +280,8 @@ def test_parallel_full_workflow(use_pool):
|
|
|
268
280
|
combinations_by_layer=combs,
|
|
269
281
|
)
|
|
270
282
|
|
|
271
|
-
if
|
|
272
|
-
|
|
273
|
-
else:
|
|
274
|
-
pool = None
|
|
283
|
+
# avoid starting worker pool if it is not needed
|
|
284
|
+
pool = request.getfixturevalue("pool") if use_pool else None
|
|
275
285
|
|
|
276
286
|
fids_df_0 = benchmark_2q_xeb_fidelities(
|
|
277
287
|
sampled_df=sampled_df, circuits=circuits, cycle_depths=cycle_depths, pool=pool
|
|
@@ -292,8 +302,6 @@ def test_parallel_full_workflow(use_pool):
|
|
|
292
302
|
xatol=5e-2,
|
|
293
303
|
pool=pool,
|
|
294
304
|
)
|
|
295
|
-
if pool is not None:
|
|
296
|
-
pool.terminate()
|
|
297
305
|
|
|
298
306
|
assert len(result.optimization_results) == graph.number_of_edges()
|
|
299
307
|
for opt_res in result.optimization_results.values():
|
|
@@ -354,7 +362,7 @@ def test_options_with_defaults_from_gate():
|
|
|
354
362
|
assert options.zeta_default == 0.0
|
|
355
363
|
|
|
356
364
|
with pytest.raises(ValueError):
|
|
357
|
-
_ = XEBPhasedFSimCharacterizationOptions().with_defaults_from_gate(cirq.
|
|
365
|
+
_ = XEBPhasedFSimCharacterizationOptions().with_defaults_from_gate(cirq.XX)
|
|
358
366
|
|
|
359
367
|
|
|
360
368
|
def test_options_defaults_set():
|
|
@@ -395,3 +403,34 @@ def test_options_defaults_set():
|
|
|
395
403
|
phi_default=0.0,
|
|
396
404
|
)
|
|
397
405
|
assert o3.defaults_set() is True
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _random_angles(n, seed):
|
|
409
|
+
rng = np.random.default_rng(seed)
|
|
410
|
+
r = 2 * rng.random((n, 5)) - 1
|
|
411
|
+
return np.pi * r
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@pytest.mark.parametrize(
|
|
415
|
+
'gate',
|
|
416
|
+
[
|
|
417
|
+
cirq.CZ,
|
|
418
|
+
cirq.SQRT_ISWAP,
|
|
419
|
+
cirq.SQRT_ISWAP_INV,
|
|
420
|
+
cirq.ISWAP,
|
|
421
|
+
cirq.ISWAP_INV,
|
|
422
|
+
cirq.cphase(0.1),
|
|
423
|
+
cirq.CZ**0.2,
|
|
424
|
+
]
|
|
425
|
+
+ [cirq.PhasedFSimGate(*r) for r in _random_angles(10, 0)],
|
|
426
|
+
)
|
|
427
|
+
def test_phased_fsim_angles_from_gate(gate):
|
|
428
|
+
angles = phased_fsim_angles_from_gate(gate)
|
|
429
|
+
angles = {k.removesuffix('_default'): v for k, v in angles.items()}
|
|
430
|
+
phasedfsim = cirq.PhasedFSimGate(**angles)
|
|
431
|
+
np.testing.assert_allclose(cirq.unitary(phasedfsim), cirq.unitary(gate), atol=1e-9)
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def test_phased_fsim_angles_from_gate_unsupporet_gate():
|
|
435
|
+
with pytest.raises(ValueError, match='Unknown default angles'):
|
|
436
|
+
_ = phased_fsim_angles_from_gate(cirq.testing.TwoQubitGate())
|
cirq/experiments/xeb_sampling.py
CHANGED
|
@@ -12,30 +12,28 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Estimation of fidelity associated with experimental circuit executions."""
|
|
15
|
-
import concurrent
|
|
16
15
|
import os
|
|
17
16
|
import time
|
|
18
17
|
import uuid
|
|
19
|
-
from concurrent.futures.thread import ThreadPoolExecutor
|
|
20
18
|
from dataclasses import dataclass
|
|
21
19
|
from typing import (
|
|
20
|
+
Any,
|
|
22
21
|
Callable,
|
|
22
|
+
ContextManager,
|
|
23
|
+
Dict,
|
|
23
24
|
List,
|
|
24
25
|
Optional,
|
|
25
26
|
Sequence,
|
|
27
|
+
Set,
|
|
26
28
|
Tuple,
|
|
27
29
|
TYPE_CHECKING,
|
|
28
|
-
Set,
|
|
29
|
-
ContextManager,
|
|
30
|
-
Dict,
|
|
31
|
-
Any,
|
|
32
30
|
)
|
|
33
31
|
|
|
34
32
|
import numpy as np
|
|
35
33
|
import pandas as pd
|
|
36
34
|
import tqdm
|
|
37
35
|
|
|
38
|
-
from cirq import ops,
|
|
36
|
+
from cirq import devices, ops, protocols, value
|
|
39
37
|
from cirq.circuits import Circuit, Moment
|
|
40
38
|
from cirq.experiments.random_quantum_circuit_generation import CircuitLibraryCombination
|
|
41
39
|
|
|
@@ -276,18 +274,16 @@ def _execute_sample_2q_xeb_tasks_in_batches(
|
|
|
276
274
|
run_batch = _SampleInBatches(
|
|
277
275
|
sampler=sampler, repetitions=repetitions, combinations_by_layer=combinations_by_layer
|
|
278
276
|
)
|
|
279
|
-
with ThreadPoolExecutor(max_workers=2) as pool:
|
|
280
|
-
futures = [pool.submit(run_batch, task_batch) for task_batch in batched_tasks]
|
|
281
277
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
278
|
+
records = []
|
|
279
|
+
with progress_bar(total=len(batched_tasks) * batch_size) as progress:
|
|
280
|
+
for task in batched_tasks:
|
|
281
|
+
new_records = run_batch(task)
|
|
282
|
+
if dataset_directory is not None:
|
|
283
|
+
os.makedirs(f'{dataset_directory}', exist_ok=True)
|
|
284
|
+
protocols.to_json(new_records, f'{dataset_directory}/xeb.{uuid.uuid4()}.json')
|
|
285
|
+
records.extend(new_records)
|
|
286
|
+
progress.update(batch_size)
|
|
291
287
|
return records
|
|
292
288
|
|
|
293
289
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Estimation of fidelity associated with experimental circuit executions."""
|
|
15
15
|
from dataclasses import dataclass
|
|
16
|
-
from typing import List, Optional, Sequence, TYPE_CHECKING
|
|
16
|
+
from typing import Any, Dict, List, Optional, Sequence, TYPE_CHECKING
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
19
|
import pandas as pd
|
|
@@ -21,9 +21,10 @@ import pandas as pd
|
|
|
21
21
|
from cirq import sim, value
|
|
22
22
|
|
|
23
23
|
if TYPE_CHECKING:
|
|
24
|
-
import cirq
|
|
25
24
|
import multiprocessing
|
|
26
25
|
|
|
26
|
+
import cirq
|
|
27
|
+
|
|
27
28
|
|
|
28
29
|
@dataclass(frozen=True)
|
|
29
30
|
class _Simulate2qXEBTask:
|
|
@@ -107,7 +108,7 @@ def simulate_2q_xeb_circuits(
|
|
|
107
108
|
# Need an actual object; not np.random or else multiprocessing will
|
|
108
109
|
# fail to pickle the closure object:
|
|
109
110
|
# https://github.com/quantumlib/Cirq/issues/3717
|
|
110
|
-
simulator = sim.Simulator(seed=np.random.RandomState())
|
|
111
|
+
simulator = sim.Simulator(seed=np.random.RandomState(), dtype=np.complex128)
|
|
111
112
|
_simulate_2q_xeb_circuit = _Simulate_2q_XEB_Circuit(simulator=simulator)
|
|
112
113
|
|
|
113
114
|
tasks = tuple(
|
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import multiprocessing
|
|
15
|
-
from typing import Dict,
|
|
16
|
-
from typing import Sequence
|
|
18
|
+
from typing import Any, Dict, Iterator, Optional, Sequence
|
|
17
19
|
|
|
18
20
|
import numpy as np
|
|
19
21
|
import pandas as pd
|
|
@@ -23,8 +25,17 @@ import cirq
|
|
|
23
25
|
import cirq.experiments.random_quantum_circuit_generation as rqcg
|
|
24
26
|
from cirq.experiments.xeb_simulation import simulate_2q_xeb_circuits
|
|
25
27
|
|
|
28
|
+
_POOL_NUM_PROCESSES = min(4, multiprocessing.cpu_count())
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@pytest.fixture
|
|
32
|
+
def pool() -> Iterator[multiprocessing.pool.Pool]:
|
|
33
|
+
ctx = multiprocessing.get_context()
|
|
34
|
+
with ctx.Pool(_POOL_NUM_PROCESSES) as pool:
|
|
35
|
+
yield pool
|
|
26
36
|
|
|
27
|
-
|
|
37
|
+
|
|
38
|
+
def test_simulate_2q_xeb_circuits(pool):
|
|
28
39
|
q0, q1 = cirq.LineQubit.range(2)
|
|
29
40
|
circuits = [
|
|
30
41
|
rqcg.random_rotations_between_two_qubit_circuit(
|
|
@@ -42,8 +53,7 @@ def test_simulate_2q_xeb_circuits():
|
|
|
42
53
|
assert len(row['pure_probs']) == 4
|
|
43
54
|
assert np.isclose(np.sum(row['pure_probs']), 1)
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
df2 = simulate_2q_xeb_circuits(circuits, cycle_depths, pool=pool)
|
|
56
|
+
df2 = simulate_2q_xeb_circuits(circuits, cycle_depths, pool=pool)
|
|
47
57
|
|
|
48
58
|
pd.testing.assert_frame_equal(df, df2)
|
|
49
59
|
|
|
@@ -76,7 +86,7 @@ def _ref_simulate_2q_xeb_circuit(task: Dict[str, Any]):
|
|
|
76
86
|
tcircuit = circuit[:circuit_depth]
|
|
77
87
|
tcircuit = cirq.resolve_parameters_once(tcircuit, param_resolver=param_resolver)
|
|
78
88
|
|
|
79
|
-
pure_sim = cirq.Simulator()
|
|
89
|
+
pure_sim = cirq.Simulator(dtype=np.complex128)
|
|
80
90
|
psi = pure_sim.simulate(tcircuit)
|
|
81
91
|
psi_vector = psi.final_state_vector
|
|
82
92
|
pure_probs = cirq.state_vector_to_probabilities(psi_vector)
|
|
@@ -118,8 +128,8 @@ def _ref_simulate_2q_xeb_circuits(
|
|
|
118
128
|
return pd.DataFrame(records).set_index(['circuit_i', 'cycle_depth']).sort_index()
|
|
119
129
|
|
|
120
130
|
|
|
121
|
-
@pytest.mark.parametrize('
|
|
122
|
-
def test_incremental_simulate(
|
|
131
|
+
@pytest.mark.parametrize('use_pool', (True, False))
|
|
132
|
+
def test_incremental_simulate(request, use_pool):
|
|
123
133
|
q0, q1 = cirq.LineQubit.range(2)
|
|
124
134
|
circuits = [
|
|
125
135
|
rqcg.random_rotations_between_two_qubit_circuit(
|
|
@@ -129,16 +139,12 @@ def test_incremental_simulate(multiprocess):
|
|
|
129
139
|
]
|
|
130
140
|
cycle_depths = np.arange(3, 100, 9, dtype=np.int64)
|
|
131
141
|
|
|
132
|
-
if
|
|
133
|
-
|
|
134
|
-
else:
|
|
135
|
-
pool = None
|
|
142
|
+
# avoid starting worker pool if it is not needed
|
|
143
|
+
pool = request.getfixturevalue("pool") if use_pool else None
|
|
136
144
|
|
|
137
145
|
df_ref = _ref_simulate_2q_xeb_circuits(circuits=circuits, cycle_depths=cycle_depths, pool=pool)
|
|
138
146
|
|
|
139
147
|
df = simulate_2q_xeb_circuits(circuits=circuits, cycle_depths=cycle_depths, pool=pool)
|
|
140
|
-
if pool is not None:
|
|
141
|
-
pool.terminate()
|
|
142
148
|
pd.testing.assert_frame_equal(df_ref, df)
|
|
143
149
|
|
|
144
150
|
# Use below for approximate equality, if e.g. you're using qsim:
|