Skip to content

Commit

Permalink
Hotfix/bus delay (#439)
Browse files Browse the repository at this point in the history
* bus delay

* unittest support for bus settings delay

* update changelog

* black formatting

* fixing type hint

* fixing typing hint

* bus logic

* removing complexity in logic and ignore typing

* format

* unittest to set parameter delay on buses

* black formatting

* relocating unittest for delay parameter

* black formatting

* including build_execution mock

* moving changes into changelog-dev

* test: 🧪 Fix coverage.

---------

Co-authored-by: AlbertMitjans <[email protected]>
  • Loading branch information
jjmartinezQT and AlbertMitjans authored Jun 22, 2023
1 parent c19b30f commit bb1d9db
Show file tree
Hide file tree
Showing 15 changed files with 71 additions and 18 deletions.
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This document contains the changes of the current release.

### New features since last release

- Added hotfix for bus delay issue from Hardware:
This fix adds a delay for each pulse on a bus
https://github.com/qilimanjaro-tech/qililab/pull/439

- Added `T1` portfolio experiment
[#409](https://github.com/qilimanjaro-tech/qililab/pull/409)

Expand Down
6 changes: 3 additions & 3 deletions interrogate_badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/qililab/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class RUNCARD:
VOLTAGE_SOURCE = "voltage_source"
CURRENT_SOURCE = "current_source"
DISTORTIONS = "distortions"
DELAY = "delay"


class PLATFORM:
Expand Down
2 changes: 2 additions & 0 deletions src/qililab/experiment/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ def set_parameter(
self.build_execution()
else:
element.set_parameter(parameter=parameter, value=value, channel_id=channel_id) # type: ignore
if parameter == Parameter.DELAY:
self.build_execution()

def to_dict(self):
"""Convert Experiment into a dictionary.
Expand Down
31 changes: 23 additions & 8 deletions src/qililab/platform/components/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ class BusSettings(DDBBElement):
system_control (SystemControl): System control used to control and readout the qubits of the bus.
port (int): Chip's port where bus is connected.
distortions (list[PulseDistotion]): List of the distortions to apply to the Bus.
delay (int): Bus delay
"""

system_control: SystemControl
port: int
platform_instruments: InitVar[Instruments]
distortions: list[PulseDistortion]
delay: int

def __post_init__(self, platform_instruments: Instruments): # type: ignore # pylint: disable=arguments-differ
if isinstance(self.system_control, dict):
Expand Down Expand Up @@ -101,6 +103,15 @@ def distortions(self):
"""
return self.settings.distortions

@property
def delay(self):
"""Bus 'delay' property.
Returns:
int: settings.delay.
"""
return self.settings.delay

@property
def category(self):
"""Bus 'category' property.
Expand Down Expand Up @@ -143,19 +154,23 @@ def to_dict(self):
RUNCARD.SYSTEM_CONTROL: self.system_control.to_dict(),
BUS.PORT: self.port,
RUNCARD.DISTORTIONS: [distortion.to_dict() for distortion in self.distortions],
RUNCARD.DELAY: self.delay,
}

def set_parameter(self, parameter: Parameter, value: float | str | bool, channel_id: int | None = None):
def set_parameter(self, parameter: Parameter, value: int | float | str | bool, channel_id: int | None = None):
"""_summary_
Args:
parameter (Parameter): parameter settings of the instrument to update
value (float | str | bool): value to update
value (int | float | str | bool): value to update
channel_id (int | None, optional): instrument channel to update, if multiple. Defaults to None.
"""
try:
self.system_control.set_parameter(parameter=parameter, value=value, channel_id=channel_id)
except ParameterNotFound as error:
raise ParameterNotFound(
f"No parameter with name {parameter.value} was found in the bus with alias {self.alias}"
) from error
if parameter == Parameter.DELAY:
self.settings.delay = int(value)
else:
try:
self.system_control.set_parameter(parameter=parameter, value=value, channel_id=channel_id)
except ParameterNotFound as error:
raise ParameterNotFound(
f"No parameter with name {parameter.value} was found in the bus with alias {self.alias}"
) from error
9 changes: 6 additions & 3 deletions src/qililab/pulse/circuit_to_pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ def translate(self, circuits: list[Circuit]) -> list[PulseSchedule]:
chip=chip,
)
if readout_pulse_event is not None:
pulse_schedule.add_event(pulse_event=readout_pulse_event, port=port)
_, bus = self.platform.get_bus(port=port)
pulse_schedule.add_event(pulse_event=readout_pulse_event, port=port, port_delay=bus.settings.delay) # type: ignore
with contextlib.suppress(ValueError):
# If we find a flux port, create empty schedule for that port
flux_port = chip.get_port_from_qubit_idx(idx=m_gate.target_qubits[0], line=Line.FLUX)
Expand Down Expand Up @@ -92,7 +93,8 @@ def translate(self, circuits: list[Circuit]) -> list[PulseSchedule]:
chip=chip,
)
if pulse_event is not None:
pulse_schedule.add_event(pulse_event=pulse_event, port=port)
_, bus = self.platform.get_bus(port=port)
pulse_schedule.add_event(pulse_event=pulse_event, port=port, port_delay=bus.settings.delay) # type: ignore
# add padd time to CZ target qubit to sync it with parking gate
# if there is more than 1 pad time, add max (this is a bit misleading)
pad_time = max((time for _, time in parking_gates_pads), default=0)
Expand All @@ -112,7 +114,8 @@ def translate(self, circuits: list[Circuit]) -> list[PulseSchedule]:
self._update_time(time=time, qubit_idx=gate.target_qubits[0], pulse_time=pad_time)
self._update_time(time=time, qubit_idx=gate.control_qubits[0], pulse_time=pad_time)
if pulse_event is not None: # this happens for the Identity gate
pulse_schedule.add_event(pulse_event=pulse_event, port=port)
_, bus = self.platform.get_bus(port=port)
pulse_schedule.add_event(pulse_event=pulse_event, port=port, port_delay=bus.settings.delay) # type: ignore

