【问题标题】:Networkx: Randomly Traverse directed graphNetworkx:随机遍历有向图
【发布时间】:2018-11-20 23:13:11
【问题描述】:

我有一个带加权边的有向图。每个节点都连接到其他每个节点,权重表示从节点 X 移动到节点 Y 的可能性(每个节点的权重之和 out = 1 - 这是一个随机矩阵)。

我需要创建一个函数,随机遍历图,每个节点只进出一次,返回起点

我不想返回最有可能的输出,只是第一次随机遍历树,它只命中每个节点一次并返回它所走的路径,以及它所走的每次跳跃的可能性。

这是我正在寻找的一个简单实现:

import pandas as pd
import numpy as np
from numpy.random import choice
import networkx as nx

testData = [('A','B',.5),('A','C',.4),('A','D',.1),('B','A',.5),('B','C',.3),('B','D',.2),('C','A',.3),('C','B',.1), 
            ('C','D',.6),('D','A',.35),('D','B',.15),('D','C',.5)]

G = nx.DiGraph()
G.add_weighted_edges_from(testData)

#traverse g from randomly selected starting node to every other node randomly and back to random start node
def randomWalk(g):
    start_node = choice(G.nodes())

    #dfs implementation available?

    return pathTaken

print (randomWalk(G))
>>> [('C','A',.3),('A':'D',.1),('D':'B',.15),('B':'C',.3)]

我找不到将随机游走组件合并到任何可用遍历算法的方法。

对我可以使用的可用实现有什么想法吗?如果可以避免的话,我宁愿不编写自定义 DFS...

谢谢!

【问题讨论】:

    标签: python graph networkx


    【解决方案1】:

    我不知道你是否会认为这是一个可用的实现,但是这个:

    random.sample(G.nodes(), len(G.nodes()))
    

    由于图是强连接的,将为您的问题返回一个随机且有效的路径。

    然后你需要处理结果以获得一个元组列表:

    def random_walk(G):
        path = random.sample(G.nodes(), len(G.nodes()))
        return [(path[i-1], node, G[path[i-1]][node]['weight']) for i, node in enumerate(path)]
    

    在你的例子中:

    print(random_walk(G))
    >>> [('B', 'C', 0.3), ('C', 'D', 0.6), ('D', 'A', 0.35), ('A', 'B', 0.5)]
    

    【讨论】:

    • 谢谢 - 这似乎不是基于可能性的加权 - 它只是返回它们。如果我要蒙特卡罗你的场景,连接两个节点的可能性不取决于权重(我不认为......)
    • 你说得对,我以为你不想使用权重,我被I don't want to return the most likely output, just the first random walk through the tree that hits each node only once and returns the path it took弄糊涂了
    • 我确实想使用权重,但我不想返回“最可能的路径”。基本上,如果我要运行蒙特卡罗场景,我观察到的平均结果应该是“最可能的路径”,但在任何单独的试验中都不需要。
    【解决方案2】:

    我最终做的是在使用节点时删除它们,然后将最后一个节点分配给第一个节点。在每一步,我都会重新加权以获得 100% 的可能性。我敢肯定这不是超级有效,但我的图表很小,所以没关系。然后我合并了每个项目最后发生的可能性。

    matchedPath = []
    
    currNode = choice(G.nodes())
    firstNode = currNode
    
    while G.number_of_nodes() >1:
        connectNodes = [x[1] for x in G.out_edges(currNode,data = True)]
        connectWeights = [x[2]['weight'] for x in G.out_edges(currNode,data = True)]
        remainingWeights = [z/sum(connectWeights) for z in connectWeights]
    
        nextNode = choice(connectNodes, 1, p=remainingWeights)[0]
        matchedPath.append((currNode,nextNode))
    
        G.remove_node(currNode)
        currNode = nextNode
    matchedPath.append((currNode,firstNode))    
    
    matched_df = pd.DataFrame(matchedPath,columns = ['from','to'])
    matched_df = pd.merge(matched_df,rawData,how = 'outer',left_on =['from'],right_on = ['Name']).drop(['Name'],axis = 1)
    matched_df = pd.merge(matched_df,link_df,how = 'left',left_on = ['from','to'],right_on = ['person_x','person_y']).drop(['person_x','person_y'],axis = 1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-30
      • 1970-01-01
      相关资源
      最近更新 更多