Interfaces Module
Overview
At a Glance
- Purpose:
Define contracts (protocols) for pluggable algorithm components
- Location:
fusion/interfaces/- Key Files:
pipelines.py,control_policy.py,router.py,spectrum.py- Depends On:
fusion.domain(type references only)- Used By:
fusion.core,fusion.pipelines,fusion.modules
The interfaces module defines contracts that algorithm implementations must satisfy.
It uses Python’s typing.Protocol classes to specify what methods a routing algorithm,
spectrum assigner, or control policy must provide without prescribing how they work internally.
Why this module matters:
Enables pluggable algorithms: swap routing strategies without changing orchestration code
Provides type safety: mypy catches incompatible implementations before runtime
Documents expected behavior: protocols serve as executable specification
Supports testing: mock implementations satisfy protocols for unit testing
In This Section
Pipeline Protocols - Detailed documentation of each pipeline protocol
Creating Custom Implementations - How to create your own algorithm implementations
When you work here:
Understanding how algorithms plug into the simulation pipeline
Creating a new routing, spectrum, or SNR algorithm
Adding a custom RL or heuristic control policy
Debugging why an implementation doesn’t satisfy a protocol
How Interfaces Differ from Domain and Modules
New developers often confuse interfaces, domain objects, and module implementations. Here’s how they relate:
+------------------+ +------------------+ +------------------+
| Interfaces | | Domain | | Modules |
| (Contracts) | | (Data Objects) | |(Implementations) |
+------------------+ +------------------+ +------------------+
| | |
| "What methods | "What data | "How to actually
| must exist" | flows between" | compute routes"
| | |
v v v
+------------------+ +------------------+ +------------------+
| RoutingPipeline | | RouteResult | | KShortestPath |
| Protocol: | | (frozen): | | Class: |
| find_routes() |<----| paths |<----| find_routes() |
| -> RouteResult | | weights_km | | returns |
+------------------+ +------------------+ +------------------+
^ ^ |
| | |
| type checks | data types | implements
| implementation | for results | protocol
| | |
+------+--------+ +------+--------+ +------+--------+
| Orchestrator |------->| NetworkState |<-------| Algorithm |
| uses protocol | | passed to | | reads from |
| type hints | | algorithms | | state |
+---------------+ +---------------+ +---------------+
Aspect |
Interfaces |
Domain |
Modules |
|---|---|---|---|
Purpose |
Define method contracts |
Define data structures |
Implement algorithms |
Contains |
Protocol classes (no logic) |
Dataclasses (no logic) |
Classes with algorithm logic |
Example |
|
|
|
Mutability |
N/A (type definitions) |
Mostly immutable |
May have internal state |
Location |
|
|
|
In short:
Interfaces: Define what methods an algorithm must have (the contract)
Domain: Define what data flows between components (the vocabulary)
Modules: Provide actual implementations of algorithms (the logic)
Understanding Policies vs Interfaces
Another common confusion is between control policies and pipeline interfaces:
- Control Policy
A decision-making component that selects which path to use from available options. Policies can be heuristics (first-fit, shortest), RL agents (PPO, DQN), or supervised/unsupervised learning models.
- Pipeline Interface
A computation component that generates options or validates constraints. Pipelines find routes, check spectrum availability, or validate SNR.
Request arrives
|
v
+------------------+
| RoutingPipeline | <-- Interface: generates candidate paths
| find_routes() |
+------------------+
|
| returns paths=[A-B-C, A-D-C, A-E-C]
v
+------------------+
| SpectrumPipeline | <-- Interface: checks spectrum for each path
| find_spectrum() |
+------------------+
|
| returns options with feasibility info
v
+------------------+
| ControlPolicy | <-- Policy: SELECTS which option to use
| select_action() | (heuristic, RL, or supervised/unsupervised)
+------------------+
|
| returns selected path index
v
+------------------+
| Orchestrator |
| allocates path |
+------------------+
Key difference:
Pipelines are stateless computations that don’t make decisions
Policies are decision-makers that choose among computed options
Key Concepts
Understanding these concepts is essential before working with interfaces:
- Protocol (typing.Protocol)
A Python typing construct that defines structural subtyping. Unlike abstract base classes, protocols don’t require inheritance; any class with matching methods satisfies the protocol. This enables duck typing with type safety.
from typing import Protocol class RoutingPipeline(Protocol): def find_routes(self, source, dest, bw, state) -> RouteResult: ... # Any class with find_routes() satisfies RoutingPipeline # No inheritance required!
- runtime_checkable
A decorator that enables
isinstance()checks on protocols at runtime. All FUSION pipeline protocols are runtime_checkable.@runtime_checkable class RoutingPipeline(Protocol): ... # Now you can do: if isinstance(my_router, RoutingPipeline): result = my_router.find_routes(...)
- Pipeline
A component that performs one stage of request processing. Pipelines receive
NetworkStateas a parameter (never store it) and return immutable result objects.- Stateless Design
Pipelines and the orchestrator don’t store
NetworkState. State is passed per-call, enabling easier testing and potential parallelization.
Architecture
Module Structure
fusion/interfaces/
|-- __init__.py # Public API exports
|-- pipelines.py # Pipeline protocols (Routing, Spectrum, etc.)
|-- control_policy.py # ControlPolicy protocol for path selection
|-- router.py # Legacy: AbstractRoutingAlgorithm ABC
|-- spectrum.py # Legacy: AbstractSpectrumAssigner ABC
|-- snr.py # Legacy: AbstractSNRMeasurer ABC
|-- agent.py # Legacy: AgentInterface ABC
|-- factory.py # Legacy: AlgorithmFactory, SimulationPipeline
|-- README.md # Module documentation
|-- TODO.md # Legacy removal roadmap
`-- tests/ # Unit tests
|-- test_pipelines.py
|-- test_control_policy.py
`-- ...
Pipeline Protocols
The main interfaces are defined in pipelines.py:
Protocol |
Key Method |
Purpose |
|---|---|---|
|
|
Find candidate paths between source and destination |
|
|
Find available spectrum slots along a path |
|
|
Pack requests onto existing lightpaths |
|
|
Check signal quality meets modulation requirements |
|
|
Divide large requests into smaller allocations |
Control Policy Protocol
The ControlPolicy protocol in control_policy.py defines the decision-making interface:
@runtime_checkable
class ControlPolicy(Protocol):
def select_action(
self,
request: Request,
options: list[PathOption],
network_state: NetworkState,
) -> int:
"""Select which path option to use. Returns index or -1."""
...
def update(self, request: Request, action: int, reward: float) -> None:
"""Update policy based on feedback (for RL policies)."""
...
def get_name(self) -> str:
"""Return policy name for logging."""
...
How Interfaces Connect to the Simulator
The orchestrator uses pipeline protocols to process requests:
SimulationEngine
|
| creates
v
+------------------+
| SDNOrchestrator |
| |
| routing: RoutingPipeline <-- Protocol type hints
| spectrum: SpectrumPipeline
| grooming: GroomingPipeline?
| snr: SNRPipeline?
| slicing: SlicingPipeline?
| policy: ControlPolicy?
+------------------+
|
| handle_arrival(request, network_state)
v
+------------------+
| 1. routing.find_routes() --> RouteResult
| 2. spectrum.find_spectrum() --> SpectrumResult
| 3. snr.validate() --> SNRResult
| 4. policy.select_action() --> int (path index)
| 5. network_state.allocate() --> lightpath_id
+------------------+
|
v
AllocationResult (success or blocked)
Key points:
The orchestrator type-hints pipelines using protocol types
Actual implementations come from
fusion/pipelines/or adaptersAny class satisfying the protocol can be substituted
This enables easy testing with mock implementations
Components
pipelines.py
- Purpose:
Define pipeline protocols for the orchestrator
- Key Classes:
RoutingPipeline,SpectrumPipeline,GroomingPipeline,SNRPipeline,SlicingPipeline
Contains the protocol definitions that all pipeline implementations must satisfy. Each protocol specifies:
Required method signatures
Parameter types (using domain objects)
Return types (using result objects)
Optional parameters with defaults
See Pipeline Protocols for detailed documentation of each protocol.
control_policy.py
- Purpose:
Define the decision-making interface for path selection
- Key Classes:
ControlPolicy- Type Alias:
PolicyAction(int)
Defines the protocol for control policies that select actions from available options. Supports three types of policies:
Heuristic policies: Rule-based selection (first-fit, shortest-path)
RL policies: Reinforcement learning agents (PPO, DQN, IQL)
Supervised/unsupervised policies: Pre-trained models for inference
Legacy Files (Deprecated)
The following files contain legacy abstract base classes that are being replaced by the protocol-based approach:
router.py:AbstractRoutingAlgorithmABCspectrum.py:AbstractSpectrumAssignerABCsnr.py:AbstractSNRMeasurerABCagent.py:AgentInterfaceABCfactory.py:AlgorithmFactory,SimulationPipeline
Warning
Legacy ABCs are deprecated and will be removed in a future version.
New implementations should use the Protocol-based interfaces in pipelines.py
and control_policy.py.
Dependencies
This Module Depends On
fusion.domain- Type references forRequest,NetworkState, result objectstyping-Protocol,runtime_checkable, type hints
Modules That Depend On This
fusion.core.orchestrator- Uses protocol type hints for pipelinesfusion.core.pipeline_factory- Creates implementations satisfying protocolsfusion.pipelines/- Implements the pipeline protocolsfusion.modules/rl/- Implements ControlPolicy protocol
Development Guide
Getting Started
Read the Key Concepts section above
Understand the difference between interfaces and implementations
Review Pipeline Protocols for protocol signatures
See Creating Custom Implementations for step-by-step implementation guides
Common Tasks
Creating a new routing algorithm
See Creating Custom Implementations for a complete guide. Quick overview:
Create a class with
find_routes()method matchingRoutingPipelineAccept
NetworkStateas parameter (don’t store it)Return
RouteResultfromfusion.domain.resultsRegister with pipeline factory if needed
Creating a custom control policy
Create a class with
select_action(),update(),get_name()Accept
PathOptionlist and return selected indexImplement
update()for RL (orpassfor heuristics)
Adding a new protocol method
Add the method signature to the protocol in
pipelines.pyUpdate all implementations (check with mypy)
Update mock implementations in tests
Document the new method
Testing
- Test Location:
fusion/interfaces/tests/- Run Tests:
pytest fusion/interfaces/tests/ -v
Test files:
test_pipelines.py- Protocol isinstance checks, mock implementationstest_control_policy.py- ControlPolicy protocol tests
Testing with protocols:
Protocols enable easy testing with mock implementations:
from fusion.interfaces import RoutingPipeline
class MockRouter:
"""Mock that satisfies RoutingPipeline for testing."""
def find_routes(self, source, dest, bw, state, *, forced_path=None):
from fusion.domain.results import RouteResult
return RouteResult.empty("mock")
# Use in tests
def test_orchestrator_handles_no_routes():
mock_router = MockRouter()
assert isinstance(mock_router, RoutingPipeline) # Protocol check passes
orchestrator = create_orchestrator(routing=mock_router)
result = orchestrator.handle_arrival(request, state)
assert result.block_reason == BlockReason.NO_PATH
Troubleshooting
Issue: Implementation doesn’t satisfy protocol
- Symptom:
mypy error “Argument has incompatible type”
- Cause:
Method signature doesn’t match protocol exactly
- Solution:
Check parameter types, return type, and optional parameters match
Issue: isinstance() check fails on valid implementation
- Symptom:
isinstance(obj, Protocol)returns False unexpectedly- Cause:
Protocol missing
@runtime_checkabledecorator, or method missing- Solution:
Ensure all required methods exist with correct names
Issue: Confusion about where to add logic
- Symptom:
Unsure whether code belongs in interface, domain, or module
- Solution:
If it’s a method signature: interfaces
If it’s a data structure: domain
If it’s algorithm logic: modules (e.g.,
fusion/modules/routing/)