Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/cirq-web/cirq_ts/non…
Browse files Browse the repository at this point in the history
…-security-a77737716f
  • Loading branch information
pavoljuhas committed Jan 28, 2025
2 parents 0866981 + b73eb28 commit 8cb7719
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 6 deletions.
11 changes: 8 additions & 3 deletions cirq-core/cirq/devices/grid_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ class _BaseGridQid(ops.Qid):
_col: int
_dimension: int
_comp_key: Optional[Tuple[int, int]] = None
_hash: Optional[int] = None
_hash: int

def __hash__(self) -> int:
if self._hash is None:
self._hash = ((self._dimension - 2) * 1_000_003 + self._col) * 1_000_003 + self._row
return self._hash

def __eq__(self, other) -> bool:
Expand Down Expand Up @@ -215,6 +213,9 @@ def __new__(cls, row: int, col: int, *, dimension: int) -> 'cirq.GridQid':
dimension: The dimension of the qid's Hilbert space, i.e.
the number of quantum levels.
"""
row = int(row)
col = int(col)
dimension = int(dimension)
key = (row, col, dimension)
inst = cls._cache.get(key)
if inst is None:
Expand All @@ -223,6 +224,7 @@ def __new__(cls, row: int, col: int, *, dimension: int) -> 'cirq.GridQid':
inst._row = row
inst._col = col
inst._dimension = dimension
inst._hash = ((dimension - 2) * 1_000_003 + col) * 1_000_003 + row
cls._cache[key] = inst
return inst

Expand Down Expand Up @@ -378,12 +380,15 @@ def __new__(cls, row: int, col: int) -> 'cirq.GridQubit':
row: the row coordinate
col: the column coordinate
"""
row = int(row)
col = int(col)
key = (row, col)
inst = cls._cache.get(key)
if inst is None:
inst = super().__new__(cls)
inst._row = row
inst._col = col
inst._hash = col * 1_000_003 + row
cls._cache[key] = inst
return inst

Expand Down
21 changes: 21 additions & 0 deletions cirq-core/cirq/devices/grid_qubit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,3 +391,24 @@ def test_immutable():
def test_complex():
assert complex(cirq.GridQubit(row=1, col=2)) == 2 + 1j
assert isinstance(complex(cirq.GridQubit(row=1, col=2)), complex)


def test_numpy_index():
np5, np6, np3 = [np.int64(i) for i in [5, 6, 3]]
q = cirq.GridQubit(np5, np6)
hash(q) # doesn't throw
assert q.row == 5
assert q.col == 6
assert q.dimension == 2
assert isinstance(q.row, int)
assert isinstance(q.col, int)
assert isinstance(q.dimension, int)

q = cirq.GridQid(np5, np6, dimension=np3)
hash(q) # doesn't throw
assert q.row == 5
assert q.col == 6
assert q.dimension == 3
assert isinstance(q.row, int)
assert isinstance(q.col, int)
assert isinstance(q.dimension, int)
9 changes: 6 additions & 3 deletions cirq-core/cirq/devices/line_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@ class _BaseLineQid(ops.Qid):

_x: int
_dimension: int
_hash: Optional[int] = None
_hash: int

def __hash__(self) -> int:
if self._hash is None:
self._hash = (self._dimension - 2) * 1_000_003 + self._x
return self._hash

def __eq__(self, other) -> bool:
Expand Down Expand Up @@ -193,13 +191,16 @@ def __new__(cls, x: int, dimension: int) -> 'cirq.LineQid':
dimension: The dimension of the qid's Hilbert space, i.e.
the number of quantum levels.
"""
x = int(x)
dimension = int(dimension)
key = (x, dimension)
inst = cls._cache.get(key)
if inst is None:
cls.validate_dimension(dimension)
inst = super().__new__(cls)
inst._x = x
inst._dimension = dimension
inst._hash = (dimension - 2) * 1_000_003 + x
cls._cache[key] = inst
return inst

Expand Down Expand Up @@ -301,10 +302,12 @@ def __new__(cls, x: int) -> 'cirq.LineQubit':
Args:
x: The x coordinate.
"""
x = int(x)
inst = cls._cache.get(x)
if inst is None:
inst = super().__new__(cls)
inst._x = x
inst._hash = x
cls._cache[x] = inst
return inst

Expand Down
18 changes: 18 additions & 0 deletions cirq-core/cirq/devices/line_qubit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import numpy as np
import pytest

import cirq
Expand Down Expand Up @@ -284,3 +285,20 @@ def test_numeric():
assert isinstance(int(cirq.LineQubit(x=5)), int)
assert isinstance(float(cirq.LineQubit(x=5)), float)
assert isinstance(complex(cirq.LineQubit(x=5)), complex)


def test_numpy_index():
np5 = np.int64(5)
q = cirq.LineQubit(np5)
assert hash(q) == 5
assert q.x == 5
assert q.dimension == 2
assert isinstance(q.x, int)
assert isinstance(q.dimension, int)

q = cirq.LineQid(np5, np.int64(3))
hash(q) # doesn't throw
assert q.x == 5
assert q.dimension == 3
assert isinstance(q.x, int)
assert isinstance(q.dimension, int)
12 changes: 12 additions & 0 deletions cirq-core/cirq/ops/raw_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,18 @@ def _qid_shape_(self) -> Tuple[int, ...]:
"""
raise NotImplementedError

def _equal_up_to_global_phase_(
self, other: Any, atol: Union[int, float] = 1e-8
) -> Union[NotImplementedType, bool]:
"""Default fallback for gates that do not implement this protocol."""
try:
return protocols.equal_up_to_global_phase(
protocols.unitary(self), protocols.unitary(other), atol=atol
)
except TypeError:
# Gate has no unitary protocol
return NotImplemented

def _commutes_on_qids_(
self, qids: 'Sequence[cirq.Qid]', other: Any, *, atol: float = 1e-8
) -> Union[bool, NotImplementedType, None]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,9 @@ def test_equal_up_to_global_phase_eq_supported():
# cast types
assert cirq.equal_up_to_global_phase(A(0.1), A(0.1j), atol=1e-2)
assert not cirq.equal_up_to_global_phase(1e-8j, B(0.0), atol=1e-10)


def test_equal_up_to_global_phase_non_eigen_gates():
gate1 = cirq.PhasedXPowGate(phase_exponent=1.5, exponent=1.0)
gate2 = cirq.PhasedXPowGate(phase_exponent=0.5, exponent=1.0)
assert cirq.equal_up_to_global_phase(gate1, gate2)

0 comments on commit 8cb7719

Please sign in to comment.