function [resistance_distances] = gsp_resistance_distances(G,param)
%GSP_RESISTANCE_DISTANCES : Compute the resitance distances of a graph
%   Usage: rd = gsp_resistance_distances(G);
%          rd = gsp_resistance_distances(L);
%
%   Input parameters:
%       G    : Graph structure or Laplacian matrix (L)
%       param: optional parameters
%   Output parameters:
%       rd   : distance matrix
%
%   This function compute the resistance distances between all vertices in 
%   a graph. The distance between two nodes is defined as the inverse of 
%   the weight matrix. For example the distance matrix:
%
%           dist = [0, 3, 1;...
%                   3, 0, 2;...
%                   1, 2, 0];
%
%   corresponds to the weight matrix:
%
%           W = [0, 1/3, 1/1;...
%                1/3, 0, 1/2;...
%                1/1, 1/2, 0];
%
%   The function will compute the resistance distance following 
%   Kirshoff's law. In the our example it is:
%
%           rd2 = [0, 3/2, 5/6;...
%                  3/2, 0, 4/3;...
%                  5/6, 4/3, 0]
%
%   In matlab, you can reproduce this example using:
%
%           % The weight 
%           dist = [0, 3, 1;...
%                   3, 0, 2;...
%                   1, 2, 0];
%           % The weight is the inverse of the distance...
%           W = dist.^(-1);
%           % Fix the diagonal
%           W([1,5,9])=0;    
%           G = gsp_graph(W);
%           rd = gsp_resistance_distance(G)
%           % Resitance computed by hand
%           rd2 = [0, 3/2, 5/6;...
%                  3/2, 0, 4/3;...
%                  5/6, 4/3, 0]
%
%   param is an optional structure that contains the following field
%
%    param.verbose*: display parameter - 0 no log - 1 display warnings
%     (default 1)
%   
%   References:
%     D. J. Klein and M. Randic. Resistance distance. Journal of Mathematical
%     Chemistry, 12(1):81--95, 1993.
%     
%     
%
%   Url: https://epfl-lts2.github.io/gspbox-html/doc/utils/gsp_resistance_distances.html

% Copyright (C) 2013-2016 Nathanael Perraudin, Johan Paratte, David I Shuman.
% This file is part of GSPbox version 0.7.5
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% If you use this toolbox please kindly cite
%     N. Perraudin, J. Paratte, D. Shuman, V. Kalofolias, P. Vandergheynst,
%     and D. K. Hammond. GSPBOX: A toolbox for signal processing on graphs.
%     ArXiv e-prints, Aug. 2014.
% http://arxiv.org/abs/1408.5781

% Author: Nathanael Perraudin, David Shuman
% Testing: test_resistance_distance

if nargin < 2
    param = struct;
end

if ~isfield(param,'verbose')
    param.verbose = 1;
end

if isstruct(G)
    % Use the non normalized laplacian
    if ~strcmp(G.lap_type, 'combinatorial')
        G = gsp_create_laplacian(G,'combinatorial');
        if param.verbose
            fprintf(['Compute the combinatorial laplacian ',...
            'for the resitance distance\n']);
        end
    end
    L = G.L;
    if (isfield(G,'U') || isfield (G,'e') )
        if issorted(G.e)
            pseudo=G.U(:,2:G.N)*diag(1./G.e(2:G.N))*G.U(:,2:G.N)';
        else
            [e, si] = sort(G.e,'ascend');
            U = G.U(:,si);
            pseudo=U(:,2:G.N)*diag(1./e(2:G.N))*U(:,2:G.N)';
        end
    else 
        pseudo=pinv(full(L));
    end
else
    L = G;
    pseudo=pinv(full(L));
end

N=size(L,1);
d = diag(pseudo);
resistance_distances = repmat(d,1,N) + repmat(d',N,1) - pseudo - pseudo';



