Random_walks/main.ipynb
2021-06-28 11:16:57 +02:00

95 KiB

import sys
import numpy as np
import networkx as nx
import sklearn.preprocessing
from matplotlib.pylab import show, cm, axis

def draw(G, A, cluster_map):

    graph = nx.Graph(G)
    clust_map = {}
    for k, vals in cluster_map.items():
        for v in vals:
            clust_map[v] = k

    colors = []
    for i in range(len(G.nodes())):
        colors.append(clust_map.get(i, 100))
    
    nx.draw_networkx(graph,node_color =colors,linewidths=7)
    axis("off")
    show(block=False)

def normalize(A):
#   Normalize the columns of the given matrix
    return sklearn.preprocessing.normalize(A, norm="l1", axis=0)

def inflate(A, inflate_factor):
#   Apply cluster inflation to the given matrix by raising each element to the given power.
    return normalize(np.power(A, inflate_factor))

def expand(A, expand_factor):
#   Apply cluster expansion to the given matrix by raising the matrix to the given power.
    return np.linalg.matrix_power(A, expand_factor)

def add_diag(A, mult_factor):
#    Add self-loops to the matrix by setting the diagonal to 1
    return A + mult_factor * np.identity(A.shape[0])

def get_clusters(A):
    clusters = []
    for i, r in enumerate((A>0).tolist()): # Pętla po każdym node, jeśli nie jest listą samych                              
                                           # False to dodajemy do tablicy klastrów
        if r[i]:
            clusters.append(A[i,:]>0)
    clust_map  ={}
    for cn , c in enumerate(clusters):                    # Pętla po tablicy klastrów i zamiana wartości True na dany węzęł
        for x in  [ i for i, x in enumerate(c) if x ]:
            clust_map[cn] = clust_map.get(cn, [])  + [x]
    return clust_map

def stop(M, i):
    if i%5==4:
        m = np.max( M**2 - M) - np.min( M**2 - M)
        if m==0:
            print("Stop at iteration %s" % i)
            return True
    return False


def mcl(M, max_loop = 10):
    expand_factor = 2
    inflate_factor = 2
    M = add_diag(M, 1)
    M = normalize(M)
    
    for i in range(max_loop):
        M = expand(M, expand_factor)
        M = inflate(M, inflate_factor)
        
        if stop(M, i): break

    clusters = get_clusters(M)
    return M, clusters

def networkx_mcl(G, max_loop = 50):
    A = nx.adjacency_matrix(G)
    return mcl(np.array(A.todense()), max_loop)


def calculate_and_draw(Graph): 
    M = nx.to_numpy_matrix(Graph)
    print(" number of nodes: %s\n" % M.shape[0])
    
    M, clusters = networkx_mcl(Graph)
    [print(key, ": ", value) for key, value in clusters.items()]
    
    draw(Graph, M, clusters)


# https://networkx.org/documentation/stable/reference/generators.html
G_bin = nx.binomial_tree(4) # Returns the Binomial Tree of order n.
calculate_and_draw(G_bin)
 number of nodes: 16

Stop at iteration 14
0 :  [0, 1]
1 :  [2, 3]
2 :  [4, 5]
3 :  [6, 7]
4 :  [8, 9]
5 :  [10, 12]
6 :  [11, 13]
7 :  [14, 15]
G_balanced = nx.balanced_tree(2,3) # Returns the perfectly balanced r-ary tree of height h.
calculate_and_draw(G_balanced)
 number of nodes: 15

0 :  [0, 1, 3, 7, 8]
1 :  [0, 1, 4, 9, 10]
2 :  [0, 2, 5, 11, 12]
3 :  [0, 2, 6, 13, 14]
G_balanced = nx.balanced_tree(2,4) # Returns the perfectly balanced r-ary tree of height h.
calculate_and_draw(G_balanced)
 number of nodes: 31

0 :  [0, 1]
1 :  [0, 2]
2 :  [3, 7, 15, 16]
3 :  [3, 8, 17, 18]
4 :  [4, 9, 19, 20]
5 :  [4, 10, 21, 22]
6 :  [5, 11, 23, 24]
7 :  [5, 12, 25, 26]
8 :  [6, 13, 27, 28]
9 :  [6, 14, 29, 30]
G_gn = nx.gn_graph(10) # (Directed) Returns the growing network (GN) digraph with n nodes.
calculate_and_draw(G_gn)
 number of nodes: 10

0 :  [0, 1]
1 :  [0, 2]
2 :  [0, 6]
3 :  [5, 7]
4 :  [3, 4, 8]
5 :  [5, 9]
G_tree = nx.random_tree(10) # Returns a uniformly random tree on n nodes.
calculate_and_draw(G_tree)
 number of nodes: 10

Stop at iteration 19
0 :  [1, 2, 6]
1 :  [3]
2 :  [4, 5, 8, 9]
3 :  [0, 7]