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)); |