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.

Encontrar todos los caminos entre dos nodos de un grafo que tengan una longitud/peso menor al valor dado.

Estoy tratando de encontrar un método eficiente para obtener todos los posibles caminos entre dos nodos bajo la condición de que el camino no incluya más de un número máximo de nodos. Para simplificar, vamos a suponer el grafo de la imagen de abajo:

Entonces, digamos que estoy interesado en ir de 1 a 5. Con diferentes limitaciones de longitud de ruta (llamado pathlengthlimit), los resultados serían algo como:

findPaths(1,5,pathlengthlimit=3) -> [[1,2,5],[1,4,5]]
findPaths(1,5,pathlengthlimit=4) -> [[1,2,5],[1,4,5],[1,2,3,5]]
findPaths(1,5,pathlengthlimit=5) -> [[1,2,5],[1,4,5],[1,2,3,5],[1,2,3,4,5]

No he encontrado ningún ejemplo de cómo hacer esto de manera eficiente. En el caso real, tengo miles de nodos, por lo que encontrar todos los posibles caminos desde el origen hasta el destino primero y luego almacenar aquellos de longitud más corta que X no es una alternativa, se convierte en algo que consume mucho tiempo.

¿Alguna sugerencia o ejemplo?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para obtener eficientemente todos los posibles caminos entre dos nodos con la condición de que el camino no incluya más de un número máximo de nodos, podemos utilizar un algoritmo de búsqueda en profundidad modificado. La idea básica es explorar todos los caminos posibles desde el nodo origen al nodo destino, mientras se realiza un seguimiento de la longitud del camino actual. Si la longitud del camino actual supera la longitud máxima permitida, retrocedemos y exploramos otros caminos.

    Aquí se muestra una implementación del algoritmo de búsqueda en profundidad modificado en Python:

    def findPaths(graph, source, target, path_length_limit):
        # inicialización
        stack = [(source, [source])]
        paths = []
    
        while stack:
            # sacar el último nodo de la pila
            node, path = stack.pop()
    
            # verificar si hemos llegado al nodo destino
            if node == target:
                paths.append(path)
                continue
    
            # verificar si la longitud del camino actual supera el límite
            if len(path) > path_length_limit:
                continue
    
            # explorar todos los vecinos del nodo actual
            for neighbor in graph[node]:
                if neighbor not in path:
                    stack.append((neighbor, path + [neighbor]))
    
        return paths
    

    Para utilizar esta función en el ejemplo de grafo mostrado en la imagen, podemos definir el grafo como un diccionario de listas:

    graph = {
        1: [2, 4],
        2: [3, 5],
        3: [5],
        4: [5],
        5: []
    }
    

    Y luego llamar a la función findPaths con diferentes valores de path_length_limit:

    >>> findPaths(graph, 1, 5, 3)
    [[1, 2, 5], [1, 4, 5]]
    
    >>> findPaths(graph, 1, 5, 4)
    [[1, 2, 5], [1, 4, 5], [1, 2, 3, 5]]
    
    >>> findPaths(graph, 1, 5, 5)
    [[1, 2, 5], [1, 4, 5], [1, 2, 3, 5], [1, 2, 3, 4, 5]]
    

    Esta implementación tiene una complejidad temporal de O(b^d), donde b es el factor de ramificación (es decir, el número promedio de vecinos por nodo) y d es la profundidad máxima del árbol de búsqueda. Sin embargo, evita explorar caminos que son más largos que la longitud máxima permitida, lo que puede reducir significativamente el número de nodos visitados.

Comments are closed.