cirq-core 1.5.0.dev20250409222543__py3-none-any.whl → 1.6.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 +16 -17
- cirq/_compat.py +21 -20
- cirq/_compat_test.py +14 -34
- cirq/_doc.py +4 -2
- cirq/_import.py +8 -6
- cirq/_import_test.py +4 -2
- cirq/_version.py +6 -6
- cirq/_version_test.py +2 -2
- cirq/circuits/_block_diagram_drawer.py +11 -10
- cirq/circuits/_block_diagram_drawer_test.py +8 -6
- cirq/circuits/_box_drawing_character_data.py +8 -8
- cirq/circuits/_box_drawing_character_data_test.py +3 -1
- cirq/circuits/_bucket_priority_queue.py +9 -7
- cirq/circuits/_bucket_priority_queue_test.py +22 -20
- cirq/circuits/circuit.py +248 -172
- cirq/circuits/circuit_operation.py +73 -83
- cirq/circuits/circuit_operation_test.py +128 -90
- cirq/circuits/circuit_test.py +211 -151
- cirq/circuits/frozen_circuit.py +23 -60
- cirq/circuits/frozen_circuit_test.py +31 -8
- cirq/circuits/insert_strategy.py +7 -5
- cirq/circuits/insert_strategy_test.py +4 -2
- cirq/circuits/moment.py +88 -40
- cirq/circuits/moment_test.py +128 -51
- cirq/circuits/optimization_pass.py +5 -5
- cirq/circuits/optimization_pass_test.py +10 -10
- cirq/circuits/qasm_output.py +11 -11
- cirq/circuits/qasm_output_test.py +25 -22
- cirq/circuits/text_diagram_drawer.py +23 -38
- cirq/circuits/text_diagram_drawer_test.py +19 -17
- cirq/conftest.py +4 -3
- cirq/contrib/__init__.py +4 -4
- cirq/contrib/acquaintance/__init__.py +1 -1
- cirq/contrib/acquaintance/bipartite.py +5 -8
- cirq/contrib/acquaintance/bipartite_test.py +18 -13
- cirq/contrib/acquaintance/devices.py +2 -2
- cirq/contrib/acquaintance/devices_test.py +5 -3
- cirq/contrib/acquaintance/executor.py +5 -5
- cirq/contrib/acquaintance/executor_test.py +13 -9
- cirq/contrib/acquaintance/gates.py +18 -28
- cirq/contrib/acquaintance/gates_test.py +24 -20
- cirq/contrib/acquaintance/inspection_utils.py +8 -4
- cirq/contrib/acquaintance/inspection_utils_test.py +4 -2
- cirq/contrib/acquaintance/mutation_utils.py +4 -4
- cirq/contrib/acquaintance/mutation_utils_test.py +4 -2
- cirq/contrib/acquaintance/optimizers.py +4 -4
- cirq/contrib/acquaintance/optimizers_test.py +4 -1
- cirq/contrib/acquaintance/permutation.py +15 -27
- cirq/contrib/acquaintance/permutation_test.py +26 -17
- cirq/contrib/acquaintance/shift.py +4 -4
- cirq/contrib/acquaintance/shift_swap_network.py +4 -4
- cirq/contrib/acquaintance/shift_swap_network_test.py +9 -6
- cirq/contrib/acquaintance/shift_test.py +8 -6
- cirq/contrib/acquaintance/strategies/cubic.py +2 -2
- cirq/contrib/acquaintance/strategies/cubic_test.py +4 -2
- cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
- cirq/contrib/acquaintance/strategies/quartic_paired_test.py +10 -6
- cirq/contrib/acquaintance/testing.py +2 -0
- cirq/contrib/acquaintance/topological_sort.py +2 -2
- cirq/contrib/acquaintance/topological_sort_test.py +3 -1
- cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
- cirq/contrib/bayesian_network/bayesian_network_gate_test.py +14 -9
- cirq/contrib/circuitdag/circuit_dag.py +4 -4
- cirq/contrib/circuitdag/circuit_dag_test.py +17 -15
- cirq/contrib/custom_simulators/custom_state_simulator.py +5 -5
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +22 -17
- cirq/contrib/graph_device/graph_device.py +12 -11
- cirq/contrib/graph_device/graph_device_test.py +18 -14
- cirq/contrib/graph_device/hypergraph.py +16 -14
- cirq/contrib/graph_device/hypergraph_test.py +13 -11
- cirq/contrib/graph_device/uniform_graph_device.py +6 -4
- cirq/contrib/graph_device/uniform_graph_device_test.py +11 -3
- cirq/contrib/hacks/disable_validation.py +6 -1
- cirq/contrib/hacks/disable_validation_test.py +3 -1
- cirq/contrib/json.py +31 -5
- cirq/contrib/json_test.py +6 -3
- cirq/contrib/json_test_data/DampedReadoutNoiseModel.json +12 -0
- cirq/contrib/json_test_data/DampedReadoutNoiseModel.repr +4 -0
- cirq/contrib/json_test_data/DepolarizingNoiseModel.json +12 -0
- cirq/contrib/json_test_data/DepolarizingNoiseModel.repr +4 -0
- cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.json +6 -0
- cirq/contrib/json_test_data/DepolarizingWithDampedReadoutNoiseModel.repr +1 -0
- cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.json +5 -0
- cirq/contrib/json_test_data/DepolarizingWithReadoutNoiseModel.repr +1 -0
- cirq/contrib/json_test_data/ReadoutNoiseModel.json +12 -0
- cirq/contrib/json_test_data/ReadoutNoiseModel.repr +4 -0
- cirq/contrib/json_test_data/__init__.py +17 -0
- cirq/contrib/json_test_data/spec.py +32 -0
- cirq/contrib/noise_models/noise_models.py +119 -5
- cirq/contrib/noise_models/noise_models_test.py +37 -9
- cirq/contrib/paulistring/clifford_optimize.py +6 -4
- cirq/contrib/paulistring/clifford_optimize_test.py +6 -5
- cirq/contrib/paulistring/clifford_target_gateset.py +10 -10
- cirq/contrib/paulistring/clifford_target_gateset_test.py +13 -11
- cirq/contrib/paulistring/optimize.py +2 -0
- cirq/contrib/paulistring/optimize_test.py +4 -3
- cirq/contrib/paulistring/pauli_string_dag.py +2 -0
- cirq/contrib/paulistring/pauli_string_dag_test.py +3 -1
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +255 -120
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +398 -19
- cirq/contrib/paulistring/pauli_string_optimize.py +7 -1
- cirq/contrib/paulistring/pauli_string_optimize_test.py +5 -3
- cirq/contrib/paulistring/recombine.py +6 -4
- cirq/contrib/paulistring/recombine_test.py +3 -1
- cirq/contrib/paulistring/separate.py +9 -6
- cirq/contrib/paulistring/separate_test.py +3 -1
- cirq/contrib/qasm_import/_lexer.py +3 -2
- cirq/contrib/qasm_import/_lexer_test.py +49 -13
- cirq/contrib/qasm_import/_parser.py +547 -83
- cirq/contrib/qasm_import/_parser_test.py +988 -97
- cirq/contrib/qasm_import/exception.py +2 -0
- cirq/contrib/qasm_import/qasm.py +8 -2
- cirq/contrib/qasm_import/qasm_test.py +7 -4
- cirq/contrib/qcircuit/qcircuit_diagram_info.py +5 -5
- cirq/contrib/qcircuit/qcircuit_diagram_info_test.py +4 -1
- cirq/contrib/qcircuit/qcircuit_pdf.py +7 -3
- cirq/contrib/qcircuit/qcircuit_pdf_test.py +3 -1
- cirq/contrib/qcircuit/qcircuit_test.py +10 -8
- cirq/contrib/quantum_volume/quantum_volume.py +31 -27
- cirq/contrib/quantum_volume/quantum_volume_test.py +19 -16
- cirq/contrib/quimb/density_matrix.py +15 -14
- cirq/contrib/quimb/density_matrix_test.py +10 -7
- cirq/contrib/quimb/grid_circuits.py +5 -2
- cirq/contrib/quimb/grid_circuits_test.py +3 -0
- cirq/contrib/quimb/mps_simulator.py +20 -20
- cirq/contrib/quimb/mps_simulator_test.py +3 -0
- cirq/contrib/quimb/state_vector.py +12 -11
- cirq/contrib/quimb/state_vector_test.py +3 -0
- cirq/contrib/quirk/export_to_quirk.py +5 -3
- cirq/contrib/quirk/export_to_quirk_test.py +18 -16
- cirq/contrib/quirk/linearize_circuit.py +2 -0
- cirq/contrib/quirk/quirk_gate.py +18 -17
- cirq/contrib/routing/device.py +5 -3
- cirq/contrib/routing/device_test.py +2 -0
- cirq/contrib/routing/greedy.py +10 -21
- cirq/contrib/routing/greedy_test.py +4 -2
- cirq/contrib/routing/initialization.py +2 -2
- cirq/contrib/routing/initialization_test.py +5 -3
- cirq/contrib/routing/router.py +9 -5
- cirq/contrib/routing/router_test.py +2 -0
- cirq/contrib/routing/swap_network.py +3 -3
- cirq/contrib/routing/swap_network_test.py +3 -1
- cirq/contrib/routing/utils.py +2 -2
- cirq/contrib/routing/utils_test.py +3 -0
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +15 -9
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +3 -0
- cirq/contrib/svg/svg.py +3 -3
- cirq/contrib/svg/svg_test.py +8 -5
- cirq/devices/device.py +4 -4
- cirq/devices/device_test.py +7 -4
- cirq/devices/grid_device_metadata.py +10 -10
- cirq/devices/grid_device_metadata_test.py +3 -0
- cirq/devices/grid_qubit.py +29 -21
- cirq/devices/grid_qubit_test.py +3 -0
- cirq/devices/insertion_noise_model.py +7 -7
- cirq/devices/insertion_noise_model_test.py +7 -5
- cirq/devices/line_qubit.py +13 -13
- cirq/devices/line_qubit_test.py +2 -0
- cirq/devices/named_topologies.py +18 -29
- cirq/devices/named_topologies_test.py +13 -10
- cirq/devices/noise_model.py +3 -3
- cirq/devices/noise_model_test.py +19 -15
- cirq/devices/noise_properties.py +15 -6
- cirq/devices/noise_properties_test.py +34 -3
- cirq/devices/noise_utils.py +11 -9
- cirq/devices/noise_utils_test.py +2 -0
- cirq/devices/superconducting_qubits_noise_properties.py +23 -22
- cirq/devices/superconducting_qubits_noise_properties_test.py +6 -6
- cirq/devices/thermal_noise_model.py +107 -37
- cirq/devices/thermal_noise_model_test.py +21 -0
- cirq/devices/unconstrained_device.py +5 -3
- cirq/devices/unconstrained_device_test.py +2 -0
- cirq/experiments/__init__.py +4 -2
- cirq/experiments/benchmarking/__init__.py +17 -0
- cirq/experiments/benchmarking/parallel_xeb.py +677 -0
- cirq/experiments/benchmarking/parallel_xeb_test.py +447 -0
- cirq/experiments/fidelity_estimation.py +14 -8
- cirq/experiments/fidelity_estimation_test.py +3 -0
- cirq/experiments/n_qubit_tomography.py +17 -16
- cirq/experiments/n_qubit_tomography_test.py +8 -5
- cirq/experiments/purity_estimation.py +2 -0
- cirq/experiments/purity_estimation_test.py +2 -0
- cirq/experiments/qubit_characterizations.py +207 -103
- cirq/experiments/qubit_characterizations_test.py +40 -12
- cirq/experiments/random_quantum_circuit_generation.py +56 -70
- cirq/experiments/random_quantum_circuit_generation_test.py +11 -8
- cirq/experiments/readout_confusion_matrix.py +24 -22
- cirq/experiments/readout_confusion_matrix_test.py +2 -0
- cirq/experiments/single_qubit_readout_calibration.py +30 -15
- cirq/experiments/single_qubit_readout_calibration_test.py +5 -2
- cirq/experiments/t1_decay_experiment.py +9 -7
- cirq/experiments/t1_decay_experiment_test.py +13 -11
- cirq/experiments/t2_decay_experiment.py +16 -13
- cirq/experiments/t2_decay_experiment_test.py +2 -0
- cirq/experiments/two_qubit_xeb.py +64 -57
- cirq/experiments/two_qubit_xeb_test.py +10 -6
- cirq/experiments/xeb_fitting.py +39 -35
- cirq/experiments/xeb_sampling.py +37 -44
- cirq/experiments/xeb_sampling_test.py +3 -0
- cirq/experiments/xeb_simulation.py +14 -10
- cirq/experiments/xeb_simulation_test.py +5 -5
- cirq/experiments/z_phase_calibration.py +32 -29
- cirq/experiments/z_phase_calibration_test.py +3 -4
- cirq/interop/quirk/cells/__init__.py +1 -1
- cirq/interop/quirk/cells/all_cells.py +7 -2
- cirq/interop/quirk/cells/arithmetic_cells.py +29 -41
- cirq/interop/quirk/cells/arithmetic_cells_test.py +17 -14
- cirq/interop/quirk/cells/cell.py +19 -28
- cirq/interop/quirk/cells/cell_test.py +3 -0
- cirq/interop/quirk/cells/composite_cell.py +13 -28
- cirq/interop/quirk/cells/composite_cell_test.py +2 -0
- cirq/interop/quirk/cells/control_cells.py +15 -15
- cirq/interop/quirk/cells/control_cells_test.py +7 -5
- cirq/interop/quirk/cells/frequency_space_cells.py +4 -3
- cirq/interop/quirk/cells/frequency_space_cells_test.py +3 -1
- cirq/interop/quirk/cells/ignored_cells.py +3 -0
- cirq/interop/quirk/cells/ignored_cells_test.py +3 -1
- cirq/interop/quirk/cells/input_cells.py +7 -5
- cirq/interop/quirk/cells/input_cells_test.py +7 -5
- cirq/interop/quirk/cells/input_rotation_cells.py +15 -13
- cirq/interop/quirk/cells/input_rotation_cells_test.py +9 -7
- cirq/interop/quirk/cells/measurement_cells.py +5 -2
- cirq/interop/quirk/cells/measurement_cells_test.py +3 -1
- cirq/interop/quirk/cells/parse.py +22 -23
- cirq/interop/quirk/cells/parse_test.py +12 -10
- cirq/interop/quirk/cells/qubit_permutation_cells.py +5 -3
- cirq/interop/quirk/cells/qubit_permutation_cells_test.py +9 -7
- cirq/interop/quirk/cells/scalar_cells.py +4 -1
- cirq/interop/quirk/cells/scalar_cells_test.py +3 -1
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +5 -2
- cirq/interop/quirk/cells/single_qubit_rotation_cells_test.py +5 -3
- cirq/interop/quirk/cells/swap_cell.py +8 -6
- cirq/interop/quirk/cells/swap_cell_test.py +6 -4
- cirq/interop/quirk/cells/testing.py +6 -6
- cirq/interop/quirk/cells/testing_test.py +8 -6
- cirq/interop/quirk/cells/unsupported_cells.py +3 -0
- cirq/interop/quirk/cells/unsupported_cells_test.py +4 -2
- cirq/interop/quirk/url_to_circuit.py +23 -36
- cirq/interop/quirk/url_to_circuit_test.py +4 -1
- cirq/json_resolver_cache.py +14 -12
- cirq/linalg/__init__.py +4 -6
- cirq/linalg/combinators.py +7 -5
- cirq/linalg/combinators_test.py +10 -7
- cirq/linalg/decompositions.py +24 -35
- cirq/linalg/decompositions_test.py +3 -1
- cirq/linalg/diagonalize.py +6 -4
- cirq/linalg/diagonalize_test.py +15 -14
- cirq/linalg/operator_spaces.py +14 -14
- cirq/linalg/operator_spaces_test.py +13 -11
- cirq/linalg/predicates.py +18 -9
- cirq/linalg/predicates_test.py +5 -0
- cirq/linalg/tolerance.py +6 -3
- cirq/linalg/tolerance_test.py +6 -4
- cirq/linalg/transformations.py +23 -20
- cirq/linalg/transformations_test.py +73 -43
- cirq/neutral_atoms/convert_to_neutral_atom_gates.py +9 -3
- cirq/neutral_atoms/convert_to_neutral_atom_gates_test.py +3 -1
- cirq/neutral_atoms/neutral_atom_devices.py +2 -0
- cirq/ops/__init__.py +2 -0
- cirq/ops/arithmetic_operation.py +21 -21
- cirq/ops/arithmetic_operation_test.py +7 -8
- cirq/ops/boolean_hamiltonian.py +23 -22
- cirq/ops/boolean_hamiltonian_test.py +12 -9
- cirq/ops/classically_controlled_operation.py +31 -36
- cirq/ops/classically_controlled_operation_test.py +121 -117
- cirq/ops/clifford_gate.py +98 -81
- cirq/ops/clifford_gate_test.py +72 -57
- cirq/ops/common_channels.py +44 -44
- cirq/ops/common_channels_test.py +83 -81
- cirq/ops/common_gate_families.py +9 -7
- cirq/ops/common_gate_families_test.py +11 -7
- cirq/ops/common_gates.py +164 -183
- cirq/ops/common_gates_test.py +135 -95
- cirq/ops/control_values.py +23 -26
- cirq/ops/control_values_test.py +22 -20
- cirq/ops/controlled_gate.py +64 -112
- cirq/ops/controlled_gate_test.py +130 -35
- cirq/ops/controlled_operation.py +24 -35
- cirq/ops/controlled_operation_test.py +8 -6
- cirq/ops/dense_pauli_string.py +38 -49
- cirq/ops/dense_pauli_string_test.py +4 -2
- cirq/ops/diagonal_gate.py +18 -31
- cirq/ops/diagonal_gate_test.py +13 -13
- cirq/ops/eigen_gate.py +29 -29
- cirq/ops/eigen_gate_test.py +45 -28
- cirq/ops/fourier_transform.py +14 -20
- cirq/ops/fourier_transform_test.py +15 -12
- cirq/ops/fsim_gate.py +43 -42
- cirq/ops/fsim_gate_test.py +29 -29
- cirq/ops/gate_features.py +2 -0
- cirq/ops/gate_features_test.py +5 -3
- cirq/ops/gate_operation.py +43 -65
- cirq/ops/gate_operation_test.py +46 -42
- cirq/ops/gateset.py +28 -40
- cirq/ops/gateset_test.py +4 -2
- cirq/ops/global_phase_op.py +45 -20
- cirq/ops/global_phase_op_test.py +44 -20
- cirq/ops/greedy_qubit_manager.py +10 -8
- cirq/ops/greedy_qubit_manager_test.py +5 -3
- cirq/ops/identity.py +14 -12
- cirq/ops/identity_test.py +24 -20
- cirq/ops/kraus_channel.py +11 -8
- cirq/ops/kraus_channel_test.py +14 -11
- cirq/ops/linear_combinations.py +65 -77
- cirq/ops/linear_combinations_test.py +14 -9
- cirq/ops/matrix_gates.py +21 -18
- cirq/ops/matrix_gates_test.py +16 -0
- cirq/ops/measure_util.py +15 -20
- cirq/ops/measure_util_test.py +2 -0
- cirq/ops/measurement_gate.py +26 -37
- cirq/ops/measurement_gate_test.py +2 -0
- cirq/ops/mixed_unitary_channel.py +12 -9
- cirq/ops/mixed_unitary_channel_test.py +14 -11
- cirq/ops/named_qubit.py +16 -13
- cirq/ops/named_qubit_test.py +15 -13
- cirq/ops/op_tree.py +9 -7
- cirq/ops/op_tree_test.py +22 -19
- cirq/ops/parallel_gate.py +15 -17
- cirq/ops/parallel_gate_test.py +18 -16
- cirq/ops/parity_gates.py +23 -25
- cirq/ops/parity_gates_test.py +36 -32
- cirq/ops/pauli_gates.py +22 -21
- cirq/ops/pauli_gates_test.py +29 -20
- cirq/ops/pauli_interaction_gate.py +15 -19
- cirq/ops/pauli_interaction_gate_test.py +10 -8
- cirq/ops/pauli_measurement_gate.py +23 -35
- cirq/ops/pauli_measurement_gate_test.py +2 -0
- cirq/ops/pauli_string.py +92 -120
- cirq/ops/pauli_string_phasor.py +52 -45
- cirq/ops/pauli_string_phasor_test.py +4 -5
- cirq/ops/pauli_string_raw_types.py +9 -7
- cirq/ops/pauli_string_raw_types_test.py +2 -0
- cirq/ops/pauli_string_test.py +31 -154
- cirq/ops/pauli_sum_exponential.py +12 -12
- cirq/ops/pauli_sum_exponential_test.py +12 -10
- cirq/ops/permutation_gate.py +8 -6
- cirq/ops/permutation_gate_test.py +10 -8
- cirq/ops/phased_iswap_gate.py +16 -16
- cirq/ops/phased_iswap_gate_test.py +17 -15
- cirq/ops/phased_x_gate.py +16 -17
- cirq/ops/phased_x_gate_test.py +18 -16
- cirq/ops/phased_x_z_gate.py +24 -22
- cirq/ops/phased_x_z_gate_test.py +17 -11
- cirq/ops/projector.py +16 -11
- cirq/ops/projector_test.py +19 -16
- cirq/ops/qid_util.py +7 -5
- cirq/ops/qid_util_test.py +2 -0
- cirq/ops/qubit_manager.py +11 -9
- cirq/ops/qubit_manager_test.py +6 -4
- cirq/ops/qubit_order.py +11 -14
- cirq/ops/qubit_order_or_list.py +4 -2
- cirq/ops/qubit_order_test.py +12 -10
- cirq/ops/random_gate_channel.py +12 -10
- cirq/ops/random_gate_channel_test.py +14 -11
- cirq/ops/raw_types.py +109 -129
- cirq/ops/raw_types_test.py +63 -57
- cirq/ops/state_preparation_channel.py +7 -7
- cirq/ops/state_preparation_channel_test.py +11 -9
- cirq/ops/swap_gates.py +13 -15
- cirq/ops/swap_gates_test.py +19 -17
- cirq/ops/tags.py +5 -3
- cirq/ops/tags_test.py +4 -2
- cirq/ops/three_qubit_gates.py +43 -76
- cirq/ops/three_qubit_gates_test.py +19 -17
- cirq/ops/two_qubit_diagonal_gate.py +13 -13
- cirq/ops/two_qubit_diagonal_gate_test.py +10 -8
- cirq/ops/uniform_superposition_gate.py +5 -3
- cirq/ops/uniform_superposition_gate_test.py +5 -3
- cirq/ops/wait_gate.py +17 -14
- cirq/ops/wait_gate_test.py +9 -6
- cirq/protocols/__init__.py +0 -3
- cirq/protocols/act_on_protocol.py +8 -6
- cirq/protocols/act_on_protocol_test.py +15 -12
- cirq/protocols/apply_channel_protocol.py +10 -14
- cirq/protocols/apply_channel_protocol_test.py +2 -0
- cirq/protocols/apply_mixture_protocol.py +13 -42
- cirq/protocols/apply_mixture_protocol_test.py +7 -5
- cirq/protocols/apply_unitary_protocol.py +39 -34
- cirq/protocols/apply_unitary_protocol_test.py +4 -1
- cirq/protocols/approximate_equality_protocol.py +2 -0
- cirq/protocols/approximate_equality_protocol_test.py +2 -0
- cirq/protocols/circuit_diagram_info_protocol.py +58 -42
- cirq/protocols/circuit_diagram_info_protocol_test.py +70 -12
- cirq/protocols/commutes_protocol.py +8 -7
- cirq/protocols/commutes_protocol_test.py +2 -0
- cirq/protocols/control_key_protocol.py +6 -4
- cirq/protocols/control_key_protocol_test.py +3 -1
- cirq/protocols/decompose_protocol.py +49 -48
- cirq/protocols/decompose_protocol_test.py +27 -16
- cirq/protocols/equal_up_to_global_phase_protocol.py +2 -0
- cirq/protocols/equal_up_to_global_phase_protocol_test.py +9 -6
- cirq/protocols/has_stabilizer_effect_protocol.py +7 -5
- cirq/protocols/has_stabilizer_effect_protocol_test.py +7 -5
- cirq/protocols/has_unitary_protocol.py +10 -6
- cirq/protocols/has_unitary_protocol_test.py +13 -8
- cirq/protocols/hash_from_pickle_test.py +2 -11
- cirq/protocols/inverse_protocol.py +13 -16
- cirq/protocols/inverse_protocol_test.py +5 -3
- cirq/protocols/json_serialization.py +35 -54
- cirq/protocols/json_serialization_test.py +14 -21
- cirq/protocols/json_test_data/CXSWAP.json +46 -0
- cirq/protocols/json_test_data/CXSWAP.repr +13 -0
- cirq/protocols/json_test_data/CZSWAP.json +46 -0
- cirq/protocols/json_test_data/CZSWAP.repr +13 -0
- cirq/protocols/json_test_data/CircuitOperation.json +6 -3
- cirq/protocols/json_test_data/CircuitOperation.repr_inward +4 -2
- cirq/protocols/json_test_data/Moment.json +24 -1
- cirq/protocols/json_test_data/Moment.repr +6 -1
- cirq/protocols/json_test_data/ThermalNoiseModel.json +32 -0
- cirq/protocols/json_test_data/ThermalNoiseModel.repr +1 -0
- cirq/protocols/json_test_data/spec.py +6 -2
- cirq/protocols/kraus_protocol.py +47 -7
- cirq/protocols/kraus_protocol_test.py +86 -12
- cirq/protocols/measurement_key_protocol.py +15 -16
- cirq/protocols/measurement_key_protocol_test.py +13 -11
- cirq/protocols/mixture_protocol.py +7 -5
- cirq/protocols/mixture_protocol_test.py +4 -2
- cirq/protocols/mul_protocol.py +2 -3
- cirq/protocols/mul_protocol_test.py +2 -0
- cirq/protocols/pauli_expansion_protocol.py +6 -3
- cirq/protocols/pauli_expansion_protocol_test.py +5 -3
- cirq/protocols/phase_protocol.py +2 -0
- cirq/protocols/phase_protocol_test.py +3 -1
- cirq/protocols/pow_protocol.py +11 -16
- cirq/protocols/pow_protocol_test.py +2 -0
- cirq/protocols/qasm.py +14 -20
- cirq/protocols/qasm_test.py +6 -3
- cirq/protocols/qid_shape_protocol.py +8 -8
- cirq/protocols/qid_shape_protocol_test.py +3 -1
- cirq/protocols/resolve_parameters.py +5 -3
- cirq/protocols/resolve_parameters_test.py +8 -7
- cirq/protocols/trace_distance_bound.py +6 -4
- cirq/protocols/trace_distance_bound_test.py +3 -1
- cirq/protocols/unitary_protocol.py +17 -7
- cirq/protocols/unitary_protocol_test.py +12 -2
- cirq/qis/channels.py +6 -2
- cirq/qis/channels_test.py +20 -16
- cirq/qis/clifford_tableau.py +21 -19
- cirq/qis/clifford_tableau_test.py +2 -2
- cirq/qis/entropy.py +14 -3
- cirq/qis/entropy_test.py +3 -1
- cirq/qis/measures.py +13 -13
- cirq/qis/measures_test.py +20 -14
- cirq/qis/noise_utils.py +2 -0
- cirq/qis/noise_utils_test.py +9 -7
- cirq/qis/quantum_state_representation.py +7 -8
- cirq/qis/states.py +58 -56
- cirq/qis/states_test.py +2 -0
- cirq/sim/classical_simulator.py +23 -22
- cirq/sim/classical_simulator_test.py +2 -0
- cirq/sim/clifford/clifford_simulator.py +23 -21
- cirq/sim/clifford/clifford_simulator_test.py +7 -4
- cirq/sim/clifford/clifford_tableau_simulation_state.py +10 -7
- cirq/sim/clifford/clifford_tableau_simulation_state_test.py +5 -5
- cirq/sim/clifford/stabilizer_ch_form_simulation_state.py +8 -6
- cirq/sim/clifford/stabilizer_ch_form_simulation_state_test.py +8 -6
- cirq/sim/clifford/stabilizer_sampler.py +9 -7
- cirq/sim/clifford/stabilizer_sampler_test.py +4 -2
- cirq/sim/clifford/stabilizer_simulation_state.py +14 -13
- cirq/sim/clifford/stabilizer_simulation_state_test.py +6 -4
- cirq/sim/clifford/stabilizer_state_ch_form.py +13 -11
- cirq/sim/clifford/stabilizer_state_ch_form_test.py +4 -2
- cirq/sim/density_matrix_simulation_state.py +26 -27
- cirq/sim/density_matrix_simulation_state_test.py +10 -8
- cirq/sim/density_matrix_simulator.py +30 -28
- cirq/sim/density_matrix_simulator_test.py +48 -48
- cirq/sim/density_matrix_utils.py +13 -11
- cirq/sim/density_matrix_utils_test.py +38 -36
- cirq/sim/mux.py +33 -31
- cirq/sim/mux_test.py +3 -0
- cirq/sim/simulation_product_state.py +15 -15
- cirq/sim/simulation_product_state_test.py +29 -26
- cirq/sim/simulation_state.py +29 -38
- cirq/sim/simulation_state_base.py +21 -32
- cirq/sim/simulation_state_test.py +15 -13
- cirq/sim/simulation_utils.py +5 -2
- cirq/sim/simulation_utils_test.py +5 -2
- cirq/sim/simulator.py +90 -106
- cirq/sim/simulator_base.py +33 -45
- cirq/sim/simulator_base_test.py +20 -15
- cirq/sim/simulator_test.py +23 -14
- cirq/sim/sparse_simulator.py +19 -17
- cirq/sim/sparse_simulator_test.py +41 -40
- cirq/sim/state_vector.py +15 -12
- cirq/sim/state_vector_simulation_state.py +31 -31
- cirq/sim/state_vector_simulation_state_test.py +16 -14
- cirq/sim/state_vector_simulator.py +17 -14
- cirq/sim/state_vector_simulator_test.py +2 -0
- cirq/sim/state_vector_test.py +6 -3
- cirq/study/flatten_expressions.py +16 -15
- cirq/study/flatten_expressions_test.py +13 -11
- cirq/study/resolver.py +18 -17
- cirq/study/resolver_test.py +22 -20
- cirq/study/result.py +17 -27
- cirq/study/result_test.py +2 -0
- cirq/study/sweepable.py +12 -10
- cirq/study/sweepable_test.py +3 -0
- cirq/study/sweeps.py +42 -61
- cirq/study/sweeps_test.py +33 -0
- cirq/testing/__init__.py +7 -11
- cirq/testing/_compat_test_data/module_a/__init__.py +1 -0
- cirq/testing/_compat_test_data/module_a/module_b/__init__.py +1 -0
- cirq/testing/_compat_test_data/module_a/sub/__init__.py +1 -0
- cirq/testing/circuit_compare.py +8 -17
- cirq/testing/circuit_compare_test.py +2 -0
- cirq/testing/consistent_act_on.py +13 -11
- cirq/testing/consistent_act_on_test.py +5 -3
- cirq/testing/consistent_channels.py +2 -0
- cirq/testing/consistent_channels_test.py +10 -8
- cirq/testing/consistent_controlled_gate_op.py +5 -5
- cirq/testing/consistent_controlled_gate_op_test.py +18 -18
- cirq/testing/consistent_decomposition.py +2 -2
- cirq/testing/consistent_decomposition_test.py +4 -2
- cirq/testing/consistent_pauli_expansion.py +2 -0
- cirq/testing/consistent_pauli_expansion_test.py +3 -1
- cirq/testing/consistent_phase_by.py +2 -0
- cirq/testing/consistent_phase_by_test.py +3 -1
- cirq/testing/consistent_protocols.py +14 -20
- cirq/testing/consistent_protocols_test.py +13 -11
- cirq/testing/consistent_qasm.py +6 -4
- cirq/testing/consistent_qasm_test.py +7 -7
- cirq/testing/consistent_resolve_parameters.py +2 -0
- cirq/testing/consistent_specified_has_unitary.py +2 -2
- cirq/testing/consistent_specified_has_unitary_test.py +6 -4
- cirq/testing/consistent_unitary.py +1 -0
- cirq/testing/consistent_unitary_test.py +4 -2
- cirq/testing/deprecation.py +5 -2
- cirq/testing/deprecation_test.py +5 -2
- cirq/testing/devices.py +7 -4
- cirq/testing/devices_test.py +7 -4
- cirq/testing/equals_tester.py +4 -2
- cirq/testing/equals_tester_test.py +21 -17
- cirq/testing/equivalent_basis_map.py +6 -4
- cirq/testing/equivalent_basis_map_test.py +6 -4
- cirq/testing/equivalent_repr_eval.py +6 -4
- cirq/testing/equivalent_repr_eval_test.py +5 -3
- cirq/testing/gate_features.py +2 -0
- cirq/testing/gate_features_test.py +7 -5
- cirq/testing/json.py +19 -15
- cirq/testing/json_test.py +5 -3
- cirq/testing/lin_alg_utils.py +10 -11
- cirq/testing/lin_alg_utils_test.py +14 -12
- cirq/testing/logs.py +7 -6
- cirq/testing/logs_test.py +9 -7
- cirq/testing/no_identifier_qubit.py +4 -2
- cirq/testing/no_identifier_qubit_test.py +5 -3
- cirq/testing/op_tree.py +2 -0
- cirq/testing/op_tree_test.py +4 -1
- cirq/testing/order_tester.py +2 -0
- cirq/testing/order_tester_test.py +8 -6
- cirq/testing/pytest_utils.py +2 -0
- cirq/testing/pytest_utils_test.py +4 -2
- cirq/testing/random_circuit.py +21 -20
- cirq/testing/random_circuit_test.py +12 -9
- cirq/testing/repr_pretty_tester.py +1 -0
- cirq/testing/repr_pretty_tester_test.py +5 -3
- cirq/testing/routing_devices.py +4 -1
- cirq/testing/routing_devices_test.py +9 -6
- cirq/testing/sample_circuits.py +4 -1
- cirq/testing/sample_circuits_test.py +3 -1
- cirq/testing/sample_gates.py +3 -0
- cirq/testing/sample_gates_test.py +5 -2
- cirq/transformers/__init__.py +11 -4
- cirq/transformers/align.py +9 -7
- cirq/transformers/align_test.py +2 -0
- cirq/transformers/analytical_decompositions/__init__.py +3 -6
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +18 -16
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +19 -16
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +2 -0
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +11 -9
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +5 -3
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +5 -3
- cirq/transformers/analytical_decompositions/pauli_string_decomposition_test.py +5 -3
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +141 -44
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +35 -1
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +8 -7
- cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +2 -0
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +7 -4
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +3 -0
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +11 -19
- cirq/transformers/analytical_decompositions/three_qubit_decomposition_test.py +8 -33
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +9 -11
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +2 -0
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +91 -27
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +36 -7
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +20 -21
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim_test.py +8 -6
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +13 -15
- cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +3 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +39 -41
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +2 -0
- cirq/transformers/drop_empty_moments.py +5 -3
- cirq/transformers/drop_empty_moments_test.py +4 -2
- cirq/transformers/drop_negligible_operations.py +7 -5
- cirq/transformers/drop_negligible_operations_test.py +2 -0
- cirq/transformers/dynamical_decoupling.py +49 -42
- cirq/transformers/dynamical_decoupling_test.py +223 -205
- cirq/transformers/eject_phased_paulis.py +28 -26
- cirq/transformers/eject_phased_paulis_test.py +12 -9
- cirq/transformers/eject_z.py +12 -12
- cirq/transformers/eject_z_test.py +2 -2
- cirq/transformers/expand_composite.py +6 -4
- cirq/transformers/expand_composite_test.py +3 -1
- cirq/transformers/gauge_compiling/__init__.py +3 -1
- cirq/transformers/gauge_compiling/cphase_gauge.py +2 -0
- cirq/transformers/gauge_compiling/cphase_gauge_test.py +2 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +2 -0
- cirq/transformers/gauge_compiling/cz_gauge_test.py +1 -0
- cirq/transformers/gauge_compiling/gauge_compiling.py +45 -41
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +2 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +1 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +5 -1
- cirq/transformers/gauge_compiling/iswap_gauge.py +2 -0
- cirq/transformers/gauge_compiling/iswap_gauge_test.py +1 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +2 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +2 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +7 -6
- cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +2 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +2 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +2 -0
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +6 -3
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +3 -0
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +12 -9
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation_test.py +9 -7
- cirq/transformers/insertion_sort.py +8 -6
- cirq/transformers/insertion_sort_test.py +3 -1
- cirq/transformers/measurement_transformers.py +29 -29
- cirq/transformers/measurement_transformers_test.py +2 -0
- cirq/transformers/merge_k_qubit_gates.py +12 -10
- cirq/transformers/merge_k_qubit_gates_test.py +18 -18
- cirq/transformers/merge_single_qubit_gates.py +197 -20
- cirq/transformers/merge_single_qubit_gates_test.py +177 -5
- cirq/transformers/noise_adding.py +5 -3
- cirq/transformers/noise_adding_test.py +2 -0
- cirq/transformers/optimize_for_target_gateset.py +19 -17
- cirq/transformers/optimize_for_target_gateset_test.py +11 -8
- cirq/transformers/qubit_management_transformers.py +13 -11
- cirq/transformers/qubit_management_transformers_test.py +5 -3
- cirq/transformers/randomized_measurements.py +16 -14
- cirq/transformers/randomized_measurements_test.py +10 -4
- cirq/transformers/routing/initial_mapper.py +6 -4
- cirq/transformers/routing/initial_mapper_test.py +2 -0
- cirq/transformers/routing/line_initial_mapper.py +16 -14
- cirq/transformers/routing/line_initial_mapper_test.py +9 -7
- cirq/transformers/routing/mapping_manager.py +10 -10
- cirq/transformers/routing/mapping_manager_test.py +2 -0
- cirq/transformers/routing/route_circuit_cqc.py +33 -31
- cirq/transformers/routing/route_circuit_cqc_test.py +15 -13
- cirq/transformers/routing/visualize_routed_circuit.py +8 -7
- cirq/transformers/routing/visualize_routed_circuit_test.py +4 -2
- cirq/transformers/stratify.py +17 -15
- cirq/transformers/stratify_test.py +3 -0
- cirq/transformers/symbolize.py +103 -0
- cirq/transformers/symbolize_test.py +62 -0
- cirq/transformers/synchronize_terminal_measurements.py +10 -10
- cirq/transformers/synchronize_terminal_measurements_test.py +12 -10
- cirq/transformers/tag_transformers.py +97 -0
- cirq/transformers/tag_transformers_test.py +103 -0
- cirq/transformers/target_gatesets/compilation_target_gateset.py +21 -19
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +20 -16
- cirq/transformers/target_gatesets/cz_gateset.py +7 -5
- cirq/transformers/target_gatesets/cz_gateset_test.py +21 -19
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +9 -7
- cirq/transformers/target_gatesets/sqrt_iswap_gateset_test.py +25 -25
- cirq/transformers/transformer_api.py +34 -47
- cirq/transformers/transformer_api_test.py +9 -8
- cirq/transformers/transformer_primitives.py +39 -49
- cirq/transformers/transformer_primitives_test.py +10 -17
- cirq/value/abc_alt.py +6 -4
- cirq/value/abc_alt_test.py +5 -3
- cirq/value/angle.py +11 -12
- cirq/value/angle_test.py +5 -3
- cirq/value/classical_data.py +27 -27
- cirq/value/classical_data_test.py +11 -8
- cirq/value/condition.py +26 -24
- cirq/value/condition_test.py +2 -0
- cirq/value/digits.py +14 -11
- cirq/value/digits_test.py +2 -0
- cirq/value/duration.py +23 -20
- cirq/value/duration_test.py +2 -0
- cirq/value/linear_dict.py +25 -30
- cirq/value/linear_dict_test.py +10 -8
- cirq/value/measurement_key.py +12 -12
- cirq/value/measurement_key_test.py +2 -0
- cirq/value/periodic_value.py +4 -4
- cirq/value/periodic_value_test.py +11 -7
- cirq/value/probability.py +3 -1
- cirq/value/probability_test.py +4 -2
- cirq/value/product_state.py +15 -13
- cirq/value/product_state_test.py +4 -1
- cirq/value/random_state.py +2 -0
- cirq/value/random_state_test.py +5 -3
- cirq/value/timestamp.py +11 -7
- cirq/value/timestamp_test.py +14 -12
- cirq/value/type_alias.py +4 -4
- cirq/value/value_equality_attr.py +8 -9
- cirq/value/value_equality_attr_test.py +14 -11
- cirq/vis/density_matrix.py +3 -3
- cirq/vis/density_matrix_test.py +20 -17
- cirq/vis/heatmap.py +24 -37
- cirq/vis/heatmap_test.py +3 -0
- cirq/vis/histogram.py +9 -6
- cirq/vis/histogram_test.py +5 -2
- cirq/vis/state_histogram.py +10 -8
- cirq/vis/state_histogram_test.py +7 -5
- cirq/vis/vis_utils.py +4 -1
- cirq/vis/vis_utils_test.py +4 -1
- cirq/work/collector.py +12 -18
- cirq/work/collector_test.py +15 -10
- cirq/work/observable_grouping.py +6 -7
- cirq/work/observable_grouping_test.py +10 -9
- cirq/work/observable_measurement.py +47 -45
- cirq/work/observable_measurement_data.py +22 -17
- cirq/work/observable_measurement_data_test.py +4 -1
- cirq/work/observable_measurement_test.py +48 -29
- cirq/work/observable_readout_calibration.py +5 -2
- cirq/work/observable_readout_calibration_test.py +5 -2
- cirq/work/observable_settings.py +13 -22
- cirq/work/observable_settings_test.py +9 -7
- cirq/work/pauli_sum_collector.py +12 -10
- cirq/work/pauli_sum_collector_test.py +9 -9
- cirq/work/sampler.py +42 -43
- cirq/work/sampler_test.py +31 -24
- cirq/work/zeros_sampler.py +6 -4
- cirq/work/zeros_sampler_test.py +7 -5
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/METADATA +7 -8
- cirq_core-1.6.0.dist-info/RECORD +1241 -0
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/WHEEL +1 -1
- cirq_core-1.5.0.dev20250409222543.dist-info/RECORD +0 -1216
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.5.0.dev20250409222543.dist-info → cirq_core-1.6.0.dist-info}/top_level.txt +0 -0
cirq/ops/linear_combinations.py
CHANGED
|
@@ -12,27 +12,14 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import numbers
|
|
16
18
|
from collections import defaultdict
|
|
17
|
-
from typing import
|
|
18
|
-
AbstractSet,
|
|
19
|
-
Any,
|
|
20
|
-
DefaultDict,
|
|
21
|
-
Dict,
|
|
22
|
-
FrozenSet,
|
|
23
|
-
Iterable,
|
|
24
|
-
List,
|
|
25
|
-
Mapping,
|
|
26
|
-
Optional,
|
|
27
|
-
Tuple,
|
|
28
|
-
TYPE_CHECKING,
|
|
29
|
-
Union,
|
|
30
|
-
)
|
|
19
|
+
from typing import AbstractSet, Any, Iterable, Mapping, TYPE_CHECKING, Union
|
|
31
20
|
|
|
32
21
|
import numpy as np
|
|
33
|
-
|
|
34
|
-
from sympy.core.expr import Expr
|
|
35
|
-
from sympy.core.symbol import Symbol
|
|
22
|
+
import sympy
|
|
36
23
|
from sympy.logic.boolalg import And, Not, Or, Xor
|
|
37
24
|
|
|
38
25
|
from cirq import linalg, protocols, qis, value
|
|
@@ -44,9 +31,11 @@ from cirq.ops.projector import ProjectorString
|
|
|
44
31
|
from cirq.value.linear_dict import _format_terms
|
|
45
32
|
|
|
46
33
|
if TYPE_CHECKING:
|
|
34
|
+
from scipy.sparse import csr_matrix
|
|
35
|
+
|
|
47
36
|
import cirq
|
|
48
37
|
|
|
49
|
-
UnitPauliStringT =
|
|
38
|
+
UnitPauliStringT = frozenset[tuple[raw_types.Qid, pauli_gates.Pauli]]
|
|
50
39
|
PauliSumLike = Union[
|
|
51
40
|
complex, PauliString, 'PauliSum', pauli_string.SingleQubitPauliStringGateOperation
|
|
52
41
|
]
|
|
@@ -81,7 +70,7 @@ class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]):
|
|
|
81
70
|
2 * cirq.X - 2 * cirq.Z
|
|
82
71
|
"""
|
|
83
72
|
|
|
84
|
-
def __init__(self, terms: Mapping[raw_types.Gate,
|
|
73
|
+
def __init__(self, terms: Mapping[raw_types.Gate, cirq.TParamValComplex]) -> None:
|
|
85
74
|
"""Initializes linear combination from a collection of terms.
|
|
86
75
|
|
|
87
76
|
Args:
|
|
@@ -90,45 +79,41 @@ class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]):
|
|
|
90
79
|
"""
|
|
91
80
|
super().__init__(terms, validator=self._is_compatible)
|
|
92
81
|
|
|
93
|
-
def num_qubits(self) ->
|
|
82
|
+
def num_qubits(self) -> int | None:
|
|
94
83
|
"""Returns number of qubits in the domain if known, None if unknown."""
|
|
95
84
|
if not self:
|
|
96
85
|
return None
|
|
97
86
|
any_gate = next(iter(self))
|
|
98
87
|
return any_gate.num_qubits()
|
|
99
88
|
|
|
100
|
-
def _is_compatible(self, gate:
|
|
89
|
+
def _is_compatible(self, gate: cirq.Gate) -> bool:
|
|
101
90
|
return self.num_qubits() is None or self.num_qubits() == gate.num_qubits()
|
|
102
91
|
|
|
103
|
-
def __add__(
|
|
104
|
-
self, other: Union[raw_types.Gate, 'LinearCombinationOfGates']
|
|
105
|
-
) -> 'LinearCombinationOfGates':
|
|
92
|
+
def __add__(self, other: raw_types.Gate | LinearCombinationOfGates) -> LinearCombinationOfGates:
|
|
106
93
|
if not isinstance(other, LinearCombinationOfGates):
|
|
107
94
|
other = other.wrap_in_linear_combination()
|
|
108
95
|
return super().__add__(other)
|
|
109
96
|
|
|
110
97
|
def __iadd__(
|
|
111
|
-
self, other:
|
|
112
|
-
) ->
|
|
98
|
+
self, other: raw_types.Gate | LinearCombinationOfGates
|
|
99
|
+
) -> LinearCombinationOfGates:
|
|
113
100
|
if not isinstance(other, LinearCombinationOfGates):
|
|
114
101
|
other = other.wrap_in_linear_combination()
|
|
115
102
|
return super().__iadd__(other)
|
|
116
103
|
|
|
117
|
-
def __sub__(
|
|
118
|
-
self, other: Union[raw_types.Gate, 'LinearCombinationOfGates']
|
|
119
|
-
) -> 'LinearCombinationOfGates':
|
|
104
|
+
def __sub__(self, other: raw_types.Gate | LinearCombinationOfGates) -> LinearCombinationOfGates:
|
|
120
105
|
if not isinstance(other, LinearCombinationOfGates):
|
|
121
106
|
other = other.wrap_in_linear_combination()
|
|
122
107
|
return super().__sub__(other)
|
|
123
108
|
|
|
124
109
|
def __isub__(
|
|
125
|
-
self, other:
|
|
126
|
-
) ->
|
|
110
|
+
self, other: raw_types.Gate | LinearCombinationOfGates
|
|
111
|
+
) -> LinearCombinationOfGates:
|
|
127
112
|
if not isinstance(other, LinearCombinationOfGates):
|
|
128
113
|
other = other.wrap_in_linear_combination()
|
|
129
114
|
return super().__isub__(other)
|
|
130
115
|
|
|
131
|
-
def __pow__(self, exponent: int) ->
|
|
116
|
+
def __pow__(self, exponent: int) -> LinearCombinationOfGates:
|
|
132
117
|
if not isinstance(exponent, int):
|
|
133
118
|
return NotImplemented
|
|
134
119
|
if exponent < 0:
|
|
@@ -155,8 +140,8 @@ class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]):
|
|
|
155
140
|
return {name for item in self.items() for name in protocols.parameter_names(item)}
|
|
156
141
|
|
|
157
142
|
def _resolve_parameters_(
|
|
158
|
-
self, resolver:
|
|
159
|
-
) ->
|
|
143
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
144
|
+
) -> LinearCombinationOfGates:
|
|
160
145
|
return self.__class__(
|
|
161
146
|
{
|
|
162
147
|
protocols.resolve_parameters(
|
|
@@ -224,7 +209,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
224
209
|
by the identity operator. Note that A may not be unitary or even normal.
|
|
225
210
|
"""
|
|
226
211
|
|
|
227
|
-
def __init__(self, terms: Mapping[raw_types.Operation,
|
|
212
|
+
def __init__(self, terms: Mapping[raw_types.Operation, cirq.TParamValComplex]) -> None:
|
|
228
213
|
"""Initializes linear combination from a collection of terms.
|
|
229
214
|
|
|
230
215
|
Args:
|
|
@@ -233,11 +218,11 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
233
218
|
"""
|
|
234
219
|
super().__init__(terms, validator=self._is_compatible)
|
|
235
220
|
|
|
236
|
-
def _is_compatible(self, operation:
|
|
221
|
+
def _is_compatible(self, operation: cirq.Operation) -> bool:
|
|
237
222
|
return isinstance(operation, raw_types.Operation)
|
|
238
223
|
|
|
239
224
|
@property
|
|
240
|
-
def qubits(self) ->
|
|
225
|
+
def qubits(self) -> tuple[raw_types.Qid, ...]:
|
|
241
226
|
"""Returns qubits acted on self."""
|
|
242
227
|
if not self:
|
|
243
228
|
return ()
|
|
@@ -245,7 +230,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
245
230
|
all_qubits = set.union(*qubit_sets)
|
|
246
231
|
return tuple(sorted(all_qubits))
|
|
247
232
|
|
|
248
|
-
def __pow__(self, exponent: int) ->
|
|
233
|
+
def __pow__(self, exponent: int) -> LinearCombinationOfOperations:
|
|
249
234
|
if not isinstance(exponent, int):
|
|
250
235
|
return NotImplemented
|
|
251
236
|
if exponent < 0:
|
|
@@ -272,8 +257,8 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
272
257
|
return {name for item in self.items() for name in protocols.parameter_names(item)}
|
|
273
258
|
|
|
274
259
|
def _resolve_parameters_(
|
|
275
|
-
self, resolver:
|
|
276
|
-
) ->
|
|
260
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
261
|
+
) -> LinearCombinationOfOperations:
|
|
277
262
|
return self.__class__(
|
|
278
263
|
{
|
|
279
264
|
protocols.resolve_parameters(op, resolver, recursive): protocols.resolve_parameters(
|
|
@@ -300,7 +285,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
300
285
|
workspace = np.empty_like(identity)
|
|
301
286
|
axes = tuple(qubit_to_axis[q] for q in op.qubits)
|
|
302
287
|
u = protocols.apply_unitary(op, protocols.ApplyUnitaryArgs(identity, workspace, axes))
|
|
303
|
-
result += coefficient * u
|
|
288
|
+
result += complex(coefficient) * u
|
|
304
289
|
return result.reshape((num_dim, num_dim))
|
|
305
290
|
|
|
306
291
|
def _has_unitary_(self) -> bool:
|
|
@@ -317,7 +302,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
317
302
|
"""Computes Pauli expansion of self from Pauli expansions of terms."""
|
|
318
303
|
|
|
319
304
|
def extend_term(
|
|
320
|
-
pauli_names: str, qubits:
|
|
305
|
+
pauli_names: str, qubits: tuple[cirq.Qid, ...], all_qubits: tuple[cirq.Qid, ...]
|
|
321
306
|
) -> str:
|
|
322
307
|
"""Extends Pauli product on qubits to product on all_qubits."""
|
|
323
308
|
assert len(pauli_names) == len(qubits)
|
|
@@ -326,8 +311,8 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
326
311
|
|
|
327
312
|
def extend(
|
|
328
313
|
expansion: value.LinearDict[str],
|
|
329
|
-
qubits:
|
|
330
|
-
all_qubits:
|
|
314
|
+
qubits: tuple[cirq.Qid, ...],
|
|
315
|
+
all_qubits: tuple[cirq.Qid, ...],
|
|
331
316
|
) -> value.LinearDict[str]:
|
|
332
317
|
"""Extends Pauli expansion on qubits to expansion on all_qubits."""
|
|
333
318
|
return value.LinearDict(
|
|
@@ -358,7 +343,7 @@ def _is_linear_dict_of_unit_pauli_string(linear_dict: value.LinearDict[UnitPauli
|
|
|
358
343
|
|
|
359
344
|
|
|
360
345
|
def _pauli_string_from_unit(
|
|
361
|
-
unit: UnitPauliStringT, coefficient:
|
|
346
|
+
unit: UnitPauliStringT, coefficient: int | float | cirq.TParamValComplex = 1
|
|
362
347
|
):
|
|
363
348
|
return PauliString(qubit_pauli_map=dict(unit), coefficient=coefficient)
|
|
364
349
|
|
|
@@ -416,7 +401,7 @@ class PauliSum:
|
|
|
416
401
|
4.0+0.0j
|
|
417
402
|
"""
|
|
418
403
|
|
|
419
|
-
def __init__(self, linear_dict:
|
|
404
|
+
def __init__(self, linear_dict: value.LinearDict[UnitPauliStringT] | None = None):
|
|
420
405
|
"""Construct a PauliSum from a linear dictionary.
|
|
421
406
|
|
|
422
407
|
Note, the preferred method of constructing PauliSum objects is either implicitly
|
|
@@ -444,7 +429,7 @@ class PauliSum:
|
|
|
444
429
|
return self._linear_dict
|
|
445
430
|
|
|
446
431
|
@staticmethod
|
|
447
|
-
def wrap(val: PauliSumLike) ->
|
|
432
|
+
def wrap(val: PauliSumLike) -> PauliSum:
|
|
448
433
|
"""Convert a `cirq.PauliSumLike` object to a PauliSum
|
|
449
434
|
|
|
450
435
|
Attempts to convert an existing int, float, complex, `cirq.PauliString`,
|
|
@@ -468,7 +453,7 @@ class PauliSum:
|
|
|
468
453
|
return PauliSum() + val
|
|
469
454
|
|
|
470
455
|
@classmethod
|
|
471
|
-
def from_pauli_strings(cls, terms:
|
|
456
|
+
def from_pauli_strings(cls, terms: PauliString | list[PauliString]) -> PauliSum:
|
|
472
457
|
"""Returns a PauliSum by combining `cirq.PauliString` terms.
|
|
473
458
|
|
|
474
459
|
Args:
|
|
@@ -480,7 +465,7 @@ class PauliSum:
|
|
|
480
465
|
"""
|
|
481
466
|
if isinstance(terms, PauliString):
|
|
482
467
|
terms = [terms]
|
|
483
|
-
termdict:
|
|
468
|
+
termdict: defaultdict[UnitPauliStringT, value.Scalar] = defaultdict(lambda: 0)
|
|
484
469
|
for pstring in terms:
|
|
485
470
|
key = frozenset(pstring._qubit_pauli_map.items())
|
|
486
471
|
termdict[key] += pstring.coefficient
|
|
@@ -488,8 +473,8 @@ class PauliSum:
|
|
|
488
473
|
|
|
489
474
|
@classmethod
|
|
490
475
|
def from_boolean_expression(
|
|
491
|
-
cls, boolean_expr: Expr, qubit_map:
|
|
492
|
-
) ->
|
|
476
|
+
cls, boolean_expr: sympy.Expr, qubit_map: dict[str, cirq.Qid]
|
|
477
|
+
) -> PauliSum:
|
|
493
478
|
"""Builds the Hamiltonian representation of a Boolean expression.
|
|
494
479
|
|
|
495
480
|
This is based on "On the representation of Boolean and real functions as Hamiltonians for
|
|
@@ -505,7 +490,7 @@ class PauliSum:
|
|
|
505
490
|
Raises:
|
|
506
491
|
ValueError: If `boolean_expr` is of an unsupported type.
|
|
507
492
|
"""
|
|
508
|
-
if isinstance(boolean_expr, Symbol):
|
|
493
|
+
if isinstance(boolean_expr, sympy.Symbol):
|
|
509
494
|
# In table 1, the entry for 'x' is '1/2.I - 1/2.Z'
|
|
510
495
|
return cls.from_pauli_strings(
|
|
511
496
|
[
|
|
@@ -540,12 +525,12 @@ class PauliSum:
|
|
|
540
525
|
raise ValueError(f'Unsupported type: {type(boolean_expr)}')
|
|
541
526
|
|
|
542
527
|
@property
|
|
543
|
-
def qubits(self) ->
|
|
528
|
+
def qubits(self) -> tuple[raw_types.Qid, ...]:
|
|
544
529
|
"""The sorted list of qubits used in this PauliSum."""
|
|
545
530
|
qs = {q for k in self._linear_dict.keys() for q, _ in k}
|
|
546
531
|
return tuple(sorted(qs))
|
|
547
532
|
|
|
548
|
-
def with_qubits(self, *new_qubits:
|
|
533
|
+
def with_qubits(self, *new_qubits: cirq.Qid) -> PauliSum:
|
|
549
534
|
"""Return a new PauliSum on `new_qubits`.
|
|
550
535
|
|
|
551
536
|
Args:
|
|
@@ -569,7 +554,7 @@ class PauliSum:
|
|
|
569
554
|
new_pauli_strings.append(pauli_string.map_qubits(qubit_map))
|
|
570
555
|
return PauliSum.from_pauli_strings(new_pauli_strings)
|
|
571
556
|
|
|
572
|
-
def copy(self) ->
|
|
557
|
+
def copy(self) -> PauliSum:
|
|
573
558
|
"""Return a copy of this PauliSum.
|
|
574
559
|
|
|
575
560
|
Returns: A copy of this PauliSum.
|
|
@@ -577,7 +562,7 @@ class PauliSum:
|
|
|
577
562
|
factory = type(self)
|
|
578
563
|
return factory(self._linear_dict.copy())
|
|
579
564
|
|
|
580
|
-
def matrix(self, qubits:
|
|
565
|
+
def matrix(self, qubits: Iterable[raw_types.Qid] | None = None) -> np.ndarray:
|
|
581
566
|
"""Returns the matrix of this PauliSum in computational basis of qubits.
|
|
582
567
|
|
|
583
568
|
Args:
|
|
@@ -761,6 +746,10 @@ class PauliSum:
|
|
|
761
746
|
other = PauliSum.from_pauli_strings([PauliString(coefficient=other)])
|
|
762
747
|
elif isinstance(other, PauliString):
|
|
763
748
|
other = PauliSum.from_pauli_strings([other])
|
|
749
|
+
elif isinstance(other, raw_types.Operation) and isinstance(
|
|
750
|
+
other.gate, identity.IdentityGate
|
|
751
|
+
):
|
|
752
|
+
other = PauliSum.from_pauli_strings([PauliString()])
|
|
764
753
|
|
|
765
754
|
if not isinstance(other, PauliSum):
|
|
766
755
|
return NotImplemented
|
|
@@ -769,11 +758,8 @@ class PauliSum:
|
|
|
769
758
|
return self
|
|
770
759
|
|
|
771
760
|
def __add__(self, other):
|
|
772
|
-
if not isinstance(other, (numbers.Complex, PauliString, PauliSum)):
|
|
773
|
-
|
|
774
|
-
other = PauliString(other)
|
|
775
|
-
else:
|
|
776
|
-
return NotImplemented
|
|
761
|
+
if not isinstance(other, (numbers.Complex, PauliString, PauliSum, raw_types.Operation)):
|
|
762
|
+
return NotImplemented
|
|
777
763
|
result = self.copy()
|
|
778
764
|
result += other
|
|
779
765
|
return result
|
|
@@ -787,8 +773,12 @@ class PauliSum:
|
|
|
787
773
|
def __isub__(self, other):
|
|
788
774
|
if isinstance(other, numbers.Complex):
|
|
789
775
|
other = PauliSum.from_pauli_strings([PauliString(coefficient=other)])
|
|
790
|
-
|
|
776
|
+
elif isinstance(other, PauliString):
|
|
791
777
|
other = PauliSum.from_pauli_strings([other])
|
|
778
|
+
elif isinstance(other, raw_types.Operation) and isinstance(
|
|
779
|
+
other.gate, identity.IdentityGate
|
|
780
|
+
):
|
|
781
|
+
other = PauliSum.from_pauli_strings([PauliString()])
|
|
792
782
|
|
|
793
783
|
if not isinstance(other, PauliSum):
|
|
794
784
|
return NotImplemented
|
|
@@ -797,7 +787,7 @@ class PauliSum:
|
|
|
797
787
|
return self
|
|
798
788
|
|
|
799
789
|
def __sub__(self, other):
|
|
800
|
-
if not isinstance(other, (numbers.Complex, PauliString, PauliSum)):
|
|
790
|
+
if not isinstance(other, (numbers.Complex, PauliString, PauliSum, raw_types.Operation)):
|
|
801
791
|
return NotImplemented
|
|
802
792
|
result = self.copy()
|
|
803
793
|
result -= other
|
|
@@ -881,7 +871,7 @@ class ProjectorSum:
|
|
|
881
871
|
"""List of mappings representing a sum of projector operators."""
|
|
882
872
|
|
|
883
873
|
def __init__(
|
|
884
|
-
self, linear_dict:
|
|
874
|
+
self, linear_dict: value.LinearDict[frozenset[tuple[raw_types.Qid, int]]] | None = None
|
|
885
875
|
):
|
|
886
876
|
"""Constructor for ProjectorSum
|
|
887
877
|
|
|
@@ -890,7 +880,7 @@ class ProjectorSum:
|
|
|
890
880
|
number. The tuple is a projector onto the qubit and the complex number is the
|
|
891
881
|
weight of these projections.
|
|
892
882
|
"""
|
|
893
|
-
self._linear_dict: value.LinearDict[
|
|
883
|
+
self._linear_dict: value.LinearDict[frozenset[tuple[raw_types.Qid, int]]] = (
|
|
894
884
|
linear_dict if linear_dict is not None else value.LinearDict({})
|
|
895
885
|
)
|
|
896
886
|
|
|
@@ -898,11 +888,11 @@ class ProjectorSum:
|
|
|
898
888
|
return self._linear_dict
|
|
899
889
|
|
|
900
890
|
@property
|
|
901
|
-
def qubits(self) ->
|
|
891
|
+
def qubits(self) -> tuple[raw_types.Qid, ...]:
|
|
902
892
|
qs = {q for k in self._linear_dict.keys() for q, _ in k}
|
|
903
893
|
return tuple(sorted(qs))
|
|
904
894
|
|
|
905
|
-
def _json_dict_(self) ->
|
|
895
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
906
896
|
linear_dict = []
|
|
907
897
|
for projector_dict, scalar in dict(self._linear_dict).items():
|
|
908
898
|
key = [[k, v] for k, v in dict(projector_dict).items()]
|
|
@@ -920,9 +910,7 @@ class ProjectorSum:
|
|
|
920
910
|
return cls(linear_dict=value.LinearDict(converted_dict))
|
|
921
911
|
|
|
922
912
|
@classmethod
|
|
923
|
-
def from_projector_strings(
|
|
924
|
-
cls, terms: Union[ProjectorString, List[ProjectorString]]
|
|
925
|
-
) -> 'ProjectorSum':
|
|
913
|
+
def from_projector_strings(cls, terms: ProjectorString | list[ProjectorString]) -> ProjectorSum:
|
|
926
914
|
"""Builds a ProjectorSum from one or more ProjectorString(s).
|
|
927
915
|
|
|
928
916
|
Args:
|
|
@@ -933,7 +921,7 @@ class ProjectorSum:
|
|
|
933
921
|
"""
|
|
934
922
|
if isinstance(terms, ProjectorString):
|
|
935
923
|
terms = [terms]
|
|
936
|
-
termdict:
|
|
924
|
+
termdict: defaultdict[frozenset[tuple[raw_types.Qid, int]], value.Scalar] = defaultdict(
|
|
937
925
|
lambda: 0.0
|
|
938
926
|
)
|
|
939
927
|
for pstring in terms:
|
|
@@ -941,10 +929,10 @@ class ProjectorSum:
|
|
|
941
929
|
termdict[key] += pstring.coefficient
|
|
942
930
|
return cls(linear_dict=value.LinearDict(termdict))
|
|
943
931
|
|
|
944
|
-
def copy(self) ->
|
|
932
|
+
def copy(self) -> ProjectorSum:
|
|
945
933
|
return ProjectorSum(self._linear_dict.copy())
|
|
946
934
|
|
|
947
|
-
def matrix(self, projector_qids:
|
|
935
|
+
def matrix(self, projector_qids: Iterable[raw_types.Qid] | None = None) -> csr_matrix:
|
|
948
936
|
"""Returns the matrix of self in computational basis of qubits.
|
|
949
937
|
|
|
950
938
|
Args:
|
|
@@ -1022,7 +1010,7 @@ class ProjectorSum:
|
|
|
1022
1010
|
def __bool__(self) -> bool:
|
|
1023
1011
|
return bool(self._linear_dict)
|
|
1024
1012
|
|
|
1025
|
-
def __iadd__(self, other:
|
|
1013
|
+
def __iadd__(self, other: ProjectorString | ProjectorSum):
|
|
1026
1014
|
if isinstance(other, ProjectorString):
|
|
1027
1015
|
other = ProjectorSum.from_projector_strings(other)
|
|
1028
1016
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -1030,7 +1018,7 @@ class ProjectorSum:
|
|
|
1030
1018
|
self._linear_dict += other._linear_dict
|
|
1031
1019
|
return self
|
|
1032
1020
|
|
|
1033
|
-
def __add__(self, other:
|
|
1021
|
+
def __add__(self, other: ProjectorString | ProjectorSum):
|
|
1034
1022
|
if isinstance(other, ProjectorString):
|
|
1035
1023
|
other = ProjectorSum.from_projector_strings(other)
|
|
1036
1024
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -1039,7 +1027,7 @@ class ProjectorSum:
|
|
|
1039
1027
|
result += other
|
|
1040
1028
|
return result
|
|
1041
1029
|
|
|
1042
|
-
def __isub__(self, other:
|
|
1030
|
+
def __isub__(self, other: ProjectorString | ProjectorSum):
|
|
1043
1031
|
if isinstance(other, ProjectorString):
|
|
1044
1032
|
other = ProjectorSum.from_projector_strings(other)
|
|
1045
1033
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -1047,7 +1035,7 @@ class ProjectorSum:
|
|
|
1047
1035
|
self._linear_dict -= other._linear_dict
|
|
1048
1036
|
return self
|
|
1049
1037
|
|
|
1050
|
-
def __sub__(self, other:
|
|
1038
|
+
def __sub__(self, other: ProjectorString | ProjectorSum):
|
|
1051
1039
|
if isinstance(other, ProjectorString):
|
|
1052
1040
|
other = ProjectorSum.from_projector_strings(other)
|
|
1053
1041
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import collections
|
|
16
|
-
from typing import Union
|
|
17
18
|
|
|
18
19
|
import numpy as np
|
|
19
20
|
import pytest
|
|
@@ -228,12 +229,12 @@ def test_parameterized_linear_combination_of_gates(
|
|
|
228
229
|
|
|
229
230
|
|
|
230
231
|
def get_matrix(
|
|
231
|
-
operator:
|
|
232
|
-
cirq.Gate
|
|
233
|
-
cirq.GateOperation
|
|
234
|
-
cirq.LinearCombinationOfGates
|
|
235
|
-
cirq.LinearCombinationOfOperations
|
|
236
|
-
|
|
232
|
+
operator: (
|
|
233
|
+
cirq.Gate
|
|
234
|
+
| cirq.GateOperation
|
|
235
|
+
| cirq.LinearCombinationOfGates
|
|
236
|
+
| cirq.LinearCombinationOfOperations
|
|
237
|
+
),
|
|
237
238
|
) -> np.ndarray:
|
|
238
239
|
if isinstance(operator, (cirq.LinearCombinationOfGates, cirq.LinearCombinationOfOperations)):
|
|
239
240
|
return operator.matrix()
|
|
@@ -241,8 +242,8 @@ def get_matrix(
|
|
|
241
242
|
|
|
242
243
|
|
|
243
244
|
def assert_linear_combinations_are_equal(
|
|
244
|
-
actual:
|
|
245
|
-
expected:
|
|
245
|
+
actual: cirq.LinearCombinationOfGates | cirq.LinearCombinationOfOperations,
|
|
246
|
+
expected: cirq.LinearCombinationOfGates | cirq.LinearCombinationOfOperations,
|
|
246
247
|
) -> None:
|
|
247
248
|
if not actual and not expected:
|
|
248
249
|
assert len(actual) == 0
|
|
@@ -970,6 +971,10 @@ def test_paulisum_validation():
|
|
|
970
971
|
ps += cirq.I(cirq.LineQubit(0))
|
|
971
972
|
assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)}))
|
|
972
973
|
|
|
974
|
+
ps = cirq.PauliSum()
|
|
975
|
+
ps -= cirq.I(cirq.LineQubit(0))
|
|
976
|
+
assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(-1)}))
|
|
977
|
+
|
|
973
978
|
|
|
974
979
|
def test_add_number_paulisum():
|
|
975
980
|
q = cirq.LineQubit.range(2)
|
cirq/ops/matrix_gates.py
CHANGED
|
@@ -14,13 +14,15 @@
|
|
|
14
14
|
|
|
15
15
|
"""Quantum gates defined by a matrix."""
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import Any, Iterable, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
20
22
|
|
|
21
23
|
from cirq import _import, linalg, protocols
|
|
22
24
|
from cirq._compat import proper_repr
|
|
23
|
-
from cirq.ops import global_phase_op,
|
|
25
|
+
from cirq.ops import global_phase_op, phased_x_z_gate, raw_types
|
|
24
26
|
|
|
25
27
|
if TYPE_CHECKING:
|
|
26
28
|
import cirq
|
|
@@ -53,8 +55,8 @@ class MatrixGate(raw_types.Gate):
|
|
|
53
55
|
self,
|
|
54
56
|
matrix: np.ndarray,
|
|
55
57
|
*,
|
|
56
|
-
name:
|
|
57
|
-
qid_shape:
|
|
58
|
+
name: str | None = None,
|
|
59
|
+
qid_shape: Iterable[int] | None = None,
|
|
58
60
|
unitary_check: bool = True,
|
|
59
61
|
unitary_check_rtol: float = 1e-5,
|
|
60
62
|
unitary_check_atol: float = 1e-8,
|
|
@@ -109,11 +111,11 @@ class MatrixGate(raw_types.Gate):
|
|
|
109
111
|
):
|
|
110
112
|
raise ValueError(f'Not a unitary matrix: {matrix}')
|
|
111
113
|
|
|
112
|
-
def with_name(self, name: str) ->
|
|
114
|
+
def with_name(self, name: str) -> MatrixGate:
|
|
113
115
|
"""Creates a new MatrixGate with the same matrix and a new name."""
|
|
114
116
|
return MatrixGate(self._matrix, name=name, qid_shape=self._qid_shape, unitary_check=False)
|
|
115
117
|
|
|
116
|
-
def _json_dict_(self) ->
|
|
118
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
117
119
|
return {
|
|
118
120
|
'matrix': self._matrix.tolist(),
|
|
119
121
|
'qid_shape': self._qid_shape,
|
|
@@ -124,16 +126,16 @@ class MatrixGate(raw_types.Gate):
|
|
|
124
126
|
def _from_json_dict_(cls, matrix, qid_shape, name=None, **kwargs):
|
|
125
127
|
return cls(matrix=np.array(matrix), qid_shape=qid_shape, name=name)
|
|
126
128
|
|
|
127
|
-
def _qid_shape_(self) ->
|
|
129
|
+
def _qid_shape_(self) -> tuple[int, ...]:
|
|
128
130
|
return self._qid_shape
|
|
129
131
|
|
|
130
|
-
def __pow__(self, exponent: Any) ->
|
|
132
|
+
def __pow__(self, exponent: Any) -> MatrixGate:
|
|
131
133
|
if not isinstance(exponent, (int, float)):
|
|
132
134
|
return NotImplemented
|
|
133
135
|
new_mat = linalg.map_eigenvalues(self._matrix, lambda b: b**exponent)
|
|
134
136
|
return MatrixGate(new_mat, qid_shape=self._qid_shape)
|
|
135
137
|
|
|
136
|
-
def _phase_by_(self, phase_turns: float, qubit_index: int) ->
|
|
138
|
+
def _phase_by_(self, phase_turns: float, qubit_index: int) -> MatrixGate:
|
|
137
139
|
if not isinstance(phase_turns, (int, float)):
|
|
138
140
|
return NotImplemented
|
|
139
141
|
if self._qid_shape[qubit_index] != 2:
|
|
@@ -147,10 +149,10 @@ class MatrixGate(raw_types.Gate):
|
|
|
147
149
|
result[linalg.slice_for_qubits_equal_to([j], 1)] *= np.conj(p)
|
|
148
150
|
return MatrixGate(matrix=result.reshape(self._matrix.shape), qid_shape=self._qid_shape)
|
|
149
151
|
|
|
150
|
-
def _decompose_(self, qubits:
|
|
152
|
+
def _decompose_(self, qubits: tuple[cirq.Qid, ...]) -> cirq.OP_TREE:
|
|
151
153
|
from cirq.circuits import Circuit
|
|
152
154
|
|
|
153
|
-
decomposed:
|
|
155
|
+
decomposed: list[cirq.Operation] = NotImplemented
|
|
154
156
|
if self._qid_shape == (2,):
|
|
155
157
|
decomposed = [
|
|
156
158
|
g.on(qubits[0])
|
|
@@ -168,8 +170,8 @@ class MatrixGate(raw_types.Gate):
|
|
|
168
170
|
return NotImplemented
|
|
169
171
|
# The above algorithms ignore phase, but phase is important to maintain if the gate is
|
|
170
172
|
# controlled. Here, we add it back in with a global phase op.
|
|
171
|
-
|
|
172
|
-
u =
|
|
173
|
+
circuit = Circuit(*decomposed)
|
|
174
|
+
u = circuit.unitary(qubit_order=qubits, qubits_that_should_be_present=qubits)
|
|
173
175
|
phase_delta = linalg.phase_delta(u, self._matrix)
|
|
174
176
|
# Phase delta is on the complex unit circle, so if real(phase_delta) >= 1, that means
|
|
175
177
|
# no phase delta. (>1 is rounding error).
|
|
@@ -183,10 +185,11 @@ class MatrixGate(raw_types.Gate):
|
|
|
183
185
|
def _unitary_(self) -> np.ndarray:
|
|
184
186
|
return np.copy(self._matrix)
|
|
185
187
|
|
|
186
|
-
def _circuit_diagram_info_(
|
|
187
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
188
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
188
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
189
189
|
n_qubits = len(self._qid_shape)
|
|
190
|
+
# No diagram for zero-qubit gates; let fallback handle it
|
|
191
|
+
if n_qubits == 0:
|
|
192
|
+
return NotImplemented
|
|
190
193
|
if self._name is not None:
|
|
191
194
|
symbols = (
|
|
192
195
|
[self._name] if n_qubits == 1 else [f'{self._name}[{i+1}]' for i in range(n_qubits)]
|
|
@@ -196,7 +199,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
196
199
|
rest = [f'#{i+1}' for i in range(1, n_qubits)]
|
|
197
200
|
return protocols.CircuitDiagramInfo(wire_symbols=[main, *rest])
|
|
198
201
|
|
|
199
|
-
def _qasm_(self, args:
|
|
202
|
+
def _qasm_(self, args: cirq.QasmArgs, qubits: tuple[cirq.Qid, ...]) -> str | None:
|
|
200
203
|
args.validate_version('2.0', '3.0')
|
|
201
204
|
if self._qid_shape == (2,):
|
|
202
205
|
return protocols.qasm(
|
|
@@ -230,7 +233,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
230
233
|
return str(self._matrix.round(3))
|
|
231
234
|
|
|
232
235
|
|
|
233
|
-
def _matrix_to_diagram_symbol(matrix: np.ndarray, args:
|
|
236
|
+
def _matrix_to_diagram_symbol(matrix: np.ndarray, args: protocols.CircuitDiagramInfoArgs) -> str:
|
|
234
237
|
if args.precision is not None:
|
|
235
238
|
matrix = matrix.round(args.precision)
|
|
236
239
|
result = str(matrix)
|
cirq/ops/matrix_gates_test.py
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
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 re
|
|
15
18
|
|
|
16
19
|
import numpy as np
|
|
@@ -410,3 +413,16 @@ def test_matrixgate_name_serialization():
|
|
|
410
413
|
gate_after_serialization3 = cirq.read_json(json_text=cirq.to_json(gate3))
|
|
411
414
|
assert gate3._name == ''
|
|
412
415
|
assert gate_after_serialization3._name == ''
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def test_decompose_when_qubits_not_in_ascending_order():
|
|
419
|
+
# Previous code for preserving global phase would misorder qubits
|
|
420
|
+
q0, q1 = cirq.LineQubit.range(2)
|
|
421
|
+
circuit1 = cirq.Circuit()
|
|
422
|
+
matrix = cirq.testing.random_unitary(4, random_state=0)
|
|
423
|
+
circuit1.append(cirq.MatrixGate(matrix).on(q1, q0))
|
|
424
|
+
u1 = cirq.unitary(circuit1)
|
|
425
|
+
decomposed = cirq.decompose(circuit1)
|
|
426
|
+
circuit2 = cirq.Circuit(decomposed)
|
|
427
|
+
u2 = cirq.unitary(circuit2)
|
|
428
|
+
np.testing.assert_allclose(u1, u2, atol=1e-14)
|