

clear;clc;
fprintf('Read matrix\n');
file = 'gre_115.mtx';
fp = fopen(file, 'r');

B = textscan(fp, '%d %d  %f', 'headerlines', 1); % read data instead of first line
%B = textscan(fp, '%d %d', 'headerlines', 1); % read data instead of first line
row = cell2mat(B(1));
col = cell2mat(B(2));
%val = ones(length(row),1);
val = cell2mat(B(3));
fclose(fp);

number_edge = length(row); %number of edge

A = sparse(double(row), double(col), double(abs(val))); 
number_of_edges = nnz(A);
nn = max(size(A)); 
A = sparse(double(row), double(col), double(abs(val)),nn ,nn); 
A = A-diag(diag(A));

[row,col,val] = find(A);
Graph_original = digraph(row,col,val);
h = plot(Graph_original,'b','LineWidth',0.5);
nn = length(A);%number of node i
D = spdiags(sum(A,2),0,nn,nn);
L = D-A'+1e-7*spdiags(ones(nn,1),0,nn,nn); % directed laplacian

%get the mini spanning tree with respect to undirected graph
A_un = sparse(nn,nn);
pro = sparse(nn,nn);
A_spar_new = sparse(nn,nn);
A_spar_old = sparse(nn,nn);
L_si = sparse(nn,nn);
 
