Core Concepts and Architecture
This guide explains the fundamental concepts and architectural design of py3plex, with an emphasis on how multilayer data are represented internally and how node-layer pairs flow through the library.
What are Multilayer Networks?
A multilayer network is a graph where nodes can participate in multiple contexts (layers), and edges may connect node instances within the same layer (intra-layer) or across layers (inter-layer). Each node-layer pair is treated as a distinct entity; the same node label may appear in several layers, but each occurrence is independent unless coupled by an inter-layer edge.
Key Characteristics
Traditional (Single-Layer) Networks
One node type
One edge type
Single interaction context
Multilayer Networks
Multiple node types (per-layer semantics)
Multiple edge types
Multiple layers of interaction
Both inter-layer and intra-layer connections
Types of Multilayer Networks
- Multiplex Networks
Multiple layers with the same set of nodes but different edge semantics.
Example: Social network with friendship, colleague, and family layers.
- Heterogeneous Networks (HINs)
Different node types, each with type-specific relationships.
Example: Academic network with authors, papers, and venues.
- Temporal Networks
Networks that evolve over time, represented as time-sliced layers.
Example: Communication network across different time periods.
- Interdependent Networks
Multiple networks where nodes in one network depend on nodes in another.
Example: Power grid and communication network interdependency.
Core Data Structure
The multi_layer_network Class
The central data structure in py3plex is the multi_layer_network class, which provides:
Layer management: add, remove, and query network layers
Node and edge operations: efficient addition and retrieval
NetworkX integration: works directly with NetworkX algorithms that support multigraphs
Matrix representations: supra-adjacency and layer-specific matrices
Basic Structure
from py3plex.core import multinet
# Create a multilayer network
network = multinet.multi_layer_network()
# The underlying NetworkX graph (MultiDiGraph or MultiGraph)
nx_graph = network.core_network
# Layer management
layers = network.get_layers() # List of layer names
layer_map = network.layer_name_map # Layer name to ID mapping
Internal Representation
py3plex represents multilayer networks using:
Core NetworkX graph: A
MultiDiGraphorMultiGraphstoring all node-layer pairs and edgesLayer encoding: Node-layer pairs are encoded as
node_id---layer_idusing a delimiter (default:---)Layer mapping: Bidirectional mapping between layer names and integer IDs for compact matrix construction
Attributes: Node and edge attributes stored on the underlying NetworkX graph
Node ordering: Methods that return matrices follow the node-layer ordering from
network.get_nodes()
Example:
# Node 'A' in 'layer1' is stored internally as 'A---layer1'
network.add_nodes([('A', 'layer1')])
# Access the encoded node
encoded_nodes = list(network.core_network.nodes())
# ['A---layer1']
Network Construction
Creating Networks from Scratch
Nodes and edges are specified as (node_id, layer_name) tuples so each occurrence of a node is bound to a specific layer.
from py3plex.core import multinet
network = multinet.multi_layer_network()
# Add layers explicitly (optional)
network.add_layer('social')
network.add_layer('professional')
# Add nodes (layer is created if it doesn't exist)
network.add_nodes([
('Alice', 'social'),
('Bob', 'social'),
('Alice', 'professional'),
('Bob', 'professional')
])
# Add edges within layers (intra-layer)
network.add_edges([
[('Alice', 'social'), ('Bob', 'social'), 1.0]
])
# Add edges between layers (inter-layer)
network.add_edges([
[('Alice', 'social'), ('Alice', 'professional'), 1.0]
])
Loading from Files
py3plex supports multiple input formats; the loader creates layers on demand when they are discovered in the input.
# From edge list
network = multinet.multi_layer_network().load_network(
"data.edgelist",
input_type="edgelist",
directed=False
)
# From multilayer edge list (source, target, layer)
network = multinet.multi_layer_network().load_network(
"data.multiedgelist",
input_type="multiedgelist"
)
# From GraphML
network = multinet.multi_layer_network().load_network(
"data.graphml",
input_type="graphml"
)
Network Operations
Querying Network Elements
# Get all nodes
nodes = network.get_nodes(data=True) # yields (node, data_dict)
# Get nodes in a specific layer
layer_nodes = network.get_nodes(layer='layer1')
# Get all edges
edges = network.get_edges(data=True)
# Get neighbors of a node in a layer
neighbors = network.get_neighbors(('Alice', 'social'))
# Get all layers (sorted by internal ID)
layers = network.get_layers()
Network Transformations
# Aggregate multiple layers into one
aggregated = network.aggregate_layers(['layer1', 'layer2'], 'combined')
# Extract a single layer as a NetworkX graph
layer_graph = network.get_layer_subgraph('layer1')
# Project to a node type (for heterogeneous networks)
projected = network.project_to_node_type('author')
Matrix Representations
# Get supra-adjacency matrix (all layers stacked)
supra_adj = network.get_supra_adjacency_matrix()
# Row/column ordering matches network.get_nodes() (node-layer pairs)
# Get adjacency matrix for a single layer
layer_adj = network.get_adjacency_matrix(layer='layer1')
# Get inter-layer coupling matrix
coupling = network.get_coupling_matrix()
Architectural Design
Modular Structure
py3plex follows a modular architecture:
py3plex/
├── core/ # Core data structures
│ ├── multinet.py # multi_layer_network class
│ ├── parsers.py # I/O for various formats
│ └── converters.py # Format conversion utilities
├── algorithms/ # Network algorithms
│ ├── community_detection/
│ ├── statistics/
│ ├── multilayer_algorithms/
│ └── general/
├── visualization/ # Plotting and rendering
│ ├── multilayer.py
│ ├── drawing_machinery.py
│ └── layout_algorithms.py
└── wrappers/ # High-level interfaces
Design Principles
- 1. NetworkX Compatibility
All operations are compatible with NetworkX, allowing use of NetworkX algorithms.
- 2. Lazy Evaluation
Expensive operations (e.g., matrix construction) are computed on demand.
- 3. Graceful Degradation
Optional features fail gracefully if dependencies are missing.
- 4. Extensibility
Easy to extend with custom algorithms and visualizations.
Data Flow
Input Data (files, NetworkX, edge lists)
↓
Parsers → multi_layer_network object
↓
Network Operations (add, remove, query)
↓
├→ Algorithms → Metrics, Communities, Centrality
├→ Visualization → Plots, Layouts
└→ Export → Files, Matrices, NetworkX
Integration with NetworkX
Full NetworkX Compatibility
The core_network attribute is a standard NetworkX graph that stores encoded node-layer pairs, so any NetworkX algorithm that supports multigraphs works directly. Algorithms that expect simple graphs may require preprocessing (e.g., edge aggregation or conversion to a simple graph):
import networkx as nx
from py3plex.core import multinet
# Create py3plex network
mlnet = multinet.multi_layer_network()
mlnet.add_edges([
[('A', 'L1'), ('B', 'L1'), 1]
])
# Access underlying NetworkX graph
G = mlnet.core_network
# Encoded nodes appear as strings (e.g., 'A---L1')
# Use any NetworkX function
betweenness = nx.betweenness_centrality(G)
communities = nx.community.louvain_communities(G)
diameter = nx.diameter(G) if nx.is_connected(G) else float('inf')
Converting to/from NetworkX
# From NetworkX to py3plex
import networkx as nx
from py3plex.core import multinet
G = nx.karate_club_graph()
mlnet = multinet.multi_layer_network()
mlnet.load_network_from_networkx(G)
# From py3plex to NetworkX
G_export = mlnet.core_network
Supra-Adjacency Matrix
Mathematical Definition
The supra-adjacency matrix is a block matrix representation of a multilayer network where rows and columns correspond to node-layer pairs. If layer \(\alpha\) has \(n_\alpha\) nodes, the overall matrix has size \((\sum_\alpha n_\alpha) \times (\sum_\alpha n_\alpha)\). Blocks are ordered by the layer mapping in network.layer_name_map (the same ordering returned by network.get_layers()):
Where:
\(A_\alpha\) is the \(n_\alpha \times n_\alpha\) adjacency matrix of layer \(\alpha\)
\(C_{\alpha\beta}\) is the \(n_\alpha \times n_\beta\) coupling matrix between layers \(\alpha\) and \(\beta\)
Construction in py3plex
from py3plex.core import multinet
network = multinet.multi_layer_network()
# ... add nodes and edges ...
# Get supra-adjacency matrix (sparse by default)
supra_adj = network.get_supra_adjacency_matrix(sparse=True)
# Shape: (total_node_layer_pairs, total_node_layer_pairs)
# where total_node_layer_pairs = sum of nodes in each layer (node repeated per layer)
print(f"Supra-adjacency shape: {supra_adj.shape}")
Layer-Specific Operations
Working with Individual Layers
# Get layer as NetworkX subgraph
layer_graph = network.get_layer_subgraph('layer1')
# Compute layer-specific metrics
from py3plex.algorithms.statistics import multilayer_statistics as mls
density = mls.layer_density(network, 'layer1')
clustering = nx.average_clustering(layer_graph)
Inter-Layer Analysis
# Inter-layer degree correlation
correlation = mls.inter_layer_degree_correlation(network, 'layer1', 'layer2')
# Edge overlap between layers
overlap = mls.edge_overlap(network, 'layer1', 'layer2')
# Layer similarity
similarity = mls.layer_similarity(network, 'layer1', 'layer2')
Extensibility
Adding Custom Algorithms
Extend py3plex by adding custom algorithms:
from py3plex.core import multinet
import networkx as nx
def my_custom_centrality(ml_network):
"""Compute custom centrality for multilayer network."""
G = ml_network.core_network
# Implement your algorithm
centrality = {}
for node in G.nodes():
# Custom computation
centrality[node] = compute_score(node, G)
return centrality
Custom Visualization
from py3plex.visualization import drawing_machinery as dm
import matplotlib.pyplot as plt
def custom_plot(ml_network):
"""Create custom visualization."""
fig, ax = plt.subplots(figsize=(10, 8))
# Use drawing machinery primitives
pos = dm.compute_layout(ml_network.core_network, 'force')
dm.draw_nodes(ax, ml_network.core_network, pos)
dm.draw_edges(ax, ml_network.core_network, pos)
plt.show()
Next Steps
Quick Start Tutorial - Practical usage examples
Multilayer Network Centrality Measures - Centrality measures
Multilayer Modularity and Community Detection - Community detection
Algorithm Selection Guide - Algorithm selection guide
Architecture and Design - Detailed architecture documentation