function Phoenix_main()

%
% Simulator of Phoenix Network Coordinate System 
%                 Version 1.0                     
% 
% Title   : Phoenix: Towards an Accurate, Practical and Decentralized Network Coordinate System
% Author  : Yang Chen (Tsinghua), Xiao Wang (Tsinghua), Xiaoxiao Song (Tsinghua), Eng Keong Lua (CMU), Cong Shi (Gatech) , Xiaohan Zhao (Tsinghua), Beixing Deng (Tsinghua), Xing Li (Tsinghua)
% E-mail  : chenyang04@mails.tsinghua.edu.cn
% Website : http://www.net-glyph.org/~chenyang/nc_tsinghua.html
% In Proc. of 8th International IFIP-TC6 Networking Conference (Networking'09), Aachen, Germany, May.2009.




clear

load('recon.mat');
load king_matrix.txt
load meridianmatrix

% Prepare the Meridian Data set %
[m, n] = size(meridianmatrix)
Meridian = zeros(2500, 2500);
for i=1:2500
    for j=1:2500
        if (i == j)
            Meridian(i, j) = 0;
        else
            Meridian(i, j) = -1;
        end
    end
end
for i=1:m
    Meridian(meridianmatrix(i, 1), meridianmatrix(i, 2)) = meridianmatrix(i, 3)/1000;
    Meridian(meridianmatrix(i, 2), meridianmatrix(i, 1)) = meridianmatrix(i, 3)/1000;
end
clear meridianmatrix


%let's use the DATA dataset as an exDATAle

%DATA=P2P_Sample;
DATA=AMP;
%DATA=Meridian; clear king_matrix;
%DATA=PL;
%DATA=P2P;
%DATA=king_matrix;


total_triangle = 0;
bad_triangle = 0;

total_pair = 0;
bad_pair = 0;


re_rpl_on = 0;
rrl_on = 0;

converge_log_on = 1; % Fig. 3 of the paper %
attack_on = 0;       % Fig. 4 of the paper %

TIV_selection_on = 0;

N = length(DATA); 

if (attack_on == 0)
    DATA_NC = DATA;
else
    DATA_NC = inaccurate(DATA, 0.01); % Percentage %
end


max_round =5;


L = 32;   % 32 neighbors
dim = 10; % 10 dimension vectors

total_re_ides_svd = [];
total_re_ides_svd_dist = [];
total_re_ides_svd_weight = [];
total_re_ides_nmf = [];
total_re_ides_nmf_nonneg = [];
total_re_ides_nmf_nonneg_dist = [];
total_re_syogurt = [];
total_re_yogurt = [];
total_re_phoenix = [];
total_re_phoenix_simple = [];
total_re_vivaldi = [];

total_rerpl_ides_svd = [];
total_rerpl_ides_svd_dist = [];
total_rerpl_ides_svd_weight = [];
total_rerpl_ides = [];
total_rerpl_ides_nmf_nonneg = [];
total_rerpl_ides_nmf_nonneg_dist = [];
total_rerpl_syogurt = [];
total_rerpl_yogurt = [];
total_rerpl_phoenix = [];
total_rerpl_phoenix_simple = [];
total_rerpl_vivaldi = [];


total_nnl_ides_svd = [];
total_nnl_ides_svd_dist = [];
total_nnl_ides_svd_weight = [];
total_nnl_ides_nmf = [];
total_nnl_ides_nmf_nonneg = [];
total_nnl_ides_nmf_nonneg_dist = [];
total_nnl_syogurt = [];
total_nnl_yogurt = [];
total_nnl_phoenix = [];
total_nnl_phoenix_simple = [];
total_nnl_vivaldi = [];

total_rrl_ides_svd = [];
total_rrl_ides_svd_dist = [];
total_rrl_ides_svd_weight = [];
total_rrl_ides_nmf = [];
total_rrl_ides_nmf_nonneg = [];
total_rrl_ides_nmf_nonneg_dist = [];
total_rrl_syogurt = [];
total_rrl_yogurt = [];
total_rrl_phoenix = [];
total_rrl_phoenix_simple = [];
total_rrl_vivaldi = [];

aa=0;bb=0;
total_neg=0;

all_estimate = [];
all_real = [];

pos_dist = zeros(1, 20);
neg_dist = zeros(1, 20);



total_fpre = [];
total_npre = [];

total_vivaldi_fperror = [];

for i = 1:max_round
    i
      
    %[CENTER, U, OBJ_FCN] = kmeans2(reconstruct(DATA), L, [100, NaN, 1]);
    mark_vec = zeros(1, N);
    tmp = randperm(N); 
    CENTER = tmp(1:L);
    tmp = 1:N;
    for jj = 1:L
        for kk = 1:N
            if tmp(kk) == CENTER(jj)
                break
            end
        end
        tmp(kk) = [];
    end
    

    landmarks = CENTER;
    hosts = tmp;
    %landmarks = tmp(1:L); % choose random L nodes as landmarks
    %hosts = tmp(L+1:N);  % the rest of them are orinary hosts

    D_landmark = DATA_NC(landmarks, landmarks);
    D_host2landmark = DATA_NC(hosts, landmarks);

    %The default ides algorithm, using SVD
    fprintf('IDES (SVD)');
    [out_l, in_l, out_h, in_h] = ides(D_landmark, D_host2landmark, dim);
    predicted_matrix = out_h*in_h;
    rerr=relative_error(predicted_matrix, DATA(hosts, hosts));
    output_re = store_re(rerr', 1, 1000);
    total_re_ides_svd = [total_re_ides_svd; output_re];
    

    %The default ides algorithm, using SVD
    fprintf('IDES (NMF)');
    [out_l, in_l, out_h, in_h] = ides_NMF(D_landmark, D_host2landmark, dim);
    predicted_matrix = out_h*in_h;
    rerr=relative_error(predicted_matrix, DATA(hosts, hosts));
    output_re = store_re(rerr', 1, 1000);
    total_re_ides_nmf = [total_re_ides_nmf; output_re];        
    
    [out_all, in_all, fpre, npre] = phoenix(DATA_NC, dim, N, L, 5, converge_log_on);
    total_fpre = [total_fpre; fpre'];
    total_npre = [total_npre; npre'];
    predicted_matrix = out_all * in_all;
    rerr=relative_error(predicted_matrix, DATA);%DATA!!
    output_re = store_re(rerr', 1, 1000);
    total_re_phoenix = [total_re_phoenix; output_re];
   
    [out_all, in_all] = phoenix_simple(DATA_NC, dim, N, L);
    predicted_matrix = out_all * in_all;
    rerr=relative_error(predicted_matrix, DATA);%DATA!!
    output_re = store_re(rerr', 1, 1000);
    total_re_phoenix_simple = [total_re_phoenix_simple; output_re];
    
    
    [coord_all, vivaldi_fperror] = vivaldi(DATA_NC, dim, N, L, converge_log_on);    
    total_vivaldi_fperror = [total_vivaldi_fperror vivaldi_fperror];
    for x = 1:N        
        for y = 1:N
            predicted_matrix(x,y) = Dist(coord_all(x,:), coord_all(y,:)); 
        end;
    end;    
    rerr=relative_error(predicted_matrix, DATA);
    output_re = store_re(rerr', 1, 1000);
    total_re_vivaldi = [total_re_vivaldi; output_re];
end


b=mean(total_re_vivaldi);
c=mean(total_re_phoenix);
d=mean(total_re_phoenix_simple);
e=mean(total_re_ides_svd);
f=mean(total_re_ides_nmf);

re_results = zeros(2, 5);

fprintf('\n\n\nFinal Simulation Results:\n\n\n');

fprintf('Phoenix ');
for i=1:1000
    if (c(i) >= 0.5 & c(i-1) < 0.5)
            fprintf('%.3f ', i/1000);
            re_results(1, 1) = i/1000;
    end
    if (c(i) >= 0.9 & c(i-1) < 0.9)
            fprintf('%.3f ', i/1000);
            re_results(2, 1) = i/1000;
    end
end
fprintf('\n');

fprintf('Phoenix (Simple)');
for i=1:1000
    if (d(i) >= 0.5 & d(i-1) < 0.5)
            fprintf('%.3f ', i/1000);
            re_results(1, 2) = i/1000;
    end
    if (d(i) >= 0.9 & d(i-1) < 0.9)
            fprintf('%.3f ', i/1000);
            re_results(2, 2) = i/1000;
    end
end
fprintf('\n');

fprintf('IDES (SVD)');
for i=1:1000
    if (e(i) >= 0.5 & e(i-1) < 0.5)
            fprintf('%.3f ', i/1000);
            re_results(1, 3) = i/1000;
    end
    if (e(i) >= 0.9 & e(i-1) < 0.9)
            fprintf('%.3f ', i/1000);
            re_results(2, 3) = i/1000;
    end
end
fprintf('\n');

fprintf('IDES (NMF)');
for i=1:1000
    if (f(i) >= 0.5 & f(i-1) < 0.5)
            fprintf('%.3f ', i/1000);
            re_results(1, 4) = i/1000;
    end
    if (f(i) >= 0.9 & f(i-1) < 0.9)
            fprintf('%.3f ', i/1000);
            re_results(2, 4) = i/1000;
    end
end
fprintf('\n');


fprintf('Vivaldi ');
for i=1:1000
    if (b(i) >= 0.5 & b(i-1) < 0.5)
            fprintf('%.3f ', i/1000);
            re_results(1, 5) = i/1000;
    end
    if (b(i) >= 0.9 & b(i-1) < 0.9)
            fprintf('%.3f ', i/1000);
            re_results(2, 5) = i/1000;
    end
end
fprintf('\n');

fprintf('Phoenix | Phoenix (Simple) | IDES (SVD) | IDES (NMF) | Vivaldi\n');
for i=1:2
    fprintf('Node_%d', N);
    if (i == 1)
        fprintf('_FPRE');
    else
        fprintf('_NPRE');
    end
    fprintf('=[');
    for j=1:5
        fprintf('%.3f ', re_results(i, j));
    end
    fprintf('];\n');

end

fprintf('Converge Behavior of Phoenix:');

fprintf('\n');

mfpre = mean(total_fpre);
vivaldi_mfperr = mean(total_vivaldi_fperror');
% size(total_vivaldi_fperror)
%mnpre = mean(total_npre);
fprintf('Node_%d', N);
fprintf('_Phoenix_FPRE_CONVERGE=');
fprintf('[');
ok = 0;
for i=1:30
    fprintf('%.3f ', mfpre(i));
    if (mfpre(i) < mfpre(30) * 1.05 & ok == 0)
        cc = i; ok = 1;
    end
end
fprintf('];\n');


fprintf('Node_%d', N);
fprintf('_Vivaldi_FPRE_CONVERGE=');
fprintf('[');
ok = 0;
for i=1:30
    fprintf('%.3f ', vivaldi_mfperr(i));
    if (vivaldi_mfperr(i) < vivaldi_mfperr(30) * 1.1 & ok == 0)
        cc = i; ok = 1;
    end
end
fprintf('];\n');