digraph_utils(3)
β¨ NAME β¨
Okay bestie, this is digraph_utils(3), chillin' in the Erlang Module Definition section. This module provides algorithms based on depth-first traversal of directed graphs. π
π¦ DESCRIPTION π¦
For basic functions on directed graphs, see the digraph module. Periodt. π
- A directed graph (or just "digraph", iykyk) is a pair
(V, E)of a finite setVof vertices and a finite setEof directed edges (or just "edges"). The set of edgesEis a subset ofV Γ V(the Cartesian product ofVwith itself). No cap. β¨ - Digraphs can be annotated with more information. That info can be attached to the vertices and to the edges of the digraph. An annotated digraph is called a labeled digraph, and the information attached to a vertex or an edge is called a label. π·οΈ
- An edge
e = (v, w)is said to emanate from vertexvand to be incident on vertexw. π« - If an edge is emanating from
vand incident onw, thenwis said to be an out-neighbor ofv, andvis said to be an in-neighbor ofw. π - A path
Pfromv[1]tov[k]in a digraph(V, E)is a non-empty sequencev[1], v[2], ..., v[k]of vertices inVsuch that there is an edge(v[i],v[i+1])inEfor1 <= i < k. π€οΈ - The length of path
Pisk-1. π - Path
Pis a cycle if the length ofPis not zero andv[1] = v[k]. π - A loop is a cycle of length one. π
- An acyclic digraph is a digraph without cycles. π«
- A depth-first traversal of a directed digraph can be viewed as a process that visits all vertices of the digraph. Initially, all vertices are marked as unvisited. The traversal starts with an arbitrarily chosen vertex, which is marked as visited, and follows an edge to an unmarked vertex, marking that vertex. The search then proceeds from that vertex in the same fashion, until there is no edge leading to an unvisited vertex. At that point the process backtracks, and the traversal continues as long as there are unexamined edges. If unvisited vertices remain when all edges from the first vertex have been examined, some so far unvisited vertex is chosen, and the process is repeated. π
- A partial ordering of a set
Sis a transitive, antisymmetric, and reflexive relation between the objects ofS. π§ - The problem of topological sorting is to find a total ordering of
Sthat is a superset of the partial ordering. A digraphG = (V, E)is equivalent to a relationEonV(we neglect that the version of directed graphs provided by thedigraphmodule allows multiple edges between vertices). If the digraph has no cycles of length two or more, the reflexive and transitive closure ofEis a partial ordering. π - A subgraph
G'ofGis a digraph whose vertices and edges form subsets of the vertices and edges ofG. π§© G'is maximal with respect to a propertyPif all other subgraphs that include the vertices ofG'do not have propertyP. π- A strongly connected component is a maximal subgraph such that there is a path between each pair of vertices. π
- A connected component is a maximal subgraph such that there is a path between each pair of vertices, considering all edges undirected. π
- An arborescence is an acyclic digraph with a vertex
V, the root, such that there is a unique path fromVto every other vertex ofG. π³ - A tree is an acyclic non-empty digraph such that there is a unique path between every pair of vertices, considering all edges undirected. π²
π«Ά See Also π«Ά
digraph
β¨ FUNCTIONS β¨
okay bestie, here's the whole function roster, and yes, every single flag and return type is staying exactly as the man page says. periodt. π
π arborescence_root(Digraph) β is this the root? let's check
arborescence_root(Digraph) -> no | {yes, Root}
when
Digraph :: digraph:graph(),
Root :: digraph:vertex().
Returns {yes, Root} if Root is literally the root of the arborescence Digraph. Otherwise? no. That's it. Iconic.
π components(Digraph) β connected components, all of them
components(Digraph) -> [Component]
when
Digraph :: digraph:graph(),
Component :: [digraph:vertex()].
Returns a list of connected components. Each component is represented by its vertices. The order of the vertices and the order of the components are arbitrary β so don't come for me about ordering. Each vertex of digraph Digraph occurs in exactly one component. no cap.
π¦ condensation(Digraph) β SCCs but make it a digraph
condensation(Digraph) -> CondensedDigraph
when
Digraph :: digraph:graph(),
CondensedDigraph :: digraph:graph().
Creates a digraph where the vertices are the strongly connected components of Digraph as returned by strong_components/1. If X and Y are two different strongly connected components, and vertices x and y exist in X and Y, respectively, such that there is an edge emanating from x and incident on y, then an edge emanating from X and incident on Y is created. slay.
The created digraph has the same type as Digraph. All vertices and edges have the default label [].
Each cycle is included in some strongly connected component, which implies that a topological ordering of the created digraph always exists. that's the tea. π΅
π cyclic_strong_components(Digraph) β SCCs that are actually cyclic
cyclic_strong_components(Digraph) -> [StrongComponent]
when
Digraph :: digraph:graph(),
StrongComponent ::
[digraph:vertex()].
Returns a list of strongly connected components. Each strongly component is represented by its vertices. The order of the vertices and the order of the components are arbitrary. Only vertices that are included in some cycle in Digraph are returned, otherwise the returned list is equal to that returned by strong_components/1. bestie, that's the whole plot twist. π
β is_acyclic(Digraph) β acyclic or not?
is_acyclic(Digraph) -> boolean() when Digraph :: digraph:graph().
Returns true if and only if digraph Digraph is acyclic. simple as. β¨
π is_arborescence(Digraph) β arborescence check
is_arborescence(Digraph) -> boolean()
when Digraph :: digraph:graph().
Returns true if and only if digraph Digraph is an arborescence. yes queen, validate that tree-adjacent situation.
πΈ is_tree(Digraph) β tree check
is_tree(Digraph) -> boolean() when Digraph :: digraph:graph().
Returns true if and only if digraph Digraph is a tree. nature is healing. π³
π loop_vertices(Digraph) β vertices stuck in loops
loop_vertices(Digraph) -> Vertices
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()].
Returns a list of all vertices of Digraph that are included in some loop. if it's looping, it's on the list. periodt.
π¦ postorder(Digraph) β depth-first, postorder vibes
postorder(Digraph) -> Vertices
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()].
Returns all vertices of digraph Digraph. The order is given by a depth-first traversal of the digraph, collecting visited vertices in postorder. More precisely, the vertices visited while searching from an arbitrarily chosen vertex are collected in postorder, and all those collected vertices are placed before the subsequently visited vertices. so it's giving "finish the kids first, then move on". π
π preorder(Digraph) β depth-first, preorder vibes
preorder(Digraph) -> Vertices
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()].
Returns all vertices of digraph Digraph. The order is given by a depth-first traversal of the digraph, collecting visited vertices in preorder. main character first, obviously. π
π reachable(Vertices, Digraph) β what can we reach from here?
reachable(Vertices, Digraph) -> Reachable
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()],
Reachable :: [digraph:vertex()].
Returns an unsorted list of digraph vertices such that for each vertex in the list, there is a path in Digraph from some vertex of Vertices to the vertex. In particular, as paths can have length zero, the vertices of Vertices are included in the returned list. so yes, you can reach yourself. self-care. π«Ά
π reachable_neighbours(Vertices, Digraph) β reachable but at least one edge away
reachable_neighbours(Vertices, Digraph) -> Reachable
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()],
Reachable :: [digraph:vertex()].
Returns an unsorted list of digraph vertices such that for each vertex in the list, there is a path in Digraph of length one or more from some vertex of Vertices to the vertex. As a consequence, only those vertices of Vertices that are included in some cycle are returned. no zero-length paths here, bestie. π«
π reaching(Vertices, Digraph) β who can reach us?
reaching(Vertices, Digraph) -> Reaching
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()],
Reaching :: [digraph:vertex()].
Returns an unsorted list of digraph vertices such that for each vertex in the list, there is a path from the vertex to some vertex of Vertices. In particular, as paths can have length zero, the vertices of Vertices are included in the returned list. it's giving "who's in our orbit". π
π reaching_neighbours(Vertices, Digraph) β reaching but at least one edge away
reaching_neighbours(Vertices, Digraph) -> Reaching
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()],
Reaching :: [digraph:vertex()].
Returns an unsorted list of digraph vertices such that for each vertex in the list, there is a path of length one or more from the vertex to some vertex of Vertices. Therefore only those vertices of Vertices that are included in some cycle are returned. same energy as reachable_neighbours but reversed. π«
π strong_components(Digraph) β SCCs, the main event
strong_components(Digraph) -> [StrongComponent]
when
Digraph :: digraph:graph(),
StrongComponent :: [digraph:vertex()].
Returns a list of strongly connected components. Each strongly component is represented by its vertices. The order of the vertices and the order of the components are arbitrary. Each vertex of digraph Digraph occurs in exactly one strong component. no vertex left behind. π
π§ subgraph(Digraph, Vertices, Options) β make a subgraph, but make it maximal
subgraph(Digraph, Vertices, Options) -> SubGraph
when
Digraph :: digraph:graph(),
SubGraph :: digraph:graph(),
Vertices :: [digraph:vertex()],
Options ::
[{type, SubgraphType} |
{keep_labels, boolean()}],
SubgraphType :: inherit | [digraph:d_type()].
Creates a maximal subgraph of Digraph having as vertices those vertices of Digraph that are mentioned in Vertices.
If the value of option type is inherit, which is the default, the type of Digraph is used for the subgraph as well. Otherwise the option value of type is used as argument to digraph:new/1.
If the value of option keep_labels is true, which is the default, the labels of vertices and edges of Digraph are used for the subgraph as well. If the value is false, default label [] is used for the vertices and edges of the subgroup. (the original says "subgroup" here β we love a lil typo, it's iconic.)
subgraph(Digraph, Vertices) is equivalent to subgraph(Digraph, Vertices, []).
If any of the arguments are invalid, a badarg exception is raised. so watch out, bestie. π¨
β topsort(Digraph) β topological ordering, or false
topsort(Digraph) -> Vertices | false
when
Digraph :: digraph:graph(),
Vertices :: [digraph:vertex()].
Returns a topological ordering of the vertices of digraph Digraph if such an ordering exists, otherwise false. For each vertex in the returned list, no out-neighbors occur earlier in the list. so if you see an out-neighbor ahead of you in line, the sort said no. π
That's the whole function roster, bestie. Every arg, every default, every <red>badarg</red>, every <yellow>arbitrary order</yellow> β all present and accounted for. π
This page is Ericsson AB's stdlib 8.0.4, digraph_utils(3) β date in the footer, but honestly the vibes are timeless. bye bestie! π
β¨
π¦ where this page comes from
- ubuntu stonking: erlang-doc 1:29.0.6+dfsg-1 Β· Apache-2.0
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms