2929from abc import ABC , abstractmethod
3030
3131
32-
3332class POWL (ProcessTree , ABC ):
3433 def print (self ) -> None :
3534 print (self .to_string ())
@@ -43,10 +42,14 @@ def simplify(self) -> "POWL":
4342 def validate_partial_orders (self ):
4443 if isinstance (self , StrictPartialOrder ):
4544 if not self .order .is_irreflexive ():
46- raise Exception ("The irreflexivity of the partial order is violated!" )
45+ raise Exception (
46+ "The irreflexivity of the partial order is violated!"
47+ )
4748 if not self .order .is_transitive ():
48- raise Exception ("The transitivity of the partial order is violated!" )
49- if hasattr (self , 'children' ):
49+ raise Exception (
50+ "The transitivity of the partial order is violated!"
51+ )
52+ if hasattr (self , "children" ):
5053 for child in self .children :
5154 child .validate_partial_orders ()
5255
@@ -84,7 +87,10 @@ def copy(self):
8487
8588 def __eq__ (self , other : object ) -> bool :
8689 if isinstance (other , Transition ):
87- return self ._label == other ._label and self ._identifier == other ._identifier
90+ return (
91+ self ._label == other ._label
92+ and self ._identifier == other ._identifier
93+ )
8894 return False
8995
9096 def equal_content (self , other : object ) -> bool :
@@ -116,7 +122,9 @@ def copy(self):
116122
117123
118124class FrequentTransition (Transition ):
119- def __init__ (self , label , min_freq : Union [str , int ], max_freq : Union [str , int ]) -> None :
125+ def __init__ (
126+ self , label , min_freq : Union [str , int ], max_freq : Union [str , int ]
127+ ) -> None :
120128 self .skippable = False
121129 self .selfloop = False
122130 if min_freq == 0 :
@@ -126,7 +134,15 @@ def __init__(self, label, min_freq: Union[str, int], max_freq: Union[str, int])
126134 min_freq = "1"
127135 self .activity = label
128136 if self .skippable or self .selfloop :
129- label = str (label ) + "\n " + "[" + str (min_freq ) + "," + str (max_freq ) + "]"
137+ label = (
138+ str (label )
139+ + "\n "
140+ + "["
141+ + str (min_freq )
142+ + ","
143+ + str (max_freq )
144+ + "]"
145+ )
130146
131147 super ().__init__ (label = label )
132148
@@ -140,15 +156,14 @@ def __init__(self, nodes: TList[POWL]) -> None:
140156 self .additional_information = None
141157
142158 def copy (self ):
143- copied_nodes = {n :n .copy () for n in self .order .nodes }
159+ copied_nodes = {n : n .copy () for n in self .order .nodes }
144160 res = StrictPartialOrder (list (copied_nodes .values ()))
145161 for n1 in self .order .nodes :
146162 for n2 in self .order .nodes :
147163 if self .order .is_edge (n1 , n2 ):
148164 res .add_edge (copied_nodes [n1 ], copied_nodes [n2 ])
149165 return res
150166
151-
152167 def _set_order (self , nodes : TList [POWL ]) -> None :
153168 self .order = BinaryRelation (nodes )
154169
@@ -162,10 +177,52 @@ def get_children(self) -> TList[POWL]:
162177 return self .order .nodes
163178
164179 def to_string (self , level = 0 , indent = False , max_indent = sys .maxsize ) -> str :
165- model_string = STRICT_PARTIAL_ORDER_LABEL + self .order .__repr__ ()
166- if indent :
167- model_string = "\n " .join (hie_utils .indent_representation (model_string , max_indent = max_indent ))
168- return model_string
180+ """
181+ Represents a StrictPartialOrder as a string, avoiding infinite recursion.
182+
183+ Parameters
184+ ----------
185+ level : int
186+ Current indentation level
187+ indent : bool
188+ Whether to indent the output
189+ max_indent : int
190+ Maximum indentation level
191+
192+ Returns
193+ -------
194+ str
195+ String representation of the partial order
196+ """
197+ # Start with the partial order label
198+ rep = f"{ STRICT_PARTIAL_ORDER_LABEL } =(nodes={{"
199+
200+ # Represent the nodes (children)
201+ nodes_str = []
202+ for i , node in enumerate (self .order .nodes ):
203+ # Call to_string on each child with increased level, preventing recursive blow-up
204+ node_str = node .to_string (level = level + 1 , indent = False , max_indent = max_indent )
205+ nodes_str .append (node_str )
206+ rep += ", " .join (nodes_str )
207+ rep += "}, order={"
208+
209+ # Represent the edges in the partial order
210+ edges_str = []
211+ for source in self .order .nodes :
212+ for target in self .order .nodes :
213+ if self .order .is_edge (source , target ):
214+ # Use a simplified representation for source and target to avoid recursion
215+ source_str = source .label if source .label else f"id_{ hash (source )} "
216+ target_str = target .label if target .label else f"id_{ hash (target )} "
217+ edges_str .append (f"{ source_str } -->{ target_str } " )
218+ rep += ", " .join (edges_str )
219+ rep += "})"
220+
221+ # Apply indentation if requested
222+ if indent and level <= max_indent :
223+ rep = "\n " .join (hie_utils .indent_representation (rep , max_indent = max_indent ))
224+
225+ return rep
169226
170227 def __repr__ (self ) -> str :
171228 return self .to_string ()
@@ -220,19 +277,28 @@ def equal_content(self, other: object) -> bool:
220277 for j in range (len (ordered_nodes_1 )):
221278 target_1 = ordered_nodes_1 [j ]
222279 target_2 = ordered_nodes_2 [j ]
223- if self .order .is_edge (source_1 , target_1 ) and not other .order .is_edge (source_2 , target_2 ):
280+ if self .order .is_edge (
281+ source_1 , target_1
282+ ) and not other .order .is_edge (source_2 , target_2 ):
224283 return False
225- if not self .order .is_edge (source_1 , target_1 ) and other .order .is_edge (source_2 , target_2 ):
284+ if not self .order .is_edge (
285+ source_1 , target_1
286+ ) and other .order .is_edge (source_2 , target_2 ):
226287 return False
227288 return True
228289
229290 def simplify_using_frequent_transitions (self ) -> "StrictPartialOrder" :
230- new_nodes = {node : node .simplify_using_frequent_transitions () for node in self .children }
291+ new_nodes = {
292+ node : node .simplify_using_frequent_transitions ()
293+ for node in self .children
294+ }
231295 res = StrictPartialOrder (list (new_nodes .values ()))
232296 for node_1 in self .children :
233297 for node_2 in self .children :
234298 if self .partial_order .is_edge (node_1 , node_2 ):
235- res .partial_order .add_edge (new_nodes [node_1 ], new_nodes [node_2 ])
299+ res .partial_order .add_edge (
300+ new_nodes [node_1 ], new_nodes [node_2 ]
301+ )
236302
237303 return res
238304
@@ -244,7 +310,9 @@ def simplify(self) -> "StrictPartialOrder":
244310
245311 def connected (node ):
246312 for node2 in self .children :
247- if self .partial_order .is_edge (node , node2 ) or self .partial_order .is_edge (node2 , node ):
313+ if self .partial_order .is_edge (
314+ node , node2
315+ ) or self .partial_order .is_edge (node2 , node ):
248316 return True
249317 return False
250318
@@ -273,14 +341,25 @@ def connected(node):
273341 for node_1 in self .children :
274342 for node_2 in self .children :
275343 if self .partial_order .is_edge (node_1 , node_2 ):
276- if node_1 in simplified_nodes .keys () and node_2 in simplified_nodes .keys ():
277- res .partial_order .add_edge (simplified_nodes [node_1 ], simplified_nodes [node_2 ])
344+ if (
345+ node_1 in simplified_nodes .keys ()
346+ and node_2 in simplified_nodes .keys ()
347+ ):
348+ res .partial_order .add_edge (
349+ simplified_nodes [node_1 ], simplified_nodes [node_2 ]
350+ )
278351 elif node_1 in simplified_nodes .keys ():
279- res .partial_order .add_edge (simplified_nodes [node_1 ], start_nodes [node_2 ])
352+ res .partial_order .add_edge (
353+ simplified_nodes [node_1 ], start_nodes [node_2 ]
354+ )
280355 elif node_2 in simplified_nodes .keys ():
281- res .partial_order .add_edge (end_nodes [node_1 ], simplified_nodes [node_2 ])
356+ res .partial_order .add_edge (
357+ end_nodes [node_1 ], simplified_nodes [node_2 ]
358+ )
282359 else :
283- res .partial_order .add_edge (end_nodes [node_1 ], start_nodes [node_2 ])
360+ res .partial_order .add_edge (
361+ end_nodes [node_1 ], start_nodes [node_2 ]
362+ )
284363 for po , simplified_po in sub_nodes .items ():
285364 for node_1 in simplified_po .children :
286365 for node_2 in simplified_po .children :
@@ -305,7 +384,9 @@ class OperatorPOWL(POWL):
305384 def __init__ (self , operator : Operator , children : TList [POWL ]) -> None :
306385 if operator is Operator .XOR :
307386 if len (children ) < 2 :
308- raise Exception ("Cannot create a choice of less than 2 submodels!" )
387+ raise Exception (
388+ "Cannot create a choice of less than 2 submodels!"
389+ )
309390 elif operator is Operator .LOOP :
310391 if len (children ) != 2 :
311392 raise Exception ("Only loops of length 2 are supported!" )
@@ -350,33 +431,68 @@ def simplify_using_frequent_transitions(self) -> POWL:
350431 if self .operator is Operator .XOR and len (self .children ) == 2 :
351432 child_0 = self .children [0 ]
352433 child_1 = self .children [1 ]
353- if isinstance (child_0 , Transition ) and isinstance (child_1 , SilentTransition ):
354- return FrequentTransition (label = child_0 .label , min_freq = 0 , max_freq = 1 )
355- elif isinstance (child_1 , Transition ) and isinstance (child_0 , SilentTransition ):
356- return FrequentTransition (label = child_1 .label , min_freq = 0 , max_freq = 1 )
434+ if isinstance (child_0 , Transition ) and isinstance (
435+ child_1 , SilentTransition
436+ ):
437+ return FrequentTransition (
438+ label = child_0 .label , min_freq = 0 , max_freq = 1
439+ )
440+ elif isinstance (child_1 , Transition ) and isinstance (
441+ child_0 , SilentTransition
442+ ):
443+ return FrequentTransition (
444+ label = child_1 .label , min_freq = 0 , max_freq = 1
445+ )
357446
358447 if self .operator is Operator .LOOP and len (self .children ) == 2 :
359448 child_0 = self .children [0 ]
360449 child_1 = self .children [1 ]
361- if isinstance (child_0 , Transition ) and isinstance (child_1 , SilentTransition ):
362- return FrequentTransition (label = child_0 .label , min_freq = 1 , max_freq = "-" )
363- elif isinstance (child_1 , Transition ) and isinstance (child_0 , SilentTransition ):
364- return FrequentTransition (label = child_1 .label , min_freq = 0 , max_freq = "-" )
365-
366- return OperatorPOWL (self .operator , [child .simplify_using_frequent_transitions () for child in self .children ])
450+ if isinstance (child_0 , Transition ) and isinstance (
451+ child_1 , SilentTransition
452+ ):
453+ return FrequentTransition (
454+ label = child_0 .label , min_freq = 1 , max_freq = "-"
455+ )
456+ elif isinstance (child_1 , Transition ) and isinstance (
457+ child_0 , SilentTransition
458+ ):
459+ return FrequentTransition (
460+ label = child_1 .label , min_freq = 0 , max_freq = "-"
461+ )
462+
463+ return OperatorPOWL (
464+ self .operator ,
465+ [
466+ child .simplify_using_frequent_transitions ()
467+ for child in self .children
468+ ],
469+ )
367470
368471 def simplify (self ) -> "OperatorPOWL" :
369472 if self .operator is Operator .XOR and len (self .children ) == 2 :
370473 child_0 = self .children [0 ]
371474 child_1 = self .children [1 ]
372475
373476 def merge_with_children (child0 , child1 ):
374- if isinstance (child0 , SilentTransition ) and isinstance (child1 , OperatorPOWL ) \
375- and child1 .operator is Operator .LOOP :
477+ if (
478+ isinstance (child0 , SilentTransition )
479+ and isinstance (child1 , OperatorPOWL )
480+ and child1 .operator is Operator .LOOP
481+ ):
376482 if isinstance (child1 .children [0 ], SilentTransition ):
377- return OperatorPOWL (Operator .LOOP , [n .simplify () for n in child1 .children ])
483+ return OperatorPOWL (
484+ Operator .LOOP ,
485+ [n .simplify () for n in child1 .children ],
486+ )
378487 elif isinstance (child1 .children [1 ], SilentTransition ):
379- return OperatorPOWL (Operator .LOOP , list (reversed ([n .simplify () for n in child1 .children ])))
488+ return OperatorPOWL (
489+ Operator .LOOP ,
490+ list (
491+ reversed (
492+ [n .simplify () for n in child1 .children ]
493+ )
494+ ),
495+ )
380496
381497 return None
382498
@@ -392,11 +508,18 @@ def merge_with_children(child0, child1):
392508 new_children = []
393509 for child in self .children :
394510 s_child = child .simplify ()
395- if isinstance (s_child , OperatorPOWL ) and s_child .operator is Operator .XOR :
511+ if (
512+ isinstance (s_child , OperatorPOWL )
513+ and s_child .operator is Operator .XOR
514+ ):
396515 for node in s_child .children :
397516 new_children .append (node .simplify ())
398517 else :
399518 new_children .append (s_child )
400- return OperatorPOWL (Operator .XOR , [child for child in new_children ])
519+ return OperatorPOWL (
520+ Operator .XOR , [child for child in new_children ]
521+ )
401522 else :
402- return OperatorPOWL (self .operator , [child .simplify () for child in self .children ])
523+ return OperatorPOWL (
524+ self .operator , [child .simplify () for child in self .children ]
525+ )
0 commit comments