Elixir wrapper of :digraph
with a pinch of protocols and sigils
The package can be installed by adding dg
to your list of dependencies in mix.exs
:
def deps do
[
{:dg, "~> 0.4"},
...
]
end
dg = DG.new()
DG.add_vertex(dg, "v1")
DG.add_vertex(dg, "v2", "label 2")
DG.add_vertex(dg, "v3")
DG.add_edge(dg, "v1", "v2")
DG.add_edge(dg, "v1", "v3", "1 to 3")
IO.inspect(dg)
Outputs mermaid.js
format flowchart
graph LR
v1-->v2[label 2]
v1--1 to 3-->v3
which can be put into livebook mermaid
block and will display as
graph LR
v1-->v2[label 2]
v1--1 to 3-->v3
Easily add
- vertices
[{:vertex, 1}, {:vertex, 2, "label 2"}, ...]
- or edges
[{:edge, 1, 2}, {:edge, "a", "b", "label ab"}, ...]
to the graph via Enum.into/2
dg = DG.new()
~w(a b c d e) |> Enum.map(&{:vertex, &1}) |> Enum.into(dg)
~w(a b c d e)
|> Enum.chunk_every(2, 1, :discard)
|> Enum.map(fn [f, t] -> {:edge, f, t} end)
|> Enum.into(dg)
IO.inspect(dg)
outputs
graph LR
b-->c
c-->d
a-->b
d-->e
- Most functions from
:digraph
and:digraph_utils
are mirrored underDG
. - Some functions have their parameters re-arranged so that the graph is always the first parameter.
(namely
reachable/2
,reachable_neighbours/2
,reaching/2
andreaching_neighbours/2
) new/{0,1,2,3}
returns%DG{}
instead of an Erlangdigraph
new/2
andnew/3
are shortcuts that can add vertices and edges on creation, which don't exist on:digraph
~G
and ~g
are provided so you can copy mermaid.js
flowchart and paste into Elixir to get a %DG{}
import DG.Sigil
dg = ~G"""
graph LR
a[some label]
b[other label]
1-->2
3[three] -- three to four --> 4[four]
a --> b
"""
# With interpolation
label = "1 2 3"
dg = ~g"""
graph LR
a --#{label}--> b
"""
caveat: :digraph
is stateful (using ets
), don't use the sigil at compile time,
e.g. as a module attribute, it won't carry over to runtime.
Only use it in runtime code, e.g. function body,
and remember to clean up properly when it's no longer used, with delete/1
.
dg = DG.new()
DG.from({:libgraph, graph})