Skip to content

Commit 8cdb293

Browse files
committed
Add noise gates to cirq_google serialization
- This is a nice-to-have feature for cirq_google protos, since tests and simulations often use noisy circuits and these could be serialized as well. - This would primarily be used for testing and storage since hardware does not (purposely) execute noise channels.
1 parent 0df354c commit 8cdb293

File tree

5 files changed

+269
-98
lines changed

5 files changed

+269
-98
lines changed

cirq-google/cirq_google/api/v2/program.proto

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,32 @@ message WaitGate {
215215
FloatArg duration_nanos = 1;
216216
}
217217

218+
// Representation of cirq.DepolarizingChannel
219+
message DepolarizingChannel {
220+
FloatArg probability = 1;
221+
int32 num_qubits = 2;
222+
}
223+
224+
// Representation of cirq.RandomGateChannel
225+
message RandomGateChannel {
226+
FloatArg probability = 1;
227+
Operation sub_gate = 2;
228+
}
229+
230+
// Representation of noisy channels
231+
// These should only be used for serialization
232+
// of noisy circuits for simulation.
233+
// These channels would generally not be supported
234+
// by hardware.
235+
message NoiseChannel {
236+
oneof channel_value {
237+
DepolarizingChannel depolarizingchannel = 1;
238+
RandomGateChannel randomgatechannel = 2;
239+
}
240+
}
241+
218242
// An operation acts on a set of qubits.
219-
// next available id = 27
243+
// next available id = 28
220244
message Operation {
221245
// Previously deprecated fields. Do not use.
222246
reserved 1, 2;
@@ -241,6 +265,7 @@ message Operation {
241265
SingleQubitCliffordGate singlequbitcliffordgate = 21;
242266
ResetGate resetgate = 24;
243267
ISwapLikeGate iswaplikegate = 26;
268+
NoiseChannel noisechannel = 27;
244269
}
245270

246271
// Which qubits the operation acts on.

cirq-google/cirq_google/api/v2/program_pb2.py

Lines changed: 99 additions & 93 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cirq-google/cirq_google/api/v2/program_pb2.pyi

Lines changed: 82 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cirq-google/cirq_google/serialization/circuit_serializer.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,20 @@ def _serialize_gate_op(
275275
arg_func_langs.float_arg_to_proto(
276276
gate.q1_detune_mhz, out=msg.couplerpulsegate.q1_detune_mhz
277277
)
278+
elif isinstance(gate, cirq.DepolarizingChannel):
279+
arg_func_langs.float_arg_to_proto(
280+
gate.p, out=msg.noisechannel.depolarizingchannel.probability
281+
)
282+
elif isinstance(gate, cirq.RandomGateChannel):
283+
arg_func_langs.float_arg_to_proto(
284+
gate.probability, out=msg.noisechannel.randomgatechannel.probability
285+
)
286+
self._serialize_gate_op(
287+
gate.sub_gate(*op.qubits),
288+
msg=msg.noisechannel.randomgatechannel.sub_gate,
289+
constants=constants,
290+
raw_constants=raw_constants,
291+
)
278292
else:
279293
raise ValueError(f'Cannot serialize op {op!r} of type {type(gate)}')
280294

@@ -730,6 +744,28 @@ def _deserialize_gate_op(
730744
or 0.0,
731745
)
732746
op = gate(*qubits)
747+
elif which_gate_type == 'noisechannel':
748+
which_channel_type = operation_proto.noisechannel.WhichOneof('channel_value')
749+
if which_channel_type == 'depolarizingchannel':
750+
p = arg_func_langs.float_arg_from_proto(
751+
operation_proto.noisechannel.depolarizingchannel.probability
752+
)
753+
op = cirq.DepolarizingChannel(p=p)(*qubits)
754+
elif which_channel_type == 'randomgatechannel':
755+
p = arg_func_langs.float_arg_from_proto(
756+
operation_proto.noisechannel.randomgatechannel.probability
757+
)
758+
sub_gate = self._deserialize_gate_op(
759+
operation_proto.noisechannel.randomgatechannel.sub_gate,
760+
constants=constants,
761+
deserialized_constants=deserialized_constants,
762+
)
763+
op = cirq.RandomGateChannel(probability=p, sub_gate=sub_gate.gate)(*qubits)
764+
else:
765+
raise ValueError(
766+
f'Unsupported serialized noise channel with type "{which_channel_type}".'
767+
f'\n\noperation_proto:\n{operation_proto}'
768+
)
733769
else:
734770
raise ValueError(
735771
f'Unsupported serialized gate with type "{which_gate_type}".'

cirq-google/cirq_google/serialization/circuit_serializer_test.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,32 @@ def circuit_proto(json: dict, qubits: list[str]):
386386
),
387387
),
388388
(cirq.I(Q0), op_proto({'identitygate': {'qid_shape': [2]}, 'qubit_constant_index': [0]})),
389+
(
390+
cirq.depolarize(0.5)(Q0),
391+
op_proto(
392+
{
393+
'noisechannel': {'depolarizingchannel': {'probability': {'float_value': 0.5}}},
394+
'qubit_constant_index': [0],
395+
}
396+
),
397+
),
398+
(
399+
cirq.X(Q0).with_probability(0.5),
400+
op_proto(
401+
{
402+
'noisechannel': {
403+
'randomgatechannel': {
404+
'probability': {'float_value': 0.5},
405+
'sub_gate': {
406+
'xpowgate': {'exponent': {'float_value': 1.0}},
407+
'qubit_constant_index': [0],
408+
},
409+
}
410+
},
411+
'qubit_constant_index': [0],
412+
}
413+
),
414+
),
389415
]
390416

391417

0 commit comments

Comments
 (0)