简体   繁体   English

Networkx:随机遍历有向图

[英]Networkx: Randomly Traverse directed graph

I have a directed graph with weighted edges. 我有一个带加权边的有向图。 Each node is connected to every other node, and the weights represent the likelihood of moving from Node X to Node Y (sum of weights for each node out = 1 - this is a stochastic matrix). 每个节点都与其他每个节点相连,权重表示从节点X迁移到节点Y的可能性(每个节点out的权重之和= 1-这是一个随机矩阵)。

I need to create a function that randomly traverses the graph and goes in and out of each node only once, returning to the starting point 我需要创建一个函数,该函数随机遍历图并仅在每个节点上进出一次,返回到起点

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, and the likelihood of each jump it took. 我不想返回最可能的输出,而只是返回树中的第一次随机遍历,该遍历仅击中每个节点一次并返回其走过的路径,以及每次跳越的可能性。

Here's a simple implementation I'm looking for: 这是我正在寻找的简单实现:

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)]

I can't find a way to incorporate the random walk component to any of the traversal algorithms available. 我找不到将随机游走组件合并到任何可用遍历算法中的方法。

Any thoughts on available implementations I could use? 对我可以使用的可用实现有任何想法吗? I'd prefer to not write a custom DFS if I can avoid it... 如果可以避免,我宁愿不编写自定义DFS ...

Thanks! 谢谢!

I don't know if you will consider this as an available implementation, but this : 我不知道您是否会将其视为可用的实现,但这是:

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

will return a random and valid path for your problem as the graph is strongly connected. 由于图表已紧密相连,因此会为您的问题返回随机有效的路径。

Then you need to process the result to have a list of tuples : 然后,您需要处理结果以获取元组列表:

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)]

In your example : 在您的示例中:

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

What I ended up doing was deleting nodes as I used them, then just assigning the last node to the first node. 我最终要做的是删除使用它们的节点,然后将最后一个节点分配给第一个节点。 At each step, I'd re-weight to get 100% likelihoods. 在每一步中,我都会重新加权以获得100%的可能性。 I'm sure this isn't super efficient, but my graph is small, so it's ok. 我确定这不是超级有效,但是我的图表很小,所以没关系。 I then merged on the likelihood of each item happening at the end. 然后,我合并了每个项目最终发生的可能性。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM