The device specification proto defines basic layout of a device as well as the gate set and serialized ids that can be used. This specification can be used to find out specific characteristics of though.
Though several standard Google devices are defined for your convenience, specific devices may have specialized layouts particular to that processor. For instance, there may be one or more qubit "drop-outs" that are non-functional for whatever reason. There could also be new or experimental features enabled on some devices but not on others.
This specification is defined in the Device proto within
Gate Set Specifications
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 gate set(s) are valid on the device, and which gates make up that set.
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.
This definition uses "target sets" to specify which qubits the operation can be applied to. See the section below for more information.
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:
import cirq # Create an Engine object to use. engine = cirq.google.Engine(project_id='your_project_id') # Replace the processor id to get the device specification with that 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: print(gateset.name) print('-------') # Prints each gate valid in the set with its duration for gate in gateset.valid_gates: print('%s %d' % (gate.id, gate.gate_duration_picos))
Note that, by convention, measurement gate duration includes both the duration of "read-out" pulses to measure the qubit as well as the "ring-down" time that it takes the measurement resonator to reset to a ground state.
Generally, most gates apply to the same set of qubits. To avoid repeating these qubits (or pairs of qubits) for each gate, each gate instead uses a target set to define the set of qubits that are valid.
Each target set contains a list of valid targets. A target is a list of qubits. For one-qubit gates, a target is simply a single qubit. For two qubit gates, a target is a pair of qubits.
The type of a target set defines how the targets are interpreted. If the
target set is set to SYMMETRIC, the order of each target does not matter (e.g.
gate.on(q1, q2) is valid, then so is
gate.on(q2, q1)). If the target
type is set to ASYMMETRIC, then the order of qubits does matter, and other
orderings of the qubits that are not specified in the definition cannot be
assumed to be valid.
The last type is PERMUTATION_SET. This type specified that any permutation of
the targets is valid. This is typically used for measurement gates. If
q2 are all specified as valid targets for a permutation set of the
gate.on(q1, q2) and
gate.on(q0, q1, q2) are all valid
uses of the gate.
This is a free form text field for additional recommendations and soft requirements that should be followed for proper operation of the device that are not captured by the hard requirements above.
For instance, "Do not apply two CZ gates in a row."
cirq.google.SerializableDevice combines a
buffer (defining the device) with a
SerializableGateSet (that defines the
translation from serialized id to cirq) to produce a
cirq.Device that can
be used to validate a circuit.
The following example illustrates retrieving the device specification live from the engine and then using it to validate a circuit.
import cirq import cirq.google as cg # Create an Engine object to use. engine = cg.Engine(project_id='your_project_id', proto_version=cirq.google.ProtoVersion.V2) # 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) # Raises a ValueError, since this is not a supported gate. cirq.Circuit(cirq.CZ(q0,q1), device=device)
Note that, if network traffic is undesired, the
easily be stored in either binary format or TextProto format for later usage.