yog_io/pajek

Pajek (.net) format serialization support.

Provides functions to serialize and deserialize graphs in the Pajek .net format, a standard format for social network analysis used by the Pajek software and compatible with many network analysis tools.

Format Overview

Pajek files have a structured text format with distinct sections:

Example

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

// 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 Pajek
let pajek_string = pajek.serialize(graph)

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

Output Format

*Vertices 3
1 "Alice"
2 "Bob"
3 "Carol"
*Arcs
1 2 5
2 3 3

Characteristics

Parsing Behavior

When parsing Pajek .net files, the following behaviors apply:

References

Types

Node visual attributes for Pajek format.

pub type NodeAttributes {
  NodeAttributes(
    x: option.Option(Float),
    y: option.Option(Float),
    shape: option.Option(NodeShape),
    size: option.Option(Float),
    color: option.Option(String),
  )
}

Constructors

Node shape options for Pajek visualization.

pub type NodeShape {
  Ellipse
  Box
  Diamond
  Triangle
  Cross
  Empty
  CustomShape(String)
}

Constructors

  • Ellipse

    Default ellipse shape

  • Box

    Box/rectangle shape

  • Diamond

    Diamond shape

  • Triangle

    Triangle shape

  • Cross

    Cross shape

  • Empty

    Empty shape (invisible node)

  • CustomShape(String)

    Custom shape name

Errors that can occur during Pajek operations.

pub type PajekError {
  EmptyInput
  InvalidVerticesLine(line: Int, content: String)
  InvalidVertexLine(line: Int, content: String)
  InvalidSectionHeader(line: Int, content: String)
  InvalidArcLine(line: Int, content: String)
  InvalidNodeId(line: Int, value: String)
  InvalidWeight(line: Int, value: String)
  NodeIdOutOfRange(line: Int, id: Int, max: Int)
  MissingVerticesSection
  ReadError(path: String, error: String)
  WriteError(path: String, error: String)
}

Constructors

  • EmptyInput

    Empty input string

  • InvalidVerticesLine(line: Int, content: String)

    Invalid *Vertices line

  • InvalidVertexLine(line: Int, content: String)

    Invalid vertex/node line

  • InvalidSectionHeader(line: Int, content: String)

    Invalid *Arcs or *Edges section header

  • InvalidArcLine(line: Int, content: String)

    Invalid arc/edge line

  • InvalidNodeId(line: Int, value: String)

    Invalid node ID

  • InvalidWeight(line: Int, value: String)

    Invalid weight value

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

    Node ID out of range

  • MissingVerticesSection

    Missing *Vertices section

  • ReadError(path: String, error: String)

    File read error

  • WriteError(path: String, error: String)

    File write error

Options for Pajek serialization.

pub type PajekOptions(n, e) {
  PajekOptions(
    node_label: fn(n) -> String,
    edge_weight: fn(e) -> option.Option(Float),
    node_attributes: fn(n) -> NodeAttributes,
    include_coordinates: Bool,
    include_visuals: Bool,
  )
}

Constructors

  • PajekOptions(
      node_label: fn(n) -> String,
      edge_weight: fn(e) -> option.Option(Float),
      node_attributes: fn(n) -> NodeAttributes,
      include_coordinates: Bool,
      include_visuals: Bool,
    )

    Arguments

    node_label

    Function to convert node data to a label string

    edge_weight

    Function to convert edge data to a weight (optional)

    node_attributes

    Function to get node attributes (for visualization)

    include_coordinates

    Include node coordinates in output

    include_visuals

    Include visual attributes (shape, color, size)

Result type for Pajek parsing.

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

Constructors

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

    Arguments

    warnings

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

Values

pub fn default_node_attributes() -> NodeAttributes

Default node attributes (no special visualization).

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

Default Pajek options for String node and edge data.

Default configuration:

  • Node labels: Uses the node data’s string representation
  • Edge weights: None (no weights)
  • Node attributes: None
  • Include coordinates: False
  • Include visuals: False
pub fn options_with(
  node_label node_label: fn(n) -> String,
  edge_weight edge_weight: fn(e) -> option.Option(Float),
  node_attributes node_attributes: fn(n) -> NodeAttributes,
  include_coordinates include_coordinates: Bool,
  include_visuals include_visuals: Bool,
) -> PajekOptions(n, e)

Creates Pajek options with custom functions.

Example

let options = pajek.options_with(
  node_label: fn(p) { p.name },
  edge_weight: fn(w) { Some(w) },
  node_attributes: fn(p) { pajek.NodeAttributes(
    x: Some(p.x),
    y: Some(p.y),
    shape: Some(pajek.Ellipse),
    size: None,
    color: None,
  )},
  include_coordinates: True,
  include_visuals: False,
)
pub fn parse(
  input: String,
) -> Result(PajekResult(String, String), PajekError)

Parses a Pajek string into a graph with String labels.

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

Example

let pajek_string = "*Vertices 2\n1 \"Alice\"\n2 \"Bob\"\n*Arcs\n1 2"

case pajek.parse(pajek_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(option.Option(Float)) -> e,
) -> Result(PajekResult(n, e), PajekError)

Parses a Pajek string into a graph with custom parsers.

Example

let pajek_string = "*Vertices 2\n1 \"Alice\"\n2 \"Bob\"\n*Arcs\n1 2"

let result = pajek.parse_with(
  pajek_string,
  node_parser: fn(s) { s },
  edge_parser: fn(_) { "" },
)

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

Reads a graph from a Pajek file.

Convenience function that reads node and edge data as strings.

Example

let result = pajek.read("graph.net")

case result {
  Ok(pajek.PajekResult(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(option.Option(Float)) -> e,
) -> Result(PajekResult(n, e), PajekError)

Reads a graph from a Pajek file with custom parsers.

Example

let result = pajek.read_with(
  "graph.net",
  node_parser: fn(s) { Person(s, 0.0, 0.0) },
  edge_parser: fn(w) { case w { Some(val) -> val None -> 0.0 } },
)
pub fn serialize(graph: model.Graph(String, String)) -> String

Serializes a graph to Pajek format.

Convenience function for graphs with String node and edge data.

Example

let pajek_string = pajek.serialize(graph)
pub fn serialize_with(
  options: PajekOptions(n, e),
  graph: model.Graph(n, e),
) -> String

Serializes a graph to Pajek format with custom options.

Time Complexity: O(V + E)

Example

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

type Person {
  Person(name: String, x: Float, y: Float)
}

let graph =
  model.new(Directed)
  |> model.add_node(1, Person("Alice", 0.5, 0.5))
  |> model.add_node(2, Person("Bob", 0.7, 0.3))

let options = pajek.options_with(
  node_label: fn(p) { p.name },
  edge_weight: fn(w) { None },
  node_attributes: fn(p) { pajek.NodeAttributes(
    x: Some(p.x),
    y: Some(p.y),
    shape: None,
    size: None,
    color: None,
  )},
  include_coordinates: True,
  include_visuals: False,
)

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

Converts a graph to a Pajek 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 Pajek file.

Example

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

Writes a graph to a Pajek file with custom options.

Example

let options = pajek.options_with(
  node_label: fn(p) { p.name },
  edge_weight: fn(w) { Some(w) },
  node_attributes: fn(_) { pajek.default_node_attributes() },
  include_coordinates: False,
  include_visuals: False,
)

let assert Ok(Nil) = pajek.write_with("graph.net", options, graph)
Search Document