1616import json
1717from itertools import product
1818from networkx .readwrite import read_gpickle , write_gpickle
19- import numpy as np
19+ import numpy as np
2020from itertools import chain , combinations
2121import argparse
2222from .utils import create_graph , string_hash , type_hash , combine_hashes , annotate , draw
23- import math
23+ import math
2424
2525this_dir = pathlib .Path (__file__ ).resolve ().parent
2626
27+
2728def comb (n : int , k : int ) -> int :
2829 """
2930 Calculates the combination of two integers.
@@ -38,11 +39,12 @@ def comb(n: int, k: int) -> int:
3839 """
3940 return math .factorial (n ) / (math .factorial (k ) * math .factorial (n - k ))
4041
42+
4143class ImbalancedMicrostructureError (Exception ):
42- pass
44+ pass
45+
4346
4447def get_children (graph : nx .DiGraph , node : str ) -> List [str ]:
45-
4648 """
4749 Gets the children of a node.
4850
@@ -55,9 +57,9 @@ def get_children(graph: nx.DiGraph, node: str) -> List[str]:
5557 :rtype: List[str].
5658 """
5759 return [child for _ , child in graph .out_edges (node )]
58-
60+
61+
5962def get_parents (graph : nx .DiGraph , node : str ) -> List [str ]:
60-
6163 """
6264 Gets the parents of a node.
6365
@@ -71,8 +73,8 @@ def get_parents(graph: nx.DiGraph, node: str) -> List[str]:
7173 """
7274 return [parent for parent , _ in graph .in_edges (node )]
7375
76+
7477def get_relatives (graph : nx .DiGraph , node : str ) -> Set [str ]:
75-
7678 """
7779 Gets all node's relatives (children and parents).
7880
@@ -86,6 +88,7 @@ def get_relatives(graph: nx.DiGraph, node: str) -> Set[str]:
8688 """
8789 return set (chain (get_children (graph , node ), get_parents (graph , node )))
8890
91+
8992def find_microstructure (graph : nx .DiGraph , n1 : str , n2 : str ):
9093 """
9194 Detects a pattern (microstructure).
@@ -121,7 +124,6 @@ def find_microstructure(graph: nx.DiGraph, n1: str, n2: str):
121124 common_friends .update (n1_new_friends .intersection (n2_new_friends ))
122125 all_friends .update (n1_new_friends .union (n2_new_friends ))
123126
124-
125127 n1_new_friends -= common_friends
126128 n2_new_friends -= common_friends
127129
@@ -130,6 +132,7 @@ def find_microstructure(graph: nx.DiGraph, n1: str, n2: str):
130132
131133 return n1_friends , n2_friends , common_friends , all_friends
132134
135+
133136def find_microstructures (graph : nx .DiGraph , verbose : bool = False ):
134137 """
135138 Detects the patterns (microstructures) that are used for replication and graph expansion.
@@ -142,7 +145,7 @@ def find_microstructures(graph: nx.DiGraph, verbose: bool = False):
142145 :return: patterns (microstructures)
143146 :rtype: Set[str].
144147 """
145-
148+
146149 if verbose :
147150 print ("Sorting nodes by type hash and parent" )
148151 nodes_by_type_hash : Dict [str , Set [str ]] = {}
@@ -174,9 +177,9 @@ def find_microstructures(graph: nx.DiGraph, verbose: bool = False):
174177
175178 return microstructures
176179
180+
177181def sort_graphs (workflow_path : Union [pathlib .Path ],
178182 verbose : bool = False ) -> List [nx .DiGraph ]:
179-
180183 """
181184 Sort graphs in crescent order of number of tasks.
182185
@@ -197,7 +200,7 @@ def sort_graphs(workflow_path: Union[pathlib.Path],
197200 annotate (graph )
198201 graph .graph ["name" ] = path .stem
199202 graphs .append (graph )
200-
203+
201204 if not graphs :
202205 raise ValueError (f"No graphs found in { workflow_path } " )
203206
@@ -207,22 +210,23 @@ def sort_graphs(workflow_path: Union[pathlib.Path],
207210 sorted_graphs = sorted (graphs , key = lambda graph : len (graph .nodes ))
208211 return sorted_graphs
209212
210- def save_microstructures (workflow_path : Union [pathlib .Path ],
211- savedir : pathlib .Path ,
212- verbose : bool = False ,
213+
214+ def save_microstructures (workflow_path : Union [pathlib .Path ],
215+ savedir : pathlib .Path ,
216+ verbose : bool = False ,
213217 img_type : Optional [str ] = 'png' ,
214218 cutoff : int = 4000 ,
215219 highlight_all_instances : bool = False ) -> List [nx .DiGraph ]:
216220 summary = {
217221 "frequencies" : {},
218222 "base_graphs" : {}
219223 }
220-
224+
221225 for graph in sort_graphs (workflow_path , verbose ):
222226 if graph .order () > cutoff :
223227 print (f'This and the next workflows have more than { cutoff } tasks' )
224228 break
225-
229+
226230 if verbose :
227231 print (f"Running for { graph .name } " )
228232 g_savedir = savedir .joinpath (graph .name )
@@ -239,7 +243,7 @@ def save_microstructures(workflow_path: Union[pathlib.Path],
239243 base_graph_image_path = g_savedir .joinpath (f"base_graph" )
240244 if verbose :
241245 print (f"Drawing base graph to { base_graph_image_path } " )
242- draw (graph , close = True , legend = False , extension = img_type , save = str (base_graph_image_path ))
246+ draw (graph , close = True , legend = False , extension = img_type , save = str (base_graph_image_path ))
243247
244248 if verbose :
245249 print ("Finding microstructures" )
@@ -259,18 +263,17 @@ def save_microstructures(workflow_path: Union[pathlib.Path],
259263 if img_type :
260264 print (f"Drawing { ms_name } " )
261265 draw (
262- graph ,
266+ graph ,
263267 subgraph = list (instances )[0 ] if not highlight_all_instances else set .union (* instances ),
264- with_labels = False ,
268+ with_labels = False ,
265269 extension = img_type ,
266- save = str (g_savedir .joinpath (ms_name )),
270+ save = str (g_savedir .joinpath (ms_name )),
267271 close = True
268272 )
269-
273+
270274 if verbose :
271275 print ()
272-
273- g_savedir .joinpath ("microstructures" ).with_suffix (".json" ).write_text (json .dumps (mdatas , indent = 2 ))
274276
275- savedir .joinpath ("summary" ).with_suffix (".json" ).write_text (json .dumps (summary , indent = 2 ))
276-
277+ g_savedir .joinpath ("microstructures" ).with_suffix (".json" ).write_text (json .dumps (mdatas , indent = 2 ))
278+
279+ savedir .joinpath ("summary" ).with_suffix (".json" ).write_text (json .dumps (summary , indent = 2 ))
0 commit comments