Почему GraphView опускает 0-ю вершину? - PullRequest
0 голосов
/ 18 июня 2020

Я использую последнюю версию graph_tool, установленную в его собственной среде conda, согласно руководству по установке .

Недавно я столкнулся с некоторым недоумением при использовании этой библиотеки. Когда я запускаю следующий код:

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-ю вершину ?

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Вы разместили документацию в своем ответе, но, похоже, вы недостаточно внимательно ее прочитали (выделено мной):

Аргумент g должен быть экземпляром класса Graph. Если указано, vfilt и efilt выбирают, какие вершины и ребра фильтруются соответственно. Эти параметры могут быть либо логическим значением PropertyMap, либо ndarray, которые определяют, какие вершины / ребра выбраны, или унарной функцией, которая возвращает True, если данная вершина / ребро должна быть выбрана, или False в противном случае. .

Если вы передаете карту свойств или массив, это должно быть логическое значение , а не список вершин. Это означает, что он должен иметь форму [True, False, False, True, ... ], где True означает, что соответствующая вершина сохраняется, в противном случае она отфильтровывается. Поэтому вершина с индексом 0 (т.е. False) удаляется из вашего примера, а все оставшиеся остаются.

0 голосов
/ 18 июня 2020

Итак, я нашел обходной путь. Из документации GraphView:

Аргумент g должен быть экземпляром класса Graph. Если указано, vfilt и efilt выбирают, какие вершины и ребра фильтруются соответственно. Эти параметры могут быть либо PropertyMap с логическим значением, либо ndarray, которые определяют, какие вершины / ребра выбраны, или унарной функцией, которая возвращает True, если данная вершина / ребро должна быть выбрана, или False в противном случае.

Таким образом, маска вершины также может быть указана с помощью унарной функции, которая сообщает, является ли вершина частью подграфа:

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]

Так что на самом деле невозможно создать GraphView, который включает 0 как вершину, это просто очевидно не работает, если вы попытаетесь сделайте это с массивом numpy.

Этот ответ работает для меня, но мне все равно было бы интересно, есть ли у кого-нибудь лучший обходной путь (тем более, что он намного медленнее возвращает подграф для большого графа ), или если кто-то знает, почему возникает такое странное поведение.

EDIT:

Эта реализация использует 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...