1
- from dataclasses import dataclass
2
- from typing import Optional
3
-
4
1
import numpy as np
5
2
from qibolab import AcquisitionType , AveragingMode , ExecutionParameters
6
3
from qibolab .platform import Platform
7
- from qibolab .pulses import PulseSequence
4
+ from qibolab .pulses import PulseSequence , PulseType
8
5
from qibolab .qubits import QubitPairId
9
6
from qibolab .sweeper import Parameter , Sweeper , SweeperType
10
7
18
15
from ..two_qubit_interaction .utils import order_pair
19
16
20
17
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 ,
40
20
platform : Platform ,
41
21
targets : list [QubitPairId ],
42
22
) -> ChevronData :
@@ -50,7 +30,7 @@ def _aquisition(
50
30
targets (list): List of pairs to use sequentially.
51
31
52
32
Returns:
53
- ChevronCouplersData : Acquisition data.
33
+ ChevronData : Acquisition data.
54
34
"""
55
35
# define the parameter to sweep and its range:
56
36
delta_amplitude_range = np .arange (
@@ -62,29 +42,27 @@ def _aquisition(
62
42
params .duration_min , params .duration_max , params .duration_step
63
43
)
64
44
65
- # create a DataUnits object to store the results,
66
45
data = ChevronData ()
67
- # sort high and low frequency qubit
68
46
for pair in targets :
69
47
sequence = PulseSequence ()
70
48
71
49
ordered_pair = order_pair (pair , platform )
72
50
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" :
75
53
initialize_lowfreq = platform .create_RX_pulse (ordered_pair [0 ], start = 0 )
76
54
sequence .add (initialize_lowfreq )
77
55
78
56
initialize_highfreq = platform .create_RX_pulse (ordered_pair [1 ], start = 0 )
79
57
80
58
sequence .add (initialize_highfreq )
81
59
82
- if params .native_gate == "CZ" :
60
+ if params .native == "CZ" :
83
61
native_gate , _ = platform .create_CZ_pulse_sequence (
84
62
(ordered_pair [1 ], ordered_pair [0 ]),
85
63
start = sequence .finish + params .dt ,
86
64
)
87
- elif params .native_gate == "iSWAP" :
65
+ elif params .native == "iSWAP" :
88
66
native_gate , _ = platform .create_iSWAP_pulse_sequence (
89
67
(ordered_pair [1 ], ordered_pair [0 ]),
90
68
start = sequence .finish + params .dt ,
@@ -103,56 +81,61 @@ def _aquisition(
103
81
104
82
sequence += ro_pulse1 + ro_pulse2
105
83
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 } "
106
95
sweeper_amplitude = Sweeper (
107
96
Parameter .amplitude ,
108
97
delta_amplitude_range ,
109
- pulses = [ p for p in native_gate . coupler_pulses ( * pair )][: 1 ] ,
98
+ pulses = coupler_flux_pulses ,
110
99
type = SweeperType .FACTOR ,
111
100
)
112
101
sweeper_duration = Sweeper (
113
102
Parameter .duration ,
114
103
delta_duration_range ,
115
- pulses = [ p for p in native_gate . coupler_pulses ( * pair )] ,
104
+ pulses = coupler_flux_pulses + qubit_flux_pulses ,
116
105
)
117
106
118
- # repeat the experiment as many times as defined by nshots
119
107
results = platform .sweep (
120
108
sequence ,
121
109
ExecutionParameters (
122
110
nshots = params .nshots ,
123
- acquisition_type = AcquisitionType .INTEGRATION ,
111
+ acquisition_type = AcquisitionType .DISCRIMINATION ,
124
112
averaging_mode = AveragingMode .CYCLIC ,
125
113
),
126
114
sweeper_duration ,
127
115
sweeper_amplitude ,
128
116
)
129
117
130
- # TODO: Explore probabilities instead of magnitude
131
118
data .register_qubit (
132
119
ordered_pair [0 ],
133
120
ordered_pair [1 ],
134
121
delta_duration_range ,
135
122
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 ) ,
138
125
)
126
+ data .label = "Probability of state |1>"
139
127
140
128
return data
141
129
142
130
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 ()
151
134
152
135
153
- def plot (data : ChevronCouplersData , fit : ChevronCouplersResults , target ):
136
+ def plot (data : ChevronData , fit : Results , target ):
154
137
return _plot (data , None , target )
155
138
156
139
157
- coupler_chevron = Routine (_aquisition , _fit , plot , two_qubit_gates = True )
140
+ coupler_chevron = Routine (_acquisition , _fit , plot , two_qubit_gates = True )
158
141
"""Coupler cz/swap flux routine."""
0 commit comments