function [coord, fperror] = vivaldi(D_change, dim, N, K, converge_on)
% parameters
delta = 0.25;
ce = 0.25;
iteration = 2000;
fprintf('Vivaldi\n');
neighbor = zeros(N,K);
fperror = [];
for i=1:N
    coord(i,:)=zeros(1,dim);

    % Randomly selected Neighbors
      tmp = randperm(N);
      point = 1;
      for j=1:K
          if (i ~= tmp(point))
              neighbor(i, j) = tmp(point);
              point = point + 1;
          else
             while(D_change(i, tmp(point))== 0 || D_change(i, tmp(point)) < 0)
                point = point + 1;
             end
              neighbor(i, j) = tmp(point);
              point = point+1;
          end
      end    
%      tmp = randperm(N); 
%      neighbor(i,:)= tmp(1:K);
    error(i) = 1;
end
delta_temp = delta;
predicted_matrix = zeros(N,N);
for j = 1:iteration
    for i = 1:N
        % ID_neigh = ceil(N*rand);   %choose a neighbor of node i
        ID_neigh = neighbor(i, ceil(K*rand));
        temp_delta = delta;
        if (D_change(ID_neigh, i) <= 0 | D_change(i, ID_neigh) <= 0)
            continue;
        end;
%        if (Select_delta)
            w = error(i) / (error(i) + error(ID_neigh));
%            e_s = abs(coord(i,:) * coord(ID_neigh,:)' - D_change(i, ID_neigh)) / D_change(i, ID_neigh);
            e_s = abs(Dist(coord(i,:), coord(ID_neigh,:)) - D_change(i, ID_neigh)) / D_change(i, ID_neigh);
            error(i) = e_s * ce * w + error(i) * (1 - ce * w);
%            if error(i) > 1
%                error(i) = 1;
%            end;
            delta = delta_temp * w;
%        end;
        Force = delta * ( D_change(i,ID_neigh) - Dist(coord(i,:),coord(ID_neigh,:)) ) * Direct(coord(i,:),coord(ID_neigh,:));
        coord(i,:) = coord(i,:) + Force;
    end;
    
    % Stat %
    
    if (mod(j, 64) == 0 & converge_on == 1)
        for x = 1:N        
            for y = 1:N
                predicted_matrix(x,y) = Dist(coord(x,:), coord(y,:)); 
            end;
        end;        
%        predicted_matrix = out_host*in_host;
        abs_err=absolute_error(predicted_matrix, D_change);
        fprintf('%.3f ', median(abs_err));
        fperror = [fperror; median(abs_err)];
    end
    %%%%%%%%%    
end;

fprintf('\n');