Yog.IO.LEDA (YogEx v1.0.0)

Copy Markdown View Source

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: -1 for directed, -2 for 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")
true

Parsing 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.

Writes a graph to a LEDA file using default string conversion.

Writes a graph to a LEDA file with custom serialization options.

Functions

default_options()

@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

options_with(node_ser, edge_ser, node_deser, edge_deser, opts \\ [])

@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) -> string
  • edge_serializer - Function to convert edge data to string for output (edge_data) -> string
  • node_deserializer - Function to convert string to node data on input (string) -> node_data
  • edge_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
)

parse(input)

@spec parse(String.t()) ::
  {:ok, {:leda_result, Yog.graph(), list()}} | {:error, term()}

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

parse_with(input, node_parser, edge_parser)

@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 string
  • node_parser - Function to transform node string to node data (string) -> node_data
  • edge_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)

read(path)

@spec read(String.t()) ::
  {:ok, {:leda_result, Yog.graph(), list()}} | {:error, term()}

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")

read_with(path, node_parser, edge_parser)

@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.

serialize(graph)

@spec serialize(Yog.graph() | Yog.DAG.t()) :: String.t()

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

serialize_with(options, graph)

@spec serialize_with(tuple(), Yog.graph() | Yog.DAG.t()) :: String.t()

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 (see options_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)

to_string(graph)

@spec to_string(Yog.graph() | Yog.DAG.t()) :: String.t()

Alias for serialize/1.

Provided for compatibility with other serialization libraries.

Time complexity: $\mathcal{O}(V + E)$

write(path, graph)

@spec write(String.t(), Yog.graph() | Yog.DAG.t()) :: :ok | {:error, atom()}

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 to
  • graph - The graph to serialize

Returns

  • :ok on 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

write_with(path, options, graph)

@spec write_with(String.t(), tuple(), Yog.graph() | Yog.DAG.t()) ::
  :ok | {:error, atom()}

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 to
  • options - LEDA options tuple (see options_with/5)
  • graph - The graph to serialize

Returns

  • :ok on 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)