Current section

Files

Jump to
yog_ex lib yog graph.ex
Raw

lib/yog/graph.ex

defmodule Yog.Graph do
@moduledoc """
Core graph data structure.
A graph is represented as a struct with four fields:
- `kind`: Either `:directed` or `:undirected`
- `nodes`: Map of node_id => node_data
- `out_edges`: Map of node_id => %{neighbor_id => weight}
- `in_edges`: Map of node_id => %{neighbor_id => weight}
The dual-map representation (storing both out_edges and in_edges) enables:
- O(1) graph transpose (just swap out_edges ↔ in_edges)
- Efficient predecessor queries without traversing the entire graph
- Fast bidirectional edge lookups
## Examples
iex> %Yog.Graph{
...> kind: :directed,
...> nodes: %{1 => "A", 2 => "B"},
...> out_edges: %{1 => %{2 => 10}},
...> in_edges: %{2 => %{1 => 10}}
...> }
"""
@type node_id :: integer()
@type kind :: :directed | :undirected
@type t :: %__MODULE__{
kind: kind(),
nodes: %{node_id() => any()},
out_edges: %{node_id() => %{node_id() => number()}},
in_edges: %{node_id() => %{node_id() => number()}}
}
@enforce_keys [:kind, :nodes, :out_edges, :in_edges]
defstruct [:kind, :nodes, :out_edges, :in_edges]
@doc """
Creates a new empty graph of the given type.
"""
@spec new(kind()) :: t()
def new(kind) when kind in [:directed, :undirected] do
%__MODULE__{
kind: kind,
nodes: %{},
out_edges: %{},
in_edges: %{}
}
end
end