NetworkX: соединить узлы двух отдельных графов в Python

Этот вопрос касается попытки смоделировать взаимозависимые сети с помощью NetworkX. Существуют специальные пакеты (например, Pymnet), но они не кажутся такими же гибкими, как NetworkX. И, кстати, я хотел дать NetworkX последний шанс.

Итак, допустим, у нас есть 2 отдельных графика, G1 и G2, которые мы строим на одном рисунке:

import networkx as nx
import matplotlib.pyplot as plt

G1=nx.barabasi_albert_graph(3, 2) #n=3, m=2 (number of initial links)
G2=nx.barabasi_albert_graph(3, 2)
pos1=nx.spring_layout(G1)
pos2=nx.spring_layout(G2)
nx.draw_networkx(G1,pos=pos1,node_color='red') #G1 is red
nx.draw_networkx(G2,pos=pos2,node_color='green') #G2 is green

введите здесь описание изображения

Теперь, если мы попытаемся соединить узел 0 G1 с узлом 1 G2:

G1.add_edge(G1.nodes()[0], G2.nodes()[1]) 

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

In[17]: G1.edges()
Out[17]: [(0, 1), (0, 2), (1, 2)]

In[18]: G2.edges()
Out[18]: [(0, 2), (1, 2)]

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

Как вы предлагаете создать это соединение от G1 к G2 в NetworkX, не прибегая к другим пакетам?


person FaCoffee    schedule 15.06.2017    source источник


Ответы (1)


Я думаю, что основная проблема в том, что у вас другая концепция того, как networkx думает о графе, чем то, что это есть на самом деле. Я полагаю, вы думаете, что узлы графа являются объектами некоторого класса node, что сами узлы по своей сути имеют некоторый атрибут, указывающий их положение. Это не тот случай. Специального node класса нет. Граф может иметь любой хешируемый объект в качестве своих узлов, потому что на самом деле граф - это просто причудливый словарь, ключи которого мы называем узлами.

Узлами вашего графа G1 являются целые числа 0, 1 и 2. G2 имеет точно одинаковые узлы. Новое ребро, которое вы добавили, находится между любым целым числом в G1.nodes()[0] и любым целым числом в G2.nodes()[1]. В вашем примере я считаю, что у G1 уже есть это преимущество.

По отдельности вы создали два разных словаря pos1 и pos2 (которые имеют одинаковые ключи - целочисленные значения, образующие узлы двух графов). Эти dicts говорят, где должны быть нанесены узлы. Вы сказали ему строить G1, используя pos1. Таким образом, он помещает круг для узла, который равен 0, в pos1[0] и аналогично для 1 и 2. Затем, когда вы позже скажете ему построить G с использованием pos1, он сделает то же самое.

Что вы, вероятно, захотите сделать, так это создать новый граф, узлы которого состоят из узлов G1 и G2, после переименования, чтобы они не были одинаковыми узлами. Это делается с помощью union (см. документацию.)

G = union(G1, G2, rename=('G1-', 'G2-'))

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

person Joel    schedule 15.06.2017
comment
Но это создает уникальный граф G, вжимающий G1 и G2 в уникальный объект. Так что, по сути, вся идея наличия взаимосвязанной сети из двух или более сетей неосуществима в NetworkX. Я думаю, что в этом пакете есть место для улучшения и добавления функций, позволяющих это сделать. - person FaCoffee; 15.06.2017
comment
В этом пакете много, и он действительно постоянно совершенствуется и добавляет функции (скоро выходит версия 2.0). Но я думаю, что это большой скачок, чтобы перейти от моего ответа к выводу о том, что «вся идея наличия взаимосвязанной сети из двух или более сетей неосуществима в NetworkX». Я дал вам один способ сделать это, который явно не удовлетворяет. Другой вариант - создать новый граф, узлами которого являются графы G1 и G2. [ctd] - person Joel; 15.06.2017
comment
довольно просто создать сеть, состоящую из нескольких взаимосвязанных сетей, но то, как это делается, будет зависеть от ваших требований. В любом случае, это приведет к созданию более крупного объекта, содержащего две сети в некотором формате. Это само по себе не является причиной реструктуризации того, как пакет хранит сети. - person Joel; 15.06.2017
comment
Дело не в том, что ваш ответ меня не удовлетворяет. Это действительно так, и я нахожу это действительно полезным (я проголосовал за него). Бывают ситуации, например, когда вы хотите моделировать взаимозависимые инфраструктуры (определенно более крупные графы, чем G1 и G2), когда вам нужно что-то более простое, особенно потому, что позиции узлов будут представлять физические объекты в реальном мире. - person FaCoffee; 15.06.2017