Skip to content
Merged
17 changes: 11 additions & 6 deletions docs/source/tutorial/chapter6/custom_app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from __future__ import annotations
from sequence.app.app import App
from sequence.kernel.process import Process
from sequence.kernel.event import Event
from sequence.topology.router_net_topo import RouterNetTopo
Expand All @@ -11,10 +12,9 @@
from sequence.topology.node import QuantumRouter


class PeriodicApp:
class PeriodicApp(App):
def __init__(self, node: QuantumRouter, other: str, memory_size=25, target_fidelity=0.9):
self.node = node
self.node.set_app(self)
super().__init__(node)
self.other = other
self.memory_size = memory_size
self.target_fidelity = target_fidelity
Expand All @@ -36,20 +36,25 @@ def get_reservation_result(self, reservation: "Reservation", result: bool):
else:
print("Reservation failed at time", self.node.timeline.now() * 1e-12)

def get_other_reservation(self, reservation: "Reservation"):
pass

def get_memory(self, info: "MemoryInfo"):
if info.state == "ENTANGLED" and info.remote_node == self.other:
print("\t{} app received memory {} ENTANGLED at time {}".format(
self.node.name, info.index, self.node.timeline.now() * 1e-12))
self.node.resource_manager.update(None, info.memory, "RAW")


class ResetApp:
class ResetApp(App):
def __init__(self, node, other_node_name, target_fidelity=0.9):
self.node = node
self.node.set_app(self)
super().__init__(node)
self.other_node_name = other_node_name
self.target_fidelity = target_fidelity

def get_reservation_result(self, reservation: "Reservation", result: bool):
pass

def get_other_reservation(self, reservation):
"""called when receiving the request from the initiating node.

Expand Down
3 changes: 2 additions & 1 deletion sequence/app/__init__.py
Comment thread
Tw1ZZLER marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
__all__ = ['random_request']
__all__ = ["app", "random_request", "teleport_app", "request_app"]


def __dir__():
return sorted(__all__)
81 changes: 81 additions & 0 deletions sequence/app/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""Abstract base class for SeQUeNCe applications.

This module defines the `App` interface that all node-attached applications
must implement. The three abstract callback methods, `get_memory`, `get_reservation_result`,
and `get_other_reservation` are correspond to the calls that `QuantumRouter` already
makes on whatever application is attached via `set_app`.

Subclasses that track throughput (e.g. `RequestApp`) should override it with a
meaningful implementation.
"""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from ..network_management.reservation import Reservation
from ..resource_management.memory_manager import MemoryInfo
from ..topology.node import QuantumRouter


class App(ABC):
"""Abstract base application attached to a quantum network node.

Every concrete application must subclass `App` and implement the three
abstract callback methods that `QuantumRouter` relies on.

The constructor automatically registers the application on the node via
`node.set_app(self)`, so subclasses should always call
`super().__init__(node)`!

Attributes:
node (QuantumRouter): The node this application is attached to.
name (str): Human-readable name for the application instance.
"""

def __init__(self, node: QuantumRouter):
self.node: QuantumRouter = node
self.node.set_app(self)
self.name: str = f"{self.node.name}.{self.__class__.__name__}"

@abstractmethod
def get_memory(self, info: MemoryInfo) -> None:
"""Called when an entangled memory becomes available.

Args:
info (MemoryInfo): Information about the available memory.
"""
Comment thread
Tw1ZZLER marked this conversation as resolved.
pass

@abstractmethod
def get_reservation_result(self, reservation: Reservation, result: bool) -> None:
"""Called when a reservation result is received from the network manager.

Args:
reservation (Reservation): The reservation that completed.
result (bool): Whether the reservation was approved.
"""
Comment thread
Tw1ZZLER marked this conversation as resolved.
pass

@abstractmethod
def get_other_reservation(self, reservation: Reservation) -> None:
"""Called when a reservation initiated by another node is approved and
uses this node as the responder.

Args:
reservation (Reservation): The approved reservation.
"""
pass

def set_name(self, name: str) -> None:
"""Override the default application name.

Args:
name (str): New name for the application.
"""
self.name = name

def __str__(self) -> str:
return self.name
18 changes: 9 additions & 9 deletions sequence/app/request_app.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
from __future__ import annotations
import warnings
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from ..topology.node import QuantumRouter
from ..network_management.reservation import Reservation
from ..resource_management.memory_manager import MemoryInfo

from .app import App
from ..kernel.event import Event
from ..kernel.process import Process
from ..utils import log


class RequestApp:
class RequestApp(App):
"""Code for the request application.

This application will create a request for entanglement.
Expand All @@ -35,8 +37,7 @@ class RequestApp:
"""

def __init__(self, node: QuantumRouter):
self.node: QuantumRouter = node
self.node.set_app(self)
super().__init__(node)
self.responder: str = ""
self.start_t: int = -1
self.end_t: int = -1
Expand All @@ -46,7 +47,6 @@ def __init__(self, node: QuantumRouter):
self.memory_counter: int = 0
self.path: list[str] = []
self.memo_to_reservation: dict[int, Reservation] = {}
self.name: str = f"{self.node.name}.RequestApp"

def start(self, responder: str, start_t: int, end_t: int, memo_size: int, fidelity: float):
"""Method to start the application.
Expand Down Expand Up @@ -143,6 +143,11 @@ def get_memory(self, info: MemoryInfo) -> None:
self.node.resource_manager.update(None, info.memory, "RAW")

def get_throughput(self) -> float:
warnings.warn(
"get_throughput is deprecated and will be removed in a future release, use THROUGHPUT_METRIC from the metrics module instead",
category=FutureWarning,
stacklevel=2,
)
return self.memory_counter / (self.end_t - self.start_t) * 1e12


Expand All @@ -167,8 +172,3 @@ def schedule_reservation(self, reservation: Reservation) -> None:
event = Event(reservation.end_time, process)
self.node.timeline.schedule(event)

def set_name(self, name: str):
self.name = name

def __str__(self) -> str:
return self.name
5 changes: 3 additions & 2 deletions sequence/topology/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from ..components.optical_channel import QuantumChannel, ClassicalChannel
from ..components.memory import Memory
from ..components.photon import Photon
from ..app.app import App
from ..app.request_app import RequestApp
from ..app.teleport_app import TeleportApp

Expand Down Expand Up @@ -441,12 +442,12 @@ def memory_expire(self, memory: "Memory") -> None:
"""
self.resource_manager.memory_expire(memory)

def set_app(self, app: "RequestApp"):
def set_app(self, app: "App"):
"""Method to add an application to the node.
NOTE: a quantum router can only have one application at a time.

Args:
app (RequestApp): the application to add.
app (App): the application to add.
"""
self.app = app

Expand Down