Skip to content

Commit

Permalink
Merge pull request #623 from qiboteam/couplers2
Browse files Browse the repository at this point in the history
Couplers2
  • Loading branch information
Jacfomg authored Nov 3, 2023
2 parents cdbd5c4 + 87805e0 commit d852e82
Show file tree
Hide file tree
Showing 11 changed files with 342 additions and 53 deletions.
5 changes: 4 additions & 1 deletion src/qibolab/couplers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Dict, Optional, Union

from qibolab.channels import Channel
from qibolab.native import CouplerNatives

QubitId = Union[str, int]
"""Type for Coupler names."""
Expand All @@ -19,7 +20,9 @@ class Coupler:
"Coupler number or name."

sweetspot: float = 0
"Coupler sweetspot to turn it on/off or off/on."
"Coupler sweetspot to center it's flux dependence if needed."
native_pulse: CouplerNatives = field(default_factory=CouplerNatives)
"For now this only contains the calibrated pulse to activate the coupler."

flux: Optional[Channel] = None
"flux (:class:`qibolab.platforms.utils.Channel`): Channel used to send flux pulses to the qubit."
Expand Down
45 changes: 45 additions & 0 deletions src/qibolab/dummy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,76 @@ native_gates:
relative_start: 0, phase: 0, type: qd}
MZ: {duration: 2000, amplitude: 0.1, shape: Rectangular(), frequency: 5500000000.0,
relative_start: 0, phase: 0, type: ro}
coupler:
0:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 0}
1:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 1}
3:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 3}
4:
CP: {duration: 30, amplitude: 0.05, shape: Rectangular(), relative_start: 0, type: coupler, coupler: 4}
two_qubit:
0-2:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 0}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 0, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 0, relative_start: 0,
type: coupler}
1-2:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 1, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 1, relative_start: 0,
type: coupler}
2-3:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 3}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 3, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 3, relative_start: 0,
type: coupler}
2-4:
CZ:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 4}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 4, relative_start: 0,
type: coupler}
iSWAP:
- {duration: 30, amplitude: 0.05, shape: Rectangular(), qubit: 2, relative_start: 0,
type: qf}
- {type: virtual_z, phase: 0.0, qubit: 1}
- {type: virtual_z, phase: 0.0, qubit: 2}
- {duration: 30, amplitude: 0.05, shape: Rectangular(), coupler: 4, relative_start: 0,
type: coupler}

characterization:
single_qubit:
Expand Down
120 changes: 94 additions & 26 deletions src/qibolab/instruments/zhinst.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
from qibo.config import log

from qibolab import AcquisitionType, AveragingMode, ExecutionParameters
from qibolab.couplers import Coupler
from qibolab.instruments.abstract import INSTRUMENTS_DATA_FOLDER, Controller
from qibolab.instruments.port import Port
from qibolab.pulses import CouplerFluxPulse, FluxPulse, PulseSequence, PulseType
from qibolab.qubits import Qubit
from qibolab.sweeper import Parameter

# this env var just needs to be set
Expand All @@ -32,6 +34,8 @@
"SHFSG_FORCE_COMMAND_TABLE": True,
"SHFSG_MIN_PLAYWAVE_HINT": 32,
"SHFSG_MIN_PLAYZERO_HINT": 32,
"HDAWG_MIN_PLAYWAVE_HINT": 64,
"HDAWG_MIN_PLAYZERO_HINT": 64,
}

