2015-10-28 2 views
2

Скажите, что у меня есть регулярный граф сетки 2d G, сделанный из NxN=100x100 узлов. Я создаю такую ​​сеть по телефону:Согласованное удаление узлов из grid_2d_graph

N=100 
G=nx.grid_2d_graph(N,N) 
pos = dict((n, n) for n in G.nodes()) #Dictionary of all positions 
labels = dict(((i, j), i + (N-1-j) * N) for i, j in G.nodes()) 
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10) 

и я получаю результат, аналогичный тому, который показан в левой части этой картины:

enter image description here

Теперь, говорят, что моя сеть испытывает разрушительное событие, которое приводит к сбою нескольких узлов (правая часть изображения). Мой график G больше не состоит из того же числа узлов: граф G2 теперь имеет K<NxN узлов. Учитывая этот случай, я хочу, чтобы иметь возможность рисовать G2 по телефону:

G2=G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes 
nx.draw_networkx(G2, pos=pos, labels=labels,with_labels=False, node_size=10) 

Мой вопрос. Как это сделать, чтобы убедиться, что словарь позиций pos не изменен? Это означает: если узел 0 находится в положении (0,0) (вверху слева) в ситуации 1) и он не терпит неудачу, то он должен появиться в том же положении, в ситуации 2). Таким образом, две сети могут быть сопоставимы, поскольку вторая - это просто «преобразование» первого. Спасибо!

ответ

1

Я попытался понять, почему вы задавали этот вопрос - код должен работать в точности так, как вы хотите. Однако у вас есть ошибка, которая может заставлять вас задавать этот вопрос.

G2= G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes 

Это сделает G2 быть None. G.remove_nodes_from(L) удаляет узлы в L от G. Он не создает новый график, который выглядит как G, но без этих узлов. Так что он ничего не возвращает. Из-за этого G2 не получает никакого значения. На графике G удалены эти узлы.

Так должно работать:

N=100 
G=nx.grid_2d_graph(N,N) 
pos = dict((n, n) for n in G.nodes()) #Dictionary of all positions 
labels = dict(((i, j), i + (N-1-j) * N) for i, j in G.nodes()) 
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10) 

#find failed nodes here 

G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes 
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10) 

pos никогда не изменяется в этом коде.

+0

Спасибо @ Джоэл. Просто чтобы убедиться, что у меня всегда есть мой ссылочный граф, как я могу убедиться, что новый графический чертеж не является измененным 'G', а что-то вроде измененной копии' G'? Возможно, я захочу сослаться на исходный 'G' на более поздних этапах. – FaCoffee

+1

Посмотрите на 'G.copy()'. Если вы еще не знаете, как правило, будьте осторожны с копированием вещей в python. Иногда вы просто даете тому же объекту новое имя, поэтому изменение объекта по имени влияет на оба: 'a = [1]', 'b = a',' b.append (2) 'делает' a 'становиться' [1,2] '. В этом случае я считаю, что 'G.copy' будет делать то, что вы хотите, но могут быть проблемы, если, например, у края есть список связанных с ним значений, и вы редактируете некоторые из этих значений. Он может изменить этот атрибут для обоих графиков. Вы хотите прочитать больше об этом. – Joel

+0

После того, как я изменил строку на 'nx.draw_networkx (G, pos = pos, labels = labels, with_labels = False, node_size = 10)', она выдает ошибку: 'AttributeError: объект NoneType 'не имеет атрибутов' node ' '. Не могу понять, о чем идет речь. Я попытаюсь выполнить ответ ниже, чтобы узнать, избавлюсь ли я от этого. – FaCoffee

1

Вы можете сделать это, перебирая узлы из (i, j) в числа, которые вы видите на рисунках из словаря. Затем удалите неудавшиеся узлы. Наконец, отрегулируйте словарь pos для сопоставления позиций с новыми метками узлов, просто изменив словарный словарь. Вот то, что я добавил после кода:

nx.relabel_nodes(G,labels,False) 
G.remove_nodes_from([0,4,12,18])    
pos = {y:x for x,y in labels.iteritems()} 
nx.draw_networkx(G, pos=pos, with_labels=True, node_size = 300) 

