function varargout = ackley(x)
%ACKLEY Ackley's function

if nargin == 0
    varargout{1} = [-8,-8];     % LB
    varargout{2} = [2,2];       % UB
    varargout{3} = [0,20];      % Zlim
    varargout{4} = [-26.5,60];  % view
    varargout{5} = [0,0];       % xmin
    varargout{6} = 'Ackley function';    % name
    varargout{7} = [-6,-5];     % default x0
    return;
end
    varargout{1} = -20 * exp(-0.2 * sqrt( sum(x .* x, 2)/ 2)) ...
        - exp(sum(cos(2*pi*x),2) / 2) ...
        + 20 + 2.7182818284590452353602874713526625;
    varargout{2} = [];
end


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

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

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

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta
%

hx = sigmoid(X * theta); %hypothesis, m * 1
% Hint: The computation of the cost function and gradients can be
%       efficiently vectorized. For example, consider the computation
%
%           sigmoid(X * theta)
%
%       Each row of the resulting matrix will contain the value of the
%       prediction for that example. You can make use of this to vectorize
%       the cost function and gradient computations.
%
J = 1 / m * sum(-y' * log(hx) - (1 - y)' * log(1 - hx)) + lambda / (2 * m) * theta(2:end)' * theta(2:end);

% Hint: When computing the gradient of the regularized cost function,
%       there're many possible vectorized solutions, but one solution
%       looks like:
%           grad = (unregularized gradient for logistic regression)
%           temp = theta;
%           temp(1) = 0;   % because we don't add anything for j = 0
%           grad = grad + YOUR_CODE_HERE (using the temp variable)
%
gradf = (1 / m) * (X(:, 1)' * (hx - y));
gradb = (1 / m) * (X(:, 2:end)' * (hx - y)) + lambda * theta(2:end) / m;

grad = [gradf;gradb];
size(grad)

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

grad = grad(:);

end


function area = sphere_cap_area_nd ( ndim, r, h )

%*****************************************************************************80
%
%% SPHERE_CAP_AREA_ND computes the area of a spherical cap in ND.
%
%  Discussion:
%
%    The spherical cap is a portion of the surface of the sphere:
%
%      sum ( X(1:N)^2 ) = R^2
%
%    which is no more than H units from the uppermost point on the sphere.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 July 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Thomas Ericson and Victor Zinoviev,
%    Codes on Euclidean Spheres,
%    Elsevier, 2001, pages 439-441.
%    QA166.7 E75
%
%  Parameters:
%
%    Input, integer NDIM, the dimension of the space.
%
%    Input, real R, the radius of the sphere.
%
%    Input, real H, the "thickness" of the spherical cap,
%    which is normally between 0 and 2 * R.
%
%    Output, real AREA, the area of the spherical cap.
%
  if ( h <= 0.0 )
    area = 0.0;
    return
  end

  if ( 2.0 * r <= h )
    area = sphere_area_nd ( ndim, r );
    return
  end
%
%  For cases where R < H < 2 * R, work with the complementary region.
%
  haver_sine = sqrt ( ( 2.0 * r - h ) * h );

  theta = r8_asin ( haver_sine / r );

  if ( ndim < 1 )

    area = -1.0;

  elseif ( ndim == 1 )

    area = 0.0;

  elseif ( ndim == 2 )

    area = 2.0 * theta * r;

  else

    ti = theta;

    tj = ti;
    ti = 1.0 - cos ( theta );

    for i = 2 : ndim-2
      tk = tj;
      tj = ti;
      ti = ( ( i - 1 ) * tk - cos ( theta ) * sin ( theta )^( i - 1 ) ) / i;
    end

    area = sphere_k ( ndim-1 ) * ti * r^( ndim - 1 );

  end
%
%  Adjust for cases where R < H < 2R.
%
  if ( r < h )
    area2 = sphere_area_nd ( ndim, r );
    area = area2 - area;
  end

  return
end


% book : Signals and Systems Laboratory with MATLAB
% authors : Alex Palamides & Anastasia Veloni
%
%
% Problem 4
% Inverse z-Transform computation of X(z)=(2z+3)/(z^2+5z+6)

% a)in rational form
syms n z
X=(2*z+3)/(z^2+5*z+6);
iztrans(X,n)

% b) in partial fraction form
num=[ 2 3]
den= [ 1 5 6];
[R,P,K]=residue(num,den)

X=3/(z+3)-1/(z+2)
iztrans(X,n)


%
% lellipf(phi, k, errtol)
%
% Inputs:
%
%   phi     Input angle vector size 1 or 1xN.
%   k       Input parameter vector size 1 or 1xN.
%   errtol  Error tolerance for Carlson's algorithms.
%
% Matlab function to compute Legendre's (incomplete) elliptic integral
% F(phi, k).  Uses a vectorized implementation of Carlson's Duplication Algorithms
% for symmetric elliptic integrals as found in "Computing Elliptic
% Integrals by Duplication," by B. C. Carlson, Numer. Math. 33, 1-16 (1979)
% and also found in ACM TOMS Algorithm 577.  Section 4 in the paper cited
% here describes how to convert between the symmetric elliptic integrals
% and Legendre's elliptic integrals.
%
% Returns NaN's for any argument values outside input range.
%

function f = lellipf(phi, k, errtol)

% Argument checking for vectorization:
lphi = length(phi);
lk = length(k);
errflag = logical(0);
if (lphi ~= lk)
    if (lphi==1)
        phivec = phi * ones(1,lk);
        kvec = k;
    elseif (lk==1)
        kvec = k * ones(1,lphi);
        phivec = phi;
    else
        disp('Incompatible input vector dimensions in lellipf!');
        errflag = logical(1);
    end
else
    phivec = phi;
    kvec = k;
end

if ~errflag
    snphi = sin(phivec);
    csphi = cos(phivec);
    csphi2 = csphi .* csphi;
    onesvec = ones(1,length(phivec));
    y = onesvec - kvec.*kvec .* snphi.*snphi;
    f = snphi .* rf(csphi2,  y, onesvec, errtol);
else
    f = NaN;
end


% Euclidean distance between polyhedra
% Section 8.2.1, Boyd & Vandenberghe "Convex Optimization"
% Joelle Skaf - 10/09/05
%
% Given two polyhedra C = {x | A1*x <= b1} and D = {x | A2*x <= b2}, the
% distance between them is the optimal value of the problem:
%           minimize    || x - y ||_2
%               s.t.    A1*x <= b1
%                       A2*y <= b2

% Input data
randn('state',0);
rand('state',0);

n  = 5;
m1 = 2*n;
m2 = 3*n;
A1 = randn(m1,n);
A2 = randn(m2,n);
b1 = rand(m1,1);
b2 = rand(m2,1) + A2*randn(n,1);

% Solution via CVX
cvx_begin
    variables x(n) y(n)
    minimize (norm(x - y))
    A1*x <= b1;
    A2*y <= b2;
cvx_end

% Displaying results
disp('------------------------------------------------------------------');
disp('The distance between the 2 polyhedra C and D is: ' );
disp(['dist(C,D) = ' num2str(cvx_optval)]);


% Euclidean distance between polyhedra in 2D
% Section 8.2.1, Boyd & Vandenberghe "Convex Optimization"
% Joelle Skaf - 10/09/05
% (a figure is generated)
%
% Given two polyhedra C = {x | A1*x <= b1} and D = {x | A2*x <= b2}, the
% distance between them is the optimal value of the problem:
%           minimize    || x - y ||_2
%               s.t.    A1*x <= b1
%                       A2*y <= b2
% Note: here x is in R^2

% Input data
randn('seed',0);
n = 2;
m = 2*n;
A1 = randn(m,n);
b1 = randn(m,1);
A2 = randn(m,n);
b2 = randn(m,1);

fprintf(1,'Computing the distance between the 2 polyhedra...');
% Solution via CVX
cvx_begin
    variables x(n) y(n)
    minimize (norm(x - y))
    norm(x,1) <= 2; %#ok
    norm(y-[4;3],inf) <=1; %#ok
cvx_end

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

% Displaying results
disp('------------------------------------------------------------------');
disp('The distance between the 2 polyhedra C and D is: ' );
disp(['dist(C,D) = ' num2str(cvx_optval)]);
disp('The optimal points are: ')
disp('x = '); disp(x);
disp('y = '); disp(y);

%Plotting
figure;
fill([-2; 0; 2; 0],[0;2;0;-2],'b', [3;5;5;3],[2;2;4;4],'r')
axis([-3 6 -3 6])
axis square
hold on;
plot(x(1),x(2),'k.')
plot(y(1),y(2),'k.')
plot([x(1) y(1)],[x(2) y(2)])
title('Euclidean distance between 2 polyhedron in R^2');
xlabel('x_1');
ylabel('x_2');


function [out] = GLCM_Features1(glcmin,pairs)
%
% GLCM_Features1 helps to calculate the features from the different GLCMs
% that are input to the function. The GLCMs are stored in a i x j x n
% matrix, where n is the number of GLCMs calculated usually due to the
% different orientation and displacements used in the algorithm. Usually
% the values i and j are equal to 'NumLevels' parameter of the GLCM
% computing function graycomatrix(). Note that matlab quantization values
% belong to the set {1,..., NumLevels} and not from {0,...,(NumLevels-1)}
% as provided in some references
% http://www.mathworks.com/access/helpdesk/help/toolbox/images/graycomatrix
% .html
%
% Although there is a function graycoprops() in Matlab Image Processing
% Toolbox that computes four parameters Contrast, Correlation, Energy,
% and Homogeneity. The paper by Haralick suggests a few more parameters
% that are also computed here. The code is not fully vectorized and hence
% is not an efficient implementation but it is easy to add new features
% based on the GLCM using this code. Takes care of 3 dimensional glcms
% (multiple glcms in a single 3D array)
%
% If you find that the values obtained are different from what you expect
% or if you think there is a different formula that needs to be used
% from the ones used in this code please let me know.
% A few questions which I have are listed in the link
% http://www.mathworks.com/matlabcentral/newsreader/view_thread/239608
%
% I plan to submit a vectorized version of the code later and provide
% updates based on replies to the above link and this initial code.
%
% Features computed
% Autocorrelation: [2]                      (out.autoc)
% Contrast: matlab/[1,2]                    (out.contr)
% Correlation: matlab                       (out.corrm)
% Correlation: [1,2]                        (out.corrp)
% Cluster Prominence: [2]                   (out.cprom)
% Cluster Shade: [2]                        (out.cshad)
% Dissimilarity: [2]                        (out.dissi)
% Energy: matlab / [1,2]                    (out.energ)
% Entropy: [2]                              (out.entro)
% Homogeneity: matlab                       (out.homom)
% Homogeneity: [2]                          (out.homop)
% Maximum probability: [2]                  (out.maxpr)
% Sum of sqaures: Variance [1]              (out.sosvh)
% Sum average [1]                           (out.savgh)
% Sum variance [1]                          (out.svarh)
% Sum entropy [1]                           (out.senth)
% Difference variance [1]                   (out.dvarh)
% Difference entropy [1]                    (out.denth)
% Information measure of correlation1 [1]   (out.inf1h)
% Informaiton measure of correlation2 [1]   (out.inf2h)
% Inverse difference (INV) is homom [3]     (out.homom)
% Inverse difference normalized (INN) [3]   (out.indnc)
% Inverse difference moment normalized [3]  (out.idmnc)
%
% The maximal correlation coefficient was not calculated due to
% computational instability
% http://murphylab.web.cmu.edu/publications/boland/boland_node26.html
%
% Formulae from MATLAB site (some look different from
% the paper by Haralick but are equivalent and give same results)
% Example formulae:
% Contrast = sum_i(sum_j(  (i-j)^2 * p(i,j) ) ) (same in matlab/paper)
% Correlation = sum_i( sum_j( (i - u_i)(j - u_j)p(i,j)/(s_i.s_j) ) ) (m)
% Correlation = sum_i( sum_j( ((ij)p(i,j) - u_x.u_y) / (s_x.s_y) ) ) (p[2])
% Energy = sum_i( sum_j( p(i,j)^2 ) )           (same in matlab/paper)
% Homogeneity = sum_i( sum_j( p(i,j) / (1 + |i-j|) ) ) (as in matlab)
% Homogeneity = sum_i( sum_j( p(i,j) / (1 + (i-j)^2) ) ) (as in paper)
%
% Where:
% u_i = u_x = sum_i( sum_j( i.p(i,j) ) ) (in paper [2])
% u_j = u_y = sum_i( sum_j( j.p(i,j) ) ) (in paper [2])
% s_i = s_x = sum_i( sum_j( (i - u_x)^2.p(i,j) ) ) (in paper [2])
% s_j = s_y = sum_i( sum_j( (j - u_y)^2.p(i,j) ) ) (in paper [2])
%
%
% Normalize the glcm:
% Compute the sum of all the values in each glcm in the array and divide
% each element by it sum
%
% Haralick uses 'Symmetric' = true in computing the glcm
% There is no Symmetric flag in the Matlab version I use hence
% I add the diagonally opposite pairs to obtain the Haralick glcm
% Here it is assumed that the diagonally opposite orientations are paired
% one after the other in the matrix
% If the above assumption is true with respect to the input glcm then
% setting the flag 'pairs' to 1 will compute the final glcms that would result
% by setting 'Symmetric' to true. If your glcm is computed using the
% Matlab version with 'Symmetric' flag you can set the flag 'pairs' to 0
%
% References:
% 1. R. M. Haralick, K. Shanmugam, and I. Dinstein, Textural Features of
% Image Classification, IEEE Transactions on Systems, Man and Cybernetics,
% vol. SMC-3, no. 6, Nov. 1973
% 2. L. Soh and C. Tsatsoulis, Texture Analysis of SAR Sea Ice Imagery
% Using Gray Level Co-Occurrence Matrices, IEEE Transactions on Geoscience
% and Remote Sensing, vol. 37, no. 2, March 1999.
% 3. D A. Clausi, An analysis of co-occurrence texture statistics as a
% function of grey level quantization, Can. J. Remote Sensing, vol. 28, no.
% 1, pp. 45-62, 2002
% 4. http://murphylab.web.cmu.edu/publications/boland/boland_node26.html
%
%
% Example:
%
% Usage is similar to graycoprops() but needs extra parameter 'pairs' apart
% from the GLCM as input
% I = imread('circuit.tif');
% GLCM2 = graycomatrix(I,'Offset',[2 0;0 2]);
% stats = GLCM_features1(GLCM2,0)
% The output is a structure containing all the parameters for the different
% GLCMs
%
% [Avinash Uppuluri: avinash_uv@yahoo.com: Last modified: 11/20/08]

