Skip to content

Commit

Permalink
Add q helper function for constructing common qubit types. (#5181)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
maffoo authored Apr 9, 2022
1 parent 1522b02 commit d9d6433
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
1 change: 1 addition & 0 deletions cirq-core/cirq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@
ProjectorString,
ProjectorSum,
RandomGateChannel,
q,
qft,
Qid,
QuantumFourierTransformGate,
Expand Down
2 changes: 2 additions & 0 deletions cirq-core/cirq/ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,8 @@
PhasedXZGate,
)

from cirq.ops.qid_util import q

from cirq.ops.random_gate_channel import (
RandomGateChannel,
)
Expand Down
68 changes: 68 additions & 0 deletions cirq-core/cirq/ops/qid_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2022 The Cirq Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import overload, TYPE_CHECKING, Union

if TYPE_CHECKING:
import cirq


@overload
def q(__x: int) -> 'cirq.LineQubit':
...


@overload
def q(__row: int, __col: int) -> 'cirq.GridQubit':
...


@overload
def q(__name: str) -> 'cirq.NamedQubit':
...


def q(*args: Union[int, str]) -> Union['cirq.LineQubit', 'cirq.GridQubit', 'cirq.NamedQubit']:
"""Constructs a qubit id of the appropriate type based on args.
This is shorthand for constructing qubit ids of common types:
>>> cirq.q(1) == cirq.LineQubit(1)
>>> cirq.q(1, 2) == cirq.GridQubit(1, 2)
>>> cirq.q("foo") == cirq.NamedQubit("foo")
Note that arguments should be treated as positional only, even
though this is only enforceable in python 3.8 or later.
Args:
*args: One or two ints, or a single str, as described above.
Returns:
cirq.LineQubit if called with one integer arg.
cirq.GridQubit if called with two integer args.
cirq.NamedQubit if called with one string arg.
Raises:
ValueError: if called with invalid arguments.
"""
import cirq # avoid circular import

if len(args) == 1:
if isinstance(args[0], int):
return cirq.LineQubit(args[0])
elif isinstance(args[0], str):
return cirq.NamedQubit(args[0])
elif len(args) == 2:
if isinstance(args[0], int) and isinstance(args[1], int):
return cirq.GridQubit(args[0], args[1])
raise ValueError(f"Could not construct qubit: args={args}")
31 changes: 31 additions & 0 deletions cirq-core/cirq/ops/qid_util_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2022 The Cirq Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pytest

import cirq


def test_q() -> None:
assert cirq.q(0) == cirq.LineQubit(0)
assert cirq.q(1, 2) == cirq.GridQubit(1, 2)
assert cirq.q("foo") == cirq.NamedQubit("foo")


def test_q_invalid() -> None:
# Ignore static type errors so we can test runtime typechecks.
with pytest.raises(ValueError):
cirq.q([1, 2, 3]) # type: ignore[call-overload]
with pytest.raises(ValueError):
cirq.q(1, "foo") # type: ignore[call-overload]

0 comments on commit d9d6433

Please sign in to comment.