funcApprox class

Defines a class to represent an approximated function

Objects created by this class are a subclass of basis, adding fields to identify a function and methods to interpolate, compute Jacobian and Hessian.

Apart from the properties inherited from basis, objects of class funcApprox have the following properties:

Object of class funcApprox have the following methods:

To date, only basisChebyshev has been implemented, so calling the function with type 'spli' or 'lin' returns an error.

Last updated: October 4, 2014.

Copyright (C) 2014 Randall Romero-Aguilar

Licensed under the MIT license, see LICENSE.txt

Contents

classdef funcApprox < basis

    properties
        fnodes  % value of functions at nodes
        fnames  % names for functions
    end


    properties (SetAccess = protected)
        Phi     % interpolation matrix
        Phiinv  % inverse of interpolation matrix
        df      % number of functions
        coef    % interpolation coefficients
    end


    methods

funcApprox

        function F = funcApprox(B,fnodes,fnames)

Constructor for funcApprox

F = funcApprox(B,fnodes,fnames)

The inputs are:

            if nargin==0
                return
            end

            for s = fieldnames(B)'
                s1 = char(s);
                F.(s1) = B.(s1);
            end

            F.Phi = B.Interpolation;
            F.Phiinv = (F.Phi'*F.Phi)\F.Phi';
            F.fnodes = fnodes;
            F.df = size(fnodes,2);

            if nargin>2
                F.fnames = fnames;
            end

        end

set.fnodes

        function set.fnodes(F,value)

Setting new values for fnodes also update the interpolation coefficients

            if size(value,1) ~= size(F.nodes,1)
                error('New value for fnodes must have %d rows (1 per node)',size(F.nodes,1))
            end

            F.fnodes = value;
            F.updateCoef;
        end

updateCoef

        function updateCoef(F)

To update coefficients, the inverse interpolation matrix is premultiplied by the value of the function at the nodes

            F.coef = F.Phiinv * F.fnodes;
        end

Interpolate

        function y = Interpolate(F,...
                varargin... inputs for interpolation method
                )
y = F.Interpolate(x,order,integrate)

Interpolates function f: R^d --> R^m at values x; optionally computes derivative/integral. It obtains the interpolation matrices by calling Interpolation on its basis.

Its inputs are

Output y returns the interpolated functions as a k.m.h array, where k is the number of evaluation points, m the number of functions (number of columns in f.coef), and h is number of order derivatives.

            if nargin <2
                y = F.fnodes;
                return
            end

            Phix = F.Interpolation(varargin{:});

            nx = size(Phix,1);  % number of evaluation points
            no = size(Phix,3);  % number of order evaluations

            y = zeros(nx,F.df,no);

            for h = 1:no
                y(:,:,h) = Phix(:,:,h) * F.coef;
            end

            if F.df==1  % only one function
                y = squeeze(y);
            end

        end %Evaluate

Jacobian

        function [DY,Y] = Jacobian(F, x, index)
[DY,Y] = F.Jacobian(x, index)

Computes the Jacobian of the approximated function f: R^d --> R^m.

Inputs:

Outputs

Solve for the one-dimensional basis

            if F.d==1
                if nargout == 1
                    Phix  = F.Interpolation(x,1,false);
                    DY = Phix * F.coef;
                else
                    Phix = F.Interpolation(x,[1;0],false);
                    DY = Phix(:,:,1) * F.coef;
                    Y = Phix(:,:,2) * F.coef;
                end

                return
            end

Solve for the multi-dimensional basis

            % Check validity of input x
            if size(x,2)~=F.d, error('In Jacobian, class basis: x must have d columns'); end

Keep track of required derivatives: Required is logical with true indicating derivative is required

            if nargin<3
                Required = true(1,F.d);
                index = 1:F.d;
            elseif numel(index) < F.d % assume that index have scalars of the desired derivatives
                Required = false(1,F.d);
                Required(index) = true;
            else % assume that index is nonzero for desired derivatives
                Required = logical(index);
                index = find(index);
            end

            nRequired = sum(Required);

HANDLE NODES DIMENSION

            Nrows = size(x,1);

HANDLE POLYNOMIALS DIMENSION

            c = F.opts.validPhi;
            Ncols = size(c,1);

Compute interpolation matrices for each dimension

            Phi0 = zeros(Nrows,Ncols,F.d);
            Phi1 = zeros(Nrows,Ncols,F.d);

            for k = 1:F.d
                if Required(k)
                    PhiOneDim = F.B1(k).Interpolation(x(:,k),...
                        [0 1],...
                        false);
                    Phi01 = PhiOneDim(:,c(:,k),:);
                    Phi0(:,:,k) = Phi01(:,:,1); % function value
                    Phi1(:,:,k) = Phi01(:,:,2); % its derivative
                else
                    PhiOneDim = F.B1(k).Interpolation(x(:,k),...
                        0,...
                        false);
                    Phi0(:,:,k) = PhiOneDim(:,c(:,k));
                end
            end

Compute the Jacobian Preallocate memory

            DY  = zeros(Nrows,F.df,nRequired);

            % Multiply the 1-dimensional bases

            for k=1:nRequired
                Phik = Phi0;
                Phik(:,:,index(k)) = Phi1(:,:,index(k));
                Phix = prod(Phik,3);
                DY(:,:,k) = Phix * F.coef;
            end

Compute the function if requested

            if nargout > 1
                Y = prod(Phi0,3) * F.coef;
            end

        end % Jacobian

Hessian

        function Hy = Hessian(F,x)
Hy = F.Hessian(x,coef)

Computes the Hessian of a function approximated by basis B and coefficients coef.

Its input is

Its output Hy returns the k.m.d.d Hessian evaluated at x.

            order = repmat({[0 1 2]'},1,F.d);
            order = gridmake(order{:});
            order = order(sum(order,2)==2,:);

            Phix = F.Interpolation(x,order,false);


            nx = size(x,1);     % number of evaluated points

            %Dy = squeeze(Dy);

            Hy = zeros(nx,F.df,F.d,F.d);

            for k = 1:size(order,1)
                i = find(order(k,:));
                if numel(i)==1
                    Hy(:,:,i,i) = Phix(:,:,k) * F.coef;%  Dy(:,k);
                else
                    Hy(:,:,i(1),i(2)) = Phix(:,:,k) * F.coef; %Dy(:,k);
                    Hy(:,:,i(2),i(1)) = Hy(:,:,i(1),i(2)); %Dy(:,k);
                end
            end
        end % Hessian
    end

end