function phin = phi ( n )

%*****************************************************************************80
%
%% PHI computes the number of relatively prime predecessors of an integer.
%
%  Definition:
%
%    PHI(N) is the number of integers between 1 and N which are
%    relatively prime to N.  I and J are relatively prime if they
%    have no common factors.  The function PHI(N) is known as
%    "Euler's totient function".
%
%    By convention, 1 and N are relatively prime.
%
%  First values:
%
%     N  PHI(N)
%
%     1    1
%     2    1
%     3    2
%     4    2
%     5    4
%     6    2
%     7    6
%     8    4
%     9    6
%    10    4
%    11   10
%    12    4
%    13   12
%    14    6
%    15    8
%    16    8
%    17   16
%    18    6
%    19   18
%    20    8
%
%  Formula:
%
%    PHI(U*V) = PHI(U) * PHI(V) if U and V are relatively prime.
%
%    PHI(P^K) = P^(K-1) * ( P - 1 ) if P is prime.
%
%    PHI(N) = N * Product ( P divides N ) ( 1 - 1 / P )
%
%    N = Sum ( D divides N ) PHI(D).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the value to be analyzed.
%
%    Output, integer PHIN, the value of PHI(N).  If N is less than
%    or equal to 0, PHI will be returned as 0.  If there is not enough
%    room for full factoring of N, PHI will be returned as -1.
%
  if ( n <= 0 )
    phin = 0;
    return
  end

  if ( n == 1 )
    phin = 1;
    return
  end
%
%  Factor N.
%
  [ nfactor, factor, power, nleft ] = i4_factor ( n );

  if ( nleft ~= 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PHI - Fatal error!\n' );
    fprintf ( 1, '  Not enough factorization space.\n' );
    error ( 'PHI - Fatal error!' );
  end

  phin = 1;
  for i = 1 : nfactor
    phin = phin * factor(i)^( power(i) - 1 ) * ( factor(i) - 1 );
  end

  return
end


function diftab = dif_basis_i ( ival, ntab, xtab )

%*****************************************************************************80
%
%% DIF_BASIS_I computes the I-th Lagrange basis polynomial in divided difference form.
%
%  Discussion:
%
%    The I-th Lagrange basis polynomial for a set of NTAB X values XTAB,
%    L(I,NTAB,XTAB)(X) is a polynomial of order NTAB-1 which is zero at
%    XTAB(J) for J not equal to I, and 1 when J is equal to I.
%
%    The Lagrange basis polynomials have the property that the interpolating
%    polynomial through a set of NTAB data points (XTAB,YTAB) may be
%    represented as
%
%      P(X) = Sum ( 1 <= I <= N ) YTAB(I) * L(I,NTAB,XTAB)(X)
%
%    Higher order interpolation at selected points may be accomplished
%    using repeated X values, and scaled derivative values.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carl deBoor,
%    A Practical Guide to Splines,
%    Springer, 2001,
%    ISBN: 0387953663,
%    LC: QA1.A647.v27.
%
%  Parameters:
%
%    Input, integer IVAL, the index of the desired Lagrange basis polynomial.
%    IVAL should be between 1 and NTAB.
%
%    Input, integer NTAB, the number of data points XTAB.
%
%    Input, real XTAB(NTAB), the X values upon which the
%    Lagrange basis polynomial is to be based.
%
%    Output, real DIFTAB(NTAB), the divided difference table
%    for the IVAL-th Lagrange basis polynomial.
%

%
%  Check IVAL.
%
  if ( ival < 1 | ntab < ival )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'DIF_BASIS_I - Fatal error!\n' );
    fprintf ( 1, '  IVAL must be between 1 and %d\n', ntab );
    fprintf ( 1, '  but your value is %d\n', ival );
    error ( 'DIF_BASIS_I - Fatal error!' );
  end
%
%  Initialize DIFTAB to Delta(I,J).
%
  diftab(1:ntab) = 0.0;
  diftab(ival) = 1.0;
%
%  Compute the IVAL-th Lagrange basis polynomial.
%
  diftab = data_to_dif ( ntab, xtab, diftab );

  return
end


function y = gauss(mu, covar, x)
%GAUSS	Evaluate a Gaussian distribution.
%
%	Description
%
%	Y = GAUSS(MU, COVAR, X) evaluates a multi-variate Gaussian  density
%	in D-dimensions at a set of points given by the rows of the matrix X.
%	The Gaussian density has mean vector MU and covariance matrix COVAR.
%
%	See also
%	GSAMP, DEMGAUSS
%

%	Copyright (c) Ian T Nabney (1996-2001)

[n, d] = size(x);

[j, k] = size(covar);

% Check that the covariance matrix is the correct dimension
if ((j ~= d) | (k ~=d))
  error('Dimension of the covariance matrix and data should match');
end

invcov = inv(covar);
mu = reshape(mu, 1, d);    % Ensure that mu is a row vector

x = x - ones(n, 1)*mu;
fact = sum(((x*invcov).*x), 2);

y = exp(-0.5*fact);

y = y./sqrt((2*pi)^d*det(covar));


function [lat, lon, sphrad] = proj_on_sphere(x)
% PROJ_ON_SPHERE  Project a point configuration onto a sphere
%
% [LAT, LON, SPHRAD] = proj_on_sphere(X)
%
%   X is a 3-row matrix. Each colum has the (x,y,z)-coordinates of a point.
%
%   LAT, LON are vectors with the latitude and longitude of the points in X
%   projected onto a sphere. The centre of the sphere is the centroid of X.
%
%   SPHRAD is the median of the distance of the points in X to the
%   centroid. It can be used as the radius of the sphere that best contains
%   the projection of X in terms of distances between the the points.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2013 University of Oxford
% Version: 0.1.1
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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 3 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. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see
% <http://www.gnu.org/licenses/>.

% check arguments
narginchk(1, 1);
nargoutchk(0, 3);

if (size(x, 2) ~= 3)
    error('X must be a matrix with 3-columns')
end

% project 3D Cartesian coordinates onto
% the surface of a sphere lon, lat given in radians, centered around 0
[lon, lat, r] = cart2sph(...
    x(:, 1) - mean(x(:, 1)), ...
    x(:, 2) - mean(x(:, 2)), ...
    x(:, 3) - mean(x(:, 3)));

% we use the median radius of the points in the configuration as the radius
% of the sphere that best can contains their projections
sphrad = median(r);


function pdf = angle_pdf ( x, n )

%*****************************************************************************80
%
%% ANGLE_PDF evaluates the Angle PDF.
%
%  Discussion:
%
%    X is an angle between 0 and PI, corresponding to the angle
%    made in an N-dimensional space, between a fixed line passing
%    through the origin, and an arbitrary line that also passes
%    through the origin, which is specified by a choosing any point
%    on the N-dimensional sphere with uniform probability.
%
%  Formula:
%
%    PDF(X) = ( sin ( X ) )**(N-2) * Gamma ( N / 2 )
%             / ( sqrt ( PI ) * Gamma ( ( N - 1 ) / 2 ) )
%
%    PDF(X) = 1 / PI if N = 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Reuven Rubinstein,
%    Monte Carlo Optimization, Simulation and Sensitivity of Queueing Networks,
%    Wiley, 1986.
%
%  Parameters:
%
%    Input, real X, the argument of the PDF.
%
%    Input, integer N, the spatial dimension.
%    N must be at least 2.
%
%    Output, real PDF, the value of the PDF.
%
  if ( n < 2 )
    fprintf ( 1, '\n' );
    fprintf ( 1, '\ANGLE_PDF - Fatal error!\n' );
    fprintf ( 1, '\  N must be at least 2.\n' );
    fprintf ( 1, '\  The input value of N = %d\n', n );
    error ( 'ANGLE_PDF - Fatal error!' );
  end

  if ( x < 0.0 | pi < x )
    pdf = 0.0;
  elseif ( n == 2 )
    pdf = 1.0 / pi;
  else
    pdf = ( sin ( x ) )^( n - 2 ) * gamma ( n / 2.0 ) ...
      / ( sqrt ( pi ) * gamma ( ( n - 1 ) / 2.0 ) );
  end

  return
end


function volume = simplex_unit_volume_nd ( dim_num )

%*****************************************************************************80
%
%% SIMPLEX_UNIT_VOLUME_ND computes the volume of the unit simplex in ND.
%
%  Discussion:
%
%    The formula is simple: volume = 1/N!.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the space.
%
%    Output, real VOLUME, the volume of the cone.
%
  volume = 1.0;
  for i = 1 : dim_num
    volume = volume / i;
  end

  return
end


function value = torus_area_3d ( r1, r2 )

%*****************************************************************************80
%
%% TORUS_AREA_3D returns the area of a torus in 3D.
%
%  Integration region:
%
%    Points (X,Y,Z) such that:
%
%      ( SQRT ( X*X + Y*Y ) - R1 )**2 + Z*Z = R2*R2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R1, R2, the two radii that define the torus.
%
%    Output, real TORUS_AREA_3D, the area of the torus.
%
  value = 4.0E+00 * pi * pi * r1 * r2;

  return
end


function val=intPowSin(u,n)
%%INTPOWSIN Evaluate the integral of u^n*sin(u) du.  A definite integral
%           can be evaluated, or an indefinite integral (with a particular
%           additive constant).
%
%INPUTS: u A 2XN (for definite integral) or a 1XN (for indefinite
%          integrals) set of N points. For definite integrals, u(1,:) are
%          the real lower bounds and u(2,:) are the real upper bounds. For
%          indefinite integrals, the integral is evaluated at the points in
%          u. The values in u should be real.
%        n The positive integer exponent of coefficient multiplying the
%          sine term.
%
%OUTPUTS: val The 1XN set of values of the integral of u^n*sin(u).
%
%This function simply implements the recursion that arises from integration
%by parts from basic calculus, as are given in the tables in the back of
%[1].
%
%REFERENCES:
%[1] J. Stewart, Calculus, 7th ed. Belmont, CA: Brooks/Cole, 2012.
%
%October 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numDim=size(u,1);

if(isempty(u))
   val=[];
   return;
end

if(numDim==1)%An indefinite integral
    val=indefIntPowSin(u,n);
else%A definite integral
    val=indefIntPowSin(u(2,:),n)-indefIntPowSin(u(1,:),n);
end

end

function val=indefIntPowSin(u,n)

if(n==0)
    val=-cos(u);
    return;
elseif(n==1)
    val=sin(u)-u*cos(u);
    return;
end

%If here, n>=1
cosVal=cos(u);
sinVal=sin(u);

val=0;
if(mod(n,2)==0)%If n is even
    endVal=2;
else
    endVal=3;
end

coeffProd=1;
for k=n:-2:endVal
    %Do a sine step and a cosine step together!!!
    val=val-coeffProd*u.^k.*cosVal;
    coeffProd=coeffProd*k;
    val=val+coeffProd*u.^(k-1).*sinVal;
    coeffProd=-coeffProd*(k-1);
end

if(endVal==2)
    %The final integral is over u^0*sin(u)
    val=val-coeffProd*cosVal;
else%The final integral is over u^1*sin(u)
    val=val+coeffProd*(sinVal-u.*cosVal);
end
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 pagerankdemo (steps)
% PAGERANKDEMO draw a 6-node web and compute its pagerank
%
% PAGERANKDEMO draws the 6-node "tiny web" in Section 2.11 of "Numerical
% Computing with MATLAB", by Cleve Moler, SIAM, 2004.  It then simulates the
% computation of Google's PageRank algorithm, by randomly selecting links to
% traverse.  If a link is traversed, the edge and the target node are displayed
% in red.  If the "random surfer" jumps to an arbitrary page, the target node
% is displayed in blue.  The number of hits at each node, and the page rank
% (in %) are displayed % on each node.  Note that after a large number of
% steps, the PageRanks (in percentages) converge to the values given in Section
% 2.11 of Moler (alpha: .321, sigma: .2007, beta: .1705, delta: .1368,
% gamma: .1066, rho: .0643).  See http://www.mathworks.com/moler for more
% details (the pagerank M-file, in particular).
%
% Note that this method is NOT how the PageRank is actually computed.  Instead
% the eigenvalue problem A*x=x is solved for x, where A is the Markov
% transition matrix, A = p*G*D + e*z', where G is the binary matrix used here.
% The method here is a simplistic random-hopping demonstration of the Markov
% process, to motivate the A*x=x formulation of the problem.  In this example,
% A does control how the transitions are made, but the matrix A is not formed
% explicitly.
%
% This demo only operates on a single graph.  It is meant as a simple demo
% only, suitable for in-class use.  To compute the PageRanks for an arbitrary
% graph, use pagerank.m, or the power method (repeat x=A*x until convergence,
% where A is the Markov transition matrix of the web).
%
% Example:
%   pagerankdemo
%   pagerankdemo (1000)   % run 1000 steps with no user input, then quit
%
% See also pagerank
%
% I suggest single-stepping a dozen times or so to see the link traversal in
% process, and then type "1000".  Hit control-C to quit.
%
% Copyright 2007, Tim Davis, University of Florida

