python 生成有向无环图(DAG)--改编自CSDN

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LucyGill/article/details/80463090

本文改编自CSDN,作者ZhouMu,原文链接如下:

https://blog.csdn.net/zhoujinyu0713/article/details/10163037?utm_source=tuicool

本文的主要工作是,说明拓扑序的含义及其在生成DAG时的妙用,并给原文代码标注释。


0. 拓扑序

这一部分主要参考自百度百科中的“拓扑排序”词条。原文链接如下:

https://baike.baidu.com/item/%E6%8B%93%E6%89%91%E6%8E%92%E5%BA%8F/5223807?fromtitle=%E6%8B%93%E6%89%91%E5%BA%8F&fromid=17352962&fr=aladdin

定义:

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

定义中所谓的“偏序”是离散数学中的概念,偏序关系指的是,满足(1)自反性(2)反对称性(3)传递性的关系R。自反性指的是,集合中的任一元素x满足:x R x。反对称性指的是,如果x R y, 则 y R x不成立。传递性指的是,若x R y, y R z, 则有 x R z。

定义中所谓的“全序”也是离散数学中的概念。它在偏序关系的基础上加了限制:集合中任意两个元素都能比较大小。

对有向无环图进行拓扑排序的方法:

(1) 选择一个入度为0的顶点并输出之;
(2) 从网中删除此顶点及所有 出边
循环结束后,若输出的顶点数小于网中的顶点数,则输出“有 回路”信息,否则输出的顶点序列就是一种拓扑 序列
下面的图一是一个给DAG进行拓扑排序的例子:

1. 生成DAG的思路

假设要生成含有N个节点的网络。首先随机生成一个 1 到N 的排列。这个排列就是DAG的拓扑序,然后每次随机从前往后连边,这样就可以保证生成的是一个DAG了。

2. Python代码及注释

下面是原文的代码。我对代码存在两个疑问:

1. 为啥要在每条边后面加上随机生成的两个数?有什么用意?难道是权重?

2. 为啥在最后生成k个随机数?有什么用? 

希望知道的小伙伴能给我讲讲。

[python]  view plain  copy
  1. from random import shuffle as sl  
  2. from random import randint as rd  
  3.   
  4. def gn():  #生成1到1000的一个随机数
  5.     num = rd(1,1000)  
  6.     return num  
  7. def w2f(f,num,fg):  #将num写入文件f,并根据fg的值决定是否换行
  8.     f.write(str(num))  
  9.     if fg==True:  
  10.         f.write('\n')  
  11.     else:  
  12.         f.write(' ')  
  13.   
  14. def DataMake(c):  #生成DAG,存入以c命名的文件内
  15.     MAXL =100000;  
  16.     f = open('data'+str(c)+'.in','w')  
  17.     n = 1000  #设置图中节点数量
  18.     node = range(1,n+1)  #生成1到n的一个序列
  19.     node=list(node) #将格式转换成list,便于下一步随机重排
  20.     sl(node)  #随机重排
  21.     sl(node)  #随机重排,生成节点的序号。在这里,node[i]的值表示节点,i表示当前节点的拓扑序。
  22.     m = rd(1,min(n*n,5000))  #设置图中边的数量
  23.     w2f(f,n,0);w2f(f,m,1)  #将节点数量n和边的数量m写入文件f
  24.     for i in range(0,m):  #随机生成m条边
  25.         p1 = rd (1,n-1)  #选择第一个节点
  26.         p2 = rd (p1+1,n)  #选择第二个节点,这个节点的拓扑序必须大于第一个节点
  27.         x = node[p1-1]  #读取拓扑序为p1的节点
  28.         y = node[p2-1]  #读取拓扑序为p2的节点
  29.         l = rd(1,MAXL)  #生成一个1到MAXL的随机数
  30.         w = gn()  #生成一个1到1000的随机数
  31.         w2f(f,x,0);w2f(f,y,0);w2f(f,l,0);w2f(f,w,1)  #将x,y,l,w写入文件
  32.     k = gn()  #生成一个1到1000的随机数k
  33.     w2f(f,k,1)  #将k写入文件
  34.     for i in range(0,k):  #生成k个1到1000的随机数
  35.         w2f(f,gn(),1)  
  36.     print(n,' node',m,' edges',k,'Queries')  
  37.     f.close()  
  38.   
  39. DataMake(1)  #生成一个名为data1.in的文件,里面存储的就是一个DAG
  40. print ('Done')

猜你喜欢

转载自blog.csdn.net/LucyGill/article/details/80463090