sopt_mltb_prox_L1 - Proximal operator with L1 norm Compute the L1 proximal operator, i.e. solve min_{z} 0.5*||x - z||_2^2 + lambda * ||Psit x||_1 , where x is the input vector and the solution z* is returned as sol. The structure param should contain the following fields: - Psit: Sparsifying transform (default = Identity). - Psi: Adjoint of Psit (default = Identity). - tight: 1 if Psit is a tight frame or 0 otherwise (default = 1). - nu: Bound on the norm^2 of the operator Psi, i.e. ||Psi x||^2 <= nu * ||x||^2 (default = 1). - max_iter: Maximum number of iterations (default = 200). - rel_obj: Minimum relative change of the objective value (default = 1e-4). The algorithm stops if | ||x(t)||_1 - ||x(t-1)||_1 | / ||x(t)||_1 < rel_obj, where x(t) is the estimate of the solution at iteration t. - verbose: Verbosity level (0 = no log, 1 = summary at convergence, 2 = print main steps; default = 1). - weights: Weights for a weighted L1-norm (default = 1). - pos: Positivity flag (1 = positive solution, 0 = general complex case; default = 0). 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 = sopt_mltb_prox_L1(x, lambda, param) 0002 % sopt_mltb_prox_L1 - Proximal operator with L1 norm 0003 % 0004 % Compute the L1 proximal operator, i.e. solve 0005 % 0006 % min_{z} 0.5*||x - z||_2^2 + lambda * ||Psit x||_1 , 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 % - Psit: Sparsifying transform (default = Identity). 0012 % 0013 % - Psi: Adjoint of Psit (default = Identity). 0014 % 0015 % - tight: 1 if Psit is a tight frame or 0 otherwise (default = 1). 0016 % 0017 % - nu: Bound on the norm^2 of the operator Psi, i.e. 0018 % ||Psi x||^2 <= nu * ||x||^2 (default = 1). 0019 % 0020 % - max_iter: Maximum number of iterations (default = 200). 0021 % 0022 % - rel_obj: Minimum relative change of the objective value 0023 % (default = 1e-4). The algorithm stops if 0024 % | ||x(t)||_1 - ||x(t-1)||_1 | / ||x(t)||_1 < rel_obj, 0025 % where x(t) is the estimate of the solution at iteration t. 0026 % 0027 % - verbose: Verbosity level (0 = no log, 1 = summary at convergence, 0028 % 2 = print main steps; default = 1). 0029 % 0030 % - weights: Weights for a weighted L1-norm (default = 1). 0031 % 0032 % - pos: Positivity flag (1 = positive solution, 0033 % 0 = general complex case; default = 0). 0034 % 0035 % References: 0036 % [1] M.J. Fadili and J-L. Starck, "Monotone operator splitting for 0037 % optimization problems in sparse recovery" , IEEE ICIP, Cairo, 0038 % Egypt, 2009. 0039 % [2] Amir Beck and Marc Teboulle, "A Fast Iterative Shrinkage-Thresholding 0040 % Algorithm for Linear Inverse Problems", SIAM Journal on Imaging Sciences 0041 % 2 (2009), no. 1, 183--202. 0042 0043 % Optional input arguments 0044 if ~isfield(param, 'verbose'), param.verbose = 1; end 0045 if ~isfield(param, 'Psit'), param.Psi = @(x) x; param.Psit = @(x) x; end 0046 if ~isfield(param, 'tight'), param.tight = 1; end 0047 if ~isfield(param, 'nu'), param.nu = 1; end 0048 if ~isfield(param, 'rel_obj'), param.rel_obj = 1e-4; end 0049 if ~isfield(param, 'max_iter'), param.max_iter = 200; end 0050 if ~isfield(param, 'Psit'), param.Psit = @(x) x; end 0051 if ~isfield(param, 'Psi'), param.Psi = @(x) x; end 0052 if ~isfield(param, 'weights'), param.weights = 1; end 0053 if ~isfield(param, 'pos'), param.pos = 0; end 0054 0055 % Useful functions 0056 soft = @(z, T) sign(z).*max(abs(z)-T, 0); 0057 0058 % Projection 0059 if param.tight && ~param.pos % TIGHT FRAME CASE 0060 0061 temp = param.Psit(x); 0062 sol = x + 1/param.nu * param.Psi(soft(temp, ... 0063 lambda*param.nu*param.weights)-temp); 0064 crit_L1 = 'REL_OBJ'; iter_L1 = 1; 0065 dummy = param.Psit(sol); 0066 norm_l1 = sum(param.weights(:).*abs(dummy(:))); 0067 0068 else % NON TIGHT FRAME CASE OR CONSTRAINT INVOLVED 0069 0070 % Initializations 0071 u_l1 = zeros(size(param.Psit(x))); 0072 sol = x - param.Psi(u_l1); 0073 prev_l1 = 0; iter_L1 = 0; 0074 0075 % Soft-thresholding 0076 % Init 0077 if param.verbose > 1 0078 fprintf(' Proximal l1 operator:\n'); 0079 end 0080 while 1 0081 0082 % L1 norm of the estimate 0083 dummy = param.Psit(sol); 0084 0085 norm_l1 = .5*norm(x(:) - sol(:), 2)^2 + lambda * ... 0086 sum(param.weights(:).*abs(dummy(:))); 0087 rel_l1 = abs(norm_l1-prev_l1)/norm_l1; 0088 0089 % Log 0090 if param.verbose>1 0091 fprintf(' Iter %i, ||Psit x||_1 = %e, rel_l1 = %e\n', ... 0092 iter_L1, norm_l1, rel_l1); 0093 end 0094 0095 % Stopping criterion 0096 if (rel_l1 < param.rel_obj) 0097 crit_L1 = 'REL_OB'; break; 0098 elseif iter_L1 >= param.max_iter 0099 crit_L1 = 'MAX_IT'; break; 0100 end 0101 0102 % Soft-thresholding 0103 res = u_l1*param.nu + param.Psit(sol); 0104 dummy = soft(res, lambda*param.nu*param.weights); 0105 if param.pos 0106 dummy = real(dummy); dummy(dummy<0) = 0; 0107 end 0108 u_l1 = 1/param.nu * (res - dummy); 0109 sol = x - param.Psi(u_l1); 0110 0111 % Update 0112 prev_l1 = norm_l1; 0113 iter_L1 = iter_L1 + 1; 0114 0115 end 0116 end 0117 0118 % Log after the projection onto the L2-ball 0119 if param.verbose >= 1 0120 fprintf([' prox_L1: ||Psi x||_1 = %e,', ... 0121 ' %s, iter = %i\n'], norm_l1, crit_L1, iter_L1); 0122 end 0123 0124 end