Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 35 additions & 80 deletions cirq-google/cirq_google/devices/grid_device_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,89 +418,44 @@ def test_to_proto_invalid_input(error_match, qubits, qubit_pairs, gateset, gate_


def test_to_proto_backward_compatibility():
# Deprecations: cirq_google.SerializableGateSet and
# cirq_google.device.known_devices.create_device_proto_for_qubits()
with cirq.testing.assert_deprecated(
'SerializableGateSet',
'create_device_specification_proto()` can be used',
deadline='v0.16',
count=None,
):
device_info, _ = _create_device_spec_with_horizontal_couplings()

# The set of gates in gate_durations are consistent with what's generated in
# _create_device_spec_with_horizontal_couplings()
base_duration = cirq.Duration(picos=1_000)
gate_durations = {
cirq.GateFamily(cirq_google.SYC): base_duration * 0,
cirq.GateFamily(cirq.SQRT_ISWAP): base_duration * 1,
cirq.GateFamily(cirq.SQRT_ISWAP_INV): base_duration * 2,
cirq.GateFamily(cirq.CZ): base_duration * 3,
cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4,
cirq.GateFamily(
cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()]
): base_duration
* 5,
cirq.GateFamily(
cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()]
): base_duration
* 6,
cirq.GateFamily(cirq_google.experimental.ops.coupler_pulse.CouplerPulse): base_duration
* 7,
cirq.GateFamily(cirq.ops.measurement_gate.MeasurementGate): base_duration * 8,
cirq.GateFamily(cirq.ops.wait_gate.WaitGate): base_duration * 9,
}

# Serialize the old way
spec = known_devices.create_device_proto_for_qubits(
device_info.grid_qubits,
device_info.qubit_pairs,
[cirq_google.FSIM_GATESET],
known_devices._SYCAMORE_DURATIONS_PICOS,
)
device_info, _ = _create_device_spec_with_horizontal_couplings()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test can be removed, since we no longer need to be backward compatible with SerializableGateSet

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


# Serialize the new way
grid_device.create_device_specification_proto(
qubits=device_info.grid_qubits,
pairs=device_info.qubit_pairs,
gateset=cirq.Gateset(*gate_durations.keys()),
gate_durations=gate_durations,
out=spec,
)

with cirq.testing.assert_deprecated(
'Use cirq_google.GridDevice', deadline='v0.16', count=None
):
# Deserialize both ways
serializable_dev = cirq_google.SerializableDevice.from_proto(
spec, [cirq_google.FSIM_GATESET]
)
grid_dev = cirq_google.GridDevice.from_proto(spec)

assert serializable_dev.metadata.qubit_set == grid_dev.metadata.qubit_set
assert serializable_dev.metadata.qubit_pairs == grid_dev.metadata.qubit_pairs

assert serializable_dev.metadata.gateset == cirq.Gateset(
cirq.FSimGate,
cirq.ISwapPowGate,
cirq.CZPowGate,
cirq.PhasedXPowGate,
cirq.XPowGate,
cirq.YPowGate,
cirq.ZPowGate,
cirq.PhasedXZGate,
cirq.MeasurementGate,
cirq.WaitGate,
cirq.GlobalPhaseGate,
)
# The set of gates in gate_durations are consistent with what's generated in
# _create_device_spec_with_horizontal_couplings()
base_duration = cirq.Duration(picos=1_000)
gate_durations = {
cirq.GateFamily(cirq_google.SYC): base_duration * 0,
cirq.GateFamily(cirq.SQRT_ISWAP): base_duration * 1,
cirq.GateFamily(cirq.SQRT_ISWAP_INV): base_duration * 2,
cirq.GateFamily(cirq.CZ): base_duration * 3,
cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate): base_duration * 4,
cirq.GateFamily(
cirq.ops.common_gates.ZPowGate, tags_to_ignore=[cirq_google.PhysicalZTag()]
): base_duration
* 5,
cirq.GateFamily(
cirq.ops.common_gates.ZPowGate, tags_to_accept=[cirq_google.PhysicalZTag()]
): base_duration
* 6,
cirq.GateFamily(cirq_google.experimental.ops.coupler_pulse.CouplerPulse): base_duration * 7,
cirq.GateFamily(cirq.ops.measurement_gate.MeasurementGate): base_duration * 8,
cirq.GateFamily(cirq.ops.wait_gate.WaitGate): base_duration * 9,
}

assert grid_dev.metadata.gateset == device_info.expected_gateset
assert (
tuple(grid_dev.metadata.compilation_target_gatesets)
== device_info.expected_target_gatesets
)
# Serialize the new way
spec = grid_device.create_device_specification_proto(
qubits=device_info.grid_qubits,
pairs=device_info.qubit_pairs,
gateset=cirq.Gateset(*gate_durations.keys()),
gate_durations=gate_durations,
)
grid_dev = cirq_google.GridDevice.from_proto(spec)

assert grid_dev.metadata.gate_durations == device_info.expected_gate_durations
assert grid_dev.metadata.gateset == device_info.expected_gateset
assert (
tuple(grid_dev.metadata.compilation_target_gatesets) == device_info.expected_target_gatesets
)
assert grid_dev.metadata.gate_durations == device_info.expected_gate_durations


