# from pylab import *
from numpy import *
import pandas as pd
import numpy as np
import operator
import math
# import matplotlib.pyplot as plt
import random
from openpyxl import Workbook
# import array

# 数据保存在.csv文件中
df_full = pd.read_excel('NLF_A_(90).xlsx',sheetname=0,header=None)
columns = list(df_full.columns)
features = columns[:len(columns)]
# class_labels = list(df_full[columns[-1]])
df = df_full[features]
print(df)
# 维度
num_attr = len(df.columns) - 1
# 分类数
k = 3
# 最大迭代数
MAX_ITER = 1000000
# 样本数
n = len(df)  # the number of row
# 模糊参数
m = 2.00


# 初始化模糊矩阵
def initializeMembershipMatrix():
    membership_mat = list()
    for i in range(n):
        random_num_list = [random.random() for i in range(k)]
        summation = sum(random_num_list)
        temp_list = [x / summation for x in random_num_list]  # 首先归一化
        membership_mat.append(temp_list)
    return membership_mat


# 计算类中心点
def calculateClusterCenter(membership_mat):
    cluster_mem_val = zip(*membership_mat)
    cluster_centers = list()
    cluster_mem_val_list = list(cluster_mem_val)
    for j in range(k):
        x = cluster_mem_val_list[j]
        xraised = [e ** m for e in x]
        denominator = sum(xraised)
        temp_num = list()
        for i in range(n):
            data_point = list(df.iloc[i])
            prod = [xraised[i] * val for val in data_point]
            temp_num.append(prod)
        numerator = map(sum, zip(*temp_num))
        center = [z / denominator for z in numerator]  # 每一维都要计算。
        cluster_centers.append(center)
    return cluster_centers


# 更新隶属度
def updateMembershipValue(membership_mat, cluster_centers):
    #    p = float(2/(m-1))
    data = []
    for i in range(n):
        x = list(df.iloc[i])  # 取出文件中的每一行数据
        data.append(x)
        distances = [np.linalg.norm(list(map(operator.sub, x, cluster_centers[j]))) for j in range(k)]
        # print('1',distances)
        for j in range(k):
            den = sum([math.pow(float(distances[j] / distances[c]), 2) for c in range(k)])
            membership_mat[i][j] = float(1 / den)
    return membership_mat, data


# 得到聚类结果
def getClusters(membership_mat):
    cluster_labels = list()
    for i in range(n):
        max_val, idx = max((val, idx) for (idx, val) in enumerate(membership_mat[i]))
        cluster_labels.append(idx)
    return cluster_labels


def fuzzyCMeansClustering():
    # 主程序
    membership_mat = initializeMembershipMatrix()
    curr = 0
    membership_mat_old = np.zeros((n,k))
    while curr <= MAX_ITER:  # 最大迭代次数
        print('step',curr)
        cluster_centers = calculateClusterCenter(membership_mat)
        membership_mat, data = updateMembershipValue(membership_mat, cluster_centers)
        cluster_labels = getClusters(membership_mat)
        membership_mat_new = np.array(membership_mat)
        print('error',np.sum(membership_mat_new-membership_mat_old))
        if abs(np.sum(membership_mat_new-membership_mat_old)) < 0.0000000000000001:#18
            print('隶属度',membership_mat)
            break
        else:
            curr += 1
        membership_mat_old = membership_mat_new
    return cluster_labels, cluster_centers, data, membership_mat


def xie_beni(membership_mat, center, data):
    sum_cluster_distance = 0
    min_cluster_center_distance = inf
    for i in range(k):
        for j in range(n):
            sum_cluster_distance = sum_cluster_distance + membership_mat[j][i] ** 2 * sum(
                power(data[j, :] - center[i, :], 2))  # 计算类一致性
    for i in range(k - 1):
        for j in range(i + 1, k):
            cluster_center_distance = sum(power(center[i, :] - center[j, :], 2))  # 计算类间距离
            if cluster_center_distance < min_cluster_center_distance:
                min_cluster_center_distance = cluster_center_distance
    return sum_cluster_distance / (n * min_cluster_center_distance)


labels, centers, data, membership = fuzzyCMeansClustering()
print(labels)
print(centers)
center_array = array(centers)
labels = np.matrix(labels)
label = np.array(labels).T
print(label.shape)
book = Workbook()
sheet = book.create_sheet('Sheet', index=0)
[w, r] = label.shape
for i in range(w):
    for j in range(r):
        sheet.cell(row=i + 1, column=j + 1, value=label[i][j])
book.save('label_NLF_A(90).xlsx')
datas = array(data)

print("聚类有效性：",xie_beni(membership,center_array,datas))