From a6e6d7802866bdef0d9dd80c5f48386b988ec3b1 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 17:15:40 -0700 Subject: [PATCH 01/23] Deprecate Gateset.accept_global_phase_op --- cirq-core/cirq/ops/gateset.py | 25 +++++++++++-- cirq-core/cirq/ops/gateset_test.py | 60 +++++++++++++++++------------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 43ef71026ee..7d69b32b150 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -16,7 +16,7 @@ from typing import Any, Callable, cast, Dict, FrozenSet, List, Optional, Type, TYPE_CHECKING, Union from cirq.ops import global_phase_op, op_tree, raw_types -from cirq import protocols, value +from cirq import _compat, protocols, value if TYPE_CHECKING: import cirq @@ -201,6 +201,12 @@ class Gateset: validation purposes. """ + @_compat.deprecated_parameter( + deadline='v0.16', + fix='Add a global phase gate to the Gateset', + parameter_desc='ignore_global_phase', + match=lambda args, kwargs: 'accept_global_phase_op' in kwargs, + ) def __init__( self, *gates: Union[Type[raw_types.Gate], raw_types.Gate, GateFamily], @@ -225,7 +231,7 @@ def __init__( name: (Optional) Name for the Gateset. Useful for description. unroll_circuit_op: If True, `cirq.CircuitOperation` is recursively validated by validating the underlying `cirq.Circuit`. - accept_global_phase_op: If True, `cirq.GlobalPhaseOperation` is accepted. + accept_global_phase_op: If True, `cirq.GlobalPhaseGate` is accepted. """ self._name = name self._unroll_circuit_op = unroll_circuit_op @@ -253,6 +259,12 @@ def name(self) -> Optional[str]: def gates(self) -> FrozenSet[GateFamily]: return self._gates + @_compat.deprecated_parameter( + deadline='v0.16', + fix='Add a global phase gate to the Gateset', + parameter_desc='ignore_global_phase', + match=lambda args, kwargs: 'accept_global_phase_op' in kwargs, + ) def with_params( self, *, @@ -287,11 +299,18 @@ def val_if_none(var: Any, val: Any) -> Any: and accept_global_phase_op == self._accept_global_phase_op ): return self + accept_global_phase = cast(bool, accept_global_phase_op) + if not accept_global_phase: + return Gateset( + *self.gates, + name=name, + unroll_circuit_op=cast(bool, unroll_circuit_op), + accept_global_phase_op=False, + ) return Gateset( *self.gates, name=name, unroll_circuit_op=cast(bool, unroll_circuit_op), - accept_global_phase_op=cast(bool, accept_global_phase_op), ) def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool: diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index 5bfc0c786d1..5482cba74a4 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -204,7 +204,8 @@ def test_gateset_init(): def test_gateset_repr_and_str(): - cirq.testing.assert_equivalent_repr(gateset) + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=3): + cirq.testing.assert_equivalent_repr(gateset) assert gateset.name in str(gateset) for gate_family in gateset.gates: assert str(gate_family) in str(gateset) @@ -263,23 +264,27 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): assert gateset.validate(item) is result op_tree = [*get_ops(use_circuit_op, use_global_phase)] - assert_validate_and_contains_consistent( - gateset.with_params( - unroll_circuit_op=use_circuit_op, - accept_global_phase_op=use_global_phase, - ), - op_tree, - True, - ) - if use_circuit_op or use_global_phase: + with cirq.testing.assert_deprecated( + 'global phase', deadline='v0.16', count=1 if use_global_phase else 2 + ): assert_validate_and_contains_consistent( gateset.with_params( - unroll_circuit_op=False, - accept_global_phase_op=False, + unroll_circuit_op=use_circuit_op, + accept_global_phase_op=use_global_phase, ), op_tree, - False, + True, ) + if use_circuit_op or use_global_phase: + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): + assert_validate_and_contains_consistent( + gateset.with_params( + unroll_circuit_op=False, + accept_global_phase_op=False, + ), + op_tree, + False, + ) def test_gateset_validate_circuit_op_negative_reps(): @@ -291,17 +296,19 @@ def test_gateset_validate_circuit_op_negative_reps(): def test_with_params(): assert gateset.with_params() is gateset - assert ( - gateset.with_params( - name=gateset.name, - unroll_circuit_op=gateset._unroll_circuit_op, - accept_global_phase_op=gateset._accept_global_phase_op, + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=1): + assert ( + gateset.with_params( + name=gateset.name, + unroll_circuit_op=gateset._unroll_circuit_op, + accept_global_phase_op=gateset._accept_global_phase_op, + ) + is gateset + ) + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): + gateset_with_params = gateset.with_params( + name='new name', unroll_circuit_op=False, accept_global_phase_op=False ) - is gateset - ) - gateset_with_params = gateset.with_params( - name='new name', unroll_circuit_op=False, accept_global_phase_op=False - ) assert gateset_with_params.name == 'new name' assert gateset_with_params._unroll_circuit_op is False assert gateset_with_params._accept_global_phase_op is False @@ -313,9 +320,10 @@ def test_gateset_eq(): eq.add_equality_group(cirq.Gateset(CustomX**3)) eq.add_equality_group(cirq.Gateset(CustomX, name='Custom Gateset')) eq.add_equality_group(cirq.Gateset(CustomX, name='Custom Gateset', unroll_circuit_op=False)) - eq.add_equality_group( - cirq.Gateset(CustomX, name='Custom Gateset', accept_global_phase_op=False) - ) + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=1): + eq.add_equality_group( + cirq.Gateset(CustomX, name='Custom Gateset', accept_global_phase_op=False) + ) eq.add_equality_group( cirq.Gateset( cirq.GateFamily(CustomX, name='custom_name', description='custom_description'), From 679a4b2c15b40f563aea5a2eb13ec42889f55891 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 19:57:21 -0700 Subject: [PATCH 02/23] Change gateset accept_global_phase_op default to False. --- cirq-core/cirq/ops/gateset.py | 6 +++--- cirq-core/cirq/ops/gateset_test.py | 12 ++++++------ cirq-ionq/cirq_ionq/ionq_devices.py | 1 - 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 7d69b32b150..1d4d11ab036 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -212,7 +212,7 @@ def __init__( *gates: Union[Type[raw_types.Gate], raw_types.Gate, GateFamily], name: Optional[str] = None, unroll_circuit_op: bool = True, - accept_global_phase_op: bool = True, + accept_global_phase_op: bool = False, ) -> None: """Init Gateset. @@ -300,12 +300,12 @@ def val_if_none(var: Any, val: Any) -> Any: ): return self accept_global_phase = cast(bool, accept_global_phase_op) - if not accept_global_phase: + if accept_global_phase: return Gateset( *self.gates, name=name, unroll_circuit_op=cast(bool, unroll_circuit_op), - accept_global_phase_op=False, + accept_global_phase_op=True, ) return Gateset( *self.gates, diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index 5482cba74a4..e415d5d8910 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -265,7 +265,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): op_tree = [*get_ops(use_circuit_op, use_global_phase)] with cirq.testing.assert_deprecated( - 'global phase', deadline='v0.16', count=1 if use_global_phase else 2 + 'global phase', deadline='v0.16', count=2 if use_global_phase else 1 ): assert_validate_and_contains_consistent( gateset.with_params( @@ -276,7 +276,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): True, ) if use_circuit_op or use_global_phase: - with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): assert_validate_and_contains_consistent( gateset.with_params( unroll_circuit_op=False, @@ -296,7 +296,7 @@ def test_gateset_validate_circuit_op_negative_reps(): def test_with_params(): assert gateset.with_params() is gateset - with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=1): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): assert ( gateset.with_params( name=gateset.name, @@ -305,7 +305,7 @@ def test_with_params(): ) is gateset ) - with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): gateset_with_params = gateset.with_params( name='new name', unroll_circuit_op=False, accept_global_phase_op=False ) @@ -320,9 +320,9 @@ def test_gateset_eq(): eq.add_equality_group(cirq.Gateset(CustomX**3)) eq.add_equality_group(cirq.Gateset(CustomX, name='Custom Gateset')) eq.add_equality_group(cirq.Gateset(CustomX, name='Custom Gateset', unroll_circuit_op=False)) - with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=1): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): eq.add_equality_group( - cirq.Gateset(CustomX, name='Custom Gateset', accept_global_phase_op=False) + cirq.Gateset(CustomX, name='Custom Gateset', accept_global_phase_op=True) ) eq.add_equality_group( cirq.Gateset( diff --git a/cirq-ionq/cirq_ionq/ionq_devices.py b/cirq-ionq/cirq_ionq/ionq_devices.py index 5f42cbe8f43..cc906e91a91 100644 --- a/cirq-ionq/cirq_ionq/ionq_devices.py +++ b/cirq-ionq/cirq_ionq/ionq_devices.py @@ -31,7 +31,6 @@ cirq.ZZPowGate, cirq.MeasurementGate, unroll_circuit_op=False, - accept_global_phase_op=False, ) From 4d953cc677b9aa252e8afec56f87672d5b213e41 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 20:11:19 -0700 Subject: [PATCH 03/23] Fix up uses of Gateset for the breaking GlobalPhaseGate change --- cirq-core/cirq/ion/ion_device.py | 1 - cirq-core/cirq/neutral_atoms/neutral_atom_devices.py | 3 --- cirq-core/cirq/optimizers/convert_to_cz_and_single_gates.py | 1 + cirq-core/cirq/optimizers/merge_interactions.py | 2 +- cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py | 2 +- cirq-pasqal/cirq_pasqal/pasqal_device.py | 1 - 6 files changed, 3 insertions(+), 7 deletions(-) diff --git a/cirq-core/cirq/ion/ion_device.py b/cirq-core/cirq/ion/ion_device.py index ea40d1193d2..5c663a1a9f0 100644 --- a/cirq-core/cirq/ion/ion_device.py +++ b/cirq-core/cirq/ion/ion_device.py @@ -30,7 +30,6 @@ def get_ion_gateset() -> ops.Gateset: ops.ZPowGate, ops.PhasedXPowGate, unroll_circuit_op=False, - accept_global_phase_op=False, ) diff --git a/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py b/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py index 166d347803d..add0fd9a13f 100644 --- a/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py +++ b/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py @@ -44,7 +44,6 @@ def neutral_atom_gateset(max_parallel_z=None, max_parallel_xy=None): ops.MeasurementGate, ops.IdentityGate, unroll_circuit_op=False, - accept_global_phase_op=False, ) @@ -100,7 +99,6 @@ def __init__( ops.ParallelGateFamily(ops.YPowGate), ops.ParallelGateFamily(ops.PhasedXPowGate), unroll_circuit_op=False, - accept_global_phase_op=False, ) self.controlled_gateset = ops.Gateset( ops.AnyIntegerPowerGateFamily(ops.CNotPowGate), @@ -108,7 +106,6 @@ def __init__( ops.AnyIntegerPowerGateFamily(ops.CZPowGate), ops.AnyIntegerPowerGateFamily(ops.CCZPowGate), unroll_circuit_op=False, - accept_global_phase_op=False, ) self.gateset = neutral_atom_gateset(max_parallel_z, max_parallel_xy) for q in qubits: diff --git a/cirq-core/cirq/optimizers/convert_to_cz_and_single_gates.py b/cirq-core/cirq/optimizers/convert_to_cz_and_single_gates.py index fcb4aba75e5..ea51b987286 100644 --- a/cirq-core/cirq/optimizers/convert_to_cz_and_single_gates.py +++ b/cirq-core/cirq/optimizers/convert_to_cz_and_single_gates.py @@ -51,6 +51,7 @@ def __init__(self, ignore_failures: bool = False, allow_partial_czs: bool = Fals ops.CZPowGate if allow_partial_czs else ops.CZ, ops.MeasurementGate, ops.AnyUnitaryGateFamily(1), + ops.GlobalPhaseGate, ) def _decompose_two_qubit_unitaries(self, op: ops.Operation) -> ops.OP_TREE: diff --git a/cirq-core/cirq/optimizers/merge_interactions.py b/cirq-core/cirq/optimizers/merge_interactions.py index 53f13b9dbb9..1feeb36ac17 100644 --- a/cirq-core/cirq/optimizers/merge_interactions.py +++ b/cirq-core/cirq/optimizers/merge_interactions.py @@ -238,8 +238,8 @@ def __init__( self.allow_partial_czs = allow_partial_czs self.gateset = ops.Gateset( ops.CZPowGate if allow_partial_czs else ops.CZ, + ops.GlobalPhaseGate, unroll_circuit_op=False, - accept_global_phase_op=True, ) def _may_keep_old_op(self, old_op: 'cirq.Operation') -> bool: diff --git a/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py b/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py index 0dcb44b9996..42472dcab73 100644 --- a/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py +++ b/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py @@ -76,8 +76,8 @@ def __init__( self.use_sqrt_iswap_inv = use_sqrt_iswap_inv self.gateset = ops.Gateset( ops.SQRT_ISWAP_INV if use_sqrt_iswap_inv else ops.SQRT_ISWAP, + ops.GlobalPhaseGate, unroll_circuit_op=False, - accept_global_phase_op=True, ) def _may_keep_old_op(self, old_op: 'cirq.Operation') -> bool: diff --git a/cirq-pasqal/cirq_pasqal/pasqal_device.py b/cirq-pasqal/cirq_pasqal/pasqal_device.py index b97c951cd94..8863f97c8fb 100644 --- a/cirq-pasqal/cirq_pasqal/pasqal_device.py +++ b/cirq-pasqal/cirq_pasqal/pasqal_device.py @@ -76,7 +76,6 @@ def __init__(self, qubits: Sequence[cirq.Qid]) -> None: cirq.IdentityGate, cirq.MeasurementGate, unroll_circuit_op=False, - accept_global_phase_op=False, ) self.qubits = qubits self._metadata = cirq.DeviceMetadata( From 4d8bff08cc54595c63fc83143fd8650cb537cd35 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 20:42:46 -0700 Subject: [PATCH 04/23] Fix allow fallback to checking for GlobalPhaseGate in gateset --- cirq-core/cirq/ops/gateset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 1d4d11ab036..4157030ab82 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -345,8 +345,8 @@ def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool g = item if isinstance(item, raw_types.Gate) else item.gate assert g is not None, f'`item`: {item} must be a gate or have a valid `item.gate`' - if isinstance(g, global_phase_op.GlobalPhaseGate): - return self._accept_global_phase_op + if isinstance(g, global_phase_op.GlobalPhaseGate) and self._accept_global_phase_op: + return True if g in self._instance_gate_families: assert item in self._instance_gate_families[g], ( From 5489cbb885fb590c19666f3ba935627e41cb00b7 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 21:07:36 -0700 Subject: [PATCH 05/23] Fix json --- cirq-core/cirq/ops/gateset.py | 29 ++++++++++++++----- cirq-core/cirq/ops/gateset_test.py | 3 +- .../protocols/json_test_data/Gateset.json | 3 +- .../protocols/json_test_data/Gateset.repr | 1 - .../json_test_data/GridDeviceMetadata.json | 3 +- .../cirq/protocols/json_test_data/spec.py | 1 + 6 files changed, 26 insertions(+), 14 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 4157030ab82..6e9a5827e68 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -232,6 +232,10 @@ def __init__( unroll_circuit_op: If True, `cirq.CircuitOperation` is recursively validated by validating the underlying `cirq.Circuit`. accept_global_phase_op: If True, `cirq.GlobalPhaseGate` is accepted. + If False, `cirq.GlobalPhaseGate` will still be accepted if it + appears in the `gates` parameter. This parameter defaults to + False (a breaking change from v0.15) and is currently being + deprecated. """ self._name = name self._unroll_circuit_op = unroll_circuit_op @@ -425,13 +429,16 @@ def _value_equality_values_(self) -> Any: def __repr__(self) -> str: name_str = f'name = "{self.name}", ' if self.name is not None else '' - return ( + data = ( f'cirq.Gateset(' f'{self._gates_repr_str}, ' f'{name_str}' - f'unroll_circuit_op = {self._unroll_circuit_op},' - f'accept_global_phase_op = {self._accept_global_phase_op})' + f'unroll_circuit_op = {self._unroll_circuit_op}' ) + if self._accept_global_phase_op: + data += 'accept_global_phase_op = True' + data += ')' + return data def __str__(self) -> str: header = 'Gateset: ' @@ -440,20 +447,28 @@ def __str__(self) -> str: return f'{header}\n' + "\n\n".join([str(g) for g in self._unique_gate_list]) def _json_dict_(self) -> Dict[str, Any]: - return { + data = { 'gates': self._unique_gate_list, 'name': self.name, 'unroll_circuit_op': self._unroll_circuit_op, - 'accept_global_phase_op': self._accept_global_phase_op, } + if self._accept_global_phase_op: + data['accept_global_phase_op'] = True + return data @classmethod def _from_json_dict_( - cls, gates, name, unroll_circuit_op, accept_global_phase_op, **kwargs + cls, gates, name, unroll_circuit_op, **kwargs ) -> 'Gateset': + if 'accept_global_phase_op' in kwargs and kwargs['accept_global_phase_op']: + return cls( + *gates, + name=name, + unroll_circuit_op=unroll_circuit_op, + accept_global_phase_op=True, + ) return cls( *gates, name=name, unroll_circuit_op=unroll_circuit_op, - accept_global_phase_op=accept_global_phase_op, ) diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index e415d5d8910..bccb244a020 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -204,8 +204,7 @@ def test_gateset_init(): def test_gateset_repr_and_str(): - with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=3): - cirq.testing.assert_equivalent_repr(gateset) + cirq.testing.assert_equivalent_repr(gateset) assert gateset.name in str(gateset) for gate_family in gateset.gates: assert str(gate_family) in str(gateset) diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.json b/cirq-core/cirq/protocols/json_test_data/Gateset.json index f1cd717ece7..6f98a9f8c30 100644 --- a/cirq-core/cirq/protocols/json_test_data/Gateset.json +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.json @@ -56,7 +56,6 @@ } ], "name": "Custom Name", - "unroll_circuit_op": false, - "accept_global_phase_op": false + "unroll_circuit_op": false } ] \ No newline at end of file diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.repr b/cirq-core/cirq/protocols/json_test_data/Gateset.repr index 3300034588d..b805a1a04fc 100644 --- a/cirq-core/cirq/protocols/json_test_data/Gateset.repr +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.repr @@ -12,6 +12,5 @@ cirq.AnyUnitaryGateFamily(num_qubits=2), name="Custom Name", unroll_circuit_op=False, - accept_global_phase_op=False, ), ] diff --git a/cirq-core/cirq/protocols/json_test_data/GridDeviceMetadata.json b/cirq-core/cirq/protocols/json_test_data/GridDeviceMetadata.json index ec46060bf59..2f17bc263e4 100644 --- a/cirq-core/cirq/protocols/json_test_data/GridDeviceMetadata.json +++ b/cirq-core/cirq/protocols/json_test_data/GridDeviceMetadata.json @@ -112,8 +112,7 @@ } ], "name": null, - "unroll_circuit_op": true, - "accept_global_phase_op": true + "unroll_circuit_op": true }, "gate_durations": [ [ diff --git a/cirq-core/cirq/protocols/json_test_data/spec.py b/cirq-core/cirq/protocols/json_test_data/spec.py index 20595dd03bb..0a992167c11 100644 --- a/cirq-core/cirq/protocols/json_test_data/spec.py +++ b/cirq-core/cirq/protocols/json_test_data/spec.py @@ -191,6 +191,7 @@ deprecated={ 'GlobalPhaseOperation': 'v0.16', 'SymmetricalQidPair': 'v0.15', + 'Gateset': 'v0.16', }, tested_elsewhere=[ # SerializableByKey does not follow common serialization rules. From eb0527dfbef3d9d313885482455c92dadbd2188e Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 21:08:34 -0700 Subject: [PATCH 06/23] format --- cirq-core/cirq/ops/gateset.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 6e9a5827e68..4daa05dd539 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -457,9 +457,7 @@ def _json_dict_(self) -> Dict[str, Any]: return data @classmethod - def _from_json_dict_( - cls, gates, name, unroll_circuit_op, **kwargs - ) -> 'Gateset': + def _from_json_dict_(cls, gates, name, unroll_circuit_op, **kwargs) -> 'Gateset': if 'accept_global_phase_op' in kwargs and kwargs['accept_global_phase_op']: return cls( *gates, From c463a0c7ea49bc81ca8eaced4a409993878518c6 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 23:11:56 -0700 Subject: [PATCH 07/23] Physically add a GlobalPhaseGate if allow_global_phase is True, rework logic around that --- cirq-core/cirq/ops/gateset.py | 51 ++++++------------- cirq-core/cirq/ops/gateset_test.py | 7 +-- .../protocols/json_test_data/Gateset.json | 3 +- .../protocols/json_test_data/Gateset.repr | 1 - .../cirq/protocols/json_test_data/spec.py | 1 - 5 files changed, 19 insertions(+), 44 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 4daa05dd539..a0bfb5d5b9d 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -234,12 +234,13 @@ def __init__( accept_global_phase_op: If True, `cirq.GlobalPhaseGate` is accepted. If False, `cirq.GlobalPhaseGate` will still be accepted if it appears in the `gates` parameter. This parameter defaults to - False (a breaking change from v0.15) and is currently being - deprecated. + False (a breaking change from v0.14) and will be removed in + v0.16. """ self._name = name self._unroll_circuit_op = unroll_circuit_op - self._accept_global_phase_op = accept_global_phase_op + if accept_global_phase_op: + gates = gates + (global_phase_op.GlobalPhaseGate,) self._instance_gate_families: Dict[raw_types.Gate, GateFamily] = {} self._type_gate_families: Dict[Type[raw_types.Gate], GateFamily] = {} self._gates_repr_str = ", ".join([_gate_str(g, repr) for g in gates]) @@ -284,7 +285,9 @@ def with_params( name: New name for the Gateset. unroll_circuit_op: If True, new Gateset will recursively validate `cirq.CircuitOperation` by validating the underlying `cirq.Circuit`. - accept_global_phase_op: If True, new Gateset will accept `cirq.GlobalPhaseOperation`. + accept_global_phase_op: If True, new Gateset will accept `cirq.GlobalPhaseGate`. + False or None have no effect. This parameter is deprecated and will be + removed in v0.16. Returns: `self` if all new values are None or identical to the values of current Gateset. @@ -296,23 +299,17 @@ def val_if_none(var: Any, val: Any) -> Any: name = val_if_none(name, self._name) unroll_circuit_op = val_if_none(unroll_circuit_op, self._unroll_circuit_op) - accept_global_phase_op = val_if_none(accept_global_phase_op, self._accept_global_phase_op) if ( name == self._name and unroll_circuit_op == self._unroll_circuit_op - and accept_global_phase_op == self._accept_global_phase_op + and (global_phase_op.GlobalPhaseGate in self.gates or not accept_global_phase_op) ): return self - accept_global_phase = cast(bool, accept_global_phase_op) - if accept_global_phase: - return Gateset( - *self.gates, - name=name, - unroll_circuit_op=cast(bool, unroll_circuit_op), - accept_global_phase_op=True, - ) + gates = self.gates + if accept_global_phase_op: + gates = gates.union({GateFamily(gate=global_phase_op.GlobalPhaseGate)}) return Gateset( - *self.gates, + *gates, name=name, unroll_circuit_op=cast(bool, unroll_circuit_op), ) @@ -349,9 +346,6 @@ def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool g = item if isinstance(item, raw_types.Gate) else item.gate assert g is not None, f'`item`: {item} must be a gate or have a valid `item.gate`' - if isinstance(g, global_phase_op.GlobalPhaseGate) and self._accept_global_phase_op: - return True - if g in self._instance_gate_families: assert item in self._instance_gate_families[g], ( f"{item} instance matches {self._instance_gate_families[g]} but " @@ -424,21 +418,16 @@ def _value_equality_values_(self) -> Any: self.gates, self.name, self._unroll_circuit_op, - self._accept_global_phase_op, ) def __repr__(self) -> str: name_str = f'name = "{self.name}", ' if self.name is not None else '' - data = ( + return ( f'cirq.Gateset(' f'{self._gates_repr_str}, ' f'{name_str}' - f'unroll_circuit_op = {self._unroll_circuit_op}' + f'unroll_circuit_op = {self._unroll_circuit_op})' ) - if self._accept_global_phase_op: - data += 'accept_global_phase_op = True' - data += ')' - return data def __str__(self) -> str: header = 'Gateset: ' @@ -447,24 +436,16 @@ def __str__(self) -> str: return f'{header}\n' + "\n\n".join([str(g) for g in self._unique_gate_list]) def _json_dict_(self) -> Dict[str, Any]: - data = { + return { 'gates': self._unique_gate_list, 'name': self.name, 'unroll_circuit_op': self._unroll_circuit_op, } - if self._accept_global_phase_op: - data['accept_global_phase_op'] = True - return data @classmethod def _from_json_dict_(cls, gates, name, unroll_circuit_op, **kwargs) -> 'Gateset': if 'accept_global_phase_op' in kwargs and kwargs['accept_global_phase_op']: - return cls( - *gates, - name=name, - unroll_circuit_op=unroll_circuit_op, - accept_global_phase_op=True, - ) + gates = gates + (global_phase_op.GlobalPhaseGate,) return cls( *gates, name=name, diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index bccb244a020..23c8679581b 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -263,9 +263,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): assert gateset.validate(item) is result op_tree = [*get_ops(use_circuit_op, use_global_phase)] - with cirq.testing.assert_deprecated( - 'global phase', deadline='v0.16', count=2 if use_global_phase else 1 - ): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): assert_validate_and_contains_consistent( gateset.with_params( unroll_circuit_op=use_circuit_op, @@ -300,7 +298,7 @@ def test_with_params(): gateset.with_params( name=gateset.name, unroll_circuit_op=gateset._unroll_circuit_op, - accept_global_phase_op=gateset._accept_global_phase_op, + accept_global_phase_op=None, ) is gateset ) @@ -310,7 +308,6 @@ def test_with_params(): ) assert gateset_with_params.name == 'new name' assert gateset_with_params._unroll_circuit_op is False - assert gateset_with_params._accept_global_phase_op is False def test_gateset_eq(): diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.json b/cirq-core/cirq/protocols/json_test_data/Gateset.json index 6f98a9f8c30..b6c4dbfd6c5 100644 --- a/cirq-core/cirq/protocols/json_test_data/Gateset.json +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.json @@ -26,8 +26,7 @@ } ], "name": null, - "unroll_circuit_op": true, - "accept_global_phase_op": true + "unroll_circuit_op": true }, { "cirq_type": "Gateset", diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.repr b/cirq-core/cirq/protocols/json_test_data/Gateset.repr index b805a1a04fc..ab50d1ffd3e 100644 --- a/cirq-core/cirq/protocols/json_test_data/Gateset.repr +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.repr @@ -4,7 +4,6 @@ cirq.AnyUnitaryGateFamily(num_qubits=2), cirq.X, unroll_circuit_op=True, - accept_global_phase_op=True, ), cirq.Gateset( cirq.X, diff --git a/cirq-core/cirq/protocols/json_test_data/spec.py b/cirq-core/cirq/protocols/json_test_data/spec.py index 0a992167c11..20595dd03bb 100644 --- a/cirq-core/cirq/protocols/json_test_data/spec.py +++ b/cirq-core/cirq/protocols/json_test_data/spec.py @@ -191,7 +191,6 @@ deprecated={ 'GlobalPhaseOperation': 'v0.16', 'SymmetricalQidPair': 'v0.15', - 'Gateset': 'v0.16', }, tested_elsewhere=[ # SerializableByKey does not follow common serialization rules. From a5245e958195e986f6d946435a525588b2b1c139 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 23:13:15 -0700 Subject: [PATCH 08/23] fix doc --- cirq-core/cirq/ops/gateset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index a0bfb5d5b9d..cb223ea8417 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -204,7 +204,7 @@ class Gateset: @_compat.deprecated_parameter( deadline='v0.16', fix='Add a global phase gate to the Gateset', - parameter_desc='ignore_global_phase', + parameter_desc='accept_global_phase_op', match=lambda args, kwargs: 'accept_global_phase_op' in kwargs, ) def __init__( @@ -267,7 +267,7 @@ def gates(self) -> FrozenSet[GateFamily]: @_compat.deprecated_parameter( deadline='v0.16', fix='Add a global phase gate to the Gateset', - parameter_desc='ignore_global_phase', + parameter_desc='accept_global_phase_op', match=lambda args, kwargs: 'accept_global_phase_op' in kwargs, ) def with_params( From a7e5c025b7d6b1ec63bcff1acd67fe891023cf45 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 8 Apr 2022 23:37:25 -0700 Subject: [PATCH 09/23] Update docs, add inward files --- cirq-core/cirq/ops/gateset.py | 16 ++--- .../json_test_data/Gateset.json_inward | 62 +++++++++++++++++++ .../json_test_data/Gateset.repr_inward | 15 +++++ 3 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 cirq-core/cirq/protocols/json_test_data/Gateset.json_inward create mode 100644 cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index cb223ea8417..75413cc467d 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -231,11 +231,11 @@ def __init__( name: (Optional) Name for the Gateset. Useful for description. unroll_circuit_op: If True, `cirq.CircuitOperation` is recursively validated by validating the underlying `cirq.Circuit`. - accept_global_phase_op: If True, `cirq.GlobalPhaseGate` is accepted. - If False, `cirq.GlobalPhaseGate` will still be accepted if it - appears in the `gates` parameter. This parameter defaults to - False (a breaking change from v0.14) and will be removed in - v0.16. + accept_global_phase_op: If True, a `GateFamily` accepting + `cirq.GlobalPhaseGate` will be included. If False, + `cirq.GlobalPhaseGate` will still be accepted if it appears in + the `gates` parameter. This parameter defaults to False (a + breaking change from v0.14) and will be removed in v0.16. """ self._name = name self._unroll_circuit_op = unroll_circuit_op @@ -285,9 +285,9 @@ def with_params( name: New name for the Gateset. unroll_circuit_op: If True, new Gateset will recursively validate `cirq.CircuitOperation` by validating the underlying `cirq.Circuit`. - accept_global_phase_op: If True, new Gateset will accept `cirq.GlobalPhaseGate`. - False or None have no effect. This parameter is deprecated and will be - removed in v0.16. + accept_global_phase_op: If True, new Gateset will include a `GateFamily` that accepts + `cirq.GlobalPhaseGate`. False or None have no effect. This parameter is deprecated + and will be removed in v0.16. Returns: `self` if all new values are None or identical to the values of current Gateset. diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward b/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward new file mode 100644 index 00000000000..ad084a30b17 --- /dev/null +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward @@ -0,0 +1,62 @@ +[ + { + "cirq_type": "Gateset", + "gates": [ + { + "cirq_type": "GateFamily", + "gate": "YPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "AnyUnitaryGateFamily", + "num_qubits": 2 + }, + { + "cirq_type": "GateFamily", + "gate": { + "cirq_type": "_PauliX", + "exponent": 1.0, + "global_shift": 0.0 + }, + "name": "Instance GateFamily: X", + "description": "Accepts `cirq.Gate` instances `g` s.t. `g == X`", + "ignore_global_phase": true + } + ], + "name": null, + "unroll_circuit_op": true, + "allow_global_phase_op": true + }, + { + "cirq_type": "Gateset", + "gates": [ + { + "cirq_type": "GateFamily", + "gate": { + "cirq_type": "_PauliX", + "exponent": 1.0, + "global_shift": 0.0 + }, + "name": "Instance GateFamily: X", + "description": "Accepts `cirq.Gate` instances `g` s.t. `g == X`", + "ignore_global_phase": true + }, + { + "cirq_type": "GateFamily", + "gate": "YPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "AnyUnitaryGateFamily", + "num_qubits": 2 + } + ], + "name": "Custom Name", + "unroll_circuit_op": false, + "allow_global_phase_op": false + } +] \ No newline at end of file diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward b/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward new file mode 100644 index 00000000000..ab50d1ffd3e --- /dev/null +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward @@ -0,0 +1,15 @@ +[ + cirq.Gateset( + cirq.ops.common_gates.YPowGate, + cirq.AnyUnitaryGateFamily(num_qubits=2), + cirq.X, + unroll_circuit_op=True, + ), + cirq.Gateset( + cirq.X, + cirq.ops.common_gates.YPowGate, + cirq.AnyUnitaryGateFamily(num_qubits=2), + name="Custom Name", + unroll_circuit_op=False, + ), +] From 7df5e95eb1f96875e5736342800c71f3a7d12ae2 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Sat, 9 Apr 2022 00:12:52 -0700 Subject: [PATCH 10/23] Add json parsing deprecation test --- cirq-core/cirq/ops/gateset.py | 9 ++- cirq-core/cirq/ops/gateset_test.py | 7 +++ .../json_test_data/Gateset.json_inward | 62 ------------------- .../json_test_data/Gateset.repr_inward | 15 ----- 4 files changed, 14 insertions(+), 79 deletions(-) delete mode 100644 cirq-core/cirq/protocols/json_test_data/Gateset.json_inward delete mode 100644 cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 75413cc467d..f25e095ca31 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -444,8 +444,13 @@ def _json_dict_(self) -> Dict[str, Any]: @classmethod def _from_json_dict_(cls, gates, name, unroll_circuit_op, **kwargs) -> 'Gateset': - if 'accept_global_phase_op' in kwargs and kwargs['accept_global_phase_op']: - gates = gates + (global_phase_op.GlobalPhaseGate,) + if 'accept_global_phase_op' in kwargs: + return cls( + *gates, + name=name, + unroll_circuit_op=unroll_circuit_op, + accept_global_phase_op=kwargs['accept_global_phase_op'], + ) return cls( *gates, name=name, diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index 23c8679581b..cfba81690ba 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -346,3 +346,10 @@ def test_gateset_eq(): ) ) ) + + +def test_from_json_allow_global_phase_deprecated(): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): + _ = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=True) + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): + _ = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=False) diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward b/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward deleted file mode 100644 index ad084a30b17..00000000000 --- a/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward +++ /dev/null @@ -1,62 +0,0 @@ -[ - { - "cirq_type": "Gateset", - "gates": [ - { - "cirq_type": "GateFamily", - "gate": "YPowGate", - "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", - "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", - "ignore_global_phase": true - }, - { - "cirq_type": "AnyUnitaryGateFamily", - "num_qubits": 2 - }, - { - "cirq_type": "GateFamily", - "gate": { - "cirq_type": "_PauliX", - "exponent": 1.0, - "global_shift": 0.0 - }, - "name": "Instance GateFamily: X", - "description": "Accepts `cirq.Gate` instances `g` s.t. `g == X`", - "ignore_global_phase": true - } - ], - "name": null, - "unroll_circuit_op": true, - "allow_global_phase_op": true - }, - { - "cirq_type": "Gateset", - "gates": [ - { - "cirq_type": "GateFamily", - "gate": { - "cirq_type": "_PauliX", - "exponent": 1.0, - "global_shift": 0.0 - }, - "name": "Instance GateFamily: X", - "description": "Accepts `cirq.Gate` instances `g` s.t. `g == X`", - "ignore_global_phase": true - }, - { - "cirq_type": "GateFamily", - "gate": "YPowGate", - "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", - "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", - "ignore_global_phase": true - }, - { - "cirq_type": "AnyUnitaryGateFamily", - "num_qubits": 2 - } - ], - "name": "Custom Name", - "unroll_circuit_op": false, - "allow_global_phase_op": false - } -] \ No newline at end of file diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward b/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward deleted file mode 100644 index ab50d1ffd3e..00000000000 --- a/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward +++ /dev/null @@ -1,15 +0,0 @@ -[ - cirq.Gateset( - cirq.ops.common_gates.YPowGate, - cirq.AnyUnitaryGateFamily(num_qubits=2), - cirq.X, - unroll_circuit_op=True, - ), - cirq.Gateset( - cirq.X, - cirq.ops.common_gates.YPowGate, - cirq.AnyUnitaryGateFamily(num_qubits=2), - name="Custom Name", - unroll_circuit_op=False, - ), -] From 144b89794f141f4f944ba3bb01d467dbf6b94885 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Sat, 9 Apr 2022 12:25:10 -0700 Subject: [PATCH 11/23] Add assertions to new test --- cirq-core/cirq/ops/gateset_test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index cfba81690ba..d18c2c67df6 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -350,6 +350,8 @@ def test_gateset_eq(): def test_from_json_allow_global_phase_deprecated(): with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): - _ = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=True) + x = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=True) + assert x.gates == {cirq.GateFamily(cirq.GlobalPhaseGate)} with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): - _ = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=False) + x = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=False) + assert not x.gates From 621e00c172426981dab86a4c03ceb432c4f7b92a Mon Sep 17 00:00:00 2001 From: daxfohl Date: Sat, 9 Apr 2022 20:40:08 -0700 Subject: [PATCH 12/23] minor refactor --- cirq-core/cirq/ops/gateset.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index f25e095ca31..28fcdc8404a 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -299,15 +299,16 @@ def val_if_none(var: Any, val: Any) -> Any: name = val_if_none(name, self._name) unroll_circuit_op = val_if_none(unroll_circuit_op, self._unroll_circuit_op) + global_phase_family = GateFamily(gate=global_phase_op.GlobalPhaseGate) if ( name == self._name and unroll_circuit_op == self._unroll_circuit_op - and (global_phase_op.GlobalPhaseGate in self.gates or not accept_global_phase_op) + and (not accept_global_phase_op or global_phase_family in self.gates) ): return self gates = self.gates if accept_global_phase_op: - gates = gates.union({GateFamily(gate=global_phase_op.GlobalPhaseGate)}) + gates = gates.union({global_phase_family}) return Gateset( *gates, name=name, From 5deea644e0c225845acfc183801937b66dac38bd Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 00:25:42 -0700 Subject: [PATCH 13/23] Force phase gate removal if allow=False' --- cirq-core/cirq/ops/gateset.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 28fcdc8404a..018f29e6480 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -212,7 +212,7 @@ def __init__( *gates: Union[Type[raw_types.Gate], raw_types.Gate, GateFamily], name: Optional[str] = None, unroll_circuit_op: bool = True, - accept_global_phase_op: bool = False, + accept_global_phase_op: Optional[bool] = None, ) -> None: """Init Gateset. @@ -232,9 +232,10 @@ def __init__( unroll_circuit_op: If True, `cirq.CircuitOperation` is recursively validated by validating the underlying `cirq.Circuit`. accept_global_phase_op: If True, a `GateFamily` accepting - `cirq.GlobalPhaseGate` will be included. If False, + `cirq.GlobalPhaseGate` will be included. If None, `cirq.GlobalPhaseGate` will still be accepted if it appears in - the `gates` parameter. This parameter defaults to False (a + the `gates` parameter. If False, `cirq.GlobalPhaseGate` will be + removed from the gates. This parameter defaults to False (a breaking change from v0.14) and will be removed in v0.16. """ self._name = name @@ -247,6 +248,10 @@ def __init__( unique_gate_list: List[GateFamily] = list( dict.fromkeys(g if isinstance(g, GateFamily) else GateFamily(gate=g) for g in gates) ) + if accept_global_phase_op is False: + unique_gate_list = [ + g for g in unique_gate_list if g.gate != global_phase_op.GlobalPhaseGate + ] for g in unique_gate_list: if type(g) == GateFamily: if isinstance(g.gate, raw_types.Gate): @@ -303,7 +308,13 @@ def val_if_none(var: Any, val: Any) -> Any: if ( name == self._name and unroll_circuit_op == self._unroll_circuit_op - and (not accept_global_phase_op or global_phase_family in self.gates) + and ( + accept_global_phase_op is True + and global_phase_family in self.gates + or accept_global_phase_op is False + and global_phase_family not in self.gates + or accept_global_phase_op is None + ) ): return self gates = self.gates From 71015aefba46ce647b84fc403c79ac7b08ed9d87 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 00:42:52 -0700 Subject: [PATCH 14/23] add global phase to gatesets --- cirq-core/cirq/transformers/target_gatesets/cz_gateset.py | 1 + .../transformers/target_gatesets/sqrt_iswap_gateset.py | 1 + cirq-google/cirq_google/devices/serializable_device.py | 7 ++++++- cirq-google/cirq_google/devices/xmon_device.py | 1 + .../transformers/target_gatesets/sycamore_gateset.py | 1 + 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py b/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py index 5fd2d358fd4..c2a2f6ed94a 100644 --- a/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py +++ b/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py @@ -39,6 +39,7 @@ def __init__(self, *, atol: float = 1e-8, allow_partial_czs: bool = False) -> No ops.CZPowGate if allow_partial_czs else ops.CZ, ops.MeasurementGate, ops.AnyUnitaryGateFamily(1), + ops.GlobalPhaseGate, name='CZPowTargetGateset' if allow_partial_czs else 'CZTargetGateset', ) self.atol = atol diff --git a/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py b/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py index 1cfdb556505..2e1fa36f6f7 100644 --- a/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +++ b/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py @@ -55,6 +55,7 @@ def __init__( ops.SQRT_ISWAP_INV if use_sqrt_iswap_inv else ops.SQRT_ISWAP, ops.MeasurementGate, ops.AnyUnitaryGateFamily(1), + ops.GlobalPhaseGate, name='SqrtIswapInvTargetGateset' if use_sqrt_iswap_inv else 'SqrtIswapTargetGateset', ) self.atol = atol diff --git a/cirq-google/cirq_google/devices/serializable_device.py b/cirq-google/cirq_google/devices/serializable_device.py index 03e77714c68..951b75bdce3 100644 --- a/cirq-google/cirq_google/devices/serializable_device.py +++ b/cirq-google/cirq_google/devices/serializable_device.py @@ -118,7 +118,12 @@ def __init__( if len(pair) == 2 and pair[0] < pair[1] ], gateset=cirq.Gateset( - *[g for g in gate_definitions.keys() if isinstance(g, (cirq.Gate, type(cirq.Gate)))] + *[ + g + for g in gate_definitions.keys() + if isinstance(g, (cirq.Gate, type(cirq.Gate))) + ], + cirq.GlobalPhaseGate, ), gate_durations=None, ) diff --git a/cirq-google/cirq_google/devices/xmon_device.py b/cirq-google/cirq_google/devices/xmon_device.py index 87187789fe9..ad8f9a27695 100644 --- a/cirq-google/cirq_google/devices/xmon_device.py +++ b/cirq-google/cirq_google/devices/xmon_device.py @@ -54,6 +54,7 @@ def __init__( cirq.PhasedXZGate, cirq.MeasurementGate, cirq.ZPowGate, + cirq.GlobalPhaseGate, ), None, ) diff --git a/cirq-google/cirq_google/transformers/target_gatesets/sycamore_gateset.py b/cirq-google/cirq_google/transformers/target_gatesets/sycamore_gateset.py index eb262b702ea..fa566b7b95b 100644 --- a/cirq-google/cirq_google/transformers/target_gatesets/sycamore_gateset.py +++ b/cirq-google/cirq_google/transformers/target_gatesets/sycamore_gateset.py @@ -128,6 +128,7 @@ def __init__( cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, + cirq.GlobalPhaseGate, name='SycamoreTargetGateset', ) self.atol = atol From 68d9951ca04efd617f2e971dca97d06f37583781 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 00:48:59 -0700 Subject: [PATCH 15/23] fix tests in google --- cirq-google/cirq_google/devices/serializable_device_test.py | 1 + cirq-google/cirq_google/devices/xmon_device_test.py | 1 + 2 files changed, 2 insertions(+) diff --git a/cirq-google/cirq_google/devices/serializable_device_test.py b/cirq-google/cirq_google/devices/serializable_device_test.py index c19526e239c..195b8fc4ed5 100644 --- a/cirq-google/cirq_google/devices/serializable_device_test.py +++ b/cirq-google/cirq_google/devices/serializable_device_test.py @@ -103,6 +103,7 @@ def test_metadata_correct(): cirq.PhasedXZGate, cirq.MeasurementGate, cirq.WaitGate, + cirq.GlobalPhaseGate, ) diff --git a/cirq-google/cirq_google/devices/xmon_device_test.py b/cirq-google/cirq_google/devices/xmon_device_test.py index 21a656a9152..b9b1413dc66 100644 --- a/cirq-google/cirq_google/devices/xmon_device_test.py +++ b/cirq-google/cirq_google/devices/xmon_device_test.py @@ -55,6 +55,7 @@ def test_device_metadata(): cirq.PhasedXZGate, cirq.MeasurementGate, cirq.ZPowGate, + cirq.GlobalPhaseGate, ) assert d.metadata.qubit_pairs == frozenset( { From 1a1ba13ab947a8670a6f19a712ebf1d6f5515b81 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 08:04:28 -0700 Subject: [PATCH 16/23] fix tests in google --- cirq-google/cirq_google/devices/known_devices_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cirq-google/cirq_google/devices/known_devices_test.py b/cirq-google/cirq_google/devices/known_devices_test.py index 9c932c46ea2..934ab071521 100644 --- a/cirq-google/cirq_google/devices/known_devices_test.py +++ b/cirq-google/cirq_google/devices/known_devices_test.py @@ -504,6 +504,7 @@ def test_sycamore_metadata(): cirq.PhasedXZGate, cirq.MeasurementGate, cirq.WaitGate, + cirq.GlobalPhaseGate, ) From 57a1745d83b986bfcd63cc595bd050431a7fe18e Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 17:11:44 -0700 Subject: [PATCH 17/23] Add warning when default `accept_global_phase_op` --- cirq-core/cirq/ion/ion_device_test.py | 6 +++--- .../cirq/neutral_atoms/neutral_atom_devices_test.py | 4 ++-- cirq-core/cirq/ops/gateset.py | 10 +++++++++- cirq-core/cirq/ops/gateset_test.py | 6 +++--- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/cirq-core/cirq/ion/ion_device_test.py b/cirq-core/cirq/ion/ion_device_test.py index 9d183e21e77..eec92851b6d 100644 --- a/cirq-core/cirq/ion/ion_device_test.py +++ b/cirq-core/cirq/ion/ion_device_test.py @@ -166,7 +166,7 @@ def num_qubits(self): def test_can_add_operation_into_moment_device_deprecated(): - with cirq.testing.assert_deprecated('can_add_operation_into_moment', deadline='v0.15', count=5): + with cirq.testing.assert_deprecated('can_add_operation_into_moment', deadline='v0.15', count=6): d = ion_device(3) q0 = cirq.LineQubit(0) q1 = cirq.LineQubit(1) @@ -218,10 +218,10 @@ def test_at(): def test_qubit_set_deprecated(): - with cirq.testing.assert_deprecated('qubit_set', deadline='v0.15'): + with cirq.testing.assert_deprecated('qubit_set', deadline='v0.15', count=2): assert ion_device(3).qubit_set() == frozenset(cirq.LineQubit.range(3)) def test_qid_pairs_deprecated(): - with cirq.testing.assert_deprecated('device.metadata', deadline='v0.15', count=1): + with cirq.testing.assert_deprecated('device.metadata', deadline='v0.15', count=2): assert len(ion_device(10).qid_pairs()) == 45 diff --git a/cirq-core/cirq/neutral_atoms/neutral_atom_devices_test.py b/cirq-core/cirq/neutral_atoms/neutral_atom_devices_test.py index 1a3d6f0eb86..fc8e37e427a 100644 --- a/cirq-core/cirq/neutral_atoms/neutral_atom_devices_test.py +++ b/cirq-core/cirq/neutral_atoms/neutral_atom_devices_test.py @@ -237,7 +237,7 @@ def test_validate_moment_errors(): def test_can_add_operation_into_moment_coverage_deprecated(): - with cirq.testing.assert_deprecated('can_add_operation_into_moment', deadline='v0.15', count=3): + with cirq.testing.assert_deprecated('can_add_operation_into_moment', deadline='v0.15', count=4): d = square_device(2, 2) q00 = cirq.GridQubit(0, 0) q01 = cirq.GridQubit(0, 1) @@ -298,5 +298,5 @@ def test_repr_pretty(): def test_qubit_set_deprecated(): - with cirq.testing.assert_deprecated('qubit_set', deadline='v0.15'): + with cirq.testing.assert_deprecated('qubit_set', deadline='v0.15', count=2): assert square_device(2, 2).qubit_set() == frozenset(cirq.GridQubit.square(2, 0, 0)) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 018f29e6480..1f141d1b0f6 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -14,9 +14,11 @@ """Functionality for grouping and validating Cirq Gates""" +import warnings from typing import Any, Callable, cast, Dict, FrozenSet, List, Optional, Type, TYPE_CHECKING, Union -from cirq.ops import global_phase_op, op_tree, raw_types + from cirq import _compat, protocols, value +from cirq.ops import global_phase_op, op_tree, raw_types if TYPE_CHECKING: import cirq @@ -252,6 +254,12 @@ def __init__( unique_gate_list = [ g for g in unique_gate_list if g.gate != global_phase_op.GlobalPhaseGate ] + elif accept_global_phase_op is None: + if not any(g.gate is global_phase_op.GlobalPhaseGate for g in unique_gate_list): + warnings.warn( + 'v0.14.1 is the last release `cirq.GlobalPhaseGate` is included by default.' + ) + for g in unique_gate_list: if type(g) == GateFamily: if isinstance(g.gate, raw_types.Gate): diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index d18c2c67df6..031aba152c3 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -263,7 +263,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): assert gateset.validate(item) is result op_tree = [*get_ops(use_circuit_op, use_global_phase)] - with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=None): assert_validate_and_contains_consistent( gateset.with_params( unroll_circuit_op=use_circuit_op, @@ -273,7 +273,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): True, ) if use_circuit_op or use_global_phase: - with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): assert_validate_and_contains_consistent( gateset.with_params( unroll_circuit_op=False, @@ -302,7 +302,7 @@ def test_with_params(): ) is gateset ) - with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): + with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): gateset_with_params = gateset.with_params( name='new name', unroll_circuit_op=False, accept_global_phase_op=False ) From 53fd09593e34d38da0fd8d080abf6aa38161f01c Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 17:16:21 -0700 Subject: [PATCH 18/23] Fix pasqal test --- cirq-pasqal/cirq_pasqal/pasqal_device_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cirq-pasqal/cirq_pasqal/pasqal_device_test.py b/cirq-pasqal/cirq_pasqal/pasqal_device_test.py index 6b97289fa2d..7b4f6120a2f 100644 --- a/cirq-pasqal/cirq_pasqal/pasqal_device_test.py +++ b/cirq-pasqal/cirq_pasqal/pasqal_device_test.py @@ -317,7 +317,7 @@ def test_qid_pairs_deprecated(): ThreeDQubit(1, 1, 1), ], ) - with cirq.testing.assert_deprecated('device.metadata', deadline='v0.15', count=2): + with cirq.testing.assert_deprecated('device.metadata', deadline='v0.15', count=3): assert len(dev.qid_pairs()) == 5 dev1 = PasqalVirtualDevice( 5, From 5aca22318a8d0e9de64cc58615530081e83d3417 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Wed, 13 Apr 2022 17:24:07 -0700 Subject: [PATCH 19/23] format --- cirq-core/cirq/ion/ion_device.py | 13 +++------- .../neutral_atoms/neutral_atom_devices.py | 13 ++-------- cirq-core/cirq/ops/gateset.py | 23 +++------------- cirq-core/cirq/ops/gateset_test.py | 18 +++---------- .../cirq/optimizers/merge_interactions.py | 10 ++----- .../merge_interactions_to_sqrt_iswap.py | 5 +--- .../target_gatesets/cz_gateset.py | 5 +--- .../target_gatesets/sqrt_iswap_gateset.py | 6 +---- cirq-ionq/cirq_ionq/ionq_devices.py | 14 +++------- cirq-pasqal/cirq_pasqal/pasqal_device.py | 18 +++---------- cirq-pasqal/cirq_pasqal/pasqal_device_test.py | 26 +++---------------- 11 files changed, 30 insertions(+), 121 deletions(-) diff --git a/cirq-core/cirq/ion/ion_device.py b/cirq-core/cirq/ion/ion_device.py index 5c663a1a9f0..f43320019e0 100644 --- a/cirq-core/cirq/ion/ion_device.py +++ b/cirq-core/cirq/ion/ion_device.py @@ -78,16 +78,12 @@ def __init__( def metadata(self) -> devices.DeviceMetadata: return self._metadata - @_compat.deprecated( - fix='Use metadata.qubit_set if applicable.', - deadline='v0.15', - ) + @_compat.deprecated(fix='Use metadata.qubit_set if applicable.', deadline='v0.15') def qubit_set(self) -> FrozenSet['cirq.LineQubit']: return self.qubits @_compat.deprecated( - deadline='v0.15', - fix='qubit coupling data can now be found in device.metadata if provided.', + deadline='v0.15', fix='qubit coupling data can now be found in device.metadata if provided.' ) def qid_pairs(self) -> FrozenSet['cirq.SymmetricalQidPair']: """Qubits have all-to-all connectivity, so returns all pairs. @@ -146,10 +142,7 @@ def at(self, position: int) -> Optional[devices.LineQubit]: def neighbors_of(self, qubit: devices.LineQubit) -> Iterable[devices.LineQubit]: """Returns the qubits that the given qubit can interact with.""" - possibles = [ - devices.LineQubit(qubit.x + 1), - devices.LineQubit(qubit.x - 1), - ] + possibles = [devices.LineQubit(qubit.x + 1), devices.LineQubit(qubit.x - 1)] return [e for e in possibles if e in self.qubits] def __repr__(self) -> str: diff --git a/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py b/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py index add0fd9a13f..b09f25b4dd7 100644 --- a/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py +++ b/cirq-core/cirq/neutral_atoms/neutral_atom_devices.py @@ -213,17 +213,8 @@ def validate_moment(self, moment: circuits.Moment): CATEGORIES = { 'Z': (ops.ZPowGate,), - 'XY': ( - ops.XPowGate, - ops.YPowGate, - ops.PhasedXPowGate, - ), - 'controlled': ( - ops.CNotPowGate, - ops.CZPowGate, - ops.CCXPowGate, - ops.CCZPowGate, - ), + 'XY': (ops.XPowGate, ops.YPowGate, ops.PhasedXPowGate), + 'controlled': (ops.CNotPowGate, ops.CZPowGate, ops.CCXPowGate, ops.CCZPowGate), 'measure': (ops.MeasurementGate,), } diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 1f141d1b0f6..fc865502939 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -328,11 +328,7 @@ def val_if_none(var: Any, val: Any) -> Any: gates = self.gates if accept_global_phase_op: gates = gates.union({global_phase_family}) - return Gateset( - *gates, - name=name, - unroll_circuit_op=cast(bool, unroll_circuit_op), - ) + return Gateset(*gates, name=name, unroll_circuit_op=cast(bool, unroll_circuit_op)) def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool: """Check for containment of a given Gate/Operation in this Gateset. @@ -383,10 +379,7 @@ def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool return any(item in gate_family for gate_family in self._gates) - def validate( - self, - circuit_or_optree: Union['cirq.AbstractCircuit', op_tree.OP_TREE], - ) -> bool: + def validate(self, circuit_or_optree: Union['cirq.AbstractCircuit', op_tree.OP_TREE]) -> bool: """Validates gates forming `circuit_or_optree` should be contained in Gateset. Args: @@ -434,11 +427,7 @@ def _validate_operation(self, op: raw_types.Operation) -> bool: return False def _value_equality_values_(self) -> Any: - return ( - self.gates, - self.name, - self._unroll_circuit_op, - ) + return (self.gates, self.name, self._unroll_circuit_op) def __repr__(self) -> str: name_str = f'name = "{self.name}", ' if self.name is not None else '' @@ -471,8 +460,4 @@ def _from_json_dict_(cls, gates, name, unroll_circuit_op, **kwargs) -> 'Gateset' unroll_circuit_op=unroll_circuit_op, accept_global_phase_op=kwargs['accept_global_phase_op'], ) - return cls( - *gates, - name=name, - unroll_circuit_op=unroll_circuit_op, - ) + return cls(*gates, name=name, unroll_circuit_op=unroll_circuit_op) diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index 031aba152c3..668674304be 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -23,10 +23,7 @@ class CustomXPowGate(cirq.EigenGate): def _eigen_components(self) -> List[Tuple[float, np.ndarray]]: - return [ - (0, np.array([[0.5, 0.5], [0.5, 0.5]])), - (1, np.array([[0.5, -0.5], [-0.5, 0.5]])), - ] + return [(0, np.array([[0.5, 0.5], [0.5, 0.5]])), (1, np.array([[0.5, -0.5], [-0.5, 0.5]]))] def __str__(self) -> str: if self._global_shift == 0: @@ -149,10 +146,7 @@ def test_gate_family_eq(): ), ( cirq.GateFamily(CustomX, ignore_global_phase=False), - [ - (CustomX, True), - (CustomXPowGate(exponent=1, global_shift=0.15), False), - ], + [(CustomX, True), (CustomXPowGate(exponent=1, global_shift=0.15), False)], ), ], ) @@ -266,8 +260,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=None): assert_validate_and_contains_consistent( gateset.with_params( - unroll_circuit_op=use_circuit_op, - accept_global_phase_op=use_global_phase, + unroll_circuit_op=use_circuit_op, accept_global_phase_op=use_global_phase ), op_tree, True, @@ -275,10 +268,7 @@ def assert_validate_and_contains_consistent(gateset, op_tree, result): if use_circuit_op or use_global_phase: with cirq.testing.assert_deprecated('global phase', deadline='v0.16', count=2): assert_validate_and_contains_consistent( - gateset.with_params( - unroll_circuit_op=False, - accept_global_phase_op=False, - ), + gateset.with_params(unroll_circuit_op=False, accept_global_phase_op=False), op_tree, False, ) diff --git a/cirq-core/cirq/optimizers/merge_interactions.py b/cirq-core/cirq/optimizers/merge_interactions.py index 1feeb36ac17..797930303c0 100644 --- a/cirq-core/cirq/optimizers/merge_interactions.py +++ b/cirq-core/cirq/optimizers/merge_interactions.py @@ -99,10 +99,7 @@ def _may_keep_old_op(self, old_op: 'cirq.Operation') -> bool: @abc.abstractmethod def _two_qubit_matrix_to_cz_operations( - self, - q0: 'cirq.Qid', - q1: 'cirq.Qid', - mat: np.ndarray, + self, q0: 'cirq.Qid', q1: 'cirq.Qid', mat: np.ndarray ) -> Sequence['cirq.Operation']: """Decomposes the merged two-qubit gate unitary into the minimum number of two-qubit gates. @@ -248,10 +245,7 @@ def _may_keep_old_op(self, old_op: 'cirq.Operation') -> bool: return old_op in self.gateset def _two_qubit_matrix_to_cz_operations( - self, - q0: 'cirq.Qid', - q1: 'cirq.Qid', - mat: np.ndarray, + self, q0: 'cirq.Qid', q1: 'cirq.Qid', mat: np.ndarray ) -> Sequence['cirq.Operation']: """Decomposes the merged two-qubit gate unitary into the minimum number of CZ gates. diff --git a/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py b/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py index 42472dcab73..3f4f8754a93 100644 --- a/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py +++ b/cirq-core/cirq/optimizers/merge_interactions_to_sqrt_iswap.py @@ -86,10 +86,7 @@ def _may_keep_old_op(self, old_op: 'cirq.Operation') -> bool: return old_op in self.gateset def _two_qubit_matrix_to_cz_operations( - self, - q0: 'cirq.Qid', - q1: 'cirq.Qid', - mat: np.ndarray, + self, q0: 'cirq.Qid', q1: 'cirq.Qid', mat: np.ndarray ) -> Sequence['cirq.Operation']: """Decomposes the merged two-qubit gate unitary into the minimum number of SQRT_ISWAP gates. diff --git a/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py b/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py index c2a2f6ed94a..fa83f481120 100644 --- a/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py +++ b/cirq-core/cirq/transformers/target_gatesets/cz_gateset.py @@ -63,10 +63,7 @@ def _value_equality_values_(self) -> Any: return self.atol, self.allow_partial_czs def _json_dict_(self) -> Dict[str, Any]: - return { - 'atol': self.atol, - 'allow_partial_czs': self.allow_partial_czs, - } + return {'atol': self.atol, 'allow_partial_czs': self.allow_partial_czs} @classmethod def _from_json_dict_(cls, atol, allow_partial_czs, **kwargs): diff --git a/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py b/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py index 2e1fa36f6f7..f6fa3f93c90 100644 --- a/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +++ b/cirq-core/cirq/transformers/target_gatesets/sqrt_iswap_gateset.py @@ -90,11 +90,7 @@ def __repr__(self) -> str: ) def _value_equality_values_(self) -> Any: - return ( - self.atol, - self.required_sqrt_iswap_count, - self.use_sqrt_iswap_inv, - ) + return (self.atol, self.required_sqrt_iswap_count, self.use_sqrt_iswap_inv) def _json_dict_(self) -> Dict[str, Any]: return { diff --git a/cirq-ionq/cirq_ionq/ionq_devices.py b/cirq-ionq/cirq_ionq/ionq_devices.py index cc906e91a91..28092c4eb40 100644 --- a/cirq-ionq/cirq_ionq/ionq_devices.py +++ b/cirq-ionq/cirq_ionq/ionq_devices.py @@ -66,18 +66,14 @@ def __init__(self, qubits: Union[Sequence[cirq.LineQubit], int], atol=1e-8): self.qubits = frozenset(qubits) self.atol = atol self._metadata = cirq.DeviceMetadata( - self.qubits, - [(a, b) for a in self.qubits for b in self.qubits if a != b], + self.qubits, [(a, b) for a in self.qubits for b in self.qubits if a != b] ) @property def metadata(self) -> cirq.DeviceMetadata: return self._metadata - @_compat.deprecated( - fix='Use metadata.qubit_set if applicable.', - deadline='v0.15', - ) + @_compat.deprecated(fix='Use metadata.qubit_set if applicable.', deadline='v0.15') def qubit_set(self) -> AbstractSet['cirq.Qid']: return self.qubits @@ -95,8 +91,7 @@ def is_api_gate(self, operation: cirq.Operation) -> bool: return operation in _VALID_GATES @_compat.deprecated( - fix='Use cirq_ionq.decompose_to_device operation instead.', - deadline='v0.15', + fix='Use cirq_ionq.decompose_to_device operation instead.', deadline='v0.15' ) def decompose_operation(self, operation: cirq.Operation) -> cirq.OP_TREE: return decompose_to_device(operation) @@ -157,6 +152,5 @@ def _decompose_two_qubit(operation: cirq.Operation) -> cirq.OP_TREE: temp = cirq.merge_single_qubit_gates_to_phased_x_and_z(temp) # A final pass breaks up PhasedXPow into Rz, Rx. yield cirq.map_operations_and_unroll( - temp, - lambda op, _: cirq.decompose_once(op) if type(op.gate) == cirq.PhasedXPowGate else op, + temp, lambda op, _: cirq.decompose_once(op) if type(op.gate) == cirq.PhasedXPowGate else op ).all_operations() diff --git a/cirq-pasqal/cirq_pasqal/pasqal_device.py b/cirq-pasqal/cirq_pasqal/pasqal_device.py index 8863f97c8fb..58013a68ae7 100644 --- a/cirq-pasqal/cirq_pasqal/pasqal_device.py +++ b/cirq-pasqal/cirq_pasqal/pasqal_device.py @@ -95,10 +95,7 @@ def maximum_qubit_number(self): def metadata(self): return self._metadata - @_compat.deprecated( - fix='Use metadata.qubit_set() if applicable.', - deadline='v0.15', - ) + @_compat.deprecated(fix='Use metadata.qubit_set() if applicable.', deadline='v0.15') def qubit_set(self) -> FrozenSet[cirq.Qid]: return frozenset(self.qubits) @@ -264,18 +261,12 @@ def __init__( cirq.AnyIntegerPowerGateFamily(cirq.CCZPowGate), ) self.controlled_gateset = cirq.Gateset( - *self.exclude_gateset.gates, - cirq.AnyIntegerPowerGateFamily(cirq.CZPowGate), + *self.exclude_gateset.gates, cirq.AnyIntegerPowerGateFamily(cirq.CZPowGate) ) @property def supported_qubit_type(self): - return ( - ThreeDQubit, - TwoDQubit, - GridQubit, - LineQubit, - ) + return (ThreeDQubit, TwoDQubit, GridQubit, LineQubit) def is_pasqal_device_op(self, op: cirq.Operation) -> bool: return super().is_pasqal_device_op(op) and op not in self.exclude_gateset @@ -366,8 +357,7 @@ def _json_dict_(self) -> Dict[str, Any]: return cirq.protocols.obj_to_dict_helper(self, ['control_radius', 'qubits']) @_compat.deprecated( - deadline='v0.15', - fix='qubit coupling data can now be found in device.metadata if provided.', + deadline='v0.15', fix='qubit coupling data can now be found in device.metadata if provided.' ) def qid_pairs(self) -> FrozenSet['cirq.SymmetricalQidPair']: """Returns a list of qubit edges on the device. diff --git a/cirq-pasqal/cirq_pasqal/pasqal_device_test.py b/cirq-pasqal/cirq_pasqal/pasqal_device_test.py index 8a6d5a27e57..3d9b3e60077 100644 --- a/cirq-pasqal/cirq_pasqal/pasqal_device_test.py +++ b/cirq-pasqal/cirq_pasqal/pasqal_device_test.py @@ -45,12 +45,7 @@ def test_init(): assert d.metadata.qubit_set == {TwoDQubit(0, 0)} assert d.qubit_list() == [TwoDQubit(0, 0)] assert d.control_radius == 1.0 - assert d.supported_qubit_type == ( - ThreeDQubit, - TwoDQubit, - cirq.GridQubit, - cirq.LineQubit, - ) + assert d.supported_qubit_type == (ThreeDQubit, TwoDQubit, cirq.GridQubit, cirq.LineQubit) def test_init_errors(): @@ -170,11 +165,7 @@ def test_qubit_set_deprecated(): def test_metadata(): d = generic_device(3) assert d.metadata.qubit_set == frozenset( - [ - cirq.NamedQubit('q0'), - cirq.NamedQubit('q1'), - cirq.NamedQubit('q2'), - ] + [cirq.NamedQubit('q0'), cirq.NamedQubit('q1'), cirq.NamedQubit('q2')] ) assert len(d.metadata.nx_graph.edges()) == 3 @@ -266,10 +257,7 @@ def test_to_json(): assert d == {"qubits": [cirq.NamedQubit('q4')]} vdev = PasqalVirtualDevice(control_radius=2, qubits=[TwoDQubit(0, 0)]) d = vdev._json_dict_() - assert d == { - "control_radius": 2, - "qubits": [cirq_pasqal.TwoDQubit(0, 0)], - } + assert d == {"control_radius": 2, "qubits": [cirq_pasqal.TwoDQubit(0, 0)]} def test_qid_pairs_deprecated(): @@ -286,12 +274,6 @@ def test_qid_pairs_deprecated(): with cirq.testing.assert_deprecated('device.metadata', deadline='v0.15', count=3): assert len(dev.qid_pairs()) == 5 dev1 = PasqalVirtualDevice( - 5, - qubits=[ - TwoDQubit(0, 0), - TwoDQubit(3, 2), - TwoDQubit(3, 4), - TwoDQubit(3, 6), - ], + 5, qubits=[TwoDQubit(0, 0), TwoDQubit(3, 2), TwoDQubit(3, 4), TwoDQubit(3, 6)] ) assert len(dev1.qid_pairs()) == 5 From f7c12da76eb58255dd0440ed208188affc048697 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 14 Apr 2022 21:52:10 -0700 Subject: [PATCH 20/23] inward json parser --- cirq-core/cirq/ops/gateset.py | 16 +++-- cirq-core/cirq/ops/gateset_test.py | 9 --- .../json_test_data/Gateset.json_inward | 69 +++++++++++++++++++ .../json_test_data/Gateset.repr_inward | 16 +++++ 4 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 cirq-core/cirq/protocols/json_test_data/Gateset.json_inward create mode 100644 cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index fc865502939..8a3b5f94d93 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -320,7 +320,7 @@ def val_if_none(var: Any, val: Any) -> Any: accept_global_phase_op is True and global_phase_family in self.gates or accept_global_phase_op is False - and global_phase_family not in self.gates + and not any(g.gate is global_phase_op.GlobalPhaseGate for g in self.gates) or accept_global_phase_op is None ) ): @@ -454,10 +454,12 @@ def _json_dict_(self) -> Dict[str, Any]: @classmethod def _from_json_dict_(cls, gates, name, unroll_circuit_op, **kwargs) -> 'Gateset': if 'accept_global_phase_op' in kwargs: - return cls( - *gates, - name=name, - unroll_circuit_op=unroll_circuit_op, - accept_global_phase_op=kwargs['accept_global_phase_op'], - ) + accept_global_phase_op = kwargs['accept_global_phase_op'] + global_phase_family = GateFamily(gate=global_phase_op.GlobalPhaseGate) + if accept_global_phase_op is True: + gates.append(global_phase_family) + elif accept_global_phase_op is False: + gates = [ + family for family in gates if family.gate is not global_phase_op.GlobalPhaseGate + ] return cls(*gates, name=name, unroll_circuit_op=unroll_circuit_op) diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index 668674304be..007142539c5 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -336,12 +336,3 @@ def test_gateset_eq(): ) ) ) - - -def test_from_json_allow_global_phase_deprecated(): - with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): - x = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=True) - assert x.gates == {cirq.GateFamily(cirq.GlobalPhaseGate)} - with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): - x = cirq.Gateset._from_json_dict_([], '', True, accept_global_phase_op=False) - assert not x.gates diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward b/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward new file mode 100644 index 00000000000..5251da9f6f9 --- /dev/null +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.json_inward @@ -0,0 +1,69 @@ +[ + { + "cirq_type": "Gateset", + "gates": [ + { + "cirq_type": "GateFamily", + "gate": "YPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "AnyUnitaryGateFamily", + "num_qubits": 2 + }, + { + "cirq_type": "GateFamily", + "gate": { + "cirq_type": "_PauliX", + "exponent": 1.0, + "global_shift": 0.0 + }, + "name": "Instance GateFamily: X", + "description": "Accepts `cirq.Gate` instances `g` s.t. `g == X`", + "ignore_global_phase": true + } + ], + "name": null, + "unroll_circuit_op": true, + "accept_global_phase_op": true + }, + { + "cirq_type": "Gateset", + "gates": [ + { + "cirq_type": "GateFamily", + "gate": { + "cirq_type": "_PauliX", + "exponent": 1.0, + "global_shift": 0.0 + }, + "name": "Instance GateFamily: X", + "description": "Accepts `cirq.Gate` instances `g` s.t. `g == X`", + "ignore_global_phase": true + }, + { + "cirq_type": "GateFamily", + "gate": "YPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "AnyUnitaryGateFamily", + "num_qubits": 2 + }, + { + "cirq_type": "GateFamily", + "gate": "GlobalPhaseGate", + "name": "Type GateFamily: cirq.ops.global_phase_gate.GlobalPhaseGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.global_phase_gate.GlobalPhaseGate)`", + "ignore_global_phase": true + } + ], + "name": "Custom Name", + "unroll_circuit_op": false, + "accept_global_phase_op": false + } +] diff --git a/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward b/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward new file mode 100644 index 00000000000..761938581e4 --- /dev/null +++ b/cirq-core/cirq/protocols/json_test_data/Gateset.repr_inward @@ -0,0 +1,16 @@ +[ + cirq.Gateset( + cirq.ops.common_gates.YPowGate, + cirq.AnyUnitaryGateFamily(num_qubits=2), + cirq.X, + cirq.GlobalPhaseGate, + unroll_circuit_op=True, + ), + cirq.Gateset( + cirq.X, + cirq.ops.common_gates.YPowGate, + cirq.AnyUnitaryGateFamily(num_qubits=2), + name="Custom Name", + unroll_circuit_op=False, + ), +] \ No newline at end of file From 7d45446ba88003799d2ccf1abca44a11ae30c0c7 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 15 Apr 2022 04:24:56 -0700 Subject: [PATCH 21/23] coverage --- cirq-core/cirq/ops/gateset.py | 2 +- cirq-core/cirq/ops/gateset_test.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 8a3b5f94d93..3ec98a528b5 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -252,7 +252,7 @@ def __init__( ) if accept_global_phase_op is False: unique_gate_list = [ - g for g in unique_gate_list if g.gate != global_phase_op.GlobalPhaseGate + g for g in unique_gate_list if g.gate is not global_phase_op.GlobalPhaseGate ] elif accept_global_phase_op is None: if not any(g.gate is global_phase_op.GlobalPhaseGate for g in unique_gate_list): diff --git a/cirq-core/cirq/ops/gateset_test.py b/cirq-core/cirq/ops/gateset_test.py index 007142539c5..c050d62e5f5 100644 --- a/cirq-core/cirq/ops/gateset_test.py +++ b/cirq-core/cirq/ops/gateset_test.py @@ -304,7 +304,13 @@ def test_gateset_eq(): eq = cirq.testing.EqualsTester() eq.add_equality_group(cirq.Gateset(CustomX)) eq.add_equality_group(cirq.Gateset(CustomX**3)) - eq.add_equality_group(cirq.Gateset(CustomX, name='Custom Gateset')) + with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): + eq.add_equality_group( + cirq.Gateset(CustomX, name='Custom Gateset'), + cirq.Gateset( + CustomX, cirq.GlobalPhaseGate, name='Custom Gateset', accept_global_phase_op=False + ), + ) eq.add_equality_group(cirq.Gateset(CustomX, name='Custom Gateset', unroll_circuit_op=False)) with cirq.testing.assert_deprecated('global phase', deadline='v0.16'): eq.add_equality_group( From 01fdb0b098c2d2795589cc14d088370da32388f0 Mon Sep 17 00:00:00 2001 From: Dax Fohl Date: Sat, 16 Apr 2022 22:43:19 -0700 Subject: [PATCH 22/23] Fix warnings --- cirq-core/cirq/ops/gateset.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 3ec98a528b5..298d04b2bf1 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -205,7 +205,9 @@ class Gateset: @_compat.deprecated_parameter( deadline='v0.16', - fix='Add a global phase gate to the Gateset', + fix='To accept global phase gates, add cirq.GlobalPhaseGate to the list of *gates passed ' + 'to the constructor. By default, global phase gates will not be accepted by the ' + 'gateset', parameter_desc='accept_global_phase_op', match=lambda args, kwargs: 'accept_global_phase_op' in kwargs, ) @@ -235,10 +237,10 @@ def __init__( validated by validating the underlying `cirq.Circuit`. accept_global_phase_op: If True, a `GateFamily` accepting `cirq.GlobalPhaseGate` will be included. If None, - `cirq.GlobalPhaseGate` will still be accepted if it appears in - the `gates` parameter. If False, `cirq.GlobalPhaseGate` will be - removed from the gates. This parameter defaults to False (a - breaking change from v0.14) and will be removed in v0.16. + `cirq.GlobalPhaseGate` will not modify the input `*gates`. + If False, `cirq.GlobalPhaseGate` will be removed from the + gates. This parameter defaults to None (a breaking change from + v0.14.1) and will be removed in v0.16. """ self._name = name self._unroll_circuit_op = unroll_circuit_op @@ -257,7 +259,10 @@ def __init__( elif accept_global_phase_op is None: if not any(g.gate is global_phase_op.GlobalPhaseGate for g in unique_gate_list): warnings.warn( - 'v0.14.1 is the last release `cirq.GlobalPhaseGate` is included by default.' + 'v0.14.1 is the last release `cirq.GlobalPhaseGate` is included by default. If' + ' you were relying on this behavior, you can include a `cirq.GlobalPhaseGate`' + ' in your `*gates`. If not, then you can ignore this warning. It will be' + ' removed in v0.16' ) for g in unique_gate_list: @@ -298,9 +303,12 @@ def with_params( name: New name for the Gateset. unroll_circuit_op: If True, new Gateset will recursively validate `cirq.CircuitOperation` by validating the underlying `cirq.Circuit`. - accept_global_phase_op: If True, new Gateset will include a `GateFamily` that accepts - `cirq.GlobalPhaseGate`. False or None have no effect. This parameter is deprecated - and will be removed in v0.16. + accept_global_phase_op: If True, a `GateFamily` accepting + `cirq.GlobalPhaseGate` will be included. If None, + `cirq.GlobalPhaseGate` will not modify the input `*gates`. + If False, `cirq.GlobalPhaseGate` will be removed from the + gates. This parameter defaults to None (a breaking change from + v0.14.1) and will be removed in v0.16. Returns: `self` if all new values are None or identical to the values of current Gateset. From a648a615afab16ed63c96d7bba8803df7aa2b4ec Mon Sep 17 00:00:00 2001 From: Dax Fohl Date: Sat, 16 Apr 2022 22:52:38 -0700 Subject: [PATCH 23/23] format --- cirq-core/cirq/ops/gateset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 298d04b2bf1..1e36e67f635 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -206,8 +206,8 @@ class Gateset: @_compat.deprecated_parameter( deadline='v0.16', fix='To accept global phase gates, add cirq.GlobalPhaseGate to the list of *gates passed ' - 'to the constructor. By default, global phase gates will not be accepted by the ' - 'gateset', + 'to the constructor. By default, global phase gates will not be accepted by the ' + 'gateset', parameter_desc='accept_global_phase_op', match=lambda args, kwargs: 'accept_global_phase_op' in kwargs, )