% If 'pairs' not entered: set pairs to 0
if ((nargin > 2) || (nargin == 0))
   error('Too many or too few input arguments. Enter GLCM and pairs.');
elseif ( (nargin == 2) )
    if ((size(glcmin,1) <= 1) || (size(glcmin,2) <= 1))
       error('The GLCM should be a 2-D or 3-D matrix.');
    elseif ( size(glcmin,1) ~= size(glcmin,2) )
        error('Each GLCM should be square with NumLevels rows and NumLevels cols');
    end
elseif (nargin == 1) % only GLCM is entered
    pairs = 0; % default is numbers and input 1 for percentage
    if ((size(glcmin,1) <= 1) || (size(glcmin,2) <= 1))
       error('The GLCM should be a 2-D or 3-D matrix.');
    elseif ( size(glcmin,1) ~= size(glcmin,2) )
       error('Each GLCM should be square with NumLevels rows and NumLevels cols');
    end
end

format long e
if (pairs == 1)
    newn = 1;
    for nglcm = 1:2:size(glcmin,3)
        glcm(:,:,newn)  = glcmin(:,:,nglcm) + glcmin(:,:,nglcm+1);
        newn = newn + 1;
    end
elseif (pairs == 0)
    glcm = glcmin;
end

size_glcm_1 = size(glcm,1);
size_glcm_2 = size(glcm,2);
size_glcm_3 = size(glcm,3);

% checked
out.autoc = zeros(1,size_glcm_3); % Autocorrelation: [2]
out.contr = zeros(1,size_glcm_3); % Contrast: matlab/[1,2]
out.corrm = zeros(1,size_glcm_3); % Correlation: matlab
out.corrp = zeros(1,size_glcm_3); % Correlation: [1,2]
out.cprom = zeros(1,size_glcm_3); % Cluster Prominence: [2]
out.cshad = zeros(1,size_glcm_3); % Cluster Shade: [2]
out.dissi = zeros(1,size_glcm_3); % Dissimilarity: [2]
out.energ = zeros(1,size_glcm_3); % Energy: matlab / [1,2]
out.entro = zeros(1,size_glcm_3); % Entropy: [2]
out.homom = zeros(1,size_glcm_3); % Homogeneity: matlab
out.homop = zeros(1,size_glcm_3); % Homogeneity: [2]
out.maxpr = zeros(1,size_glcm_3); % Maximum probability: [2]

out.sosvh = zeros(1,size_glcm_3); % Sum of sqaures: Variance [1]
out.savgh = zeros(1,size_glcm_3); % Sum average [1]
out.svarh = zeros(1,size_glcm_3); % Sum variance [1]
out.senth = zeros(1,size_glcm_3); % Sum entropy [1]
out.dvarh = zeros(1,size_glcm_3); % Difference variance [4]
%out.dvarh2 = zeros(1,size_glcm_3); % Difference variance [1]
out.denth = zeros(1,size_glcm_3); % Difference entropy [1]
out.inf1h = zeros(1,size_glcm_3); % Information measure of correlation1 [1]
out.inf2h = zeros(1,size_glcm_3); % Informaiton measure of correlation2 [1]
%out.mxcch = zeros(1,size_glcm_3);% maximal correlation coefficient [1]
%out.invdc = zeros(1,size_glcm_3);% Inverse difference (INV) is homom [3]
out.indnc = zeros(1,size_glcm_3); % Inverse difference normalized (INN) [3]
out.idmnc = zeros(1,size_glcm_3); % Inverse difference moment normalized [3]

% correlation with alternate definition of u and s
%out.corrm2 = zeros(1,size_glcm_3); % Correlation: matlab
%out.corrp2 = zeros(1,size_glcm_3); % Correlation: [1,2]

glcm_sum  = zeros(size_glcm_3,1);
glcm_mean = zeros(size_glcm_3,1);
glcm_var  = zeros(size_glcm_3,1);

% http://www.fp.ucalgary.ca/mhallbey/glcm_mean.htm confuses the range of
% i and j used in calculating the means and standard deviations.
% As of now I am not sure if the range of i and j should be [1:Ng] or
% [0:Ng-1]. I am working on obtaining the values of mean and std that get
% the values of correlation that are provided by matlab.
u_x = zeros(size_glcm_3,1);
u_y = zeros(size_glcm_3,1);
s_x = zeros(size_glcm_3,1);
s_y = zeros(size_glcm_3,1);

% % alternate values of u and s
% u_x2 = zeros(size_glcm_3,1);
% u_y2 = zeros(size_glcm_3,1);
% s_x2 = zeros(size_glcm_3,1);
% s_y2 = zeros(size_glcm_3,1);

% checked p_x p_y p_xplusy p_xminusy
p_x = zeros(size_glcm_1,size_glcm_3); % Ng x #glcms[1]
p_y = zeros(size_glcm_2,size_glcm_3); % Ng x #glcms[1]
p_xplusy = zeros((size_glcm_1*2 - 1),size_glcm_3); %[1]
p_xminusy = zeros((size_glcm_1),size_glcm_3); %[1]
% checked hxy hxy1 hxy2 hx hy
hxy  = zeros(size_glcm_3,1);
hxy1 = zeros(size_glcm_3,1);
hx   = zeros(size_glcm_3,1);
hy   = zeros(size_glcm_3,1);
hxy2 = zeros(size_glcm_3,1);

%Q    = zeros(size(glcm));

for k = 1:size_glcm_3 % number glcms

    glcm_sum(k) = sum(sum(glcm(:,:,k)));
    glcm(:,:,k) = glcm(:,:,k)./glcm_sum(k); % Normalize each glcm
    glcm_mean(k) = mean2(glcm(:,:,k)); % compute mean after norm
    glcm_var(k)  = (std2(glcm(:,:,k)))^2;

    for i = 1:size_glcm_1

        for j = 1:size_glcm_2

            out.contr(k) = out.contr(k) + (abs(i - j))^2.*glcm(i,j,k);
            out.dissi(k) = out.dissi(k) + (abs(i - j)*glcm(i,j,k));
            out.energ(k) = out.energ(k) + (glcm(i,j,k).^2);
            out.entro(k) = out.entro(k) - (glcm(i,j,k)*log(glcm(i,j,k) + eps));
            out.homom(k) = out.homom(k) + (glcm(i,j,k)/( 1 + abs(i-j) ));
            out.homop(k) = out.homop(k) + (glcm(i,j,k)/( 1 + (i - j)^2));
            % [1] explains sum of squares variance with a mean value;
            % the exact definition for mean has not been provided in
            % the reference: I use the mean of the entire normalized glcm
            out.sosvh(k) = out.sosvh(k) + glcm(i,j,k)*((i - glcm_mean(k))^2);

            %out.invdc(k) = out.homom(k);
            out.indnc(k) = out.indnc(k) + (glcm(i,j,k)/( 1 + (abs(i-j)/size_glcm_1) ));
            out.idmnc(k) = out.idmnc(k) + (glcm(i,j,k)/( 1 + ((i - j)/size_glcm_1)^2));
            u_x(k)          = u_x(k) + (i)*glcm(i,j,k); % changed 10/26/08
            u_y(k)          = u_y(k) + (j)*glcm(i,j,k); % changed 10/26/08
            % code requires that Nx = Ny
            % the values of the grey levels range from 1 to (Ng)
        end

    end
    out.maxpr(k) = max(max(glcm(:,:,k)));
end
% glcms have been normalized:
% The contrast has been computed for each glcm in the 3D matrix
% (tested) gives similar results to the matlab function

for k = 1:size_glcm_3

    for i = 1:size_glcm_1

        for j = 1:size_glcm_2
            p_x(i,k) = p_x(i,k) + glcm(i,j,k);
            p_y(i,k) = p_y(i,k) + glcm(j,i,k); % taking i for j and j for i
            if (ismember((i + j),[2:2*size_glcm_1]))
                p_xplusy((i+j)-1,k) = p_xplusy((i+j)-1,k) + glcm(i,j,k);
            end
            if (ismember(abs(i-j),[0:(size_glcm_1-1)]))
                p_xminusy((abs(i-j))+1,k) = p_xminusy((abs(i-j))+1,k) +...
                    glcm(i,j,k);
            end
        end
    end

%     % consider u_x and u_y and s_x and s_y as means and standard deviations
%     % of p_x and p_y
%     u_x2(k) = mean(p_x(:,k));
%     u_y2(k) = mean(p_y(:,k));
%     s_x2(k) = std(p_x(:,k));
%     s_y2(k) = std(p_y(:,k));

end

% marginal probabilities are now available [1]
% p_xminusy has +1 in index for matlab (no 0 index)
% computing sum average, sum variance and sum entropy:
for k = 1:(size_glcm_3)

    for i = 1:(2*(size_glcm_1)-1)
        out.savgh(k) = out.savgh(k) + (i+1)*p_xplusy(i,k);
        % the summation for savgh is for i from 2 to 2*Ng hence (i+1)
        out.senth(k) = out.senth(k) - (p_xplusy(i,k)*log(p_xplusy(i,k) + eps));
    end

end
% compute sum variance with the help of sum entropy
for k = 1:(size_glcm_3)

    for i = 1:(2*(size_glcm_1)-1)
        out.svarh(k) = out.svarh(k) + (((i+1) - out.senth(k))^2)*p_xplusy(i,k);
        % the summation for savgh is for i from 2 to 2*Ng hence (i+1)
    end

end
% compute difference variance, difference entropy,
for k = 1:size_glcm_3
% out.dvarh2(k) = var(p_xminusy(:,k));
% but using the formula in
% http://murphylab.web.cmu.edu/publications/boland/boland_node26.html
% we have for dvarh
    for i = 0:(size_glcm_1-1)
        out.denth(k) = out.denth(k) - (p_xminusy(i+1,k)*log(p_xminusy(i+1,k) + eps));
        out.dvarh(k) = out.dvarh(k) + (i^2)*p_xminusy(i+1,k);
    end
end

% compute information measure of correlation(1,2) [1]
for k = 1:size_glcm_3
    hxy(k) = out.entro(k);
    for i = 1:size_glcm_1

        for j = 1:size_glcm_2
            hxy1(k) = hxy1(k) - (glcm(i,j,k)*log(p_x(i,k)*p_y(j,k) + eps));
            hxy2(k) = hxy2(k) - (p_x(i,k)*p_y(j,k)*log(p_x(i,k)*p_y(j,k) + eps));
%             for Qind = 1:(size_glcm_1)
%                 Q(i,j,k) = Q(i,j,k) +...
%                     ( glcm(i,Qind,k)*glcm(j,Qind,k) / (p_x(i,k)*p_y(Qind,k)) );
%             end
        end
        hx(k) = hx(k) - (p_x(i,k)*log(p_x(i,k) + eps));
        hy(k) = hy(k) - (p_y(i,k)*log(p_y(i,k) + eps));
    end
    out.inf1h(k) = ( hxy(k) - hxy1(k) ) / ( max([hx(k),hy(k)]) );
    out.inf2h(k) = ( 1 - exp( -2*( hxy2(k) - hxy(k) ) ) )^0.5;
%     eig_Q(k,:)   = eig(Q(:,:,k));
%     sort_eig(k,:)= sort(eig_Q(k,:),'descend');
%     out.mxcch(k) = sort_eig(k,2)^0.5;
% The maximal correlation coefficient was not calculated due to
% computational instability
% http://murphylab.web.cmu.edu/publications/boland/boland_node26.html
end

corm = zeros(size_glcm_3,1);
corp = zeros(size_glcm_3,1);
% using http://www.fp.ucalgary.ca/mhallbey/glcm_variance.htm for s_x s_y
for k = 1:size_glcm_3
    for i = 1:size_glcm_1
        for j = 1:size_glcm_2
            s_x(k)  = s_x(k)  + (((i) - u_x(k))^2)*glcm(i,j,k);
            s_y(k)  = s_y(k)  + (((j) - u_y(k))^2)*glcm(i,j,k);
            corp(k) = corp(k) + ((i)*(j)*glcm(i,j,k));
            corm(k) = corm(k) + (((i) - u_x(k))*((j) - u_y(k))*glcm(i,j,k));
            out.cprom(k) = out.cprom(k) + (((i + j - u_x(k) - u_y(k))^4)*...
                glcm(i,j,k));
            out.cshad(k) = out.cshad(k) + (((i + j - u_x(k) - u_y(k))^3)*...
                glcm(i,j,k));
        end
    end
    % using http://www.fp.ucalgary.ca/mhallbey/glcm_variance.htm for s_x
    % s_y : This solves the difference in value of correlation and might be
    % the right value of standard deviations required
    % According to this website there is a typo in [2] which provides
    % values of variance instead of the standard deviation hence a square
    % root is required as done below:
    s_x(k) = s_x(k) ^ 0.5;
    s_y(k) = s_y(k) ^ 0.5;
    out.autoc(k) = corp(k);
    out.corrp(k) = (corp(k) - u_x(k)*u_y(k))/(s_x(k)*s_y(k));
    out.corrm(k) = corm(k) / (s_x(k)*s_y(k));
