yog_io/gdf

GDF (GUESS Graph Format) serialization support.

Provides functions to serialize and deserialize graphs in GDF format, a simple text-based format used by Gephi and other graph visualization tools. GDF uses a column-based format similar to CSV with separate sections for nodes and edges.

Format Overview

GDF files consist of two sections:

Example

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

// 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 GDF
let gdf_string = gdf.serialize(graph)

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

Output Format

nodedef>name VARCHAR,label VARCHAR
1,Alice
2,Bob
edgedef>node1 VARCHAR,node2 VARCHAR,directed BOOLEAN,weight VARCHAR
1,2,true,5

References

Types

A graph with string-based attributes for nodes and edges.

pub type AttributedGraph =
  model.Graph(
    dict.Dict(String, String),
    dict.Dict(String, String),
  )

Attributes for an edge as a dictionary of string key-value pairs.

pub type EdgeAttributes =
  dict.Dict(String, String)

Options for GDF serialization.

pub type GdfOptions {
  GdfOptions(
    separator: String,
    include_types: Bool,
    include_directed: option.Option(Bool),
  )
}

Constructors

  • GdfOptions(
      separator: String,
      include_types: Bool,
      include_directed: option.Option(Bool),
    )

    Arguments

    separator

    Column separator (default: comma)

    include_types

    Include type annotations in header (default: True)

    include_directed

    Include the ‘directed’ column for edges (default: auto-detect from graph type)

Attributes for a node as a dictionary of string key-value pairs.

pub type NodeAttributes =
  dict.Dict(String, String)

Values

pub fn default_options() -> GdfOptions

Default GDF serialization options.

pub fn deserialize(
  gdf: String,
) -> Result(
  model.Graph(
    dict.Dict(String, String),
    dict.Dict(String, String),
  ),
  String,
)

Deserializes a GDF string to a graph.

This is a simplified version of deserialize_with for graphs where you want node data and edge data as string dictionaries containing all attributes.

Time Complexity: O(V + E)

Example

import yog_io/gdf

let gdf_string = "..."
let assert Ok(graph) = gdf.deserialize(gdf_string)

// Access node data
let node1_data = dict.get(graph.nodes, 1)  // Dict(String, String)
let label = dict.get(node1_data, "label")
pub fn deserialize_with(
  node_folder: fn(dict.Dict(String, String)) -> n,
  edge_folder: fn(dict.Dict(String, String)) -> e,
  gdf: String,
) -> Result(model.Graph(n, e), String)

Deserializes a GDF string into a graph with custom data mappers.

This function allows you to control how GDF columns are converted to your node and edge data types. Use deserialize for simple cases where you want node/edge data as string dictionaries.

Time Complexity: O(V + E)

Example

import gleam/dict
import yog_io/gdf

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

let node_folder = fn(attrs: dict.Dict(String, String)) {
  let name = dict.get(attrs, "label") |> result.unwrap("")
  let age = dict.get(attrs, "age") |> result.unwrap("0") |> int.parse |> result.unwrap(0)
  Person(name, age)
}

let gdf = "..."
let assert Ok(graph) = gdf.deserialize_with(node_folder, fn(attrs) {
  dict.get(attrs, "weight") |> result.unwrap("")
}, gdf)
pub fn read(
  path: String,
) -> Result(
  model.Graph(
    dict.Dict(String, String),
    dict.Dict(String, String),
  ),
  String,
)

Reads a graph from a GDF file.

Example

import yog_io/gdf

let assert Ok(graph) = gdf.read("graph.gdf")
pub fn read_with(
  path: String,
  node_folder: fn(dict.Dict(String, String)) -> n,
  edge_folder: fn(dict.Dict(String, String)) -> e,
) -> Result(model.Graph(n, e), String)

Reads a graph from a GDF file with custom data mappers.

pub fn serialize(graph: model.Graph(String, String)) -> String

Serializes a graph to GDF format where node and edge data are strings.

This is a simplified version of serialize_with for graphs where node data and edge data are already strings. The string data is used as the “label” attribute for both nodes and edges.

Time Complexity: O(V + E)

Example

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

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

let gdf = gdf.serialize(graph)
// nodedef>name VARCHAR,label VARCHAR
// 1,Alice
// 2,Bob
// edgedef>node1 VARCHAR,node2 VARCHAR,directed BOOLEAN,label VARCHAR
// 1,2,true,friend
pub fn serialize_weighted(
  graph: model.Graph(String, Int),
) -> String

Serializes a graph to GDF format with integer edge weights.

This is a convenience function for the common case of graphs with integer weights. Node data is used as labels, and edge weights are serialized to the “weight” column.

Time Complexity: O(V + E)

Example

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

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)

let gdf = gdf.serialize_weighted(graph)
pub fn serialize_with(
  node_attr: fn(n) -> dict.Dict(String, String),
  edge_attr: fn(e) -> dict.Dict(String, String),
  options: GdfOptions,
  graph: model.Graph(n, e),
) -> String

Serializes a graph to GDF format with custom attribute mappers and options.

This function allows you to control how node and edge data are converted to GDF attributes, and customize the output format.

Time Complexity: O(V + E)

Example

import gleam/dict
import yog/model.{Directed}
import yog_io/gdf

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

type Connection {
  Connection(weight: Int, relation: String)
}

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

let node_attrs = fn(p: Person) {
  dict.from_list([#("label", p.name), #("age", int.to_string(p.age))])
}

let edge_attrs = fn(c: Connection) {
  dict.from_list([#("weight", int.to_string(c.weight)), #("type", c.relation)])
}

let gdf = gdf.serialize_with(node_attrs, edge_attrs, gdf.default_options(), graph)
pub fn write(
  path: String,
  graph: model.Graph(String, String),
) -> Result(Nil, simplifile.FileError)

Writes a graph to a GDF file.

Example

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

let graph =
  model.new(Directed)
  |> model.add_node(1, "Start")
  |> model.add_node(2, "End")

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

let assert Ok(Nil) = gdf.write("mygraph.gdf", graph)
pub fn write_with(
  path: String,
  node_attr: fn(n) -> dict.Dict(String, String),
  edge_attr: fn(e) -> dict.Dict(String, String),
  options: GdfOptions,
  graph: model.Graph(n, e),
) -> Result(Nil, simplifile.FileError)

Writes a graph to a GDF file with custom attribute mappers.

Search Document