我是Python的新手,正在使用NetworkX来构建图表。
在我的脚本中,我有三个字典,可能需要互相嵌套:
dict1={'0':1,'1':1,'2':1, ...}
dict2={'0':[1,2,4], ...}
dict3={'1':1, '2':0, '4':1}
为了清楚起见,dict1
告诉我节点是活动的(1)还是失败的(0)[在这种情况下,dict1
的所有节点都是活动的]; dict2
包含连接到dict1
的每个节点的所有节点; dict3
告诉我连接到dict1
的每个节点的所有节点是活动的(1)还是失败的(0)。
我的问题。我希望能够模拟节点之间的交互。这意味着如果节点0
处于活动状态(status=1
),并且有3个节点连接到它,如果所有节点都发生故障(status=0
),则节点0
将失败太。如果只有一个连接的节点仍处于活动状态,则节点0
也仍处于活动状态。
我的尝试。这是我设想的理论流程图,但我不知道如何将其翻译成Python,也不知道这是否是最佳方法:
PS:此流程图将应用于10000个节点的网络,因此重点实际上是速度。嵌套3 for循环可能听起来像(非常)坏主意,所以我将不胜感激。
我为无法将其放入正确的代码而道歉,但我真的很挣扎。非常感谢!
答案 0 :(得分:1)
正如JoshRomRock在评论中所建议的那样,你可以创建一个这样的类:
class Node(object):
def __init__(self, node_id, neighbours, status):
# neighbours could be a list of other Node objects
self.node_id = node_id
self.neighbours = neighbours
self.status = status
def neighbours_status(self):
# this method would return a list of tuples,
# where first tuple elem is node_id and the second is its status
return [(n.node_id, n.status) for n in self.neighbours]
以后在你的代码中使用它:
my_nodes = set() # create set
my_nodes.add(Node(0, [], 1)) # add a node with no neighbours
# add some more nodes here ...
for node in my_nodes:
# do something with node.status, or node.node_id, or node.neighbours_status()
答案 1 :(得分:1)
我认为这可能是一个"X/Y"问题。我不相信你试图实施解决方案的方式是最好的,但我会尝试回答你问过的问题。你可能会问另一个问题,但参数稍宽一些。
这是我认为你所描述的伪代码:
initialize nodes
create some initial set_of_nodes such that all have status active.
for node in set_of_nodes:
if node has no neighbors:
move on
else:
has_active_neighbor = False
for neighbor in neighbors(node):
add neighbor to set_of_nodes
if neighbor's status is active:
has_active_neighbor = True
if has_active_neighbor = False:
node's status becomes inactive.
此代码存在一些潜在问题。您可以在迭代时迭代并更改某些节点的状态,这意味着如果您再次检查它们,某些已经处理的节点将会失败。所以你正在寻找某种级联。您可能希望循环遍历节点,直到不发生更改。而且,在循环播放它时添加到集合中会有点奇怪。这在Python(和一般情况下)中有点禁忌。所以我正在创建一组你正在添加的新节点。因此,根据您尝试研究的系统规则,这可能不是最好的。另外,我不明白你为什么只从一个子集开始而不是你的dict1的整个网络。
这是networkx的实现。我将循环遍历它,直到没有变化发生。
import networkx as nx
# code here to define graph, assign initial statuses, and create node_set
# node attributes can be defined in several ways (one appears below)
changes = True
while changes:
changes = False
added_nodes = set()
for x in node_set:
if G.degree(x)==0 or G.node[x]['status'] == 'failed':
continue #nothing to see here, move on.
else:
has_active_neighbor=False
for neighbor in G.neighbors(x):
added_nodes.add(neighbor) #put it here even if it is already in node_set
if G.node[neighbor]['status'] == 'active':
has_active_neighbor = True
break
if not has_active_neighbor:
changes = True
G.node[x]['status'] = 'failed'
if node_set.difference(added_nodes): #True if any new nodes:
node_set = node_set.union(added_nodes)
changes = True
#everything is done now - here's the dictionary of statuses:
statuses = nx.get_node_attributes(G, 'status')