Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions cirq-google/cirq_google/api/v2/program.proto
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,18 @@ message FSimGate {
FloatArg theta = 1;
FloatArg phi = 2;

// If true, this is equivalent to:
// cirq.FSimGate(...).with_tags(cirq_google.FSimViaModelTag()).

// This field controls how we translate the gate implementation.
bool translate_via_model = 3;
oneof translate_tag {
// If true, this is equivalent to:
// cirq.FSimGate(...).with_tags(cirq_google.FSimViaModelTag()).
bool translate_via_model = 3;

// If true, this is equivalent to:
// cirq.FSimGate(...).with_tags(cirq_google.TwoPulseFSimTag()).
bool translate_to_two_pulse = 4;
}

}

// Representation of cirq.ISwapPowGate
Expand Down
246 changes: 123 additions & 123 deletions cirq-google/cirq_google/api/v2/program_pb2.py

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions 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.

15 changes: 14 additions & 1 deletion cirq-google/cirq_google/serialization/circuit_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
InternalTag,
PhysicalZTag,
SycamoreGate,
TwoPulseFSimTag,
WaitGateWithUnit,
WillowGate,
)
Expand Down Expand Up @@ -367,8 +368,16 @@ def _serialize_gate_op(
elif isinstance(gate, cirq.FSimGate):
arg_func_langs.float_arg_to_proto(gate.theta, out=msg.fsimgate.theta)
arg_func_langs.float_arg_to_proto(gate.phi, out=msg.fsimgate.phi)
if any(isinstance(tag, FSimViaModelTag) for tag in op.tags):
has_model_tag = any(isinstance(tag, FSimViaModelTag) for tag in op.tags)
has_two_pulse_tag = any(isinstance(tag, TwoPulseFSimTag) for tag in op.tags)
if has_model_tag and has_two_pulse_tag:
raise ValueError(
'FSimViaModelTag and TwoPulseFSimTag cannot be added to the same FSim gate'
)
if has_model_tag:
msg.fsimgate.translate_via_model = True
if has_two_pulse_tag:
msg.fsimgate.translate_to_two_pulse = True
elif isinstance(gate, cirq.MeasurementGate):
arg_func_langs.arg_to_proto(gate.key, out=msg.measurementgate.key)
if len(gate.invert_mask):
Expand Down Expand Up @@ -870,6 +879,8 @@ def _deserialize_gate_op(
raise ValueError('theta and phi must be specified for FSimGate')
if operation_proto.fsimgate.translate_via_model:
op = op.with_tags(FSimViaModelTag())
if operation_proto.fsimgate.translate_to_two_pulse:
op = op.with_tags(TwoPulseFSimTag())
elif which_gate_type == 'measurementgate':
key = arg_func_langs.arg_from_proto(
operation_proto.measurementgate.key, required_arg_name=None
Expand Down Expand Up @@ -1117,6 +1128,8 @@ def _deserialize_tag(self, msg: v2.program_pb2.Tag):
return PhysicalZTag()
elif which == 'fsim_via_model':
return FSimViaModelTag()
elif which == 'two_pulse_fsim':
return TwoPulseFSimTag()
elif which == 'calibration_tag':
return CalibrationTag.from_proto(msg)
elif which == 'internal_tag':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,20 @@ def circuit_proto(json: dict, qubits: list[str]):
}
),
),
(
cirq.FSimGate(theta=2, phi=1)(Q0, Q1).with_tags(cg.TwoPulseFSimTag()),
op_proto(
{
'fsimgate': {
'theta': {'float_value': 2.0},
'phi': {'float_value': 1.0},
'translate_to_two_pulse': True,
},
'qubit_constant_index': [0, 1],
'tag_indices': [2],
}
),
),
(
cirq.WaitGate(duration=cirq.Duration(nanos=15))(Q0),
op_proto(
Expand Down Expand Up @@ -982,6 +996,13 @@ def test_deserialize_fsim_missing_parameters():
serializer.deserialize(proto)


def test_fsim_with_both_tags_raises_error():
serializer = cg.CircuitSerializer()
op = cirq.FSimGate(theta=2, phi=1)(Q0, Q1).with_tags(cg.FSimViaModelTag(), cg.TwoPulseFSimTag())
with pytest.raises(ValueError, match='FSimViaModelTag and TwoPulseFSimTag'):
serializer.serialize(cirq.Circuit(op))


def test_deserialize_wrong_types():
serializer = cg.CircuitSerializer()
proto = circuit_proto(
Expand Down Expand Up @@ -1054,6 +1075,7 @@ def test_circuit_with_analog_detune_coupler_only():
[
cg.ops.DynamicalDecouplingTag('X'),
cg.FSimViaModelTag(),
cg.TwoPulseFSimTag(),
cg.PhysicalZTag(),
cg.InternalTag(name='abc', package='xyz'),
],
Expand Down
Loading