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)))
Exemple #2
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)))
Exemple #3
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)))
Exemple #4
0
def _create_device_spec_with_horizontal_couplings():
    # Qubit layout:
    #   x -- x
    #   x -- x
    #   x -- x
    #   x -- x
    #   x -- x

    grid_qubits = [
        cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2)
    ]

    spec = v2.device_pb2.DeviceSpecification()
    spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_targets'
    grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC
    for row in range(int(GRID_HEIGHT / 2)):
        new_target = grid_targets.targets.add()
        new_target.ids.extend(
            [v2.qubit_to_proto_id(cirq.GridQubit(row, j)) for j in range(2)])
    for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT):
        # Flip the qubit pair order for the second half of qubits
        # to verify GridDevice properly handles pair symmetry.
        new_target = grid_targets.targets.add()
        new_target.ids.extend([
            v2.qubit_to_proto_id(cirq.GridQubit(row, 1 - j)) for j in range(2)
        ])
    gate = spec.valid_gates.add()
    gate.syc.SetInParent()
    gate.gate_duration_picos = 12000
    gate.valid_targets.extend(['2_qubit_targets'])

    return grid_qubits, spec
Exemple #5
0
    def to_proto(
        self,
        op: cirq.CircuitOperation,
        msg: Optional[v2.program_pb2.CircuitOperation] = None,
        *,
        arg_function_language: Optional[str] = '',
        constants: List[v2.program_pb2.Constant] = None,
        raw_constants: Dict[Any, int] = None,
    ) -> v2.program_pb2.CircuitOperation:
        """Returns the cirq.google.api.v2.CircuitOperation message as a proto dict.

        Note that this function requires constants and raw_constants to be
        pre-populated with the circuit in op.
        """
        if constants is None or raw_constants is None:
            raise ValueError(
                'CircuitOp serialization requires a constants list and a corresponding list of '
                'pre-serialization values (raw_constants).')

        if not isinstance(op, cirq.CircuitOperation):
            raise ValueError(
                f'Serializer expected CircuitOperation but got {type(op)}.')

        msg = msg or v2.program_pb2.CircuitOperation()
        try:
            msg.circuit_constant_index = raw_constants[op.circuit]
        except KeyError as err:
            # Circuits must be serialized prior to any CircuitOperations that use them.
            raise ValueError(
                'Encountered a circuit not in the constants table. '
                f'Full error message:\n{err}')

        if (op.repetition_ids is not None and op.repetition_ids !=
                circuit_operation.default_repetition_ids(op.repetitions)):
            for rep_id in op.repetition_ids:
                msg.repetition_specification.repetition_ids.ids.append(rep_id)
        else:
            msg.repetition_specification.repetition_count = op.repetitions

        for q1, q2 in op.qubit_map.items():
            entry = msg.qubit_map.entries.add()
            entry.key.id = v2.qubit_to_proto_id(q1)
            entry.value.id = v2.qubit_to_proto_id(q2)

        for mk1, mk2 in op.measurement_key_map.items():
            entry = msg.measurement_key_map.entries.add()
            entry.key.string_key = mk1
            entry.value.string_key = mk2

        for p1, p2 in op.param_resolver.param_dict.items():
            entry = msg.arg_map.entries.add()
            arg_to_proto(p1,
                         out=entry.key,
                         arg_function_language=arg_function_language)
            arg_to_proto(p2,
                         out=entry.value,
                         arg_function_language=arg_function_language)

        return msg
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))
Exemple #7
0
def test_results_from_proto_default_ordering():
    proto = v2.result_pb2.Result()
    sr = proto.sweep_results.add()
    sr.repetitions = 8
    pr = sr.parameterized_results.add()
    pr.params.assignments.update({'i': 1})
    mr = pr.measurement_results.add()
    mr.key = 'foo'
    for qubit, results in [(q(0, 1), 0b1100_1100), (q(1, 1), 0b1010_1010),
                           (q(0, 0), 0b1111_0000)]:
        qmr = mr.qubit_measurement_results.add()
        qmr.qubit.id = v2.qubit_to_proto_id(qubit)
        qmr.results = bytes([results])

    trial_results = v2.results_from_proto(proto)
    trial = trial_results[0][0]
    assert trial.params == cirq.ParamResolver({'i': 1})
    assert trial.repetitions == 8
    np.testing.assert_array_equal(
        trial.measurements['foo'],
        np.array(
            [
                [0, 0, 0],
                [0, 1, 0],
                [1, 0, 0],
                [1, 1, 0],
                [0, 0, 1],
                [0, 1, 1],
                [1, 0, 1],
                [1, 1, 1],
            ],
            dtype=bool,
        ),
    )
