% Create random frame (in the unit circle).
% function [D,A,B] = RandFrame(dim,M,show,max_loop)
%
% usage:  D = RandFrame(dim,M,show,max_loop)
%         [D,A,B] = RandFrame(dim,M,show,max_loop)
%         [D,fc] = RandFrame(dim,M,show,max_loop)
%
% This simple algorithm creates a random frame with elements of 
% length <= 1 by creating random matrices and checking, if their ranks are
% full. For 2- and 3-dimensional frames the elements are plotted using 
% PlotFrame.m 
%  
% inputs : dim ......... dimension of the space 
%          M ........... number of frame elements
%
% Options: 'show' ........ print text and plot graph 
%                          (for dimension 2 and 3)
%          'max=XX' ...... set maximum number of loops to search
%          'randomangle' . randomize the angle (and norm), only possible
%                          for dimension 2
%          'unitnorm' .... only randomize angle 
%          'tight' ....... create tight frame (by creating a general frame
%                          and applying S^{1/2}
%
% output:  D ......... synthesis matrix of frames of dimension dim x M
%          A ......... optimal lower frame bound
%          B ......... optimal upper frame bound
%          fc ........ frame condition number
%
% test:   M = 5;
%         dim = 3;
%         D = RandFrame(dim,M);
%
% date: 27/06/2006 
% latest changes: 05/09/2007
%
% Author:  XXL .. Peter Balazs, contact: Peter.Balazs@oeaw.ac.at
%
% Literature : [Xxl] P. Balazs;Frames and Finite Dimensionality: 
%                    Frame Transformation, Classification and Algorithms; 
%                    preprint (2007)
%
% See also: ApprFramMult.m, PlotFrame.m, framebounds.m
%
% Copyright : (c) Acoustics Research Institute, Austrian Academy of
%              Sciences
%              http://www.kfs.oeaw.ac.at
function [D,A,B] = RandFrame(dim,M,varargin)

if nargin < 2
    error('Two inputs needed! Type help RandFrame.');
end

if isnumeric(dim) ~= 1 || dim < 2 || round(dim) ~= dim
    error(sprintf('Dimensionality (input: dim, now: %g) has to be an integer at least 2.',dim));
elseif isnumeric(M) ~= 1 || round(M) ~= M || M < dim
    error(sprintf('Number of elements (input: M, now: %g) has to be an integer bigger or equal than dim (now: %g).',M,dim));
elseif M == dim && show == 1
    disp(sprintf('WARNING! Number of elements (%g) is equal to the dimension (%g). It can take a while until a random frame can be found.',M,dim));
end

show = 0;
max_loop = 100;
maketight = 0;
rand_angle = 0;
fix_norm = 0;

for ii=1:length(varargin)
  option=varargin{ii};
  if length(option)> 4 && lower(option(1:4))=='max='
      max_i = option(5:length(option)); 
      if isnumeric(max_i) && max_i > 0 && max_i == round(max_i)
          max_loop = max_i;
      else
         disp(sprintf('WARNING: Unknown option in Plotframe: %s',option));
      end
  else
      switch(lower(option))
        case {'show'}
          show = 1;
        case ('tight')
          maketight = 1;
        case ('unitnorm')
            if dim ~= 2 
                error(sprintf('Option "unitnorm" is currently only implemented for dim=2.',M,dim));
            end
            rand_angle = 1;
            fix_norm = 1;
        case ('randomangle');
            if dim ~= 2 
                error(sprintf('Option "unitnorm" is currently only implemented for dim=2.',M,dim));
            end
            rand_angle = 1;      
        otherwise
            disp(sprintf('WARNING: Unknown option in Plotframe: %s',option));
      end;
  end
end;

D = zeros(dim,M);
loop = 0;
while rank(D) ~= dim && loop < max_loop
    if rand_angle == 0
        D = (rand(dim,M)-0.5)*2;
    else
        Phi = rand(dim,M)*2*pi;
        if fix_norm == 1
            Rho = zeros(dim,M)+1;
        else
            Rho = rand(dim,M);
        end
        if dim == 2
            [X,Y] = pol2cart(THETA,RHO);
            D = [X(:),Y(:)].';
        else
            error('Problem with Error handling! Polar coefficients only implemented for dimensions 2 and 3.');
        end
    end
    loop = loop +1;
end;

if loop == max_loop
    disp(sprintf('In %i loops no fittings frame was found',max_loop));
    D = []; A=0; B=0;
else
    [A B] = framebounds(D);
    if show == 1
        disp(sprintf('Created a frame with lower bound A = %g and upper bound B = %g',A,B));
        % plot frames if possible
        if dim == 2 || dim == 3
            PlotFrame(D);
        end
    end
end
if maketight == 1
    S = D*D';
    D = S^(-1/2)*D;
end
if nargout == 2
    A = B/A;
end