import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from stochasticBlockModel import SBM

x = range(5,150,25)
y_sparse = []
y_dense = []

for i in x: # sparse graph
	n_vertices = i  # number of vertices
	n_communities = 2  # number of communities
	cin = 15
	cout = 5
	probability_matrix = (1.0/n_vertices)*(np.full((n_communities,n_communities), cout) + np.diag([cin-cout]*n_communities))
	sbm = SBM(n_vertices, n_communities, probability_matrix)
	y_sparse.append(sbm.average_degree)

for i in x: # dense graph
	n_vertices = i  # number of vertices
	n_communities = 2  # number of communities
	cin = 0.7
	cout = 0.3
	probability_matrix = np.full((n_communities,n_communities), cout) + np.diag([cin-cout]*n_communities)
	sbm = SBM(n_vertices, n_communities, probability_matrix)
	y_dense.append(sbm.average_degree)

plt.xlim(0,x[-1])
plt.xlabel("Number of vertices")
plt.ylabel("Average degree")
plt.plot(x,y_sparse, 'r', label="sparse")
def main():
    #----------------------------------------------------------------------
    # Stochastic block model parameters
    #----------------------------------------------------------------------
    n_vertices = 100  # number of vertices
    n_communities = 2  # number of communities

    # cin > cout is referred to as the assortative case
    # cout > cin is called the disassortative case
    cin = 15
    cout = 5
    probability_matrix = (1.0/n_vertices)*(np.full((n_communities,n_communities), cout) + np.diag([cin-cout]*n_communities)) # matrix of edge probabilities (to generate a sparse graph)
    sbm = SBM(n_vertices, n_communities, probability_matrix)
    print("Average degree: {}, abs(cin - cout): {}, n_commuties*sqrt(c): {}".format(sbm.average_degree, abs(cin-cout), n_communities*np.sqrt(sbm.average_degree)))

    #----------------------------------------------------------------------
    # Draw generated graph and print communities
    #----------------------------------------------------------------------
    color_map = np.array(['cyan', 'red', 'yellow', 'magenta', 'blue', 'green', 'white'])
    for i in xrange(n_communities):
        indices = [j+1 for j, x in enumerate(sbm.community_labels) if x == i]
        print("Community C{}, n{} = {} vertices, color: {}, E[di] = {}".format(i, i, sbm.n_per_community[i], color_map[i], sbm.expected_degrees[i]))

    if n_vertices > PLOT_MAX_NODES: print("Can't draw graph if number of vertices is too big")
    else:
        G = nx.from_numpy_matrix(sbm.adjacency_matrix) # generate networkx graph
        labels = {key: key+1 for key in xrange(n_vertices)} # vertices numbers
        node_color = color_map[sbm.community_labels]
        plt.title("Generated graph using Stochastic block model\n{} nodes and {} communities".format(n_vertices, n_communities))
        nx.draw(G, labels=labels, node_color=node_color, font_size=10)
        plt.figure()

    #----------------------------------------------------------------------
    # Spectral clustering
    #----------------------------------------------------------------------
    n_clusters = 2
    if n_clusters != n_communities:
        print("Number of clusters ({}) is not equal to number of communities generated by the SBM ({})!".format(n_clusters, n_communities))
    spectral_labels, eigvals, eigvects, W = SpectralClustering(n_clusters, BetheHessian(sbm.adjacency_matrix), "BetheHessian") # spectral clustering
    well_placed_vertices = pg.permutation_calculator(sbm.community_labels, spectral_labels, n_clusters)
    print("Spectral clustering accuracy: " + str(100*well_placed_vertices/n_vertices) + "%")
    print("Normalized Mutual Information: " + str(normalized_mutual_info_score(sbm.community_labels, spectral_labels)))

    # Eigenvalues and eigenvectors
    plt.title("Histogram of matrix eigenvalues")
    plt.hist(eigvals, bins=100) # plot histogram of the eigenvalues
    if n_clusters <= 2:
        plt.figure()
        plt.title("Eigenvectors corresponding to the {} smallest eigenvalues".format(n_clusters))
        plt.plot(W[:,0], W[:,1], 'o', markersize=5) # plot eigenvectors corresponding to the 'n_clusters' smallest eigenvalues

        plt.figure()
        plt.title("Kmeans, n_vertices = {}".format(n_vertices))
        for i in xrange(n_clusters):
            ds = W[np.where(spectral_labels == i)]
            plt.plot(ds[:,0], ds[:,1], color=color_map[i], marker='o', markersize=5, ls='')

    if n_vertices <= PLOT_MAX_NODES:
        plt.figure()
        plt.title("Detected communities")
        nx.draw(G, labels=labels, node_color=color_map[spectral_labels], font_size=10)
    plt.show()
    pass