Skip to content

Commit d9d6433

Browse files
authored
Add q helper function for constructing common qubit types. (#5181)
* Add q helper function * fmt * Ignore static type errors in tests * Ignore intentional type errors * Fix Raises docstring * Fixes from review * Use *args * remove unused import
1 parent 1522b02 commit d9d6433

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

cirq-core/cirq/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@
290290
ProjectorString,
291291
ProjectorSum,
292292
RandomGateChannel,
293+
q,
293294
qft,
294295
Qid,
295296
QuantumFourierTransformGate,

cirq-core/cirq/ops/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@
258258
PhasedXZGate,
259259
)
260260

261+
from cirq.ops.qid_util import q
262+
261263
from cirq.ops.random_gate_channel import (
262264
RandomGateChannel,
263265
)

cirq-core/cirq/ops/qid_util.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright 2022 The Cirq Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from typing import overload, TYPE_CHECKING, Union
16+
17+
if TYPE_CHECKING:
18+
import cirq
19+
20+
21+
@overload
22+
def q(__x: int) -> 'cirq.LineQubit':
23+
...
24+
25+
26+
@overload
27+
def q(__row: int, __col: int) -> 'cirq.GridQubit':
28+
...
29+
30+
31+
@overload
32+
def q(__name: str) -> 'cirq.NamedQubit':
33+
...
34+
35+
36+
def q(*args: Union[int, str]) -> Union['cirq.LineQubit', 'cirq.GridQubit', 'cirq.NamedQubit']:
37+
"""Constructs a qubit id of the appropriate type based on args.
38+
39+
This is shorthand for constructing qubit ids of common types:
40+
>>> cirq.q(1) == cirq.LineQubit(1)
41+
>>> cirq.q(1, 2) == cirq.GridQubit(1, 2)
42+
>>> cirq.q("foo") == cirq.NamedQubit("foo")
43+
44+
Note that arguments should be treated as positional only, even
45+
though this is only enforceable in python 3.8 or later.
46+
47+
Args:
48+
*args: One or two ints, or a single str, as described above.
49+
50+
Returns:
51+
cirq.LineQubit if called with one integer arg.
52+
cirq.GridQubit if called with two integer args.
53+
cirq.NamedQubit if called with one string arg.
54+
55+
Raises:
56+
ValueError: if called with invalid arguments.
57+
"""
58+
import cirq # avoid circular import
59+
60+
if len(args) == 1:
61+
if isinstance(args[0], int):
62+
return cirq.LineQubit(args[0])
63+
elif isinstance(args[0], str):
64+
return cirq.NamedQubit(args[0])
65+
elif len(args) == 2:
66+
if isinstance(args[0], int) and isinstance(args[1], int):
67+
return cirq.GridQubit(args[0], args[1])
68+
raise ValueError(f"Could not construct qubit: args={args}")

cirq-core/cirq/ops/qid_util_test.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2022 The Cirq Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import pytest
16+
17+
import cirq
18+
19+
20+
def test_q() -> None:
21+
assert cirq.q(0) == cirq.LineQubit(0)
22+
assert cirq.q(1, 2) == cirq.GridQubit(1, 2)
23+
assert cirq.q("foo") == cirq.NamedQubit("foo")
24+
25+
26+
def test_q_invalid() -> None:
27+
# Ignore static type errors so we can test runtime typechecks.
28+
with pytest.raises(ValueError):
29+
cirq.q([1, 2, 3]) # type: ignore[call-overload]
30+
with pytest.raises(ValueError):
31+
cirq.q(1, "foo") # type: ignore[call-overload]

0 commit comments

Comments
 (0)