import networkx as nx
from collections import deque
from itertools import chain, islice, combinations


class KCliquePercolation:
    def __init__(self, graph, edges_weight, k, threshold):
        self.graph = graph
        self.edges_weight = edges_weight
        self.k = k
        self.threshold = threshold
        self.g = None
        print 'kclique_percolation: initialization ...'

    def build_graph(self):
        self.g = nx.Graph()
        self.g.add_weighted_edges_from(self.edges_weight)

    def enumerate_all_cliques(self):
        # https://networkx.github.io/documentation/development/_modules/networkx/algorithms/clique.html#enumerate_all_cliques
        print 'enumerate_all_cliques ...'
        index = {}
        nbrs = {}
        for u in self.g:
            index[u] = len(index)
            # Neighbors of u that appear after u in the iteration order of G.
            nbrs[u] = {v for v in self.g[u] if v not in index}

        queue = deque(([u], sorted(nbrs[u], key=index.__getitem__)) for u in self.g)
        # Loop invariants:
        # 1. len(base) is nondecreasing.
        # 2. (base + cnbrs) is sorted with respect to the iteration order of G.
        # 3. cnbrs is a set of common neighbors of nodes in base.
        while queue:
            base, cnbrs = map(list, queue.popleft())
            yield base
            for i, u in enumerate(cnbrs):
                # Use generators to reduce memory consumption.
                queue.append((chain(base, [u]),
                              filter(nbrs[u].__contains__,
                                     islice(cnbrs, i + 1, None))))

    def get_geometric_mean(self, weights):
        multiplication = 1
        for weight in weights:
            multiplication = multiplication * weight

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

        return round(gmean, 5)

    def find_weighted_kclique(self):
        print 'find_weighted_kclique ...'
        self.build_graph()
        cliques = list(self.enumerate_all_cliques())
        k_cliques = [clique for clique in cliques if len(clique) == self.k]
        valid_cliques = []
        for clique in k_cliques:
            weights = []
            for u, v in combinations(clique, 2):
                reduced_precision = round(self.g[u][v]['weight'], 5)
                weights.append(reduced_precision)
            gmean = self.get_geometric_mean(weights)
            if gmean > self.threshold:
                valid_cliques.append(frozenset(clique))

        return valid_cliques

    def get_kclique_percolation(self):
        print 'get_kclique_percolation ...'
        cliques = self.find_weighted_kclique()
        percolation_graph = nx.Graph()
        percolation_graph.add_nodes_from(cliques)

        # Add an edge in the percolation graph for each pair of cliques that percolate
        for clique1, clique2 in combinations(cliques, 2):
            if len(clique1.intersection(clique2)) >= (self.k - 1):
                percolation_graph.add_edge(clique1, clique2)

        # Get all connected component in percolation graph
        kclique_percolation = []
        for component in nx.connected_components(percolation_graph):
            kclique_percolation.append(frozenset.union(*component))

        # set cluster id
        cluster_id = 0
        for cluster in kclique_percolation:
            for node in cluster:
                self.graph.node[node]['cluster'] = cluster_id
            cluster_id += 1

        return kclique_percolation

@@ -338,55 +338,245 @@
     
-print 'kclique_percolation: initialization ...'
+self.kcliques = None%0A        self.valid_kcliques = %5B%5D%0A        print 'kclique_percolation: initialization ...'%0A%0A    def get_kcliques(self):%0A        return self.kcliques%0A%0A    def get_valid_kcliques(self):%0A        return self.valid_kcliques
 %0A%0A  
@@ -2285,32 +2285,38 @@
 graph()%0A        
+self.k
 cliques = list(s
@@ -2386,16 +2386,22 @@
 ique in 
+self.k
 cliques 
@@ -2430,35 +2430,8 @@
 .k%5D%0A
-        valid_cliques = %5B%5D%0A
     
@@ -2760,22 +2760,28 @@
         
+self.
 valid_
+k
 cliques.
@@ -2822,22 +2822,28 @@
  return 
+self.
 valid_
+k
 cliques%0A

Add setter and getter for individual k-clique and valid cliques