for qubit in chip.qubits:
with contextlib.suppress(ValueError):
Expand Down
3 changes: 2 additions & 1 deletion src/qililab/pulse/pulse_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ class PulseSchedule:

elements: list[PulseBusSchedule] = field(default_factory=list)

def add_event(self, pulse_event: PulseEvent, port: int):
def add_event(self, pulse_event: PulseEvent, port: int, port_delay: int):
"""Add pulse event.
Args:
pulse (PulseEvent): PulseEvent object.
"""
pulse_event.start_time += port_delay
for pulse_sequence in self.elements:
if port == pulse_sequence.port:
pulse_sequence.add_event(pulse_event=pulse_event)
Expand Down
1 change: 1 addition & 0 deletions src/qililab/settings/runcard_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class BusSchema:
port: int
distortions: list[dict]
alias: str | None = None
delay: int = 0

@dataclass
class ChipSchema:
Expand Down
1 change: 1 addition & 0 deletions src/qililab/typings/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ class Parameter(str, Enum):
OUT1_OFFSET_PATH0 = "out1_offset_path0"
OUT0_OFFSET_PATH1 = "out0_offset_path1"
OUT1_OFFSET_PATH1 = "out1_offset_path1"
DELAY = "delay"


class ResultName(str, Enum):
Expand Down
3 changes: 3 additions & 0 deletions tests/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,7 @@ class Galadriel:
},
NodeName.PORT.value: 0,
RUNCARD.DISTORTIONS: [],
RUNCARD.DELAY: 0,
},
{
RUNCARD.ID: 1,
Expand All @@ -527,6 +528,7 @@ class Galadriel:
},
NodeName.PORT.value: 1,
RUNCARD.DISTORTIONS: [],
RUNCARD.DELAY: 0,
},
{
RUNCARD.ID: 2,
Expand All @@ -540,6 +542,7 @@ class Galadriel:
},
NodeName.PORT.value: 10,
RUNCARD.DISTORTIONS: [],
RUNCARD.DELAY: 0,
},
]

