Лучшая реализация для удаления определенных ребер в Networkx - PullRequest
2 голосов
/ 26 апреля 2019

Я работаю с графиком, в котором ребра могут быть двух типов.Нет ограничений на то, как эти два типа связаны.

В работе, которую я делаю, я беру из этого подграф и хочу удалить только те ребра, которые относятся к одному из двух типов.

Я добавил тип в качестве ребраатрибут и попытался отфильтровать эти ребра, используя понимание списка и удалить, как указано ниже:

In [1]: import networkx as nx

In [2]: G = nx.path_graph(3)

In [3]: nx.set_edge_attributes(G,'B', '_type')

In [4]: G.add_edge(2, 3, _type="A")

In [5]: SG = G.subgraph([1,2,3])

In [6]: to_remove = [(a,b) for a,b,c in SG.edges(data=True) if c['_type']=="A"]

In [6]: to_remove
Out[6]: [(2, 3)]

In [7]: SG.remove_edges_from(to_remove)

In [8]: SG.edges(data=True)
Out[8]: EdgeDataView([(1, 2, {'_type': 'B'})])

Есть ли лучший способ реализовать это либо

  1. без добавления типов какатрибут или
  2. более эффективный способ реализации, чем выше

Ответы [ 2 ]

1 голос
/ 26 апреля 2019

Если вам нужно сделать это несколько раз, вы можете улучшить производительность, создав три графика.

  1. График со всеми ребрами
  2. График с ребрами типа A
  3. Граф с ребрами типа B

Вместо фильтрации вы просто генерируете подграф необходимого графа.Сложность фильтрации, вероятно, примерно такая, как O (| E_subgraph | + | V_subgraph |) по сравнению с фильтрацией, которая требует O (| E |) и удаления O (| E_selected |).

Вы можете сравнитьоба подхода с timeit, если вы хотите быть уверены.

0 голосов
/ 26 апреля 2019

Узлы и ребра Networkx не имеют подтипов или чего-то подобного. Каждая информация, связанная с элементом, записывается в его атрибуты. Так что ответ на первый вопрос - нет. Единственный правильный способ работы с ним - создать атрибут type.

Networkx имеет только [1] несколько [2] функций [3] для «фильтрации» [4] графиков и все они используют итеративную связку узлов / ребер. Таким образом, ваше решение уже не оптимально. Вы можете сделать некоторые микрооптимизации, такие как:

G.remove_edges_from([(x, y) for x, y, t in G.edges.data('type') if t == 1])

или

G.remove_edges_from(filter(lambda x: x[2] == 1, G.edges.data('type')))

но не более того. Вы также можете изменить свой основной график, но я не уверен, что он вам нужен. Ваш код уже довольно хорош.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...