"""Translating to Zurich ExecutionParameters"""
Expand Down Expand Up @@ -220,28 +224,48 @@ class ZhSweeperLine:
Near Time sweeps
"""

def __init__(self, sweeper, qubit=None, sequence=None):
def __init__(self, sweeper, qubit=None, sequence=None, pulse=None):
self.sweeper = sweeper
"""Qibolab sweeper"""

# TODO: Do something with the pulse coming here
if sweeper.parameter is Parameter.bias:
pulse = FluxPulse(
start=sequence.start,
duration=sequence.duration,
amplitude=1,
shape="Rectangular",
channel=qubit.flux.name,
qubit=qubit.name,
)
if isinstance(qubit, Qubit):
pulse = FluxPulse(
start=0,
duration=sequence.duration + sequence.start,
amplitude=1,
shape="Rectangular",
channel=qubit.flux.name,
qubit=qubit.name,
)
self.signal = f"flux{qubit.name}"
if isinstance(qubit, Coupler):
pulse = CouplerFluxPulse(
start=0,
duration=sequence.duration + sequence.start,
amplitude=1,
shape="Rectangular",
channel=qubit.flux.name,
qubit=qubit.name,
)
self.signal = f"couplerflux{qubit.name}"

self.pulse = pulse
self.signal = f"flux{qubit.name}"

self.zhpulse = lo.pulse_library.const(
uid=(f"{pulse.type.name.lower()}_{pulse.qubit}_"),
length=round(pulse.duration * NANO_TO_SECONDS, 9),
amplitude=pulse.amplitude,
)

elif sweeper.parameter is Parameter.start:
if pulse:
self.pulse = pulse
self.signal = f"flux{qubit}"

self.zhpulse = ZhPulse(pulse).zhpulse

# Need something better to store multiple sweeps on the same pulse
self.zhsweeper = self.select_sweeper(sweeper)

Expand Down Expand Up @@ -324,7 +348,7 @@ def connect(self):
self.create_device_setup()
# To fully remove logging #configure_logging=False
# I strongly advise to set it to 20 to have time estimates of the experiment duration!
self.session = lo.Session(self.device_setup, log_level=30)
self.session = lo.Session(self.device_setup, log_level=20)
self.device = self.session.connect(do_emulation=self.emulation)
self.is_connected = True

Expand Down Expand Up @@ -591,8 +615,13 @@ def nt_loop(sweeper):
aux_list[aux_list.index(element)].add_sweeper(sweeper, qubits[pulse.qubit])

if sweeper.parameter.name in SWEEPER_BIAS:
for qubit in sweeper.qubits:
zhsequence[f"flux{qubit.name}"] = [ZhSweeperLine(sweeper, qubit, sequence)]
# TODO: This should be joined
if sweeper.qubits:
for qubit in sweeper.qubits:
zhsequence[f"flux{qubit.name}"] = [ZhSweeperLine(sweeper, qubit, sequence)]
if sweeper.couplers:
for coupler in sweeper.couplers:
zhsequence[f"couplerflux{coupler.name}"] = [ZhSweeperLine(sweeper, coupler, sequence)]

# FIXME: This may not place the Zhsweeper when the start occurs among different sections or lines
if sweeper.parameter.name in SWEEPER_START:
Expand All @@ -603,7 +632,7 @@ def nt_loop(sweeper):
if isinstance(aux_list[aux_list.index(element)], ZhPulse):
aux_list.insert(
aux_list.index(element),
ZhSweeperLine(sweeper, pulse.qubit, sequence),
ZhSweeperLine(sweeper, pulse.qubit, sequence, pulse),
)
break

Expand Down Expand Up @@ -765,15 +794,16 @@ def couplerflux(self, exp, couplers):
i = 0
time = 0
for pulse in self.sequence[f"couplerflux{c}"]:
if not isinstance(pulse, ZhSweeperLine):
pulse.zhpulse.uid += str(i)
exp.delay(
signal=f"couplerflux{c}",
time=round(pulse.pulse.start * NANO_TO_SECONDS, 9) - time,
)
time = round(pulse.pulse.duration * NANO_TO_SECONDS, 9) + round(
pulse.pulse.start * NANO_TO_SECONDS, 9
)
# TODO: Needed ?
# if not isinstance(pulse, ZhSweeperLine):
pulse.zhpulse.uid += str(i)
exp.delay(
signal=f"couplerflux{c}",
time=round(pulse.pulse.start * NANO_TO_SECONDS, 9) - time,
)
time = round(pulse.pulse.duration * NANO_TO_SECONDS, 9) + round(
pulse.pulse.start * NANO_TO_SECONDS, 9
)
# TODO: Check of play sweep doesnt need changes
if isinstance(pulse, ZhSweeperLine):
self.play_sweep(exp, coupler, pulse, section="couplerflux")
Expand Down Expand Up @@ -861,16 +891,40 @@ def play_after_set(sequence, ptype):
def measure_relax(self, exp, qubits, relaxation_time, acquisition_type):
"""qubit readout pulse, data acquisition and qubit relaxation"""
play_after = None

# TODO: This need to be simplified !!!
if len(self.sequence_qibo.qf_pulses) != 0 and len(self.sequence_qibo.qd_pulses) != 0:
play_after = (
self.play_after_set(self.sequence_qibo.qf_pulses, "bias")
if self.sequence_qibo.qf_pulses.finish > self.sequence_qibo.qd_pulses.finish
else self.play_after_set(self.sequence_qibo.qd_pulses, "drive")
)
if len(self.sequence_qibo.cf_pulses) != 0 and len(self.sequence_qibo.qd_pulses) != 0:
play_after = (
self.play_after_set(self.sequence_qibo.cf_pulses, "bias_coupler")
if self.sequence_qibo.cf_pulses.finish > self.sequence_qibo.qd_pulses.finish
else self.play_after_set(self.sequence_qibo.qd_pulses, "drive")
)

elif len(self.sequence_qibo.qf_pulses) != 0:
play_after = self.play_after_set(self.sequence_qibo.qf_pulses, "bias")
elif len(self.sequence_qibo.qd_pulses) != 0:
play_after = self.play_after_set(self.sequence_qibo.qd_pulses, "drive")
elif (
len(self.sequence_qibo.qf_pulses) != 0
and len(self.sequence_qibo.qd_pulses) != 0
and len(self.sequence_qibo.cf_pulses) != 0
):
seq_qf = self.sequence_qibo.qf_pulses.finish
seq_qd = self.sequence_qibo.qd_pulses.finish
seq_cf = self.sequence_qibo.cf_pulses.finish
# add here for flux coupler pulses
if seq_qf > seq_qd and seq_qf > seq_cf:
play_after = self.play_after_set(self.sequence_qibo.qf_pulses, "bias")
elif seq_qd > seq_qf and seq_qd > seq_cf:
play_after = self.play_after_set(self.sequence_qibo.qd_pulses, "drive")
elif seq_cf > seq_qf and seq_cf > seq_qd:
play_after = self.play_after_set(self.sequence_qibo.cf_pulse, "bias_coupler")

readout_schedule = defaultdict(list)
qubit_readout_schedule = defaultdict(list)
Expand All @@ -894,6 +948,16 @@ def measure_relax(self, exp, qubits, relaxation_time, acquisition_type):
for pulse, q, iq_angle in zip(pulses, qubits, iq_angles):
pulse.zhpulse.uid += str(i)

if play_after is None:
exp.delay(
signal=f"measure{q}",
time=self.sequence_qibo.start * NANO_TO_SECONDS,
)
exp.delay(
signal=f"acquire{q}",
time=self.sequence_qibo.start * NANO_TO_SECONDS,
)

# Integration weights definition or load from the chip folder
weights_file = (
INSTRUMENTS_DATA_FOLDER / f"{self.chip}/weights/integration_weights_optimization_qubit_{q}.npy"
Expand Down Expand Up @@ -1063,7 +1127,7 @@ def sweep(self, qubits, couplers, sequence: PulseSequence, options, *sweepers):
self.offsets_off()

# html containing the pulse sequence schedule
# lo.show_pulse_sheet("pulses", self.exp)
lo.show_pulse_sheet("pulses", self.exp)
return results

# TODO: This may work without changes due to couplers
Expand Down Expand Up @@ -1101,8 +1165,12 @@ def sweep_recursion(self, qubits, couplers, exp, exp_calib, exp_options):
sweeper.values *= aux_max

if sweeper.parameter is Parameter.bias:
for qubit in sweeper.qubits:
parameter = ZhSweeperLine(sweeper, qubit, self.sequence_qibo).zhsweeper
if sweeper.qubits:
for qubit in sweeper.qubits:
parameter = ZhSweeperLine(sweeper, qubit, self.sequence_qibo).zhsweeper
if sweeper.couplers:
for qubit in sweeper.couplers:
parameter = ZhSweeperLine(sweeper, qubit, self.sequence_qibo).zhsweeper

elif sweeper.parameter is Parameter.start:
parameter = ZhSweeperLine(sweeper).zhsweeper
Expand Down
Loading

0 comments on commit d852e82

Please sign in to comment.