LEDA (Library of Efficient Data types and Algorithms) graph format support.
Provides functions to serialize and deserialize graphs in the LEDA format, a text-based format used by the LEDA library and compatible with NetworkX.
Format Overview
LEDA files have a structured text format with distinct sections:
- Header:
LEDA.GRAPH - Type declarations: Node type and edge type
- Direction:
-1for directed,-2for undirected - Nodes: Count followed by node data lines
- Edges: Count followed by edge data lines
Example
iex> graph = Yog.directed()
...> |> Yog.add_node(1, "Alice")
...> |> Yog.add_node(2, "Bob")
...> |> Yog.add_edge_ensure(from: 1, to: 2, with: "5")
iex>
iex> leda_string = Yog.IO.LEDA.serialize(graph)
iex> String.contains?(leda_string, "LEDA.GRAPH")
true
iex> String.contains?(leda_string, "Alice")
trueParsing Behavior
- 1-indexed nodes: LEDA format uses 1-based indexing
- Sequential order: Nodes must appear in sequential order
- Strict node references: Auto-creation is not supported
- Reversal edges: Third field indicates index for undirected graphs
Summary
Functions
Returns default LEDA options for String node and edge data.
Creates LEDA options with custom serializers and deserializers.
Parses a LEDA string into a graph with String labels.
Parses a LEDA string into a graph with custom parser options.
Reads a graph from a LEDA file using String labels.
Reads a graph from a LEDA file with custom parsers.
Serializes a graph to LEDA format using default string conversion.
Serializes a graph to LEDA format with custom options.
Alias for serialize/1.
Writes a graph to a LEDA file using default string conversion.
Writes a graph to a LEDA file with custom serialization options.
Functions
@spec default_options() :: tuple()
Returns default LEDA options for String node and edge data.
Default behavior:
- Serialization: Convert data to string using
to_string/1 - Deserialization: Keep data as-is (identity function)
Example
iex> {:leda_options, _, _, _, _, _, _} = Yog.IO.LEDA.default_options()
iex> :ok
:ok
@spec options_with( (any() -> any()), (any() -> any()), (any() -> any()), (any() -> any()), keyword() ) :: tuple()
Creates LEDA options with custom serializers and deserializers.
Raises ArgumentError if any serializer or deserializer is not an arity-1 function or opts is invalid.
Time complexity: $\mathcal{O}(1)$
Parameters
node_serializer- Function to convert node data to string for output(node_data) -> stringedge_serializer- Function to convert edge data to string for output(edge_data) -> stringnode_deserializer- Function to convert string to node data on input(string) -> node_dataedge_deserializer- Function to convert string to edge data on input(string) -> edge_data
Returns
LEDA options tuple for use with serialize_with/2 and parse_with/2
Example
options = Yog.IO.LEDA.options_with(
fn %{name: n} -> n end, # Serialize node
fn weight -> Integer.to_string(weight) end, # Serialize edge
fn str -> %{name: str} end, # Deserialize node
fn str -> String.to_integer(str) end # Deserialize edge
)
Parses a LEDA string into a graph with String labels.
Node and edge data are stored as strings. For custom data structures,
use parse_with/3.
Raises ArgumentError if input is not a binary string.
Time complexity: $\mathcal{O}(V + E)$
Parameters
input- LEDA format string
Returns
{:ok, {:leda_result, graph, warnings}}on success{:error, reason}on parsing failure
Example
iex> leda_string = "LEDA.GRAPH\nstring\nstring\n-1\n2\n|{Alice}|\n|{Bob}|\n1\n1 2 0 |{follows}|"
iex> {:ok, {:leda_result, graph, _warnings}} = Yog.IO.LEDA.parse(leda_string)
iex> Yog.Model.node_count(graph)
2
@spec parse_with(String.t(), (any() -> any()), (any() -> any())) :: {:ok, {:leda_result, Yog.graph(), list()}} | {:error, term()}
Parses a LEDA string into a graph with custom parser options.
This function allows you to transform LEDA data into custom Elixir data structures as the graph is built.
Raises ArgumentError if input is not a binary string or parsers are invalid.
Time complexity: $\mathcal{O}(V + E)$
Parameters
input- LEDA format stringnode_parser- Function to transform node string to node data(string) -> node_dataedge_parser- Function to transform edge string to edge data(string) -> edge_data
Returns
{:ok, {:leda_result, graph, warnings}}on success{:error, reason}on parsing failure
The warnings list contains any issues encountered during parsing.
Example
leda_str = "LEDA.GRAPH\nstring\nstring\n-1\n2\n|{Alice}|\n|{Bob}|\n1\n1 2 0 |{5}|"
node_parser = fn str -> String.upcase(str) end
edge_parser = fn str -> String.to_integer(str) end
{:ok, {:leda_result, graph, _warnings}} =
Yog.IO.LEDA.parse_with(leda_str, node_parser, edge_parser)
Reads a graph from a LEDA file using String labels.
Raises ArgumentError if path is not a binary string.
Time complexity: $\mathcal{O}(V + E)$ + file I/O
Parameters
path- File path to read from
Returns
{:ok, {:leda_result, graph, warnings}}on success{:error, reason}on file read or parse failure
Example
{:ok, {:leda_result, graph, warnings}} =
Yog.IO.LEDA.read("network.leda")
IO.puts("Loaded graph with #{Yog.Model.node_count(graph)} nodes")
@spec read_with(String.t(), (any() -> any()), (any() -> any())) :: {:ok, {:leda_result, Yog.graph(), list()}} | {:error, term()}
Reads a graph from a LEDA file with custom parsers.
Raises ArgumentError if path is not a binary string.
Serializes a graph to LEDA format using default string conversion.
Node and edge data are converted to strings.
Raises ArgumentError if graph is invalid.
Time complexity: $\mathcal{O}(V + E)$
Example
iex> graph = Yog.directed()
...> |> Yog.add_node(1, "Alice")
...> |> Yog.add_node(2, "Bob")
...> |> Yog.add_edge_ensure(from: 1, to: 2, with: "5")
iex> leda = Yog.IO.LEDA.serialize(graph)
iex> String.contains?(leda, "LEDA.GRAPH") and String.contains?(leda, "Alice")
true
Serializes a graph to LEDA format with custom options.
Allows full control over how node and edge data are converted to LEDA format.
Raises ArgumentError if graph or options are invalid.
Time complexity: $\mathcal{O}(V + E)$ where $V$ is node count and $E$ is edge count.
Parameters
options- LEDA options tuple (seeoptions_with/5)graph- The graph to serialize
Returns
LEDA format string
Example
graph = Yog.directed()
|> Yog.add_node(1, %{name: "Alice"})
|> Yog.add_node(2, %{name: "Bob"})
options = Yog.IO.LEDA.options_with(
fn data -> data.name end,
fn _ -> "1" end,
fn _ -> nil end,
fn _ -> nil end
)
leda = Yog.IO.LEDA.serialize_with(options, graph)
Alias for serialize/1.
Provided for compatibility with other serialization libraries.
Time complexity: $\mathcal{O}(V + E)$
Writes a graph to a LEDA file using default string conversion.
Raises ArgumentError if path is not a binary string or graph is invalid.
Time complexity: $\mathcal{O}(V + E)$ + file I/O
Parameters
path- File path to write tograph- The graph to serialize
Returns
:okon success{:error, reason}on file write failure
Example
graph = Yog.directed()
|> Yog.add_node(1, "Alice")
|> Yog.add_node(2, "Bob")
Yog.IO.LEDA.write("network.leda", graph)
# => :ok
Writes a graph to a LEDA file with custom serialization options.
Raises ArgumentError if path is not a binary string or options/graph are invalid.
Time complexity: $\mathcal{O}(V + E)$ + file I/O
Parameters
path- File path to write tooptions- LEDA options tuple (seeoptions_with/5)graph- The graph to serialize
Returns
:okon success{:error, reason}on file write failure
Example
graph = Yog.directed() |> Yog.add_node(1, %{name: "Alice"})
options = Yog.IO.LEDA.options_with(
fn d -> d.name end, fn _ -> "1" end,
fn _ -> nil end, fn _ -> nil end
)
Yog.IO.LEDA.write_with("network.leda", options, graph)