annotate matlab/SL0/SL0_approx.m @ 68:cab8a215f9a1 tip

Minor
author Nic Cleju <nikcleju@gmail.com>
date Tue, 09 Jul 2013 14:50:09 +0300
parents 0d66a0aafb39
children
rev   line source
nikcleju@10 1 function s=SL0_approx(A, x, eps, sigma_min, sigma_decrease_factor, mu_0, L, A_pinv, true_s)
nikcleju@10 2 %
nikcleju@10 3 % SL0(A, x, sigma_min, sigma_decrease_factor, mu_0, L, A_pinv, true_s)
nikcleju@10 4 %
nikcleju@10 5 % Returns the sparsest vector s which satisfies underdetermined system of
nikcleju@10 6 % linear equations A*s=x, using Smoothed L0 (SL0) algorithm. Note that
nikcleju@10 7 % the matrix A should be a 'wide' matrix (more columns than rows). The
nikcleju@10 8 % number of the rows of matrix A should be equal to the length of the
nikcleju@10 9 % column vector x.
nikcleju@10 10 %
nikcleju@10 11 % The first 3 arguments should necessarily be provided by the user. The
nikcleju@10 12 % other parameters have defult values calculated within the function, or
nikcleju@10 13 % may be provided by the user.
nikcleju@10 14 %
nikcleju@10 15 % Sequence of Sigma (sigma_min and sigma_decrease_factor):
nikcleju@10 16 % This is a decreasing geometric sequence of positive numbers:
nikcleju@10 17 % - The first element of the sequence of sigma is calculated
nikcleju@10 18 % automatically. The last element is given by 'sigma_min', and the
nikcleju@10 19 % change factor for decreasing sigma is given by 'sigma_decrease_factor'.
nikcleju@10 20 % - The default value of 'sigma_decrease_factor' is 0.5. Larger value
nikcleju@10 21 % gives better results for less sparse sources, but it uses more steps
nikcleju@10 22 % on sigma to reach sigma_min, and hence it requires higher
nikcleju@10 23 % computational cost.
nikcleju@10 24 % - There is no default value for 'sigma_min', and it should be
nikcleju@10 25 % provided by the user (depending on his/her estimated source noise
nikcleju@10 26 % level, or his/her desired accuracy). By `noise' we mean here the
nikcleju@10 27 % noise in the sources, that is, the energy of the inactive elements of
nikcleju@10 28 % 's'. For example, by the noiseless case, we mean the inactive
nikcleju@10 29 % elements of 's' are exactly equal to zero. As a rule of tumb, for the
nikcleju@10 30 % noisy case, sigma_min should be about 2 to 4 times of the standard
nikcleju@10 31 % deviation of this noise. For the noiseless case, smaller 'sigma_min'
nikcleju@10 32 % results in better estimation of the sparsest solution, and hence its
nikcleju@10 33 % value is determined by the desired accuracy.
nikcleju@10 34 %
nikcleju@10 35 % mu_0:
nikcleju@10 36 % The value of mu_0 scales the sequence of mu. For each vlue of
nikcleju@10 37 % sigma, the value of mu is chosen via mu=mu_0*sigma^2. Note that this
nikcleju@10 38 % value effects Convergence.
nikcleju@10 39 % The default value is mu_0=2 (see the paper).
nikcleju@10 40 %
nikcleju@10 41 % L:
nikcleju@10 42 % number of iterations of the internal (steepest ascent) loop. The
nikcleju@10 43 % default value is L=3.
nikcleju@10 44 %
nikcleju@10 45 % A_pinv:
nikcleju@10 46 % is the pseudo-inverse of matrix A defined by A_pinv=A'*inv(A*A').
nikcleju@10 47 % If it is not provided, it will be calculated within the function. If
nikcleju@10 48 % you use this function for solving x(t)=A s(t) for different values of
nikcleju@10 49 % 't', it would be a good idea to calculate A_pinv outside the function
nikcleju@10 50 % to prevent its re-calculation for each 't'.
nikcleju@10 51 %
nikcleju@10 52 % true_s:
nikcleju@10 53 % is the true value of the sparse solution. This argument is for
nikcleju@10 54 % simulation purposes. If it is provided by the user, then the function
nikcleju@10 55 % will calculate the SNR of the estimation for each value of sigma and
nikcleju@10 56 % it provides a progress report.
nikcleju@10 57 %
nikcleju@10 58 % Authors: Massoud Babaie-Zadeh and Hossein Mohimani
nikcleju@10 59 % Version: 1.4
nikcleju@10 60 % Last modified: 4 April 2010.
nikcleju@10 61 %
nikcleju@10 62 %
nikcleju@10 63 % Web-page:
nikcleju@10 64 % ------------------
nikcleju@10 65 % http://ee.sharif.ir/~SLzero
nikcleju@10 66 %
nikcleju@10 67 % Code History:
nikcleju@10 68 %--------------
nikcleju@10 69 % Version 2.0: 4 April 2010
nikcleju@10 70 % Doing a few small modifications that enable the code to work also
nikcleju@10 71 % for complex numbers (not only for real numbers).
nikcleju@10 72 %
nikcleju@10 73 % Version 1.3: 13 Sep 2008
nikcleju@10 74 % Just a few modifications in the comments
nikcleju@10 75 %
nikcleju@10 76 % Version 1.2: Adding some more comments in the help section
nikcleju@10 77 %
nikcleju@10 78 % Version 1.1: 4 August 2008
nikcleju@10 79 % - Using MATLAB's pseudo inverse function to generalize for the case
nikcleju@10 80 % the matrix A is not full-rank.
nikcleju@10 81 %
nikcleju@10 82 % Version 1.0 (first official version): 4 July 2008.
nikcleju@10 83 %
nikcleju@10 84 % First non-official version and algorithm development: Summer 2006
nikcleju@10 85
nikcleju@10 86 if nargin < 5
nikcleju@10 87 sigma_decrease_factor = 0.5;
nikcleju@10 88 A_pinv = pinv(A);
nikcleju@10 89 mu_0 = 2;
nikcleju@10 90 L = 3;
nikcleju@10 91 ShowProgress = logical(0);
nikcleju@10 92 elseif nargin == 5
nikcleju@10 93 A_pinv = pinv(A);
nikcleju@10 94 mu_0 = 2;
nikcleju@10 95 L = 3;
nikcleju@10 96 ShowProgress = logical(0);
nikcleju@10 97 elseif nargin == 6
nikcleju@10 98 A_pinv = pinv(A);
nikcleju@10 99 L = 3;
nikcleju@10 100 ShowProgress = logical(0);
nikcleju@10 101 elseif nargin == 7
nikcleju@10 102 A_pinv = pinv(A);
nikcleju@10 103 ShowProgress = logical(0);
nikcleju@10 104 elseif nargin == 8
nikcleju@10 105 ShowProgress = logical(0);
nikcleju@10 106 elseif nargin == 9
nikcleju@10 107 ShowProgress = logical(1);
nikcleju@10 108 else
nikcleju@10 109 error('Error in calling SL0_approx function');
nikcleju@10 110 end
nikcleju@10 111
nikcleju@10 112
nikcleju@10 113 % Initialization
nikcleju@10 114 %s = A\x;
nikcleju@10 115 s = A_pinv*x;
nikcleju@15 116 sigma = 2*max(abs(s));
nikcleju@10 117
nikcleju@10 118 % Main Loop
nikcleju@10 119 while sigma>sigma_min
nikcleju@10 120 for i=1:L
nikcleju@10 121 delta = OurDelta(s,sigma);
nikcleju@10 122 % Update s in the direction of steepest ascent
nikcleju@10 123 s = s - mu_0*delta;
nikcleju@10 124 % At this point, s no longer exactly satisfies x = A*s
nikcleju@10 125 % The original SL0 algorithm projects s onto {s | x = As} with
nikcleju@10 126 %s = s - A_pinv*(A*s-x); % Projection
nikcleju@10 127 % We want to project s onto {s | |x-As| < eps}
nikcleju@10 128 % We move onto the direction -A_pinv*(A*s-x), but only with a
nikcleju@10 129 % smaller step:
nikcleju@10 130 dir = A_pinv*(A*s-x);
nikcleju@10 131 if norm(A*dir) >= eps
nikcleju@10 132 s = s - (1-eps/norm(A*dir)) * dir;
nikcleju@10 133 end
nikcleju@12 134 assert(norm(x - A*s) < eps + 1e-6)
nikcleju@10 135 end
nikcleju@10 136
nikcleju@10 137 if ShowProgress
nikcleju@10 138 fprintf(' sigma=%f, SNR=%f\n',sigma,estimate_SNR(s,true_s))
nikcleju@10 139 end
nikcleju@10 140
nikcleju@10 141 sigma = sigma * sigma_decrease_factor;
nikcleju@10 142 end
nikcleju@10 143
nikcleju@10 144
nikcleju@10 145 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nikcleju@10 146 function delta=OurDelta(s,sigma)
nikcleju@10 147
nikcleju@10 148 delta = s.*exp(-abs(s).^2/sigma^2);
nikcleju@10 149
nikcleju@10 150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nikcleju@10 151 function SNR=estimate_SNR(estim_s,true_s)
nikcleju@10 152
nikcleju@10 153 err = true_s - estim_s;
nikcleju@10 154 SNR = 10*log10(sum(abs(true_s).^2)/sum(abs(err).^2));