Expand Down
3 changes: 2 additions & 1 deletion tests/unit/execution/test_execution_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def test_build_method_with_wrong_pulse_bus_schedule(
):
"""Test build method with wrong pulse sequence."""
test_port = 1234
pulse_schedule.add_event(pulse_event=pulse_event, port=test_port)
delay = 0
pulse_schedule.add_event(pulse_event=pulse_event, port=test_port, port_delay=delay)
with pytest.raises(ValueError, match=f"There is no bus connected to port {test_port}."):
EXECUTION_BUILDER.build(platform=platform, pulse_schedules=[pulse_schedule])

Expand Down
10 changes: 10 additions & 0 deletions tests/unit/experiment/test_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,16 @@ def test_set_parameter_method_with_instrument_controller_reset(self, exp: Experi
is False
)

def test_set_parameter_method_with_delay(self, exp: Experiment):
"""Test set_parameter method with delay parameter."""
bus_delay = 0
exp.build_execution = MagicMock()
alias = Galadriel.buses[0][RUNCARD.ALIAS]
element = exp.platform.get_element(alias)
exp.set_parameter(element=element, alias=alias, parameter=Parameter.DELAY, value=bus_delay)
assert exp.platform.get_bus_by_alias(alias).delay == bus_delay
exp.build_execution.assert_called_once_with()


class TestReset:
"""Unit tests for the reset option."""
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/platform/test_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from qililab.platform import Bus, Buses, Platform, Schema
from qililab.settings import RuncardSchema
from qililab.system_control import ReadoutSystemControl
from qililab.typings.enums import InstrumentName
from qililab.typings.enums import InstrumentName, Parameter
from tests.data import Galadriel
from tests.utils import platform_db, platform_yaml

Expand Down
11 changes: 11 additions & 0 deletions tests/unit/pulse/test_circuit_to_pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 0,
"distortions": [],
"delay": 0,
},
{
"id_": 20,
Expand All @@ -187,6 +188,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 8,
"distortions": [],
"delay": 0,
},
{
"id_": 30,
Expand All @@ -200,6 +202,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 13,
"distortions": [],
"delay": 0,
},
{
"id_": 21,
Expand All @@ -213,6 +216,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 9,
"distortions": [],
"delay": 0,
},
{
"id_": 31,
Expand All @@ -226,6 +230,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 14,
"distortions": [],
"delay": 0,
},
{
"id_": 22,
Expand All @@ -239,6 +244,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 10,
"distortions": [],
"delay": 0,
},
{
"id_": 32,
Expand All @@ -252,6 +258,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 15,
"distortions": [],
"delay": 0,
},
{
"id_": 23,
Expand All @@ -265,6 +272,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 11,
"distortions": [],
"delay": 0,
},
{
"id_": 33,
Expand All @@ -278,6 +286,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 16,
"distortions": [],
"delay": 0,
},
{
"id_": 24,
Expand All @@ -291,6 +300,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 12,
"distortions": [],
"delay": 0,
},
{
"id_": 34,
Expand All @@ -304,6 +314,7 @@ def fixture_platform(chip: Chip) -> Platform:
},
"port": 17,
"distortions": [],
"delay": 0,
},
]
settings = RuncardSchema.PlatformSettings(**settings) # type: ignore # pylint: disable=unexpected-keyword-arg
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/pulse/test_pulse_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class TestPulseSequences:

def test_add_event_method(self, pulse_schedule: PulseSchedule, pulse_event: PulseEvent):
"""Tead add_event method."""
pulse_schedule.add_event(pulse_event=pulse_event, port=0)
pulse_schedule.add_event(pulse_event=pulse_event, port=0, port_delay=0)

def test_to_dict_method(self, pulse_schedule: PulseSchedule):
"""Test to_dict method"""
Expand Down

0 comments on commit bb1d9db

Please sign in to comment.