для п = 5 и не узлы [0,4,12,18], вот результаты, которые я получил до (слева) и после (справа) не удаляются узлы. enter image description here

+0

Спасибо! Мне нравится визуализация. Но так как разрывающие события имеют разную степень серьезности раз за разом, мне нужна согласованная модель, которая подсказывает мне, если узел '0' потерпел неудачу после события * i *. Если бы я изменил 'pos' dict, я бы потерял эту последовательность. Единственное, что меняется в этой модели, - это загрузка (серьезность события) и поведение каждого узла, но не их позиции или маркировка. – FaCoffee

+0

К сожалению, я только что обнаружил ошибку в моем коде для построения сети после сбоя. Я хотел бы обсудить это в чате, если вы иногда доступны! – FaCoffee

+0

Я бы не прочь, но я не могу найти тебя в чате, ты исчезаешь. попробуйте закладок последнего чата, в котором мы были. Я уже отправил вам сообщение там: http://chat.stackoverflow.com/rooms/95121/discussion-between-abdallah-sobehy-and-francesco-castellani –

1

Я бы немного ответил на вопрос @AbdallahSobehy. Однако для более общей повторной обработки графиков networkx я бы предложил хранить информацию о позиции и метке внутри структуры графика, а не в отдельных контейнерах.

Начиная с уменьшенной версии вашего графика (для N = 5):

N = 5 
G = nx.grid_2d_graph(N,N) 
pos = dict((n, n) for n in G.nodes()) 
labels = dict(((i, j), i + (N-1-j) * N) for i, j in G.nodes()) 

можно хранить pos и label словарей в качестве атрибутов графа:

nx.set_node_attributes(G, 'pos', pos) 
nx.set_node_attributes(G, 'labels', labels) 

и использовать их для ploting:

nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'), 
       labels=nx.get_node_attributes(G, 'labels'), 
       with_labels=True, node_size=500) 

enter image description here

Вы можете позже perfom любой операции на графике, например, удаление некоторых узлов:

G.remove_nodes_from([(0,0),(0,2),(2,2),(2,1)]) 

И Replot график фактически не нуждаясь пересчитывать pos или label словарей, так как записи автоматически обновляются с графа. Следующая строка точно так же, как вызов участка выше:

nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),  
       labels=nx.get_node_attributes(G, 'labels'), 
       with_labels=True, node_size=500) 

Но на этот раз, дает другое изображение:

enter image description here

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

+0

Ваш намек сказочный! Но мне было интересно: есть ли что-то похожее на это, если я хочу также назначить данный атрибут краям? Например, скажем, что у меня есть распределение длины краев другой сети и хотелось бы создать сеть с теми же позициями, что и решетка, но с ее ребрами, исходящими из определенного распределения. Реализуемое? – FaCoffee

+0

КПП, я пробовал ваш подход и получил некоторые проблемы. У меня есть строка, которая говорит 'G = nx.relabel_nodes (G, метки, False)'. Поэтому, когда я вызываю 'nx.draw_networkx (G, pos = nx.get_node_attributes (G, 'pos'), метки = nx.get_node_attributes (G, 'labels'), with_labels = False, node_size = 10)', он бросает out: 'AttributeError: объект NoneType не имеет атрибута 'node''. Это потому, что линия «relabel» противоречит друг другу? – FaCoffee

+1

@FrancescoCastellani Отвечая на первый вопрос: networkx также имеет [set/get_edge_attributes] (https://networkx.github.io/documentation/latest/reference/functions.html#attributes). Кроме того, вы можете установить атрибут определенного края вручную как «g [node1] [node2] ['attribute'] = value' с' g' в качестве вашего графика. Во втором вопросе 'relabel_nodes' является * inplace *, поэтому он возвращает' None' и вы переопределяете 'G' с помощью' None': замените эту строку на 'nx.relabel_nodes (G, label, False)' (без присвоения возвращаемого значения 'G'). –

Смежные вопросы