Yog.FSharp
Getting Started Examples API Reference GitHub

GraphML Module

GraphML (Graph Markup Language) serialization support.

Provides functions to serialize and deserialize graphs in the GraphML format, an XML-based format widely supported by graph visualization and analysis tools like Gephi, yEd, Cytoscape, and NetworkX.

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
open Yog.IO
open Yog.Model

// Create a simple graph
let graph =
    empty Directed
    |> addNode 1 "Alice"
    |> addNode 2 "Bob"
    |> addEdge 1 2 5

// Serialize to GraphML
let xml = GraphML.serialize graph
File.WriteAllText("graph.graphml", xml)

// Deserialize from GraphML
let loaded = File.ReadAllText("graph.graphml") |> GraphML.deserialize
namespace Yog
namespace Yog.IO
module Model from Yog
<summary> Core graph data structures and basic operations for the yog library. This module defines the fundamental `Graph` type and provides all basic operations for creating and manipulating graphs. The graph uses an adjacency list representation with dual indexing (both outgoing and incoming edges) for efficient traversal in both directions. </summary>
val graph: Graph<string,int>
val empty: graphType: GraphType -> Graph<'n,'e>
<summary> Creates a new empty graph of the specified type. ## Example ```fsharp let graph = Model.empty Directed ``` </summary>
union case GraphType.Directed: GraphType
<summary> A directed graph where edges have a direction from source to destination. </summary>
val addNode: id: NodeId -> data: 'n -> graph: Graph<'n,'e> -> Graph<'n,'e>
<summary> Adds a node to the graph with the given ID and data. If a node with this ID already exists, its data will be replaced. ## Example ```fsharp graph |&gt; addNode 1 "Node A" |&gt; addNode 2 "Node B" ``` </summary>
val addEdge: src: NodeId -> dst: NodeId -> weight: 'e -> graph: Graph<'n,'e> -> Graph<'n,'e>
<summary> Adds an edge to the graph with the given weight. For directed graphs, adds a single edge from src to dst. For undirected graphs, adds edges in both directions. &gt; **Note:** If `src` or `dst` have not been added via `addNode`, &gt; the edge will still be created in the edge dictionaries, but the &gt; nodes will be missing from `graph.Nodes`. This creates "ghost nodes" &gt; that are traversable but invisible to functions that iterate over &gt; nodes (e.g. `order`, `allNodes`). Use `addEdgeEnsured` to &gt; auto-create missing endpoints with a default value. ## Example ```fsharp graph |&gt; addEdge 1 2 10 ``` </summary>
val xml: string
module GraphML from Yog.IO
<summary> GraphML (Graph Markup Language) serialization support. Provides functions to serialize and deserialize graphs in the GraphML format, an XML-based format widely supported by graph visualization and analysis tools like Gephi, yEd, Cytoscape, and NetworkX. ## Example ```fsharp open Yog.IO open Yog.Model // Create a simple graph let graph = empty Directed |&gt; addNode 1 "Alice" |&gt; addNode 2 "Bob" |&gt; addEdge 1 2 5 // Serialize to GraphML let xml = GraphML.serialize graph File.WriteAllText("graph.graphml", xml) // Deserialize from GraphML let loaded = File.ReadAllText("graph.graphml") |&gt; GraphML.deserialize ``` </summary>
val serialize: graph: Graph<string,string> -> string
<summary> Serializes a graph to a GraphML string. This is a simplified version of `serializeWith` for graphs where node data and edge data are already strings. **Time Complexity:** O(V + E) ## Example ```fsharp let graph = empty Directed |&gt; addNode 1 "Alice" |&gt; addNode 2 "Bob" |&gt; addEdge 1 2 "5" let xml = GraphML.serialize graph // &lt;?xml version="1.0" encoding="utf-8"?&gt; // &lt;graphml xmlns="http://graphml.graphdrawing.org/xmlns"&gt; // &lt;key id="label" for="node" attr.name="label" attr.type="string" /&gt; // &lt;key id="weight" for="edge" attr.name="weight" attr.type="string" /&gt; // &lt;graph id="G" edgedefault="directed"&gt; // &lt;node id="1"&gt;&lt;data key="label"&gt;Alice&lt;/data&gt;&lt;/node&gt; // &lt;node id="2"&gt;&lt;data key="label"&gt;Bob&lt;/data&gt;&lt;/node&gt; // &lt;edge source="1" target="2"&gt;&lt;data key="weight"&gt;5&lt;/data&gt;&lt;/edge&gt; // &lt;/graph&gt; // &lt;/graphml&gt; ``` </summary>
val loaded: Graph<Map<string,string>,Map<string,string>>
val deserialize: xml: string -> Graph<Map<string,string>,Map<string,string>>
<summary> Deserializes a GraphML string to a graph. This is a simplified version of `deserializeWith` for graphs where you want node data and edge data as string maps containing all attributes. **Time Complexity:** O(V + E) ## Example ```fsharp let xml = File.ReadAllText("graph.graphml") let graph = GraphML.deserialize xml // Access node data let node1Data = graph.Nodes.[1] // Map&lt;string, string&gt; let label = Map.tryFind "label" node1Data ``` </summary>

