From 47d17f86ad5bac312b9fd1da9ca05c125f6a968f Mon Sep 17 00:00:00 2001 From: Noureldin Date: Mon, 31 Jul 2023 19:01:53 +0100 Subject: [PATCH 1/7] Restore legacy behaviour --- cirq-google/cirq_google/serialization/arg_func_langs.py | 3 +++ .../cirq_google/serialization/circuit_serializer_test.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/cirq-google/cirq_google/serialization/arg_func_langs.py b/cirq-google/cirq_google/serialization/arg_func_langs.py index 3e0b24ed4fc..87fedbb838b 100644 --- a/cirq-google/cirq_google/serialization/arg_func_langs.py +++ b/cirq-google/cirq_google/serialization/arg_func_langs.py @@ -181,6 +181,9 @@ def arg_to_proto( ) field, types_tuple = numerical_fields[cur_index] field.extend(types_tuple[0](x) for x in value) + else: + # Preserve legacy behaviour. + msg.arg_value.bool_values.values.extend(()) else: _arg_func_to_proto(value, arg_function_language, msg) diff --git a/cirq-google/cirq_google/serialization/circuit_serializer_test.py b/cirq-google/cirq_google/serialization/circuit_serializer_test.py index c8f99d57756..fd50d71912d 100644 --- a/cirq-google/cirq_google/serialization/circuit_serializer_test.py +++ b/cirq-google/cirq_google/serialization/circuit_serializer_test.py @@ -660,3 +660,11 @@ def test_no_constants_table(): with pytest.raises(ValueError, match='Proto has references to constants table'): serializer._deserialize_gate_op(op) + + +def test_deserialize() -> None: + q = cirq.NamedQubit('q') + circuit = cirq.Circuit(cirq.X(q) ** 0.5, cirq.measure(q)) + msg = cg.CIRCUIT_SERIALIZER.serialize(circuit) + + assert cg.CIRCUIT_SERIALIZER.deserialize(msg) == circuit From 5e34d383ac0d2c2cc2488c74fd40886bc96ead36 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Mon, 31 Jul 2023 19:15:16 +0100 Subject: [PATCH 2/7] protos --- cirq-google/cirq_google/api/v2/device_pb2.pyi | 4 ++-- cirq-google/cirq_google/api/v2/program_pb2.pyi | 2 +- cirq-google/cirq_google/api/v2/run_context_pb2.pyi | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cirq-google/cirq_google/api/v2/device_pb2.pyi b/cirq-google/cirq_google/api/v2/device_pb2.pyi index f1b26dadc67..1e547a26f29 100644 --- a/cirq-google/cirq_google/api/v2/device_pb2.pyi +++ b/cirq-google/cirq_google/api/v2/device_pb2.pyi @@ -295,7 +295,7 @@ class ArgDefinition(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _ArgTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ArgDefinition._ArgType.ValueType], builtins.type): # noqa: F821 + class _ArgTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ArgDefinition._ArgType.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor UNSPECIFIED: ArgDefinition._ArgType.ValueType # 0 FLOAT: ArgDefinition._ArgType.ValueType # 1 @@ -373,7 +373,7 @@ class TargetSet(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _TargetOrderingEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TargetSet._TargetOrdering.ValueType], builtins.type): # noqa: F821 + class _TargetOrderingEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TargetSet._TargetOrdering.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor UNSPECIFIED: TargetSet._TargetOrdering.ValueType # 0 SYMMETRIC: TargetSet._TargetOrdering.ValueType # 1 diff --git a/cirq-google/cirq_google/api/v2/program_pb2.pyi b/cirq-google/cirq_google/api/v2/program_pb2.pyi index aa688fabb77..ac75a2dc0ac 100644 --- a/cirq-google/cirq_google/api/v2/program_pb2.pyi +++ b/cirq-google/cirq_google/api/v2/program_pb2.pyi @@ -105,7 +105,7 @@ class Circuit(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _SchedulingStrategyEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Circuit._SchedulingStrategy.ValueType], builtins.type): # noqa: F821 + class _SchedulingStrategyEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Circuit._SchedulingStrategy.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor SCHEDULING_STRATEGY_UNSPECIFIED: Circuit._SchedulingStrategy.ValueType # 0 """The scheduling strategy is unspecified.""" diff --git a/cirq-google/cirq_google/api/v2/run_context_pb2.pyi b/cirq-google/cirq_google/api/v2/run_context_pb2.pyi index 2c104967440..e3708de1f69 100644 --- a/cirq-google/cirq_google/api/v2/run_context_pb2.pyi +++ b/cirq-google/cirq_google/api/v2/run_context_pb2.pyi @@ -105,7 +105,7 @@ class SweepFunction(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _FunctionTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SweepFunction._FunctionType.ValueType], builtins.type): # noqa: F821 + class _FunctionTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SweepFunction._FunctionType.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor FUNCTION_TYPE_UNSPECIFIED: SweepFunction._FunctionType.ValueType # 0 """The function type is not specified. Should never be used.""" From a32e7342ad39b54934f70a71d14a88ac9317bf69 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Tue, 1 Aug 2023 11:41:44 +0100 Subject: [PATCH 3/7] protos --- cirq-google/cirq_google/api/v2/device_pb2.pyi | 4 ++-- cirq-google/cirq_google/api/v2/program_pb2.pyi | 2 +- cirq-google/cirq_google/api/v2/run_context_pb2.pyi | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cirq-google/cirq_google/api/v2/device_pb2.pyi b/cirq-google/cirq_google/api/v2/device_pb2.pyi index 1e547a26f29..f1b26dadc67 100644 --- a/cirq-google/cirq_google/api/v2/device_pb2.pyi +++ b/cirq-google/cirq_google/api/v2/device_pb2.pyi @@ -295,7 +295,7 @@ class ArgDefinition(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _ArgTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ArgDefinition._ArgType.ValueType], builtins.type): + class _ArgTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[ArgDefinition._ArgType.ValueType], builtins.type): # noqa: F821 DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor UNSPECIFIED: ArgDefinition._ArgType.ValueType # 0 FLOAT: ArgDefinition._ArgType.ValueType # 1 @@ -373,7 +373,7 @@ class TargetSet(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _TargetOrderingEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TargetSet._TargetOrdering.ValueType], builtins.type): + class _TargetOrderingEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[TargetSet._TargetOrdering.ValueType], builtins.type): # noqa: F821 DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor UNSPECIFIED: TargetSet._TargetOrdering.ValueType # 0 SYMMETRIC: TargetSet._TargetOrdering.ValueType # 1 diff --git a/cirq-google/cirq_google/api/v2/program_pb2.pyi b/cirq-google/cirq_google/api/v2/program_pb2.pyi index ac75a2dc0ac..aa688fabb77 100644 --- a/cirq-google/cirq_google/api/v2/program_pb2.pyi +++ b/cirq-google/cirq_google/api/v2/program_pb2.pyi @@ -105,7 +105,7 @@ class Circuit(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _SchedulingStrategyEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Circuit._SchedulingStrategy.ValueType], builtins.type): + class _SchedulingStrategyEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Circuit._SchedulingStrategy.ValueType], builtins.type): # noqa: F821 DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor SCHEDULING_STRATEGY_UNSPECIFIED: Circuit._SchedulingStrategy.ValueType # 0 """The scheduling strategy is unspecified.""" diff --git a/cirq-google/cirq_google/api/v2/run_context_pb2.pyi b/cirq-google/cirq_google/api/v2/run_context_pb2.pyi index e3708de1f69..2c104967440 100644 --- a/cirq-google/cirq_google/api/v2/run_context_pb2.pyi +++ b/cirq-google/cirq_google/api/v2/run_context_pb2.pyi @@ -105,7 +105,7 @@ class SweepFunction(google.protobuf.message.Message): ValueType = typing.NewType("ValueType", builtins.int) V: typing_extensions.TypeAlias = ValueType - class _FunctionTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SweepFunction._FunctionType.ValueType], builtins.type): + class _FunctionTypeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[SweepFunction._FunctionType.ValueType], builtins.type): # noqa: F821 DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor FUNCTION_TYPE_UNSPECIFIED: SweepFunction._FunctionType.ValueType # 0 """The function type is not specified. Should never be used.""" From 8d5be1aaa599b70244c562e4dd3c76edd20d3454 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Tue, 1 Aug 2023 15:16:11 +0100 Subject: [PATCH 4/7] rerun ci From 3f82cc2924683c10506f4c52cd4187ff9769998d Mon Sep 17 00:00:00 2001 From: Noureldin Date: Tue, 1 Aug 2023 16:05:17 +0100 Subject: [PATCH 5/7] Support empty invert_mask in measument gate deserialization --- .../serialization/arg_func_langs.py | 3 --- .../serialization/circuit_serializer.py | 24 +++++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/cirq-google/cirq_google/serialization/arg_func_langs.py b/cirq-google/cirq_google/serialization/arg_func_langs.py index 87fedbb838b..3e0b24ed4fc 100644 --- a/cirq-google/cirq_google/serialization/arg_func_langs.py +++ b/cirq-google/cirq_google/serialization/arg_func_langs.py @@ -181,9 +181,6 @@ def arg_to_proto( ) field, types_tuple = numerical_fields[cur_index] field.extend(types_tuple[0](x) for x in value) - else: - # Preserve legacy behaviour. - msg.arg_value.bool_values.values.extend(()) else: _arg_func_to_proto(value, arg_function_language, msg) diff --git a/cirq-google/cirq_google/serialization/circuit_serializer.py b/cirq-google/cirq_google/serialization/circuit_serializer.py index aaac880266a..8fa3c6e1869 100644 --- a/cirq-google/cirq_google/serialization/circuit_serializer.py +++ b/cirq-google/cirq_google/serialization/circuit_serializer.py @@ -14,7 +14,7 @@ """Support for serializing and deserializing cirq_google.api.v2 protos.""" -from typing import cast, Any, Dict, List, Optional +from typing import Any, Dict, List, Optional, Tuple import sympy import cirq @@ -546,18 +546,18 @@ def _deserialize_gate_op( arg_function_language=arg_function_language, required_arg_name=None, ) - invert_mask = cast( - List[bool], - arg_func_langs.arg_from_proto( - operation_proto.measurementgate.invert_mask, - arg_function_language=arg_function_language, - required_arg_name=None, - ), + invert_mask_ = arg_func_langs.arg_from_proto( + operation_proto.measurementgate.invert_mask, + arg_function_language=arg_function_language, + required_arg_name=None, ) - if isinstance(invert_mask, list) and isinstance(key, str): - op = cirq.MeasurementGate( - num_qubits=len(qubits), key=key, invert_mask=tuple(invert_mask) - )(*qubits) + invert_mask: Tuple[bool, ...] = () + if isinstance(invert_mask_, list): + invert_mask = tuple(bool(x) for x in invert_mask_) + if isinstance(invert_mask, tuple) and isinstance(key, str): + op = cirq.MeasurementGate(num_qubits=len(qubits), key=key, invert_mask=invert_mask)( + *qubits + ) else: raise ValueError(f'Incorrect types for measurement gate {invert_mask} {key}') From 0a511533ad1df251c50ff8dc971e1edee8418410 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Tue, 1 Aug 2023 16:39:03 +0100 Subject: [PATCH 6/7] rerun ci From fd61d08bd11f4de5a1286b89d9d86cc5e51edaf6 Mon Sep 17 00:00:00 2001 From: Noureldin Date: Tue, 1 Aug 2023 18:02:57 +0100 Subject: [PATCH 7/7] nits --- .../serialization/circuit_serializer.py | 16 +++++++++------- .../serialization/circuit_serializer_test.py | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cirq-google/cirq_google/serialization/circuit_serializer.py b/cirq-google/cirq_google/serialization/circuit_serializer.py index 8fa3c6e1869..16fd0396755 100644 --- a/cirq-google/cirq_google/serialization/circuit_serializer.py +++ b/cirq-google/cirq_google/serialization/circuit_serializer.py @@ -14,7 +14,7 @@ """Support for serializing and deserializing cirq_google.api.v2 protos.""" -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional import sympy import cirq @@ -546,20 +546,22 @@ def _deserialize_gate_op( arg_function_language=arg_function_language, required_arg_name=None, ) - invert_mask_ = arg_func_langs.arg_from_proto( + parsed_invert_mask = arg_func_langs.arg_from_proto( operation_proto.measurementgate.invert_mask, arg_function_language=arg_function_language, required_arg_name=None, ) - invert_mask: Tuple[bool, ...] = () - if isinstance(invert_mask_, list): - invert_mask = tuple(bool(x) for x in invert_mask_) - if isinstance(invert_mask, tuple) and isinstance(key, str): + if (isinstance(parsed_invert_mask, list) or parsed_invert_mask is None) and isinstance( + key, str + ): + invert_mask: tuple[bool, ...] = () + if parsed_invert_mask is not None: + invert_mask = tuple(bool(x) for x in parsed_invert_mask) op = cirq.MeasurementGate(num_qubits=len(qubits), key=key, invert_mask=invert_mask)( *qubits ) else: - raise ValueError(f'Incorrect types for measurement gate {invert_mask} {key}') + raise ValueError(f'Incorrect types for measurement gate {parsed_invert_mask} {key}') elif which_gate_type == 'waitgate': total_nanos = arg_func_langs.float_arg_from_proto( diff --git a/cirq-google/cirq_google/serialization/circuit_serializer_test.py b/cirq-google/cirq_google/serialization/circuit_serializer_test.py index fd50d71912d..0db07c3e36d 100644 --- a/cirq-google/cirq_google/serialization/circuit_serializer_test.py +++ b/cirq-google/cirq_google/serialization/circuit_serializer_test.py @@ -662,7 +662,7 @@ def test_no_constants_table(): serializer._deserialize_gate_op(op) -def test_deserialize() -> None: +def test_measurement_gate_deserialize() -> None: q = cirq.NamedQubit('q') circuit = cirq.Circuit(cirq.X(q) ** 0.5, cirq.measure(q)) msg = cg.CIRCUIT_SERIALIZER.serialize(circuit)