0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 function out = l1homotopy_v1(A, y, opts)
0078
0079 N = size(A,2);
0080 M = size(A,1);
0081
0082
0083
0084 if isfield(opts,'xh_old'); xh_old = opts.xh_old; else xh_old = zeros(N,1); end
0085
0086 if isfield(opts,'pk_old'); pk_old = opts.pk_old; else pk_old = -A'*y; end
0087
0088 if isfield(opts,'gamma'); gamma_xh = opts.gamma; else gamma_xh = []; end
0089 if isempty(gamma_xh); [tau_old gamma_xh] = max(abs(pk_old)); end
0090
0091 if isfield(opts,'Atdyu'); Atdyu = opts.Atdyu; else Atdyu = 0; end
0092
0093 if isfield(opts,'W_new'); W_new = opts.W_new; else W_new = opts.tau; end
0094
0095 if isfield(opts,'W_old'); W_old = opts.W_old; else W_old = tau_old; end
0096
0097 if norm(xh_old) == 0; pk_old = -A'*y; Atdyu = 0; [tau_old gamma_xh] = max(abs(pk_old)); W_old = tau_old; end
0098
0099 if norm(y) == 0;
0100 out = opts;
0101 out.x_out = zeros(N,1);
0102 out.gamma = [];
0103 out.iter = 0;
0104 out.time = 0;
0105 disp('input is a zero vector');
0106 return;
0107 end
0108
0109 if nnz(abs(A'*y) < W_new) == N
0110 out = opts;
0111 out.x_out = zeros(N,1);
0112 out.gamma = [];
0113 out.iter = 0;
0114 out.time = 0;
0115 disp('output is a zero vector');
0116 return;
0117 end
0118
0119
0120 W_old = ones(N,1).*W_old; W_new = ones(N,1).*W_new;
0121
0122
0123 if isfield(opts,'maxiter'); maxiter = opts.maxiter; else maxiter = 2*N; end
0124
0125 if isfield(opts,'nonneg'); nonneg = opts.nonneg; else nonneg = 0; end
0126
0127 if isfield(opts,'Te'); Te = opts.Te; else Te = inf; end
0128
0129 if isfield(opts,'record'); err_record = opts.record; else err_record = 0; end
0130 if err_record; err_fun = opts.err_fun; end
0131
0132 if isfield(opts,'debias'); debias = opts.debias; else debias = 0; end
0133
0134
0135 if isfield(opts,'early_terminate'); early_terminate = opts.early_terminate; else early_terminate = 0; end
0136
0137 if isfield(opts,'verbose'); verbose = opts.verbose; else verbose = 0; end
0138
0139 if isfield(opts,'plots'); plots = opts.plots; else plots = 0; end
0140
0141
0142 t0 = cputime;
0143
0144
0145 epsilon = 0;
0146 Wk = (1-epsilon)*W_old + epsilon*W_new;
0147 dW = W_new-W_old;
0148
0149 temp_gamma = zeros(N,1);
0150 temp_gamma(gamma_xh) = gamma_xh;
0151 gamma_xc = find([1:N]' ~= temp_gamma);
0152
0153 z_x = zeros(N,1);
0154 z_x(gamma_xh) = -sign(pk_old(gamma_xh));
0155 pk_old(gamma_xh) = sign(pk_old(gamma_xh)).*W_old(gamma_xh);
0156 pk = pk_old;
0157 dk = 0*pk;
0158 xk_1 = xh_old;
0159
0160
0161 idelta = gamma_xh(1); flag = 1;
0162
0163
0164 in_delx = [];
0165 delx_mode = opts.delx_mode;
0166 rhs = -dW.*z_x-Atdyu;
0167
0168 if norm(xh_old)==0 && length(gamma_xh) == 1
0169 update_mode = 'init0';
0170 else
0171 update_mode = 'init1';
0172 end
0173 update_delx;
0174
0175
0176 done = 0;
0177 iter = 0;
0178 itr_history = [];
0179 error_table = [];
0180 if err_record
0181 error_table = [epsilon err_fun(xk_1) length(gamma_xh)];
0182 end
0183
0184 while iter < maxiter
0185 iter = iter+1;
0186
0187
0188
0189 x_k = xk_1;
0190
0191
0192 delx_vec = zeros(N,1);
0193 delx_vec(gamma_xh) = delx;
0194
0195 if ~isempty(idelta) && (sign(delx_vec(idelta)) == sign(pk_old(idelta)) && abs(x_k(idelta)) == 0)
0196 delta = 0; flag = 0;
0197 else
0198 pk = pk_old;
0199
0200
0201 dk_temp = mvprod(A,delx_vec,gamma_xh,0);
0202 dk = A'*dk_temp+Atdyu;
0203
0204
0205 in = [];
0206
0207
0208
0209 in.shrinkage_flag = 2;
0210 in.nonneg = nonneg;
0211 in.pk = pk; in.dk = dk;
0212 in.ak = Wk; in.bk = dW;
0213 in.gamma = gamma_xh; in.gamma_c = gamma_xc;
0214 in.delx_vec = delx_vec; in.x = xk_1;
0215 out = compute_delta(in);
0216 delta = out.delta; idelta = out.idelta;
0217 flag = out.flag;
0218 end
0219 e0 = epsilon;
0220 epsilon = e0 + delta;
0221
0222 if epsilon > 1
0223 delta_end = 1-e0;
0224 xk_1 = x_k + delta_end*delx_vec;
0225 pk_old = pk + delta_end*dk;
0226 Wk = W_new;
0227 pk_old(gamma_xh) = sign(pk_old(gamma_xh)).*Wk(gamma_xh);
0228 break;
0229 end
0230
0231 xk_1 = x_k + delta*delx_vec;
0232 gamma_old = gamma_xh;
0233
0234 itr_history = [itr_history; idelta delta flag];
0235
0236
0237 update_supp;
0238
0239 pk_old = pk+delta*dk;
0240 Wk_old = Wk;
0241 Wk = (1-epsilon)*W_old + epsilon*W_new;
0242 pk_old([gamma_xh; idelta]) = sign(pk_old([gamma_xh; idelta])).*Wk([gamma_xh; idelta]);
0243
0244
0245 z_x = -sign(pk_old);
0246 rhs = -dW.*z_x-Atdyu;
0247 update_mode = 'update';
0248 update_delx;
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259 if early_terminate
0260 if length(gamma_xh) < M/2
0261 xhat = zeros(N,1);
0262
0263 switch delx_mode
0264 case 'mil'
0265 xhat(gamma_xh) = iAtA*(A(:,gamma_xh)'*y);
0266 case {'qr','chol'}
0267 xhat(gamma_xh) = R\(R'\(A(:,gamma_xh)'*y));
0268 end
0269 if norm(y-A*xhat) < tau
0270 xk_1 = xhat;
0271 break;
0272 end
0273 end
0274 end
0275
0276
0277 if err_record
0278 error_table = [error_table; epsilon err_fun(xk_1) length(gamma_xh)];
0279 end
0280
0281
0282 constr_violation = nnz((abs(pk_old(gamma_xc))-Wk(gamma_xc))>1e-10);
0283 sign_violation = nnz((sign(pk_old(gamma_xh))+sign(xk_1(gamma_xh)))>1);
0284 if constr_violation
0285 chk = gamma_xc((abs(pk_old(gamma_xc))-Wk(gamma_xc))>1e-10);
0286 stp = 1;
0287 fprintf('problem... with constraint violation -- %s \n', mfilename);
0288 fprintf('Refactorize the matrix... recompute delx \n');
0289
0290 update_mode = 'init0';
0291 update_delx;
0292 end
0293 if sign_violation>=1
0294 chk = gamma_xh(sign(pk_old(gamma_xh))+sign(xk_1(gamma_xh))>1);
0295 stp = 1;
0296 fprintf('problem... sign mismatch -- %s \n',mfilename);
0297 fprintf('Refactorize the matrix... recompute delx \n');
0298 update_mode = 'init0';
0299 update_delx;
0300 end
0301
0302
0303 if mod(iter-1,verbose) == 0 && verbose
0304 fprintf(['iter = %d, delta = %3.4g, idelta = %d, flag = %d.\n'], iter, delta, idelta, flag);
0305 end
0306 if mod(iter-1,plots) == 0 && plots
0307 fig1 = figure(1234);
0308 subplot(2,1,1)
0309 hold off
0310 plot(pk,'.r', 'MarkerSize',14);
0311 hold on;
0312 plot(pk_old, 'LineWidth',1);
0313
0314 if flag == 1
0315 plot(idelta, pk_old(idelta),'or','MarkerSize',18,'LineWidth',2);
0316 text(idelta, pk_old(idelta)*1.1, ['Incoming \gamma = ',num2str(idelta)],'FontSize',14);
0317 else
0318 plot(idelta, pk_old(idelta),'ok','MarkerSize',18,'LineWidth',2);
0319 text(idelta, pk_old(idelta)*1.1, ['Outgoing \gamma = ',num2str(idelta)],'FontSize',14);
0320 end
0321 set(gca,'FontSize',16, 'XLim',[1 N] );
0322 title(sprintf('BPDN shrinkage constraints: N = %d, M = %d', N, M));
0323 plot(1:N, Wk,'--k','MarkerSize',12);
0324 plot(1:N, -Wk, '--k','MarkerSize',12);
0325 plot(1:N, Wk_old,'--m','MarkerSize',12);
0326 plot(1:N, -Wk_old, '--m','MarkerSize',12);
0327
0328 figure(fig1);
0329 subplot(2,1,2)
0330 hold off
0331 plot(x_k,'.r','MarkerSize',14); hold on;
0332 plot(xk_1,'LineWidth',1);
0333 if flag == 0
0334 plot(idelta, 0,'ok', 'MarkerSize',18,'LineWidth',2);
0335 else
0336 plot(idelta, 0,'or', 'MarkerSize',18,'LineWidth',2);
0337 end
0338 set(gca,'FontSize',16,'XLim',[1 N]);
0339 title(['Solution estimate at \epsilon = ',num2str(epsilon), ', iter. = ', num2str(iter)]);
0340
0341 if iter == 1 && verbose
0342 disp(' ');
0343 disp('Every frame in the figure corresponds to a critical point on the homotopy path.')
0344 disp('Circle represents an incoming element, star represents an outgoing element.');
0345 disp(' ');
0346 disp('Put pause somewhere in the code to see this. ');
0347 disp('For now press some key to continue...');
0348 pause
0349 end
0350 end
0351
0352 end
0353
0354
0355 if debias
0356 x_out = zeros(N,1);
0357 switch delx_mode
0358 case 'mil'
0359 x_out(gamma_xh) = iAtA*(A(:,gamma_xh)'*y);
0360 case {'qr','chol'}
0361 x_out(gamma_xh) = R\(R'\(A(:,gamma_xh)'*y));
0362 end
0363 else
0364 x_out = xk_1;
0365 end
0366
0367
0368 if err_record
0369 error_table = [error_table; epsilon err_fun(x_out) length(gamma_xh)];
0370 end
0371 total_iter = iter;
0372 total_time = cputime-t0;
0373
0374
0375 out = opts;
0376 out.x_out = x_out;
0377 out.gamma = gamma_xh;
0378 out.iter = total_iter;
0379 out.time = total_time;
0380 out.error_table = error_table;
0381 out.pk = pk_old;
0382 switch delx_mode
0383 case 'mil'
0384 out.iAtA = iAtA;
0385 case 'qr'
0386 out.Q = Q;
0387 out.R = R;
0388 case 'chol'
0389 out.R = R;
0390 case 'qrM'
0391 out.Q0 = Q0;
0392 out.R0 = R0;
0393 end
0394