%     % alternate values of u and s
%     out.corrp2(k) = (corp(k) - u_x2(k)*u_y2(k))/(s_x2(k)*s_y2(k));
%     out.corrm2(k) = corm(k) / (s_x2(k)*s_y2(k));
end
% Here the formula in the paper out.corrp and the formula in matlab
% out.corrm are equivalent as confirmed by the similar results obtained

% % The papers have a slightly different formular for Contrast
% % I have tested here to find this formula in the papers provides the
% % same results as the formula provided by the matlab function for
% % Contrast (Hence this part has been commented)
% out.contrp = zeros(size_glcm_3,1);
% contp = 0;
% Ng = size_glcm_1;
% for k = 1:size_glcm_3
%     for n = 0:(Ng-1)
%         for i = 1:Ng
%             for j = 1:Ng
%                 if (abs(i-j) == n)
%                     contp = contp + glcm(i,j,k);
%                 end
%             end
%         end
%         out.contrp(k) = out.contrp(k) + n^2*contp;
%         contp = 0;
%     end
%
% end

%       GLCM Features (Soh, 1999; Haralick, 1973; Clausi 2002)
%           f1. Uniformity / Energy / Angular Second Moment (done)
%           f2. Entropy (done)
%           f3. Dissimilarity (done)
%           f4. Contrast / Inertia (done)
%           f5. Inverse difference
%           f6. correlation
%           f7. Homogeneity / Inverse difference moment
%           f8. Autocorrelation
%           f9. Cluster Shade
%          f10. Cluster Prominence
%          f11. Maximum probability
%          f12. Sum of Squares
%          f13. Sum Average
%          f14. Sum Variance
%          f15. Sum Entropy
%          f16. Difference variance
%          f17. Difference entropy
%          f18. Information measures of correlation (1)
%          f19. Information measures of correlation (2)
%          f20. Maximal correlation coefficient
%          f21. Inverse difference normalized (INN)
%          f22. Inverse difference moment normalized (IDN)


function fx = p54_fun ( n, x )

%*****************************************************************************80
%
%% P54_FUN evaluates the integrand for problem 54.
%
%  Discussion:
%
%    The reference claims that this integrand is more closely approximated
%    by the trapezoid rule than by Gauss-Legendre quadrature.
%
%    Points  Trapezoid  Gauss-Legendre
%     4      1.91667    2.53883
%    12      2.1594     2.25809
%
%    However, the stated results hardly give one confindence in
%    the convergence of the trapezoid results, and I am unable to
%    confirm them, because my results for 4 points give good results
%    (about 1.14) for BOTH Trapezoid and Gauss-Legendre%
%
%  Interval:
%
%    0 <= x <= 1
%
%  Integrand:
%
%    2 / ( 2 + sin ( 10 * PI * x ) )
%
%  Exact Integral:
%
%    2 / sqrt ( 3 ) = 1.1547...
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Prem Kythe, Pratap Puri,
%    Computational Methods for Linear Integral Equations,
%    Birkhaeuser, 2002.
%
%  Parameters:
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real X(N), the evaluation points.
%
%    Output, real FX(N), the integrand values.
%
  fx(1:n) = 2.0 ./ ( 2.0 + sin ( 10.0 * pi * x(1:n) ) );

  return
end


% .............................................................
    function [shape,naturalDerivatives]=shapeFunctionL2(xi)

    % shape function and derivatives for L2 elements
    % shape : Shape functions
    % naturalDerivatives: derivatives w.r.t. xi
    % xi: natural coordinates (-1 ... +1)

    shape=([1-xi,1+xi]/2);

    naturalDerivatives=[-1,1]/2;

    end % end function shapeFunctionL2


function [zProj,AProj]=projEllipsOntoSpace(z,A,gammaVal,d,T)
%%PROJELLIPSONTOSPACE Determine the orthogonal projection of an ellipsoid
%                    onto an affine space. The projection itself will be an
%                    ellipsoid. For example, in 3D, the projection onto a
%                    plane will be an ellipse.
%
%INPUTS: z  The numDimX1 center of the ellipsoid.
%        A  A numDimXnumDim symmetric, positive definite matrix that
%           specifies the size and shape of the ellipse or ellipsoid, where
%           a point zp is on the ellipse/ellipsoid if
%           (zp-z)'*A*(zp-z)=gammaVal.
%  gammaVal The threshold for declaring a point to be in the ellipsoid. If
%           an empty matrix is passed, the default value of 1 is used.
%      d,T  A numDimX1 point d and a numDImXn matrix such that points in
%           the affine subspace are defined by x=d+T*t where t is an nX1
%           real vector, n<numDim.
%
%OUTPUTS: zProj, AProj Parameters defining the projected ellipsoid. zProj
%           is numDImX1 and AProj is numDimXnumDim. However, AProj will be
%           a singular matrix as everything resides on a subspace. A point
%           is on the projected ellipsoid if
%           (zp-zProj)'*AProj*(zp-zProj)=1
%           The example below shows gives an example of using such a
%           singular matrix to display the projection of a 3D ellipsoid
%           onto a 2D plane.
%
%The algorithm is taken from Section 13 of [1].
%
%EXAMPLE:
%We will project an ellipsoid in 3D onto a plane.
%Define the ellipsoid:
% A=[10,0,0;
%     0,20,0;
%     0,0,1];
% %A rotation matrix
% M=[-0.039622269933159, -0.378261925022885, -0.924850253718582;
%     0.765018603761816, -0.606901366847761,  0.215446668149313;
%    -0.642788154545232, -0.698991163746939,  0.313424219517309];
% A=M*A*M';
% c=[0;0;0];%The center of the ellipsoid
% %Define a plane.
% d=[1;0;3];
% T=[1,1;
%    0,1;
%    0,1];
% T=orth(T);%Must be othonormal.
% %Determine the projection of the ellipsoid onto the plane.
% [cProj,AProj]=projEllipsOntoSpace(c,A,1,d,T);
%
% figure(1)
% clf
% hold on
% axis([-4,4,-4,4,-4,4])
% %Draw the ellipsoid
% drawEllipse(c,A,1,'EdgeColor','none')
% view(104,-29)
% %Compute points on the plane to display.
% numPoints=50;
% tSpan=linspace(-10,10,numPoints);
% [tx,ty]=meshgrid(tSpan,tSpan);
% t=[tx(:)';ty(:)'];
% placeSurfVals=bsxfun(@plus,d,T*t);
% X=reshape(placeSurfVals(1,:),numPoints,numPoints);
% Y=reshape(placeSurfVals(2,:),numPoints,numPoints);
% Z=reshape(placeSurfVals(3,:),numPoints,numPoints);
% %Draw the plane
% surf(X,Y,Z)
% %Draw the projection of the ellipsoid onto the plane
% drawEllipse(cProj,AProj,1)
% %This makes the ellipsoid shiny
% light('Position',[0;1;-1])
%
%REFERENCES:
%[1] S. B. Pope, "Algorithms for ellipsoids," Cornell University, Tech.
%    Rep. FDA-08-01, Feb. 2008. [Online].
%    Available: https://tcg.mae.cornell.edu/pubs/Pope_FDA_08.pdf
%
%May 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(isempty(gammaVal))
   gammaVal=1;
end

A=A/gammaVal;

L=chol(A,'lower');

%Make T into an orthonormal matrix. This does not rotate or shift the
%affine space at all. It just changes the parameterization as in x=d+T*t
%still holds, but if T is orthonormalized, then a different value of t
%is needed to get the same x.
T=orth(T);%Must be othonormal.

%Extracted from Equation 126
zProj=d+T*T'*(z-d);
[U,Sigma,~]=svd(T'/(L'),'econ');

L=T*U/Sigma;
AProj=L*L';

end


function boundary_num = boundary_edge_count_euler_q4_mesh ( node_num, ...
  element_num, hole_num )

%*****************************************************************************80
%
%% BOUNDARY_EDGE_COUNT_EULER_Q4_MESH counts boundary edges using Euler's formula.
%
%  Discussion:
%
%    We assume we are given information about a quadrilateral mesh
%    of a set of nodes in the plane.
%
%    Given the number of nodes, elements and holes, we are going to apply
%    Euler's formula to determine the number of edges that lie on the
%    boundary of the set of nodes.
%
%    The number of faces, including the infinite face and internal holes,
%    is ELEMENT_NUM + HOLE_NUM + 1.
%
%    Let BOUNDARY_NUM denote the number of edges on the boundary.
%    Each of the ELEMENT_NUM quadrilaterals uses four edges.  Every edge
%    occurs in two different elements, so the number of edges must be
%    ( 4 * ELEMENT_NUM + BOUNDARY_NUM ) / 2.
%
%    The number of nodes used in the mesh is NODE_NUM.
%
%    Euler's formula asserts that, for a simple connected figure in the
%    plane with no edge crossings, NODE_NUM nodes, EDGE_NUM edges and
%    FACE_NUM faces:
%
%      NODE_NUM - EDGE_NUM + FACE_NUM = 2
%
%    In our context, this becomes
%
%      NODE_NUM - ( 4 * ELEMENT_NUM + BOUNDARY_NUM ) / 2
%      + ELEMENT_NUM + HOLE_NUM + 1 = 2
%
%    or
%
%      BOUNDARY_NUM = 2 * NODE_NUM + 2 * HOLE_NUM - 2 * ELEMENT_NUM - 2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 February 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Marc de Berg, Marc Krevald, Mark Overmars, Otfried Schwarzkopf,
%    Computational Geometry, Section 9.1,
%    Springer, 2000.
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, integer ELEMENT_NUM, the number of elements.
%
%    Input, integer HOLE_NUM, the number of internal holes.
%
%    Output, integer BOUNDARY_NUM, the number of edges that
%    lie on the boundary of the mesh.
%
  boundary_num = 2 * node_num + 2 * hole_num - 2 * element_num - 2;

  return
end


function mat = createRotation90(varargin)
%CREATEROTATION90  Matrix of a rotation for 90 degrees multiples
%
%   MAT = createRotation90
%   Returns the 3-by-3 matrix corresponding to a rotation by 90 degrees.
%   As trigonometric functions are explicitley converted to +1 or -1, the
%   resulting matrix obtained with this function is more precise than
%   the one obtained with createRotation.
%
%   MAT = createRotation90(NUM)
%   Specifies the number of rotations to performs. NUM should be an integer
%   (possibly negative).
%
%   Example
%     poly = [10 0;20 0;10 10];
%     rot = createRotation90;
%     poly2 = transformPoint(poly, rot);
%     figure; hold on; axis equal;
%     drawPolygon(poly);
%     drawPolygon(poly2, 'm');
%     legend('original', 'rotated');
%
%     % specify number of rotations, and center
%     rot = createRotation90(2, [10 10]);
%     poly3 = transformPoint(poly, rot);
%     drawPolygon(poly3, 'g');
%
%   See also
%   transforms2d, createRotation
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2012-06-20,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2012 INRA - Cepia Software Platform.

% default values
num = 1;
center = [0 0];

% process input arguments
while ~isempty(varargin)
    var = varargin{1};
    if isnumeric(var) && isscalar(var)
        % extract number of rotations
        num = mod(mod(var, 4) + 4, 4);

    elseif isnumeric(var) && length(var) == 2
        % extract rotation center
        center = var;

    else
        % unknown argument
        error('MatGeom:createRotation90', ...
            'Unable to parse input arguments');
    end
    varargin(1) = [];
end

% determine rotation parameters
switch num
    case 0
        ct = 1;
        st = 0;
    case 1
        ct = 0;
        st = 1;
    case 2
        ct = -1;
        st = 0;
    case 3
        ct = 0;
        st = -1;
end

% compute transform matrix
mat = [ ...
    ct -st 0; ...
    st ct 0; ...
    0 0 1];

% change center if needed
if sum(center ~= [0 0]) > 0
    tra = createTranslation(center);
    mat = tra * mat / tra;
end


function [J, grad] = cofiCostFunc(params, Y, R, num_users, num_movies, ...
                                  num_features, lambda)
%COFICOSTFUNC Collaborative filtering cost function
%   [J, grad] = COFICOSTFUNC(params, Y, R, num_users, num_movies, ...
%   num_features, lambda) returns the cost and gradient for the
%   collaborative filtering problem.
%

% Unfold the U and W matrices from params
X = reshape(params(1:num_movies*num_features), num_movies, num_features);
Theta = reshape(params(num_movies*num_features+1:end), ...
                num_users, num_features);

