[~,extra_h] = unix('ls -1 /usr/local/igl/libigl/include/igl/*/*.h');
[~,extra_cpp] = unix('ls -1 /usr/local/igl/libigl/include/igl/*/*.cpp');
[~,examples] = unix('ls -1 /usr/local/igl/libigl/examples/*/*.cpp');
[~,dropbox] = unix('ls -1 ~/Dropbox/*/*.cpp');
files = textscan([ ...
  ls('~/Documents/Puppet/Code/C++/*.cpp') ...
  ls('~/Documents/Puppet/Code/C++/*.h') ...
  ls('~/Documents/EdgeBasedLaplacian/Code/C++/src/*.cpp') ...
  ls('~/Documents/EdgeBasedLaplacian/Code/C++/src/*.h') ...
  ls('~/Documents/volume/winding_number/*.cpp') ...
  ls('~/Documents/volume/winding_number/*.h') ...
  ls('~/Documents/volume/selfintersect/src/*.cpp') ...
  ls('~/Documents/volume/selfintersect/src/*.h') ...
  ls('~/Documents/volume/post_graph_cut/*.cpp') ...
  ls('~/Documents/volume/post_graph_cut/*.h') ...
  ls('~/Documents/AutoDOF/Code/skinning/skinning/*.cpp') ...
  ls('~/Documents/AutoDOF/Code/skinning/skinning/*.h') ...
  ls('/usr/local/igl/libigl/include/igl/*.h') ...
  ls('/usr/local/igl/libigl/include/igl/*.cpp') ...
  extra_h ...
  extra_cpp ...
  examples ...
  dropbox  ...
  ],'%s', 'delimiter', '\n' );
files = files{1};
[~,H,f2H] = header_adjacency(files);
% Must be included at least twice
H = H(sum(f2H,1) > 1);
f2H = f2H(:,sum(f2H,1) > 1);
A = f2H' * f2H;
% diagonal is not interesting
A = A - diag(diag(A));
% Must have at least median mutual includes to be an edge
A(A(:)<1) = 0;
% Must have at least median other mutual includes
H = H(sum(A,2)>median(sum(A,2)));
A = A( sum(A,2)>median(sum(A,2)), sum(A,2)>median(sum(A,2)));

P = rand(numel(H),2);
[EI,EJ] = find(tril(A+A'));
E = [EJ EI];
L = (A-diag(sum(A,2)));
I = 0*speye(size(L));
[EV,ED] = eigs(L+I,size(A,1),'sm');
EV = EV(:,2:end);
ED = ED(2:end, 2:end);
p = 1;
B = EV * (inv(abs(ED))^(p/2));

%nsp = 2;
%subplot(1,nsp,1);
%plot_edges(P,E);
%subplot(1,nsp,2);
plot_edges(B(:,1:3),E);

C = kmeans(B,20);

for c = 1:max(C)
  fprintf('%s\n',H{C==c});
  fprintf('\n');
end