diff --git a/cirq-core/cirq/contrib/paulistring/recombine_test.py b/cirq-core/cirq/contrib/paulistring/recombine_test.py index 62279ec0b07..318c15104ba 100644 --- a/cirq-core/cirq/contrib/paulistring/recombine_test.py +++ b/cirq-core/cirq/contrib/paulistring/recombine_test.py @@ -43,8 +43,11 @@ def test_move_non_clifford_into_clifford(): _assert_no_multi_qubit_pauli_strings(c_recombined1) _assert_no_multi_qubit_pauli_strings(c_recombined2) - baseline_len = len(cg.optimized_for_xmon(c_orig)) - opt_len1 = len(cg.optimized_for_xmon(c_recombined1)) - opt_len2 = len(cg.optimized_for_xmon(c_recombined2)) - assert opt_len1 <= baseline_len - assert opt_len2 <= baseline_len + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=None + ): + baseline_len = len(cg.optimized_for_xmon(c_orig)) + opt_len1 = len(cg.optimized_for_xmon(c_recombined1)) + opt_len2 = len(cg.optimized_for_xmon(c_recombined2)) + assert opt_len1 <= baseline_len + assert opt_len2 <= baseline_len diff --git a/cirq-google/cirq_google/optimizers/optimize_for_sycamore.py b/cirq-google/cirq_google/optimizers/optimize_for_sycamore.py index 51a0be9c820..5223a249943 100644 --- a/cirq-google/cirq_google/optimizers/optimize_for_sycamore.py +++ b/cirq-google/cirq_google/optimizers/optimize_for_sycamore.py @@ -18,6 +18,7 @@ import numpy as np import cirq +from cirq import _compat from cirq_google import ops as cg_ops from cirq_google.transformers.target_gatesets import sycamore_gateset @@ -48,6 +49,17 @@ def _gate_product_tabulation_cached( raise NotImplementedError(f"Two qubit gate tabulation not supported for {optimizer_type}") +@_compat.deprecated( + deadline='v0.16', + fix="""Use `cirq.optimize_for_target_gateset(circuit, gateset=).` +If `optimizer_type` is 'sqrt_iswap', `gateset=cirq.SqrtIswapTargetGateset(atol=tolerance)`. +If `optimizer_type` is 'sycamore', `gateset=cirq_google.SycamoreTargetGateset(atol=tolerance), + optionally setting tabulation in the SycamoreTargetGateset constructor. +If `optimizer_type` is 'xmon', `gateset=cirq.CZTargetGateset(atol=tolerance). +If `optimizer_type` is 'xmon_partial_cz', + `gateset=cirq.CZTargetGateset(atol=tolerance, allow_partial_czs=True). +""", +) def optimized_for_sycamore( circuit: cirq.Circuit, *, diff --git a/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py b/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py index b5159ed93f3..0190d64b00e 100644 --- a/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py +++ b/cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py @@ -38,10 +38,14 @@ def test_optimizer_output_gates_are_supported(optimizer_type, gateset): circuit = cirq.Circuit( cirq.CZ(q0, q1), cirq.X(q0) ** 0.2, cirq.Z(q1) ** 0.2, cirq.measure(q0, q1, key='m') ) - new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type) - for moment in new_circuit: - for op in moment: - assert gateset.is_supported_operation(op) + + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=1 + ): + new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type) + for moment in new_circuit: + for op in moment: + assert gateset.is_supported_operation(op) @pytest.mark.parametrize('optimizer_type, gateset', _OPTIMIZERS_AND_GATESETS) @@ -53,19 +57,26 @@ def test_optimize_large_measurement_gates(optimizer_type, gateset): [cirq.CZ(qubits[i], qubits[i + 1]) for i in range(1, len(qubits) - 1, 2)], cirq.measure(*qubits, key='m'), ) - new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type) - for moment in new_circuit: - for op in moment: - assert gateset.is_supported_operation(op) + + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=1 + ): + new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type) + for moment in new_circuit: + for op in moment: + assert gateset.is_supported_operation(op) def test_invalid_input(): - with pytest.raises(ValueError): - q0, q1 = cirq.LineQubit.range(2) - circuit = cirq.Circuit( - cirq.CZ(q0, q1), cirq.X(q0) ** 0.2, cirq.Z(q1) ** 0.2, cirq.measure(q0, q1, key='m') - ) - _ = cg.optimized_for_sycamore(circuit, optimizer_type='for_tis_100') + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=1 + ): + with pytest.raises(ValueError): + q0, q1 = cirq.LineQubit.range(2) + circuit = cirq.Circuit( + cirq.CZ(q0, q1), cirq.X(q0) ** 0.2, cirq.Z(q1) ** 0.2, cirq.measure(q0, q1, key='m') + ) + _ = cg.optimized_for_sycamore(circuit, optimizer_type='for_tis_100') def test_tabulation(): @@ -74,31 +85,41 @@ def test_tabulation(): circuit = cirq.Circuit(cirq.MatrixGate(u).on(q0, q1)) np.testing.assert_allclose(u, cirq.unitary(circuit)) - circuit2 = cg.optimized_for_sycamore(circuit, optimizer_type='sycamore') - cirq.testing.assert_allclose_up_to_global_phase(u, cirq.unitary(circuit2), atol=1e-5) - assert len(circuit2) == 13 - - # Note this is run on every commit, so it needs to be relatively quick. - # This requires us to use relatively loose tolerances - circuit3 = cg.optimized_for_sycamore( - circuit, optimizer_type='sycamore', tabulation_resolution=0.1 - ) - cirq.testing.assert_allclose_up_to_global_phase(u, cirq.unitary(circuit3), rtol=1e-1, atol=1e-1) - assert len(circuit3) == 7 + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + circuit2 = cg.optimized_for_sycamore(circuit, optimizer_type='sycamore') + cirq.testing.assert_allclose_up_to_global_phase(u, cirq.unitary(circuit2), atol=1e-5) + assert len(circuit2) == 13 + # Note this is run on every commit, so it needs to be relatively quick. + # This requires us to use relatively loose tolerances + circuit3 = cg.optimized_for_sycamore( + circuit, optimizer_type='sycamore', tabulation_resolution=0.1 + ) + cirq.testing.assert_allclose_up_to_global_phase( + u, cirq.unitary(circuit3), rtol=1e-1, atol=1e-1 + ) + assert len(circuit3) == 7 def test_no_tabulation(): circuit = cirq.Circuit(cirq.X(cirq.LineQubit(0))) - with pytest.raises(NotImplementedError): - cg.optimized_for_sycamore(circuit, optimizer_type='sqrt_iswap', tabulation_resolution=0.01) - with pytest.raises(NotImplementedError): - cg.optimized_for_sycamore(circuit, optimizer_type='xmon', tabulation_resolution=0.01) + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=3 + ): + with pytest.raises(NotImplementedError): + cg.optimized_for_sycamore( + circuit, optimizer_type='sqrt_iswap', tabulation_resolution=0.01 + ) - with pytest.raises(NotImplementedError): - cg.optimized_for_sycamore( - circuit, optimizer_type='xmon_partial_cz', tabulation_resolution=0.01 - ) + with pytest.raises(NotImplementedError): + cg.optimized_for_sycamore(circuit, optimizer_type='xmon', tabulation_resolution=0.01) + + with pytest.raises(NotImplementedError): + cg.optimized_for_sycamore( + circuit, optimizer_type='xmon_partial_cz', tabulation_resolution=0.01 + ) def test_one_q_matrix_gate(): @@ -106,21 +127,25 @@ def test_one_q_matrix_gate(): q = cirq.LineQubit(0) circuit0 = cirq.Circuit(cirq.MatrixGate(u).on(q)) assert len(circuit0) == 1 - circuit_iswap = cg.optimized_for_sycamore(circuit0, optimizer_type='sqrt_iswap') - assert len(circuit_iswap) == 1 - for moment in circuit_iswap: - for op in moment: - assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op) - # single qubit gates shared between gatesets, so: - assert cg.SYC_GATESET.is_supported_operation(op) - - circuit_syc = cg.optimized_for_sycamore(circuit0, optimizer_type='sycamore') - assert len(circuit_syc) == 1 - for moment in circuit_iswap: - for op in moment: - assert cg.SYC_GATESET.is_supported_operation(op) - # single qubit gates shared between gatesets, so: - assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op) + + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + circuit_iswap = cg.optimized_for_sycamore(circuit0, optimizer_type='sqrt_iswap') + assert len(circuit_iswap) == 1 + for moment in circuit_iswap: + for op in moment: + assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op) + # single qubit gates shared between gatesets, so: + assert cg.SYC_GATESET.is_supported_operation(op) + + circuit_syc = cg.optimized_for_sycamore(circuit0, optimizer_type='sycamore') + assert len(circuit_syc) == 1 + for moment in circuit_iswap: + for op in moment: + assert cg.SYC_GATESET.is_supported_operation(op) + # single qubit gates shared between gatesets, so: + assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op) @pytest.mark.parametrize( @@ -131,20 +156,23 @@ def test_circuit_operation_conversion(optimizer_type, two_qubit_gate_type): q0, q1 = cirq.LineQubit.range(2) subcircuit = cirq.FrozenCircuit(cirq.X(q0), cirq.SWAP(q0, q1)) circuit = cirq.Circuit(cirq.CircuitOperation(subcircuit)) - converted_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type) - # Verify that the CircuitOperation was preserved. - ops = list(converted_circuit.all_operations()) - assert isinstance(ops[0], cirq.CircuitOperation) - # Verify that the contents of the CircuitOperation were optimized. - converted_subcircuit = cg.optimized_for_sycamore( - subcircuit.unfreeze(), optimizer_type=optimizer_type - ) - assert len( - [*converted_subcircuit.findall_operations_with_gate_type(two_qubit_gate_type)] - ) == len([*ops[0].circuit.findall_operations_with_gate_type(two_qubit_gate_type)]) - cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( - ops[0].circuit, converted_subcircuit, atol=1e-6 - ) - cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( - circuit, converted_circuit, atol=1e-6 - ) + with cirq.testing.assert_deprecated( + 'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + converted_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type) + # Verify that the CircuitOperation was preserved. + ops = list(converted_circuit.all_operations()) + assert isinstance(ops[0], cirq.CircuitOperation) + # Verify that the contents of the CircuitOperation were optimized. + converted_subcircuit = cg.optimized_for_sycamore( + subcircuit.unfreeze(), optimizer_type=optimizer_type + ) + assert len( + [*converted_subcircuit.findall_operations_with_gate_type(two_qubit_gate_type)] + ) == len([*ops[0].circuit.findall_operations_with_gate_type(two_qubit_gate_type)]) + cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( + ops[0].circuit, converted_subcircuit, atol=1e-6 + ) + cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( + circuit, converted_circuit, atol=1e-6 + ) diff --git a/cirq-google/cirq_google/optimizers/optimize_for_xmon.py b/cirq-google/cirq_google/optimizers/optimize_for_xmon.py index 0c91646b403..988fcd3ba3d 100644 --- a/cirq-google/cirq_google/optimizers/optimize_for_xmon.py +++ b/cirq-google/cirq_google/optimizers/optimize_for_xmon.py @@ -15,12 +15,18 @@ from typing import Callable, cast, TYPE_CHECKING import cirq +from cirq import _compat from cirq_google.optimizers import optimized_for_sycamore if TYPE_CHECKING: import cirq_google +@_compat.deprecated( + deadline='v0.16', + # pylint: disable=line-too-long + fix='Use cirq.optimize_for_target_gateset(circuit, gateset=cirq.CZTargetGateset(atol=tolerance, allow_partial_czs=allow_partial_czs)).', +) def optimized_for_xmon( circuit: cirq.Circuit, qubit_map: Callable[[cirq.Qid], cirq.GridQubit] = lambda e: cast(cirq.GridQubit, e), diff --git a/cirq-google/cirq_google/optimizers/optimize_for_xmon_test.py b/cirq-google/cirq_google/optimizers/optimize_for_xmon_test.py index 246bee47770..ee69984eb87 100644 --- a/cirq-google/cirq_google/optimizers/optimize_for_xmon_test.py +++ b/cirq-google/cirq_google/optimizers/optimize_for_xmon_test.py @@ -28,10 +28,13 @@ def test_swap_field(n: int, d: int): ) before.append(cirq.measure(*before.all_qubits())) - after = cg.optimized_for_xmon(before) - assert len(after) == d * 4 + 2 - if n <= 5: - assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4) + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + after = cg.optimized_for_xmon(before) + assert len(after) == d * 4 + 2 + if n <= 5: + assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4) def test_ccz(): @@ -39,20 +42,26 @@ def test_ccz(): cirq.CCZ(cirq.GridQubit(5, 5), cirq.GridQubit(5, 6), cirq.GridQubit(5, 7)) ) - after = cg.optimized_for_xmon(before) + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + after = cg.optimized_for_xmon(before) - assert len(after) <= 22 - assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4) + assert len(after) <= 22 + assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4) def test_remap_qubits(): before = cirq.Circuit([cirq.Moment([cirq.CZ(cirq.LineQubit(0), cirq.LineQubit(1))])]) - after = cg.optimized_for_xmon(before, qubit_map=lambda q: cirq.GridQubit(q.x, 0)) + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + after = cg.optimized_for_xmon(before, qubit_map=lambda q: cirq.GridQubit(q.x, 0)) - assert after == cirq.Circuit( - [cirq.Moment([cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0))])] - ) + assert after == cirq.Circuit( + [cirq.Moment([cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0))])] + ) def test_dont_allow_partial_czs(): @@ -60,17 +69,20 @@ def test_dont_allow_partial_czs(): [cirq.Moment([cirq.CZ(cirq.GridQubit(5, 5), cirq.GridQubit(5, 6)) ** 0.5])] ) - after = cg.optimized_for_xmon(before, allow_partial_czs=False) + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + after = cg.optimized_for_xmon(before, allow_partial_czs=False) - cz_gates = [ - op.gate - for op in after.all_operations() - if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate) - ] - num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) - num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) - assert num_full_cz == 2 - assert num_part_cz == 0 + cz_gates = [ + op.gate + for op in after.all_operations() + if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate) + ] + num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) + num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) + assert num_full_cz == 2 + assert num_part_cz == 0 def test_allow_partial_czs(): @@ -78,14 +90,17 @@ def test_allow_partial_czs(): [cirq.Moment([cirq.CZ(cirq.GridQubit(5, 5), cirq.GridQubit(5, 6)) ** 0.5])] ) - after = cg.optimized_for_xmon(before, allow_partial_czs=True) - - cz_gates = [ - op.gate - for op in after.all_operations() - if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate) - ] - num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) - num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) - assert num_full_cz == 0 - assert num_part_cz == 1 + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2 + ): + after = cg.optimized_for_xmon(before, allow_partial_czs=True) + + cz_gates = [ + op.gate + for op in after.all_operations() + if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate) + ] + num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1) + num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1) + assert num_full_cz == 0 + assert num_part_cz == 1 diff --git a/examples/advanced/quantum_volume_test.py b/examples/advanced/quantum_volume_test.py index c5ae7ad9b86..0c85e5594cb 100644 --- a/examples/advanced/quantum_volume_test.py +++ b/examples/advanced/quantum_volume_test.py @@ -2,6 +2,7 @@ import pytest +import cirq from examples.advanced import quantum_volume @@ -10,7 +11,10 @@ def test_main_loop(): # Keep test from taking a long time by lowering repetitions. pytest.importorskip("cirq_google") args = '--num_qubits 5 --depth 5 --num_circuits 1 --routes 3'.split() - quantum_volume.main(**quantum_volume.parse_arguments(args)) + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=None + ): + quantum_volume.main(**quantum_volume.parse_arguments(args)) def test_parse_args(): diff --git a/examples/examples_test.py b/examples/examples_test.py index 1f415f238b7..38e29abacd3 100644 --- a/examples/examples_test.py +++ b/examples/examples_test.py @@ -70,7 +70,10 @@ def test_example_runs_quantum_fourier_transform(): def test_example_runs_bcs_mean_field(): pytest.importorskip("cirq_google") - examples.bcs_mean_field.main() + with cirq.testing.assert_deprecated( + 'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=None + ): + examples.bcs_mean_field.main() def test_example_runs_grover():