function [w,fun,time,iter] = gistLogistic(X,y,lambda,theta,varargin)

% Generalized Iterative Shrinkage and Thresholding (GIST) with Logsitic Regression loss
%
% Non-convex optimization problem:
%
% min_w L(w) + \sum_i r_i(w)
%
% ================================ loss function ==========================
%
% L(w) = 1/n \sum_j log(1 + exp(-y_j*x_j'*w)) (n: number of samples)
%
% ================================ regularizer ============================
%
%  regtype = 1: Capped L1 regularizer (CapL1) (default)
%            r_i(w) = lambda*\min(|w_i|,theta), (theta > 0, lambda >= 0)
%
%  regtype = 2: Log Sum Penalty (LSP)
%            r_i(w) = lambda*\sum_i log(1 + |w_i|/theta), (theta > 0, lambda >= 0)
%
%  regtype = 3: Smoothly Clipped Absolute Deviation (SCAD)
%            r_i(w) = lambda*|w_i|, if |w_i|<=lambda
%            r_i(w) = (-w_i^2 + 2*theta*lambda*|w_i| - lambda^2)/(2(theta - 1)), if lambda<=|w_i|<=theta*lambda
%            r_i(w) = 0.5*(theta + 1)*lambda^2, if |w_i| > theta*lambda, (theta > 2, lambda >= 0)
%
%  regtype = 4: Minimax Concave Penalty (MCP)
%            r_i(w) = lambda*|w_i| - 0.5*w_i^2/theta, if |w_i|<=theta*lambda
%            r_i(w) = 0.5*theta*lambda^2, if |w_i| > theta*lambda, (theta >
%            0, lambda >= 0)
%
% ============================ Input ======================================
%
% X: data matrix with each row as a sample
%
% y: label vector (+1 or -1)
%
% lambda: regularization parameter
%
% theta: theresholding parameter
%
% ======================= varargin: optional settings  ====================
%
% 'regtype': nonconvex regularization type
%          1: CapL1 (default)
%          2: LSP
%          3: SCAD
%          4: MCP
%
% 'stopcriterion': stopping criterion
%                1: relative difference of objective functions
%                   is less than tol (default)
%                0: relative difference of iterative weights is less
%                   than tol
%
% 'startingpoint': starting point (default: zero vector)
%
% 'tolerance': stopping tolerance (default: 1e-5)
%
% 'maxiteration': number of maximum iteration (default: 1000)
%
% 'tinitialization': initialization of t (default: 1)
%
% 'tmin': tmin parameter (default: 1e-20)
%
% 'tmax': tmax parameter (default: 1e-20)
%
% 'eta': eta factor (default: 2)
%
% 'sigma': parameter in the line search (default: 1e-5)
%
% 'nonmonotone': nonmonotone steps in the line search (default: 5)
%
% 'stopnum': number of satisfying stopping criterion (default: 3)
%
% 'maxinneriter': number of maximum inner iteration (line search) (default: 20)
%
% ============================= Output ====================================
%
% w: output weight vector
%
% fun: a vector including all function values at each iteration
%
% time: a vector including all CPU times at each iteration
%
% iter: the number of iterative steps
%
% =========================================================================
%
% Copyright (C) 2012-2013 Pinghua Gong
%
% For any problem, please contact Pinghua Gong via pinghuag@gmail.com
%
% Last modified on March 14, 2013.
%
% Related papers:
%
% [1] Pinghua Gong, Changshui Zhang, Zhaosong Lu, Jianhua Huang, Jieping Ye,
%     A General Iterative Shrinkage and Thresholding Algorithm for Non-convex
%     Regularized Optimization Problems. ICML 2013.
%
% ========================================================================

if nargin < 4
    error('Too few input parameters!');
end

if theta <= 0 || lambda < 0
    error('\theta must be positive and \lambda must be nonneagtive!');
end

% Parse the optional inputs.
if (mod(length(varargin), 2) ~= 0 ),
    error(['Optional Parameters passed to the function ''' mfilename ''' must be passed in pairs!']);
end

% default parameter settings
regtype = 1;
[n,d] = size(X);
w0 = zeros(d,1);
stopcriterion = 1;
tol = 1e-5;
maxiter = 1000;
M = 5;
sigma = 1e-5;

t = 1;
tmin = 1e-20;
tmax = 1e20;

% % t, tmin and tmax are adaptively estimated
% Linfnorm = full(max(sum(abs(X),2)))/n; L1norm = full(max(sum(abs(X),1)))/n; Lmaxnorm = full(max(max(abs(X))))/n;
% t = max([Linfnorm*Linfnorm/d,L1norm*L1norm/n,Lmaxnorm]);
% tmin = min([Linfnorm*Linfnorm/d,L1norm*L1norm/n,Lmaxnorm]);
% tmax = min([Linfnorm*L1norm,n*d*Lmaxnorm,n*Linfnorm*Linfnorm,d*L1norm*L1norm])/(1-sigma);

eta = 2;
stopnum = 3;
maxinneriter = 20;

% Optional parameter settings
parameterCount = length(varargin)/2;

for parameterIndex = 1:parameterCount,
    parameterName = varargin{parameterIndex*2 - 1};
    parameterValue = varargin{parameterIndex*2};
    switch lower(parameterName)
        case 'regtype'
            regtype = parameterValue;
            if regtype == 3 && theta <= 2
                error('\theta must be greater than 2!');
            end
        case 'startingpoint'
            w0 = parameterValue;
        case 'stopcriterion'
            stopcriterion = parameterValue;
        case 'tolerance'
            tol = parameterValue;
        case 'maxiteration'
            maxiter = parameterValue;
        case 'nonmonotone'
            M = parameterValue;
        case 'tinitialization'
            t = parameterValue;
        case 'tmin'
            tmin = parameterValue;
        case 'tmax'
            tmax =  parameterValue;
        case 'sigma'
            sigma =  parameterValue;
        case 'eta'
            eta = parameterValue;
        case 'stopnum'
            stopnum = parameterValue;
        case 'maxinneriter'
            maxinneriter = parameterValue;
        otherwise
            error(['The parameter ''' parameterName ''' is not recognized by the function ''' mfilename '''!']);
    end
end

w = w0;
fun = zeros(maxiter+1,1); time = fun;
logist = zeros(n,1);

% Initial function value
Z = sparse(1:n,1:n,y,n,n)*X;
Zw = -Z*w; posind = (Zw > 0);
logist(posind) = 1 + exp(-Zw(posind));
logist(~posind) = 1 + exp(Zw(~posind));

temp = logist;
temp(posind) = 1./logist(posind);
temp(~posind) = (logist(~posind)-1)./logist(~posind);
grad =  -Z'*temp/n;

fun(1) = (sum(log(logist(~posind))) + sum(Zw(posind) + log(logist(posind))))/n + funRegC(w,d,lambda,theta,regtype);
time(1) = 0;

count = 0;
for iter = 1:maxiter
    tic;

    w_old = w;
    grad_old = grad;
    t = min(max(t,tmin),tmax);

    % line search
    for inneriter = 1:maxinneriter
        w = proximalRegC(w_old - grad_old/t, d, lambda/t, theta,regtype);
        dw = w - w_old;
        Zw = -Z*w; posind = (Zw > 0);
        logist(posind) = 1 + exp(-Zw(posind));
        logist(~posind) = 1 + exp(Zw(~posind));
        fun(iter+1) = (sum(log(logist(~posind))) + sum(Zw(posind) + log(logist(posind))))/n + funRegC(w,d,lambda,theta,regtype);
        if fun(iter+1) <= max(fun(max(iter-M+1,1): iter)) - 0.5*sigma*t*norm(dw)^2
            break;
        else
            t = t*eta;
        end
    end
    time(iter+1) = time(iter) + toc;

    % stopping condition
    if stopcriterion
        relativediff = abs(fun(iter) - fun(iter+1))/fun(iter+1);
    else
        relativediff = norm(w - w_old)/norm(w);
    end
    if relativediff < tol
        count = count + 1;
    else
        count = 0;
    end
    if count >= stopnum
        break;
    end

    temp = logist;
    temp(posind) = 1./logist(posind);
    temp(~posind) = (logist(~posind)-1)./logist(~posind);
    grad =  -Z'*temp/n;

    % BB rule
    st = w - w_old;
    rt = grad - grad_old;
    if norm(st)/d < 1e-12 || norm(rt)/d < 1e-12
        break;
    end
    t = st'*rt/(st'*st);

end
fun = fun(1: min(maxiter,iter)+1);
time = time(1: min(maxiter,iter)+1);


function shape_test ( code )

%*****************************************************************************80
%
%% SHAPE_TEST verifies the shape function values at the basis nodes.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 February 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character ( len = * ) CODE, identifies the element to be used.
%    Legal values include 'Q4', 'Q8', 'Q9', 'Q12', 'Q16', 'QL',
%    'T3', 'T4', 'T6' and 'T10'.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  SHAPE_TEST: Verify shape functions of type "%s"\n', code );

  element_order = order_code ( code );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Element order = %d\n', element_order );

  [ r, s, area ] = node_reference ( code );

  fprintf ( 1, '  Basis function values at basis nodes\n' );
  fprintf ( 1, '  should form the identity matrix.\n' );
  fprintf ( 1, '\n' );

  for i = 1 : element_order
    [ t, dtdr, dtds ] = shape ( code, r(i), s(i) );
    for j = 1 : element_order
      fprintf ( 1, '  %7f', t(j) );
    end
    fprintf ( 1, '\n' );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The R and S derivatives should sum to 0.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '        dTdR sum        dTdS sum\n' );
  fprintf ( 1, '\n' );
  for i = 1 : element_order
    [ t, dtdr, dtds ] = shape ( code, r(i), s(i) );
    rsum = sum ( dtdr(1:element_order) );
    ssum = sum ( dtds(1:element_order) );
    fprintf ( 1, '  %14f  %14f\n', rsum, ssum );
  end

  return
end


function x = tridisolve ( a, b, c, d )

%*****************************************************************************80
%
%% TRIDISOLVE solves a tridiagonal system of linear equations.
%
%  Discussion:
%
%    We can describe an NxN tridiagonal matrix by vectors A, B, and C, where
%    A and C are of length N-1.  In that case, a linear system can be
%    represented as
%                        b(1) * x(1) + c(1) * x(2)   = d(1),
%      a(j-1) * x(j-1) + b(j) * x(j) + c(j) * x(j+1) = d(j), j = 2:n-1,
%      a(n-1) * x(n-1) + b(n) * x(n)                 = d(n)
%
%    This function produces the solution vector X.
%
%    This function is derived from Cleve Moler's Matlab suite.
%
%  Modified:
%
%    19 May 2013
%
%  Author:
%
%    Cleve Moler.
%
%  Parameters:
%
%    Input, real A(N-1), B(N), C(N-1), the matrix entries.
%
%    Input, real D(N), the right hand side.
%
%    Output, real X(N), the solution.
%
  x = d;
  n = length ( x );
  bi = zeros ( n, 1 );

  for j = 1 : n - 1
    bi(j) = 1.0 / b(j);
    mu = a(j) * bi(j);
    b(j+1) = b(j+1) - mu * c(j);
    x(j+1) = x(j+1) - mu * x(j);
  end

  x(n) = x(n) / b(n);
  for j = n - 1 : -1 : 1
    x(j) = ( x(j) - c(j) * x(j+1) ) * bi(j);
  end

  return
end


function [ nf, xf, wf, vf ] = line_fekete_monomial ( m, a, b, n, x )

%*****************************************************************************80
%
%% LINE_FEKETE_MONOMIAL computes approximate Fekete points in an interval [A,B].
%
%  Discussion:
%
%    We use the uniform weight and the monomial basis:
%
%      P(j) = x^(j-1)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 April 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Alvise Sommariva, Marco Vianello,
%    Computing approximate Fekete points by QR factorizations of Vandermonde
%    matrices,
%    Computers and Mathematics with Applications,
%    Volume 57, 2009, pages 1324-1336.
%
%  Parameters:
%
%    Input, integer M, the number of basis polynomials.
%
%    Input, real A, B, the endpoints of the interval.
%
%    Input, integer N, the number of sample points.
%    M <= N.
%
%    Input, real X(N), the coordinates of the sample points.
%
%    Output, integer NF, the number of Fekete points.
%    If the computation is successful, NF = M.
%
%    Output, real XF(NF), the coordinates of the Fekete points.
%
%    Output, real WF(NF), the weights of the Fekete points.
%
%    Output, real VF(NF,M), the nonsingular Vandermonde submatrix.
%
  if ( n < m )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LINE_FEKETE_MONOMIAL - Fatal error!\n' );
    fprintf ( 1, '  N < M.\n' );
    error ( 'LINE_FEKETE_MONOMIAL - Fatal error!' );
  end
%
%  Destroy all row vectors!
%
  x = x(:);
%
%  Moments of monomials:
%
  mom = line_monomial_moments ( a, b, m );
%
%  Form the rectangular Vandermonde matrix V for the polynomial basis.
%
  v = zeros ( m, n );

  v(1,1:n) = 1.0;
  for i = 2 : m
    v(i,1:n) = v(i-1,1:n) .* x(1:n)';
  end
%
%  Solve the system for the weights W.
%
  w = v \ mom;
%
%  Locate nonzero W's.
%
  ind = find ( w ~= 0.0 );
%
%  Retain data associated with nonzero W's.
%
  nf = length ( ind );
  xf = x ( ind );
  wf = w ( ind );
  vf = v ( :, ind );

  return
end


function [H] = traditional(f);

% TRADITIONAL creates the homogenous spatial transformation matrix
% for a 9 parameter traditional "Talairach-model" transformation
%
% Use as
%   [H] = traditional(f)
%
% The transformation vector f should contain the
%   x-shift
%   y-shift
%   z-shift
% followed by the
%   pitch (rotation around x-axis)
%   roll  (rotation around y-axis)
%   yaw   (rotation around z-axis)
% followed by the
%   x-rescaling factor
%   y-rescaling factor
%   z-rescaling factor
%
% The order in which the transformations are done is exactly opposite as
% the list above, i.e. first z-rescale, ... and finally x-shift.

% Copyright (C) 2000-2005, Robert Oostenveld
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% $Log: traditional.m,v $
% Revision 1.1  2009/01/30 04:02:12  arno
% *** empty log message ***
%
% Revision 1.5  2005/08/15 08:15:33  roboos
% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference)
% changed all functions to be dependent on the rotate, translate and scale function
% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations
%
% Revision 1.4  2005/08/11 07:57:14  roboos
% fixed bug in y-rotation
%
% Revision 1.3  2005/04/21 08:28:45  roboos
% fixed bug in rotation matrix (thanks to Arno)
%
% Revision 1.2  2004/05/19 09:57:07  roberto
% added GPL copyright statement, added CVS log item
%

% compute the homogenous transformation matrix for the translation
T = translate(f([1 2 3]));

% compute the homogenous transformation matrix for the rotation
R = rotate(f([4 5 6]));

% compute the homogenous transformation matrix for the scaling
S = scale(f([7 8 9]));

% compute the homogenous transformation matrix for the combination
H = T*R*S;


function [t,a,k]=BSplineInterpDeriv(t,a,k,numDerivs)
%%BSPLINEINTERPDERIV Given a set of b-spline interpolation weights a and
%            knots t for scalar interpolation, compute the weights and
%            knots to interpolate the numDerivs derivative value using
%            b-splines interpolation.
%
%INPUTS: t The NX1 or 1XN set of knots for the interpolation function. The
%          first and last k-1 knots are outside of the ends of the region
%          with data or mark the ends of the region with data. These vslues
%          must be real.
%        a The npXnumSets collection of b-spline coefficients for
%          interpolating over a certain region for numSets sets of
%          interpolation problems. Such coefficients could be obtained from
%          the function BSplinePolyCoeffs along with t if one wishes to
%          interpolate over gridded data. These values can be complex.
%        k The order of the B-spline polynomials. The order of the
%          interpolation accuracy is k-numDerivs-1.
% numDerivs The number of derivatives to take. This must be less than k-1.
%
%OUTPUTS: a The (np-numDerivs)XnumSets modified coefficients.
%         t The (N-2*numDerivs)X1 modified knots.
%         k The modified B-spline order.
%
%This function implements Equation 12b in Chapter X of [1]. The
%modifications to t simply reflect the modification to the overall length
%of a.
%
%The first and last elements in t are not used in this function. However,
%the equations in [1] assume that those elements are present as they end up
%being used when computing integrals.
%
%EXAMPLE 1:
%Here, we approximate the derivative of a fourth-order function using
%piecewise third-order b-splines and plot the results.
% f=@(t)(t.^4-2*t.^2+t);
% tau=[-2;-1;0;0.5;1;1.5;2];
% y=f(tau);
% k=4;%k-1=3 is the order....
% [a,t]=BSplinePolyFit(tau,y,k);
%
% x=linspace(-2,2,500);
% numDerivs=1;
% [t,a,k]=BSplineInterpDeriv(t,a,k,numDerivs);
% ypDeriv=BSplineInterpVal(x,t,a,k);
% yDeriv=1-4*x+4*x.^3;%First derivative
%
% figure(1)
% clf
% hold on
% plot(x,yDeriv,'-k','linewidth',4)
% plot(x,ypDeriv,'--r','linewidth',2)
%
%EXAMPLE 2:
%This is similar to the previous example, except multiple sets of
%coefficients are computed and evaluated at once.
% f1=@(t)(t.^4-2*t.^2+t);
% f2=@(t)(t.^3-2*t.^2+t);
% tau=[-2;-1;0;0.5;1;1.5;2];
% y=[f1(tau),f2(tau)];
% k=4;%k-1=3 is the order....
% [a,t]=BSplinePolyFit(tau,y,k);
%
% x=linspace(-2,2,500).';
% numDerivs=1;
% [t,a,k]=BSplineInterpDeriv(t,a,k,numDerivs);
% ypDeriv=BSplineInterpVal(x,t,a,k);
% yDeriv=[1-4*x+4*x.^3,1-4*x+3*x.^2];%First derivative
%
% figure(1)
% clf
% hold on
% plot(x,yDeriv(:,1),'-k','linewidth',4)
% plot(x,ypDeriv(:,1),'--r','linewidth',2)
%
% figure(2)
% clf
% hold on
% plot(x,yDeriv(:,2),'-k','linewidth',4)
% plot(x,ypDeriv(:,2),'--r','linewidth',2)
%
%EXAMPLE 3:
%This is an example where a complex function parameterized by a single real
%value is differentiated and interpolated.
% numPoints=300;
% xMin=0;
% xMax=5;
% x=linspace(xMin,xMax,numPoints);
% f=@(x)exp(-1j*2*x).*(4*x.^3+x.*exp(1j*2*x.^2)+12*x+x.^3.*exp(-1j*2*x.^2));
%
% fDx=@(x)exp(-2*1j*x.*(1+x)).*(exp(4*1j*x.^2).*(1+2*1j*x.*(-1+2*x))+x.^2.*(3-2*1j*x.*(1+2*x))+4*exp(2*1j*x.^2).*(3+x.*(-6*1j+(3-2*1j*x).*x)));
%
% fx=f(x);
% k=5;
% [a,t]=BSplinePolyFit(x,fx(:),k);
% numDerivs=1;
% [t,a,k]=BSplineInterpDeriv(t,a,k,numDerivs);
%
% %Interpolate on a finer grid.
% numPoints=2000;
% x=linspace(xMin,xMax,numPoints);
% fx=fDx(x);
% fxInterp=BSplineInterpVal(x,t,a,k);
%
% %Plot the function values and the interpolated values for the real and
% %complex parts.
% figure(1)
% clf
% hold on
% plot(x,real(fx),'-k','linewidth',2)
% plot(x,imag(fx),'--k','linewidth',2)
% plot(x,real(fxInterp),'-r')
% plot(x,imag(fxInterp),'--r')
%
% %Plot the interpolation error.
% figure(2)
% clf
% hold on
% plot(x,real(fxInterp(:))-real(fx(:)))
% plot(x,imag(fxInterp(:))-imag(fx(:)))
%
%REFERENCES:
%[1] C. de Boor, A Practical Guide to Splines. New York: Springer-Verlag,
%    1978.
%
%April 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numA=size(a,1);

for curDeriv=1:numDerivs
    aNext=a;
    for idxA=(curDeriv+1):numA
        denom=(t(idxA+k-curDeriv)-t(idxA))/(k-curDeriv);

        if(denom==0)
            aNext(idxA,:)=0;
        else
            aNext(idxA,:)=(a(idxA,:)-a(idxA-1,:))/denom;
        end
    end

    a=aNext;
end
a=a((1+numDerivs):end,:);
t=t((1+numDerivs):(end-numDerivs));
k=k-numDerivs;
end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function [suspicious_index lof] = LOF(A, k)
%#####################################################################
%# Local Outlier Factor                                              #
%# Authors: Markus M. Breunig, Hans-Peter Kriegel,                   #
%#          Raymond T. Ng, J?rg Sander                               #
%# Oringinal paper :                                                 #
%# LOF: Identifying Density-Based Local Outliers                     #
%# e-mail : { breunig | kriegel | sander }                           #
%#          @dbs.informatik.uni-muenchen.de                          #
%#          rng@cs.ubc.ca                                            #
%# Programmer: Yi-Ren Yeh(yirenyeh@gmail.com)                        #
%# modified by: Zi-Wen Gui(evan176@hotmail.com)                      #
%#                                                                   #
%#                                                                   #
%# Inputs                                                            #
%#   A: the data matrix, each row reprent an instance                #
%#   k: the number of nearest neighbors                              #
%#                                                                   #
%# Outputs                                                           #
%#   lof: the local outlier factor for each instance                 #
%#   suspicious_index: the ranking of instances according to their   #
%#                     suspiciuous score                             #
%#                     For example, suspicious_index(i)=j means the  #
%#                     ith instance is in jth position in the ranking#
%#####################################################################

%Find the nearest neighbors by "KDTree" for each elements
[k_index, k_dist] = knnsearch(A,A,'k',k+1,'nsmethod','kdtree');
%Ignore first element(itself) at nearest neighbors
k_index = k_index(:,2:end);
%Get k-distance
k_dist1 = k_dist(:,end);
%Get row length of matrix A
n = length(A(:,1));
%Initializa lrd_value vector
lrd_value = zeros(n,1);
%Calculate lrd for each elements
for i = 1:n
    lrd_value(i) = lrd(A, i, k_dist1,k_index, k);
end
%Initializa lof vector
lof = zeros(n,1);
%Calculate LOF
for i = 1:n
    lof(i) = sum(lrd_value(k_index(i,:))/lrd_value(i))/k;
end
%Sort lof factor
[non,suspicious_index]=sort(lof,'descend');

%=========================================================================
function lrd_value = lrd(A, index_p, k_dist,k_index, k)
%Calculate the reachability distance for nearest neighbors
Temp = repmat(A(index_p,:),k,1) - A(k_index(index_p,:),:);
Temp = sqrt(sum(Temp.^2,2));
%max{k-distance(b), d(a, b)}
rd_dsit = max([Temp k_dist(k_index(index_p,:))],[],2);
%Calculate the local reachability density for each elements
lrd_value = k/sum(rd_dsit);


function [ point_coord, face_order, face_point ] = ...
  tetrahedron_rhombic_shape_3d ( point_num, face_num, face_order_max )

%*****************************************************************************80
%
%% TETRAHEDRON_RHOMBIC_SHAPE_3D describes a rhombic tetrahedron in 3D.
%
%  Discussion:
%
%    Call TETRAHEDRON_RHOMBIC_SIZE_3D first, to get dimension information.
%
%    The tetrahedron is described using 10 nodes.  If we label the vertices
%    P0, P1, P2 and P3, then the extra nodes lie halfway between vertices,
%    and have the labels P01, P02, P03, P12, P13 and P23.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 January 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Anwei Liu, Barry Joe,
%    Quality Local Refinement of Tetrahedral Meshes Based
%    on 8-Subtetrahedron Subdivision,
%    Mathematics of Computation,
%    Volume 65, Number 215, July 1996, pages 1183-1200.
%
%  Parameters:
%
%    Input, integer POINT_NUM, the number of points in the shape.
%
%    Input, integer FACE_NUM, the number of faces in the shape.
%
%    Input, integer FACE_ORDER_MAX, the maximum number of vertices per face.
%
%    Output, real POINT_COORD(3,POINT_NUM), the vertices.
%
%    Output, integer FACE_ORDER(FACE_NUM), the number of vertices
%    for each face.
%
%    Output, integer FACE_POINT(FACE_ORDER_MAX,FACE_NUM); FACE_POINT(I,J)
%    contains the index of the I-th point in the J-th face.  The
%    points are listed in the counter clockwise direction defined
%    by the outward normal at the face.
%
  dim_num = 3;

  a =        1.0   / sqrt ( 3.0 );
  b = sqrt ( 2.0 ) / sqrt ( 3.0 );
  c = sqrt ( 3.0 ) /        6.0;
  d =        1.0   / sqrt ( 6.0 );
  z = 0.0;
%
%  Set the point coordinates.
%
  point_coord(1:dim_num,1)  = [ -b,  z,  z ]';
  point_coord(1:dim_num,2)  = [  z, -a,  z ]';
  point_coord(1:dim_num,3)  = [  z,  a,  z ]';
  point_coord(1:dim_num,4)  = [  z,  z,  b ]';
  point_coord(1:dim_num,5)  = [ -d, -c,  z ]';
  point_coord(1:dim_num,6)  = [ -d,  c,  z ]';
  point_coord(1:dim_num,7)  = [ -d,  z,  d ]';
  point_coord(1:dim_num,8)  = [  z,  z,  z ]';
  point_coord(1:dim_num,9)  = [  z, -c,  d ]';
  point_coord(1:dim_num,10) = [  z,  c,  d ]';
%
%  Set the face orders.
%
  face_order(1:face_num) = [ 6, 6, 6, 6 ];
%
%  Set faces.
%
  face_point(1:face_order_max,1:face_num) = [ ...
     1,  5,  2,  9,  4,  7; ...
     2,  8,  3, 10,  4,  9; ...
     3,  6,  1,  7,  4, 10; ...
     1,  6,  3,  8,  2,  5 ]';

  return
end


% LLE ALGORITHM (using K nearest neighbors)
%
% [Y] = lle(X,K,dmax)
%
% X = data as D x N matrix (D = dimensionality, N = #points)
% K = number of neighbors
% dmax = max embedding dimensionality
% Y = embedding as dmax x N matrix

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [Y] = lle(X,K,d)

[D,N] = size(X);
fprintf(1,'LLE running on %d points in %d dimensions\n',N,D);

% STEP1: COMPUTE PAIRWISE DISTANCES & FIND NEIGHBORS
fprintf(1,'-->Finding %d nearest neighbours.\n',K);

X2 = sum(X.^2,1);
distance = repmat(X2,N,1)+repmat(X2',1,N)-2*X'*X;

[sorted,index] = sort(distance);
neighborhood = index(2:(1+K),:);

% STEP2: SOLVE FOR RECONSTRUCTION WEIGHTS
fprintf(1,'-->Solving for reconstruction weights.\n');

if(K>D)
  fprintf(1,'   [note: K>D; regularization will be used]\n');
  tol=1e-3; % regularlizer in case constrained fits are ill conditioned
else
  tol=0;
end

W = zeros(K,N);
for ii=1:N
   z = X(:,neighborhood(:,ii))-repmat(X(:,ii),1,K); % shift ith pt to origin
   C = z'*z;                                        % local covariance
   C = C + eye(K,K)*tol*trace(C);                   % regularlization (K>D)
   W(:,ii) = C\ones(K,1);                           % solve Cw=1
   W(:,ii) = W(:,ii)/sum(W(:,ii));                  % enforce sum(w)=1
end;

% STEP 3: COMPUTE EMBEDDING FROM EIGENVECTS OF COST MATRIX M=(I-W)'(I-W)
fprintf(1,'-->Computing embedding.\n');

% M=eye(N,N); % use a sparse matrix with storage for 4KN nonzero elements
M = sparse(1:N,1:N,ones(1,N),N,N,4*K*N);
for ii=1:N
   w = W(:,ii);
   jj = neighborhood(:,ii);
   M(ii,jj) = M(ii,jj) - w';
   M(jj,ii) = M(jj,ii) - w;
   M(jj,jj) = M(jj,jj) + w*w';
end;

% CALCULATION OF EMBEDDING
options.disp = 0; options.isreal = 1; options.issym = 1;
[Y,eigenvals] = eigs(M,d+1,0,options);
Y = Y(:,2:d+1)'*sqrt(N); % bottom evect is [1,1,1,1...] with eval 0

fprintf(1,'Done.\n');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% other possible regularizers for K>D
%   C = C + tol*diag(diag(C));                       % regularlization
%   C = C + eye(K,K)*tol*trace(C)*K;                 % regularlization


function Y = spe(X, no_dims, varargin)
%SPE Perform the Stochastic Proximity Embedding algorithm
%
%   Y = spe(X, no_dims, 'Global')
%   Y = spe(X, no_dims, 'Local', k)
%
% Perform the Stochastic Proximity Embedding algorithm. The SPE algorithm
% can be compared to the MDS algorithm, although it is much more efficient.
% The total number of updates necessary after the random initialization is
% usually less than n^2 (where n is the number of datapoints). X is the set
% of datapoints on which SPE has to be applied, and no_dims the number of
% dimensions in the embedding space. If the method is used with the 'Global'
% switch, a minimization of the traditional MDS raw stress function is
% performed (the default). Execution with the 'Local' switch only retains
% Euclidean distances in the local neighborhood of the datapoints. The size
% of the neighborhood is defined by the variable k (default = 12).
%
%

% This file is part of the Matlab Toolbox for Dimensionality Reduction.
% The toolbox can be obtained from http://homepage.tudelft.nl/19j49
% You are free to use, change, or redistribute this code in any way you
% want for non-commercial purposes. However, it is appreciated if you
% maintain the name of the original author.
%
% (C) Laurens van der Maaten, Delft University of Technology

    if nargin <= 2
        variant = 'Global';
    else
        variant = varargin{1};
    end
    if strcmp(variant, 'Local')
        if nargin > 3, k = varargin{2};
        else k = 12; end
    end
    if ~strcmp(variant, 'Global') && ~strcmp(variant, 'Local')
        error('Unknown parameter.');
    end
    if exist('k', 'var') && ischar(k)
        error('Adaptive neighborhood selection is not yet supported in SPE.');
    end

    % Initialize parameters
    lambda = 1;                                         % initial learning parameter
    s = 100;                                            % number of updates per iteration
    max_iter = 20000 + round(.04 * size(X, 1) ^ 2);     % number of iterations
    tol = 1e-5;                                         % regularlization parameter
    n = size(X, 1);                                     % number of datapoints
    if strcmp(variant, 'Local')
        max_iter = max_iter * 3;
    end

    % Compute proximity matrix in original space
    if strcmp(variant, 'Global')
        R = L2_distance(X', X');
        R = R / max(max(R)) * sqrt(2);
    else
        [R, n_ind] = find_nn(X, k);
    end

    % Initialize datapoints randomly
    Y = rand(n, no_dims);

    % Perform SPE
    for i=1:max_iter
        if rem(i, 10000) == 0
            disp(['Iteration ' num2str(i) ' of ' num2str(max_iter) '...']);
        end

        % Select points that should be updated
        J = randperm(n);
        ind1 = J(1:s);
        if strcmp(variant, 'Global')
            ind2 = J(s+1:2*s);
        else
            ind2 = double(n_ind(ind1,:))';
            J = round(rand(1, size(ind2, 2)) * (k - 1)) + 1;
            J = J + ((0:length(J) - 1) * k);
            ind2 = ind2(J);
        end

        % Compute distances between points in embedded space
        D = sqrt(sum((Y(ind1,:) - Y(ind2,:)) .^ 2, 2));

        % Get corresponding distances in real space
        Rt = R((ind1 - 1) * size(R, 1) + ind2)';

        % Update locations of points
        Y(ind1,:) = Y(ind1,:) + lambda * (1/2) * repmat(((Rt - D) ./ (D + tol)), 1, no_dims) .* (Y(ind1,:) - Y(ind2,:));
        Y(ind2,:) = Y(ind2,:) + lambda * (1/2) * repmat(((Rt - D) ./ (D + tol)), 1, no_dims) .* (Y(ind2,:) - Y(ind1,:));

        % Update learning parameter
        lambda = lambda - (lambda / max_iter);
    end


function llh=local2llh(xy,origin)
%local2llh     llh=local2llh(xy,origin)
%
%Converts from local coorindates to longitude and latitude
%given the [lon, lat] of an origin. 'origin' should be in
%decimal degrees. Note that heights are ignored and that
%xy is in km.  Output is [lon, lat, height] in decimal
%degrees. This is an iterative solution for the inverse of
%a polyconic projection.

%-------------------------------------------------------------
%   Record of revisions:
%
%   Date          Programmer            Description of Change
%   ====          ==========            =====================
%
%   Aug 23, 2001  Jessica Murray        Clarification to help.
%
%   Apr 4, 2001   Peter Cervelli        Added failsafe to avoid
%                                       infinite loop because of
%                                       covergence failure.
%   Sep 7, 2000   Peter Cervelli		Original Code
%
%-------------------------------------------------------------

%Set ellipsoid constants (WGS84)

   a=6378137.0;
   e=0.08209443794970;

%Convert to radians / meters

%   xy=xy*1000;
%   origin=origin*pi/180;
   xy=double(xy)*1000;
   origin=double(origin)*pi/180;

%Iterate to perform inverse projection

   M0=a*((1-e^2/4-3*e^4/64-5*e^6/256)*origin(2) - ...
        (3*e^2/8+3*e^4/32+45*e^6/1024)*sin(2*origin(2)) + ...
        (15*e^4/256 +45*e^6/1024)*sin(4*origin(2)) - ...
        (35*e^6/3072)*sin(6*origin(2)));

   z=xy(2,:)~=-M0;

   A=(M0+xy(2,z))/a;
   B=xy(1,z).^2./a^2+A.^2;

   llh(2,z)=A;

   delta=Inf;

   c=0;

   while max(abs(delta))>1e-8

      C=sqrt((1-e^2*sin(llh(2,z)).^2)).*tan(llh(2,z));

      M=a*((1-e^2/4-3*e^4/64-5*e^6/256)*llh(2,z) - ...
           (3*e^2/8+3*e^4/32+45*e^6/1024)*sin(2*llh(2,z)) + ...
           (15*e^4/256 +45*e^6/1024)*sin(4*llh(2,z)) - ...
           (35*e^6/3072)*sin(6*llh(2,z)));

      Mn=1-e^2/4-3*e^4/64-5*e^6/256 - ...
         -2*(3*e^2/8+3*e^4/32+45*e^6/1024)*cos(2*llh(2,z)) + ...
         4*(15*e^4/256 +45*e^6/1024)*cos(4*llh(2,z)) + ...
         -6*(35*e^6/3072)*cos(6*llh(2,z));

      Ma=M/a;

      delta=-(A.*(C.*Ma+1)-Ma-0.5*(Ma.^2+B).*C)./ ...
           (e^2*sin(2*llh(2,z)).*(Ma.^2+B-2*A.*Ma)./(4*C)+(A-Ma).*(C.*Mn-2./sin(2*llh(2,z)))-Mn);

      llh(2,z)=llh(2,z)+delta;

      c=c+1;
      if c>100
          error('Convergence failure.')
      end
   end

   llh(1,z)=(asin(xy(1,z).*C/a))./sin(llh(2,z))+origin(1);

%Handle special case of latitude = 0

   llh(1,~z)=xy(1,~z)/a+origin(1);
   llh(2,~z)=0;

%Convert back to decimal degrees

   llh=llh*180/pi;


function [param]=zn2pd(input)
% [param]=zn2pd(input)
% Ziegler-Nichols PD controller for processes of 2nd order.
% Controller uses reference variable (w) just in proportional component.
% This function computes parameters of the controller (r0, q0, q1, q2, p1, p2).
% Output of the controller is calculated follows:
%
%                  r0                            q0 + q1*z^-1 + q2*z^-2
% U(z^-1) = ----------------------- * W(z^-1) - ------------------------ * Y(z^-1)
%            1 + p1*z^-1 + p2*z^-2                1 + p1*z^-1 + p2*z^-2
%
% where p1=0, p2=0, q2=0
%
% Transfer function of the controlled system is:
%
%               b1*z^-1 + b2*z^-2
% Gs(z^-1) = -----------------------
%             1 + a1*z^-1 + a2*z^-2
%
% Input: input ... input parameters
%                  input(1) ... a1
%                  input(2) ... b1
%                  input(3) ... a2
%                  input(4) ... b2
%                  input(5) ... sample time T0
% Output: param ... controller parameters
%                   param(1) ... r0
%                   param(2) ... q0
%                   param(3) ... q1
%                   param(4) ... q2 (0)
%                   param(5) ... p1 (0)
%                   param(6) ... p2 (0)

a1 = input(1);
b1 = input(2);
a2 = input(3);
b2 = input(4);
T0 = input(5);

% compute ultimate gain and frequency
[Kpu, Tu] =  ultim([b1 b2],[a1 a2],T0);

Kp = 0.4*Kpu;
Td = Tu/20;

r0 = Kp;
q0 = Kp*(1+Td/T0);
q1 = -Kp*(Td/T0);
q2 = 0;
p1 = 0;
p2 = 0;

param=[r0; q0; q1; q2; p1; p2];


function p = normpdfln(x, m, S, V)
% NORMPDFLN    log of multivariate normal density.
%   See NORMPDF for argument description.

log2pi = 1.83787706640935;
[d, n] = size(x);
if nargin == 1
  dx = x;
elseif isempty(m)
  dx = x;
else
  % m specified
  sz = size(m);
  if sz(1) ~= d
    error('rows(m) ~= rows(x)')
  end
  nm = sz(2);
  if nm == 1
    dx = x - repmat(m,1,n);
  elseif n == 1
    dx = repmat(x,1,nm) - m;
  elseif nm == n
    dx = x - m;
  else
    error('incompatible number of columns in x and m')
  end
end
if nargin < 3
  % unit variance
  p = -0.5*(d*log2pi + col_sum(dx.*dx));
  return
end
have_inv = 0;
if nargin == 3
  % standard deviation given
  if d == 1
    dx = dx./S;
    p = (-log(S) -0.5*log2pi) - 0.5*(dx.*dx);
    return;
  end
  if S(2,1) ~= 0
    error('S is not upper triangular')
  end
  if any(size(S) ~= [d d])
    error('S is not the right size')
  end
else
  if ischar(V)
    if strcmp(V,'inv')
      % inverse stddev given
      iS = S;
      have_inv = 1;
    else
      error('unknown directive')
    end
  elseif ischar(S)
    if strcmp(S,'inv')
      % inverse variance given
      if d == 1
	iS = sqrt(V);
      else
	iS = chol(V);
      end
      have_inv = 1;
    else
      error('unknown directive')
    end
  else
    % variance given
    if d == 1
      S = sqrt(V);
    else
      S = chol(V);
    end
  end
end
if have_inv
  if d == 1
    dx = iS .* dx;
    logdetiS = log(iS);
  else
    dx = iS*dx;
    logdetiS = sum(log(diag(iS)));
  end
else
  if d == 1
    dx = dx./S;
    logdetiS = -log(S);
  else
    dx = solve_tril(S',dx);
    %dx = S'\dx;
    logdetiS = -sum(log(diag(S)));
  end
end
p = (logdetiS -0.5*d*log2pi) -0.5*col_sum(dx.*dx);


function y = VBA_spm_detrend(x,p)
% Polynomial detrending over columns
% FORMAT y = spm_detrend(x,p)
% x   - data matrix
% p   - order of polynomial [default: 0]
%
% y   - detrended data matrix
%__________________________________________________________________________
%
% spm_detrend removes linear and nonlinear trends from column-wise data
% matrices.
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_detrend.m 5219 2013-01-29 17:07:07Z spm $

% defaults
%--------------------------------------------------------------------------
[m,n] = size(x);
if ~m || ~n
    y = [];
    return
end
if nargin == 1
    p = 0;
end

% centre columns
%--------------------------------------------------------------------------
if ~p
    y = x - ones(m,1)*mean(x);
    return
end

% polynomial adjustment
%--------------------------------------------------------------------------
G     = zeros(m,p+1);
for i = 0:p
    d = (1:m).^i;
    G(:,i+1) = d(:);
end
y     = x - G*(pinv(full(G))*x);


%% rastrigrin function
[x,y]=meshgrid(-5:0.1:5,-5:0.1:5);
     z=x.^2+y.^2-10*cos(2*pi*x)-10*cos(2*pi*y)+20;
     mesh(x,y,z)


function res = polynomialTransform2d(pts, coeffs)
%POLYNOMIALTRANSFORM2D Apply a polynomial transform to a set of points.
%
%   RES = polynomialTransform2d(PTS, COEFFS)
%   Transforms the input points PTS given as a N-by-2 array of coordinates
%   using the polynomial transform defined by PARAMS.
%   PARAMS given as [a0 b0 a1 b1 ... an bn]
%
%   Example
%   coeffs = [0 0  1 0  0 1   0.1 0  0 0  0 0.1];
%       %     cte   x    y     x^2   x*y   y^2
%   pts = rand(200, 2) * 2 - 1;
%   pts2 = polynomialTransform2d(pts, coeffs);
%   figure; hold on;
%   drawPoint(pts);
%   drawPoint(pts2, 'g');
%
%   See also
%     transformPoint, fitPolynomialTransform2d

% ------
% Author: David Legland
% E-mail: david.legland@grignon.inra.fr
% Created: 2013-09-04, using Matlab 7.9.0.529 (R2009b)
% Copyright 2013-2022 INRA - Cepia Software Platform

x = pts(:,1);
y = pts(:,2);
nPoints = length(x);

xCoeffs = coeffs(1:2:end);
yCoeffs = coeffs(2:2:end);
nCoeffs = length(xCoeffs);

% allocate memory for result
x2 = zeros(nPoints, 1);
y2 = zeros(nPoints, 1);

% degree from coefficient number
degree = sqrt(9/4 - 4*(1 - nCoeffs)/2) - 1.5;

% iterate over degrees
iCoeff = 0;
for iDegree = 0:degree

    % iterate over binomial coefficients of a given degree
    for k = 0:iDegree
        iCoeff = iCoeff + 1;
        tmp = power(x, iDegree-k) .* power(y, k);
        x2 = x2 + xCoeffs(iCoeff) .* tmp;
        y2 = y2 + yCoeffs(iCoeff) .* tmp;
    end
end

res = [x2 y2];


function value = wedge01_integral ( e )

%*****************************************************************************80
%
%% WEDGE01_INTEGRAL returns the integral of a monomial in the unit wedge in 3D.
%
%  Discussion:
%
%    This routine returns the integral of
%
%      product ( 1 <= I <= 3 ) X(I)^E(I)
%
%    over the unit wedge.
%
%    The integration region is:
%
%      0 <= X
%      0 <= Y
%      X + Y <= 1
%      -1 <= Z <= 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 August 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Arthur Stroud,
%    Approximate Calculation of Multiple Integrals,
%    Prentice Hall, 1971,
%    ISBN: 0130438936,
%    LC: QA311.S85.
%
%  Parameters:
%
%    Input, integer E(3), the exponents.
%
%    Output, real VALUE, the integral of the monomial.
%
  value = 1.0;

  k = e(1);

  for i = 1 : e(2)
    k = k + 1;
    value = value * i / k;
  end

  k = k + 1;
  value = value / k;

  k = k + 1;
  value = value / k;
%
%  Now account for integration in Z.
%
  if ( e(3) == - 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'WEDGE01_INTEGRAL - Fatal error!\n' );
    fprintf ( 1, '  E(3) = -1 is not a legal input.\n' );
    error ( 'WEDGE01_INTEGRAL - Fatal error!' );
  elseif ( mod ( e(3), 2 ) == 1 )
    value = 0.0;
  else
    value = value * 2.0 / ( e(3) + 1 );
  end

  return
end


function jac = compute_jacobian(v,u,w)
%
% To compute Jacobian determinant for the image deformation field
% Usage: jac = compute_jacobian(vy,vx,vz);
%
[a11,a12,a13] = gradient_3d_by_mask(u); clear u;
[a21,a22,a23] = gradient_3d_by_mask(v); clear v;
[a31,a32,a33] = gradient_3d_by_mask(w); clear w;
a11 = a11+1;
a22 = a22+1;
a33 = a33+1;

jac = a11.*a22.*a33-a11.*a23.*a32-a21.*a12.*a33+a21.*a13.*a32+a31.*a12.*a23-a31.*a13.*a22;


function [lp,dlp] = priorInvGauss(mu,lam,x)

% Univariate Inverse Gaussian hyperparameter prior distribution.
% Compute log-likelihood and its derivative or draw a random sample.
% The prior distribution is parameterized as:
%
%   p(x) = exp(-lam*(x-mu)^2/(2*mu^2*x)) / sqrt(2*pi*x^3/lam)
%
% where mu(1x1) is the mean parameter, lam(1x1) is the scale parameter
% and x(1xN) contains query hyperparameters for prior evaluation.
%
% For more help on design of priors, try "help priorDistributions".
%
% Copyright (c) by Roman Garnett and Hannes Nickisch, 2014-09-08.
%
% See also PRIORDISTRIBUTIONS.M.

if nargin<2, error('mu and lam parameters need to be provided'), end
if ~(isscalar(mu)&&isscalar(lam))
  error('mu and lam parameters need to be scalars'),end
if nargin<3                                                    % return a sample
  n = randn; y = n*n;
  r = mu + mu*(mu*y-sqrt(4*mu*lam*y+mu^2*y^2))/(2*lam);
  z = rand;
  if z<=mu/(mu+r)
    lp = r;
  else
    lp = mu^2/r;
  end
  return
end

lp  = -lam*(x-mu).^2./(2*mu^2*x) - log(2*pi*x.^3/lam)/2;
q = (x-mu)./x;
dlp = -lam*q.*(2-q)/(2*mu^2) - 3./(2*x);
lp(x<0) = -inf; dlp(x<0) = 0;


function val = gamma_multivariate_ln(x,p);
% function val = gamma_multivariate_ln(x,p);
%
% x: array(1,K)
% p: scalor
%
% x must be more than (p-1)/2
% x should be more than p/2
%
% Gamma_p(x) = pi^(p(p-1)/4) prod_(j=1)^p Gamma(x+(1-j)/2)
% log Gamma_p(x) = p(p-1)/4 log pi + sum_(j=1)^p log Gamma(x+(1-j)/2)

K = length(x);
gammaln_val = gammaln(repmat(x,p,1)+0.5*(1-repmat([1:p]',1,K))); % p by K
val = p*(p-1)*0.25 * log(pi) + sum(gammaln_val,1);

% Local Variables: ***
% mode: matlab ***
% End: ***


% l1_tv_restore1
% illustrate image restoration using a l1-type data fit term
% (for noise robustness) and a (anisotropic) TV-type regularizer
% based on l1_regress_example.m
% Copyright 2010-05-25, Jeff Fessler, University of Michigan

if ~isvar('xtrue')
	f.dir = [path_find_dir('mri') '/../data/mri/'];
	f.xtrue = [f.dir 'brainweb_t1.jpg'];
	xtrue = single(imread(f.xtrue)');
	xtrue = xtrue(2:end-1,2:end-1);
	im(xtrue), cbar
end

	snr = @(a,b) 20 * log10(norm(a(:))/norm(b(:)));

if ~isvar('A')
%	psf = fspecial('Gaussian', [7 7], 5)
	psf = gaussian_kernel(5 * sqrt(log(256)), 3);
	psf = psf * psf'; psf = psf / sum(psf(:));
	mask = true(size(xtrue));
	A = Gblur(mask, 'psf', psf);

	yb = A * xtrue;
	im(yb), cbar
	f.snr_db = 25;
	sig = 10^(-f.snr_db/20) * norm(yb(:)) / sqrt(numel(yb));

	rng(0)
	yi = yb + sig * randn(size(yb));
	printm('data snr = %g dB', snr(yb, yi-yb))

	im(yi), cbar
end

if ~isvar('xh')
	xh = l1_tv_restore1_fun(yi, A, 'l2b', -2);
	xh = embed(xh, mask);
	im(xh), cbar
end

	printm('raw snr = %g dB', snr(xtrue, yi - xtrue))
	printm('new snr = %g dB', snr(xtrue, xh - xtrue))

if 0
	beta = 1e-3;
	gamma = 1e-6;
	mu = 1/25; % for 25% random-valued noise
%	sqrt((y - A f)^2 + gamma) + mu * sqrt((Cx f)^2 + (Cy *f)^2 + beta)
end


function D = sqdistance(A, B, M)
% Square Euclidean or Mahalanobis distances between all sample pairs
% A: d x n1 data matrix
% B: d x n2 data matrix
% M: d x d  Mahalanobis matrix
% D: n1 x n2 pairwise square distance matrix
% Written by Michael Chen (sth4nth@gmail.com). July 2009.

if nargin == 1
    A = bsxfun(@minus,A,mean(A,2));
    S = full(sum(A.^2,1));
    D = full((-2)*(A'*A));
    D = bsxfun(@plus,D,S);
    D = bsxfun(@plus,D,S');
elseif nargin == 2
    assert(size(A,1)==size(B,1));

    m = (sum(A,2)+sum(B,2))/(size(A,2)+size(B,2));
    A = bsxfun(@minus,A,m);
    B = bsxfun(@minus,B,m);
    D = full((-2)*(A'*B));
    D = bsxfun(@plus,D,full(sum(B.^2,1)));
    D = bsxfun(@plus,D,full(sum(A.^2,1)'));
elseif nargin == 3
    assert(size(A,1)==size(B,1));

    m = (sum(A,2)+sum(B,2))/(size(A,2)+size(B,2));
    A = bsxfun(@minus,A,m);
    B = bsxfun(@minus,B,m);
    D = full((-2)*(A'*M*B));
    D = bsxfun(@plus,D,full(sum(B.*(M*B),1)));
    D = bsxfun(@plus,D,full(sum(A.*(M*A),1)'));
end


function out=cosh(x)

out=(exp(x)+exp(-x))/2;


%DISNORM Trainable mapping for dissimilarity matrix normalization
%
% 	V = DISNORM(D,OPT)
% 	V = D*DISNORM([],OPT)
% 	V = D*DISNORM(OPT)
%   F = E*V
%
% INPUT
%   D 	 NxN dissimilarity matrix or dataset, which defines the norm
%   E    Matrix to be normalized, e.g. D itself
% 	OPT  'max' : maximum dissimilarity is set to 1 by global rescaling
% 		   'mean': average dissimilarity is set to 1 by global rescaling (default)
%
% OUTPUT
%   V 	Trained mapping
%   F  	Normalized dissimilarity data
%
% DEFAULT
%   OPT = 'mean'
%
% DESCRIPTION
% Operation on dissimilarity matrices, like the computation of classifiers
% in dissimilarity space, may depend on the scaling of the dissimilarities
% (a single scalar for the entire matrix). This routine computes a scaling
% for a giving matrix, e.g. a training set and applies it to other
% matrices, e.g. the same training set or based on a test set.
%
% Note that DNORM = (DISNORM*MAPEX); F = D*DNORM is equivalent to
% F = D*DISNORM(D). So the user defined DNORM can be treated as a fixed
% mapping for normalizing dissimilarity matrices by themselves.
%
% SEE ALSO (PRTools Guide)
% DATASETS, MAPPINGS, MAPEX

% Copyright: R.P.W. Duin, r.p.w.duin@37steps.com

function out = disnorm(varargin)

	argin = shiftargin(varargin,'char');
  argin = setdefaults(argin,[],'mean');
  if mapping_task(argin,'definition')
    % call like U=disnorm or U=disnorm('mean') or U=disnorm([],'mean')
    out = define_mapping(argin,'untrained');
    out = setname(out,'Disnorm');
  elseif mapping_task(argin,'training')
    % call like W=disnorm(D,'mean') or W=D*U
    [D,opt] = deal(argin{:});
    if ~isdataset(D)
      D = prdataset(D,1);
      D = setfeatlab(D,getlabels(D));
    end
    if strcmpi(opt,'mean')
      n = size(D,1);
      m = sum(sum(+D))/(n*(n-1));
    elseif strcmpi(opt,'max')
      m = max(D(:));
    else
      error('Wrong OPT')
    end
    out = prmapping(mfilename,'trained',{m},[],size(D,2),size(D,2));
  elseif mapping_task(argin,'trained execution')
    % call like E=D*W
    [D,W] = deal(argin{:});
    m = getdata(W,1);
    out = D./m;
  else
    error('Illegal input')
  end


function [varargout] = wavefilter(wname, type)
%WAVEFILTER Create wavelet decomposition and reconstruction filters.
%   [VARARGOUT] = WAVEFILTER(WNAME, TYPE) returns the decomposition
%   and/or reconstruction filters used in the computation of the
%   forward and inverse FWT (fast wavelet transform).
%
%   EXAMPLES:
%     [ld, hd, lr, hr] = wavefilter('haar') Get the low and highpass
%                                           decomposition (ld, hd)
%                                           and reconstruction
%                                           (lr, hr) filters for
%                                           wavelet 'haar'.
%     [ld, hd] = wavefilter('haar','d')     Get decomposition filters
%                                           ld and hd.
%     [lr, hr] = wavefilter('haar','r')     Get reconstruction
%                                           filters lr and hr.
%
%   INPUTS:
%     WNAME             Wavelet Name
%     ---------------------------------------------------------
%     'haar' or 'db1'   Haar
%     'db4'             4th order Daubechies
%     'sym4'            4th order Symlets
%     'bior6.8'         Cohen-Daubechies-Feauveau biorthogonal
%     'jpeg9.7'         Antonini-Barlaud-Mathieu-Daubechies
%
%     TYPE              Filter Type
%     ---------------------------------------------------------
%     'd'               Decomposition filters
%     'r'               Reconstruction filters
%
%   See also WAVEFAST and WAVEBACK.

%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.5 $  $Date: 2003/10/13 01:09:39 $

% Check the input and output arguments.
error(nargchk(1, 2, nargin));

if (nargin == 1 & nargout ~= 4) | (nargin == 2 & nargout ~= 2)
   error('Invalid number of output arguments.');
end

if nargin == 1 & ~ischar(wname)
   error('WNAME must be a string.');
end

if nargin == 2 & ~ischar(type)
   error('TYPE must be a string.');
end

% Create filters for the requested wavelet.
switch lower(wname)
case {'haar', 'db1'}
   ld = [1 1]/sqrt(2);     hd = [-1 1]/sqrt(2);
   lr = ld;                hr = -hd;

case 'db4'
   ld = [-1.059740178499728e-002 3.288301166698295e-002 ...
         3.084138183598697e-002 -1.870348117188811e-001 ...
         -2.798376941698385e-002 6.308807679295904e-001 ...
         7.148465705525415e-001 2.303778133088552e-001];
   t = (0:7);
   hd = ld;    hd(end:-1:1) = cos(pi * t) .* ld;
   lr = ld;    lr(end:-1:1) = ld;
   hr = cos(pi * t) .* ld;

case 'sym4'
   ld = [-7.576571478927333e-002 -2.963552764599851e-002 ...
         4.976186676320155e-001 8.037387518059161e-001 ...
         2.978577956052774e-001 -9.921954357684722e-002 ...
         -1.260396726203783e-002 3.222310060404270e-002];
   t = (0:7);
   hd = ld;    hd(end:-1:1) = cos(pi * t) .* ld;
   lr = ld;    lr(end:-1:1) = ld;
   hr = cos(pi * t) .* ld;

case 'bior6.8'
   ld = [0 1.908831736481291e-003 -1.914286129088767e-003 ...
         -1.699063986760234e-002 1.193456527972926e-002 ...
         4.973290349094079e-002 -7.726317316720414e-002 ...
         -9.405920349573646e-002 4.207962846098268e-001 ...
         8.259229974584023e-001 4.207962846098268e-001 ...
         -9.405920349573646e-002 -7.726317316720414e-002 ...
         4.973290349094079e-002 1.193456527972926e-002 ...
         -1.699063986760234e-002 -1.914286129088767e-003 ...
         1.908831736481291e-003];
   hd = [0 0 0 1.442628250562444e-002 -1.446750489679015e-002 ...
         -7.872200106262882e-002 4.036797903033992e-002 ...
         4.178491091502746e-001 -7.589077294536542e-001 ...
         4.178491091502746e-001 4.036797903033992e-002 ...
         -7.872200106262882e-002 -1.446750489679015e-002 ...
         1.442628250562444e-002 0 0 0 0];
   t = (0:17);
   lr = cos(pi * (t + 1)) .* hd;
   hr = cos(pi * t) .* ld;

case 'jpeg9.7'
   ld = [0 0.02674875741080976 -0.01686411844287495 ...
         -0.07822326652898785 0.2668641184428723 ...
         0.6029490182363579 0.2668641184428723 ...
         -0.07822326652898785 -0.01686411844287495 ...
         0.02674875741080976];
   hd = [0 -0.09127176311424948 0.05754352622849957 ...
         0.5912717631142470 -1.115087052456994 ...
         0.5912717631142470 0.05754352622849957 ...
         -0.09127176311424948 0 0];
   t = (0:9);
   lr = cos(pi * (t + 1)) .* hd;
   hr = cos(pi * t) .* ld;

otherwise
   error('Unrecognizable wavelet name (WNAME).');
end

% Output the requested filters.
if (nargin == 1)
   varargout(1:4) = {ld, hd, lr, hr};
else
   switch lower(type(1))
   case 'd'
      varargout = {ld, hd};
   case 'r'
      varargout = {lr, hr};
   otherwise
      error('Unrecognizable filter TYPE.');
   end
end


function [patch_loc] = patchLocation(imagesize, size_patch, size_skip)

y = 1:size_skip(1):imagesize(1)-size_patch(1)+1;
x = 1:size_skip(2):imagesize(2)-size_patch(2)+1;

y = [y imagesize(1)-size_patch(1)+1];
x = [x imagesize(2)-size_patch(2)+1];

[Y,X] = meshgrid(y,x);
[dY,dX] = meshgrid(0:size_patch(1)-1,0:size_patch(2)-1);
dY = repmat(reshape(Y,[1 1 size(Y(:),1)]), [size_patch(1) size_patch(2) 1]) + repmat(dY, [1 1 size(Y(:),1)]);
dX = repmat(reshape(X,[1 1 size(X(:),1)]), [size_patch(1) size_patch(2) 1]) + repmat(dX, [1 1 size(X(:),1)]);
patch_loc = dY+(dX-1)*imagesize(1);


function hpdi = hpdi(x, p)
% HPDI - Estimates the Bayesian HPD intervals
%
%   Y = HPDI(X,P) returns a Highest Posterior Density (HPD) interval
%   for each column of X. P must be a scalar. Y is a 2 row matrix
%   where ith column is HPDI for ith column of X.

%   References:
%      [1] Chen, M.-H., Shao, Q.-M., and Ibrahim, J. Q., (2000).
%          Monte Carlo Methods in Bayesian Computation. Springer-Verlag.

% Copyright (C) 2001 Aki Vehtari
%
% This software is distributed under the GNU General Public
% Licence (version 3 or later); please refer to the file
% Licence.txt, included with the software, for details.

if nargin < 2
  error('Not enough arguments')
end

m=size(x,2);
pts=linspace(0.1,99.9-p,20);
pt1=prctile(x,pts);
pt2=prctile(x,p+pts);
cis=abs(pt2-pt1);
[foo,hpdpi]=min(cis);
if m==1
  hpdi=[pt1(hpdpi); pt2(hpdpi)];
else
  hpdpi=sub2ind(size(pt1),hpdpi,1:m);
  hpdi=[pt1(hpdpi); pt2(hpdpi)];
end


function I = integral2(f, S)
%INTEGRAL2    Surface integral of a CHEBFUN3.
%   INTEGRAL2(F, S) returns integral of the CHEBFUN3 object F over the
%   parametric surface S defined as a CHEBFUN2V object.
%
%   I = INTEGRAL2(F) is the same as I = SUM2(F).
%
% See also CHEBFUN3/INTEGRAL, CHEBFUN3/INTEGRAL3, CHEBFUN3/SUM,
% CHEBFUN3/SUM2 and CHEBFUN3/SUM3.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Developer Note: If F = F(x,y,z) is a CHEBFUN3 and
% S = {(u,v)\in DOM, s.t. x = x(u,v), y = y(u,v) and z = z(u,v)}, is a
% parametric surface represented by a CHEBFUN2V object, then
% \int \int_S F(x,y,z) dS = \int \int_DOM F(x(u,v), y(u,v), z(u,v))) ...
%                                                 norm(cross(r_u, r_v)) dA.
% Note that the domain of f should contain the range of S.
% TODO: Check for this in the code.

% Empty check:
if ( isempty(f) )
    I = [];
    return
end

if ( nargin == 1 )
    % Double definite integral:
    I = sum2(f);

   elseif ( nargin == 2 )
       if ( isa(S, 'chebfun2v') )
           % Integral over a parametric surface represented by a CHEBFUN2V.
           % Get the surface:
           S_compon = S.components;
           S1 = S_compon{1};
           S2 = S_compon{2};
           S3 = S_compon{3};

           % Surface integral:
           diffCu = diff(S, 1, 2); % Note the Chebfun2 convention to
           diffCv = diff(S, 1, 1); % use 2 for the 1st variable.
           ds = cross(diffCu, diffCv);
           op = @(u,v) feval(f, feval(S1, u, v), feval(S2, u, v), ...
               feval(S3, u, v));
           I = sum2(chebfun2(op, S1.domain).*ds);

       elseif ( isvector(S) && numel(S) == 2 )
           % Double definite integral over specified dimensions:
           I = sum2(f, S);
       end
else
    error('CHEBFUN:CHEBFUN3:integral2:nargin', ['Incorrect number of '...
        'input arguments.']);
end

end

function ds = cross(F, G)
H = [F(2).*G(3) - F(3).*G(2);
     F(3).*G(1) - F(1).*G(3);
     F(1).*G(2) - F(2).*G(1)];
% Developer note: In principle, here we should use
% ds = sqrt(H(1).^2 + H(2).^2 + H(3).^2);
% which uses chebfun2/sqrt. But, that code calls a singleSingTest
% subroutine which sometimes gives error even in this case where the input
% to sqrt is always nonnegative. We bypass that code by calling chebfun2
% constructor as follows:
ds = chebfun2(@(u,v) sqrt(abs(feval(H(1),u,v).^2 + feval(H(2), u, v).^2 +...
    feval(H(3), u, v).^2)), H(1).domain);
end


function c=ref_dcti_1(f)
%REF_DCTI_1  Reference Discrete Consine Transform type I
%   Usage:  c=ref_dcti_1(f);
%
%

L=size(f,1);
W=size(f,2);

if L==1
  c=f;
  return;
end;

R=1/sqrt(2)*[eye(L);...
	     [zeros(L-2,1),flipud(eye(L-2)),zeros(L-2,1)]];

R(1,1)=1;
R(L,L)=1;

c=R'*dft(R*f);


function[]=makefigs_maternoise
%MAKEFIGS_MATERNOISE  Makes a sample figure for MATERNOISE.

N=1000;
alpha=[0.6 1 1.5 2 3 4];
h=[.01 .02 .05 .2 1];
[alpha,h]=meshgrid(alpha,h);
h=h.*alpha;

rng(1);  %set seed
z=maternoise(1,N,10,alpha,h);
z=z./vrep(std(z,1,1),size(z,1),1);  %Set to unit std
y=detrend(cumsum(z),'constant');
y=y./vrep(std(y,1,1),size(y,1),1);  %Set to unit std

%This is just to make an offset
[xo,yo]=meshgrid(1:6,1:5);
zo=xo(:)'+1i*yo(:)';
zo=vrep(zo,length(z),1);

figure,
plot(y+zo*3),axis equal,noxlabels,noylabels
xlabel('Increasing $\alpha \rightarrow$'),ylabel('Increasing $\lambda \rightarrow$')
set(gca,'xticklabel',[]),set(gca,'xticklabel',[])
title('Example of Matern Processes')


% MINIMAL_LSTM
%   Demonstrates LSTMs on a toy binary addition problem.
%   The task is to predict the sequence of bits of the sum of two numbers,
%   given their binary sequences (one bit at a time).

run('../../setup_autonn.m') ;  % add AutoNN to the path
rng(0) ;  % set random seed

T = 8 ;  % number of bits / time steps
d = 16 ;  % dimensionality of the LSTM state
iters = 1500 ;  % number of iterations

% inputs
x = Input() ;
y = Input() ;

% initialize the shared parameters for an LSTM with d hidden units and
% two inputs
[W, b] = vl_nnlstm_params(d, 2) ;

% initial state
h = cell(T+1, 1);
c = cell(T+1, 1);
h{1} = zeros(d, 1, 'single');
c{1} = zeros(d, 1, 'single');

% run LSTM over all time steps
for t = 1:T
  [h{t+1}, c{t+1}] = vl_nnlstm(x(:,t), h{t}, c{t}, W, b);
end

% concatenate output into m x T matrix, ignoring initial state (h{1})
H = [h{2:end}] ;

% final projection (note the same projection is applied at all time steps)
prediction = vl_nnconv(reshape(H, 1, 1, d, T), 'size', [1, 1, d, 1]) ;

% define loss, and classification error
loss = vl_nnloss(prediction, y, 'loss', 'logistic') ;
err = vl_nnloss(prediction, y, 'loss','binaryerror') ;

% use workspace variables' names as the layers' names, and compile net
Layer.workspaceNames() ;
net = Net(loss, err) ;

% initialize solver
solver = solvers.Adam() ;
solver.learningRate = 1e-2 ;

losses = zeros(1, iters) ;
errors = zeros(1, iters) ;

for iter = 1:iters
  % generate a simple binary addition problem
  A = randi([0, 2^(T-1) - 1]) ;  % last bit is always 0 to prevent overflow
  B = randi([0, 2^(T-1) - 1]) ;
  C = A + B ;  % true answer

  % convert to vectors of binary digits
  data_x = [dec2bin(A, T); dec2bin(B, T)] ;  % concatenate binary numbers
  data_x = single(fliplr(data_x) == '1') ;  % convert from string to double, and reverse sequence
  data_y = dec2bin(C, T) ;  % same for the true answer
  data_y = single(fliplr(data_y) == '1') * 2 - 1;  % bit classes for prediction will be -1 or 1

  % evaluate network to compute gradients
  net.eval({'x', data_x, 'y', data_y}) ;

  % take one SGD step
  solver.step(net) ;

  % plot loss and error
  losses(iter) = net.getValue(loss) ;
  errors(iter) = net.getValue(err) ;

  if mod(iter, 100) == 0
    % display the current prediction
    fprintf('Iteration %i\n', iter);
    fprintf('True sequence: %s\n', sprintf('%i ', data_y > 0));
    fprintf('Predicted:     %s\n', sprintf('%i ', net.getValue('prediction') > 0));
    fprintf('Errors: %i\n\n', errors(iter) * T);
  end
end

figure(3) ;
subplot(1, 2, 1) ; plot(1 : 10 : iters, losses(1 : 10 : iters)) ;
xlabel('Iteration') ; ylabel('Loss') ;
subplot(1, 2, 2) ; plot(1 : 10 : iters, errors(1 : 10 : iters)) ;
xlabel('Iteration') ; ylabel('Error') ;

loss
net


function chud_pi_test ( )

%*****************************************************************************80
%
%% CHUD_PI_TEST tests the CHUD_PI function.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 February 2012
%
%  Author:
%
%    John Burkardt
%
  clear all

  fprintf ( 1, '\n' );
  fprintf ( 1, 'CHUD_PI_TEST\n' );
  fprintf ( 1, '  CHUD_PI computes the value of pi using the \n' );
  fprintf ( 1, '  Chudnovsky approach.\n' );
%
%  Get pi to 10, 20, 40, 80 decimal digits:
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Request PI to 10, 20, 40, 80 digits.\n' );
  fprintf ( 1, '\n' );
%
%  Trying to print P out neatly using concatenation fails here,
%  although it works in AGM_PI_TEST.
%
%  The procedure for printing out the D-digit representation of
%  a symbolic variable (if you are not willing to simply name
%  the variable and have its value plop out on the screen) is
%  not apparent to me!
%
  d = 10;

  for i = 1 : 4

    p = chud_pi ( d );

    fprintf ( 1, '  Request %6d digits:', d );
    p
    d = d * 2;

  end
%
%  Timings.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  How long does it take to compute PI to D digits?\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '          Digits    Seconds\n' );
  fprintf ( 1, '\n' );
  d = 2;
  for i = 1 : 13
    tic
    p = chud_pi ( d );
    t = toc;
    fprintf ( 1, '  %2d  %10d  %14g\n', i, d, t );
    d = d * 2;
  end

  return
end


function a = cheby_t_inverse ( n )

%*****************************************************************************80
%
%% CHEBY_T_INVERSE returns the inverse of the CHEBY_T matrix.
%
%
%  Example:
%
%    N = 11
%
%      1   .   .  .   .  .  .  .  .  .  .
%      .   1   .  .   .  .  .  .  .  .  .
%      1   .   1  .   .  .  .  .  .  .  .  /   2
%      .   3   .  1   .  .  .  .  .  .  .  /   4
%      3   .   4  .   1  .  .  .  .  .  .  /   8
%      .  10   .  5   .  1  .  .  .  .  .  /  16
%     10   .  15  .   6  .  1  .  .  .  .  /  32
%      .  35   . 21   .  7  .  1  .  .  .  /  64
%     35   .  56  .  28  .  8  .  1  .  .  / 128
%      . 126   . 84   . 36  .  9  .  1  .  / 256
%    126   . 210  . 120  . 45  . 10  .  1  / 512
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 September 20007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  a(1,1) = 1.0;

  if ( n == 1 )
    return
  end

  a(2,2) = 1.0;

  if ( n == 2 )
    return
  end

  for i = 3 : n
    for j = 1 : n
      if ( j == 1 )
        a(i,j) =                      a(i-1,j+1)   / 2.0;
      elseif ( j == 2 )
        a(i,j) = ( 2.0 * a(i-1,j-1) + a(i-1,j+1) ) / 2.0;
      elseif ( j < n )
        a(i,j) = (       a(i-1,j-1) + a(i-1,j+1) ) / 2.0;
      else
        a(i,j) =         a(i-1,j-1)                / 2.0;
      end
    end
  end

  return
end


function value = r4_si ( x )

%*****************************************************************************80
%
%% R4_SI evaluates the sine integral Si of an R4 argument.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 September 2011
%
%  Author:
%
%    Original FORTRAN77 version by Wayne Fullerton.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Wayne Fullerton,
%    Portable Special Function Routines,
%    in Portability of Numerical Software,
%    edited by Wayne Cowell,
%    Lecture Notes in Computer Science, Volume 57,
%    Springer 1977,
%    ISBN: 978-3-540-08446-4,
%    LC: QA297.W65.
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real VASLUE, the sine integral Si evaluated at X.
%
  persistent nsi
  persistent sics
  persistent xsml

  if ( isempty ( nsi ) )

    sics = [ ...
      -0.1315646598184841929, ...
      -0.2776578526973601892, ...
       0.0354414054866659180, ...
      -0.0025631631447933978, ...
       0.0001162365390497009, ...
      -0.0000035904327241606, ...
       0.0000000802342123706, ...
      -0.0000000013562997693, ...
       0.0000000000179440722, ...
      -0.0000000000001908387, ...
       0.0000000000000016670, ...
      -0.0000000000000000122 ]';

    nsi = r4_inits ( sics, 12, 0.1 * r4_mach ( 3 ) );
    xsml = sqrt ( eps );

  end

  absx = abs ( x );

  if ( absx < xsml )

    value = x;

  elseif ( absx <= 4.0 )

    value = x * ( 0.75 + r4_csevl ( ( x * x - 8.0 ) * 0.125, sics, nsi ) );

  else

    [ f, g ] = r4_sifg ( absx );
    cosx = cos ( absx );

    if ( x < 0.0 )
      value = - 0.5 * pi + f * cosx + g * sin ( x );
    else
      value = 0.5 * pi - f * cosx - g * sin ( x );
    end

  end

  return
end


function [ vX ] = ProxLogisticLossFunctionGd( vX, vY, vC, paramLambda, numIterations, stopThr )
% ----------------------------------------------------------------------------------------------- %
% [ vX ] = ProxLogisticLossFunction( vX, vY, vC, paramLambda, numIterations, stopThr )
%   Calculates the Prox of the Logistic Cost Function using Gradient Descent.
% Input:
%   - vX            -   Input Vector.
%                       Starting point for the iterative procedure.
%                       Structure: Vector (Column).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
%   - vY            -   Input Vector.
%                       Structure: Vector (Column).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
%   - vC            -   Model Vector.
%                       The model vector in the Logsitic Cost Function.
%                       Structure: Vector (Column).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
%   - numIterations -   Number of Iterations.
%                       Sets the number of iterations for the algorithm to
%                       run.
%                       Structure: Scalar.
%                       Type: 'Single' / 'Double'.
%                       Range {1, 2, ...}.
%   - stopTol       -   Stopping Condition Tolerance.
%                       Sets the stopping threshold for the L Inf (Maximum
%                       Absolute Value) of the change between 2 iterations
%                       of the algorithm.
%                       Structure: Scalar.
%                       Type: 'Single' / 'Double'.
%                       Range [0, inf).
% Output:
%   - vX            -   Output Vector.
%                       The Prox for the logistic cost function for the
%                       input vector 'vY'.
%                       Structure: Vector (Column).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
% References
%   1.  https://math.stackexchange.com/a/3571521/33.
%   2.  Elementary Numerical Analysis MATH:3800/CS:3700(22M:072/22C:072)
%       (https://homepage.divms.uiowa.edu/~whan/3800.d/3800.html, Section 3.4).
% Remarks:
%   1.  On some cases it fails to converge (While Newton Method converge to
%       the right solution).
% TODO:
%   1.  C
% Release Notes:
%   -   1.0.000     06/03/2020  Royi Avital
%       *   First release version.
% ----------------------------------------------------------------------------------------------- %

FALSE   = 0;
TRUE    = 1;

OFF     = 0;
ON      = 1;

vXPrev = vX;
vG = zeros(size(vX, 1), 1);

hObjFun = @(vX) 0.5 * sum((vX - vY) .^ 2) + (paramLambda * log(1 + exp(-vC.' * vX)));
stepSizeMax = 2;
sSolverOptions = optimset('fminbnd');
sSolverOptions = optimset(sSolverOptions, 'Display', 'off');

for ii = 1: numIterations
    vXPrev(:) = vX;

    valExp  = exp(-vC.' * vX);
    vG(:) = vX - vY - (paramLambda * (valExp / (1 + valExp)) * vC);

    hStepSizeFun    = @(stepSize) hObjFun(vX - (stepSize * vG));
    stepSize        = fminbnd(hStepSizeFun, 0, stepSizeMax, sSolverOptions);

    vX(:) = vX - (stepSize * vG);

    if(max(abs(vX - vXPrev)) < stopThr)
        break;
    end
end

end


function h = p06_fh ( p )

%*****************************************************************************80
%
%% P06_FH is the mesh density function for problem 06.
%
%  Licensing:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Modified:
%
%    06 February 2006
%
%  Parameters:
%
%    Input, real P, one or more points.
%
%    Output, real H, the value of the mesh density function at P.
%
  h = dexpr ( p, '(x^4+y^4)^(1/4)' );

  return
end