Skip to content

Commit

Permalink
sketch ideas
Browse files Browse the repository at this point in the history
  • Loading branch information
hay-k committed Jan 30, 2024
1 parent 3e2ce53 commit 61c143f
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 5 deletions.
40 changes: 40 additions & 0 deletions src/qibolab/channel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from dataclasses import dataclass


@dataclass
class NamedChannel:
"""Channel that has a name. This is part of the end-user API, i.e. is in the top layer.
The idea is the following:
1. End users do not know what are the types of channels in a platform, they just know names.
They use only NamedChannels to describe pulse sequences. THey can create NamedChannels using the get_channel function below.
2. User makes some assumptions about the types of channels. E.g. they assume that the channel NamedChannel("qubit_0/drive")
is an IQ channel, hence they play IQ pulses on it and they provide IQChannelConfig for it.
3. Upon receival of the execution request qibolab validates that the requested execution can be done,
i.e. user's assumptions are correct.
4. qibolab proceeds with execution.
For the last two steps qibolab needs to replace generic NamedChannels with concrete channels (e.g. ZurichIQChannel, QbloxDCChannel, etc.), and
those should be available in Platform.
TODO: I am not sure if having this class brings any benefit to this plan compared to the case where we just use naked str names, but I will figure
this out later during implementation.
TODO: One might argue that it is reasonable to provide the end user the types of channels as well, and then do all the validation while constructing the pulse
sequence. I though about this and failed to find real benefit, it just seems to complicate the code and the user-facing API for no real benefit.
Please comment if you have anything to say regarding this.
"""

name: str

def __str__(self) -> str:
return self.name


def get_channel(element: str, line: str) -> NamedChannel:
"""Named channel for given element (qubit|qubit|coupler|etc.), for given line (drive|flux|readout|etc.)
This method can be used by users to get the channel that they are interested in, and then use this in their pulse sequence description.
FIXME: the function signature is just a mock/sketch. Needs to be designed properly.
"""
return NamedChannel(f"{element}/{line}")
38 changes: 38 additions & 0 deletions src/qibolab/channel_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from dataclasses import dataclass
from enum import Enum
"""Definitions for common options for various types of channels. This is part of the end-user API, i.e. is in the top layer.
"""


class AcquisitionType(Enum):
RAW = "raw"
INTEGRATION = "integration"
CLASSIFICATION = "classification"


@dataclass
class DCChannelConfig:
sampling_rate: float
bias: float


@dataclass
class IQChannelConfig:
sampling_rate: float
frequency: float
mixer_g: float = 0.0
mixer_phi: float = 0.0


@dataclass
class OscillatorChannelConfig:
frequency: float


@dataclass
class AcquisitionChannelConfig:
type: AcquisitionType
integration_weights_i: list[float]
integration_weights_q: list[float]
classification_kernel: float # FIXME

28 changes: 28 additions & 0 deletions src/qibolab/instruments/abstract_channels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from abc import ABC, abstractmethod

"""
In the instrument layer we shall try to do as many things as possible in a unified manner.
This file defines the requrements on various types of channels that instrument-specific implementations should satisfy.
E.g. there could be methods returning the memory limitation on a channel, so that a unified unrolling-batching algorithm
can be written that is not instrument-specific.
TODO: this needs proper design
"""


class IQChannel(ABC):

@abstractmethod
def foo(self, args, kwargs):
...

@abstractmethod
def bar(self, args):
...


class DCChannel(ABC):

@abstractmethod
def baz(self, kwargs):
...
24 changes: 24 additions & 0 deletions src/qibolab/instruments/zi/channels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from qibolab.channel import NamedChannel
from qibolab.channel_config import IQChannelConfig
from qibolab.instruments.abstract_channels import IQChannel

"""The glue part of the platform shall manually define all channels according to wiring,
then for each user request appropriate channels will be collected for handling the execution.
"""


class ZIIQChannel(IQChannel, NamedChannel):
"""IQChannel using a from Zurich instruments
"""

config: IQChannelConfig

# FIXME: add all the necessary stuff needed to define a ZI IQ channel

def foo(self, args, kwargs):
...

def bar(self, args):
...

# TODO: Similarly, other ZI channels can be implemented
5 changes: 0 additions & 5 deletions src/qibolab/qubits.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,6 @@ class Qubit:
threshold: Optional[float] = None
iq_angle: float = 0.0
kernel: Optional[np.ndarray] = field(default=None, repr=False)
# required for mixers (not sure if it should be here)
mixer_drive_g: float = 0.0
mixer_drive_phi: float = 0.0
mixer_readout_g: float = 0.0
mixer_readout_phi: float = 0.0

readout: Optional[Channel] = None
feedback: Optional[Channel] = None
Expand Down

0 comments on commit 61c143f

Please sign in to comment.