-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFBackGraph.py
More file actions
160 lines (139 loc) · 5.67 KB
/
FBackGraph.py
File metadata and controls
160 lines (139 loc) · 5.67 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
from Graph import *
class FBackGraph(Graph):
"""
This class is a subclass of 'Graph'. Whereas the parent class is for
analyzing DAGs without feedback loops, this class can handle feedback
loops.
If one asks an instance of this class to draw a graph with slices=1,
it will draw a single time-slice and DASHED GREEN feedback arrows. If
slices=j>1, it will draw j time-slices connected by SOLID GREEN feedback
arrows.
Attributes
----------
fback_arrows: list[(str, str)]
feedback arrows that connect 2 adjacent time-slices. Their arrow
gains are represented by \beta_{i|j}.
inslice_arrows: list[(str, str)]
arrows whose orgin and target occur at the same time. Their arrow
gains are represented by \alpha_{ i|j}.
"""
def __init__(self,
dot_file_path,
amputated_arrows=None):
"""
Constructor
Parameters
----------
dot_file_path: str
amputated_arrows: list[(str, str)]
"""
Graph.__init__(self,
dot_file_path,
amputated_arrows=amputated_arrows,
is_DAG=False)
self.inslice_arrows, self.fback_arrows =\
self.get_inslice_and_fback_arrows()
self.nx_graph = nx.DiGraph()
self.nx_graph.add_edges_from(self.inslice_arrows)
# this bombs if not DAG
self.ord_nodes = list(nx.topological_sort(self.nx_graph))
def get_inslice_and_fback_arrows(self):
"""
This method returns a list of inslice arrows, and a list of feedback
arrows.
Returns
-------
list[(str, str)], list[(str, str)]
"""
inslice_arrows = []
fback_arrows = []
with open(self.path) as f:
in_lines = f.readlines()
for line in in_lines:
if "->" not in line:
continue
else:
green_arrow = False
if "green" in line:
green_arrow = True
pa, ch_list = FBackGraph.get_pa_and_ch_list(line)
for ch in ch_list:
if green_arrow:
fback_arrows.append((pa, ch))
else:
inslice_arrows.append((pa, ch))
# print("ccvbb---------------", fback_arrows)
return inslice_arrows, fback_arrows
def draw(self, jupyter=False, slices=1, point_right=False):
"""
This method draws the graph either on the console (jupyter=False) or
in a jupyter notebook (jupyter=True). Amputated arrows are drawn in
red, non-amputated ones in black.
Parameters
----------
jupyter: bool
slices: int
number of slices=1,2,3, ... to draw. slices=1 draws one
time-slice with feedback loops as dashed green arrows. slices=2
draws 2 time-slices (DAGs) connected by feedback arrows in solid
green.
point_right: bool
If point_right=False, time points down (the default
orientation). If point_right=True, time points right.
Returns
-------
None
"""
new_dot = ""
with open(self.path) as f:
in_lines = f.readlines()
for line in in_lines:
if "->" not in line:
new_dot += line
if "{" in line and point_right:
new_dot += "rankdir=LR;\n"
else:
green_arrow = False
if "green" in line:
green_arrow = True
pa, ch_list = Graph.get_pa_and_ch_list(line)
for ch in ch_list:
if slices == 1:
new_dot += pa + " -> " + ch
if (pa, ch) in self.amputated_arrows:
new_dot += " [color=red];\n"
elif green_arrow:
new_dot += " [color=green, style=dashed];\n"
else:
new_dot += ";\n"
elif slices > 1:
for sli in range(slices):
long_pa = pa + "[" + str(sli+1) + "]"
long_pa = '"' + long_pa + '"'
if green_arrow:
long_ch = ch + "[" + str(sli + 2) + "]"
else:
long_ch = ch + "[" + str(sli+1) + "]"
long_ch = '"' + long_ch + '"'
if green_arrow:
if sli != slices-1:
new_dot += long_pa + " -> " + long_ch
new_dot += "[color=green];\n"
else:
new_dot += long_pa + " -> " + long_ch
new_dot += ";\n"
else:
assert False
with open("tempo1389.dot", "w") as file:
file.write(new_dot)
DotTool.draw('tempo1389.dot', jupyter)
if __name__ == "__main__":
def main(draw):
path = 'dot_atlas/fback-2node.dot'
g = FBackGraph(path)
print('fback_arrows:', g.fback_arrows)
print('inslice_arrows:', g.inslice_arrows)
if draw:
g.draw(jupyter=False, slices=1)
g.draw(jupyter=False, slices=3, point_right=True)
main(True)