forked from V3D3/prashaant-netgen
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathverifier.py
134 lines (109 loc) · 3.73 KB
/
verifier.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# Visualizer for generated network
####
# Requires: networkx, pygraphviz, and runs in an IPython environment (jupyter)
# Usage: run once to obtain a diagram of the network for given topology files (network.txt is updated)
# and a DOT format output to visualize using other applications (eg. qvge / gephi / etc)
####
###################################
###### DEPENDENCIES ######
###################################
# for running executable
import subprocess
# for representation and graph operations
# requires networkx
import networkx as nx
# for drawing
import matplotlib.pyplot as plt
# for easy errors
from os import error
##############################
###### CONSTANTS ######
##############################
# number of chars to ignore when parsing the lines
# "Links : <integer>"
# "NodeID: <identifier>"
IGN_LINKS = 8
IGN_NODEID = 8
##############################
###### HELPERS ######
##############################
# reads a file and returns its contents as string
def fileStr(f):
# open the given file, read only
f = open(f, 'r')
# read into a string
s = f.read()
# free the lock on the file
f.close()
return s
## END DEF
# parses a single line in a topology-describing file
def parseTopologyLine(s):
# split according to COMMAs
s = s.split(',')
# return X:str, n:int, m:int
return (s[0], int(s[1]), int(s[2]))
## END DEF
# given a string with the contents of the generated network file
# parses it into a graph, with sanity checks along the way
def parseNetwork(s):
# initialize graph
G = nx.DiGraph()
# currnode : the current node from whom we're adding edges to others
# edgecount : the number of edges remaining to be added from current node
# encnodes : the total number of nodes encountered in the input
currnode = 'error'
edgecount = 0
encnodes = 0
# parse each line
for i in s.split('\n'):
# Line style: NodeID: <identifier>
# Action: Add a node
if len(i) == 0:
continue
if i[0] == 'N':
# sanity check before starting with a new node
if edgecount > 0:
error(f'not enough edges for node: {currnode}, remaining: {edgecount}')
# add node to graph
G.add_node(i[IGN_NODEID:])
# set currnode
currnode = i[IGN_NODEID:]
# increment encountered nodes count
encnodes += 1
# Line style: Links: <integer>
# Action: Set edge count
elif i[1] == 'i':
# count of edges
edgecount = int(i[IGN_LINKS:])
# Line style: L(<integer>): <identifier>
# Action: Add a directed edge
elif i[1] == '(':
# add a link
G.add_edge(currnode, i.split(':')[1])
# one less link remaining
edgecount -= 1
# Line style: *
# Action: ERROR
else:
# ERROR
error('umm weird input: ' + i)
# sanity check: don't add more edges than reported
if edgecount < 0:
error('too many edges for node: ' + currnode)
## END FOR
# graph fully constructed
return G
## END DEF
##############################
###### TESTING ######
##############################
# run the executable, with topology input files from testdir
subprocess.run(["./generator.py"])
# we use networkx library to save time reimplementing directed graphs
# totalNodes are passed just as a sanity check
network1 = parseNetwork(fileStr("Network.txt"))
# draw the graph object (require an IPython environment)
nx.draw_shell(network1, with_labels=True)
# output in DOT format (requires pygraphviz)
nx.drawing.nx_agraph.write_dot(network1, "Out.txt")