4

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.

RM-
  • 986
  • 1
  • 13
  • 30

3 Answers3

2

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)
carstenbauer
  • 9,817
  • 1
  • 27
  • 40
2

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
2

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
sbromberger
  • 1,026
  • 6
  • 12