Giraffe.Graph.Undirected (giraffe v0.2.0)

Implementation of an undirected graph with weighted edges. Vertices can be any term, and edges have numeric weights.

Summary

Functions

Adds an edge between two vertices with the given weight. If the vertices don't exist, they will be added to the graph.

Adds a vertex to the graph with an optional label.

Finds shortest paths from a source vertex using the Bellman-Ford algorithm. Returns nil if a negative cycle is detected.

Detects all maximal cliques in the graph using the Bron-Kerbosch algorithm.

Returns a list of all edges in the graph as tuples of {from, to, weight}.

Returns a list of all edges for a specific vertex.

Gets the label associated with a vertex.

Finds all possible paths between two vertices. Returns a list of tuples containing the path and its total weight.

Finds the shortest path between two vertices using Dijkstra's algorithm. Returns {:ok, path, total_weight} if a path exists, :no_path otherwise.

Returns true if the given vertex exists in the graph.

Checks if the graph is acyclic (contains no cycles).

Checks if the graph contains any cycles.

Creates a new empty graph.

Returns the number of edges in the graph

Returns the number of vertices in the graph

Returns vertices in post-order DFS traversal order.

Returns a list of all vertices reachable from the given starting vertices.

Sets a label for an existing vertex. Returns unchanged graph if vertex doesn't exist.

Finds shortest paths using Bellman-Ford algorithm.

Returns the label for the given vertex

Returns a list of all vertices in the graph.

Types

edge()

@type edge() :: {vertex(), vertex(), weight()}

t()

@type t() :: %Giraffe.Graph.Undirected{
  edges: %{required(vertex()) => %{required(vertex()) => weight()}},
  labels: map(),
  vertices: MapSet.t()
}

vertex()

@type vertex() :: any()

weight()

@type weight() :: number()

Functions

add_edge(graph, v1, v2, opts_or_weight \\ 1)

@spec add_edge(t(), vertex(), vertex(), number() | keyword()) :: t()

Adds an edge between two vertices with the given weight. If the vertices don't exist, they will be added to the graph.

add_vertex(graph, vertex, labels \\ [])

@spec add_vertex(t(), vertex(), [any()]) :: t()

Adds a vertex to the graph with an optional label.

Examples

iex> graph = Giraffe.Graph.Directed.new()
iex> Giraffe.Graph.Directed.add_vertex(graph, :a, "vertex A")
%Giraffe.Graph.Directed{vertices: MapSet.new([:a]), edges: %{}, labels: %{a: "vertex A"}}

bellman_ford(graph, source)

@spec bellman_ford(t(), vertex()) :: %{required(vertex()) => number()} | nil

Finds shortest paths from a source vertex using the Bellman-Ford algorithm. Returns nil if a negative cycle is detected.

Examples

iex> graph = Giraffe.Graph.Undirected.new()
...> graph = graph |> Giraffe.Graph.Undirected.add_edge(:a, :b, 1)
...> graph |> Giraffe.Graph.Undirected.bellman_ford(:a)
%{a: 0, b: 1}

cliques(graph)

@spec cliques(t()) :: [[vertex()]]

Detects all maximal cliques in the graph using the Bron-Kerbosch algorithm.

edges(undirected)

@spec edges(t()) :: [{vertex(), vertex(), number()}]

Returns a list of all edges in the graph as tuples of {from, to, weight}.

Examples

iex> graph = Giraffe.Graph.Undirected.new()
...> graph = Giraffe.Graph.Undirected.add_edge(graph, :a, :b, 1)
...> Giraffe.Graph.Undirected.edges(graph)
[{:a, :b, 1}]

edges(undirected, vertex)

@spec edges(t(), vertex()) :: [{vertex(), vertex(), number()}]

Returns a list of all edges for a specific vertex.

Examples

iex> graph = Giraffe.Graph.Undirected.new()
...> graph = Giraffe.Graph.Undirected.add_edge(graph, :a, :b, 1)
...> Giraffe.Graph.Undirected.edges(graph, :a)
[{:a, :b, 1}]

