# DAG_Generator

Random Directed Acyclic Graph Generator

#### verison1.0

##### 简介

Edges: [(1, 5), (1, 6), (2, 4), (2, 6), (3, 6), (4, 7), (4, 9), (5, 9), (5, 7), (6, 7), (‘Start’, 1), (‘Start’, 2), (‘Start’, 3), (‘Start’, 8), (‘Start’, 10), (7, ‘Exit’), (8, ‘Exit’), (9, ‘Exit’), (10, ‘Exit’)]

In_degree: [1, 1, 1, 1, 1, 3, 3, 1, 2, 1] #不包括虚拟节点

out_degree: [2, 2, 1, 2, 2, 1, 1, 1, 1, 1] #不包括虚拟节点

##### 参数设定

set_dag_size = [20,30,40,50,60,70,80,90]             #random number of DAG  nodes
set_max_out = [1,2,3,4,5]                            #max out_degree of one node
set_alpha = [0.5,1.0,1.5]                            #DAG shape
set_beta = [0.0,0.5,1.0,2.0]                         #DAG regularity
1. set_dag_size : 设定的DAG任务大小，有[20,30,40,50,60,70,80,90]，默认为20。
2. set_max_out: 设定的一个节点最大出度，有[1,2,3,4,5]，默认为2。
3. set_alpha : 设定DAG控制形状的参数，有[0.5,1.0,1.5]，默认为1.0。
4. set_beta ：设定DAG每层宽度的规则度参数，有[0.0,0.5,1.0,2.0] ，默认为1.0。

DAG的层数（深度）被设置为$\sqrt{set_dag_size}/set_alpha$, $\alpha$控制着DAG的Fat，$\alpha$越小，DAG越瘦长，$\alpha$越大，DAG越肥密。

##### 绘制

def plot_DAG(edges,postion):
g1 = nx.DiGraph()
nx.draw_networkx(g1, arrows=True, pos=postion)
plt.savefig("DAG.png", format="PNG")
return plt.clf

n = 30,max_out = 3, $\alpha$ = 1, $\beta$ = 1.0

n = 30,max_out = 3, $\alpha$ = 0.5, $\beta$ = 1.0

n = 30,max_out = 3, $\alpha$ = 1.5, $\beta$ = 1.0

##### 代码

import random,math,argparse
import numpy as np
from numpy.random.mtrand import sample
from matplotlib import pyplot as plt
import networkx as nx

parser = argparse.ArgumentParser()
parser.add_argument('--n', default=10, type=int)          #number of DAG  nodes
parser.add_argument('--max_out', default=2, type=float)   #max out_degree of one node
args = parser.parse_args()

set_dag_size = [20,30,40,50,60,70,80,90]             #random number of DAG  nodes
set_max_out = [1,2,3,4,5]                              #max out_degree of one node
set_alpha = [0.5,1.0,2.0]                            #DAG shape
set_beta = [0.0,0.5,1.0,2.0]                         #DAG regularity

def DAGs_generate(mode = 'default',n = 10,max_out = 2,alpha = 1,beta = 1.0):
##############################################initialize###########################################
args.mode = mode
if args.mode != 'default':
args.n = random.sample(set_dag_size,1)[0]
args.max_out = random.sample(set_max_out,1)[0]
args.alpha = random.sample(set_alpha,1)[0]
args.beta = random.sample(set_alpha,1)[0]
else:
args.n = n
args.max_out = max_out
args.alpha = alpha
args.beta = beta

length = math.floor(math.sqrt(args.n)/args.alpha)
mean_value = args.n/length
random_num = np.random.normal(loc = mean_value, scale = args.beta,  size = (length,1))
###############################################division############################################
position = {'Start':(0,4),'Exit':(10,4)}
generate_num = 0
dag_num = 1
dag_list = []
for i in range(len(random_num)):
dag_list.append([])
for j in range(math.ceil(random_num[i])):
dag_list[i].append(j)
generate_num += math.ceil(random_num[i])

if generate_num != args.n:
if generate_num<args.n:
for i in range(args.n-generate_num):
index = random.randrange(0,length,1)
dag_list[index].append(len(dag_list[index]))
if generate_num>args.n:
i = 0
while i < generate_num-args.n:
index = random.randrange(0,length,1)
if len(dag_list[index])==1:
i = i-1 if i!=0 else 0
else:
del dag_list[index][-1]
i += 1

dag_list_update = []
pos = 1
max_pos = 0
for i in range(length):
dag_list_update.append(list(range(dag_num,dag_num+len(dag_list[i]))))
dag_num += len(dag_list_update[i])
pos = 1
for j in dag_list_update[i]:
position[j] = (3*(i+1),pos)
pos += 5
max_pos = pos if pos > max_pos else max_pos
position['Start']=(0,max_pos/2)
position['Exit']=(3*(length+1),max_pos/2)

into_degree = [0]*args.n
out_degree = [0]*args.n
edges = []
pred = 0

for i in range(length-1):
sample_list = list(range(len(dag_list_update[i+1])))
for j in range(len(dag_list_update[i])):
od = random.randrange(1,args.max_out+1,1)
od = len(dag_list_update[i+1]) if len(dag_list_update[i+1])<od else od
bridge = random.sample(sample_list,od)
for k in bridge:
edges.append((dag_list_update[i][j],dag_list_update[i+1][k]))
into_degree[pred+len(dag_list_update[i])+k]+=1
out_degree[pred+j]+=1
pred += len(dag_list_update[i])

######################################create start node and exit node################################
for node,id in enumerate(into_degree):#给所有没有入边的节点添加入口节点作父亲
if id ==0:
edges.append(('Start',node+1))
into_degree[node]+=1

for node,od in enumerate(out_degree):#给所有没有出边的节点添加出口节点作儿子
if od ==0:
edges.append((node+1,'Exit'))
out_degree[node]+=1

#############################################plot##################################################
return edges,into_degree,out_degree,position

## 参考

[1] [List Scheduling Algorithm for Heterogeneous Systems by an Optimistic Cost Table](https://ieeexplore.ieee.org/abstract/document/6471969/)

View Github