<commit_before>from itertools import combinations
from operator import itemgetter


class ClusterUtility(object):
    """A class contains some utilities to do clustering algorithm.
    """
    @staticmethod
    def get_geometric_mean(weights):
        """Get geometric mean or intensity in a clique. A clique can be a k-clique or maximal clique.

        Parameters
        ----------
        weights : list[float]
            List of edge weight in a clique.

        Returns
        -------
        gmean   : float
            Geometric mean of given edge weights.
        """
        multiplication = 1
        for weight in weights:
            multiplication *= weight

        gmean = 0.0
        if multiplication > 0.0:
            k = float(len(weights))
            gmean = multiplication ** (1 / k)

        gmean = round(gmean, 5)
        return gmean

    @staticmethod
    def get_weighted_cliques(graph, cliques, threshold):
        """Get weighted cliques based on given intensity threshold.

        A clique which its weight are less then threshold is omiited.
        This procedure will filter unsignificant cliques.

        Parameters
        ----------
        graph       : graph
            A graph to check for its weighted cliques.
        cliques     : list[frozenset]
            List of clique list found.
        threshold   : float
            Intensity (geometric mean) threshold.

        Returns
        -------
        weighted_cliques    : list[list]
            List of clique with significant weight.
        """
        weighted_kcliques = []
        for clique in cliques:
            weights = []
            for u, v in combinations(clique, 2):
                reduced_precision = round(graph[u][v][0]['weight'], 5)
                weights.append(reduced_precision)
            gmean = ClusterUtility.get_geometric_mean(weights)

            if gmean > threshold:
                weighted_kcliques.append(frozenset(clique))

        return weighted_kcliques

    @staticmethod
    def set_cluster_id(graph, clusters):
        """Set incremental cluster identifier start from 0.

        Parameters
        ----------
        graph       : graph
            Graph to be set for its cluster id.
        clusters    : dict[list]
            Dictionary contains list of node in a particular cluster.
        """
        for cluster_id, cluster in clusters.iteritems():
            for node in cluster:
                graph.node[node]['cluster'] = cluster_id

    @staticmethod
    def set_cluster_label_id(graph, clusters, original_logs, analysis_dir):
        """Get all logs per cluster, get most dominant cluster label, and write clustering result to file.

        Parameters
        ----------
        graph           : graph
            Graph to be analyzed.
        clusters        : dict[list]
            Dictionary contains sequence of nodes in all clusters.
        original_logs   :
            List of event logs.
        analysis_dir    : str
            Path to save the analysis result.

        References
        ----------
        .. [1] <NAME>, <NAME> & <NAME>, Evaluation of clustering,
               in Introduction to Information Retrieval, 2008, Cambridge University Press.
               http://nlp.stanford.edu/IR-book/html/htmledition/evaluation-of-clustering-1.html
        """
        new_cluster_member_label = {}   # store individiual cluster id for each cluster member
        dominant_cluster_labels = {}    # store dominant cluster label from all clusters
        cluster_labels = ['accepted password', 'accepted publickey', 'authentication failure', 'check pass',
                          'connection closed', 'connection reset by peer', 'did not receive identification string',
                          'failed password', 'ignoring max retries', 'invalid user', 'pam adding faulty module',
                          'pam unable to dlopen', 'received disconnect', 'received signal',<commit_msg>Fix bug in docstring references Manning2008<commit_after>from itertools import combinations
from operator import itemgetter


class ClusterUtility(object):
    """A class contains some utilities to do clustering algorithm.
    """
    @staticmethod
    def get_geometric_mean(weights):
        """Get geometric mean or intensity in a clique. A clique can be a k-clique or maximal clique.

        Parameters
        ----------
        weights : list[float]
            List of edge weight in a clique.

        Returns
        -------
        gmean   : float
            Geometric mean of given edge weights.
        """
        multiplication = 1
        for weight in weights:
            multiplication *= weight

        gmean = 0.0
        if multiplication > 0.0:
            k = float(len(weights))
            gmean = multiplication ** (1 / k)

        gmean = round(gmean, 5)
        return gmean

    @staticmethod
    def get_weighted_cliques(graph, cliques, threshold):
        """Get weighted cliques based on given intensity threshold.

        A clique which its weight are less then threshold is omiited.
        This procedure will filter unsignificant cliques.

        Parameters
        ----------
        graph       : graph
            A graph to check for its weighted cliques.
        cliques     : list[frozenset]
            List of clique list found.
        threshold   : float
            Intensity (geometric mean) threshold.

        Returns
        -------
        weighted_cliques    : list[list]
            List of clique with significant weight.
        """
        weighted_kcliques = []
        for clique in cliques:
            weights = []
            for u, v in combinations(clique, 2):
                reduced_precision = round(graph[u][v][0]['weight'], 5)
                weights.append(reduced_precision)
            gmean = ClusterUtility.get_geometric_mean(weights)

            if gmean > threshold:
                weighted_kcliques.append(frozenset(clique))

        return weighted_kcliques

    @staticmethod
    def set_cluster_id(graph, clusters):
        """Set incremental cluster identifier start from 0.

        Parameters
        ----------
        graph       : graph
            Graph to be set for its cluster id.
        clusters    : dict[list]
            Dictionary contains list of node in a particular cluster.
        """
        for cluster_id, cluster in clusters.iteritems():
            for node in cluster:
                graph.node[node]['cluster'] = cluster_id

    @staticmethod
    def set_cluster_label_id(graph, clusters, original_logs, analysis_dir):
        """Get all logs per cluster, get most dominant cluster label, and write clustering result to file [Manning2008]_.

        Parameters
        ----------
        graph           : graph
            Graph to be analyzed.
        clusters        : dict[list]
            Dictionary contains sequence of nodes in all clusters.
        original_logs   :
            List of event logs.
        analysis_dir    : str
            Path to save the analysis result.

        References
        ----------
        .. [Manning2008] <NAME>, <NAME> & <NAME>, Evaluation of clustering,
                         in Introduction to Information Retrieval, 2008, Cambridge University Press.
                         http://nlp.stanford.edu/IR-book/html/htmledition/evaluation-of-clustering-1.html
        """
        new_cluster_member_label = {}   # store individiual cluster id for each cluster member
        dominant_cluster_labels = {}    # store dominant cluster label from all clusters
        cluster_labels = ['accepted password', 'accepted publickey', 'authentication failure', 'check pass',
                          'connection closed', 'connection reset by peer', 'did not receive identification string',
                          'failed password', 'ignoring max retries', 'invalid user', 'pam adding faulty module',
                          'pam unable to dlopen', 'received disconnect', 'received signal',
{'fraction_non_alphanumeric': 0.08255393440578626, 'fraction_numerical': 0.005611672278338945, 'mean_word_length': 1.7993019197207678, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, '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': '1441765', 'n_tokens_mistral': 2013, 'n_tokens_neox': 1878, 'n_words': 683}