aonyx/graph

Types

pub type ContinueOrStop(acc) {
  Continue(acc)
  Stop
}

Constructors

  • Continue(acc)
  • Stop

Represents a graph with nodes identified by a key, containing an optional value, with edges having an associated optional label.

pub opaque type Graph(key, value, label)

Returned when trying to retrieve a node or edge that does not exist.

pub type GraphError(key) {
  NodeNotFoundError(key: key)
  EdgeNotFoundError(from: key, to: key)
}

Constructors

  • NodeNotFoundError(key: key)
  • EdgeNotFoundError(from: key, to: key)

Values

pub fn fold_breadth_first_until(
  over graph: Graph(key, value, label),
  using start: key,
  from initial: acc,
  with fun: fn(acc, node.Node(key, value), Int) -> ContinueOrStop(
    acc,
  ),
) -> Result(acc, GraphError(key))

Reduces the graph using a breadth-first traversal by calling the given function on each node, starting from the given node.

The folding function should return ContinueOrStop(accumulator).

If the returned value is Continue(accumulator) fold_breadth_first_until will try to move on to the next node or return that accumulator.

If the returned value is Stop(accumulator) fold_breadth_first_until will stop and return that accumulator.

Returns the final accumulator value, or an error if the start node is not found in the graph.

pub fn fold_depth_first_until(
  over graph: Graph(key, value, label),
  using start: key,
  from initial: acc,
  with fun: fn(acc, node.Node(key, value), Int) -> ContinueOrStop(
    acc,
  ),
) -> Result(acc, GraphError(key))

Reduces the graph using a depth-first traversal by calling the given function on each node, starting from the given node.

The folding function should return ContinueOrStop(accumulator).

If the returned value is Continue(accumulator) fold_depth_first_until will try to move on to the next node or return that accumulator.

If the returned value is Stop(accumulator) fold_depth_first_until will stop and return that accumulator.

Returns the final accumulator value, or an error if the start node is not found in the graph.

pub fn get_edge(
  graph: Graph(key, value, label),
  from: key,
  to: key,
) -> Result(edge.Edge(key, label), GraphError(key))

Returns the edge from the graph with the given from and to node keys, or an error when the edge does not exist.

Examples

let graph = new() |> insert_edge(edge.new("A", "B") |> edge.with_weight(5.0))
get_edge(graph, "A", "B")
// -> Ok(Edge(from: "A", to: "B", weight: Some(5.0), label: None))
let graph = new()
get_edge(graph, "A", "B") 
// -> Error(EdgeNotFoundError(from: "A", to: "B"))
pub fn get_edges(
  graph: Graph(key, value, label),
) -> List(edge.Edge(key, label))

Returns a list of all edges in the graph.

Examples

let graph = new()
|> insert_edge(edge.new("A", "B"))
|> insert_edge(edge.new("B", "C"))

get_edges(graph)
// -> [Edge(from: "A", to: "B", ...), Edge(from: "B", to: "C", ...)]
pub fn get_node(
  graph: Graph(key, value, label),
  key: key,
) -> Result(node.Node(key, value), GraphError(key))

Returns the node from the graph with the given key, or an error when the node does not exist.

Examples

let graph = new()
  |> insert_edge(edge.new("A", "B"))

get_node(graph, "A")
// -> Ok(Node(key: "A", outgoing: Set(["B"]), incoming: Set([]), value: None))
let graph = new()
get_node(graph, "X") 
// -> Error(NodeNotFoundError(key: "X"))
pub fn get_nodes(
  graph: Graph(key, value, label),
) -> List(node.Node(key, value))

Returns a list of all nodes in the graph.

Examples

let graph = new()
|> insert_edge(edge.new("A", "B"))
|> insert_edge(edge.new("B", "C"))

get_nodes(graph)
// -> [Node(key: "A", ...), Node(key: "B", ...), Node(key: "C", ...)]
pub fn insert_edge(
  graph: Graph(key, value, label),
  edge: edge.Edge(key, label),
  default_node_value: value,
) -> Graph(key, value, label)

Inserts an edge into the graph. If any of the two nodes do not exist in the graph, they are created using the default value. If the edge already exists, it is replaced.

Examples

let graph = new()
let edge = edge.new("A", "B") |> edge.with_weight(5.0)
insert_edge_with_default(graph, edge, "Default Value")
// -> Graph with 2 nodes (A and B) and an edge from A to B with weight 5.0
let graph = new()
let edge1 = edge.new("A", "B") |> edge.with_label("connects to")
let graph = insert_edge_with_default(graph, edge1, "Default Value")

// Replace with a new edge
let edge2 = edge.new("A", "B") |> edge.with_weight(10.0)
insert_edge_with_default(graph, edge2, "Default Value")
// -> Edge from A to B now has weight 10.0 and no label
pub fn insert_node(
  graph: Graph(key, value, label),
  node: node.Node(key, value),
) -> Graph(key, value, label)

Inserts a node into the graph. If a node with the same key already exists, it is replaced.

New edges are added to the graph. Edges in the graph that are not present in the inserted node are removed. Existing edges remain unchanged. If any of the target nodes do not exist, they are created.

Examples

let graph = new()
let node = node.new("A") |> node.with_value("Node A")
insert_node(graph, node)
// -> Graph with node A having value "Node A"
// Adding a node with connections
let graph = new()
let node = node.new("A") 
  |> node.with_outgoing(["B", "C"])
  |> node.with_value("Node A")
insert_node(graph, node)
// -> Graph with node A and edges to B and C
pub fn new() -> Graph(key, value, label)

Creates a new empty graph.

Examples

new()
// -> Graph with 0 nodes and 0 edges
pub fn remove_edge(
  graph: Graph(key, value, label),
  edge: edge.Edge(key, label),
) -> Graph(key, value, label)

Removes an edge from the graph. If the edge does not exist, the graph remains unchanged.

Examples

let graph = new() |> insert_edge(edge.new("A", "B"))
let updated_graph = remove_edge(graph, edge.new("A", "B"))
// -> Graph with nodes A and B but no edges between them
pub fn remove_node(
  graph: Graph(key, value, label),
  key: node.NodeKey(key),
) -> Graph(key, value, label)

Removes a node and all its edges from the graph. If the node does not exist, the graph remains unchanged.

Examples

let graph = new()
  |> insert_edge(edge.new("A", "B"))
  |> insert_edge(edge.new("B", "C"))

let node_b = node.new("B")
remove_node(graph, node_b)
// -> Graph with nodes A and C, but no edges between them
pub fn try_insert_edge(
  graph: Graph(key, value, label),
  edge: edge.Edge(key, label),
) -> Result(Graph(key, value, label), Nil)

Inserts an edge into the graph. If a node does not exist in the graph, an error is returned. If the edge already exists, it is replaced.

Examples

let graph = new()
let edge = edge.new("A", "B") |> edge.with_weight(5.0)
insert_edge(graph, edge)
// -> Error(Nil)
let graph = new()
let edge1 = edge.new("A", "B") |> edge.with_label("connects to")
let graph = insert_edge(graph, edge1)

// Replace with a new edge
let edge2 = edge.new("A", "B") |> edge.with_weight(10.0)
insert_edge(graph, edge2)
// -> Edge from A to B now has weight 10.0 and no label
Search Document