Skip to content
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

Deprecate Gateset.accept_global_phase_op #5239

Merged
merged 27 commits into from
Apr 18, 2022
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a6e6d78
Deprecate Gateset.accept_global_phase_op
daxfohl Apr 9, 2022
679a4b2
Change gateset accept_global_phase_op default to False.
daxfohl Apr 9, 2022
4d953cc
Fix up uses of Gateset for the breaking GlobalPhaseGate change
daxfohl Apr 9, 2022
4d8bff0
Fix allow fallback to checking for GlobalPhaseGate in gateset
daxfohl Apr 9, 2022
5489cbb
Fix json
daxfohl Apr 9, 2022
eb0527d
format
daxfohl Apr 9, 2022
c463a0c
Physically add a GlobalPhaseGate if allow_global_phase is True, rewor…
daxfohl Apr 9, 2022
a5245e9
fix doc
daxfohl Apr 9, 2022
a7e5c02
Update docs, add inward files
daxfohl Apr 9, 2022
7df5e95
Add json parsing deprecation test
daxfohl Apr 9, 2022
144b897
Add assertions to new test
daxfohl Apr 9, 2022
621e00c
minor refactor
daxfohl Apr 10, 2022
5deea64
Force phase gate removal if allow=False'
daxfohl Apr 13, 2022
71015ae
add global phase to gatesets
daxfohl Apr 13, 2022
68d9951
fix tests in google
daxfohl Apr 13, 2022
1a1ba13
fix tests in google
daxfohl Apr 13, 2022
57a1745
Add warning when default `accept_global_phase_op`
daxfohl Apr 14, 2022
53fd095
Fix pasqal test
daxfohl Apr 14, 2022
ff2b152
Merge branch 'master' into dep-accepts-global-phase
daxfohl Apr 14, 2022
5aca223
format
daxfohl Apr 14, 2022
22d1ed8
Merge branch 'master' into dep-accepts-global-phase
daxfohl Apr 14, 2022
f7c12da
inward json parser
daxfohl Apr 15, 2022
7d45446
coverage
daxfohl Apr 15, 2022
01fdb0b
Fix warnings
daxfohl Apr 17, 2022
a648a61
format
daxfohl Apr 17, 2022
ac31654
Merge branch 'master' into dep-accepts-global-phase
daxfohl Apr 17, 2022
4d152e4
Merge branch 'master' into dep-accepts-global-phase
CirqBot Apr 18, 2022
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
1 change: 0 additions & 1 deletion cirq-core/cirq/ion/ion_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def get_ion_gateset() -> ops.Gateset:
ops.ZPowGate,
ops.PhasedXPowGate,
unroll_circuit_op=False,
accept_global_phase_op=False,
)


Expand Down
6 changes: 3 additions & 3 deletions cirq-core/cirq/ion/ion_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
3 changes: 0 additions & 3 deletions cirq-core/cirq/neutral_atoms/neutral_atom_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)


Expand Down Expand Up @@ -100,15 +99,13 @@ 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),
ops.AnyIntegerPowerGateFamily(ops.CCNotPowGate),
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:
Expand Down
4 changes: 2 additions & 2 deletions cirq-core/cirq/neutral_atoms/neutral_atom_devices_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
91 changes: 62 additions & 29 deletions cirq-core/cirq/ops/gateset.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 import _compat, protocols, value
from cirq.ops import global_phase_op, op_tree, raw_types
from cirq import protocols, value

if TYPE_CHECKING:
import cirq
Expand Down Expand Up @@ -201,12 +203,18 @@ class Gateset:
validation purposes.
"""

@_compat.deprecated_parameter(
deadline='v0.16',
fix='Add a global phase gate to the Gateset',
daxfohl marked this conversation as resolved.
Show resolved Hide resolved
parameter_desc='accept_global_phase_op',
match=lambda args, kwargs: 'accept_global_phase_op' in kwargs,
)
def __init__(
self,
*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: Optional[bool] = None,
) -> None:
"""Init Gateset.

