nikcleju@17
|
1 function [xhat, Lambdahat] = GAP(y, M, MH, Omega, OmegaH, params, xinit)
|
nikcleju@17
|
2
|
nikcleju@17
|
3 %%
|
nikcleju@17
|
4 % [xhat, Lambdahat] = GAP(y, M, MH, Omega, OmegaH, params, xinit)
|
nikcleju@17
|
5 %
|
nikcleju@17
|
6 % Greedy Analysis Pursuit Algorithm
|
nikcleju@17
|
7 % This aims to find an approximate (sometimes exact) solution of
|
nikcleju@17
|
8 % xhat = argmin || Omega * x ||_0 subject to || y - M * x ||_2 <= epsilon.
|
nikcleju@17
|
9 %
|
nikcleju@17
|
10 % Outputs:
|
nikcleju@17
|
11 % xhat : estimate of the target cosparse vector x0.
|
nikcleju@17
|
12 % Lambdahat : estimate of the cosupport of x0.
|
nikcleju@17
|
13 %
|
nikcleju@17
|
14 % Inputs:
|
nikcleju@17
|
15 % y : observation/measurement vector of a target cosparse solution x0,
|
nikcleju@17
|
16 % given by relation y = M * x0 + noise.
|
nikcleju@17
|
17 % M : measurement matrix. This should be given either as a matrix or as a function handle
|
nikcleju@17
|
18 % which implements linear transformation.
|
nikcleju@17
|
19 % MH : conjugate transpose of M.
|
nikcleju@17
|
20 % Omega : analysis operator. Like M, this should be given either as a matrix or as a function
|
nikcleju@17
|
21 % handle which implements linear transformation.
|
nikcleju@17
|
22 % OmegaH : conjugate transpose of OmegaH.
|
nikcleju@17
|
23 % params : parameters that govern the behavior of the algorithm (mostly).
|
nikcleju@17
|
24 % params.num_iteration : GAP performs this number of iterations.
|
nikcleju@17
|
25 % params.greedy_level : determines how many rows of Omega GAP eliminates at each iteration.
|
nikcleju@17
|
26 % if the value is < 1, then the rows to be eliminated are determined by
|
nikcleju@17
|
27 % j : |omega_j * xhat| > greedy_level * max_i |omega_i * xhat|.
|
nikcleju@17
|
28 % if the value is >= 1, then greedy_level is the number of rows to be
|
nikcleju@17
|
29 % eliminated at each iteration.
|
nikcleju@17
|
30 % params.stopping_coefficient_size : when the maximum analysis coefficient is smaller than
|
nikcleju@17
|
31 % this, GAP terminates.
|
nikcleju@17
|
32 % params.l2solver : legitimate values are 'pseudoinverse' or 'cg'. determines which method
|
nikcleju@17
|
33 % is used to compute
|
nikcleju@17
|
34 % argmin || Omega_Lambdahat * x ||_2 subject to || y - M * x ||_2 <= epsilon.
|
nikcleju@17
|
35 % params.l2_accuracy : when l2solver is 'cg', this determines how accurately the above
|
nikcleju@17
|
36 % problem is solved.
|
nikcleju@17
|
37 % params.noise_level : this corresponds to epsilon above.
|
nikcleju@17
|
38 % xinit : initial estimate of x0 that GAP will start with. can be zeros(d, 1).
|
nikcleju@17
|
39 %
|
nikcleju@17
|
40 % Examples:
|
nikcleju@17
|
41 %
|
nikcleju@17
|
42 % Not particularly interesting:
|
nikcleju@17
|
43 % >> d = 100; p = 110; m = 60;
|
nikcleju@17
|
44 % >> M = randn(m, d);
|
nikcleju@17
|
45 % >> Omega = randn(p, d);
|
nikcleju@17
|
46 % >> y = M * x0 + noise;
|
nikcleju@17
|
47 % >> params.num_iteration = 40;
|
nikcleju@17
|
48 % >> params.greedy_level = 0.9;
|
nikcleju@17
|
49 % >> params.stopping_coefficient_size = 1e-4;
|
nikcleju@17
|
50 % >> params.l2solver = 'pseudoinverse';
|
nikcleju@17
|
51 % >> [xhat, Lambdahat] = GAP(y, M, M', Omega, Omega', params, zeros(d, 1));
|
nikcleju@17
|
52 %
|
nikcleju@17
|
53 % Assuming that FourierSampling.m, FourierSamplingH.m, FDAnalysis.m, etc. exist:
|
nikcleju@17
|
54 % >> n = 128;
|
nikcleju@17
|
55 % >> M = @(t) FourierSampling(t, n);
|
nikcleju@17
|
56 % >> MH = @(u) FourierSamplingH(u, n);
|
nikcleju@17
|
57 % >> Omega = @(t) FDAnalysis(t, n);
|
nikcleju@17
|
58 % >> OmegaH = @(u) FDSynthesis(t, n);
|
nikcleju@17
|
59 % >> params.num_iteration = 1000;
|
nikcleju@17
|
60 % >> params.greedy_level = 50;
|
nikcleju@17
|
61 % >> params.stopping_coefficient_size = 1e-5;
|
nikcleju@17
|
62 % >> params.l2solver = 'cg'; % in fact, 'pseudoinverse' does not even make sense.
|
nikcleju@17
|
63 % >> [xhat, Lambdahat] = GAP(y, M, MH, Omega, OmegaH, params, zeros(d, 1));
|
nikcleju@17
|
64 %
|
nikcleju@17
|
65 % Above: FourierSampling and FourierSamplingH are conjugate transpose of each other.
|
nikcleju@17
|
66 % FDAnalysis and FDSynthesis are conjugate transpose of each other.
|
nikcleju@17
|
67 % These routines are problem specific and need to be implemented by the user.
|
nikcleju@17
|
68
|
nikcleju@17
|
69 d = length(xinit(:));
|
nikcleju@17
|
70
|
nikcleju@17
|
71 if strcmp(class(Omega), 'function_handle')
|
nikcleju@17
|
72 p = length(Omega(zeros(d,1)));
|
nikcleju@17
|
73 else %% Omega is a matrix
|
nikcleju@17
|
74 p = size(Omega, 1);
|
nikcleju@17
|
75 end
|
nikcleju@17
|
76
|
nikcleju@17
|
77 iter = 0;
|
nikcleju@17
|
78 lagmult = 1e-4;
|
nikcleju@17
|
79 Lambdahat = 1:p;
|
nikcleju@17
|
80 while iter < params.num_iteration
|
nikcleju@17
|
81 iter = iter + 1;
|
nikcleju@17
|
82 [xhat, analysis_repr, lagmult] = ArgminOperL2Constrained(y, M, MH, Omega, OmegaH, Lambdahat, xinit, lagmult, params);
|
nikcleju@17
|
83 [to_be_removed, maxcoef] = FindRowsToRemove(analysis_repr, params.greedy_level);
|
nikcleju@17
|
84 %disp(['** maxcoef=', num2str(maxcoef), ' target=', num2str(params.stopping_coefficient_size), ' rows_remaining=', num2str(length(Lambdahat)), ' lagmult=', num2str(lagmult)]);
|
nikcleju@17
|
85 if check_stopping_criteria(xhat, xinit, maxcoef, lagmult, Lambdahat, params)
|
nikcleju@17
|
86 break;
|
nikcleju@17
|
87 end
|
nikcleju@17
|
88 xinit = xhat;
|
nikcleju@17
|
89 Lambdahat(to_be_removed) = [];
|
nikcleju@17
|
90
|
nikcleju@17
|
91 %n = sqrt(d);
|
nikcleju@17
|
92 %figure(9);
|
nikcleju@17
|
93 %RR = zeros(2*n, n-1);
|
nikcleju@17
|
94 %RR(Lambdahat) = 1;
|
nikcleju@17
|
95 %XD = ones(n, n);
|
nikcleju@17
|
96 %XD(:, 2:end) = XD(:, 2:end) .* RR(1:n, :);
|
nikcleju@17
|
97 %XD(:, 1:(end-1)) = XD(:, 1:(end-1)) .* RR(1:n, :);
|
nikcleju@17
|
98 %XD(2:end, :) = XD(2:end, :) .* RR((n+1):(2*n), :)';
|
nikcleju@17
|
99 %XD(1:(end-1), :) = XD(1:(end-1), :) .* RR((n+1):(2*n), :)';
|
nikcleju@17
|
100 %XD = FD2DiagnosisPlot(n, Lambdahat);
|
nikcleju@17
|
101 %imshow(XD);
|
nikcleju@17
|
102 %figure(10);
|
nikcleju@17
|
103 %imshow(reshape(real(xhat), n, n));
|
nikcleju@17
|
104 end
|
nikcleju@17
|
105 return;
|
nikcleju@17
|
106
|
nikcleju@17
|
107
|
nikcleju@17
|
108 function [to_be_removed, maxcoef] = FindRowsToRemove(analysis_repr, greedy_level)
|
nikcleju@17
|
109
|
nikcleju@17
|
110 abscoef = abs(analysis_repr(:));
|
nikcleju@17
|
111 n = length(abscoef);
|
nikcleju@17
|
112 maxcoef = max(abscoef);
|
nikcleju@17
|
113 if greedy_level >= 1
|
nikcleju@17
|
114 qq = quantile(abscoef, 1-greedy_level/n);
|
nikcleju@17
|
115 else
|
nikcleju@17
|
116 qq = maxcoef*greedy_level;
|
nikcleju@17
|
117 end
|
nikcleju@17
|
118
|
nikcleju@17
|
119 to_be_removed = find(abscoef >= qq);
|
nikcleju@17
|
120 return;
|
nikcleju@17
|
121
|
nikcleju@17
|
122 function r = check_stopping_criteria(xhat, xinit, maxcoef, lagmult, Lambdahat, params)
|
nikcleju@17
|
123
|
nikcleju@17
|
124 r = 0;
|
nikcleju@17
|
125
|
nikcleju@17
|
126 if isfield(params, 'stopping_coefficient_size') && maxcoef < params.stopping_coefficient_size
|
nikcleju@17
|
127 r = 1;
|
nikcleju@17
|
128 return;
|
nikcleju@17
|
129 end
|
nikcleju@17
|
130
|
nikcleju@17
|
131 if isfield(params, 'stopping_lagrange_multiplier_size') && lagmult > params.stopping_lagrange_multiplier_size
|
nikcleju@17
|
132 r = 1;
|
nikcleju@17
|
133 return;
|
nikcleju@17
|
134 end
|
nikcleju@17
|
135
|
nikcleju@17
|
136 if isfield(params, 'stopping_relative_solution_change') && norm(xhat-xinit)/norm(xhat) < params.stopping_relative_solution_change
|
nikcleju@17
|
137 r = 1;
|
nikcleju@17
|
138 return;
|
nikcleju@17
|
139 end
|
nikcleju@17
|
140
|
nikcleju@17
|
141 if isfield(params, 'stopping_cosparsity') && length(Lambdahat) < params.stopping_cosparsity
|
nikcleju@17
|
142 r = 1;
|
nikcleju@17
|
143 return;
|
nikcleju@17
|
144 end
|