[docs]
class StitchSubclusterSelectorBase:
"""Subclasses of this class are used to make choice which subclusters
will be stitched next based on criteria."""
def __init__(self, *args, **kwargs):
pass
def select(self, dst, src, stitched, is_intra=False):
raise NotImplementedError
[docs]
class MaxCommonNodeSelector(StitchSubclusterSelectorBase):
"""
Return subclusters that have maximum common node count.
"""
def __init__(self, cn_count_treshold=0):
self.cn_count_treshold = cn_count_treshold
def select(self, dst, src, stitched, is_intra=False):
cn_count_max = 0
dstSubIndex = None
srcSubIndex = None
for src_index, src_sc in enumerate(src):
for dst_index, dst_sc in enumerate(dst):
# same subcluster
if is_intra and src_index == dst_index:
continue
# already stitched
if (dst_index, src_index) in stitched:
continue
# src_sc is subset of dst_sc mark src_sc stitched with dst
if set(src_sc.keys()) <= set(dst_sc.keys()):
stitched[(dst_index, src_index)] = ()
continue
commonNodes = [node for node in list(dst_sc.keys()) if node in list(src_sc.keys())]
cn_count = len(commonNodes)
if cn_count > cn_count_max and cn_count >= self.cn_count_treshold:
cn_count_max = cn_count
dstSubIndex = dst_index
srcSubIndex = src_index
# in intraStitch make sure that dstSub is larger one
if is_intra and cn_count_max != 0 and len(src[srcSubIndex]) > len(dst[dstSubIndex]):
return (srcSubIndex, dstSubIndex) # swapped src and dst indexes
return (dstSubIndex, srcSubIndex)