Skip to content

Commit

Permalink
Add single-qubit detuning parameters to CouplerPulse (#5971)
Browse files Browse the repository at this point in the history
* Add single-qubit detuning parameters to CouplerPulse

* Update test json data with new coupler detune parameters.

* Add test to confirm that deserialization continues to work with added fields.

* Fix formatting

Co-authored-by: Matthew Neeley <maffoo@google.com>
  • Loading branch information
wcourtney and maffoo committed Jan 5, 2023
1 parent 0c4f742 commit b014036
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 19 deletions.
55 changes: 46 additions & 9 deletions cirq-google/cirq_google/experimental/ops/coupler_pulse.py
Expand Up @@ -47,6 +47,8 @@ class CouplerPulse(cirq.ops.Gate):
coupling_mhz: Target qubit-qubit coupling reached at the plateau.
rise_time: Width of the rising (or falling) section of the trapezoidal pulse.
padding_time: Symmetric padding around the coupler pulse.
q0_detune_mhz: Detuning of the first qubit.
q1_detune_mhz: Detuning of the second qubit.
"""

def __init__(
Expand All @@ -55,6 +57,8 @@ def __init__(
coupling_mhz: cirq.TParamVal,
rise_time: Optional[cirq.Duration] = cirq.Duration(nanos=8),
padding_time: Optional[cirq.Duration] = cirq.Duration(nanos=2.5),
q0_detune_mhz: cirq.TParamVal = 0.0,
q1_detune_mhz: cirq.TParamVal = 0.0,
):
"""Inits CouplerPulse.
Expand All @@ -63,12 +67,16 @@ def __init__(
coupling_mhz: Target qubit-qubit coupling reached at the plateau.
rise_time: Width of the rising (or falling) action of the trapezoidal pulse.
padding_time: Symmetric padding around the coupler pulse.
q0_detune_mhz: Detuning of the first qubit.
q1_detune_mhz: Detuning of the second qubit.
"""
self.hold_time = hold_time
self.coupling_mhz = coupling_mhz
self.rise_time = rise_time or cirq.Duration(nanos=8)
self.padding_time = padding_time or cirq.Duration(nanos=2.5)
self.q0_detune_mhz = q0_detune_mhz
self.q1_detune_mhz = q1_detune_mhz

def num_qubits(self) -> int:
return 2
Expand All @@ -79,18 +87,22 @@ def _unitary_(self) -> np.ndarray:
def __repr__(self) -> str:
return (
'cirq_google.experimental.ops.coupler_pulse.'
+ f'CouplerPulse(hold_time={proper_repr(self.hold_time)}, '
+ f'coupling_mhz={proper_repr(self.coupling_mhz)}, '
+ f'rise_time={proper_repr(self.rise_time)}, '
+ f'padding_time={proper_repr(self.padding_time)})'
f'CouplerPulse(hold_time={proper_repr(self.hold_time)}, '
f'coupling_mhz={proper_repr(self.coupling_mhz)}, '
f'rise_time={proper_repr(self.rise_time)}, '
f'padding_time={proper_repr(self.padding_time)}, '
f'q0_detune_mhz={proper_repr(self.q0_detune_mhz)}, '
f'q1_detune_mhz={proper_repr(self.q1_detune_mhz)})'
)

def __str__(self) -> str:
return (
f'CouplerPulse(hold_time={self.hold_time}, '
+ f'coupling_mhz={self.coupling_mhz}, '
+ f'rise_time={self.rise_time}, '
+ f'padding_time={self.padding_time})'
f'coupling_mhz={self.coupling_mhz}, '
f'rise_time={self.rise_time}, '
f'padding_time={self.padding_time}, '
f'q0_detune_mhz={self.q0_detune_mhz}, '
f'q1_detune_mhz={self.q1_detune_mhz})'
)

def _is_parameterized_(self) -> bool:
Expand All @@ -99,6 +111,8 @@ def _is_parameterized_(self) -> bool:
or cirq.is_parameterized(self.coupling_mhz)
or cirq.is_parameterized(self.rise_time)
or cirq.is_parameterized(self.padding_time)
or cirq.is_parameterized(self.q0_detune_mhz)
or cirq.is_parameterized(self.q1_detune_mhz)
)

def _parameter_names_(self: Any) -> AbstractSet[str]:
Expand All @@ -107,6 +121,8 @@ def _parameter_names_(self: Any) -> AbstractSet[str]:
| cirq.parameter_names(self.coupling_mhz)
| cirq.parameter_names(self.rise_time)
| cirq.parameter_names(self.padding_time)
| cirq.parameter_names(self.q0_detune_mhz)
| cirq.parameter_names(self.q1_detune_mhz)
)

def _resolve_parameters_(
Expand All @@ -117,16 +133,37 @@ def _resolve_parameters_(
coupling_mhz=cirq.resolve_parameters(self.coupling_mhz, resolver, recursive=recursive),
rise_time=cirq.resolve_parameters(self.rise_time, resolver, recursive=recursive),
padding_time=cirq.resolve_parameters(self.padding_time, resolver, recursive=recursive),
q0_detune_mhz=cirq.resolve_parameters(
self.q0_detune_mhz, resolver, recursive=recursive
),
q1_detune_mhz=cirq.resolve_parameters(
self.q1_detune_mhz, resolver, recursive=recursive
),
)

def _value_equality_values_(self) -> Any:
return self.hold_time, self.coupling_mhz, self.rise_time, self.padding_time
return (
self.hold_time,
self.coupling_mhz,
self.rise_time,
self.padding_time,
self.q0_detune_mhz,
self.q1_detune_mhz,
)

def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
s = f'/‾‾({self.hold_time}@{self.coupling_mhz}MHz)‾‾\\'
return (s, s)

def _json_dict_(self):
return cirq.obj_to_dict_helper(
self, ['hold_time', 'coupling_mhz', 'rise_time', 'padding_time']
self,
[
'hold_time',
'coupling_mhz',
'rise_time',
'padding_time',
'q0_detune_mhz',
'q1_detune_mhz',
],
)
45 changes: 36 additions & 9 deletions cirq-google/cirq_google/experimental/ops/coupler_pulse_test.py
Expand Up @@ -86,20 +86,47 @@ def test_coupler_pulse_str_repr():
hold_time=cirq.Duration(nanos=10), coupling_mhz=25.0, rise_time=cirq.Duration(nanos=18)
)
assert (
str(gate)
== 'CouplerPulse(hold_time=10 ns, coupling_mhz=25.0, '
+ 'rise_time=18 ns, padding_time=2500.0 ps)'
str(gate) == 'CouplerPulse(hold_time=10 ns, coupling_mhz=25.0, '
'rise_time=18 ns, padding_time=2500.0 ps, q0_detune_mhz=0.0, q1_detune_mhz=0.0)'
)
assert (
repr(gate)
== 'cirq_google.experimental.ops.coupler_pulse.CouplerPulse('
+ 'hold_time=cirq.Duration(nanos=10), '
+ 'coupling_mhz=25.0, '
+ 'rise_time=cirq.Duration(nanos=18), '
+ 'padding_time=cirq.Duration(picos=2500.0))'
repr(gate) == 'cirq_google.experimental.ops.coupler_pulse.CouplerPulse('
'hold_time=cirq.Duration(nanos=10), '
'coupling_mhz=25.0, '
'rise_time=cirq.Duration(nanos=18), '
'padding_time=cirq.Duration(picos=2500.0), '
'q0_detune_mhz=0.0, '
'q1_detune_mhz=0.0)'
)


def test_coupler_pulse_json_deserialization_defaults_on_missing_fields():
gate = coupler_pulse.CouplerPulse(
hold_time=cirq.Duration(nanos=10), coupling_mhz=25.0, rise_time=cirq.Duration(nanos=18)
)
json_text = """{
"cirq_type": "CouplerPulse",
"hold_time": {
"cirq_type": "Duration",
"picos": 10000
},
"coupling_mhz": 25.0,
"rise_time": {
"cirq_type": "Duration",
"picos": 18000
},
"padding_time": {
"cirq_type": "Duration",
"picos": 2500.0
}
}"""

deserialized = cirq.read_json(json_text=json_text)

assert deserialized == gate
assert deserialized.q0_detune_mhz == 0.0


def test_coupler_pulse_circuit_diagram():
a, b = cirq.LineQubit.range(2)
gate = coupler_pulse.CouplerPulse(
Expand Down
4 changes: 3 additions & 1 deletion cirq-google/cirq_google/json_test_data/CouplerPulse.json
Expand Up @@ -12,5 +12,7 @@
"padding_time": {
"cirq_type": "Duration",
"picos": 2500.0
}
},
"q0_detune_mhz": 0.0,
"q1_detune_mhz": 0.0
}

0 comments on commit b014036

Please sign in to comment.