% Polynomial discrimination
% Section 8.6.2, Boyd & Vandenberghe "Convex Optimization"
% Original by Lieven Vandenberghe
% Adapted for CVX by Joelle Skaf - 10/23/05
% (a figure is generated)
%
% The goal is to find the polynomial of degree 4 on R^n that separates
% two sets of points {x_1,...,x_N} and {y_1,...,y_N}. We are trying to find
% the coefficients of an order-4-polynomial P(x) that would satisfy:
%           minimize    t
%               s.t.    P(x_i) <= t  for i = 1,...,N
%                       P(y_i) >= t   for i = 1,...,M

% Data generation
rand('state',0);
N = 100;
M = 120;

% The points X lie within a circle of radius 0.9, with a wedge of points
% near [1.1,0] removed. The points Y lie outside a circle of radius 1.1,
% with a wedge of points near [1.1,0] added. The wedges are precisely what
% makes the separation difficult and interesting.
X = 2 * rand(2,N) - 1;
X = X * diag(0.9*rand(1,N)./sqrt(sum(X.^2)));
Y = 2 * rand(2,M) - 1;
Y = Y * diag((1.1+rand(1,M))./sqrt(sum(Y.^2)));
d = sqrt(sum((X-[1.1;0]*ones(1,N)).^2));
Y = [ Y, X(:,d<0.9) ];
X = X(:,d>1);
N = size(X,2);
M = size(Y,2);

% Construct Vandermonde-style monomial matrices
p1   = [0,0,1,0,1,2,0,1,2,3,0,1,2,3,4]';
p2   = [0,1,1,2,2,2,3,3,3,3,4,4,4,4,4]'-p1;
np   = length(p1);
op   = ones(np,1);
monX = X(op,:) .^ p1(:,ones(1,N)) .* X(2*op,:) .^ p2(:,ones(1,N));
monY = Y(op,:) .^ p1(:,ones(1,M)) .* Y(2*op,:) .^ p2(:,ones(1,M));

% Solution via CVX
fprintf(1,'Finding the optimal polynomial of order 4 that separates the 2 classes...');

cvx_begin
    variables a(np) t(1)
    minimize ( t )
    a'*monX <= t;
    a'*monY >= -t;
    % For normalization purposes only
    norm(a) <= 1;
cvx_end

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

% Displaying results
nopts = 2000;
angles = linspace(0,2*pi,nopts);
cont = zeros(2,nopts);
for i=1:nopts
   v = [cos(angles(i)); sin(angles(i))];
   l = 0;  u = 1;
   while ( u - l > 1e-3 )
      s = (u+l)/2;
      x = s * v;
      if a' * ( x(op,:) .^ p1 .* x(2*op) .^ p2 ) > 0,
          u = s;
      else
          l = s;
      end
   end;
   s = (u+l)/2;
   cont(:,i) = s*v;
end;

graph = plot(X(1,:),X(2,:),'o', Y(1,:), Y(2,:),'o', cont(1,:), cont(2,:), '-');
set(graph(2),'MarkerFaceColor',[0 0.5 0]);
title('Optimal order-4 polynomial that separates the 2 classes')
% print -deps min-deg-discr.eps

%%%% Dual infeasible ?????


function len = polygonLength(poly, varargin)
%POLYGONLENGTH Perimeter of a polygon.
%
%   L = polygonLength(POLYGON);
%   Computes the boundary length of a polygon. POLYGON is given by a N-by-2
%   array of vertices.
%
%   Example
%     % Perimeter of a circle approximation
%     poly = circleToPolygon([0 0 1], 200);
%     polygonLength(poly)
%     ans =
%         6.2829
%
%   See also
%   polygons2d, polygonCentroid, polygonArea, drawPolygon, polylineLength
%

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2005-05-11
% Copyright 2005-2022 INRA - TPV URPOI - BIA IMASTE

% If first argument is a cell array, this is a multi-polygon, and we simply
% add the lengths of individual polygons
if iscell(poly)
    len = 0;
    for i = 1:length(poly)
        len = len + polygonLength(poly{i});
    end
    return;
end

% case of a polygon given as two coordinate arrays
if nargin == 2
    poly = [poly varargin{1}];
end

% check there are enough points
if size(poly, 1) < 2
    len = 0;
    return;
end

% compute length
if size(poly, 2) == 2
    % polygon in dimension 2 (classical case)
    dp = diff(poly([1:end 1], :), 1, 1);
    len = sum(hypot(dp(:, 1), dp(:, 2)));
else
    % polygon of larger dimension
    len = sum(sqrt(sum(diff(poly([2:end 1], :), 1, 1).^2, 2)));
end


function qr = plane_normal_xyz_to_qr ( pp, normal, pq, pr, n, xyz )

%*****************************************************************************80
%
%% PLANE_NORMAL_XYZ_TO_QR: XYZ to QR coordinates for a normal form plane.
%
%  Discussion:
%
%    The normal form of a plane in 3D is:
%
%      PP is a point on the plane,
%      NORMAL is a normal vector to the plane.
%
%    Two vectors PQ and PR can be computed with the properties that
%    * NORMAL, PQ and PR are pairwise orthogonal;
%    * PQ and PR have unit length;
%    * every point P in the plane has a "QR" representation
%      as P = PP + q * PQ + r * PR.
%
%    This function is given the XYZ coordinates of a set of points on the
%    plane, and returns the QR coordinates.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 November 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real PP(3), a point on the plane.
%
%    Input, real NORMAL(3), a normal vector N to the plane.  The
%    vector must not have zero length, but it is not necessary for N
%    to have unit length.
%
%    Input, real PQ(3), a vector of unit length,
%    perpendicular to the vector N and the vector PR.
%
%    Input, real PR(3), a vector of unit length,
%    perpendicular to the vector N and the vector PQ.
%
%    Input, integer N, the number of points on the plane.
%
%    Input, real XYZ(3,N), the XYZ coordinates of the points.
%
%    Output, real QR(2,N), the QR coordinates of the points.
%
  qr = [ pq'; pr' ] * ( xyz(1:3,1:n) - repmat ( pp, 1, n ) );

  return
end


