4
$\begingroup$

How would you use the MATLAB function below to create a FIR filter with a custom magnitude and phase response? It is from the Statistical Modeling and Inference MATLAB Toolbox

function [a, rw, info] = irls(X, y, wf, s, r2, a0, varargin)
% Iterative Reweighted Least Square
%
%   The iterative reweighted least square algorithm updates vector a
%   by alternating between the following two steps:
%
%       1. solve the weighted least square problem to get a
%
%           minimize sum_i w_i || x_i' * a - y_i ||^2 + (r2/2) * ||a||^2
%
%       2. update the weights as
%
%           w_i = wf(||x_i' * a - y_i|| / s)
%
%          Here, wf is a function that calculates a weight based on 
%          the residue norm.
%
%   a = irls(X, y, wf, s, r2, a0, ...);
%   [a, rw] = irls(X, y, wf, s, r2, a0, ...);
%   [a, rw, info] = irls(X, y, wf, s, r2, a0, ...);
%
%       performs iterative reweighted least square in solving the
%       coefficient vector/matrix a.
%
%       Input arguments:
%       - X:        the design matrix. In particular, x_i is given by
%                   the i-th row of X, i.e. X(i,:).
%
%       - y:        the response vector/matrix. y(i,:) corresponds to 
%                   X(i,:).
%
%       - wf:       the weighting function, which should be able to take
%                   into multiple input residues in form of a matrix, and
%                   return a matrix of the same size.
%
%       - s:        the scale parameter
%
%       - a0:       the initial guess of a.
%
%       Output arguments:
%       - a:        the resultant coefficient vector/matrix.
%
%       - rw:       the weights used in the final iteration (n x 1)
%
%       - info:     a struct that contains the procedural information.
%
%       Suppose X is a matrix of size n x d, and y is a matrix of size
%       n x q, then a (and a0) will be a matrix of size d x q.
%
%       One can specify additional options to control the procedure in
%       name/value pairs.
%
%       - MaxIter:      the maximum number of iterations {100}
%       - TolFun:       the tolerance of objective value change at
%                       convergence {1e-8}
%       - TolX:         the tolerance of change of a at convergence {1e-8}
%       - Display:      the level of information displaying
%                       {'none'|'proc'|'iter'}
%       - Monitor:      the monitor that responses to procedural updates
%

%   History
%   -------
%       - Created by Dahua Lin, on Jan 6, 2011
%

%% verify input and check options

if ~(isfloat(X) && ndims(X) == 2)
    error('irls:invalidarg', 'X should be a numeric matrix.');
end
[n, d] = size(X);

if ~(isfloat(y) && ndims(y) == 2 && size(y, 1) == n)
    error('irls:invalidarg', 'y should be a numeric matrix with n rows.');
end
q = size(y, 2);

if ~isa(wf, 'function_handle')
    error('irls:invalidarg', 'wf should be a function handle.');
end

if ~(isfloat(s) && isscalar(s) && s > 0)
    error('irls:invalidarg', 's should be a positive scalar.');
end

if ~(isfloat(r2) && isscalar(r2) && r2 >= 0)
    error('irls:invalidarg', 'r2 should be a non-negative scalar.');
end

if ~(isfloat(a0) && isequal(size(a0), [d q]))
    error('irls:invalidarg', 'a0 should be a numeric matrix of size d x q.');
end

if numel(varargin) == 1 && isstruct(varargin{1})
    options = varargin{1};
else
    options = struct('MaxIter', 100, 'TolFun', 1e-8, 'TolX', 1e-8);

    if nargin == 1 && strcmpi(f, 'options')
        a = options;
        return;
    end
    options = smi_optimset(options, varargin{:});
end

omon_level = 0;
if isfield(options, 'Monitor')
    omon = options.Monitor;
    omon_level = omon.level;
end


%% main

a = a0;
converged = false;
it = 0;

if omon_level >= optim_mon.ProcLevel
    omon.on_proc_start();
end

% initial weighting

e = X * a - y;
[rn, rn2] = e_to_rn(e);
rw = wf(rn);
v = (rw' * rn2) / 2;


while ~converged && it < options.MaxIter

    it = it + 1;
    if omon_level >= optim_mon.IterLevel
        omon.on_iter_start(it);
    end

    a_p = a;
    v_p = v;

    % re-solve a
    a = llsq(X, y, rw, r2);

    % re-evaluate rw and v
    e = (1/s) * (X * a - y);
    [rn, rn2] = e_to_rn(e);
    rw = wf(rn);
    v = (rw' * rn2) / 2;

    % determine convergence
    ch = v - v_p;
    nrm_da = norm(a - a_p);
    converged = abs(ch) < options.TolFun && nrm_da < options.TolX;  


    if omon_level >= optim_mon.IterLevel        
        itstat = struct( ...
            'FunValue', v, ...
            'FunChange', ch, ...
            'Move', NaN, ...
            'MoveNorm', nrm_da, ...
            'IsConverged', converged);                    
        omon.on_iter_end(it, itstat);
    end
end


if  nargout >= 2 || omon_level >= optim_mon.ProcLevel
    info = struct( ...
        'FunValue', v, ...
        'LastChange', ch, ...
        'LastMove', nrm_da, ...
        'IsConverged', converged, ...
        'NumIters', it);
end

if omon_level >= optim_mon.ProcLevel
    omon.on_proc_end(info);
end


function [rn, rn2] = e_to_rn(e)

if size(e, 2) == 1
    rn = abs(e);
    rn2 = e .^ 2;
else
    rn2 = dot(e, e, 2);
    rn = sqrt(rn2);
end
$\endgroup$
2

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.