Functions and values

Function or value Description

deserialize xml

Full Usage: deserialize xml

Parameters:
    xml : string

Returns: Graph<Map<string, string>, Map<string, string>>

Deserializes a GraphML string to a graph.

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

Time Complexity: O(V + E)

Example

1: 
2: 
3: 
4: 
5: 
6: 
let xml = File.ReadAllText("graph.graphml")
let graph = GraphML.deserialize xml

// Access node data
let node1Data = graph.Nodes.[1]  // Map<string, string>
let label = Map.tryFind "label" node1Data
val xml: obj
val graph: obj
val node1Data: Map<string,obj>
val label: obj option
Multiple items
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
val tryFind: key: 'Key -> table: Map<'Key,'T> -> 'T option (requires comparison)

xml : string
Returns: Graph<Map<string, string>, Map<string, string>>

deserializeWith nodeFolder edgeFolder xml

Full Usage: deserializeWith nodeFolder edgeFolder xml

Parameters:
    nodeFolder : Map<string, string> -> 'n
    edgeFolder : Map<string, string> -> 'e
    xml : string

Returns: Graph<'n, 'e>

Deserializes GraphML string back into a Yog Graph with custom data mappers.

This function allows you to control how GraphML attributes are converted to your node and edge data types. Use deserialize for simple cases where node/edge data are strings.

Time Complexity: O(V + E)

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
type Person = { Name: string; Age: int }

let nodeFolder (data: Map<string, string>) =
    { Name = Map.tryFind "name" data |> Option.defaultValue ""
      Age = Map.tryFind "age" data |> Option.map int |> Option.defaultValue 0 }

let edgeFolder (data: Map<string, string>) =
    Map.tryFind "type" data |> Option.defaultValue ""

let xml = File.ReadAllText("people.graphml")
let graph : Graph<Person, string> = GraphML.deserializeWith nodeFolder edgeFolder xml
type Person = { Name: string Age: int }
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val nodeFolder: data: Map<string,string> -> Person
val data: Map<string,string>
Multiple items
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
val tryFind: key: 'Key -> table: Map<'Key,'T> -> 'T option (requires comparison)
module Option from Microsoft.FSharp.Core
val defaultValue: value: 'T -> option: 'T option -> 'T
val map: mapping: ('T -> 'U) -> option: 'T option -> 'U option
val edgeFolder: data: Map<string,string> -> string
val xml: obj
val graph: obj

nodeFolder : Map<string, string> -> 'n
edgeFolder : Map<string, string> -> 'e
xml : string
Returns: Graph<'n, 'e>

readFile path

Full Usage: readFile path

Parameters:
    path : string

Returns: Graph<Map<string, string>, Map<string, string>>

Reads a graph from a GraphML file.

Example

1: 
2: 
3: 
4: 
5: 
let graph : Graph<Map<string, string>, Map<string, string>> = GraphML.readFile "graph.graphml"

// Access node data
for (id, data) in Map.toSeq graph.Nodes do
    printfn "Node %d: %A" id data
val graph: obj
Multiple items
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
val id: int
val data: obj
val toSeq: table: Map<'Key,'T> -> ('Key * 'T) seq (requires comparison)
val printfn: format: Printf.TextWriterFormat<'T> -> 'T

path : string
Returns: Graph<Map<string, string>, Map<string, string>>

readFileWith nodeFolder edgeFolder path

Full Usage: readFileWith nodeFolder edgeFolder path

Parameters:
    nodeFolder : Map<string, string> -> 'n
    edgeFolder : Map<string, string> -> 'e
    path : string

Returns: Graph<'n, 'e>

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

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
type Person = { Name: string; Age: int }

let nodeFolder (data: Map<string, string>) =
    { Name = Map.tryFind "name" data |> Option.defaultValue ""
      Age = Map.tryFind "age" data |> Option.map int |> Option.defaultValue 0 }

let edgeFolder (data: Map<string, string>) =
    Map.tryFind "weight" data |> Option.map int |> Option.defaultValue 0

let graph : Graph<Person, int> = GraphML.readFileWith nodeFolder edgeFolder "people.graphml"
type Person = { Name: string Age: int }
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val nodeFolder: data: Map<string,string> -> Person
val data: Map<string,string>
Multiple items
module Map from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...

