comparison toolboxes/alps/ALPS/infty_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] = infty_ALPS(y, Phi, K, params)
2 % =========================================================================
3 % infty-ALPS(#) algorithm - Beta Version
4 % =========================================================================
5 % Algebraic Pursuit (ALPS) algorithm with infty-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,... Value: solveNewtonb = 0. Not used in infty
23 % methods.
24 % gradientDescentx,... If gradientDescentx == 1: single gradient
25 % update of x_{i+1} restricted ot its support with
26 % line search. Default value: gradientDescentx =
27 % 1.
28 % solveNewtonx,... If solveNewtonx == 1: Akin to Hard Thresholding Pursuit
29 % (c.f. Simon Foucart, "Hard Thresholding Pursuit,"
30 % preprint, 2010). Default vale: solveNewtonx = 0
31 % tau,... Variable that controls the momentum in
32 % non-memoryless case. Ignored in memoryless
33 % case. Default value: tau = 1/2.
34 % Special cases:
35 % - tau = -1: momentum step size is automatically
36 % optimized in every step.
37 % - tau as a function handle: user defined
38 % behavior of tau momentum term.
39 % mu,... Variable that controls the step size selection.
40 % When mu = 0, step size is computed adaptively
41 % per iteration. Default value: mu = 0.
42 % cg_maxiter,... Maximum iterations for Conjugate-Gradients method.
43 % cg_tol Tolerance variable for Conjugate-Gradients method.
44 % =========================================================================
45 % OUTPUT ARGUMENTS:
46 % x_hat N x 1 recovered K-sparse vector.
47 % numiter Number of iterations executed.
48 % x_path Keeps a series of computed N x 1 K-sparse vectors
49 % until the end of the iterative process.
50 % =========================================================================
51 % 01/04/2011, by Anastasios Kyrillidis. anastasios.kyrillidis@epfl.ch, EPFL.
52 % =========================================================================
53 % cgsolve.m is written by Justin Romberg, Caltech, Oct. 2005.
54 % Email: jrom@acm.caltech.edu
55 % =========================================================================
56 % This work was supported in part by the European Commission under Grant
57 % MIRG-268398 and DARPA KeCoM program #11-DARPA-1055. VC also would like
58 % to acknowledge Rice University for his Faculty Fellowship.
59 % =========================================================================
60
61 [~,N] = size(Phi);
62
63 %% Initialize transpose of measurement matrix
64
65 Phi_t = Phi';
66
67 %% Initialize to zero vector
68 x_cur = zeros(N,1);
69 y_cur = zeros(N,1);
70 X_i = [];
71
72 x_path = zeros(N, params.ALPSiters);
73
74 %% CG params
75 if (params.solveNewtonx == 1 || params.solveNewtonb == 1)
76 cg_verbose = 0;
77 cg_A = Phi_t*Phi;
78 cg_b = Phi_t*y;
79 end;
80
81 %% Determine momentum step size selection strategy
82 optimizeTau = 0;
83 function_tau = 0;
84
85 if (isa(params.tau,'float'))
86 if (params.tau == -1)
87 optimizeTau = 1;
88 end;
89 elseif (isa(params.tau, 'function_handle'))
90 function_tau = 1;
91 end;
92
93 %% Determine step size selection strategy
94 function_mu = 0;
95 adaptive_mu = 0;
96
97 if (isa(params.mu,'float'))
98 function_mu = 0;
99 if (params.mu == 0)
100 adaptive_mu = 1;
101 else
102 adaptive_mu = 0;
103 end;
104 elseif (isa(params.mu,'function_handle'))
105 function_mu = 1;
106 end;
107
108 %% Help variables
109 complementary_Xi = ones(N,1);
110 setXi = zeros(N,1);
111 setYi = zeros(N,1);
112
113 i = 1;
114 %% infty-ALPS(#)
115 while (i <= params.ALPSiters)
116 x_path(:,i) = x_cur;
117 x_prev = x_cur;
118
119 % Compute the residual
120 if (i == 1)
121 res = y;
122 else
123 Phi_x_cur = Phi(:,X_i)*x_cur(X_i);
124 res = y - Phi_x_cur;
125 end;
126
127 % Compute the derivative
128 der = Phi_t*res;
129
130 % Determine S_i set via eq. (11)
131 complementary_Xi(X_i) = 0;
132 [~, ind_der] = sort(abs(der).*complementary_Xi, 'descend');
133 complementary_Xi(X_i) = 1;
134 S_i = [X_i; ind_der(1:K)];
135
136 ider = der(S_i);
137
138 setder = zeros(N,1);
139 setder(S_i) = 1;
140 if (adaptive_mu)
141 % Step size selection via eq. (12) and eq. (13)
142 Pder = Phi(:,S_i)*ider;
143 mu_bar = ider'*ider/(Pder'*Pder);
144 end;
145
146 iy_cur = y_cur.*setYi;
147 if (~function_tau) % If tau is not a function handle...
148 if (optimizeTau) % Compute optimized tau
149
150 % tau = argmin || u - Phi(x_i + y_i) ||
151 % = <Phi*y_i, u - Phi(x_i - mu/2 * grad_Si f(xi))>/||Phi*y_i||^2
152
153 if (i == 1)
154 params.tau = 0;
155 else
156 % u - Phi*(x_i - mu/2 grad_Si f(xi)) = u - Phi*b
157 if (adaptive_mu)
158 b = x_cur(S_i) + mu_bar*ider; % Non-zero elems: S_i
159 elseif (function_mu)
160 b = x_cur(S_i) + params.mu(i)*ider;
161 else b = x_cur(S_i) + params.mu*ider;
162 end;
163
164 y_Phi_b = y - Phi(:,S_i)*b;
165 Phi_y_prev = Phi(:,Y_i)*y_cur(Y_i); % Phi * y_i
166 params.tau = y_Phi_b'*Phi_y_prev/(Phi_y_prev'*Phi_y_prev);
167 end;
168
169 if (adaptive_mu)
170 y_cur = params.tau*iy_cur + mu_bar*der.*setder;
171 elseif (function_mu)
172 y_cur = params.tau*iy_cur + params.mu(i)*der.*setder;
173 else y_cur = params.tau*iy_cur + params.mu*der.*setder;
174 end;
175
176 Y_i = ne(y_cur,0);
177 setYi = zeros(N,1);
178 setYi(Y_i) = 1;
179 else % Tau fixed and user-defined
180 if (adaptive_mu)
181 y_cur = params.tau*iy_cur + mu_bar*der.*setder;
182 elseif (function_mu)
183 y_cur = params.tau*iy_cur + params.mu(i)*der.*setder;
184 else y_cur = params.tau*iy_cur + params.mu*der.*setder;
185 end;
186
187 Y_i = ne(y_cur,0);
188 setYi = zeros(N,1);
189 setYi(Y_i) = 1;
190 end;
191 else
192 if (adaptive_mu)
193 y_cur = params.tau(i)*iy_cur + mu_bar*der.*setder;
194 elseif (function_mu)
195 y_cur = params.tau(i)*iy_cur + params.mu(i)*der.*setder;
196 else y_cur = params.tau(i)*iy_cur + params.mu*der.*setder;
197 end;
198
199 Y_i = ne(y_cur,0);
200 setYi = zeros(N,1);
201 setYi(Y_i) = 1;
202 end;
203
204 % Hard-threshold b and compute X_{i+1}
205 set_Xi_Yi = setXi + setYi;
206 ind_Xi_Yi = find(set_Xi_Yi > 0);
207 z = x_cur(ind_Xi_Yi) + y_cur(ind_Xi_Yi);
208 [~, ind_z] = sort(abs(z), 'descend');
209 x_cur = zeros(N,1);
210 x_cur(ind_Xi_Yi(ind_z(1:K))) = z(ind_z(1:K));
211 X_i = ind_Xi_Yi(ind_z(1:K));
212
213 setXi = zeros(N,1);
214 setXi(X_i) = 1;
215
216 if (params.gradientDescentx == 1)
217 % Calculate gradient of estimated vector x_cur
218 Phi_x_cur = Phi(:,X_i)*x_cur(X_i);
219 res = y - Phi_x_cur;
220 der = Phi_t*res;
221
222 ider = der(X_i);
223
224 if (adaptive_mu)
225 Pder = Phi(:,X_i)*ider;
226 mu_bar = ider'*ider/(Pder'*Pder);
227 x_cur(X_i) = x_cur(X_i) + mu_bar*ider;
228 elseif (function_mu)
229 x_cur = x_cur(X_i) + params.mu(i)*ider;
230 else x_cur = x_cur(X_i) + params.mu*ider;
231 end;
232 elseif (params.solveNewtonx == 1)
233 % Similar to HTP
234 if (params.useCG == 1)
235 [v, ~, ~] = cgsolve(cg_A(X_i, X_i), cg_b(X_i), params.cg_tol, params.cg_maxiter, cg_verbose);
236 else
237 v = cg_A(X_i,X_i)\cg_b(X_i);
238 end;
239 x_cur(X_i) = v;
240 end;
241
242 % Test stopping criterion
243 if (i > 1) && (norm(x_cur - x_prev) < params.tol*norm(x_cur))
244 break;
245 end;
246 i = i + 1;
247 end;
248
249 x_hat = x_cur;
250 numiter = i;
251
252 if (i > params.ALPSiters)
253 x_path = x_path(:,1:numiter-1);
254 else
255 x_path = x_path(:,1:numiter);
256 end;