Exemple #8
0
def results_to_proto(
    trial_sweeps: Iterable[Iterable[study.Result]],
    measurements: List[MeasureInfo],
    *,
    out: Optional[result_pb2.Result] = None,
) -> result_pb2.Result:
    """Converts trial results from multiple sweeps to v2 protobuf message.

    Args:
        trial_sweeps: Iterable over sweeps and then over trial results within
            each sweep.
        measurements: List of info about measurements in the program.
        out: Optional message to populate. If not given, create a new message.
    """
    if out is None:
        out = result_pb2.Result()
    for trial_sweep in trial_sweeps:
        sweep_result = out.sweep_results.add()
        for i, trial_result in enumerate(trial_sweep):
            if i == 0:
                sweep_result.repetitions = trial_result.repetitions
            elif trial_result.repetitions != sweep_result.repetitions:
                raise ValueError(
                    'different numbers of repetitions in one sweep')
            pr = sweep_result.parameterized_results.add()
            pr.params.assignments.update(trial_result.params.param_dict)
            for m in measurements:
                mr = pr.measurement_results.add()
                mr.key = m.key
                m_data = trial_result.measurements[m.key]
                for i, qubit in enumerate(m.qubits):
                    qmr = mr.qubit_measurement_results.add()
                    qmr.qubit.id = v2.qubit_to_proto_id(qubit)
                    qmr.results = pack_bits(m_data[:, i])
    return out
Exemple #9
0
 def to_proto(self) -> v2.metrics_pb2.MetricsSnapshot:
     """Reconstruct the protobuf message represented by this class."""
     proto = v2.metrics_pb2.MetricsSnapshot()
     for key in self._metric_dict:
         for targets, value_list in self._metric_dict[key].items():
             current_metric = proto.metrics.add()
             current_metric.name = key
             current_metric.targets.extend(
                 [
                     target if isinstance(target, str) else v2.qubit_to_proto_id(target)
                     for target in targets
                 ]
             )
             for value in value_list:
                 current_value = current_metric.values.add()
                 if isinstance(value, float):
                     current_value.double_val = value
                 elif isinstance(value, int):
                     current_value.int64_val = value
                 elif isinstance(value, str):
                     current_value.str_val = value
                 else:
                     raise ValueError(
                         f'Unsupported metric value {value}. '
                         'Must be int, float, or str to '
                         'convert to proto.'
                     )
     return proto
Exemple #10
0
def _create_device_spec_duplicate_qubit() -> v2.device_pb2.DeviceSpecification:
    """Creates a DeviceSpecification with a qubit name that does not conform to '<int>_<int>'."""
    q_proto_id = v2.qubit_to_proto_id(cirq.GridQubit(0, 0))

    spec = v2.device_pb2.DeviceSpecification()
    spec.valid_qubits.extend([q_proto_id, q_proto_id])

    return spec
