Skip to content

Commit 7f46121

Browse files
Add InternalTag to support non-public tags (#7040)
* Add InternalTag to support non-public tags - This will be a container to support tags that are not currently public, similar to how InternalGate works. * Forgot to add json files. * Update cirq-google/cirq_google/ops/internal_tag.py Co-authored-by: Pavol Juhas <[email protected]> * address comments --------- Co-authored-by: Pavol Juhas <[email protected]>
1 parent 72e1d20 commit 7f46121

File tree

7 files changed

+127
-1
lines changed

7 files changed

+127
-1
lines changed

cirq-google/cirq_google/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
FSimGateFamily as FSimGateFamily,
6060
FSimViaModelTag as FSimViaModelTag,
6161
InternalGate as InternalGate,
62+
InternalTag as InternalTag,
6263
PhysicalZTag as PhysicalZTag,
6364
SYC as SYC,
6465
SycamoreGate as SycamoreGate,

cirq-google/cirq_google/json_resolver_cache.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,5 @@ def _old_xmon(*args, **kwargs):
8080
'cirq.google.DeviceParameter': cirq_google.study.device_parameter.DeviceParameter,
8181
'cirq.google.Metadata': cirq_google.study.device_parameter.Metadata,
8282
'InternalGate': cirq_google.InternalGate,
83+
'InternalTag': cirq_google.InternalTag,
8384
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"cirq_type": "InternalTag",
3+
"name": "IdleWaitTag",
4+
"package": "internal.module",
5+
"phase_match": true,
6+
"pad_ns": 20.0
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cirq_google.InternalTag(name="IdleWaitTag", package="internal.module", phase_match=True, pad_ns=20.0)

cirq-google/cirq_google/ops/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"""Qubit Gates, Operations, and Tags useful for Google devices. """
15+
"""Qubit Gates, Operations, and Tags useful for Google devices."""
1616

1717
from cirq_google.ops.calibration_tag import CalibrationTag as CalibrationTag
1818

@@ -28,6 +28,8 @@
2828

2929
from cirq_google.ops.internal_gate import InternalGate as InternalGate
3030

31+
from cirq_google.ops.internal_tag import InternalTag as InternalTag
32+
3133
from cirq_google.ops.dynamical_decoupling_tag import (
3234
DynamicalDecouplingTag as DynamicalDecouplingTag,
3335
)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright 2025 The Cirq Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from typing import Any, Dict
16+
17+
from cirq import value
18+
19+
20+
@value.value_equality
21+
class InternalTag:
22+
"""InternalTag is a placeholder tag for internal tags that
23+
are not specified publicly.
24+
25+
These tags can hold the information needed to instantiate a
26+
tag specified in an internal library.
27+
"""
28+
29+
def __init__(self, name: str, package: str, **kwargs):
30+
"""Instantiates an InternalTag.
31+
32+
Arguments:
33+
name: Tag class name.
34+
package: The python module of the tag.
35+
**kwargs: Arbitrary keyword parameters that should be passed to the tag.
36+
"""
37+
self.name = name
38+
self.package = package
39+
self.tag_args = kwargs
40+
41+
def __str__(self):
42+
tag_args = ', '.join(f'{k}={v}' for k, v in self.tag_args.items())
43+
return f'{self.package}.{self.name}({tag_args})'
44+
45+
def __repr__(self) -> str:
46+
tag_args = ', '.join(f'{k}={v!r}' for k, v in self.tag_args.items())
47+
if tag_args:
48+
tag_args = ', ' + tag_args
49+
return f"cirq_google.InternalTag(name='{self.name}', package='{self.package}'{tag_args})"
50+
51+
def _json_dict_(self) -> Dict[str, Any]:
52+
return dict(name=self.name, package=self.package, **self.tag_args)
53+
54+
def _value_equality_values_(self):
55+
try:
56+
tag_args_eq_values = frozenset(self.tag_args.items())
57+
except TypeError:
58+
tag_args_eq_values = self.tag_args
59+
return (self.name, self.package, tag_args_eq_values)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright 2025 The Cirq Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import cirq_google
16+
import pytest
17+
18+
19+
def test_internal_tag():
20+
g = cirq_google.InternalTag(
21+
name="IdleWaitTag",
22+
package='internal_module',
23+
phase_match=True,
24+
pad_ns=10,
25+
pad_start=True,
26+
pad_end=False,
27+
)
28+
assert (
29+
str(g) == "internal_module.IdleWaitTag("
30+
"phase_match=True, pad_ns=10, pad_start=True, pad_end=False)"
31+
)
32+
assert (
33+
repr(g) == "cirq_google.InternalTag(name='IdleWaitTag', "
34+
"package='internal_module', phase_match=True, "
35+
"pad_ns=10, pad_start=True, pad_end=False)"
36+
)
37+
38+
39+
def test_internal_tag_with_no_args():
40+
g = cirq_google.InternalTag(name="TagWithNoArgs", package='test')
41+
assert str(g) == 'test.TagWithNoArgs()'
42+
assert repr(g) == "cirq_google.InternalTag(name='TagWithNoArgs', package='test')"
43+
44+
45+
def test_internal_tag_with_hashable_args_is_hashable():
46+
hashable = cirq_google.InternalTag(
47+
name="TagWithHashableArgs", package='test', foo=1, bar="2", baz=(("a", 1),)
48+
)
49+
_ = hash(hashable)
50+
51+
unhashable = cirq_google.InternalTag(
52+
name="TagWithUnHashableArgs", package='test', foo=1, bar="2", baz={"a": 1}
53+
)
54+
with pytest.raises(TypeError, match="unhashable"):
55+
_ = hash(unhashable)

0 commit comments

Comments
 (0)