Skip to content

Commit 9cac7d9

Browse files
verultrht
authored andcommitted
Deprecate optimize_for_sycamore and optimize_for_xmon (quantumlib#5531)
* Added deprecation warnings * Updated tests to check for deprecation warnings. @tanujkhattar @MichaelBroughton
1 parent d50183c commit 9cac7d9

File tree

7 files changed

+175
-104
lines changed

7 files changed

+175
-104
lines changed

cirq-core/cirq/contrib/paulistring/recombine_test.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ def test_move_non_clifford_into_clifford():
4343
_assert_no_multi_qubit_pauli_strings(c_recombined1)
4444
_assert_no_multi_qubit_pauli_strings(c_recombined2)
4545

46-
baseline_len = len(cg.optimized_for_xmon(c_orig))
47-
opt_len1 = len(cg.optimized_for_xmon(c_recombined1))
48-
opt_len2 = len(cg.optimized_for_xmon(c_recombined2))
49-
assert opt_len1 <= baseline_len
50-
assert opt_len2 <= baseline_len
46+
with cirq.testing.assert_deprecated(
47+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=None
48+
):
49+
baseline_len = len(cg.optimized_for_xmon(c_orig))
50+
opt_len1 = len(cg.optimized_for_xmon(c_recombined1))
51+
opt_len2 = len(cg.optimized_for_xmon(c_recombined2))
52+
assert opt_len1 <= baseline_len
53+
assert opt_len2 <= baseline_len

cirq-google/cirq_google/optimizers/optimize_for_sycamore.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import numpy as np
1919

2020
import cirq
21+
from cirq import _compat
2122
from cirq_google import ops as cg_ops
2223
from cirq_google.transformers.target_gatesets import sycamore_gateset
2324

@@ -48,6 +49,17 @@ def _gate_product_tabulation_cached(
4849
raise NotImplementedError(f"Two qubit gate tabulation not supported for {optimizer_type}")
4950

5051

52+
@_compat.deprecated(
53+
deadline='v0.16',
54+
fix="""Use `cirq.optimize_for_target_gateset(circuit, gateset=<target_gateset>).`
55+
If `optimizer_type` is 'sqrt_iswap', `gateset=cirq.SqrtIswapTargetGateset(atol=tolerance)`.
56+
If `optimizer_type` is 'sycamore', `gateset=cirq_google.SycamoreTargetGateset(atol=tolerance),
57+
optionally setting tabulation in the SycamoreTargetGateset constructor.
58+
If `optimizer_type` is 'xmon', `gateset=cirq.CZTargetGateset(atol=tolerance).
59+
If `optimizer_type` is 'xmon_partial_cz',
60+
`gateset=cirq.CZTargetGateset(atol=tolerance, allow_partial_czs=True).
61+
""",
62+
)
5163
def optimized_for_sycamore(
5264
circuit: cirq.Circuit,
5365
*,

cirq-google/cirq_google/optimizers/optimize_for_sycamore_test.py

Lines changed: 93 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ def test_optimizer_output_gates_are_supported(optimizer_type, gateset):
3838
circuit = cirq.Circuit(
3939
cirq.CZ(q0, q1), cirq.X(q0) ** 0.2, cirq.Z(q1) ** 0.2, cirq.measure(q0, q1, key='m')
4040
)
41-
new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type)
42-
for moment in new_circuit:
43-
for op in moment:
44-
assert gateset.is_supported_operation(op)
41+
42+
with cirq.testing.assert_deprecated(
43+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=1
44+
):
45+
new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type)
46+
for moment in new_circuit:
47+
for op in moment:
48+
assert gateset.is_supported_operation(op)
4549

4650

4751
@pytest.mark.parametrize('optimizer_type, gateset', _OPTIMIZERS_AND_GATESETS)
@@ -53,19 +57,26 @@ def test_optimize_large_measurement_gates(optimizer_type, gateset):
5357
[cirq.CZ(qubits[i], qubits[i + 1]) for i in range(1, len(qubits) - 1, 2)],
5458
cirq.measure(*qubits, key='m'),
5559
)
56-
new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type)
57-
for moment in new_circuit:
58-
for op in moment:
59-
assert gateset.is_supported_operation(op)
60+
61+
with cirq.testing.assert_deprecated(
62+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=1
63+
):
64+
new_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type)
65+
for moment in new_circuit:
66+
for op in moment:
67+
assert gateset.is_supported_operation(op)
6068

6169

