function [ d , l , ncc , k ] = charg( A , bequiet )
%CHARG  calculates characteristic values of a graph
%
%   [d,l,ncc,k] = CHARG(A) calculates four characteristic values 
%      of the corresponding graph of the adjacency matrix A where
%         d: diameter (as of longest shortest path)
%         l: average path length
%       ncc: the number of connected components
%         k: average node degree
%
%       Note: If A is reducible, a warning is issued.
%
%  Last change:  10/2/2005 - Florian Knorn

if nargin < 1
    error('Please input adjacency matrix !');
else
	A = logical(sparse(A));
	n = size(A,1);
	if n ~= size(A,2)
        error('Please input SQUARE matrix !');
    end
end

% some initialisation
nn = n^2; d = 0; l = 0; count = [];

k = avk(A);

Asum1 = sparse(n,n); Asum2 = speye(n);
while (nnz(Asum2) ~= nn) & (nnz(Asum2)-nnz(Asum1) ~= 0) & (d <= n)
	d = d + 1; Asum1 = Asum2; Asum2 = Asum1 + Asum1*A;
	count(d) = nnz(Asum2)-nnz(Asum1); % calculate "gain" of new shortest paths
end
% output warning if graph is not connected
if (nnz(Asum2) - nnz(Asum1) == 0) | (d == n)
	disp(' '); warning off backtrace; warning('Graph is not connected !'); d = d - 1;
end

% finish calculating average path length
for i=1:length(count)
	l = l + count(i)*i;
end
l = l/sum(count);

% calculate number of connected components
ncc = 0;
while ~isempty(Asum2)
	ncc = ncc + 1;
	zeroz = find(Asum2(1,:)==0);
	Asum2 = Asum2(zeroz,zeroz);
end

if exist('bequiet')
	if ~bequiet
		disp(sprintf('diam.: %i, av.pl.: %i, ncc.: %i',d,l,ncc));
	end
else
	disp(sprintf('diam.: %i \t|\t av.pl.: %f \t|\t ncc.: %i \t|\t av.nd.: %f',d,l,ncc,k));
end