我有一个连接的无向图,有n个节点和根r。我需要找到路径的所有组合,其长度在范围(l)中,用于连接所有节点。
最后,我想找到最佳的路径组合,其中边缘的权重由长度及其在序列中的位置决定。
我已经尝试了一些解决方案,但最终有这么多选项,它变成了计算的噩梦。 在我的例子中,n = 35,所有节点的度数为8到10,路径长度应为7或8。
我正在使用Python 3.5。
在所有情况下,我都从定义所有可能的路径开始。因此,我使用NetworkX软件包的解决方案,如下所示: All paths of length L from node n using python
# Create a random graph that looks like the real one
G = nx.dense_gnm_random_graph(n=35, m=164, seed=0)
# Find all paths from root with length 0 to 8
n = 0
L = 8
no_n_node = G.nodes()
no_n_node.remove(n)
result = []
for paths in (nx.all_simple_paths(G=G, source=n, target=target, cutoff=L) for target in no_n_node):
result+=paths
# Only keep paths of length 7 or 8
res78 = []
for path in result:
if len(path) >= 8:
res78.append(path[1:])
这导致24,383,690个路径,减少到'仅'3,181,622个7或8个点的集合(路径忽略的节点顺序)
这是我陷入困境的地方,因为我现在想要找到所有节点的所有路径,但只有一次。
我的第一个想法是蛮力: - 对于所有唯一路径,从图中删除节点 - 计算剩余图中范围(l)中所有长度的路径 - 等等 但这是太多的计算
我的另一个想法是,独立于它们的连接,找到组合包含所有节点一次的所有可能节点组合(跨越集)。 如何计算生成集,我基于Algorithm to generate (not quite) spanning set in Python
data = G.nodes()
data.remove[0]
from itertools import combinations
def cut(lst, indexes):
last = 0
for i in indexes:
yield tuple(lst[last:i])
last = i
yield tuple(lst[last:])
def generate(lst, n):
for indexes in combinations(tuple(range(1,len(lst))), n - 1):
yield (tuple(cut(lst, indexes)))
这导致2 ^ n的列表。我试图制作一个只有长度为7或8的子集的生成集,但不知道该怎么做。
我猜它仍然计算太重,但我当时想做的是: - 退出生成集,只包含那些只包含也可以在路径中找到的集合的集合 - 对于所有这个子集,从根(旅行商问题)
开始,找到集合中的最短路径修改/添加
我睡了一夜之后想到的另一个方向就是找到所有的生树,只保留那些没有分支的树,只有一定长度的树枝。 剩下的问题:如何找到所有生成树? 我发现How to efficiently generate all possible spanning trees from a graph可能会让我开始。
编辑结束
有没有人有关于如何优化我使用的算法的建议,或者知道我错过了NetworkX中的一个功能但是会让一切变得容易一些?