Zog.ResourceGraph (Zog v0.4.0)
View SourceNative graph resource backed by Zog (Zig) via Zigler.
Unlike the Copy-In/Copy-Out pattern, ResourceGraph keeps the Zig
ArrayGraph or GraphMap alive as a NIF resource between calls. Build once,
run many algorithms, destroy when done.
Backends
Zog supports two native graph backends, selectable via the :backend option:
:soa(default) - Structure of Arrays (ArrayGraph).- Structure: Stores nodes and edges in flat, contiguous memory slices.
- Performance: Provides maximum execution speed and optimal cache locality.
- Use Case: Recommended for read-heavy, build-once-run-many query workloads where the topology does not change between NIF calls.
:hash_graph- Hash Map Graph (GraphMap).- Structure: Stores nodes and edges using standard hash tables with buckets and dynamic resizing.
- Performance: Incurs significant overhead due to pointer-heavy hashing, collision resolution, and lack of cache locality.
- Use Case: Use only if your workload relies on dynamic graph mutation (adding or deleting nodes/edges natively) between algorithm executions.
Examples
Create a resource graph using the high-performance :soa backend:
graph = Zog.directed() |> Zog.add_edge("A", "B", 1.0)
res = Zog.ResourceGraph.new(graph, backend: :soa)
# compute centralities...
Zog.ResourceGraph.destroy(res)Create a resource graph using the :hash_graph backend:
res = Zog.ResourceGraph.read_edgelist("edges.txt", backend: :hash_graph)
# compute centralities...
Zog.ResourceGraph.destroy(res)
Summary
Functions
Returns true if the directed ResourceGraph contains no directed cycles.
Alpha centrality.
Analyzes an undirected ResourceGraph natively to find all bridges and articulation points.
Computes the Approximate Neighborhood Function (ANF) and effective diameter.
Returns {:ok, %{neighborhood_sizes: [float()], effective_diameter: float()}} or {:error, any()}.
Checks if the native resource graph is an arborescence.
Finds the root label of an arborescence in the native resource graph, or nil.
Degree assortativity.
Computes the shortest path and its weight between two nodes using A* algorithm directly on the native graph resource.
Average clustering coefficient.
Returns the average path length of a ResourceGraph.
Computes the shortest path and its weight between two nodes using Bellman-Ford algorithm directly on the native graph resource.
Weighted betweenness centrality.
Unweighted betweenness centrality.
Checks whether a ResourceGraph is bipartite (2-colourable) natively.
Returns the bipartite partition of a ResourceGraph as two MapSets of
node labels, or {:error, :not_bipartite} if the graph is not 2-colourable.
Computes maximum cardinality matching on general (non-bipartite) graphs using Edmonds' Blossom algorithm.
Checks if the native resource graph is a branching.
Closeness centrality.
Checks if the native resource graph is complete.
Contracts two nodes in a ResourceGraph into a single node.
Calculates all core numbers for all nodes in the ResourceGraph.
Returns true if the directed ResourceGraph contains at least one directed
cycle.
Explicitly destroys a native graph resource, freeing its memory.
Returns the diameter of a ResourceGraph.
Computes the shortest path and its weight between two nodes using Dijkstra's algorithm directly on the native graph resource.
Returns a map from node label to eccentricity for a ResourceGraph.
Returns the ego graph of center from a ResourceGraph.
Eigenvector centrality.
Finds an Eulerian circuit in the native graph.
Finds an Eulerian path in the native graph.
Finds node mapping dict %{g1_label => g2_label} if isomorphic, or nil.
Floyd-Warshall all-pairs shortest paths.
Checks if the native resource graph is a forest.
Builds a native graph resource directly from a Graph (from libgraph).
Builds a native graph resource directly from a Yog.Graph.
Computes the global minimum cut of the undirected network using the Stoer-Wagner algorithm.
Harmonic centrality.
Checks if the native graph contains an Eulerian circuit.
Checks if the native graph contains an Eulerian path.
Calculates the Weisfeiler-Lehman structural graph hash for a ResourceGraph.
Computes all health metrics at once on a ResourceGraph.
Calculates HITS hub and authority scores for a ResourceGraph.
Calculates weighted bipartite matching using the O(V³) Hungarian (Kuhn-Munkres) algorithm.
Checks if two native resource graphs are isomorphic using exact VF2 matching.
Johnson's Algorithm for all-pairs shortest paths.
Katz centrality.
Label Propagation community detection.
Leiden community detection.
Leiden hierarchical community detection.
Local clustering coefficient for each node.
Louvain community detection.
Computes the maximum flow and minimum cut natively on a ResourceGraph.
Computes a maximum bipartite matching on a ResourceGraph using the
Hopcroft-Karp algorithm.
Computes modularity for a given community partition.
Builds a native graph resource from a SoA.
Graph density.
Returns a list of node degrees directly corresponding to internal u32 node IDs.
PageRank centrality.
Returns the radius of a ResourceGraph.
Checks if a target node is reachable from a start node using BFS traversal directly on the native graph resource.
Reads a graph from an adjacency list file directly in native memory.
Reads a graph from an edge list file directly in native memory.
Reads a graph from a Trivial Graph Format (TGF) file directly in native memory.
Checks if the native resource graph is k-regular.
Finds strongly connected components in the ResourceGraph natively. Returns a list of lists of node labels.
Extracts an induced subgraph from a ResourceGraph containing only the
specified node labels and the edges between them.
Converts a native graph resource back to a Graph (from libgraph).
Converts a native graph resource back to a Yog.Graph.
Computes a topological ordering of the directed ResourceGraph.
Computes the transitive closure of a ResourceGraph.
Computes the transitive reduction of a ResourceGraph.
Checks if the native resource graph is a tree.
Triangle count.
Walktrap community detection.
Hierarchical Walktrap community detection.
Finds weakly connected components in the ResourceGraph natively. Returns a list of lists of node labels.
Computes the k shortest loopless paths and their weights between two nodes using Yen's algorithm directly on the native graph resource.
Types
Functions
Returns true if the directed ResourceGraph contains no directed cycles.
@spec alpha_centrality( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Alpha centrality.
Options
:alpha- Attenuation factor (defaults to0.5).:initial- Initial values (defaults to1.0).:max_iterations- Maximum iteration steps (defaults to100).:tolerance- Convergence tolerance (defaults to0.0001).:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec analyze( t(), keyword() ) :: %{ bridges: [{Zog.SoA.label(), Zog.SoA.label()}], articulation_points: [Zog.SoA.label()] }
Analyzes an undirected ResourceGraph natively to find all bridges and articulation points.
@spec anf( t(), keyword() ) :: {:ok, %{neighborhood_sizes: [float()], effective_diameter: float()}} | {:error, any()}
Computes the Approximate Neighborhood Function (ANF) and effective diameter.
Returns {:ok, %{neighborhood_sizes: [float()], effective_diameter: float()}} or {:error, any()}.
Options
:max_steps- Maximum number of steps to traverse (defaults to30).:m- Number of registers (trials) per node (defaults to64).
Checks if the native resource graph is an arborescence.
Finds the root label of an arborescence in the native resource graph, or nil.
Degree assortativity.
@spec astar( t(), Zog.SoA.label(), Zog.SoA.label(), map() | list(), map() | list(), atom(), keyword() ) :: {:ok, {[Zog.SoA.label()], float()}} | {:error, :no_path}
Computes the shortest path and its weight between two nodes using A* algorithm directly on the native graph resource.
Average clustering coefficient.
Returns the average path length of a ResourceGraph.
@spec bellman_ford(t(), Zog.SoA.label(), Zog.SoA.label(), keyword()) :: {:ok, {[Zog.SoA.label()], float()}} | {:error, :no_path} | {:error, :negative_cycle}
Computes the shortest path and its weight between two nodes using Bellman-Ford algorithm directly on the native graph resource.
@spec betweenness_f64( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Weighted betweenness centrality.
Options
:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec betweenness_unweighted( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Unweighted betweenness centrality.
Options
:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
Checks whether a ResourceGraph is bipartite (2-colourable) natively.
Returns true when the graph is bipartite, false otherwise.
@spec bipartite_partition( t(), keyword() ) :: {:ok, MapSet.t(Zog.SoA.label()), MapSet.t(Zog.SoA.label())} | {:error, :not_bipartite}
Returns the bipartite partition of a ResourceGraph as two MapSets of
node labels, or {:error, :not_bipartite} if the graph is not 2-colourable.
Returns {:ok, set_a, set_b}.
@spec blossom_maximum_matching( t(), keyword() ) :: %{required(Zog.SoA.label()) => Zog.SoA.label()}
Computes maximum cardinality matching on general (non-bipartite) graphs using Edmonds' Blossom algorithm.
Returns matching map %{u => v, v => u}.
Checks if the native resource graph is a branching.
@spec closeness_f64( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Closeness centrality.
Options
:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
Checks if the native resource graph is complete.
@spec contract(t(), Zog.SoA.label(), Zog.SoA.label(), keyword()) :: t()
Contracts two nodes in a ResourceGraph into a single node.
See Zog.Transform.contract/4 for options.
@spec core_numbers( t(), keyword() ) :: %{required(Zog.SoA.label()) => integer()} | [integer()]
Calculates all core numbers for all nodes in the ResourceGraph.
Options
:raw- If true, returns a list of core numbers directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
Returns true if the directed ResourceGraph contains at least one directed
cycle.
@spec destroy(t()) :: :ok
Explicitly destroys a native graph resource, freeing its memory.
Returns the diameter of a ResourceGraph.
@spec dijkstra(t(), Zog.SoA.label(), Zog.SoA.label(), keyword()) :: {:ok, {[Zog.SoA.label()], float()}} | {:error, :no_path}
Computes the shortest path and its weight between two nodes using Dijkstra's algorithm directly on the native graph resource.
@spec eccentricity( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Returns a map from node label to eccentricity for a ResourceGraph.
@spec edge_count(t()) :: non_neg_integer()
@spec ego_graph(t(), Zog.SoA.label(), keyword()) :: t()
Returns the ego graph of center from a ResourceGraph.
The returned ResourceGraph contains the center node, all nodes within
:radius hops (default 1), and all edges between those nodes. Edges are
treated as undirected when expanding the neighbourhood.
Options
:radius- number of hops to include (default 1)
@spec eigenvector( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Eigenvector centrality.
Options
:max_iterations- Maximum iteration steps (defaults to100).:tolerance- Convergence tolerance (defaults to0.0001).:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec eulerian_circuit( t(), keyword() ) :: {:ok, [Zog.SoA.label()]} | {:error, :no_eulerian_circuit}
Finds an Eulerian circuit in the native graph.
@spec eulerian_path( t(), keyword() ) :: {:ok, [Zog.SoA.label()]} | {:error, :no_eulerian_path}
Finds an Eulerian path in the native graph.
Finds node mapping dict %{g1_label => g2_label} if isomorphic, or nil.
Floyd-Warshall all-pairs shortest paths.
Checks if the native resource graph is a forest.
Builds a native graph resource directly from a Graph (from libgraph).
Builds a native graph resource directly from a Yog.Graph.
@spec global_min_cut( t(), keyword() ) :: %{ cut_value: float(), source_side: [Zog.SoA.label()], sink_side: [Zog.SoA.label()] }
Computes the global minimum cut of the undirected network using the Stoer-Wagner algorithm.
@spec harmonic_centrality_f64( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Harmonic centrality.
Options
:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
Checks if the native graph contains an Eulerian circuit.
Checks if the native graph contains an Eulerian path.
Calculates the Weisfeiler-Lehman structural graph hash for a ResourceGraph.
Returns a 32-character hexadecimal MD5 hash string.
@spec health_metrics( t(), keyword() ) :: %{ eccentricity: %{required(Zog.SoA.label()) => float()} | [float()], diameter: float(), radius: float(), average_path_length: float() }
Computes all health metrics at once on a ResourceGraph.
Returns a map with :eccentricity, :diameter, :radius, and
:average_path_length. The :eccentricity value is a map from node
labels to eccentricity values.
Options
:raw- If true, returns eccentricity as a list directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec hits( t(), keyword() ) :: %{ hubs: %{required(Zog.SoA.label()) => float()}, authorities: %{required(Zog.SoA.label()) => float()} }
Calculates HITS hub and authority scores for a ResourceGraph.
Returns %{hubs: %{label => score}, authorities: %{label => score}}.
Options
:max_iterations- Maximum power iterations (default: 100).:tolerance- Convergence threshold for L2 norm (default: 1.0e-6).
@spec hungarian( t(), keyword() ) :: {float(), %{required(Zog.SoA.label()) => Zog.SoA.label()}}
Calculates weighted bipartite matching using the O(V³) Hungarian (Kuhn-Munkres) algorithm.
Returns {cost, matching} where matching is a map of {u => v, v => u}.
Raises ArgumentError if the graph is not bipartite.
Options
:optimization-:min(default) or:max.
Checks if two native resource graphs are isomorphic using exact VF2 matching.
Johnson's Algorithm for all-pairs shortest paths.
Alias for yen_k_shortest/5.
@spec katz( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Katz centrality.
Options
:alpha- Attenuation factor (defaults to0.1).:beta- Weight parameter (defaults to1.0).:max_iterations- Maximum iteration steps (defaults to100).:tolerance- Convergence tolerance (defaults to0.0001).:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec kruskal( t(), keyword() ) :: {:ok, [Yog.MST.edge()]}
@spec label_propagation( t(), keyword() ) :: %{required(Zog.SoA.label()) => non_neg_integer()} | [non_neg_integer()]
Label Propagation community detection.
Options
:max_iterations- Maximum iteration steps (defaults to100).:seed- Random seed (defaults to0).:raw- If true, returns a list of community IDs directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec label_propagation( reference(), 0..18_446_744_073_709_551_615, 0..18_446_744_073_709_551_615 ) :: [ 0..18_446_744_073_709_551_615 ]
@spec leiden( t(), keyword() ) :: %{required(Zog.SoA.label()) => non_neg_integer()} | [non_neg_integer()]
Leiden community detection.
Options
:min_modularity_gain- Minimum modularity gain to stop iterations (defaults to0.000001).:max_iterations- Maximum iteration steps (defaults to100).:seed- Random seed for execution (defaults to42).:theta- Resolution parameter theta (defaults to1.0).:raw- If true, returns a list of community IDs directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec leiden_hierarchical( t(), keyword() ) :: Zog.Community.Dendrogram.t() | [[non_neg_integer()]]
Leiden hierarchical community detection.
Options
:min_modularity_gain- Minimum modularity gain to stop iterations (defaults to0.000001).:max_iterations- Maximum iteration steps (defaults to100).:seed- Random seed for execution (defaults to42).:theta- Resolution parameter theta (defaults to1.0).:raw- If true, returns a raw list of lists of community assignments for each level instead of aDendrogramstruct.
@spec local_clustering_coefficient( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
Local clustering coefficient for each node.
Options
:raw- If true, returns a list of coefficients directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec louvain( t(), keyword() ) :: %{required(Zog.SoA.label()) => non_neg_integer()} | [non_neg_integer()]
Louvain community detection.
Options
:min_modularity_gain- Minimum modularity gain to stop iterations (defaults to0.000001).:max_iterations- Maximum iteration steps (defaults to100).:seed- Random seed for execution (defaults to42).:raw- If true, returns a list of community IDs directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
@spec max_flow(t(), Zog.SoA.label(), Zog.SoA.label(), atom() | keyword(), keyword()) :: %{ max_flow: float(), residual_graph: Zog.SoA.t(), source_side: [Zog.SoA.label()], sink_side: [Zog.SoA.label()] }
Computes the maximum flow and minimum cut natively on a ResourceGraph.
@spec maximum_bipartite_matching( t(), keyword() ) :: {:ok, [{Zog.SoA.label(), Zog.SoA.label()}]} | {:error, :not_bipartite}
Computes a maximum bipartite matching on a ResourceGraph using the
Hopcroft-Karp algorithm.
Returns {:ok, pairs} where pairs is a list of {left_label, right_label}
tuples. Returns {:error, :not_bipartite} if the graph is not bipartite.
@spec modularity(t(), %{required(Zog.SoA.label()) => non_neg_integer()}) :: float()
Computes modularity for a given community partition.
Builds a native graph resource from a SoA.
Options
:backend- Choose the native graph backend, either:soaor:hash_graph(defaults to:soa).
@spec nif_core_numbers(reference()) :: [0..4_294_967_295]
@spec nif_destroy(reference()) :: :ok
@spec nif_edge_count(reference()) :: 0..18_446_744_073_709_551_615
@spec nif_node_count(reference()) :: 0..18_446_744_073_709_551_615
@spec nif_node_degrees(reference()) :: [0..4_294_967_295]
@spec nif_strongly_connected_components(reference()) :: [0..4_294_967_295]
@spec nif_triangle_count(reference()) :: 0..18_446_744_073_709_551_615
@spec nif_walktrap_hierarchical(reference(), 0..18_446_744_073_709_551_615) :: [ [0..18_446_744_073_709_551_615] ]
@spec nif_weakly_connected_components(reference()) :: [0..4_294_967_295]
@spec node_count(t()) :: non_neg_integer()
Graph density.
Returns a list of node degrees directly corresponding to internal u32 node IDs.
@spec pagerank( t(), keyword() ) :: %{required(Zog.SoA.label()) => float()} | [float()]
PageRank centrality.
Options
:damping- PageRank damping factor (defaults to0.85).:max_iterations- Maximum iteration steps (defaults to100).:tolerance- Convergence tolerance (defaults to0.0001).:raw- If true, returns a list of scores directly corresponding to internalu32node IDs instead of mapping to Elixir labels.
Returns the radius of a ResourceGraph.
@spec reachable?(t(), Zog.SoA.label(), Zog.SoA.label(), keyword()) :: boolean()
Checks if a target node is reachable from a start node using BFS traversal directly on the native graph resource.
Reads a graph from an adjacency list file directly in native memory.
Options
:directed- Boolean flag representing if the graph is directed (defaults totrue).:backend- Choose the native graph backend, either:soaor:hash_graph(defaults to:soa).:integer_labels- If true, parses labels as integers directly in Zig, bypassing string hash-map lookups (defaults tofalse). Note that sparse ID spaces will result in placeholder nodes being created up tomax_id, meaningnode_countwill returnmax_id + 1rather than the count of unique active nodes.
Reads a graph from an edge list file directly in native memory.
Options
:directed- Boolean flag representing if the graph is directed (defaults totrue).:backend- Choose the native graph backend, either:soaor:hash_graph(defaults to:soa).:integer_labels- If true, parses labels as integers directly in Zig, bypassing string hash-map lookups (defaults tofalse). Note that sparse ID spaces will result in placeholder nodes being created up tomax_id, meaningnode_countwill returnmax_id + 1rather than the count of unique active nodes.
Reads a graph from a Trivial Graph Format (TGF) file directly in native memory.
Options
:directed- Boolean flag representing if the graph is directed (defaults totrue).:backend- Choose the native graph backend, either:soaor:hash_graph(defaults to:soa).:integer_labels- If true, parses labels as integers directly in Zig, bypassing string hash-map lookups (defaults tofalse). Note that sparse ID spaces will result in placeholder nodes being created up tomax_id, meaningnode_countwill returnmax_id + 1rather than the count of unique active nodes.
Checks if the native resource graph is k-regular.
Finds strongly connected components in the ResourceGraph natively. Returns a list of lists of node labels.
Options
:raw- If true, returns a list of component IDs directly corresponding to internalu32node IDs instead of grouping and mapping to Elixir labels.
@spec subgraph(t(), [Zog.SoA.label()] | MapSet.t(Zog.SoA.label()), keyword()) :: t()
Extracts an induced subgraph from a ResourceGraph containing only the
specified node labels and the edges between them.
Returns a new ResourceGraph holding both the native Zig resource and the
corresponding Elixir SoA metadata. Call ResourceGraph.destroy/1 on the
returned graph when it is no longer needed to release native memory.
Converts a native graph resource back to a Graph (from libgraph).
Converts a native graph resource back to a Yog.Graph.
@spec topological_sort( t(), keyword() ) :: {:ok, [Zog.SoA.label()]} | {:ok, [non_neg_integer()]} | {:error, :cycle}
Computes a topological ordering of the directed ResourceGraph.
Returns {:ok, [labels]} for a DAG, or {:error, :cycle} if the graph
contains a directed cycle.
Options
:raw- If true, returns a list of internalu32node IDs instead of mapping to Elixir labels.
Computes the transitive closure of a ResourceGraph.
Returns a new directed ResourceGraph with an edge (u, v) for every node
v reachable from u in the original graph, including self-loops.
Raises ArgumentError if the input graph is undirected.
Computes the transitive reduction of a ResourceGraph.
Returns a new directed ResourceGraph containing the minimal set of edges
that preserves the same reachability as the original DAG.
Raises ArgumentError if the graph is undirected or contains cycles.
Checks if the native resource graph is a tree.
@spec triangle_count(t()) :: non_neg_integer()
Triangle count.
Walktrap community detection.
Options
:walk_length- Length of random walks (default: 4):target_communities- Target number of communities (default: nil):raw- If true, returns a Result with node indices instead of labels.
Hierarchical Walktrap community detection.
@spec weakly_connected_components( t(), keyword() ) :: [[Zog.SoA.label()]] | [non_neg_integer()]
Finds weakly connected components in the ResourceGraph natively. Returns a list of lists of node labels.
Options
:raw- If true, returns a list of component IDs directly corresponding to internalu32node IDs instead of grouping and mapping to Elixir labels.
@spec yen_k_shortest(t(), Zog.SoA.label(), Zog.SoA.label(), pos_integer(), keyword()) :: {:ok, [{[Zog.SoA.label()], float()}]} | {:error, :no_path}
Computes the k shortest loopless paths and their weights between two nodes using Yen's algorithm directly on the native graph resource.