@@ -310,79 +310,36 @@ class LoopCutDFG(LoopCut[IMDataStructureDFG]):
310310 @classmethod
311311 def project (
312312 cls ,
313- obj : IMDataStructureDFG ,
313+ obj : IMDataStructureUVCL ,
314314 groups : List [Collection [Any ]],
315315 parameters : Optional [Dict [str , Any ]] = None ,
316316 ) -> List [IMDataStructureDFG ]:
317- """
318- Project the original DFG onto the loop cut groups.
319-
320- groups[0] is the 'do' part, groups[1:] are one or more 'redo' parts.
321-
322- Semantics:
323- - For every group, we keep all intra-group edges with their original weights.
324- - For the 'do' part: start/end activities are the original start/end activities restricted to the group.
325- - For each 'redo' part: start activities are the group nodes that have incoming edges from outside the group;
326- end activities are the group nodes that have outgoing edges to outside the group. We aggregate their
327- frequencies from the boundary edges. If none are found (edge-case), we fall back to marking all nodes
328- as both start and end with weight 1 to keep the sub-DFG well-formed.
329- - Skippability: do-part is NOT skippable (must run at least once in a loop).
330- Every redo-part IS skippable (redo can repeat zero times).
331- """
332- original : DFG = obj .dfg
333-
334- # Precompute for convenience/performance
335- edges = original .graph # Dict[(a,b) -> weight]
336- start_acts = original .start_activities # Dict[a -> weight]
337- end_acts = original .end_activities # Dict[a -> weight]
338-
339- group_sets = [set (g ) for g in groups ]
340- dfgs : List [DFG ] = []
341- skippable : List [bool ] = [False ] + [True ] * max (0 , (len (groups ) - 1 ))
342-
343- for idx , g in enumerate (group_sets ):
344- sub = DFG ()
345-
346- # 1) Copy intra-group edges with their weights
347- for (a , b ), w in edges .items ():
317+ dfg = obj .dfg
318+ dfgs = []
319+ skippable = [False , False ]
320+ for gind , g in enumerate (groups ):
321+ dfn = DFG ()
322+ for a , b in dfg .graph :
348323 if a in g and b in g :
349- sub .graph [(a , b )] = w
350-
351- if idx == 0 :
352- # 2) DO part: restrict original start/end to the group
353- for a , w in start_acts . items () :
324+ dfn .graph [(a , b )] = dfg . graph [( a , b )]
325+ if b in dfg . start_activities and a in dfg . end_activities :
326+ skippable [ 1 ] = True
327+ if gind == 0 :
328+ for a in dfg . start_activities :
354329 if a in g :
355- sub .start_activities [a ] = w
356- for a , w in end_acts .items ():
330+ dfn .start_activities [a ] = dfg .start_activities [a ]
331+ else :
332+ skippable [0 ] = True
333+ for a in dfg .end_activities :
357334 if a in g :
358- sub .end_activities [a ] = w
359- else :
360- # 3) REDO part: derive starts/ends from boundary edges
361- start_counts : Dict [Any , int ] = {}
362- end_counts : Dict [Any , int ] = {}
363-
364- # Entries into the group (from outside) -> starts
365- # Exits from the group (to outside) -> ends
366- for (a , b ), w in edges .items ():
367- if b in g and a not in g :
368- start_counts [b ] = start_counts .get (b , 0 ) + w
369- if a in g and b not in g :
370- end_counts [a ] = end_counts .get (a , 0 ) + w
371-
372- # Fallback to keep the sub-DFG well-formed (very rare, but safe)
373- if not start_counts :
374- for a in g :
375- start_counts [a ] = 1
376- if not end_counts :
377- for a in g :
378- end_counts [a ] = 1
379-
380- sub .start_activities .update (start_counts )
381- sub .end_activities .update (end_counts )
382-
383- dfgs .append (sub )
384-
385- # Wrap each projected DFG as an InductiveDFG with correct skippability
335+ dfn .end_activities [a ] = dfg .end_activities [a ]
336+ else :
337+ skippable [0 ] = True
338+ elif gind == 1 :
339+ for a in g :
340+ dfn .start_activities [a ] = 1
341+ dfn .end_activities [a ] = 1
342+ dfgs .append (dfn )
386343 return [
387344 IMDataStructureDFG (InductiveDFG (dfg = dfgs [i ], skip = skippable [i ]))
388345 for i in range (len (dfgs ))
0 commit comments