get_label(graph, vertex)

@spec get_label(t(), vertex()) :: any() | nil

Gets the label associated with a vertex.

Examples

iex> graph = Giraffe.Graph.Directed.new() |> Giraffe.Graph.Directed.add_vertex(:a, "vertex A")
iex> Giraffe.Graph.Directed.get_label(graph, :a)
"vertex A"

get_paths(graph, start, finish)

@spec get_paths(t(), vertex(), vertex()) :: [{[vertex()], weight()}]

Finds all possible paths between two vertices. Returns a list of tuples containing the path and its total weight.

get_shortest_path(undirected, start, finish)

@spec get_shortest_path(t(), vertex(), vertex()) ::
  {:ok, [vertex()], weight()} | :no_path

Finds the shortest path between two vertices using Dijkstra's algorithm. Returns {:ok, path, total_weight} if a path exists, :no_path otherwise.

has_vertex?(graph, vertex)

@spec has_vertex?(t(), vertex()) :: boolean()

Returns true if the given vertex exists in the graph.

is_acyclic?(undirected)

@spec is_acyclic?(t()) :: boolean()

Checks if the graph is acyclic (contains no cycles).

is_cyclic?(graph)

@spec is_cyclic?(t()) :: boolean()

Checks if the graph contains any cycles.

neighbors(undirected, vertex)

@spec neighbors(t(), vertex()) :: [vertex()]

new(opts \\ [])

@spec new(keyword()) :: t()

Creates a new empty graph.

Examples

iex> Giraffe.Graph.Directed.new()
%Giraffe.Graph.Directed{vertices: MapSet.new(), edges: %{}, labels: %{}}

num_edges(graph)

@spec num_edges(t()) :: non_neg_integer()

Returns the number of edges in the graph

num_vertices(graph)

@spec num_vertices(t()) :: non_neg_integer()

Returns the number of vertices in the graph

postorder(undirected)

@spec postorder(t()) :: [vertex()]

Returns vertices in post-order DFS traversal order.

Examples

iex> graph = Giraffe.Graph.Directed.new()
...> |> Giraffe.Graph.Directed.add_edge(:a, :b, 1)
...> |> Giraffe.Graph.Directed.add_edge(:b, :c, 1)
iex> Giraffe.Graph.Directed.postorder(graph)
[:c, :b, :a]

reachable(graph, vertices)

@spec reachable(t(), [vertex()]) :: [vertex()]

Returns a list of all vertices reachable from the given starting vertices.

Examples

iex> graph = Giraffe.Graph.Directed.new()
...> |> Giraffe.Graph.Directed.add_edge(:a, :b, 1)
...> |> Giraffe.Graph.Directed.add_edge(:b, :c, 1)
iex> Giraffe.Graph.Directed.reachable(graph, [:a])
[:a, :b, :c]

set_label(graph, vertex, label)

@spec set_label(t(), vertex(), label :: any()) :: t()

Sets a label for an existing vertex. Returns unchanged graph if vertex doesn't exist.

Examples

iex> graph = Giraffe.Graph.Directed.new() |> Giraffe.Graph.Directed.add_vertex(:a)
iex> Giraffe.Graph.Directed.set_label(graph, :a, "new label")
%Giraffe.Graph.Directed{vertices: MapSet.new([:a]), edges: %{}, labels: %{a: "new label"}}

shortest_paths(graph, source)

Finds shortest paths using Bellman-Ford algorithm.

vertex_labels(graph, vertex)

@spec vertex_labels(t(), vertex()) :: [any()]

Returns the label for the given vertex

vertices(undirected)

@spec vertices(t()) :: [vertex()]

Returns a list of all vertices in the graph.

Examples

iex> graph = Giraffe.Graph.Directed.new() |> Giraffe.Graph.Directed.add_vertex(:a)
iex> Giraffe.Graph.Directed.vertices(graph)
[:a]