Skip to content

Commit a759e41

Browse files
authored
Add get_device for engine_processor (#2954)
* 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.
1 parent f907314 commit a759e41

File tree

4 files changed

+75
-25
lines changed

4 files changed

+75
-25
lines changed

cirq/google/engine/engine_processor.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@
1313
# limitations under the License.
1414
import datetime
1515

16-
from typing import List, Optional, TYPE_CHECKING, Union, Tuple
16+
from typing import Iterable, List, Optional, TYPE_CHECKING, Union
1717
from pytz import utc
1818

1919
from cirq.google.engine.client.quantum import types as qtypes
2020
from cirq.google.engine.client.quantum import enums as qenums
21+
from cirq.google import serializable_gate_set
2122
from cirq.google.api import v2
23+
from cirq.google.devices import serializable_device
2224
from cirq.google.engine import calibration
2325
from cirq.google.engine.engine_timeslot import EngineTimeSlot
2426

2527
if TYPE_CHECKING:
2628
import cirq.google.engine.engine as engine_base
29+
import cirq
2730

2831

2932
class EngineProcessor:
@@ -108,6 +111,21 @@ def get_device_specification(
108111
else:
109112
return None
110113

114+
def get_device(
115+
self, gate_sets: Iterable[serializable_gate_set.SerializableGateSet]
116+
) -> 'cirq.Device':
117+
"""Returns a `Device` created from the processor's device specification.
118+
119+
This method queries the processor to retrieve the device specification,
120+
which is then use to create a `SerializableDevice` that will validate
121+
that operations are supported and use the correct qubits.
122+
"""
123+
spec = self.get_device_specification()
124+
if not spec:
125+
raise ValueError('Processor does not have a device specification')
126+
return serializable_device.SerializableDevice.from_proto(
127+
spec, gate_sets)
128+
111129
@staticmethod
112130
def _to_calibration(calibration_any: qtypes.any_pb2.Any
113131
) -> calibration.Calibration:

cirq/google/engine/engine_processor_test.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from google.protobuf.duration_pb2 import Duration
2121
from google.protobuf.text_format import Merge
2222
from google.protobuf.timestamp_pb2 import Timestamp
23+
import cirq
2324
import cirq.google as cg
2425
from cirq.google.api import v2
2526
from cirq.google.engine.engine import EngineContext
@@ -107,6 +108,21 @@ def _to_timestamp(json_string):
107108
""", v2.device_pb2.DeviceSpecification()))
108109

109110

111+
_GATE_SET = cg.SerializableGateSet(
112+
gate_set_name='x_gate_set',
113+
serializers=[
114+
cg.GateOpSerializer(gate_type=cirq.XPowGate,
115+
serialized_gate_id='x',
116+
args=[])
117+
],
118+
deserializers=[
119+
cg.GateOpDeserializer(serialized_gate_id='x',
120+
gate_constructor=cirq.XPowGate,
121+
args=[])
122+
],
123+
)
124+
125+
110126
@pytest.fixture(scope='session', autouse=True)
111127
def mock_grpc_client():
112128
with mock.patch('cirq.google.engine.engine_client'
@@ -211,6 +227,30 @@ def test_get_device_specification():
211227
assert processor.get_device_specification() == expected
212228

213229

230+
def test_get_device():
231+
processor = cg.EngineProcessor(
232+
'a',
233+
'p',
234+
EngineContext(),
235+
_processor=qtypes.QuantumProcessor(device_spec=_DEVICE_SPEC))
236+
device = processor.get_device(gate_sets=[_GATE_SET])
237+
assert device.qubits == [cirq.GridQubit(0, 0), cirq.GridQubit(1, 1)]
238+
device.validate_operation(cirq.X(cirq.GridQubit(0, 0)))
239+
with pytest.raises(ValueError):
240+
device.validate_operation(cirq.X(cirq.GridQubit(1, 2)))
241+
with pytest.raises(ValueError):
242+
device.validate_operation(cirq.Y(cirq.GridQubit(0, 0)))
243+
244+
245+
def test_get_missing_device():
246+
processor = cg.EngineProcessor('a',
247+
'p',
248+
EngineContext(),
249+
_processor=qtypes.QuantumProcessor())
250+
with pytest.raises(ValueError, match='device specification'):
251+
_ = processor.get_device(gate_sets=[_GATE_SET])
252+
253+
214254
@mock.patch('cirq.google.engine.engine_client.EngineClient.list_calibrations')
215255
def test_list_calibrations(list_calibrations):
216256
list_calibrations.return_value = [_CALIBRATION]

docs/google/devices.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ Since quantum hardware is an active area of research, hardware specifications an
55
practices are constantly evolving in an attempt to continuously improve performance.
66
While this information should be a solid base for beginning your quantum application,
77
please work with your Google sponsor to obtain the latest information on devices that
8-
you plan to use.
8+
you plan to use.
99

1010
## General limitations
1111

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

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

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

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

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

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

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

91-
The device is arrayed on a grid in a diamond pattern like this.
91+
The device is arrayed on a grid in a diamond pattern like this.
9292

9393
```
9494
11
@@ -121,8 +121,3 @@ algorithms on NISQ devices.
121121
It can be accessing by using `cirq.google.Foxtail`. Circuits can be compiled to it by using
122122
`cirq.google.optimized_for_xmon` or by using `cirq.google.optimized_for_sycamore` with
123123
optimizer_type `xmon`.
124-
125-
126-
127-
128-

docs/google/specification.md

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,25 @@ This specification is defined in the Device proto within `cirq.google.api.v2`.
1616

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

2222
### Gate Definitions
2323

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

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

3131
### Gate Durations
3232

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

3636
Example code to print out the gate durations for every gate supported by the
37-
device is shown below:
37+
device is shown below:
3838

3939
```
4040
import cirq
@@ -44,7 +44,7 @@ engine = cirq.google.Engine(project_id='your_project_id',
4444
proto_version=cirq.google.ProtoVersion.V2)
4545
4646
# Replace the processor id to get the device specification with that id.
47-
spec = engine.get_device_specification('processor_id')
47+
spec = engine.get_processor('processor_id').get_device_specification()
4848
4949
# Iterate through each gate set valid on the device.
5050
for gateset in spec.valid_gate_sets:
@@ -82,7 +82,7 @@ the targets is valid. This is typically used for measurement gates. If `q0`,
8282
gate, then `gate.on(q0)`, `gate.on(q1)`, `gate.on(q2)`, `gate.on(q0, q1)`,
8383
`gate.on(q0, q2)`, `gate.on(q1, q2)` and `gate.on(q0, q1, q2)` are all valid
8484
uses of the gate.
85-
85+
8686
### Developer Recommendations
8787

8888
This is a free form text field for additional recommendations and soft
@@ -113,12 +113,9 @@ import cirq.google as cg
113113
engine = cg.Engine(project_id='your_project_id',
114114
proto_version=cirq.google.ProtoVersion.V2)
115115
116-
# Replace the processor id to get the device specification with that id.
117-
spec = engine.get_device_specification('processor_id')
118-
119-
device = cg.SerializableDevice.from_proto(
120-
proto=spec,
121-
gate_sets=[cg.gate_sets.SQRT_ISWAP_GATESET)
116+
# Replace the processor id to get the device with that id.
117+
device = engine.get_processor('processor_id').get_device(
118+
gate_sets=[cg.gate_sets.SQRT_ISWAP_GATESET])
122119
123120
q0, q1 = cirq.LineQubit.range(2)
124121
@@ -127,4 +124,4 @@ cirq.Circuit(cirq.CZ(q0,q1), device=device)
127124
```
128125

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

0 commit comments

Comments
 (0)