Exemple #1
0
    def create_calibration_program(
        self,
        layers: List['cirq_google.CalibrationLayer'],
        program_id: Optional[str] = None,
        gate_set: Optional[Serializer] = None,
        description: Optional[str] = None,
        labels: Optional[Dict[str, str]] = None,
    ) -> engine_program.EngineProgram:
        """Wraps a list of calibration layers into an Any for Quantum Engine.

        Args:
            layers: The calibration routines to execute.  All layers will be
                executed within the same API call in the order specified,
                though some layers may be interleaved together using
                hardware-specific batching.
            program_id: A user-provided identifier for the program. This must be
                unique within the Google Cloud project being used. If this
                parameter is not provided, a random id of the format
                'calibration-################YYMMDD' will be generated,
                where # is alphanumeric and YYMMDD is the current year, month,
                and day.
            gate_set: The gate set used to serialize the circuits in each
                layer.  The gate set must be supported by the processor.
            description: An optional description to set on the program.
            labels: Optional set of labels to set on the program.

        Returns:
            A EngineProgram for the newly created program.

        Raises:
            ValueError: If not gate set is given.
        """
        if not gate_set:
            raise ValueError('Gate set must be specified.')
        if not program_id:
            program_id = _make_random_id('calibration-')

        calibration = v2.calibration_pb2.FocusedCalibration()
        for layer in layers:
            new_layer = calibration.layers.add()
            new_layer.calibration_type = layer.calibration_type
            for arg in layer.args:
                arg_to_proto(layer.args[arg], out=new_layer.args[arg])
            gate_set.serialize(layer.program, msg=new_layer.layer)

        new_program_id, new_program = self.context.client.create_program(
            self.project_id,
            program_id,
            code=self._pack_any(calibration),
            description=description,
            labels=labels,
        )

        return engine_program.EngineProgram(
            self.project_id,
            new_program_id,
            self.context,
            new_program,
            result_type=ResultType.Calibration,
        )
Exemple #2
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
Exemple #3
0
def test_xeb_to_calibration_layer():
    with cirq.testing.assert_deprecated('SerializableGateSet',
                                        deadline='v0.16',
                                        count=None):
        q_00, q_01, q_02, q_03 = [
            cirq.GridQubit(0, index) for index in range(4)
        ]
        gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)
        request = XEBPhasedFSimCalibrationRequest(
            gate=gate,
            pairs=((q_00, q_01), (q_02, q_03)),
            options=XEBPhasedFSimCalibrationOptions(
                n_library_circuits=22,
                fsim_options=XEBPhasedFSimCharacterizationOptions(
                    characterize_theta=True,
                    characterize_zeta=True,
                    characterize_chi=False,
                    characterize_gamma=False,
                    characterize_phi=True,
                ),
            ),
        )
        layer = request.to_calibration_layer()
        assert layer == cirq_google.CalibrationLayer(
            calibration_type='xeb_phased_fsim_characterization',
            program=cirq.Circuit([gate.on(q_00, q_01),
                                  gate.on(q_02, q_03)]),
            args={
                'n_library_circuits': 22,
                'n_combinations': 10,
                'cycle_depths': '5_25_50_100_200_300',
                'fatol': 5e-3,
                'xatol': 5e-3,
                'characterize_theta': True,
                'characterize_zeta': True,
                'characterize_chi': False,
                'characterize_gamma': False,
                'characterize_phi': True,
            },
        )

        # Serialize to proto
        calibration = v2.calibration_pb2.FocusedCalibration()
        new_layer = calibration.layers.add()
        new_layer.calibration_type = layer.calibration_type
        for arg in layer.args:
            arg_to_proto(layer.args[arg], out=new_layer.args[arg])
        cirq_google.SQRT_ISWAP_GATESET.serialize(layer.program,
                                                 msg=new_layer.layer)
        with open(
                os.path.dirname(__file__) +
                '/test_data/xeb_calibration_layer.textproto') as f:
            desired_textproto = f.read()

        layer_str = str(new_layer)
        # Fix precision issues
        layer_str = re.sub(r'0.004999\d+', '0.005', layer_str)
        assert layer_str == desired_textproto
Exemple #4
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 #5
0
def test_unsupported_function_language():
    with pytest.raises(ValueError, match='Unrecognized arg_function_language'):
        _ = arg_to_proto(sympy.Symbol('a') + sympy.Symbol('b'),
                         arg_function_language='NEVER GONNAH APPEN')
    with pytest.raises(ValueError, match='Unrecognized arg_function_language'):
        _ = arg_to_proto(3 * sympy.Symbol('b'),
                         arg_function_language='NEVER GONNAH APPEN')
    with pytest.raises(ValueError, match='Unrecognized arg_function_language'):
        _ = arg_from_proto(
            v2.program_pb2.Arg(func=v2.program_pb2.ArgFunction(
                type='add',
                args=[
                    v2.program_pb2.Arg(symbol='a'),
                    v2.program_pb2.Arg(symbol='b')
                ],
            )),
            arg_function_language='NEVER GONNAH APPEN',
        )
Exemple #6
0
def test_serialize_conversion(value: ARG_LIKE, proto: v2.program_pb2.Arg):
    msg = v2.program_pb2.Arg()
    json_format.ParseDict(proto, msg)
    packed = json_format.MessageToDict(
        arg_to_proto(value, arg_function_language=''),
        including_default_value_fields=True,
        preserving_proto_field_name=True,
        use_integers_for_enums=True,
    )
    assert packed == proto
Exemple #7
0
def test_serialize_sympy_constants():
    proto = arg_to_proto(sympy.pi, arg_function_language='')
    packed = json_format.MessageToDict(
        proto,
        including_default_value_fields=True,
        preserving_proto_field_name=True,
        use_integers_for_enums=True,
    )
    assert len(packed) == 1
    assert len(packed['arg_value']) == 1
    # protobuf 3.12+ truncates floats to 4 bytes
    assert np.isclose(packed['arg_value']['float_value'],
                      np.float32(sympy.pi),
                      atol=1e-7)
Exemple #8
0
def test_correspondence(min_lang: str, value: ARG_LIKE,
                        proto: v2.program_pb2.Arg):
    msg = v2.program_pb2.Arg()
    json_format.ParseDict(proto, msg)
    min_i = LANGUAGE_ORDER.index(min_lang)
    for i, lang in enumerate(LANGUAGE_ORDER):
        if i < min_i:
            with pytest.raises(ValueError,
                               match='not supported by arg_function_language'):
                _ = arg_to_proto(value, arg_function_language=lang)
            with pytest.raises(ValueError, match='Unrecognized function type'):
                _ = arg_from_proto(msg, arg_function_language=lang)
        else:
            parsed = arg_from_proto(msg, arg_function_language=lang)
            packed = json_format.MessageToDict(
                arg_to_proto(value, arg_function_language=lang),
                including_default_value_fields=True,
                preserving_proto_field_name=True,
                use_integers_for_enums=True,
            )

            assert parsed == value
            assert packed == proto
Exemple #9
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.

        Raises:
            ValueError: If the operation cannot be serialized.
        """
        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