我正在使用Python中的Networkx(用于图形管理)工作的项目,我一直在努力实现我需要的东西
我有一组有向图,将特殊对象作为节点和权重与边相关联,我需要从输出节点到输入节点遍历图。并且对于每个节点,我必须从其前任节点获取权重,并且由该前任节点计算的操作从我的输出节点构建操作。但问题是前辈的操作可能取决于他们自己的前辈等等,所以我想知道如何解决这个问题。
到目前为止,我已经尝试了下一个,假设我有一个输出节点列表,我可以使用Networkx库的方法浏览前辈:
# graph is the object containig my directe graph
for node in outputNodes:
activate_predecessors(node , graph)
# ...and a function to activate the predecessors ..
def activate_predecessors( node = None , graph ):
ws = [] # a list for the weight
res = [] # a list for the response from the predecessor
for pred in graph.predecessors( node ):
# get the weights
ws.append( graph[pred][node]['weight'] )
activate_predecessors( pred , graph )
res.append( pred.getResp() ) # append the response from my predecessor node to a list, but this response depend on their own predecessors, so i call this function over the current predecessor in a recursive way
# after I have the two lists ( weights and the response the node should calculate a reduce operation
# do after turning those lists into numpy arrays...
node.response = np.sum( ws*res )
这段代码似乎有效...我在一些随机的试验中多次,但在很多情况下它会超出最大递归深度所以我需要更稳定地重写它(并且可能是迭代的)以避免最大递归。但是我已经没有想法来解决这个问题了。
图书馆有一些搜索算法(Depth first search),但在我不知道如何帮助我解决这个问题之后。
我还尝试在节点上放置一些标志,以确定它是否已被激活,但我一直收到同样的错误。
编辑:我忘了,输入节点有一个定义的响应值,因此他们不需要进行计算。
答案 0 :(得分:2)
您的代码可能包含无限递归。例如:
import networkx as nx
G = nx.DiGraph()
G.add_edges_from([(1,2), (2,1)])
def activate_nodes(g, node):
for pred in g.predecessors(node):
activate_nodes(g, pred)
activate_nodes(G, 1)
RuntimeError: maximum recursion depth exceeded
如果您在其中一个图表上有可能的周期,则最好将每个节点标记为已访问,或者更改图表上的边缘以使其没有周期。
假设您的图表上没有循环,这里是迭代实现算法的示例:
import networkx as nx
G = nx.DiGraph()
G.add_nodes_from([1,2,3])
G.add_edges_from([(2, 1), (3, 1), (2, 3)])
G.node[1]['weight'] = 1
G.node[2]['weight'] = 2
G.node[3]['weight'] = 3
def activate_node(g, start_node):
stack = [start_node]
ws = []
while stack:
node = stack.pop()
preds = g.predecessors(node)
stack += preds
print('%s -> %s' % (node, preds))
for pred in preds:
ws.append(g.node[pred]['weight'])
print('weights: %r' % ws)
return sum(ws)
print('total sum %d' % activate_node(G, 1))
此代码打印:
1 -> [2, 3]
3 -> [2]
2 -> []
2 -> []
weights: [2, 3, 2]
total sum 7
您可以使用DiGraph.reverse()
如果您需要使用DFS或其他东西,您可以反转图形以使前一个只是该节点的直接连接邻居。使用它,像DFS这样的算法可能更容易使用。