Skip to content

Commit

Permalink
Add get_device for engine_processor (#2954)
Browse files Browse the repository at this point in the history
* Add get_device for engine_processor

- Adds get_device() that returns a cirq.Device out of the
device specification.

- Also, cleaned up some documentation that was not using the
engine processor correctly.
  • Loading branch information
dstrain115 committed May 4, 2020
1 parent f907314 commit a759e41
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 25 deletions.
20 changes: 19 additions & 1 deletion cirq/google/engine/engine_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@
# limitations under the License.
import datetime

from typing import List, Optional, TYPE_CHECKING, Union, Tuple
from typing import Iterable, List, Optional, TYPE_CHECKING, Union
from pytz import utc

from cirq.google.engine.client.quantum import types as qtypes
from cirq.google.engine.client.quantum import enums as qenums
from cirq.google import serializable_gate_set
from cirq.google.api import v2
from cirq.google.devices import serializable_device
from cirq.google.engine import calibration
from cirq.google.engine.engine_timeslot import EngineTimeSlot

if TYPE_CHECKING:
import cirq.google.engine.engine as engine_base
import cirq


class EngineProcessor:
Expand Down Expand Up @@ -108,6 +111,21 @@ def get_device_specification(
else:
return None

def get_device(
self, gate_sets: Iterable[serializable_gate_set.SerializableGateSet]
) -> 'cirq.Device':
"""Returns a `Device` created from the processor's device specification.
This method queries the processor to retrieve the device specification,
which is then use to create a `SerializableDevice` that will validate
that operations are supported and use the correct qubits.
"""
spec = self.get_device_specification()
if not spec:
raise ValueError('Processor does not have a device specification')
return serializable_device.SerializableDevice.from_proto(
spec, gate_sets)

@staticmethod
def _to_calibration(calibration_any: qtypes.any_pb2.Any
) -> calibration.Calibration:
Expand Down
40 changes: 40 additions & 0 deletions cirq/google/engine/engine_processor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from google.protobuf.duration_pb2 import Duration
from google.protobuf.text_format import Merge
from google.protobuf.timestamp_pb2 import Timestamp
import cirq
import cirq.google as cg
from cirq.google.api import v2
from cirq.google.engine.engine import EngineContext
Expand Down Expand Up @@ -107,6 +108,21 @@ def _to_timestamp(json_string):
""", v2.device_pb2.DeviceSpecification()))


_GATE_SET = cg.SerializableGateSet(
gate_set_name='x_gate_set',
serializers=[
cg.GateOpSerializer(gate_type=cirq.XPowGate,
serialized_gate_id='x',
args=[])
],
deserializers=[
cg.GateOpDeserializer(serialized_gate_id='x',
gate_constructor=cirq.XPowGate,
args=[])
],
)


@pytest.fixture(scope='session', autouse=True)
def mock_grpc_client():
with mock.patch('cirq.google.engine.engine_client'
Expand Down Expand Up @@ -211,6 +227,30 @@ def test_get_device_specification():
assert processor.get_device_specification() == expected


def test_get_device():
processor = cg.EngineProcessor(
'a',
'p',
EngineContext(),
_processor=qtypes.QuantumProcessor(device_spec=_DEVICE_SPEC))
device = processor.get_device(gate_sets=[_GATE_SET])
assert device.qubits == [cirq.GridQubit(0, 0), cirq.GridQubit(1, 1)]
device.validate_operation(cirq.X(cirq.GridQubit(0, 0)))
with pytest.raises(ValueError):
device.validate_operation(cirq.X(cirq.GridQubit(1, 2)))
with pytest.raises(ValueError):
device.validate_operation(cirq.Y(cirq.GridQubit(0, 0)))


def test_get_missing_device():
processor = cg.EngineProcessor('a',
'p',
EngineContext(),
_processor=qtypes.QuantumProcessor())
with pytest.raises(ValueError, match='device specification'):
_ = processor.get_device(gate_sets=[_GATE_SET])


@mock.patch('cirq.google.engine.engine_client.EngineClient.list_calibrations')
def test_list_calibrations(list_calibrations):
list_calibrations.return_value = [_CALIBRATION]
Expand Down
17 changes: 6 additions & 11 deletions docs/google/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ Since quantum hardware is an active area of research, hardware specifications an
practices are constantly evolving in an attempt to continuously improve performance.
While this information should be a solid base for beginning your quantum application,
please work with your Google sponsor to obtain the latest information on devices that
you plan to use.
you plan to use.

## General limitations

Qubits on Google devices are laid out in a grid structure. Connectivity is limited to
adjacent qubits, either horizontally or vertically.
adjacent qubits, either horizontally or vertically.

Measurement takes much longer than other gates. Currently, the only supported
configuration is to have terminal measurement in the final moment of a circuit.

Most devices have a limited set of gates that can be applied. Gates not in that set
must be decomposed into an equivalent circuit using gates within the set.
See below for those restrictions.
See below for those restrictions.

There are some limitations to the total circuit length due to hardware limitations.
Several factors can influence this limit, but this can be estimated at about 40 microseconds
Expand All @@ -30,12 +30,12 @@ of total circuit run-time. Circuits that exceed this limit will return a

The Sycamore device is a 54 qubit device introduced in 2019 with a
[publication in Nature](https://www.nature.com/articles/s41586-019-1666-5).
Note that the supremacy result in the paper utilized a device that had 53 qubits since
Note that the supremacy result in the paper utilized a device that had 53 qubits since
one qubit had malfunctioned.

It can be accessed using `cirq.GridQubit(row, col)` using grid coordinates specified below.

```
```
0123456789
0 -----AB---
1 ----ABCD--
Expand Down Expand Up @@ -88,7 +88,7 @@ compilation as the Sycamore device.
The Bristlecone processor is a 72 qubit device
[announced by Google in 2018](https://ai.googleblog.com/2018/03/a-preview-of-bristlecone-googles-new.html).

The device is arrayed on a grid in a diamond pattern like this.
The device is arrayed on a grid in a diamond pattern like this.

```
11
Expand Down Expand Up @@ -121,8 +121,3 @@ algorithms on NISQ devices.
It can be accessing by using `cirq.google.Foxtail`. Circuits can be compiled to it by using
`cirq.google.optimized_for_xmon` or by using `cirq.google.optimized_for_sycamore` with
optimizer_type `xmon`.





23 changes: 10 additions & 13 deletions docs/google/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@ This specification is defined in the Device proto within `cirq.google.api.v2`.

Most devices can only accept a limited set of gates. This is known as the
gate set of the device. Any circuits sent to this device must only use gates
within this set. The gate set portion of the protocol buffer defines which
within this set. The gate set portion of the protocol buffer defines which
gate set(s) are valid on the device, and which gates make up that set.

### Gate Definitions

Each gate in the gate set will have a definition that defines the id that
the gate is serialized as, the number of qubits for the gates, the arguments
to the gate, the duration, and which qubits it can be applied to.
to the gate, the duration, and which qubits it can be applied to.

This definition uses "target sets" to specify which qubits the operation can
be applied to. See the section below for more information.
be applied to. See the section below for more information.

### Gate Durations

The time it takes the device to perform each gate is stored within the device
specification. This time is stored as an integer number of picoseconds.

Example code to print out the gate durations for every gate supported by the
device is shown below:
device is shown below:

```
import cirq
Expand All @@ -44,7 +44,7 @@ engine = cirq.google.Engine(project_id='your_project_id',
proto_version=cirq.google.ProtoVersion.V2)
# Replace the processor id to get the device specification with that id.
spec = engine.get_device_specification('processor_id')
spec = engine.get_processor('processor_id').get_device_specification()
# Iterate through each gate set valid on the device.
for gateset in spec.valid_gate_sets:
Expand Down Expand Up @@ -82,7 +82,7 @@ the targets is valid. This is typically used for measurement gates. If `q0`,
gate, then `gate.on(q0)`, `gate.on(q1)`, `gate.on(q2)`, `gate.on(q0, q1)`,
`gate.on(q0, q2)`, `gate.on(q1, q2)` and `gate.on(q0, q1, q2)` are all valid
uses of the gate.

### Developer Recommendations

This is a free form text field for additional recommendations and soft
Expand Down Expand Up @@ -113,12 +113,9 @@ import cirq.google as cg
engine = cg.Engine(project_id='your_project_id',
proto_version=cirq.google.ProtoVersion.V2)
# Replace the processor id to get the device specification with that id.
spec = engine.get_device_specification('processor_id')
device = cg.SerializableDevice.from_proto(
proto=spec,
gate_sets=[cg.gate_sets.SQRT_ISWAP_GATESET)
# Replace the processor id to get the device with that id.
device = engine.get_processor('processor_id').get_device(
gate_sets=[cg.gate_sets.SQRT_ISWAP_GATESET])
q0, q1 = cirq.LineQubit.range(2)
Expand All @@ -127,4 +124,4 @@ cirq.Circuit(cirq.CZ(q0,q1), device=device)
```

Note that, if network traffic is undesired, the `DeviceSpecification` can
easily be stored in either binary format or TextProto format for later usage.
easily be stored in either binary format or TextProto format for later usage.

0 comments on commit a759e41

Please sign in to comment.