Skip to content

Commit f4d1a50

Browse files
tanujkhattarrht
authored andcommitted
Add cg.SycamoreTargetGateset and deprecate cg.ConvertToSycamoreGates (quantumlib#5054)
- Part of quantumlib#5028 - Follows the new Transformer API quantumlib#4483 - Supports no compile tags NoCompile Tag for optimizers quantumlib#4253
1 parent 9eeb83d commit f4d1a50

File tree

9 files changed

+580
-30
lines changed

9 files changed

+580
-30
lines changed

cirq-google/cirq_google/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
from cirq_google.transformers import (
110110
known_2q_op_to_sycamore_operations,
111111
two_qubit_matrix_to_sycamore_operations,
112+
SycamoreTargetGateset,
112113
)
113114

114115
from cirq_google.serialization import (

cirq-google/cirq_google/json_test_data/spec.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
'WITHOUT_CHI_FLOQUET_PHASED_FSIM_CHARACTERIZATION',
2323
'XmonDevice',
2424
'XMON',
25+
'SycamoreTargetGateset',
2526
],
2627
should_not_be_serialized=[
2728
'AnnealSequenceSearchStrategy',

cirq-google/cirq_google/optimizers/convert_to_sycamore_gates.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
from cirq_google.transformers.analytical_decompositions import two_qubit_to_sycamore
2222

2323

24+
@cirq._compat.deprecated_class(
25+
deadline='v1.0',
26+
fix='Use cirq.optimize_for_target_gateset and cirq_google.SycamoreTargetGateset instead.',
27+
)
2428
class ConvertToSycamoreGates(cirq.PointOptimizer):
2529
"""Attempts to convert non-native gates into SycamoreGates.
2630

cirq-google/cirq_google/optimizers/convert_to_sycamore_gates_test.py

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ def test_convert_to_sycamore_gates_swap_zz():
2727
)
2828

2929
compiled_circuit1 = circuit1.copy()
30-
cgoc.ConvertToSycamoreGates()(compiled_circuit1)
30+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
31+
cgoc.ConvertToSycamoreGates()(compiled_circuit1)
3132
compiled_circuit2 = circuit2.copy()
32-
cgoc.ConvertToSycamoreGates()(compiled_circuit2)
33+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
34+
cgoc.ConvertToSycamoreGates()(compiled_circuit2)
3335

3436
cirq.testing.assert_same_circuits(compiled_circuit1, compiled_circuit2)
3537
assert (
@@ -45,7 +47,8 @@ def test_convert_to_sycamore_gates_fsim():
4547
q0, q1 = cirq.LineQubit.range(2)
4648
circuit = cirq.Circuit(cirq.FSimGate(theta=np.pi / 2, phi=np.pi / 6)(q0, q1))
4749
compiled_circuit = circuit.copy()
48-
cgoc.ConvertToSycamoreGates()(compiled_circuit)
50+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
51+
cgoc.ConvertToSycamoreGates()(compiled_circuit)
4952

5053
cirq.testing.assert_same_circuits(circuit, compiled_circuit)
5154

@@ -56,7 +59,8 @@ def test_single_qubit_gate():
5659
gate = cirq.MatrixGate(mat, qid_shape=(2,))
5760
circuit = cirq.Circuit(gate(q))
5861
converted_circuit = circuit.copy()
59-
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
62+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
63+
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
6064
ops = list(converted_circuit.all_operations())
6165
assert len(ops) == 1
6266
assert isinstance(ops[0].gate, cirq.PhasedXZGate)
@@ -70,7 +74,8 @@ def test_single_qubit_gate_phased_xz():
7074
gate = cirq.PhasedXZGate(axis_phase_exponent=0.2, x_exponent=0.3, z_exponent=0.4)
7175
circuit = cirq.Circuit(gate(q))
7276
converted_circuit = circuit.copy()
73-
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
77+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
78+
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
7479
ops = list(converted_circuit.all_operations())
7580
assert len(ops) == 1
7681
assert ops[0].gate == gate
@@ -80,24 +85,28 @@ def test_circuit_operation_inspection():
8085
q0, q1 = cirq.LineQubit.range(2)
8186
gate = cirq.PhasedXZGate(axis_phase_exponent=0.2, x_exponent=0.3, z_exponent=0.4)
8287
cop = cirq.CircuitOperation(cirq.FrozenCircuit(gate(q0)))
83-
assert cgoc.ConvertToSycamoreGates()._is_native_sycamore_op(cop)
88+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
89+
assert cgoc.ConvertToSycamoreGates()._is_native_sycamore_op(cop)
8490

8591
cop2 = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.SWAP(q0, q1)))
86-
assert not cgoc.ConvertToSycamoreGates()._is_native_sycamore_op(cop2)
92+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
93+
assert not cgoc.ConvertToSycamoreGates()._is_native_sycamore_op(cop2)
8794

8895

8996
def test_circuit_operation_conversion():
9097
q0, q1 = cirq.LineQubit.range(2)
9198
subcircuit = cirq.FrozenCircuit(cirq.X(q0), cirq.SWAP(q0, q1))
9299
circuit = cirq.Circuit(cirq.CircuitOperation(subcircuit))
93100
converted_circuit = circuit.copy()
94-
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
101+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
102+
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
95103
# Verify that the CircuitOperation was preserved.
96104
ops = list(converted_circuit.all_operations())
97105
assert isinstance(ops[0], cirq.CircuitOperation)
98106
# Verify that the contents of the CircuitOperation were optimized.
99107
reconverted_subcircuit = ops[0].circuit.unfreeze().copy()
100-
cgoc.ConvertToSycamoreGates().optimize_circuit(reconverted_subcircuit)
108+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
109+
cgoc.ConvertToSycamoreGates().optimize_circuit(reconverted_subcircuit)
101110
assert ops[0].circuit == reconverted_subcircuit
102111
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
103112
circuit, converted_circuit, atol=1e-8
@@ -111,7 +120,10 @@ class UnknownGate(cirq.testing.TwoQubitGate):
111120
q0, q1 = cirq.LineQubit.range(2)
112121
circuit = cirq.Circuit(UnknownGate()(q0, q1))
113122
with pytest.raises(TypeError, match='gate with a known unitary'):
114-
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)
123+
with cirq.testing.assert_deprecated(
124+
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
125+
):
126+
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)
115127

116128

117129
def test_nested_unsupported_gate():
@@ -123,7 +135,10 @@ class UnknownGate(cirq.testing.TwoQubitGate):
123135
subcircuit = cirq.FrozenCircuit(UnknownGate()(q0, q1))
124136
circuit = cirq.Circuit(cirq.CircuitOperation(subcircuit))
125137
with pytest.raises(TypeError, match='gate with a known unitary'):
126-
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)
138+
with cirq.testing.assert_deprecated(
139+
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
140+
):
141+
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)
127142

128143

129144
def test_unsupported_phased_iswap():
@@ -133,7 +148,8 @@ def test_unsupported_phased_iswap():
133148
q1 = cirq.LineQubit(1)
134149
circuit = cirq.Circuit(cirq.PhasedISwapPowGate(exponent=0.5, phase_exponent=0.33)(q0, q1))
135150
converted_circuit = circuit.copy()
136-
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
151+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
152+
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
137153
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
138154
circuit, converted_circuit, atol=1e-8
139155
)
@@ -155,7 +171,8 @@ def with_qubits(self, *new_qubits):
155171
q0 = cirq.LineQubit(0)
156172
circuit = cirq.Circuit(UnknownOperation([q0]))
157173
converted_circuit = circuit.copy()
158-
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
174+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
175+
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
159176
assert circuit == converted_circuit
160177

161178

@@ -168,7 +185,10 @@ class ThreeQubitGate(cirq.testing.ThreeQubitGate):
168185
q2 = cirq.LineQubit(2)
169186
circuit = cirq.Circuit(ThreeQubitGate()(q0, q1, q2))
170187
with pytest.raises(TypeError):
171-
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)
188+
with cirq.testing.assert_deprecated(
189+
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
190+
):
191+
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)
172192

173193

174194
def random_single_qubit_unitary():
@@ -199,7 +219,10 @@ def test_zztheta_qaoa_like():
199219
]
200220
)
201221
syc_circuit = cirq_circuit.copy()
202-
cgoc.ConvertToSycamoreGates().optimize_circuit(syc_circuit)
222+
with cirq.testing.assert_deprecated(
223+
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
224+
):
225+
cgoc.ConvertToSycamoreGates().optimize_circuit(syc_circuit)
203226

204227
cirq.testing.assert_allclose_up_to_global_phase(
205228
cirq.unitary(cirq_circuit), cirq.unitary(syc_circuit), atol=1e-7
@@ -214,7 +237,8 @@ def test_zztheta_zzpow_unsorted_qubits():
214237
cirq.ZZPowGate(exponent=exponent, global_shift=-0.5).on(qubits[0], qubits[1]),
215238
)
216239
actual_circuit = expected_circuit.copy()
217-
cgoc.ConvertToSycamoreGates().optimize_circuit(actual_circuit)
240+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
241+
cgoc.ConvertToSycamoreGates().optimize_circuit(actual_circuit)
218242

219243
cirq.testing.assert_allclose_up_to_global_phase(
220244
cirq.unitary(expected_circuit), cirq.unitary(actual_circuit), atol=1e-7
@@ -231,15 +255,19 @@ def test_swap_zztheta():
231255
)
232256
expected_unitary = cirq.unitary(expected_circuit)
233257
actual_circuit = expected_circuit.copy()
234-
cgoc.ConvertToSycamoreGates().optimize_circuit(actual_circuit)
258+
with cirq.testing.assert_deprecated(
259+
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
260+
):
261+
cgoc.ConvertToSycamoreGates().optimize_circuit(actual_circuit)
235262
actual_unitary = cirq.unitary(actual_circuit)
236263
cirq.testing.assert_allclose_up_to_global_phase(actual_unitary, expected_unitary, atol=1e-7)
237264

238265

239266
def test_known_two_q_operations_to_sycamore_operations_cnot():
240267
a, b = cirq.LineQubit.range(2)
241268
op = cirq.CNOT(a, b)
242-
decomposed = cirq.Circuit(cgoc.ConvertToSycamoreGates().convert(op))
269+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
270+
decomposed = cirq.Circuit(cgoc.ConvertToSycamoreGates().convert(op))
243271

244272
# Should be equivalent.
245273
cirq.testing.assert_allclose_up_to_global_phase(
@@ -271,7 +299,8 @@ def test_known_two_q_operations_to_sycamore_operations_cnot():
271299
def test_convert_to_sycamore_equivalent_unitaries(gate):
272300
qubits = [cirq.NamedQubit('a'), cirq.NamedQubit('b')]
273301
operation = gate.on(qubits[0], qubits[1])
274-
converted = cgoc.ConvertToSycamoreGates().convert(operation)
302+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
303+
converted = cgoc.ConvertToSycamoreGates().convert(operation)
275304
u1 = cirq.unitary(cirq.Circuit(converted))
276305
u2 = cirq.unitary(operation)
277306
cirq.testing.assert_allclose_up_to_global_phase(u1, u2, atol=1e-8)
@@ -284,7 +313,8 @@ def test_convert_to_sycamore_tabulation():
284313
)
285314
qubits = [cirq.NamedQubit('a'), cirq.NamedQubit('b')]
286315
operation = cirq.MatrixGate(cirq.unitary(cirq.CX), qid_shape=(2, 2)).on(qubits[0], qubits[1])
287-
converted = cgoc.ConvertToSycamoreGates(sycamore_tabulation).convert(operation)
316+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
317+
converted = cgoc.ConvertToSycamoreGates(sycamore_tabulation).convert(operation)
288318
u1 = cirq.unitary(cirq.Circuit(converted))
289319
u2 = cirq.unitary(operation)
290320
overlap = abs(np.trace(u1.conj().T @ u2))
@@ -295,7 +325,10 @@ def test_sycamore_invalid_tabulation():
295325
# An object other than a tabulation.
296326
sycamore_tabulation = {}
297327
with pytest.raises(ValueError):
298-
cgoc.ConvertToSycamoreGates(sycamore_tabulation)
328+
with cirq.testing.assert_deprecated(
329+
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
330+
):
331+
cgoc.ConvertToSycamoreGates(sycamore_tabulation)
299332

300333

301334
q = cirq.GridQubit.rect(1, 3)
@@ -315,4 +348,7 @@ def test_sycamore_invalid_tabulation():
315348
)
316349
def test_supported_operation(op, is_valid):
317350
c = cirq.Circuit(op)
318-
assert (cirq_google.ConvertToSycamoreGates().optimization_at(c, 0, op) is not None) == is_valid
351+
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
352+
assert (
353+
cirq_google.ConvertToSycamoreGates().optimization_at(c, 0, op) is not None
354+
) == is_valid

cirq-google/cirq_google/optimizers/optimize_for_sycamore.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
from cirq_google import ops as cg_ops
2222
from cirq_google.optimizers import (
2323
convert_to_xmon_gates,
24-
ConvertToSycamoreGates,
2524
)
25+
from cirq_google.transformers.target_gatesets import sycamore_gateset
2626

2727
if TYPE_CHECKING:
2828
import cirq_google
@@ -51,20 +51,16 @@ def _get_xmon_optimizers_part_cz(
5151
]
5252

5353

54-
def _get_sycamore_optimizers(
55-
tolerance: float, tabulation: Optional[cirq.TwoQubitGateTabulation]
56-
) -> List[Callable[[cirq.Circuit], None]]:
57-
return [ConvertToSycamoreGates(tabulation=tabulation).optimize_circuit]
58-
59-
6054
_OPTIMIZER_TYPES = {
6155
'xmon': _get_xmon_optimizers,
6256
'xmon_partial_cz': _get_xmon_optimizers_part_cz,
63-
'sycamore': _get_sycamore_optimizers,
6457
}
6558

6659
_TARGET_GATESETS = {
6760
'sqrt_iswap': lambda atol, _: cirq.SqrtIswapTargetGateset(atol=atol),
61+
'sycamore': lambda atol, tabulation: sycamore_gateset.SycamoreTargetGateset(
62+
atol=atol, tabulation=tabulation
63+
),
6864
'xmon': lambda atol, _: cirq.CZTargetGateset(atol=atol),
6965
'xmon_partial_cz': lambda atol, _: cirq.CZTargetGateset(atol=atol, allow_partial_czs=True),
7066
}

cirq-google/cirq_google/transformers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@
1616
known_2q_op_to_sycamore_operations,
1717
two_qubit_matrix_to_sycamore_operations,
1818
)
19+
20+
from cirq_google.transformers.target_gatesets import SycamoreTargetGateset
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2022 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+
"""`cirq.CompilationTargetGateset` implementations for cirq_google gatesets and devices."""
16+
17+
from cirq_google.transformers.target_gatesets.sycamore_gateset import SycamoreTargetGateset

0 commit comments

Comments
 (0)