Generating a weighted and directed network form adjacency matrix in Julia

Viewed 2327

I want to generate a weighted and directed network from an adjacency matrix in Julia (v0.7).

So far I've tried:

using LightGraphs
using SimpleWeightedGraphs

A = rand(100, 100)
G = Graph(A)

but I get error:

ERROR: ArgumentError: Adjacency / distance matrices must be symmetric
Stacktrace:
 [1] SimpleGraph{Int64}(::Array{Float64,2}) at /home/user/.julia/packages/LightGraphs/PPsyP/src/SimpleGraphs/simplegraph.jl:78
 [2] SimpleGraph(::Array{Float64,2}) at /home/user/.julia/packages/LightGraphs/PPsyP/src/SimpleGraphs/simplegraph.jl:72
 [3] top-level scope at none:0

So far I have only seen the example on the github (https://github.com/JuliaGraphs/SimpleWeightedGraphs.jl) page which generates the weighted graph from and edgelist. However, I would prefer if I could generate the graph directly from an adjacency matrix.

3 Answers

By no means a Julia graph expert, but I think what you want is

julia> A = rand(100,100);

julia> G = SimpleWeightedDiGraph(A)
{100, 10000} directed simple Int64 graph with Float64 weights

Graph(a::AbstractMatrix) is the constructor for an undirected (unit-weighted) graph:

julia> A = A+transpose(A); # making A symmetric

julia> G = Graph(A)
{100, 5050} undirected simple Int64 graph

julia> weights(G)
100 × 100 default distance matrix (value = 1)

Building off crstnbr's answer, a Graph is an unweighted undirected, so the adjacency matrix is ideally symmetric with values in [0, 1].
Feeding the Graph constructor any symmetric matrix creates edges for every non-zero element:

A = rand(3,3);
Graph(A+A');
println.(edges(G));
 Edge 1 => 1
 Edge 1 => 2
 Edge 1 => 3
 Edge 2 => 2
 Edge 2 => 3
 Edge 3 => 3

The SimpleWeightedDiGraph has several constructors that can take a dense or SparseMatrixCSC adjacency matrix:

SimpleWeightedDiGraph(rand(4,4))
 {4, 16} directed simple Int64 graph with Float64 weights

SimpleWeightedDiGraph(rand([0,1], 3, 3))
 {3, 5} directed simple Int64 graph with Int64 weights

using SparseArrays
SimpleWeightedDiGraph( sprand(3, 3, 0.5) )
 {3, 5} directed simple Int64 graph with Float64 weights

The first problem you're running into is that your random adjacency matrix is not symmetric, and that's required for an undirected graph. You want to create a directed graph.

Secondly, if you want a weighted graph, you'll want to use the SimpleWeightedGraphs.jl package, which means that you can simply do

julia> using LightGraphs, SimpleWeightedGraphs

julia> a = rand(100,100);

julia> g = SimpleWeightedDiGraph(a)
{100, 10000} directed simple Int64 graph with Float64 weights

but note that this is a really bad way to create a random weighted graph because the rand function all but guarantees that this will be a complete graph. Much better is to use sprand:

julia> using SparseArrays

julia> a = sprand(100, 100, 0.2);

julia> g = SimpleWeightedDiGraph(a)
{100, 2048} directed simple Int64 graph with Float64 weights
Related