--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
val tryFind: key: 'Key -> table: Map<'Key,'T> -> 'T option (requires comparison)
module Option from Microsoft.FSharp.Core
val defaultValue: value: 'T -> option: 'T option -> 'T
val map: mapping: ('T -> 'U) -> option: 'T option -> 'U option
val edgeFolder: data: Map<string,string> -> int
val graph: obj

nodeFolder : Map<string, string> -> 'n
edgeFolder : Map<string, string> -> 'e
path : string
Returns: Graph<'n, 'e>

serialize graph

Full Usage: serialize graph

Parameters:
    graph : Graph<string, string>

Returns: string

Serializes a graph to a GraphML string.

This is a simplified version of serializeWith for graphs where node data and edge data are already strings.

Time Complexity: O(V + E)

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
let graph =
    empty Directed
    |> addNode 1 "Alice"
    |> addNode 2 "Bob"
    |> addEdge 1 2 "5"

let xml = GraphML.serialize graph
// <?xml version="1.0" encoding="utf-8"?>
// <graphml xmlns="http://graphml.graphdrawing.org/xmlns">
//   <key id="label" for="node" attr.name="label" attr.type="string" />
//   <key id="weight" for="edge" attr.name="weight" attr.type="string" />
//   <graph id="G" edgedefault="directed">
//     <node id="1"><data key="label">Alice</data></node>
//     <node id="2"><data key="label">Bob</data></node>
//     <edge source="1" target="2"><data key="weight">5</data></edge>
//   </graph>
// </graphml>
val graph: obj
val xml: obj

graph : Graph<string, string>
Returns: string

serializeWith nodeAttr edgeAttr graph

Full Usage: serializeWith nodeAttr edgeAttr graph

Parameters:
    nodeAttr : 'n -> (string * string) list
    edgeAttr : 'e -> (string * string) list
    graph : Graph<'n, 'e>

Returns: string

Renders a graph to a GraphML string with custom attribute mappers.

This function allows you to control how node and edge data are converted to GraphML attributes. Use serialize for simple cases where node/edge data are strings.

Time Complexity: O(V + E)

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
type Person = { Name: string; Age: int }
type Connection = { Weight: int; Type: string }

let graph =
    empty Directed
    |> addNode 1 { Name = "Alice"; Age = 30 }
    |> addNode 2 { Name = "Bob"; Age = 25 }
    |> addEdge 1 2 { Weight = 5; Type = "friend" }

let nodeAttrs p = ["name", p.Name; "age", string p.Age]
let edgeAttrs c = ["weight", string c.Weight; "type", c.Type]

let xml = GraphML.serializeWith nodeAttrs edgeAttrs graph

Use Cases

  • Exporting graphs with complex data types
  • Interoperability with tools like Gephi, yEd, Cytoscape
  • Preserving node and edge attributes in XML format
type Person = { Name: string Age: int }
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
type Connection = { Weight: int Type: string }
val graph: obj
val nodeAttrs: p: Person -> (string * string) list
val p: Person
Person.Name: string
Person.Age: int
val edgeAttrs: c: Connection -> (string * string) list
val c: Connection
Connection.Weight: int
Connection.Type: string
val xml: obj

nodeAttr : 'n -> (string * string) list
edgeAttr : 'e -> (string * string) list
graph : Graph<'n, 'e>
Returns: string

writeFile path graph

Full Usage: writeFile path graph

Parameters:
    path : string
    graph : Graph<string, string>

Writes a graph to a GraphML file.

Example

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let graph =
    empty Directed
    |> addNode 1 "Start"
    |> addNode 2 "End"
    |> addEdge 1 2 "connection"

GraphML.writeFile "mygraph.graphml" graph
val graph: obj

path : string
graph : Graph<string, string>

writeFileWith nodeAttr edgeAttr path graph

Full Usage: writeFileWith nodeAttr edgeAttr path graph

Parameters:
    nodeAttr : 'n -> (string * string) list
    edgeAttr : 'e -> (string * string) list
    path : string
    graph : Graph<'n, 'e>

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

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
type Person = { Name: string; Age: int }

let graph =
    empty Directed
    |> addNode 1 { Name = "Alice"; Age = 30 }
    |> addEdge 1 2 "friend"

GraphML.writeFileWith
    (fun p -> ["name", p.Name; "age", string p.Age])
    (fun e -> ["type", e])
    "people.graphml"
    graph
type Person = { Name: string Age: int }
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val graph: obj

nodeAttr : 'n -> (string * string) list
edgeAttr : 'e -> (string * string) list
path : string
graph : Graph<'n, 'e>