yog_io/leda

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:

Example

import yog/model.{Directed}
import yog_io/leda

// Create a simple graph
let graph =
  model.new(Directed)
  |> model.add_node(1, "Alice")
  |> model.add_node(2, "Bob")

let assert Ok(graph) = model.add_edge(graph, from: 1, to: 2, with: "5")

// Serialize to LEDA
let leda_string = leda.serialize(graph)

// Write to file
let assert Ok(Nil) = leda.write("graph.gw", graph)

Output Format

LEDA.GRAPH
string
string
-1
2
|{Alice}|
|{Bob}|
1
1 2 0 |{5}|

Characteristics

Parsing Behavior

When parsing LEDA files, the following behaviors apply:

References

Types

Errors that can occur during LEDA operations.

pub type LedaError {
  EmptyInput
  InvalidHeader
  InvalidNodeType(line: Int, content: String)
  InvalidEdgeType(line: Int, content: String)
  InvalidDirection(line: Int, content: String)
  InvalidNodeCount(line: Int, content: String)
  InvalidEdgeCount(line: Int, content: String)
  InvalidNodeData(line: Int, content: String)
  InvalidEdgeData(line: Int, content: String)
  InvalidNodeId(line: Int, value: String)
  NodeIdOutOfRange(line: Int, id: Int, count: Int)
  ReadError(path: String, error: String)
  WriteError(path: String, error: String)
}

Constructors

  • EmptyInput

    Empty input string

  • InvalidHeader

    Invalid header (expected “LEDA.GRAPH”)

  • InvalidNodeType(line: Int, content: String)

    Invalid node type declaration

  • InvalidEdgeType(line: Int, content: String)

    Invalid edge type declaration

  • InvalidDirection(line: Int, content: String)

    Invalid direction (expected “-1” or “-2”)

  • InvalidNodeCount(line: Int, content: String)

    Invalid node count

  • InvalidEdgeCount(line: Int, content: String)

    Invalid edge count

  • InvalidNodeData(line: Int, content: String)

    Invalid node data format

  • InvalidEdgeData(line: Int, content: String)

    Invalid edge data format

  • InvalidNodeId(line: Int, value: String)

    Invalid node ID (not an integer)

  • NodeIdOutOfRange(line: Int, id: Int, count: Int)

    Node ID out of range (LEDA uses 1-indexing)

  • ReadError(path: String, error: String)

    File read error

  • WriteError(path: String, error: String)

    File write error

Options for LEDA serialization.

pub type LedaOptions(n, e) {
  LedaOptions(
    node_serializer: fn(n) -> String,
    edge_serializer: fn(e) -> String,
    node_deserializer: fn(String) -> n,
    edge_deserializer: fn(String) -> e,
  )
}

Constructors

  • LedaOptions(
      node_serializer: fn(n) -> String,
      edge_serializer: fn(e) -> String,
      node_deserializer: fn(String) -> n,
      edge_deserializer: fn(String) -> e,
    )

    Arguments

    node_serializer

    Function to convert node data to a string representation

    edge_serializer

    Function to convert edge data to a string representation

    node_deserializer

    Function to convert string back to node data

    edge_deserializer

    Function to convert string back to edge data

Result type for LEDA parsing.

