sopt_mltb_fast_proj_B2 - Fast projection onto L2-ball Compute the projection onto the L2 ball, i.e. solve min_{z} ||x - z||_2^2 s.t. ||y - A z||_2 < epsilon where x is the input vector and the solution z* is returned as sol. The structure param should contain the following fields: - y: Measurements (default = 0). - A: Forward operator (default = Identity). - At: Adjoint operator (default = Identity). - epsilon: Radius of the L2 ball (default = 1e-3). - tight: 1 if A is a tight frame or 0 otherwise (default = 1). - nu: Bound on the norm^2 of the operator A, i.e. ||A x||^2 <= nu * ||x||^2 (default = 1). - tol: Tolerance for the projection onto the L2 ball. The algorithms stops if epsilon/(1-tol) <= ||y - A z||_2 <= epsilon/(1+tol) (default = 1e-3). - max_iter: Maximum number of iterations (default: 200). - verbose: Verbosity level (0 = no log, 1 = summary at convergence, 2 = print main steps; default = 1). - u: Initial vector for the dual problem, same dimension as y (default = 0). - pos: Positivity flag (1 = positive solution, 0 general complex case; default = 0). - real: Reality flag (1 = real solution, 0 = general complex case; default = 0). Outputs: - sol: Final solution. - u: Final dual vector. References: [1] M.J. Fadili and J-L. Starck, "Monotone operator splitting for optimization problems in sparse recovery" , IEEE ICIP, Cairo, Egypt, 2009. [2] Amir Beck and Marc Teboulle, "A Fast Iterative Shrinkage-Thresholding Algorithm for Linear Inverse Problems", SIAM Journal on Imaging Sciences 2 (2009), no. 1, 183--202.
0001 function [sol, u] = sopt_mltb_fast_proj_B2(x, param) 0002 % sopt_mltb_fast_proj_B2 - Fast projection onto L2-ball 0003 % 0004 % Compute the projection onto the L2 ball, i.e. solve 0005 % 0006 % min_{z} ||x - z||_2^2 s.t. ||y - A z||_2 < epsilon 0007 % 0008 % where x is the input vector and the solution z* is returned as sol. 0009 % The structure param should contain the following fields: 0010 % 0011 % - y: Measurements (default = 0). 0012 % 0013 % - A: Forward operator (default = Identity). 0014 % 0015 % - At: Adjoint operator (default = Identity). 0016 % 0017 % - epsilon: Radius of the L2 ball (default = 1e-3). 0018 % 0019 % - tight: 1 if A is a tight frame or 0 otherwise (default = 1). 0020 % 0021 % - nu: Bound on the norm^2 of the operator A, i.e. 0022 % ||A x||^2 <= nu * ||x||^2 (default = 1). 0023 % 0024 % - tol: Tolerance for the projection onto the L2 ball. The algorithms 0025 % stops if 0026 % epsilon/(1-tol) <= ||y - A z||_2 <= epsilon/(1+tol) 0027 % (default = 1e-3). 0028 % 0029 % - max_iter: Maximum number of iterations (default: 200). 0030 % 0031 % - verbose: Verbosity level (0 = no log, 1 = summary at convergence, 0032 % 2 = print main steps; default = 1). 0033 % 0034 % - u: Initial vector for the dual problem, same dimension as y 0035 % (default = 0). 0036 % 0037 % - pos: Positivity flag (1 = positive solution, 0038 % 0 general complex case; default = 0). 0039 % 0040 % - real: Reality flag (1 = real solution, 0041 % 0 = general complex case; default = 0). 0042 % 0043 % Outputs: 0044 % 0045 % - sol: Final solution. 0046 % 0047 % - u: Final dual vector. 0048 % 0049 % References: 0050 % [1] M.J. Fadili and J-L. Starck, "Monotone operator splitting for 0051 % optimization problems in sparse recovery" , IEEE ICIP, Cairo, 0052 % Egypt, 2009. 0053 % [2] Amir Beck and Marc Teboulle, "A Fast Iterative Shrinkage-Thresholding 0054 % Algorithm for Linear Inverse Problems", SIAM Journal on Imaging Sciences 0055 % 2 (2009), no. 1, 183--202. 0056 0057 % Optional input arguments 0058 if ~isfield(param, 'y'), param.y = 0; end 0059 if ~isfield(param, 'A'), param.A = @(x) x; end 0060 if ~isfield(param, 'At'), param.At = @(x) x; end 0061 if ~isfield(param, 'epsilon'), param.epsilon = 1e-3; end 0062 if ~isfield(param, 'tight'), param.tight = 1; end 0063 if ~isfield(param, 'tol'), param.tol = 1e-3; end 0064 if ~isfield(param, 'verbose'), param.verbose = 1; end 0065 if ~isfield(param, 'nu'), param.nu = 1; end 0066 if ~isfield(param, 'max_iter'), param.max_iter = 200; end 0067 if ~isfield(param, 'u'), param.u = zeros(size(param.y)); end 0068 if ~isfield(param, 'pos'), param.pos = 0; end 0069 if ~isfield(param, 'real'), param.real = 0; end 0070 0071 % Useful functions for the projection 0072 sc = @(z) z*min(param.epsilon/norm(z(:)), 1); % scaling 0073 0074 % Projection 0075 if (param.tight && ~(param.pos||param.real)) % TIGHT FRAME CASE 0076 0077 temp = param.A(x) - param.y; 0078 sol = x + 1/param.nu * param.At(sc(temp)-temp); 0079 crit_B2 = 'TOL_EPS'; iter = 0; 0080 u = 0; 0081 0082 else % NON TIGHT FRAME CASE 0083 0084 % Initializations 0085 sol = x; u = param.u; v = u; 0086 iter = 1; true = 1; told = 1; 0087 0088 % Tolerance onto the L2 ball 0089 epsilon_low = param.epsilon/(1+param.tol); 0090 epsilon_up = param.epsilon/(1-param.tol); 0091 0092 % Check if we are in the L2 ball 0093 dummy = param.A(sol); 0094 norm_res = norm(param.y(:)-dummy(:), 2); 0095 if norm_res <= epsilon_up 0096 crit_B2 = 'TOL_EPS'; true = 0; 0097 end 0098 0099 % Projection onto the L2-ball 0100 % Init 0101 if param.verbose > 1 0102 fprintf(' Proj. B2:\n'); 0103 end 0104 while true 0105 0106 % Residual 0107 res = param.A(sol) - param.y; norm_res = norm(res(:), 2); 0108 0109 % Scaling for the projection 0110 res = u*param.nu + res; norm_proj = norm(res(:), 2); 0111 0112 % Log 0113 if param.verbose>1 0114 fprintf(' Iter %i, epsilon = %e, ||y - Ax||_2 = %e\n', ... 0115 iter, param.epsilon, norm_res); 0116 end 0117 0118 % Stopping criterion 0119 if (norm_res>=epsilon_low && norm_res<=epsilon_up) 0120 crit_B2 = 'TOL_EPS'; break; 0121 elseif iter >= param.max_iter 0122 crit_B2 = 'MAX_IT'; break; 0123 end 0124 0125 % Projection onto the L2 ball 0126 t = (1+sqrt(1+4*told^2))/2; 0127 ratio = min(1, param.epsilon/norm_proj); 0128 u = v; 0129 v = 1/param.nu * (res - res*ratio); 0130 u = v + (told-1)/t * (v - u); 0131 0132 % Current estimate 0133 sol = x - param.At(u); 0134 0135 % Projection onto the non-negative orthant (positivity constraint) 0136 if (param.pos) 0137 sol = real(sol); 0138 sol(sol<0) = 0; 0139 0140 end 0141 0142 % Projection onto the real orthant (reality constraint) 0143 if (param.real) 0144 sol = real(sol); 0145 end 0146 0147 % Update number of iteration 0148 told = t; 0149 0150 % Update number of iterations 0151 iter = iter + 1; 0152 0153 end 0154 end 0155 0156 % Log after the projection onto the L2-ball 0157 if param.verbose >= 1 0158 temp = param.A(sol); 0159 fprintf([' Proj. B2: epsilon = %e, ||y-Ax||_2 = %e,', ... 0160 ' %s, iter = %i\n'], param.epsilon, norm(param.y(:)-temp(:)), ... 0161 crit_B2, iter); 0162 end 0163 0164 0165 end