cirq-core 1.7.0.dev20250924231107__py3-none-any.whl → 1.7.0.dev20251203004401__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.
- cirq/__init__.py +1 -0
- cirq/_compat.py +3 -2
- cirq/_compat_test.py +16 -15
- cirq/_doc.py +4 -3
- cirq/_import.py +2 -1
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/_bucket_priority_queue.py +2 -1
- cirq/circuits/circuit.py +7 -13
- cirq/circuits/circuit_operation.py +2 -1
- cirq/circuits/circuit_test.py +13 -12
- cirq/circuits/frozen_circuit.py +3 -2
- cirq/circuits/moment.py +3 -15
- cirq/circuits/optimization_pass.py +2 -1
- cirq/circuits/qasm_output.py +39 -10
- cirq/circuits/qasm_output_test.py +51 -2
- cirq/circuits/text_diagram_drawer.py +2 -1
- cirq/contrib/acquaintance/bipartite.py +2 -1
- cirq/contrib/acquaintance/devices.py +1 -1
- cirq/contrib/acquaintance/executor.py +4 -5
- cirq/contrib/acquaintance/executor_test.py +2 -1
- cirq/contrib/acquaintance/gates.py +2 -1
- cirq/contrib/acquaintance/gates_test.py +1 -1
- cirq/contrib/acquaintance/inspection_utils.py +2 -1
- cirq/contrib/acquaintance/mutation_utils.py +2 -1
- cirq/contrib/acquaintance/optimizers.py +2 -1
- cirq/contrib/acquaintance/permutation.py +2 -1
- cirq/contrib/acquaintance/permutation_test.py +1 -1
- cirq/contrib/acquaintance/shift.py +2 -1
- cirq/contrib/acquaintance/shift_swap_network.py +2 -1
- cirq/contrib/acquaintance/strategies/complete.py +3 -2
- cirq/contrib/acquaintance/strategies/cubic.py +2 -1
- cirq/contrib/acquaintance/strategies/quartic_paired.py +2 -1
- cirq/contrib/acquaintance/strategies/quartic_paired_test.py +1 -1
- cirq/contrib/acquaintance/testing.py +2 -1
- cirq/contrib/acquaintance/topological_sort.py +2 -1
- cirq/contrib/bayesian_network/bayesian_network_gate.py +3 -2
- cirq/contrib/circuitdag/circuit_dag.py +4 -2
- cirq/contrib/custom_simulators/custom_state_simulator.py +2 -1
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +1 -1
- cirq/contrib/graph_device/graph_device.py +2 -1
- cirq/contrib/graph_device/graph_device_test.py +2 -1
- cirq/contrib/graph_device/hypergraph.py +2 -1
- cirq/contrib/graph_device/uniform_graph_device.py +2 -1
- cirq/contrib/json.py +14 -2
- cirq/contrib/json_test_data/BayesianNetworkGate.json +10 -0
- cirq/contrib/json_test_data/BayesianNetworkGate.repr +3 -0
- cirq/contrib/json_test_data/QuantumVolumeResult.json +169 -0
- cirq/contrib/json_test_data/QuantumVolumeResult.repr +22 -0
- cirq/contrib/json_test_data/SwapPermutationGate.json +3 -0
- cirq/contrib/json_test_data/SwapPermutationGate.repr +1 -0
- cirq/contrib/json_test_data/spec.py +0 -2
- cirq/contrib/noise_models/noise_models.py +2 -1
- cirq/contrib/paulistring/clifford_optimize.py +20 -2
- cirq/contrib/paulistring/optimize.py +1 -1
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +146 -35
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +74 -171
- cirq/contrib/paulistring/recombine.py +5 -2
- cirq/contrib/paulistring/separate.py +1 -1
- cirq/contrib/qasm_import/_parser.py +2 -1
- cirq/contrib/qasm_import/_parser_test.py +3 -3
- cirq/contrib/quantikz/__init__.py +21 -0
- cirq/contrib/quantikz/circuit_to_latex_quantikz.py +680 -0
- cirq/contrib/quantikz/circuit_to_latex_quantikz_test.py +253 -0
- cirq/contrib/quantikz/circuit_to_latex_render.py +424 -0
- cirq/contrib/quantikz/circuit_to_latex_render_test.py +44 -0
- cirq/contrib/quantum_volume/quantum_volume.py +2 -1
- cirq/contrib/quimb/density_matrix.py +1 -1
- cirq/contrib/quimb/grid_circuits.py +2 -1
- cirq/contrib/quimb/grid_circuits_test.py +1 -1
- cirq/contrib/quimb/mps_simulator.py +4 -3
- cirq/contrib/quimb/state_vector.py +2 -1
- cirq/contrib/quirk/export_to_quirk.py +2 -1
- cirq/contrib/quirk/linearize_circuit.py +1 -1
- cirq/contrib/quirk/quirk_gate.py +2 -1
- cirq/contrib/routing/device.py +1 -1
- cirq/contrib/routing/greedy.py +2 -1
- cirq/contrib/routing/initialization.py +2 -1
- cirq/contrib/routing/router.py +2 -1
- cirq/contrib/routing/swap_network.py +2 -1
- cirq/contrib/routing/utils.py +2 -1
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +7 -5
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking_test.py +6 -6
- cirq/devices/device.py +2 -1
- cirq/devices/grid_device_metadata.py +2 -1
- cirq/devices/grid_qubit.py +7 -6
- cirq/devices/insertion_noise_model.py +2 -1
- cirq/devices/line_qubit.py +2 -1
- cirq/devices/named_topologies.py +2 -1
- cirq/devices/noise_model.py +2 -1
- cirq/devices/noise_model_test.py +1 -1
- cirq/devices/noise_properties.py +2 -1
- cirq/devices/superconducting_qubits_noise_properties_test.py +2 -1
- cirq/devices/thermal_noise_model.py +2 -1
- cirq/experiments/__init__.py +2 -0
- cirq/experiments/benchmarking/parallel_xeb.py +2 -1
- cirq/experiments/benchmarking/parallel_xeb_test.py +1 -1
- cirq/experiments/fidelity_estimation.py +2 -1
- cirq/experiments/fidelity_estimation_test.py +1 -1
- cirq/experiments/ghz_2d.py +150 -0
- cirq/experiments/ghz_2d_test.py +155 -0
- cirq/experiments/n_qubit_tomography.py +2 -1
- cirq/experiments/n_qubit_tomography_test.py +1 -1
- cirq/experiments/purity_estimation.py +1 -1
- cirq/experiments/qubit_characterizations.py +2 -1
- cirq/experiments/random_quantum_circuit_generation.py +2 -1
- cirq/experiments/random_quantum_circuit_generation_test.py +2 -1
- cirq/experiments/readout_confusion_matrix.py +2 -1
- cirq/experiments/readout_confusion_matrix_test.py +1 -1
- cirq/experiments/single_qubit_readout_calibration.py +2 -1
- cirq/experiments/single_qubit_readout_calibration_test.py +1 -1
- cirq/experiments/t1_decay_experiment.py +2 -1
- cirq/experiments/two_qubit_xeb.py +2 -1
- cirq/experiments/two_qubit_xeb_test.py +1 -1
- cirq/experiments/xeb_fitting.py +2 -1
- cirq/experiments/xeb_fitting_test.py +1 -1
- cirq/experiments/xeb_sampling.py +5 -3
- cirq/experiments/xeb_sampling_test.py +1 -1
- cirq/experiments/xeb_simulation.py +2 -1
- cirq/experiments/xeb_simulation_test.py +2 -1
- cirq/experiments/z_phase_calibration.py +2 -1
- cirq/experiments/z_phase_calibration_test.py +18 -3
- cirq/interop/quirk/cells/__init__.py +1 -2
- cirq/interop/quirk/cells/all_cells.py +2 -1
- cirq/interop/quirk/cells/arithmetic_cells.py +2 -1
- cirq/interop/quirk/cells/cell.py +2 -1
- cirq/interop/quirk/cells/composite_cell.py +2 -1
- cirq/interop/quirk/cells/composite_cell_test.py +1 -1
- cirq/interop/quirk/cells/control_cells.py +2 -1
- cirq/interop/quirk/cells/frequency_space_cells.py +1 -1
- cirq/interop/quirk/cells/ignored_cells.py +1 -1
- cirq/interop/quirk/cells/input_cells.py +2 -1
- cirq/interop/quirk/cells/input_rotation_cells.py +2 -1
- cirq/interop/quirk/cells/measurement_cells.py +2 -1
- cirq/interop/quirk/cells/parse.py +2 -11
- cirq/interop/quirk/cells/qubit_permutation_cells.py +2 -1
- cirq/interop/quirk/cells/scalar_cells.py +2 -1
- cirq/interop/quirk/cells/single_qubit_rotation_cells.py +2 -1
- cirq/interop/quirk/cells/swap_cell.py +2 -1
- cirq/interop/quirk/cells/unsupported_cells.py +1 -1
- cirq/interop/quirk/url_to_circuit.py +2 -1
- cirq/json_resolver_cache.py +0 -2
- cirq/linalg/decompositions.py +6 -2
- cirq/linalg/decompositions_test.py +1 -0
- cirq/linalg/diagonalize.py +1 -1
- cirq/linalg/predicates.py +2 -1
- cirq/linalg/tolerance.py +2 -1
- cirq/linalg/transformations.py +2 -1
- cirq/ops/arithmetic_operation.py +2 -1
- cirq/ops/arithmetic_operation_test.py +1 -1
- cirq/ops/boolean_hamiltonian.py +4 -3
- cirq/ops/classically_controlled_operation.py +3 -2
- cirq/ops/clifford_gate.py +2 -1
- cirq/ops/clifford_gate_test.py +1 -2
- cirq/ops/common_channels.py +2 -1
- cirq/ops/common_gates.py +2 -1
- cirq/ops/control_values.py +2 -1
- cirq/ops/controlled_gate.py +3 -2
- cirq/ops/controlled_gate_test.py +2 -1
- cirq/ops/controlled_operation.py +3 -2
- cirq/ops/controlled_operation_test.py +2 -1
- cirq/ops/dense_pauli_string.py +3 -13
- cirq/ops/diagonal_gate.py +3 -2
- cirq/ops/eigen_gate.py +9 -7
- cirq/ops/fourier_transform.py +3 -2
- cirq/ops/fourier_transform_test.py +2 -4
- cirq/ops/fsim_gate.py +3 -2
- cirq/ops/gate_operation.py +8 -12
- cirq/ops/gateset.py +22 -2
- cirq/ops/global_phase_op.py +3 -2
- cirq/ops/greedy_qubit_manager.py +2 -1
- cirq/ops/identity.py +2 -1
- cirq/ops/kraus_channel.py +2 -1
- cirq/ops/linear_combinations.py +8 -3
- cirq/ops/linear_combinations_test.py +23 -1
- cirq/ops/matrix_gates.py +2 -1
- cirq/ops/measure_util.py +2 -1
- cirq/ops/measurement_gate.py +2 -1
- cirq/ops/mixed_unitary_channel.py +2 -1
- cirq/ops/named_qubit.py +2 -2
- cirq/ops/op_tree.py +2 -1
- cirq/ops/parallel_gate.py +3 -2
- cirq/ops/parity_gates.py +2 -1
- cirq/ops/pauli_interaction_gate.py +2 -1
- cirq/ops/pauli_measurement_gate.py +2 -1
- cirq/ops/pauli_string.py +6 -12
- cirq/ops/pauli_string_phasor.py +3 -2
- cirq/ops/pauli_string_raw_types.py +2 -1
- cirq/ops/pauli_string_test.py +2 -2
- cirq/ops/pauli_sum_exponential.py +2 -1
- cirq/ops/permutation_gate.py +2 -1
- cirq/ops/phased_iswap_gate.py +3 -2
- cirq/ops/phased_x_gate.py +5 -4
- cirq/ops/phased_x_z_gate.py +12 -5
- cirq/ops/projector.py +2 -1
- cirq/ops/qubit_manager.py +2 -1
- cirq/ops/qubit_order.py +2 -1
- cirq/ops/qubit_order_or_list.py +1 -1
- cirq/ops/random_gate_channel.py +3 -2
- cirq/ops/raw_types.py +7 -15
- cirq/ops/raw_types_test.py +4 -3
- cirq/ops/state_preparation_channel.py +2 -1
- cirq/ops/three_qubit_gates.py +3 -2
- cirq/ops/two_qubit_diagonal_gate.py +3 -2
- cirq/ops/uniform_superposition_gate.py +2 -1
- cirq/ops/wait_gate.py +10 -4
- cirq/protocols/act_on_protocol.py +2 -1
- cirq/protocols/act_on_protocol_test.py +2 -1
- cirq/protocols/apply_channel_protocol.py +2 -1
- cirq/protocols/apply_mixture_protocol.py +2 -1
- cirq/protocols/apply_mixture_protocol_test.py +2 -1
- cirq/protocols/apply_unitary_protocol.py +2 -1
- cirq/protocols/apply_unitary_protocol_test.py +2 -0
- cirq/protocols/approximate_equality_protocol.py +2 -1
- cirq/protocols/circuit_diagram_info_protocol.py +2 -1
- cirq/protocols/decompose_protocol.py +2 -12
- cirq/protocols/has_stabilizer_effect_protocol.py +1 -1
- cirq/protocols/hash_from_pickle_test.py +2 -2
- cirq/protocols/inverse_protocol.py +2 -1
- cirq/protocols/json_serialization.py +2 -1
- cirq/protocols/kraus_protocol.py +4 -3
- cirq/protocols/kraus_protocol_test.py +2 -2
- cirq/protocols/measurement_key_protocol.py +2 -1
- cirq/protocols/mixture_protocol.py +2 -1
- cirq/protocols/pow_protocol.py +2 -1
- cirq/protocols/qasm.py +2 -1
- cirq/protocols/qid_shape_protocol.py +2 -1
- cirq/protocols/resolve_parameters.py +16 -14
- cirq/protocols/trace_distance_bound.py +2 -1
- cirq/protocols/unitary_protocol.py +21 -21
- cirq/qis/channels.py +1 -1
- cirq/qis/channels_test.py +1 -1
- cirq/qis/clifford_tableau.py +2 -1
- cirq/qis/entropy.py +2 -2
- cirq/qis/quantum_state_representation.py +2 -1
- cirq/qis/states.py +7 -2
- cirq/sim/classical_simulator.py +2 -1
- cirq/sim/clifford/clifford_simulator.py +2 -1
- cirq/sim/clifford/clifford_simulator_test.py +1 -1
- cirq/sim/clifford/clifford_tableau_simulation_state.py +2 -1
- cirq/sim/clifford/stabilizer_ch_form_simulation_state.py +2 -1
- cirq/sim/clifford/stabilizer_sampler.py +1 -1
- cirq/sim/clifford/stabilizer_simulation_state.py +2 -1
- cirq/sim/clifford/stabilizer_state_ch_form.py +3 -2
- cirq/sim/clifford/stabilizer_state_ch_form_test.py +0 -1
- cirq/sim/density_matrix_simulation_state.py +2 -1
- cirq/sim/density_matrix_simulator.py +2 -1
- cirq/sim/density_matrix_utils.py +2 -1
- cirq/sim/mux.py +2 -1
- cirq/sim/mux_test.py +0 -1
- cirq/sim/simulation_product_state.py +2 -1
- cirq/sim/simulation_product_state_test.py +2 -1
- cirq/sim/simulation_state.py +2 -1
- cirq/sim/simulation_state_base.py +2 -1
- cirq/sim/simulation_state_test.py +2 -1
- cirq/sim/simulation_utils.py +2 -1
- cirq/sim/simulator.py +2 -1
- cirq/sim/simulator_base.py +2 -1
- cirq/sim/simulator_base_test.py +2 -1
- cirq/sim/simulator_test.py +2 -1
- cirq/sim/sparse_simulator.py +2 -1
- cirq/sim/state_vector.py +2 -1
- cirq/sim/state_vector_simulation_state.py +2 -1
- cirq/sim/state_vector_simulator.py +2 -1
- cirq/sim/state_vector_test.py +1 -2
- cirq/study/__init__.py +1 -0
- cirq/study/flatten_expressions.py +2 -1
- cirq/study/resolver.py +31 -18
- cirq/study/resolver_test.py +1 -1
- cirq/study/result.py +2 -1
- cirq/study/sweepable.py +2 -1
- cirq/study/sweeps.py +26 -1
- cirq/study/sweeps_test.py +24 -0
- cirq/testing/_compat_test_data/__init__.py +3 -3
- cirq/testing/circuit_compare.py +2 -1
- cirq/testing/consistent_act_on_test.py +1 -1
- cirq/testing/consistent_controlled_gate_op.py +1 -1
- cirq/testing/consistent_controlled_gate_op_test.py +2 -1
- cirq/testing/consistent_protocols.py +2 -1
- cirq/testing/consistent_protocols_test.py +3 -3
- cirq/testing/consistent_qasm.py +2 -1
- cirq/testing/consistent_resolve_parameters.py +1 -1
- cirq/testing/consistent_unitary.py +1 -1
- cirq/testing/consistent_unitary_test.py +1 -1
- cirq/testing/deprecation.py +1 -1
- cirq/testing/devices.py +3 -2
- cirq/testing/equals_tester.py +4 -3
- cirq/testing/equivalent_basis_map.py +4 -2
- cirq/testing/json.py +3 -2
- cirq/testing/logs.py +1 -1
- cirq/testing/op_tree.py +1 -1
- cirq/testing/order_tester.py +2 -2
- cirq/testing/pytest_utils.py +2 -1
- cirq/testing/random_circuit.py +2 -1
- cirq/testing/random_circuit_test.py +2 -1
- cirq/testing/repr_pretty_tester.py +3 -3
- cirq/transformers/__init__.py +1 -0
- cirq/transformers/_connected_component.py +231 -0
- cirq/transformers/_connected_component_test.py +200 -0
- cirq/transformers/align_test.py +13 -13
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +8 -7
- cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +5 -5
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +11 -10
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +6 -6
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +3 -2
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +11 -10
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +8 -7
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +17 -20
- cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +33 -27
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +1 -1
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +1 -1
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +12 -11
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +5 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +3 -3
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +2 -2
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +2 -1
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +32 -30
- cirq/transformers/drop_negligible_operations_test.py +7 -7
- cirq/transformers/dynamical_decoupling.py +185 -112
- cirq/transformers/dynamical_decoupling_test.py +195 -201
- cirq/transformers/eject_phased_paulis.py +2 -1
- cirq/transformers/eject_phased_paulis_test.py +3 -2
- cirq/transformers/eject_z.py +4 -3
- cirq/transformers/eject_z_test.py +23 -25
- cirq/transformers/expand_composite.py +3 -2
- cirq/transformers/expand_composite_test.py +14 -14
- cirq/transformers/gauge_compiling/__init__.py +8 -0
- cirq/transformers/gauge_compiling/gauge_compiling.py +3 -2
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +14 -12
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +3 -3
- cirq/transformers/gauge_compiling/idle_moments_gauge.py +5 -2
- cirq/transformers/gauge_compiling/multi_moment_cphase_gauge.py +242 -0
- cirq/transformers/gauge_compiling/multi_moment_cphase_gauge_test.py +243 -0
- cirq/transformers/gauge_compiling/multi_moment_gauge_compiling.py +151 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +2 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py +1 -1
- cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +6 -6
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +2 -1
- cirq/transformers/measurement_transformers.py +2 -1
- cirq/transformers/measurement_transformers_test.py +45 -39
- cirq/transformers/merge_k_qubit_gates.py +2 -1
- cirq/transformers/merge_k_qubit_gates_test.py +1 -1
- cirq/transformers/merge_single_qubit_gates.py +2 -1
- cirq/transformers/merge_single_qubit_gates_test.py +22 -22
- cirq/transformers/noise_adding_test.py +2 -2
- cirq/transformers/optimize_for_target_gateset.py +2 -1
- cirq/transformers/optimize_for_target_gateset_test.py +11 -9
- cirq/transformers/qubit_management_transformers_test.py +6 -2
- cirq/transformers/routing/mapping_manager.py +2 -1
- cirq/transformers/routing/route_circuit_cqc.py +2 -1
- cirq/transformers/stratify.py +2 -1
- cirq/transformers/symbolize.py +2 -1
- cirq/transformers/tag_transformers.py +2 -1
- cirq/transformers/target_gatesets/compilation_target_gateset.py +2 -1
- cirq/transformers/target_gatesets/cz_gateset.py +2 -1
- cirq/transformers/target_gatesets/cz_gateset_test.py +1 -1
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +2 -1
- cirq/transformers/transformer_api.py +2 -1
- cirq/transformers/transformer_primitives.py +271 -145
- cirq/transformers/transformer_primitives_test.py +185 -1
- cirq/value/abc_alt.py +2 -1
- cirq/value/classical_data.py +2 -1
- cirq/value/condition.py +2 -1
- cirq/value/digits.py +9 -2
- cirq/value/duration.py +6 -5
- cirq/value/linear_dict.py +4 -9
- cirq/value/measurement_key.py +2 -1
- cirq/value/periodic_value.py +3 -2
- cirq/value/product_state.py +2 -1
- cirq/value/value_equality_attr.py +2 -1
- cirq/vis/density_matrix.py +1 -1
- cirq/vis/heatmap.py +2 -1
- cirq/vis/histogram.py +2 -1
- cirq/vis/state_histogram.py +2 -1
- cirq/work/collector.py +2 -1
- cirq/work/observable_grouping.py +2 -1
- cirq/work/observable_measurement.py +2 -1
- cirq/work/observable_measurement_data.py +2 -1
- cirq/work/observable_measurement_test.py +1 -1
- cirq/work/observable_readout_calibration.py +2 -1
- cirq/work/observable_readout_calibration_test.py +1 -1
- cirq/work/observable_settings.py +2 -1
- cirq/work/sampler.py +2 -1
- cirq/work/sampler_test.py +1 -1
- {cirq_core-1.7.0.dev20250924231107.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/METADATA +4 -4
- {cirq_core-1.7.0.dev20250924231107.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/RECORD +391 -374
- cirq/contrib/json_test.py +0 -33
- {cirq_core-1.7.0.dev20250924231107.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/WHEEL +0 -0
- {cirq_core-1.7.0.dev20250924231107.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.7.0.dev20250924231107.dist-info → cirq_core-1.7.0.dev20251203004401.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Copyright 2025 The Cirq Developers
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import pytest
|
|
18
|
+
|
|
19
|
+
import cirq
|
|
20
|
+
from cirq.transformers._connected_component import (
|
|
21
|
+
ComponentSet,
|
|
22
|
+
ComponentWithCircuitOpSet,
|
|
23
|
+
ComponentWithOpsSet,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _always_mergeable(_: cirq.Operation) -> bool:
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _never_mergeable(_: cirq.Operation) -> bool:
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _always_can_merge(_ops1: list[cirq.Operation], _ops2: list[cirq.Operation]) -> bool:
|
|
36
|
+
return True
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _never_can_merge(_ops1: list[cirq.Operation], _ops2: list[cirq.Operation]) -> bool:
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _merge_as_first_operation(op1: cirq.Operation, _op2: cirq.Operation) -> cirq.Operation:
|
|
44
|
+
return op1
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _merge_never_successful(op1: cirq.Operation, _op2: cirq.Operation) -> None:
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_find_returns_itself_for_singleton():
|
|
52
|
+
cset = ComponentSet(_always_mergeable)
|
|
53
|
+
|
|
54
|
+
q = cirq.NamedQubit('x')
|
|
55
|
+
c = cset.new_component(op=cirq.X(q), moment_id=0)
|
|
56
|
+
assert cset.find(c) is c
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_merge_components():
|
|
60
|
+
cset = ComponentSet(_always_mergeable)
|
|
61
|
+
|
|
62
|
+
q = cirq.NamedQubit('x')
|
|
63
|
+
c = [cset.new_component(op=cirq.X(q), moment_id=i) for i in range(5)]
|
|
64
|
+
cset.merge(c[1], c[0])
|
|
65
|
+
cset.merge(c[2], c[1])
|
|
66
|
+
cset.merge(c[4], c[3])
|
|
67
|
+
cset.merge(c[3], c[0])
|
|
68
|
+
|
|
69
|
+
for i in range(5):
|
|
70
|
+
assert cset.find(c[i]) is cset.find(c[0])
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_merge_same_component():
|
|
74
|
+
cset = ComponentSet(_always_mergeable)
|
|
75
|
+
|
|
76
|
+
q = cirq.NamedQubit('x')
|
|
77
|
+
c = [cset.new_component(op=cirq.X(q), moment_id=i) for i in range(3)]
|
|
78
|
+
cset.merge(c[1], c[0])
|
|
79
|
+
cset.merge(c[2], c[1])
|
|
80
|
+
|
|
81
|
+
root = cset.find(c[0])
|
|
82
|
+
|
|
83
|
+
assert cset.merge(c[0], c[2]) is root
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_merge_returns_None_if_one_component_is_not_mergeable():
|
|
87
|
+
cset = ComponentSet(_always_mergeable)
|
|
88
|
+
|
|
89
|
+
q = cirq.NamedQubit('x')
|
|
90
|
+
c0 = cset.new_component(op=cirq.X(q), moment_id=0, is_mergeable=True)
|
|
91
|
+
c1 = cset.new_component(op=cirq.X(q), moment_id=1, is_mergeable=False)
|
|
92
|
+
assert cset.merge(c0, c1) is None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_cset_merge_returns_None_if_is_mergeable_is_false():
|
|
96
|
+
q = cirq.NamedQubit('x')
|
|
97
|
+
cset = ComponentSet(is_mergeable=_never_mergeable)
|
|
98
|
+
|
|
99
|
+
c0 = cset.new_component(op=cirq.X(q), moment_id=0, is_mergeable=True)
|
|
100
|
+
c1 = cset.new_component(op=cirq.X(q), moment_id=1, is_mergeable=True)
|
|
101
|
+
assert cset.merge(c0, c1) is None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@pytest.mark.parametrize("merge_left,expected_moment_id", [(True, 0), (False, 1)])
|
|
105
|
+
def test_merge_qubits_with_merge_left(merge_left: bool, expected_moment_id: int) -> None:
|
|
106
|
+
cset = ComponentSet(_always_mergeable)
|
|
107
|
+
|
|
108
|
+
q0 = cirq.NamedQubit('x')
|
|
109
|
+
q1 = cirq.NamedQubit('y')
|
|
110
|
+
c0 = cset.new_component(op=cirq.X(q0), moment_id=0)
|
|
111
|
+
c1 = cset.new_component(op=cirq.X(q1), moment_id=1)
|
|
112
|
+
c2 = cset.new_component(op=cirq.X(q1), moment_id=2)
|
|
113
|
+
cset.merge(c1, c2)
|
|
114
|
+
cset.merge(c0, c1, merge_left=merge_left)
|
|
115
|
+
assert cset.find(c1).qubits == frozenset([q0, q1])
|
|
116
|
+
assert cset.find(c1).moment_id == expected_moment_id
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_component_with_ops_merge():
|
|
120
|
+
cset = ComponentWithOpsSet(_always_mergeable, _always_can_merge)
|
|
121
|
+
|
|
122
|
+
q = cirq.LineQubit.range(3)
|
|
123
|
+
ops = [cirq.X(q[i]) for i in range(3)]
|
|
124
|
+
c = [cset.new_component(op=ops[i], moment_id=i) for i in range(3)]
|
|
125
|
+
cset.merge(c[0], c[1])
|
|
126
|
+
cset.merge(c[1], c[2])
|
|
127
|
+
assert cset.find(c[0]).ops == ops
|
|
128
|
+
# check merge of indirectly merged components does not make a difference
|
|
129
|
+
assert cset.merge(c[0], c[2]).ops == ops
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_component_with_ops_merge_when_merge_fails():
|
|
133
|
+
cset = ComponentWithOpsSet(_always_mergeable, _never_can_merge)
|
|
134
|
+
|
|
135
|
+
q = cirq.LineQubit.range(3)
|
|
136
|
+
ops = [cirq.X(q[i]) for i in range(3)]
|
|
137
|
+
c = [cset.new_component(op=ops[i], moment_id=i) for i in range(3)]
|
|
138
|
+
|
|
139
|
+
cset.merge(c[0], c[1])
|
|
140
|
+
cset.merge(c[1], c[2])
|
|
141
|
+
# No merge happened
|
|
142
|
+
for i in range(3):
|
|
143
|
+
assert cset.find(c[i]) is c[i]
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_component_with_ops_merge_when_is_mergeable_is_false():
|
|
147
|
+
cset = ComponentWithOpsSet(_never_mergeable, _always_can_merge)
|
|
148
|
+
|
|
149
|
+
q = cirq.LineQubit.range(3)
|
|
150
|
+
ops = [cirq.X(q[i]) for i in range(3)]
|
|
151
|
+
c = [cset.new_component(op=ops[i], moment_id=i) for i in range(3)]
|
|
152
|
+
|
|
153
|
+
cset.merge(c[0], c[1])
|
|
154
|
+
cset.merge(c[1], c[2])
|
|
155
|
+
# No merge happened
|
|
156
|
+
for i in range(3):
|
|
157
|
+
assert cset.find(c[i]) is c[i]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_component_with_circuit_op_merge():
|
|
161
|
+
cset = ComponentWithCircuitOpSet(_always_mergeable, _merge_as_first_operation)
|
|
162
|
+
|
|
163
|
+
q = cirq.LineQubit.range(3)
|
|
164
|
+
ops = [cirq.X(q[i]) for i in range(3)]
|
|
165
|
+
c = [cset.new_component(op=ops[i], moment_id=i) for i in range(3)]
|
|
166
|
+
|
|
167
|
+
cset.merge(c[0], c[1])
|
|
168
|
+
cset.merge(c[1], c[2])
|
|
169
|
+
for i in range(3):
|
|
170
|
+
assert cset.find(c[i]).circuit_op == ops[0]
|
|
171
|
+
# check merge of indirectly merged components does not make a difference
|
|
172
|
+
assert cset.merge(c[0], c[2]) is cset.find(c[1])
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def test_component_with_circuit_op_merge_func_is_none():
|
|
176
|
+
cset = ComponentWithCircuitOpSet(_always_mergeable, _merge_never_successful)
|
|
177
|
+
|
|
178
|
+
q = cirq.LineQubit.range(3)
|
|
179
|
+
ops = [cirq.X(q[i]) for i in range(3)]
|
|
180
|
+
c = [cset.new_component(op=ops[i], moment_id=i) for i in range(3)]
|
|
181
|
+
|
|
182
|
+
cset.merge(c[0], c[1])
|
|
183
|
+
cset.merge(c[1], c[2])
|
|
184
|
+
# No merge happened
|
|
185
|
+
for i in range(3):
|
|
186
|
+
assert cset.find(c[i]) is c[i]
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def test_component_with_circuit_op_merge_when_is_mergeable_is_false():
|
|
190
|
+
cset = ComponentWithCircuitOpSet(_never_mergeable, _merge_as_first_operation)
|
|
191
|
+
|
|
192
|
+
q = cirq.LineQubit.range(3)
|
|
193
|
+
ops = [cirq.X(q[i]) for i in range(3)]
|
|
194
|
+
c = [cset.new_component(op=ops[i], moment_id=i) for i in range(3)]
|
|
195
|
+
|
|
196
|
+
cset.merge(c[0], c[1])
|
|
197
|
+
cset.merge(c[1], c[2])
|
|
198
|
+
# No merge happened
|
|
199
|
+
for i in range(3):
|
|
200
|
+
assert cset.find(c[i]) is c[i]
|
cirq/transformers/align_test.py
CHANGED
|
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
import cirq
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def test_align_basic_no_context():
|
|
20
|
+
def test_align_basic_no_context() -> None:
|
|
21
21
|
q1 = cirq.NamedQubit('q1')
|
|
22
22
|
q2 = cirq.NamedQubit('q2')
|
|
23
23
|
c = cirq.Circuit(
|
|
@@ -45,7 +45,7 @@ def test_align_basic_no_context():
|
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
def test_align_left_no_compile_context():
|
|
48
|
+
def test_align_left_no_compile_context() -> None:
|
|
49
49
|
q1 = cirq.NamedQubit('q1')
|
|
50
50
|
q2 = cirq.NamedQubit('q2')
|
|
51
51
|
cirq.testing.assert_same_circuits(
|
|
@@ -59,7 +59,7 @@ def test_align_left_no_compile_context():
|
|
|
59
59
|
cirq.measure(*[q1, q2], key='a'),
|
|
60
60
|
]
|
|
61
61
|
),
|
|
62
|
-
context=cirq.TransformerContext(tags_to_ignore=
|
|
62
|
+
context=cirq.TransformerContext(tags_to_ignore=("nocompile",)),
|
|
63
63
|
),
|
|
64
64
|
cirq.Circuit(
|
|
65
65
|
[
|
|
@@ -73,7 +73,7 @@ def test_align_left_no_compile_context():
|
|
|
73
73
|
)
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
def test_align_left_deep():
|
|
76
|
+
def test_align_left_deep() -> None:
|
|
77
77
|
q1, q2 = cirq.LineQubit.range(2)
|
|
78
78
|
c_nested = cirq.FrozenCircuit(
|
|
79
79
|
[
|
|
@@ -104,11 +104,11 @@ def test_align_left_deep():
|
|
|
104
104
|
c_nested_aligned,
|
|
105
105
|
cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"),
|
|
106
106
|
)
|
|
107
|
-
context = cirq.TransformerContext(tags_to_ignore=
|
|
107
|
+
context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True)
|
|
108
108
|
cirq.testing.assert_same_circuits(cirq.align_left(c_orig, context=context), c_expected)
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
def test_align_left_subset_of_operations():
|
|
111
|
+
def test_align_left_subset_of_operations() -> None:
|
|
112
112
|
q1 = cirq.NamedQubit('q1')
|
|
113
113
|
q2 = cirq.NamedQubit('q2')
|
|
114
114
|
tag = "op_to_align"
|
|
@@ -134,7 +134,7 @@ def test_align_left_subset_of_operations():
|
|
|
134
134
|
cirq.toggle_tags(
|
|
135
135
|
cirq.align_left(
|
|
136
136
|
cirq.toggle_tags(c_orig, [tag]),
|
|
137
|
-
context=cirq.TransformerContext(tags_to_ignore=
|
|
137
|
+
context=cirq.TransformerContext(tags_to_ignore=(tag,)),
|
|
138
138
|
),
|
|
139
139
|
[tag],
|
|
140
140
|
),
|
|
@@ -142,7 +142,7 @@ def test_align_left_subset_of_operations():
|
|
|
142
142
|
)
|
|
143
143
|
|
|
144
144
|
|
|
145
|
-
def test_align_right_no_compile_context():
|
|
145
|
+
def test_align_right_no_compile_context() -> None:
|
|
146
146
|
q1 = cirq.NamedQubit('q1')
|
|
147
147
|
q2 = cirq.NamedQubit('q2')
|
|
148
148
|
cirq.testing.assert_same_circuits(
|
|
@@ -156,7 +156,7 @@ def test_align_right_no_compile_context():
|
|
|
156
156
|
cirq.measure(*[q1, q2], key='a'),
|
|
157
157
|
]
|
|
158
158
|
),
|
|
159
|
-
context=cirq.TransformerContext(tags_to_ignore=
|
|
159
|
+
context=cirq.TransformerContext(tags_to_ignore=("nocompile",)),
|
|
160
160
|
),
|
|
161
161
|
cirq.Circuit(
|
|
162
162
|
[
|
|
@@ -170,7 +170,7 @@ def test_align_right_no_compile_context():
|
|
|
170
170
|
)
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
def test_align_right_deep():
|
|
173
|
+
def test_align_right_deep() -> None:
|
|
174
174
|
q1, q2 = cirq.LineQubit.range(2)
|
|
175
175
|
c_nested = cirq.FrozenCircuit(
|
|
176
176
|
cirq.Moment([cirq.X(q1)]),
|
|
@@ -199,11 +199,11 @@ def test_align_right_deep():
|
|
|
199
199
|
c_nested_aligned,
|
|
200
200
|
cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"),
|
|
201
201
|
)
|
|
202
|
-
context = cirq.TransformerContext(tags_to_ignore=
|
|
202
|
+
context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True)
|
|
203
203
|
cirq.testing.assert_same_circuits(cirq.align_right(c_orig, context=context), c_expected)
|
|
204
204
|
|
|
205
205
|
|
|
206
|
-
def test_classical_control():
|
|
206
|
+
def test_classical_control() -> None:
|
|
207
207
|
q0, q1 = cirq.LineQubit.range(2)
|
|
208
208
|
circuit = cirq.Circuit(
|
|
209
209
|
cirq.H(q0), cirq.measure(q0, key='m'), cirq.X(q1).with_classical_controls('m')
|
|
@@ -212,7 +212,7 @@ def test_classical_control():
|
|
|
212
212
|
cirq.testing.assert_same_circuits(cirq.align_right(circuit), circuit)
|
|
213
213
|
|
|
214
214
|
|
|
215
|
-
def test_measurement_and_classical_control_same_moment_preserve_order():
|
|
215
|
+
def test_measurement_and_classical_control_same_moment_preserve_order() -> None:
|
|
216
216
|
q0, q1 = cirq.LineQubit.range(2)
|
|
217
217
|
circuit = cirq.Circuit()
|
|
218
218
|
op_measure = cirq.measure(q0, key='m')
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import functools
|
|
20
|
+
from collections.abc import Sequence
|
|
20
21
|
from typing import TYPE_CHECKING
|
|
21
22
|
|
|
22
23
|
import numpy as np
|
|
@@ -31,7 +32,7 @@ def _X(
|
|
|
31
32
|
q: int,
|
|
32
33
|
args: sim.CliffordTableauSimulationState,
|
|
33
34
|
operations: list[ops.Operation],
|
|
34
|
-
qubits:
|
|
35
|
+
qubits: Sequence[cirq.Qid],
|
|
35
36
|
):
|
|
36
37
|
protocols.act_on(ops.X, args, qubits=[qubits[q]], allow_decompose=False)
|
|
37
38
|
operations.append(ops.X(qubits[q]))
|
|
@@ -41,7 +42,7 @@ def _Z(
|
|
|
41
42
|
q: int,
|
|
42
43
|
args: sim.CliffordTableauSimulationState,
|
|
43
44
|
operations: list[ops.Operation],
|
|
44
|
-
qubits:
|
|
45
|
+
qubits: Sequence[cirq.Qid],
|
|
45
46
|
):
|
|
46
47
|
protocols.act_on(ops.Z, args, qubits=[qubits[q]], allow_decompose=False)
|
|
47
48
|
operations.append(ops.Z(qubits[q]))
|
|
@@ -51,7 +52,7 @@ def _Sdg(
|
|
|
51
52
|
q: int,
|
|
52
53
|
args: sim.CliffordTableauSimulationState,
|
|
53
54
|
operations: list[ops.Operation],
|
|
54
|
-
qubits:
|
|
55
|
+
qubits: Sequence[cirq.Qid],
|
|
55
56
|
):
|
|
56
57
|
# Apply the tableau with S^\{dagger}
|
|
57
58
|
protocols.act_on(ops.S**-1, args, qubits=[qubits[q]], allow_decompose=False)
|
|
@@ -62,7 +63,7 @@ def _H(
|
|
|
62
63
|
q: int,
|
|
63
64
|
args: sim.CliffordTableauSimulationState,
|
|
64
65
|
operations: list[ops.Operation],
|
|
65
|
-
qubits:
|
|
66
|
+
qubits: Sequence[cirq.Qid],
|
|
66
67
|
):
|
|
67
68
|
protocols.act_on(ops.H, args, qubits=[qubits[q]], allow_decompose=False)
|
|
68
69
|
operations.append(ops.H(qubits[q]))
|
|
@@ -73,7 +74,7 @@ def _CNOT(
|
|
|
73
74
|
q2: int,
|
|
74
75
|
args: sim.CliffordTableauSimulationState,
|
|
75
76
|
operations: list[ops.Operation],
|
|
76
|
-
qubits:
|
|
77
|
+
qubits: Sequence[cirq.Qid],
|
|
77
78
|
):
|
|
78
79
|
protocols.act_on(ops.CNOT, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False)
|
|
79
80
|
operations.append(ops.CNOT(qubits[q1], qubits[q2]))
|
|
@@ -84,14 +85,14 @@ def _SWAP(
|
|
|
84
85
|
q2: int,
|
|
85
86
|
args: sim.CliffordTableauSimulationState,
|
|
86
87
|
operations: list[ops.Operation],
|
|
87
|
-
qubits:
|
|
88
|
+
qubits: Sequence[cirq.Qid],
|
|
88
89
|
):
|
|
89
90
|
protocols.act_on(ops.SWAP, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False)
|
|
90
91
|
operations.append(ops.SWAP(qubits[q1], qubits[q2]))
|
|
91
92
|
|
|
92
93
|
|
|
93
94
|
def decompose_clifford_tableau_to_operations(
|
|
94
|
-
qubits:
|
|
95
|
+
qubits: Sequence[cirq.Qid], clifford_tableau: qis.CliffordTableau
|
|
95
96
|
) -> list[ops.Operation]:
|
|
96
97
|
"""Decompose an n-qubit Clifford Tableau into a list of one/two qubit operations.
|
|
97
98
|
|
|
@@ -21,14 +21,14 @@ import cirq
|
|
|
21
21
|
from cirq.testing import assert_allclose_up_to_global_phase
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def test_misaligned_qubits():
|
|
24
|
+
def test_misaligned_qubits() -> None:
|
|
25
25
|
qubits = cirq.LineQubit.range(1)
|
|
26
26
|
tableau = cirq.CliffordTableau(num_qubits=2)
|
|
27
27
|
with pytest.raises(ValueError):
|
|
28
28
|
cirq.decompose_clifford_tableau_to_operations(qubits, tableau)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def test_clifford_decompose_one_qubit():
|
|
31
|
+
def test_clifford_decompose_one_qubit() -> None:
|
|
32
32
|
"""Two random instance for one qubit decomposition."""
|
|
33
33
|
qubits = cirq.LineQubit.range(1)
|
|
34
34
|
args = cirq.CliffordTableauSimulationState(
|
|
@@ -63,7 +63,7 @@ def test_clifford_decompose_one_qubit():
|
|
|
63
63
|
assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
def test_clifford_decompose_two_qubits():
|
|
66
|
+
def test_clifford_decompose_two_qubits() -> None:
|
|
67
67
|
"""Two random instance for two qubits decomposition."""
|
|
68
68
|
qubits = cirq.LineQubit.range(2)
|
|
69
69
|
args = cirq.CliffordTableauSimulationState(
|
|
@@ -98,7 +98,7 @@ def test_clifford_decompose_two_qubits():
|
|
|
98
98
|
assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
def test_clifford_decompose_by_unitary():
|
|
101
|
+
def test_clifford_decompose_by_unitary() -> None:
|
|
102
102
|
"""Validate the decomposition of random Clifford Tableau by unitary matrix.
|
|
103
103
|
|
|
104
104
|
Due to the exponential growth in dimension, it cannot validate very large number of qubits.
|
|
@@ -125,7 +125,7 @@ def test_clifford_decompose_by_unitary():
|
|
|
125
125
|
assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7)
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
def test_clifford_decompose_by_reconstruction():
|
|
128
|
+
def test_clifford_decompose_by_reconstruction() -> None:
|
|
129
129
|
"""Validate the decomposition of random Clifford Tableau by reconstruction.
|
|
130
130
|
|
|
131
131
|
This approach can validate large number of qubits compared with the unitary one.
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import itertools
|
|
18
|
+
from collections.abc import Sequence
|
|
18
19
|
from typing import TYPE_CHECKING
|
|
19
20
|
|
|
20
21
|
import numpy as np
|
|
@@ -114,7 +115,7 @@ def _ccnot_congruent(c0: cirq.Qid, c1: cirq.Qid, target: cirq.Qid) -> list[cirq.
|
|
|
114
115
|
|
|
115
116
|
|
|
116
117
|
def decompose_multi_controlled_x(
|
|
117
|
-
controls:
|
|
118
|
+
controls: Sequence[cirq.Qid], target: cirq.Qid, free_qubits: Sequence[cirq.Qid]
|
|
118
119
|
) -> list[cirq.Operation]:
|
|
119
120
|
"""Implements action of multi-controlled Pauli X gate.
|
|
120
121
|
|
|
@@ -152,11 +153,11 @@ def decompose_multi_controlled_x(
|
|
|
152
153
|
elif len(free_qubits) >= 1:
|
|
153
154
|
# See [1], Lemma 7.3.
|
|
154
155
|
m1 = n // 2
|
|
155
|
-
free1 = controls[m1:]
|
|
156
|
+
free1 = [*controls[m1:], target, *free_qubits[1:]]
|
|
156
157
|
ctrl1 = controls[:m1]
|
|
157
158
|
part1 = decompose_multi_controlled_x(ctrl1, free_qubits[0], free1)
|
|
158
|
-
free2 = controls[:m1]
|
|
159
|
-
ctrl2 = controls[m1:]
|
|
159
|
+
free2 = [*controls[:m1], *free_qubits[1:]]
|
|
160
|
+
ctrl2 = [*controls[m1:], free_qubits[0]]
|
|
160
161
|
part2 = decompose_multi_controlled_x(ctrl2, target, free2)
|
|
161
162
|
return [*part1, *part2, *part1, *part2]
|
|
162
163
|
else:
|
|
@@ -167,7 +168,7 @@ def decompose_multi_controlled_x(
|
|
|
167
168
|
|
|
168
169
|
|
|
169
170
|
def _decompose_su(
|
|
170
|
-
matrix: np.ndarray, controls:
|
|
171
|
+
matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid
|
|
171
172
|
) -> list[cirq.Operation]:
|
|
172
173
|
"""Decomposes controlled special unitary gate into elementary gates.
|
|
173
174
|
|
|
@@ -193,9 +194,9 @@ def _decompose_su(
|
|
|
193
194
|
def _decompose_recursive(
|
|
194
195
|
matrix: np.ndarray,
|
|
195
196
|
power: float,
|
|
196
|
-
controls:
|
|
197
|
+
controls: Sequence[cirq.Qid],
|
|
197
198
|
target: cirq.Qid,
|
|
198
|
-
free_qubits:
|
|
199
|
+
free_qubits: Sequence[cirq.Qid],
|
|
199
200
|
) -> list[cirq.Operation]:
|
|
200
201
|
"""Decomposes controlled unitary gate into elementary gates.
|
|
201
202
|
|
|
@@ -205,20 +206,20 @@ def _decompose_recursive(
|
|
|
205
206
|
if len(controls) == 1:
|
|
206
207
|
return _decompose_single_ctrl(_unitary_power(matrix, power), controls[0], target)
|
|
207
208
|
|
|
208
|
-
cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], free_qubits
|
|
209
|
+
cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], [*free_qubits, target])
|
|
209
210
|
return [
|
|
210
211
|
*_decompose_single_ctrl(_unitary_power(matrix, 0.5 * power), controls[-1], target),
|
|
211
212
|
*cnots,
|
|
212
213
|
*_decompose_single_ctrl(_unitary_power(matrix, -0.5 * power), controls[-1], target),
|
|
213
214
|
*cnots,
|
|
214
215
|
*_decompose_recursive(
|
|
215
|
-
matrix, 0.5 * power, controls[:-1], target, [controls[-1]
|
|
216
|
+
matrix, 0.5 * power, controls[:-1], target, [controls[-1], *free_qubits]
|
|
216
217
|
),
|
|
217
218
|
]
|
|
218
219
|
|
|
219
220
|
|
|
220
221
|
def decompose_multi_controlled_rotation(
|
|
221
|
-
matrix: np.ndarray, controls:
|
|
222
|
+
matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid
|
|
222
223
|
) -> list[cirq.Operation]:
|
|
223
224
|
"""Implements action of multi-controlled unitary gate.
|
|
224
225
|
|
|
@@ -20,7 +20,7 @@ import scipy.stats
|
|
|
20
20
|
import cirq
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def test_decompose_x():
|
|
23
|
+
def test_decompose_x() -> None:
|
|
24
24
|
"""Verifies correctness of multi-controlled X decomposition."""
|
|
25
25
|
for total_qubits_count in range(1, 8):
|
|
26
26
|
qubits = cirq.LineQubit.range(total_qubits_count)
|
|
@@ -83,14 +83,14 @@ def _test_decompose(matrix, controls_count):
|
|
|
83
83
|
cirq.testing.assert_allclose_up_to_global_phase(expected_matrix, result_matrix, atol=1e-8)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def test_decompose_specific_matrices():
|
|
86
|
+
def test_decompose_specific_matrices() -> None:
|
|
87
87
|
for gate in [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.I, cirq.T, cirq.S]:
|
|
88
88
|
for controls_count in range(7):
|
|
89
89
|
_test_decompose(cirq.unitary(gate), controls_count)
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
@cirq.testing.retry_once_with_later_random_values
|
|
93
|
-
def test_decompose_random_unitary():
|
|
93
|
+
def test_decompose_random_unitary() -> None:
|
|
94
94
|
for controls_count in range(5):
|
|
95
95
|
for _ in range(10):
|
|
96
96
|
_test_decompose(_random_unitary(), controls_count)
|
|
@@ -99,7 +99,7 @@ def test_decompose_random_unitary():
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
@cirq.testing.retry_once_with_later_random_values
|
|
102
|
-
def test_decompose_random_special_unitary():
|
|
102
|
+
def test_decompose_random_special_unitary() -> None:
|
|
103
103
|
for controls_count in range(5):
|
|
104
104
|
for _ in range(10):
|
|
105
105
|
_test_decompose(_random_special_unitary(), controls_count)
|
|
@@ -113,7 +113,7 @@ def _decomposition_size(U, controls_count):
|
|
|
113
113
|
return _count_operations(operations)
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
def test_decompose_size_special_unitary():
|
|
116
|
+
def test_decompose_size_special_unitary() -> None:
|
|
117
117
|
np.random.seed(0)
|
|
118
118
|
u = _random_special_unitary()
|
|
119
119
|
assert _decomposition_size(u, 0) == (1, 0, 0)
|
|
@@ -126,7 +126,7 @@ def test_decompose_size_special_unitary():
|
|
|
126
126
|
assert _decomposition_size(u, i) == (64 * i - 312, 48 * i - 234, 16)
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
def test_decompose_size_unitary():
|
|
129
|
+
def test_decompose_size_unitary() -> None:
|
|
130
130
|
np.random.seed(0)
|
|
131
131
|
u = _random_unitary()
|
|
132
132
|
assert _decomposition_size(u, 0) == (1, 0, 0)
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from collections.abc import Sequence
|
|
18
|
+
from typing import TYPE_CHECKING
|
|
18
19
|
|
|
19
20
|
import numpy as np
|
|
20
21
|
import sympy
|
|
@@ -100,7 +101,7 @@ def decompose_cphase_into_two_fsim(
|
|
|
100
101
|
fsim_gate: cirq.FSimGate,
|
|
101
102
|
qubits: Sequence[cirq.Qid] | None = None,
|
|
102
103
|
atol: float = 1e-8,
|
|
103
|
-
) -> cirq.
|
|
104
|
+
) -> Sequence[cirq.Operation]:
|
|
104
105
|
"""Decomposes CZPowGate into two FSimGates.
|
|
105
106
|
|
|
106
107
|
This function implements the decomposition described in section VII F I
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import itertools
|
|
18
|
-
from
|
|
18
|
+
from collections.abc import Sequence
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
import pytest
|
|
@@ -24,7 +24,7 @@ import sympy
|
|
|
24
24
|
import cirq
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def test_symbols():
|
|
27
|
+
def test_symbols() -> None:
|
|
28
28
|
with pytest.raises(ValueError, match='Symbolic arguments'):
|
|
29
29
|
cirq.compute_cphase_exponents_for_fsim_decomposition(
|
|
30
30
|
cirq.FSimGate(theta=sympy.Symbol('t'), phi=sympy.Symbol('phi'))
|
|
@@ -36,8 +36,9 @@ class FakeSycamoreGate(cirq.FSimGate):
|
|
|
36
36
|
super().__init__(theta=np.pi / 2, phi=np.pi / 6)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def test_parameterized_gates():
|
|
39
|
+
def test_parameterized_gates() -> None:
|
|
40
40
|
t = sympy.Symbol('t')
|
|
41
|
+
fsim_gate: cirq.FSimGate
|
|
41
42
|
with pytest.raises(ValueError):
|
|
42
43
|
cphase_gate = cirq.CZPowGate(exponent=t)
|
|
43
44
|
fsim_gate = FakeSycamoreGate()
|
|
@@ -54,14 +55,14 @@ def test_parameterized_gates():
|
|
|
54
55
|
cirq.decompose_cphase_into_two_fsim(cphase_gate, fsim_gate=fsim_gate)
|
|
55
56
|
|
|
56
57
|
|
|
57
|
-
def test_invalid_qubits():
|
|
58
|
+
def test_invalid_qubits() -> None:
|
|
58
59
|
with pytest.raises(ValueError):
|
|
59
60
|
cirq.decompose_cphase_into_two_fsim(
|
|
60
61
|
cphase_gate=cirq.CZ, fsim_gate=FakeSycamoreGate(), qubits=cirq.LineQubit.range(3)
|
|
61
62
|
)
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
def test_circuit_structure():
|
|
65
|
+
def test_circuit_structure() -> None:
|
|
65
66
|
syc = FakeSycamoreGate()
|
|
66
67
|
ops = cirq.decompose_cphase_into_two_fsim(cirq.CZ, fsim_gate=syc)
|
|
67
68
|
num_interaction_moments = 0
|
|
@@ -73,7 +74,7 @@ def test_circuit_structure():
|
|
|
73
74
|
assert num_interaction_moments == 2
|
|
74
75
|
|
|
75
76
|
|
|
76
|
-
def assert_decomposition_valid(cphase_gate, fsim_gate):
|
|
77
|
+
def assert_decomposition_valid(cphase_gate, fsim_gate) -> None:
|
|
77
78
|
u_expected = cirq.unitary(cphase_gate)
|
|
78
79
|
ops = cirq.decompose_cphase_into_two_fsim(cphase_gate, fsim_gate=fsim_gate)
|
|
79
80
|
u_actual = cirq.unitary(cirq.Circuit(ops))
|
|
@@ -83,7 +84,7 @@ def assert_decomposition_valid(cphase_gate, fsim_gate):
|
|
|
83
84
|
@pytest.mark.parametrize(
|
|
84
85
|
'exponent', (-5.5, -3, -1.5, -1, -0.65, -0.2, 0, 0.1, 0.75, 1, 1.5, 2, 5.5)
|
|
85
86
|
)
|
|
86
|
-
def test_decomposition_to_sycamore_gate(exponent):
|
|
87
|
+
def test_decomposition_to_sycamore_gate(exponent) -> None:
|
|
87
88
|
cphase_gate = cirq.CZPowGate(exponent=exponent)
|
|
88
89
|
assert_decomposition_valid(cphase_gate, FakeSycamoreGate())
|
|
89
90
|
|
|
@@ -95,7 +96,7 @@ def test_decomposition_to_sycamore_gate(exponent):
|
|
|
95
96
|
(-1.4 * np.pi, -np.pi / 9, np.pi / 11, np.pi / 2, 2.4 * np.pi),
|
|
96
97
|
),
|
|
97
98
|
)
|
|
98
|
-
def test_valid_cphase_exponents(theta, phi):
|
|
99
|
+
def test_valid_cphase_exponents(theta, phi) -> None:
|
|
99
100
|
fsim_gate = cirq.FSimGate(theta=theta, phi=phi)
|
|
100
101
|
valid_exponent_intervals = cirq.compute_cphase_exponents_for_fsim_decomposition(fsim_gate)
|
|
101
102
|
assert valid_exponent_intervals
|
|
@@ -131,7 +132,7 @@ def complement_intervals(intervals: Sequence[tuple[float, float]]) -> Sequence[t
|
|
|
131
132
|
(-1.7 * np.pi, -np.pi / 5, np.pi / 7, 2.5 * np.pi),
|
|
132
133
|
),
|
|
133
134
|
)
|
|
134
|
-
def test_invalid_cphase_exponents(theta, phi):
|
|
135
|
+
def test_invalid_cphase_exponents(theta, phi) -> None:
|
|
135
136
|
fsim_gate = cirq.FSimGate(theta=theta, phi=phi)
|
|
136
137
|
valid_exponent_intervals = cirq.compute_cphase_exponents_for_fsim_decomposition(fsim_gate)
|
|
137
138
|
invalid_exponent_intervals = complement_intervals(valid_exponent_intervals)
|
|
@@ -151,6 +152,6 @@ def test_invalid_cphase_exponents(theta, phi):
|
|
|
151
152
|
@pytest.mark.parametrize(
|
|
152
153
|
'bad_fsim_gate', (cirq.FSimGate(theta=0, phi=0), cirq.FSimGate(theta=np.pi / 4, phi=np.pi / 2))
|
|
153
154
|
)
|
|
154
|
-
def test_invalid_fsim_gate(bad_fsim_gate):
|
|
155
|
+
def test_invalid_fsim_gate(bad_fsim_gate) -> None:
|
|
155
156
|
with pytest.raises(ValueError):
|
|
156
157
|
cirq.decompose_cphase_into_two_fsim(cirq.CZ, fsim_gate=bad_fsim_gate)
|