为什么 GraphView 会省略第 0 个顶点?

Why does a GraphView omit the 0th vertex?

我正在使用根据 installation guide.

安装在它自己的 conda 环境中的最新版本 graph_tool

我最近 运行 对此库的一些令人费解的行为感到困惑。当我运行以下代码时:

import graph_tool

graph = graph_tool.Graph(directed=False)
graph.add_vertex(10)
subgraph = graph_tool.GraphView(graph, graph.get_vertices())

print(graph.get_vertices())
print(subgraph.get_vertices())

输出为:

[0 1 2 3 4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]

我认为 GraphView 应该像在指定顶点上诱导的子图一样工作(所以在我的示例代码的情况下,整个顶点集)。那么为什么 GraphView 会省略第 0 个顶点?

或者,如果这实际上是 graph_tool 中的错误,如果我想使用包含第 0 个顶点的子图,有什么好的解决方法?

所以我找到了解决方法。来自 GraphView 的文档:

The argument g must be an instance of a Graph class. If specified, vfilt and efilt select which vertices and edges are filtered, respectively. These parameters can either be a boolean-valued PropertyMap or a ndarray, which specify which vertices/edges are selected, or an unary function that returns True if a given vertex/edge is to be selected, or False otherwise.

因此顶点掩码也可以由一元函数指定,该函数说明顶点是否是子图的一部分:

def get_subgraph(graph, vertices):
    f = lambda x: x in vertices
    return graph_tool.GraphView(graph, f)

而且,不知何故,这个版本确实有效!

subgraph = get_subgraph(graph, graph.get_vertices())
print(graph.get_vertices())
print(subgraph.get_vertices())

输出:

[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]

所以实际上 不可能 制作一个包含 0 作为顶点的 GraphView,如果你尝试用 numpy 数组来做它显然是行不通的。

这个答案对我有用,但如果有人有更好的解决方法(特别是因为这个方法使 return 大图的子图慢得多),或者如果有人知道为什么首先会出现这种奇怪的行为。

编辑:

这个实现利用 numpy 来计算顶点掩码而不是原生的 python "in" 操作,因此对于更大的图来说要快得多:

def get_subgraph(graph, vertices):
    property_map = graph.new_vertex_property("bool")
    property_map.a = np.isin(graph.get_vertices(), vertices)
    return graph_tool.GraphView(graph, property_map)

您在回答中发布了文档,但您似乎没有足够仔细地阅读它(强调):

The argument g must be an instance of a Graph class. If specified, vfilt and efilt select which vertices and edges are filtered, respectively. These parameters can either be a boolean-valued PropertyMap or a ndarray, which specify which vertices/edges are selected, or an unary function that returns True if a given vertex/edge is to be selected, or False otherwise.

如果传递 属性 地图或数组,它必须是 布尔值 ,而不是顶点列表。这意味着它必须具有 [True, False, False, True, ... ] 的形式,其中 True 表示保留相应的顶点,否则将被过滤掉。这就是为什么从您的示例中删除索引为 0(即 False)的顶点,并保留所有剩余的顶点。