Skip to content

Commit d464973

Browse files
authored
Merge pull request #1014 from qiboteam/coupler_chevron_improvements
coupler_chevron improvements
2 parents 03e65d0 + f724746 commit d464973

File tree

3 files changed

+36
-50
lines changed

3 files changed

+36
-50
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
from dataclasses import dataclass
2-
from typing import Optional
3-
41
import numpy as np
52
from qibolab import AcquisitionType, AveragingMode, ExecutionParameters
63
from qibolab.platform import Platform
7-
from qibolab.pulses import PulseSequence
4+
from qibolab.pulses import PulseSequence, PulseType
85
from qibolab.qubits import QubitPairId
96
from qibolab.sweeper import Parameter, Sweeper, SweeperType
107

@@ -18,25 +15,8 @@
1815
from ..two_qubit_interaction.utils import order_pair
1916

2017

21-
@dataclass
22-
class ChevronCouplersParameters(ChevronParameters):
23-
24-
native_gate: Optional[str] = "CZ"
25-
"""Native gate to implement, CZ or iSWAP."""
26-
27-
"""ChevronCouplers protocol parameters.
28-
29-
Amplitude and duration are referred to the coupler pulse.
30-
"""
31-
32-
33-
@dataclass
34-
class ChevronCouplersData(ChevronData):
35-
"""Data structure for chevron couplers protocol."""
36-
37-
38-
def _aquisition(
39-
params: ChevronCouplersParameters,
18+
def _acquisition(
19+
params: ChevronParameters,
4020
platform: Platform,
4121
targets: list[QubitPairId],
4222
) -> ChevronData:
@@ -50,7 +30,7 @@ def _aquisition(
5030
targets (list): List of pairs to use sequentially.
5131
5232
Returns:
53-
ChevronCouplersData: Acquisition data.
33+
ChevronData: Acquisition data.
5434
"""
5535
# define the parameter to sweep and its range:
5636
delta_amplitude_range = np.arange(
@@ -62,29 +42,27 @@ def _aquisition(
6242
params.duration_min, params.duration_max, params.duration_step
6343
)
6444

65-
# create a DataUnits object to store the results,
6645
data = ChevronData()
67-
# sort high and low frequency qubit
6846
for pair in targets:
6947
sequence = PulseSequence()
7048

7149
ordered_pair = order_pair(pair, platform)
7250

73-
# initialize in system in 11(CZ) or 10(iSWAP) state
74-
if params.native_gate == "CZ":
51+
# initialize system to state 11(CZ) or 10(iSWAP)
52+
if params.native == "CZ":
7553
initialize_lowfreq = platform.create_RX_pulse(ordered_pair[0], start=0)
7654
sequence.add(initialize_lowfreq)
7755

7856
initialize_highfreq = platform.create_RX_pulse(ordered_pair[1], start=0)
7957

8058
sequence.add(initialize_highfreq)
8159

82-
if params.native_gate == "CZ":
60+
if params.native == "CZ":
8361
native_gate, _ = platform.create_CZ_pulse_sequence(
8462
(ordered_pair[1], ordered_pair[0]),
8563
start=sequence.finish + params.dt,
8664
)
87-
elif params.native_gate == "iSWAP":
65+
elif params.native == "iSWAP":
8866
native_gate, _ = platform.create_iSWAP_pulse_sequence(
8967
(ordered_pair[1], ordered_pair[0]),
9068
start=sequence.finish + params.dt,
@@ -103,56 +81,61 @@ def _aquisition(
10381

10482
sequence += ro_pulse1 + ro_pulse2
10583

84+
coupler_flux_pulses = [p for p in native_gate.coupler_pulses(*pair)]
85+
assert (
86+
len(coupler_flux_pulses) == 1
87+
), f"coupler_chevron expects exactly one coupler flux pulse, but {len(coupler_flux_pulses)} are present."
88+
qubit_flux_pulses = [
89+
p for p in native_gate.get_qubit_pulses(*pair) if p.type is PulseType.FLUX
90+
]
91+
assert all(
92+
len(list(filter(lambda x: x.qubit == q, qubit_flux_pulses))) < 2
93+
for q in pair
94+
), f"coupler_chevron expects no more than 1 flux pulse for each qubit, but more are present for the pair {pair}"
10695
sweeper_amplitude = Sweeper(
10796
Parameter.amplitude,
10897
delta_amplitude_range,
109-
pulses=[p for p in native_gate.coupler_pulses(*pair)][:1],
98+
pulses=coupler_flux_pulses,
11099
type=SweeperType.FACTOR,
111100
)
112101
sweeper_duration = Sweeper(
113102
Parameter.duration,
114103
delta_duration_range,
115-
pulses=[p for p in native_gate.coupler_pulses(*pair)],
104+
pulses=coupler_flux_pulses + qubit_flux_pulses,
116105
)
117106

118-
# repeat the experiment as many times as defined by nshots
119107
results = platform.sweep(
120108
sequence,
121109
ExecutionParameters(
122110
nshots=params.nshots,
123-
acquisition_type=AcquisitionType.INTEGRATION,
111+
acquisition_type=AcquisitionType.DISCRIMINATION,
124112
averaging_mode=AveragingMode.CYCLIC,
125113
),
126114
sweeper_duration,
127115
sweeper_amplitude,
128116
)
129117

130-
# TODO: Explore probabilities instead of magnitude
131118
data.register_qubit(
132119
ordered_pair[0],
133120
ordered_pair[1],
134121
delta_duration_range,
135122
delta_amplitude_range * data.native_amplitude[ordered_pair],
136-
results[ordered_pair[0]].magnitude,
137-
results[ordered_pair[1]].magnitude,
123+
results[ordered_pair[0]].probability(state=1),
124+
results[ordered_pair[1]].probability(state=1),
138125
)
126+
data.label = "Probability of state |1>"
139127

140128
return data
141129

142130

143-
@dataclass
144-
class ChevronCouplersResults(Results):
145-
"""Empty fitting outputs for chevron couplers is not implemented in this case."""
146-
147-
148-
def _fit(data: ChevronCouplersData) -> ChevronCouplersResults:
149-
""" "Results for ChevronCouplers."""
150-
return ChevronCouplersResults()
131+
def _fit(data: ChevronData) -> Results:
132+
"""Results for ChevronCouplers."""
133+
return Results()
151134

152135

153-
def plot(data: ChevronCouplersData, fit: ChevronCouplersResults, target):
136+
def plot(data: ChevronData, fit: Results, target):
154137
return _plot(data, None, target)
155138

156139

157-
coupler_chevron = Routine(_aquisition, _fit, plot, two_qubit_gates=True)
140+
coupler_chevron = Routine(_acquisition, _fit, plot, two_qubit_gates=True)
158141
"""Coupler cz/swap flux routine."""

src/qibocal/protocols/two_qubit_interaction/chevron/chevron.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ class ChevronData(Data):
109109
"""Sweetspot value for high frequency qubit."""
110110
data: dict[QubitPairId, npt.NDArray[ChevronType]] = field(default_factory=dict)
111111

112+
label: Optional[str] = None
113+
"""Label for the data."""
114+
112115
def register_qubit(self, low_qubit, high_qubit, length, amp, prob_low, prob_high):
113116
"""Store output for single qubit."""
114117
size = len(length) * len(amp)
@@ -308,7 +311,7 @@ def _plot(data: ChevronData, fit: ChevronResults, target: QubitPairId):
308311
fig.update_layout(
309312
xaxis_title="Duration [ns]",
310313
xaxis2_title="Duration [ns]",
311-
yaxis_title="Amplitude [a.u.]",
314+
yaxis_title=data.label or "Amplitude [a.u.]",
312315
legend=dict(orientation="h"),
313316
)
314317
fig.update_layout(

tests/runcards/protocols_couplers.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ actions:
6666
duration_min: 50
6767
duration_max: 100
6868
duration_step: 10
69-
native_gate: "CZ"
69+
native: "CZ"
7070
dt: 5
7171
nshots: 10
7272

@@ -81,6 +81,6 @@ actions:
8181
duration_min: 50
8282
duration_max: 100
8383
duration_step: 10
84-
native_gate: "iSWAP"
84+
native: "iSWAP"
8585
dt: 5
8686
nshots: 10

0 commit comments

Comments
 (0)