
import numpy as np
import matplotlib.pyplot as plt
#from sklearn.datasets import make_blobs
from sklearn import datasets

import random
from math import sqrt
from math import pow

DIM_N = 4
POINT_N = 300
CLUST_N = 3

#data, targ, centers = datasets.make_blobs(n_samples=POINT_N, n_features=DIM_N, centers=CLUST_N, center_box=(-2.0, 2.0), shuffle=True, random_state=42, return_centers=True)
#data, targ = datasets.make_blobs(n_samples=POINT_N, n_features=DIM_N, centers=CLUST_N, center_box=(-2.0, 2.0), shuffle=True, random_state=42)
data, targ = datasets.load_iris(return_X_y=True)
POINT_N = len(data)

class POINT:
    def __init__(self, cl, X):
        self.clust = cl
        self.X = X

class CLUSTER(POINT):
    def __init__(self, cl, X):
        POINT.__init__(self, cl, X)
        self.N = 0
    def Dist(self, p):
        return sqrt( ((self.X - p.X)*(self.X - p.X)).sum() )
    def Eval_Center(self, P, M):
        self.N = 0
        self.X = np.zeros((DIM_N))
        a = 0.0
        for i in range(POINT_N):
            if P[i].clust == self.clust:
                self.N += 1
                self.X = self.X + P[i].X*M[i][self.clust]
                a = a + M[i][self.clust]
        self.X = self.X/a

Color = ['green', 'blue', 'magenta', 'orange']
for i in range(POINT_N):
    plt.scatter(data[i][0], data[i][1], c=Color[targ[i]], s=20)
plt.show()

Cl = [CLUSTER(i, [2.0*random.random()-1.0 for j in range(DIM_N)]) for i in range(CLUST_N)]

PP = [POINT(CLUST_N, data[i]) for i in range(POINT_N)]

QU = 0.3

for nn in range(10):
    CC = [POINT(i, Cl[i].X) for i in range(CLUST_N)]

    Mu = np.empty((POINT_N,CLUST_N))
    for i in range(POINT_N):
        a = 0.0
        for k in range(CLUST_N):
            Mu[i][k] = pow(Cl[k].Dist(PP[i]), -1.0/QU)
            a = a + Mu[i][k]
        for k in range(CLUST_N):
            Mu[i][k] = Mu[i][k]/a

    for i in range(POINT_N):
        r = random.random()
        a = 0.0
        for n in range(CLUST_N):
            a += Mu[i][n]
            if r < a:
                PP[i].clust = n
                break;

    for k in range(CLUST_N):
        Cl[k].Eval_Center(PP, Mu)

    for p in PP:
        plt.scatter(p.X[0], p.X[1], c=Color[p.clust], s=20)
    for cl in Cl:
        plt.scatter(CC[cl.clust].X[0], CC[cl.clust].X[1], c='cyan', marker="*")
        plt.scatter(cl.X[0], cl.X[1], c='red', marker="*")
    plt.show()