% Initial graph
Graph = graphinit ;
rand ('state', 0) ;
n = size (Graph.G, 1) ;

help pagerankdemo

% initialize the page counts
hits = zeros (1,n) ;
oldwhere = 1 ;
where = 1 ;
hits (where) = 1 ;
set (Graph.node (where), 'FaceColor', [0 0 1]) ;

p = 0.85 ;		% probability a link will be followed
c = sum (Graph.G) ;	% outgoing degree

links = cell (1,n) ;
for k = 1:n
    links {k} = find (Graph.G (:,k)) ;
end

follow_link = 0 ;
if (nargin < 1)
    input ('hit enter to start at node alpha: ') ;
end

% write the stats to the figure
set (Graph.nodelabel (where), 'string', ...
	sprintf ('%s %d (%3.1f%%)', Graph.nodes {where}, hits (where), ...
	100 * hits (where) / sum (hits))) ;

if (nargin < 1)
    input ('hit enter to take one step: ') ;
    steps = 1 ;
end

% repeat
while (1)

    % clear the old color and old arrow
    set (Graph.node (where), 'FaceColor', [0 1 0]) ;
    if (follow_link)
	set (Graph.arrows (where,oldwhere), 'LineWidth', 2) ;
	set (Graph.arrows (where,oldwhere), 'Color', [0 0 0]) ;
    end

    % determine where to go to next
    oldwhere = where ;
    if (c (where) == 0 || rand > p)
	% no outgoing links, or ignore the links
	follow_link = 0 ;
	where = floor (n * rand + 1) ;
	set (Graph.node (where), 'FaceColor', [0 0 1]) ;
    else
	% move along the link
	follow_link = 1 ;
	where = links{where}(floor (c (where) * rand + 1)) ;
	set (Graph.node (where), 'FaceColor', [1 0 0]) ;
	set (Graph.arrows (where,oldwhere), 'LineWidth', 5) ;
	set (Graph.arrows (where,oldwhere), 'Color', [1 0 0]) ;
    end

    % increment the hit count
    hits (where) = hits (where) + 1 ;

    % write the stats to the figure
    for k = 1:n
	set (Graph.nodelabel (k), 'string', ...
	sprintf ('%s %d (%3.1f%%)', Graph.nodes {k}, hits (k), ...
	100 * hits (k) / sum (hits))) ;
    end

    drawnow

    % go the next step
    steps = steps - 1 ;
    if (steps <= 0)
        if (nargin > 0)
            break ;
        end
        steps = input ...
	    ('number of steps to make (default 1, control-C to quit): ') ;
	if (steps == 0)
	    break ;
	end
	if (isempty (steps))
	    steps = 1 ;
	end
    end

end

%-------------------------------------------------------------------------------

function Graph = graphinit
% GRAPHINIT create the tiny-web example in Moler, section 2.11, and draw it.
% Example
%   G = graphinit ;

figure (1)
clf

nodes = { 'alpha', 'beta', 'gamma', 'delta', 'rho', 'sigma' } ;

xy = [
0 4
1 3
1 2
2 4
2 0
0 0
] ;

x = xy (:,1) ;
y = xy (:,2) ;

% scale x and y to be in the range 0.1 to 0.9
x = 0.8 * x / 2 + .1 ;
y = 0.8 * y / 4 + .1 ;
xy = [x y] ;

xy_delta = [
 .08 .04 0
-.03 -.02 -1
 .04  0   0
-.05  .04 -1
-.03  0  -1
 .03  0   0
] ;

xd = xy_delta (:,1) ;
yd = xy_delta (:,2) ;
tjust = xy_delta (:,3) ;

G = [
0 0 0 1 0 1
1 0 0 0 0 0
0 1 0 0 0 0
0 1 1 0 0 0
0 0 1 0 0 0
1 0 1 0 0 0 ] ;

clf

n = size (G,1) ;

axes ('Position', [0 0 1 1], 'Visible', 'off') ;

node = zeros (n,1) ;
nodelabel = zeros (n,1) ;
for k = 1:n
    node (k) = annotation ('ellipse', [x(k)-.025 y(k)-.025 .05 .05]) ;
    set (node (k), 'LineWidth', 2) ;
    set (node (k), 'FaceColor', [0 1 0]) ;
    nodelabel (k) = text (x (k) + xd (k), y (k) + yd (k), nodes {k}, ...
	'Units', 'normalized', 'FontSize', 16) ;
    if (tjust (k) < 0)
	set (nodelabel (k), 'HorizontalAlignment', 'right') ;
    end
end

axis off

% Yes, I realize that this is overkill; arrows should be sparse.
% This example is not meant for large graphs.
arrows = zeros (n,n) ;

[i j] = find (G) ;
for k = 1:length (i)
    % get the center of the two nodes
    figx = [x(j(k)) x(i(k))] ;
    figy = [y(j(k)) y(i(k))] ;
%   [figx figy] = dsxy2figxy (gca, axx, axy);
    % shorten the arrows by s units at each end
    s = 0.03 ;
    len = sqrt (diff (figx)^2 + diff (figy)^2) ;
    fy (1) = diff (figy) * (s/len) + figy(1) ;
    fy (2) = diff (figy) * (1-s/len) + figy(1) ;
    fx (1) = diff (figx) * (s/len) + figx(1) ;
    fx (2) = diff (figx) * (1-s/len) + figx(1) ;
    arrows (i(k),j(k)) = annotation ('arrow', fx, fy) ;
    set (arrows (i(k),j(k)), 'LineWidth', 2) ;
    set (arrows (i(k),j(k)), 'HeadLength', 20) ;
    set (arrows (i(k),j(k)), 'HeadWidth', 20) ;
end

Graph.G = G ;
Graph.nodes = nodes ;
Graph.node = node ;
Graph.xy = xy ;
Graph.xy_delta = xy_delta ;
Graph.nodelabel = nodelabel ;
Graph.arrows = arrows ;


% Example 6.2: Robust regression using the Huber penalty
% Section 6.1.2, Figure 6.5
% Boyd & Vandenberghe "Convex Optimization"
% Original by Lieven Vandenberghe
% Adapted for CVX by Joelle Skaf - 09/07/05
%
% Compares the solution of regular Least-squares:
%           minimize    sum(y_i - alpha - beta*t_i)^2
% to the solution of the following:
%           minimize    sum( phi_h (y_i - alpha - beta*t_i)^2 )
% where phi_h is the Huber penalty function, (t_i,y_i) are data points in a
% plane.

% Input data
randn('seed',1);
rand('seed',1);

m=40;  n=2;
xex = [5;1];
pts = -10+20*rand(m,1);
A = [ones(m,1) pts];
b = A*xex + .5*randn(m,1);
outliers = [-9.5; 9];  outvals = [20; -15];
A = [A; ones(length(outliers),1), outliers];
b = [b; outvals];
m = size(A,1);
pts = [pts;outliers];

% Least Squares
fprintf(1,'Computing the solution of the least-squares problem...');

xls =  A\b;

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

% Huber
fprintf(1,'Computing the solution of the huber-penalized problem...');

cvx_begin quiet
    variable xhub(n)
    minimize(sum(huber(A*xhub-b)))
cvx_end

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

% Plots
figure(1);  hold off
plot(pts,b,'o', [-11; 11], [1 -11; 1 11]*xhub, '-', ...
     [-11; 11], [1 -11; 1 11]*xls, '--');
axis([-11 11 -20 25])
title('Least-square fit vs robust least-squares fit (Huber-penalized)');
xlabel('x');
ylabel('y');
legend('Data points','Huber penalty','Regular LS','Location','Best');
%print -deps robustls.eps


function rz = vecrotz(angle)
%
% Function Name:
%
%   vecrotz - Transformation matrix for a rotation around the z axis.
%
% Calling Sequence:
%
%   rz = vecrotz(angle);
%
% Parameters:
%
%   angle	: rotation angle defined in radians
%
%   rz		: (4x4) Transformation matrix.
%
%
% Description:
%
%   Return the (4x4) Transformation matrix for a rotation about the z axis
%   by the defined angle.
%
%   The matrix is:
%
%         [  cos(angle)  -sin(angle)       0          0]
%         [ -sin(angle)   cos(angle)       0          0]
%         [      0            0            1          0]
%         [      0            0            0          1]
%
% Examples:
%
%  Rotate the NURBS line (0.0 0.0 0.0) - (3.0 3.0 3.0) by 45 degrees
%  around the z-axis
%
%    line = nrbline([0.0 0.0 0.0],[3.0 3.0 3.0]);
%    trans = vecrotz(%pi/4);
%    rline = nrbtform(line, trans);
%
% See:
%
%    nrbtform

%  Dr D.M. Spink
%  Copyright (c) 2000.

sn = sin(angle);
cn = cos(angle);
rz = [cn -sn 0 0; sn cn 0 0; 0 0 1 0; 0 0 0 1];


function value = sin_power_int ( a, b, n )

