Skip to content

Commit 4f7d3b4

Browse files
authored
Merge branch 'main' into u/maffoo/moment-eq
2 parents 2a31f47 + 181d7aa commit 4f7d3b4

File tree

14 files changed

+267
-59
lines changed

14 files changed

+267
-59
lines changed

cirq-core/cirq/_compat.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ def with_debug(value: bool) -> Iterator[None]:
6767
from backports.cached_property import cached_property # type: ignore[no-redef]
6868

6969

70+
# Sentinel used by wrapped_no_args below when method has not yet been cached.
71+
_NOT_FOUND = object()
72+
73+
7074
TFunc = TypeVar('TFunc', bound=Callable)
7175

7276

@@ -103,9 +107,11 @@ def decorator(func):
103107

104108
@functools.wraps(func)
105109
def wrapped_no_args(self):
106-
if not hasattr(self, cache_name):
107-
object.__setattr__(self, cache_name, func(self))
108-
return getattr(self, cache_name)
110+
result = getattr(self, cache_name, _NOT_FOUND)
111+
if result is _NOT_FOUND:
112+
result = func(self)
113+
object.__setattr__(self, cache_name, result)
114+
return result
109115

110116
return wrapped_no_args
111117

cirq-core/cirq/circuits/circuit.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
AbstractSet,
3030
Any,
3131
Callable,
32-
Mapping,
33-
MutableSequence,
3432
cast,
3533
Dict,
3634
FrozenSet,
3735
Iterable,
3836
Iterator,
3937
List,
38+
Mapping,
39+
MutableSequence,
4040
Optional,
4141
overload,
4242
Sequence,
@@ -58,9 +58,9 @@
5858
from cirq.circuits._bucket_priority_queue import BucketPriorityQueue
5959
from cirq.circuits.circuit_operation import CircuitOperation
6060
from cirq.circuits.insert_strategy import InsertStrategy
61+
from cirq.circuits.moment import Moment
6162
from cirq.circuits.qasm_output import QasmOutput
6263
from cirq.circuits.text_diagram_drawer import TextDiagramDrawer
63-
from cirq.circuits.moment import Moment
6464
from cirq.protocols import circuit_diagram_info_protocol
6565
from cirq.type_workarounds import NotImplementedType
6666

@@ -203,19 +203,24 @@ def unfreeze(self, copy: bool = True) -> 'cirq.Circuit':
203203
copy: If True and 'self' is a Circuit, returns a copy that circuit.
204204
"""
205205

206-
def __bool__(self):
206+
def __bool__(self) -> bool:
207207
return bool(self.moments)
208208

209-
def __eq__(self, other):
209+
def __eq__(self, other) -> bool:
210210
if not isinstance(other, AbstractCircuit):
211211
return NotImplemented
212-
return tuple(self.moments) == tuple(other.moments)
212+
return other is self or (
213+
len(self.moments) == len(other.moments)
214+
and all(m0 == m1 for m0, m1 in zip(self.moments, other.moments))
215+
)
213216

214217
def _approx_eq_(self, other: Any, atol: Union[int, float]) -> bool:
215218
"""See `cirq.protocols.SupportsApproximateEquality`."""
216219
if not isinstance(other, AbstractCircuit):
217220
return NotImplemented
218-
return cirq.protocols.approx_eq(tuple(self.moments), tuple(other.moments), atol=atol)
221+
return other is self or cirq.protocols.approx_eq(
222+
tuple(self.moments), tuple(other.moments), atol=atol
223+
)
219224

220225
def __ne__(self, other) -> bool:
221226
return not self == other

cirq-core/cirq/contrib/quimb/mps_simulator_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ def test_random_circuits_equal_more_rows():
335335
assert_same_output_as_dense(circuit, qubits)
336336

337337

338-
def test_supremacy_equal_more_cols():
338+
def test_random_circuits_equal_more_cols():
339339
circuit = cirq.testing.random_circuit(
340340
qubits=cirq.GridQubit.rect(2, 3), n_moments=6, op_density=1.0
341341
)

cirq-core/cirq/devices/grid_qubit.py

+34-8
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ class _BaseGridQid(ops.Qid):
3333
_row: int
3434
_col: int
3535
_dimension: int
36+
_comp_key: Optional[Tuple[int, int]] = None
3637
_hash: Optional[int] = None
3738

3839
def __hash__(self) -> int:
3940
if self._hash is None:
4041
self._hash = hash((self._row, self._col, self._dimension))
4142
return self._hash
4243

43-
def __eq__(self, other):
44+
def __eq__(self, other) -> bool:
4445
# Explicitly implemented for performance (vs delegating to Qid).
4546
if isinstance(other, _BaseGridQid):
4647
return self is other or (
@@ -50,7 +51,7 @@ def __eq__(self, other):
5051
)
5152
return NotImplemented
5253

53-
def __ne__(self, other):
54+
def __ne__(self, other) -> bool:
5455
# Explicitly implemented for performance (vs delegating to Qid).
5556
if isinstance(other, _BaseGridQid):
5657
return self is not other and (
@@ -60,8 +61,38 @@ def __ne__(self, other):
6061
)
6162
return NotImplemented
6263

64+
def __lt__(self, other) -> bool:
65+
# Explicitly implemented for performance (vs delegating to Qid).
66+
if isinstance(other, _BaseGridQid):
67+
k0, k1 = self._comparison_key(), other._comparison_key()
68+
return k0 < k1 or (k0 == k1 and self._dimension < other._dimension)
69+
return super().__lt__(other)
70+
71+
def __le__(self, other) -> bool:
72+
# Explicitly implemented for performance (vs delegating to Qid).
73+
if isinstance(other, _BaseGridQid):
74+
k0, k1 = self._comparison_key(), other._comparison_key()
75+
return k0 < k1 or (k0 == k1 and self._dimension <= other._dimension)
76+
return super().__le__(other)
77+
78+
def __ge__(self, other) -> bool:
79+
# Explicitly implemented for performance (vs delegating to Qid).
80+
if isinstance(other, _BaseGridQid):
81+
k0, k1 = self._comparison_key(), other._comparison_key()
82+
return k0 > k1 or (k0 == k1 and self._dimension >= other._dimension)
83+
return super().__ge__(other)
84+
85+
def __gt__(self, other) -> bool:
86+
# Explicitly implemented for performance (vs delegating to Qid).
87+
if isinstance(other, _BaseGridQid):
88+
k0, k1 = self._comparison_key(), other._comparison_key()
89+
return k0 > k1 or (k0 == k1 and self._dimension > other._dimension)
90+
return super().__gt__(other)
91+
6392
def _comparison_key(self):
64-
return self._row, self._col
93+
if self._comp_key is None:
94+
self._comp_key = self._row, self._col
95+
return self._comp_key
6596

6697
@property
6798
def row(self) -> int:
@@ -359,11 +390,6 @@ def __getnewargs__(self):
359390
def _with_row_col(self, row: int, col: int) -> 'GridQubit':
360391
return GridQubit(row, col)
361392

362-
def _cmp_tuple(self):
363-
cls = GridQid if type(self) is GridQubit else type(self)
364-
# Must be same as Qid._cmp_tuple but with cls in place of type(self).
365-
return (cls.__name__, repr(cls), self._comparison_key(), self.dimension)
366-
367393
@staticmethod
368394
def square(diameter: int, top: int = 0, left: int = 0) -> List['GridQubit']:
369395
"""Returns a square of GridQubits.