Exemple #11
0
    def to_proto(
        self,
        op: cirq.Operation,
        msg: Optional[v2.program_pb2.Operation] = None,
        *,
        arg_function_language: Optional[str] = '',
        constants: List[v2.program_pb2.Constant] = None,
        raw_constants: Dict[Any, int] = None,
    ) -> Optional[v2.program_pb2.Operation]:
        """Returns the cirq_google.api.v2.Operation message as a proto dict.

        Note that this function may modify the constant list if it adds
        tokens to the circuit's constant table.
        """

        gate = op.gate
        if not isinstance(gate, self.internal_type):
            raise ValueError(
                f'Gate of type {type(gate)} but serializer expected type {self.internal_type}'
            )

        if not self._can_serialize_predicate(op):
            return None

        if msg is None:
            msg = v2.program_pb2.Operation()

        msg.gate.id = self._serialized_gate_id
        for qubit in op.qubits:
            msg.qubits.add().id = v2.qubit_to_proto_id(qubit)
        for arg in self._args:
            value = self._value_from_gate(op, arg)
            if value is not None and (not arg.default or value != arg.default):
                arg_to_proto(
                    value,
                    out=msg.args[arg.serialized_name],
                    arg_function_language=arg_function_language,
                )
        if self._serialize_tokens:
            for tag in op.tags:
                if isinstance(tag, CalibrationTag):
                    if constants is not None:
                        constant = v2.program_pb2.Constant()
                        constant.string_value = tag.token
                        try:
                            msg.token_constant_index = constants.index(
                                constant)
                        except ValueError:
                            # Token not found, add it to the list
                            msg.token_constant_index = len(constants)
                            constants.append(constant)
                            if raw_constants is not None:
                                raw_constants[
                                    tag.token] = msg.token_constant_index
                    else:
                        msg.token_value = tag.token
        return msg
Exemple #12
0
def test_qubit_to_proto_id():
    assert v2.qubit_to_proto_id(cirq.GridQubit(1, 2)) == '1_2'
    assert v2.qubit_to_proto_id(cirq.GridQubit(10, 2)) == '10_2'
    assert v2.qubit_to_proto_id(cirq.GridQubit(-1, 2)) == '-1_2'
    assert v2.qubit_to_proto_id(cirq.LineQubit(1)) == '1'
    assert v2.qubit_to_proto_id(cirq.LineQubit(10)) == '10'
    assert v2.qubit_to_proto_id(cirq.LineQubit(-1)) == '-1'
    assert v2.qubit_to_proto_id(cirq.NamedQubit('named')) == 'named'
def populate_qubits_in_device_proto(
        qubits: Collection[cirq.Qid],
        out: device_pb2.DeviceSpecification) -> None:
    """Populates `DeviceSpecification.valid_qubits` with the device's qubits.

    Args:
        qubits: The collection of the device's qubits.
        out: The `DeviceSpecification` to be populated.
    """
    out.valid_qubits.extend(v2.qubit_to_proto_id(q) for q in qubits)
Exemple #14
0
def _create_device_spec_with_horizontal_couplings():
    # Qubit layout:
    #   x -- x
    #   x -- x
    #   x -- x
    #   x -- x
    #   x -- x

    grid_qubits = [cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2)]

    spec = v2.device_pb2.DeviceSpecification()
    spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits])
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_targets'
    grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC
    for row in range(int(GRID_HEIGHT / 2)):
        new_target = grid_targets.targets.add()
        new_target.ids.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, j)) for j in range(2)])
    for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT):
        # Flip the qubit pair order for the second half of qubits
        # to verify GridDevice properly handles pair symmetry.
        new_target = grid_targets.targets.add()
        new_target.ids.extend([v2.qubit_to_proto_id(cirq.GridQubit(row, 1 - j)) for j in range(2)])

    gate_names = [
        'syc',
        'sqrt_iswap',
        'sqrt_iswap_inv',
        'cz',
        'phased_xz',
        'virtual_zpow',
        'physical_zpow',
        'coupler_pulse',
        'meas',
        'wait',
    ]
    for i, g in enumerate(gate_names):
        gate = spec.valid_gates.add()
        getattr(gate, g).SetInParent()
        gate.gate_duration_picos = i * 1000

    return grid_qubits, spec
Exemple #15
0
def _create_device_spec_with_all_couplings():
    # Qubit layout:
    #   x -- x
    #   |    |
    #   x -- x
    #   |    |
    #   x -- x
    #   |    |
    #   x -- x
    #   |    |
    #   x -- x

    grid_qubits, spec = _create_device_spec_with_horizontal_couplings()
    for row in range(GRID_HEIGHT - 1):
        for col in range(2):
            new_target = spec.valid_targets[0].targets.add()
            new_target.ids.extend([
                v2.qubit_to_proto_id(cirq.GridQubit(row, col)),
                v2.qubit_to_proto_id(cirq.GridQubit(row + 1, col)),
            ])
    return grid_qubits, spec
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)))
Exemple #17
0
def _create_device_spec_qubit_pair_self_loops() -> v2.device_pb2.DeviceSpecification:
    """Creates an invalid DeviceSpecification with a qubit pair ('0_0', '0_0')."""

    q_proto_id = v2.qubit_to_proto_id(cirq.GridQubit(0, 0))

    spec = v2.device_pb2.DeviceSpecification()
    spec.valid_qubits.extend([q_proto_id])
    targets = spec.valid_targets.add()
    targets.name = 'test_targets'
    targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC
    new_target = targets.targets.add()
    new_target.ids.extend([q_proto_id, q_proto_id])

    return spec