6270
def test_invalid_input():
63-
with pytest.raises(ValueError):
64-
q0, q1 = cirq.LineQubit.range(2)
65-
circuit = cirq.Circuit(
66-
cirq.CZ(q0, q1), cirq.X(q0) ** 0.2, cirq.Z(q1) ** 0.2, cirq.measure(q0, q1, key='m')
67-
)
68-
_ = cg.optimized_for_sycamore(circuit, optimizer_type='for_tis_100')
71+
with cirq.testing.assert_deprecated(
72+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=1
73+
):
74+
with pytest.raises(ValueError):
75+
q0, q1 = cirq.LineQubit.range(2)
76+
circuit = cirq.Circuit(
77+
cirq.CZ(q0, q1), cirq.X(q0) ** 0.2, cirq.Z(q1) ** 0.2, cirq.measure(q0, q1, key='m')
78+
)
79+
_ = cg.optimized_for_sycamore(circuit, optimizer_type='for_tis_100')
6980

7081

7182
def test_tabulation():
@@ -74,53 +85,67 @@ def test_tabulation():
7485
circuit = cirq.Circuit(cirq.MatrixGate(u).on(q0, q1))
7586
np.testing.assert_allclose(u, cirq.unitary(circuit))
7687

77-
circuit2 = cg.optimized_for_sycamore(circuit, optimizer_type='sycamore')
78-
cirq.testing.assert_allclose_up_to_global_phase(u, cirq.unitary(circuit2), atol=1e-5)
79-
assert len(circuit2) == 13
80-
81-
# Note this is run on every commit, so it needs to be relatively quick.
82-
# This requires us to use relatively loose tolerances
83-
circuit3 = cg.optimized_for_sycamore(
84-
circuit, optimizer_type='sycamore', tabulation_resolution=0.1
85-
)
86-
cirq.testing.assert_allclose_up_to_global_phase(u, cirq.unitary(circuit3), rtol=1e-1, atol=1e-1)
87-
assert len(circuit3) == 7
88+
with cirq.testing.assert_deprecated(
89+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2
90+
):
91+
circuit2 = cg.optimized_for_sycamore(circuit, optimizer_type='sycamore')
92+
cirq.testing.assert_allclose_up_to_global_phase(u, cirq.unitary(circuit2), atol=1e-5)
93+
assert len(circuit2) == 13
94+
# Note this is run on every commit, so it needs to be relatively quick.
95+
# This requires us to use relatively loose tolerances
96+
circuit3 = cg.optimized_for_sycamore(
97+
circuit, optimizer_type='sycamore', tabulation_resolution=0.1
98+
)
99+
cirq.testing.assert_allclose_up_to_global_phase(
100+
u, cirq.unitary(circuit3), rtol=1e-1, atol=1e-1
101+
)
102+
assert len(circuit3) == 7
88103

89104

90105
def test_no_tabulation():
91106
circuit = cirq.Circuit(cirq.X(cirq.LineQubit(0)))
92-
with pytest.raises(NotImplementedError):
93-
cg.optimized_for_sycamore(circuit, optimizer_type='sqrt_iswap', tabulation_resolution=0.01)
94107

95-
with pytest.raises(NotImplementedError):
96-
cg.optimized_for_sycamore(circuit, optimizer_type='xmon', tabulation_resolution=0.01)
108+
with cirq.testing.assert_deprecated(
109+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=3
110+
):
111+
with pytest.raises(NotImplementedError):
112+
cg.optimized_for_sycamore(
113+
circuit, optimizer_type='sqrt_iswap', tabulation_resolution=0.01
114+
)
97115

98-
with pytest.raises(NotImplementedError):
99-
cg.optimized_for_sycamore(
100-
circuit, optimizer_type='xmon_partial_cz', tabulation_resolution=0.01
101-
)
116+
with pytest.raises(NotImplementedError):
117+
cg.optimized_for_sycamore(circuit, optimizer_type='xmon', tabulation_resolution=0.01)
118+
119+
with pytest.raises(NotImplementedError):
120+
cg.optimized_for_sycamore(
121+
circuit, optimizer_type='xmon_partial_cz', tabulation_resolution=0.01
122+
)
102123

103124