%*****************************************************************************80
%
%% SIN_POWER_INT evaluates the sine power integral.
%
%  Discussion:
%
%    The function is defined by
%
%      SIN_POWER_INT(A,B,N) = Integral ( A <= T <= B ) ( sin ( t ))^n dt
%
%    The algorithm uses the following fact:
%
%      Integral sin^n ( t ) = (1/n) * (
%        sin^(n-1)(t) * cos(t) + ( n-1 ) * Integral sin^(n-2) ( t ) dt )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters
%
%    Input, real A, B, the limits of integration.
%
%    Input, integer N, the power of the sine function.
%
%    Output, real SIN_POWER_INT, the value of the integral.
%
  if ( n < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SIN_POWER_INT - Fatal error!\n' );
    fprintf ( 1, '  Power N < 0.\n' );
    value = 0.0;
    error ( 'SIN_POWER_INT - Fatal error!' );
  end

  sa = sin ( a );
  sb = sin ( b );
  ca = cos ( a );
  cb = cos ( b );

  if ( mod ( n, 2 ) == 0 )
    value = b - a;
    mlo = 2;
  else
    value = ca - cb;
    mlo = 3;
  end

  for m = mlo : 2 : n
    value = ( ( m - 1 ) * value + sa^(m-1) * ca - sb^(m-1) * cb ) / m;
  end

  return
end


function a = jordan_inverse ( n, alpha )

%*****************************************************************************80
%
%% JORDAN_INVERSE returns the inverse of the JORDAN matrix.
%
%  Formula:
%
%    if ( I <= J )
%      A(I,J) =  -1 * (-1/ALPHA)^(J+1-I)
%    else
%      A(I,J) = 0
%
%  Example:
%
%    ALPHA = 2, N = 4
%
%    1/2 -1/4  1/8 -1/16
%    0    1/2 -1/4  1/8
%    0    0    1/2 -1/4
%    0    0    0    1/2
%
%  Properties:
%
%    A is upper triangular.
%
%    A is Toeplitz: constant along diagonals.
%
%    A is generally not symmetric: A' /= A.
%
%    A is persymmetric: A(I,J) = A(N+1-J,N+1-I).
%
%    The inverse of A is the Jordan block matrix, whose diagonal
%    entries are ALPHA, whose first superdiagonal entries are 1,
%    with all other entries zero.
%
%    det ( A ) = (1/ALPHA)^N.
%
%    LAMBDA(1:N) = 1 / ALPHA.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Input, real ALPHA, the eigenvalue of the Jordan matrix.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  if ( alpha == 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'JORDAN_INVERSE - Fatal error!\n' );
    fprintf ( 1, '  The input parameter ALPHA was 0.\n' );
    error ( 'JORDAN_INVERSE - Fatal error!' );
  end

  for i = 1 : n
    for j = 1 : n

      if ( i <= j )
        a(i,j) =  - ( - 1.0 / alpha )^(j+1-i);
      else
        a(i,j) = 0.0;
      end

    end
  end

  return
end


function g = sigmoid(z)
%SIGMOID Compute sigmoid function
%   g = SIGMOID(z) computes the sigmoid of z.

% You need to return the following variables correctly
g = zeros(size(z));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the sigmoid of each value of z (z can be a matrix,
%               vector or scalar).

g = 1 ./ (1 + exp(-z));

% =============================================================

end


function [mu sigma2] = estimateGaussian(X)
%ESTIMATEGAUSSIAN This function estimates the parameters of a
%Gaussian distribution using the data in X
%   [mu sigma2] = estimateGaussian(X),
%   The input X is the dataset with each n-dimensional data point in one row
%   The output is an n-dimensional vector mu, the mean of the data set
%   and the variances sigma^2, an n x 1 vector
%

% Useful variables
[m, n] = size(X);

% You should return these values correctly
mu = zeros(n, 1);
sigma2 = zeros(n, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the mean of the data and the variances
%               In particular, mu(i) should contain the mean of
%               the data for the i-th feature and sigma2(i)
%               should contain variance of the i-th feature.
%

mu = 1/m * sum(X);

sigma2 = 1/m * sum((X - repmat(mu, m, 1)).^2);

% =============================================================

end

github-repos/MATLAB/Borye-machine-learning-coursera-1/machine-learning-coursera-1-033fdc2e6da393eeb1179a09aafe92362021effb/Week 9 Assignments/Anomaly Detection and Recommender Systems/mlclass-ex8/estimateGaussian.m


function [hyperplane_normal, hyperplane_offset] = linortfitn(data)
% LINORTFITN  Fit a line to data by ORTHOGONAL least-squares.
%    [N,C] = LINORTFITN(DATA) finds the coefficients of a hyperplane (in
%    Hessian normal form) that best fits the data in an ORTHOGONAL
%    least-squares sense.  Consider the hyperplane
%       H = {x | dot(N,x) + C == 0},
%    and the minimum (Euclidean) distance between this hyperplane and each
%    datapoint DATA(i,:) -- LINORTFITN finds N and C such that the sum of
%    squared distances is minimized.

[M,N] = size(data);
if M <= N,
    error('linortfitn:DegenerateProblem',...
        'There are fewer datapoints than dimensions: the data is perfectly fit by a hyperplane.');
end

[U,S,V] = svd(data - repmat(mean(data),M,1), 0);
hyperplane_normal = V(:,end);
hyperplane_offset = - mean(data * hyperplane_normal);


function a = lesp ( m, n )

%*****************************************************************************80
%
%% LESP returns the LESP matrix.
%
%  Formula:
%
%    if ( I - J == 1 )
%      A(I,J) = 1 / I
%    else if ( I - J == 0 )
%      A(I,J) = - ( 2*I+3 )
%    else if ( I - J == 1 )
%      A(I,J) = J
%    else
%      A(I,J) = 0.0
%
%  Example:
%
%    M = 5, N = 5
%
%     -5    2    .    .     .
%     1/2  -7    3    .     .
%      .   1/3  -9    4     .
%      .    .   1/4 -11     5
%      .    .    .   1/5  -13
%
%
%  Properties:
%
%    The matrix is tridiagonal.
%
%    Because A is tridiagonal, it has property A (bipartite).
%
%    A is generally not symmetric: A' /= A.
%
%    The eigenvalues are real, and smoothly distributed in [-2*N-3.5, -4.5].
%
%    The eigenvalues are sensitive.
%
%    The matrix is similar to the symmetric tridiagonal matrix with
%    the same diagonal entries and with off-diagonal entries 1,
%    via a similarity transformation using the diagonal matrix
%    D = diagonal ( 1!, 2!, ..., N! ).
%
%    The family of matrices is nested as a function of N.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Wim Lenferink, MN Spijker,
%    On the use of stability regions in the numerical analysis of initial
%    value problems,
%    Mathematics of Computation,
%    Volume 57, 1991, pages 221-237.
%
%    Lloyd Trefethen,
%    Pseudospectra of matrices,
%    in Numerical Analysis 1991,
%    Proceedings of the 14th Dundee Conference,
%    D F Griffiths and G A Watson, editors,
%    Pitman Research Notes in Mathematics, volume 260,
%    Longman Scientific and Technical, Essex, UK, 1992, pages 234-266.
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns of A.
%
%    Output, real A(M,N), the matrix.
%
  a = zeros ( m, n );

  for i = 1 : m
    for j = 1 : n

      if ( i - j == 1 )
        a(i,j) = 1.0 / i;
      elseif ( i - j == 0 )
        a(i,j) = - ( 2 * i + 3 );
      elseif ( i - j == -1 )
        a(i,j) = j;
      else
        a(i,j) = 0.0;
      end

    end
  end

  return
end


function ell = inertiaEllipse(points)
%INERTIAELLIPSE Inertia ellipse of a set of points
%
%   ELL = inertiaEllipse(PTS);
%   where PTS is a N*2 array containing coordinates of N points, computes
%   the inertia ellispe of the set of points.
%
%   The result has the form:
%   ELL = [XC YC A B THETA],
%   with XC and YC being the center of mass of the point set, A and B are
%   the lengths of the inertia ellipse (see below), and THETA is the angle
%   of the main inertia axis with the horizontal (counted in degrees
%   between 0 and 180).
%   A and B are the standard deviations of the point coordinates when
%   ellipse is aligned with the inertia axes.
%
%   Example
%   pts = randn(100, 2);
%   pts = transformPoint(pts, createScaling(5, 2));
%   pts = transformPoint(pts, createRotation(pi/6));
%   pts = transformPoint(pts, createTranslation(3, 4));
%   ell = inertiaEllipse(pts);
%   figure(1); clf; hold on;
%   drawPoint(pts);
%   drawEllipse(ell, 'linewidth', 2, 'color', 'r');
%
%   See also
%   ellipses2d, drawEllipse
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2008-02-21,    using Matlab 7.4.0.287 (R2007a)
% Copyright 2008 INRA - BIA PV Nantes - MIAJ Jouy-en-Josas.

% HISTORY
% 2009-07-29 take into account ellipse orientation
% 2011-03-12 rewrite using inertia moments

% ellipse center
xc = mean(points(:,1));
yc = mean(points(:,2));

% recenter points
x = points(:,1) - xc;
y = points(:,2) - yc;

% number of points
n = size(points, 1);

% inertia parameters
Ixx = sum(x.^2) / n;
Iyy = sum(y.^2) / n;
Ixy = sum(x.*y) / n;

% compute ellipse semi-axis lengths
common = sqrt( (Ixx - Iyy)^2 + 4 * Ixy^2);
ra = sqrt(2) * sqrt(Ixx + Iyy + common);
rb = sqrt(2) * sqrt(Ixx + Iyy - common);

% compute ellipse angle in degrees
theta = atan2(2 * Ixy, Ixx - Iyy) / 2;
theta = rad2deg(theta);

% create the resulting inertia ellipse
ell = [xc yc ra rb theta];


function value = i4_gcd ( i, j )

%*****************************************************************************80
%
%% I4_GCD finds the greatest common divisor of I and J.
%
%  Discussion:
%
%    Only the absolute values of I and J are
%    considered, so that the result is always nonnegative.
%
%    If I or J is 0, I4_GCD is returned as max ( 1, abs ( I ), abs ( J ) ).
%
%    If I and J have no common factor, I4_GCD is returned as 1.
%
%    Otherwise, using the Euclidean algorithm, I4_GCD is the
%    largest common factor of I and J.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I, J, two numbers whose greatest common divisor
%    is desired.
%
%    Output, integer VALUE, the greatest common divisor of I and J.
%
  value = 1;
%
%  Return immediately if either I or J is zero.
%
  if ( i == 0 )
    value = max ( 1, abs ( j ) );
    return
  elseif ( j == 0 )
    value = max ( 1, abs ( i ) );
    return
  end
%
%  Set IP to the larger of I and J, IQ to the smaller.
%  This way, we can alter IP and IQ as we go.
%
  ip = max ( abs ( i ), abs ( j ) );
  iq = min ( abs ( i ), abs ( j ) );
%
%  Carry out the Euclidean algorithm.
%
  while ( 1 )

    ir = mod ( ip, iq );

    if ( ir == 0 )
      break;
    end

    ip = iq;
    iq = ir;

  end

  value = iq;

  return
end


function a = cheby_van2 ( n )

%*****************************************************************************80
%
%% CHEBY_VAN2 returns the CHEBY_VAN2 matrix.
%
%  Discussion:
%
%    CHEBY_VAN2 is the Chebyshev Vandermonde-like matrix.
%
%    The formula for this matrix has been slightly modified, by a scaling
%    factor, in order to make it closer to its inverse.
%
%  Formula:
%
%    A(I,J) = ( 1 / sqrt ( N - 1 ) ) * cos ( (I-1) * (J-1) * PI / (N-1) )
%
%  Example:
%
%    N = 4
%
%                 1      1           1           1
%    1/sqrt(3) *  1  COS(PI/3)   COS(2*PI/3) COS(3*PI/3)
%                 1  COS(2*PI/3) COS(4*PI/3) COS(6*PI/3)
%                 1  COS(3*PI/3) COS(6*PI/3) COS(9*PI/3)
%
%  Properties:
%
%    A is symmetric: A' = A.
%
%    Because A is symmetric, it is normal.
%
%    Because A is normal, it is diagonalizable.
%
%    The entries of A are based on the extrema of the Chebyshev
%    polynomial T(n-1).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 September 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  if ( n == 1 )
    a(1,1) = 1.0;
    return
  end

  for i = 1 : n
    for j = 1 : n

      angle = ( ( i - 1 ) * ( j - 1 ) ) * pi / ( n - 1 );

      a(i,j) = cos ( angle );

    end
  end

  a(1:n,1:n) = a(1:n,1:n) / sqrt ( n - 1 );

  return
end


function f=dft(f,N,dim);
%DFT   Normalized Discrete Fourier Transform
%   Usage: f=dft(f);
%          f=dft(f,N,dim);
%
%   `dft` computes a normalized or unitary discrete Fourier transform. The
%   unitary discrete Fourier transform is computed by
%
%   ..                     L-1
%     c(k+1) = 1/sqrt(L) * sum f(l+1)*exp(-2*pi*i*k*l/L)
%                          l=0
%
%   .. math:: c\left(k+1\right)=\frac{1}{\sqrt{L}}\sum_{l=0}^{L-1}f\left(l+1\right)e^{-2\pi ikl/L}
%
%   for $k=0,\ldots,L-1$.
%
%   The output of `dft` is a scaled version of the output from `fft`. The
%   function takes exactly the same arguments as `fft`. See the help on `fft`
%   for a thorough description.
%
%   See also:  idft

%   AUTHOR: Peter L. Søndergaard, Jordy van Velthoven
%   TESTING: TEST_DFT
%   REFERENCE: REF_DFT

complainif_argnonotinrange(nargin,1,3,mfilename);

if nargin<3
  dim=[];
end;

if nargin<2
  N=[];
end;

[f,N,Ls,W,dim,permutedsize,order]=assert_sigreshape_pre(f,N,dim,'DFT');

% Force FFT along dimension 1, since we have permuted the dimensions
% manually
f=fft(f,N,1)/sqrt(N);

f=assert_sigreshape_post(f,dim,permutedsize,order);


function K = knGauss(X, Y, s)
% Gaussian (RBF) kernel K = exp(-|x-y|/(2s));
% Input:
%   X: d x nx data matrix
%   Y: d x ny data matrix
%   s: sigma of gaussian
% Ouput:
%   K: nx x ny kernel matrix
% Written by Mo Chen (sth4nth@gmail.com).
if nargin < 3
    s = 0.4;
end

if nargin < 2 || isempty(Y)
    K = ones(1,size(X,2));            % norm in kernel space
else
    D = bsxfun(@plus,dot(X,X,1)',dot(Y,Y,1))-2*(X'*Y);
    K = exp(D/(-2*s^2));
end


%MAIN_cannon.m
%
% This script is used to find the optimal initial state for the cannon
% example problem, as described below:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Cannon Example:
%
% Find the optimal initial velocity for a projectile such that the
% resulting trajectory passes through a desired target.
%
% States:
%   x = horizontal position
%   y = vertical position
%   dx = horizontal speed
%   dy = vertical speed
%   ddx = horizontal acceleration
%   ddy = vertical acceleration
%
% Parameters:
%   c = quadratic drag coefficient
%   T = final simulation time
%
% Boundary Conditions:
%   x(0) = 0;
%   y(0) = 0;
%   x(T) = xf;
%   y(T) = yf;
%
% Objective Function:
%   J = dx(0)^2 + dy(0)^2;
%
% Dynamics Constraint:
%   ddx = -c*dx*sqrt(dx.*dx + dy.*dy);
%   ddy = -c*dy*sqrt(dx.*dx + dy.*dy) - 1;
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc; clear;
%%%% Adjust the following parameters and see what happens.
%
% 1) The problem becomes trivial if the drag coefficient (c) is small, but
% numerically stiff if c is large (>0.4). Which methods can handle large
% values of c the best?
%
%
% 2) What do you think happens if you use more (or fewer) grid points?
%
% 3) What happens if you move the target away?
% Open:  TEST_cannonFeasibility.m   to see the answer.
%
% 4) For either large range or large damping, the problem becomes stiff. As
% a result, the integration methods (either implicit or explicit) start to
% fail near the beginning of the trajectory where the speed is very high.
% If you use a log spaced grid (rather than uniform), then all methods
% perform better.
%
% 5) You can speed up the optimizations by disabling diagnostics or making
% each animation shorter.
%

