-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfull_graph_layout_algorithm.py
More file actions
206 lines (199 loc) · 5.4 KB
/
full_graph_layout_algorithm.py
File metadata and controls
206 lines (199 loc) · 5.4 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
# Example graph from the initial description
graph = [
{
"id": "101",
"from": "entry",
"to": "action1",
"label": "Workflow starts when an Event Planning form is created"
},
{
"id": "102",
"from": "action1",
"to": "decision1",
"label": "Main Process: Create the Marketing and Promotion Subtask process"
},
{
"id": "103",
"from": "action1",
"to": "action2",
"label": "Create the Marketing and Promotion Subtask process"
},
{
"id": "104",
"from": "action1",
"to": "action3",
"label": "Create the Marketing and Promotion Subtask process"
},
{
"id": "105",
"from": "action1",
"to": "action4",
"label": "Create the Marketing and Promotion Subtask process"
},
{
"id": "106",
"from": "action2",
"to": "exit1",
"label": "Catering subtask, adds 275 USD to the Total Cost in the main process"
},
{
"id": "107",
"from": "action3",
"to": "exit2",
"label": "Venue Setup subtask, adds 650 USD to the Total Cost in the main process"
},
{
"id": "108",
"from": "action4",
"to": "exit3",
"label": "Marketing subtask, adds 400 USD to the Total Cost in the main process"
},
{
"id": "109",
"from": "decision1",
"to": "action5",
"label": "if total cost exceeds 1850 USD"
},
{
"id": "110",
"from": "decision1",
"to": "action6",
"label": "if total cost exceeds 1850 USD"
},
{
"id": "111",
"from": "action5",
"to": "exit4",
"label": "Process is automatically approved"
},
{
"id": "112",
"from": "action6",
"to": "decision2",
"label": "Assign to Finance Team for further review"
},
{
"id": "113",
"from": "decision2",
"to": "action7",
"label": "if the Finance team denies the request"
},
{
"id": "114",
"from": "decision2",
"to": "action8",
"label": "if the Finance team denies the request"
},
{
"id": "115",
"from": "action7",
"to": "exit5",
"label": "Finance team approves the event planning"
},
{
"id": "116",
"from": "action8",
"to": "decision1",
"label": "Finance team denies the event planning"
}
]
# return the id by from node
def get_id_by_from(graph, from_node):
for node in graph:
if node["from"] == from_node:
return node["id"]
return None
edge_specs = {
"101": [
"[Task/Project Created] && task[Task Form] === \"Event Planning\""
],
"102": [
"task[Total Cost] = 500",
"task[Status] = \"In Progress\""
],
"103": [
"task[Parent Project] = 'Use Trigger Project'",
"task[Is Project] = 'No'"
],
"104": [
"task[Parent Project] = 'Use Trigger Project'",
"task[Is Project] = 'No'"
],
"105": [
"task[Parent Project] = 'Use Trigger Project'",
"task[Is Project] = 'No'"
],
"106": [
"task[Task Status] = \"In Progress\"",
"task[Due Date] = \"{{Today + 7:0:0:b}}\"",
"parent[Catering Status] = \"Being Arranged\"",
"parent[Total Cost] = parent[Total Cost] + 275"
],
"107": [
"task[Task Status] = \"In Progress\"",
"task[Due Date] = \"{{Today + 5:0:0:b}}\"",
"parent[Venue Status] = \"Setup In Progress\"",
"parent[Total Cost] = parent[Total Cost] + 650"
],
"108": [
"task[Task Status] = \"In Progress\"",
"task[Due Date] = \"{{Today + 10:0:0:b}}\"",
"parent[Marketing Status] = \"Campaigns Running\"",
"parent[Total Cost] = parent[Total Cost] + 400"
],
"109": [
"task[Total Cost] <= 1850"
],
"110": [
"task[Total Cost] > 1850"
],
"111": [
"task[Approval Status] = \"Automatically Approved\""
],
"112": [
"task[Assigned To] = \"Finance Team\""
],
"113": [
"task[Finance Decision] === \"Approve\""
],
"114": [
"task[Finance Decision] === \"Deny\""
],
"115": [
"task[Approval Status] = \"Approved by Finance\""
],
"116": [
"task[Approval Status] = \"Denied by Finance\""
]
}
def dfs_count_subgraph_size(node, adj, subgraph_size, visited):
if node in visited:
return 0
visited.add(node)
size = 1
for neighbor in adj.get(node, []):
size += dfs_count_subgraph_size(neighbor, adj, subgraph_size, visited.copy())
subgraph_size[node] = size
return size
def calculate_subgraph_sizes(graph):
adj = {}
subgraph_size = {}
for edge in graph:
if edge['from'] not in adj:
adj[edge['from']] = []
adj[edge['from']].append(edge['to'])
for node in adj:
if node not in subgraph_size:
dfs_count_subgraph_size(node, adj, subgraph_size, set())
return subgraph_size
def create_adjacency_list_and_edges(graph):
adj_list = {}
edges_list = []
for edge in graph:
if edge['from'] not in adj_list:
adj_list[edge['from']] = []
adj_list[edge['from']].append(edge['to'])
edges_list.append(edge)
return adj_list, edges_list