Skip to content

Deprecate cirq_google.ConvertToXmonGates and replace with cirq.CZTargetGateset + cirq.optimize_for_target_gateset #5029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ def _decompose_single_qubit_operation(
) -> DecomposeResult:
"""Decomposes (connected component of) 1-qubit operations using gates from this gateset.

By default, rewrites every operation using a single `cirq.PhasedXZGate`.
By default, rewrites every operation `op` using a single `cirq.PhasedXZGate` if `op`
is not contained in self or if `op` is a newly merged connected component of operations.

Args:
op: A single-qubit operation (can be a tagged `cirq.CircuitOperation` wrapping
Expand All @@ -197,6 +198,7 @@ def _decompose_single_qubit_operation(
return (
ops.PhasedXZGate.from_matrix(protocols.unitary(op)).on(op.qubits[0])
if protocols.has_unitary(op)
and (op not in self or self._intermediate_result_tag in op.tags)
else NotImplemented
)

Expand Down
6 changes: 5 additions & 1 deletion cirq-core/cirq/transformers/target_gatesets/cz_gateset.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ def __init__(self, *, atol: float = 1e-8, allow_partial_czs: bool = False) -> No
super().__init__(
ops.CZPowGate if allow_partial_czs else ops.CZ,
ops.MeasurementGate,
ops.AnyUnitaryGateFamily(1),
ops.XPowGate,
ops.YPowGate,
ops.ZPowGate,
ops.PhasedXPowGate,
ops.PhasedXZGate,
name='CZPowTargetGateset' if allow_partial_czs else 'CZTargetGateset',
)
self.atol = atol
Expand Down
13 changes: 10 additions & 3 deletions cirq-google/cirq_google/devices/xmon_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

import cirq
from cirq import _compat
from cirq_google.optimizers import convert_to_xmon_gates

if TYPE_CHECKING:
import cirq
Expand Down Expand Up @@ -52,6 +51,7 @@ def __init__(
cirq.XPowGate,
cirq.YPowGate,
cirq.PhasedXPowGate,
cirq.PhasedXZGate,
cirq.MeasurementGate,
cirq.ZPowGate,
),
Expand All @@ -72,10 +72,15 @@ def qubit_set(self) -> FrozenSet[cirq.GridQubit]:

@_compat.deprecated(
deadline='v0.15',
fix='XmonDevice.decompose_operation is deperecated. Please use ConvertToXmonGates().',
fix='XmonDevice.decompose_operation is deprecated. '
'Please use cirq.optimize_for_target_gateset() and cirq.CZTargetGateset.',
)
def decompose_operation(self, operation: cirq.Operation) -> cirq.OP_TREE:
return convert_to_xmon_gates.ConvertToXmonGates().convert(operation)
return [
*cirq.optimize_for_target_gateset(
cirq.Circuit(operation), gateset=cirq.CZTargetGateset(allow_partial_czs=True)
).all_operations()
]

def neighbors_of(self, qubit: cirq.GridQubit):
"""Returns the qubits that the given qubit can interact with."""
Expand Down Expand Up @@ -109,6 +114,7 @@ def is_supported_gate(cls, gate: cirq.Gate):
cirq.XPowGate,
cirq.YPowGate,
cirq.PhasedXPowGate,
cirq.PhasedXZGate,
cirq.MeasurementGate,
cirq.ZPowGate,
),
Expand Down Expand Up @@ -154,6 +160,7 @@ def _check_if_exp11_operation_interacts(
cirq.XPowGate,
cirq.YPowGate,
cirq.PhasedXPowGate,
cirq.PhasedXZGate,
cirq.MeasurementGate,
cirq.ZPowGate,
),
Expand Down
1 change: 1 addition & 0 deletions cirq-google/cirq_google/devices/xmon_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def test_device_metadata():
cirq.XPowGate,
cirq.YPowGate,
cirq.PhasedXPowGate,
cirq.PhasedXZGate,
cirq.MeasurementGate,
cirq.ZPowGate,
)
Expand Down
4 changes: 4 additions & 0 deletions cirq-google/cirq_google/optimizers/convert_to_xmon_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import cirq


@cirq._compat.deprecated_class(
deadline='v1.0',
fix='Use cirq.optimize_for_target_gateset and cirq.CZTargetGateset instead.',
)
class ConvertToXmonGates(cirq.PointOptimizer):
"""Attempts to convert strange gates into XmonGates.

Expand Down
12 changes: 9 additions & 3 deletions cirq-google/cirq_google/optimizers/convert_to_xmon_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ class NonNativeGate(cirq.SingleQubitGate):
def test_avoids_infinite_cycle_when_matrix_available():
q = cirq.GridQubit(0, 0)
c = cirq.Circuit(OtherX().on(q), OtherOtherX().on(q))
cirq_google.ConvertToXmonGates().optimize_circuit(c)
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
cirq_google.ConvertToXmonGates().optimize_circuit(c)
cirq.testing.assert_has_diagram(c, '(0, 0): ───PhX(1)───PhX(1)───')