%Provide an initial guess for the solver
guess.initSpeed = 9.0;
guess.initAngle = (pi/180)*45;

% Set the target (assuming that the trajectory starts at x=0, y=0)
target.x = 6.0;
target.y = 0;

% Set up the parameters for the dynamics function:
param.dynamics.c = 0.4;  %Quadratic drag coefficient

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

%%% Set up the grid discretization for each method:
param.singleShooting.nGrid = 100;
param.multipleShooting.nSegment = 10;
param.multipleShooting.nSubStep = 5;
param.collocation.nSegment = 50;
param.gpops.nSegment = 10;

%%% Parameters for diagnostics (visualization only)
param.diagnostics.enable = true;   %Enable plotting and log iterations?
param.diagnostics.animationDuration = 5;  %(seconds) How long is the animation?
param.diagnostics.writeGif = true;   %Save animation to a gif?
param.diagnostics.gifPixelDim = [800,400];  %How big of a gif to make?
param.diagnostics.figNum.singleShooting = 10;
param.diagnostics.figNum.multipleShooting = 11;
param.diagnostics.figNum.collocation = 12;
param.diagnostics.figNum.gpops = 13;

% Use single shooting to find the solution:
soln.singleShooting = cannon_singleShooting(guess,target,param);

% Use multiple shooting to find the solution:
soln.multipleShooting = cannon_multipleShooting(guess,target,param);

% Use collocation to find the solution:
soln.collocation = cannon_collocation(guess,target,param);

