Networks.jl

Networks.jl is a work-in-progress, alternative graph library in Julia. Designed to overcome the limitations of Graphs.jl when custom graphs, hyperedges, multi-edges, or arbitrary vertex types are needed.

Motivation

During the development of Tenet.jl, several requirements arose that are not covered by Graphs.jl:

  • Support for hyperedges, open edges, and multi-edges
  • Graph types based on the incidence matrix
  • Automatic method delegation for wrapping graph types, based on DelegatorTraits.jl
  • Allowing vertices of any type, not just integers
  • Interfaces that are extensible and better decoupled from concrete implementations

The Edge entity

One of the biggest differences between the AbstractGraph and Network interfaces is that for Network, an edge is its own entity; i.e. an edge can be just an identifier like a UUID instead of a relation between two other objects.

This choice makes a Network a more abstract interface than AbstractGraph, where the description of a graph is not forced to be based on adjacency matrices.

Basic Example

Let's start by creating an IncidentNetwork, which implements a Network using a incidence matrix representation. The first type parameterizes the vertex type, while the second one parameterizes the edge type.

julia> g = IncidentNetwork{Symbol, Int}()IncidentNetwork{Symbol, Int64}(Dict{Symbol, Set{Int64}}(), Dict{Int64, Set{Symbol}}())
julia> vertex_type(g)Symbol
julia> edge_type(g)Int64

Unlike Graphs.jl, you must explicitly pass the vertex to add it to a network.

julia> addvertex!(g, :a)IncidentNetwork{Symbol, Int64}(Dict{Symbol, Set{Int64}}(:a => Set()), Dict{Int64, Set{Symbol}}())
julia> addvertex!(g, :b)IncidentNetwork{Symbol, Int64}(Dict{Symbol, Set{Int64}}(:a => Set(), :b => Set()), Dict{Int64, Set{Symbol}}())
julia> addvertex!(g, :c)IncidentNetwork{Symbol, Int64}(Dict{Symbol, Set{Int64}}(:a => Set(), :b => Set(), :c => Set()), Dict{Int64, Set{Symbol}}())
julia> vertices(g)KeySet for a Dict{Symbol, Set{Int64}} with 3 entries. Keys: :a :b :c

Edges are independent entities in an IncidentNetwork, so you must add it and then relate it to the vertices.

julia> addedge!(g, 1)IncidentNetwork{Symbol, Int64}(Dict{Symbol, Set{Int64}}(:a => Set(), :b => Set(), :c => Set()), Dict{Int64, Set{Symbol}}(1 => Set()))
julia> edges(g)KeySet for a Dict{Int64, Set{Symbol}} with 1 entry. Keys: 1
julia> Networks.link!(g, :a, 1)Set{Symbol} with 1 element: :a
julia> Networks.link!(g, :b, 1)Set{Symbol} with 2 elements: :a :b
julia> Networks.link!(g, :c, 1)Set{Symbol} with 3 elements: :a :b :c

In order to query the vertices connected by an edge, use edge_incidents:

julia> edge_incidents(g, 1)Set{Symbol} with 3 elements:
  :a
  :b
  :c

... and to query the edges connected to a vertex, use edge_incidents:

julia> vertex_incidents(g, :a)Set{Int64} with 1 element:
  1