pub type LedaResult(n, e) {
  LedaResult(
    graph: model.Graph(n, e),
    warnings: List(#(Int, String)),
  )
}

Constructors

  • LedaResult(
      graph: model.Graph(n, e),
      warnings: List(#(Int, String)),
    )

    Arguments

    warnings

    Lines that couldn’t be parsed (with line numbers)

LEDA data types for type declarations in the header.

Note: Currently, serialization always uses "string" for both node and edge types for maximum compatibility. This type is reserved for future enhancements to support typed LEDA files with proper int, double, and custom types. The LEDA format specification supports these types in the header section (lines 2-3), but the current implementation prioritizes simplicity and broad compatibility.

pub type LedaType {
  VoidType
  StringType
  IntType
  DoubleType
  CustomType(String)
}

Constructors

  • VoidType

    Void type - no data

  • StringType

    String type

  • IntType

    Integer type

  • DoubleType

    Double/float type

  • CustomType(String)

    Custom type with name

Values

pub fn default_options() -> LedaOptions(String, String)

Default LEDA options for String node and edge data.

Uses identity functions for serialization/deserialization.

pub fn options_with(
  node_serializer node_serializer: fn(n) -> String,
  edge_serializer edge_serializer: fn(e) -> String,
  node_deserializer node_deserializer: fn(String) -> n,
  edge_deserializer edge_deserializer: fn(String) -> e,
) -> LedaOptions(n, e)

Creates LEDA options with custom serializers.

Example

let options = leda.options_with(
  node_serializer: fn(p) { p.name },
  edge_serializer: fn(w) { int.to_string(w) },
  node_deserializer: fn(s) { Person(s, 0) },
  edge_deserializer: fn(s) {
    case int.parse(s) { Ok(n) -> n Error(_) -> 0 }
  },
)
pub fn parse(
  input: String,
) -> Result(LedaResult(String, String), LedaError)

Parses a LEDA string into a graph with String labels.

Convenience function for the common case where both node and edge data are just Strings.

Example

let leda_string = "LEDA.GRAPH\nstring\nstring\n-1\n2\n|{Alice}|\n|{Bob}|\n1\n1 2 0 |{follows}|"

case leda.parse(leda_string) {
  Ok(result) -> {
    // result.graph is Graph(String, String)
    process_graph(result.graph)
  }
  Error(e) -> handle_error(e)
}
pub fn parse_with(
  input: String,
  node_parser node_parser: fn(String) -> n,
  edge_parser edge_parser: fn(String) -> e,
) -> Result(LedaResult(n, e), LedaError)

Parses a LEDA string into a graph with custom options.

Example

let leda_string = "LEDA.GRAPH\nstring\nstring\n-1\n2\n|{Alice}|\n|{Bob}|\n1\n1 2 0 |{follows}|"

let result = leda.parse_with(
  leda_string,
  node_parser: fn(s) { s },
  edge_parser: fn(s) { s },
)

case result {
  Ok(leda.LedaResult(graph, warnings)) -> {
    // Use the graph
    process_graph(graph)
  }
  Error(e) -> handle_error(e)
}
pub fn read(
  path: String,
) -> Result(LedaResult(String, String), LedaError)

Reads a graph from a LEDA file.

Convenience function that reads node and edge data as strings.

Example

let result = leda.read("graph.gw")

case result {
  Ok(leda.LedaResult(graph, warnings)) -> {
    // Use the graph
    process_graph(graph)
  }
  Error(e) -> handle_error(e)
}
pub fn read_with(
  path: String,
  node_parser node_parser: fn(String) -> n,
  edge_parser edge_parser: fn(String) -> e,
) -> Result(LedaResult(n, e), LedaError)

Reads a graph from a LEDA file with custom parsers.

Example

let result = leda.read_with(
  "graph.gw",
  node_parser: fn(s) { Person(s, 0) },
  edge_parser: fn(s) { case int.parse(s) { Ok(n) -> n Error(_) -> 0 } },
)
pub fn serialize(graph: model.Graph(String, String)) -> String

Serializes a graph to LEDA format.

Convenience function for graphs with String node and edge data.

Example

let leda_string = leda.serialize(graph)
pub fn serialize_with(
  options: LedaOptions(n, e),
  graph: model.Graph(n, e),
) -> String

Serializes a graph to LEDA format with custom options.

Time Complexity: O(V + E)

Example

import yog/model.{Directed}
import yog_io/leda

type Person {
  Person(name: String, age: Int)
}

let graph =
  model.new(Directed)
  |> model.add_node(1, Person("Alice", 30))
  |> model.add_node(2, Person("Bob", 25))

let options = leda.options_with(
  node_serializer: fn(p) { p.name },
  edge_serializer: fn(w) { w },
  node_deserializer: fn(s) { Person(s, 0) },
  edge_deserializer: fn(s) { s },
)

let leda_string = leda.serialize_with(options, graph)
pub fn to_string(graph: model.Graph(String, String)) -> String

Converts a graph to a LEDA string.

Alias for serialize for consistency with other modules.

pub fn write(
  path: String,
  graph: model.Graph(String, String),
) -> Result(Nil, simplifile.FileError)

Writes a graph to a LEDA file.

Example

let assert Ok(Nil) = leda.write("graph.gw", graph)
pub fn write_with(
  path: String,
  options: LedaOptions(n, e),
  graph: model.Graph(n, e),
) -> Result(Nil, simplifile.FileError)

Writes a graph to a LEDA file with custom options.

Example

let options = leda.options_with(
  node_serializer: fn(p) { p.name },
  edge_serializer: fn(w) { int.to_string(w) },
  node_deserializer: fn(s) { Person(s, 0) },
  edge_deserializer: fn(s) { case int.parse(s) { Ok(n) -> n Error(_) -> 0 } },
)

let assert Ok(Nil) = leda.write_with("graph.gw", options, graph)
Search Document