graphbrewer v0.1.7 Graph

This module serves as a graph library that enables to handle undirected weighted graphs (directed is in the works) in memory. It features simple operations such as adding and removing nodes and edges and finding the shortest path between nodes.

Supported features:

  • Nodes with an optional heuristic costs (for the shortest path algorithm) and and optional label
  • Edges from and to nodes with certain costs
  • Adding and deleting nodes
  • Adding and deleting edges

The Graph module is strucutred like so:

  • nodes is a Map that has the node_id (atom) as a key and another Map as value. This Map conatins label and costs as keys that refer to the corresponding value.
  • edges is a Map that has the node_id (atom) as a key and another Map as value. The key refers to the starting node of the edge and all nodes stored in the second map refer to the edge’s end. Additionally, the second map stores the edge’s weight mapped to the end node.

Link to this section Summary

Functions

Adds an edge to the given graph from a to b & b to a and assigns the according costs. If the nodes a and / or b do not exist they are created (costs and label of these nodes is set to nil). If there are no costs set, the default value of 0 will be assigned

Adds a node to the graph with the specified information

Deletes an the edge that goes from a to b. The edge is only deleted if it really exists

Deletes a given node plus the edges it is involved in

Returns the costs for the edge from node A to node B. Returns nil if there is no connection

Gets the edge connecting two nodes. Returns nil if there is no connection

Gets the list of all nodes that have an edge towards or from the given node

Gets node info for the ID. Unlike other functions, this returns the information as a map

Creates a new undirected Graph

Gets the total costs for a path (considering edge weights)

Find the shortest path from a to b in the given graph

Link to this section Types

Link to this type edge_info()
edge_info() :: %{optional(node_id()) => costs()}
Link to this type label()
label() :: term()
Link to this type node_id()
node_id() :: atom()
Link to this type node_info()
node_info() :: %{label: label(), costs: costs()}
Link to this type t()
t() :: %Graph{
  edges: %{optional(node_id()) => edge_info()},
  nodes: %{optional(node_id()) => node_info()}
}

Link to this section Functions

Link to this function add_edge(g, from, to, costs \\ 1)
add_edge(t(), node_id(), node_id(), costs()) :: t()

Adds an edge to the given graph from a to b & b to a and assigns the according costs. If the nodes a and / or b do not exist they are created (costs and label of these nodes is set to nil). If there are no costs set, the default value of 0 will be assigned.

Example

iex> g = Graph.new |> Graph.add_edge(:a, :b, 5) |> Graph.add_edge(:b, :c, 3)
%Graph{
  edges: %{a: %{b: 5}, b: %{a: 5, c: 3}, c: %{b: 3}},
  nodes: %{
    a: %{costs: 0, label: nil},
    b: %{costs: 0, label: nil},
    c: %{costs: 0, label: nil}
  }
}
iex> Graph.add_edge(g, :b, :c, 9)
%Graph{
  edges: %{a: %{b: 5}, b: %{a: 5, c: 9}, c: %{b: 9}},
  nodes: %{
    a: %{costs: 0, label: nil},
    b: %{costs: 0, label: nil},
    c: %{costs: 0, label: nil}
  }
}
Link to this function add_node(g, node, opts \\ [])
add_node(t(), node_id(), node_info()) :: t()

Adds a node to the graph with the specified information.

Example

iex> g = Graph.new |> Graph.add_node(:a, label: "This is a", costs: 2)
%Graph{edges: %{}, nodes: %{a: %{costs: 2, label: "This is a"}}}
iex> Graph.add_node(g, :a, costs: 5)
%Graph{edges: %{}, nodes: %{a: %{costs: 5, label: "This is a"}}}
Link to this function delete_edge(g, from, to)
delete_edge(t(), node_id(), node_id()) :: t()

Deletes an the edge that goes from a to b. The edge is only deleted if it really exists.

Example

iex> g = Graph.new |> Graph.add_edge(:a, :b, 5) |> Graph.add_edge(:b, :c, 5)
%Graph{
  edges: %{a: %{b: 5}, b: %{a: 5, c: 5}, c: %{b: 5}},
  nodes: %{
    a: %{costs: 0, label: nil},
    b: %{costs: 0, label: nil},
    c: %{costs: 0, label: nil}
  }
}
iex> Graph.delete_edge(g, :b, :c)
%Graph{
  edges: %{a: %{b: 5}, b: %{a: 5}},
  nodes: %{
    a: %{costs: 0, label: nil},
    b: %{costs: 0, label: nil},
    c: %{costs: 0, label: nil}
  }
}
Link to this function delete_edge!(g, from, to)
Link to this function delete_node(g, node)
delete_node(t(), node_id()) :: t()