% You need to return the following values correctly
J = 0;
X_grad = zeros(size(X));
Theta_grad = zeros(size(Theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost function and gradient for collaborative
%               filtering. Concretely, you should first implement the cost
%               function (without regularization) and make sure it is
%               matches our costs. After that, you should implement the
%               gradient and use the checkCostFunction routine to check
%               that the gradient is correct. Finally, you should implement
%               regularization.
%
% Notes: X - num_movies  x num_features matrix of movie features
%        Theta - num_users  x num_features matrix of user features
%        Y - num_movies x num_users matrix of user ratings of movies
%        R - num_movies x num_users matrix, where R(i, j) = 1 if the
%            i-th movie was rated by the j-th user
%
% You should set the following variables correctly:
%
%        X_grad - num_movies x num_features matrix, containing the
%                 partial derivatives w.r.t. to each element of X
%        Theta_grad - num_users x num_features matrix, containing the
%                     partial derivatives w.r.t. to each element of Theta
%

J = (1 / 2) * sum(sum((X * Theta' .* R - Y) .^ 2)) + ...
    (lambda / 2) * sum(sum(Theta .^ 2)) + (lambda / 2) * sum(sum(X .^ 2));

X_grad = (X * Theta' .* R - Y) * Theta + lambda * X;

Theta_grad = (X * Theta' .* R - Y)' * X + lambda * Theta;

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

grad = [X_grad(:); Theta_grad(:)];

end


function x = logistic_cdf_inv ( cdf, a, b )

%*****************************************************************************80
%
%% LOGISTIC_CDF_INV inverts the Logistic CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real CDF, the value of the CDF.
%    0.0 <= CDF <= 1.0.
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < B.
%
%    Output, real X, the corresponding argument.
%
  if ( cdf < 0.0 | 1.0 < cdf )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LOGISTIC_CDF_INV - Fatal error!\n' );
    fprintf ( 1, '  CDF < 0 or 1 < CDF.\n' );
    error ( 'LOGISTIC_CDF_INV - Fatal error!' );
  end

  x = a - b * log ( ( 1.0 - cdf ) / cdf );

  return
end


function yval = spline_beta_val ( beta1, beta2, ndata, tdata, ydata, tval )

%*****************************************************************************80
%
%% SPLINE_BETA_VAL evaluates a cubic beta spline approximant.
%
%  Discussion:
%
%    The cubic beta spline will approximate the data, but is not
%    designed to interpolate it.
%
%    If BETA1 = 1 and BETA2 = 0, the cubic beta spline will be the
%    same as the cubic B spline approximant.
%
%    With BETA1 = 1 and BETA2 large, the beta spline becomes more like
%    a linear spline.
%
%    In effect, two "phantom" data values are appended to the data,
%    so that the spline will interpolate the first and last data values.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real BETA1, the skew or bias parameter.
%    BETA1 = 1 for no skew or bias.
%
%    Input, real BETA2, the tension parameter.
%    BETA2 = 0 for no tension.
%
%    Input, integer NDATA, the number of data values.
%
%    Input, real TDATA(NDATA), the abscissas of the data.
%
%    Input, real YDATA(NDATA), the data values.
%
%    Input, real TVAL, a point at which the spline is to be evaluated.
%
%    Output, real YVAL, the value of the function at TVAL.
%

%
%  Find the nearest interval [ TDATA(LEFT), TDATA(RIGHT) ] to TVAL.
%
  [ left, right ] = r8vec_bracket ( ndata, tdata, tval );
%
%  Evaluate the 5 nonzero beta spline basis functions in the interval,
%  weighted by their corresponding data values.
%
  u = ( tval - tdata(left) ) / ( tdata(right) - tdata(left) );

  delta = ( ( 2.0E+00   ...
    * beta1 + 4.0E+00 ) ...
    * beta1 + 4.0E+00 ) ...
    * beta1 + 2.0E+00 + beta2;

  yval = 0.0E+00;
%
%  Beta function associated with node LEFT - 1, (or "phantom node"),
%  evaluated in its 4th interval.
%
  bval = 2.0E+00 * ( beta1 * ( 1.0E+00 - u ) )^3  / delta;

  if ( 0 < left-1 )
    yval = yval + ydata(left-1) * bval;
  else
    yval = yval + ( 2.0E+00 * ydata(1) - ydata(2) ) * bval;
  end
%
%  Beta function associated with node LEFT,
%  evaluated in its third interval.
%
  a = beta2 + ( 4.0E+00 + 4.0E+00 * beta1 ) * beta1;

  b = - 6.0E+00 * beta1 * ( 1.0E+00 - beta1 ) * ( 1.0E+00 + beta1 );

  c = ( (     - 6.0E+00   ...
      * beta1 - 6.0E+00 ) ...
      * beta1 + 0.0E+00 ) ...
      * beta1 - 3.0E+00 * beta2;

  d = ( (     + 2.0E+00   ...
      * beta1 + 2.0E+00 ) ...
      * beta1 + 2.0E+00 ) ...
      * beta1 + 2.0E+00 * beta2;

  bval = ( a + u * ( b + u * ( c + u * d ) ) ) / delta;

  yval = yval + ydata(left) * bval;
%
%  Beta function associated with node RIGHT,
%  evaluated in its second interval.
%
  a = 2.0E+00;

  b = 6.0E+00 * beta1;

  c = 3.0E+00 * beta2 + 6.0E+00 * beta1 * beta1;

  d = - 2.0E+00 * ( 1.0E+00 + beta2 + beta1 + beta1 * beta1 );

  bval = ( a + u * ( b + u * ( c + u * d ) ) ) / delta;

  yval = yval + ydata(right) * bval;
%
%  Beta function associated with node RIGHT+1, (or "phantom node"),
%  evaluated in its first interval.
%
  bval = 2.0E+00 * u^3 / delta;

  if ( right+1 <= ndata )
    yval = yval + ydata(right+1) * bval;
  else
    yval = yval + ( 2.0E+00 * ydata(ndata) - ydata(ndata-1) ) * bval;
  end

  return
end


function [ f, g, H ] = opt10_fgh ( x, flag )

%*****************************************************************************80
%
%% OPT10_FGH evaluates F, G and H for test case #10.
%
%  Discussion:
%
%    This example is known as the Wood function.
%
%    The optimizing value is
%
%      X* = (1,1,1,1)
%
%    for which
%
%      F(X*) = 0.
%
%  Modified:
%
%    09 January 2008
%
%  Author:
%
%    Jeff Borggaard,
%    Gene Cliff,
%    Virginia Tech.
%
%  Reference:
%
%    John Dennis, Robert Schnabel,
%    Numerical Methods for Unconstrained Optimization
%    and Nonlinear Equations,
%    SIAM, 1996,
%    ISBN13: 978-0-898713-64-0,
%    LC: QA402.5.D44.
%
%  Parameters:
%
%    Input, real X(4), the evaluation point.
%
%    Input, string FLAG, indicates what must be computed.
%    'f' means only the value of F is needed,
%    'g' means only the value of G is needed,
%    'all' means F, G and H (if appropriate) are needed.
%    It is acceptable to behave as though FLAG was 'all'
%    on every call.
%
%    Output, real F, the optimization function.
%
%    Output, real G(4,1), the gradient column vector.
%
%    Output, real H(4,4), the Hessian matrix.
%
  n = length ( x );

  if ( n ~= 4 )
    fprintf ( '\n' );
    fprintf ( 'OPT10_FGH - Fatal error!\n' );
    fprintf ( '  The input vector X should have length 4.\n'),
    fprintf ( '  Instead, it has length = %d.\n', n );
    keyboard
  end

  f = 100   * ( x(1)^2 - x(2)   )^2 ...
    +         ( 1 - x(1)        )^2 ...
    +  90   * ( x(3)^2 - x(4)   )^2 ...
    +         ( 1 - x(3)        )^2 ...
    +  10   * ( x(2) + x(4) - 2 )^2 ...
    +   0.1 * ( x(2) - x(4)     )^2;

  g = zeros(n,1);

  g(1,1) =   100   * 2 * ( x(1)^2 - x(2) ) * 2 * x(1)...
         -           2 * ( 1 - x(1) );

  g(2,1) = - 100   * 2 * ( x(1)^2 - x(2) )...
           +  10   * 2 * ( x(2) + x(4) - 2 )...
           +   0.1 * 2 * ( x(2) - x(4) );

  g(3,1) =    90   * 2 * ( x(3)^2 - x(4) ) * 2 * x(3)...
           -         2 * ( 1 - x(3) );

  g(4,1) = -  90   * 2 * ( x(3)^2 - x(4) )...
           +  10   * 2 * ( x(2) + x(4) - 2 )...
           -   0.1 * 2 * ( x(2) - x(4) );

  H = zeros(n,n);

  H(1,1) =   1200 * x(1)^2 - 400 * x(2) + 2;
  H(1,2) = - 400 * x(1);
  H(1,3) =     0;
  H(1,4) =     0;

  H(2,1) = - 400 * x(1);
  H(2,2) =   220.2;
  H(2,3) =     0;
  H(2,4) =    19.8;

  H(3,1) = H(1,3);
  H(3,2) = H(2,3);
  H(3,3) = 1080 * x(3)^2 - 360 * x(4) + 2;
  H(3,4) = - 360 * x(3);

  H(4,1) = H(1,4);
  H(4,2) = H(2,4);
  H(4,3) = H(3,4);
  H(4,4) = 200.2;


function [R2_cv,mP,VP,R2] = PRESS_GLM(X,y,verbose)
% evaluates the PRESS-R2 cross-valuidation metric for a GLM
% function [R2_cv,mP,VP,R2] = PRESS_GLM(X,y,verbose)
% This function evaluates a prediction accuracy metric (PRESS-R2), in the
% context of a leave-one-out cross-validation scheme for a GLM. Note: it is
% based upon the predicted residual error sum of squares (PRESS) statistic.
% IN:
%   - X: nxp design matrix (independent variables)
%   - y: nxk dependent variables
%   - verbose: verbose flag
% OUT:
%   - R2_cv: PRESS-R2, i.e. percentage of predicted variance, where
%   predictions are derived for each fold of the leave-one-out
%   cross-validation scheme.
%   - mP: pxk OLS-estimates of the GLM parameters
%   - VP: pxk varianceso of the parameters estimates
%   - R2: coefficeint of determination

% Get time
et0 = clock;

% 0- check basic data dimension requirements
[n,p] = size(X);
if n < 3
    disp('Error: PRESS_GLM: data dimension is lower than 3!!')
    R2_cv = [];
    return
else
    if verbose
        fprintf(1,'PRESS_GLM: leave-one-out cross-validation scheme:...')
        fprintf(1,'%6.2f %%',0)
    end
end

% 1- perform leave-one-out scheme
Eg = NaN(size(y));
ii = 0;
for i=1:n
    X0 = X;
    X0(i,:) = [];
    y0 = y;
    y0(i,:) = [];
    b = pinv(X0'*X0)*X0'*y0;
    Eg(i,:) = X(i,:)*b;
    if verbose
        fprintf(1,repmat('\b',1,8))
        fprintf(1,'%6.2f %%',floor(100*i/n))
    end
end
if verbose
    fprintf(1,repmat('\b',1,8))
    fprintf(1,[' OK (took ',num2str(etime(clock,et0)),' seconds).'])
    fprintf(1,'\n')
end

% 2- evaluate PRESS and R2_cv
for i=1:size(y,2)
    PRESS = sum((y(:,i)-Eg(:,i)).^2);
    TSS(i) = sum((y(:,i)-mean(y(:,i))).^2);
    R2_cv(i) = 1 - PRESS./TSS(i);
end

% 3- fit the model conditional on all data and wrap-up
if verbose
    disp('PRESS_GLM: model fit on full-data...')
end
iX = pinv(X'*X);
mP = iX*X'*y;
for i=1:size(y,2)
    yhat = X*mP(:,i);
    RSS = sum((yhat-y(:,i)).^2);
    vhat = RSS./(n-p);
    C = vhat*iX;
    VP(:,i) = diag(C);
    R2(i) = 1 - RSS./TSS(i);
end
if verbose
    disp('PRESS_GLM: model fit on full-data... OK.')
end


function value = rayleigh ( n, a, x )

%*****************************************************************************80
%
%% RAYLEIGH returns the Rayleigh quotient of the matrix A and the vector X.
%
%  Formula:
%
%    RAYLEIGH = X' * A * X / ( X' * X )
%
%  Properties:
%
%    If X is an eigenvector of A, then RAYLEIGH will equal the
%    corresponding eigenvalue.
%
%    The set of all Rayleigh quotients for a matrix is known
%    as its "field of values".
%
%  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 A(N,N), the matrix.
%
%    Input, real X(N), the vector used in the Rayleigh quotient.
%
%    Output, real VALUE, the Rayleigh quotient of A and X.
%
  value = ( x(1:n) * a(1:n,1:n) * x(1:n))') /  ( x(1:n) * x(1:n)' );

  return
end


function p = sphere_stereograph2_inverse ( q, focus, center )

%*****************************************************************************80
%
%% SPHERE_STEREOGRAPH2_INVERSE computes stereographic preimages of points.
%
%  Discussion:
%
%    We start with a sphere of center C.
%
%    F is a point on the sphere which is the focus of the mapping,
%    and the antipodal point 2*C-F is the point of tangency
%    to the sphere of a plane.
%
%    For any point Q on the plane, the stereographic inverse projection
%    P of the point is defined by drawing the line from F through Q, and
%    computing P as the intersection of this line with the sphere.
%
%    The spatial dimension M is arbitrary, but should be at least 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 November 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    C F Marcus,
%    The stereographic projection in vector notation,
%    Mathematics Magazine,
%    Volume 39, Number 2, March 1966, pages 100-102.
%
%  Parameters:
%
%    Input, real Q(M,N), the points, which are presumed to lie
%    on the plane.
%
%    Input, real FOCUS(M,1), the coordinates of the focus point.
%
%    Input, real CENTER(M,1), the coordinates of the center of the sphere.
%
%    Output, real P(M,N), the stereographic inverse projections of the points.
%
  [ m, n ] = size ( q );

  ff = repmat ( focus, 1, n );

  s(1,1:n) = 2.0 * ( center - focus )' * ( q - ff ) ./ sum ( ( q - ff ).^2, 1 );

  ss = repmat ( s, m, 1 );

  p = ss .* q + ( 1.0 - ss ) .* ff;

  return
end


function Mutual_Information=MutualInformation(x,y)

% Compute Mutual Information and Joint entropy of two images
% Takes two images and returns the mutual information and  joint
% entropy. For implementing this function also download function
% joint_histogram.m in my file exchange.
%
% written by Amir Pasha Mahmoudzadeh
% Wright State University
% Biomedical Imaging Lab

h=joint_histogram(x,y); % Joint histogram for 2D
[m,n] = size(h);
J= h./(m*n); % normalized joint histogram
y_summ=sum(J); %sum of the rows of normalized joint histogram
x_summ=sum(J);%sum of columns of normalized joint histogran

sy=0;
for s=1:n;    %  column
      if( y_summ(s)==0 )

      else
         sy = sy + -(y_summ(s)*(log2(y_summ(s)))); %marginal entropy for image 1
      end
   end

sx=0;
for s=1:m;    %rows
   if( x_summ(s)==0 )

      else
         sx = sx + -(x_summ(s)*(log2(x_summ(s)))); %marginal entropy for image 2
      end
   end
joint_entropy = -sum(sum(J.*(log2(J+(J==0))))) % joint entropy
Mutual_Information = sx + sy - joint_entropy; % Mutual information
end


function vol=elemvolume(node,elem,option)
%
% vol=elemvolume(node,elem,option)
%
% calculate the volume for a list of simplexes
%
% author: Qianqian Fang, <q.fang at neu.edu>
% date: 2007/11/21
%
% input:
%    node:  node coordinates
%    elem:  element table of a mesh
%    option: if option='signed', the volume is the raw determinant,
%            else, the results will be the absolute values
%
% output:
%    vol:   volume values for all elements
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

if(size(elem,2)==size(node,2))
	enum=size(elem,1);
	vol=zeros(enum,1);
	acol=ones(3,1);
	for i=1:enum
		e1=det([node(elem(i,:),2),node(elem(i,:),3),acol]);
		e2=det([node(elem(i,:),3),node(elem(i,:),1),acol]);
		e3=det([node(elem(i,:),1),node(elem(i,:),2),acol]);
		vol(i)=sqrt(e1*e1+e2*e2+e3*e3)/2;
	end
	return;
end
dim=size(elem,2);
enum=size(elem,1);
vol=zeros(enum,1);
for i=1:enum
    detmat=[node(elem(i,:),:)';ones(1,dim)];
    vol(i)=det(detmat);
end
if(nargin==3 && strcmp(option,'signed'))
  vol=vol/prod(1:size(node,2));
else
  vol=abs(vol)/prod(1:size(node,2));
end


function pdf = beta_binomial_pdf ( x, a, b, c )

%*****************************************************************************80
%
%% BETA_BINOMIAL_PDF evaluates the Beta Binomial PDF.
%
%  Discussion:
%
%    PDF(X)(A,B,C) = Beta(A+X,B+C-X)
%      / ( (C+1) * Beta(X+1,C-X+1) * Beta(A,B) )  for 0 <= X <= C.
%
%    This PDF can be reformulated as:
%
%      The beta binomial probability density function for X successes
%      out of N trials is
%
%      PDF2(X)( N, MU, THETA ) =
%        C(N,X) * Product ( 0 <= R <= X - 1 ) ( MU + R * THETA )
%               * Product ( 0 <= R <= N - X - 1 ) ( 1 - MU + R * THETA )
%               / Product ( 0 <= R <= N - 1 )  ( 1 + R * THETA )
%
%      where
%
%        C(N,X) is the combinatorial coefficient;
%        MU is the expectation of the underlying Beta distribution;
%        THETA is a shape parameter.
%
%      A THETA value of 0 ( or A+B --> Infinity ) results in the binomial
%      distribution:
%
%        PDF2(X) ( N, MU, 0 ) = C(N,X) * MU**X * ( 1 - MU )**(N-X)
%
%    Given A, B, C for PDF, then the equivalent PDF2 has:
%
%      N     = C
%      MU    = A / ( A + B )
%      THETA = 1 / ( A + B )
%
%    Given N, MU, THETA for PDF2, the equivalent PDF has:
%
%      A = MU / THETA
%      B = ( 1 - MU ) / THETA
%      C = N
%
%    BETA_BINOMIAL_PDF(X)(1,1,C) = UNIFORM_DISCRETE_PDF(X)(0,C-1)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer X, the argument of the PDF.
%
%    Input, real A, B, parameters of the PDF.
%    0.0D+00 < A,
%    0.0D+00 < B.
%
%    Input, integer C, a parameter of the PDF.
%    0 <= C.
%
%    Output, real PDF, the value of the PDF.
%
  if ( x < 0 )

    pdf = 0.0;

  elseif ( x <= c )

    pdf = beta ( a + x, b + c - x ) ...
      / ( ( c + 1 ) * beta ( x + 1, c - x + 1 ) * beta ( a, b ) );

  elseif ( c < x )

    pdf = 0.0;

  end

  return
end


function [ w, x ] = line_rule ( a, b, order )

%*****************************************************************************80
%
%% LINE_RULE returns a quadrature rule for a line segment in 1D.
%
%  Discussion:
%
%    The integration region is:
%      A <= X <= B
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 September 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carlos Felippa,
%    A compendium of FEM integration formulas for symbolic work,
%    Engineering Computation,
%    Volume 21, Number 8, 2004, pages 867-890.
%
%  Parameters:
%
%    Input, real A, B, the lower and upper limits.
%
%    Input, integer ORDER, the order of the rule.
%
%    Output, real W(ORDER), the weights.
%
%    Output, real X(ORDER), the abscissas.
%
  if ( order == 1 )
    [ w, x ] = line_unit_o01 ( );
  elseif ( order == 2 )
    [ w, x ] = line_unit_o02 ( );
  elseif ( order == 3 )
    [ w, x ] = line_unit_o03 ( );
  elseif ( order == 4 )
    [ w, x ] = line_unit_o04 ( );
  elseif ( order == 5 )
    [ w, x ] = line_unit_o05 ( );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LINE_RULE - Fatal error!\n' );
    fprintf ( 1, '  Illegal value of ORDER.\n' );
    error ( 'LINE_RULE - Fatal error!' );
  end
%
%  Transform from [-1,+1] to [A,B]
%
  for j = 1 : order
    w(j) = w(j) * ( b - a ) / 2.0;
    x(j) = ( ( 1.0 - x(j) ) * a   ...
           + ( 1.0 + x(j) ) * b ) ...
           /   2.0;
  end

  return
end


% sine wave fitting from noisy sine signal
% phase fitting has to be considered
% with a fixed omega!
% Written by Dr Chen YangQuan <yqchen@ieee.org>
% Last modified in 05-11-2000
% DESCRIPTIONS:
% s0: sampled series. 1xNp (note here)
% omega: known freq. (2*pi*f) (rad/sec.)
% Ts: sampling period (in Sec.)
% t0: initial time (in Sec.)
% Ahat: estimated amplitude
% Theta: fitted theta_0 (in rad.)
% RMS: root mean squares.
%
% See also "jomega"
function [Ahat,Theta,RMS]=sinefit2(s0,omega,t0,Ts)
Np=size(s0);
t=t0+[0:Np(2)-1]*Ts;
A11= (sin(omega*t)*(sin(omega*t))');
A12= (sin(omega*t)*(cos(omega*t))');
A22= (cos(omega*t)*(cos(omega*t))');
b1=s0*(sin(omega*t))';
b2=s0*(cos(omega*t))';
A=[A11,A12;A12,A22];
Alpha=inv(A)*[b1,b2]';
% be careful here...
Asintheta=Alpha(2);Acostheta=Alpha(1);
Ahat=sqrt(Asintheta*Asintheta+Acostheta*Acostheta);
Theta=atan2(Asintheta,Acostheta);
RMS=sqrt((s0-Ahat*sin(omega*t+Theta))*...
(s0-Ahat*sin(omega*t+Theta))'/(Np(2)-1.));
if (0)
figure;
plot(t,s0,'k:',t, Ahat*sin(omega*t+Theta),'-r');
legend(['measured (RMS=',num2str(RMS),', f=',...
num2str(omega/2/pi),')'],['fitted: ',...
' A.hat=',num2str(Ahat),' | theta.hat=',num2str(Theta*180/pi)])
end
return;


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

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

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

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta

n = length(theta);

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

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

end


function area = sphere01_triangle_vertices_to_area ( v1, v2, v3 )

%*****************************************************************************80
%
%% SPHERE01_TRIANGLE_VERTICES_TO_AREA: area of a spherical triangle on unit sphere.
%
%  Discussion:
%
%    A unit sphere centered at 0 in 3D satisfies the equation:
%
%      X * X + Y * Y + Z * Z = 1
%
%    A spherical triangle is specified by three points on the surface
%    of the sphere.
%
%    The area formula is known as Girard's formula.
%
%    The area of a spherical triangle on the unit sphere is:
%
%      AREA = ( A + B + C - PI )
%
%    where A, B and C are the (surface) angles of the triangle.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 September 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real V1(3), V2(3), V3(3), the vertices of the triangle.
%
%    Output, real AREA, the area of the spherical triangle.
%

%
%  Compute the lengths of the sides of the spherical triangle.
%
  [ as, bs, cs ] = sphere01_triangle_vertices_to_sides ( v1, v2, v3 );
%
%  Get the spherical angles.
%
  [ a, b, c ] = sphere01_triangle_sides_to_angles ( as, bs, cs );
%
%  Get the area.
%
  area = sphere01_triangle_angles_to_area ( a, b, c );

  return
end


function det = r8mat_det_4d ( a )

%*****************************************************************************80
%
%% R8MAT_DET_4D computes the determinant of a 4 by 4 matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A(4,4), the matrix whose determinant is desired.
%
%    Output, real DET, the determinant of the matrix.
%
  det = ...
      a(1,1) * ( ...
        a(2,2) * ( a(3,3) * a(4,4) - a(3,4) * a(4,3) ) ...
      - a(2,3) * ( a(3,2) * a(4,4) - a(3,4) * a(4,2) ) ...
      + a(2,4) * ( a(3,2) * a(4,3) - a(3,3) * a(4,2) ) ) ...
    - a(1,2) * ( ...
        a(2,1) * ( a(3,3) * a(4,4) - a(3,4) * a(4,3) ) ...
      - a(2,3) * ( a(3,1) * a(4,4) - a(3,4) * a(4,1) ) ...
      + a(2,4) * ( a(3,1) * a(4,3) - a(3,3) * a(4,1) ) ) ...
    + a(1,3) * ( ...
        a(2,1) * ( a(3,2) * a(4,4) - a(3,4) * a(4,2) ) ...
      - a(2,2) * ( a(3,1) * a(4,4) - a(3,4) * a(4,1) ) ...
      + a(2,4) * ( a(3,1) * a(4,2) - a(3,2) * a(4,1) ) ) ...
    - a(1,4) * ( ...
        a(2,1) * ( a(3,2) * a(4,3) - a(3,3) * a(4,2) ) ...
      - a(2,2) * ( a(3,1) * a(4,3) - a(3,3) * a(4,1) ) ...
      + a(2,3) * ( a(3,1) * a(4,2) - a(3,2) * a(4,1) ) );

  return
end


function [K,H,Pmax,Pmin] = surfature(X,Y,Z),
% SURFATURE -  COMPUTE GAUSSIAN AND MEAN CURVATURES OF A SURFACE
%   [K,H] = SURFATURE(X,Y,Z), WHERE X,Y,Z ARE 2D ARRAYS OF POINTS ON THE
%   SURFACE.  K AND H ARE THE GAUSSIAN AND MEAN CURVATURES, RESPECTIVELY.
%   SURFATURE RETURNS 2 ADDITIONAL ARGUEMENTS,
%   [K,H,Pmax,Pmin] = SURFATURE(...), WHERE Pmax AND Pmin ARE THE MINIMUM
%   AND MAXIMUM CURVATURES AT EACH POINT, RESPECTIVELY.

% First Derivatives
[Xu,Xv] = gradient(X);
[Yu,Yv] = gradient(Y);
[Zu,Zv] = gradient(Z);

% Second Derivatives
[Xuu,Xuv] = gradient(Xu);
[Yuu,Yuv] = gradient(Yu);
[Zuu,Zuv] = gradient(Zu);

[Xuv,Xvv] = gradient(Xv);
[Yuv,Yvv] = gradient(Yv);
[Zuv,Zvv] = gradient(Zv);

% Reshape 2D Arrays into Vectors
Xu = Xu(:);   Yu = Yu(:);   Zu = Zu(:);
Xv = Xv(:);   Yv = Yv(:);   Zv = Zv(:);
Xuu = Xuu(:); Yuu = Yuu(:); Zuu = Zuu(:);
Xuv = Xuv(:); Yuv = Yuv(:); Zuv = Zuv(:);
Xvv = Xvv(:); Yvv = Yvv(:); Zvv = Zvv(:);

Xu          =   [Xu Yu Zu];
Xv          =   [Xv Yv Zv];
Xuu         =   [Xuu Yuu Zuu];
Xuv         =   [Xuv Yuv Zuv];
Xvv         =   [Xvv Yvv Zvv];

% First fundamental Coeffecients of the surface (E,F,G)
E           =   dot(Xu,Xu,2);
F           =   dot(Xu,Xv,2);
G           =   dot(Xv,Xv,2);

m           =   cross(Xu,Xv,2);
p           =   sqrt(dot(m,m,2));
n           =   m./[p p p];

% Second fundamental Coeffecients of the surface (L,M,N)
L           =   dot(Xuu,n,2);
M           =   dot(Xuv,n,2);
N           =   dot(Xvv,n,2);

[s,t] = size(Z);

% Gaussian Curvature
K = (L.*N - M.^2)./(E.*G - F.^2);
K = reshape(K,s,t);

% Mean Curvature
H = (E.*N + G.*L - 2.*F.*M)./(2*(E.*G - F.^2));
H = reshape(H,s,t);

% Principal Curvatures
Pmax = H + sqrt(H.^2 - K);
Pmin = H - sqrt(H.^2 - K);


function [A,z]=jacobiancsd(fun,x)
% JACOBIANCSD    Complex Step Jacobian
% J = jacobiancsd(f,x) returns the numberical (m x n) Jacobian matrix of a
% m-vector function, f(x) at the refdrence point, x (n-vector).
% [J,z] = jacobiancsd(f,x) also returns the function value, z=f(x).
%
% Example
% f=@(x)[x(1)*x(2)^2;x(1)*x(3)^2;x(1)^2];
% x=1:3;
% [J,z]=jacobiancsd(f,x)
% J =
%     4     4     0
%     9     0     6
%     2     0     0
% z =
%     4
%     9
%     1
%
% By Yi Cao at Cranfield University, 02/01/2008
%
z=fun(x);                       % function value
n=numel(x);                     % size of independent
m=numel(z);                     % size of dependent
A=zeros(m,n);                   % allocate memory for the Jacobian matrix
h=n*eps;                        % differentiation step size
for k=1:n                       % loop for each independent variable
    x1=x;                       % reference point
    x1(k)=x1(k)+h*i;            % increment in kth independent variable
    A(:,k)=imag(fun(x1))/h;     % complex step differentiation
end


function [A,b,x] = phillips(n)
%PHILLIPS Test problem: Phillips' "famous" problem.
%
% [A,b,x] = phillips(n)
%
% Discretization of the `famous' first-kind Fredholm integral
% equation deviced by D. L. Phillips.  Define the function
%    phi(x) = | 1 + cos(x*pi/3) ,  |x| <  3 .
%             | 0               ,  |x| >= 3
% Then the kernel K, the solution f, and the right-hand side
% g are given by:
%    K(s,t) = phi(s-t) ,
%    f(t)   = phi(t) ,
%    g(s)   = (6-|s|)*(1+.5*cos(s*pi/3)) + 9/(2*pi)*sin(|s|*pi/3) .
% Both integration intervals are [-6,6].
%
% The order n must be a multiple of 4.

% Reference: D. L. Phillips, "A technique for the numerical solution
% of certain integral equations of the first kind", J. ACM 9
% (1962), 84-97.

% Discretized by Galerkin method with orthonormal box functions.

% Per Christian Hansen, IMM, 09/17/92.

% Check input.
if (rem(n,4)~=0), error('The order n must be a multiple of 4'), end

% Compute the matrix A.
h = 12/n; n4 = n/4; r1 = zeros(1,n);
c = cos((-1:n4)*4*pi/n);
r1(1:n4) = h + 9/(h*pi^2)*(2*c(2:n4+1) - c(1:n4) - c(3:n4+2));
r1(n4+1) = h/2 + 9/(h*pi^2)*(cos(4*pi/n)-1);
A = toeplitz(r1);

% Compute the right-hand side b.
if (nargout>1),
  b = zeros(n,1); c = pi/3;
  for i=n/2+1:n
    t1 = -6 + i*h; t2 = t1 - h;
    b(i) =   t1*(6-abs(t1)/2) ...
           + ((3-abs(t1)/2)*sin(c*t1) - 2/c*(cos(c*t1) - 1))/c ...
           - t2*(6-abs(t2)/2) ...
           - ((3-abs(t2)/2)*sin(c*t2) - 2/c*(cos(c*t2) - 1))/c;
    b(n-i+1) = b(i);
  end
  b = b/sqrt(h);
end

% Compute the solution x.
if (nargout==3)
  x = zeros(n,1);
  x(2*n4+1:3*n4) = (h + diff(sin((0:h:(3+10*eps))'*c))/c)/sqrt(h);
  x(n4+1:2*n4) = x(3*n4:-1:2*n4+1);
end


function [ x, seed ] = sample_sphere_uniform ( m, n, seed )

%*****************************************************************************80
%
%% SAMPLE_SPHERE_UNIFORM samples points inside the unit sphere.
%
%  Discussion:
%
%    The sphere has center 0 and radius 1.
%
%    We first generate a point ON the sphere, and then distribute it
%    IN the sphere.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Russell Cheng,
%    Random Variate Generation,
%    in Handbook of Simulation,
%    edited by Jerry Banks,
%    Wiley, 1998, pages 168.
%
%    Reuven Rubinstein,
%    Monte Carlo Optimization, Simulation, and Sensitivity
%    of Queueing Networks,
%    Wiley, 1986, page 232.
%
%  Parameters:
%
%    Input, integer M, the dimension of the space.
%
%    Input, integer N, the number of points.
%
%    Input/output, integer SEED, a seed for the random number generator.
%
%    Output, real X(M,N), the points.
%
  exponent = 1.0 / m;

  for j = 1 : n
%
%  Fill a vector with normally distributed values.
%
    [ y, seed ] = r8ec_normal_01 ( m, seed );
%
%  Compute the length of the vector.
%
    norm = sqrt ( sum ( y(1:m).^2 ) );
%
%  Normalize the vector.
%
    y(1:m) = y(1:m) / norm;
%
%  Now compute a value to map the point ON the sphere INTO the sphere.
%
    [ r, seed ] = r8_uniform_01 ( seed );

    x(1:m,j) = r^exponent * y(1:m)';

  end

  return
end


function [ c_est, r_est, c_err, r_err ] = ellipsoid_random_centralize ( ...
  m, n, c, r )

%*****************************************************************************80
%
%% ELLIPSOID_RANDOM_CENTRALIZE estimates the center and radius of an ellipsoid.
%
%  Discussion:
%
%    We generate N points on the M dimensional ellipsoid of center C,
%    and radiuses R.  We seek to estimate the values of C and R.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 April 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of random points to generate.
%
%    Input, real C(M,1), the center.
%
%    Input, real R(M,1), the radiuses.
%
%    Output, real C_EST(M,1), R_EST, the estimated center and radius.
%
%    Output, real C_ERR, R_ERR, the errors in the estimates.
%
  c = c(:);
  r = r(:);
%
%  Construct a diagonal matrix from R.
%
  a = diag ( r );
%
%  Multiply it by a random orthogonal matrix.
%
  q = r8mat_orth_uniform ( m );
  a = q * a * q';
%
%  Now generate points on the ellipsoid surface (X-C)' * A * (X-C) = R * R.
%
  rr = 1.0;
  x = ellipsoid_surface_sample ( m, n, a, c, rr );

  c_est = sum ( x, 2 ) / n;
  c_err = norm ( c - c_est );

  r_mat = x - repmat ( c_est, 1, n );
  r_mat = r_mat.^2;
  r_mat = sum ( r_mat, 1 );
  r_mat = sqrt ( r_mat );
  r_est = sum ( r_mat ) / n;
% r_err = abs ( r - r_est );
  r_err = 0.0;

  return
end


function angles = polyangles(x, y)
%POLYANGLES Computes internal polygon angles.
%   ANGLES = POLYANGLES(X, Y) computes the interior angles (in
%   degrees) of an arbitrary polygon whose vertices are given in
%   [X, Y], ordered in a clockwise manner.  The program eliminates
%   duplicate adjacent rows in [X Y], except that the first row may
%   equal the last, so that the polygon is closed.

%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.6 $  $Date: 2003/11/21 14:44:06 $

% Preliminaries.
[x y] = dupgone(x, y); % Eliminate duplicate vertices.
xy = [x(:) y(:)];
if isempty(xy)
   % No vertices!
   angles = zeros(0, 1);
   return;
end
if size(xy, 1) == 1 | ~isequal(xy(1, :), xy(end, :))
   % Close the polygon
   xy(end + 1, :) = xy(1, :);
end

% Precompute some quantities.
d = diff(xy, 1);
v1 = -d(1:end, :);
v2 = [d(2:end, :); d(1, :)];
v1_dot_v2 = sum(v1 .* v2, 2);
mag_v1 = sqrt(sum(v1.^2, 2));
mag_v2 = sqrt(sum(v2.^2, 2));

% Protect against nearly duplicate vertices; output angle will be 90
% degrees for such cases. The "real" further protects against
% possible small imaginary angle components in those cases.
mag_v1(~mag_v1) = eps;
mag_v2(~mag_v2) = eps;
angles = real(acos(v1_dot_v2 ./ mag_v1 ./ mag_v2) * 180 / pi);

% The first angle computed was for the second vertex, and the
% last was for the first vertex. Scroll one position down to
% make the last vertex be the first.
angles = circshift(angles, [1, 0]);

% Now determine if any vertices are concave and adjust the angles
% accordingly.
sgn = convex_angle_test(xy);

% Any element of sgn that's -1 indicates that the angle is
% concave. The corresponding angles have to be subtracted
% from 360.
I = find(sgn == -1);
angles(I) = 360 - angles(I);

%-------------------------------------------------------------------%
function sgn = convex_angle_test(xy)
%   The rows of array xy are ordered vertices of a polygon. If the
%   kth angle is convex (>0 and <= 180 degress) then sgn(k) =
%   1. Otherwise sgn(k) = -1. This function assumes that the first
%   vertex in the list is convex, and that no other vertex has a
%   smaller value of x-coordinate. These two conditions are true in
%   the first vertex generated by the MPP algorithm. Also the
%   vertices are assumed to be ordered in a clockwise sequence, and
%   there can be no duplicate vertices.
%
%   The test is based on the fact that every convex vertex is on the
%   positive side of the line passing through the two vertices
%   immediately following each vertex being considered.  If a vertex
%   is concave then it lies on the negative side of the line joining
%   the next two vertices. This property is true also if positive and
%   negative are interchanged in the preceding two sentences.

% It is assumed that the polygon is closed.  If not, close it.
if size(xy, 1) == 1 | ~isequal(xy(1, :), xy(end, :))
   xy(end + 1, :) = xy(1, :);
end

% Sign convention: sgn = 1 for convex vertices (i.e, interior angle > 0
% and <= 180 degrees), sgn = -1 for concave vertices.

% Extreme points to be used in the following loop.  A 1 is appended
% to perform the inner (dot) product with w, which is 1-by-3 (see
% below).
L = 10^25;
top_left = [-L, -L, 1];
top_right = [-L, L, 1];
bottom_left = [L, -L, 1];
bottom_right = [L, L, 1];

sgn = 1; % The first vertex is known to be convex.

% Start following the vertices.
for k = 2:length(xy) - 1
   pfirst= xy(k - 1, :);
   psecond = xy(k, :); % This is the point tested for convexity.
   pthird = xy(k + 1, :);
   % Get the coefficients of the line (polygon edge) passing
   % through pfirst and psecond.
   w = polyedge(pfirst, psecond);

   % Establish the positive side of the line w1x + w2y + w3 = 0.
   % The positive side of the line should be in the right side of the
   % vector (psecond - pfirst).  deltax and deltay of this vector
   % give the direction of travel. This establishes which of the
   % extreme points (see above) should be on the + side. If that
   % point is on the negative side of the line, then w is replaced by -w.

   deltax = psecond(:, 1) - pfirst(:, 1);
   deltay = psecond(:, 2) - pfirst(:, 2);
   if deltax == 0 & deltay == 0
      error('Data into convexity test is 0 or duplicated.')
   end
   if deltax <= 0  & deltay >= 0 % Bottom_right should be on + side.
      vector_product = dot(w, bottom_right); % Inner product.
      w = sign(vector_product)*w;
   elseif deltax <= 0 & deltay <= 0 % Top_right should be on + side.
      vector_product = dot(w, top_right);
      w = sign(vector_product)*w;
   elseif deltax >= 0 & deltay <= 0  % Top_left should be on + side.
      vector_product = dot(w, top_left);
      w = sign(vector_product)*w;
   else % deltax >= 0 & deltay >= 0, so bottom_left should be on + side.
      vector_product = dot(w, bottom_left);
      w = sign(vector_product)*w;
   end
   % For the vertex at psecond to be convex, pthird has to be on the
   % positive side of the line.
   sgn(k) = 1;
   if (w(1)*pthird(:, 1) + w(2)*pthird(:, 2) + w(3)) < 0
      sgn(k) = -1;
   end
end

%-------------------------------------------------------------------%
function w = polyedge(p1, p2)
%   Outputs the coefficients of the line passing through p1 and
%   p2. The line is of the form w1x + w2y + w3 = 0.

x1 = p1(:, 1);  y1 = p1(:, 2);
x2 = p2(:, 1);  y2 = p2(:, 2);
if x1==x2
   w2 = 0;
   w1 = -1/x1;
   w3 = 1;
elseif y1==y2
   w1 = 0;
   w2 = -1/y1;
   w3 = 1;
elseif x1 == y1 & x2 == y2
   w1 = 1;
   w2 = 1;
   w3 = 0;
else
   w1 = (y1 - y2)/(x1*(y2 - y1) - y1*(x2 - x1) + eps);
   w2 = -w1*(x2 - x1)/(y2 - y1);
   w3 = 1;
end
w = [w1, w2, w3];

%-------------------------------------------------------------------%
function [xg, yg] = dupgone(x, y)
% Eliminates duplicate, adjacent rows in [x y], except that the
% first and last rows can be equal so that the polygon is closed.

xg = x;
yg = y;
if size(xg, 1) > 2
   I = find((x(1:end-1, :) == x(2:end, :)) & ...
            (y(1:end-1, :) == y(2:end, :)));
   xg(I) = [];
   yg(I) = [];
end


% ============================================================= %
% Files of the Matlab programs included in the book:            %
%     Xin-She Yang, Nature-Inspired Metaheuristic Algorithms,   %
%     Second Edition, Luniver Press, (2010).   www.luniver.com  %
% ============================================================= %
% The Accelerated Particle Swarm Optimization:                  %
% For detail, section Chapter 5 (section 5.3) in the book by    %
% Xin-She Yang, Nature-Inspired Metaheuristic Algorithms,       %
% First Edition, Luniver Press, (2008). Also in Chapter 8       %
% (section 8.3, page 65) of the second edition (2010).          %
% ------------------------------------------------------------- %

% =============================================================
% Usage: apso(number_of_particles,timesteps)
%  eg:   best=apso(20,10);
%  where best=[xbest ybest zbest]  %a n by 3 matrix
% -------------------------------------------------------------
function [best]=apso(n,timesteps)
% n=number of particles
% timesteps=total number of time steps
if nargin<2,   timesteps=15;  end
if nargin<1,   n=20;         end
% -------------------------------------------------------------
% Michalewicz Function f*=-1.8013 at [2.20319, 1.57049]
funstr='-sin(x)*(sin(x^2/pi))^20-sin(y)*(sin(2*y^2/pi))^20';
f=inline(vectorize(funstr));
% Lb=[xmin  ymin] and Ub=[xmax ymax];
Lb=[0 0]; Ub=[4 4];
% -------------------------------------------------------------
% Setting  parameters alpha, beta
% Randomization amplitude of roaming particles alpha=[0,1]
% alpha=gamma^t=0.7^t;
% Speed of convergence (0->1)=(slow->fast); % beta=0.5
beta=0.5;
% -------------------------------------------------------------
% Grid values for show the topology of the function
% to be optimized. For display only, not used for optimization.
Ngrid=100; % Ngrid=100;
dx=(Ub(1)-Lb(1))/Ngrid;
dy=(Ub(2)-Lb(2))/Ngrid;

[x,y]=meshgrid(Lb(1):dx:Ub(1),Lb(2):dy:Ub(2));
% get the shape of the function
% you can define any function to be optimized in 'fun(x,y)'
% funflag=1 or 2 or 3 choose a function from a list

z=f(x,y);

% Display the shape of the function to be optimized
figure(1);
surfc(x,y,z);
% -----------------------------------------------------------
best=zeros(timesteps,3);

% ===========================================================
% ------------- Start Particle Swarm Optimization -----------
% generating the initial locations of n particles
[xn,yn]=init_pso(n,Lb,Ub);
% Display the paths of particles in a figure with
% contours of the function to be optimized
   figure(2);

% Time-marching or iterations
for i=1:timesteps,     %%%%% start time-stepping
   % Show the contour of the function
  contour(x,y,z,15); hold on;
  colormap cool;

% Find the current best location (xo,yo)
zn=f(xn,yn);
zn_min=min(zn);
xo=min(xn(zn==zn_min));
yo=min(yn(zn==zn_min));
zo=min(zn(zn==zn_min));

% Trace the paths of all roaming particles
% Display these roaming particles
plot(xn,yn,'.',xo,yo,'d','markersize',10,'markerfacecolor','g');

% The accelerated PSO alpha=alpha_0* gamma^t with alpha_0=1
  gamma=0.7; alpha=gamma.^i;
% Move all particle to new locations
  [xn,yn]=pso_moving(xn,yn,xo,yo,alpha,beta,Lb,Ub);
  drawnow;

% If you keep "hold on", then the paths of particles are displayed
	hold off;
% History
   best(i,1)=xo; best(i,2)=yo; best(i,3)=zo;
% Output the results (xo,yo) to screen
   str=strcat('Best estimates: =',num2str([xo yo]));
   str=strcat(str,'  fmin='); str=strcat(str,num2str(best(i,3)));
   str=strcat(str,'  Iteration='); str=strcat(str,num2str(i));
   disp(str);
end   %%%%% end of time-stepping

% Postprocessing & display best
bestsolution=best(end,1:2)
fmin=best(end,3)
% -----------------------------------------------------------------
% All subfunctions are listed here
% -----------------------------------------------------------------
% Intial locations of particles
function [xn,yn]=init_pso(n,Lb,Ub)
xn=rand(1,n)*(Ub(1)-Lb(1))+Lb(1);
yn=rand(1,n)*(Ub(2)-Lb(1))+Lb(2);

% Move all the particles toward (xo,yo)
function [xn,yn]=pso_moving(xn,yn,xo,yo,alpha,beta,Lb,Ub)
% Get the number of particles
nn=size(yn,2);
xn=xn.*(1-beta)+xo.*beta+alpha.*randn(1,nn);
yn=yn.*(1-beta)+yo.*beta+alpha.*randn(1,nn);
[xn,yn]=findrange(xn,yn,Lb,Ub);

% Make sure the particles are not outside of the range
function [xn,yn]=findrange(xn,yn,Lb,Ub)
nn=length(yn);
for i=1:nn,
   if xn(i)<=Lb(1), xn(i)=Lb(1); end
   if xn(i)>=Ub(1), xn(i)=Ub(1); end
   if yn(i)<=Lb(2), yn(i)=Lb(2); end
   if yn(i)>=Ub(2), yn(i)=Ub(2); end
end
% End of the APSO -------------------------------------------------


%% Homework 12 (a)
% Heat equation with variable coeficients using Point Jacobi Method:
%
% $\frac{\partial}{\partial x}\left (k(x,y)\frac{\partial{T}}{\partial{x}} \right )+\frac{\partial}{\partial x}\left (k(x,y)\frac{\partial{T}}{\partial{y}} \right)=0$
%
% where:
%
% $k(x,y)=1+exp\left[-\left( \frac{x-0.25-0.5y}{0.25} \right)^2 \right]$

%close all
clear all

%% Grid
h = 0.02;
lx = [0,1]; dx = h; x = lx(1):dx:lx(2); n = length(x);
ly = [0,1]; dy = h; y = ly(1):dy:ly(2); m = length(y);
T = zeros(m,n); T_next = zeros(m,n);

% Computing k(x,y) on the grid
k = zeros(m,n);
for j=1:m
    for i=1:n
        %k(j,i)=1+exp(-((x(i)-0.25-0.5*y(j))/0.25)^2);
        k(j,i)=1;
    end
end

%% Boundary Conditions
T(1,:) = 0; % Bottom (last row of the matrix)
T(m,:) = 1-cos(pi*x); % Top (first row of the matrix)
% Left and Right BCs will be updated on every iteration

%% Method of Solution
%
A = zeros(m,n); B = zeros(m,n); C = zeros(m,n); D = zeros(m,n);
r = 0.00001;
iter = 0;
r_iter = 1;
while r_iter >= r
%for s=1:5000
    for i=2:m-1
        for j=2:n-1
            A(i,j)=k(i,j)+k(i+1,j);
            B(i,j)=k(i,j)+k(i,j+1);
            C(i,j)=k(i,j)+k(i-1,j);
            D(i,j)=k(i,j)+k(i,j-1);
            if j == 2 % Matrix left Column, Neumann BC
                T_next(i,j)=...
                    1/(k(i+1,j)+k(i-1,j)+3*k(i,j)+k(i,j+1))*(...
                    A(i,j)*T(i+1,j)+...
                    B(i,j)*T(i,j+1)+...
                    C(i,j)*T(i-1,j));
            elseif j == n-1 % Matrix right Column, Neumann BC
                T_next(i,j)=...
                    1/(k(i+1,j)+k(i-1,j)+3*k(i,j)+k(i,j-1))*(...
                    A(i,j)*T(i+1,j)+...
                    C(i,j)*T(i-1,j)+...
                    D(i,j)*T(i,j-1));
            else
                T_next(i,j)=...
                    1/(k(i+1,j)+k(i-1,j)+4*k(i,j)+k(i,j+1)+k(i,j-1))*(...
                    A(i,j)*T(i+1,j)+...
                    B(i,j)*T(i,j+1)+...
                    C(i,j)*T(i-1,j)+...
                    D(i,j)*T(i,j-1));
            end
        end
    end
    T_next(1,:) = 0;            % Matrix bottom row, Direchlet BC
    T_next(m,:) = 1-cos(pi*x);  % Matrix top row, Direchlet BC
    T_next(2:m-1,1)= T_next(2:m-1,2); % Matrix Left column, Neumann BC
    T_next(2:m-1,n)= T_next(2:m-1,n-1); % Matrix right column, Neumann BC
    %r_iter = norm(T_next-T,2);
    r_iter = max(max(abs(T_next-T)));
    T = T_next;
    iter=iter+1;
end
fprintf('iterations: %4.1f \n',iter);

%% Plot Figures
figure
contourf(T)
title(['Point Jacobi Method, h =',num2str(h),', iterations: ',num2str(iter)])
xlabel('x points')
ylabel('y points')
colormap hot
colorbar('location','southoutside')


function plist = partitions(total_sum,candidate_set,max_count,fixed_count)
% extracts the list of all partitions of a number as integer sums of a list of candidates
% usage: plist = partitions(total_sum,candidate_set)
% usage: plist = partitions(total_sum,candidate_set,max_count,fixed_count)
%
% PARTITIONS solves the money changing problem. E.g.,
% how can you make change for one dollar given coins
% of a given set of denominations. A good reference on
% the general problem is found here:
%
% http://en.wikipedia.org/wiki/Integer_partition
%
% PARTITIONS uses a recursive strategy to enumerate all
% possible partitions of the total_sum. This may be
% highly intensive for large sums or large sets of
% candidates.
%
% arguments: (input)
%  total_sum - scalar positive integer (to be partitioned)
%
%              BEWARE! a large total_sum can easily cause
%              stack problems. For example, the number of
%              partitions of 40 is 37338, a set that took 24
%              seconds to completely enumerate on my cpu.
%
%  candidate_set - (OPTIONAL) vector of (distinct) candidate
%              positive integers for the partitions.
%
%              Efficiency considerations force me to require
%              that the candidates be sorted in non-decreasing
%              order. An error is produced otherwise.
%
%              DEFAULT: candidate_set = 1:total_sum
%
%              BEWARE! large candidate sets can easily cause
%              stack problems
%
%  max_count - (OPTIONAL) the maximum quantity of any
%              candidate in the final sum.
%
%              max_count must be either a vector of the
%              same length as candidate_set, or a scalar
%              that applies to all elements in that set.
%
%              DEFAULT = floor(total_sum./candidate_set)
%
%  fixed_count - (OPTIONAL) Allows you to specify a fixed
%              number of terms in the partitioned sum.
%
%              fixed_count must be a positive integer if
%              supplied.
%
%              DEFAULT = []
%
% arguments: (output)
%  plist - array of partitions of total_sum. This is a list
%              of the quantity of each element such that
%              plist*candidate_set(:) yields total_sum
%
%
% example: Write 9 as an integer combination of the set [1 2 4 7]
%
%  partitions(9,[1 2 4 7])
%
% ans =
%    9     0     0     0
%    7     1     0     0
%    5     2     0     0
%    3     3     0     0
%    1     4     0     0
%    5     0     1     0
%    3     1     1     0
%    1     2     1     0
%    1     0     2     0
%    2     0     0     1
%    0     1     0     1
%
% Thus, we can write 9 = 9*1
% or 9 = 1*1 + 4*2
% or 9 = 1*2 + 1*7
% or any of 8 distinct other ways.
%
% There are 11 such ways to write 9 in terms of these
% candidates.
%
%
% example: Change a 1 dollar bill (100 cents) as an integer
%  combination of the set [1 5 10 25 50], using no more than
%  4 of any one coin denomination. Note that no pennies will
%  be allowed by the maximum constraint.
%
%  partitions(100,[1 5 10 25 50],4)
%
% ans =
%    0     4     3     2     0
%    0     2     4     2     0
%    0     3     1     3     0
%    0     1     2     3     0
%    0     0     0     4     0
%    0     4     3     0     1
%    0     2     4     0     1
%    0     3     1     1     1
%    0     1     2     1     1
%    0     0     0     2     1
%    0     0     0     0     2
%
% example: Write 13 as an integer combination of the set [2 4 6 8 10 12]
%  (Note that no such combination exists.)
%
%  partitions(13,[2 4 6 8 10 12])
%
% ans =
%   Empty matrix: 0-by-6
%
%
% example: find all possible ways to write 100 as a sum of EXACTLY 4
%  squares of the integers 1:9.
%
%  partitions(100,(1:9).^2,[],4)
% ans =
%   0    0    0    0    4    0    0    0    0
%   1    0    0    0    2    0    1    0    0
%   2    0    0    0    0    0    2    0    0
%   0    1    0    2    0    0    0    1    0
%   1    0    2    0    0    0    0    0    1
%
%
% Author: John D'Errico
% e-mail: woodchips@rochester.rr.com
% Release: 2
% Release date: 7/15/08

% default for candidate_set
if (nargin<2) || isempty(candidate_set)
  candidate_set = 1:total_sum;
end

% how many candidates are there
n = length(candidate_set);

% error checks
if any(candidate_set<=0)
  error('All members of candidate_set must be > 0')
end
% candidates must be sorted in increasng order
if any(diff(candidate_set)<0)
  error('Efficiency requires that candidate_set be sorted')
end

% check for a max_count. do we supply a default?
if (nargin<3) || isempty(max_count)
  % how high do we need look?
  max_count = floor(total_sum./candidate_set);
elseif length(max_count)==1
  % if a scalar was provided, then turn it into a vector
  max_count = repmat(max_count,1,n);
end

% check for a fixed_count
if (nargin<4) || isempty(fixed_count)
  fixed_count = [];
elseif (fixed_count<0) || (fixed_count~=round(fixed_count))
  error('fixed_count must be a positive integer if supplied')
end

% check for degenerate cases
if isempty(fixed_count)
  if total_sum == 0
    plist = zeros(1,n);
    return
  elseif (n == 0)
    plist = [];
    return
  elseif (n == 1)
    % only one element in the set. can we form
    % total_sum from it as an integer multiple?
    p = total_sum/candidate_set;
    if (p==fix(p)) && (p<=max_count)
      plist = p;
    else
      plist = [];
    end
    return
 end
else
  % there was a fixed_count supplied
  if (total_sum == 0) && (fixed_count == 0)
    plist = zeros(1,n);
    return
  elseif (n == 0) || (fixed_count <= 0)
    plist = [];
    return
  elseif (n==1)
    % there must be a non-zero fixed_count, since
    % we did not trip the last test. since there
    % is only one candidate in the set, will it work?
    if (fixed_count*candidate_set) == total_sum
      plist = fixed_count;
    else
      plist = [];
    end
    return
  end
end

% finally, we can do some work. start with the
% largest element and work backwards
m = max_count(end);
% do we need to back off on m?
c = candidate_set(end);
m = min([m,floor(total_sum/c),fixed_count]);

plist = zeros(0,n);
for i = 0:m
  temp = partitions(total_sum - i*c, ...
      candidate_set(1:(end-1)), ...
      max_count(1:(end-1)),fixed_count-i);
  plist = [plist;[temp,repmat(i,size(temp,1),1)]];  %#ok
end


function[r]=ellrad(varargin)
%ELLRAD  Average and instantaneous ellipse radius.
%
%   R=ELLRAD(KAPPA,LAMBDA,PHI,STR) where KAPPA and LAMBDA are the amplitude
%   and linearity of a time-varying ellise, and PHI is its time-varying
%   phase, returns various measures of the ellipse 'radius'.
%
%   STR determines the radius quantity to be output.
%
%       STR       Symbol     Description
%       ----------------------------------------------------------------
%      'geo'      RM         Geometric mean radius = SQRT(A*B)
%      'ave'      RBAR       Period-averaged distance from the origin
%      'ins'      RI         Instantaneous distance from the origin
%
%   See Lilly and Gascard (2006) for details.
%
%   If STR is omitted, the geometric mean radius is returned by default.
%
%   RM=ELLRAD(KAPPA,LAMBDA) with PHI omitted also works for computing RM.
%   ____________________________________________________________________
%
%   Cell array input/output
%
%   If ELLRAD is given cell array input, it returns cell array output.
%
%   Thus KAPPA, LAMBDA, and PHI may each be cell arrays of the same size,
%   where each element in the cell array is a numerical array.
%
%   The output variables will be also cell arrays of this size.
%   ____________________________________________________________________
%
%   See also ELLVEL, ELLPARAMS, ELLDIFF.
%
%   Usage:  rm=ellrad(kappa,lambda);
%           rbar=ellrad(kappa,lambda,phi,'average');
%           ri=ellrad(kappa,lambda,phi,'instantaneous');
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2005--2014 J.M. Lilly --- type 'help jlab_license' for details

if ischar(varargin{end})
    str=varargin{end}(1:3);
    varargin=varargin(1:end-1);
else
    str='geo';
end

kappa=varargin{1};
lambda=varargin{2};

if length(varargin)==2
    if ~aresame(str,'geo')
           error('Only the geometric mean radius can be computed without PHI input.')
    else
        phi=kappa;  %It doesn't matter what we set this to as it will not be used.
    end
else
    phi=varargin{3};
end

if ~isempty(kappa)
    if ~iscell(kappa)
        r=ellrad_one(kappa,lambda,phi,str);
    else
        r=kappa;
        for i=1:length(kappa)
            r{i}=ellrad_one(kappa{i},lambda{i},phi{i},str);
        end
    end
else
    r=kappa;
end

function[r]=ellrad_one(kappa,lambda,phi,str)
if aresame(str,'geo')
     [a,b]=kl2ab(kappa,lambda);
     r=sqrt(a.*abs(b));   %r=kappa^2*sqrt(1-lambda^2);
elseif aresame(str,'ave')
     ecc=ecconv(lambda,'lin2ecc');
     [K,E]=ellipke(ecc.^2);
     r=frac(2*kappa,pi).*sqrt(1+abs(lambda)).*E;
elseif aresame(str,'ins')
     r=kappa.*sqrt(1+abs(lambda).*cos(2*phi));
end


function sigma = PropError(f,varlist,vals,errs)
%SIGMA = PROPERROR(F,VARLIST,VALS,ERRS)
%
%Finds the propagated uncertainty in a function f with estimated variables
%"vals" with corresponding uncertainties "errs".
%
%varlist is a row vector of variable names. Enter in the estimated values
%in "vals" and their associated errors in "errs" at positions corresponding
%to the order you typed in the variables in varlist.
%
%Example using period of a simple harmonic pendulum:
%
%For this example, lets say the pendulum length is 10m with an uncertainty
%of 1mm, and no error in g.
%syms L g
%T = 2*pi*sqrt(L/g)
%type the function T = 2*pi*sqrt(L/g)
%
%PropError(T,[L g],[10 9.81],[0.001 0])
%ans =
%
%    [       6.3437]    '+/-'    [3.1719e-004]
%    'Percent Error'    '+/-'    [     0.0050]
%
%(c) Brad Ridder 2007. Feel free to use this under the BSD guidelines. If
%you wish to add to this program, just leave my name and add yours to it.
n = numel(varlist);
sig = vpa(ones(1,n));
for i = 1:n
    sig(i) = diff(f,varlist(i),1);
end
error1 =sqrt((sum((subs(sig,varlist,vals).^2).*(errs.^2))));
error = double(error1);
sigma = [{subs(f,varlist,vals)} {'+/-'} {error};
         {'Percent Error'} {'+/-'} {abs(100*(error)/subs(f,varlist,vals))}];


function mean = log_normal_mean ( a, b )

%*****************************************************************************80
%
%% LOG_NORMAL_MEAN returns the mean of the Lognormal PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 1999
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < B.
%
%    Output, real MEAN, the mean of the PDF.
%
  mean = exp ( a + 0.5 * b * b );

  return
end


function N=nmultichoosek(n,k,type)
%NMULTICHOOSEK   Unordered samples WITH or WITHOUT repetition.
%   NMULTICHOOSEK(N,K) finds the number of multisets of length k on n
%   symbols. NMULTICHOOSEK can take vector or scalar input.
%
%   NMULTICHOOSEK(N,K,'single') is the same as NCHOOSEK (unordered samples WITHOUT
%    repetition), except that it accepts vector inputs for both n and k.
%
%   NMULTICHOOSEK(N,K,'multi') is the same as NMULTICHOOSEK(N,K).
%
%   Examples:
%      N = nmultichoosek(5,1:5)
%
%   finds the number of multisets of length 1 to 5 from a 5 symbol set
%
%      N = nmultichoosek(5,1:5,'single')
%
%   is the same as:
%
%      for k=1:5
%         N(k) = nchoosek(5,k);
%      end
%
%   See also nchoosek, perms.

% Author: Peter (PB) Bodin
% Email: pbodin@kth.se
% Created: 14-Nov-2005 19:48:49

msg = nargchk(2,3,nargin);
error(msg);
n = n(:);           % Convert N-D arrays to 1-D
k = k(:);           % Convert N-D arrays to 1-D
if numel(n)>1 & numel(k)>1
    if numel(n)~=numel(k)
        error('vectors must have the same number of elements')
    end
end

if nargin > 2
    switch type
        case 'single'
            N = round(exp(gammaln(n+1) - gammaln(k+1) - gammaln(n-k+1)));
            return;
        case 'multi'
        otherwise
            error('valid types are ''multi'' and ''single''');
    end
end

N = round(exp(gammaln(n+k) - gammaln(k+1) - gammaln(n)));
N(n<k)=NaN;


function [ r, t ] = xy_to_polar ( xy )

%*****************************************************************************80
%
%% XY_TO_POLAR converts XY coordinates to polar coordinates.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 December 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real XY(2,1), the Cartesian coordinates.
%
%    Output, real R, T, the radius and angle (in radians).
%
  r = norm ( xy );

  if ( r == 0.0 )
    t = 0.0;
  else
    t = atan2 ( xy(2,1), xy(1,1) );
  end

  return
end


function theRank=rankPartition(thePartition)
%%RANKPARTITION Rank a given partition of the integer n when considering
%               the partitions given in reverse lexicographic order. A
%               partition of the integer n is a set of integers that sum to
%               n.
%
%INPUTS: thePartition An sX1 or 1Xs partition. The values start at 1.
%
%OUTPUTS: the Rank. The integer rank of the partition starting from 1.
%
%Let p(n,m) be the number of partitions of n with up to m parts. It is
%known that p(n,m)=p(n,m-1)+p(n-m,m). This relation is given in Chapter
%7.2.1.4 of [1]. The rank generated is derived using that recurrence
%relation.
%
%EXAMPLE:
%The function getNextPartition generates partitions in reverse
%lexicographic order. Here, we demonstrate that the partitions generated
%are ranked correctly. We partition the integer 6.
% n=6;
% [thePartition,theData]=getNextPartition(n);
% while(~isempty(thePartition))
%     theRank=rankPartition(thePartition)
%     [thePartition,theData]=getNextPartition(n,theData);
% end
%One will see that theRank goes from 1 to 11 in order.
%
%REFERENCES:
%[1] D. E. Knuth, The Art of Computer Programming. Vol. 4, Fascicle 3:
%    Generating all Combinations and Partitions, Upper Saddle River, NJ:
%    Addison-Wesley, 2009.
%
%September 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

    m=length(thePartition);
    n=sum(thePartition);

    thePartition=sort(thePartition,'descend');

    theRank=0;
    for idx=1:m
        curParts=thePartition(idx)-1;
        if(curParts>0)
            theRank=theRank+numMPartitions(sum(thePartition(idx:m)),curParts,true);
        end
    end
    theRank=numberOfPartitions(n)-theRank;
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 = quat_norm ( q )

%*****************************************************************************80
%
%% QUAT_NORM computes the norm of a quaternion.
%
%  Discussion:
%
%    A quaternion is a quadruplet (A,B,C,D) of real numbers, which
%    may be written as
%
%      Q = A + Bi + Cj + Dk.
%
%    The norm of Q is
%
%      norm(Q) = sqrt ( A**2 + B**2 + C**2 + D**2 ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real Q(4), the quaternion.
%
%    Output, real VALUE, the norm of the quaternion.
%
  value = sqrt ( sum ( q(1:4).^2 ) );

  return
end


function [eu,cEu]=grIsEulerian(E)
% Function eu=grIsEulerian(E) returns 1 for Eulerian graph,
% 0.5 for semi-Eulerian and 0 otherwise.
% Input parameter:
%   E(m,2) - the edges of graph;
%     1st and 2nd elements of each row is numbers of vertexes;
%     m - number of edges.
% Output parameter:
%   eu = 1 for Eulerian graph;
%   eu = 0.5 for semi-Eulerian graph;
%   eu = 0 otherwise.
% The graph is Eulerian, if he is connected and powers of
% all vertexes is even.
% The graph is semi-Eulerian, if he is connected and only
% two vertexes have odd powers, and other powers of vertexes is even.
% [eu,cEu]=grIsEulerian(E) return also
%   cEu(m,1) - the vector-column with numbers of edges
%     included to Eulerian cycle (if eu=1) or Eulerian way (if eu=0.5)
%     and cEu=[] otherwise. The Fleury algorithm is used.
% Author: Sergiy Iglin
% e-mail: siglin@yandex.ru
% personal page: http://iglin.exponenta.ru

if nargin<1,
  error('There are no input data!')
end
eu = 0; % the graph is not Eulerian
cEu=[];
ncV=grComp(E); % the number of components
if max(ncV)>1, % 2 or more components
  return % the graph is not Eulerian
end
n=max(max(E(:,1:2))); % number of vertexes
E1=find([diff(sort(E(:)));1]);
p=[E1(1);diff(E1)]; % powers of vertexes
rp=rem(p,2); % remainder after division to 2
srp=sum(rp); % summa of remainders
switch srp
  case 0, % Eulerian graph
    eu=1;
  case 2, % semi-Eulerian graph
    eu=0.5;
  otherwise, % not Eulerian graph
    return
end
%=========== we find the Eulerian cycle or way =============
if nargout>1,
  if srp==0, % Eulerian graph
    v1=1; % first vertex of Eulerian cycle
  else % semi-Eulerian graph
    v1=find(rp);
    v1=v1(1); % first vertex of Eulerian way
  end
  vc=v1; % the current vertex
  m=size(E,1); % number of edges
  E1=[E(:,1:2), [1:m]']; % all edges with numbers
  while ~isempty(E1), % the Fleury algorithm
    evc=find((E1(:,1)==vc)|(E1(:,2)==vc)); % edges connected with vc
    levc=length(evc); % number of edges connected with vertex vc
    if levc==1, % only one way
      cEu=[cEu;E1(evc,3)]; % we add new edge to Eulerian cycle (way)
      vcold=vc;
      vc=sum(E1(evc,1:2))-vc; % new current vertex
      E1=E1(setdiff([1:size(E1,1)],evc),:); % we delete isolated vertex
      E2=E1(:,1:2);
      E2gv=E2>vcold;
      E2(E2gv)=E2(E2gv)-1;
      E1(:,1:2)=E2;
      if vc>vcold,
        vc=vc-1;
      end
      if v1>vcold,
        v1=v1-1;
      end
    else % several ways from vertex vc
      for k=1:levc,
        E2=E1(setdiff([1:size(E1,1)],evc(k)),:);
        ncv=grComp(E2); % number of components
        nco=max(ncv);
        if (max(ncv)==1), % this edge is not bridge
          cEu=[cEu;E1(evc(k),3)]; % we add new edge to Eulerian cycle (way)
          vc=sum(E1(evc(k),1:2))-vc; % new current vertex
          E1=E2;
          break;
        end
      end
    end
  end
end
return