Build graphs using arbitrary labels instead of integer IDs.
This module provides a convenient way to build graphs when your nodes are naturally identified by strings, atoms, or other types, rather than integers.
Example Usage
# Build a graph with string labels
builder = Yog.Builder.Labeled.directed()
|> Yog.Builder.Labeled.add_edge("home", "work", 10)
|> Yog.Builder.Labeled.add_edge("work", "gym", 5)
# Convert to a Graph to use with algorithms
graph = Yog.Builder.Labeled.to_graph(builder)
# Get the node ID for a label
{:ok, home_id} = Yog.Builder.Labeled.get_id(builder, "home")
# Use with pathfinding
case Yog.Pathfinding.Dijkstra.shortest_path(
in: graph,
from: home_id,
to: gym_id,
zero: 0,
add: &Kernel.+/2,
compare: &Integer.compare/2
) do
{:some, path} -> path
:none -> :no_path
endBatch Construction
For building from existing data, use the from_list functions:
edges = [{"A", "B", 5}, {"B", "C", 3}, {"A", "C", 10}]
builder = Yog.Builder.Labeled.from_list(:directed, edges)
graph = Yog.Builder.Labeled.to_graph(builder)Migration Note: This module was ported from Gleam to pure Elixir in v0.53.0. The API remains unchanged.
Summary
Functions
Adds an edge between two labeled nodes with a weight.
Adds a node with the given label.
Adds a simple edge with weight 1 between two labeled nodes.
Adds an unweighted edge between two labeled nodes.
Returns all labels that have been added to the builder.
Creates a new labeled directed graph builder.
Gets or creates a node for the given label.
Creates a builder from a list of labeled edges.
Creates a builder from a list of unweighted labeled edges.
Looks up the internal node ID for a given label.
Creates a new labeled graph builder of the specified type.
Gets the next available node ID.
Gets the predecessors of a node by its label.
Gets the successors of a node by its label.
Converts the builder to a standard Graph.
Gets the label-to-ID registry as a map.
Creates a new labeled undirected graph builder.
Types
@type builder() :: {:labeled_builder, Yog.Model.graph_type(), Yog.graph(), map(), integer()} | t()
Legacy builder type (deprecated)
@type label() :: term()
Any type can be used as a label
@type t() :: %Yog.Builder.Labeled{ graph: Yog.graph(), kind: Yog.Model.graph_type(), label_to_id: %{required(label()) => Yog.node_id()}, next_id: integer() }
Labeled builder struct
Functions
Adds an edge between two labeled nodes with a weight.
If either node doesn't exist, it will be created automatically.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_edge("A", "B", 10)
iex> {:ok, successors} = Yog.Builder.Labeled.successors(builder, "A")
iex> successors
[{"B", 10}]
Adds a node with the given label.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_node("Node A")
iex> Yog.Builder.Labeled.all_labels(builder)
["Node A"]
Adds a simple edge with weight 1 between two labeled nodes.
Unlike add_unweighted_edge/3 which stores weight as nil, this stores weight as 1.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_simple_edge("A", "B")
iex> is_struct(builder, Yog.Builder.Labeled)
true
Adds an unweighted edge between two labeled nodes.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_unweighted_edge("A", "B")
iex> {:ok, [{"B", nil}]} = Yog.Builder.Labeled.successors(builder, "A")
Returns all labels that have been added to the builder.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_node("A")
...> |> Yog.Builder.Labeled.add_node("B")
iex> Yog.Builder.Labeled.all_labels(builder)
["A", "B"]
@spec directed() :: t()
Creates a new labeled directed graph builder.
Examples
iex> builder = Yog.Builder.Labeled.directed()
iex> is_struct(builder, Yog.Builder.Labeled)
true
@spec ensure_node(t(), label()) :: {t(), Yog.node_id()}
Gets or creates a node for the given label.
If a node with this label already exists, returns its existing ID. If it doesn't exist, creates a new node and returns the new ID.
Examples
iex> builder = Yog.Builder.Labeled.directed()
iex> {_builder, id} = Yog.Builder.Labeled.ensure_node(builder, "A")
iex> is_integer(id)
true
@spec from_list(Yog.Model.graph_type(), [{label(), label(), term()}]) :: t()
Creates a builder from a list of labeled edges.
Examples
iex> edges = [{"A", "B", 5}, {"B", "C", 3}]
iex> builder = Yog.Builder.Labeled.from_list(:directed, edges)
iex> {:ok, [{"B", 5}]} = Yog.Builder.Labeled.successors(builder, "A")
@spec from_unweighted_list(Yog.Model.graph_type(), [{label(), label()}]) :: t()
Creates a builder from a list of unweighted labeled edges.
Examples
iex> edges = [{"A", "B"}, {"B", "C"}]
iex> builder = Yog.Builder.Labeled.from_unweighted_list(:directed, edges)
iex> {:ok, [{"B", nil}]} = Yog.Builder.Labeled.successors(builder, "A")
@spec get_id(t() | builder(), label()) :: {:ok, Yog.node_id()} | {:error, nil}
Looks up the internal node ID for a given label.
Returns {:ok, id} if the label exists, {:error, nil} otherwise.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_node("A")
iex> Yog.Builder.Labeled.get_id(builder, "A")
{:ok, 0}
iex> builder = Yog.Builder.Labeled.directed()
iex> Yog.Builder.Labeled.get_id(builder, "NonExistent")
{:error, nil}
@spec new(Yog.Model.graph_type()) :: t()
Creates a new labeled graph builder of the specified type.
Examples
iex> builder = Yog.Builder.Labeled.new(:directed)
iex> is_struct(builder, Yog.Builder.Labeled)
true
@spec next_id(t() | builder()) :: Yog.node_id()
Gets the next available node ID.
This is the ID that would be assigned to the next new node.
Examples
iex> builder = Yog.Builder.Labeled.directed()
iex> Yog.Builder.Labeled.next_id(builder)
0
iex> builder = Yog.Builder.Labeled.add_node(builder, "A")
iex> Yog.Builder.Labeled.next_id(builder)
1
Gets the predecessors of a node by its label.
Returns {:ok, edges} where edges is a list of {label, weight} tuples,
or {:error, nil} if the label doesn't exist.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_edge("A", "B", 5)
iex> Yog.Builder.Labeled.predecessors(builder, "B")
{:ok, [{"A", 5}]}
Gets the successors of a node by its label.
Returns {:ok, edges} where edges is a list of {label, weight} tuples,
or {:error, nil} if the label doesn't exist.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_edge("A", "B", 10)
iex> Yog.Builder.Labeled.successors(builder, "A")
{:ok, [{"B", 10}]}
Converts the builder to a standard Graph.
The resulting graph can be used with all Yog algorithms.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_edge("A", "B", 5)
iex> graph = Yog.Builder.Labeled.to_graph(builder)
iex> Yog.graph?(graph)
true
@spec to_registry(t() | builder()) :: %{required(label()) => Yog.node_id()}
Gets the label-to-ID registry as a map.
Returns a map where keys are labels and values are node IDs.
Examples
iex> builder = Yog.Builder.Labeled.directed()
...> |> Yog.Builder.Labeled.add_node("A")
iex> registry = Yog.Builder.Labeled.to_registry(builder)
iex> Map.get(registry, "A")
0
@spec undirected() :: t()
Creates a new labeled undirected graph builder.
Examples
iex> builder = Yog.Builder.Labeled.undirected()
iex> is_struct(builder, Yog.Builder.Labeled)
true