sumA = sum(A, 2);
prob = bsxfun(@rdivide, A_un, sumA);
A_un = tril((A+A')/2); 
[row_m,col_m,val_m] = find(A_un);
Graph_modified = graph(row_m,col_m,1./val_m);

T = minspantree(Graph_modified)  %T is minimum spaaning tree
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure;
h_un = plot(Graph_modified,'EdgeColor','g','LineWidth',1.5);
highlight(h_un,T,'EdgeColor','b','LineWidth',2.5)

flag = sparse(double(row),double(col),-1,nn,nn);
 
ss = table2array(T.Edges);
rows = int16(ss(:,1));
cols = int16(ss(:,2));
vals = ss(:,2);
A_temp = sparse(double(rows), double(cols),ones(length(rows),1), nn ,nn);

A_temp = A_temp + A_temp';
A_temp=triu(A_temp);
[rows,cols,vals] = find(A_temp);
A_spar_new= sparse(double(rows), double(cols),ones(length(rows),1), nn ,nn).*A;
row_add = find(~sum(A_spar_new,2)); 
for i = 1:length(row_add)
   	[M,I] = max(A(row_add(i),:)); 
  	A_spar_new(row_add(i),I) = A(row_add(i),I);  
end
%for i = 1:nn
%   	[M,I] = max(A(:,i)); 
%  	A_spar_new(I,i) = A(I,i);  
%end

[rs,cs,vs] = find(A_spar_new);
Graph_spars = digraph(rs,cs,vs);
flag = flag + sparse(double(rs),double(cs),2, nn,nn);
Ls =  sparse(diag(sum(A_spar_new,2)))-A_spar_new'+1e-6*spdiags(ones(nn,1),0,nn,nn);
LsLs =  Ls*Ls'+1e-6*spdiags(ones(nn,1),0,nn,nn);
[ht,lambda_new] = Ht_v2(L,LsLs, 3);
fprintf('the intial lambda is %f\n',lambda_new);

times = 1;
cc(1) = lambda_new;
Percent_added(1) = nnz(A_spar_new)/nnz(A);
P_in(1) = (nnz(A_spar_new)-nn)/nn;
num = int16(number_of_edges*0.05);
fprintf('the number of  added off-tree edges each time  is %d\n',num);

[flag_row,flag_col] = find(flag > 0);
Number_of_edge_spanning = length(flag_row);
lambda_old = 1e8;
while((lambda_new>20)&(times < 10))
	times = times+1;
 	lambda_old = lambda_new;
 	A_spar_old = A_spar_new; 
    ht_old = ht;
	LsLs_old = LsLs;
 	%[flag_row,flag_col] = find(flag > 0);
	
 	A_si = sparse(nn,nn);
 	A_si = sparse(double(flag_row),double(flag_col),ones(length(flag_row),1),nn,nn);
 	L_si = spdiags(sum(A_si,2),0,nn,nn)- A_si';  %laplacain without weight to calculate the similarity 
 	[flagoff_row,flagoff_col] = find(flag==-1);
 	score = zeros(length(flagoff_row),1);
 	top = zeros(length(flagoff_row),1);
 	top_row = zeros(length(flagoff_row),1);
 	%score_similarity = zeros(length(flagoff_row),1);
%------------------------------------the similarity of off tree edges
	s = Score(A, Ls, flagoff_row, flagoff_col, ht);
	score = s;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%add the first important edges into sparsifier

	[top,top_row] = sort(score,'descend');
	num_positive = length(find(score>0));
	
	number = min(num,num_positive);
	x0 = rand(nn,3);
   	for nt=1:3
      	[x0(:,nt), lambda] = Ht_v2(L, LsLs, 3);
   	end   

	frt = flagoff_row(top_row);
    fct = flagoff_col(top_row);

	%s = Score(A, Ls, flagoff_row, flagoff_col, ht);
	sc_si=zeros(length(top_row),3);
	
	%%
	for nt = 1:3
	sc_si(:,nt) = Score(A_si, L_si,frt,fct, x0(:,nt));
	end
 	
	score_similarity = sum(sc_si,2);;

	if number<2
    	break;
	end
	
	flag(flagoff_row(top_row(1)),flagoff_col(top_row(1))) = 1;
 	for i=2:1:number
    	%if D(flagoff_row(top_row(i)),flagoff_row(top_row(i))) < 200000000
			if max(abs(score_similarity(i)-score_similarity(1:i-1))/score_similarity(i))>0.5
        		flag(flagoff_row(top_row(i)),flagoff_col(top_row(i))) = 1;
    		end
	%	end
	end
	%%
	
	
	%cdx =2:2:number;
	%fort = top_row(cdx);
	%fort_f= sparse(flagoff_row(fort),flagoff_col(fort), 2*ones(length(fort),1),nn,nn);
	%flag = flag + fort_f;
	%flag(flagoff_row(fort),flagoff_col(fort)) = 1;
    
 	[rp,cp] = find(flag > 0);
	A_spar_new = sparse(double(rp),double(cp),ones(length(rp),1), nn, nn).*A;
	Ls = sparse(diag(sum(A_spar_new,2)))-A_spar_new';
 	
	%%
	[ht,lambda_new] = Ht_v2(L, LsLs, 3);
 	
	%fprintf('the lambda is %f\n',lambda_new );
 	if lambda_new>lambda_old
 		lambda_new = lambda_old;
 		A_spar_new = A_spar_old;
 		Ls = spdiags(sum(A_spar_new,2),0,nn,nn)-A_spar_new';
 	end

	%%
	LsLs =  Ls*Ls'+1e-6*spdiags(ones(nn,1),0,nn,nn);

	cc(times) = lambda_new;
	Percent_added(times) = nnz(A_spar_new)/nnz(A);
	P_in(times) = (nnz(A_spar_new)-nn)/nn;
end

[rp,cp] = find(flag > 0);
A_spar_new = sparse(double(rp),double(cp),ones(length(rp),1), nn, nn).*A;
Ls = sparse(diag(sum(A_spar_new,2)))-A_spar_new';
LsLs =  Ls*Ls'+1e-6*spdiags(ones(nn,1),0,nn,nn);
[ht,lambda_new] = Ht_v2(L, LsLs, 3);
if lambda_new>lambda_old
 	lambda_new = lambda_old;
 	A_spar_new = A_spar_old;
 	Ls = sparse(diag(sum(A_spar_new,2)))-A_spar_new';
	ht = ht_old;
 end
cc(times) = lambda_new;
Percent_added(times) = nnz(A_spar_new)/nnz(A);
P_in(times) = (nnz(A_spar_new)-nn)/nn;


[row_spars,col_spars,val_spars] = find(A_spar_new);
Graph_spars = digraph(row_spars,col_spars,val_spars);
number_of_selected_edges = length(flag_row);%-Number_of_edge_spanning; 
fprintf('The number of edges in sparsifier over the number of edges in original graph at each iteration:\n');
Percent_added

fprintf('largest generalized eigenvalue between sparsifier and original graph at each iteration :\n');
cc

fprintf('largest genrealized eigenvalue drop ratio:');
sz = cc(1)/cc(end)