104125
def test_one_q_matrix_gate():
105126
u = cirq.testing.random_special_unitary(2)
106127
q = cirq.LineQubit(0)
107128
circuit0 = cirq.Circuit(cirq.MatrixGate(u).on(q))
108129
assert len(circuit0) == 1
109-
circuit_iswap = cg.optimized_for_sycamore(circuit0, optimizer_type='sqrt_iswap')
110-
assert len(circuit_iswap) == 1
111-
for moment in circuit_iswap:
112-
for op in moment:
113-
assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op)
114-
# single qubit gates shared between gatesets, so:
115-
assert cg.SYC_GATESET.is_supported_operation(op)
116-
117-
circuit_syc = cg.optimized_for_sycamore(circuit0, optimizer_type='sycamore')
118-
assert len(circuit_syc) == 1
119-
for moment in circuit_iswap:
120-
for op in moment:
121-
assert cg.SYC_GATESET.is_supported_operation(op)
122-
# single qubit gates shared between gatesets, so:
123-
assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op)
130+
131+
with cirq.testing.assert_deprecated(
132+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2
133+
):
134+
circuit_iswap = cg.optimized_for_sycamore(circuit0, optimizer_type='sqrt_iswap')
135+
assert len(circuit_iswap) == 1
136+
for moment in circuit_iswap:
137+
for op in moment:
138+
assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op)
139+
# single qubit gates shared between gatesets, so:
140+
assert cg.SYC_GATESET.is_supported_operation(op)
141+
142+
circuit_syc = cg.optimized_for_sycamore(circuit0, optimizer_type='sycamore')
143+
assert len(circuit_syc) == 1
144+
for moment in circuit_iswap:
145+
for op in moment:
146+
assert cg.SYC_GATESET.is_supported_operation(op)
147+
# single qubit gates shared between gatesets, so:
148+
assert cg.SQRT_ISWAP_GATESET.is_supported_operation(op)
124149

125150

126151
@pytest.mark.parametrize(
@@ -131,20 +156,23 @@ def test_circuit_operation_conversion(optimizer_type, two_qubit_gate_type):
131156
q0, q1 = cirq.LineQubit.range(2)
132157
subcircuit = cirq.FrozenCircuit(cirq.X(q0), cirq.SWAP(q0, q1))
133158
circuit = cirq.Circuit(cirq.CircuitOperation(subcircuit))
134-
converted_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type)
135-
# Verify that the CircuitOperation was preserved.
136-
ops = list(converted_circuit.all_operations())
137-
assert isinstance(ops[0], cirq.CircuitOperation)
138-
# Verify that the contents of the CircuitOperation were optimized.
139-
converted_subcircuit = cg.optimized_for_sycamore(
140-
subcircuit.unfreeze(), optimizer_type=optimizer_type
141-
)
142-
assert len(
143-
[*converted_subcircuit.findall_operations_with_gate_type(two_qubit_gate_type)]
144-
) == len([*ops[0].circuit.findall_operations_with_gate_type(two_qubit_gate_type)])
145-
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
146-
ops[0].circuit, converted_subcircuit, atol=1e-6
147-
)
148-
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
149-
circuit, converted_circuit, atol=1e-6
150-
)
159+
with cirq.testing.assert_deprecated(
160+
'Use `cirq.optimize_for_target_gateset', deadline='v0.16', count=2
161+
):
162+
converted_circuit = cg.optimized_for_sycamore(circuit, optimizer_type=optimizer_type)
163+
# Verify that the CircuitOperation was preserved.
164+
ops = list(converted_circuit.all_operations())
165+
assert isinstance(ops[0], cirq.CircuitOperation)
166+
# Verify that the contents of the CircuitOperation were optimized.
167+
converted_subcircuit = cg.optimized_for_sycamore(
168+
subcircuit.unfreeze(), optimizer_type=optimizer_type
169+
)
170+
assert len(
171+
[*converted_subcircuit.findall_operations_with_gate_type(two_qubit_gate_type)]
172+
) == len([*ops[0].circuit.findall_operations_with_gate_type(two_qubit_gate_type)])
173+
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
174+
ops[0].circuit, converted_subcircuit, atol=1e-6
175+
)
176+
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
177+
circuit, converted_circuit, atol=1e-6
178+
)

cirq-google/cirq_google/optimizers/optimize_for_xmon.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@
1515
from typing import Callable, cast, TYPE_CHECKING
1616

1717
import cirq
18+
from cirq import _compat
1819
from cirq_google.optimizers import optimized_for_sycamore
1920

2021
if TYPE_CHECKING:
2122
import cirq_google
2223

2324

25+
@_compat.deprecated(
26+
deadline='v0.16',
27+
# pylint: disable=line-too-long
28+
fix='Use cirq.optimize_for_target_gateset(circuit, gateset=cirq.CZTargetGateset(atol=tolerance, allow_partial_czs=allow_partial_czs)).',
29+
)
2430
def optimized_for_xmon(
2531
circuit: cirq.Circuit,
2632
qubit_map: Callable[[cirq.Qid], cirq.GridQubit] = lambda e: cast(cirq.GridQubit, e),

cirq-google/cirq_google/optimizers/optimize_for_xmon_test.py

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -28,64 +28,79 @@ def test_swap_field(n: int, d: int):
2828
)
2929
before.append(cirq.measure(*before.all_qubits()))
3030