cirq.protocols.decompose(c)


Expand All @@ -52,7 +54,10 @@ def test_avoids_infinite_cycle_when_matrix_available():
def test_bad_operation():
c = cirq.Circuit(NonNativeGate().on(q[0]))
with pytest.raises(TypeError):
cirq_google.ConvertToXmonGates().optimize_circuit(c)
with cirq.testing.assert_deprecated(
"Use cirq.optimize_for_target_gateset", deadline='v1.0'
):
cirq_google.ConvertToXmonGates().optimize_circuit(c)


@pytest.mark.parametrize(
Expand All @@ -68,4 +73,5 @@ def test_bad_operation():
)
def test_supported_operation(op, is_valid):
c = cirq.Circuit(op)
assert (cirq_google.ConvertToXmonGates().optimization_at(c, 0, op) is not None) == is_valid
with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
assert (cirq_google.ConvertToXmonGates().optimization_at(c, 0, op) is not None) == is_valid
47 changes: 13 additions & 34 deletions cirq-google/cirq_google/optimizers/optimize_for_sycamore.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import cirq
from cirq_google import ops as cg_ops
from cirq_google.optimizers import (
convert_to_xmon_gates,
ConvertToSycamoreGates,
ConvertToSqrtIswapGates,
)
Expand All @@ -29,29 +28,6 @@
import cirq_google


def _get_xmon_optimizers(
tolerance: float, tabulation: Optional[cirq.TwoQubitGateTabulation]
) -> List[Callable[[cirq.Circuit], None]]:
if tabulation is not None:
# coverage: ignore
raise ValueError("Gate tabulation not supported for xmon")

return [
convert_to_xmon_gates.ConvertToXmonGates().optimize_circuit,
]


def _get_xmon_optimizers_part_cz(
tolerance: float, tabulation: Optional[cirq.TwoQubitGateTabulation]
) -> List[Callable[[cirq.Circuit], None]]:
if tabulation is not None:
# coverage: ignore
raise ValueError("Gate tabulation not supported for xmon")
return [
convert_to_xmon_gates.ConvertToXmonGates().optimize_circuit,
]


def _get_sycamore_optimizers(
tolerance: float, tabulation: Optional[cirq.TwoQubitGateTabulation]
) -> List[Callable[[cirq.Circuit], None]]:
Expand All @@ -68,12 +44,15 @@ def _get_sqrt_iswap_optimizers(


_OPTIMIZER_TYPES = {
'xmon': _get_xmon_optimizers,
'xmon_partial_cz': _get_xmon_optimizers_part_cz,
'sqrt_iswap': _get_sqrt_iswap_optimizers,
'sycamore': _get_sycamore_optimizers,
}

_TARGET_GATESETS = {
'xmon': lambda atol, _: cirq.CZTargetGateset(atol=atol),
'xmon_partial_cz': lambda atol, _: cirq.CZTargetGateset(atol=atol, allow_partial_czs=True),
}


@lru_cache()
def _gate_product_tabulation_cached(
Expand Down Expand Up @@ -131,7 +110,7 @@ def optimized_for_sycamore(
ValueError: If the `optimizer_type` is not a supported type.
"""
copy = circuit.copy()
if optimizer_type not in _OPTIMIZER_TYPES:
if optimizer_type not in _OPTIMIZER_TYPES and optimizer_type not in _TARGET_GATESETS:
raise ValueError(
f'{optimizer_type} is not an allowed type. Allowed '
f'types are: {_OPTIMIZER_TYPES.keys()}'
Expand All @@ -141,16 +120,16 @@ def optimized_for_sycamore(
if tabulation_resolution is not None:
tabulation = _gate_product_tabulation_cached(optimizer_type, tabulation_resolution)

opts = _OPTIMIZER_TYPES[optimizer_type](tolerance=tolerance, tabulation=tabulation)
for optimizer in opts:
optimizer(copy)
if optimizer_type.startswith('xmon'):
if optimizer_type in _TARGET_GATESETS:
copy = cirq.optimize_for_target_gateset(
circuit,
gateset=cirq.CZTargetGateset(
atol=tolerance, allow_partial_czs=optimizer_type.endswith('partial_cz')
),
gateset=_TARGET_GATESETS[optimizer_type](tolerance, tabulation),
)
if optimizer_type in _OPTIMIZER_TYPES:
opts = _OPTIMIZER_TYPES[optimizer_type](tolerance=tolerance, tabulation=tabulation)
for optimizer in opts:
optimizer(copy)

copy = cirq.merge_single_qubit_gates_to_phxz(copy, atol=tolerance)
copy = cirq.eject_phased_paulis(copy, atol=tolerance)
copy = cirq.eject_z(copy, atol=tolerance)
Expand Down