# Keep track of order of graph edges when iterating over them

**URL:** https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759
**Category:** Graphs
**Tags:** graphs
**Created:** [September 11, 2023, 7:56pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759 "2023-09-11T19:56:31Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)
#### Post date: [September 11, 2023, 7:56pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/1 "2023-09-11T19:56:31Z")

</div>

I have a piece of code where I might want to convert `Graph`s to `DiGraph`s. However, I need to keep track of where the edges are (so that for the edge connecting vertices 1 and 2 in the original graph, I know where `1 => 2` and `2 => 1` are for the created digraph. However, it seems that whenever you iterate over a graph’s list o edges, they always do so in order of the index of the source followed by the destination, which makes it an utter mess to keep track of this order.

E.g, if I have:

```julia
using Graphs
g0 = DiGraph(4)
add_edge!(g0, 1, 2)
add_edge!(g0, 2, 3)
add_edge!(g0, 3, 4)
add_edge!(g0, 4, 1)
foreach(e -> println(e), edges(g0))

```

I get:

```julia
Edge 1 => 2
Edge 2 => 3
Edge 3 => 4
Edge 4 => 1

```

And then if I add the reverse edges and print:

```julia
add_edge!(g0, 2, 1)
add_edge!(g0, 3, 2)
add_edge!(g0, 4, 3)
add_edge!(g0, 1, 4)
foreach(e -> println(e), edges(g0))

```

I get:

```julia
Edge 1 => 2
Edge 1 => 4
Edge 2 => 1
Edge 2 => 3
Edge 3 => 2
Edge 3 => 4
Edge 4 => 1
Edge 4 => 3

```

While I ideally would have liked:

```julia
Edge 1 => 2
Edge 2 => 3
Edge 3 => 4
Edge 4 => 1
Edge 2 => 1
Edge 3 => 2
Edge 4 => 3
Edge 1 => 4

```

(where edge i maps to i and i+4)  
or maybe

```julia
Edge 1 => 2
Edge 2 => 1
Edge 2 => 3
Edge 3 => 2
Edge 3 => 4
Edge 4 => 3
Edge 4 => 1
Edge 1 => 4

```

(where edge i maps to 2\*(i-1)+1 and 2\*(i-1)+2)

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [September 11, 2023, 9:41pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/2 "2023-09-11T21:41:04Z")

</div>

Can you just create both graphs and then a dictionary mapping edge indices in one to edge indices in the other?

---

<div class="post-metadata">

### Author: ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)
#### Post date: [September 11, 2023, 9:45pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/3 "2023-09-11T21:45:52Z")

</div>

Sorry, confussed, do you mean creating both

```julia
g0_1 = DiGraph(4)
add_edge!(g0, 1, 2)
add_edge!(g0, 2, 3)
add_edge!(g0, 3, 4)
add_edge!(g0, 4, 1)

```

and

```julia
g0_2 = DiGraph(4)
add_edge!(g0, 2, 1)
add_edge!(g0, 3, 2)
add_edge!(g0, 4, 3)
add_edge!(g0, 1, 4)

```

or both

```julia
g0_1 = DiGraph(4)
add_edge!(g0, 1, 2)
add_edge!(g0, 2, 3)
add_edge!(g0, 3, 4)
add_edge!(g0, 4, 1)

```

and

```julia
g0_1 = DiGraph(4)
add_edge!(g0, 1, 2)
add_edge!(g0, 2, 3)
add_edge!(g0, 3, 4)
add_edge!(g0, 4, 1)
add_edge!(g0, 2, 1)
add_edge!(g0, 3, 2)
add_edge!(g0, 4, 3)
add_edge!(g0, 1, 4)

```

?

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [September 12, 2023, 6:58am UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/4 "2023-09-12T06:58:12Z")

</div>

No I meant creating the Graph on one side and the DiGraph on the other side then iterating to link the two, but it has quadratic complexity. Perhaps you can tell me a bit more about _why_ you need to keep track of edge indices?

---

<div class="post-metadata">

### Author: ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)
#### Post date: [September 12, 2023, 12:14pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/5 "2023-09-12T12:14:35Z")

</div>

Sorry, yeah, the request is probably a bit confusing.

Basically, I am building a spatial simulator for biological ODEs (also SDE and Gillespie stuff). Basically, I provide a non-spatial ODE and a graph, and the simulator simulates the ODE in every vertex of the graph. There is also a transportation rule for some variables, so that these can “move” between vertexes, along edges.

The rate at which this movement occurs is provided as a parameter (`d`) to the simulator.

- Often, `d` is constant along all edges (in which a single value is provided, e.g. `d=0.1`).
- It is also possible that `d` vary from edge to edge. Here, `d` would be a vector (e.g. `d=[0.10, 0.11, 0.12, 0.09, 0.11, ...]`) where `d[i]` correspond to the rate along the i’th edge.
- Internally, the spatial geometry is represented as a `DiGraph`. In most cases, the system is symmetric along each edge, so the user can provide a `Graph`, which is internally converted to a `DiGraph`.
- If a `Graph` with `ne=N` is provided, for the internal digraph, we will have `ne=2N`. Here, I want the user to be able to provide a `d` vector of length `N`, and it is implicitly assumed that the value `d[i]` will be used for the two edges generated by the i’th edge in the input `Graph`.

It is internally recorded if a `Graph` (rather than a `DiGraph`) was used as input, and if then `d` is a vector of length `N` (rather than `2N`) I want to engage this routine. My idea was that if I had a custom-made way to generate the `DiGraph` from the `Graph, where I used one of these schemes to generate the former from the latter, creating the new `d` vector is trivial, e.g. by running

```julia
(2length(d) == ne(g)) && (d = [d_val for d_val in d for _ in 1:2])
# Sets d = [d1,d1,d2,d2,d3,d3,d4,d4, ...]

```

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [September 13, 2023, 7:58am UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/6 "2023-09-13T07:58:01Z")

</div>

No matter how you generate the `DiGraph`, its iteration order will stay the same.

- An inelegant solution would be changing the internal mechanics handling `d` so that it adapts to the current order of iteration in `Graph` and `DiGraph`, but since this order is not part of the API, I don’t like it.
- An elegant solution would be rolling out your own graph format with custom edge order.
- A middle ground would be using a sparse matrix, which can then be made symmetric? Or a weighted graph?

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [September 13, 2023, 8:34am UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/7 "2023-09-13T08:34:03Z")

</div>

So basically you want to keep track of the order of the edges to associate some metadata with every edge? I think there is [MetaGraphs.jl](https://github.com/JuliaGraphs/MetaGraphs.jl) that allows you to assign metadata directly to the edges (@gdalle knows a lot more about that package ^^). With that you could for example assign an index to each edge that indexes into your parameter vector. Does that solve your problem?

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [September 13, 2023, 8:34am UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/8 "2023-09-13T08:34:57Z")

</div>

Don’t use MetaGraphs.jl, use [MetaGraphsNext.jl](https://github.com/JuliaGraphs/MetaGraphsNext.jl), it’s way more efficient 😉 But yes, that is the fourth solution

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [September 13, 2023, 8:36am UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/9 "2023-09-13T08:36:53Z")

</div>

Ah interesting, didn’t know about MetaGraphsNext 😄 May I suggest putting this info/warning at the top the Readme.md of MetaGraphs?

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [September 13, 2023, 8:38am UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/10 "2023-09-13T08:38:44Z")

</div>

That is a solid point

---

<div class="post-metadata">

### Author: ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)
#### Post date: [September 13, 2023, 6:09pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/11 "2023-09-13T18:09:18Z")

</div>

Thanks a lot, that makes it very clear what is (and is not) possible. I should be able to sort thing out from here

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [September 13, 2023, 6:39pm UTC](https://discourse.julialang.org/t/keep-track-of-order-of-graph-edges-when-iterating-over-them/103759/12 "2023-09-13T18:39:40Z")

</div>

done
