<commit_before>from functools import reduce

from skyline_path.core import SkylineStatus
from skyline_path.core.dominate import dominate_check
from skyline_path.core.edge_helper import aggregate

class SkyPath:
    """
    Implement SkyPath Algorithm.
    composite with MultiAttributeGraph
    """
    def __init__(self, mag):
        # record partial skyline paths and full skyline paths
        # with their attributes
        self.mag = mag
        self.partial_sp = {}
        self.full_sp = {}

    def skypath_query(self, src, dst):
        """
        Give src and dst (Both are Nodes in this Graph)
        Find out all of skyline paths by SkyPath Algorithm.
        """
        return self._path_recursive(src, dst)

    def _path_recursive(self, cur, dst, path=None):
        if path is None:
            path = []
        path = path + [cur]
        if cur == dst:
            self.__add_new_sp_check(path)
            return
        for neighbor in self.mag.neighbors[cur] - set(path):
            if self.__next_hop(neighbor, path):
                self._path_recursive(neighbor, dst, path)

    def __next_hop(self, neighbor, path):
        target_attrs = self.__attrs_in(path + [neighbor])
        if self.__partial_dominace(path + [neighbor], target_attrs):
            return False
        elif self.__full_dominace(path + [neighbor], target_attrs):
            return False
        else:
            return True

    def __partial_dominace(self, path, target_attrs):
        existed_attrs = self.partial_sp.get((path[0], path[-1]))
        if existed_attrs is not None:
            check = dominate_check(existed_attrs, target_attrs)
            if check is SkylineStatus.DOMINATE:
                return True
            elif check is SkylineStatus.NON_DOMINATE:
                return False
        # Here means old partial are dominated and replace it.
        self.partial_sp[(path[0], path[-1])] = target_attrs
        return False

    def __full_dominace(self, path, target_attrs):
        for _, existed_attrs in self.full_sp.items():
           check = dominate_check(existed_attrs, target_attrs)
           if check is SkylineStatus.DOMINATE:
                return True
        return False

    def __add_new_sp_check(self, path):
        temp_attrs = self.__attrs_in(path)
        # should use copy full sp due to changed size during iteration
        for sp, existed_attrs in self.full_sp.copy().items():
            check = dominate_check(existed_attrs, temp_attrs)
            if check is SkylineStatus.DOMINATE:
                return
            elif check is SkylineStatus.BE_DOMINATED:
                self.full_sp.pop(sp)
        # Check finished, add the new skyline path.
        self.full_sp[tuple(path)] = temp_attrs

    def __attrs_in(self, path):
        edges_attrs = self.__edges_to_attrs(self.__split_to(path))
        return reduce(lambda a1, a2: aggregate(a1, a2), edges_attrs)

    def __split_to(self, path):
        return [(path[i], path[i+1]) for i in range(len(path[:-1]))]

    def __edges_to_attrs(self, edges):
        return map(lambda e: self.mag.attrs_between(e[0], e[1]), edges)<commit_msg>fix typo<commit_after>from functools import reduce

from skyline_path.core import SkylineStatus
from skyline_path.core.dominate import dominate_check
from skyline_path.core.edge_helper import aggregate

class SkyPath:
    """
    Implement SkyPath Algorithm.
    composite with MultiAttributeGraph
    """
    def __init__(self, mag):
        # record partial skyline paths and full skyline paths
        # with their attributes
        self.mag = mag
        self.partial_sp = {}
        self.full_sp = {}

    def skypath_query(self, src, dst):
        """
        Give src and dst (Both are Nodes in this Graph)
        Find out all of skyline paths by SkyPath Algorithm.
        """
        return self._path_recursive(src, dst)

    def _path_recursive(self, cur, dst, path=None):
        if path is None:
            path = []
        path = path + [cur]
        if cur == dst:
            self.__add_new_sp_check(path)
            return
        for neighbor in self.mag.neighbors[cur] - set(path):
            if self.__next_hop(neighbor, path):
                self._path_recursive(neighbor, dst, path)

    def __next_hop(self, neighbor, path):
        target_attrs = self.__attrs_in(path + [neighbor])
        if self.__partial_dominace(path + [neighbor], target_attrs):
            return False
        elif self.__full_dominace(path + [neighbor], target_attrs):
            return False
        else:
            return True

    def __partial_dominace(self, path, target_attrs):
        existed_attrs = self.partial_sp.get((path[0], path[-1]))
        if existed_attrs is not None:
            check = dominate_check(existed_attrs, target_attrs)
            if check is SkylineStatus.DOMINATE:
                return True
            elif check is SkylineStatus.NON_DOMINATE:
                return False
        # Here means old partial are dominated and replace it.
        self.partial_sp[(path[0], path[-1])] = target_attrs
        return False

    def __full_dominace(self, path, target_attrs):
        for _, existed_attrs in self.full_sp.items():
           check = dominate_check(existed_attrs, target_attrs)
           if check is SkylineStatus.DOMINATE:
                return True
        return False

    def __add_new_sp_check(self, path):
        temp_attrs = self.__attrs_in(path)
        # should use copy() full sp due to changed size during iteration
        for sp, existed_attrs in self.full_sp.copy().items():
            check = dominate_check(existed_attrs, temp_attrs)
            if check is SkylineStatus.DOMINATE:
                return
            elif check is SkylineStatus.BE_DOMINATED:
                self.full_sp.pop(sp)
        # Check finished, add the new skyline path.
        self.full_sp[tuple(path)] = temp_attrs

    def __attrs_in(self, path):
        edges_attrs = self.__edges_to_attrs(self.__split_to(path))
        return reduce(lambda a1, a2: aggregate(a1, a2), edges_attrs)

    def __split_to(self, path):
        return [(path[i], path[i+1]) for i in range(len(path[:-1]))]

    def __edges_to_attrs(self, edges):
        return map(lambda e: self.mag.attrs_between(e[0], e[1]), edges)
{'fraction_non_alphanumeric': 0.08688758522276835, 'fraction_numerical': 0.003805295703186935, 'mean_word_length': 2.3375661375661374, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5882223', 'n_tokens_mistral': 1862, 'n_tokens_neox': 1812, 'n_words': 506}