Skip to content

Commit

Permalink
Add GridCoupler Qid to cirq_google (#6678)
Browse files Browse the repository at this point in the history
* Add Coupler Qid to cirq_google

- This adds a Qid type to cirq_google that represents the
coupler between two qubits.
  • Loading branch information
dstrain115 authored Jul 26, 2024
1 parent 6e19d0d commit c58a05c
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 0 deletions.
1 change: 1 addition & 0 deletions cirq-google/cirq_google/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from cirq_google._version import __version__

from cirq_google.devices import (
Coupler,
GoogleNoiseProperties,
GridDevice,
NoiseModelFromGoogleNoiseProperties,
Expand Down
2 changes: 2 additions & 0 deletions cirq-google/cirq_google/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@

from cirq_google.devices.known_devices import Sycamore, Sycamore23

from cirq_google.devices.coupler import Coupler

from cirq_google.devices.grid_device import GridDevice
100 changes: 100 additions & 0 deletions cirq-google/cirq_google/devices/coupler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Copyright 2024 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 Any, Dict, Optional, Tuple, TYPE_CHECKING

from cirq import ops, protocols

if TYPE_CHECKING:
import cirq


class Coupler(ops.Qid):
"""A Qid representing the coupler between two qubits."""

_qubit0: ops.Qid
_qubit1: ops.Qid
_hash: Optional[int] = None
_comp_key: Optional[Tuple[Any, Any]] = None

def __new__(cls, qubit0: ops.Qid, qubit1: ops.Qid) -> 'Coupler':
"""Creates a grid coupler between two qubits.
Note that the qubits will be implicitly sorted.
ie. `cirq_google.GridCoupler(q1, q2)` will be the same as
`cirq_google.GridCoupler(q2, q1)`.
Note that, if using custom Qid objects, the Qid must
have an ordering that allows for comparison.
Args:
qubit0: The first qubit/Qid of the pair
qubit1: The second qubit/Qid of the pair
"""
inst = super().__new__(cls)
if qubit0 < qubit1:
inst._qubit0 = qubit0
inst._qubit1 = qubit1
else:
inst._qubit0 = qubit1
inst._qubit1 = qubit0
return inst

def __hash__(self) -> int:
if self._hash is None:
self._hash = hash((self._qubit0, self._qubit1))
return self._hash

def __eq__(self, other) -> bool:
# Explicitly implemented for performance (vs delegating to Qid).
if isinstance(other, Coupler):
return self is other or (
self._qubit0 == other._qubit0 and self._qubit1 == other._qubit1
)
return NotImplemented

def _comparison_key(self):
if self._comp_key is None:
self._comp_key = (self._qubit0._comparison_key(), self.qubit1._comparison_key())
return self._comp_key

@property
def qubit0(self) -> ops.Qid:
return self._qubit0

@property
def qubit1(self) -> ops.Qid:
return self._qubit1

@property
def qubits(self) -> Tuple[ops.Qid, ops.Qid]:
return self._qubit0, self._qubit1

@property
def dimension(self) -> int:
return 2

def __repr__(self) -> str:
return f"cirq_google.Coupler({self._qubit0!r}, {self._qubit1!r})"

def __str__(self) -> str:
return f"c({self._qubit0},{self._qubit1})"

def _circuit_diagram_info_(
self, args: 'cirq.CircuitDiagramInfoArgs'
) -> 'cirq.CircuitDiagramInfo':
return protocols.CircuitDiagramInfo(wire_symbols=(str(self),))

def _json_dict_(self) -> Dict[str, Any]:
return protocols.obj_to_dict_helper(self, ['qubit0', 'qubit1'])
42 changes: 42 additions & 0 deletions cirq-google/cirq_google/devices/coupler_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2024 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 cirq
import cirq_google as cg


def test_grid_coupler():
q1 = cirq.GridQubit(1, 2)
q2 = cirq.GridQubit(2, 2)
grid_coupler = cg.Coupler(q1, q2)
assert grid_coupler.qubit0 == q1
assert grid_coupler.qubit1 == q2
assert grid_coupler.qubits == (q1, q2)
assert cg.Coupler(q2, q1).qubits == (q1, q2)

assert str(grid_coupler) == 'c(q(1, 2),q(2, 2))'
assert cirq.circuit_diagram_info(grid_coupler) == cirq.CircuitDiagramInfo(
wire_symbols=('c(q(1, 2),q(2, 2))',)
)
cirq.testing.assert_equivalent_repr(grid_coupler, global_vals={'cirq_google': cg})


def test_eq():
eq = cirq.testing.EqualsTester()
q1 = cirq.GridQubit(1, 2)
q2 = cirq.GridQubit(2, 2)
q3 = cirq.GridQubit(2, 1)
eq.make_equality_group(lambda: cg.Coupler(q1, q2), lambda: cg.Coupler(q2, q1))
eq.make_equality_group(lambda: cg.Coupler(q2, q3), lambda: cg.Coupler(q3, q2))
eq.make_equality_group(lambda: cg.Coupler(q1, q3), lambda: cg.Coupler(q3, q1))
1 change: 1 addition & 0 deletions cirq-google/cirq_google/json_resolver_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def _old_xmon(*args, **kwargs):
'CalibrationTag': cirq_google.CalibrationTag,
'CalibrationLayer': cirq_google.CalibrationLayer,
'CouplerPulse': cirq_google.experimental.CouplerPulse,
'Coupler': cirq_google.Coupler,
'GoogleNoiseProperties': cirq_google.GoogleNoiseProperties,
'SycamoreGate': cirq_google.SycamoreGate,
# cirq_google.GateTabulation has been removed and replaced by cirq.TwoQubitGateTabulation.
Expand Down
13 changes: 13 additions & 0 deletions cirq-google/cirq_google/json_test_data/Coupler.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"cirq_type": "Coupler",
"qubit0": {
"cirq_type": "GridQubit",
"row": 1,
"col": 2
},
"qubit1": {
"cirq_type": "GridQubit",
"row": 2,
"col": 2
}
}
1 change: 1 addition & 0 deletions cirq-google/cirq_google/json_test_data/Coupler.repr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cirq_google.Coupler(cirq.GridQubit(1,2), cirq.GridQubit(2,2))

0 comments on commit c58a05c

Please sign in to comment.