Transform Module
Graph transformations and mappings - functor operations on graphs.
This module provides operations that transform graphs while preserving their structure. These are useful for adapting graph data types, creating derived graphs, and preparing graphs for specific algorithms.
Available Transformations
Transformation |
Function |
Complexity |
Use Case |
|---|---|---|---|
Transpose |
|
O(1) |
Reverse edge directions |
Map Nodes |
|
O(V) |
Transform node data |
Map Edges |
|
O(E) |
Transform edge weights |
Filter Nodes |
|
O(V) |
Subgraph extraction |
Filter Edges |
|
O(E) |
Remove unwanted edges |
The O(1) Transpose Operation
Due to yog's dual-map representation (storing both outgoing and incoming edges), transposing a graph is a single pointer swap - dramatically faster than O(E) implementations in traditional adjacency list libraries.
Functor Laws
The mapping operations satisfy functor laws:
- Identity: mapNodes g identity = g
- Composition: mapNodes (mapNodes g f) h = mapNodes g (h << f)
Use Cases
- Kosaraju's Algorithm: Requires transposed graph for SCC finding
- Type Conversion: Changing node/edge data types for algorithm requirements
- Subgraph Extraction: Working with portions of large graphs
- Weight Normalization: Preprocessing edge weights
Functions and values
| Function or value |
Description
|
||||
|
Creates the complement of a graph. The complement contains the same nodes but connects all pairs of nodes
that are not connected in the original graph, and removes all edges
that are present. Each new edge gets the supplied Self-loops are never added in the complement. Time Complexity: O(V² + E)
Example
Use Cases
val graph: obj
val comp: obj
|
||||
|
Contracts an edge by merging node Node Self-loops (edges from a node to itself) are removed during contraction. Important for undirected graphs: Since undirected edges are stored bidirectionally, each logical edge is processed twice during contraction, causing weights to be combined twice. For example, if edge weights represent capacities, this effectively doubles them. Consider dividing weights by 2 or using a custom combine function if this behavior is undesired. Time Complexity: O(deg(a) + deg(b)) - proportional to the combined degree of both nodes.
Example
Combining WeightsWhen both
Use Cases
val graph: obj
val contracted: obj
|
||||
|
Filters edges by a predicate, preserving all nodes. Returns a new graph with the same nodes but only the edges where the
predicate returns Time Complexity: O(E) where E is the number of edges
Example
Use Cases
val graph: obj
val heavy: obj
|
||||
|
Filters nodes by a predicate, automatically pruning connected edges. Returns a new graph containing only nodes whose data satisfies the predicate. All edges connected to removed nodes (both incoming and outgoing) are automatically removed to maintain graph consistency. Time Complexity: O(V + E) where V is nodes and E is edges
Example
Use Cases
val graph: obj
val filtered: obj
|
||||
|
Transforms edge weights using a function, preserving graph structure. This is a functor operation - it applies a function to every edge's weight/data while keeping all nodes and the graph topology unchanged. Time Complexity: O(E) where E is the number of edges Functor Law:
Example
Type ChangesCan change the edge weight type:
val graph: obj
val doubled: obj
Multiple items
val float: value: 'T -> float (requires member op_Explicit) -------------------- type float = System.Double -------------------- type float<'Measure> = float
|
||||
|
Transforms node data using a function, preserving graph structure. This is a functor operation - it applies a function to every node's data while keeping all edges and the graph structure unchanged. Time Complexity: O(V) where V is the number of nodes Functor Law:
Example
Type ChangesCan change the node data type:
val graph: obj
val uppercased: obj
namespace System
[<Struct>]
type Int32 =
member CompareTo: value: int -> int + 1 overload
member Equals: obj: int -> bool + 1 overload
member GetHashCode: unit -> int
member GetTypeCode: unit -> TypeCode
member ToString: unit -> string + 3 overloads
member TryFormat: utf8Destination: Span<byte> * bytesWritten: byref<int> * ?format: ReadOnlySpan<char> * ?provider: IFormatProvider -> bool + 1 overload
static member Abs: value: int -> int
static member BigMul: left: int * right: int -> int64
static member Clamp: value: int * min: int * max: int -> int
static member CopySign: value: int * sign: int -> int
...
<summary>Represents a 32-bit signed integer.</summary> System.Int32.TryParse([<NotNullWhenAttribute (true)>] s: string, result: byref<int>) : bool
System.Int32.TryParse(s: System.ReadOnlySpan<char>, result: byref<int>) : bool System.Int32.TryParse(utf8Text: System.ReadOnlySpan<byte>, result: byref<int>) : bool System.Int32.TryParse([<NotNullWhenAttribute (true)>] s: string, provider: System.IFormatProvider, result: byref<int>) : bool System.Int32.TryParse(s: System.ReadOnlySpan<char>, provider: System.IFormatProvider, result: byref<int>) : bool System.Int32.TryParse(utf8Text: System.ReadOnlySpan<byte>, provider: System.IFormatProvider, result: byref<int>) : bool System.Int32.TryParse([<NotNullWhenAttribute (true)>] s: string, style: System.Globalization.NumberStyles, provider: System.IFormatProvider, result: byref<int>) : bool System.Int32.TryParse(s: System.ReadOnlySpan<char>, style: System.Globalization.NumberStyles, provider: System.IFormatProvider, result: byref<int>) : bool System.Int32.TryParse(utf8Text: System.ReadOnlySpan<byte>, style: System.Globalization.NumberStyles, provider: System.IFormatProvider, result: byref<int>) : bool
|
||||
|
Combines two graphs, with the second graph's data taking precedence on conflicts. Merges nodes, OutEdges, and InEdges from both graphs. When a node exists in
both graphs, the node data from Importantly, edges from different nodes are combined - if The resulting graph uses the Time Complexity: O(V + E) for both graphs combined
Example
Use Cases
val other: obj
val merged: 'a
|
||||
|
Extracts a subgraph containing only the specified nodes and their connecting edges. Returns a new graph with only the nodes whose IDs are in the provided list, along with any edges that connect nodes within this subset. Nodes not in the list are removed, and all edges touching removed nodes are pruned. Time Complexity: O(V + E) where V is nodes and E is edges
Example
Use Cases
Comparison with
|
||||
|
Converts an undirected graph to a directed graph. Since Yog internally stores undirected edges as bidirectional directed edges,
this is essentially free — it just changes the If the graph is already directed, it is returned unchanged. Time Complexity: O(1)
Example
val undirected: obj
val directed: obj
|
||||
|
Converts a directed graph to an undirected graph. For each directed edge A→B, ensures B→A also exists. If both A→B and B→A
already exist with different weights, the If the graph is already undirected, it is returned unchanged. Time Complexity: O(E) where E is the number of edges
Example
val directed: obj
val undirected: obj
val min: e1: 'T -> e2: 'T -> 'T (requires comparison)
|
||||
|
Reverses the direction of every edge in the graph (graph transpose). Due to the dual-map representation (storing both OutEdges and InEdges), this is an O(1) operation - just a pointer swap! This is dramatically faster than most graph libraries where transpose is O(E). Time Complexity: O(1) Property:
Example
Use Cases
val graph: obj
val reversed: obj
|