Estoy trabajando en un problema que requiere encontrar todas las rutas entre dos nodos en un gráfico dirigido. El gráfico puede tener ciclos.Encontrar todas las rutas en un gráfico dirigido con ciclos
Observe que este enfoque de implementación particular es un DFS iterativo.
varios enfoques que he considerar son los siguientes -
BFS no parecen tener una forma de gestionar cuidadosamente este tipo de relaciones pathing entre nodos.
No veo un mecanismo fácil para que un algoritmo recursivo DFS pase por la ruta cuando se encuentra el nodo de terminación. (Lo más probable es que se podría hacer, si implemento un tipo de cosa Maybe Monaco).
Creando una rutina GRAPH-PARENT. Eso agregaría una buena cantidad de churn (& bugs) en el código existente.
En abstracto, lo que se necesita es un árbol necesita ser generada, con el nodo de inicio como root, y todas las hojas son los nodos de terminación. Cada camino de hoja a raíz es una ruta legal. Eso es lo que un DFS recursivo trazaría.
Estoy razonablemente seguro de que se puede hacer aquí, pero no veo exactamente cómo hacerlo.
He definido un protocolo para este algoritmo donde se pueden definir GRAPH-EQUAL y GRAPH-NEXT para objetos arbitrarios.
El tipo de nodo de depuración es un SEÑAL DE BÚSQUEDA, y tiene el acceso de datos o SEARCH-NODE-DATA.
(defun all-paths (start end)
(let ((stack (list start))
(mark-list (list start)) ;I've chosen to hold marking information local to all-paths, instead of marking the objects themselves.
(all-path-list '())) ; Not used yet, using debug statements to think about the problem
(do () ;; intializing no variables
;; While Stack still has elements
((not stack))
(let ((item (pop stack)))
;; I'm looking at the item.
(format t "I: ~a~%" (search-node-data item))
(cond ((graph-equal item end)
(format t "*Q: ~a~%" (loop for var in stack collect (search-node-data var)))
;;Unmark the terminal node so we can view it it next time.
(setf mark-list (remove item mark-list))))
(loop for next in (graph-next item)
do
(cond ((not (in next mark-list :test #'graph-equal))
;; mark the node
(push next mark-list)
;;Put it on the stack
(push next stack))))))))
Hm. Es un documento insoportablemente denso. No estoy dispuesto a tratar de usarlo debido a la complejidad de extraer el algoritmo en Lisp, así como el requisito de interconectar el código existente con la representación. –
La versión corta es "usar el algoritmo de Floyd". La esencia del artículo es que el algoritmo de Floyd funciona sobre una estructura matemática muy general, un * -semiring y demuestra el uso de dicho algoritmo sobre varios * cambios. –
Yo diría la versión corta de la siguiente manera. Considere su gráfico como un DFA con el estado inicial de su nodo de inicio y el estado final de su nodo final y otorgue a todos sus bordes etiquetas únicas y use el conjunto de etiquetas como su alfabeto. El lenguaje aceptado por este DFA representa el conjunto de todas las rutas desde su nodo de inicio hasta su nodo final. Si lo desea, puede calcular una expresión regular para este idioma utilizando el algoritmo McNaughton-Yamada. –