function [A G res muMin] = grassmannian(n,m,nIter,dd1,dd2,initA,verb)
% grassmanian attempts to create an n by m matrix with minimal mutual
% coherence using an iterative projection method.
%
% [A G res] = grassmanian(n,m,nIter,dd1,dd2,initA)
%
%
%% Parameters and Defaults
error(nargchk(2,7,nargin));

if ~exist('verb','var')  || isempty(verb),  verb = false; end %verbose output
if ~exist('initA','var') || isempty(initA), initA = randn(n,m); end %initial matrix
if ~exist('dd2','var')   || isempty(dd2),   dd2 = 0.95; end %shrinking factor
if ~exist('dd1','var')   || isempty(dd1),   dd1 = 0.9; end %percentage of coherences to be shrinked
if ~exist('nIter','var') || isempty(nIter), nIter = 5; end %number of iterations

%% Compute svd and gramian
A = normc(initA); %normalise columns
[Uinit Sigma] = svd(A); %calculate svd of the matrix
G = A'*A; %gramian matrix

muMin = sqrt((m-n)/(n*(m-1)));              %Lower bound on mutual coherence
res = zeros(nIter,1);
for iIter = 1:nIter
   gg  = sort(abs(G(:))); %sort inner products from less to ost correlated
   pos = find(abs(G(:))>gg(round(dd1*(m^2-m))) & abs(G(:)-1)>1e-6); 
   G(pos) = G(pos)*dd2;
   [U S V] = svd(G);
   S(n+1:end,1+n:end) = 0;
   G = U*S*V';
   G = diag(1./abs(sqrt(diag(G))))*G*diag(1./abs(sqrt(diag(G))));
   gg = sort(abs(G(:)));
   pos = find(abs(G(:))>gg(round(dd1*(m^2-m))) & abs(G(:)-1)>1e-6);
   res(iIter) = max(abs(G(pos)));
   if verb
    fprintf(1,'%6i  %12.8f   %12.8f  %12.8f \n',...
            [iIter,muMin,mean(abs(G(pos))),max(abs(G(pos)))]);
   end
end

[~, Sigma_gram V_gram] = svd(G); %calculate svd decomposition of gramian
Sigma_new = sqrt(Sigma_gram(1:n,:)).*sign(Sigma);
A = Uinit*Sigma_new*V_gram';
A = normc(A);