Exemple #18
0
def _create_device_spec_invalid_qubit_in_qubit_pair() -> v2.device_pb2.DeviceSpecification:
    """Creates a DeviceSpecification where qubit '0_1' is in a pair but not in valid_qubits."""

    q_proto_ids = [v2.qubit_to_proto_id(cirq.GridQubit(0, i)) for i in range(2)]

    spec = v2.device_pb2.DeviceSpecification()
    spec.valid_qubits.extend([q_proto_ids[0]])
    targets = spec.valid_targets.add()
    targets.name = 'test_targets'
    targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC
    new_target = targets.targets.add()
    new_target.ids.extend([q_proto_ids[0], q_proto_ids[1]])

    return spec
Exemple #19
0
def test_to_proto_id_unsupport_qid():
    class ValidQubit(cirq.Qid):
        def __init__(self, name):
            self._name = name

        @property
        def dimension(self):
            pass

        def _comparison_key(self):
            pass

    with pytest.raises(ValueError, match='ValidQubit'):
        _ = v2.qubit_to_proto_id(ValidQubit('d'))
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)))
def populate_qubit_pairs_in_device_proto(
        pairs: Collection[Tuple[cirq.Qid, cirq.Qid]],
        out: device_pb2.DeviceSpecification) -> None:
    """Populates `DeviceSpecification.valid_targets` with the device's qubit pairs.

    Args:
        pairs: The collection of the device's bi-directional qubit pairs.
        out: The `DeviceSpecification` to be populated.
    """
    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)
Exemple #22
0
def _create_device_spec_invalid_subset_permutation_target(
) -> v2.device_pb2.DeviceSpecification:
    """Creates a DeviceSpecification where a SUBSET_PERMUTATION target contains 2 qubits."""

    q_proto_ids = [
        v2.qubit_to_proto_id(cirq.GridQubit(0, i)) for i in range(2)
    ]

    spec = v2.device_pb2.DeviceSpecification()
    spec.valid_qubits.extend(q_proto_ids)
    targets = spec.valid_targets.add()
    targets.name = 'test_targets'
    targets.target_ordering = v2.device_pb2.TargetSet.SUBSET_PERMUTATION
    new_target = targets.targets.add()
    new_target.ids.extend(q_proto_ids)  # should only have 1 qubit instead

    return spec
