├── MDPC(+)-master ├── data │ ├── A3.mat │ ├── Agg.mat │ ├── D31.mat │ ├── R15.mat │ ├── s3.mat │ ├── Flame.mat │ ├── jain.mat │ ├── compound.mat │ ├── spiral.mat │ └── threecircles.mat └── code │ ├── dijkstra │ ├── dijkstra1.mexa64 │ ├── dijkstra1.mexw64 │ ├── dijkstra1.mexmaci64 │ ├── dijkstra.m │ └── dijkstra1.cpp │ ├── Evaluation.m │ ├── main.m │ ├── resultshow.m │ ├── MDPC_Plus.m │ ├── GetAmi.m │ └── Library.m └── README.md /MDPC(+)-master/data/A3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/A3.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/Agg.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/Agg.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/D31.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/D31.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/R15.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/R15.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/s3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/s3.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/Flame.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/Flame.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/jain.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/jain.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/compound.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/compound.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/spiral.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/spiral.mat -------------------------------------------------------------------------------- /MDPC(+)-master/data/threecircles.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/data/threecircles.mat -------------------------------------------------------------------------------- /MDPC(+)-master/code/dijkstra/dijkstra1.mexa64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/code/dijkstra/dijkstra1.mexa64 -------------------------------------------------------------------------------- /MDPC(+)-master/code/dijkstra/dijkstra1.mexw64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/code/dijkstra/dijkstra1.mexw64 -------------------------------------------------------------------------------- /MDPC(+)-master/code/dijkstra/dijkstra1.mexmaci64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Guanjunyi/MDPCplus/HEAD/MDPC(+)-master/code/dijkstra/dijkstra1.mexmaci64 -------------------------------------------------------------------------------- /MDPC(+)-master/code/Evaluation.m: -------------------------------------------------------------------------------- 1 | function [AMI,ARI,FMI] = Evaluation(cl,answer) 2 | import java.util.LinkedList 3 | import Library.* 4 | if~isempty(answer) 5 | AMI=GetAmi(answer,cl); 6 | ARI=GetAri(answer,cl); 7 | FMI=GetFmi(answer,cl); 8 | else 9 | AMI=nan; 10 | ARI=nan; 11 | FMI=nan; 12 | end -------------------------------------------------------------------------------- /MDPC(+)-master/code/main.m: -------------------------------------------------------------------------------- 1 | % Please kindly cite the paper Junyi Guan, Sheng li, Xiongxiong He, and Jiajia Chen 2 | %"Clustering by fast detection of main density peaks within a peak digraph" 3 | % Information Sciences,2023 4 | 5 | % The code was written by Junyi Guan in 2022. 6 | clear;close all;clc; 7 | %% load dataset 8 | load data/Agg 9 | data_with_lable = Agg; 10 | %% deduplicate data 11 | data_x = unique(data_with_lable,'rows'); 12 | if size(data_x,1) ~= size(data_with_lable,1) 13 | data_with_lable = data_x; 14 | end 15 | lable = data_with_lable(:,end); 16 | data = data_with_lable(:,1:end-1); 17 | %% data preprocessing 18 | data=(data-min(data))./(max(data)-min(data));%% data normalization 19 | data(isnan(data))=0; 20 | %% MDPC+ clustering 21 | [CL,NC,centers,runtime] = MDPC_Plus(data); 22 | %% evaluation 23 | [AMI,ARI,FMI] = Evaluation(CL,lable); 24 | %% show result 25 | resultshow(data,CL,centers); 26 | %% clustering result 27 | result = struct; 28 | result.NC = NC; 29 | result.AMI = AMI; 30 | result.ARI = ARI; 31 | result.FMI = FMI; 32 | result.runtime = runtime; 33 | result -------------------------------------------------------------------------------- /MDPC(+)-master/code/dijkstra/dijkstra.m: -------------------------------------------------------------------------------- 1 | function [D,P] = dijkstra2( G, varargin ) 2 | 3 | % Runs Dijkstra's shortest path algorithm on a distance matrix. 4 | % 5 | % Runs Dijkstra's on the given SPARSE nxn distance matrix G, where missing 6 | % values mean no edge (infinite distance). Uses a Finonacci heap resulting 7 | % in fast computation. Finds the shortest path distance from every point 8 | % S(i) in the 1xp source vector S to every other point j, resulting in a 9 | % pxn distance matrix D. P(i,j) contains the second to last node on the 10 | % path from S(i) to j. If point j is not reachable from point S(i) then 11 | % D(i,j)=inf and P(i,j)=-1. 12 | % 13 | % USAGE 14 | % [D P] = dijkstra( G, [S] ) 15 | % 16 | % INPUT 17 | % G - sparse nxn distance matrix 18 | % S - 1xp array of source indices i 19 | % 20 | % OUPUT 21 | % D - pxn - shortest path lengths from S(i) to j 22 | % P - pxn - indicies of second to last node on path from S(i) to j 23 | % 24 | % EXAMPLE 25 | % n=11; G=sparse(n,n); for i=1:n-1, G(i,i+1)=1; end; G=G+G'; 26 | % [D,P] = dijkstra(G,5), % D=[4:-1:0 1:6]; P=[2:5 -1 5:10]; 27 | % 28 | % See also 29 | % 30 | % Piotr's Computer Vision Matlab Toolbox Version 3.20 31 | % Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] 32 | % Licensed under the Simplified BSD License [see external/bsd.txt] 33 | 34 | [D,P] = dijkstra1( G, varargin{:} ); 35 | -------------------------------------------------------------------------------- /MDPC(+)-master/code/resultshow.m: -------------------------------------------------------------------------------- 1 | function resultshow(data,CL,centers) 2 | 3 | PtSize = 2; 4 | 5 | NC = length(unique(CL)); 6 | label_set = unique(CL); 7 | 8 | 9 | [N,M] = size(data); 10 | 11 | figure('Position',[400 400 350 300]); 12 | cmap = UiGetColormap(NC); 13 | 14 | for i=1:NC 15 | l=label_set(i); 16 | if M~=3 17 | if l~=0 18 | scatter(data((CL==l),1),data((CL==l),2),PtSize+5,'o','filled','MarkerFaceColor',cmap(l,:),'MarkerEdgeColor',cmap(l,:)); 19 | else 20 | scatter(data((CL==l),1),data((CL==l),2),PtSize+50,'x','MarkerEdgeColor','k'); 21 | end 22 | else 23 | if l~=0 24 | scatter3(data((CL==l),1),data((CL==l),2),data((CL==l),3),PtSize+5,'o','filled','MarkerFaceColor',cmap(l,:),'MarkerEdgeColor',cmap(l,:)); 25 | else 26 | scatter3(data((CL==l),1),data((CL==l),2),data((CL==l),3),PtSize+5,'x','filled','MarkerEdgeColor','k'); 27 | end 28 | end 29 | hold on 30 | end 31 | 32 | 33 | for i=1:NC 34 | 35 | scatter(data(centers(i),1),data(centers(i),2),PtSize+200,'p','filled','k','MarkerEdgeColor','k'); 36 | hold on 37 | end 38 | 39 | 40 | 41 | set(gca,'XTickLabel',''); 42 | set(gca,'YTickLabel',''); 43 | set(gca,'ZTickLabel',''); 44 | if M~=3 45 | axis off 46 | end 47 | 48 | 49 | function [cmap]=UiGetColormap(NC) 50 | colormap jet 51 | cmap=colormap; 52 | cmap=cmap(round(linspace(1,length(cmap),NC+1)),:); 53 | cmap=cmap(1:end-1,:); 54 | 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MDPC+:Clustering by fast detection of main density peaks within a peak digraph 2 | 3 | which is published in Information Sciences, 2023. Doi: https://doi.org/10.1016/j.ins.2023.01.144 4 | 5 | Abstract: The well-known Density Peak Clustering algorithm (DPC) proposed a heuristic center detection idea, i.e., to find density peaks as cluster centers. Nevertheless, such a center detection idea cannot work well on multi-peak clusters of complex shapes. Besides, DPC needs the distances between data, making it prohibitively time-consuming. To overcome these problems, a Main Density Peak Clustering algorithm (MDPC+1)—clustering by fast detection of main density peaks within a peak digraph—is proposed, where a main density peak is the highest density peak in a cluster. MDPC+ can easily detect the real centers of multi-peak clusters based on its new center assumption. In MDPC+, the clustering problem is viewed as a graph cut problem and a specific graph structure is designed for non-peak and density peak allocation, respectively, so it can reasonably reconstruct clusters of complex shapes. Meanwhile, a satel- lite peak attenuation technique is embedded into MDPC+ to give it a high resistance to the interference of satellite peaks (i.e., non-center density peaks). Besides, MDPC+ only needs kNN distances of data as its input, so it is suitable for large datasets. Experimental results on both synthetic and real-world datasets demonstrate the superiority of MDPC+ in center detection, complex shape reconstruction, and running speed. 6 | -------------------------------------------------------------------------------- /MDPC(+)-master/code/MDPC_Plus.m: -------------------------------------------------------------------------------- 1 | % Please kindly cite the paper Junyi Guan, Sheng li, Xiongxiong He, and Jiajia Chen 2 | %"Clustering by fast detection of main density peaks within a peak digraph" 3 | % Information Sciences,2023 4 | 5 | % The code was written by Junyi Guan in 2022. 6 | function [CL,NC,centers,runtime] = MDPC_Plus(data,k) 7 | %% parameters 8 | [n,dim] = size(data); % n: the number of data points; d:dimensions 9 | alpha = 0.5; 10 | lambda = 2; 11 | if nargin<2 12 | k = round(sqrt(n)); %k: the number of neighbors 13 | end 14 | k_b = min(2*floor(log(n)),k); 15 | tic; 16 | 17 | %% Fast KNN based on Kd-tree (when dimension is not large than 10) 18 | if dim<=11;[knn,knn_dist] = knnsearch(data,data,'k',max(k,k_b)); 19 | else;DIST = squareform(pdist(data)); 20 | [knn_dist,knn] = sort(DIST,2); 21 | end 22 | 23 | %% KNN-based Density 24 | rho=sum(exp(-knn_dist(:,2:k)).^2,2)'; 25 | 26 | %% Allocation 27 | [~,OrdRho]=sort(rho,'descend'); 28 | 29 | %% The identification of local density peaks and sub-clusters, and center-association degree 30 | peaks = []; 31 | for i=1:n 32 | point = OrdRho(i); 33 | all_neigh=knn(point,2:k); 34 | all_neigh_dist = knn_dist(point,2:k); 35 | big_neigh = all_neigh(rho(all_neigh)>rho(point)); 36 | 37 | bb = (rho(all_neigh)-rho(point))./rho(all_neigh); 38 | dd = all_neigh_dist./all_neigh_dist(end); 39 | bb = bb(bb>0); 40 | dd = dd(bb>0); 41 | bb=(bb-min(bb))./(max(bb)-min(bb)); 42 | bb(isnan(bb))=0; 43 | dd=(dd-min(dd))./(max(dd)-min(dd)); 44 | dd(isnan(dd))=0; 45 | bb_dd = alpha*bb + (1-alpha)*dd; 46 | 47 | if length(bb)>0 48 | best_big_index = find(bb_dd == min(bb_dd)); 49 | best_big = big_neigh(best_big_index(1)); 50 | neigh = best_big; 51 | else 52 | neigh = []; 53 | end 54 | if neigh 55 | phi(point) = (abs(rho(neigh)-rho(point))/rho(neigh))^lambda; 56 | pn(point)=neigh; %pn:parent node 57 | else 58 | phi(point) = 0; 59 | peaks = [point peaks]; 60 | end 61 | end 62 | 63 | for i=1:n 64 | if pn(OrdRho(i)) 65 | denisty_deviation_cost_to_peak(OrdRho(i)) = denisty_deviation_cost_to_peak(pn(OrdRho(i))) + phi(OrdRho(i)); 66 | else 67 | denisty_deviation_cost_to_peak (OrdRho(i)) = 0; 68 | end 69 | end 70 | 71 | %% label initialization 72 | for i=1:n 73 | sub_l(i)=-1; %% sub_l:sub-cluster label 74 | end 75 | 76 | n_p = length(peaks);%% n_p:Number of peaks 77 | sub_l(peaks) = (1:n_p); 78 | for i=1:n 79 | if (sub_l(OrdRho(i))==-1) 80 | sub_l(OrdRho(i))=sub_l(pn(OrdRho(i))); 81 | end 82 | end 83 | %% edges matrix 84 | rho_peaks= rho(peaks); [~,OrdRho_peaks]=sort(rho_peaks,'descend'); 85 | edges = Inf*ones(n_p,n_p);% edges: edge matrix between subtrees(graph theory) 86 | for i=1:n 87 | BB = rho(i)*ones(1,k_b-1); 88 | CC = rho(knn(i,2:k_b)); 89 | denisty_deviation_cost_of_link_set = (abs(BB-CC)./max(BB,CC)).^lambda; 90 | for j = 2:k_b 91 | jj = knn(i,j); 92 | AA = denisty_deviation_cost_to_peak(i)+denisty_deviation_cost_to_peak(jj); 93 | if sub_l(i)~=sub_l(jj) & edges(sub_l(i),sub_l(jj))> AA 94 | if find(knn(jj,2:k)==i) 95 | denisty_deviation_cost_of_link = denisty_deviation_cost_of_link_set(j-1); 96 | edges(sub_l(i),sub_l(jj)) = AA+denisty_deviation_cost_of_link; 97 | edges(sub_l(jj),sub_l(i)) = AA+denisty_deviation_cost_of_link; 98 | end 99 | end 100 | end 101 | end 102 | 103 | %% PEAK-GRAPH 104 | G=sparse(n_p,n_p); 105 | for i=1:n_p 106 | for j = 1:n_p 107 | if edges(i,j) ~= Inf 108 | G(i,j) = edges(i,j); 109 | G(j,i) = edges(i,j); 110 | end 111 | end 112 | end 113 | [dim ~] = dijkstra(G,(1:n_p)); 114 | delta_peaks = Inf*ones(n_p,1); 115 | pn_peaks = -1*ones(n_p,1); 116 | for i = 2:n_p 117 | ii = OrdRho_peaks(i); 118 | for j = 1:i-1 119 | jj = OrdRho_peaks(j); 120 | if delta_peaks(ii) > dim(ii,jj) 121 | delta_peaks(ii) = dim(ii,jj); 122 | pn_peaks(ii) = jj; 123 | end 124 | end 125 | end 126 | 127 | %% delta of peaks 128 | delta = zeros(n,1); 129 | delta(peaks) = delta_peaks; 130 | if n_p > 1 131 | Must_C = length(find(delta==Inf)); 132 | if Must_C>1 133 | delta(delta==Inf) = max(delta(delta~=Inf))*1.2; 134 | delta_peaks = delta(peaks); 135 | else 136 | delta(delta==Inf) = max(delta(delta~=Inf)*1.2); 137 | delta_peaks = delta(peaks); 138 | end 139 | end 140 | time1 = toc; 141 | 142 | %% center selection 143 | figure; 144 | plot(rho(peaks), delta(peaks),'o','MarkerSize',4,'MarkerFaceColor','k','MarkerEdgeColor','k') 145 | hold on 146 | grid on; 147 | axis([0 max(rho(peaks)) 0 max(delta(peaks))]); 148 | title ('Decision Graph','FontSize',15.0); 149 | xlabel ('\rho'); 150 | ylabel ('\delta'); 151 | rect = getrect; 152 | rhomin = rect(1); 153 | deltamin=rect(2); 154 | 155 | %% center confirm 156 | tic; 157 | NC=0; 158 | for i=1:n_p 159 | Cl_peaks(i)=-1; % clutser label of peaks 160 | end 161 | for i=1:n_p 162 | if rho_peaks(i)>rhomin & delta_peaks(i) > deltamin 163 | NC=NC+1; 164 | Cl_peaks(i)=NC; 165 | icl(NC)=i; 166 | end 167 | end 168 | for i=1:n_p 169 | if (Cl_peaks(OrdRho_peaks(i))==-1) 170 | Cl_peaks(OrdRho_peaks(i))=Cl_peaks(pn_peaks(OrdRho_peaks(i))); 171 | end 172 | end 173 | 174 | %% allocation 175 | for i=1:n_p 176 | CL(sub_l== i) = Cl_peaks(i); 177 | end 178 | centers = peaks(icl); 179 | time2 = toc; 180 | runtime = time1+time2; 181 | 182 | 183 | -------------------------------------------------------------------------------- /MDPC(+)-master/code/GetAmi.m: -------------------------------------------------------------------------------- 1 | %Program for calculating the Adjusted Mutual Information (AMI) between 2 | %two clusterings, tested on Matlab 7.0 (R14) 3 | %(C) Nguyen Xuan Vinh 2008-2010 4 | %Contact: n.x.vinh@unsw.edu.au 5 | % vthesniper@yahoo.com 6 | %-------------------------------------------------------------------------- 7 | %**Input: a contingency table T 8 | % OR 9 | % cluster label of the two clusterings in two vectors 10 | % eg: true_mem=[1 2 4 1 3 5] 11 | % mem=[2 1 3 1 4 5] 12 | % Cluster labels are coded using positive integer. 13 | %**Output: AMI: adjusted mutual information (AMI_max) 14 | % 15 | %**Note: In a prevous published version, if you observed strange AMI results, eg. AMI>>1, 16 | %then it's likely that in these cases the expected MI was incorrectly calculated (the EMI is the sum 17 | %of many tiny elements, each falling out the precision range of the computer). 18 | %However, you'll likely see that in those cases, the upper bound for the EMI will be very 19 | %tiny, and hence the AMI -> NMI (see [3]). It is recommended setting AMI=NMI in 20 | %these cases, which is implemented in this version. 21 | %-------------------------------------------------------------------------- 22 | %References: 23 | % [1] 'A Novel Approach for Automatic Number of Clusters Detection based on Consensus Clustering', 24 | % N.X. Vinh, and Epps, J., in Procs. IEEE Int. Conf. on 25 | % Bioinformatics and Bioengineering (Taipei, Taiwan), 2009. 26 | % [2] 'Information Theoretic Measures for Clusterings Comparison: Is a 27 | % Correction for Chance Necessary?', N.X. Vinh, Epps, J. and Bailey, J., 28 | % in Procs. the 26th International Conference on Machine Learning (ICML'09) 29 | % [3] 'Information Theoretic Measures for Clusterings Comparison: Variants, Properties, 30 | % Normalization and Correction for Chance', N.X. Vinh, Epps, J. and 31 | % Bailey, J., Journal of Machine Learning Research, 11(Oct), pages 32 | % 2837-2854, 2010 33 | 34 | function [AMI_]=AMI(true_mem,mem) 35 | if nargin==1 36 | T=true_mem; %contingency table pre-supplied 37 | elseif nargin==2 38 | %build the contingency table from membership arrays 39 | R=max(true_mem); 40 | C=max(mem); 41 | n=length(mem);N=n; 42 | 43 | %identify & removing the missing labels 44 | list_t=ismember(1:R,true_mem); 45 | list_m=ismember(1:C,mem); 46 | T=Contingency(true_mem,mem); 47 | T=T(list_t,list_m); 48 | end 49 | 50 | %-----------------------calculate Rand index and others---------- 51 | n=sum(sum(T));N=n; 52 | C=T; 53 | nis=sum(sum(C,2).^2); %sum of squares of sums of rows 54 | njs=sum(sum(C,1).^2); %sum of squares of sums of columns 55 | 56 | t1=nchoosek(n,2); %total number of pairs of entities 57 | t2=sum(sum(C.^2)); %sum over rows & columnns of nij^2 58 | t3=.5*(nis+njs); 59 | 60 | %Expected index (for adjustment) 61 | nc=(n*(n^2+1)-(n+1)*nis-(n+1)*njs+2*(nis*njs)/n)/(2*(n-1)); 62 | 63 | A=t1+t2-t3; %no. agreements 64 | D= -t2+t3; %no. disagreements 65 | 66 | if t1==nc 67 | AR=0; %avoid division by zero; if k=1, define Rand = 0 68 | else 69 | AR=(A-nc)/(t1-nc); %adjusted Rand - Hubert & Arabie 1985 70 | end 71 | 72 | RI=A/t1; %Rand 1971 %Probability of agreement 73 | MIRKIN=D/t1; %Mirkin 1970 %p(disagreement) 74 | HI=(A-D)/t1; %Hubert 1977 %p(agree)-p(disagree) 75 | Dri=1-RI; %distance version of the RI 76 | Dari=1-AR; %distance version of the ARI 77 | %-----------------------%calculate Rand index and others%---------- 78 | 79 | %update the true dimensions 80 | [R C]=size(T); 81 | if C>1 a=sum(T');else a=T';end; 82 | if R>1 b=sum(T);else b=T;end; 83 | 84 | %calculating the Entropies 85 | Ha=-(a/n)*log(a/n)'; 86 | Hb=-(b/n)*log(b/n)'; 87 | 88 | %calculate the MI (unadjusted) 89 | MI=0; 90 | for i=1:R 91 | for j=1:C 92 | if T(i,j)>0 MI=MI+T(i,j)*log(T(i,j)*n/(a(i)*b(j)));end; 93 | end 94 | end 95 | MI=MI/n; 96 | 97 | %-------------correcting for agreement by chance--------------------------- 98 | AB=a'*b; 99 | bound=zeros(R,C); 100 | sumPnij=0; 101 | 102 | E3=(AB/n^2).*log(AB/n^2); 103 | 104 | EPLNP=zeros(R,C); 105 | LogNij=log([1:min(max(a),max(b))]/N); 106 | for i=1:R 107 | for j=1:C 108 | sumPnij=0; 109 | nij=max(1,a(i)+b(j)-N); 110 | X=sort([nij N-a(i)-b(j)+nij]); 111 | if N-b(j)>X(2) 112 | nom=[[a(i)-nij+1:a(i)] [b(j)-nij+1:b(j)] [X(2)+1:N-b(j)]]; 113 | dem=[[N-a(i)+1:N] [1:X(1)]]; 114 | else 115 | nom=[[a(i)-nij+1:a(i)] [b(j)-nij+1:b(j)]]; 116 | dem=[[N-a(i)+1:N] [N-b(j)+1:X(2)] [1:X(1)]]; 117 | end 118 | p0=prod(nom./dem)/N; 119 | 120 | sumPnij=p0; 121 | 122 | EPLNP(i,j)=nij*LogNij(nij)*p0; 123 | p1=p0*(a(i)-nij)*(b(j)-nij)/(nij+1)/(N-a(i)-b(j)+nij+1); 124 | 125 | for nij=max(1,a(i)+b(j)-N)+1:1:min(a(i), b(j)) 126 | sumPnij=sumPnij+p1; 127 | EPLNP(i,j)=EPLNP(i,j)+nij*LogNij(nij)*p1; 128 | p1=p1*(a(i)-nij)*(b(j)-nij)/(nij+1)/(N-a(i)-b(j)+nij+1); 129 | 130 | end 131 | CC=N*(a(i)-1)*(b(j)-1)/a(i)/b(j)/(N-1)+N/a(i)/b(j); 132 | bound(i,j)=a(i)*b(j)/N^2*log(CC); 133 | end 134 | end 135 | 136 | EMI_bound=sum(sum(bound)); 137 | EMI_bound_2=log(R*C/N+(N-R)*(N-C)/(N*(N-1))); 138 | EMI=sum(sum(EPLNP-E3)); 139 | 140 | AMI_=(MI-EMI)/(max(Ha,Hb)-EMI); 141 | NMI=MI/sqrt(Ha*Hb); 142 | 143 | 144 | %If expected mutual information negligible, use NMI. 145 | if abs(EMI)>EMI_bound 146 | % fprintf('The EMI is small: EMI < %f, setting AMI=NMI',EMI_bound); 147 | AMI_=NMI; 148 | end; 149 | 150 | %---------------------auxiliary functions--------------------- 151 | function Cont=Contingency(Mem1,Mem2) 152 | 153 | if nargin < 2 || min(size(Mem1)) > 1 || min(size(Mem2)) > 1 154 | error('Contingency: Requires two vector arguments') 155 | return 156 | end 157 | 158 | Cont=zeros(max(Mem1),max(Mem2)); 159 | 160 | for i = 1:length(Mem1); 161 | Cont(Mem1(i),Mem2(i))=Cont(Mem1(i),Mem2(i))+1; 162 | end 163 | 164 | -------------------------------------------------------------------------------- /MDPC(+)-master/code/dijkstra/dijkstra1.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Piotr's Computer Vision Matlab Toolbox Version 3.20 3 | * Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] 4 | * Licensed under the Simplified BSD License [see external/bsd.txt] 5 | *******************************************************************************/ 6 | 7 | /******************************************************************************* 8 | * Based on ISOMAP code which can be found at http:*isomap.stanford.edu/. 9 | * See accompanying m file (dijkstra.m) for usage. 10 | *******************************************************************************/ 11 | 12 | /******************************************************************************* 13 | * Bug fix for certain versions of VC++ compiler when used in Matlab. 14 | * http://www.mathworks.com/matlabcentral/newsreader/view_thread/281754 15 | *******************************************************************************/ 16 | #if (_MSC_VER >= 1600) 17 | #define __STDC_UTF_16__ 18 | typedef unsigned short char16_t; 19 | #endif 20 | 21 | #include "mex.h" 22 | #include "fibheap.h" 23 | #define DIJKSTRA_CPP 24 | 25 | /******************************************************************************* 26 | * class HeapNode 27 | *******************************************************************************/ 28 | class HeapNode : public FibHeapNode { 29 | double N; 30 | long int IndexV; 31 | 32 | public: 33 | HeapNode() : FibHeapNode() { N = 0; }; 34 | virtual void operator =(FibHeapNode& RHS); 35 | virtual int operator ==(FibHeapNode& RHS); 36 | virtual int operator <(FibHeapNode& RHS); 37 | virtual void operator =(double NewKeyVal ); 38 | virtual void Print(); 39 | double GetKeyValue() { return N; }; 40 | void SetKeyValue(double n) { N = n; }; 41 | long int GetIndexValue() { return IndexV; }; 42 | void SetIndexValue( long int v) { IndexV = v; }; 43 | }; 44 | 45 | void HeapNode::Print() { 46 | FibHeapNode::Print(); 47 | mexPrintf( "%f (%d)" , N , IndexV ); 48 | } 49 | 50 | void HeapNode::operator =(double NewKeyVal) { 51 | HeapNode Tmp; 52 | Tmp.N = N = NewKeyVal; 53 | FHN_Assign(Tmp); 54 | } 55 | 56 | void HeapNode::operator =(FibHeapNode& RHS) { 57 | FHN_Assign(RHS); 58 | N = ((HeapNode&) RHS).N; 59 | } 60 | 61 | int HeapNode::operator ==(FibHeapNode& RHS) { 62 | if (FHN_Cmp(RHS)) return 0; 63 | return N == ((HeapNode&) RHS).N ? 1 : 0; 64 | } 65 | 66 | int HeapNode::operator <(FibHeapNode& RHS) { 67 | int X; 68 | if ((X=FHN_Cmp(RHS)) != 0) 69 | return X < 0 ? 1 : 0; 70 | return N < ((HeapNode&) RHS).N ? 1 : 0; 71 | }; 72 | 73 | /******************************************************************************* 74 | * main 75 | *******************************************************************************/ 76 | void dijkstra1( long int n, long int s, double *D1, double *P1, double *Gpr, mwIndex *Gir, mwIndex *Gjc) { 77 | int finished; 78 | long int i, startInd, endInd, whichNeigh, nDone, closest; 79 | double closestD, arcLength, INF, SMALL, oldDist; 80 | HeapNode *A, *hnMin, hnTmp; FibHeap *heap; 81 | INF=mxGetInf(); SMALL=mxGetEps(); 82 | 83 | // setup heap 84 | if ((heap = new FibHeap) == NULL || (A = new HeapNode[n+1]) == NULL ) 85 | mexErrMsgTxt( "Memory allocation failed-- ABORTING.\n" ); 86 | heap->ClearHeapOwnership(); 87 | 88 | // initialize 89 | for (i=0; iInsert( &A[i] ); 94 | A[ i ].SetIndexValue( (long int) i ); 95 | } 96 | 97 | // Insert 0 then extract it, which will balance heap 98 | heap->Insert(&hnTmp); heap->ExtractMin(); 99 | 100 | // loop over nonreached nodes 101 | finished = nDone = 0; 102 | while ((finished==0) && (nDone < n)) { 103 | hnMin = (HeapNode *) heap->ExtractMin(); 104 | closest = hnMin->GetIndexValue(); 105 | closestD = hnMin->GetKeyValue(); 106 | if ((closest<0) || (closest>=n)) 107 | mexErrMsgTxt( "Minimum Index out of bound..." ); 108 | D1[ closest ] = closestD; 109 | if (closestD == INF) finished=1; else { 110 | // relax all nodes adjacent to closest 111 | nDone++; 112 | startInd = Gjc[ closest ]; 113 | endInd = Gjc[ closest+1 ] - 1; 114 | if( startInd!=endInd+1 ) 115 | for( i=startInd; i<=endInd; i++ ) { 116 | whichNeigh = Gir[ i ]; 117 | arcLength = Gpr[ i ]; 118 | oldDist = D1[ whichNeigh ]; 119 | if ( oldDist > ( closestD + arcLength )) { 120 | D1[ whichNeigh ] = closestD + arcLength; 121 | P1[ whichNeigh ] = closest + 1; 122 | hnTmp = A[ whichNeigh ]; 123 | hnTmp.SetKeyValue( closestD + arcLength ); 124 | heap->DecreaseKey( &A[ whichNeigh ], hnTmp ); 125 | } 126 | } 127 | } 128 | } 129 | 130 | // cleanup 131 | delete heap; delete[] A; 132 | } 133 | 134 | void dijkstra( long int n, long int nSrc, double *sources, double *D, double *P, const mxArray *G ) { 135 | // dealing with sparse array 136 | double *Gpr = mxGetPr(G); 137 | mwIndex *Gir = mxGetIr(G); 138 | mwIndex *Gjc = mxGetJc(G); 139 | 140 | // allocate memory for single source results (automatically recycled) 141 | double *D1 = (double *) mxCalloc( n , sizeof( double )); 142 | double *P1 = (double *) mxCalloc( n , sizeof( double )); 143 | 144 | // loop over sources 145 | long int s, i, j; 146 | for( i=0; i n-1) mexErrMsgTxt( "Source node(s) out of bound" ); 151 | dijkstra1( n, s, D1, P1, Gpr, Gir, Gjc ); 152 | 153 | // store results 154 | for( j=0; j 2) mexErrMsgTxt( "Only 2 output argument allowed." ); 168 | n = mxGetN( prhs[0] ); 169 | if (mxGetM( prhs[0] ) != n) mexErrMsgTxt( "Input matrix G needs to be square." ); 170 | sources = mxGetPr(prhs[1]); mSrc = mxGetM(prhs[1]); nSrc=mxGetN(prhs[1]); 171 | if ((mSrc==0) || (nSrc==0) || ((mSrc>1) && (nSrc>1))) 172 | mexErrMsgTxt( "Source nodes are specified in vector only" ); 173 | if(mSrc>nSrc) nSrc=mSrc; 174 | if(mxIsSparse(prhs[0])==0) mexErrMsgTxt( "Distance Matrix must be sparse" ); 175 | 176 | // create outputs arrays D and P 177 | plhs[0] = mxCreateDoubleMatrix( nSrc, n, mxREAL ); 178 | plhs[1] = mxCreateDoubleMatrix( nSrc, n, mxREAL ); 179 | D = mxGetPr(plhs[0]); 180 | P = mxGetPr(plhs[1]) ; 181 | 182 | // run dijkstras to fill D and P 183 | dijkstra( n, nSrc, sources, D, P, prhs[0] ); 184 | } 185 | -------------------------------------------------------------------------------- /MDPC(+)-master/code/Library.m: -------------------------------------------------------------------------------- 1 | classdef Library 2 | %LIBRARY Summary of this class goes here 3 | % Detailed explanation goes here 4 | 5 | properties 6 | end 7 | 8 | methods(Static) 9 | 10 | %Data processing functions 11 | 12 | function [varargout]=Swap(varargin) 13 | varargout=varargin; 14 | end 15 | 16 | function [ari]=GetAri(answer,cluster) 17 | [p,o]=meshgrid(answer,answer); 18 | answerPair=~squareform(p~=o); 19 | [p,o]=meshgrid(cluster,cluster); 20 | resultPair=~squareform(p~=o); 21 | a=sum(answerPair&resultPair); 22 | b=sum(answerPair&~resultPair); 23 | c=sum(~answerPair&resultPair); 24 | d=sum(~answerPair&~resultPair); 25 | ari=2*(a*d-b*c)/((a+b)*(b+d)+(a+c)*(c+d)); 26 | end 27 | 28 | function [fmi]=GetFmi(answer,cluster) 29 | [p,o]=meshgrid(answer,answer); 30 | answerPair=~squareform(p~=o); 31 | [p,o]=meshgrid(cluster,cluster); 32 | resultPair=~squareform(p~=o); 33 | tp=sum(answerPair&resultPair); 34 | fp=sum(answerPair&~resultPair); 35 | fn=sum(~answerPair&resultPair); 36 | fmi=tp/sqrt((tp+fp)*(tp+fn)); 37 | end 38 | 39 | %User interface functions 40 | 41 | function [fig]=UiShowFigure() 42 | %Calculate where to display figure window 43 | screenSize=get(0,'ScreenSize'); 44 | fig=figure('Position',[36 72 screenSize(3)/2.3 screenSize(4)/1.3]); 45 | end 46 | 47 | function [data]=UiReduceDimension(data) 48 | if size(data,2)>2 49 | rng default 50 | data=tsne(data); 51 | end 52 | end 53 | 54 | function [cmap]=UiGetColormap(NC) 55 | %Get colormap for plotting below 56 | colormap hsv 57 | cmap=colormap; 58 | cmap=cmap(round(linspace(1,length(cmap),NC+1)),:); 59 | cmap=cmap(1:end-1,:)*0.5+0.4; 60 | end 61 | 62 | function [x,y,click,fig,ax1,ax2]=UiMakeDecision(rho,delta,varargin) 63 | %Specify figure and axes 64 | if nargin<3 65 | fig=Library.UiShowFigure(); 66 | else 67 | fig=varargin{1}; 68 | end 69 | set(0,'CurrentFigure',fig); 70 | if nargin<5 71 | ax1=subplot(2,2,1,'Parent',fig); 72 | ax2=subplot(2,2,2,'Parent',fig); 73 | else 74 | ax1=varargin{2}; 75 | ax2=varargin{3}; 76 | end 77 | %Plot decision graph 78 | scatter(ax1,rho,delta,'.'); 79 | title(ax1,'Decision Graph','FontSize',15);xlabel(ax1,'\rho');ylabel(ax1,'\delta'); 80 | grid(ax1,'on'); 81 | %Show hints 82 | fprintf('Click on Decision Graph to determine the lower bound of rho and delta\n'); 83 | fprintf('Or click on Gamma Graph to determine the lower bound of gamma\n'); 84 | %Plot gamma graph 85 | Library.UiPlotGamma(rho.*delta,fig,ax2); 86 | %Make decision 87 | [x,y]=ginput(1); 88 | if gca==ax1 89 | click=1; 90 | elseif gca==ax2 91 | click=2; 92 | else 93 | error('You must click at either graph'); 94 | end 95 | end 96 | 97 | function [fig,ax1,ax2]=UiShowDecision(rho,delta,x,y,click,K,varargin) 98 | if nargin<7 99 | fig=Library.UiShowFigure(); 100 | else 101 | fig=varargin{1}; 102 | end 103 | if nargin<9 104 | ax1=subplot(2,2,1,'Parent',fig); 105 | ax2=subplot(2,2,2,'Parent',fig); 106 | else 107 | ax1=varargin{2}; 108 | ax2=varargin{3}; 109 | end 110 | scatter(ax1,rho,delta,'.'); 111 | pbaspect(ax1,[1,1,1]); 112 | title(ax1,'Decision Graph','FontSize',15);xlabel(ax1,'\rho');ylabel(ax1,'\delta'); 113 | grid(ax1,'on'); 114 | Library.UiPlotGamma(rho.*delta,fig,ax2); 115 | if click==1 116 | NC=sum(rho>x&delta>y); 117 | Library.UiDrawMarker(NC,x,y,click,K,fig,ax1,ax2); 118 | Library.UiDrawCenter(intersect(find(rho>x),find(delta>y)),rho,delta,Library.UiGetColormap(NC),fig,ax1,ax2); 119 | else 120 | gamma=rho.*delta; 121 | Library.UiDrawMarker(sum(gamma>y),x,y,click,K,fig,ax1,ax2); 122 | Library.UiDrawCenter(find(gamma>=y),rho,delta,Library.UiGetColormap(sum(gamma>y)),fig,ax1,ax2); 123 | end 124 | end 125 | 126 | function [fig,ax1,ax2]=UiDrawMarker(NC,x,y,click,K,varargin) 127 | %Draw markers on decision graph and gamma graph 128 | if nargin<6 129 | fig=Library.UiShowFigure(); 130 | else 131 | fig=varargin{1}; 132 | end 133 | if nargin<8 134 | ax1=subplot(2,2,1,'Parent',fig); 135 | ax2=subplot(2,2,2,'Parent',fig); 136 | else 137 | ax1=varargin{2}; 138 | ax2=varargin{3}; 139 | end 140 | if click==1 141 | %x->rhoLeast,y->deltaLeast 142 | line(ax1,[x,ax1.XLim(2)],[y,y],'Color','Red'); 143 | line(ax1,[x,x],[y,ax1.YLim(2)],'Color','Red'); 144 | line(ax2,ax2.XLim,[x*y,x*y],'Color','Red'); 145 | text(ax2,(ax2.XLim(2)-ax2.XLim(1))*0.1,(ax2.YLim(2)-ax2.YLim(1))*0.8,sprintf('NC = %i, K = %i',NC,K),'FontSize',10); 146 | elseif click==2 147 | %y->gammaLeast 148 | line(ax2,ax2.XLim,[y,y],'Color','Red'); 149 | text(ax2,(ax2.XLim(2)-ax2.XLim(1))*0.1,(ax2.YLim(2)-ax2.YLim(1))*0.8,sprintf('NC = %i, K = %i',NC,K),'FontSize',10); 150 | end 151 | end 152 | 153 | function [fig,ax1,ax2]=UiDrawCenter(center,rho,delta,cmap,varargin) 154 | %Plot centers on decision graph 155 | if nargin<5 156 | fig=Library.UiShowFigure(); 157 | else 158 | fig=varargin{1}; 159 | end 160 | if nargin<7 161 | ax1=subplot(2,2,1,'Parent',fig); 162 | ax2=subplot(2,2,2,'Parent',fig); 163 | else 164 | ax1=varargin{2}; 165 | ax2=varargin{3}; 166 | end 167 | gamma=rho.*delta; 168 | [~,gammaOrder]=sort(gamma); 169 | [~,gammaOrderReverse]=sort(gammaOrder); 170 | hold(ax1,'on'); 171 | scatter(ax1,rho(center),delta(center),[],cmap,'o','Filled'); 172 | hold(ax1,'off'); 173 | hold(ax2,'on'); 174 | scatter(ax2,gammaOrderReverse(center),gamma(center),[],cmap,'o','Filled'); 175 | hold(ax2,'off'); 176 | end 177 | 178 | function [fig,ax]=UiPlotGamma(gamma,varargin) 179 | %Plot \gamma graph 180 | if nargin<2 181 | fig=Library.UiShowFigure(); 182 | else 183 | fig=varargin{1}; 184 | end 185 | if nargin<3 186 | ax=axes(fig); 187 | else 188 | ax=varargin{2}; 189 | end 190 | N=length(gamma); 191 | gammaSort=sort(gamma); 192 | scatter(ax,1:N,gammaSort,'.'); 193 | pbaspect(ax,[1,1,1]); 194 | title(ax,'Distribution of \gamma value','FontSize',15);xlabel(ax,'Number');ylabel(ax,'\gamma'); 195 | grid(ax,'on'); 196 | end 197 | 198 | function [fig,ax]=UiPlotResultAndRho(cluster,center,rho,data,cmap,varargin) 199 | %Plot clustering result and \rho graph 200 | if nargin<6 201 | fig=Library.UiShowFigure(); 202 | else 203 | fig=varargin{1}; 204 | end 205 | if nargin<7 206 | ax=axes(fig); 207 | else 208 | ax=varargin{2}; 209 | end 210 | NC=length(center); 211 | hold(ax,'on'); 212 | grid(ax,'on'); 213 | scatter3(ax,data(cluster<0,1),data(cluster<0,2),rho(cluster<0),[],[0.6,0.6,0.6],'x'); 214 | for p=1:NC 215 | scatter3(ax,data(cluster==p,1),data(cluster==p,2),rho(cluster==p),[],cmap(p,:),'.'); 216 | end 217 | scatter3(ax,data(center,1),data(center,2),rho(center),40,cmap,'Pentagram','Filled','MarkerEdgeColor','Black'); 218 | pbaspect(ax,[1,1,1]); 219 | title(ax,'Result and \rho value (3D)','FontSize',15);xlabel('X');ylabel('Y');zlabel('\rho') 220 | xlabel('X'); 221 | ylabel('Y'); 222 | zlabel('\rho'); 223 | hold(ax,'off'); 224 | end 225 | 226 | function [fig,ax]=UiPlotResultAndDelta(cluster,center,delta,data,cmap,varargin) 227 | %Plot clustering result and \delta graph 228 | if nargin<6 229 | fig=Library.UiShowFigure(); 230 | else 231 | fig=varargin{1}; 232 | end 233 | if nargin<7 234 | ax=axes(fig); 235 | else 236 | ax=varargin{2}; 237 | end 238 | NC=length(center); 239 | hold(ax,'on'); 240 | grid(ax,'on'); 241 | scatter3(ax,data(cluster<0,1),data(cluster<0,2),delta(cluster<0),[],[0.6,0.6,0.6],'x'); 242 | for p=1:NC 243 | scatter3(ax,data(cluster==p,1),data(cluster==p,2),(delta(cluster==p)),[],cmap(p,:),'.'); 244 | end 245 | scatter3(ax,data(center,1),data(center,2),delta(center),40,cmap,'Pentagram','Filled','MarkerEdgeColor','Black'); 246 | pbaspect(ax,[1,1,1]); 247 | title(ax,'Result and \delta value (3D)','FontSize',15);xlabel('X');ylabel('Y');zlabel('\delta'); 248 | xlabel('X'); 249 | ylabel('Y'); 250 | zlabel('\delta'); 251 | hold(ax,'off'); 252 | end 253 | 254 | function [fig,ax1,ax2,ax3]=UiReshowDecision(result,data,varargin) 255 | if nargin<3 256 | screenSize = get(0,'ScreenSize'); 257 | fig=figure('Position',[36 72 screenSize(3)/1.5 screenSize(4)/3]); 258 | else 259 | fig=varargin{1}; 260 | end 261 | if nargin<5 262 | ax1=subplot(1,3,1,'Parent',fig); 263 | ax2=subplot(1,3,2,'Parent',fig); 264 | ax3=subplot(1,3,3,'Parent',fig); 265 | else 266 | ax1=varargin{2}; 267 | ax2=varargin{3}; 268 | ax3=varargin{4}; 269 | end 270 | [fig,ax1]=Library.UiReplotResultAndRho(result,data,fig,ax1); 271 | title(ax1,'Result'); 272 | [fig,ax2,ax3]=Library.UiShowDecision(result.rho,result.delta,result.x,result.y,result.click,result.K,fig,ax2,ax3); 273 | end 274 | 275 | function [fig,ax]=UiReplotGamma(result,varargin) 276 | if nargin<2 277 | fig=Library.UiShowFigure(); 278 | else 279 | fig=varargin{1}; 280 | end 281 | if nargin<3 282 | ax=axes(fig); 283 | else 284 | ax=varargin{2}; 285 | end 286 | [fig,ax]=Library.UiPlotGamma(result.gamma,fig,ax); 287 | end 288 | 289 | function [fig,ax]=UiReplotResultAndRho(result,data,varargin) 290 | if nargin<3 291 | fig=Library.UiShowFigure(); 292 | else 293 | fig=varargin{1}; 294 | end 295 | if nargin<4 296 | ax=axes(fig); 297 | else 298 | ax=varargin{2}; 299 | end 300 | [fig,ax]=Library.UiPlotResultAndRho(result.cluster,result.center,result.rho,data,Library.UiGetColormap(result.NC),fig,ax); 301 | end 302 | 303 | function [fig,ax]=UiReplotResultAndDelta(result,data,varargin) 304 | if nargin<3 305 | fig=Library.UiShowFigure(); 306 | else 307 | fig=varargin{1}; 308 | end 309 | if nargin<4 310 | ax=axes(fig); 311 | else 312 | ax=varargin{2}; 313 | end 314 | [fig,ax]=Library.UiPlotResultAndDelta(result.cluster,result.center,result.delta,data,Library.UiGetColormap(result.NC),fig,ax); 315 | end 316 | 317 | end 318 | 319 | end 320 | --------------------------------------------------------------------------------