如何使用networkx删除有向图中的所有相关节点?

发布于 2024-12-25 17:32:01 字数 415 浏览 4 评论 0原文

我不确定我的问题的正确术语是什么,所以我只会解释我想做的事情。我有一个有向图,删除节点后我希望所有独立相关的节点也被删除。

这是一个示例:

在此处输入图像描述

比如说,我删除节点“11”,我希望删除节点“2”同样(在我自己的示例中,它们将是 2 以下的节点,现在也必须删除),因为它不再连接到主图。请注意,不应删除节点“9”或“10”,因为节点“8”和“3”仍然连接到它们。

我正在使用 python 库 networkx。我搜索了文档,但我不确定术语,所以我不确定这叫什么。如果可能的话,我想使用库提供的函数,而不是通过图形创建我自己的递归(因为我的图形很大)。

任何有关如何执行此操作的帮助或建议都会很棒。

谢谢!

I'm not sure exactly sure what the correct terminology is for my question so I'll just explain what I want to do. I have a directed graph and after I delete a node I want all independently related nodes to be removed as well.

Here's an example:

enter image description here

Say, I delete node '11', I want node '2' to be deleted as well(and in my own example, they'll be nodes under 2 that will now have to be deleted as well) because its not connected to the main graph anymore. Note, that node '9' or '10' should not be deleted because node '8' and '3' connect to them still.

I'm using the python library networkx. I searched the documentation but I'm not sure of the terminology so I'm not sure what this is called. If possible, I would want to use a function provided by the library than create my own recursion through the graph(as my graph is quite large).

Any help or suggestions on how to do this would be great.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我是有多爱你 2025-01-01 17:32:01

我假设以下条件成立:

  • 该图是非循环的。您在评论中提到了这一点,但我想明确表示这是一个起始假设。
  • 有一组已知的根节点。我们需要有某种方法来知道哪些节点始终被认为是可达的,并且我假设(以某种方式)该信息是已知的。
  • 初始图不包含任何多余的节点。也就是说,如果初始图包含任何应该删除的节点,那么它们就已经被删除了。这允许算法通过维护每个节点都应该存在的不变量来工作。

如果是这种情况,则给定初始设置,节点位于图中的唯一原因是

  1. 该节点位于根可达节点集中,或者
  2. 该节点具有位于根可达节点集中的父节点。节点。

因此,每当您从图中删除节点时,可能需要删除的唯一节点就是该节点的后代。如果您删除的节点位于根集中,则可能需要修剪大量图形,并且如果您删除的节点是其后代节点很少的后代节点,则您可能需要做的事情很少。

鉴于此设置,一旦删除节点,您将需要扫描该节点的所有子节点,以查看其中是否有任何节点没有其他父节点将它们保留在图中。由于我们假设图中唯一的节点是需要存在的节点,因此如果已删除节点的子节点至少有一个其他父节点,那么它仍然应该在图中。否则,需要删除该节点。因此,执行删除步骤的一种方法是以下递归算法:

  • 对于要删除的节点的每个子节点:
    • 如果该节点只有一个父节点:(它一定是我们要删除的节点)
      • 从图中递归地删除该节点。
  • 从图中删除指定的节点。

不过,这可能不是一个直接实现的好算法,因为如果您有一个大图,所涉及的递归可能会变得相当深。因此,您可能希望使用如下工作列表算法来实现它:

  • 创建一个工作列表 W。
  • 将要删除的节点 v 添加到 W。
  • 当 W 不为空时:
    • 删除 W 中的第一个条目;称之为w。
    • 对于 w 的每个孩子:
      • 如果该子项只有一个父项,请将其添加到 W。
    • 从图表中删除 w。

这最终是最坏情况的 O(m) 时间,其中 m 是图中的边数,因为理论上每条边都必须被扫描。但是,假设您的图表中有一些冗余,它可能会快得多。

希望这有帮助!

I am assuming that the following are true:

  • The graph is acyclic. You mentioned this in your comment, but I'd like to make explicit that this is a starting assumption.
  • There is a known set of root nodes. We need to have some way of knowing what nodes are always considered reachable, and I assume that (somehow) this information is known.
  • The initial graph does not contain any superfluous nodes. That is, if the initial graph contains any nodes that should be deleted, they've already been deleted. This allows the algorithm to work by maintaining the invariant that every node should be there.

If this is the case, then given an initial setup, the only reason that a node is in the graph would be either

  1. The node is in the root reachable set of nodes, or
  2. The node has a parent that is in the root reachable set of nodes.

Consequently, any time you delete a node from the graph, the only nodes that might need to be deleted are that node's descendants. If the node that you remove is in the root set, you may need to prune a lot of the graph, and if the node that you remove is a descendant node with few of its own descendants, then you might need to do very little.

Given this setup, once a node is deleted, you would need to scan all of that node's children to see if any of them have no other parents that would keep them in the graph. Since we assume that the only nodes in the graph are nodes that need to be there, if the child of a deleted node has at least one other parent, then it should still be in the graph. Otherwise, that node needs to be removed. One way to do the deletion step, therefore, would be the following recursive algorithm:

  • For each of children of the node to delete:
    • If that node has exactly one parent: (it must be the node that we're about to delete)
      • Recursively remove that node from the graph.
  • Delete the specified node from the graph.

This is probably not a good algorithm to implement directly, though, since the recursion involved might get pretty deep if you have a large graph. Thus you might want to implement it using a worklist algorithm like this one:

  • Create a worklist W.
  • Add v, the node to delete, to W.
  • While W is not empty:
    • Remove the first entry from W; call it w.
    • For each of w's children:
      • If that child has just one parent, add it to W.
    • Remove w from the graph.

This ends up being worst-case O(m) time, where m is the number of edges in the graph, since in theory every edge would have to be scanned. However, it could be much faster, assuming that your graph has some redundancies in it.

Hope this helps!

錯遇了你 2025-01-01 17:32:01

让我为您提供解决您的任务的 python networkX 代码:

import networkx as nx
import matplotlib.pyplot as plt#for the purpose of drawing the graphs
DG=nx.DiGraph()
DG.add_edges_from([(3,8),(3,10),(5,11),(7,11),(7,8),(11,2),(11,9),(11,10),(8,9)])
DG.remove_node(11)

connected_components 方法令人惊讶地不适用于有向图,因此我们将图转换为无向,找出未连接的节点,然后从有向图中删除它们

UG=DG.to_undirected()
not_connected_nodes=[]
for component in nx.connected_components(UG):
    if len(component)==1:#if it's not connected, there's only one node inside
        not_connected_nodes.append(component[0])
for node in not_connected_nodes:
    DG.remove_node(node)#delete non-connected nodes

如果您愿意要查看结果,请将以下两行添加到脚本中:

nx.draw(DG)
plt.show() 

Let me provide you with the python networkX code that solves your task:

import networkx as nx
import matplotlib.pyplot as plt#for the purpose of drawing the graphs
DG=nx.DiGraph()
DG.add_edges_from([(3,8),(3,10),(5,11),(7,11),(7,8),(11,2),(11,9),(11,10),(8,9)])
DG.remove_node(11)

connected_components method surprisingly doesn't work on the directed graphs, so we turn the graph to undirected, find out not connected nodes and then delete them from the directed graph

UG=DG.to_undirected()
not_connected_nodes=[]
for component in nx.connected_components(UG):
    if len(component)==1:#if it's not connected, there's only one node inside
        not_connected_nodes.append(component[0])
for node in not_connected_nodes:
    DG.remove_node(node)#delete non-connected nodes

If you want to see the result, add to the script the following two lines:

nx.draw(DG)
plt.show() 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文