Exemple #23
0
def test_results_from_proto_duplicate_qubit():
    measurements = [
        v2.MeasureInfo('foo', [q(0, 0), q(0, 1), q(1, 1)],
                       slot=0,
                       invert_mask=[False, False, False],
                       tags=[])
    ]
    proto = v2.result_pb2.Result()
    sr = proto.sweep_results.add()
    sr.repetitions = 8
    pr = sr.parameterized_results.add()
    pr.params.assignments.update({'i': 0})
    mr = pr.measurement_results.add()
    mr.key = 'foo'
    for qubit, results in [(q(0, 0), 0b1100_1100), (q(0, 1), 0b1010_1010),
                           (q(0, 1), 0b1111_0000)]:
        qmr = mr.qubit_measurement_results.add()
        qmr.qubit.id = v2.qubit_to_proto_id(qubit)
        qmr.results = bytes([results])
    with pytest.raises(ValueError, match='Qubit already exists'):
        v2.results_from_proto(proto, measurements)
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))
Exemple #25
0
    def _serialize_gate_op(
        self,
        op: cirq.Operation,
        msg: v2.program_pb2.Operation,
        *,
        constants: List[v2.program_pb2.Constant],
        raw_constants: Dict[Any, int],
        arg_function_language: Optional[str] = '',
    ) -> v2.program_pb2.Operation:
        """Serialize an Operation to cirq_google.api.v2.Operation proto.

        Args:
            op: The operation to serialize.
            msg: An optional proto object to populate with the serialization
                results.
            arg_function_language: The `arg_function_language` field from
                `Program.Language`.
            constants: The list of previously-serialized Constant protos.
            raw_constants: A map raw objects to their respective indices in
                `constants`.

        Returns:
            The cirq.google.api.v2.Operation proto.
        """
        gate = op.gate

        if isinstance(gate, cirq.XPowGate):
            arg_func_langs.float_arg_to_proto(
                gate.exponent,
                out=msg.xpowgate.exponent,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.YPowGate):
            arg_func_langs.float_arg_to_proto(
                gate.exponent,
                out=msg.ypowgate.exponent,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.ZPowGate):
            arg_func_langs.float_arg_to_proto(
                gate.exponent,
                out=msg.zpowgate.exponent,
                arg_function_language=arg_function_language,
            )
            if any(isinstance(tag, PhysicalZTag) for tag in op.tags):
                msg.zpowgate.is_physical_z = True
        elif isinstance(gate, cirq.PhasedXPowGate):
            arg_func_langs.float_arg_to_proto(
                gate.phase_exponent,
                out=msg.phasedxpowgate.phase_exponent,
                arg_function_language=arg_function_language,
            )
            arg_func_langs.float_arg_to_proto(
                gate.exponent,
                out=msg.phasedxpowgate.exponent,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.PhasedXZGate):
            arg_func_langs.float_arg_to_proto(
                gate.x_exponent,
                out=msg.phasedxzgate.x_exponent,
                arg_function_language=arg_function_language,
            )
            arg_func_langs.float_arg_to_proto(
                gate.z_exponent,
                out=msg.phasedxzgate.z_exponent,
                arg_function_language=arg_function_language,
            )
            arg_func_langs.float_arg_to_proto(
                gate.axis_phase_exponent,
                out=msg.phasedxzgate.axis_phase_exponent,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.CZPowGate):
            arg_func_langs.float_arg_to_proto(
                gate.exponent,
                out=msg.czpowgate.exponent,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.ISwapPowGate):
            arg_func_langs.float_arg_to_proto(
                gate.exponent,
                out=msg.iswappowgate.exponent,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.FSimGate):
            arg_func_langs.float_arg_to_proto(
                gate.theta,
                out=msg.fsimgate.theta,
                arg_function_language=arg_function_language,
            )
            arg_func_langs.float_arg_to_proto(
                gate.phi,
                out=msg.fsimgate.phi,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.MeasurementGate):
            arg_func_langs.arg_to_proto(
                gate.key,
                out=msg.measurementgate.key,
                arg_function_language=arg_function_language,
            )
            arg_func_langs.arg_to_proto(
                gate.invert_mask,
                out=msg.measurementgate.invert_mask,
                arg_function_language=arg_function_language,
            )
        elif isinstance(gate, cirq.WaitGate):
            arg_func_langs.float_arg_to_proto(
                gate.duration.total_nanos(),
                out=msg.waitgate.duration_nanos,
                arg_function_language=arg_function_language,
            )
        else:
            raise ValueError(
                f'Cannot serialize op {op!r} of type {type(gate)}')

        for qubit in op.qubits:
            if qubit not in raw_constants:
                constants.append(
                    v2.program_pb2.Constant(qubit=v2.program_pb2.Qubit(
                        id=v2.qubit_to_proto_id(qubit))))
                raw_constants[qubit] = len(constants) - 1
            msg.qubit_constant_index.append(raw_constants[qubit])

        for tag in op.tags:
            if isinstance(tag, CalibrationTag):
                constant = v2.program_pb2.Constant()
                constant.string_value = tag.token
                if tag.token in raw_constants:
                    msg.token_constant_index = raw_constants[tag.token]
                else:
                    # Token not found, add it to the list
                    msg.token_constant_index = len(constants)
                    constants.append(constant)
                    if raw_constants is not None:
                        raw_constants[tag.token] = msg.token_constant_index
        return msg
