igraph - 在有向未加权图中找到 N 个集合之间的最短路径
问题描述
我想为以下问题找到一种算法:给定一个有向图 G,其起点为 s 和 N 组节点,我需要找到一条从起始节点开始的路径,然后到达每个集合中的至少一个节点。并非所有节点都在集合中——只有其中一些。没有多于一组的节点。
例如:
- 起点:[n1]
- 第一组:[n5,n6,n8,n9]
- 第二组:[n2,n10]
- 第三组:[n4,n7]
- 第四组:[n3]
- 其他节点:[m1..m7]
显示图形边缘:
在这种情况下,最短路径将是:
- [n1,m3,m4,m5,n3,m6,n2,m7,n9]
- [n1,m1,n7,m5,n3,m6,n2,m7,n9]
这个问题类似于旅行推销员问题(维基百科)的概括,但在这种情况下,图是有方向的且未加权的。此外,我们有一个已知的起点,我们不仅有集合中的节点,而且我们可以多次在同一个节点上行走。
我尝试从一种惰性快速方法开始,使用 Dijkstra 从开始到所有集合中的所有节点搜索最近的节点,然后从计算中删除该集合并继续从该集合中搜索下一个最近的节点观点。
很容易注意到这种方式并没有给出最短路径,但真正的问题是有时它会陷入死胡同,即使有路径也会返回“无路径”。
我可以看到可以使用的一种天真的方法是创建一个函数来计算集合的每个特定排列,并使用类似于此处建议的算法来解决一个接近但更简单的问题。
它将花费 O(|N|! * 2^(所有 N 个集合中所有节点的数量))
添加惰性方式的代码(对不起,混乱)。
from Queue import Queue
from my_utils import RGBtoHex
from igraph import *
from random import choice
class path_info:
def __init__(self, way, length_of_way, satisfied_goal):
self.way = way
self.length_of_way = length_of_way
self.satisfied_goal = satisfied_goal
class graph_actions():
# Goal point has a "start" node and all other goal points are saved in a dictionary
def __init__(self, graph, goal_points):
self.graph = graph
self.goal_points = goal_points
self.best_path = list()
def calculate_best_path(self):
self.best_path = list()
queued_best_path = scatter(self.graph, self.goal_points)
while not queued_best_path.empty():
self.best_path.append(queued_best_path.get())
return self.best_path
def scatter(graph, goal_points):
best_path = Queue()
starting_point = goal_points["start"]
del goal_points["start"]
paths_dict = dict()
return find_best_way(best_path, goal_points, graph, paths_dict, starting_point)
def find_best_way(best_path, goal_points, graph, paths_dict, starting_point):
last = -1
while len(goal_points) > 0:
vertex_color = known_colors[choice(known_colors.keys())]
for vertex in goal_points.keys():
# Find shortest paths from vertex
# Color vertex
graph.vs.find(str(vertex).encode('ascii', 'replace'))["Fill Color"] = RGBtoHex(vertex_color)
# Find shortest path if exist with igraph function
way = graph.get_shortest_paths(starting_point, vertex)
if len(way[0]) != 0:
if (last != -1):
# Taking out the first node that is the end of the last route taken
way[0].pop(0)
paths_dict[vertex] = path_info(way, len(way[0]), goal_points[vertex])
# Find the closest node
stage = min(paths_dict, key=lambda x: paths_dict[x].length_of_way)
# Transfer from list to queue
for step in paths_dict[stage].way[0]:
best_path.put(step)
last = step
# Delete the other nodes with of the same group from the goal list
for key, value in goal_points.items():
if paths_dict.has_key(stage) and value == paths_dict[stage].satisfied_goal:
del goal_points[key]
if key != stage:
del paths_dict[key]
del paths_dict[stage]
# Saving the last node of this route
starting_point = last
graph.save("states_graph_color.graphml", "graphml")
return best_path
有没有比天真的更好的方法?如果没有,我可以使用启发式方法来做到这一点吗?我还想知道 igraph 是否以更干净的方式解决了这个问题。
即使只有天真的方式是可能的,我也不确定如何实现它。
解决方案
推荐阅读
- .htaccess - 将带有 301 的域和子页面重定向到新域
- r - R Studio 对 Run All 没有反应
- string - 从数据框中删除字符串模式(RStudio 中的 Twitter 数据)
- angular - 在没有 npm install 命令的情况下安装 Angular
- c++ - 如何使用 Visual Studio 2017 编译 CEF 库?
- c# - 不同的视图取决于模型属性
- android - 如何解决缺少 R 类的问题?
- sql-server - sql server 配置管理器和服务中缺少 sql 服务
- buffer - Verilog VGA 缓冲区未按预期工作
- javascript - 匹配中的多个条件使用 $or 或 $and