def __init__( self, qubits: List[cirq.Qid], gate_definitions: Dict[_GateOrFrozenCircuitTypes, List[_GateDefinition]], ): """Constructor for SerializableDevice using python objects. Note that the preferred method of constructing this object is through the static from_proto() call. Args: qubits: A list of valid Qid for the device. gate_definitions: Maps cirq gates to device properties for that gate. """ self.qubits = qubits self.gate_definitions = gate_definitions has_subcircuit_support: bool = cirq.FrozenCircuit in gate_definitions self._metadata = cirq.GridDeviceMetadata( qubit_pairs=[(pair[0], pair[1]) for gate_defs in gate_definitions.values() for gate_def in gate_defs if gate_def.number_of_qubits == 2 for pair in gate_def.target_set if len(pair) == 2 and pair[0] < pair[1]], gateset=cirq.Gateset( *(g for g in gate_definitions.keys() if issubclass(g, cirq.Gate)), cirq.GlobalPhaseGate, unroll_circuit_op=has_subcircuit_support, ), gate_durations=None, )
def test_griddevice_metadata(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] isolated_qubits = [cirq.GridQubit(9, 9), cirq.GridQubit(10, 10)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ) metadata = cirq.GridDeviceMetadata(qubit_pairs, gateset, all_qubits=qubits + isolated_qubits) expected_pairings = frozenset({ (cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)), (cirq.GridQubit(0, 1), cirq.GridQubit(0, 2)), (cirq.GridQubit(0, 1), cirq.GridQubit(1, 1)), (cirq.GridQubit(0, 2), cirq.GridQubit(1, 2)), (cirq.GridQubit(1, 0), cirq.GridQubit(1, 1)), (cirq.GridQubit(1, 1), cirq.GridQubit(1, 2)), (cirq.GridQubit(0, 0), cirq.GridQubit(1, 0)), }) assert metadata.qubit_set == frozenset(qubits + isolated_qubits) assert metadata.qubit_pairs == expected_pairings assert metadata.gateset == gateset expected_graph = nx.Graph() expected_graph.add_nodes_from(sorted(list(qubits + isolated_qubits))) expected_graph.add_edges_from(sorted(list(expected_pairings)), directed=False) assert metadata.nx_graph.edges() == expected_graph.edges() assert metadata.nx_graph.nodes() == expected_graph.nodes() assert metadata.gate_durations is None assert metadata.isolated_qubits == frozenset(isolated_qubits)
def __init__( self, qubits: List[cirq.Qid], gate_definitions: Dict[Type[cirq.Gate], List[_GateDefinition]], ): """Constructor for SerializableDevice using python objects. Note that the preferred method of constructing this object is through the static from_proto() call. Args: qubits: A list of valid Qid for the device. gate_definitions: Maps cirq gates to device properties for that gate. """ self.qubits = qubits self.gate_definitions = gate_definitions self._metadata = cirq.GridDeviceMetadata( qubit_pairs=[(pair[0], pair[1]) for gate_defs in gate_definitions.values() for gate_def in gate_defs if gate_def.number_of_qubits == 2 for pair in gate_def.target_set if len(pair) == 2 and pair[0] < pair[1]], gateset=cirq.Gateset(*[ g for g in gate_definitions.keys() if isinstance(g, (cirq.Gate, type(cirq.Gate))) ]), gate_durations=None, )
def __init__( self, measurement_duration: cirq.DURATION_LIKE, exp_w_duration: cirq.DURATION_LIKE, exp_11_duration: cirq.DURATION_LIKE, qubits: Iterable[cirq.GridQubit], ) -> None: """Initializes the description of an xmon device. Args: measurement_duration: The maximum duration of a measurement. exp_w_duration: The maximum duration of an ExpW operation. exp_11_duration: The maximum duration of an ExpZ operation. qubits: Qubits on the device, identified by their x, y location. """ self._measurement_duration = cirq.Duration(measurement_duration) self._exp_w_duration = cirq.Duration(exp_w_duration) self._exp_z_duration = cirq.Duration(exp_11_duration) self.qubits = frozenset(qubits) self._metadata = cirq.GridDeviceMetadata( [(q0, q1) for q0 in self.qubits for q1 in self.qubits if q0.is_adjacent(q1)], cirq.Gateset( cirq.CZPowGate, cirq.XPowGate, cirq.YPowGate, cirq.PhasedXPowGate, cirq.PhasedXZGate, cirq.MeasurementGate, cirq.ZPowGate, cirq.GlobalPhaseGate, ), None, )
def test_griddevice_self_loop(): bad_pairs = [ (cirq.GridQubit(0, 0), cirq.GridQubit(0, 0)), (cirq.GridQubit(1, 0), cirq.GridQubit(1, 1)), ] with pytest.raises(ValueError, match='Self loop'): _ = cirq.GridDeviceMetadata(bad_pairs, cirq.Gateset(cirq.XPowGate))
def test_griddevice_metadata_bad_isolated(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] fewer_qubits = [cirq.GridQubit(0, 0)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ) with pytest.raises(ValueError, match='node_set'): _ = cirq.GridDeviceMetadata(qubit_pairs, gateset, all_qubits=fewer_qubits)
def test_griddevice_json_load_with_defaults(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ) # Don't set parameters with default values metadata = cirq.GridDeviceMetadata(qubit_pairs, gateset) rep_str = cirq.to_json(metadata) assert metadata == cirq.read_json(json_text=rep_str)
def test_griddevice_metadata_bad_durations(): qubits = tuple(cirq.GridQubit.rect(1, 2)) gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate) invalid_duration = { cirq.GateFamily(cirq.XPowGate): cirq.Duration(nanos=1), cirq.GateFamily(cirq.ZPowGate): cirq.Duration(picos=1), } with pytest.raises(ValueError, match="ZPowGate"): cirq.GridDeviceMetadata([qubits], gateset, gate_durations=invalid_duration)
def from_proto(cls, proto: v2.device_pb2.DeviceSpecification) -> 'GridDevice': """Create a `GridDevice` from a `DeviceSpecification` proto. Args: proto: The `DeviceSpecification` proto describing a Google device. Raises: ValueError: If the given `DeviceSpecification` is invalid. It is invalid if: * A `DeviceSpecification.valid_qubits` string is not in the form `<int>_<int>`, thus cannot be parsed as a `cirq.GridQubit`. * `DeviceSpecification.valid_targets` refer to qubits which are not in `DeviceSpecification.valid_qubits`. * A target set in `DeviceSpecification.valid_targets` has type `SYMMETRIC` but contains targets with repeated qubits, e.g. a qubit pair with a self loop. """ _validate_device_specification(proto) # Create qubit set all_qubits = { v2.grid_qubit_from_proto_id(q) for q in proto.valid_qubits } # Create qubit pair set qubit_pairs = [ (v2.grid_qubit_from_proto_id(target.ids[0]), v2.grid_qubit_from_proto_id(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 ] gateset, gate_durations = _build_gateset_and_gate_durations(proto) try: metadata = cirq.GridDeviceMetadata( qubit_pairs=qubit_pairs, gateset=gateset, gate_durations=gate_durations if len(gate_durations) > 0 else None, all_qubits=all_qubits, compilation_target_gatesets=_build_compilation_target_gatesets( gateset), ) except ValueError as ve: # coverage: ignore # Spec errors should have been caught in validation above. raise ValueError( "DeviceSpecification is invalid.") from ve # coverage: ignore return GridDevice(metadata)
def test_griddevice_metadata_equality(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate) duration = { cirq.Gateset(cirq.XPowGate): cirq.Duration(nanos=1), cirq.Gateset(cirq.YPowGate): cirq.Duration(picos=3), cirq.Gateset(cirq.ZPowGate): cirq.Duration(picos=2), } duration2 = { cirq.Gateset(cirq.XPowGate): cirq.Duration(nanos=10), cirq.Gateset(cirq.YPowGate): cirq.Duration(picos=13), cirq.Gateset(cirq.ZPowGate): cirq.Duration(picos=12), } metadata = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration) metadata2 = cirq.GridDeviceMetadata(qubit_pairs[:2], gateset, gate_durations=duration) metadata3 = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=None) metadata4 = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration2) metadata5 = cirq.GridDeviceMetadata(reversed(qubit_pairs), gateset, gate_durations=duration) eq = cirq.testing.EqualsTester() eq.add_equality_group(metadata) eq.add_equality_group(metadata2) eq.add_equality_group(metadata3) eq.add_equality_group(metadata4) assert metadata == metadata5
def test_repr(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate) duration = { cirq.Gateset(cirq.XPowGate): cirq.Duration(nanos=1), cirq.Gateset(cirq.YPowGate): cirq.Duration(picos=3), cirq.Gateset(cirq.ZPowGate): cirq.Duration(picos=2), } metadata = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration) cirq.testing.assert_equivalent_repr(metadata)
def test_griddevice_json_load(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate) duration = { cirq.Gateset(cirq.XPowGate): cirq.Duration(nanos=1), cirq.Gateset(cirq.YPowGate): cirq.Duration(picos=2), cirq.Gateset(cirq.ZPowGate): cirq.Duration(picos=3), } metadata = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration) rep_str = cirq.to_json(metadata) assert metadata == cirq.read_json(json_text=rep_str)
def test_griddevice_metadata(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] isolated_qubits = [cirq.GridQubit(9, 9), cirq.GridQubit(10, 10)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ) gate_durations = { cirq.GateFamily(cirq.XPowGate): 1_000, cirq.GateFamily(cirq.YPowGate): 1_000, cirq.GateFamily(cirq.ZPowGate): 1_000, # omitting cirq.CZ } target_gatesets = (cirq.CZTargetGateset(), ) metadata = cirq.GridDeviceMetadata( qubit_pairs, gateset, gate_durations=gate_durations, all_qubits=qubits + isolated_qubits, compilation_target_gatesets=target_gatesets, ) expected_pairings = frozenset({ frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(0, 1))), frozenset((cirq.GridQubit(0, 1), cirq.GridQubit(0, 2))), frozenset((cirq.GridQubit(0, 1), cirq.GridQubit(1, 1))), frozenset((cirq.GridQubit(0, 2), cirq.GridQubit(1, 2))), frozenset((cirq.GridQubit(1, 0), cirq.GridQubit(1, 1))), frozenset((cirq.GridQubit(1, 1), cirq.GridQubit(1, 2))), frozenset((cirq.GridQubit(0, 0), cirq.GridQubit(1, 0))), }) assert metadata.qubit_set == frozenset(qubits + isolated_qubits) assert metadata.qubit_pairs == expected_pairings assert metadata.gateset == gateset expected_graph = nx.Graph() expected_graph.add_nodes_from(sorted(list(qubits + isolated_qubits))) expected_graph.add_edges_from(sorted(list(expected_pairings)), directed=False) assert metadata.nx_graph.edges() == expected_graph.edges() assert metadata.nx_graph.nodes() == expected_graph.nodes() assert metadata.gate_durations == gate_durations assert metadata.isolated_qubits == frozenset(isolated_qubits) assert metadata.compilation_target_gatesets == target_gatesets
def test_repr(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ) duration = { cirq.GateFamily(cirq.XPowGate): cirq.Duration(nanos=1), cirq.GateFamily(cirq.YPowGate): cirq.Duration(picos=3), cirq.GateFamily(cirq.ZPowGate): cirq.Duration(picos=2), cirq.GateFamily(cirq.CZ): cirq.Duration(nanos=4), } isolated_qubits = [cirq.GridQubit(9, 9)] target_gatesets = [cirq.CZTargetGateset()] metadata = cirq.GridDeviceMetadata( qubit_pairs, gateset, gate_durations=duration, all_qubits=qubits + isolated_qubits, compilation_target_gatesets=target_gatesets, ) cirq.testing.assert_equivalent_repr(metadata)
def test_griddevice_json_load(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ) duration = { cirq.GateFamily(cirq.XPowGate): cirq.Duration(nanos=1), cirq.GateFamily(cirq.YPowGate): cirq.Duration(picos=2), cirq.GateFamily(cirq.ZPowGate): cirq.Duration(picos=3), cirq.GateFamily(cirq.CZ): cirq.Duration(nanos=4), } isolated_qubits = [cirq.GridQubit(9, 9), cirq.GridQubit(10, 10)] target_gatesets = [cirq.CZTargetGateset()] metadata = cirq.GridDeviceMetadata( qubit_pairs, gateset, gate_durations=duration, all_qubits=qubits + isolated_qubits, compilation_target_gatesets=target_gatesets, ) rep_str = cirq.to_json(metadata) assert metadata == cirq.read_json(json_text=rep_str)
def from_proto(cls, proto: v2.device_pb2.DeviceSpecification) -> 'GridDevice': """Create a `GridDevice` from a `DeviceSpecification` proto. Args: proto: The `DeviceSpecification` proto describing a Google device. Raises: ValueError: If the given `DeviceSpecification` is invalid. It is invalid if: * A `DeviceSpecification.valid_qubits` string is not in the form `<int>_<int>`, thus cannot be parsed as a `cirq.GridQubit`. * `DeviceSpecification.valid_targets` refer to qubits which are not in `DeviceSpecification.valid_qubits`. * A target set in `DeviceSpecification.valid_targets` has type `SYMMETRIC` or `ASYMMETRIC` but contains targets with repeated qubits, e.g. a qubit pair with a self loop. * A target set in `DeviceSpecification.valid_targets` has type `SUBSET_PERMUTATION` but contains targets which do not have exactly one element. A `SUBSET_PERMUTATION` target set uses each target to represent a single qubit, and a gate can be applied to any subset of qubits in the target set. """ _validate_device_specification(proto) # Create qubit set all_qubits = { v2.grid_qubit_from_proto_id(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(#5050) Consider removing `GateSpecification.valid_targets` and # ASYMMETRIC and SUBSET_PERMUTATION target types. # If they are not removed, then their validation should be tightened. qubit_pairs = [ (v2.grid_qubit_from_proto_id(target.ids[0]), v2.grid_qubit_from_proto_id(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: # coverage: ignore # Spec errors should have been caught in validation above. raise ValueError( "DeviceSpecification is invalid.") from ve # coverage: ignore return GridDevice(metadata)
def test_griddevice_metadata_equality(): qubits = cirq.GridQubit.rect(2, 3) qubit_pairs = [(a, b) for a in qubits for b in qubits if a != b and a.is_adjacent(b)] gateset = cirq.Gateset(cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, cirq.CZ, cirq.SQRT_ISWAP) duration = { cirq.GateFamily(cirq.XPowGate): cirq.Duration(nanos=1), cirq.GateFamily(cirq.YPowGate): cirq.Duration(picos=3), cirq.GateFamily(cirq.ZPowGate): cirq.Duration(picos=2), cirq.GateFamily(cirq.CZ): cirq.Duration(nanos=4), cirq.GateFamily(cirq.SQRT_ISWAP): cirq.Duration(nanos=5), } duration2 = { cirq.GateFamily(cirq.XPowGate): cirq.Duration(nanos=10), cirq.GateFamily(cirq.YPowGate): cirq.Duration(picos=13), cirq.GateFamily(cirq.ZPowGate): cirq.Duration(picos=12), cirq.GateFamily(cirq.CZ): cirq.Duration(nanos=14), cirq.GateFamily(cirq.SQRT_ISWAP): cirq.Duration(nanos=15), } isolated_qubits = [cirq.GridQubit(9, 9)] target_gatesets = [cirq.CZTargetGateset(), cirq.SqrtIswapTargetGateset()] metadata = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration) metadata2 = cirq.GridDeviceMetadata(qubit_pairs[:2], gateset, gate_durations=duration) metadata3 = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=None) metadata4 = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration2) metadata5 = cirq.GridDeviceMetadata(reversed(qubit_pairs), gateset, gate_durations=duration) metadata6 = cirq.GridDeviceMetadata(qubit_pairs, gateset, gate_durations=duration, all_qubits=qubits + isolated_qubits) metadata7 = cirq.GridDeviceMetadata( qubit_pairs, gateset, compilation_target_gatesets=target_gatesets) metadata8 = cirq.GridDeviceMetadata( qubit_pairs, gateset, compilation_target_gatesets=target_gatesets[::-1]) metadata9 = cirq.GridDeviceMetadata( qubit_pairs, gateset, compilation_target_gatesets=tuple(target_gatesets)) metadata10 = cirq.GridDeviceMetadata( qubit_pairs, gateset, compilation_target_gatesets=set(target_gatesets)) eq = cirq.testing.EqualsTester() eq.add_equality_group(metadata) eq.add_equality_group(metadata2) eq.add_equality_group(metadata3) eq.add_equality_group(metadata4) eq.add_equality_group(metadata6) eq.add_equality_group(metadata7, metadata8, metadata9, metadata10) assert metadata == metadata5
def __init__(self): self.qubits = cirq.GridQubit.rect(2, 8) neighbors = [(a, b) for a in self.qubits for b in self.qubits if a.is_adjacent(b)] self._metadata = cirq.GridDeviceMetadata(neighbors, cirq.Gateset(cirq.H))