Exemple #26
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
def _create_device_spec_with_horizontal_couplings():
    # Qubit layout:
    #   x -- x
    #   x -- x
    #   x -- x
    #   x -- x
    #   x -- x

    grid_qubits = [
        cirq.GridQubit(i, j) for i in range(GRID_HEIGHT) for j in range(2)
    ]

    spec = v2.device_pb2.DeviceSpecification()

    spec.valid_qubits.extend([v2.qubit_to_proto_id(q) for q in grid_qubits])

    qubit_pairs = []
    grid_targets = spec.valid_targets.add()
    grid_targets.name = '2_qubit_targets'
    grid_targets.target_ordering = v2.device_pb2.TargetSet.SYMMETRIC
    for row in range(int(GRID_HEIGHT / 2)):
        qubit_pairs.append((cirq.GridQubit(row, 0), cirq.GridQubit(row, 1)))
    for row in range(int(GRID_HEIGHT / 2), GRID_HEIGHT):
        # Flip the qubit pair order for the second half of qubits
        # to verify GridDevice properly handles pair symmetry.
        qubit_pairs.append((cirq.GridQubit(row, 1), cirq.GridQubit(row, 0)))
    for pair in qubit_pairs:
        new_target = grid_targets.targets.add()
        new_target.ids.extend([v2.qubit_to_proto_id(q) for q in pair])

    gate_names = [
        'syc',
        'sqrt_iswap',
        'sqrt_iswap_inv',
        'cz',
        'phased_xz',
        'virtual_zpow',
        'physical_zpow',
        'coupler_pulse',
        'meas',
        'wait',
    ]
    gate_durations = [(n, i * 1000) for i, n in enumerate(gate_names)]
    for gate_name, duration in sorted(gate_durations):
        gate = spec.valid_gates.add()
        getattr(gate, gate_name).SetInParent()
        gate.gate_duration_picos = duration

    expected_gateset = cirq.Gateset(
        cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]),
        cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]),
        cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]),
        cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]),
        cirq.ops.phased_x_z_gate.PhasedXZGate,
        cirq.ops.common_gates.XPowGate,
        cirq.ops.common_gates.YPowGate,
        cirq.ops.phased_x_gate.PhasedXPowGate,
        cirq.GateFamily(cirq.ops.common_gates.ZPowGate,
                        tags_to_ignore=[cirq_google.PhysicalZTag()]),
        cirq.GateFamily(cirq.ops.common_gates.ZPowGate,
                        tags_to_accept=[cirq_google.PhysicalZTag()]),
        cirq_google.experimental.ops.coupler_pulse.CouplerPulse,
        cirq.ops.measurement_gate.MeasurementGate,
        cirq.ops.wait_gate.WaitGate,
    )

    base_duration = cirq.Duration(picos=1_000)
    expected_gate_durations = {
        cirq_google.FSimGateFamily(gates_to_accept=[cirq_google.SYC]):
        base_duration * 0,
        cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP]):
        base_duration * 1,
        cirq_google.FSimGateFamily(gates_to_accept=[cirq.SQRT_ISWAP_INV]):
        base_duration * 2,
        cirq_google.FSimGateFamily(gates_to_accept=[cirq.CZ]):
        base_duration * 3,
        cirq.GateFamily(cirq.ops.phased_x_z_gate.PhasedXZGate):
        base_duration * 4,
        cirq.GateFamily(cirq.ops.common_gates.XPowGate):
        base_duration * 4,
        cirq.GateFamily(cirq.ops.common_gates.YPowGate):
        base_duration * 4,
        cirq.GateFamily(cirq.ops.phased_x_gate.PhasedXPowGate):
        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,
    }

    expected_target_gatesets = (
        cirq.CZTargetGateset(),
        cirq_google.SycamoreTargetGateset(),
        cirq.SqrtIswapTargetGateset(use_sqrt_iswap_inv=True),
    )

    return (
        _DeviceInfo(
            grid_qubits,
            qubit_pairs,
            expected_gateset,
            expected_gate_durations,
            expected_target_gatesets,
        ),
        spec,
    )