MultilayerGraphs.jl
A Julia package for the creation, manipulation and analysis of the structure, dynamics and functions of multilayer graphs.
Install / Use
/learn @JuliaGraphs/MultilayerGraphs.jlREADME
MultilayerGraphs.jl
<img align="right" width="220" height="220" src="https://github.com/JuliaGraphs/MultilayerGraphs.jl/blob/main/docs/src/assets/logo.png?raw=true">MultilayerGraphs.jl is a Julia package for the creation, manipulation and analysis of the structure, dynamics and functions of multilayer graphs.
🌐 Overview
A multilayer graph is a graph consisting of multiple standard subgraphs called layers which can be interconnected through bipartite graphs called interlayers composed of the vertex sets of two different layers and the edges between them. The vertices in each layer represent a single set of nodes, although not all nodes have to be represented in every layer.
Formally, a multilayer graph can be defined as a triple $G=(V,E,L)$, where:
- $V$ is the set of vertices;
- $E$ is the set of edges, pairs of nodes $(u, v)$ representing a connection, relationship or interaction between the nodes $u$ and $v$;
- $L$ is a set of layers, which are subsets of $V$ and $E$ encoding the nodes and edges within each layer.
Each layer $\ell$ in $L$ is a tuple $(V_\ell, E_\ell)$, where $V_\ell$ is a subset of $V$ that represents the vertices within that layer, and $E_\ell$ is a subset of $E$ that represents the edges within that layer.
Multiple theoretical frameworks have been proposed to formally subsume all instances of multilayer graphs (De Domenico et al. (2013); Kivelä et al. (2014); Boccaletti et al. (2014); Lee et al. (2015); Aleta and Moreno (2019); Bianconi (2018); Cozzo et al. (2018); Artime et al. (2022); De Domenico (2022)).
Multilayer graphs have been adopted to model the structure and dynamics of a wide spectrum of high-dimensional, non-linear, multi-scale, time-dependent complex systems including physical, chemical, biological, neuronal, socio-technical, epidemiological, ecological and economic networks (Cozzo et al. (2013); Granell et al. (2013); Massaro and Bagnoli (2014); Estrada and Gomez-Gardenes (2014); Azimi-Tafreshi (2016); Baggio et al. (2016); DeDomenico et al. (2016); Amato et al. (2017); DeDomenico (2017); Pilosof et al. (2017); de Arruda et al. (2017); Gosak et al. (2018); Soriano-Panos et al. (2018); Timteo et al. (2018); Buldú et al. (2018); Lim et al. (2019); Mangioni et al. (2020); Aleta et al. (2020); Aleta et al. (2022)).
MultilayerGraphs.jl is an integral part of the JuliaGraphs ecosystem extending Graphs.jl so all the methods and metrics exported by Graphs.jl work for multilayer graphs, but due to the special nature of multilayer graphs the package features a peculiar implementation that maps a standard integer-labelled vertex representation to a more user-friendly framework exporting all the objects an experienced practitioner would expect such as nodes (Node), vertices (MultilayerVertex), layers (Layer), interlayers (Interlayer), etc.
MultilayerGraphs.jl features multilayer-specific methods and metrics including the global clustering coefficient, the overlay clustering coefficient, the multilayer eigenvector centrality, the multilayer modularity and the Von Neumann entropy.
Finally, MultilayerGraphs.jl has been integrated within the JuliaDynamics ecosystem so that any Multilayer(Di)Graph can be utilised as an argument to the GraphSpace constructor in Agents.jl.
🔰 Installation
To install the latest stable release of MultilayerGraphs.jl, make sure you have installed Julia v1.8 or later and run the following command:
using Pkg
Pkg.add("MultilayerGraphs")
The development version can be installed as follows:
using Pkg
Pkg.add(url="https://github.com/JuliaGraphs/MultilayerGraphs.jl")
🔍 Usage
Let's begin by importing the necessary dependencies and setting the relevant constants.
# Import necessary dependencies
using Distributions, Graphs, SimpleValueGraphs
using MultilayerGraphs
# Set the number of nodes
const n_nodes = 100
# Create a list of nodes
const node_list = [Node("node_$i") for i in 1:n_nodes]
Layers and Interlayers
We will instantiate layers and interlayers with randomly-selected edges and vertices adopting a variety of techniques. Layers and Interlayers are not immutable, and mostly behave like normal graphs. The user is invited to consult the API for further details.
Here we define a layer with an underlying simple directed graph using a graph generator-like (or "configuration model"-like) constructor which allows us to specify both the indegree and the outdegree sequences. Before instantiating each layer we sample the number of its vertices and, optionally, of its edges.
# Create a simple directed layer
n_vertices = rand(1:100) # Number of vertices
layer_simple_directed = layer_simpledigraph( # Layer constructor
:layer_simple_directed, # Layer name
sample(node_list, n_vertices; replace=false), # Nodes represented in the layer
Truncated(Normal(5, 5), 0, 20), # Indegree sequence distribution
Truncated(Normal(5, 5), 0, 20) # Outdegree sequence distribution
)
Then we define a layer with an underlying simple weighted directed graph. This is another kind of constructor that allows the user to specify the number of edges to be randomly distributed among vertices.
# Create a simple directed weighted layer
n_vertices = rand(1:n_nodes) # Number of vertices
n_edges = rand(n_vertices:(n_vertices * (n_vertices - 1) - 1)) # Number of edges
layer_simple_directed_weighted = layer_simpleweighteddigraph( # Layer constructor
:layer_simple_directed_weighted, # Layer name
sample(node_list, n_vertices; replace=false), # Nodes represented in the layer
n_edges; # Number of randomly distributed edges
default_edge_weight=(src, dst) -> rand() # Function assigning weights to edges
)
Similar constructors, more flexible at the cost of ease of use, enable a finer tuning. The constructor we use below should be necessary only in rare circumstances, e.g. if the equivalent simplified constructor layer_simplevaldigraph is not able to infer the correct return types of default_vertex_metadata or default_edge_metadata, or to use and underlying graph structure that isn't currently supported.
# Create a simple directed value layer
n_vertices = rand(1:n_nodes) # Number of vertices
n_edges = rand(n_vertices:(n_vertices * (n_vertices - 1) - 1)) # Num
