Description of sopt_mltb_proj_B2
Description: sopt_mltb_proj_B2 - Projection onto L2-ball

Home > matlab > prox_operators > sopt_mltb_proj_B2.m

# sopt_mltb_proj_B2

## PURPOSE

sopt_mltb_proj_B2 - Projection onto L2-ball

## SYNOPSIS

function [sol, u] = sopt_mltb_proj_B2(x, param)

## DESCRIPTION

     sopt_mltb_proj_B2 - 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).

     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.

## CROSS-REFERENCE INFORMATION

This function calls:

This function is called by:

## SOURCE CODE

    0001 function [sol, u] = sopt_mltb_proj_B2(x, param)
    0002 % sopt_mltb_proj_B2 - 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 % Outputs:
    0038 %
    0039 %   - sol: Final solution.
    0040 %
    0041 %   - u: Final dual vector.
    0042 %
    0043 % References:
    0044 % [1] M.J. Fadili and J-L. Starck, "Monotone operator splitting for
    0045 % optimization problems in sparse recovery" , IEEE ICIP, Cairo,
    0046 % Egypt, 2009.
    0047
    0048 % Optional input arguments
    0049 if ~isfield(param, 'y'), param.y = 0; end
    0050 if ~isfield(param, 'A'), param.A = @(x) x; end
    0051 if ~isfield(param, 'At'), param.At = @(x) x; end
    0052 if ~isfield(param, 'epsilon'), param.epsilon = 1e-3; end
    0053 if ~isfield(param, 'tight'), param.tight = 1; end
    0054 if ~isfield(param, 'tol'), param.tol = 1e-3; end
    0055 if ~isfield(param, 'verbose'), param.verbose = 1; end
    0056 if ~isfield(param, 'nu'), param.nu = 1; end
    0057 if ~isfield(param, 'max_iter'), param.max_iter = 200; end
    0058 if ~isfield(param, 'u'), param.u = zeros(size(param.y)); end
    0059
    0060 % Useful functions for the projection
    0061 sc = @(z) z*min(param.epsilon/norm(z(:)), 1); % scaling
    0062
    0063 % Projection
    0064 if param.tight % TIGHT FRAME CASE
    0065
    0066     temp = param.A(x) - param.y;
    0067     sol = x + 1/param.nu * param.At(sc(temp)-temp);
    0068     crit_B2 = 'TOL_EPS'; iter = 0; u = NaN;
    0069
    0070 else % NON TIGHT FRAME CASE
    0071
    0072     % Initializations
    0073     sol = x; u = param.u;
    0074     iter = 1; true = 1;
    0075
    0076     % Tolerance onto the L2 ball
    0077     epsilon_low = param.epsilon/(1+param.tol);
    0078     epsilon_up = param.epsilon/(1-param.tol);
    0079
    0080     % Check if we are in the L2 ball
    0081     norm_res = norm(param.y(:)-param.A(sol), 2);
    0082     if norm_res <= epsilon_up
    0083         crit_B2 = 'TOL_EPS'; true = 0;
    0084     end
    0085
    0086     % Projection onto the L2-ball
    0087     % Init
    0088     if param.verbose > 1
    0089         fprintf('  Proj. B2:\n');
    0090     end
    0091     while true
    0092
    0093         % Residual
    0094         res = param.A(sol) - param.y; norm_res = norm(res(:), 2);
    0095
    0096         % Scaling for the projection
    0097         res = u*param.nu + res; norm_proj = norm(res(:), 2);
    0098
    0099         % Log
    0100         if param.verbose>1
    0101             fprintf('   Iter %i, epsilon = %e, ||y - Ax||_2 = %e\n', ...
    0102                 iter, param.epsilon, norm_res);
    0103         end
    0104
    0105         % Stopping criterion
    0106         if (norm_res>=epsilon_low && norm_res<=epsilon_up)
    0107             crit_B2 = 'TOL_EPS'; break;
    0108         elseif iter >= param.max_iter
    0109             crit_B2 = 'MAX_IT'; break;
    0110         end
    0111
    0112         % Projection onto the L2 ball
    0113         ratio = min(1, param.epsilon/norm_proj);
    0114         u = 1/param.nu * (res - res*ratio);
    0115
    0116         % Current estimate
    0117         sol = x - param.At(u);
    0118
    0119         % Update number of iteration
    0120         iter = iter + 1;
    0121
    0122     end
    0123 end
    0124
    0125 % Log after the projection onto the L2-ball
    0126 if param.verbose >= 1
    0127     temp = param.A(sol);
    0128     fprintf(['  Proj. B2: epsilon = %e, ||y-Ax||_2 = %e,', ...
    0129         ' %s, iter = %i\n'], param.epsilon, norm(param.y(:)-temp(:)), ...
    0130         crit_B2, iter);
    0131 end
    0132
    0133 end