Skip to content

Instantly share code, notes, and snippets.

@MyklClason
Last active December 20, 2023 05:00
Show Gist options
  • Save MyklClason/fe603a6005a1dedc6ec65fda7ff47f68 to your computer and use it in GitHub Desktop.
Save MyklClason/fe603a6005a1dedc6ec65fda7ff47f68 to your computer and use it in GitHub Desktop.
Basic graph utility functions class (Ruby)
# This is a very simple hash based graph utility class.
# By Mykl Clason
# https://gist.github.com/MyklClason/fe603a6005a1dedc6ec65fda7ff47f68
class Graph
def self.undirected_graph_from_edges(edges)
# Edges are (a,b) pairs with a => b and b => a relationships.
edges.each_with_object(Hash.new { |h, k| h[k] = Set.new }) { |(k, v), h| h[k] << v }
end
def self.directed_graph_from_edges(edges)
edges.each_with_object(Hash.new { |h, k| h[k] = Set.new }) { |(k, v), h| h[k] << v; h[v] << k }
end
def self.invert(graph)
# Reverses direction of graph
graph.each_with_object({}) { |(k, vs), h| Array(vs).each { |v| (h[v] ||= []) << k } }
end
def self.diff(graph, subgraph)
# Generates a new graph that is graph - subgraph
graph_a.each_with_object({}) { |(k, vs), h| h[k] = vs - (graph_b[k] || Set.new) }
end
def self.diff!(graph, subgraph)
# Removes subgraph from graph
graph_a.transform_values { |vs| vs - (graph_b[vs] || Set.new) }
end
def self.intersect(primary_graph, secondary_graph)
# Generates a new graph that is primary_graph | secondary_graph
graph_a.each_with_object({}) { |(k, vs), h| h[k] = vs & (graph_b[k] || Set.new) }
end
def self.intersect!(primary_graph, secondary_graph)
# Inersects primary_graph with secondary_graph, transforming the primary graph.
graph_a.transform_values { |vs| vs & (graph_b[vs] || Set.new) }
end
def self.union(primary_graph, secondary_graph)
# Generates a new graph that is primary_graph & secondary_graph
graph_a.each_with_object({}) { |(k, vs), h| h[k] = vs | (graph_b[k] || Set.new) }
end
def self.union!(primary_graph, secondary_graph)
# Unions primary_graph with secondary_graph, transforming the primary graph.
graph_a.transform_values { |vs| vs | (graph_b[vs] || Set.new) }
end
def self.adjacency_counter_hash(graph)
# Generates a hash of the counts of the adjacencies.
graph_a.each_with_object({}) { |(k, vs), h| h[k] = (hash_counter[size] || 0) + 1 }
end
def self.adjacency_size_map(graph)
graph_a.each_with_object({}) { |(k, vs), h| h[k] = (graph_b[vs] || Set.new).size }
end
def self.adjacency_counts(graph)
graph.values.map(&:size)
end
def self.size(graph)
graph_vertex_sizes(graph).sum
end
def self.vertex_subset(graph, vertex_set)
# Creates a subset of the graph that contains only the vertex set
graph.each_with_object({}) do |(k, vs), h|
next unless vertex_set.include?(k)
h[k] = vs.select { |v| vertex_set.include?(v) }
end
end
end
@MyklClason
Copy link
Author

No credit required for this. I use this in several projects and feel free to use it in yours. Pretty basic and standard graph utility functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment