A high-performance graph library for Python implemented in Rust, providing fast graph algorithms and data structures for computational tasks
—
Specialized algorithms for ranking, matching, coloring, and advanced graph analytics. These algorithms provide solutions for complex graph problems including node ranking, maximum matching, graph coloring, and other computationally intensive graph analysis tasks.
Algorithms for computing node importance and ranking based on graph structure and link analysis.
def pagerank(graph, alpha: float = 0.85, personalization = None, max_iter: int = 100, tol: float = 1e-6, weight_fn = None, default_weight: float = 1.0):
"""
Compute PageRank centrality using power iteration method.
PageRank computes node importance based on the link structure,
originally developed for ranking web pages. Higher scores indicate
more important nodes in the network.
Parameters:
- graph: Input graph (PyGraph or PyDiGraph)
- alpha (float): Damping parameter, probability of following links (default: 0.85)
- personalization (dict, optional): Personalization vector for personalized PageRank
- max_iter (int): Maximum number of iterations (default: 100)
- tol (float): Error tolerance for convergence (default: 1e-6)
- weight_fn (callable, optional): Function to extract edge weights
- default_weight (float): Default edge weight (default: 1.0)
Returns:
CentralityMapping: Dictionary mapping node indices to PageRank scores
"""
def hits(graph, max_iter: int = 100, tol: float = 1e-8):
"""
Compute HITS (Hyperlink-Induced Topic Search) authority and hub scores.
HITS computes two scores for each node: authority (pointed to by important hubs)
and hub (points to important authorities). Useful for analyzing directed networks
with hierarchical or topic-based structure.
Parameters:
- graph: PyDiGraph input (directed graph required)
- max_iter (int): Maximum number of iterations (default: 100)
- tol (float): Error tolerance for convergence (default: 1e-8)
Returns:
tuple: (hubs_dict, authorities_dict) where each is a CentralityMapping
mapping node indices to hub/authority scores
"""Algorithms for finding maximum and weighted matchings in graphs.
def max_weight_matching(graph, max_cardinality: bool = False, weight_fn = None, default_weight: float = 1.0):
"""
Find maximum weight matching in undirected graph.
A matching is a subset of edges with no common vertices.
Maximum weight matching maximizes the sum of edge weights.
Parameters:
- graph: PyGraph input (undirected graph)
- max_cardinality (bool): Prioritize cardinality over weight if True
- weight_fn (callable, optional): Function to extract edge weights
- default_weight (float): Default edge weight (default: 1.0)
Returns:
set: Set of edges forming maximum weight matching as (node1, node2) tuples
"""
def is_matching(graph, matching) -> bool:
"""
Test if a set of edges forms a valid matching.
A valid matching has no vertices appearing in multiple edges.
Parameters:
- graph: Input graph
- matching: Set or list of edges to test
Returns:
bool: True if edges form a valid matching, False otherwise
"""
def is_maximal_matching(graph, matching) -> bool:
"""
Test if a matching is maximal (cannot be extended).
A maximal matching cannot have any more edges added without
violating the matching property.
Parameters:
- graph: Input graph
- matching: Set or list of edges representing a matching
Returns:
bool: True if matching is maximal, False otherwise
"""Algorithms for vertex and edge coloring problems.
def greedy_color(graph, strategy = None):
"""
Color graph vertices using greedy coloring algorithm.
Assigns colors to vertices such that no adjacent vertices
share the same color, using a greedy approach that may not
find the optimal coloring but runs efficiently.
Parameters:
- graph: Input graph (PyGraph or PyDiGraph)
- strategy (str, optional): Vertex ordering strategy:
- None: Default ordering
- 'largest_first': Order by descending degree
- 'smallest_last': Recursive smallest degree removal
- 'saturation_largest_first': DSatur algorithm
Returns:
dict: Mapping of node indices to color integers (0, 1, 2, ...)
"""
def greedy_edge_color(graph):
"""
Color graph edges using greedy edge coloring.
Assigns colors to edges such that no incident edges
share the same color.
Parameters:
- graph: Input graph
Returns:
dict: Mapping of edge indices to color integers
"""
def bipartite_edge_color(graph, first_nodes):
"""
Color edges of bipartite graph optimally.
For bipartite graphs, edge coloring can be solved optimally
in polynomial time using König's theorem.
Parameters:
- graph: PyGraph input (must be bipartite)
- first_nodes: Set of node indices in first partition
Returns:
dict: Mapping of edge indices to color integers
Note: Graph must be bipartite for correct results
"""
def misra_gries_edge_color(graph):
"""
Color graph edges using Misra-Gries edge coloring algorithm.
Efficient edge coloring algorithm that provides good results
for general graphs.
Parameters:
- graph: Input graph
Returns:
dict: Mapping of edge indices to color integers
"""Advanced algorithms for analyzing cycles in graphs.
def simple_cycles(graph):
"""
Find all simple cycles in directed graph.
A simple cycle is a closed path with no repeated vertices
except the first and last. Uses Johnson's algorithm.
Parameters:
- graph: PyDiGraph input
Returns:
list: List of cycles, each cycle is a list of node indices
Warning: Can return exponentially many cycles for some graphs
"""
def cycle_basis(graph):
"""
Find fundamental cycle basis of undirected graph.
A cycle basis is a minimal set of cycles that can generate
all cycles in the graph through linear combination.
Parameters:
- graph: PyGraph input (undirected)
Returns:
list: List of fundamental cycles, each cycle is a list of node indices
"""Algorithms for finding minimum cuts and analyzing graph flow properties.
def stoer_wagner_min_cut(graph, weight_fn = None, default_weight: float = 1.0):
"""
Find minimum cut using Stoer-Wagner algorithm.
Finds the minimum cut that separates the graph into two components
with minimum total edge weight crossing the cut.
Parameters:
- graph: PyGraph input (undirected)
- weight_fn (callable, optional): Function to extract edge weights
- default_weight (float): Default edge weight (default: 1.0)
Returns:
tuple: (cut_value, cut_nodes) where cut_value is minimum cut weight
and cut_nodes is set of nodes in one partition
"""Algorithms for constructing derived graphs.
def line_graph(graph):
"""
Construct line graph of input graph.
In the line graph, each edge of the original graph becomes a vertex,
and two vertices in the line graph are connected if the corresponding
edges in the original graph share a common vertex.
Parameters:
- graph: Input graph
Returns:
Same type as input: Line graph where edges become vertices
"""import rustworkx as rx
# Create web-like directed graph
web_graph = rx.PyDiGraph()
pages = web_graph.add_nodes_from(['Home', 'About', 'Products', 'Contact', 'Blog'])
# Add links between pages (edges represent hyperlinks)
web_graph.add_edges_from([
(pages[0], pages[1], None), # Home -> About
(pages[0], pages[2], None), # Home -> Products
(pages[1], pages[0], None), # About -> Home
(pages[2], pages[4], None), # Products -> Blog
(pages[4], pages[0], None), # Blog -> Home
(pages[4], pages[2], None), # Blog -> Products
])
# Compute PageRank scores
pagerank_scores = rx.pagerank(web_graph, alpha=0.85)
print("PageRank scores:")
for node_idx, score in pagerank_scores.items():
page_name = web_graph[node_idx]
print(f" {page_name}: {score:.3f}")
# Find most important page
most_important = max(pagerank_scores, key=pagerank_scores.get)
print(f"Most important page: {web_graph[most_important]}")# HITS works best on directed graphs with authority/hub structure
citation_graph = rx.PyDiGraph()
papers = citation_graph.add_nodes_from([
'Survey_Paper_A', 'Research_Paper_B', 'Research_Paper_C',
'Survey_Paper_D', 'Research_Paper_E'
])
# Add citation relationships
citation_graph.add_edges_from([
(papers[0], papers[1], None), # Survey A cites Research B
(papers[0], papers[2], None), # Survey A cites Research C
(papers[3], papers[1], None), # Survey D cites Research B
(papers[3], papers[4], None), # Survey D cites Research E
(papers[1], papers[2], None), # Research B cites Research C
])
# Compute HITS scores
hubs, authorities = rx.hits(citation_graph)
print("Hub scores (good at citing others):")
for node_idx, score in hubs.items():
print(f" {citation_graph[node_idx]}: {score:.3f}")
print("Authority scores (well-cited):")
for node_idx, score in authorities.items():
print(f" {citation_graph[node_idx]}: {score:.3f}")# Create weighted graph representing job assignments
job_graph = rx.PyGraph()
workers = job_graph.add_nodes_from(['Alice', 'Bob', 'Carol'])
jobs = job_graph.add_nodes_from(['Job1', 'Job2', 'Job3'])
# Add edges with weights representing worker-job compatibility scores
job_graph.add_edges_from([
(workers[0], jobs[0], 8), # Alice-Job1: score 8
(workers[0], jobs[1], 6), # Alice-Job2: score 6
(workers[1], jobs[0], 5), # Bob-Job1: score 5
(workers[1], jobs[2], 9), # Bob-Job3: score 9
(workers[2], jobs[1], 7), # Carol-Job2: score 7
(workers[2], jobs[2], 4), # Carol-Job3: score 4
])
# Find maximum weight matching
matching = rx.max_weight_matching(job_graph, weight_fn=lambda x: x)
print("Optimal job assignments:")
for worker_idx, job_idx in matching:
worker_name = job_graph[worker_idx]
job_name = job_graph[job_idx]
edge_weight = job_graph.get_edge_data(worker_idx, job_idx)
print(f" {worker_name} -> {job_name} (score: {edge_weight})")# Create conflict graph for scheduling
conflict_graph = rx.PyGraph()
meetings = conflict_graph.add_nodes_from([
'Team_A_Meeting', 'Team_B_Meeting', 'All_Hands',
'Project_Review', 'Training_Session'
])
# Add edges representing scheduling conflicts
conflict_graph.add_edges_from([
(meetings[0], meetings[2], None), # Team A conflicts with All Hands
(meetings[1], meetings[2], None), # Team B conflicts with All Hands
(meetings[0], meetings[3], None), # Team A conflicts with Project Review
(meetings[3], meetings[4], None), # Project Review conflicts with Training
])
# Find coloring (each color represents a time slot)
coloring = rx.greedy_color(conflict_graph, strategy='largest_first')
print("Meeting schedule (by time slot):")
time_slots = {}
for meeting_idx, color in coloring.items():
meeting_name = conflict_graph[meeting_idx]
slot_name = f"Time_Slot_{color + 1}"
if slot_name not in time_slots:
time_slots[slot_name] = []
time_slots[slot_name].append(meeting_name)
for slot, meetings_list in time_slots.items():
print(f" {slot}: {', '.join(meetings_list)}")# Create directed graph with cycles
process_graph = rx.PyDiGraph()
steps = process_graph.add_nodes_from(['Start', 'Process', 'Check', 'Finish', 'Retry'])
process_graph.add_edges_from([
(steps[0], steps[1], None), # Start -> Process
(steps[1], steps[2], None), # Process -> Check
(steps[2], steps[3], None), # Check -> Finish
(steps[2], steps[4], None), # Check -> Retry
(steps[4], steps[1], None), # Retry -> Process (creates cycle)
])
# Find all simple cycles
cycles = rx.simple_cycles(process_graph)
print("Process cycles found:")
for i, cycle in enumerate(cycles):
cycle_names = [process_graph[node] for node in cycle]
print(f" Cycle {i+1}: {' -> '.join(cycle_names)} -> {cycle_names[0]}")# Create network flow graph
network = rx.PyGraph()
nodes = network.add_nodes_from(['Source', 'Router1', 'Router2', 'Router3', 'Sink'])
# Add edges with capacities
network.add_edges_from([
(nodes[0], nodes[1], 10), # Source-Router1: capacity 10
(nodes[0], nodes[2], 8), # Source-Router2: capacity 8
(nodes[1], nodes[3], 5), # Router1-Router3: capacity 5
(nodes[2], nodes[3], 7), # Router2-Router3: capacity 7
(nodes[1], nodes[4], 6), # Router1-Sink: capacity 6
(nodes[3], nodes[4], 12), # Router3-Sink: capacity 12
])
# Find minimum cut
cut_value, cut_partition = rx.stoer_wagner_min_cut(network, weight_fn=lambda x: x)
print(f"Minimum cut value: {cut_value}")
print("Cut partition:")
partition_names = [network[node] for node in cut_partition]
print(f" Side 1: {partition_names}")
remaining = set(network.node_indices()) - cut_partition
remaining_names = [network[node] for node in remaining]
print(f" Side 2: {remaining_names}")Install with Tessl CLI
npx tessl i tessl/pypi-rustworkx