Python Dijkstra k кратчайших путей

Я пытаюсь сделать небольшое приложение маршрутизации общественного транспорта.

мои данные представлены в следующей структуре:

graph = {'A': {'B':3, 'C':5},
     'B': {'C':2, 'D':2},
     'C': {'D':1},
     'D': {'C':3},
     'E': {'F':8},
     'F': {'C':2}}

где:

  1. graph dict ключ является узлом
  2. ключ субдикта-это ребро между 2 узлами
  3. значение subdict-это вес ребра

я использовал алгоритм find_shortest_path, описанный здесь https://www.python.org/doc/essays/graphs/ но это довольно медленно из-за рекурсии и не имеет поддержки Весов.

поэтому я перешел к алгоритму, описанному Давидом Эпштейном здесь http://code.activestate.com/recipes/119466-dijkstras-algorithm-for-shortest-paths/ (а еще лучшую реализацию можно найти там в комментариях с использованием heapq)

он отлично работает, он очень быстрый, но я получаю только лучший маршрут вместо списка всех возможных маршрутов. И там я застрял.

может кто-нибудь помогите мне с этим пожалуйста, или хотя бы дать направление? Я не очень хорош в алгоритмах кратчайших путей графа.

спасибо заранее!

3 ответов


несомненно, что на графике будет огромное количество кратчайших путей. Поэтому трудно сгенерировать весь кратчайший путь за удовлетворительное время-сложность. Но я могу дать вам простой метод, который может получить столько кратчайших путей, сколько вы хотите.

алгоритм

  1. запустите алгоритм Дейкстры из начальной точки и получите список дисс[i] (кратчайшее расстояние между начальной точкой и точкой я). А затем запустите алгоритм Дейкстры из конечной точки и получите disT[i] список (кратчайшее расстояние между конечной точкой и точкой i)
  2. создать новый график: для ребра в исходном графике, если disS[a] + disT[b] + w(a, b) == disS[конечная точка], добавим ребро в новый граф. Очевидно, что новый граф является DAG(направленным ациклическим графом) и имеет приемник(начальную точку) и цель (конечную точку). Любой путь от приемника до цели будет кратчайшим путем в исходном графике.
  3. вы можете запустить DFS на новом графике. Сохранить путь в рекурсия и backtracking, в любое время вы достигаете цели, сохраненный информация-это самый короткий путь. Когда алгоритм заканчивается, все зависит от вас.

Псевдокод:

def find_one_shortest_path(graph, now, target, path_info):
    if now == target:
        print path_info
        return
    for each neighbor_point of graph[now]:
        path_info.append(neighbor_point) 
        find_one_shortest_path(graph, neighbor_point, target, path_info) #recursion
        path_info.pop(-1) #backtracking

def all_shortest_paths(graph, starting_point, ending_point):
    disS = [] # shortest path from S
    disT = [] # shortest path from T
    new_graph = []
    disS = Dijkstra(graph, starting_point)
    disT = Dijkstra(graph, endinng_point)
    for each edge<a, b> in graph:
        if disS[a] + w<a, b> + disT[b] == disS[ending_point]:
            new_graph.add(<a, b>)
    find_one_shortest_path(new_graph, starting_point, ending_point, []) 

Networkx имеет функцию для этого all_shortest_paths.

он возвращает генератор всех кратчайших путей.


Я столкнулся с аналогичной проблемой в анализе транспортной сети. Я использовал отличный модуль python NetworkX. Она имеет функцию для генерации всех простых путей между двумя узлами. Вот ссылка:

http://networkx.lanl.gov/reference/generated/networkx.algorithms.simple_paths.all_simple_paths.html