Yog.FSharp
Getting Started Examples API Reference GitHub

Model Module

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.

Types

Type Description

Graph<'nodeData, 'edgeData>

A simple graph data structure that can be directed or undirected.

  • 'nodeData: The type of data stored at each node
  • 'edgeData: The type of data (usually weight) stored on each edge

GraphType

The type of graph: directed or undirected.

NodeId

Unique identifier for a node in the graph.

Functions and values

Function or value Description

addEdge src dst weight graph

Full Usage: addEdge src dst weight graph

Parameters:
Returns: Graph<'n, 'e>

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.

Note: If src or dst have not been added via addNode, the edge will still be created in the edge dictionaries, but the nodes will be missing from graph.Nodes. This creates "ghost nodes" that are traversable but invisible to functions that iterate over nodes (e.g. order, allNodes). Use addEdgeEnsured to auto-create missing endpoints with a default value.

Example

1: 
2: 
graph
|> addEdge 1 2 10

src : NodeId
dst : NodeId
weight : 'e
graph : Graph<'n, 'e>
Returns: Graph<'n, 'e>

addEdgeEnsured src dst weight defaultData graph

Full Usage: addEdgeEnsured src dst weight defaultData graph

Parameters:
Returns: Graph<'n, 'e>

Like addEdge, but ensures both endpoint nodes exist first.

If src or dst is not already in the graph, it is created with the supplied defaultData before the edge is added. Nodes that already exist are left unchanged.

Example

1: 
2: 
3: 
// Nodes 1 and 2 are created automatically with data "unknown"
empty Directed
|> addEdgeEnsured 1 2 10 "unknown"
1: 
2: 
3: 
4: 
5: 
// Existing nodes keep their data; only missing ones get the default
empty Directed
|> addNode 1 "Alice"
|> addEdgeEnsured 1 2 5 "anon"
// Node 1 is still "Alice", node 2 is "anon"

src : NodeId
dst : NodeId
weight : 'e
defaultData : 'n
graph : Graph<'n, 'e>
Returns: Graph<'n, 'e>

addEdgeWithCombine src dst weight combine graph

Full Usage: addEdgeWithCombine src dst weight combine graph

Parameters:
    src : NodeId
    dst : NodeId
    weight : 'e
    combine : 'e -> 'e -> 'e
    graph : Graph<'n, 'e>

Returns: Graph<'n, 'e>

Adds an edge, but if an edge already exists between src and dst, it combines the new weight with the existing one using combine.

The combine function receives (existingWeight, newWeight) and should return the combined weight.

Time Complexity: O(1)

Example

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let graph =
  empty Directed
  |> addNode 1 "A"
  |> addNode 2 "B"
  |> addEdge 1 2 10
  |> addEdgeWithCombine 1 2 5 (+)
// Edge 1->2 now has weight 15 (10 + 5)

Use Cases

  • Edge contraction in graph algorithms (Stoer-Wagner min-cut)
  • Multi-graph support (adding parallel edges with combined weights)
  • Incremental graph building (accumulating weights from multiple sources)
val graph: obj

src : NodeId
dst : NodeId
weight : 'e
combine : 'e -> 'e -> 'e
graph : Graph<'n, 'e>
Returns: Graph<'n, 'e>

addNode id data graph

Full Usage: addNode id data graph

Parameters:
Returns: Graph<'n, 'e>

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

1: 
2: 
3: 
graph
|> addNode 1 "Node A"
|> addNode 2 "Node B"

id : NodeId
data : 'n
graph : Graph<'n, 'e>
Returns: Graph<'n, 'e>

allNodes graph

Full Usage: allNodes graph

Parameters:
Returns: NodeId list

Returns all node IDs in the graph. This includes all nodes, even isolated nodes with no edges.

graph : Graph<'n, 'e>
Returns: NodeId list

edgeCount graph

Full Usage: edgeCount graph

Parameters:
Returns: int

Returns the number of edges in the graph.

For undirected graphs, each edge is counted once (the pair {u, v}). For directed graphs, each directed edge (u -> v) is counted once.

Time Complexity: O(V)

graph : Graph<'n, 'e>
Returns: int

empty graphType

Full Usage: empty graphType

Parameters:
Returns: Graph<'n, 'e>

Creates a new empty graph of the specified type.

Example

1: 
let graph = Model.empty Directed
val graph: obj

graphType : GraphType
Returns: Graph<'n, 'e>

neighbors id graph

Full Usage: neighbors id graph

Parameters:
Returns: (NodeId * 'e) list

Gets everyone connected to the node, regardless of direction.

For undirected graphs, this is equivalent to successors. For directed graphs, this combines both outgoing and incoming edges without duplicates.

id : NodeId
graph : Graph<'n, 'e>
Returns: (NodeId * 'e) list

nodeCount

Full Usage: nodeCount

Returns: Graph<'a, 'b> -> int

Returns the number of nodes in the graph. Equivalent to order.

Time Complexity: O(1)

Returns: Graph<'a, 'b> -> int

order graph

Full Usage: order graph

Parameters:
Returns: int

Returns the number of nodes in the graph (graph order).

Time Complexity: O(1)

graph : Graph<'n, 'e>
Returns: int

predecessorIds node graph

Full Usage: predecessorIds node graph

Parameters:
Returns: NodeId list

Returns just the NodeIds of predecessors (without edge weights).

node : NodeId
graph : Graph<'n, 'e>
Returns: NodeId list

predecessors id graph

Full Usage: predecessors id graph

Parameters:
Returns: (NodeId * 'e) list

Gets nodes you came FROM (Predecessors).

id : NodeId
graph : Graph<'n, 'e>
Returns: (NodeId * 'e) list

removeEdge src dst graph

Full Usage: removeEdge src dst graph

Parameters:
Returns: Graph<'n, 'e>

Removes an edge from src to dst. For undirected graphs, removes edges in both directions.

Time Complexity: O(1)

Example

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
// Directed graph - removes single directed edge
let graph =
  empty Directed
  |> addNode 1 "A"
  |> addNode 2 "B"
  |> addEdge 1 2 10
  |> removeEdge 1 2
// Edge 1->2 is removed
val graph: obj

src : NodeId
dst : NodeId
graph : Graph<'n, 'e>
Returns: Graph<'n, 'e>

removeNode id graph

Full Usage: removeNode id graph

Parameters:
Returns: Graph<'n, 'e>

Removes a node and all its connected edges (incoming and outgoing).

Time Complexity: O(deg(v)) - proportional to the number of edges connected to the node, not the whole graph.

Example

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
let graph =
  empty Directed
  |> addNode 1 "A"
  |> addNode 2 "B"
  |> addNode 3 "C"
  |> addEdge 1 2 10
  |> addEdge 2 3 20

let graph = removeNode 2 graph
// Node 2 is removed, along with edges 1->2 and 2->3
val graph: obj

id : NodeId
graph : Graph<'n, 'e>
Returns: Graph<'n, 'e>

successorIds id graph

Full Usage: successorIds id graph

Parameters:
Returns: NodeId list

Returns just the NodeIds of successors (without edge weights). Convenient for traversal algorithms that only need the IDs.

id : NodeId
graph : Graph<'n, 'e>
Returns: NodeId list

successors id graph

Full Usage: successors id graph

Parameters:
Returns: (NodeId * 'e) list

Gets nodes you can travel TO (Successors).

id : NodeId
graph : Graph<'n, 'e>
Returns: (NodeId * 'e) list