Deletes a given node plus the edges it is involved in.

Example

iex> g = Graph.new |> Graph.add_node(:a) |> Graph.add_node(:b) |> Graph.add_edge(:a, :b)
%Graph{
  edges: %{a: %{b: 1}, b: %{a: 1}},
  nodes: %{a: %{costs: 0, label: nil}, b: %{costs: 0, label: nil}}
}
iex> Graph.delete_node(g, :b)
%Graph{edges: %{}, nodes: %{a: %{costs: 0, label: nil}}}
Link to this function edge_costs(g, from, to)
edge_costs(t(), node_id(), node_id()) :: costs()

Returns the costs for the edge from node A to node B. Returns nil if there is no connection.

Example

iex> g = Graph.new |>
...> Graph.add_edge(:s, :a, 3)  |>
...> Graph.add_edge(:a, :b, 5)  |>
...> Graph.add_edge(:b, :c, 10) |>
...> Graph.add_edge(:c, :d, 3)  |>
...> Graph.add_edge(:d, :e, 4)  |>
...> Graph.add_edge(:b, :e, 5)
iex> Graph.edge_costs(g, :s, :a)
3
Link to this function get_edge(graph, from, to)
get_edge(t(), node_id(), node_id()) :: {node_id(), node_id(), costs()}

Gets the edge connecting two nodes. Returns nil if there is no connection.

Example

iex> g = Graph.new |> Graph.add_edge(:a, :b, 3)
%Graph{
  edges: %{a: %{b: 3}, b: %{a: 3}},
  nodes: %{a: %{costs: 0, label: nil}, b: %{costs: 0, label: nil}}
}
iex> Graph.get_edge(g, :a, :b)
{:a, :b, 3}
iex> Graph.get_edge(g, :a, :s)
nil
Link to this function get_neighbors(g, id)
get_neighbors(t(), node_id()) :: []

Gets the list of all nodes that have an edge towards or from the given node.

Example

iex> Graph.new |> Graph.add_edge(:a, :b, 5) |> Graph.add_edge(:b, :c, 5) |> Graph.get_neighbors(:b)
[:a, :c]
Link to this function get_node(graph, id)
get_node(t(), node_id()) :: node_info()

Gets node info for the ID. Unlike other functions, this returns the information as a map.

Example

iex> g = Graph.new |> Graph.add_node(:a, label: "This is a", costs: 4)
%Graph{edges: %{}, nodes: %{a: %{costs: 4, label: "This is a"}}}
iex> Graph.get_node(g, :a)
%{costs: 4, label: "This is a"}
Link to this function new()
new() :: t()

Creates a new undirected Graph.

Link to this function path_costs(g, path)
path_costs(t(), []) :: costs()

Gets the total costs for a path (considering edge weights).

Example

iex> g = Graph.new |>
...> Graph.add_edge(:s, :a, 3)  |>
...> Graph.add_edge(:a, :b, 5)  |>
...> Graph.add_edge(:b, :c, 10) |>
...> Graph.add_edge(:c, :d, 3)  |>
...> Graph.add_edge(:d, :e, 4)  |>
...> Graph.add_edge(:b, :e, 5)
%Graph{
  edges: %{
    a: %{b: 5, s: 3},
    b: %{a: 5, c: 10, e: 5},
    c: %{b: 10, d: 3},
    d: %{c: 3, e: 4},
    e: %{b: 5, d: 4},
    s: %{a: 3}
  },
  nodes: %{
    a: %{costs: 0, label: nil},
    b: %{costs: 0, label: nil},
    c: %{costs: 0, label: nil},
    d: %{costs: 0, label: nil},
    e: %{costs: 0, label: nil},
    s: %{costs: 0, label: nil}
  }
}
iex> Graph.shortest_path(g, :s, :e) |>
...> Graph.path_costs(g)
13
Link to this function shortest_path(g, from, to)
shortest_path(t(), node_id(), node_id()) :: [node_id(), ...]

Find the shortest path from a to b in the given graph.

Example

iex> Graph.new |>
...> Graph.add_edge(:s, :a, 3)  |>
...> Graph.add_edge(:a, :b, 5)  |>
...> Graph.add_edge(:b, :c, 10) |>
...> Graph.add_edge(:c, :d, 3)  |>
...> Graph.add_edge(:d, :e, 4)  |>
...> Graph.add_edge(:b, :e, 5)  |>
...> Graph.shortest_path(:s, :e)
[:s, :a, :b, :e]