cirq-core/cirq/devices/line_qubit.py

+34-8
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,52 @@ def __hash__(self) -> int:
3737
self._hash = hash((self._x, self._dimension))
3838
return self._hash
3939

40-
def __eq__(self, other):
40+
def __eq__(self, other) -> bool:
4141
# Explicitly implemented for performance (vs delegating to Qid).
4242
if isinstance(other, _BaseLineQid):
4343
return self is other or (self._x == other._x and self._dimension == other._dimension)
4444
return NotImplemented
4545

46-
def __ne__(self, other):
46+
def __ne__(self, other) -> bool:
4747
# Explicitly implemented for performance (vs delegating to Qid).
4848
if isinstance(other, _BaseLineQid):
4949
return self is not other and (
5050
self._x != other._x or self._dimension != other._dimension
5151
)
5252
return NotImplemented
5353

54+
def __lt__(self, other) -> bool:
55+
# Explicitly implemented for performance (vs delegating to Qid).
56+
if isinstance(other, _BaseLineQid):
57+
return self._x < other._x or (
58+
self._x == other._x and self._dimension < other._dimension
59+
)
60+
return super().__lt__(other)
61+
62+
def __le__(self, other) -> bool:
63+
# Explicitly implemented for performance (vs delegating to Qid).
64+
if isinstance(other, _BaseLineQid):
65+
return self._x < other._x or (
66+
self._x == other._x and self._dimension <= other._dimension
67+
)
68+
return super().__le__(other)
69+
70+
def __ge__(self, other) -> bool:
71+
# Explicitly implemented for performance (vs delegating to Qid).
72+
if isinstance(other, _BaseLineQid):
73+
return self._x > other._x or (
74+
self._x == other._x and self._dimension >= other._dimension
75+
)
76+
return super().__ge__(other)
77+
78+
def __gt__(self, other) -> bool:
79+
# Explicitly implemented for performance (vs delegating to Qid).
80+
if isinstance(other, _BaseLineQid):
81+
return self._x > other._x or (
82+
self._x == other._x and self._dimension > other._dimension
83+
)
84+
return super().__gt__(other)
85+
5486
def _comparison_key(self):
5587
return self._x
5688

@@ -279,12 +311,6 @@ def __getnewargs__(self):
279311
def _with_x(self, x: int) -> 'LineQubit':
280312
return LineQubit(x)
281313

282-
def _cmp_tuple(self):
283-
cls = LineQid if type(self) is LineQubit else type(self)
284-
# Must be the same as Qid._cmp_tuple but with cls in place of
285-
# type(self).
286-
return (cls.__name__, repr(cls), self._comparison_key(), self._dimension)
287-
288314
@staticmethod
289315
def range(*range_args) -> List['LineQubit']:
290316
"""Returns a range of line qubits.

cirq-core/cirq/experiments/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
TomographyResult,
2121
two_qubit_randomized_benchmarking,
2222
two_qubit_state_tomography,
23+
parallel_single_qubit_randomized_benchmarking,
2324
)
2425

2526
from cirq.experiments.fidelity_estimation import (

0 commit comments

Comments
 (0)