是否可以通过路径中包含的属性在 networkx 中获得唯一路径?
Is it possible to get unique paths in networkx with attribute included in the path?
我有下图,我希望能够发现从 'ip' 到 'name' 的所有方法,网络中的下图表明我可以从 'ip' 到 'name' 如果我遵循这条路径 [['ip', 'address', 'name']]
问题是我还定义了 address
到 name
可以从两个不同的边缘开始,一个具有属性through=isptool
和另一个通过属性 through=phyonebook
是否可以让 networkx 将这两个路径列为单独的路径,并在路径中包含 through 属性?像
ip -sometool-> address -isptool-> name
ip -sometool-> address -phonebook-> name
import networkx as nx
g = nx.DiGraph()
g.add_node('email')
g.add_node('ip')
g.add_node('address')
g.add_node('name')
g.add_edges_from([('address', 'name')], through='isptool')
g.add_edges_from([('address', 'name')], through='phonebook')
g.add_edge('email', 'address')
g.add_edge('ip', 'address', through='sometool')
list(nx.all_simple_paths(g, 'ip', 'name'))
>>>[['ip', 'address', 'name']] # should have 2 paths one using isptool and one using phonebook edge
list(nx.all_simple_paths(g, 'email', 'name'))
>>>[['email', 'address', 'name']] # same here, should have 2 paths
问题是您正在尝试使用 DiGraph
,它只能处理从一个节点到另一个节点的一条有向边。如果我们切换到使用 MultiDiGraph
、nx.all_simple_paths()
returns 预期结果:
>>> import networkx as nx
g = nx.MultiDiGraph()
g.add_nodes_from(['email', 'ip', 'address', 'name'])
g.add_edges_from([('address', 'name')], through='isptool')
g.add_edges_from([('address', 'name')], through='phonebook')
g.add_edge('email', 'address')
g.add_edge('ip', 'address', through='sometool')
>>> list(nx.all_simple_paths(g, 'ip', 'name'))
[['ip', 'address', 'name'], ['ip', 'address', 'name']]
>>> list(nx.all_simple_paths(g, 'email', 'name'))
[['email', 'address', 'name'], ['email', 'address', 'name']]
但是,虽然我们现在得到了两条路径,但是我们看不到边的属性。我们可以使用 nx.all_simple_edge_paths()
代替:
>>> list(nx.all_simple_edge_paths(g, 'email', 'name'))
[[('email', 'address', 0), ('address', 'name', 0)],
[('email', 'address', 0), ('address', 'name', 1)]]
并且通过一些 f-string 魔法,我们可以使用边缘数据来产生您想要的输出:
>>> for path in nx.all_simple_edge_paths(g, 'email', 'name'):
a, b, e = path[0]
print(f'{a} -{g[a][b][e].get("through", "sometool")}-> {b}', end='')
for a, b, e in path[1:]:
print(f' -{g[a][b][e].get("through", "sometool")}-> {b}', end='')
print('\n')
email -sometool-> address -isptool-> name
email -sometool-> address -phonebook-> name
我有下图,我希望能够发现从 'ip' 到 'name' 的所有方法,网络中的下图表明我可以从 'ip' 到 'name' 如果我遵循这条路径 [['ip', 'address', 'name']]
问题是我还定义了 address
到 name
可以从两个不同的边缘开始,一个具有属性through=isptool
和另一个通过属性 through=phyonebook
是否可以让 networkx 将这两个路径列为单独的路径,并在路径中包含 through 属性?像
ip -sometool-> address -isptool-> name
ip -sometool-> address -phonebook-> name
import networkx as nx
g = nx.DiGraph()
g.add_node('email')
g.add_node('ip')
g.add_node('address')
g.add_node('name')
g.add_edges_from([('address', 'name')], through='isptool')
g.add_edges_from([('address', 'name')], through='phonebook')
g.add_edge('email', 'address')
g.add_edge('ip', 'address', through='sometool')
list(nx.all_simple_paths(g, 'ip', 'name'))
>>>[['ip', 'address', 'name']] # should have 2 paths one using isptool and one using phonebook edge
list(nx.all_simple_paths(g, 'email', 'name'))
>>>[['email', 'address', 'name']] # same here, should have 2 paths
问题是您正在尝试使用 DiGraph
,它只能处理从一个节点到另一个节点的一条有向边。如果我们切换到使用 MultiDiGraph
、nx.all_simple_paths()
returns 预期结果:
>>> import networkx as nx
g = nx.MultiDiGraph()
g.add_nodes_from(['email', 'ip', 'address', 'name'])
g.add_edges_from([('address', 'name')], through='isptool')
g.add_edges_from([('address', 'name')], through='phonebook')
g.add_edge('email', 'address')
g.add_edge('ip', 'address', through='sometool')
>>> list(nx.all_simple_paths(g, 'ip', 'name'))
[['ip', 'address', 'name'], ['ip', 'address', 'name']]
>>> list(nx.all_simple_paths(g, 'email', 'name'))
[['email', 'address', 'name'], ['email', 'address', 'name']]
但是,虽然我们现在得到了两条路径,但是我们看不到边的属性。我们可以使用 nx.all_simple_edge_paths()
代替:
>>> list(nx.all_simple_edge_paths(g, 'email', 'name'))
[[('email', 'address', 0), ('address', 'name', 0)],
[('email', 'address', 0), ('address', 'name', 1)]]
并且通过一些 f-string 魔法,我们可以使用边缘数据来产生您想要的输出:
>>> for path in nx.all_simple_edge_paths(g, 'email', 'name'):
a, b, e = path[0]
print(f'{a} -{g[a][b][e].get("through", "sometool")}-> {b}', end='')
for a, b, e in path[1:]:
print(f' -{g[a][b][e].get("through", "sometool")}-> {b}', end='')
print('\n')
email -sometool-> address -isptool-> name
email -sometool-> address -phonebook-> name