es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Implementando el algoritmo de Kosaraju para CFC’s

Estoy tratando de implementar el algoritmo de Kosaraju para encontrar los componentes fuertemente conexos de un grafo dirigido en tiempo lineal. El objetivo es almacenar y mostrar la lista de tamaños de los SCC.

class Graph:
  def __init__(self, edge_list, num_nodes):
    self.graph = edge_list
    self.rev_graph = self.reverse_graph()
    self.num_nodes = num_nodes

    self.traversed_nodes_p1 = []
    self.traversed_nodes_p2 = []

    self.counter = 0
    self.scc_size_list = []

    self.scc_sl()

  def reverse_graph(self):
    r_graph = []
    for e in self.graph:
      tail = e[0]
      head = e[1]
      r_graph.append([head, tail])
    r_graph = sorted(r_graph, key = lambda x: x[0])
    return r_graph

  def dfs_p1(self, starting_node, g, t_nodes): 
    if starting_node not in t_nodes:
      t_nodes.insert(0, starting_node)
    for i in range(len(g)):
      if g[i][0] == starting_node and g[i][1] not in t_nodes:
        self.dfs_p1(g[i][1], g, t_nodes)

  def dfs_loop_p1(self):
    for i in range(1, self.num_nodes + 1):
      self.dfs_p1(i, self.rev_graph, self.traversed_nodes_p1)

  def dfs_p2(self, starting_node, g, t_nodes):
    if starting_node not in t_nodes:
      self.counter += 1
      t_nodes.append(starting_node)
    for i in range(len(g)):
      if g[i][0] == starting_node and g[i][1] not in t_nodes:
        self.dfs_p2(g[i][1], g, t_nodes)

  def dfs_loop_p2(self):
    for i in self.traversed_nodes_p1:
      self.counter = 0
      self.dfs_p2(i, self.graph, self.traversed_nodes_p2)
      if self.counter > 0:
        self.scc_size_list.append(self.counter)

  def scc_sl(self):
    self.dfs_loop_p1()
    self.dfs_loop_p2()

    self.scc_size_list.sort()
    self.scc_size_list.reverse()

Este código produce la salida correcta para grafos más pequeños (por ejemplo, 9 nodos, 15 aristas).

test_edge_list = [[1,2], [1,9], [2,3], [2,8], [3,4], [3,5], [4,5], [6,5], [6,8], [7,6], [7,9], [8,3], [8,7], [9,2], [9,8]]
test = Graph(test_edge_list, 9)
print(test.scc_size_list)

Pero tarda mucho tiempo en funcionar para grafos más grandes. ¿Cómo puedo optimizar esto?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Una optimización potencial es utilizar el algoritmo de búsqueda en profundidad (DFS por sus siglas en inglés) para visitar los nodos de una manera más eficiente. En lugar de comenzar siempre el DFS desde el primer nodo, podemos comenzar desde los nodos que no han sido visitados aún y que no forman parte de ningún componente fuerte. De esta manera, evitamos trabajo innecesario al volver a visitar nodos que ya han sido explorados en iteraciones anteriores del algoritmo.

    Otra optimización es utilizar una estructura de datos más eficiente para representar el grafo. Por ejemplo, utilizar una lista de adyacencia en lugar de una lista de aristas puede reducir la complejidad temporal de verificar los nodos vecinos durante el recorrido DFS.

    Por último, paralelizar el algoritmo en múltiples procesadores o utilizar aceleración GPU también puede acelerar significativamente el tiempo de computación para grafos grandes.

Comments are closed.