Encontrar todos los ciclos en un gráfico dirigido

Resuelto user7305 asked hace 15 años • 0 respuestas

¿Cómo puedo encontrar (iterar) TODOS los ciclos en un gráfico dirigido desde/hacia un nodo determinado?

Por ejemplo, quiero algo como esto:

A->B->A
A->B->C->A

pero no: B->C->B

user7305 avatar Feb 13 '09 23:02 user7305
Aceptado

Encontré esta página en mi búsqueda y dado que los ciclos no son lo mismo que los componentes fuertemente conectados, seguí buscando y finalmente encontré un algoritmo eficiente que enumera todos los ciclos (elementales) de un gráfico dirigido. Es de Donald B. Johnson y el artículo se puede encontrar en el siguiente enlace:

http://www.cs.tufts.edu/comp/150GA/homeworks/hw1/Johnson%2075.PDF

Se puede encontrar una implementación de Java en:

http://normalisiert.de/code/java/elementaryCycles.zip

Puede encontrar una demostración de Mathematica del algoritmo de Johnson aquí ; la implementación se puede descargar desde la derecha ( "Descargar código de autor" ).

Nota: En realidad, existen muchos algoritmos para este problema. Algunos de ellos se enumeran en este artículo:

http://dx.doi.org/10.1137/0205007

Según el artículo, el algoritmo de Johnson es el más rápido.

eminsenay avatar May 08 '2010 15:05 eminsenay

La primera búsqueda en profundidad con retroceso debería funcionar aquí. Mantenga una serie de valores booleanos para realizar un seguimiento de si visitó un nodo antes. Si se queda sin nuevos nodos a los que ir (sin llegar a un nodo en el que ya haya estado), simplemente retroceda y pruebe con una rama diferente.

El DFS es fácil de implementar si tiene una lista de adyacencia para representar el gráfico. Por ejemplo adj[A] = {B,C} indica que B y C son hijos de A.

Por ejemplo, el pseudocódigo siguiente. "inicio" es el nodo desde el que comienza.

dfs(adj,node,visited):  
  if (visited[node]):  
    if (node == start):  
      "found a path"  
    return;  
  visited[node]=YES;  
  for child in adj[node]:  
    dfs(adj,child,visited)
  visited[node]=NO;

Llame a la función anterior con el nodo inicial:

visited = {}
dfs(adj,start,visited)
Himadri Choudhury avatar Feb 14 '2009 16:02 Himadri Choudhury

La opción más sencilla que encontré para resolver este problema fue utilizar la biblioteca de Python llamada networkx.

Implementa el algoritmo de Johnson mencionado en la mejor respuesta de esta pregunta, pero su ejecución es bastante sencilla.

En resumen necesitas lo siguiente:

import networkx as nx
import matplotlib.pyplot as plt

# Create Directed Graph
G=nx.DiGraph()

# Add a list of nodes:
G.add_nodes_from(["a","b","c","d","e"])

# Add a list of edges:
G.add_edges_from([("a","b"),("b","c"), ("c","a"), ("b","d"), ("d","e"), ("e","a")])

#Return a list of cycles described as a list o nodes
list(nx.simple_cycles(G))

Respuesta: [['a', 'b', 'd', 'e'], ['a', 'b', 'c']]

ingrese la descripción de la imagen aquí

fernandosjp avatar Nov 27 '2015 11:11 fernandosjp