def test_to_proto_empty():
Expand Down
138 changes: 0 additions & 138 deletions cirq-google/cirq_google/devices/known_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,42 +55,6 @@ def _parse_device(s: str) -> Tuple[List[cirq.GridQubit], Dict[str, Set[cirq.Grid
return qubits, measurement_lines


@_compat.deprecated(
deadline='v0.16',
fix='This function will no longer be available.'
' `cirq_google.grid_device.create_device_specification_proto()` can be used'
' to generate a DeviceSpecification proto which matches the format expected'
' by GridDevice.',
)
def create_device_proto_from_diagram(
ascii_grid: str,
gate_sets: Optional[Iterable[serializable_gate_set.SerializableGateSet]] = None,
durations_picos: Optional[Dict[str, int]] = None,
out: Optional[device_pb2.DeviceSpecification] = None,
) -> device_pb2.DeviceSpecification:
"""Parse ASCIIart device layout into DeviceSpecification proto.
This function assumes that all pairs of adjacent qubits are valid targets
for two-qubit gates.
Args:
ascii_grid: ASCII version of the grid (see _parse_device for details).
gate_sets: Gate sets that define the translation between gate ids and
cirq Gate objects.
durations_picos: A map from gate ids to gate durations in picoseconds.
out: If given, populate this proto, otherwise create a new proto.
"""
qubits, _ = _parse_device(ascii_grid)

# Create a list of all adjacent pairs on the grid for two-qubit gates.
qubit_set = frozenset(qubits)
pairs: List[Tuple[cirq.Qid, cirq.Qid]] = []
for qubit in qubits:
for neighbor in sorted(qubit.neighbors()):
if neighbor > qubit and neighbor in qubit_set:
pairs.append((qubit, neighbor))

return create_device_proto_for_qubits(qubits, pairs, gate_sets, durations_picos, out)


def _create_grid_device_from_diagram(
ascii_grid: str,
gateset: cirq.Gateset,
Expand Down Expand Up @@ -124,108 +88,6 @@ def _create_grid_device_from_diagram(
return grid_device.GridDevice.from_proto(device_specification)


@_compat.deprecated(
deadline='v0.16',
fix='This function will no longer be available.'
' `cirq_google.grid_device.create_device_specification_proto()` can be used'
' to generate a DeviceSpecification proto which matches the format expected'
' by GridDevice.',
)
def create_device_proto_for_qubits(
qubits: Collection[cirq.Qid],
pairs: Collection[Tuple[cirq.Qid, cirq.Qid]],
gate_sets: Optional[Iterable[serializable_gate_set.SerializableGateSet]] = None,
durations_picos: Optional[Dict[str, int]] = None,
out: Optional[device_pb2.DeviceSpecification] = None,
) -> device_pb2.DeviceSpecification:
"""Create device spec for the given qubits and coupled pairs.

Args:
qubits: Qubits that can perform single-qubit gates.
pairs: Pairs of coupled qubits that can perform two-qubit gates.
gate_sets: Gate sets that define the translation between gate ids and
cirq Gate objects.
durations_picos: A map from gate ids to gate durations in picoseconds.
out: If given, populate this proto, otherwise create a new proto.
"""
if out is None:
out = device_pb2.DeviceSpecification()

# Create valid qubit list
populate_qubits_in_device_proto(qubits, out)

# Single qubit gates in this gateset
single_qubit_gates = (cirq.PhasedXPowGate, cirq.PhasedXZGate, cirq.ZPowGate)

# Set up a target set for measurement (any qubit permutation)
meas_targets = out.valid_targets.add()
meas_targets.name = _MEAS_TARGET_SET
meas_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION

# Set up a target set for 2 qubit gates (specified qubit pairs)
populate_qubit_pairs_in_device_proto(pairs, out)

# Create gate sets
arg_def = device_pb2.ArgDefinition
for gate_set in gate_sets or []:
gs_proto = out.valid_gate_sets.add()
gs_proto.name = gate_set.name
gate_ids: Set[str] = set()
for internal_type in gate_set.serializers:
for serializer in gate_set.serializers[internal_type]:
gate_id = serializer.serialized_id
if gate_id in gate_ids:
# Only add each type once
continue

gate_ids.add(gate_id)
gate = gs_proto.valid_gates.add()
gate.id = gate_id

if not isinstance(serializer, op_serializer._GateOpSerializer):
# This implies that 'serializer' handles non-gate ops,
# such as CircuitOperations. No other properties apply.
continue

# Choose target set and number of qubits based on gate type.
gate_type = internal_type

# Note: if it is not a measurement gate and it's type
# is not in the single_qubit_gates tuple, it's assumed to be a two qubit gate.
if gate_type == cirq.MeasurementGate:
gate.valid_targets.append(_MEAS_TARGET_SET)
elif gate_type == cirq.WaitGate:
# TODO: Refactor gate-sets / device to eliminate the need
# to keep checking type here.
# Github issue:
# https://github.com/quantumlib/Cirq/issues/2537
gate.number_of_qubits = 1
elif gate_type in single_qubit_gates:
gate.number_of_qubits = 1
else:
# This must be a two-qubit gate
gate.valid_targets.append(_2_QUBIT_TARGET_SET)
gate.number_of_qubits = 2

# Add gate duration
if durations_picos is not None and gate.id in durations_picos:
gate.gate_duration_picos = durations_picos[gate.id]

# Add argument names and types for each gate.
for arg in serializer.args:
new_arg = gate.valid_args.add()
if arg.serialized_type == str:
new_arg.type = arg_def.STRING
if arg.serialized_type == float:
new_arg.type = arg_def.FLOAT
if arg.serialized_type == List[bool]:
new_arg.type = arg_def.REPEATED_BOOLEAN
new_arg.name = arg.serialized_name
# Note: this does not yet support adding allowed_ranges

return out


def populate_qubits_in_device_proto(
qubits: Collection[cirq.Qid], out: device_pb2.DeviceSpecification
) -> None:
Expand Down
Loading