我有一个带有邻接矩阵形状的图(adj_mat.shape=(40004000)
)。我当前的问题是找到从源(row=0
)到目标(col=trans\u mat.shape[0]-1
)的路径长度列表(节点顺序并不重要)。
我对寻找路径序列不感兴趣;我只对传播路径长度感兴趣。因此,这不同于找到所有简单的路径——这太慢了(即。找到从源到目标的所有路径;然后给每条路径打分)。有没有一种表演方法可以快速做到这一点?
建议将DFS作为一种可能的策略(此处注明)。我当前的实施(如下)根本不是最优的:
# create graph
G = nx.from_numpy_matrix(adj_mat, create_using=nx.DiGraph())
# initialize nodes
for node in G.nodes:
G.nodes[node]['cprob'] = []
# set starting node value
G.nodes[0]['cprob'] = [0]
def propagate_prob(G, node):
# find incoming edges to node
predecessors = list(G.predecessors(node))
curr_node_arr = []
for prev_node in predecessors:
# get incoming edge weight
edge_weight = G.get_edge_data(prev_node, node)['weight']
# get predecessor node value
if len(G.nodes[prev_node]['cprob']) == 0:
G.nodes[prev_node]['cprob'] = propagate_prob(G, prev_node)
prev_node_arr = G.nodes[prev_node]['cprob']
# add incoming edge weight to prev_node arr
curr_node_arr = np.concatenate([curr_node_arr, np.array(edge_weight) + np.array(prev_node_arr)])
# update current node array
G.nodes[node]['cprob'] = curr_node_arr
return G.nodes[node]['cprob']
# calculate all path lengths from source to sink
part_func = propagate_prob(G, 4000)
使用igraph
,我可以在~1秒内计算多达300个节点。我还发现访问相邻矩阵本身(而不是调用igraph
的函数来检索边/顶点)也节省了时间。两个关键的瓶颈是1)以有效的方式追加一个长列表(同时保持内存)2)找到并行化的方法。这个时间指数增长超过~300个节点,我很想看看是否有人有更快的解决方案(同时也适合内存)。
import igraph
# create graph from adjacency matrix
G = igraph.Graph.Adjacency((trans_mat_pad > 0).tolist())
# add edge weights
G.es['weight'] = trans_mat_pad[trans_mat_pad.nonzero()]
# initialize nodes
for node in range(trans_mat_pad.shape[0]):
G.vs[node]['cprob'] = []
# set starting node value
G.vs[0]['cprob'] = [0]
def propagate_prob(G, node, trans_mat_pad):
# find incoming edges to node
predecessors = trans_mat_pad[:, node].nonzero()[0] # G.get_adjlist(mode='IN')[node]
curr_node_arr = []
for prev_node in predecessors:
# get incoming edge weight
edge_weight = trans_mat_pad[prev_node, node] # G.es[prev_node]['weight']
# get predecessor node value
if len(G.vs[prev_node]['cprob']) == 0:
curr_node_arr = np.concatenate([curr_node_arr, np.array(edge_weight) + propagate_prob(G, prev_node, trans_mat_pad)])
else:
curr_node_arr = np.concatenate([curr_node_arr, np.array(edge_weight) + np.array(G.vs[prev_node]['cprob'])])
## NB: If memory constraint, uncomment below
# set max size
# if len(curr_node_arr) > 100:
# curr_node_arr = np.sort(curr_node_arr)[:100]
# update current node array
G.vs[node]['cprob'] = curr_node_arr
return G.vs[node]['cprob']
# calculate path lengths
path_len = propagate_prob(G, trans_mat_pad.shape[0]-1, trans_mat_pad)
我手头没有一个大的例子(例如:。
import networkx as nx
g = nx.DiGraph()
nx.add_path(g, range(7))
g.add_edge(0, 3)
g.add_edge(0, 5)
g.add_edge(1, 4)
g.add_edge(3, 6)
# first step retrieve topological sorting
sorted_nodes = nx.algorithms.topological_sort(g)
start = 0
target = 6
path_lengths = {start: [0]}
for node in sorted_nodes:
if node == target:
print(path_lengths[node])
break
if node not in path_lengths or g.out_degree(node) == 0:
continue
new_path_length = path_lengths[node]
new_path_length = [i + 1 for i in new_path_length]
for successor in g.successors(node):
if successor in path_lengths:
path_lengths[successor].extend(new_path_length)
else:
path_lengths[successor] = new_path_length.copy()
if node != target:
del path_lengths[node]
输出:[2,4,2,4,4,6]
如果您只对不同长度的路径数感兴趣,例如上面的例子中的{2:2,4:3,6:1}
,您甚至可以将列表减少为dicts。
一些解释我在做什么(我希望对更大的例子也有效)。第一步是检索拓扑排序。为什么啊?然后我知道边在哪个“方向”流动,我可以简单地按照这个顺序处理节点,而不会像递归变体中的“丢失任何边”或任何“回溯”。之后,我用包含当前路径长度的列表初始化开始节点([0]
)。这个列表被复制到所有的后继者,同时更新路径长度(所有元素1)。目标是在每次迭代中计算从起始节点到所有处理节点的路径长度,并将其存储在path_lengths。循环在到达目标
-节点后停止。
是否有任何标准算法可以在有向无环图中找到所有可能的路径。如果没有,我如何在BFS / Dijkstra /任何其他算法中进行更改以枚举DAG中的所有路径
我想在有向(无环)图中找到最长的路径。假设我知道起始节点-汇。路径应该从这一点开始。我在想我可以将边的权重设置为-1。有很多方法可以找到所有最短的路径,但你必须通过终点。有没有可能得到最短的路径(无论最终节点如何)? 假设我想为节点 nr 1(汇)找到最长路径。所以这个算法给了我1-2-3-4-5-6。
我试图将这个问题概念化,然后为它编写Java代码。我知道这里有一些讨论,但我没有看到很多回答者,所以我想通过写下我的想法来重申这个问题,我希望从你们那里得到一些反馈。谢谢 我的想法:对于每个叶节点,找到从根节点到它的最长路径。对于所有路径,找到最大路径长度 然而,这不就是蛮力吗,对此还有更优雅的解决方案吗? 我听说过使用Djikstra的负权重算法,但在某些地方它说这只适用于特定情况?我也看到了关
我需要为一组有向无环图找到从节点 0 开始的最长路径。我正在使用维基百科中的最长路径问题算法。我已经让算法适用于大多数图形,但对于其他图形,它没有给出正确的结果。算法为: 图形实现使用邻接列表来存储图形。如果我传递一个图,例如: 我得到的答案5,这是正确的。但是,如果我通过图表: 然后我得到2,而正确答案应该是3。 我使用的TopSort2算法是: DFS 算法包括:
我有一个有向图。我想找到从源到目标的所有可能路径,覆盖所有转换。这与“覆盖所有顶点的所有可能路径”不同。该图将正好有一个起始顶点,并且可能有多个结束顶点。如果没有传出转换,则节点是结束节点。集合中的路径可能具有重复的变换,但不能具有重复的顶点。附有一个示例有向图。顶点a(黑色)是起始顶点,顶点e和f是结束节点(黄色)。此图的解决方案如下所示。 您可以看到最后一条路径有两次b。这是有效的。i、 例如