{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b149ac1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import math\n",
    "import scipy\n",
    "import warnings\n",
    "import os\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "import numpy as np\n",
    "from numpy import linalg as npla\n",
    "import scipy.spatial.distance\n",
    "from scipy.sparse import csgraph\n",
    "import sklearn\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.metrics import silhouette_score\n",
    "from itertools import permutations\n",
    "from sklearn.metrics.cluster import adjusted_mutual_info_score\n",
    "import time\n",
    "def construct_L(X):\n",
    "    n = len(X[:, 0])\n",
    "    Dist_temp = scipy.spatial.distance.pdist(X, 'euclidean')\n",
    "    W = np.zeros([n,n])\n",
    "    Dist = scipy.spatial.distance.squareform(Dist_temp)\n",
    "    sigma = np.amax(Dist)\n",
    "    for i in range(0,n):\n",
    "        for j in range(0,n):\n",
    "            W[i,j] = np.exp((-Dist[i,j]**2)/(sigma*sigma))\n",
    "    L = csgraph.laplacian(W,normed = True)\n",
    "    L_shift = (2*np.eye(n))-L\n",
    "    return (L_shift)\n",
    "def eigen(A):\n",
    "    eigenValues, eigenVectors = npla.eigh(A)\n",
    "    idx = np.argsort(eigenValues)[::-1]\n",
    "    eigenValues = eigenValues[idx]\n",
    "    eigenVectors = eigenVectors[:,idx]\n",
    "    return (eigenValues, eigenVectors)\n",
    "def orthogonalize(U, eps=1e-15):\n",
    "    n = len(U[0])\n",
    "    V = U.T\n",
    "    for i in range(n):\n",
    "        prev_basis = V[0:i]\n",
    "        coeff_vec = np.dot(prev_basis, V[i].T)\n",
    "        V[i] -= np.dot(coeff_vec, prev_basis).T\n",
    "        if npla.norm(V[i]) < eps:\n",
    "            V[i][V[i] < eps] = 0\n",
    "        else:\n",
    "            V[i] /= npla.norm(V[i])\n",
    "    return V.T\n",
    "def acc_clusters(pred_labels, true_labels):\n",
    "    pred_labels, true_labels = np.array(pred_labels), np.array(true_labels)\n",
    "    assert pred_labels.ndim == 1 == true_labels.ndim\n",
    "    assert len(pred_labels) == len(true_labels)\n",
    "    cluster_names = np.unique(pred_labels)\n",
    "    accuracy = 0\n",
    "    perms = np.array(list(permutations(np.unique(true_labels))))\n",
    "    remapped_labels = true_labels\n",
    "    for perm in perms:\n",
    "        flipped_labels = np.zeros(len(true_labels))\n",
    "        for label_index, label in enumerate(cluster_names):\n",
    "            flipped_labels[pred_labels == label] = perm[label_index]\n",
    "        testAcc = np.sum(flipped_labels == true_labels) / len(true_labels)\n",
    "        if testAcc > accuracy:\n",
    "            accuracy = testAcc\n",
    "            remapped_labels = flipped_labels\n",
    "    return accuracy\n",
    "a = next(os.walk('./'))[1]\n",
    "dataset_list = []\n",
    "for diter in range(len(a)):\n",
    "    start = time.time()\n",
    "    dataset_list.append(a[diter])\n",
    "    data_name = a[diter]\n",
    "    modality_list = next(os.walk('./'+dataset_list[diter]))[1]\n",
    "    data = []\n",
    "    for miter in range(len(modality_list)):\n",
    "        data_modality = dataset_list[diter]+'/'+modality_list[miter]+'/'\n",
    "        cluster_data = data_modality+\"clustering.txt\"\n",
    "        cluster_file = open(cluster_data,\"r\")\n",
    "        clus_data = np.asarray([[float(num) for num in line.split()] for line in cluster_file])\n",
    "        data.append(clus_data)\n",
    "    ground_truth_file = open(dataset_list[diter]+'/cluster_ground_truth.txt',\"r\")\n",
    "    ground_truth = np.asarray([[float(num) for num in line.split()] for line in ground_truth_file])\n",
    "    groundtruth = np.empty(len(ground_truth))\n",
    "    groundtruth = np.empty(len(ground_truth))\n",
    "    for i in range(len(ground_truth)):\n",
    "        groundtruth[i] =int(ground_truth[i,0])\n",
    "    v = len(data)\n",
    "    rank_lower = int(np.ceil(len(np.unique(ground_truth))/len(data)))\n",
    "    rank_upper = int(np.ceil(len(ground_truth)/len(data)))\n",
    "    eigval = []\n",
    "    eigvec = []\n",
    "    eigenVector = []\n",
    "    laplacian = []\n",
    "    view_acc_order = []\n",
    "    weight_init = []\n",
    "    single_view_rank_table = np.empty([len(data),(rank_upper-rank_lower)+1])\n",
    "    for view in range(len(data)):\n",
    "        L = construct_L(data[view])\n",
    "        sveigval,sveigvec = eigen(L)\n",
    "        eigval.append(sveigval[1])\n",
    "        eigvec.append(sveigvec)\n",
    "        laplacian.append(L)\n",
    "        for rank in range(rank_lower,rank_upper+1):\n",
    "            eigenvec = sveigvec[:,0:rank+1]\n",
    "            kmeans = KMeans(n_clusters=len(np.unique(groundtruth))).fit(eigenvec)\n",
    "            cluslabel=kmeans.labels_\n",
    "            sil_view = silhouette_score(data[view],cluslabel)+1\n",
    "            sil_view = 0.25*sveigval[1]*sil_view\n",
    "            single_view_rank_table[view,rank-rank_lower] = sil_view\n",
    "        weight_view = np.argmax(single_view_rank_table[view])+1+rank_lower\n",
    "        temp = eigvec[view]\n",
    "        eigenVector.append(temp[:,0:(weight_view)])\n",
    "        weight_init.append(np.max(single_view_rank_table[view])/(weight_view))\n",
    "    view_order = weight_init\n",
    "    view_descend = np.multiply(view_order,-1)\n",
    "    indices = (np.argsort(view_descend))\n",
    "    u = (eigenVector[indices[0]])\n",
    "    for i in range(len(data)-1):\n",
    "        utemp = eigenVector[indices[i+1]]\n",
    "        s = u.T@utemp\n",
    "        p = u@s\n",
    "        q = utemp-p\n",
    "        u = np.concatenate((u,q),axis=1)\n",
    "        u,R = np.linalg.qr(u)\n",
    "    H = np.empty_like(u.T@laplacian[indices[0]]@u)\n",
    "    w = weight_init\n",
    "    index = indices.astype(float)\n",
    "    damp = np.ones_like(w)\n",
    "    damp = np.ones_like(w)\n",
    "    for i in range(len(indices)):\n",
    "        temp = 1.25**(i+1)\n",
    "        damp[indices[i]] = 1.0/temp \n",
    "    W = np.multiply(w,damp)\n",
    "    w_prime = W/np.sum(W)\n",
    "    for i in range(len(data)):\n",
    "        htemp = u.T@laplacian[i]@u\n",
    "        H = H+(w_prime[i]*htemp)\n",
    "    P,R = eigen(H)\n",
    "    V = u@R\n",
    "    w_new = w_prime\n",
    "    for witer in range(1,2):\n",
    "        H_learned = np.zeros_like(H)\n",
    "        t = np.zeros(len(data))\n",
    "        for viter in range(len(data)):\n",
    "            tr = V.T@laplacian[indices[viter]]@V\n",
    "            T = W[indices[viter]]\n",
    "            t[indices[viter]] = T\n",
    "        for viter in range(len(data)):\n",
    "            w_new[viter]=math.exp(t[viter])\n",
    "        W_new = w_new/np.sum(w_new)\n",
    "        for viter in range(len(data)):\n",
    "            hl_temp = u.T@laplacian[viter]@u\n",
    "            H_learned = H_learned+(W_new[viter]*hl_temp)\n",
    "        P1,R1 = eigen(H_learned)\n",
    "        V = u@R1\n",
    "    silhoutte_list = []\n",
    "    acc_list = []\n",
    "    ami_list =[]\n",
    "    ari_list =[]\n",
    "    sil_check = -1\n",
    "    labels = []\n",
    "    for k in range(len(np.unique(groundtruth)),u.shape[1]):\n",
    "        V_new = V[:,0:k]\n",
    "        kmeans = KMeans(n_clusters=len(np.unique(groundtruth))).fit(V_new)\n",
    "        label1=kmeans.labels_\n",
    "        silhoutte = silhouette_score(V_new,label1)\n",
    "        acc = acc_clusters(label1,groundtruth)\n",
    "        nmi = adjusted_mutual_info_score(groundtruth,label1)\n",
    "        ari = sklearn.metrics.adjusted_rand_score(label1, groundtruth)\n",
    "        silhoutte_list.append(silhoutte)\n",
    "        acc_list.append(acc)\n",
    "        ami_list.append(nmi)\n",
    "        ari_list.append(ari)\n",
    "        if sil_check<silhoutte:\n",
    "            sil_check = silhoutte\n",
    "            labels = label1\n",
    "    sil = np.round(np.max(silhoutte_list),4)\n",
    "    K = np.argmax(silhoutte_list)\n",
    "    accu = np.round(acc_list[K],4)\n",
    "    AMI = np.round(ami_list[K],4)\n",
    "    ARI = np.round(ari_list[K],4)\n",
    "    V_prime = V[:,0:len(np.unique(groundtruth))+K+1]\n",
    "    stop = time.time()\n",
    "    V_mod = np.append(V_prime,ground_truth,axis =1)\n",
    "    "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
