Beispiel #1
0
def test_asymmetric_gate():
    spec = device_pb2.DeviceSpecification()
    for row in range(5):
        for col in range(2):
            spec.valid_qubits.extend(
                [v2.qubit_to_proto_id(cirq.GridQubit(row, col))])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'left_to_right'
    grid_targets.target_ordering = device_pb2.TargetSet.ASYMMETRIC
    for row in range(5):
        new_target = grid_targets.targets.add()
        new_target.ids.extend([
            v2.qubit_to_proto_id(cirq.GridQubit(row, 0)),
            v2.qubit_to_proto_id(cirq.GridQubit(row, 1)),
        ])

    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'cz_left_to_right_only'

    gate = gs_proto.valid_gates.add()
    gate.id = 'cz'
    gate.valid_targets.extend(['left_to_right'])

    dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ])

    for row in range(5):
        dev.validate_operation(
            cirq.CZ(cirq.GridQubit(row, 0), cirq.GridQubit(row, 1)))
        with pytest.raises(ValueError):
            dev.validate_operation(
                cirq.CZ(cirq.GridQubit(row, 1), cirq.GridQubit(row, 0)))
Beispiel #2
0
def test_constrained_permutations():
    spec = device_pb2.DeviceSpecification()
    for row in range(5):
        for col in range(2):
            spec.valid_qubits.extend(
                [v2.qubit_to_proto_id(cirq.GridQubit(row, col))])

    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'meas_on_first_line'
    grid_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION
    new_target = grid_targets.targets.add()
    new_target.ids.extend(
        [v2.qubit_to_proto_id(cirq.GridQubit(i, 0)) for i in range(5)])

    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'meas_set'

    gate = gs_proto.valid_gates.add()
    gate.id = 'meas'
    gate.valid_targets.extend(['meas_on_first_line'])

    dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_MEAS])

    dev.validate_operation(cirq.measure(cirq.GridQubit(0, 0)))
    dev.validate_operation(cirq.measure(cirq.GridQubit(1, 0)))
    dev.validate_operation(cirq.measure(cirq.GridQubit(2, 0)))
    dev.validate_operation(
        cirq.measure(*[cirq.GridQubit(i, 0) for i in range(5)]))

    with pytest.raises(ValueError):
        dev.validate_operation(cirq.measure(cirq.GridQubit(1, 1)))
    with pytest.raises(ValueError):
        dev.validate_operation(
            cirq.measure(cirq.GridQubit(0, 0), cirq.GridQubit(1, 1)))
def test_mixing_types():
    """Mixing SUBSET_PERMUTATION with SYMMETRIC targets is confusing,
    and not yet supported"""
    spec = device_pb2.DeviceSpecification()

    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'subset'
    grid_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION

    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'sym'
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC

    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'set_with_mismatched_targets'

    gate = gs_proto.valid_gates.add()
    gate.id = 'meas'
    gate.valid_targets.extend(['subset', 'sym'])

    meas_gateset = _just_meas()
    with cirq.testing.assert_deprecated('Use cirq_google.GridDevice',
                                        deadline='v0.16',
                                        count=1):
        with pytest.raises(NotImplementedError):
            _ = cg.SerializableDevice.from_proto(proto=spec,
                                                 gate_sets=[meas_gateset])
def test_number_of_qubits_cz():
    spec = device_pb2.DeviceSpecification()
    spec.valid_qubits.extend([
        v2.qubit_to_proto_id(cirq.GridQubit(0, 0)),
        v2.qubit_to_proto_id(cirq.GridQubit(0, 1))
    ])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_anywhere'
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC
    gs_proto = spec.valid_gate_sets.add()

    gs_proto.name = 'cz_requires_three_qubits'

    gate = gs_proto.valid_gates.add()
    gate.id = 'cz'
    gate.valid_targets.extend(['2_qubit_anywhere'])
    gate.number_of_qubits = 3

    cz_gateset = _just_cz()
    with cirq.testing.assert_deprecated('Use cirq_google.GridDevice',
                                        deadline='v0.16',
                                        count=2):
        dev = cg.SerializableDevice.from_proto(proto=spec,
                                               gate_sets=[cz_gateset])

        with pytest.raises(ValueError):
            dev.validate_operation(
                cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)))
