A directed graph data structure.
The vertices can hold any data, but you can't have two vertices holding the same data. (Think of it as of Set
.)
The edges can also hold any data, but you can't have two edges going from/to the same place.
{ from : vertex
, to : vertex
, data : edge
}
A representation of an edge between two vertices.
empty : Graph vertex edge
An empty graph. No vertices, no edges.
fromVerticesAndEdges : List vertex -> List (Edge vertex edge) -> Graph vertex edge
Construct a graph from a list of vertices and a list of edges.
Implicitly adds vertices that are present in the edges list, as if they were mentioned in the vertices list too.
Graph.fromVerticesAndEdges
[ "x", "y" ]
[ { from = "x", to = "y", data = 100 }
, { from = "y", to = "z", data = 200 }
, { from = "z", to = "x", data = 300 }
]
|> Graph.vertices
|> List.length
--> 3
addVertex : vertex -> Graph vertex edge -> Graph vertex edge
Add the vertex to the graph. (Nothing happens if it's already present.)
By default it's not connected to any other vertex.
Graph.empty
|> Graph.addVertex "foo"
|> Graph.vertices
--> [ "foo" ]
removeVertex : vertex -> Graph vertex edge -> Graph vertex edge
Remove the vertex from the graph. (Nothing happens if it's not present.)
Graph.empty
|> Graph.addVertex "foo"
|> Graph.removeVertex "foo"
|> Graph.isEmpty
--> True
updateVertex : vertex -> (vertex -> vertex) -> Graph vertex edge -> Graph vertex edge
Updates the vertex data. Does nothing if the vertex is not present.
Graph.empty
|> Graph.addVertex "foo"
|> Graph.updateVertex "foo" String.toUpper
|> Graph.vertices
--> [ "FOO" ]
addEdge : vertex -> vertex -> edge -> Graph vertex edge -> Graph vertex edge
Add an edge to the graph, along with the associated data
If any of the vertices aren't present yet, this function will add them before adding the edge.
Directed: the order of the vertices does matter.
Graph.empty
|> Graph.addEdge "foo" "bar" ()
|> Graph.vertices
--> [ "foo", "bar" ]
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.edges
--> [ { from = "foo", to = "bar", data = 100 } ]
removeEdge : vertex -> vertex -> Graph vertex edge -> Graph vertex edge
Remove an edge from the first vertex to the second one. Does nothing if the edge is not present.
Directed: the order of the vertices does matter.
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.removeEdge "foo" "bar"
|> Graph.edges
--> []
updateEdge : vertex -> vertex -> (edge -> edge) -> Graph vertex edge -> Graph vertex edge
Updates the edge data. Does nothing if the edge is not present.
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.updateEdge "foo" "bar" (\v -> v + 1000)
|> Graph.edges
--> [ { from = "foo", bar = "bar", data = 1100 } ]
mapVertices : (vertex1 -> vertex2) -> Graph vertex1 edge -> Graph vertex2 edge
Applies a function to all the vertices.
Graph.empty
|> Graph.addVertex "foo"
|> Graph.addVertex "bar"
|> Graph.mapVertices String.toUpper
|> Graph.vertices
--> [ "FOO", "BAR" ]
mapEdges : (edge1 -> edge2) -> Graph vertex edge1 -> Graph vertex edge2
Applies a function to all the edges.
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.addEdge "bar" "baz" 200
|> Graph.mapEdges (\x -> x + 1000)
|> Graph.edges
--> [ { from = "foo", to = "bar", data = 1100 }
-- , { from = "bar", to = "baz", data = 1200 }
-- ]
--
-- (sans the ordering on the edges list, see the note in `edges`)
reverseEdges : Graph vertex edge -> Graph vertex edge
Reverse the direction of all the edges in the graph.
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.reverseEdges
|> Graph.edges
--> [ { from = "bar", to = "foo", data = 100 } ]
isEmpty : Graph vertex edge -> Basics.Bool
Is the graph empty?
hasVertex : vertex -> Graph vertex edge -> Basics.Bool
Is this vertex present in the graph?
Graph.empty
|> Graph.hasVertex "x"
--> False
Graph.empty
|> Graph.addVertex "x"
|> Graph.hasVertex "x"
--> True
hasEdge : vertex -> vertex -> Graph vertex edge -> Basics.Bool
Is this edge present in the graph?
Graph.empty
|> Graph.hasEdge "x" "y"
--> False
Graph.empty
|> Graph.addEdge "x" "y" ()
|> Graph.hasEdge "x" "y"
--> True
Graph.empty
|> Graph.addEdge "y" "x" ()
|> Graph.hasEdge "x" "y"
--> False
areAdjacent : vertex -> vertex -> Graph vertex edge -> Basics.Bool
Does the graph contain an edge between these two vertices (in any direction)?
Graph.empty
|> Graph.areAdjacent "x" "y"
--> False
Graph.empty
|> Graph.addEdge "x" "y" ()
|> Graph.areAdjacent "x" "y"
--> True
Graph.empty
|> Graph.addEdge "y" "x" ()
|> Graph.areAdjacent "x" "y"
--> True
fold : (vertex -> acc -> acc) -> acc -> Graph vertex edge -> acc
Fold a function over all the vertices, starting with the "oldest" vertices.
Graph.empty
|> Graph.addVertex "foo"
|> Graph.addVertex "bar"
|> Graph.fold (\v acc -> acc ++ v) ""
--> "foobar"
size : Graph vertex edge -> Basics.Int
Determine the number of vertices in the graph.
Graph.size Graph.empty
--> 0
Graph.empty
|> Graph.addVertex "foo"
|> Graph.addVertex "bar"
|> Graph.size
--> 2
vertices : Graph vertex edge -> List vertex
Return a list of the vertices, starting with the "oldest".
Graph.empty
|> Graph.addVertex "foo"
|> Graph.addVertex "bar"
|> Graph.vertices
--> [ "foo", "bar" ]
edges : Graph vertex edge -> List (Edge vertex edge)
Return a list of the edges.
Don't expect any sensible order - it's implementation defined.
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.addEdge "bar" "quux" 200
|> Graph.edges
--> [ { from = "bar", to = "quux", data = 200 }
-- , { from = "foo", to = "bar", data = 100 }
-- ]
verticesAndEdges : Graph vertex edge -> { vertices : List vertex, edges : List (Edge vertex edge) }
Return a record with a list of vertices and list of edges in the graph.
Graph.empty
|> Graph.addVertex "foo"
|> Graph.addEdge "foo" "bar" 100
|> Graph.verticesAndEdges
--> { vertices = [ "foo", "bar" ]
-- , edges = [ { from = "foo", to = "bar", data = 100 } ]
-- }
outgoingEdges : vertex -> Graph vertex edge -> List vertex
Lists all vertices this vertex has edges to.
Directed - only lists the edges that go from the given vertex.
Graph.empty
|> Graph.outgoingEdges "foo"
--> []
Graph.empty
|> Graph.addEdge "foo" "bar" ()
|> Graph.addEdge "foo" "baz" ()
|> Graph.addEdge "quux" "foo" ()
|> Graph.outgoingEdges "foo"
--> [ "bar", "baz" ]
outgoingEdgesWithData : vertex -> Graph vertex edge -> List ( vertex, edge )
Lists all vertices this vertex has edges to, along with the edge data.
Directed - only lists the edges that go from the given vertex.
Graph.empty
|> Graph.outgoingEdgesWithData "foo"
--> []
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.addEdge "foo" "baz" 200
|> Graph.addEdge "quux" "foo" 300
|> Graph.outgoingEdgesWithData "foo"
--> [ ("bar", 100)
-- , ("baz", 200)
-- ]
getEdge : vertex -> vertex -> Graph vertex edge -> Maybe edge
Get the value associated with the edge.
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.getEdge "foo" "bar"
--> Just 100
Graph.empty
|> Graph.addEdge "foo" "bar" 100
|> Graph.getEdge "bar" "quux"
--> Nothing
edgeToComparable : Edge comparableVertex comparableEdge -> ( comparableVertex, comparableVertex, comparableEdge )
Transform the record into a (from, to, data)
tuple.
Graph.edgeToComparable { from = "foo", to = "bar", data = 123 }
--> ("foo", "bar", 123)