Python - Networkx搜索前任节点 - 超出最大深度

时间:2017-01-23 05:36:22

标签: python algorithm graph networkx

我正在使用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),但在我不知道如何帮助我解决这个问题之后。

我还尝试在节点上放置一些标志,以确定它是否已被激活,但我一直收到同样的错误。

编辑:我忘了,输入节点有一个定义的响应值,因此他们不需要进行计算。

1 个答案:

答案 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这样的算法可能更容易使用。