Policies Module
Tip
Lost in the architecture? This page explains where policies fit. Start with The Big Picture: Where Policies Fit below before diving into details.
Overview
At a Glance
- Purpose:
Decision-making for path selection (“which path should I use?”)
- Location:
fusion/policies/- Key Files:
heuristic_policy.py,ml_policy.py,rl_policy.py,policy_factory.py- Used By:
SDNOrchestrator(new architecture)- Protocol:
Implements
ControlPolicyfromfusion/interfaces/control_policy.py
What this module does:
Chooses which path to use when serving a network request
Provides pluggable strategies: heuristics, ML models, RL models
Decouples “how to decide” from “how to execute”
What this module does NOT do:
Find paths (that’s
fusion/modules/routing/orfusion/pipelines/)Assign spectrum (that’s
fusion/modules/spectrum/)Run the simulation (that’s
fusion/core/)
The Big Picture: Where Policies Fit
Important
The core confusion: FUSION has many components with similar-sounding names. This section explains what each does and how they connect.
The Request Lifecycle
When a network request arrives, here’s what happens:
+==========================================================================+
| REQUEST LIFECYCLE (Orchestrator) |
+==========================================================================+
| |
| 1. REQUEST ARRIVES |
| | |
| v |
| 2. FIND CANDIDATE PATHS |
| +------------------+ |
| | RoutingPipeline | "Here are 5 possible paths from A to Z" |
| +--------+---------+ |
| | |
| v |
| 3. CHECK FEASIBILITY |
| +------------------+ |
| | SpectrumPipeline | "Paths 1, 3, 5 have available spectrum" |
| | SNRPipeline | "Paths 1, 5 meet SNR requirements" |
| +--------+---------+ |
| | |
| v |
| 4. SELECT PATH <-- THIS IS WHERE POLICIES COME IN |
| +------------------+ |
| | ControlPolicy | "Use path 5 (it's the least congested)" |
| +--------+---------+ |
| | |
| v |
| 5. ALLOCATE RESOURCES |
| +------------------+ |
| | SpectrumPipeline | "Reserved slots 10-15 on path 5" |
| +--------+---------+ |
| | |
| v |
| 6. LIGHTPATH CREATED |
| |
+==========================================================================+
Policies answer ONE question: Given multiple feasible paths, which one should we use?
The Component Map
Here’s how all the confusing components relate:
+==========================================================================+
| FUSION COMPONENT MAP |
+==========================================================================+
| |
| DECISION LAYER ("What to do") |
| +------------------------------------------------------------------+ |
| | fusion/policies/ <-- YOU ARE HERE | |
| | - Chooses which path to use | |
| | - Heuristics, ML models, RL models | |
| +------------------------------------------------------------------+ |
| | |
| | "Use path 3" |
| v |
| ORCHESTRATION LAYER ("How to coordinate") |
| +------------------------------------------------------------------+ |
| | fusion/core/orchestrator.py | |
| | - Coordinates the request lifecycle | |
| | - Calls pipelines in order | |
| | - Asks policy for decisions | |
| +------------------------------------------------------------------+ |
| | |
| v |
| PIPELINE LAYER ("How to do multi-step operations") |
| +------------------------------------------------------------------+ |
| | fusion/pipelines/ | |
| | - RoutingPipeline: find paths with protection | |
| | - SlicingPipeline: split large requests | |
| | - ProtectionPipeline: 1+1 backup allocation | |
| +------------------------------------------------------------------+ |
| | |
| v |
| ALGORITHM LAYER ("How to do single operations") |
| +------------------------------------------------------------------+ |
| | fusion/modules/routing/ - K-shortest path, congestion-aware | |
| | fusion/modules/spectrum/ - First-fit, best-fit assignment | |
| | fusion/modules/snr/ - GSNR calculation | |
| +------------------------------------------------------------------+ |
| | |
| v |
| DATA LAYER ("What we're working with") |
| +------------------------------------------------------------------+ |
| | fusion/domain/ - Request, NetworkState, Lightpath | |
| | fusion/interfaces/ - Protocols (contracts) | |
| +------------------------------------------------------------------+ |
| |
+==========================================================================+
Why Do Policies Exist?
Without policies: The path selection logic is hardcoded in the simulator. Want to try a different strategy? Edit the simulator code.
With policies: Path selection is pluggable. The simulator asks “which path?” and the policy answers. Want to try ML? Just swap the policy.
# Without policies (hardcoded in simulator)
def serve_request(request, paths):
for path in paths:
if path.is_feasible:
return allocate(path) # Always picks first feasible
# With policies (pluggable)
def serve_request(request, paths, policy):
action = policy.select_action(request, paths, network_state)
return allocate(paths[action]) # Policy decides
This separation enables:
Experimentation: Compare heuristics vs ML vs RL without changing simulator
Research: Train RL agents, then deploy trained policies
Flexibility: Different policies for different scenarios
Legacy vs. Orchestrator Architecture
Warning
FUSION has TWO architectures. Understanding which one you’re working with is critical to understanding where policies fit.
+==========================================================================+
| LEGACY vs ORCHESTRATOR |
+==========================================================================+
| |
| LEGACY (SDNController) ORCHESTRATOR (SDNOrchestrator) |
| ======================== ============================== |
| |
| - Decision logic embedded - Decision logic in policies |
| - Uses modules directly - Uses pipelines + adapters |
| - No ControlPolicy protocol - Uses ControlPolicy protocol |
| - Hardcoded heuristics - Pluggable policies |
| |
| fusion/core/sdn_controller.py fusion/core/orchestrator.py |
| | | |
| v v |
| fusion/modules/routing/ fusion/pipelines/ (routing) |
| fusion/modules/spectrum/ fusion/pipelines/ (slicing) |
| | | |
| | v |
| | fusion/policies/ <-- NEW |
| | | |
| v v |
| [Hardcoded: first feasible] [Pluggable: any policy] |
| |
+==========================================================================+
Key point: Policies are part of the NEW orchestrator architecture. If you’re working with the legacy SDNController, policies are not used.
How Policies Work Internally
The ControlPolicy Protocol
All policies implement this protocol (from fusion/interfaces/control_policy.py):
class ControlPolicy(Protocol):
def select_action(
self,
request: Request,
options: list[PathOption],
network_state: NetworkState,
) -> int:
"""Return index of selected path, or -1 if none."""
...
def update(
self,
request: Request,
action: int,
reward: float,
) -> None:
"""Update policy from experience (no-op for heuristics/deployment)."""
...
Policy Types
Type |
When to Use |
Examples |
|---|---|---|
Heuristic |
Baselines, simple deployments, fallbacks |
FirstFeasible, ShortestFeasible, LeastCongested |
ML |
Deploy pre-trained supervised models |
PyTorch, sklearn, ONNX models |
RL |
Deploy pre-trained RL agents |
SB3 PPO, MaskablePPO, DQN |
Decision Flow
+===========================================================================+
| POLICY DECISION FLOW |
+===========================================================================+
| |
| INPUT |
| +------------------------+ |
| | Request | bandwidth=100Gbps, src=A, dst=Z |
| | PathOptions (list) | [Path0, Path1, Path2, Path3, Path4] |
| | NetworkState | current topology and spectrum state |
| +------------------------+ |
| | |
| v |
| FEASIBILITY CHECK (already done by pipelines) |
| +------------------------+ |
| | PathOption.is_feasible | [True, False, True, False, True] |
| +------------------------+ |
| | |
| v |
| POLICY DECISION |
| +------------------------+ |
| | Heuristic: "Pick shortest feasible" -> Path 2 |
| | ML Model: "Score each, pick highest" -> Path 4 |
| | RL Model: "Predict action from obs" -> Path 0 |
| +------------------------+ |
| | |
| v |
| OUTPUT |
| +------------------------+ |
| | action = 2 | (index of selected path) |
| +------------------------+ |
| |
+===========================================================================+
Components
heuristic_policy.py
- Purpose:
Rule-based deterministic policies
- Classes:
FirstFeasiblePolicy,ShortestFeasiblePolicy,LeastCongestedPolicy,RandomFeasiblePolicy,LoadBalancedPolicy
from fusion.policies import ShortestFeasiblePolicy
policy = ShortestFeasiblePolicy()
action = policy.select_action(request, options, network_state)
# Returns index of shortest feasible path
ml_policy.py
- Purpose:
Deploy pre-trained ML models (PyTorch, sklearn, ONNX)
- Classes:
MLControlPolicy,FeatureBuilder, model wrappers
from fusion.policies import MLControlPolicy
policy = MLControlPolicy(
model_path="model.pt",
fallback_type="first_feasible", # Fallback if model fails
)
action = policy.select_action(request, options, network_state)
Key feature: Automatic fallback to heuristic on errors.
rl_policy.py
- Purpose:
Deploy pre-trained Stable-Baselines3 models
- Classes:
RLPolicy,RLControlPolicy
from fusion.policies import RLPolicy
policy = RLPolicy.from_file(
model_path="trained_ppo.zip",
algorithm="MaskablePPO",
)
action = policy.select_action(request, options, network_state)
Key feature: Supports action masking for feasibility constraints.
policy_factory.py
- Purpose:
Create policies from configuration
- Classes:
PolicyFactory,PolicyConfig
from fusion.policies import PolicyFactory, PolicyConfig
# From config object
config = PolicyConfig(policy_type="heuristic", policy_name="shortest")
policy = PolicyFactory.create(config)
# From dictionary (e.g., config file)
policy = PolicyFactory.from_dict({"policy_type": "rl", "model_path": "model.zip"})
Frequently Asked Questions
Q: What’s the difference between policies and pipelines?
Policies = decision-making (“which path?”)
Pipelines = execution (“find paths”, “assign spectrum”, “allocate protection”)
Q: What’s the difference between policies and modules/routing?
Policies = high-level decision (“use path 3”)
modules/routing = low-level algorithm (“here are the 5 shortest paths”)
Q: Why do ML/RL policies have update() if they don’t learn?
The update() method satisfies the ControlPolicy protocol. For deployment
policies, it’s a no-op. For online RL training, use UnifiedSimEnv with SB3’s
learn() method instead.
Q: When should I use policies vs. just using modules directly?
Use policies when you want pluggable path selection in the orchestrator
Use modules directly for custom simulations or legacy SDNController
Q: Can I add a new policy type?
Yes! Implement the ControlPolicy protocol:
from fusion.interfaces.control_policy import ControlPolicy
class MyCustomPolicy:
def select_action(self, request, options, network_state) -> int:
# Your logic here
return selected_index
def update(self, request, action, reward) -> None:
pass # No-op for deployment
def get_name(self) -> str:
return "MyCustomPolicy"
Testing
# Run all policy tests
pytest fusion/policies/tests/ -v
# Run with coverage
pytest --cov=fusion.policies fusion/policies/tests/