Source code for synkit.Rule.Modify.longest_path
import networkx as nx
from collections import deque
from typing import Tuple, List, Set
[docs]
class LongestPath:
def __init__(self, G: nx.Graph):
"""Initializes the LongestPath object with a graph.
Parameters:
- G (nx.Graph): The networkx graph.
"""
self.G = G
self.vertices = len(G.nodes)
[docs]
def BFS(self, u: int) -> Tuple[int, int]:
"""Performs a Breadth-First Search (BFS) from a given node `u` to find
the farthest node and its distance.
Parameters:
- u (int): The starting node for the BFS.
Returns:
- Tuple[int, int]: The farthest node from `u` and its distance.
"""
# Initialize visited and distance dictionaries
visited = {i: False for i in self.G.nodes}
distance = {i: -1 for i in self.G.nodes}
# Distance of `u` from itself is 0
distance[u] = 0
queue = deque([u])
visited[u] = True
while queue:
front = queue.popleft()
# Explore neighbors of the current node
for neighbor in self.G.neighbors(front):
if not visited[neighbor]:
visited[neighbor] = True
distance[neighbor] = distance[front] + 1
queue.append(neighbor)
# Find the farthest node and its distance
maxDis = 0
nodeIdx = u # Default to start node if no farther node is found
for node, dist in distance.items():
if dist > maxDis:
maxDis = dist
nodeIdx = node
return nodeIdx, maxDis
[docs]
def LongestPathInDisconnectedGraph(self) -> int:
"""Finds the longest path in a potentially disconnected graph. The
graph can consist of multiple components.
This method performs a BFS on every unvisited component to find the
farthest node and computes the longest path across all components.
Returns:
int: The length of the longest path in the graph across all components.
"""
visited_components: Set[int] = set()
longest_path: int = 0
component_paths: List[Tuple[int, int, int]] = []
# Iterate over all nodes to ensure all components are covered
for node in self.G.nodes:
if node not in visited_components:
# First BFS to find one end point of the longest path in this component
farthest_node, _ = self.BFS(node)
# Second BFS from that node to find the actual longest path
node_2, component_longest_path = self.BFS(farthest_node)
# Track the longest path found
longest_path = max(longest_path, component_longest_path)
component_paths.append((farthest_node, node_2, component_longest_path))
# Mark all nodes in this component as visited
queue = deque([farthest_node])
while queue:
current = queue.popleft()
if current not in visited_components:
visited_components.add(current)
for neighbor in self.G.neighbors(current):
if neighbor not in visited_components:
queue.append(neighbor)
return longest_path