Expand All @@ -225,17 +233,33 @@ 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, 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.
daxfohl marked this conversation as resolved.
Show resolved Hide resolved
"""
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])
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 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):
warnings.warn(
'v0.14.1 is the last release `cirq.GlobalPhaseGate` is included by default.'
daxfohl marked this conversation as resolved.
Show resolved Hide resolved
)

for g in unique_gate_list:
if type(g) == GateFamily:
if isinstance(g.gate, raw_types.Gate):
Expand All @@ -253,6 +277,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='accept_global_phase_op',
match=lambda args, kwargs: 'accept_global_phase_op' in kwargs,
)
def with_params(
self,
*,
Expand All @@ -268,7 +298,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 include a `GateFamily` that accepts
`cirq.GlobalPhaseGate`. False or None have no effect. This parameter is deprecated
daxfohl marked this conversation as resolved.
Show resolved Hide resolved
and will be removed in v0.16.

Returns:
`self` if all new values are None or identical to the values of current Gateset.
Expand All @@ -280,19 +312,23 @@ 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)
global_phase_family = GateFamily(gate=global_phase_op.GlobalPhaseGate)
if (
name == self._name
and unroll_circuit_op == self._unroll_circuit_op
and accept_global_phase_op == self._accept_global_phase_op
and (
accept_global_phase_op is True
and global_phase_family in self.gates
or accept_global_phase_op is False
and not any(g.gate is global_phase_op.GlobalPhaseGate for g in self.gates)
or accept_global_phase_op is None
)
):
return self
return Gateset(
*self.gates,
name=name,
unroll_circuit_op=cast(bool, unroll_circuit_op),
accept_global_phase_op=cast(bool, accept_global_phase_op),
)
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))

def __contains__(self, item: Union[raw_types.Gate, raw_types.Operation]) -> bool:
"""Check for containment of a given Gate/Operation in this Gateset.
Expand Down Expand Up @@ -326,9 +362,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):
return self._accept_global_phase_op

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 "
Expand Down Expand Up @@ -394,16 +427,15 @@ 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, self._accept_global_phase_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 ''
return (
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})'
)

def __str__(self) -> str:
Expand All @@ -417,16 +449,17 @@ def _json_dict_(self) -> Dict[str, Any]:
'gates': self._unique_gate_list,
'name': self.name,
'unroll_circuit_op': self._unroll_circuit_op,
'accept_global_phase_op': self._accept_global_phase_op,
}

@classmethod
def _from_json_dict_(
cls, gates, name, unroll_circuit_op, accept_global_phase_op, **kwargs
) -> 'Gateset':
return cls(
*gates,
name=name,
unroll_circuit_op=unroll_circuit_op,
accept_global_phase_op=accept_global_phase_op,
)
def _from_json_dict_(cls, gates, name, unroll_circuit_op, **kwargs) -> 'Gateset':
if 'accept_global_phase_op' in kwargs:
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)
60 changes: 35 additions & 25 deletions cirq-core/cirq/ops/gateset_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,19 +257,21 @@ 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=None):
assert_validate_and_contains_consistent(
gateset.with_params(unroll_circuit_op=False, accept_global_phase_op=False),
gateset.with_params(
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():
Expand All @@ -281,31 +283,39 @@ 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'):
assert (
gateset.with_params(
name=gateset.name,
unroll_circuit_op=gateset._unroll_circuit_op,
accept_global_phase_op=None,
)
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


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))
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'):
eq.add_equality_group(
cirq.Gateset(CustomX, name='Custom Gateset', accept_global_phase_op=True)
)
eq.add_equality_group(
cirq.Gateset(
cirq.GateFamily(CustomX, name='custom_name', description='custom_description'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/optimizers/merge_interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 2 additions & 4 deletions cirq-core/cirq/protocols/json_test_data/Gateset.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
}
],
"name": null,
"unroll_circuit_op": true,
"accept_global_phase_op": true
"unroll_circuit_op": true
daxfohl marked this conversation as resolved.
Show resolved Hide resolved
},
{
"cirq_type": "Gateset",
Expand Down Expand Up @@ -56,7 +55,6 @@
}
],
"name": "Custom Name",
"unroll_circuit_op": false,
"accept_global_phase_op": false
"unroll_circuit_op": false
}
]
Loading