Skip to content

Commit

Permalink
Merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
NoureldinYosri committed Nov 11, 2024
2 parents f2807a0 + d1b0430 commit 71c7661
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 65 deletions.
12 changes: 12 additions & 0 deletions cirq-google/cirq_google/api/v2/program.proto
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,18 @@ message Operation {
string token_value = 4;
int32 token_constant_index = 5;
}

repeated Tag tags = 22;
}

message DynamicalDecouplingTag {
optional string protocol = 1;
}

message Tag {
oneof tag {
DynamicalDecouplingTag dynamical_decoupling = 1;
}
}

// The instruction identifying the action taken on the quantum computer.
Expand Down
122 changes: 60 additions & 62 deletions cirq-google/cirq_google/api/v2/program_pb2.py

Large diffs are not rendered by default.

41 changes: 40 additions & 1 deletion cirq-google/cirq_google/api/v2/program_pb2.pyi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions cirq-google/cirq_google/ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@
from cirq_google.ops.sycamore_gate import SycamoreGate as SycamoreGate, SYC as SYC

from cirq_google.ops.internal_gate import InternalGate as InternalGate

from cirq_google.ops.dynamical_decoupling_tag import (
DynamicalDecouplingTag as DynamicalDecouplingTag,
)
56 changes: 56 additions & 0 deletions cirq-google/cirq_google/ops/dynamical_decoupling_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2024 The Cirq Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional

import attrs

from cirq_google.api.v2 import program_pb2


SUPPORTED_DD_PROTOCOLS = frozenset(
[
"X", # An even number of X
"Y", # An even number of Y
"XY4", # Repetitions of XYXY blocks.
"XY8", # Repetitions of XYXYYXYX blocks.
]
)


@attrs.frozen
class DynamicalDecouplingTag:
"""A tag to indicate using DD to fill qubit time.
Attributes:
protocol: The name of the decoupling protocol (eg 'X', 'XY4').
"""

protocol: str = attrs.field() # Which DD protocol to use.

@protocol.validator
def _validate_protocol(self, attribute, value):
assert value in SUPPORTED_DD_PROTOCOLS

def to_proto(
self, msg: Optional[program_pb2.DynamicalDecouplingTag] = None
) -> program_pb2.DynamicalDecouplingTag:
if msg is None:
msg = program_pb2.DynamicalDecouplingTag()
msg.protocol = self.protocol
return msg

@staticmethod
def from_proto(msg: program_pb2.DynamicalDecouplingTag) -> 'DynamicalDecouplingTag':
return DynamicalDecouplingTag(protocol=msg.protocol)
28 changes: 28 additions & 0 deletions cirq-google/cirq_google/ops/dynamical_decoupling_tag_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2024 The Cirq Developers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pytest

from cirq_google.ops.dynamical_decoupling_tag import DynamicalDecouplingTag


def test_invalid_value():
with pytest.raises(AssertionError):
_ = DynamicalDecouplingTag('_Z')


def test_proto_serialization():
tag = DynamicalDecouplingTag('X')
msg = tag.to_proto()
assert tag == DynamicalDecouplingTag.from_proto(msg)
13 changes: 11 additions & 2 deletions cirq-google/cirq_google/serialization/circuit_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import cirq
from cirq_google.api import v2
from cirq_google.ops import PhysicalZTag, InternalGate, FSimViaModelTag
from cirq_google.ops import PhysicalZTag, InternalGate, FSimViaModelTag, DynamicalDecouplingTag
from cirq_google.ops.calibration_tag import CalibrationTag
from cirq_google.experimental.ops import CouplerPulse
from cirq_google.serialization import serializer, op_deserializer, op_serializer, arg_func_langs
Expand Down Expand Up @@ -296,6 +296,8 @@ def _serialize_gate_op(
constants.append(constant)
if raw_constants is not None:
raw_constants[tag.token] = msg.token_constant_index
elif isinstance(tag, DynamicalDecouplingTag):
tag.to_proto(msg=msg.tags.add().dynamical_decoupling)
return msg

def _serialize_circuit_op(
Expand Down Expand Up @@ -417,13 +419,14 @@ def _deserialize_circuit(
for moment_proto in circuit_proto.moments:
moment_ops = []
for op in moment_proto.operations:
tags = [self._deserialize_tag(tag) for tag in op.tags]
moment_ops.append(
self._deserialize_gate_op(
op,
arg_function_language=arg_function_language,
constants=constants,
deserialized_constants=deserialized_constants,
)
).with_tags(*tags)
)
for op in moment_proto.circuit_operations:
moment_ops.append(
Expand Down Expand Up @@ -737,5 +740,11 @@ def _deserialize_circuit_op(
deserialized_constants=deserialized_constants,
)

def _deserialize_tag(self, msg: v2.program_pb2.Tag):
which = msg.WhichOneof('tag')
if which == 'dynamical_decoupling':
return DynamicalDecouplingTag.from_proto(msg.dynamical_decoupling)
raise ValueError(f'unsupported tag {msg=}') # pragma: no cover


CIRCUIT_SERIALIZER = CircuitSerializer()
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,15 @@ def test_circuit_with_couplerpulse():
assert cg.CIRCUIT_SERIALIZER.deserialize(msg) == circuit


def test_circuit_with_dd_tag():
tag = cg.ops.DynamicalDecouplingTag('X')
c = cirq.Circuit(cirq.X(cirq.q(0)).with_tags(tag))
msg = cg.CIRCUIT_SERIALIZER.serialize(c)
nc = cg.CIRCUIT_SERIALIZER.deserialize(msg)
assert c == nc
assert nc[0].operations[0].tags == (tag,)


def test_circuit_with_units():
c = cirq.Circuit(
cg.InternalGate(
Expand Down

0 comments on commit 71c7661

Please sign in to comment.