Random walks in directed graphs/networks
我有一个(实际上)多达50000个顶点的加权图。给定一个顶点,我想根据所有相邻边的相对权重随机选择一个相邻顶点。
我应该如何将此图存储在内存中,以便进行有效的选择?最好的算法是什么?它可以像每个顶点的键值存储一样简单,但这可能不适合最有效的算法。我还需要更新网络。
请注意,我一次只想迈出一步。
更正式地说:给定一个加权、有向和可能完整的图,让w(a,b)是边a->b的权重,让wa->sub>是a的所有边的总和。给定一个输入顶点v,我想随机选择一个顶点,其中选择顶点x的可能性是w(v,x)/wv->sub>
例子:
假设w(v,a)=2,w(v,b)=1,w(v,c)=1。
给定输入v,函数应返回概率为0.5的a和概率为0.25的b或c。
如果您关心生成随机漫游的性能,那么可以使用Alias方法构建一个数据结构,它非常适合您选择随机传出边缘的要求。开销只是您必须为每个定向边分配一个概率权重和一个所谓的别名边。
所以对于每个音符,都有一个输出边的向量,以及权重和别名边。然后您可以在恒定时间内选择随机边(相对于总边数或节点边数,只有生成th edata结构的时间是线性时间)。在示例中,边缘用
1 2 3 4 5 6 7 8 9 10 | Node v ->a (p=1, alias= ...) ->b (p=3/4, alias= ->a) ->c (p=3/4, alias= ->a) Node a ->c (p=1/2, alias= ->b) ->b (p=1, alias= ...) ... |
如果要选择传出边缘(即下一个节点),只需从间隔[0,1]生成单个随机数
然后得到
然后将该边的指定概率
例如,如果我们有来自随机数发生器的
1 2 |
号
因此,我们选择第二个传出边缘(注意索引以零开头),即
1 | ->b (p=3/4, alias= ->a) |
并切换到别名边缘
因此,对于节点
- 用概率
1/3*3/4 选择边b (即每当no=1 和pv<3/4 时) - 用概率
1/3*3/4 选择边c (即每当no=2 和pv<3/4 时) - 用概率
1/3 + 1/3*1/4 + 1/3*1/4 选择边a (即每当no=0 或pv>=3/4 时)
理论上,最有效的方法是为每个节点存储平衡二叉树(红-黑,或btree,或skip-list-all-fit)的道德等价物及其权重,以及每侧的总权重。然后你可以选择一个从0到1的随机数,乘以连接节点的总权重,然后做一个二进制搜索来找到它。
然而,像这样遍历二叉树需要很多选择,这些选择往往会造成管道阻塞。很贵的。所以在实践中,如果你用高效的语言编程(如C++),如果每个节点的连接边少于几百个,那么你在一个循环中的边(具有预先计算的总和)的线性列表可能被证明是更快的。