comparison toolboxes/alps/ALPS/one_ALPS.m @ 154:0de08f68256b ivand_dev

ALPS toolbox - Algebraic Pursuit added to smallbox
author Ivan Damnjanovic lnx <ivan.damnjanovic@eecs.qmul.ac.uk>
date Fri, 12 Aug 2011 11:17:47 +0100
parents
children
comparison
equal deleted inserted replaced
153:af307f247ac7 154:0de08f68256b
1 function [x_hat, numiter, x_path] = one_ALPS(y, Phi, K, params)
2 % =========================================================================
3 % 1-ALPS(#) algorithm - Beta Version
4 % =========================================================================
5 % Algebraic Pursuit (ALPS) algorithm with 1-memory acceleration.
6 %
7 % Detailed discussion on the algorithm can be found in
8 % [1] "On Accelerated Hard Thresholding Methods for Sparse Approximation", written
9 % by Volkan Cevher, Technical Report, 2011.
10 % =========================================================================
11 % INPUT ARGUMENTS:
12 % y M x 1 undersampled measurement vector.
13 % Phi M x N regression matrix.
14 % K Sparsity of underlying vector x* or desired
15 % sparsity of solution.
16 % params Structure of parameters. These are:
17 %
18 % tol,... Early stopping tolerance. Default value: tol =
19 % 1-e5.
20 % ALPSiters,... Maximum number of algorithm iterations. Default
21 % value: 300.
22 % solveNewtonb,... If solveNewtonb == 1: Corresponds to solving a
23 % Newton system restricted to a sparse support.
24 % It is implemented via conjugate gradients.
25 % If solveNewtonb == 0: Step size selection as described
26 % in eqs. (12) and (13) in [1].
27 % Default value: solveNewtonb = 0.
28 % gradientDescentx,... If gradientDescentx == 1: single gradient
29 % update of x_{i+1} restricted ot its support with
30 % line search. Default value: gradientDescentx =
31 % 1.
32 % solveNewtonx,... If solveNewtonx == 1: Akin to Hard Thresholding Pursuit
33 % (c.f. Simon Foucart, "Hard Thresholding Pursuit,"
34 % preprint, 2010). Default vale: solveNewtonx = 0.
35 % tau,... Variable that controls the momentum in
36 % non-memoryless case. Ignored in memoryless
37 % case. Default value: tau = 1/2.
38 % Special cases:
39 % - tau = 0: momentum step size selection is
40 % driven by the following formulas:
41 % a_1 = 1;
42 % a_{i+1} = (1+\sqrt(1+4a_i^2)/2;
43 % tau = (a_i - 1)/(a_{i+1});
44 % described in [2] "A fast iterative
45 % shrinkage-thresholding algorithm for linear
46 % inverse problems", Beck A., and Teboulle M.
47 % - tau = -1: momentum step size is automatically
48 % optimized in every step.
49 % - tau as a function handle: user defined
50 % behavior of tau momentum term.
51 % mu,... Variable that controls the step size selection.
52 % When mu = 0, step size is computed adaptively
53 % per iteration. Default value: mu = 0.
54 % cg_maxiter,... Maximum iterations for Conjugate-Gradients method.
55 % cg_tol Tolerance variable for Conjugate-Gradients method.
56 % =========================================================================
57 % OUTPUT ARGUMENTS:
58 % x_hat N x 1 recovered K-sparse vector.
59 % numiter Number of iterations executed.
60 % x_path Keeps a series of computed N x 1 K-sparse vectors
61 % until the end of the iterative process.
62 % =========================================================================
63 % 01/04/2011, by Anastasios Kyrillidis. anastasios.kyrillidis@epfl.ch, EPFL.
64 % =========================================================================
65 % cgsolve.m is written by Justin Romberg, Caltech, Oct. 2005.
66 % Email: jrom@acm.caltech.edu
67 % =========================================================================
68 % This work was supported in part by the European Commission under Grant
69 % MIRG-268398 and DARPA KeCoM program #11-DARPA-1055. VC also would like
70 % to acknowledge Rice University for his Faculty Fellowship.
71 % =========================================================================
72
73 [M,N] = size(Phi);
74
75 %% Initialize transpose of measurement matrix
76
77 Phi_t = Phi';
78
79 %% Initialize to zero vector
80 x_cur = zeros(N,1);
81 y_cur = zeros(N,1);
82 Phi_x_cur = zeros(M,1);
83 Y_i = [];
84
85 x_path = zeros(N, params.ALPSiters);
86
87 %% CG params
88 if (params.solveNewtonx == 1 || params.solveNewtonb == 1)
89 cg_verbose = 0;
90 cg_A = Phi_t*Phi;
91 cg_b = Phi_t*y;
92 end;
93
94 %% Determine momentum step size selection strategy
95 fista = 0;
96 optimizeTau = 0;
97 a_prev = 1;
98 function_tau = 0;
99
100 if (isa(params.tau,'float'))
101 function_tau = 0;
102 if (params.tau == 0)
103 fista = 1;
104 optimizeTau = 0;
105 elseif (params.tau == -1)
106 optimizeTau = 1;
107 fista = 0;
108 end;
109 elseif (isa(params.tau, 'function_handle'))
110 function_tau = 1;
111 end;
112
113 %% Determine step size selection strategy
114 function_mu = 0;
115 adaptive_mu = 0;
116
117 if (isa(params.mu,'float'))
118 function_mu = 0;
119 if (params.mu == 0)
120 adaptive_mu = 1;
121 else
122 adaptive_mu = 0;
123 end;
124 elseif (isa(params.mu,'function_handle'))
125 function_mu = 1;
126 end;
127
128 %% Help variables
129 complementary_Yi = ones(N,1);
130
131 i = 1;
132 %% 1-ALPS(#)
133 while (i <= params.ALPSiters)
134 x_path(:,i) = x_cur;
135 x_prev = x_cur;
136
137 % Compute the residual
138 if (i == 1)
139 res = y;
140 % Compute the derivative
141 der = Phi_t*res;
142 else
143 % Compute the derivative
144 if (optimizeTau)
145 res = y - Phi_x_cur - params.tau*Phi_diff;
146 else
147 res = y - Phi(:,Y_i)*y_cur(Y_i);
148 end;
149 der = Phi_t*res;
150 end;
151
152 Phi_x_prev = Phi_x_cur;
153
154 % Determine S_i set via eq. (11) (change of variable from x_i to y_i)
155 complementary_Yi(Y_i) = 0;
156 [tmpArg, ind_der] = sort(abs(der).*complementary_Yi, 'descend');
157 complementary_Yi(Y_i) = 1;
158 S_i = [Y_i; ind_der(1:K)];
159
160 ider = der(S_i);
161 if (params.solveNewtonb == 1)
162 % Compute least squares solution of the system A*y = (A*A)x using CG
163 if (params.useCG == 1)
164 [b, tmpArg, tmpArg] = cgsolve(cg_A(S_i, S_i), cg_b(S_i), params.cg_tol, params.cg_maxiter, cg_verbose);
165 else
166 b = cg_A(S_i,S_i)\cg_b(S_i);
167 end;
168 else
169 % Step size selection via eq. (12) and eq. (13) (change of variable from x_i to y_i)
170 if (adaptive_mu)
171 Pder = Phi(:,S_i)*ider;
172 mu_bar = ider'*ider/(Pder'*Pder);
173 b = y_cur(S_i) + (mu_bar)*ider;
174 elseif (function_mu)
175 b = y_cur(S_i) + params.mu(i)*ider;
176 else b = y_cur(S_i) + params.mu*ider;
177 end;
178 end;
179
180 % Hard-threshold b and compute X_{i+1}
181 [tmpArg, ind_b] = sort(abs(b), 'descend');
182 x_cur = zeros(N,1);
183 x_cur(S_i(ind_b(1:K))) = b(ind_b(1:K));
184 X_i = S_i(ind_b(1:K));
185
186 if (params.gradientDescentx == 1)
187 % Calculate gradient of estimated vector x_cur
188 Phi_x_cur = Phi(:,X_i)*x_cur(X_i);
189 res = y - Phi_x_cur;
190 der = Phi_t*res;
191 ider = der(X_i);
192
193 if (adaptive_mu)
194 Pder = Phi(:,X_i)*ider;
195 mu_bar = ider'*ider/(Pder'*Pder);
196 x_cur(X_i) = x_cur(X_i) + mu_bar*ider;
197 elseif (function_mu)
198 x_cur(X_i) = x_cur(X_i) + params.mu(i)*ider;
199 else x_cur(X_i) = x_cur(X_i) + params.mu*ider;
200 end;
201 elseif (params.solveNewtonx == 1)
202 % Similar to HTP
203 if (params.useCG == 1)
204 [v, tmpArg, tmpArg] = cgsolve(cg_A(X_i, X_i), cg_b(X_i), params.cg_tol, params.cg_maxiter, cg_verbose);
205 else
206 v = cg_A(X_i, X_i)\cg_b(X_i);
207 end;
208 x_cur(X_i) = v;
209 end;
210
211 if (~function_tau) % If tau is not a function handle...
212 if (fista) % Fista configuration
213 a_cur = (1 + sqrt(1 + 4*a_prev^2))/2;
214 params.tau = (a_prev - 1)/a_cur;
215 a_prev = a_cur;
216 elseif (optimizeTau) % Compute optimized tau
217
218 % tau = argmin ||u - Phi*y_{i+1}||
219 % = <res, Phi*(x_cur - x_prev)>/||Phi*(x_cur - x_prev)||^2
220
221 Phi_x_cur = Phi(:,X_i)*x_cur(X_i);
222 res = y - Phi_x_cur;
223 if (i == 1)
224 Phi_diff = Phi_x_cur;
225 else
226 Phi_diff = Phi_x_cur - Phi_x_prev;
227 end;
228 params.tau = res'*Phi_diff/(Phi_diff'*Phi_diff);
229 end;
230
231 y_cur = x_cur + params.tau*(x_cur - x_prev);
232 Y_i = find(ne(y_cur, 0));
233 else
234 y_cur = x_cur + params.tau(i)*(x_cur - x_prev);
235 Y_i = find(ne(y_cur, 0));
236 end;
237
238 % Test stopping criterion
239 if (i > 1) && (norm(x_cur - x_prev) < params.tol*norm(x_cur))
240 break;
241 end;
242 i = i + 1;
243 end;
244
245 x_hat = x_cur;
246 numiter= i;
247
248 if (i > params.ALPSiters)
249 x_path = x_path(:,1:numiter-1);
250 else
251 x_path = x_path(:,1:numiter);
252 end;