% % Use GPOPS to solve the problem   (http://www.gpops2.com/)
% % - adaptive high-order collocation
% % - not included in Matlab. Must be purchased seperately.
% soln.gpops = cannon_gpops(guess,target,param);


function [ r, center ] = tetrahedron_circumsphere_3d ( tetra )

%*****************************************************************************80
%
%% TETRAHEDRON_CIRCUMSPHERE_3D computes the circumsphere of a tetrahedron in 3D.
%
%  Discussion:
%
%    The circumsphere, or circumscribed sphere, of a tetrahedron is the sphere that
%    passes through the four vertices.  The circumsphere is not necessarily
%    the smallest sphere that contains the tetrahedron.
%
%    Surprisingly, the diameter of the sphere can be found by solving
%    a 3 by 3 linear system.  This is because the vectors P2 - P1,
%    P3 - P1 and P4 - P1 are secants of the sphere, and each forms a
%    right triangle with the diameter through P1.  Hence, the dot product of
%    P2 - P1 with that diameter is equal to the square of the length
%    of P2 - P1, and similarly for P3 - P1 and P4 - P1.  This determines
%    the diameter vector originating at P1, and hence the radius and
%    center.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 August 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Adrian Bowyer and John Woodwark,
%    A Programmer's Geometry,
%    Butterworths, 1983.
%
%  Parameters:
%
%    Input, real TETRA(3,4) the tetrahedron vertices.
%
%    Output, real R, CENTER(3), the center of the
%    circumscribed sphere, and its radius.  If the linear system is
%    singular, then R = -1, CENTER(1:3) = 0.
%
  dim_num = 3;
  nrhs = 1;
%
%  Set up the linear system.
%
  a(1:dim_num,1:3) = ( tetra(1:dim_num,2:4) )';

  for j = 1 : dim_num
    a(1:dim_num,j) = a(1:dim_num,j) - tetra(j,1);
  end

  for i = 1 : dim_num
    a(i,4) = sum ( a(i,1:3).^2 );
  end
%
%  Solve the linear system.
%
  [ a, info ] = r8mat_solve ( dim_num, nrhs, a );
%
%  If the system was singular, return a consolation prize.
%
  if ( info ~= 0 )
    r = -1.0;
    center(1:dim_num) = 0.0;
    return
  end
%
%  Compute R, X, Y, Z.
%
  r = 0.5 * sqrt ( sum ( a(1:dim_num,dim_num+1).^2 ) );

  center(1:dim_num) = tetra(1:dim_num,1) + 0.5 * a(1:dim_num,dim_num+1);

  return
end


function [J, grad] = lrCostFunction(theta, X, y, lambda)
%LRCOSTFUNCTION Compute cost and gradient for logistic regression with
%regularization
%   J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using
%   theta as the parameter for regularized logistic regression and the
%   gradient of the cost w.r.t. to the parameters.

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta
%
% Hint: The computation of the cost function and gradients can be
%       efficiently vectorized. For example, consider the computation
%
%           sigmoid(X * theta)
%
%       Each row of the resulting matrix will contain the value of the
%       prediction for that example. You can make use of this to vectorize
%       the cost function and gradient computations.
%
% Hint: When computing the gradient of the regularized cost function,
%       there're many possible vectorized solutions, but one solution
%       looks like:
%           grad = (unregularized gradient for logistic regression)
%           temp = theta;
%           temp(1) = 0;   % because we don't add anything for j = 0
%           grad = grad + YOUR_CODE_HERE (using the temp variable)
%

n = length(theta);

% X.shape = [m, n], y.shape = [m, 1], theta.shape = [n, 1]
% y_pred = sigmoid(X*theta), y_pred.shape = [m, 1]
y_pred = sigmoid(X*theta);
J = -1.0 / m * sum( y.*log(y_pred) + (1-y).*log(1-y_pred) );
J = J + lambda / (2.0*m) * sum( theta(2:n, 1).^2 );  % ignore theta(1)
grad = 1.0 / m .* (X' * (y_pred - y));
grad(2:n, 1) = grad(2:n, 1) + lambda / m * theta(2:n, 1);   % ignore theta(1)

% =============================================================

grad = grad(:);

end


function [ n_data, m, n, fmn ] = i4_rise_values ( n_data )

%*****************************************************************************80
%
%% I4_RISE_VALUES returns values of the integer rising factorial function.
%
%  Discussion:
%
%    The integer rising factorial function is sometimes symbolized by (m)_n.
%
%    The definition is
%
%      (m)_n = (m-1+n)! / (m-1)!
%            = ( m ) * ( m + 1 ) * ( m + 2 ) ... * ( m - 1 + n )
%            = Gamma ( m + n ) / Gamma ( m )
%
%    We assume 0 <= N <= M.
%
%    In Mathematica, the function can be evaluated by:
%
%      Pochhammer[m,n]
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 December 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%    Stephen Wolfram,
%    The Mathematica Book,
%    Fourth Edition,
%    Wolfram Media / Cambridge University Press, 1999.
%
%  Parameters:
%
%    Input/output, integer N_DATA.  The user sets N_DATA to 0 before the
%    first call.  On each call, the routine increments N_DATA by 1, and
%    returns the corresponding data; when there is no more data, the
%    output value of N_DATA will be 0 again.
%
%    Output, integer M, N, the arguments of the function.
%
%    Output, integer FMN, the value of the function.
%
  n_max = 8;

  fmn_vec = [ ...
     1, 5, 30, 210, 1680, ...
     15120, 151200, 1, 10, 4000, ...
     110, 6840, 840, 970200, 5040 ];

  m_vec = [ ...
    5, 5, 5, 5, 5, ...
    5, 5, 50, 10, 4000, ...
    10, 18, 4, 98, 1 ];

  n_vec = [ ...
    0, 1, 2, 3, 4, ...
    5, 6, 0, 1, 1, ...
    2, 3, 4, 3, 7 ];

  if ( n_data < 0 )
    n_data = 0;
  end

  n_data = n_data + 1;

  if ( n_max < n_data )
    n_data = 0;
    m = 0;
    n = 0;
    fmn = 0;
  else
    m = m_vec(n_data);
    n = n_vec(n_data);
    fmn = fmn_vec(n_data);
  end

  return
end


function Z = projectData(X, U, K)
%PROJECTDATA Computes the reduced data representation when projecting only
%on to the top k eigenvectors
%   Z = projectData(X, U, K) computes the projection of
%   the normalized inputs X into the reduced dimensional space spanned by
%   the first K columns of U. It returns the projected examples in Z.
%

% You need to return the following variables correctly.
Z = zeros(size(X, 1), K);

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the projection of the data using only the top K
%               eigenvectors in U (first K columns).
%               For the i-th example X(i,:), the projection on to the k-th
%               eigenvector is given as follows:
%                    x = X(i, :)';
%                    projection_k = x' * U(:, k);
%

subsetU = U(:, 1:K);
Z = X * subsetU;

% =============================================================

end


%KF_LOOP  Performs the prediction and update steps of the Kalman filter
%         for a set of measurements.
%
% Syntax:
%   [MM,PP] = KF_LOOP(X,P,H,R,Y,A,Q)
%
% In:
%   X - Nx1 initial estimate for the state mean
%   P - NxN initial estimate for the state covariance
%   H - DxN measurement matrix
%   R - DxD measurement noise covariance
%   Y - DxM matrix containing all the measurements.
%   A - Transition matrix of the discrete model (optional, default identity)
%   Q - Process noise of the discrete model     (optional, default zero)
%
% Out:
%   MM - Filtered state mean sequence
%   PP - Filtered state covariance sequence
%
%  Description:
%    Calculates state estimates for a set measurements using the
%    Kalman filter. This function is for convience, as it basically consists
%    only of a space reservation for the estimates and of a for-loop which
%    calls the predict and update steps of the KF for each time step in
%    the measurements.
%
%  See also:
%    KF_PREDICT, KF_UPDATE

%  History:
%
%    12.2.2007 JH Initial version.
%
% Copyright (C) 2007 Jouni Hartikainen
%
% This software is distributed under the GNU General Public
% Licence (version 2 or later); please refer to the file
% Licence.txt, included with the software, for details.

function [MM,PP] = kf_loop(X,P,H,R,Y,A,Q)

  % Check the input parameters.
  if nargin < 5
     error('Too few arguments');
  end
  if nargin < 6
     A = [];
  end
  if nargin < 7
     Q = [];
  end

  % Apply the defaults
  if isempty(A)
    A = eye(size(X,1));
  end
  if isempty(Q)
    Q = zeros(size(X,1));
  end

  % Space for the estimates.
  MM = zeros(size(X,1), size(Y,2));
  PP = zeros(size(X,1), size(X,1), size(Y,2));

  % Filtering steps.
  for i = 1:size(Y,2)
     [X,P] = kf_predict(X,P,A,Q);
     [X,P] = kf_update(X,P,Y(:,i),H,R);
     MM(:,i) = X;
     PP(:,:,i) = P;
  end


function [P_intersect,distances] = lineIntersect3D(PA,PB)
% Find intersection point of lines in 3D space, in the least squares sense.
% PA :          Nx3-matrix containing starting point of N lines
% PB :          Nx3-matrix containing end point of N lines
% P_Intersect : Best intersection point of the N lines, in least squares sense.
% distances   : Distances from intersection point to the input lines
% Anders Eikenes, 2012

Si = PB - PA; %N lines described as vectors
ni = Si ./ (sqrt(sum(Si.^2,2))*ones(1,3)); %Normalize vectors
nx = ni(:,1); ny = ni(:,2); nz = ni(:,3);
SXX = sum(nx.^2-1);
SYY = sum(ny.^2-1);
SZZ = sum(nz.^2-1);
SXY = sum(nx.*ny);
SXZ = sum(nx.*nz);
SYZ = sum(ny.*nz);
S = [SXX SXY SXZ;SXY SYY SYZ;SXZ SYZ SZZ];
CX  = sum(PA(:,1).*(nx.^2-1) + PA(:,2).*(nx.*ny)  + PA(:,3).*(nx.*nz));
CY  = sum(PA(:,1).*(nx.*ny)  + PA(:,2).*(ny.^2-1) + PA(:,3).*(ny.*nz));
CZ  = sum(PA(:,1).*(nx.*nz)  + PA(:,2).*(ny.*nz)  + PA(:,3).*(nz.^2-1));
C   = [CX;CY;CZ];
P_intersect = (S\C)';

if nargout>1
    N = size(PA,1);
    distances=zeros(N,1);
    for i=1:N %This is faster:
        ui=(P_intersect-PA(i,:))*Si(i,:)'/(Si(i,:)*Si(i,:)');
        distances(i)=norm(P_intersect-PA(i,:)-ui*Si(i,:));
    end
    %for i=1:N %http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html:
    %    distances(i) = norm(cross(P_intersect-PA(i,:),P_intersect-PB(i,:))) / norm(Si(i,:));
    %end
end
end


function value = gud ( x )

%*****************************************************************************80
%
%% GUD evaluates the Gudermannian function.
%
%  Discussion:
%
%    The Gudermannian function relates the hyperbolic and trigonometric
%    functions.  For any argument X, there is a corresponding value
%    G so that
%
%      sinh(x) = tan(g).
%
%    The value G is called the Gudermannian of X.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument of the Gudermannian.
%
%    Output, real VALUE, the value of the Gudermannian.
%
  value = 2.0 * atan ( tanh ( 0.5 * x ) );

  return
end


function acv= autocov(x,maxlag)
%
% autocov computes the sample autocovariance of a time series x for lags
% from 0 to maxlag, returning a column vector of length maxlag+1.  x must
% be a column vector having length m not less than maxlag+1.  If no value
% is supplied for maxlag, the default is the minimum of m-1 and 100.
%
% Dr. Phillip M. Feldman
% Last update 21 June 2008
%
% Based on equations on p. 19 of "Introduction to Time Series and
% Forecasting" 2nd Edition by Brockwell and Davis.

% Section 1: Check input arguments and supply default value for maxlag
% if needed.

if nargin < 1, error('Missing input vector.'); end

[m n]= size(x);
if (n ~= 1)
   error('x must be a column vector.')
end
if (m <= maxlag)
   error('The length of the input vector x must be at least maxlag+1.');
end

if nargin < 2, maxlag= min(m-1,100); end

% Section 2: Compute autocovariance.

% Remove mean from x:
x= x - mean(x);

% For faster running time, we pre-allocate the output array:
acv= zeros(maxlag+1,1);

% Compute autocovariance:
for h= 0 : maxlag
   % Take matrix product of row vector and column vector to obtain a
   % scalar.  The row vector contains the first n-h elements of x; the
   % column vector contains the last n-h elements of x.
   acv(h+1)= x(1:m-h)' * x(1+h:m);
end

acv= acv / m;


function optimal = fibonacci(f,a,b,n)

% Program : fibonacci.m
%
% Purpose : find the optimal point of a given single
%           variable function within the given interval
%
% Author :  Aamir Alaud Din
% Date :    26.09.2013
%
% Inputs :  Four input arguments are required viz., function, initial and
%           final points of the interval, and function evaluation number n
%
% Syntax :  optimal = fibonacci(f,a,b)
%           where f is an inline function
%           e.g., f = inline('sin(x)','x');
%           a and b are initial and final points of the interval
%
% Example:  optimal = fibonacci(f,-3,5)
%
%           Fourth input argument is fibonacci number decided by the user.
%           Default fibonacci number is 11 which gives 10 iterations.
%           Number of iterations is one less then fibonacci number, i.e.,
%           number of iterations = fibonacci number - 1
%
% Syntax:   optimal = fibonacci(f,a,b,n)
%           f, a, and b are described above
%           n is the number of iterations decided by the user
% Example:  optimal = fibonacci(f,0,1,20)
%

if (nargin < 3)
    error('Too few input arguments');
    optimal = 'Fibonacci search is not possible with too few inputs';
    return;

elseif (nargin == 3)
    n = 11;
    fss = [1,1];
    for ii = 1:(n-1)
        fs = fss(end) + fss(end-1);
        fss = [fss,fs];
    end

    disp('Iteration          N          x1              x2             f(x1)           f(x2)');
    disp('=========        ===       ========        ========        =========       =========');
    Iter = 0;
    for jj = n:-1:2
        Iter = Iter + 1;
        L = b - a;
        x1 = a + ((fss(jj-1)/fss(jj+1))*L);
        x2 = b - ((fss(jj-1)/fss(jj+1))*L);
        if (f(x1) < f(x2))
            b = x2;
        elseif (f(x1) > f(x2))
            a = x1;
        elseif (f(x1) == f(x2))
            a = x1;
            b = x2 + 0.0001;
        end
        fprintf('%3d', Iter);
        fprintf('\t\t\t\t');
        fprintf('%4d', jj-1);
        fprintf('\t');
        fprintf('%11.4f', x1);
        fprintf('\t\t');
        fprintf('%11.4f', x2);
        fprintf('\t\t');
        fprintf('%12.4f', f(x1));
        fprintf('\t\t');
        fprintf('%12.4f', f(x2));
        fprintf('\n');
    end
    optimal = min(x1,x2);

elseif (nargin == 4)
    fss = [1,1];
    for ii = 1:(n-1)
        fs = fss(end) + fss(end-1);
        fss = [fss,fs];
    end

    disp('Iteration          N          x1              x2             f(x1)           f(x2)');
    disp('=========        ===       ========        ========        =========       =========');
    Iter = 0;
    for jj = n:-1:2
        Iter = Iter + 1;
        L = b - a;
        x1 = a + ((fss(jj-1)/fss(jj+1))*L);
        x2 = b - ((fss(jj-1)/fss(jj+1))*L);
        if (f(x1) < f(x2))
            b = x2;
        elseif (f(x1) > f(x2))
            a = x1;
        elseif (f(x1) == f(x2))
            a = x1;
            b = x2 + 0.0001;
        end
        fprintf('%3d', Iter);
        fprintf('\t\t\t\t');
        fprintf('%4d', jj-1);
        fprintf('\t');
        fprintf('%11.4f', x1);
        fprintf('\t\t');
        fprintf('%11.4f', x2);
        fprintf('\t\t');
        fprintf('%12.4f', f(x1));
        fprintf('\t\t');
        fprintf('%12.4f', f(x2));
        fprintf('\n');
    end
    optimal = min(x1,x2);

elseif (nargin > 4)
    error('Too many input arguments');
    optimal = 'Fibonacci search is not possible with too many inputs';
    return

end


function [U, S] = pca(X)
%PCA Run principal component analysis on the dataset X
%   [U, S, X] = pca(X) computes eigenvectors of the covariance matrix of X
%   Returns the eigenvectors U, the eigenvalues (on diagonal) in S
%

% Useful values
[m, n] = size(X);

% You need to return the following variables correctly.
U = zeros(n);
S = zeros(n);

% ====================== YOUR CODE HERE ======================
% Instructions: You should first compute the covariance matrix. Then, you
%               should use the "svd" function to compute the eigenvectors
%               and eigenvalues of the covariance matrix.
%
% Note: When computing the covariance matrix, remember to divide by m (the
%       number of examples).
%

Sigma = (X' * X) / m;  %'
[U, S, V] = svd(Sigma);

% =========================================================================

end


% book : Signals and Systems Laboratory with MATLAB
% authors : Alex Palamides & Anastasia Veloni
%
%
%
% time invariant or time variant

%time variant
t=-5:.001:10;
p=heaviside(t)-heaviside(t-5);
y=t.*exp(-t).*p;
plot(t,y)
ylim([-.05 .4]);
legend('y(t)')

figure
plot(t+3,y)
ylim([-.05 .4]);
legend('y(t-3)')

figure
t=-5:.001:10;
p=heaviside(t-3)-heaviside(t-8);
y2=t.*exp(-t).*p;
plot(t,y2)
ylim([-.01 .2]);
legend('S[x(t-3)]')

%time invariant
figure
t=-5:.01:20;
p=heaviside(t-1)-heaviside(t-11);
y=1-2*cos(t-1).*p;
plot(t,y)
legend('y(t)')

figure
p=heaviside(t)-heaviside(t-10);
x=cos(t).*p;
plot(t+1,1-2*x)
legend('y(t)')

figure
plot(t+4,y)
legend('y(t-4)')

figure
p=heaviside(t-4)-heaviside(t-14);
x=cos(t-4).*p;
plot(t,x)

figure
p=heaviside(t-4)-heaviside(t-14);
x=cos(t-4).*p;
plot(t+1,1-2*x)

figure
t=-5:.01:20;
p=heaviside(t-5)-heaviside(t-15);
y2=1-2*cos(t-5).*p ;
plot(t,y2) ;
legend('S[x(t-4)]')

%time variant
figure
t=-5:.1:10;
x=heaviside(t+2)-heaviside(t-2);
plot(t,x);
ylim([-.1 1.1]);

figure
plot((1/2)*t,x);
ylim([-.1 1.1]);

figure
plot((1/2)*t+2,x);
ylim([-.1 1.1]);
legend('y_1(t)')

figure
plot(t+2,x);
ylim([-.1 1.1]);
legend('x(t-2)')

figure
t=-5:.1:10;
x2=heaviside(t)-heaviside(t-4);
plot(t,x2);
ylim([-.1 1.1]);

figure
plot((1/2)*t,x2);
ylim([-.1 1.1]);
legend('y_2(t)')

%shift invariant
figure
n=0:5;
x=0.8.^n;
y=x.^2;
stem(n,y);
xlim([-.1 5.1])
legend('y[n]')

figure
stem(n+2,y)
legend('y[n-2]')
xlim([1.9 7.1])

figure
n=2:7;
y2=(0.8.^(n-2)).^2;
stem(n,y2);
xlim([1.9 7.1])
legend('S[x[n-2]]')


function K=commutationMatrix(m,n)
%%COMMUTATIONMATRIX Return a commutation matrix K for an mXn matrix. This
%          means that given an mXn matrix A that K*A(:)=B(:) where
%          B=transpose(A). As shown below, this matrix can also be used for
%          reversing the order of Kronecker products. As in [2], this
%          matrix is also known as a vec-permutation matrix.
%
%INPUTS: m,n The number of rows and the number of columns of the matrix
%            that is to be commutated by this commutation matrix.
%
%OUTPUTS: K An (m*n)X(m*n) commutation matrix.
%
%The matrix K is just a type of permutation matrix with 1's in the correct
%places.
%
%Properties of the commutation matrix are given in [1] and in [2]. For
%example, commutationMatrix(m,n)=commutationMatrix(n,m)' and also there is
%an inverse relation that
%commutationMatrix(m,n)*commutationMatrix(n,m)==eye(n*m) and
%Note that the Vec permutation matrix I_{m,n} as in [2] is actually
%commutationMatrix(n,m).
%
%EXAMPLE 1:
%Here, we demonstrate the property that the vec-permutation matrix
%(commutation matrix) allows one to get vec(A') from vec(A):
% m=12;
% n=17;
% A=randn(m,n);
% Imn=commutationMatrix(n,m);%The vec-permutation matrix as in [2].
% all(vec(A)==Imn*vec(A'))
%The result will be true, showing that
%vec(A)==commutationMatrix(n,m)*vec(A')
%which agrees with the identity given in the abstract to [2].
%
%EXAMPLE 2:
%Here, we give a demonstration of how to reverse the ordering of a
%Kronecker product of two matrices:
% m=12;
% n=17;
% A=randn(m,n);
% p=4;
% q=6;
% B=randn(p,q);
% Imp=commutationMatrix(p,m);
% Iqn=commutationMatrix(n,q);
% %Reversing the order of the matrix Kronecker product as in Equation 25 in
% %[2].
% all(vec(kron(B,A)==Imp*kron(A,B)*Iqn))
%The result will be true, showing that one can use two commutation matrices
%to reverse the ordering of Kronecker products of matrices.
%
%EXAMPLE 3:
%Now, we demonstrate that one can use a single commutation matrix (vec-
%permutation matrix) to reverse the order of the Kronecker product of two
%vectors.
% m=13;
% n=7;
% a=randn(m,1);
% b=randn(n,1);
% Imat=commutationMatrix(m,n);
% all(vec(kron(a,b)==Imat*kron(b,a)))
%The result will be true.
%
%REFERENCES:
%[1] J. R. Magnus and H. Neudecker, "The elimination matrix: Some lemmas
%    and applications," SIAM Journal on Algebraic Discrete Methods, vol. 1,
%    no. 4, pp. 422-449, 1980.
%[2] H. V. Henderson and S. R. Searle, "The vec-permutation matrix, the vec
%    operator and Kronecker products: A review," Linear and Multilinear
%    Algebra, vol. 9, no. 4, pp. 271-288, 1981.
%
%December 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

K=zeros(m*n,m*n);

idx=0;
col=0;

for i=1:n
    idx=idx+1;
    row=idx;

    for j=1:m
        col=col+1;
        K(row,col)=1;
        row=row+n;
    end
end

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 pcof = r8poly_lagrange_coef ( npol, ipol, xpol )

%*****************************************************************************80
%
%% R8POLY_LAGRANGE_COEF returns the coefficients of a Lagrange polynomial.
%
%  Discussion:
%
%    Given distinct abscissas XPOL(1:NPOL), the IPOL-th Lagrange
%    polynomial L(IPOL)(X) is defined as the polynomial of degree
%    NPOL - 1 which is 1 at XPOL(IPOL) and 0 at the NPOL - 1 other
%    abscissas.
%
%    A formal representation is:
%
%      L(IPOL)(X) = Product ( 1 <= I <= NPOL, I /= IPOL )
%       ( X - X(I) ) / ( X(IPOL) - X(I) )
%
%    However sometimes it is desirable to be able to write down
%    the standard polynomial coefficients of L(IPOL)(X).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 October 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NPOL, the number of abscissas.
%    NPOL must be at least 1.
%
%    Input, integer IPOL, the index of the polynomial to evaluate.
%    IPOL must be between 1 and NPOL.
%
%    Input, real XPOL(NPOL), the abscissas of the
%    Lagrange polynomials.  The entries in XPOL must be distinct.
%
%    Output, real PCOF(1:NPOL), the standard polynomial
%    coefficients of the IPOL-th Lagrange polynomial:
%      L(IPOL)(X) = SUM ( 0 <= I <= NPOL-1 ) PCOF(I+1) * X**I
%

%
%  Make sure IPOL is legal.
%
  if ( ipol < 1 || npol < ipol )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8POLY_LAGRANGE_COEF - Fatal error!\n' );
    fprintf ( 1, '  1 <= IPOL <= NPOL is required.\n' );
    error ( 'R8POLY_LAGRANGE_COEF - Fatal error!' );
  end
%
%  Check that the abscissas are distinct.
%
  if ( ~r8vec_distinct ( npol, xpol ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8POLY_LAGRANGE_COEF - Fatal error!\n' );
    fprintf ( 1, '  Two or more entries of XPOL are equal:\n' );
    error ( 'R8POLY_LAGRANGE_COEF - Fatal error!' );
  end

  pcof(1) = 1.0;
  pcof(2:npol) = 0.0;

  indx = 0;

  for i = 1 : npol

    if ( i ~= ipol )

      indx = indx + 1;

      for j = indx : -1 : 0

        pcof(j+1) = -xpol(i) * pcof(j+1) / ( xpol(ipol) - xpol(i) );

        if ( 0 < j )
          pcof(j+1) = pcof(j+1) + pcof(j) / ( xpol(ipol) - xpol(i) );
        end

      end

    end

  end

  return
end


function matrixData=ivech(stackedData)
% Transform a vector in to a symmetric matrix for use in covariance applications
%
% USAGE:
%   MATRIXDATA = ivech(STACKEDDATA)
%
% INPUTS:
%   STACKEDDATA:   A K(K+1)/2 vector of data to be transformed
%
% OUTPUTS:
%   MATRIXDATA   - a K by K symmetric matrix of the form
%                  [ data(1) data(2)    data(3)     ...               data(K)
%                    data(2) data(K+1)  data(K+2)   ...               ...
%                    data(3) data(K+2)  data(2K)    ...               ...
%                    ...     ....       ...         ...               data(K(K+1)/2-1)
%                    data(K) data(2K-1) ...         data(K(K+1)/2-1)  data(K(K+1)/2) ]
%
% COMMENTS:
%
% See also VECH

% Author: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 3    Date: 2/1/2008

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if size(stackedData,2)>size(stackedData,1)
    stackedData=stackedData';
end

if size(stackedData,2)~=1
    error('STACKED_DATA must be a column vector.')
end

K2=size(stackedData,1);
K=(-1+sqrt(1+8*K2))/2;

if floor(K)~=K
    error(['The number of elemeents in STACKED_DATA must be conformable to' ...
    'the inverse vech operation.'])
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Initialize the output data
matrixData=zeros(K);

% Use a logical trick to inverse the vech
pl=tril(true(K));
matrixData(pl)=stackedData;
diag_matrixData=diag(diag(matrixData));
matrixData=matrixData+matrixData'-diag_matrixData;


function [a, tri] = trifacet_signed_area(tri, x)
% TRIFACET_SIGNED_AREA  Signed area of the facets in a 2D triangulation.
%
% A = trifacet_signed_area(TRI, X)
%
%   TRI is a 3-column matrix. Each row contains the 3 nodes that form one
%   triangular facet in the mesh.
%
%   X is a 2-column matrix. X(i, :) contains the xy-coordinates of the
%   i-th node in the mesh.
%
%   A is a vector where A(i) is the signed area of the i-th triangle.
%   Positive areas correspond to counter-clockwise triangles, and negative
%   areas, to clockwise triangles.
%
% [..., TRI2] = trifacet_signed_area(...)
%
%   TRI2 returns TRI reoriented when necessary so that all triangles have
%   a positive signed area.

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2013 University of Oxford
% Version: 0.2.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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 3 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. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see
% <http://www.gnu.org/licenses/>.

% check arguments
narginchk(2, 2);
nargoutchk(0, 2);

if (size(tri, 2) ~= 3)
    error('TRI must have 3 columns')
end
if (size(x, 2) ~= 2)
    error('X must have 2 columns')
end

% signed area of a triangle with vertices  V1, V2, V3 in counter-clockwise
% orientation
%
% a = 1/2*((x2-x1)(y3-y1) - (x3-x1)(y2-y1))

x2x1 = x(tri(:, 2), 1) - x(tri(:, 1), 1);
y3y1 = x(tri(:, 3), 2) - x(tri(:, 1), 2);
x3x1 = x(tri(:, 3), 1) - x(tri(:, 1), 1);
y2y1 = x(tri(:, 2), 2) - x(tri(:, 1), 2);

a = 0.5 * (x2x1 .* y3y1 - x3x1 .* y2y1);

% reorient negative area triangles
if (nargout > 1)

    % triangles with negative area
    idx = a < 0;

    % reorient triangles with negative area so that they become positive
    tri(idx, 1:2) = tri(idx, [2 1]);

end


function c = cardinal_cos ( j, m, t )

%*****************************************************************************80
%
%% CARDINAL_COS evaluates the J-th cardinal cosine basis function.
%
%  Discussion:
%
%    The base points are T(I) = pi * I / ( M + 1 ), 0 <= I <= M + 1.
%    Basis function J is 1 at T(J), and 0 at T(I) for I /= J
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 May 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    John Boyd,
%    Exponentially convergent Fourier-Chebyshev quadrature schemes on
%    bounded and infinite intervals,
%    Journal of Scientific Computing,
%    Volume 2, Number 2, 1987, pages 99-109.
%
%  Parameters:
%
%    Input, integer J, the index of the basis function.
%    0 <= J <= M + 1.
%
%    Input, integer M, indicates the size of the basis set.
%
%    Input, real T(*), one or more points in [0,pi] where the
%    basis function is to be evaluated.
%
%    Output, real C, the value of the function at T.
%
  if ( j == 0 || j == m + 1 )
    cj = 2.0;
  else
    cj = 1.0;
  end

  tj = pi * j / ( m + 1 );

  c = ( -1.0 ) ^ mod ( j + 1, 2 ) ...
    * sin ( t ) ...
    .* sin ( ( m + 1 ) * t ) ...
    / cj ...
    / ( m + 1 ) ...
    ./ ( cos ( t ) - cos ( tj ) );

  i = find ( abs ( t - tj ) < eps );
  c(i) = 1.0;

  return
end


function [x,y] = km_kde(data,sigma,nsteps,range_x)
% KM_KDE performs kernel density estimation (KDE) on one-dimensional data
% http://en.wikipedia.org/wiki/Kernel_density_estimation
%
% Input:	- data: input data, one-dimensional
%           - sigma: bandwidth (sometimes called "h")
%           - nsteps: optional number of abscis points. If nsteps is an
%             array, the abscis points will be taken directly from it.
%           - range_x: optional factor for abscis expansion beyond extrema
% Output:	- x: equispaced abscis points
%			- y: estimates of p(x)
% USAGE: [xx,pp] = km_kde(data,sigma,nsteps,range_x)
%
% Author: Steven Van Vaerenbergh (steven *at* gtas.dicom.unican.es), 2010.
%
% This file is part of the Kernel Methods Toolbox for MATLAB.
% https://github.com/steven2358/kmbox

N = length(data);	% number of data points

if (nargin<4), range_x = 1; end % default abscis expansion
if (nargin<3), nsteps = 100; end % default number of abscis points

% obtain full data range + extra bit
mm(1) = min(data);
mm(2) = max(data);
if length(nsteps) > 1
    x = nsteps;
else
    xm = range_x*mm;
    if (mm(1)>0), xm(1)=mm(1)/range_x; end
    if (mm(2)<0), xm(2)=mm(2)/range_x; end
    x = linspace(xm(1),xm(2),nsteps);
end
y = zeros(size(x));

% kernel density estimation
c = 1/sqrt(2*pi*sigma^2);
for i=1:N,
	y = y + 1/N*c*exp(-(data(i)-x).^2/(2*sigma^2));
end


function value = hermite_integral ( n )

%*****************************************************************************80
%
%% HERMITE_INTEGRAL returns the value of a Hermite polynomial integral.
%
%  Discussion:
%
%    H(n) = Integral ( -oo < x < +oo ) x^n exp(-x^2) dx
%
%    H(n) is 0 for n odd.
%
%    H(n) = (n-1)!! * sqrt(pi) / 2^(n/2) for n even.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 July 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the integral.
%    0 <= N.
%
%    Output, real VALUE, the value of the integral.
%
  if ( n < 0 )

    value = - r8_huge ( );

  elseif ( mod ( n, 2 ) == 1 )

    value = 0.0;

  else

    value = i4_factorial2 ( n - 1 ) * sqrt ( pi ) / 2.0^( n / 2 );

  end

  return
end


function pdf = hypergeometric_pdf ( x, n, m, l )

%*****************************************************************************80
%
%% HYPERGEOMETRIC_PDF evaluates the Hypergeometric PDF.
%
%  Discussion:
%
%    PDF(X)(N,M,L) = C(M,X) * C(L-M,N-X) / C(L,N).
%
%    PDF(X)(N,M,L) is the probability of drawing X white balls in a
%    single random sample of size N from a population containing
%    M white balls and a total of L balls.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer X, the desired number of white balls.
%    0 <= X <= N, usually, although any value of X can be given.
%
%    Input, integer N, the number of balls selected.
%    0 <= N <= L.
%
%    Input, integer M, the number of white balls in the population.
%    0 <= M <= L.
%
%    Input, integer L, the number of balls to select from.
%    0 <= L.
%
%    Output, real PDF, the probability of exactly K white balls.
%

%
%  Special cases.
%
  if ( x < 0 )

    pdf = 1.0;

  elseif ( n < x )

    pdf = 0.0;

  elseif ( m < x )

    pdf = 0.0;

  elseif ( l < x )

    pdf = 0.0;

  elseif ( n == 0 )

    if ( x == 0 )
      pdf = 1.0;
    else
      pdf = 0.0;
    end

  else

    c1 = binomial_coef_log (   m,   x );
    c2 = binomial_coef_log ( l-m, n-x );
    c3 = binomial_coef_log ( l,   n   );

    pdf_log = c1 + c2 - c3;

    pdf = exp ( pdf_log );

  end

  return
end


function d = dcircle ( p, xc, yc, r )

%*****************************************************************************80
%
%% DCIRCLE returns the signed distance of one or more points to a circle.
%
%  Discussion:
%
%    The corresponding routine in 3D is DSPHERE.
%
%  Licensing:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input, real P(NP,2), the point coordinates.
%
%    Input, real XC, YC, the coordinates of the center of the circle.
%
%    Input, real R, the radius of the circle.
%
%    Output, real D(NP), the signed distance of each point to the
%    circle.  The point is inside, on, or outside the circle depending
%    on whether D is negative, zero, or positive.
%
  d = sqrt ( ( p(:,1) - xc ).^2 + ( p(:,2) - yc ).^2 ) - r;

  return
end


function [A,d]=affineTransBetweenTriangles(v1,v2)
%%AFFINETRANSBETWEENTRIANGLES Given the vertices of one triangle in 2D and
%       the vertices of a second triangle in 2D, obtain a matrix M and a
%       vector d such that p2=M*p1+d transforms a point p1 in the first
%       triangle into a point p2 in the second triangle.
%
%INPUTS: v1 The 2X3 set of vertices in the first triangle.
%        v2 The 2X3 set of vertices in the second triangle (into which we
%           wish to transform the first triangle).
%
%OUTPUTS: A A 2X2 scale/rotation matrix.
%         d A 2X1 origin shift vector.
%
%Equations for the transformation are given in Chapter 5 of [1].
%
%EXAMPLE:
%This just find the transformation between two sets of vertices and
%transforms the first set of vertices into the second set. The error is on
%the order of typical finite precision limitations.
% v1=[ 5, -22,   3;
%     18,   8, -13];
% v2=[-4, 35, -13;
%      3, 27,  30];
% [A,d]=affineTransBetweenTriangles(v1,v2);
% v2Trans=bsxfun(@plus,A*v1,d);
% RelErr=max(abs((v2Trans-v2)./v2))
%
%REFERENCES:
%[1] K. Anjyo and H. Ochiai, Mathematical Basics of Motion and Deformation
%    in Computer Graphics, 2nd ed. Morgan and Claypool Publishers, 2017.
%
%October 2022 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

A1=[v1;
   1,1,1];
A2=[v2;
   1,1,1];

M=A2/A1;

A=M(1:2,1:2);
d=M(1:2,3);

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 [mu sigma2] = estimateGaussian(X)
%ESTIMATEGAUSSIAN This function estimates the parameters of a
%Gaussian distribution using the data in X
%   [mu sigma2] = estimateGaussian(X),
%   The input X is the dataset with each n-dimensional data point in one row
%   The output is an n-dimensional vector mu, the mean of the data set
%   and the variances sigma^2, an n x 1 vector
%

% Useful variables
[m, n] = size(X);

% You should return these values correctly
mu = zeros(n, 1);
sigma2 = zeros(n, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the mean of the data and the variances
%               In particular, mu(i) should contain the mean of
%               the data for the i-th feature and sigma2(i)
%               should contain variance of the i-th feature.
%

mu = sum(X)./size(X,1);
murep = repmat(mu, [size(X,1) 1]);
sigma2 = sum((X-murep).^2)/size(X,1);

% =============================================================

end


%% Principal Component Analysis and Partial Least Squares
% Principal Component Analysis (PCA) and Partial Least Squares (PLS) are
% widely used tools. This code is to show their relationship through the
% Nonlinear Iterative PArtial Least Squares (NIPALS) algorithm.

%% The Eigenvalue and Power Method
% The NIPALS algorithm can be derived from the Power method to solve the
% eigenvalue problem. Let x be the eigenvector of a square matrix, A,
% corresponding to the eignvalue s:
%
% $$Ax=sx$$
%
% Modifying both sides by A iteratively leads to
%
% $$A^kx=s^kx$$
%
% Now, consider another vectro y, which can be represented as a linear
% combination of all eigenvectors:
%
% $$y=\sum_i^n b_ix_i=Xb$$
%
% where
%
% $$X=\left[x_1\,\,\, \cdots\,\,\, x_n \right]$$
%
% and
%
% $$b = \left[b_1\,\,\, \cdots\,\,\, b_n \right]^T$$
%
% Modifying y by A gives
%
% $$Ay=AXb=XSb$$
%
% Where S is a diagnal matrix consisting all eigenvalues. Therefore, for
% a large enough k,
%
% $$A^ky=XS^kb\approx \alpha x_1$$
%
% That is the iteration will converge to the direction of x_1, which is the
% eigenvector corresponding to the eigenvalue with the maximum module.
% This leads to the following Power method to solve the eigenvalue problem.

A=randn(10,5);
% sysmetric matrix to ensure real eigenvalues
B=A'*A;
%find the column which has the maximum norm
[dum,idx]=max(sum(A.*A));
x=A(:,idx);
%storage to judge convergence
x0=x-x;
%convergence tolerant
tol=1e-6;
%iteration if not converged
while norm(x-x0)>tol
    %iteration to approach the eigenvector direction
    y=A'*x;
    %normalize the vector
    y=y/norm(y);
    %save previous x
    x0=x;
    %x is a product of eigenvalue and eigenvector
    x=A*y;
end
% the largest eigen value corresponding eigenvector is y
s=x'*x;
% compare it with those obtained with eig
[V,D]=eig(B);
[d,idx]=max(diag(D));
v=V(:,idx);
disp(d-s)
% v and y may be different in signs
disp(min(norm(v-y),norm(v+y)))

%% The NIPALS Algorithm for PCA
% The PCA is a dimension reduction technique, which is based on the
% following decomposition:
%
% $$X=TP^T+E$$
%
% Where X is the data matrix (m x n) to be analysed, T is the so called
% score matrix (m x a), P the loading matrix (n x a) and E the residual.
% For a given tolerance of residual, the number of principal components, a,
% can be much smaller than the orginal variable dimension, n.
% The above power algorithm can be extended to get T and P by iteratively
% subtracting A (in this case, X) by x*y' (in this case, t*p') until the
% given tolerance satisfied. This is the so called NIPALS algorithm.

% The data matrix with normalization
A=randn(10,5);
meanx=mean(A);
stdx=std(A);
X=(A-meanx(ones(10,1),:))./stdx(ones(10,1),:);
B=X'*X;
% allocate T and P
T=zeros(10,5);
P=zeros(5);
% tol for convergence
tol=1e-6;
% tol for PC of 95 percent
tol2=(1-0.95)*5*(10-1);
for k=1:5
    %find the column which has the maximum norm
    [dum,idx]=max(sum(X.*X));
    t=A(:,idx);
    %storage to judge convergence
    t0=t-t;
    %iteration if not converged
    while norm(t-t0)>tol
        %iteration to approach the eigenvector direction
        p=X'*t;
        %normalize the vector
        p=p/norm(p);
        %save previous t
        t0=t;
        %t is a product of eigenvalue and eigenvector
        t=X*p;
    end
    %subtracing PC identified
    X=X-t*p';
    T(:,k)=t;
    P(:,k)=p;
    if norm(X)<tol2
        break
    end
end
T(:,k+1:5)=[];
P(:,k+1:5)=[];
S=diag(T'*T);
% compare it with those obtained with eig
[V,D]=eig(B);
[D,idx]=sort(diag(D),'descend');
D=D(1:k);
V=V(:,idx(1:k));
fprintf('The number of PC: %i\n',k);
fprintf('norm of score difference between EIG and NIPALS: %g\n',norm(D-S));
fprintf('norm of loading difference between EIG and NIPALS: %g\n',norm(abs(V)-abs(P)));

%% The NIPALS Algorithm for PLS
% For PLS, we will have two sets of data: the independent X and dependent
% Y. The NIPALS algorithm can be used to decomposes both X and Y so that
%
% $$X=TP^T+E,\,\,\,\,Y=UQ^T+F,\,\,\,\,U=TB$$
%
% The regression, U=TB is solved through least sequares whilst the
% decompsition may not include all components. That is why the approach is
% called partial least squares. This algorithm is implemented in the PLS
% function.

%% Example: Discriminant PLS using the NIPALS Algorithm
% From Chiang, Y.Q., Zhuang, Y.M and Yang, J.Y, "Optimal Fisher
% discriminant analysis using the rank decomposition", Pattern Recognition,
% 25 (1992), 101--111.

% Three classes data, each has 50 samples and 4 variables.
x1=[5.1 3.5 1.4 0.2; 4.9 3.0 1.4 0.2; 4.7 3.2 1.3 0.2; 4.6 3.1 1.5 0.2;...
    5.0 3.6 1.4 0.2; 5.4 3.9 1.7 0.4; 4.6 3.4 1.4 0.3; 5.0 3.4 1.5 0.2; ...
    4.4 2.9 1.4 0.2; 4.9 3.1 1.5 0.1; 5.4 3.7 1.5 0.2; 4.8 3.4 1.6 0.2; ...
    4.8 3.0 1.4 0.1; 4.3 3.0 1.1 0.1; 5.8 4.0 1.2 0.2; 5.7 4.4 1.5 0.4; ...
    5.4 3.9 1.3 0.4; 5.1 3.5 1.4 0.3; 5.7 3.8 1.7 0.3; 5.1 3.8 1.5 0.3; ...
    5.4 3.4 1.7 0.2; 5.1 3.7 1.5 0.4; 4.6 3.6 1.0 0.2; 5.1 3.3 1.7 0.5; ...
    4.8 3.4 1.9 0.2; 5.0 3.0 1.6 0.2; 5.0 3.4 1.6 0.4; 5.2 3.5 1.5 0.2; ...
    5.2 3.4 1.4 0.2; 4.7 3.2 1.6 0.2; 4.8 3.1 1.6 0.2; 5.4 3.4 1.5 0.4; ...
    5.2 4.1 1.5 0.1; 5.5 4.2 1.4 0.2; 4.9 3.1 1.5 0.2; 5.0 3.2 1.2 0.2; ...
    5.5 3.5 1.3 0.2; 4.9 3.6 1.4 0.1; 4.4 3.0 1.3 0.2; 5.1 3.4 1.5 0.2; ...
    5.0 3.5 1.3 0.3; 4.5 2.3 1.3 0.3; 4.4 3.2 1.3 0.2; 5.0 3.5 1.6 0.6; ...
    5.1 3.8 1.9 0.4; 4.8 3.0 1.4 0.3; 5.1 3.8 1.6 0.2; 4.6 3.2 1.4 0.2; ...
    5.3 3.7 1.5 0.2; 5.0 3.3 1.4 0.2];
x2=[7.0 3.2 4.7 1.4; 6.4 3.2 4.5 1.5; 6.9 3.1 4.9 1.5; 5.5 2.3 4.0 1.3; ...
    6.5 2.8 4.6 1.5; 5.7 2.8 4.5 1.3; 6.3 3.3 4.7 1.6; 4.9 2.4 3.3 1.0; ...
    6.6 2.9 4.6 1.3; 5.2 2.7 3.9 1.4; 5.0 2.0 3.5 1.0; 5.9 3.0 4.2 1.5; ...
    6.0 2.2 4.0 1.0; 6.1 2.9 4.7 1.4; 5.6 2.9 3.9 1.3; 6.7 3.1 4.4 1.4; ...
    5.6 3.0 4.5 1.5; 5.8 2.7 4.1 1.0; 6.2 2.2 4.5 1.5; 5.6 2.5 3.9 1.1; ...
    5.9 3.2 4.8 1.8; 6.1 2.8 4.0 1.3; 6.3 2.5 4.9 1.5; 6.1 2.8 4.7 1.2; ...
    6.4 2.9 4.3 1.3; 6.6 3.0 4.4 1.4; 6.8 2.8 4.8 1.4; 6.7 3.0 5.0 1.7; ...
    6.0 2.9 4.5 1.5; 5.7 2.6 3.5 1.0; 5.5 2.4 3.8 1.1; 5.5 2.4 3.7 1.0; ...
    5.8 2.7 3.9 1.2; 6.0 2.7 5.1 1.6; 5.4 3.0 4.5 1.5; 6.0 3.4 4.5 1.6; ...
    6.7 3.1 4.7 1.5; 6.3 2.3 4.4 1.3; 5.6 3.0 4.1 1.3; 5.5 2.5 5.0 1.3; ...
    5.5 2.6 4.4 1.2; 6.1 3.0 4.6 1.4; 5.8 2.6 4.0 1.2; 5.0 2.3 3.3 1.0; ...
    5.6 2.7 4.2 1.3; 5.7 3.0 4.2 1.2; 5.7 2.9 4.2 1.3; 6.2 2.9 4.3 1.3; ...
    5.1 2.5 3.0 1.1; 5.7 2.8 4.1 1.3];
x3=[6.3 3.3 6.0 2.5; 5.8 2.7 5.1 1.9; 7.1 3.0 5.9 2.1; 6.3 2.9 5.6 1.8; ...
    6.5 3.0 5.8 2.2; 7.6 3.0 6.6 2.1; 4.9 2.5 4.5 1.7; 7.3 2.9 6.3 1.8; ...
    6.7 2.5 5.8 1.8; 7.2 3.6 6.1 2.5; 6.5 3.2 5.1 2.0; 6.4 2.7 5.3 1.9; ...
    6.8 3.0 5.5 2.1; 5.7 2.5 5.0 2.0; 5.8 2.8 5.1 2.4; 6.4 3.2 5.3 2.3; ...
    6.5 3.0 5.5 1.8; 7.7 3.8 6.7 2.2; 7.7 2.6 6.9 2.3; 6.0 2.2 5.0 1.5; ...
    6.9 3.2 5.7 2.3; 5.6 2.8 4.9 2.0; 7.7 2.8 6.7 2.0; 6.3 2.7 4.9 1.8; ...
    6.7 3.3 5.7 2.1; 7.2 3.2 6.0 1.8; 6.2 2.8 4.8 1.8; 6.1 3.0 4.9 1.8; ...
    6.4 2.8 5.6 2.1; 7.2 3.0 5.8 1.6; 7.4 2.8 6.1 1.9; 7.9 3.8 6.4 2.0; ...
    6.4 2.8 5.6 2.2; 6.3 2.8 5.1 1.5; 6.1 2.6 5.6 1.4; 7.7 3.0 6.1 2.3; ...
    6.3 3.4 5.6 2.4; 6.4 3.1 5.5 1.8; 6.0 3.0 4.8 1.8; 6.9 3.1 5.4 2.1; ...
    6.7 3.1 5.6 2.4; 6.9 3.1 5.1 2.3; 5.8 2.7 5.1 1.9; 6.8 3.2 5.9 2.3; ...
    6.7 3.3 5.7 2.5; 6.7 3.0 5.2 2.3; 6.3 2.5 5.0 1.9; 6.5 3.0 5.2 2.0; ...
    6.2 3.4 5.4 2.3; 5.9 3.0 5.1 1.8];
%Split data set into training (1:25) and testing (26:50)
idxTrain = 1:25;
idxTest = 26:50;

% Combine training data with normalization
X = [x1(idxTrain,:);x2(idxTrain,:);x3(idxTrain,:)];
% Define class indicator as Y
Y = kron(eye(3),ones(25,1));
% Normalization
xmean = mean(X);
xstd = std(X);
ymean = mean(Y);
ystd = std(Y);
X = (X - xmean(ones(75,1),:))./xstd(ones(75,1),:);
Y = (Y - ymean(ones(75,1),:))./ystd(ones(75,1),:);
% Tolerance for 90 percent score
tol = (1-0.9) * 25 * 4;
% Perform PLS
[T,P,U,Q,B] = pls(X,Y,tol);
% Results
fprintf('Number of components retained: %i\n',size(B,1))
% Predicted classes
X1 = (x1(idxTest,:) - xmean(ones(25,1),:))./xstd(ones(25,1),:);
X2 = (x2(idxTest,:) - xmean(ones(25,1),:))./xstd(ones(25,1),:);
X3 = (x3(idxTest,:) - xmean(ones(25,1),:))./xstd(ones(25,1),:);
Y1 = X1 * (P*B*Q');
Y2 = X2 * (P*B*Q');
Y3 = X3 * (P*B*Q');
Y1 = Y1 .* ystd(ones(25,1),:) + ymean(ones(25,1),:);
Y2 = Y2 .* ystd(ones(25,1),:) + ymean(ones(25,1),:);
Y3 = Y3 .* ystd(ones(25,1),:) + ymean(ones(25,1),:);
% Class is determined from the cloumn which is most close to 1
[dum,classid1]=min(abs(Y1-1),[],2);
[dum,classid2]=min(abs(Y2-1),[],2);
[dum,classid3]=min(abs(Y3-1),[],2);
bar(1:25,classid1,'b');
hold on
bar(26:50,classid2,'r');
bar(51:75,classid3,'g');
hold off

% The results show that most samples are classified correctly.


function [x,w] = GaussHermite2(N)
%
% [X W] = HERMQUAD(N)
%
% Find the Gauss-Hermite abscissae and weights.
%
% Arguments:
%  N - The number of abscissae and weights to return.
%
% Return Values:
%  X - A column vector containing the abscissae.
%  W - A column vector containing the corresponding weights.
%
% Gauss-Hermite quadrature approximates definite integrals of the form
%
%     \int^{-\infty}_{\infty} dx W(x) f(x)
%
% where
%
%     W(x) = \exp( - x^2 )
%
% with the sum
%
%     \sum_{n=1}^{N} w_{n} f(x_{n}).
%
% This function returns the set of abscissae and weights
%
%     {x_{n}, w_{n}}^{N}_{n=1}
%
% for performing this calculation given N, the number of abscissae.
% These abscissae correspond to the zeros of the Nth Hermite
% polynomial.  It can be shown that such integration is exact when f(x)
% is a polynomial of maximum order 2N-1.
%
% The procedure in this calculation is taken more or less directly from
%
% @BOOK{ press-etal-1992a,
%	 AUTHOR   = { Press, William  H.   and
%                     Flannery, Brian  P.  and
%                     Teukolsky, Saul  A.  and
%                     Vetterling, William  T. },
%       ISBN      = {0521431085},
%	MONTH     = {October},
%	PUBLISHER = {{Cambridge University Press}},
%	TITLE     = {Numerical Recipes in C : The Art of Scientific Computing},
%	YEAR      = {1992}
%      }
%

% precision
EPS = 3.0e-14;

% 1/\pi^{1/4}
PIM4 = 0.7511255444649425;

% maximum number of loops
MAXIT = 10;

% allocate the return values
x = zeros([N 1]);
w = zeros([N 1]);

for i=1:(N+1)/2

  % good guesses at initial values for specific roots
  if i == 1
    z = sqrt(2.0*N+1.0) - 1.85575*((2.0*N+1)^(-0.16667));
  elseif i == 2
    z = z - (1.14 * N^0.426 / z);
  elseif i == 3
    z = 1.86 * z - 0.86 * x(1);
  elseif i == 4
    z = 1.91 * z - 0.91 * x(2);
  else
    z = 2.0*z - x(i-2);
  end

  for iter=1:MAXIT+1
    p1 = PIM4;
    p2 = 0.0;

    for j=1:N
      p3 = p2;
      p2 = p1;
      p1 = z * sqrt(2.0/j) * p2 - sqrt((j-1.0)/j) * p3;
    end

    % the derivative
    pp = sqrt(2.0*N) * p2;

    % newton step
    z1 = z;
    z  = z1 - p1/pp;

    if abs(z-z1) <= EPS
      break;
    end
  end

  if iter == MAXIT+1
    fprintf('Too many iterations in hermquad.\n');
  end

  x(i)     = z;
  x(N+1-i) = -z;
  w(i)     = 2.0/(pp*pp);
  w(N+1-i) = w(i);

end


% Fig. 8.5   Feedback Control of Dynamic Systems, 5e
%             Franklin, Powell, Emami
%

clear all;
close all;

th=0:.1:pi;
Im=sin(th);
Re=cos(th);

figure(1)
plot(Re,Im,'-',.5*Re,.5*Im,'--'),grid
axis([-1 1 -.5 1.5])
axis('square')
hold on
plot(1,0,'x')
plot(.6,0,'x')
plot(.3,0,'x')
plot(0,0,'x')
plot(-.5,0,'x')
plot(-1,0,'x')
j=sqrt(-1);
p=[exp(j*pi/4) exp(-j*pi/4)];
plot(p,'x')
p2=[exp(j*pi/2) exp(-j*pi/2)];
plot(p2,'x')
p3=1.2*[exp(j*pi/2) exp(-j*pi/2)];
plot(p3,'x')
p4=.5*[exp(j*pi/4) exp(-j*pi/4)];
plot(p4,'x')
p5=.5*[exp(j*pi/2) exp(-j*pi/2)];
plot(p5,'x')
p6=.5*[exp(j*3*pi/4) exp(-j*3*pi/4)];
plot(p6,'x')
title('Fig. 8.5  Time sequences associated with poles in the z-plane')
hold off

figure(2) % This figure creates four of the time responses
num=[1  0];
den=[1 -1];
N=11;
n=0:N-1;
y=dimpulse(num,den,N);
Ny=size(y);
subplot(2,2,1)
axis([1 10 -1.5 1.5])
zero=zeros(Ny);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = +1')

den=[1 -.6];
subplot(2,2,2)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = +.6')

den=[1 -.3];
subplot(2,2,3)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = +.3')

den=[1 0];
subplot(2,2,4)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = 0')

figure(3)   % This figure creates four more of the time responses
num=[1  0];
j=sqrt(-1);
p=[exp(j*pi/4) exp(-j*pi/4)];
den=poly(p);
N=11;
n=0:N-1;
y=.67*dimpulse(num,den,N);
Ny=size(y);
subplot(2,2,1)
axis([1 10 -1.5 1.5])
zero=zeros(Ny);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = exp(+-j*45 deg)')

p=[exp(j*pi/2) exp(-j*pi/2)];
den=poly(p);
subplot(2,2,2)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = exp(+-j*90 deg)')

den=[1  1];
subplot(2,2,3)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = -1')

p=1.2*[exp(j*pi/2) exp(-j*pi/2)];
den=poly(p);
subplot(2,2,4)
y=.5*dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = 1.2*exp(+-j*90 deg)')

figure(4)  % This figure creates four more of the time responses
num=[1  0];
j=sqrt(-1);
p=.5*[exp(j*pi/4) exp(-j*pi/4)];
den=poly(p);
N=11;
n=0:N-1;
y=dimpulse(num,den,N);
Ny=size(y);
subplot(2,2,1)
axis([1 10 -1.5 1.5])
zero=zeros(Ny);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = .5*exp(+-j*45 deg)')

p=.5*[exp(j*pi/2) exp(-j*pi/2)];
den=poly(p);
subplot(2,2,2)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = .5*exp(+-j*90 deg)')

p=.5*[exp(j*3*pi/4) exp(-j*3*pi/4)];
den=poly(p);
subplot(2,2,3)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = .5*exp(+-j*135 deg)')

den=[1 .5];
subplot(2,2,4)
y=dimpulse(num,den,N);
plot(n,y,'*',n,y,'--',n,zero,'-')
title('z = -.5')