How to have condition on SimpleWeightedDiGraph function?

Hi Guys

According to the documentation the way SimpleWeightedDiGraph works is something like a g = SimpleWeightedDiGraph(heads, tails, weights). If so and if having a three list of requirements:

heads = [ 62, 17, 15, 22, 19,14,61, 21,51,35]
tails =     [62, 57, 29, 20, 19, 31,61,13,51,35]
weights = [309, 310, 307,308,302,316,321,301,302]

Is it possible when creating graph, directly exclude those edges that has same head and tails (eliminating loops) ?

And it seems that when we create g with graph package it starts at 1 regardless of the smallest node ID. For instance, in this simple example, if we call vertices(g) it return 1:62. This creates lots of single nodes that has degree of zero and makes my computations difficult when I want to work with node IDs that starts at 1000. I mean I have 1000 nodes that are empty and makes my graph very spars. When I call density on g it shows a very small number although my graph should be very dense. Is there any way to force SimpleWeightedDiGraph to not start at 1 but at the smallest node ID?

Thanks

Hi,
The best answer to both of your questions at the moment is to take care of it manually outside of the graph structure.
For self-edges, it is not hard to scan heads and tails and exclude pairs where both are identical:

new_heads = [h for (h, t, w) in zip(heads, tails, weights) if h != t]
new_tails = [t for (h, t, w) in zip(heads, tails, weights) if h != t]
new_weights = [w for (h, t, w) in zip(heads, tails, weights) if h != t]

Regarding vertex indices, the convention in the Graphs.jl ecosystem is that vertices should go from 1 to n. If you want to circumvent that, you can either

  • Translate the indices manually by keeping a dict outside of the graph
  • Use a more sophisticated structure for graphs with metadata, such as MetaGraphsNext.jl
1 Like

Thanks @gdalle for the info :slight_smile:

1 Like

Hi again @gdalle I just wanted to ask what do you suggest for translating indices?
The way I did it is in spreadsheet. But is there any direct way in julia to change IDs while keeping the relationship between nodes (how they form edges)?

For example, you have 15 nodes and suppose that we want to encode them.

node_id = union(heads, tails) |> unique! |> sort!
encode = Dict(node_id .=> 1:15)

replace!(heads, encode...)
replace!(tails, encode...)

and then just duplicate of @gdalle, we get below.

julia> new_heads = [h for (h, t, w) in zip(heads, tails, weights) if h != t]
5-element Vector{Int64}:
 4
 3
 8
 2
 7

julia> new_tails = [t for (h, t, w) in zip(heads, tails, weights) if h != t]
5-element Vector{Int64}:
 13
  9
  6
 10
  1

julia> new_weights = [w for (h, t, w) in zip(heads, tails, weights) if h != t]
5-element Vector{Int64}:
 310
 307
 308
 316
 301
1 Like

Thanks @rmsmsgood very much!

Is there any command like factorize in julia?
Python | Pandas Series.factorize() - GeeksforGeeks.

There are packages like CategoricalArrays.jl but that shouldn’t be needed here since all vertex indices and labels must be unique anyway

1 Like