From 53880e6722208eed33efc877b6bc72800a5f193e Mon Sep 17 00:00:00 2001 From: Cheng Xing Date: Wed, 6 Apr 2022 00:34:46 +0000 Subject: [PATCH] GoogleDevice, minus gateset and gate durations --- .../cirq/devices/grid_device_metadata.py | 7 +- cirq-core/cirq/ops/gateset.py | 3 +- cirq-google/cirq_google/__init__.py | 1 + cirq-google/cirq_google/devices/__init__.py | 4 + .../cirq_google/devices/google_device.py | 226 ++++++++++++++++++ .../cirq_google/devices/google_device_test.py | 207 ++++++++++++++++ .../cirq_google/json_resolver_cache.py | 1 + .../json_test_data/GoogleDevice.json | 204 ++++++++++++++++ .../json_test_data/GoogleDevice.repr | 1 + 9 files changed, 652 insertions(+), 2 deletions(-) create mode 100644 cirq-google/cirq_google/devices/google_device.py create mode 100644 cirq-google/cirq_google/devices/google_device_test.py create mode 100644 cirq-google/cirq_google/json_test_data/GoogleDevice.json create mode 100644 cirq-google/cirq_google/json_test_data/GoogleDevice.repr diff --git a/cirq-core/cirq/devices/grid_device_metadata.py b/cirq-core/cirq/devices/grid_device_metadata.py index e0ccd2d55f68..ca8d00c05ae9 100644 --- a/cirq-core/cirq/devices/grid_device_metadata.py +++ b/cirq-core/cirq/devices/grid_device_metadata.py @@ -169,4 +169,9 @@ def _json_dict_(self): @classmethod def _from_json_dict_(cls, qubit_pairs, gateset, gate_durations, all_qubits, **kwargs): - return cls(qubit_pairs, gateset, dict(gate_durations), all_qubits) + return cls( + qubit_pairs, + gateset, + None if gate_durations is None else dict(gate_durations), + all_qubits, + ) diff --git a/cirq-core/cirq/ops/gateset.py b/cirq-core/cirq/ops/gateset.py index 43ef71026ee8..f50606269867 100644 --- a/cirq-core/cirq/ops/gateset.py +++ b/cirq-core/cirq/ops/gateset.py @@ -406,9 +406,10 @@ def _value_equality_values_(self) -> Any: def __repr__(self) -> str: name_str = f'name = "{self.name}", ' if self.name is not None else '' + gates_str = f'{self._gates_repr_str}, ' if len(self._gates_repr_str) > 0 else '' return ( f'cirq.Gateset(' - f'{self._gates_repr_str}, ' + f'{gates_str}' f'{name_str}' f'unroll_circuit_op = {self._unroll_circuit_op},' f'accept_global_phase_op = {self._accept_global_phase_op})' diff --git a/cirq-google/cirq_google/__init__.py b/cirq-google/cirq_google/__init__.py index c253ac20c1c2..105abd20fe48 100644 --- a/cirq-google/cirq_google/__init__.py +++ b/cirq-google/cirq_google/__init__.py @@ -59,6 +59,7 @@ from cirq_google.devices import ( Bristlecone, Foxtail, + GoogleDevice, SerializableDevice, Sycamore, Sycamore23, diff --git a/cirq-google/cirq_google/devices/__init__.py b/cirq-google/cirq_google/devices/__init__.py index 9746693735ab..8c9c3650dc2c 100644 --- a/cirq-google/cirq_google/devices/__init__.py +++ b/cirq-google/cirq_google/devices/__init__.py @@ -19,6 +19,10 @@ Sycamore23, ) +from cirq_google.devices.google_device import ( + GoogleDevice, +) + from cirq_google.devices.serializable_device import ( SerializableDevice, ) diff --git a/cirq-google/cirq_google/devices/google_device.py b/cirq-google/cirq_google/devices/google_device.py new file mode 100644 index 000000000000..c9d526086ccc --- /dev/null +++ b/cirq-google/cirq_google/devices/google_device.py @@ -0,0 +1,226 @@ +# 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. + +"""Device object representing Google devices.""" + +from typing import Any, Set, Tuple, cast +import cirq +from cirq_google.api import v2 + + +@cirq.value_equality +class GoogleDevice(cirq.Device): + """Device object representing Google devices. + + For end users, instances of this class are typically accessed via + `Engine.get_processor('processor_name').get_device()`. + + This class is compliant with the core `cirq.Device` abstraction. In particular: + * Device information is captured in the `metadata` property. + * An instance of `GoogleDevice` can be used to validate circuits, moments, and operations. + + Example use cases: + + * Get an instance of a Google device. + >>> device = cirq_google.get_engine().get_processor('weber').get_device() + + * Print the grid layout of the device. + >>> print(device) + + * Determine whether a circuit can be run on the device. + >>> device.validate_circuit(circuit) # Raises an exception if the circuit is invalid. + + * Determine whether an operation can be run on the device. + >>> device.validate_operation(operation) # Raises an exception if the operation is invalid. + + * Get the `cirq.Gateset` containing valid gates for the device, and inspect the full list + of valid gates. + >>> gateset = device.metadata.gateset + >>> print(gateset) + + * Determine whether a gate is available on the device. + >>> gate in device.metadata.gateset + + * Get a collection of valid qubits on the device. + >>> device.metadata.qubit_set + + * Get a collection of valid qubit pairs for two-qubit gates. + >>> device.metadata.qubit_pairs + + * Get a collection of isolated qubits, i.e. qubits which are not part of any qubit pair. + >>> device.metadata.isolated_qubits + + * Get a collection of approximate durations of performing each gate supported by the device. + >>> device.metadata.gate_durations + + TODO(#5050) Add compilation_target_gatesets example. + + Notes for cirq_google internal implementation: + + For Google devices, the + [DeviceSpecification proto]( + https://github.com/quantumlib/Cirq/blob/3969c2d3964cea56df33b329f036ba6810683882/cirq-google/cirq_google/api/v2/device.proto#L13 + ) + is the main specification for device information surfaced by the Quantum Computing Service. + Thus, this class is should be instantiated using a `DeviceSpecification` proto via the + `from_proto()` class method. + """ + + def __init__(self, metadata: cirq.GridDeviceMetadata): + """Creates a GoogleDevice object. + + This constructor typically should not be used directly. Use `from_proto()` instead. + """ + self._metadata = metadata + + @classmethod + def from_proto(cls, proto: v2.device_pb2.DeviceSpecification) -> 'GoogleDevice': + """Create a `GoogleDevice` from a DeviceSpecification proto. + + This class only supports `cirq.GridQubit`s and `cirq.NamedQubit`s. If a + `DeviceSpecification.valid_qubits` string is in the form `_`, it is parsed as a + GridQubit. Otherwise it is parsed as a NamedQubit. + + Args: + proto: The `DeviceSpecification` proto describing a Google device. + + Raises: + ValueError: If the given `DeviceSpecification` is invalid. + """ + + # Create qubit set + all_qubits = [_qid_from_str(q) for q in proto.valid_qubits] + + # Create qubit pair set + # + # While the `GateSpecification` proto message contains qubit target references, they are + # ignored here because the following assumptions make them unnecessary currently: + # * All valid qubit pairs work for all two-qubit gates. + # * All valid qubits work for all single-qubit gates. + # * Measurement gate can always be applied to all subset of qubits. + # + # TODO(#5169) Consider adding the reversed pair, depending on the issue's solution. + qubit_pairs = [ + (_qid_from_str(target.ids[0]), _qid_from_str(target.ids[1])) + for ts in proto.valid_targets + for target in ts.targets + if len(target.ids) == 2 and ts.target_ordering == v2.device_pb2.TargetSet.SYMMETRIC + ] + + # TODO(#5050) implement gate durations + try: + metadata = cirq.GridDeviceMetadata( + qubit_pairs=qubit_pairs, + gateset=cirq.Gateset(), # TODO(#5050) implement + all_qubits=all_qubits, + ) + except ValueError as ve: + raise ValueError("DeviceSpecification is invalid.") from ve + + return GoogleDevice(metadata) + + @property + def metadata(self): + """Get metadata information for the device.""" + return self._metadata + + def validate_operation(self, operation: cirq.Operation) -> None: + """Raises an exception if an operation is not valid. + + An operation is valid if + * The operation is in the device gateset. + * The operation targets a valid qubit + * The operation targets a valid qubit pair, if it is a two-qubit operation. + + Args: + operation: The operation to validate. + + Raises: + ValueError: The operation isn't valid for this device. + """ + # TODO(#5050) uncomment once gateset logic is implemented + # if operation not in self._metadata.gateset: + # raise ValueError(f'Operation {operation} is not a supported gate') + + for q in operation.qubits: + if q not in self._metadata.qubit_set: + raise ValueError(f'Qubit not on device: {q!r}') + + # TODO(#5169) May need to check the reverse pair depending on the issue's solution. + if len(operation.qubits) == 2 and tuple(operation.qubits) not in self._metadata.qubit_pairs: + raise ValueError(f'Qubit pair is not valid on device: {operation.qubits!r}') + + def __str__(self) -> str: + # If all qubits are grid qubits, render an appropriate text diagram. + if all(isinstance(q, cirq.GridQubit) for q in self._metadata.qubit_set): + diagram = cirq.TextDiagramDrawer() + + qubits = cast(Set[cirq.GridQubit], self._metadata.qubit_set) + + # Don't print out extras newlines if the row/col doesn't start at 0 + min_col = min(q.col for q in qubits) + min_row = min(q.row for q in qubits) + + for q in qubits: + diagram.write(q.col - min_col, q.row - min_row, str(q)) + + # Find pairs that are connected by two-qubit gates. + Pair = Tuple[cirq.GridQubit, cirq.GridQubit] + pairs = sorted({cast(Pair, pair) for pair in self._metadata.qubit_pairs}) + + # Draw lines between connected pairs. Limit to horizontal/vertical + # lines since that is all the diagram drawer can handle. + for q1, q2 in pairs: + if q1.row == q2.row or q1.col == q2.col: + diagram.grid_line( + q1.col - min_col, q1.row - min_row, q2.col - min_col, q2.row - min_row + ) + + return diagram.render( + horizontal_spacing=3, vertical_spacing=2, use_unicode_characters=True + ) + + return super().__str__() + + def _repr_pretty_(self, p: Any, cycle: bool) -> None: + """Creates ASCII diagram for Jupyter, IPython, etc.""" + # There should never be a cycle, but just in case use the default repr. + p.text(repr(self) if cycle else str(self)) + + def __repr__(self) -> str: + return f'cirq_google.GoogleDevice({repr(self._metadata)})' + + def _json_dict_(self): + return { + 'metadata': self._metadata, + } + + @classmethod + def _from_json_dict_(cls, metadata, **kwargs): + return cls(metadata) + + def _value_equality_values_(self): + return self._metadata + + +def _qid_from_str(id_str: str) -> cirq.Qid: + """Translates a qubit id string info cirq.Qid objects. + + Tries to translate to GridQubit if possible (e.g. '4_3'), otherwise + falls back to using NamedQubit. + """ + try: + return v2.grid_qubit_from_proto_id(id_str) + except ValueError: + return v2.named_qubit_from_proto_id(id_str) diff --git a/cirq-google/cirq_google/devices/google_device_test.py b/cirq-google/cirq_google/devices/google_device_test.py new file mode 100644 index 000000000000..8fd9cb863e13 --- /dev/null +++ b/cirq-google/cirq_google/devices/google_device_test.py @@ -0,0 +1,207 @@ +# 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 unittest.mock as mock + +import pytest + +import cirq +import cirq_google +from cirq_google.api import v2 + + +GRID_HEIGHT = 5 + + +def _create_device_spec_with_horizontal_couplings(): + # Qubit layout: + # x -- x + # x -- x + # x -- x + # x -- x + # x -- x + + grid_qubits = [cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2)] + spec = v2.device_pb2.DeviceSpecification() + spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits]) + grid_targets = spec.valid_targets.add() + grid_targets.name = '2_qubit_targets' + grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC + for row in range(GRID_HEIGHT): + new_target = grid_targets.targets.add() + new_target.ids.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, j)) for j in range(2)]) + gate = spec.valid_gates.add() + gate.syc.SetInParent() + gate.gate_duration_picos = 12000 + gate.valid_targets.extend(['2_qubit_targets']) + + return grid_qubits, spec + + +def _create_device_spec_with_all_couplings(): + # Qubit layout: + # x -- x + # | | + # x -- x + # | | + # x -- x + # | | + # x -- x + # | | + # x -- x + + grid_qubits, spec = _create_device_spec_with_horizontal_couplings() + for row in range(GRID_HEIGHT - 1): + for col in range(2): + new_target = spec.valid_targets[0].targets.add() + new_target.ids.extend( + [ + v2.qubit_to_proto_id(cirq.GridQubit(row, col)), + v2.qubit_to_proto_id(cirq.GridQubit(row + 1, col)), + ] + ) + return grid_qubits, spec + + +def _create_device_spec_with_qubit_pair_self_loops() -> v2.device_pb2.DeviceSpecification: + q_proto_id = v2.qubit_to_proto_id(cirq.NamedQubit('q')) + + spec = v2.device_pb2.DeviceSpecification() + spec.valid_qubits.extend([q_proto_id]) + targets = spec.valid_targets.add() + targets.name = 'test_targets' + targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC + new_target = targets.targets.add() + new_target.ids.extend([q_proto_id, q_proto_id]) + + return spec + + +def _create_device_spec_with_invalid_qubit_in_qubit_pair() -> v2.device_pb2.DeviceSpecification: + q_proto_ids = [v2.qubit_to_proto_id(cirq.GridQubit(0, i)) for i in range(2)] + + spec = v2.device_pb2.DeviceSpecification() + spec.valid_qubits.extend([q_proto_ids[0]]) + targets = spec.valid_targets.add() + targets.name = 'test_targets' + targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC + new_target = targets.targets.add() + new_target.ids.extend([q_proto_ids[0], q_proto_ids[1]]) + + return spec + + +def test_google_device_from_proto_and_validation(): + grid_qubits, spec = _create_device_spec_with_horizontal_couplings() + + device = cirq_google.GoogleDevice.from_proto(spec) + + assert len(device.metadata.qubit_set) == len(grid_qubits) + assert device.metadata.qubit_set == frozenset(grid_qubits) + assert all( + (cirq.GridQubit(row, 0), cirq.GridQubit(row, 1)) in device.metadata.qubit_pairs + for row in range(GRID_HEIGHT) + ) + + +def test_google_device_validate_operations_positive(): + grid_qubits, spec = _create_device_spec_with_horizontal_couplings() + device = cirq_google.GoogleDevice.from_proto(spec) + + for q in grid_qubits: + device.validate_operation(cirq.X(q)) + + # horizontal qubit pairs + for i in range(GRID_HEIGHT): + device.validate_operation(cirq.CZ(grid_qubits[2 * i], grid_qubits[2 * i + 1])) + + # TODO(#5050) verify validate_operations gateset support + + +def test_google_device_validate_operations_negative(): + grid_qubits, spec = _create_device_spec_with_horizontal_couplings() + device = cirq_google.GoogleDevice.from_proto(spec) + + q = cirq.GridQubit(10, 10) + with pytest.raises(ValueError, match='Qubit not on device'): + device.validate_operation(cirq.X(q)) + + # vertical qubit pair + q00, q10 = grid_qubits[0], grid_qubits[2] # (0, 0), (1, 0) + with pytest.raises(ValueError, match='Qubit pair is not valid'): + device.validate_operation(cirq.CZ(q00, q10)) + + # TODO(#5050) verify validate_operations gateset errors + + +@pytest.mark.parametrize( + 'spec', + [ + # TODO(#5050) implement once gateset support is implemented + # _create_device_spec_with_missing_gate_durations(), + _create_device_spec_with_qubit_pair_self_loops(), + _create_device_spec_with_invalid_qubit_in_qubit_pair(), + ], +) +def test_google_device_invalid_device_spec(spec): + with pytest.raises(ValueError, match='DeviceSpecification is invalid'): + cirq_google.GoogleDevice.from_proto(spec) + + +def test_google_device_repr_json(): + _, spec = _create_device_spec_with_horizontal_couplings() + device = cirq_google.GoogleDevice.from_proto(spec) + + assert eval(repr(device)) == device + assert cirq.read_json(json_text=cirq.to_json(device)) == device + + +def test_google_device_str_grid_qubits(): + _, spec = _create_device_spec_with_all_couplings() + device = cirq_google.GoogleDevice.from_proto(spec) + + assert ( + str(device) + == """\ +(0, 0)───(0, 1) +│ │ +│ │ +(1, 0)───(1, 1) +│ │ +│ │ +(2, 0)───(2, 1) +│ │ +│ │ +(3, 0)───(3, 1) +│ │ +│ │ +(4, 0)───(4, 1)""" + ) + + +@pytest.mark.parametrize('cycle,func', [(False, str), (True, repr)]) +def test_google_device_repr_pretty(cycle, func): + _, spec = _create_device_spec_with_all_couplings() + device = cirq_google.GoogleDevice.from_proto(spec) + printer = mock.Mock() + device._repr_pretty_(printer, cycle) + printer.text.assert_called_once_with(func(device)) + + +def test_serializable_device_str_named_qubits(): + q_proto_id = v2.qubit_to_proto_id(cirq.NamedQubit('q')) + spec = v2.device_pb2.DeviceSpecification() + spec.valid_qubits.extend([q_proto_id]) + device = cirq_google.GoogleDevice.from_proto(spec) + assert device.__class__.__name__ in str(device) diff --git a/cirq-google/cirq_google/json_resolver_cache.py b/cirq-google/cirq_google/json_resolver_cache.py index db11e11eae00..4efcd6485043 100644 --- a/cirq-google/cirq_google/json_resolver_cache.py +++ b/cirq-google/cirq_google/json_resolver_cache.py @@ -32,6 +32,7 @@ def _class_resolver_dictionary() -> Dict[str, ObjectFactory]: 'CouplerPulse': cirq_google.experimental.CouplerPulse, 'SycamoreGate': cirq_google.SycamoreGate, 'GateTabulation': cirq_google.GateTabulation, + 'GoogleDevice': cirq_google.GoogleDevice, 'PhysicalZTag': cirq_google.PhysicalZTag, 'FSimGateFamily': cirq_google.FSimGateFamily, 'FloquetPhasedFSimCalibrationOptions': cirq_google.FloquetPhasedFSimCalibrationOptions, diff --git a/cirq-google/cirq_google/json_test_data/GoogleDevice.json b/cirq-google/cirq_google/json_test_data/GoogleDevice.json new file mode 100644 index 000000000000..890ce5c3648e --- /dev/null +++ b/cirq-google/cirq_google/json_test_data/GoogleDevice.json @@ -0,0 +1,204 @@ +{ + "cirq_type": "GoogleDevice", + "metadata": { + "cirq_type": "GridDeviceMetadata", + "qubit_pairs": [ + [ + { + "cirq_type": "GridQubit", + "row": 0, + "col": 0 + }, + { + "cirq_type": "GridQubit", + "row": 0, + "col": 1 + } + ], + [ + { + "cirq_type": "GridQubit", + "row": 0, + "col": 0 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 0 + } + ], + [ + { + "cirq_type": "GridQubit", + "row": 0, + "col": 1 + }, + { + "cirq_type": "GridQubit", + "row": 0, + "col": 2 + } + ], + [ + { + "cirq_type": "GridQubit", + "row": 0, + "col": 1 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 1 + } + ], + [ + { + "cirq_type": "GridQubit", + "row": 0, + "col": 2 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 2 + } + ], + [ + { + "cirq_type": "GridQubit", + "row": 1, + "col": 0 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 1 + } + ], + [ + { + "cirq_type": "GridQubit", + "row": 1, + "col": 1 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 2 + } + ] + ], + "gateset": { + "cirq_type": "Gateset", + "gates": [ + { + "cirq_type": "GateFamily", + "gate": "XPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.XPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.XPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "GateFamily", + "gate": "YPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "GateFamily", + "gate": "ZPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.ZPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.ZPowGate)`", + "ignore_global_phase": true + } + ], + "name": null, + "unroll_circuit_op": true, + "accept_global_phase_op": true + }, + "gate_durations": [ + [ + { + "cirq_type": "GateFamily", + "gate": "XPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.XPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.XPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "Duration", + "picos": 1000 + } + ], + [ + { + "cirq_type": "GateFamily", + "gate": "YPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.YPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.YPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "Duration", + "picos": 1 + } + ], + [ + { + "cirq_type": "GateFamily", + "gate": "ZPowGate", + "name": "Type GateFamily: cirq.ops.common_gates.ZPowGate", + "description": "Accepts `cirq.Gate` instances `g` s.t. `isinstance(g, cirq.ops.common_gates.ZPowGate)`", + "ignore_global_phase": true + }, + { + "cirq_type": "Duration", + "picos": 1 + } + ] + ], + "all_qubits": [ + { + "cirq_type": "GridQubit", + "row": 0, + "col": 0 + }, + { + "cirq_type": "GridQubit", + "row": 0, + "col": 1 + }, + { + "cirq_type": "GridQubit", + "row": 0, + "col": 2 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 0 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 1 + }, + { + "cirq_type": "GridQubit", + "row": 1, + "col": 2 + }, + { + "cirq_type": "GridQubit", + "row": 9, + "col": 9 + }, + { + "cirq_type": "GridQubit", + "row": 10, + "col": 10 + } + ] + } +} \ No newline at end of file diff --git a/cirq-google/cirq_google/json_test_data/GoogleDevice.repr b/cirq-google/cirq_google/json_test_data/GoogleDevice.repr new file mode 100644 index 000000000000..6b7b096bacac --- /dev/null +++ b/cirq-google/cirq_google/json_test_data/GoogleDevice.repr @@ -0,0 +1 @@ +cirq_google.GoogleDevice(cirq.GridDeviceMetadata(frozenset({(cirq.GridQubit(1, 1), cirq.GridQubit(1, 2)), (cirq.GridQubit(0, 2), cirq.GridQubit(1, 2)), (cirq.GridQubit(1, 0), cirq.GridQubit(1, 1)), (cirq.GridQubit(0, 1), cirq.GridQubit(0, 2)), (cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)), (cirq.GridQubit(0, 1), cirq.GridQubit(1, 1)), (cirq.GridQubit(0, 0), cirq.GridQubit(0, 1))}), cirq.Gateset(cirq.ops.common_gates.XPowGate, cirq.ops.common_gates.YPowGate, cirq.ops.common_gates.ZPowGate, unroll_circuit_op = True,accept_global_phase_op = True), {cirq.GateFamily(gate=cirq.ops.common_gates.XPowGate, ignore_global_phase=True): cirq.Duration(nanos=1), cirq.GateFamily(gate=cirq.ops.common_gates.YPowGate, ignore_global_phase=True): cirq.Duration(picos=1), cirq.GateFamily(gate=cirq.ops.common_gates.ZPowGate, ignore_global_phase=True): cirq.Duration(picos=1)}, frozenset({cirq.GridQubit(0, 0), cirq.GridQubit(1, 2), cirq.GridQubit(1, 0), cirq.GridQubit(0, 2), cirq.GridQubit(10, 10), cirq.GridQubit(0, 1), cirq.GridQubit(1, 1), cirq.GridQubit(9, 9)}))) \ No newline at end of file