31-
after = cg.optimized_for_xmon(before)
32-
assert len(after) == d * 4 + 2
33-
if n <= 5:
34-
assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4)
31+
with cirq.testing.assert_deprecated(
32+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2
33+
):
34+
after = cg.optimized_for_xmon(before)
35+
assert len(after) == d * 4 + 2
36+
if n <= 5:
37+
assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4)
3538

3639

3740
def test_ccz():
3841
before = cirq.Circuit(
3942
cirq.CCZ(cirq.GridQubit(5, 5), cirq.GridQubit(5, 6), cirq.GridQubit(5, 7))
4043
)
4144

42-
after = cg.optimized_for_xmon(before)
45+
with cirq.testing.assert_deprecated(
46+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2
47+
):
48+
after = cg.optimized_for_xmon(before)
4349

44-
assert len(after) <= 22
45-
assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4)
50+
assert len(after) <= 22
51+
assert_circuits_with_terminal_measurements_are_equivalent(before, after, atol=1e-4)
4652

4753

4854
def test_remap_qubits():
4955
before = cirq.Circuit([cirq.Moment([cirq.CZ(cirq.LineQubit(0), cirq.LineQubit(1))])])
5056

51-
after = cg.optimized_for_xmon(before, qubit_map=lambda q: cirq.GridQubit(q.x, 0))
57+
with cirq.testing.assert_deprecated(
58+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2
59+
):
60+
after = cg.optimized_for_xmon(before, qubit_map=lambda q: cirq.GridQubit(q.x, 0))
5261

53-
assert after == cirq.Circuit(
54-
[cirq.Moment([cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0))])]
55-
)
62+
assert after == cirq.Circuit(
63+
[cirq.Moment([cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(1, 0))])]
64+
)
5665

5766

5867
def test_dont_allow_partial_czs():
5968
before = cirq.Circuit(
6069
[cirq.Moment([cirq.CZ(cirq.GridQubit(5, 5), cirq.GridQubit(5, 6)) ** 0.5])]
6170
)
6271

63-
after = cg.optimized_for_xmon(before, allow_partial_czs=False)
72+
with cirq.testing.assert_deprecated(
73+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2
74+
):
75+
after = cg.optimized_for_xmon(before, allow_partial_czs=False)
6476

65-
cz_gates = [
66-
op.gate
67-
for op in after.all_operations()
68-
if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate)
69-
]
70-
num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1)
71-
num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1)
72-
assert num_full_cz == 2
73-
assert num_part_cz == 0
77+
cz_gates = [
78+
op.gate
79+
for op in after.all_operations()
80+
if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate)
81+
]
82+
num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1)
83+
num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1)
84+
assert num_full_cz == 2
85+
assert num_part_cz == 0
7486

7587

7688
def test_allow_partial_czs():
7789
before = cirq.Circuit(
7890
[cirq.Moment([cirq.CZ(cirq.GridQubit(5, 5), cirq.GridQubit(5, 6)) ** 0.5])]
7991
)
8092

81-
after = cg.optimized_for_xmon(before, allow_partial_czs=True)
82-
83-
cz_gates = [
84-
op.gate
85-
for op in after.all_operations()
86-
if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate)
87-
]
88-
num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1)
89-
num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1)
90-
assert num_full_cz == 0
91-
assert num_part_cz == 1
93+
with cirq.testing.assert_deprecated(
94+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=2
95+
):
96+
after = cg.optimized_for_xmon(before, allow_partial_czs=True)
97+
98+
cz_gates = [
99+
op.gate
100+
for op in after.all_operations()
101+
if isinstance(op, cirq.GateOperation) and isinstance(op.gate, cirq.CZPowGate)
102+
]
103+
num_full_cz = sum(1 for cz in cz_gates if cz.exponent % 2 == 1)
104+
num_part_cz = sum(1 for cz in cz_gates if cz.exponent % 2 != 1)
105+
assert num_full_cz == 0
106+
assert num_part_cz == 1

examples/advanced/quantum_volume_test.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44

5+
import cirq
56
from examples.advanced import quantum_volume
67

78

@@ -10,7 +11,10 @@ def test_main_loop():
1011
# Keep test from taking a long time by lowering repetitions.
1112
pytest.importorskip("cirq_google")
1213
args = '--num_qubits 5 --depth 5 --num_circuits 1 --routes 3'.split()
13-
quantum_volume.main(**quantum_volume.parse_arguments(args))
14+
with cirq.testing.assert_deprecated(
15+
'Use cirq.optimize_for_target_gateset', deadline='v0.16', count=None
16+
):
17+
quantum_volume.main(**quantum_volume.parse_arguments(args))
1418

1519

1620
def test_parse_args():

0 commit comments

Comments
 (0)