0001 function sol = sopt_mltb_prox_TVoA(b, lambda, param)
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 if ~isfield(param, 'rel_obj'), param.rel_obj = 1e-4; end
0037 if ~isfield(param, 'verbose'), param.verbose = 1; end
0038 if ~isfield(param, 'max_iter'), param.max_iter = 200; end
0039 if ~isfield(param, 'At'), param.At = @(x) x; end
0040 if ~isfield(param, 'A'), param.A = @(x) x; end
0041 if ~isfield(param, 'nu'), param.nu = 1; end
0042 
0043 
0044 if ~isfield(param, 'weights_dx'), param.weights_dx = 1; end
0045 if ~isfield(param, 'weights_dy'), param.weights_dy = 1; end
0046 if ~isfield(param, 'zero_weights_flag'), param.zero_weights_flag = 1; end
0047 if ~isfield(param, 'identical_weights_flag')
0048     param.identical_weights_flag = 0; 
0049 end
0050 if ~isfield(param, 'sphere_flag'), param.sphere_flag = 0; end
0051 if ~isfield(param, 'incNP'), param.incNP = 0; end
0052 
0053 
0054 
0055 if (param.sphere_flag)
0056    G = @sopt_mltb_gradient_op_sphere;
0057    D = @sopt_mltb_div_op_sphere;
0058 else
0059    G = @sopt_mltb_gradient_op;
0060    D = @sopt_mltb_div_op;
0061 end
0062 
0063 if (~param.identical_weights_flag && param.zero_weights_flag)
0064     grad = @(x) G(x, param.weights_dx, param.weights_dy);
0065     div = @(r, s) D(r, s, param.weights_dx, param.weights_dy);
0066     max_weights = max([abs(param.weights_dx(:)); ...
0067         abs(param.weights_dy(:))])^2;
0068 else
0069     grad = @(x) G(x);
0070     div = @(r, s) D(r, s);
0071 end
0072 
0073 
0074 [r, s] = grad(param.A(b*0));
0075 pold = r; qold = s;
0076 told = 1; prev_obj = 0;
0077 
0078 
0079 if param.verbose > 1
0080     fprintf('  Proximal TV operator:\n');
0081 end
0082 for iter = 1:param.max_iter
0083     
0084     
0085     sol = b - lambda*param.At(div(r, s));
0086     
0087     
0088     obj = .5*norm(b(:)-sol(:), 2) + lambda * ...
0089         sopt_mltb_TV_norm(param.A(sol), param.weights_dx, param.weights_dy);
0090     rel_obj = abs(obj-prev_obj)/obj;
0091     prev_obj = obj;
0092     
0093     
0094     if param.verbose>1
0095         fprintf('   Iter %i, obj = %e, rel_obj = %e\n', ...
0096             iter, obj, rel_obj);
0097     end
0098     if rel_obj < param.rel_obj
0099         crit_TV = 'TOL_EPS'; break;
0100     end
0101     
0102     
0103     [dx, dy] = grad(param.A(sol));
0104     if (param.identical_weights_flag)
0105         r = r - 1/(8*lambda*param.nu) * dx;
0106         s = s - 1/(8*lambda*param.nu) * dy;
0107         weights = max(param.weights_dx, sqrt(abs(r).^2+abs(s).^2));
0108         p = r./weights.*param.weights_dx; q = s./weights.*param.weights_dx;
0109     else
0110         if (~param.zero_weights_flag)
0111             r = r - 1/(8*lambda*param.nu) * dx;
0112             s = s - 1/(8*lambda*param.nu) * dy;
0113             weights = max(1, sqrt(abs(r./param.weights_dx).^2+...
0114                 abs(s./param.weights_dy).^2));
0115             p = r./weights; q = s./weights;
0116         else
0117             
0118             r = r - 1/(8*lambda*param.nu*max_weights) * dx;
0119             s = s - 1/(8*lambda*param.nu*max_weights) * dy;
0120             weights = max(1, sqrt(abs(r).^2+abs(s).^2));
0121             p = r./weights; q = s./weights;
0122         end
0123     end
0124     
0125     
0126     t = (1+sqrt(4*told^2))/2;
0127     r = p + (told-1)/t * (p - pold); pold = p;
0128     s = q + (told-1)/t * (q - qold); qold = q;
0129     told = t;
0130     
0131 end
0132 
0133 
0134 if ~exist('crit_TV', 'var'), crit_TV = 'MAX_IT'; end
0135 if param.verbose >= 1
0136     fprintf(['  Prox_TV: obj = %e, rel_obj = %e,' ...
0137         ' %s, iter = %i\n'], obj, rel_obj, crit_TV, iter);
0138 end
0139 
0140 end