function C = ttimes(A,B)
% TTIMES Tropical multiplication (max-plus algebra)
%
% C = TTIMES(A,B) Computes the tropical multiplication of the matrices A
% and B, AB(i,j) = max(A(i,:) + B(:,j)');
%
% See also tplus

n = size(A,1);
m = size(B,2);
C = reshape(max(kron(ones(m,1),A)+kron(B',ones(n,1)),[],2),n,m);


% Weighted analytic center of a set of linear inequalities
% Joëlle Skaf - 04/29/08
%
% The weighted analytic center of a set of linear inequalities:
%           a_i^Tx <= b_i   i=1,...,m,
% is the solution of the unconstrained minimization problem
%           minimize    -sum_{i=1}^m w_i*log(b_i-a_i^Tx),
% where w_i>0

% Input data
randn('state', 0);
rand('state', 0);
n = 10;
m = 50;
tmp = randn(n,1);
A = randn(m,n);
b = A*tmp + 2*rand(m,1);
w = rand(m,1);

% Analytic center
cvx_begin
    variable x(n)
    minimize -sum(w.*log(b-A*x))
cvx_end

disp('The weighted analytic center of the set of linear inequalities is: ');
disp(x);


function index = subv2ind(siz,sub)
%SUBV2IND   Linear index from subscript vector.
% SUBV2IND(SIZ,SUB) returns an equivalent single index corresponding to a
% subscript vector for an array of size SIZ.
% If SUB is a matrix, with subscript vectors as rows, then the result is a
% column vector.
%
% This is the opposite of IND2SUBV, so that
%   SUBV2IND(SIZ,IND2SUBV(SIZ,IND)) == IND.
%
% See also IND2SUBV, SUB2IND.

%index = subv2indTest(siz,sub);
prev_cum_size = [1 cumprod(siz(1:end-1))];
%index = (sub-1)*prev_cum_size' + 1;
index = sub*prev_cum_size' - sum(prev_cum_size) + 1;


% StackExchange Signal Processing Q63449
% https://dsp.stackexchange.com/questions/63449
% Deconvolution of an Image Acquired by a Square Uniform Detector
% References:
%   1.  aa
% Remarks:
%   1.  sa
% TODO:
% 	1.  ds
% Release Notes
% - 1.0.000     25/01/2020
%   *   First release.

%% General Parameters

subStreamNumberDefault = 79;

run('InitScript.m');

figureIdx           = 0; %<! Continue from Question 1
figureCounterSpec   = '%04d';

generateFigures = ON;

CONVOLUTION_SHAPE_FULL         = 1;
CONVOLUTION_SHAPE_SAME         = 2;
CONVOLUTION_SHAPE_VALID        = 3;

%% Simulation Parameters

imageFileName   = 'Lenna256.png';
kernelRadius    = 1;
convShape       = CONVOLUTION_SHAPE_VALID;

paramLambda = 0.005;

maxSize = 256;

%% Generate Data

mA = im2double(imread(imageFileName));
numRows = size(mA, 1);
numCols = size(mA, 2);

imgSize = min(numRows, numCols);
maxSize = min(imgSize, maxSize);
mA = mA(1:imgSize, 1:imgSize, :);
mA = imresize(mA, [maxSize, maxSize]);

mK = ones((2 * kernelRadius) + 1);
% mK = rand((2 * kernelRadius) + 1);
mK = mK / sum(mK(:));

switch(convShape)
    case(CONVOLUTION_SHAPE_FULL)
        convShapeString = 'full';
    case(CONVOLUTION_SHAPE_SAME)
        convShapeString = 'same';
    case(CONVOLUTION_SHAPE_VALID)
        convShapeString = 'valid';
end

hFigure     = figure();
hAxes       = axes();
hImageObj   = imshow(mA);
set(get(hAxes, 'Title'), 'String', {['Input Image - Lenna']}, ...
    'FontSize', fontSizeTitle);

mB = conv2(mA, mK, convShapeString);

hFigure     = figure();
hAxes       = axes();
hImageObj   = imshow(mB);
set(get(hAxes, 'Title'), 'String', {['Sensor Image - Lenna']}, ...
    'FontSize', fontSizeTitle);

%% Solution by Linear Algebra

mKK = CreateConvMtx2D(mK, maxSize, maxSize, convShape);
% Basically:
% vB = mKK * mA(:);
vA = mKK \ mB(:);
% vA = pinv(full(mKK)) * mB(:);

vA = ((mKK.' * mKK) + (paramLambda * speye(maxSize * maxSize))) \ (mKK.' * mB(:));

mAA = reshape(vA, maxSize, maxSize); %<! Restored Image

hFigure     = figure();
hAxes       = axes();
hImageObj   = imshow(mAA);
set(get(hAxes, 'Title'), 'String', {['Estimated Image - Lenna']}, ...
    'FontSize', fontSizeTitle);

%% Restore Defaults

% set(0, 'DefaultFigureWindowStyle', 'normal');
% set(0, 'DefaultAxesLooseInset', defaultLoosInset);


function lambda = gk316_eigenvalues ( n )

%*****************************************************************************80
%
%% GK316_EIGENVALUES returns the eigenvalues of GK316.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real LAMBDA(N,1), the eigenvalues.
%
  lambda = zeros ( n, 1 );

  if ( n == 1 )

    lambda(1,1) = 1.0;

  else

    lambda(1:n-2,1) = 1.0;

    a = 1.0;
    b = - ( n + 1 );
    c = - ( n * ( n + 1 ) * ( 2 * n - 5 ) ) / 6.0;

    lambda(n-1,1) = ( - b + sqrt ( b * b - 4.0 * a * c ) ) / ( 2.0 * a );
    lambda(n,1) =   ( - b - sqrt ( b * b - 4.0 * a * c ) ) / ( 2.0 * a );

  end

  return
end


function [a,t,tLength,k]=BSplineInterpIntMultiDim(t,tLength,a,k,intDims)
%%BSPLINEINTERPINTMULTIDIM Given a hypermatrix of multivariate b-spline
%            interpolation weights a and a set of knots t,compute the
%            modified weights and knots to interpolate the integral of the
%            a given point using b-spline interpolation. If all knots at
%            the ith boundary are repeated k(i) times, then an integral
%            over the ith dimension will start from the beginning of the
%            interpolation region. Otherwise, this can be considered an
%            indefinite integral with a particular additive constant and
%            differencing and be used to get a definite integral.
%
%INPUTS: t The maxNumKnotsXnumDims set of knots fo r the interpolation
%          function. These are actually the values in each coordinate
%          dimension given in ascending order. The full knots are implied
%          [t1,t2,etc.]=ndgrid(t(1:tLengths(1),1),t(1:tLengths(2),2),...)
%          and the dimensions can be put together into the full set of
%          numDimsXtotalNumPoints points as tTotal=[t1(:).';t2(:).';...].
%          The first and last k(curDim)-1 knots in each dimension are
%          outside of the ends of the region with data or mark the ends of
%          the region with data. The number of rows is the maximum number
%          needed for all of the dimensions. tLength says how many items
%          in each column are actually used. These values must be real.
%  tLength A numDimX1 vector where tLength(i) says the number of elements
%          in t(:,i).
%        a A hypermatrix with numDim+1 indices containing the set of
%          coefficients for the b-splines covering all of the interpolation
%          intervals for all of the sets of interpolation values. If there
%          is only one set, the final dimension is unitary meaning that
%          there are effectively only numDim dimensions. The derivatives
%          will be applied to all sets present. These values can be real or
%          complex.
%        k A numDimsX1 or 1XnumDims set of the order of the b-splines in
%          each dimension. The value k-1 is the polynomial order of the
%          approximation being performed. If the order is the same in all
%          dimensions, then a single scalar can be passed.
%  intDims This is a numDimsX1 or a 1XnumDims boolean vector indicating
%          over which dimensions the integrals should be taken.
%
%OUTPUTS: a The modified coefficient matrix. This is one larger in each
%           dimensions where an integral was taken.
%         t The modified knots.
%   tLength The modified vector indicating how many knows are present.
%         k The modified set of orders.
%
%Equation 22 in Chapter X of [1] has 1D integration. Chapter XVII describes
%the use of tensor product splines for more than one dimension. The
%generalization to more than one dimension comes from just evaluating the
%integrals across each dimension one at a time, if they are taken.
%
%EXAMPLE 1:
% f=@(x,y,z)(x.^4-2*x.^2+x).*(y.^4-2*y.^2+y).*(z.^4-3*z.^2+z);
% %The definite integral of f with respect to x and z starting at -1.5 is
% fIntXZ=@(x,y,z)((-891+240*x.^2-320*x.^3+96*x.^5).*y.*(1-2*y+y.^3).*(-477+80*z.^2-160*z.^3+32*z.^5))/76800;
%
% numDims=3;
% numPointsX=10;
% numPointsY=11;
% numPointsZ=9;
% tauLengths=[numPointsX;numPointsY;numPointsZ];
% tau=zeros(max(tauLengths),numDims);
% tau(1:tauLengths(1),1)=linspace(-1.5,1.5,numPointsX);
% tau(1:tauLengths(2),2)=linspace(-1.5,1.5,numPointsY);
% tau(1:tauLengths(3),3)=linspace(-1.5,1.5,numPointsZ);
% %Note that using meshgrid would have put the elements in the wong order.
% %ndgrid must be used.
% [tau1,tau2,tau3]=ndgrid(tau(1:tauLengths(1),1),tau(1:tauLengths(2),2),tau(1:tauLengths(3),3));
% y=f(tau1,tau2,tau3);
%
% k=[5;5;5];
% [a,t,tLength]=BSplinePolyFitMultiDim(tau,tauLengths,y(:),k);
% intDims=[1;0;1];
% [a,t,tLength,k]=BSplineInterpIntMultiDim(t,tLength,a,k,intDims);
%
% numPointsY=21;
% numPointsZ=19;
% pointsX=linspace(-1.5,1.5,numPointsX);
% pointsY=linspace(-1.5,1.5,numPointsY);
% pointsZ=linspace(-1.5,1.5,numPointsZ);
% [X,Y,Z]=ndgrid(pointsX,pointsY,pointsZ);
% x=[X(:).';Y(:).';Z(:).'];
%
% zIntTrue=fIntXZ(X,Y,Z);
% z=BSplineInterpValMultiDim(x,t,tLength,a,k);
% max(abs(z(:)-zIntTrue(:)))
%
%EXAMPLE 2:
%This is similar to example 1, except two sets of values are fitted,
%integrated, and interpolated at once.
% f1=@(x,y,z)(x.^4-2*x.^2+x).*(y.^4-2*y.^2+y).*(z.^4-3*z.^2+z);
% f2=@(x,y,z)(x.^3-2*x.^2+x).*(y.^4-2*y.^2+y).*(2*z.^3-2*z.^2+1);
% %The definite integral of f with respect to x and z starting at -1.5 is
% fIntXZ1=@(x,y,z)((-891+240*x.^2-320*x.^3+96*x.^5).*y.*(1-2*y+y.^3).*(-477+80*z.^2-160*z.^3+32*z.^5))/76800;
% fIntXZ2=@(x,y,z)(((-891+16*x.^2.*(6+x.*(-8+3*x))).*y.*(1-2*y+y.^3).*(-315+16*z.*(6+z.^2.*(-4+3*z))))/18432);
%
% numDims=3;
% numPointsX=10;
% numPointsY=11;
% numPointsZ=9;
% tauLengths=[numPointsX;numPointsY;numPointsZ];
% tau=zeros(max(tauLengths),numDims);
% tau(1:tauLengths(1),1)=linspace(-1.5,1.5,numPointsX);
% tau(1:tauLengths(2),2)=linspace(-1.5,1.5,numPointsY);
% tau(1:tauLengths(3),3)=linspace(-1.5,1.5,numPointsZ);
% %Note that using meshgrid would have put the elements in the wong order.
% %ndgrid must be used.
% [tau1,tau2,tau3]=ndgrid(tau(1:tauLengths(1),1),tau(1:tauLengths(2),2),tau(1:tauLengths(3),3));
% y1=f1(tau1,tau2,tau3);
% y2=f2(tau1,tau2,tau3);
% y=[y1(:),y2(:)];
%
% k=[5;5;5];
% [a,t,tLength]=BSplinePolyFitMultiDim(tau,tauLengths,y,k);
% intDims=[1;0;1];
% [a,t,tLength,k]=BSplineInterpIntMultiDim(t,tLength,a,k,intDims);
%
% numPointsY=21;
% numPointsZ=19;
% pointsX=linspace(-1.5,1.5,numPointsX);
% pointsY=linspace(-1.5,1.5,numPointsY);
% pointsZ=linspace(-1.5,1.5,numPointsZ);
% [X,Y,Z]=ndgrid(pointsX,pointsY,pointsZ);
% x=[X(:).';Y(:).';Z(:).'];
%
% zIntTrue1=fIntXZ1(X,Y,Z);
% zIntTrue2=fIntXZ2(X,Y,Z);
% z=BSplineInterpValMultiDim(x,t,tLength,a,k);
% max(abs(z(:,1)-zIntTrue1(:)))
% max(abs(z(:,2)-zIntTrue2(:)))
%
%EXAMPLE 3:
%This is an example of a bivariate complex function whose integral over the
%first dimension is interpolated.numPoints=80;
% xMin=0;
% xMax=3;
% yMin=0;
% yMax=3;
% x=linspace(xMin,xMax,numPoints);
% y=linspace(yMin,yMax,numPoints);
% [X,Y]=ndgrid(x,y);
% f=@(x,y)(sin(5*y)+1j*cos(10*x));
% %The integral from 0 in the x dimension.
% fIntx=@(x,y)((1/10)*1j*sin(10*x)+x.*sin(5*y));
%
% fxy=f(X(:),Y(:));
% k=[5;5];
% tau=[x(:),y(:)];
% tauLengths=[numPoints,numPoints];
% [a,t,tLength]=BSplinePolyFitMultiDim(tau,tauLengths,fxy,k);
% intDims=[1;0];
% [a,t,tLength,k]=BSplineInterpIntMultiDim(t,tLength,a,k,intDims);
%
% %Interpolate the derivative
% numPoints=100;
% x=linspace(xMin,xMax,numPoints);
% y=linspace(xMin,xMax,numPoints);
% [X,Y]=ndgrid(x,y);
%
% fxy=fIntx(X(:),Y(:));
% pts=[X(:).';Y(:).'];
% fxyInterp=reshape(BSplineInterpValMultiDim(pts,t,tLength,a,k),[numPoints,numPoints]);
% fxy=reshape(fxy,[numPoints,numPoints]);
%
% figure(1)
% clf
% hold on
% surface(X,Y,real(fxy),'EdgeColor','none')
% title('Real Integral Values')
% colorbar()
%
% figure(2)
% clf
% hold on
% surface(X,Y,imag(fxy),'EdgeColor','none')
% title('Imaginary Integral Values')
% colorbar()
%
% figure(3)
% clf
% hold on
% surface(X,Y,abs(real(fxyInterp)-real(fxy)),'EdgeColor','none')
% title('Real Interpolation Error')
% colorbar()
%
% figure(4)
% clf
% hold on
% surface(X,Y,abs(imag(fxyInterp)-imag(fxy)),'EdgeColor','none')
% title('Imaginary Interpolation Error')
% colorbar()
%
%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.

numDims=length(tLength);
numA=size(a);

if(length(numA)==numDims)
    numSets=1;
    numA=[numA,1];
else
    numSets=numA(end);
end

tNew=zeros(max(tLength)+2,numDims);
for curDim=1:numDims
    if(intDims(curDim)==0)
        tNew(1:tLength(curDim),curDim)=t(1:tLength(curDim),curDim);
        continue;
    end

    temp=zeros(1,numDims);
    temp(curDim)=1;
    aNew=zeros(numA+[temp,0]);

    %Next, we go through all tuples of values for the dimensions other than
    %this one. In each instance, we must take the integral of the a terms
    %that are present. These indices select all of the dimensions that are
    %not the current one across which derivatives are being taken.
    for curSet=1:numSets
        idxList=[1:(curDim-1),(curDim+1):numDims];

        maxVals=numA(idxList)-1;
        numACur=numA(curDim);
        curTuple=getNextTuple(numDims-1);
        idxCell=cell(1,numDims+1);
        idxCell{numDims+1}=curSet;
        tCur=t(1:tLength(curDim),curDim);
        kCur=k(curDim);

        outputIdx=1:(numACur+1);
        while(~isempty(curTuple))
            idxCell{curDim}=1:numA(curDim);%Mark the free dimension.

            %We have to select the elements in a to work on based on the
            %current tuple.
            for curIdx=1:(numDims-1)
                idxCell{idxList(curIdx)}=curTuple(curIdx)+1;
            end

            aCur=reshape(a(idxCell{:}),[numACur,1]);

            [~,aCur]=BSplineInterpInt(tCur,aCur,kCur);
            idxCell{curDim}=outputIdx;
            aNew(idxCell{:})=aCur;

            curTuple=getNextTuple(curTuple,maxVals);
        end
    end
    numA(curDim)=numA(curDim)+1;
    a=aNew;
    k(curDim)=k(curDim)+1;
    tNew(1:(tLength(curDim)+2),curDim)=[t(1,curDim);t(1:tLength(curDim),curDim);t(tLength(curDim),curDim)];
    tLength(curDim)=tLength(curDim)+2;
end
a=aNew;
t=tNew;

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 value = beta_inc ( a, b, x )

%*****************************************************************************80
%
%% BETA_INC returns the value of the incomplete Beta function.
%
%  Discussion:
%
%    This calculation requires an iteration.  In some cases, the iteration
%    may not converge rapidly, or may become inaccurate.
%
%    BETA_INC(A,B,X)
%
%      =   Integral ( 0 <= T <= X ) T^(A-1) (1-T)^(B-1) dT
%        / Integral ( 0 <= T <= 1 ) T^(A-1) (1-T)^(B-1) dT
%
%      =   Integral ( 0 <= T <= X ) T^(A-1) (1-T)^(B-1) dT
%        / BETA(A,B)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 September 2004
%
%  Author:
%
%    Original FORTRAN77 version by Majumder, Bhattacharjee.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Majumder and Bhattacharjee,
%    Algorithm AS63,
%    Applied Statistics,
%    1973, volume 22, number 3.
%
%  Parameters:
%
%    Input, A, B, the parameters of the function.
%    0.0D+00 < A,
%    0.0D+00 < B.
%
%    Input, real X, the argument of the function.
%    Normally, 0.0D+00 <= X <= 1.0.
%
%    Output, BETA_INC, the value of the function.
%
  it_max = 1000;
  tol = 1.0E-07;

  if ( a <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'BETA_INC - Fatal error!\n' );
    fprintf ( 1, '  A <= 0.\n' );
    error ( 'BETA_INC - Fatal error!' );
  end

  if ( b <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'BETA_INC - Fatal error!\n' );
    fprintf ( 1, '  B <= 0.\n' );
    error ( 'BETA_INC - Fatal error!' );
  end

  if ( x <= 0.0 )
    value = 0.0;
    return
  elseif ( 1.0 <= x )
    value = 1.0;
    return
  end
%
%  Change tail if necessary and determine S.
%
  psq = a + b;

  if ( a < ( a + b ) * x )
    xx = 1.0 - x;
    cx = x;
    pp = b;
    qq = a;
    indx = 1;
  else
    xx = x;
    cx = 1.0 - x;
    pp = a;
    qq = b;
    indx = 0;
  end

  term = 1.0;
  i = 1;
  value = 1.0;

  ns = floor ( qq + cx * ( a + b ) );
%
%  Use Soper's reduction formulas.
%
  rx = xx / cx;

  temp = qq - i;
  if ( ns == 0 )
    rx = xx;
  end

  it = 0;

  while ( 1 )

    it = it + 1;

    if ( it_max < it )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'BETA_INC - Fatal error!\n' );
      fprintf ( 1, '  Maximum number of iterations exceeded!\n' );
      fprintf ( 1, '  IT_MAX = %d\n', it_max );
      error ( 'BETA_INC - Fatal error!' );
    end

    term = term * temp * rx / ( pp + i );
    value = value + term;
    temp = abs ( term );

    if ( temp <= tol & temp <= tol * value )
      break
    end

    i = i + 1;
    ns = ns - 1;

    if ( 0 <= ns )
      temp = qq - i;
      if ( ns == 0 )
        rx = xx;
      end
    else
      temp = psq;
      psq = psq + 1.0;
    end

  end
%
%  Finish calculation.
%
  value = value * exp ( pp * log ( xx )  + ( qq - 1.0 ) * log ( cx ) ) ...
    / ( beta ( a, b ) * pp );

  if ( indx )
    value = 1.0 - value;
  end

  return
end


%% Pendulum example
%  This example applies energy-preserving piDMD to reconstruct the trajectory of
%  a double pendulum from noisy measurements.
addpath('../src')
rng(1); % Set random seed

% Define parameters of problem
l1=1; l2=1.5; % Lengths of rods
m1=1 ; m2=1.5; g=9.81; % Masses and gravity
params = [l1, l2, m1, m2, g]; % Concatenate parameters

% Construct linearised energy inner product
W(1,1) = (m1/2+m2/2)*g*l1;
W(2,2) = m2/2*g*l2;
W(3,3) = (m1/2+m2/2)*l1^2;
W(4,3) = m2/2*l1*l2;
W(3,4) = W(4,3);
W(4,4) = m2/2*l2^2;
C = chol(W); % Calculate inner product

% Set number of samples and span
tend = 30; nt = 1000;
tspan= linspace(0,tend,nt);

% Set initial conditions
theta1= 0.4; theta1_prime=0;
theta2= 0.7; theta2_prime=0;
y0=[theta1 theta1_prime theta2 theta2_prime];

% Solve ODE
[t,y]=ode45(@(t,y) pendulum(t,y,params), tspan,y0);

% Extract data
th1 = y(:,1); th2 = y(:,3); th1dt = y(:,2); th2dt = y(:,4);
x = [th1'; th2'; th1dt'; th2dt'];
xn = x + 1e-1*std(x,[],2).*randn(size(x)); % Add noise
data = C*xn; % Rescale measurements into energy norm
nTrain = nt-1;
X = data(:,1:nTrain); Y = data(:,2:nTrain+1);

% Train models
[piA,piVals] = piDMD(X,Y,'orthogonal');
[exA,exVals] = piDMD(X,Y,'exact');

% Perform reconstructions
piRec = zeros(4,nt); piRec(:,1) = data(:,1);
exRec = zeros(4,nt); exRec(:,1) = data(:,1);
for j = 2:nt
piRec(:,j) = piA(piRec(:,j-1));
exRec(:,j) = exA(exRec(:,j-1));
end

% Rescale reconstructions back into physical norm
fpiRec = C\piRec; fexRec = C\exRec;

%% Plot results
figure(1); LW = 'LineWidth'; IN = 'Interpreter'; LT = 'Latex'; FS = 'FontSize';
subplot(3,1,1)
c1 = .8*[1 1 1]; c2 = .8*[1 1 1];
plot(tspan,xn(1,:),LW,2,'Color',c1)
hold on
plot(tspan,xn(2,:),LW,2,'Color',c2)
hold off; trajPlot('measurements'); xticklabels([])
subplot(3,1,2)
plot(tspan,x(1,:),LW,3,'Color', c1)
hold on
plot(tspan,fpiRec(1,:),'b--',LW,2)
plot(tspan,fexRec(1,:),'r--',LW,2)
ylabel('$\theta_1$',IN,LT)
hold off; trajPlot('$\theta_1$'); xticklabels([])
subplot(3,1,3)
l1=plot(t,x(2,:),LW,3,'Color', c2);
hold on
l2=plot(t,fpiRec(2,:),'b--',LW,2);
l3=plot(t,fexRec(2,:),'r--',LW,2);
hold off; xlabel('time',FS,20,IN,LT)
trajPlot('$\theta_2$')
legend([l1,l2,l3],{'truth','piDMD','exact DMD'},IN,LT)
function yp = pendulum(~, y, params)

l1=params(1);  l2=params(2);
m1=params(3);  m2=params(4);
g=params(5);

a = (m1+m2)*l1 ;
b = m2*l2*cos(y(1)-y(3)) ;
c = m2*l1*cos(y(1)-y(3)) ;
d = m2*l2 ;
e = -m2*l2*y(4)* y(4)*sin(y(1)-y(3))-g*(m1+m2)*sin(y(1)) ;
f = m2*l1*y(2)*y(2)*sin(y(1)-y(3))-m2*g*sin(y(3)) ;
yp=zeros(4,1);
yp(1) = y(2);
yp(3)= y(4) ;
yp(2)= (e*d-b*f)/(a*d-c*b) ;
yp(4)= (a*f-c*e)/(a*d-c*b) ;
end

function trajPlot(j) % Nice plot of trajectories
yticks([-pi/4,0,pi/4]); yticklabels([{'$-\pi/4$'},{'0'},{'$\pi/4$'}])
set(gca,'TickLabelInterpreter','Latex','FontSize',20);grid on
ylim([-1,1])
ylabel(j,'Interpreter','latex','FontSize',20)
end


%
% This code calculates the interevent distances and the correlation integral
% of a given earthquake distribution.
% Francesco Pacchiani 3/2000
%
%
% Calculation of the 3D distances between all possible pairs
% (combination of n epicenters taken 2 at a time) of earthquakes of
% the given dataset.
%
%
% Variables
%
N = size(E,1);				% N= # of events in the catalogue; E= Earthquake catalogue
pairdist = []; 			% pairdist= Vector of interevent distances
j = nchoosek(N,2);			% j= # of interevent distances calculated
pairdist = zeros(j,1);
k = 0;
%E.Latitude= (max(Da(:,2))+min(Da(:,2)))/2;
%
%
% Calculation of the interevent distances in 2D plus the depths differences.
%
%
for i = 1:(N-1)

    lon1 = repmat(E(i,1), [(N-i),1]);
    lat1 = repmat(E(i,2), [(N-i),1]);

    lon2 = E((i+1):end, 1);
    lat2 = E((i+1):end, 2);

    pairdist(k+1:k + size(lon1, 1)) = distance(lat1,lon1,lat2,lon2);

    k = k + size(lon1,1);

end

clear i j k;
%
%
% Conversion of the interevent distances from degrees to kilometers and calculates
% the interevent distances in three dimensions.
%
%
if dtokm == 1
    pairdist = pairdist.*111;
end
%
%
% Calculation of the correlation integral using as input the
% pair distances computed above.
%
%
% Variables
%
d = 2;						%d = the dimension of the embedding volume.
rmax = max(pairdist);
rmin = min(pairdist);

if rmin == 0
    rmin = 0.01;
end

lrmin = log10(rmin);
lrmax = log10(max(pairdist));

%u = (log10(rmin):0.15:log10(rmax))';
%
% Defining the distance vector r in order that on the
% log-log graph all the points plot at equal distances from one another.
%
r = (logspace(lrmin, lrmax, 50))';
%r = zeros(size(u,1),1);
%r = 10.^u;
%
%
corint = [];						% corint= Vector of ?cumulative? correlation integral values for increasing interevent radius
corint = zeros(size(r,1),1);
k = 1;

for i = 1:size(r,1)

    j = [];
    j = pairdist < r(i);
    corint (k,1) = (2/(N*(N-1)))*sum(j);
    k = k + 1;

end

clear i j k;
%
%
% Plotting of the correlation integral in function of the interevent
% distance r.
%
%
dofdnofig;


function [label, model, llh] = mixGaussEm(X, init)
% Perform EM algorithm for fitting the Gaussian mixture model.
% Input:
%   X: d x n data matrix
%   init: k (1 x 1) number of components or label (1 x n, 1<=label(i)<=k) or model structure
% Output:
%   label: 1 x n cluster label
%   model: trained model structure
%   llh: loglikelihood
% Written by Mo Chen (sth4nth@gmail.com).
%% init
fprintf('EM for Gaussian mixture: running ... \n');
tol = 1e-6;
maxiter = 500;
llh = -inf(1,maxiter);
R = initialization(X,init);
for iter = 2:maxiter
    [~,label(1,:)] = max(R,[],2);
    R = R(:,unique(label));   % remove empty clusters
    model = maximization(X,R);
    [R, llh(iter)] = expectation(X,model);
    if abs(llh(iter)-llh(iter-1)) < tol*abs(llh(iter)); break; end;
end
llh = llh(2:iter);

function R = initialization(X, init)
n = size(X,2);
if isstruct(init)  % init with a model
    R  = expectation(X,init);
elseif numel(init) == 1  % random init k
    k = init;
    label = ceil(k*rand(1,n));
    R = full(sparse(1:n,label,1,n,k,n));
elseif all(size(init)==[1,n])  % init with labels
    label = init;
    k = max(label);
    R = full(sparse(1:n,label,1,n,k,n));
else
    error('ERROR: init is not valid.');
end

function [R, llh] = expectation(X, model)
mu = model.mu;
Sigma = model.Sigma;
w = model.w;

n = size(X,2);
k = size(mu,2);
R = zeros(n,k);
for i = 1:k
    R(:,i) = loggausspdf(X,mu(:,i),Sigma(:,:,i));
end
R = bsxfun(@plus,R,log(w));
T = logsumexp(R,2);
llh = sum(T)/n; % loglikelihood
R = exp(bsxfun(@minus,R,T));

function model = maximization(X, R)
[d,n] = size(X);
k = size(R,2);
nk = sum(R,1);
w = nk/n;
mu = bsxfun(@times, X*R, 1./nk);

Sigma = zeros(d,d,k);
r = sqrt(R);
for i = 1:k
    Xo = bsxfun(@minus,X,mu(:,i));
    Xo = bsxfun(@times,Xo,r(:,i)');
    Sigma(:,:,i) = Xo*Xo'/nk(i)+eye(d)*(1e-6);
end

model.mu = mu;
model.Sigma = Sigma;
model.w = w;

function y = loggausspdf(X, mu, Sigma)
d = size(X,1);
X = bsxfun(@minus,X,mu);
[U,p]= chol(Sigma);
if p ~= 0
    error('ERROR: Sigma is not PD.');
end
Q = U'\X;
q = dot(Q,Q,1);  % quadratic term (M distance)
c = d*log(2*pi)+2*sum(log(diag(U)));   % normalization constant
y = -(c+q)/2;


function value = r8_cotd ( degrees )

%*****************************************************************************80
%
%% R8_COTD returns the cotangent of an angle given in degrees.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 July 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real DEGREES, the angle in degrees.
%
%    Output, real VALUE, the cotangent of the angle.
%
  radians = pi * ( degrees / 180.0 );

  value = cos ( radians ) / sin ( radians );

  return
end


function [h mu ul ll] = circ_mtest(alpha, dir, xi, w, d)
%
% [pval, z] = circ_mtest(alpha, dir, w, d)
%   One-Sample test for the mean angle.
%   H0: the population has mean dir.
%   HA: the population has not mean dir.
%
%   Note: This is the equvivalent to a one-sample t-test with specified
%         mean direction.
%
%   Input:
%     alpha	sample of angles in radians
%     dir   assumed mean direction
%     [xi   alpha level of the test]
%     [w		number of incidences in case of binned angle data]
%     [d    spacing of bin centers for binned data, if supplied
%           correction factor is used to correct for bias in
%           estimation of r, in radians (!)]
%
%   Output:
%     h     0 if H0 can not be rejected, 1 otherwise
%     mu    mean
%     ul    upper (1-xi) confidence level
%     ll    lower (1-xi) confidence level
%
% PHB 7/6/2008
%
% References:
%   Biostatistical Analysis, J. H. Zar
%
% Circular Statistics Toolbox for Matlab

% By Philipp Berens, 2009
% berens@tuebingen.mpg.de - www.kyb.mpg.de/~berens/circStat.html

if size(alpha,2) > size(alpha,1)
	alpha = alpha';
end

if nargin<3
  xi = 0.05;
end

if nargin<4
  % if no specific weighting has been specified
  % assume no binning has taken place
	w = ones(size(alpha));
else
  if size(w,2) > size(w,1)
    w = w';
  end
  if length(alpha)~=length(w)
    error('Input dimensions do not match.')
  end
end

if nargin<5
  % per default do not apply correct for binned data
  d = 0;
end

% compute ingredients
mu = circ_mean(alpha,w);
t = circ_confmean(alpha,xi,w,d);
ul = mu + t;
ll = mu - t;

% compute test via confidence limits (example 27.3)
h = abs(circ_dist2(dir,mu)) > t;


function [z,pv1,pv2,pv3]=compare_bino_prob(X,Y)
% [z,pv1,pv2,pv3]=compare_bino_prob(X,Y)
% Compares probabilities of two binomial samples X, Y
% Let X and Y be sets of 0 or 1, results from a Bernoully experiments
% with probability p1 for set X and p2 for set Y.
% Test the null hypothesis
%       H_0: p1 = p2
%    vs alternatives
%       H_1: p1 > p2
%       H_2: p1 < p2
%       H_3: p1 != p2
%
% Input:
%       X - row of 0 or 1
%       Y - row of 0 or 1
%
% Output:
%       z   - normal statistics N(0,1) for H_0
%       pv1 - p-value for H_1
%       pv2 - p-value for H_2
%       pv3 - p-value for H_3

% Dimiar Atanasov (2008)
% datanasov@nbu.bg

if size(X,1) > 1 || size(Y,1) > 1
    error('Sets should be rows');
end;

n_x1 = size( find(X == 1), 1 );
n_x0 = size( find(X == 0), 1 );

n_y1 = size( find(Y == 1), 2);
n_y0 = size( find(Y == 0), 2);

n_x = n_x1 + n_x0;
n_y = n_y1 + n_y0;

n_1 = n_x1 + n_y1;
n_0 = n_x0 + n_y0;

n = n_0 + n_1;

h_x = n_x1 / n_x;
h_y = n_y1 / n_y;

h = (n_x1 + n_y1)/(n_x + n_y);

if (n_1^2  / n < 5) || (n_0^2 / n < 5) || ( n_1*n_0 / n < 5)
    disp('Missing asymptotic behaviour!!!');
end;

s = h*(1-h)*(1/n_x + 1/n_y);

z = (h_x - h_y) / sqrt(s);

pv1 = 1 - normcdf(z);
pv2 = normcdf(z);
pv3 = (1 - normcdf( abs(z) ))/2;


function coeff = eq_dist_coeff(dim,N,varargin)
%EQ_DIST_COEFF Coefficient of minimum distance of an EQ point set
%
%Syntax
% coeff = eq_dist_coeff(dim,N,options);
%
%Description
% COEFF = EQ_DIST_COEFF(dim,N) does the following:
% 1) uses the recursive zonal equal area sphere partitioning algorithm to
%    partition the unit sphere S^dim into N regions,
% 2) finds the EQ point set, the set of center points of each region,
% 3) finds the minimum Euclidean distance between points of the EQ point set,
% 4) sets COEFF to be the coefficient in the expression for the lower bound on
%    the minimum distance of a minimum energy point set:
%
%    DIST >= COEFF N^(-1/dim).
%
% The argument dim must be a positive integer.
% The argument N must be a positive integer or an array of positive integers.
% The result COEFF will be an array of the same size as N.
%
% COEFF = EQ_DIST_COEFF(dim,N,'offset','extra'), for dim == 2 or dim == 3, uses
% experimental extra rotation offsets to try to maximize the minimum distance.
% For dim > 3, extra offsets are not used.
%
%Notes
% The expression for the lower bound on minimum distance of a minimum r^(-s)
% energy point set on S^dim was given by [RakSZ95] for s == 0 and dim = 2,
% [Dahl78] for s == dim-1, [KuiSS04 Theorem 8] for dim-1 <= s < dim and
% [KuiS98 (1.12) p. 525] for s > dim.
%
% Ideally eq_dist_coeff(dim,N) should tend to area_of_sphere(dim)^(1/dim) as
% N goes to infinity.
%
%Examples
% > coeff=eq_dist_coeff(2,10)
%  coeff =
%      3.3250
%
% > coeff=eq_dist_coeff(3,1:6)
%  coeff =
%      2.0000    2.5198    2.0396    2.2449    2.4183    2.5698
%
%See also
% PARTITION_OPTIONS, EQ_MIN_DIST

% Copyright 2004-2005 Paul Leopardi for the University of New South Wales.
% $Revision 1.10 $ $Date 2005-06-01 $
% Documentation files renamed
% $Revision 1.00 $ $Date 2005-02-12 $
%
% For licensing, see COPYING.
% For references, see AUTHORS.
% For revision history, see CHANGELOG.

%
% Check number of arguments
%
error(nargchk(2,4,nargin));
%
% dim is the number of dimensions
% N is the number of regions
%
dist = eq_min_dist(dim,N,varargin{:});
coeff =  dist .* N.^(1/dim);
%
% end function


function u = ref_to_koorn ( r )

%*****************************************************************************80
%
%% REF_TO_KOORN maps points from the reference to Koornwinder's triangle.
%
%  Discussion:
%
%    The reference triangle has vertices:
%
%      ( -1, -1/sqrt(3) )
%      ( +1, -1/sqrt(3) )
%      (  0, +2/sqrt(3) )
%
%    Koornwinder's triangle has vertices:
%
%      ( -1, -1 )
%      ( +1, -1 )
%      ( -1, +1 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 June 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R(2), the coordinates of a point in the
%    reference triangle.
%
%    Output, real U(2), the coordinates of the point in
%    the Koornwinder triangle.
%
  a10 = -1.0 / 3.0;
  a11 =  1.0;
  a12 = -1.0 / sqrt ( 3.0 );

  a20 = - 1.0 / 3.0;
  a21 =   0.0;
  a22 =   2.0 * sqrt ( 3.0 ) / 3.0;

  u(1) = a10 + r(1) + a12 * r(2);
  u(2) = a20 +        a22 * r(2);

  return
end


function [A, B] = reflexKronApprox( K, m, n )
%
%       [A, B] = reflexKronApprox( K, m, n );
%
% computes a kronecker sum approximation to the blurring matrix K
% that arises from the input PSF under reflexive boundary conditions.
% This approximation is done a-la Nagy-Ng-Perrone (see paper for details).
%
%  Input:
%         K - psfMatrix object
%         m - size of matrix A (assumed square)
%         n - size of matrix B (assumed square)
%
%  Output:
%      Matrices A and B such that K \aprrox A \otimes B.
%

%  L. Perrone, 4/28/02

%  Modifications:
%  5/25/02, J. Nagy
%           Cosmetic changes to incorporate into RestoreTools
%
%
%  11/17/02, J. Nagy
%            This was designed for image processing problems, where
%            it is common to use lexicographical (row) ordering.
%            But @kronMatrix functions where designed using vec (column)
%            ordering.  This inconsistency has been fixed.

P1 = K.psf;
P2 = P1.image;
PSF = P2{1};
c1 = P1.center;
center = c1{1};

[mp, np] = size(PSF);

if ( mp ~= np )
  error('For now, we expect PSF to be square')
end

%
% Compute weighted PSF.
%
c = zeros(mp,1);
c(1) = mp;
c(2:2:end) = 1;
R = chol( toeplitz(c) );

Phat = R*PSF*R';

%
% Compute SVD of weighted PSF, which is then used to construct
% the separable approximation.
%
[U,S,V] = svd( Phat );

%
% check to make sure first column looks like
% a Gaussian, and is not inverted.
%
minU = abs(min(min(U(:,1))));
maxU = max(max(abs(U(:,1))));
if minU == maxU
  U = -U;
  V = -V;
end

%
% Construct approximation.
%
a = R \ ( U(:,1) * sqrt(S(1,1)) );
b = R \ ( V(:,1) * sqrt(S(1,1)) );

%
%  This construction corresponds to lexicographical ordering,
%  but kronMatrix does everything corresponding to vec ordering.
%  Thus, these two do not work together.
%%
%%A = build_toep(a, center(1), n) + buildHank(a, center(1), n);
%%B = build_toep(b, center(2), m) + buildHank(b, center(2), m);

A = build_toep(b, center(2), m) + buildHank(b, center(2), m);
B = build_toep(a, center(1), n) + buildHank(a, center(1), n);


function h=plotgauss2d(mu, Sigma, plot_cross)
% PLOTGAUSS2D Plot a 2D Gaussian as an ellipse with optional cross hairs
% h=plotgauss2(mu, Sigma)
%
% h=plotgauss2(mu, Sigma, 1) also plots the major and minor axes
%
% Example
% clf; S=[2 1; 1 2]; plotgauss2d([0;0], S, 1); axis equal

h = plotcov2(mu, Sigma);
return;

%%%%%%%%%%%%%%%%%%%%%%%%
function old

if nargin < 3, plot_cross = 0; end
[V,D]=eig(Sigma);
lam1 = D(1,1);
lam2 = D(2,2);
v1 = V(:,1);
v2 = V(:,2);
%assert(approxeq(v1' * v2, 0))
if v1(1)==0
  theta = 0; % horizontal
else
  theta = atan(v1(2)/v1(1));
end
a = sqrt(lam1);
b = sqrt(lam2);
h=plot_ellipse(mu(1), mu(2), theta, a,b);

if plot_cross
  mu = mu(:);
  held = ishold;
  hold on
  minor1 = mu-a*v1; minor2 = mu+a*v1;
  hminor = line([minor1(1) minor2(1)], [minor1(2) minor2(2)]);

  major1 = mu-b*v2; major2 = mu+b*v2;
  hmajor = line([major1(1) major2(1)], [major1(2) major2(2)]);
  %set(hmajor,'color','r')
  if ~held
    hold off
  end
end


function g = sigmoidGradient(z)
%SIGMOIDGRADIENT returns the gradient of the sigmoid function
%evaluated at z
%   g = SIGMOIDGRADIENT(z) computes the gradient of the sigmoid function
%   evaluated at z. This should work regardless if z is a matrix or a
%   vector. In particular, if z is a vector or matrix, you should return
%   the gradient for each element.

g = zeros(size(z));

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

g = sigmoid(z) .* (1 .- sigmoid(z));

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

end


function determ = skew_circulant_determinant ( n, x )

%*****************************************************************************80
%
%% SKEW_CIRCULANT_DETERMINANT returns the determinant of the SKEW_CIRCULANT matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Input, real X(N), the values in the first row of A.
%
%    Output, real DETERM, the determinant.
%
  determ = 1.0;

  j_hi = floor ( ( n + 1 ) / 2 );

  for j = 1 : j_hi

    lambda = 0.0;

    for k = 1 : n
      angle = ( 2 * j - 1 ) * ( k - 1 ) * pi / n;
      lambda = lambda + x(k) * complex ( cos ( angle ), sin ( angle ) );
    end

    if ( 2 * j <= n )
      determ = determ * ( abs ( lambda ) )^2;
    else
      determ = determ * real ( lambda );
    end

  end

  return
end


%% Test script for optimum mixing
% 17/Feb./2016
% Hideki Kawahara

clear all
close all

nSignal = 6;
baseValue = 100;
nData = 10000;
nIteration = 5000;

stdBest = zeros(nIteration, 1);
stdMean = zeros(nIteration, 1);
stdSD = zeros(nIteration, 1);
for kk = 1:nIteration
    sdList = 0.2 + 3 * rand(nSignal, 1);
    sampleData = randn(nData, nSignal) * diag(sdList) + baseValue;

    H = ones(nSignal, nSignal) * baseValue^2 * 2;
    for ii = 1:nSignal
        H(ii, ii) = H(ii, ii) + 2 * sdList(ii)^2;
    end;
    v = ones(nSignal, 1) * 2 * baseValue^2;
    a = inv(H) * v;
    stdBest(kk) = std(sampleData * a);
    stdMean(kk) = std(sampleData  *ones(nSignal, 1) / nSignal);
    wSD = (1.0 ./ sdList);
    wSD = wSD / sum(wSD);
    stdSD(kk) = std(sampleData * wSD);
end;
figure;plot(stdBest, stdMean, '.');grid on;
hold all
plot([0 100],[0 100]);
axis([0 max([stdBest; stdMean]) 0 max([stdBest; stdMean])]);
axis('square');
xlabel('optimized SD');
ylabel('SD of simple mean');
figure;plot(stdBest, stdSD, '.');grid on;
hold all
plot([0 100],[0 100]);
axis([0 max([stdBest; stdSD]) 0 max([stdBest; stdSD])]);
axis('square');
xlabel('optimized SD');
ylabel('SD of 1/SD mixing');


% Gives the spectrum of a derivative effect (i.e. a zero at zero frequency)
%
% Input
%  dftlen : the number of bin in spectrum (full DFT length).
%  fs     : [Hz] The sampling frequency
%
% Output
%  S      : The spectrum of the derivative effect
%
% Copyright (c) 2011 University of Crete - Computer Science Department
%
% License
%  This file is under the LGPL license,  you can
%  redistribute it and/or modify it under the terms of the GNU Lesser General
%  Public License as published by the Free Software Foundation, either version 3
%  of the License, or (at your option) any later version. This file 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 Lesser General Public License for more
%  details.
%
% This function is part of the Covarep project: http://covarep.github.io/covarep
%
% Author
%  Gilles Degottex <degottex@csd.uoc.gr>
%

function S = spec_derivative(dftlen, fs)

    % The half-spectrum of a zero at frequency zero is:
    hS = fs*(2i*pi/dftlen)*(0:dftlen/2).';

    if mod(dftlen,2)==1
        % If DFT length is odd
        S = [hS; hS(end:-1:2)];
    else
        % If DFT length is even
        hS(end) = 0;
        S = hspec2spec(hS);
    end

return


function [X_poly] = polyFeatures(X, p)
%POLYFEATURES Maps X (1D vector) into the p-th power
%   [X_poly] = POLYFEATURES(X, p) takes a data matrix X (size m x 1) and
%   maps each example into its polynomial features where
%   X_poly(i, :) = [X(i) X(i).^2 X(i).^3 ...  X(i).^p];
%

% You need to return the following variables correctly.
X_poly = zeros(numel(X), p);

% ====================== YOUR CODE HERE ======================
% Instructions: Given a vector X, return a matrix X_poly where the p-th
%               column of X contains the values of X to the p-th power.
%
%

for i=1:p
	X_poly(:, i) = X(:,1).^i;
end

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

end


%KMEANS  Finds centers of clusters and groups input samples around the clusters
%
%     labels = cv.kmeans(data, K)
%     [labels, centers, compactness] = cv.kmeans(...)
%     [...] = cv.kmeans(..., 'OptionName', optionValue, ...)
%
% ## Input
% * __data__ Data for clustering. An array of D-dimensional points with
%   floating-point coordinates is needed. Examples of this matrix can be: NxD
%   numeric matrix (one row per sample), or Nx1xD/1xNxD array (with dimensions
%   across slices).
% * __K__ Number of clusters to split the set by.
%
% ## Output
% * __labels__ Integer array that stores the cluster indices for every sample.
% * __centers__ Output matrix of the cluster centers, one row per each cluster
%   center.
% * __compactness__ Measure of compactness. See below.
%
% ## Options
% * __Criteria__ The algorithm termination criteria, that is, the maximum
%   number of iterations and/or the desired accuracy. The accuracy is
%   specified as `criteria.epsilon`. As soon as each of the cluster centers
%   moves by less than `criteria.epsilon` on some iteration, the algorithm
%   stops. default
%   `struct('type','Count+EPS', 'maxCount',100, 'epsilon',eps('float'))`
% * __Attempts__ The number of times the algorithm is executed using different
%   initial labelings. The algorithm returns the labels that yield the best
%   compactness (see the last function parameter). default 10.
% * __Initialization__ Method to initialize seeds. One of the followings:
%   * __Random__ Select random initial centers in each attempt. (default)
%   * __PP__ Use kmeans++ center initialization by Arthur and Vassilvitskii
%     [Arthur2007].
% * __InitialLabels__ Integer array that stores the initial cluster indices
%   for every sample. During the first (and possibly the only) attempt, kmeans
%   uses the user-supplied labels instead of computing them from the initial
%   centers. For the second and further attempts, it uses the random or
%   semi-random centers. Use one of the `Initialization` methods to specify
%   the exact method. Not set by default.
%
% The function cv.kmeans implements a k-means algorithm that finds the centers
% of `K` clusters and groups the input samples around the clusters. As an
% output, `labels(i)` contains a 0-based cluster index for the sample stored
% in the i-th row of the samples matrix.
%
% The function returns the compactness measure that is computed as:
%
%     sum_{i} (|| samples_i - centers_{labels_i} ||^2)
%
% after every attempt. The best (minimum) value is chosen and the
% corresponding labels and the compactness value are returned by the
% function. Basically, you can use only the core of the function, set the
% number of attempts to 1, initialize labels each time using a custom
% algorithm, pass them with the `InitialLabels` option, and then choose the
% best (most-compact) clustering.
%
% ## References
% [Arthur2007]:
% > D. Arthur, S. Vassilvitskii: "k-means++: The Advantages of Careful Seeding".
% > In Proceedings of the eighteenth annual ACM-SIAM symposium
% > on Discrete algorithms, 1027-1035, 2007.
%
% See also: kmeans
%


function area = area_quad ( quad_xy )

%*****************************************************************************80
%
%% AREA_QUAD returns the area of a quadrilateral.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 February 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real QUAD_XY(2,4), the coordinates of the nodes.
%
%    Output, real AREA, the area of the quadrilateral.
%
  t1(1:2,1) = quad_xy(1:2,1);
  t1(1:2,2) = quad_xy(1:2,2);
  t1(1:2,3) = quad_xy(1:2,3);

  area1 = triangle_area ( t1 );

  t2(1:2,1) = quad_xy(1:2,3);
  t2(1:2,2) = quad_xy(1:2,4);
  t2(1:2,3) = quad_xy(1:2,1);

  area2 = triangle_area ( t2 );

  if ( area1 < 0.0 | area2 < 0.0 )

    t1(1:2,1) = quad_xy(1:2,2);
    t1(1:2,2) = quad_xy(1:2,3);
    t1(1:2,3) = quad_xy(1:2,4);

    area1 = triangle_area ( t1 );

    t2(1:2,1) = quad_xy(1:2,4);
    t2(1:2,2) = quad_xy(1:2,1);
    t2(1:2,3) = quad_xy(1:2,2);

    area2 = triangle_area ( t2 );

    if ( area1 < 0.0 | area2 < 0.0 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'AREA_QUAD - Fatal error!\n' );
      fprintf ( 1, '  The quadrilateral nodes seem to be listed in\n' );
      fprintf ( 1, '  the wrong order, or the quadrilateral is\n' );
      fprintf ( 1, '  degenerate.\n' );
      error ( 'AREA_QUAD - Fatal error!' );
    end

  end

  area = area1 + area2;

  return
end


function [ Tree,Cost ] =  UndirectedMaximumSpanningTree (CostMatrix)
% The function takes CostMatrix as input and returns the maximum spanning tree T
% Uses Kruskal's Algorithm
% Extract the edge weights from the cost matrix
% Sort the edges in a non decreasing order of weights
% This algorithm is revised by Lowell Guangdi at 2009/06/11.

n = size (CostMatrix,1); %Number of vertices
EdgeWeights = 0;         %Edges and corresponding weights
EdgeWeightsCounter = 0;
for i = 1:n
    for j = (i+1):n
        if ((CostMatrix(i,j))~=0)
            EdgeWeightsCounter = EdgeWeightsCounter + 1;
            EdgeWeights(EdgeWeightsCounter,1) = CostMatrix(i,j);
            EdgeWeights(EdgeWeightsCounter,2) = i;
            EdgeWeights(EdgeWeightsCounter,3) = j;
        end
    end
end

SortedEdgeWeights = 0;
SortedEdgeWeights = sortrows(EdgeWeights);
% First column of SortedEdgeWeights are the weights
% Second and third column are the vertices that the edges connect
m = size(SortedEdgeWeights,1); % number of edges

% We use the Disjoint sets data structures to detect cycle while adding new
% edges. Union by Rank with path compression is implemented here.

% Assign parent pointers to each vertex. Initially each vertex points to
% itself. Now we have a conceptual forest of n trees representing n disjoint
% sets
global ParentPointer ;
ParentPointer = 0;
ParentPointer(1:n) = 1:n;

% Assign a rank to each vertex (root of each tree). Initially all vertices
% have the rank zero.
TreeRank = 0;
TreeRank(1:n) = 0;

% Visit each edge in the sorted edges array
% If the two end vertices of the edge are in different sets (no cycle), add
% the edge to the set of edges in maximum spanning tree
MSTreeEdges = 0;
MSTreeEdgesCounter = 0; i = m;
while ((MSTreeEdgesCounter < (n-1)) && (i>=1))
%Find the roots of the trees that the selected edge's two vertices
%belong to. Also perform path compression.
    root1=0; root2=0; temproot=0;
    temproot = SortedEdgeWeights(i,2);
    root1 = FIND_PathCompression(temproot);

    temproot = SortedEdgeWeights(i,3);
    root2 = FIND_PathCompression(temproot);

    if (root1 ~= root2)
        MSTreeEdgesCounter = MSTreeEdgesCounter + 1;
        MSTreeEdges(MSTreeEdgesCounter,1:3) = SortedEdgeWeights(i,:);
        if (TreeRank(root1)>TreeRank(root2))
            ParentPointer(root2)=root1;
        else
            if (TreeRank(root1)==TreeRank(root2))
               TreeRank(root2)=TreeRank(root2) + 1;
            end
            ParentPointer(root1)=root2;
        end
    end
    i = i - 1;
end

MSTreeEdgesCounter = 0;
Tree = 0;
Tree(1:n,1:n)=0;
while (MSTreeEdgesCounter < (n-1))
    MSTreeEdgesCounter = MSTreeEdgesCounter + 1;
    Tree(MSTreeEdges(MSTreeEdgesCounter,2),MSTreeEdges(MSTreeEdgesCounter,3))=1;
    Tree(MSTreeEdges(MSTreeEdgesCounter,3),MSTreeEdges(MSTreeEdgesCounter,2))=1;
end
%T

Cost = 0;
for p = 1:n
    for q = p+1:n
       if Tree( p,q ) == 1
          Cost = Cost + CostMatrix( p,q );
       end
    end
end

end

function [parent] = FIND_PathCompression(temproot)

global ParentPointer;
ParentPointer(temproot);
if (ParentPointer(temproot)~=temproot)
    ParentPointer(temproot) = FIND_PathCompression(ParentPointer(temproot));
end
parent = ParentPointer(temproot);
end


function value = tetrahedron_unit_monomial ( expon )

%*****************************************************************************80
%
%% TETRAHEDRON_UNIT_MONOMIAL integrates a monomial over the unit tetrahedron.
%
%  Discussion:
%
%    This routine integrates a monomial of the form
%
%      product ( 1 <= dim <= 3 ) x(dim)^expon(dim)
%
%    where the exponents are nonnegative integers.  Note that
%    if the combination 0^0 is encountered, it should be treated
%    as 1.
%
%    Integral ( over unit tetrahedron ) x^l y^m z^n dx dy =
%    l% * m% * n% / ( m + n + 3 )%
%
%    The integration region is defined as:
%
%      0 <= X
%      0 <= Y
%      0 <= Z
%      0 <= X + Y + Z <= 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer EXPON(3), the exponents.
%
%    Output, real VALUE, the integral of the monomial.
%

%
%  The first computation ends with VALUE = 1.0;
%
  value = 1.0;
%
%  The first loop simply calculates 1, so we short circuit it.
%
% k = 0;
%
% for i = 1 : expon(1)
%   k = k + 1;
%   value = value * i / k;
% end

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

  for i = 1 : expon(3)
    k = k + 1;
    value = value * i / k;
  end

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

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

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

  return
end


function H = ent_g(x, biascorrect)
% ENT_G Entropy of a Gaussian variable in bits
%   H = ent_g(x) returns the entropy of a (possibly
%   multidimensional) Gaussian variable x with bias correction.
%   Rows of x correspond to samples, columns to dimensions/variables.
%   (Samples first axis)
%
%   biascorrect : true / false option (default true) which specifies
%   whether bias correction should be applied to the estimated entropy.

if isvector(x)
    x = x(:);
end
if ndims(x)~=2
    error('ent_g: input arrays should be 2d')
end
[Ntrl, Nvarx] = size(x);

if nargin < 2
    % default is to apply bias correction
    biascorrect = true;
end

% demean data
gx.m = sum(x,1)/Ntrl;
x = bsxfun(@minus,x,gx.m);

% covariance
C = (x'*x) / (Ntrl - 1);
chC = chol(C);

% entropy in nats
HX = sum(log(diag(chC))) + 0.5*Nvarx*(log(2*pi)+1);

ln2 = log(2);
if biascorrect
    psiterms = psi((Ntrl - (1:Nvarx))/2) / 2;
    dterm = (ln2 - log(Ntrl-1)) / 2;
    HX = (HX - Nvarx*dterm - sum(psiterms));
end

% convert to bits
H = HX / ln2;


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.

    n = length(y); % number of training examples

    % cost: J, this time with the penalty for the magnitude of theta
    J = -1/n * sum(...
        y      .* log(sigmoid(X * theta)) + ...
        (1 - y) .* log(1 - sigmoid(X * theta)) ...
    ) + lambda / (2 * n) * sum(theta(2:end) .* theta(2:end));

    % gradient: compute as the derivative of the cost function
    grad = 1/n * X' * ((sigmoid(X * theta)) - y) + theta * lambda / n;

    % we do not regularize the constant offset term,
    % undo the gradient penalization for the constant x_0 term
    grad(1) = grad(1) - lambda / n * theta(1);
end


function [ArcData, Ang] = ComputeArc(V1,V2,Dist,NumPoints,DirectionFlag)
%COMPUTEARC Computes Arc between two 3D vectors at a specified distance

%Direction of angle, 0 indicates the shortest direction, one indicates to
%go the other direction which results in an angle > 180
if ~exist('DirectionFlag','var')
    DirectionFlag = 0;
end

%Make vectors unit vectors
V1 = V1./norm(V1);
V2 = V2./norm(V2);

%get angle between vectors
Ang = acosd(dot(V1,V2));

if DirectionFlag
    Ang = -1*(360-Ang); %make neg to go the other direction
end

%cross V1 and V2 to get axis or rotation
V3 = cross(V1,V2);
V3 = V3./norm(V3);

%allocate ArcDta
ArcData = zeros(NumPoints,3);

%Set up angles to rotate through
Angs = linspace(0,Ang,NumPoints);

for i=1:NumPoints
    %create rotation matrix to perform rotations
    T = RotateAboutAxis(V3,Angs(i));
    ArcData(i,:) = (T*V1)'*Dist;
end

%set angle back to positive
if DirectionFlag
    Ang = -1*Ang;
end


function [fSignificanceLevel, fMu, fSigma] = kj_CalcNormSig(mValues, fTestValue)
% function [fSignificanceLevel, fMu, fSigma] = kj_CalcNormSig(mValues, fTestValue)
% --------------------------------------------------------------------------------
% Calculates the level of significance of fTestValue assuming the distribution
% to be a normal distribution
%
% Input parameters:
%   mValues               Value distribution (assumed to be a normal distribution)
%   fTestValue            Value to be tested
%
% Output parameter:
%   fSignificanceLevel    Level of significance
%   fMu                   Mu of normal distribution
%   fSigma                Sigma of normal distribution
%
% Danijel Schorlemmer
% March 13, 2002

global bDebug;
if bDebug
  report_this_filefun(mfilename('fullpath'));
end

% Select all non-NaN values of the distribution
vSelection = ~isnan(mValues);
mNoNanValues = mValues(vSelection);

% Fit the values to a normal distribution
[fMu, fSigma] = normfit(mNoNanValues);

% Return the significance level of the testvalue
fSignificanceLevel = 1 - (normcdf(fTestValue, fMu, fSigma));


function e = imEntropy(img, varargin)
%IMENTROPY Compute entropy of an image
%
%   H = imEntropy(IMG)
%   Computes the entropy of the image IMG.
%   The entropy is computed as:
%     H  = -sum(P .* log2(P));
%   where P is the density probability that image takes a given value.
%
%   Note that the computation of the entropy depends on the way the
%   histogram is computed. This should not be a concern for uint8 images,
%   but can give results inconsistent with imMutualInformation for double
%   images.
%
%   H = imEntropy(IMG, N)
%   H = imEntropy(IMG, BINS)
%   Computes the histogram using N bins, or the bins specified by BINS.
%
%
%   Example
%     % compute entropy on a sample image
%     img = imread('rice.png');
%     H = imEntropy(img)
%     H =
%         7.0115
%
%     % entropy is independent of pixel ordering
%     img2 = circshift(img, [30 40]);
%     H = imEntropy(img2)
%     H =
%         7.0115
%
%     % entropy computed on an histogram with fewer bins
%     imEntropy(img, 16)
%     ans =
%         3.1158
%
%   See also
%     imJointEntropy, imMutualInformation, imHistogram
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2010-08-26,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

% first compute histogram
h = imHistogram(img, varargin{:});

% keep only positive values, and normalize by 1 to have density
h(h==0) = [];
h = h / sum(h);

% compute entropy
e = -sum(h .* log2(h));


function [d, xd, bw] = kernelDensity(x, bins, h, kernel)
%KERNELDENSITY Calculate the kernel density of a data set
%
%   [D, XD] = IOSR.STATISTICS.KERNELDENSITY(X) calculate the kernel density
%   D of a dataset X for query points XD. The kernel density is calculated
%   for 100 query points equally spaced between the minimum and maximum of
%   the data X. The density is estimated using a gaussian kernel with a
%   width that is optimal for normal data. X may be a vector, matrix, or
%   multi-dimensional array; the entire array is treated as the sample. D
%   and XD are 100-point column vectors. NaN are excluded from the
%   calculations.
%
%   ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS) calculates the density for
%   the query points specified by BINS. If BINS is a scalar, then BINS
%   points are queried between MIN(X(:)) and MAX(X(:)); if BINS is a
%   vector, then the values are used as the query points directly. D and XD
%   are column vectors.
%
%   ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, H) uses the bandwidth H to
%   calculate the kernel density. H must be a scalar. BINS may be an empty
%   array in order to use the default described above.
%
%   ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, [], KERNEL) uses the
%   kernel function specified by KERNEL to calculate the density. The
%   kernel may be:
%       - 'normal' (default),
%       - 'uniform',
%       - 'triangular',
%       - 'epanechnikov',
%       - 'quartic',
%       - 'triweight',
%       - 'tricube',
%       - 'cosine',
%       - 'logistic',
%       - 'sigmoid', or
%       - 'silverman'.
%   For the uniform case the bandwidth is set to 15% of the range of the
%   data [1]. Otherwise the bandwidth is chosen to be optimal for normal
%   data assuming a gaussian kernel.
%
%   ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, H, KERNEL) allows the
%   bins BINS and bandwidth H to be specified directly.
%
%   [D, XD, BW] = IOSR.STATISTICS.KERNELDENSITY(...) returns the badwidth
%   BW.
%
%   Examples
%
%     Example 1: Plot the kernel density of gaussian data
%       figure
%       % gaussian random numbers
%       y = randn(100000, 1);
%       % density
%       [d, xd] = iosr.statistics.kernelDensity(y);
%       % plot
%       plot(xd, d);
%
%     Example 2: Density trace with 200 bins of width of 10% of data range
%       figure
%       % random numbers
%       y = randn(100000, 1);
%       % y range
%       range = max(y(:)) - min(y(:));
%       % density trace
%       [d, xd] = iosr.statistics.kernelDensity(y, 200, 0.1*range, 'uniform');
%       % plot
%       plot(xd, d);
%
%   References
%
%   [1] Hintze, Jerry L.; Nelson, Ray D. (1998). "Violin Plots: A Box
%       Plot-Density Trace Synergism". The American Statistician. 52 (2):
%       181?4.

    %% input check

    x = x(:);
    x = x(~isnan(x));
    assert(numel(x) > 1, 'X must be a vector, matrix, or array.')

    % x bins
    if nargin < 2
        bins = [];
    end
    if isempty(bins)
        bins = 100;
    end
    if isscalar(bins)
        bins = linspace(min(x), max(x), round(bins));
    end
    bins = bins(:);

    % bin width
    if nargin < 3
        h = [];
    end

    % kernel
    if nargin < 4
        kernel = [];
    end
    if isempty(kernel)
        kernel = 'normal';
    end
    % return kernel function
    switch lower(kernel)
        case 'uniform'
            K = @(u) 0.5*(abs(u) <= 1);
            if isempty(h)
                h = 0.15 * (max(x) - min(x));
            end
        case 'normal'
            K = @(u) ((1/sqrt(2*pi)) * exp(-0.5*(u.^2)));
        case 'triangular'
            K = @(u) ((1-abs(u)) .* (abs(u) <= 1));
        case 'epanechnikov'
            K = @(u) ((0.75*(1-(u.^2))) .* (abs(u) <= 1));
        case 'quartic'
            K = @(u) (((15/16)*(1-(u.^2)).^2) .* (abs(u) <= 1));
        case 'triweight'
            K = @(u) (((35/32)*(1-(u.^2)).^3) .* (abs(u) <= 1));
        case 'tricube'
            K = @(u) (((70/81)*(1-(abs(u).^3)).^3) .* (abs(u) <= 1));
        case 'cosine'
            K = @(u) (((pi/4)*cos((pi/2)*u)) .* (abs(u) <= 1));
        case 'logistic'
            K = @(u) (1 / (exp(u) + 2 + exp(-u)));
        case 'sigmoid'
            K = @(u) ((2/pi) * (1 / (exp(u) + exp(-u))));
        case 'silverman'
            K = @(u) (0.5 * exp((-abs(u))/(sqrt(2))) .* sin((abs(u))/(sqrt(2)) + (pi/4)));
        otherwise
            error('Unknown kernel specified');
    end
    if isempty(h)
        h = ((4*(std(x).^5))/(3*numel(x))).^(1/5);
    end

    assert(isscalar(h), 'h must be a scalar')

    %% calculate kernel density

    xd = sort(bins);
    d = zeros(size(xd));

    for i = 1:numel(xd)
        d(i) = sum(K((x-xd(i))/h))./(numel(x)*h);
    end
    d(isnan(d)) = 0;
    bw = h;

end


function p = predict(theta, X)
%PREDICT Predict whether the label is 0 or 1 using learned logistic
%regression parameters theta
%   p = PREDICT(theta, X) computes the predictions for X using a
%   threshold at 0.5 (i.e., if sigmoid(theta'*x) >= 0.5, predict 1)

m = size(X, 1); % Number of training examples

% You need to return the following variables correctly
p = zeros(m, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned logistic regression parameters.
%               You should set p to a vector of 0's and 1's
%

h_theta = sigmoid(X*theta);
p = ceil(2*h_theta)-1;

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

end


function y = sinc(x, c)
%SINC   The function SIN(PI*X)/(PI*X).
%
%   SINC(X) returns the SIN(PI*X)/(PI*X) function which is defined as
%
%      1                 if x = 0
%      sin(pi*x)/(pi*x)  if 0 < |x| < infinity
%      0                 if |x| = infinity
%
%   SINC(X, C) returns the SIN(C*X)/(C*X) function, where C > 0, which is a
%   generalization of the above and is defined as
%
%      1                 if x = 0
%      sin(c*x)/(c*x)    if 0 < |x| < infinity
%      0                 if |x| = infinity
%
%   See also SIN.

%   Author:      Peter J. Acklam
%   Time-stamp:  2003-10-20 08:45:14 +0200
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

   nargsin = nargin;

   % check number of input arguments
   error(nargchk(1, 2, narsgin));

   if nargsin < 2
      c = pi;
   else
      if any(size(c) ~= 0) | (c <= 0)
         error('Second argument must be a positive scalar.');
      end
   end

   y = ones(size(x));           % initialize output
   i = x ~= 0;                  % find non-zero elements
   t = c * x(i);                % precompute C*X
   y(i) = sin(t) ./ t;          % compute SIN(C*X)/(C*X)
   y(isinf(x)) = 0;             % 0 not NaN when X = +/-Inf


function line_monte_carlo_test01 ( )

%*****************************************************************************80
%
%% LINE_MONTE_CARLO_TEST01 estimates integrals in 1D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 January 2014
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'LINE_MONTE_CARLO_TEST01\n' );
  fprintf ( 1, '  Use LINE01_SAMPLE to estimate integrals\n' );
  fprintf ( 1, '  along the length of the unit line in 1D.\n' );

  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, '         N' );
  fprintf ( 1, '        1' );
  fprintf ( 1, '               X' );
  fprintf ( 1, '              X^2' );
  fprintf ( 1, '             X^3' );
  fprintf ( 1, '             X^4' );
  fprintf ( 1, '             X^5' );
  fprintf ( 1, '           X^6\n' );
  fprintf ( 1, '\n' );

  n = 1;

  while ( n <= 65536 )

    [ x, seed ] = line01_sample ( n, seed );

    fprintf ( 1, '  %8d', n );

    for j = 1 : 7

      e = j - 1;

      value = monomial_value_1d ( n, e, x );

      result = line01_length ( ) * sum ( value(1:n) ) / n;

      fprintf ( 1, '  %14.6g', result );

    end

    fprintf ( 1, '\n' );

    n = 2 * n;

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '     Exact' );

  for j = 1 : 7

    e = j - 1;

    result = line01_monomial_integral ( e );
    fprintf ( 1, '  %14.6g', result );

  end

  fprintf ( 1, '\n' );

  return
end


function b = isPointInEllipse(point, ellipse, varargin)
%ISPOINTINELLIPSE Check if a point is located inside a given ellipse
%
%   B = isPointInEllipse(POINT, ELLIPSE)
%   Returns true if point is located inside the given ellipse.
%
%   B = isPointInEllipse(POINT, ELLIPSE, TOL)
%   Specifies the tolerance value
%
%   Example:
%   isPointInEllipse([1 0], [0 0 2 1 0])
%   ans =
%       1
%   isPointInEllipse([0 0], [0 0 2 1 0])
%   ans =
%       1
%   isPointInEllipse([1 1], [0 0 2 1 0])
%   ans =
%       0
%   isPointInEllipse([1 1], [0 0 2 1 30])
%   ans =
%       1
%
%   See also:
%   ellipses2d, isPointInCircle
%
%   ---------
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 11/03/2011
%

%   HISTORY

% extract computation tolerance
tol = 1e-14;
if ~isempty(varargin)
    tol = varargin{1};
end

% compute ellipse to unit circle transform
rot = createRotation(-deg2rad(ellipse(5)));
sca = createScaling(1./ellipse(3:4));
trans = sca * rot;

% transform points to unit circle basis
pTrans = bsxfun(@minus, point, ellipse(:,1:2));
pTrans = transformPoint(pTrans, trans);

% test if distance to origin smaller than 1
b = sqrt(sum(power(pTrans, 2), 2)) - 1 <= tol;


function [ area, radin, side ] = polygon_outrad_data_2d ( n, radout )

%*****************************************************************************80
%
%% POLYGON_OUTRAD_DATA_2D determines polygonal data from its outer radius in 2D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 September 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of sides of the polygon.
%    N must be at least 3.
%
%    Input, real RADOUT, the outer radius of the polygon, that is,
%    the radius of the smallest circle that can be described
%    around the polygon.
%
%    Output, real AREA, the area of the regular polygon.
%
%    Output, real RADIN, the inner radius of the polygon, that is,
%    the radius of the largest circle that can be inscribed
%    within the polygon.
%
%    Output, real SIDE, the length of one side of the polygon.
%
  if ( n < 3 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'POLYGON_OUTRAD_DATA_2D - Fatal error!\n' );
    fprintf ( 1, '  Input value of N must be at least 3.\n' );
    fprintf ( 1, '  but your input value was N = %d\n', n );
    error ( 'POLYGON_OUTRAD_DATA_2D - Fatal error!' );
  end

  angle = pi / n;
  area = 0.5 * n * radout * radout * sin ( 2.0 * angle );
  side = 2.0 * radout * sin ( angle );
  radin = 0.5 * side / tan ( angle );

  return
end


%
% This demo shows the designed of filters and some figures in
%
% Ha T. Nguyen and Minh N. Do, Hybrid Filter Banks with Fractional Delays:
% Minimax Design and Application to Multichannel Sampling, vol. 56, no. 7,
% pp. 3180-3190, July 2008.

initialization;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Design of (IIR for FIR) synthesis filters F_i(z)

% Design IIR synthesis filters F_i(z)
[num, den, gamma] = designIIR(phi, D, m0, h, M);

% Design FIR synthesis filters F_i(z)
% [num, den, gamma] = designFIR(phi, D, m0, h, M, n);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Demo of the approximation of the high-resolution signal
% Filtering using the synthesis filters F_i(z)
y0hat = 0*y0;

for i = 1:N
    z = filter(num{i}, den{i}, upsample(x{i},M));
    y0hat = y0hat + z(1:L);
end

% Approximation error
e = y0 - y0hat;

% Compute the errors
max(e)
mean(e(1:200).^2)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Plot the results,

% Plot Fig. 9
figure(9);
bode(numphi, denphi);
title('Bode diagram of \Phi(s)')

% Plot Fig. 10
plot_equi_filters;

% Plot of Fig. 11
% (plot only the first 2 filters if more than 2 are available)
figure(11);
freqz(num{1}, den{1});
hold on;
freqz(num{2}, den{2});

% figure;
% plot(e(1:200));
% xlabel('sample');
% ylabel('error');
% title('Approximation error')

% Plot Fig. 12
figure(12);
plot(e(1:50));
hold on;
plot(y0(1:50), 'r--')
xlabel('sample');
ylabel('error');
legend('error', 'signal')
title('Approximation error vs the high resolution signal')


function [v] = spm_mar_gen (w,A,C,n,ndisc)
% Generate data from MAR model
% FORMAT [v] = spm_mar_gen (w,A,C,n,ndisc)
%
% Generates n time steps of the MAR(p) process
%
%     v(k,:)' = w' + A1*v(k-1,:)' +...+ Ap*v(k-p,:)' + eta(k,:)',
%
%  where A=[A1 ... Ap] is the coefficient matrix, and w is a vector of
%  intercept terms that is included to allow for a nonzero mean of the
%  process. The vectors eta(k,:) are independent Gaussian noise
%  vectors with mean zero and covariance matrix C.
%
%  This function is adapted from the ARFIT toolbox by Neumaier and
%  Schneider
%___________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Will Penny
% $Id: spm_mar_gen.m 1143 2008-02-07 19:33:33Z spm $

m       = size(C,1);                  % dimension of state vectors
p       = size(A,2)/m;                % order of process

if (p ~= round(p))
    error('Bad arguments.');
end

if (length(w) ~= m | min(size(w)) ~= 1)
    error('Dimensions of arguments are mutually incompatible.')
end
w       = w(:)';                      % force w to be row vector

% Discard the first ndisc time steps; if ndisc is not given as input
% argument, use default
if (nargin < 5)
    ndisc = 10^3;
end

% Compute Cholesky factor of covariance matrix C
R       = chol(C);                    % R is upper triangular

% Get ndisc+n independent Gaussian pseudo-random vectors with
% covariance matrix C=R'*R
randvec = randn([ndisc+n,m])*R;

% Add intercept vector to random vectors
randvec = randvec + ones(ndisc+n,1)*w;

% Get transpose of system matrix A (use transpose in simulation because
% we want to obtain the states as row vectors)
AT      = A';

% Take the p initial values of the simulation to equal the process mean,
% which is calculated from the parameters A and w
if any(w)
    %  Process has nonzero mean    mval = inv(B)*w'    where
    %             B = eye(m) - A1 -... - Ap;
    %  Assemble B
    B    = eye(m);
    for j=1:p
        B = B - A(:, (j-1)*m+1:j*m);
    end
    %  Get mean value of process
    mval = w / B';

    %  The optimal forecast of the next state given the p previous
    %  states is stored in the vector x. The vector x is initialized
    %  with the process mean.
    x    = ones(p,1)*mval;
else
    %  Process has zero mean
    x    = zeros(p,m);
end

% Initialize state vectors
u      = [x; zeros(ndisc+n,m)];

% Simulate n+ndisc observations. In order to make use of Matlab's
% vectorization capabilities, the cases p=1 and p>1 must be treated
% separately.
if p==1
    for k=2:ndisc+n+1;
        x(1,:) = u(k-1,:)*AT;
        u(k,:) = x + randvec(k-1,:);
    end
else
    for k=p+1:ndisc+n+p;
        for j=1:p;
            x(j,:) = u(k-j,:)*AT((j-1)*m+1:j*m,:);
        end
        u(k,:) = sum(x)+randvec(k-p,:);
    end
end

% return only the last n simulated state vectors
v = u(ndisc+p+1:ndisc+n+p,:);


function [ax_mps2] = calcPathAx(s_m, v_mps)
%_________________________________________________________________
%% Documentation
%
% Authors:      Alexander Wischnewski (alexander.wischnewski@tum.de)
%
% Start Date:   08.02.2018
%
% Description:  calculates the acceleration profile corresponding to a
%               velocity profile for a given path length. Constant
%               acceleration is assumed between the discretization points.
%
% Inputs:
%   s_m         Vector with path length values
%   v_mps       Vector with velocity at these path points
%
% Outputs:
%   ax_mps2     Vector with accelerations valid from the current to the
%               next point.

% initialize variables
ax_mps2 = zeros(length(v_mps), 1);
% calculate acceleration based on the assumption that it is constant
% between two discretization points. Last point can't be calculated as no
% further velocity information is available for the point behind.
dS = diff(s_m);
dV = diff(v_mps);
ax_mps2(1:(end-1)) = (dV.^2 + 2.*dV.*v_mps(1:(end-1)))./(2.*dS);
% copy last point which could be calculated, as no better information is
% available
ax_mps2(end) = ax_mps2(end-1);


function phi=pt2MaxEntropyCoords(x,v,algorithm,maxIter,epsScal)
%%PT2MAXENTROPYCOORDS Convert a point in a polygon to maximum entropy
%       coordinates. This is a type of barycentric coordinate system in 2D
%       that applies to points in polygons and is described in Section 7 of
%       [1]. These coordinates can be useful for Barycentric mapping and
%       for interpolation.
%
%INPUTS: x The 2XnumPts set of points to convert into maximum entropy
%          coordinates.
%        v The 2XnumBases set of vertices of the polygon defining the
%          coordinate system. The vertices can be given in clockwise or
%          counterclockwise order. It is assumed that the first vertex is
%          not repeated at the end.
% algorithm An optional parameter specifying the edge weight function to
%          use. Possible values are:
%          0 (The default if omitted or an empty matrix is passed) Use the
%            edge weight of Hormann and Sukumar, which is the first one
%            given in [1].
%          1 Use the second edge weight given in [1].
%  maxIter The maximum number of iterations of Newton's method to use. The
%          default if omitted or an empty matrix is passed is 100 and
%          generally, far fewer iterations are actually needed.
%  epsScal Convergence is determined when
%          abs(stepSize)<=epsScal*eps(lambda), where lambda is the 2X1
%          vector parameter being estimated from which the weights phi are
%          derived in [1]. The default if omitted or an empty matrix is
%          passed is 1.
%
%OUTPUTS: phi A numBasesXnumPts set of the maximum entropy coordinates of
%             the points given in x. Note that sum(phi(:,k))=1 for any k.
%             Points on the edge and outside of the polygon will typically
%             return a vector of NaNs.
%
%EXAMPLE 1:
%In this example, the coordinates of two points are found and the points
%are recreated from the phi values. The residual error of the reverse
%conversion is seen to be on the order of finite precision errors.
% numVertices=5;
% v=zeros(2,numVertices);
% v(:,1)=[-2;3];
% v(:,2)=[11;0];
% v(:,3)=[9;10];
% v(:,4)=[7;11];
% v(:,5)=[0;10];
% x=[[6;5],[8;2]];
% phi=pt2MaxEntropyCoords(x,v);
% xBack=barycentricCoords2Pt(phi,v);
% ResidualErr=max(max(abs(xBack-x)))
%
%EXAMPLE 2:
%This draws a convex polygon and a set of horizontal and vertical lines in
%the polygon. Then, the points of the lines are converted to maximum
%entropy coordinates and the vertices of the polygon are moved. After
%conversion back to Cartesian coordinates, one can see how the original
%grid in the polygon has been warped.
% numVertices=5;
% v=zeros(2,numVertices);
% v(:,1)=[-2;3];
% v(:,2)=[11;0];
% v(:,3)=[9;10];
% v(:,4)=[7;11];
% v(:,5)=[0;10];
%
% vertLines=-1:1:10;
% numVertLines=length(vertLines);
% horizLines=1:10;
% numHorizLines=length(horizLines);
% numLinPts=99;
% xVert=zeros(2,numLinPts,numVertLines);
% xHoriz=zeros(2,numLinPts,numHorizLines);
% for k=1:numVertLines
%     xVert(1,:,k)=vertLines(k);
%     xVert(2,:,k)=linspace(0,11,numLinPts);
%     sel=pointIsInPolygon(v,xVert(:,:,k),false)==0;
%     xVert(:,sel,k)=NaN;
% end
% for k=1:numHorizLines
%     xHoriz(1,:,k)=linspace(-2,11,numLinPts);
%     xHoriz(2,:,k)=horizLines(k);
%     sel=pointIsInPolygon(v,xHoriz(:,:,k),false)==0;
%     xHoriz(:,sel,k)=NaN;
% end
%
% figure(1)
% clf
% hold on
% plot([v(1,:),v(1,1)],[v(2,:),v(2,1)],'-c','linewidth',2)
% axis([-2, 12, 0, 12])
% for k=1:numVertLines
%     plot(xVert(1,:,k),xVert(2,:,k),'-r')
% end
% for k=1:numHorizLines
%     plot(xHoriz(1,:,k),xHoriz(2,:,k),'-b')
% end
% phiVert=pt2MaxEntropyCoords(xVert(:,:),v);
% phiHoriz=pt2MaxEntropyCoords(xHoriz(:,:),v);
%
% %Move the vertices, but keep the shape convex and the vertices still in
% %counterclockwise order.
% v(:,1)=[3;2];
% v(:,2)=[8;0];
% v(:,3)=[10;10];
% v(:,4)=[9;11];
% v(:,5)=[3;10];
%
% figure(2)
% clf
% hold on
% plot([v(1,:),v(1,1)],[v(2,:),v(2,1)],'-c','linewidth',2)
% axis([-2, 12, 0, 12])
% %Synthesize the corresponding points in the transformed coordinate
% %system.
% xTransVert=reshape(barycentricCoords2Pt(phiVert,v),[2,numLinPts,numVertLines]);
% xTransHoriz=reshape(barycentricCoords2Pt(phiHoriz,v),[2,numLinPts,numHorizLines]);
% for k=1:numVertLines
%     plot(xTransVert(1,:,k),xTransVert(2,:,k),'-r')
% end
% for k=1:numHorizLines
%     plot(xTransHoriz(1,:,k),xTransHoriz(2,:,k),'-b')
% end
%
%REFERENCES:
%[1] M. S. Floater, "Generalized barycentric coordinates and applications,"
%    Acta Numerica, vol. 24, pp. 161-214, 1 May 2015.
%
%September 2021 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<5||isempty(epsScal))
    epsScal=1;
end

if(nargin<4||isempty(maxIter))
    maxIter=100;
end

if(nargin<3||isempty(algorithm))
    algorithm=0;
end

numPts=size(x,2);
numBases=size(v,2);
phi=zeros(numBases,numPts);
for curPt=1:numPts
    if(any(isnan(x(:,curPt))))
       phi(:,curPt)=NaN;
       continue;
    end

    diffs=bsxfun(@minus,x(:,curPt),v);
    mags=sqrt(sum(diffs.*diffs,1));

    rhoVals=zeros(numBases,1);
    if(algorithm==0)
        for k=1:(numBases-1)
            rhoVals(k)=mags(k)+mags(k+1)-norm(v(:,k)-v(:,k+1));
        end
        rhoVals(numBases)=mags(numBases)+mags(1)-norm(v(:,numBases)-v(:,1));
    elseif(algorithm==1)
        for k=1:(numBases-1)
            rhoVals(k)=mags(k)*mags(k+1)+dot(diffs(:,k),diffs(:,k+1));
        end
        rhoVals(numBases)=mags(numBases)*mags(1)+dot(diffs(:,numBases),diffs(:,1));
    else
       error('Unknown algorithm specified.')
    end

    piVals=zeros(1,numBases);
    piVals(1)=prod(rhoVals(2:(numBases-1)));
    for k=2:(numBases-1)
        piVals(k)=prod(rhoVals([1:(k-2),(k+1):numBases]));
    end
    piVals(numBases)=prod(rhoVals(1:(numBases-2)));

    mi=piVals/sum(piVals);
    d=-diffs;

    %lambda can start uniform.
    lambda=[1/2;1/2];
    %Use Newton's method.
    for curIter=1:maxIter
        [F,H]=getFAndH(lambda,d,mi);

        if(any(~isfinite(H(:))))
           lambda=[NaN;NaN];
           break;
        end

        stepVal=pinv(H)*F;

        if(all(abs(stepVal)<=epsScal*eps(lambda)))
            %Convergence to some multiple of finite precision limits.
            break;
        end
        lambda=lambda-stepVal;
    end

    wi=mi.*exp(sum(bsxfun(@times,lambda,d),1));
    phi(:,curPt)=wi/sum(wi);
end
end

function [gradF,H]=getFAndH(lambda,d,mi)
%%GETFANDH Get the the gradient and the Hessian of the cost function.

mExpdTerms=bsxfun(@times,mi.*exp(sum(bsxfun(@times,lambda,d),1)),d);

%The gradient.
gradF=sum(mExpdTerms,2);
H=zeros(2,2);
H(1,1)=sum(mExpdTerms(1,:).*d(1,:));
H(2,1)=sum(mExpdTerms(1,:).*d(2,:));
H(1,2)=H(2,1);
H(2,2)=sum(mExpdTerms(2,:).*d(2,:));

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.


% Chapter 4: Convex optimization problems
%
%  chebyshev_center_2D.m       - Section 4.3.1: Compute and display the Chebyshev center of a 2D polyhedron
%  chebyshev_center.m          - Section 4.3.1: Compute the Chebyshev center of a polyhedron
%  cantilever_beam_rec.m       - Section 4.5.4: Design of a cantilever beam: recursive formulation (GP)
%  frob_norm_diag_scaling.m    - Section 4.5.4: Frobenius norm diagonal scaling (GP)
%  min_spec_rad_ppl_dynamics.m - Section 4.5.4: Minimum spectral radius via Peron-Frobenius theory (GP)
%  fastest_mixing_MC.m         - Section 4.6.3: Find the fastest mixing Markov chain on a graph
%  ex_4_27.m                   - Exercise 4.27: Matrix fractional minimization using second-order cone programming
%  cantilever_beam.m           - Exercise 4.31: Design of a cantilever beam (GP)
%  ex_4_38.m                   - Exercise 4.38(b): Linear matrix inequalities with one variable
%  ex_4_3.m                    - Exercise 4.3: Solve a simple QP with inequality constraints
%  max_det_psd_completion.m    - Exercise 4.47: Maximum determinant PSD matrix completion
%  channel_capacity.m          - Exercise 4.57: Capacity of a communication channel
%  ex_4_5.m                    - Exercise 4.5: Show the equivalence of 3 convex problem formations
%  logopt_investment.m         - Exercise 4.60: Log-optimal investment strategy
%  cantilever_beam_plot.m      - Plots a cantilever beam as a 3D figure.
help Contents


function cadj=ref_spreadadj_5(coef)
%REF_SPREADADJ_5  Symbol of adjoint spreading function.
%   Usage: cadj=ref_spreadadj_5(c,number);
%
%   Development version by FJ for comparison of different implementations
%   cadj=SPREADADJ(c) will compute the symbol cadj of the spreading
%   operator that is the adjoint of the spreading operator with symbol c.
%
%   Implementation for sparse matrix using loop

L=size(coef,1);

[row,col,val]=find(coef);

% Optimization note : As said in note of case 3, we are computing
% the Lth root of unity which have special properties and symetries
% taht could be exploited to highly reduce this computation.
% Furthermore here we precompute every possible exponential
% term even if some are unneeded. But there is no simple way to
% know which one should be computed and the computation needed to
% know it could be worst than this computation. Nevertheless, it
% could be used in a different implementation
temp=exp((-i*2*pi/L)*(0:L-1));

cadj=spalloc(L,L,length(val));
for k=1:length(val)
  ii=mod(L-row(k)+1, L);
  jj=mod(L-col(k)+1, L);
  cadj(ii+1,jj+1)=conj(val(k))*temp(mod(ii*jj,L)+1);
end


function [C, L, U] = SpectralClustering(W, k, Type)
%SPECTRALCLUSTERING Executes spectral clustering algorithm
%   Executes the spectral clustering algorithm defined by
%   Type on the adjacency matrix W and returns the k cluster
%   indicator vectors as columns in C.
%   If L and U are also called, the (normalized) Laplacian and
%   eigenvectors will also be returned.
%
%   'W' - Adjacency matrix, needs to be square
%   'k' - Number of clusters to look for
%   'Type' - Defines the type of spectral clustering algorithm
%            that should be used. Choices are:
%      1 - Unnormalized
%      2 - Normalized according to Shi and Malik (2000)
%      3 - Normalized according to Jordan and Weiss (2002)
%
%   References:
%   - Ulrike von Luxburg, "A Tutorial on Spectral Clustering",
%     Statistics and Computing 17 (4), 2007
%
%   Author: Ingo Buerk
%   Year  : 2011/2012
%   Bachelor Thesis

% calculate degree matrix
degs = sum(W, 2);
D    = sparse(1:size(W, 1), 1:size(W, 2), degs);

% compute unnormalized Laplacian
L = D - W;

% compute normalized Laplacian if needed
switch Type
    case 2
        % avoid dividing by zero
        degs(degs == 0) = eps;
        % calculate inverse of D
        D = spdiags(1./degs, 0, size(D, 1), size(D, 2));

        % calculate normalized Laplacian
        L = D * L;
    case 3
        % avoid dividing by zero
        degs(degs == 0) = eps;
        % calculate D^(-1/2)
        D = spdiags(1./(degs.^0.5), 0, size(D, 1), size(D, 2));

        % calculate normalized Laplacian
        L = D * L * D;
end

% compute the eigenvectors corresponding to the k smallest
% eigenvalues
diff   = eps;
[U, ~] = eigs(L, k, diff);

% in case of the Jordan-Weiss algorithm, we need to normalize
% the eigenvectors row-wise
if Type == 3
    U = bsxfun(@rdivide, U, sqrt(sum(U.^2, 2)));
end

% now use the k-means algorithm to cluster U row-wise
% C will be a n-by-1 matrix containing the cluster number for
% each data point
C = kmeans(U, k, 'start', 'sample', ...
                 'EmptyAction', 'singleton');

% now convert C to a n-by-k matrix containing the k indicator
% vectors as columns
C = sparse(1:size(D, 1), C, 1);

end


%% Efficient subpixel image registration by cross-correlation.
% Registers two images (2-D rigid translation) within a  fraction
% of a pixel specified by the user. Instead of computing a zero-padded FFT
% (fast Fourier transform), this code uses selective upsampling by a
% matrix-multiply DFT (discrete FT) to dramatically reduce computation time and memory
% without sacrificing accuracy. With this procedure all the image points are used to
% compute the upsampled cross-correlation in a very small neighborhood around its peak. This
% algorithm is referred to as the single-step DFT algorithm in [1].
%
% [1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup,
% "Efficient subpixel image registration algorithms," Opt. Lett. 33,
% 156-158 (2008).
%
% -----------------------------------------------------------------------
%
% Copyright (c) 2016, Manuel Guizar Sicairos, James R. Fienup, University of Rochester
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * Redistributions in binary form must reproduce the above copyright
%       notice, this list of conditions and the following disclaimer in
%       the documentation and/or other materials provided with the distribution
%     * Neither the name of the University of Rochester nor the names
%       of its contributors may be used to endorse or promote products derived
%       from this software without specific prior written permission.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
% --------------------------------------------------------------------------

%% Syntax
% The code receives the FFT of the reference and the shifted images, and an
% (integer) upsampling factor. The code expects FFTs with DC in (1,1) so do not use
% fftshift.
%
%    output = dftregistration(fft2(f),fft2(g),usfac);
%
% The images are registered to within 1/usfac of a pixel.
%
% output(1) is the normalized root-mean-squared error (NRMSE) [1] between f and
% g.
%
% output(2) is the global phase difference between the two images (should be
% zero if images are real-valued and non-negative).
%
% output(3) and output(4) are the row and column shifts between f and g respectively.
%
%    [output Greg] = dftregistration(fft2(f),fft2(g),usfac);
%
% Greg is an optional output, it returns the Fourier transform of the registered version of g,
% where the global phase difference [output(2)] is also compensated.

%% Obtain a reference and shifted images
% To illustrate the use of the algorithm, lets obtain a reference and a
% shifted image. First we read the reference image f(x,y)
f = im2double(imread('cameraman.tif'));

%%
% Define g(x,y) as a version of f(x,y) shifted by fractional values of a
% pixel and multiplied by a global phase.
deltar = -3.48574;
deltac = 8.73837;
phase = 2;
[nr,nc]=size(f);
Nr = ifftshift((-fix(nr/2):ceil(nr/2)-1));
Nc = ifftshift((-fix(nc/2):ceil(nc/2)-1));
[Nc,Nr] = meshgrid(Nc,Nr);
g = ifft2(fft2(f).*exp(1i*2*pi*(deltar*Nr/nr+deltac*Nc/nc))).*exp(-1i*phase);
figure(1);
subplot(1,2,1);
imshow(abs(f));
title('Reference image, f(x,y)')
subplot(1,2,2);
imshow(abs(g));
title('Shifted image, g(x,y)')
%%
% We have shifted the image by 8.73837 and -3.48574 pixels in the x and
% y direction, respectively, and added a phase of 2 radians to g(x,y). The shift
% was implemented by applying a linear phase on its
% FT, thus we have assumed that the images wrap around (features leaving one
% side of the window reappear on the opposite side) and that the image is band-limited
% (interpolated by a sinc function). Cross-correlation image registration by DFTs
% (both the matrix-multiply DFT and the zero-padded FFT) share these assumptions.
%
% This registration technique is well suited to compare images that are captured
% in Fourier domain (i.e. to evaluate an image reconstruction by holography
% or phase retrieval) which are strictly band-limited and exhibit the
% wrap-around effect.
%
% Even though the registration code assumes band-limited images that wrap around, we
% have obtained very good results when applying it to
% band-limited microscope images, and aliased imagery. That is when shifting
% the image brings in new content instead of wrapping it around or when the
% images are not band-limited.

%% Sample Image Registration
% dftregistration.m receives the FT of f and g and the upsampling factor.
% The code expects DC of the FTs at (1,1) so don't use fftshift.
%
% We now use the image registration code to register f and g within 0.01
% pixels by specifying an upsampling parameter of 100
usfac = 100;
[output, Greg] = dftregistration(fft2(f),fft2(g),usfac);
display(output),

%%
% The pixel shift error (difference between the true and obtained shifts)
% is 0.0016 and 0.0043 in the x and y directions respectively. Well within
% the expected accuracy of 0.01. Notice that using the conventional zero-padded
% FFT approach with the same accuracy, would
% require computation of a 25,600x25,600 FFT, which would require more than
% 19 Gbytes of RAM and a very comfortable chair.
%
% The following plot shows the reference image and the registered image.
figure(1);
subplot(1,2,1);
imshow(abs(f));
title('Reference image, f(x,y)')
subplot(1,2,2);
imshow(abs(ifft2(Greg)));
title('Registered image, gr(x,y)')
%% Disclaimer
% I have made every effort to evaluate the proper working of this code
% under many different conditions. However, it is the responsibility of
% the user to ensure that this registration code is adequate and working
% correcntly for their application.
%
% Feel free to e-mail me with questions or comments.


function value = i4_bit_lo0 ( n )

%*****************************************************************************80
%
%% I4_BIT_LO0 returns the position of the low 0 bit base 2 in an integer.
%
%  Example:
%
%       N    Binary    Lo 0
%    ----    --------  ----
%       0           0     1
%       1           1     2
%       2          10     1
%       3          11     3
%       4         100     1
%       5         101     2
%       6         110     1
%       7         111     4
%       8        1000     1
%       9        1001     2
%      10        1010     1
%      11        1011     3
%      12        1100     1
%      13        1101     2
%      14        1110     1
%      15        1111     5
%      16       10000     1
%      17       10001     2
%    1023  1111111111     1
%    1024 10000000000     1
%    1025 10000000001     1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 April 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the integer to be measured.
%    N should be nonnegative.
%
%    Output, integer VALUE, the position of the low 1 bit.
%
  bit = 0;
  i = n;

  while ( 1 )

    bit = bit + 1;
    i2 = floor ( i / 2 );

    if ( i == 2 * i2 )
      break
    end

    i = i2;

  end

  value = bit;

  return
end


% CIRCLES3D  Create a data set containing 2 circles in 3 dimensions.
%
%   DATA = CIRCLES3D(N)
%
%	Creates a data set containing N points in 3 dimensions.
%
% If N is a vector of sizes, exactly N(I) objects are generated
% for class I, I = 1,2.Default: N = [50 50].
%
% See also DATASETS, PRDATASETS

% Copyright: E. Pekalska, R.P.W. Duin, duin@ph.tn.tudelft.nl
% Faculty of Applied Sciences, Delft University of Technology
% P.O. Box 5046, 2600 GA Delft, The Netherlands

% $Id: circles3d.m,v 1.2 2006/03/08 22:06:58 duin Exp $

function data = circles3d(N)
			if nargin< 1, N = [50 50]; end
	N = genclass(N,ones(1,2)/2);

	n2a = N(1);
	n2b = N(2);
	ha = 0:(2*pi/n2a):2*pi*(n2a/(n2a+1)); ha = ha';
	hb = 0:(2*pi/n2b):2*pi*(n2b/(n2b+1)); hb = hb';

	a = [ sin(ha) cos(ha) zeros(n2a,1) ];
	b = [ sin(hb) cos(hb) ones(n2b,1)  ];

	data = prdataset([a;b],genlab(N));
	data = setname(data,'3D Circles');

return


%ELLIPSE2POLY  Approximates an elliptic arc with a polyline
%
%     pts = cv.ellipse2Poly(center, axes)
%     [...] = cv.ellipse2Poly(..., 'OptionName', optionValue, ...)
%
% ## Input
% * __center__ Center of the arc `[x,y]`.
% * __axes__ Half of the size of the ellipse main axes `[a,b]`. See cv.ellipse
%   for details.
%
% ## Output
% * __pts__ Output vector of polyline vertices. An Nx2 numeric matrix
%   `[x y; ...]`.
%
% ## Options
% * __Angle__ Rotation angle of the ellipse in degrees. See cv.ellipse for
%   details. default 0.
% * __StartAngle__ Starting angle of the elliptic arc in degrees. default 0
% * __EndAngle__ Ending angle of the elliptic arc in degrees. default 360
% * __Delta__ Angle between the subsequent polyline vertices. It defines the
%   approximation accuracy. default 5.
%
% The function cv.ellipse2Poly computes the vertices of a polyline that
% approximates the specified elliptic arc. It is used by cv.ellipse. If
% `StartAngle` is greater than `EndAngle`, they are swapped.
%
% See also: cv.ellipse
%


function lambda = minij_eigenvalues ( n )

%*****************************************************************************80
%
%% MINIJ_EIGENVALUES returns the eigenvalues of the MINIJ matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Output, real LAMBDA(N,1), the eigenvalues.
%
  lambda = zeros ( n, 1 );

  for i = 1 : n
    angle = ( 2 * i - 1 ) * pi / ( 2 * n + 1 );
    lambda(i,1) = 0.5 / ( 1.0 - cos ( angle ) );
  end

  return
end