def test_unconstrained_gate():
    spec = device_pb2.DeviceSpecification()
    for row in range(5):
        for col in range(5):
            spec.valid_qubits.extend(
                [v2.qubit_to_proto_id(cirq.GridQubit(row, col))])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_anywhere'
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC
    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'cz_free_for_all'

    gate = gs_proto.valid_gates.add()
    gate.id = 'cz'
    gate.valid_targets.extend(['2_qubit_anywhere'])

    cz_gateset = _just_cz()
    with cirq.testing.assert_deprecated('Use cirq_google.GridDevice',
                                        deadline='v0.16',
                                        count=2):
        dev = cg.SerializableDevice.from_proto(proto=spec,
                                               gate_sets=[cz_gateset])

        valid_qubit1 = cirq.GridQubit(4, 4)
        for row in range(4):
            for col in range(4):
                valid_qubit2 = cirq.GridQubit(row, col)
                dev.validate_operation(cirq.CZ(valid_qubit1, valid_qubit2))
def test_number_of_qubits_cz():
    spec = device_pb2.DeviceSpecification()
    spec.valid_qubits.extend(
        [v2.qubit_to_proto_id(cirq.GridQubit(0, 0)), v2.qubit_to_proto_id(cirq.GridQubit(0, 1))]
    )
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_anywhere'
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC
    gs_proto = spec.valid_gate_sets.add()

    gs_proto.name = 'cz_requires_three_qubits'

    gate = gs_proto.valid_gates.add()
    gate.id = 'cz'
    gate.valid_targets.extend(['2_qubit_anywhere'])
    gate.number_of_qubits = 3

    dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ])

    with pytest.raises(ValueError):
        dev.validate_operation(cirq.CZ(cirq.GridQubit(0, 0), cirq.GridQubit(0, 1)))
def test_mixing_types():
    """Mixing SUBSET_PERMUTATION with SYMMETRIC targets is confusing,
    and not yet supported"""
    spec = device_pb2.DeviceSpecification()

    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'subset'
    grid_targets.target_ordering = device_pb2.TargetSet.SUBSET_PERMUTATION

    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'sym'
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC

    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'set_with_mismatched_targets'

    gate = gs_proto.valid_gates.add()
    gate.id = 'meas'
    gate.valid_targets.extend(['subset', 'sym'])

    with pytest.raises(NotImplementedError):
        _ = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_MEAS])
def test_unconstrained_gate():
    spec = device_pb2.DeviceSpecification()
    for row in range(5):
        for col in range(5):
            spec.valid_qubits.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, col))])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_anywhere'
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC
    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'cz_free_for_all'

    gate = gs_proto.valid_gates.add()
    gate.id = 'cz'
    gate.valid_targets.extend(['2_qubit_anywhere'])

    dev = cg.SerializableDevice.from_proto(proto=spec, gate_sets=[_JUST_CZ])

    valid_qubit1 = cirq.GridQubit(4, 4)
    for row in range(4):
        for col in range(4):
            valid_qubit2 = cirq.GridQubit(row, col)
            dev.validate_operation(cirq.CZ(valid_qubit1, valid_qubit2))
def test_asymmetric_gate():
    spec = device_pb2.DeviceSpecification()
    for row in range(5):
        for col in range(2):
            spec.valid_qubits.extend(
                [v2.qubit_to_proto_id(cirq.GridQubit(row, col))])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = 'left_to_right'
    grid_targets.target_ordering = device_pb2.TargetSet.ASYMMETRIC
    for row in range(5):
        new_target = grid_targets.targets.add()
        new_target.ids.extend([
            v2.qubit_to_proto_id(cirq.GridQubit(row, 0)),
            v2.qubit_to_proto_id(cirq.GridQubit(row, 1)),
        ])

    gs_proto = spec.valid_gate_sets.add()
    gs_proto.name = 'cz_left_to_right_only'

    gate = gs_proto.valid_gates.add()
    gate.id = 'cz'
    gate.valid_targets.extend(['left_to_right'])

    cz_gateset = _just_cz()
    with cirq.testing.assert_deprecated('Use cirq_google.GridDevice',
                                        deadline='v0.16',
                                        count=2):
        dev = cg.SerializableDevice.from_proto(proto=spec,
                                               gate_sets=[cz_gateset])

        for row in range(5):
            dev.validate_operation(
                cirq.CZ(cirq.GridQubit(row, 0), cirq.GridQubit(row, 1)))
            with pytest.raises(ValueError):
                dev.validate_operation(
                    cirq.CZ(cirq.GridQubit(row, 1), cirq.GridQubit(row, 0)))
Beispiel #10
0
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
    out.valid_qubits.extend(v2.qubit_to_proto_id(q) for q in qubits)

    # 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)
    grid_targets = out.valid_targets.add()
    grid_targets.name = _2_QUBIT_TARGET_SET
    grid_targets.target_ordering = device_pb2.TargetSet.SYMMETRIC
    for pair in pairs:
        new_target = grid_targets.targets.add()
        new_target.ids.extend(v2.qubit_to_proto_id(q) for q in pair)

    # 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 doesn't inherit
                # from SingleQubitGate, 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 issubclass(gate_type, cirq.SingleQubitGate):
                    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