function det = r8ge_np_det ( n, a_lu )

%*****************************************************************************80
%
%% R8GE_NP_DET computes the determinant of a matrix factored by R8GE_NP_FA.
%
%  Discussion:
%
%    The R8GE storage format is used for a general M by N matrix.  A storage
%    space is made for each logical entry.  The two dimensional logical
%    array is mapped to a vector, in which storage is by columns.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 March 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%    N must be positive.
%
%    Input, real A_LU(N,N), the LU factors from R8GE_NP_FA.
%
%    Output, real DET, the determinant of the matrix.
%
  det = 1.0E+00;

  for i = 1 : n
    det = det * a_lu(i,i);
  end

  return
end


function model = ml_trainlda(varargin)
% Learn a linear predictive model by (regularized) Linear Discriminant Analysis.
% Model = ml_trainlda(Trials, Targets, Lambda, Options...)
%
% LDA is one of the simplest and oldest learning algorithms, originally introduced by Fisher in [1].
% Its basic assumption is that the data originates from two classes (extended to more via 1-vs-1
% voting), where the data in each class is distributed in the feature space according to a normal
% distribution. The shape of the distribution is assumed to be identical for both classes, and the
% relative weight/prior probability of each class is (by default) assumed to be identical, as well.
% An example would be data with features generated as a weighted sum of some latent variables which
% take on different values between conditions (but identical values within each condition), and
% which are superimposed with gaussian noise (which is identically distributed across conditions,
% e.g. from a large sum of independent random variables).
%
% Despite its simplicity, LDA assumes more structure in the data than is usually necessary (namely a
% certain normal distribution per class), and sometimes, more than what can be satisfactorily
% learned from the data, so that, even when the assumptions are fulfilled, the method is not
% guaranteed to give the optimal result. The estimation of the per-class covariance matrix is a
% notoriously data-hungry (and especially outlier-sensitive) step, and the main weakness of standard
% LDA.
%
% ml_trainlda offers three advanced covariance estimators, with different trade-offs to mitigate
% these problems. The variants 'shrinkage' and 'independence' each introduce a regularization
% parameter [2] which controls the complexity of the estimated matrix, and which need to be selected
% in a parameter search (which is orders of magnitude more time-consuming). The 'auto' variant
% computes the degree of regularization analyically in closed form, and is therefore both fast and
% (in some sense) optimal (but more restricted than 'independence') [3]. When enough trials are
% available, full covariance matrices are learned, but the less trials are given, the more the
% covariance estimates degrade to spherical (though well-formed) ones. Auto is the default for lda.
%
% While regularization can automatically control the complexity of a classifier, it is not a panacea
% which allows to add arbitrarily many features, since with each additional feature, the amount of
% structure (here:correlation) that can be captured in the remaining ones gets reduced.
%
% Within the toolbox, LDA is one of the bread-and-butter classifiers, and is worth trying in every
% reasonably simple classification task, especially for its speed. The major problem with LDA
% compared to other available classifiers is that it easier to break it with outliers than, for
% example, support vector machines or logistic regression. Another weakness is that the outputs are
% relatively primitive probability estimates, in contrast to, for example, logistic regression
% (somewhat better) or relevance vector machines (clearly better).
%
% In:
%   Trials       : training data, as in ml_train
%
%   Targets      : target variable, as in ml_train
%
%   Lambda       : optional regularization parameter, reasonable range: 0:0.1:1, greater is stronger
%                  requires that the regularization mode is set to either 'shrinkage' or 'independence' (default: [])
%
%   Options  : optional name-value parameters to control the training details:
%              'regularization' -> 'shrinkage': covariance shrinkage, depends on plambda
%                                  'independence': feature independence, depends on plambda
%                                  'auto': analytical covariance shrinkage, plambda is ignored (default)
%              'weight_bias' -> 0/1, take unequal class priors into account for bias calculation
%                               default: 0
%              'weight_cov' -> 0/1, take unequal class priors into account for covariance calculation
%                              default: 0
% Out:
%   Model   : a linear model; w is the linear weights, b is the bias; classes indicates the class labels which the model predicts
%
% Examples:
%   % learn a standard shrinkage LDA model
%   model = ml_trainlda(trials,targets);
%
%   % take unequal class priors into account for both the bias and the covariance matrix
%   model = ml_trainlda(trials,targets,[],'weight_bias',1,'weight_cov',1);
%
%   % use a different type of regularization, which controls feature independence and requires cross-validation
%   model = utl_searchmodel({trials,target},'args',{{'lda',search(0:0.1:1),'regularization','independence'}})
%
%
% See also:
%   ml_predictlda
%
% References:
%   [1] Fisher, R. "The use of multiple measurements in taxonomic problems."
%       Annals Eugen. 7 (1936), 188, 179.
%   [2] Friedman, J. "Regularized discriminant analysis."
%       Journal of the American Statistical Association 84, 405 (1989), 175, 165.
%   [3] O. Ledoit and M. Wolf, "A well-conditioned estimator for large-dimensional covariance matrices"
%       J Multivar Anal, 88(2): 365-411, 2004.
%
%                           Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                           2010-04-03
dp;

arg_define([0 3],varargin, ...
    arg_norep('trials'), ...
    arg_norep('targets'), ...
    arg({'plambda','Lambda','lambda'}, [], [0 1], 'Optional regularization parameter. Reasonable range: 0:0.1:1 - greater is stronger. Requires that the regularization mode is set to either "shrinkage" or "independence" (not necessary in "auto" mode).'), ...
    arg({'regularization','Regularizer','Regularization'}, 'auto', {'none','auto','shrinkage','independence'}, 'Type of regularization. Regularizes the robustness / flexibility of covariance estimates. Auto is analytical covariance shrinkage, shrinkage is shrinkage as selected via plambda, and independence is feature independence, also selected via plambda.'), ...
    arg({'weight_bias','WeightedBias'}, false, [], 'Account for class priors in bias. If you do have unequal probabilities for the different classes, this should be enabled.'), ...
    arg({'weight_cov','WeightedCov'}, false, [], 'Account for class priors in covariance. If you do have unequal probabilities for the different classes, it makes sense to enable this.'), ...
    arg({'robust','Robust'}, false, [], 'Use robust estimation. Uses geometric medians in place of means; can help if some trials are very noisy.'), ...
    arg({'votingScheme','VotingScheme'},'1vR',{'1v1','1vR'},'Voting scheme. If multi-class classification is used, this determine how binary classifiers are arranged to solve the multi-class problem. 1v1 gets slow for large numbers of classes (as all pairs are tested), but can be more accurate than 1vR.'));

% find the class labels
classes = unique(targets);
if length(classes) > 2
    % learn a voting arrangement of models...
    model = ml_trainvote(trials, targets, votingScheme, @ml_trainlda, @ml_predictlda, varargin{:},'weight_bias',true);    %#ok<*NODEF>
elseif length(classes) == 1
    error('BCILAB:only_one_class','Your training data set has no trials for one of your classes; you need at least two classes to train a classifier.\n\nThe most likely reasons are that one of your target markers does not occur in the data, or that all your trials of a particular class are concentrated in a single short segment of your data (10 or 20 percent). The latter would be a problem with the experiment design.');
else
    % pre-prune degenerate features
    retain = true(1,size(trials,2));
    for c = 1:length(classes)
        X = trials(targets==classes(c),:);
        n{c} = size(X,1);
        mu{c} = mean(X,1);
        v{c} = var(X,[],1);
        retain = retain & isfinite(mu{c}) & isfinite(v{c}) & (n{c}==1 | v{c} > eps);
    end
    % apply feature mask...
    trials = trials(:,retain);
    % estimate distribution of each class...
    for c = 1:length(classes)
        lams{c} = NaN;
        X = trials(targets==classes(c),:);
        n{c} = size(X,1);
        if robust
            mu{c} = geometric_median(X);
        else
            mu{c} = mean(X,1);
        end
        if n{c} == 1
            sig{c} = zeros(size(X,2));
        elseif strcmp(regularization,'auto')
            if robust
                % for lack of a better solution in this case we estimate lambda using a non-robust
                % Ledoit-Wolf estimator and then use it in a subsequent robust re-estimation
                [dummy,lams{c}] = cov_shrink(X); %#ok<ASGLU>
                sig{c} = cov_blockgeom(X,1);
                sig{c} = (1-lams{c})*sig{c} + lams{c}*eye(length(sig{c}))*abs(mean(diag(sig{c})));
            else
                [sig{c},lams{c}] = cov_shrink(X);
            end
        else
            if robust
                sig{c} = cov_blockgeom(X,1);
            else
                sig{c} = cov(X);
            end
            if ~isempty(plambda) && ~strcmp(regularization,'none')
                % plambda-dependent regularization
                if strcmp(regularization,'independence')
                    sig{c} = (1-plambda)*sig{c} + plambda * diag(diag(sig{c}));
                elseif strcmp(regularization,'shrinkage')
                    sig{c} = (1-plambda)*sig{c} + plambda*eye(length(sig{c}))*abs(mean(diag(sig{c})));
                else
                    error('unknown regularization mode');
                end
            end
        end
    end

    ns = quickif(weight_cov,n,{1 1});
    nb = quickif(weight_bias,n,{1 1});
    % do the math
    mu_both = (mu{1}*nb{2} + mu{2}*nb{1}) / (nb{1}+nb{2});
    sig_both = (sig{1}*ns{1} + sig{2}*ns{2}) / (ns{1}+ns{2});
    w = (mu{2} - mu{1}) / sig_both;
    w = w / (mu{2}*w' - mu_both*w');
    model = struct('w',{w}, 'b',{mu_both*w'}, 'classes',{classes},'featuremask',{retain},'lams',{lams});
    1;
end


function [samples,gammas,Lambda,joints2D,hists] = DGAnyMarginal(pmfs,Sigma,supports,Nsamples)

% [samples,gammas,Lambda,joints2D,hists] = DGAnyMarginal(pmfs,Sigma,supports,Nsamples)
%   Generates samples from a Multivariate Discretized Gaussian with specified marginals
%   and covariance. Also returns parameters of the fitted DG.
%
%   Inputs:
%     pmfs: the probability mass functions of the marginal distribution of the
%       input-random variables. Must be a cell-array with n elements, each of
%       which is a vector which sums to one
%     Sigma: The covariance matrix of the input-random variable. The function
%       does not check for admissability, i.e. results might be wrong if there
%       exists no random variable which has the specified marginals and
%       covariance.
%     supports: The support of each dimension of the input random variable.
%       Must be a cell-array with n elements, each of whcih is a vector with
%       increasing entries giving the possible values of each random variable,
%       e.g. if the first dimension of the rv is 1 with probability .2, 3 with
%       prob .8, then pmfs{1}=[.2,.8], supports{1}=[1,3]; If empty support is
%       specified, then each is taken to be [0:numel(pdfs{k}-1];
%     Nsamples: The number of samples to be generated.
%
%   Outputs:
%     samples: a matrix of size Nsamples by n, where each row is a sample from
%       the DG.
%     gammas: the discretization thresholds, as described in the paper. When
%       sampling. The k-th dimension of the output random variable is f if e.g.
%       supports{k}(1)=f and gammas{k}(f) <= U(k) <= gammas{k}(f+1)
%     Lambda: the covariance matrix of the latent Gaussian random variable U
%     joints2D: An n by n cell array, where each entry contains the 2
%       dimensional joint distribution of  a pair of dimensions of the DG.
%     hists: the empirical marginals of the samples returned in "samples"
%
%   Usage:
%
% Code from the paper: 'Generating spike-trains with specified
% correlations', Macke et al., submitted to Neural Computation
%
% www.kyb.mpg.de/bethgegroup/code/efficientsampling

[gammas,Lambda,joints2D]=FindDGAnyMarginal(pmfs,Sigma,supports);

[samples,hists]=SampleDGAnyMarginal(gammas,Lambda,supports,Nsamples);

samples = samples';


function [dist, proj] = distancePointEllipse(point, elli)
%DISTANCEPOINTELLIPSE Distance from a point to an ellipse.
%
%   DIST = distancePointEllipse(POINT, ELLI)
%   Computes the Euclidean distance between the point POINT and the ellipse
%   ELLI.
%   POINT may also be a N-by-2 array of point coordinates. In that case the
%   result is a N-by-1 array of distances.
%
%   [DIST, PROJ] = distancePointEllipse(POINT, ELLI)
%   Also return the coordinates of the projection of the point onto the
%   ellipse. PROJ has same dimensions as the array POINT.
%
%   Example
%     % create an ellipse
%     elli = [50 50 40 30 20];
%     % generate points along a regular grid
%     [x, y] = meshgrid(1:100, 1:100);
%     pts = [x(:) y(:)];
%     % compute distance map
%     distMap = reshape(distancePointEllipse(pts, elli), size(x));
%     figure; imshow(distMap, []); colormap parula;
%
%
%   References:
%     https://blog.chatfield.io/simple-method-for-distance-to-ellipse/
%
%   See also
%     ellipses2d, projPointOnEllipse, distancePoints
%

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2022-07-17, using Matlab 9.12.0.1884302 (R2022a)
% Copyright 2022 INRAE - BIA Research Unit - BIBS Platform (Nantes)

proj = projPointOnEllipse(point, elli);

dist = distancePoints(point, proj, 'diag');


function [ fea, out ] = ex_poisson1( varargin )
%EX_POISSON1  1D Poisson equation example.
%
%   [ FEA, OUT ] = EX_POISSON1( VARARGIN ) Poisson equation on a line with a
%   constant source term equal to 1, homogenous boundary conditions, and
%   exact solution (-x^2+x)/2. Accepts the following property/value pairs.
%
%       Input       Value/{Default}        Description
%       -----------------------------------------------------------------------------------
%       hmax        scalar {1/10}          Grid cell size
%       sfun        string {sflag1}        Finite element shape function
%       iphys       scalar 0/{1}           Use physics mode to define problem    (=1)
%                                          or directly define fea.eqn/bdr fields (=0)
%                                          or use core assembly functions        (<0)
%       iplot       scalar 0/{1}           Plot solution (=1)
%                                                                                .
%       Output      Value/(Size)           Description
%       -----------------------------------------------------------------------------------
%       fea         struct                 Problem definition struct
%       out         struct                 Output struct

% Copyright 2013-2022 Precise Simulation, Ltd.

cOptDef = { 'hmax',   1/10;
            'sfun',   'sflag1';
            'refsol', '(-x^2+x)/2';
            'fsrc',   '1';
            'iphys',  1;
            'icub',   2;
            'iplot',  1;
            'tol',    2e-2;
            'fid',    1 };
[got,opt] = parseopt(cOptDef,varargin{:});
fid       = opt.fid;

% Grid generation.
if( opt.hmax>0 )
  nx = round( 1/opt.hmax );
  fea.grid = linegrid( nx, 0, 1 );
else   % Scrambled testing grid.
  fea.grid.p = [ 0 1/10 4/10 1/3 1 1-1/3 ];
  fea.grid.c = [ 1 4 2 6 3 ;
                 2 3 4 5 6 ];
  fea.grid.a = [ 0 2 1 4 3 ;
                 2 4 3 0 5 ];
  fea.grid.b = [ 1 1 1 -1 ;
                 4 2 2  1 ]';
  fea.grid.s = ones(1,5);
end
n_bdr = 2;   % Number of boundaries.

% Problem definition.
fea.sdim  = { 'x' };                    % Coordinate name.
switch opt.iphys

 case 0   % Directly define fea.eqn/bdr fields.

  fea.dvar  = { 'u' };                  % Dependent variable name.
  fea.sfun  = { opt.sfun  };            % Shape function.

  % Define equation system.
  fea.eqn.a.form = { [2;2] };           % First row indicates test function space   (2=x-derivative),
                                        % second row indicates trial function space (2=x-derivative).
  fea.eqn.a.coef = { 1 };               % Coefficient used in assembling stiffness matrix.

  fea.eqn.f.form = { 1 };               % Test function space to evaluate in right hand side (1=function values).
  fea.eqn.f.coef = { opt.fsrc };        % Coefficient used in right hand side.

  % Define boundary conditions.
  if( strcmp(opt.sfun(end-1:end),'H3') )   % Prescribed derivatives at end points for Hermite elements.
    fea.bdr.d = {{ 0 0 ; 1/2 -1/2 }};
  else
    fea.bdr.d     = cell(1,n_bdr);
    [fea.bdr.d{:}] = deal(0);              % Assign zero to all boundaries (homogenous Dirichlet conditions).
  end

  fea.bdr.n     = cell(1,n_bdr);        % No Neumann boundaries ('fea.bdr.n' empty).

  % Parse and solve problem.
  fea       = parseprob(fea);           % Check and parse problem struct.
  fea.sol.u = solvestat(fea,'fid',fid,'icub',opt.icub); % Call to stationary solver.

 case 1   % Use physics mode.

  fea = addphys(fea,@poisson);          % Add Poisson equation physics mode.
  fea.phys.poi.sfun = { opt.sfun };     % Set shape function.
  fea.phys.poi.eqn.coef{3,4} = { opt.fsrc };   % Set source term coefficient.
  fea.phys.poi.bdr.coef{1,end} = repmat({0},1,n_bdr);   % Set Dirichlet boundary coefficient to zero.
  fea = parsephys(fea);                 % Check and parse physics modes.
  if( strcmp(opt.sfun(end-1:end),'H3') )   % Prescribed derivatives at end points for Hermite elements.
    fea.bdr.d = {{ 0 0 ; 1/2 -1/2 }};
  end

  % Parse and solve problem.
  fea       = parseprob(fea);           % Check and parse problem struct.
  fea.sol.u = solvestat(fea,'fid',fid,'icub',opt.icub); % Call to stationary solver.

 otherwise   % Use core assembly functions.

  fea.dvar  = { 'u' };                  % Dependent variable name.
  fea.sfun  = { opt.sfun  };            % Shape function.
  fea       = parseprob(fea);           % Check and parse problem struct.

  % Assemble stiffness matrix.
  form  = [2;2];
  sfun  = {opt.sfun;opt.sfun};
  coefa = 1;
  sind  = 1;
  i_cub = opt.icub;

  [vRowInds,vColInds,vAvals,n_rows,n_cols] = ...
    assemblea(form,sfun,coefa,i_cub,fea.grid.p,fea.grid.c,fea.grid.a,fea.grid.s,[]);
  A = sparse(vRowInds,vColInds,vAvals,n_rows,n_cols);

  % Check and compare with finite difference stencil.
  if (strcmp(opt.sfun,'sflag1'))
    h = 1/nx;
    n = nx+1;
    e = ones(n,1);
    A_ref = 1/h*spdiags([-e 2*e -e], -1:1, n, n);
    A_ref(1) = A_ref(1)/2;
    A_ref(end) = A_ref(end)/2;

    err = norm(A(:)-A_ref(:));
    if err>opt.tol
      out.err  = err;
      out.pass = -1;
      return
    end
  end

  form  = 1;
  sfun  = sfun{1};
  coeff = 1;

  f = assemblef(form,sfun,coeff,i_cub,fea.grid.p,fea.grid.c,fea.grid.a,fea.grid.s,[]);

  % Check and compare with finite difference stencil.
  if (strcmp(opt.sfun,'sflag1'))
    f_ref          = coeff*h*ones(n,1);
    f_ref([1 end]) = coeff*1/2*h;

    err = norm(f-f_ref);
    if err>1e-6
      out.err  = err;
      out.pass = -2;
      return
    end
  end

  % Set homogenous Dirichlet boundary conditions on first and last dof/node.
  bind = [1 nx+1];
  A = A';   %'
  A(:,bind) = 0;         % Zero out Dirichlet BC rows.
  for i=1:length(bind)   % Loop to set diagonal entry to 1.
    i_a = bind(i);
    A(i_a,i_a) = 1;
  end
  A = A';   %'
  f(bind) = 0;           % Set corresponding source term entries to Dirichlet BC values.

  % Solve problem.
  fea.sol.u = A\f;

end

% Postprocessing.
if ( opt.iplot>0 )
  x = linspace( 0, 1, 41 );
  u = evalexpr( 'u', x, fea )';
  figure
  subplot(3,1,1)
  plot( x, u )
  axis( [0 1 0 0.2])
  grid on
  title('Solution u')
  subplot(3,1,2)
  ux = (-x.^2+x)/2;
  plot( x, ux )
  axis( [0 1 0 0.2])
  grid on
  title('Exact solution')
  subplot(3,1,3)
  plot( x, abs(ux-u) )
  title('Error')
end

% Error checking.
xi = [1/2; 1/2];
s_err = ['abs(',opt.refsol,'-u)'];
err = evalexpr0(s_err,xi,1,1:size(fea.grid.c,2),[],fea);
ref = evalexpr0('u',xi,1,1:size(fea.grid.c,2),[],fea);
err = sqrt(sum(err.^2)/sum(ref.^2));

if( ~isempty(fid) )
  fprintf(fid,'\nL2 Error: %e\n',err)
  fprintf(fid,'\n\n')
end

out.err  = err;
out.tol  = opt.tol;
out.pass = out.err<out.tol;
if ( nargout==0 )
  clear fea out
end


function [lambda_vec, error_train, error_val] = ...
    validationCurve(X, y, Xval, yval)
%VALIDATIONCURVE Generate the train and validation errors needed to
%plot a validation curve that we can use to select lambda
%   [lambda_vec, error_train, error_val] = ...
%       VALIDATIONCURVE(X, y, Xval, yval) returns the train
%       and validation errors (in error_train, error_val)
%       for different values of lambda. You are given the training set (X,
%       y) and validation set (Xval, yval).
%

% Selected values of lambda (you should not change this)
lambda_vec = [0 0.001 0.003 0.01 0.03 0.1 0.3 1 3 10]';

% You need to return these variables correctly.
error_train = zeros(length(lambda_vec), 1);
error_val = zeros(length(lambda_vec), 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return training errors in
%               error_train and the validation errors in error_val. The
%               vector lambda_vec contains the different lambda parameters
%               to use for each calculation of the errors, i.e,
%               error_train(i), and error_val(i) should give
%               you the errors obtained after training with
%               lambda = lambda_vec(i)
%
% Note: You can loop over lambda_vec with the following:
%
%       for i = 1:length(lambda_vec)
%           lambda = lambda_vec(i);
%           % Compute train / val errors when training linear
%           % regression with regularization parameter lambda
%           % You should store the result in error_train(i)
%           % and error_val(i)
%           ....
%
%       end
%
%

for i = 1 : length(lambda_vec),
	lambda = lambda_vec(i);
	[theta] = trainLinearReg(X, y, lambda);
	[error_train(i), grad] = linearRegCostFunction(X, y, theta, 0);
	[error_val(i), grad] = linearRegCostFunction(Xval , yval, theta, 0);
end

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

end


% Copyright (C) 1999 Paul Kienzle <pkienzle@users.sf.net>
% Copyright (C) 2003 Doug Stewart <dastew@sympatico.ca>
% Copyright (C) 2011 Alexander Klein <alexander.klein@math.uni-giessen.de>
%
% This program is free software; you can redistribute it and/or modify it under
% the terms of the GNU General Public License as published by the Free Software
% Foundation; either version 3 of the License, or (at your option) any later
% version.
%
% This program is distributed in the hope that it will be useful, but WITHOUT
% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
% FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
% details.
%
% You should have received a copy of the GNU General Public License along with
% this program; if not, see <http://www.gnu.org/licenses/>.

% Generate a butterworth filter.
% Default is a discrete space (Z) filter.
%
% [b,a] = butter(n, Wc)
%    low pass filter with cutoff pi*Wc radians
%
% [b,a] = butter(n, Wc, 'high')
%    high pass filter with cutoff pi*Wc radians
%
% [b,a] = butter(n, [Wl, Wh])
%    band pass filter with edges pi*Wl and pi*Wh radians
%
% [b,a] = butter(n, [Wl, Wh], 'stop')
%    band reject filter with edges pi*Wl and pi*Wh radians
%
% [z,p,g] = butter(...)
%    return filter as zero-pole-gain rather than coefficients of the
%    numerator and denominator polynomials.
%
% [...] = butter(...,'s')
%     return a Laplace space filter, W can be larger than 1.
%
% [a,b,c,d] = butter(...)
%  return  state-space matrices
%
% References:
%
% Proakis & Manolakis (1992). Digital Signal Processing. New York:
% Macmillan Publishing Company.

function [a, b, c, d] = oc_butter (n, W, varargin)

if (nargin>4 || nargin<2) || (nargout>4 || nargout<2)
    print_usage;
end

% interpret the input parameters
if (~(length(n)==1 && n == round(n) && n > 0))
    error ('butter: filter order n must be a positive integer');
end

stop = 0;
digital = 1;
for i=1:length(varargin)
    switch varargin{i}
        case 's', digital = 0;
        case 'z', digital = 1;
        case { 'high', 'stop' }, stop = 1;
        case { 'low',  'pass' }, stop = 0;
        otherwise,  error ('butter: expected [high|stop] or [s|z]');
    end
end

[r, c]=size(W);
if (~(length(W)<=2 && (r==1 || c==1)))
    error ('butter: frequency must be given as w0 or [w0, w1]');
elseif (~(length(W)==1 || length(W) == 2))
    error ('butter: only one filter band allowed');
elseif (length(W)==2 && ~(W(1) < W(2)))
    error ('butter: first band edge must be smaller than second');
end

if ( digital && ~all(W >= 0 & W <= 1))
    error ('butter: critical frequencies must be in (0 1)');
elseif ( ~digital && ~all(W >= 0 ))
    error ('butter: critical frequencies must be in (0 inf)');
end

% Prewarp to the band edges to s plane
if digital
    T = 2;       % sampling frequency of 2 Hz
    W = 2/T*tan(pi*W/T);
end

% Generate splane poles for the prototype butterworth filter
% source: Kuc
C = 1; % default cutoff frequency
pole = C*exp(1i*pi*(2*(1:n) + n - 1)/(2*n));
if mod(n,2) == 1, pole((n+1)/2) = -1; end  % pure real value at exp(i*pi)
zero = [];
gain = C^n;

% splane frequency transform
[zero, pole, gain] = oc_sftrans(zero, pole, gain, W, stop);

% Use bilinear transform to convert poles to the z plane
if digital
    [zero, pole, gain] = oc_bilinear(zero, pole, gain, T);
end

% convert to the correct output form
if nargout==2,
    a = real(gain*poly(zero));
    b = real(poly(pole));
elseif nargout==3,
    a = zero;
    b = pole;
    c = gain;
else
    % output ss results
    % [a, b, c, d] = oc_zp2ss(zero, pole, gain);
    error('Not supported');
end

end


%% Ex. 13 Making a quick plot
x = [0:0.1:20];
y = sin(x);
plot(x,y)

% remaks : Remarks: This only serves as a very quick example of what Matlab can do in making
% plots.The first line is equivalent to x = [0 0.1 0.2 0.3 ... 19.8 19.9 20]. It
% assigns the content of x which is an array of 201 elements. The "0:0.1:20" means the
% 201 numbers are evenly spaced. They start from 0 and end at 20 with an increment of
% 0.1. The second line gives the content of the new array, y, as
 % y = [sin(x(1)) sin(x(2)) sin(x(3)) ... sin(x(200)) sin(x(201))] ,
% or
% y = [sin(0) sin(0.1) sin(0.2) ... sin(19.9) sin(20)] .
% The 3rd line makes a plot of y vs. x.


% Count the number of multiple edges in the graph.
%
% INPUT: adjacency matrix, nxn
% OUTPUT: integer, number of multiple edges
%
% Examples: multiEdges([0 2; 2 0])=1, and multiEdges([0 0 1; 2 0 0; 0 1 0])=1
%
% Note 1: The definition of number of multi-arcs/edges (node pairs
%         that have multiple edges across them) here is:
%         mA = length(find(adj>1)); (normalized by 2 if the graph is directed).
%
% Note 2: This creates a natural difference in counting for
% undirected and directed graphs.
%
% Other routines used: isSymmetric.m
% GB: last updated, Sep 26 2014

function mE=multiEdges(adj)

if isSymmetric(adj) % here use "is symmetric" as surrogate for "is directed"
  mE=length(find(adj>1))/2;
else
  mE=length(find(adj>1));
end


function [ r, seed ] = r8mat_uniform_01 ( m, n, seed )

%*****************************************************************************80
%
%% R8MAT_UNIFORM_01 returns a unit pseudorandom R8MAT.
%
%  Modified:
%
%    21 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Paul Bratley, Bennett Fox, Linus Schrage,
%    A Guide to Simulation,
%    Springer Verlag, pages 201-202, 1983.
%
%    Bennett Fox,
%    Algorithm 647:
%    Implementation and Relative Efficiency of Quasirandom
%    Sequence Generators,
%    ACM Transactions on Mathematical Software,
%    Volume 12, Number 4, pages 362-376, 1986.
%
%    Peter Lewis, Allen Goodman, James Miller,
%    A Pseudo-Random Number Generator for the System/360,
%    IBM Systems Journal,
%    Volume 8, pages 136-143, 1969.
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns in the array.
%
%    Input, integer SEED, the integer "seed" used to generate
%    the output random number.
%
%    Output, real R(M,N), an array of random values between 0 and 1.
%
%    Output, integer SEED, the updated seed.  This would
%    normally be used as the input seed on the next call.
%
  if ( seed == 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_UNIFORM_01 - Fatal error!\n' );
    fprintf ( 1, '  Input SEED = 0!\n' );
    error ( 'R8MAT_UNIFORM_01 - Fatal error!' );
  end

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

      seed = floor ( seed );

      seed = mod ( seed, 2147483647 );

      if ( seed < 0 )
        seed = seed + 2147483647;
      end

      k = floor ( seed / 127773 );

      seed = 16807 * ( seed - k * 127773 ) - k * 2836;

      if ( seed < 0 )
        seed = seed + 2147483647;
      end

      r(i,j) = seed * 4.656612875E-10;

    end
  end


function a = dorr_inverse ( alpha, n )

%*****************************************************************************80
%
%% DORR_INVERSE returns the inverse of the DORR matrix.
%
%  Discussion:
%
%    The DORR matrix is a special case of the TRIV matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 February 2015
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    CM daFonseca, J Petronilho,
%    Explicit Inverses of Some Tridiagonal Matrices,
%    Linear Algebra and Its Applications,
%    Volume 325, 2001, pages 7-21.
%
%  Parameters:
%
%    Input, real ALPHA, the parameter.
%
%    Input, integer N, the order of the matrix.
%
%    Output, real A(N,N), the inverse of the matrix.
%

%
%  Form the three diagonals.
%
  x = zeros ( n - 1, 1 );
  y = zeros ( n,     1 );
  z = zeros ( n - 1, 1 );

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

      if ( i <= floor ( ( n + 1 ) / 2 ) )

        if ( j == i - 1 )
          x(i-1) = - alpha * ( n + 1 )^2;
        elseif ( j == i )
          y(i) = 2.0 * alpha * ( n + 1 )^2 + 0.5 * ( n + 1 ) - i;
        elseif ( j == i + 1 )
          z(i) = - alpha * ( n + 1 )^2 - 0.5 * ( n + 1 ) + i;
        end

      else

        if ( j == i - 1 )
          x(i-1) = - alpha * ( n + 1 )^2 + 0.5 * ( n + 1 ) - i;
        elseif ( j == i )
          y(i) = 2.0 * alpha * ( n + 1 )^2 - 0.5 * ( n + 1 ) + i;
        elseif ( j == i + 1 )
          z(i) = - alpha * ( n + 1 )^2;
        end

      end

    end
  end
%
%  Now evaluate the inverse.
%
  a = zeros ( n, n );

  d = zeros ( n, 1 );
  e = zeros ( n, 1 );

  d(n) = y(n);
  for i = n - 1 : -1 : 1
    d(i) = y(i) - x(i) * z(i) / d(i+1);
  end

  e(1) = y(1);
  for i = 2 : n
    e(i) = y(i) - x(i-1) * z(i-1) / e(i-1);
  end

  for i = 1 : n
    for j = 1 : i
      a(i,j) = r8_mop ( i + j ) * prod ( x(j:i-1) ) ...
        * prod ( d(i+1:n) ) / prod ( e(j:n) );
    end
    for j = i + 1 : n
      a(i,j) = r8_mop ( i + j ) * prod ( z(i:j-1) ) ...
        * prod ( d(j+1:n) ) / prod ( e(i:n) );
    end
  end

  return
end


function [lambda_vec, error_train, error_val] = ...
    validationCurve(X, y, Xval, yval)
%VALIDATIONCURVE Generate the train and validation errors needed to
%plot a validation curve that we can use to select lambda
%   [lambda_vec, error_train, error_val] = ...
%       VALIDATIONCURVE(X, y, Xval, yval) returns the train
%       and validation errors (in error_train, error_val)
%       for different values of lambda. You are given the training set (X,
%       y) and validation set (Xval, yval).
%

% Selected values of lambda (you should not change this)
lambda_vec = [0 0.001 0.003 0.01 0.03 0.1 0.3 1 3 10]';

% You need to return these variables correctly.
error_train = zeros(length(lambda_vec), 1);
error_val = zeros(length(lambda_vec), 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return training errors in
%               error_train and the validation errors in error_val. The
%               vector lambda_vec contains the different lambda parameters
%               to use for each calculation of the errors, i.e,
%               error_train(i), and error_val(i) should give
%               you the errors obtained after training with
%               lambda = lambda_vec(i)
%
% Note: You can loop over lambda_vec with the following:
%
%       for i = 1:length(lambda_vec)
%           lambda = lambda_vec(i);
%           % Compute train / val errors when training linear
%           % regression with regularization parameter lambda
%           % You should store the result in error_train(i)
%           % and error_val(i)
%           ....
%
%       end
%
%
for i = 1:length(lambda_vec)
	lambda = lambda_vec(i);
	theta = trainLinearReg(X, y, lambda);
    error_train(i) = linearRegCostFunction(X, y, theta, 0);
	error_val(i) = linearRegCostFunction(Xval,yval,theta,0);
end

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

end


function tanh_plot ( )

%*****************************************************************************80
%
%% TANH_PLOT makes a plot of certain tanh() functions.
%
%  Discussion:
%
%    The value is +1 if the number is positive or zero, and it is -1 otherwise.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 April 2012
%
%  Author:
%
%    John Burkardt
%
  m = 101;
  x = ( linspace ( -1.0, +1.0, m ) )';

  u = zeros ( m, 6 );
  for j = 0 : 5
    s = 2^j;
    u(:,j+1) = tanh ( s * x(:) / 2.0 ) / ( tanh ( s * -1.0 / 2.0 ) );
  end

  plot ( x, u, 'Linewidth', 3 )
  grid on
  axis ( [-1, +1, -1.1, +1.1 ] )
  xlabel ( '<--- X --->' )
  ylabel ( '<--- U(X) ---> ' )
  title ( 'tanh ( 2^J * x / 2.0 ), J = 0, 1, ..., 5 scaled to be +1 at -1' )

  return
end


function lattice_rule_test06 ( )

%*****************************************************************************80
%
%% LATTICE_RULE_TEST06 tests FIBONACCI_LATTICE_Q3;
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 November 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Ian Sloan, Stephen Joe,
%    Lattice Methods for Multiple Integration,
%    Oxford, 1994.
%
  dim_num = 2;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'LATTICE_RULE_TEST06\n' );
  fprintf ( 1, '  FIBONACCI_LATTICE_Q3 applies a Fibonacci lattice rule\n' );
  fprintf ( 1, '  to integrate a function over the unit square.\n' );
  fprintf ( 1, '  A nonlinear coordinate transformation is applied.\n' );
  fprintf ( 1, '  These Fibonacci rules are only available in 2D.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The spatial dimension DIM_NUM = %d\n', dim_num );

  a(1:dim_num) = 0.0;
  b(1:dim_num) = 1.0;

  exact = e_01_2d ( dim_num, a, b );

  fprintf ( 1, '\n' );
  fprintf ( 1, '         K         M    EXACT       ESTIMATE    ERROR\n' );
  fprintf ( 1, '\n' );

  for k = 3 : 18

    quad = fibonacci_lattice_q3 ( k, @f_01_2d );

    error = abs ( exact - quad );
    m = fibonacci ( k );

    fprintf ( 1, '  %8d  %8d  %10.6f  %10.6f  %10.6e\n', k, m, exact, quad, error );

  end

  return
end


%% Transient diffusion equation
%% PDE and boundary conditions
% The transient diffusion equation reads
%
% $$\alpha\frac{\partial c}{\partial t}+\nabla.\left(-D\nabla c\right)=0,$$
%
% where $c$ is the independent variable (concentration, temperature, etc)
% , $D$ is the diffusion coefficient, and $\alpha$ is a constant.
% Written by Ali A. Eftekhari
% Last checked: June 2021
clc

%% Define the domain and create a mesh structure
L = 50;  % domain length
Nx = 20; % number of cells
m = createMesh2D(Nx,Nx, L,L);
%% Create the boundary condition structure
BC = createBC(m); % all Neumann boundary condition structure
BC.left.a(:) = 0; BC.left.b(:)=1; BC.left.c(:)=0; % left boundary
BC.right.a(:) = 0; BC.right.b(:)=1; BC.right.c(:)=0; % right boundary
BC.top.a(:) = 0; BC.top.b(:)=1; BC.top.c(:)=0; % top boundary
BC.bottom.a(:) = 0; BC.bottom.b(:)=1; BC.bottom.c(:)=0; % bottom boundary
%% define the transfer coeffs
D_val = 1;
D = createCellVariable(m, D_val);
alfa = createCellVariable(m, 1);
%% define initial values
c_init = 1;
c_old = createCellVariable(m, c_init,BC); % initial values
c = c_old; % assign the old value of the cells to the current values
%% loop
dt = 1; % time step
final_t = 100;
for t=dt:dt:final_t
    [M_trans, RHS_trans] = transientTerm(c_old, dt, alfa);
    Dave = harmonicMean(D);
    Mdiff = diffusionTerm(Dave);
    [Mbc, RHSbc] = boundaryCondition(BC);
    M = M_trans-Mdiff+Mbc;
    RHS = RHS_trans+RHSbc;
    c = solvePDE(m,M, RHS);
    c_old = c;
    figure(1);visualizeCells(c);drawnow;
end


%  Figure 3.26      Feedback Control of Dynamic Systems, 6e
%                        Franklin, Powell, Emami
% script to generate Fig. 3.26

clf;
zeta=.5;
k=1/zeta;
den=[1 1 1];

a=10;
num=[k/a 1];
t=0:.1:10;
y1=step(num,den,t);

a=4;
num=[k/a 1];
t=0:.1:10;
y2=step(num,den,t);

a=2;
num=[k/a 1];
t=0:.1:10;
y3=step(num,den,t);

a=1;
num=[k/a 1];
t=0:.1:10;
y4=step(num,den,t);

plot(t,y1,'-',t,y2,'-',t,y3,'-',t,y4,'-'),grid
title('Fig. 3.26 Step response with \xi = 0.5')
xlabel('\omega_n t')
ylabel('Step response of H(s)')
text(.1,.9,'\alpha=')
text(.6,.9,'1')
text(1.1,.9,'2')
text(1.5,.85,'4')
text(1.8,.8,'100')
% grid
nicegrid


function f = f_function ( x, y1, y2, Md, Nd, L )

%*****************************************************************************80
%
%% F_FUNCTION: RHS function from exact coefficient Q and the exact solution U.
%
%  Discussion:
%
%    The differential equation has the form:
%
%      ( q(x) u_x(x) )_x = f(x)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Parameters:
%
%    x = physical space point of length one
%
%    y1 = stochastic vector of length Md (from the expansion for u)
%
%    y2 = stochastic vector of length Nd (from the expansion for q)
%
%    Md = dimension of the probability space for u
%
%    Nd = dimension of the probability space for q
%
%    L = the correlation length of the random variables
%
  [n_nodes, dim] = size(x);
  f = zeros( n_nodes, 1 );

  for n=1:Nd

  	for m=1:Md

  	 f = f + qn(n) * um( m ) * pn(y2, n) * pm(y1, m) * ...
  	 ( -(pi/L)^2 * m^2 .* sin((m*pi*x)/L) .* cos((n*pi*x)/L) ...
  	 -n*m * (pi/L)^2 * cos((m*pi*x)/L) .* sin((n*pi*x)/L) );

 	end

  end

  return
end
function p_m = pm( y, m )

%*****************************************************************************80
%
%% PM
%
  p_m = y(m);

  return
end
function p_n = pn( y, n )

%*****************************************************************************80
%
%% PN
%
  p_n = y(n);

  return
end
function q_n = qn( n )

%*****************************************************************************80
%
%% QN
%
  q_n = 1;

  return
end
function u_m = um( m )

%*****************************************************************************80
%
%% UM
%
 u_m = 1;

 return
end


function [P1, P2, spectrum] = slcopca(X1, X2, d, varargin)
%SLCOPCA Performs Coupled PCA Learning
%
% $ Syntax $
%   - [P1, P2] = slcopca(X1, X2, sch, ...)
%   - [P1, P2, spectrum] = slcopca(...)
%
% $ Arguments $
%   - X1:       The samples in the first modality
%   - X2:       The samples in the second modality
%   - d:        The target space dimension
%   - P1:       The projection matrix (bases) of the first modality space
%   - P2:       The projection matrix (bases) of the second modality space
%   - spectrum: The covariance energy along dimensions of target space
%
% $ Description $
%   - [P1, P2] = slcopca(X1, X2, sch, ...) performs coupled PCA learning
%     for two correlated sample spaces. The learning objective is to
%     pursue two subspaces such that they are maximally correlated. The
%     objective function is formulated as
%
%       maximize trace( P1^T * C_12 * P2 * P2^T * C_21 * P1 ) / n
%           s.t. P1^T * P1 = I, and  P2^T * P2 = I
%       where C_12 is the covariance between X1 and X2,
%             C_21 is the covariance between X2 and X1
%
%     Suppose the dimensions for the two spaces are d1 and d2 respectively,
%     and n pairs of corresponding samples are given in X1 and X2. Then X1
%     and X2 should be d1 x n and d2 x n matrices respectively.
%     You can further specify the following properties to control the
%     learning procedure:
%       - 'weights':    The weights of the samples, default = []
%       - 'mean1':      The pre-computed mean vector for X1, default = []
%                       if mean1 is set as 0, then it means that X1 has
%                       been centralized.
%       - 'mean2':      The pre-computed mean vector for X2, default = []
%
%   - [P1, P2, spectrum] = slcopca(...) also outputs the spectrum. You
%     can specify the following properties to control the type of the
%     output spectrum:
%       - 'spectype':   The type of output spectrum
%                       - 'normal': The average energies along target
%                                   dimensions.
%                       - 'ratio':  The ratio of preserved energy along
%                                   target dimensions to the total
%                                   energy.
%                       default = 'normal'.
%
% $ History $
%   - Created by Dahua Lin, on Sep 16, 2006
%

%% parse and verify input arguments

if nargin < 3
    raise_lackinput('slcopca', 3);
end

if ~isnumeric(X1) || ~isnumeric(X2) || ndims(X1) ~= 2 || ndims(X2) ~= 2
    error('sltoolbox:invalidarg', ...
        'X1 and X2 should be 2D numeric matrices');
end

[d1, n] = size(X1);
[d2, n2] = size(X2);
if n ~= n2
    error('sltoolbox:sizmismatch', ...
        'The numbers of samples in X1 and X2 do not match');
end

dmax = min(d1, d2);
if d > dmax
    error('sltoolbox:invalidarg', ...
        'The target dimension d should not exceed d1 or d2');
end

opts.weights = [];
opts.mean1 = [];
opts.mean2 = [];
opts.spectype = 'normal';
opts = slparseprops(opts, varargin{:});

w = opts.weights;
if ~isempty(w)
    if ~isequal(size(w), [1, n])
        error('sltoolbox:sizmismatch', ...
            'w should be a 1 x n row vector');
    end
end

vmean1 = opts.mean1;
vmean2 = opts.mean2;
if ~isempty(vmean1) && ~isequal(vmean1, 0) && ~isequal(size(vmean1), [d1, 1])
    error('sltoolbox:sizmismatch', ...
        'The size of mean1 is illegal');
end
if ~isempty(vmean2) && ~isequal(vmean2, 0) && ~isequal(size(vmean2), [d2, 1])
    error('sltoolbox:sizmismatch', ...
        'The size of mean1 is illegal');
end

%% main skeleton

% preprocess sample matrices

X1 = preprocess_samples(X1, vmean1, w);
X2 = preprocess_samples(X2, vmean2, w);

% construct problem
S = X1 * X2';

switch opts.spectype
    case 'normal'
        if isempty(w)
            tw = n;
        else
            tw = sum(w);
        end
    case 'ratio'
        tw = trace(S * S');
    otherwise
        error('sltoolbox:invalidarg', ...
            'Invalid spectrum type: %s', opts.spectype);
end

if d > dmax / 3;
    [P1, D, P2] = svd(S, 'econ');
    spectrum = diag(D);
    spectrum = spectrum(1:d);
    P1 = P1(:, 1:d);
    P2 = P2(:, 1:d);
else
    [P1, D, P2] = svds(S, d);
    spectrum = diag(D);
end

% post-process spectrum
if nargout >= 3
    spectrum = spectrum .* spectrum / tw;
end

%% Auxiliary functions

function Xp = preprocess_samples(X, vmean, w)

if ~isequal(vmean, 0)
    if isempty(vmean)
        vmean = slmean(X, w, true);
    end
    Xp = sladdvec(X, -vmean, 1);
else
    Xp = X;
end

if ~isempty(w)
    Xp = slmulvec(Xp, w, 2);
end


function [ n_data, n, k, x, b ] = bernstein_poly_01_values ( n_data )

%*****************************************************************************80
%
%% BERNSTEIN_POLY_01_VALUES returns some values of the Bernstein polynomials.
%
%  Discussion:
%
%    The Bernstein polynomials are assumed to be based on [0,1].
%
%    The formula for the Bernstein polynomials is
%
%      B(N,I)(X) = [N!/(I!*(N-I)!)] * (1-X)**(N-I) * X**I
%
%    In Mathematica, the function can be evaluated by:
%
%      Binomial[n,i] * (1-x)^(n-i) * x^i
%
%  First values:
%
%    B(0,0)(X) = 1
%
%    B(1,0)(X) =      1-X
%    B(1,1)(X) =                X
%
%    B(2,0)(X) =     (1-X)**2
%    B(2,1)(X) = 2 * (1-X)    * X
%    B(2,2)(X) =                X**2
%
%    B(3,0)(X) =     (1-X)**3
%    B(3,1)(X) = 3 * (1-X)**2 * X
%    B(3,2)(X) = 3 * (1-X)    * X**2
%    B(3,3)(X) =                X**3
%
%    B(4,0)(X) =     (1-X)**4
%    B(4,1)(X) = 4 * (1-X)**3 * X
%    B(4,2)(X) = 6 * (1-X)**2 * X**2
%    B(4,3)(X) = 4 * (1-X)    * X**3
%    B(4,4)(X) =                X**4
%
%  Special values:
%
%    B(N,I)(X) has a unique maximum value at X = I/N.
%
%    B(N,I)(X) has an I-fold zero at 0 and and N-I fold zero at 1.
%
%    B(N,I)(1/2) = C(N,K) / 2**N
%
%    For a fixed X and N, the polynomials add up to 1:
%
%      Sum ( 0 <= I <= N ) B(N,I)(X) = 1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Stephen Wolfram,
%    The Mathematica Book,
%    Fourth Edition,
%    Wolfram Media / Cambridge University Press, 1999.
%
%  Parameters:
%
%    Input/output, integer N_DATA.  The user sets N_DATA to 0 before the
%    first call.  On each call, the routine increments N_DATA by 1, and
%    returns the corresponding data; when there is no more data, the
%    output value of N_DATA will be 0 again.
%
%    Output, integer N, the degree of the polynomial.
%
%    Output, integer K, the index of the polynomial.
%
%    Output, real X, the argument of the polynomial.
%
%    Output, real B, the value of the polynomial B(N,K)(X).
%
  n_max = 15;

  b_vec = [ ...
     0.1000000000000000E+01, ...
     0.7500000000000000E+00, ...
     0.2500000000000000E+00, ...
     0.5625000000000000E+00, ...
     0.3750000000000000E+00, ...
     0.6250000000000000E-01, ...
     0.4218750000000000E+00, ...
     0.4218750000000000E+00, ...
     0.1406250000000000E+00, ...
     0.1562500000000000E-01, ...
     0.3164062500000000E+00, ...
     0.4218750000000000E+00, ...
     0.2109375000000000E+00, ...
     0.4687500000000000E-01, ...
     0.3906250000000000E-02 ];

  k_vec = [ ...
    0, ...
    0, 1, ...
    0, 1, 2, ...
    0, 1, 2, 3, ...
    0, 1, 2, 3, 4 ];

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

  x_vec = [ ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00, ...
     0.25E+00 ];

  if ( n_data < 0 )
    n_data = 0;
  end

  n_data = n_data + 1;

  if ( n_max < n_data )
    n_data = 0;
    n = 0;
    k = 0;
    x = 0.0;
    b = 0.0;
  else
    n = n_vec(n_data);
    k = k_vec(n_data);
    x = x_vec(n_data);
    b = b_vec(n_data);
  end

  return
end


function binv = beta_inv (x, a, b)
%  BETA_INV Inverse of the beta cumulative distribution function (cdf).
%     X = BETA_INV(P,A,B) returns the inverse of the beta cdf with
%     parameters A and B at the values in P.

% Copyright (c) 1995-1997, 2005-2007 Kurt Hornik

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

if (nargin ~= 3)
  error('must provide 3 parameters')
end

if (~isscalar (a) || ~isscalar(b))
  if ((size(a,1) ~= size(b,1)) || (size(b,1) ~= size(x,1)))
    error ('betainv: x, a and b must be of common size or scalars');
  end
end

[n,nin] = size(x);
binv = zeros(n,nin);

k = find ((x<0) || (x>1) || (a<0) || (b<0) || isnan(x));
if (any(k))
  binv(k) = NaN;
end

k = find ((x==1) && (a>0) && (b>0));
if (any (k))
  binv(k) = 1;
end

k = find ((x > 0) & (x < 1) & (a > 0) & (b > 0));
if (any (k))
  if (~isscalar(a) || ~isscalar(b))
    a = a(k);
    b = b(k);
    y = a./(a+b);
  else
    y = a/(a + b)*ones(size(k));
  end
  x = x(k);
  l = find (y < eps);
  if (any (l))
    y(l) = sqrt (eps) * ones (length (l), 1);
  end
  l = find (y > 1 - eps);
  if (any (l))
    y(l) = 1 - sqrt (eps) * ones (length (l), 1);
  end

  y_old = y;
  for i = 1 : 10000
    h     = (beta_cdf (y_old, a, b) - x) ./ beta_pdf (y_old, a, b);
    y_new = y_old - h;
    ind   = find (y_new <= eps);
    if (any (ind))
      y_new (ind) = y_old (ind) / 10;
    end
    ind = find (y_new >= 1 - eps);
    if (any (ind))
      y_new (ind) = 1 - (1 - y_old (ind)) / 10;
    end
    h = y_old - y_new;
    if (max (abs (h)) < sqrt (eps))
      break;
    end
    y_old = y_new;
  end

  binv(k) = y_new;
end

end


% Laplacian Smoothing Transform for face recognition

function [gammak,lambda]=lst_basis(M,N,k)
% By Suicheng Gu at Peking University, Jan. 5, 2009
% Email: gusuch@gmail.com

% Output: v: basis. vv: k minimal eigenvalues
% Input:
% N: width of input image, or columns of a matrix
% M: height of input image, or rows of a matrix
% k: Number of low frequency features

%************ An Example ************
% To extract 30 LST low frequency coefficients of an grey image:
%  Im=rand(50,40); [M,N]=size(Im);
%  v=lst_basis(M,N,30);
%  temp=zeros(1,M*N);temp(:)=Im(:);
%  Im_feature=temp*v;
%*********** End ******************

W = sparse([],[],[],M*N,M*N,4*M*N-2*M-2*N);
for x=0:N-2;
    for y=0:M-1;
        W(x*M+y+1,x*M+M+y+1)=1;
        W(x*M+M+y+1,x*M+y+1)=1;
    end;
end;
for x=0:N-1;
    for y=0:M-2;
        W(x*M+y+1,x*M+y+2)=1;
        W(x*M+y+2,x*M+y+1)=1;
    end;
end;
L=sparse(diag(sum(W)))-W;
options.disp = 0; options.isreal = 1; options.issym = 1;
[v,lambda]=eigs(L,k,0,options);
[vv,index] = sort(diag(lambda));
gammak = v(:,index);


function img = discreteTrefoil(varargin)
%DISCRETETREFOIL  Discretize a trefoil curve
%
%   IMG = discreteTrefoil(LX, LY, TREFOIL);
%   Computes the discretisation of a trefoil curve. Inputs are LX and LY,
%   two row vectors specifying pixel positions along each direction, and
%   TREFOIL = [XC YC ROUT RIN THETA], where (XC YC) is the center of the
%   trefoil, ROUT and RIN are the outer and the inner radius, and THETA is
%   the orientation of the first lobe, in degrees counted counter
%   clockwise.
%
%   Example
%     trefoil = [50.12 50.23 45 15 10];
%     img = discreteTrefoil(1:100, 1:100, trefoil);
%     imshow(img)
%
%   See also
%   imShapes, discreteEllipse, discreteStarfish
%

% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-07-13,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% compute coordinate of image pixels
[lx, ly, varargin] = parseGridArgs(varargin{:});
[x, y]   = meshgrid(lx, ly);

% process input parameters
var = varargin{1};
center  = var(:, 1:2);
rOut    = var(:, 3);
rIn     = var(:, 4);
theta   = var(:, 5);

% compute middle radius, and radius extent
rc = (rOut + rIn) / 2;
dr = (rOut - rIn) / 2;

% transforms pixels according to shape position
tra     = createTranslation(-center);
rot     = createRotation(-deg2rad(theta));

[x, y]   = transformPoint(x, y, rot*tra);

% convert to polar coordinates
[th, rho] = cart2pol(x(:), y(:));

% compute theoretical polar distance
rhoTh = rc + dr * cos(3 * th);

% create image
img = false(size(x));
img(rho < rhoTh) = 1;


function [varargout]=ellipsoidFit_centered(varargin)

% function [M,s,R,MU]=ellipsoidFit_centered(X,MU)
% ------------------------------------------------------------------------
%
% Kevin Mattheus Moerman
% kevinmoerman@hotmail.com
% 2014/11/11
%------------------------------------------------------------------------

%%

switch nargin
    case 1
        X=varargin{1};
        MU=mean(X,1); %Point set mean
    case 2
        X=varargin{1};
        MU=varargin{2};
end

if isempty(MU)
    MU=mean(X,1); %Point set mean
end

%%

%Centre on mean
X=X-MU(ones(size(X,1),1),:); %Centre points around mean

%Compute singular value decomposition to get principal directions
[~,D,V]=svd(X,0);

%Compute input radii
r = sqrt(sum(X.^2,2));

%Create sphere coordinates
Xr=(V\X')'; %Rotate back
Xc=(D\Xr')'; %Scale back to unit sphere
[theta,phi,~] = cart2sph(Xc(:,1),Xc(:,2),Xc(:,3));
[Xc(:,1),Xc(:,2),Xc(:,3)]=sph2cart(theta,phi,ones(size(theta)));

%Transforming sphere to ellipsoid according to fit
X_fit=Xc;
X_fit=(D*X_fit')'; %Scale
X_fit=(V*X_fit')'; %Rotate
[~,~,r_fit] = cart2sph(X_fit(:,1),X_fit(:,2),X_fit(:,3));

w=mean(r./r_fit); %Determine SVD weight factor

D=D*w; %Scale singular values using weight to convert to ellipsoid semi-axis constants

%Identity
I=eye(4,4);

%Rotation
R=I;
R(1:3,1:3)=V;

%Stretch factors

s=diag(D)';

S=I;
S(1:3,1:3)=D; %Stretch

T=I;
T(1:3,4)=MU(:); %Translation

M  = T * R * S; %The transformation matrix

%%
varargout{1}=M;
varargout{2}=s;
varargout{3}=R;
varargout{4}=MU;

%%

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function idx = findClosestCentroids(X, centroids)
%FINDCLOSESTCENTROIDS computes the centroid memberships for every example
%   idx = FINDCLOSESTCENTROIDS (X, centroids) returns the closest centroids
%   in idx for a dataset X where each row is a single example. idx = m x 1
%   vector of centroid assignments (i.e. each entry in range [1..K])
%

% Set K
K = size(centroids, 1);

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

% ====================== YOUR CODE HERE ======================
% Instructions: Go over every example, find its closest centroid, and store
%               the index inside idx at the appropriate location.
%               Concretely, idx(i) should contain the index of the centroid
%               closest to example i. Hence, it should be a value in the
%               range 1..K
%
% Note: You can use a for-loop over the examples to compute this.
%

for i = 1:size(X, 1),
  min_d = inf;
  for k = 1:K,
    dis = X(i, :)' - centroids(k, :)';
    dis_sq = dis' * dis;
    if min_d > dis_sq,
      idx(i) = k;
      min_d = dis_sq;
    endif
  endfor
endfor

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

end


function result = bdf_sum ( func, n, x, w )

%*****************************************************************************80
%
%% BDF_SUM carries out an explicit backward difference quadrature rule for [0,1].
%
%  Discussion:
%
%    The integral:
%
%      Integral ( 0 <= X <= 1 ) F(X) dX
%
%    The quadrature rule:
%
%      sum ( 1 <= I <= N ) W(I) * BDF^(I-1) FUNC ( 0 )
%
%    The integral from 0 to 1 is approximated using data at X = 0,
%    -1, -2, ..., -N+1.  This is a form of extrapolation, and
%    the approximation can become poor as N increases.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 June 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, external FUNC, the function which evaluates
%    the integrand.  The function must have the form
%      function value = func ( x ).
%
%    Input, integer N, the order.
%
%    Input, real X(N), the abscissas.
%
%    Input, real W(N), the weights.
%
%    Output, real RESULT, the approximate value of the integral.
%
  diftab = zeros ( n, 1 );

  for i = 1 : n
    diftab(i) = func ( x(i) );
  end

  for i = 2 : n
    for j = i : n
      diftab(n+i-j) = ( diftab(n+i-j-1) - diftab(n+i-j) );
    end
  end

  result = w(1:n)' * diftab(1:n);

  return
end


function x=complexBarycentricCoords2Pt(c,v)
%%COMPLEXBARYCENTRICCOORDS2PT Given a set of complex barycentric
%   coordinates and a st of vertices, get the real 2D point that is
%   specified by the coordinates.
%
%INPUTS: c A numVertXnumPts set of complex coordinate vectors to convert.
%        v This is either a 2XN set of real vertices, or a length N vctor
%          of complex scalar vertices (x coordinate is real and y
%          coordinate is imaginery). These define the polygon over which
%          the vertices are specified.
%
%OUTPUTS: x The 2XnumPts set of the points given by the complex barycentric
%           coordinates.
%
%Complex barycentric coordinates are discussed in [1].
%
%REFERENCES:
%[1] O. Weber, M. Ben-Chen, C. Gotsman, and K. Hormann, "A complex view of
%    barycentric mappings," Computer Graphics Forum, vol. 30, no. 5, pp.
%    1533-1542, Aug. 2011.
%
%October 2021 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numPts=size(c,2);

if(isvector(v))
    zj=v;
else
    zj=v(1,:).'+1j*v(2,:).';
end

x=zeros(2,numPts);
for curPt=1:numPts
    xComplex=sum(c(:,curPt).*zj);
    x(:,curPt)=[real(xComplex);imag(xComplex)];
end
end

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


function draw_mandelbrot(x0, x1, y0, y1)

n_grid = 1000;

[x,y] = meshgrid(linspace(x0,x1,n_grid), linspace(y0,y1,n_grid));

c = x + 1i*y;
z = c;
n_iter = 100;
M = zeros(size(c));

for i = 1:n_iter
    z = z.^2 + c;
    M(M==0 & abs(z)>2) = n_iter-i;
end

imagesc(x(1,:), y(:,1),M)
colormap jet


function [phi, Dphi, J] = hexbasis(node,elem,GaussPt)
%% HEXBASIS the basis and their derivatives and the det of Jacobi.
%
%   [phi, Dphi, J] = hexbasis(node,elem,GaussPts) compute the values of
%   bilinear basis and their derivatives and Jacobi det at a gauss point GaussPt in a
%   hex.
%
% Author: Huayi Wei < huayiwei1984@gmail.com>
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

NT = size(elem,1);

xi = GaussPt(1);
eta = GaussPt(2);
theta = GaussPt(3);

%% basis function and their derivatives
% for a point (x, y) in real element,  there exist a point in reference
% element (xi, eta), satisfy
%    x = x_1*phi_1 + x_2*phi_2 + x_3*phi_3 + x_4 *phi_4 +
%        x_5*phi_5 +x_6*phi_6 + x_7*phi_7 + x_8 *phi_8
%    y = y_1*phi_1 + y_2*phi_2 + y_3*phi_3 + y_4 *phi_4+
%        y_5*phi_5 +y_6*phi_6 + y_7*phi_7 + y_8 *phi_8
%    z = z_1*phi_1 + z_2*phi_2 + z_3*phi_3 + z_4 *phi_4+
%        z_5*phi_5 +z_6*phi_6 + z_7*phi_7 + z_8 *phi_8

g1 = [xi, 1 - xi];
g2 = [eta, 1 - eta];
g3 = [theta, 1 - theta];

phi = zeros(8,1);
phi(1) = g1(2)*g2(2)*g3(2);
phi(2) = g1(1)*g2(2)*g3(2);
phi(3) = g1(1)*g2(1)*g3(2);
phi(4) = g1(2)*g2(1)*g3(2);
phi(5) = g1(2)*g2(2)*g3(1);
phi(6) = g1(1)*g2(2)*g3(1);
phi(7) = g1(1)*g2(1)*g3(1);
phi(8) = g1(2)*g2(1)*g3(1);

rDphi = zeros(8,3);
rDphi(1,:) = [ -g2(2)*g3(2), -g1(2)*g3(2), -g1(2)*g2(2)];
rDphi(2,:) = [  g2(2)*g3(2), -g1(1)*g3(2), -g1(1)*g2(2)];
rDphi(3,:) = [  g2(1)*g3(2),  g1(1)*g3(2), -g1(1)*g2(1)];
rDphi(4,:) = [ -g2(1)*g3(2),  g1(2)*g3(2), -g1(2)*g2(1)];
rDphi(5,:) = [ -g2(2)*g3(1), -g1(2)*g3(1),  g1(2)*g2(2)];
rDphi(6,:) = [  g2(2)*g3(1), -g1(1)*g3(1),  g1(1)*g2(2)];
rDphi(7,:) = [  g2(1)*g3(1),  g1(1)*g3(1),  g1(1)*g2(1)];
rDphi(8,:) = [ -g2(1)*g3(1),  g1(2)*g3(1),  g1(2)*g2(1)];

X = node(:,1);
Y = node(:,2);
Z = node(:,3);

JM = zeros(NT,3,3);
JM(:,:,1) = X(elem)*rDphi;
JM(:,:,2) = Y(elem)*rDphi;
JM(:,:,3) = Z(elem)*rDphi;

J = JM(:,1,1).*JM(:,2,2).*JM(:,3,3) + JM(:,2,1).*JM(:,3,2).*JM(:,1,3)+ ...
    JM(:,3,1).*JM(:,1,2).*JM(:,2,3) - JM(:,3,1).*JM(:,2,2).*JM(:,1,3)- ...
    JM(:,1,1).*JM(:,3,2).*JM(:,2,3) - JM(:,2,1).*JM(:,1,2).*JM(:,3,3);

InvJM = zeros(NT,3,3);
InvJM(:,:,1) = [JM(:,2,2).*JM(:,3,3) - JM(:,3,2).*JM(:,2,3), JM(:,3,1).*JM(:,2,3)-JM(:,2,1).*JM(:,3,3), JM(:,2,1).*JM(:,3,2) - JM(:,3,1).*JM(:,2,2)];
InvJM(:,:,2) = [JM(:,3,2).*JM(:,1,3) - JM(:,1,2).*JM(:,3,3), JM(:,1,1).*JM(:,3,3)-JM(:,3,1).*JM(:,1,3), JM(:,3,1).*JM(:,1,2) - JM(:,1,1).*JM(:,3,2)];
InvJM(:,:,3) = [JM(:,1,2).*JM(:,2,3) - JM(:,2,2).*JM(:,1,3), JM(:,2,1).*JM(:,1,3)-JM(:,1,1).*JM(:,2,3), JM(:,1,1).*JM(:,2,2) - JM(:,2,1).*JM(:,1,2)];

InvJM(:,:,1) = InvJM(:,:,1)./[J,J,J];
InvJM(:,:,2) = InvJM(:,:,2)./[J,J,J];
InvJM(:,:,3) = InvJM(:,:,3)./[J,J,J];

Dphi = zeros(NT, 3, 8);

for i = 1:8
  Dphi(1:NT,:,i) = [InvJM(:,:,1)*rDphi(i,:)', InvJM(:,:,2)*rDphi(i,:)', InvJM(:,:,3)*rDphi(i,:)'];
end


function phiFaceAverage = geometricMean(phi)
% This function gets the value of the field variable phi defined
% over the MeshStructure and calculates the geometric average on
% the cell faces, for a uniform mesh.
%
% SYNOPSIS:
%   phiFaceAverage = geometricMean(phi)
%
% PARAMETERS:
%
%
% RETURNS:
%
%
% EXAMPLE:
%
% SEE ALSO:
%

% Written by Ali A. Eftekhari
% See the license file

% extract data from the mesh structure

d = phi.domain.dimension;
if (d ==1) || (d==1.5) || (d==1.8)
    dx = phi.domain.cellsize.x;
    xvalue=exp((dx(1:end-1).*log(phi.value(1:end-1))+dx(2:end).*log(phi.value(2:end)))./(dx(2:end)+dx(1:end-1)));
    yvalue=[];
    zvalue=[];
elseif (d == 2) || (d == 2.5) || (d == 2.8)
    Nx = phi.domain.dims(1);
    Ny = phi.domain.dims(2);
    dx = repmat(phi.domain.cellsize.x, 1, Ny);
    dy = repmat(phi.domain.cellsize.y', Nx, 1);
	xvalue=exp((dx(1:end-1,:).*log(phi.value(1:end-1,2:end-1))+...
        dx(2:end,:).*log(phi.value(2:end,2:end-1)))./(dx(2:end,:)+dx(1:end-1,:)));
    yvalue=exp((dy(:,1:end-1).*log(phi.value(2:end-1,1:end-1))+...
        dy(:,2:end).*log(phi.value(2:end-1,2:end)))./(dy(:,2:end)+dy(:,1:end-1)));
    zvalue=[];
elseif (d == 3) || (d==3.2)
    Nx = phi.domain.dims(1);
    Ny = phi.domain.dims(2);
    Nz = phi.domain.dims(3);
    dx = repmat(phi.domain.cellsize.x, 1, Ny, Nz);
    dy = repmat(phi.domain.cellsize.y', Nx, 1, Nz);
    DZ = zeros(1,1,Nz+2);
    DZ(1,1,:) = phi.domain.cellsize.z;
    dz=repmat(DZ, Nx, Ny, 1);
    xvalue=exp((dx(1:end-1,:,:).*log(phi.value(1:end-1,2:end-1,2:end-1))+...
        dx(2:end,:,:).*log(phi.value(2:end,2:end-1,2:end-1)))./(dx(2:end,:,:)+dx(1:end-1,:,:)));
    yvalue=exp((dy(:,1:end-1,:).*log(phi.value(2:end-1,1:end-1,2:end-1))+...
        dy(:,2:end,:).*log(phi.value(2:end-1,2:end,2:end-1)))./(dy(:,1:end-1,:)+dy(:,2:end,:)));
    zvalue=exp((dz(:,:,1:end-1).*log(phi.value(2:end-1,2:end-1,1:end-1))+...
        dz(:,:,2:end).*log(phi.value(2:end-1,2:end-1,2:end)))./(dz(:,:,1:end-1)+dz(:,:,2:end)));
end
phiFaceAverage=FaceVariable(phi.domain, xvalue, yvalue, zvalue);


function [T, Y]=FOChuaNR(parameters, orders, TSim, Y0)
%
% Numerical Solution of the Fractional-Order Chua's System
% with piecewise linear nonlinearity defined in function f_x()
%
%   D^q1 x(t) = alpha(y(t) - x(t) - f(x))
%   D^q2 y(t) = x(t) - y(t) + z(t)
%   D^q3 z(t) = -beta y(t) - gamma z(t)
%   where  f(x) is defined as f_x(m0, m1, x);
%
% function [T, Y] = FOChuaNR(parameters, orders, TSim, Y0)
%
% Input:    parameters - model parameters [alpha, beta, gamma, m0, m1]
%           orders - derivatives orders [q1, q2, q3]
%           TSim - simulation time (0 - TSim) in sec
%           Y0 - initial conditions [Y0(1), Y0(2), Y0(3)]
%
% Output:   T - simulation time (0 : Tstep : TSim)
%           Y - solution of the system (x=Y(1), y=Y(2), z=Y(3))
%
% Author:  (c) Ivo Petras (ivo.petras@tuke.sk), 2010.
%

% time step:
h=0.005;
% number of calculated mesh points:
n=round(TSim/h);
%orders of derivatives, respectively:
q1=orders(1); q2=orders(2); q3=orders(3);
% constants of Volta's system:
alpha=parameters(1); beta=parameters(2); gamma=parameters(3);
m0=parameters(4); m1=parameters(5);
% binomial coefficients calculation:
cp1=1; cp2=1; cp3=1;
for j=1:n
    c1(j)=(1-(1+q1)/j)*cp1;
    c2(j)=(1-(1+q2)/j)*cp2;
    c3(j)=(1-(1+q3)/j)*cp3;
    cp1=c1(j); cp2=c2(j); cp3=c3(j);
end
% initial conditions setting:
x(1)=Y0(1); y(1)=Y0(2); z(1)=Y0(3);
% calculation of phase portraits /numerical solution/:
for i=2:n
    x(i)=(alpha*(y(i-1)-x(i-1)-f_x(m1,m0,x(i-1))))*h^q1 - memo(x, c1, i);
    y(i)=(x(i)-y(i-1)+z(i-1))*h^q2 - memo(y, c2, i);
    z(i)=(-beta*y(i)-gamma*z(i-1))*h^q3 - memo(z, c3, i);
end
for j=1:n
    Y(j,1)=x(j);
    Y(j,2)=y(j);
    Y(j,3)=z(j);
end
T=h:h:TSim;
%


function legendre_2d_exactness ( a, b, n, x, y, w, t )

%*****************************************************************************80
%
%% LEGENDRE_2D_EXACTNESS: monomial exactness for the 2D Legendre integral.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 May 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A(2), the lower limits of integration.
%
%    Input, real B(2), the upper limits of integration.
%
%    Input, integer N, the number of points in the rule.
%
%    Input, real X(N), Y(N), the quadrature points.
%
%    Input, real W(N), the quadrature weights.
%
%    Input, integer T, the maximum total degree.
%    0 <= T.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Quadrature rule for the 2D Legendre integral.\n' );
  fprintf ( 1, '  Number of points in rule is %d\n', n );
  fprintf ( 1, '\n' );
  fprintf ( 1, '   D   I       J          Relative Error\n' );

  for tt = 0 : t

    fprintf ( 1, '  %2d\n', tt );

    for j = 0 : tt

      i = tt - j;

      p(1) = i;
      p(2) = j;

      s = legendre_2d_monomial_integral ( a, b, p );

      v(1:n,1) = x(1:n,1) .^ p(1) .* y(1:n,1) .^ p(2);

      q = w' * v;

      if ( s == 0.0 )
        e = abs ( q );
      else
        e = abs ( q - s ) / abs ( s );
      end

      fprintf ( 1, '  %6d  %6d  %24.16g\n', p(1), p(2), e );

    end
  end

  return
end


function X = positive_definite_karcher_mean(A)
% Computes a Karcher mean of a collection of positive definite matrices.
%
% function X = positive_definite_karcher_mean(A)
%
% Input:  A 3D matrix A of size nxnxm such that each slice A(:,:,k) is a
%         positive definite matrix of size nxn.
%
% Output: A positive definite matrix X of size nxn which is a Karcher mean
%         of the m matrices in A, that is, X minimizes the sum of squared
%         Riemannian distances to the matrices in A:
%            f(X) = sum_k=1^m .5*dist^2(X, A(:, :, k))
%         The distance is defined by the natural metric on the set of
%         positive definite matrices: dist(X,Y) = norm(logm(X\Y), 'fro').
%
% This simple example is not the best way to compute Karcher means. Its
% purpose it to serve as base code to explore other algorithms. In
% particular, in the presence of large noise, this algorithm seems to not
% be able to reach points with a very small gradient norm. This may be
% caused by insufficient accuracy in the gradient computation.

% This file is part of Manopt and is copyrighted. See the license file.
%
% Main author: Nicolas Boumal, Sept. 3, 2013
% Contributors:
%
% Change log:
%

    % Generate some random data to test the function if none is given.
    if ~exist('A', 'var') || isempty(A)
        n = 5;
        m = 10;
        A = zeros(n, n, m);
        ref = diag(max(.1, 1+.1*randn(n, 1)));
        for i = 1 : m
            noise = 0.01*randn(n);
            noise = (noise + noise')/2;
            [V, D] = eig(ref + noise);
            A(:, :, i) = V*diag(max(.01, diag(D)))*V';
        end
    end

    % Retrieve the size of the problem:
    % There are m matrices of size nxn to average.
    n = size(A, 1);
    m = size(A, 3);
    assert(n == size(A, 2), ...
           ['The slices of A must be square, i.e., the ' ...
	        'first and second dimensions of A must be equal.']);

    % Our search space is the set of positive definite matrices of size n.
    % Notice that this is the only place we specify on which manifold we
    % wish to compute Karcher means. Replacing this factory for another
    % geometry will yield code to compute Karcher means on that other
    % manifold, provided that manifold is equipped with a dist function and
    % a logarithmic map log.
    M = sympositivedefinitefactory(n);

    % Define a problem structure, specifying the manifold M, the cost
    % function and its gradient.
    problem.M = M;
    problem.cost = @cost;
    problem.grad = @grad;

    % Explicitly pick an approximate Hessian for the trust-region method
    problem.approxhess = approxhessianFD(problem, struct('stepsize', 1e-4));

    % The functions below make many redundant computations. This
    % performance hit can be alleviated by using the caching system. We go
    % for a simple implementation here, as a tutorial example.

    % Cost function
    function f = cost(X)
        f = 0;
        for k = 1 : m
            f = f + M.dist(X, A(:, :, k))^2;
        end
        f = f/(2*m);
    end

    % Riemannian gradient of the cost function
    function g = grad(X)
        g = M.zerovec(X);
        for k = 1 : m
            % Update g in a linear combination of the form
            % g = g - [something]/m.
            g = M.lincomb(X, 1, g, -1/m, M.log(X, A(:, :, k)));
        end
    end

    % Execute some checks on the derivatives for early debugging.
    % These things can be commented out of course.
    % The slopes should agree on part of the plot at least. In this case,
    % it is sometimes necessary to inspect the plot visually to make the
    % call, but it is indeed correct.
    % checkgradient(problem);
    % pause;

    % Execute this if you want to force using a proper parallel vector
    % transport. This is not necessary. If you omit this, the default
    % vector transport is the identity map, which is (of course) cheaper
    % and seems to perform well in practice.
    % M.transp = M.paralleltransp;

    % Issue a call to a solver. Default options are selected.
    % Our initial guess is the first data point.
    X = trustregions(problem, A(:, :, 1));

end


function U = unionHull(varargin)
%unionHull - computes the convex hull of the union of other bounded convex polyhedra.
%Any number of polyhedra can be input to the union operation. They can
%be expressed using either vertices or linear in/equalities, according to
%the input scheme,
%
%
%   I = intersectionHull('vert', V1, 'lcon', A2,b2,...,'qlcon', x3,A3,b3,...)
%
%The arguments specifying different polyhedra are separated using labels
%'vert', 'lcon', or 'qlcon'. The label 'vert' signifies that an input polyhedron will
%be expressed using vertices and is to be followed by any string of input arguments
%accepted by vert2lcon(). The label 'lcon' signifies that an input polyhedron will
%be expressed using linear constraints and is to be followed by any string of
%input arguments accepted by lcon2vert(). The label 'qlcon' signifies that an input
%polyhedron will be expressed using linear constraints and a known interior point and
%is to be followed by  input arguments accepted by qlcon2vert().
%
%The output, U, is a struct containing fields
%
%   U.vert: A matrix whose rows are the vertices of the output polyhedron.
%   U.lcon: The quadruplet of linear constraint data {A,b,Aeq,beq}
%           describing the output polyhedron.
%
%EXAMPLE 1: The unit simplex in 3D is formed as the convex hull of the union
%of a cube and a triangle, both expressed in terms of their vertices.
%
%     V1=(dec2bin(0:2^3-1,3)-'0')/3.0001;    %vertices of 3D cube
%     V2=eye(3);  %vertices of triangle
%
%     U=unionHull('vert',V1,'vert',V2);   %compute the union
%
%One can verify that the vertices of the result are those of the unit
%simplex,
%
%       >> U.vert
%
%             ans =
%
%                  0     0     0
%                  0     0     1
%                  0     1     0
%                  1     0     0
%
%We also demonstrate the use of separateBounds() to convert the result to
%Optimization Toolbox representation. The tolerance parameter 0.99 is used
%to deal with residual floating point noise.
%
%         >> [A,b,Aeq,beq,lb,ub]=separateBounds(U.lcon{:},.99)
%
%             A =
%
%                 0.5774    0.5774    0.5774
%
%
%             b =
%
%                 0.5774
%
%
%             Aeq =
%
%                  []
%
%
%             beq =
%
%                Empty matrix: 0-by-1
%
%
%             lb =
%
%                  0
%                  0
%                  0
%
%
%             ub =
%
%                Inf
%                Inf
%                Inf
%
%
%
%EXAMPLE 2: The unit cube is formed as the union of a simplex, a square,
%and a single 3D point. The simplex and square are both represented using
%equalites and inequalities. For convenience, we use the addBounds() utility
%to compose the in/equality matrices. The representation of the square illustrates
%the use of the 'qlcon' label, when a known interior point is available.
%
%
%     [A1,b1,Aeq1,beq1] = addBounds([1 1 1],1,[],[],[0;0;0]); %unit simplex
%
%     [A2,b2,Aeq2,beq2] = addBounds([],[],[],[],[1;0;0],[1;1;1]); %a square face of the unit cube
%
%                    x2 = [1,0.5,0.5];%a point in the relative interior of the square
%
%     V3 = [0,1,1]; %one vertex of the unit cube
%
%
%     U=unionHull('lcon',A1,b1,Aeq1,beq1,...         %compute the union
%                 'qlcon',x2,A2,b2,Aeq2,beq2,...
%                  'vert',V3);
%
%One can verify that the result contains the 8 vertices of the unit cube,
%
%       >> U.vert
%
%         ans =
%
%                  0   -0.0000   -0.0000
%             0.0000   -0.0000    1.0000
%            -0.0000    1.0000   -0.0000
%                  0    1.0000    1.0000
%             1.0000    0.0000    0.0000
%             1.0000    0.0000    1.0000
%             1.0000    1.0000    0.0000
%             1.0000    1.0000    1.0000
%
%As before, we can use separateBounds() to convert to Optimization Toolbox
%form,
%
%     >>  [A,b,Aeq,beq,lb,ub]=separateBounds(U.lcon{:},.99)
%
%which results in A=b=Aeq=beq=[] and
%
%    lb =
%
%          0
%          0
%          0
%
%
%     ub =
%
%         1.0000
%         1.0000
%         1.0000

%%%%begin parsing

if isnumeric(varargin{1})
   TOLcell=varargin(1);
   varargin(1)=[];
else
    TOLcell={};
end

N=length(varargin);
idxType = [find(cellfun(@ischar,varargin)),N+1];

L=length(idxType)-1;
S(L).type=[];
S(L).args={};

for i=1:L

    j=idxType(i);
    k=idxType(i+1);
    S(i).type=varargin{j};
    S(i).args=varargin(j+1:k-1);

    if isempty(S(i).args)
     error 'Syntax error - arguments missing'
    end

     switch S(i).type

        case 'lcon'

             S(i).V = lcon2vert(S(i).args{:});

        case 'qlcon'

            S(i).V = qlcon2vert(S(i).args{:});

        case 'vert'

            S(i).V = S(i).args{1};

        otherwise

            error(['Unrecognized representation label of polyhedron ' num2str(i)]);

      end

 end

%%%%end parsing

    V=vertcat(S.V);

    x0=mean(V,1);

   [U.lcon{1:4}]=vert2lcon(V,TOLcell{:});

   U.vert=qlcon2vert(x0,U.lcon{:},TOLcell{:});


function mb_lbfgs

% 2010 m.bangert@dkfz.de
% fitting a gaussian distribution to data with a quasi newton method using
% a lbfgs update for the inverse hessian matrix
%
% example : mb_bfgs (function does not take any argument)

% options
visLineSearch = 1;
visBool       = 1;

% sample data from a gaussian distribution
randn('seed',12345); %set the seed of the random number generator - if you do not want to do that comment...
numOfSamples = 250;
data(:,1)    = linspace(-2,4,numOfSamples) + 6/numOfSamples*randn(1,numOfSamples);
data(:,2)    = exp(-(linspace(-2,4,250)-1.5).^2) + .05*randn(1,250);

% plot data
if visBool
    close all
    figure
    hold on
    plot(data(:,1),data(:,2),'b+')
    xlabel('X')
    ylabel('Y')
    visHandle = [];
end

% specify input
mem          = 10;        % number of past gradients and function values used for inverse hessian contruction
x            = NaN*ones(3,mem);
x(:,1)       = [1 1 1]';  % starting value for parameters
objFuncValue = NaN*ones(1,mem);
dx           = NaN*ones(3,mem);

s_k = ones(3,mem-1);
y_k = ones(3,mem-1);
r_k = ones(mem-1,1);
a_k = ones(1,mem-1);

fprintf(['\nFitting a gaussian distribution to data with an L-BFGS-B algorithm...\n\n']);

% 1st calculation of objective function and gradient
objFunc         = @(x) sum((x(3,1).*exp(-(data(:,1)-x(1,1)).^2./x(2,1))-data(:,2)).^2);
objFuncValue(1) = objFunc(x(:,1));
objFuncValue(2) = objFuncValue(1) + 1;
dx(:,1)          = mb_numDiff(objFunc,x(:,1));

% iterate
iter      = 0;
numOfIter = 100;
prec      = 1e-5;

% convergence if gradient smaller than prec, change in objective function
% smaller than prec or maximum number of iteration reached...
while iter < numOfIter && abs((objFuncValue(2)-objFuncValue(1))/objFuncValue(1))>prec && norm(dx(:,1))>prec

    % implementation of L-BFGS according to
    % http://en.wikipedia.org/wiki/L-BFGS

    % inverse hessian update
    q = dx(:,1);
    for i = 1:min(iter,mem-1)
        a_k(i) = r_k(i)*s_k(:,i)'*q;
        q      = q - a_k(i)*y_k(:,i);
    end
    z = s_k(:,1)'*y_k(:,1)/(y_k(:,1)'*y_k(:,1))*q; % this corresponds to H*q where H is approximated as described in Nocedal 9.1
    for i = min(iter,mem-1):-1:1
        b = r_k(i)*y_k(:,i)'*z;
        z = z + s_k(:,i)*(a_k(i)-b);
    end

    % obtain search direction
    dir = -z;

    % 2.1 armijo linesearch to to find acceptable stepsize alpha
    alpha = mb_backtrackingLineSearch(objFunc,objFuncValue(1),x(:,1),dx(:,1),dir);

    % 3
    p = alpha*dir;

        % visualize the line search (optional) used for debugging
        if visLineSearch
            figure
            hold on
            alphas   = linspace(0,2*alpha,100);
            alphaVis = NaN*alphas;
            for i = 1:100
                alphaVis(i) = objFunc(x(:,1)+alphas(i)*dir);
            end
            plot(alphas,alphaVis,'b') % function in direction of line search
            plot(alpha,objFunc(x(:,1)+alpha*dir),'r.') % the steplength found
            plot(alphas,objFuncValue(1) + 1e-1*alphas*(dir'*dx(:,1)),'g') % constraint
            pause(.5)
            close
        end

    % 2.2 update x
    x(:,2:end) = x(:,1:end-1);
    x(:,1)     = x(:,1) + p;
    s_k        = -diff(x,[],2);

    % update objective function (and remember old objective function to
    % check for convergence)
    objFuncValue(2) = objFuncValue(1);
    objFuncValue(1) = objFunc(x(:,1));

    % increment iteration counter
    iter = iter + 1;

    fprintf(1,'Iteration %d: alpha_min=%f, OF=%f\n',iter,alpha,objFuncValue(1));

    % calculate difference of gradients
    dx(:,2:end) = dx(:,1:end-1);
    dx(:,1)     = mb_numDiff(objFunc,x(:,1));
    y_k         = -diff(dx,[],2);

    r_k = 1./diag(y_k'*s_k);

    % update function with new x and plot
    if visBool
        pause(0.5)
        fitFunc = @(t) x(3).*exp(-(t-x(1)).^2./x(2));
        delete(visHandle);
        visHandle = plot(data(:,1),fitFunc(data(:,1)),'r','LineWidth',4);
        drawnow;
    end

end

fprintf(['\n' num2str(iter) ' iteration(s) performed to converge\n'])

fprintf(1,'Final solution: x=(%f,%f,%f)\n',x(1),x(2),x(3));

end


function R = Rroll(phi)

c = cos(phi); s = sin(phi);
R = [1 0 0; 0 c -s; 0 s c];


function value = i4_modp ( i, j )

%*****************************************************************************80
%
%% I4_MODP returns the nonnegative remainder of I4 division.
%
%  Discussion:
%
%    If
%      NREM = I4_MODP ( I, J )
%      NMULT = ( I - NREM ) / J
%    then
%      I = J * NMULT + NREM
%    where NREM is always nonnegative.
%
%    The MOD function computes a result with the same sign as the
%    quantity being divided.  Thus, suppose you had an angle A,
%    and you wanted to ensure that it was between 0 and 360.
%    Then mod(A,360) would do, if A was positive, but if A
%    was negative, your result would be between -360 and 0.
%
%    On the other hand, I4_MODP(A,360) is between 0 and 360, always.
%
%  Example:
%
%        I     J     MOD  I4_MODP    Factorization
%
%      107    50       7       7    107 =  2 *  50 + 7
%      107   -50       7       7    107 = -2 * -50 + 7
%     -107    50      -7      43   -107 = -3 *  50 + 43
%     -107   -50      -7      43   -107 =  3 * -50 + 43
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 August 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I, the number to be divided.
%
%    Input, integer J, the number that divides I.
%
%    Output, integer VALUE, the nonnegative remainder when I is
%    divided by J.
%
  if ( j == 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4_MODP - Fatal error!\n' );
    fprintf ( 1, '  Illegal divisor J = %d\n', j );
    error ( 'I4_MODP - Fatal error!' );
  end

  value = mod ( i, j );

  if ( value < 0 )
    value = value + abs ( j );
  end

  return
end


function sftpack_test02 ( )

%*****************************************************************************80
%
%% TEST02 tests R8VEC_SFTB and R8VEC_SFTF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 February 2010
%
%  Author:
%
%    John Burkardt
%
  n = 36;
  alo = 0.0;
  ahi = 5.0;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST02\n' );
  fprintf ( 1, '  For real slow Fourier transforms,\n' );
  fprintf ( 1, '  R8VEC_SFTF computes the forward transform.\n' );
  fprintf ( 1, '  R8VEC_SFTB computes the backward transform.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The number of data values, N = %d\n', n );

  seed = 123456789;

  [ x, seed ] = r8vec_uniform ( n, alo, ahi, seed );

  r8vec_print_part ( n, x, 10, '  The original data:' );
%
%  Compute the slow Fourier transform of the data.
%
  [ azero, a, b ] = r8vec_sftf ( n, x );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  A (cosine) coefficients:\n' );
  fprintf ( 1, '\n' );

  fprintf ( 1, '  %4d  %f\n', 0, azero );

  for i = 1 : floor ( n / 2 )
   fprintf ( 1, '  %4d  %f\n', i, a(i) );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  B (sine) coefficients:\n' );
  fprintf ( 1, '\n' );

  for i = 1 : floor ( n / 2 )
    fprintf ( 1, '  %4d  %f\n', i, b(i) );
  end
%
%  Now try to retrieve the data from the coefficients.
%
  x = r8vec_sftb ( n, azero, a, b );

  r8vec_print_part ( n, x, 10, '  The retrieved data:' );

  return
end


function spline_test125 ( )

%*****************************************************************************80
%
%% TEST125 tests LEAST_SET_OLD, LEAST_VAL_OLD.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 January 2007
%
%  Author:
%
%    John Burkardt
%
  maxdeg = 6;
  ntab = 21;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST125\n' );
  fprintf ( 1, '  LEAST_SET_OLD sets a least squares polynomial,\n' );
  fprintf ( 1, '  LEAST_VAL_OLD evaluates it.\n' );

  for i = 1 : ntab
    xtab(i) = ( ( ntab - i     ) * ( -1.0 )   ...
              + (        i - 1 ) * ( +1.0 ) ) ...
              / ( ntab     - 1 );
    ytab(i) = ( floor ( exp ( xtab(i) ) * 100.0 + 0.5 ) ) / 100.0;
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The data to be interpolated:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of data values = %d\n', ntab );
  fprintf ( 1, '\n' );
  fprintf ( 1, '       X             Y\n' );
  fprintf ( 1, '\n' );

  for i = 1 : ntab
    fprintf ( 1, '%14f  %14f\n', xtab(i), ytab(i) );
  end

  for ndeg = 1 : maxdeg

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Use a polynomial of degree: %d\n', ndeg );
    fprintf ( 1, '\n' );

    [ ptab, b, c, d, eps, ierror ] = least_set_old ( ntab, xtab, ytab, ndeg );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Total approximation error = %f\n', eps );
    fprintf ( 1, '\n' );
    fprintf ( 1, '  X, F(X), P(X), Error\n' );
    fprintf ( 1, '\n' );

    for i = 1 : ntab

      if ( i < ntab )
        jhi = 2;
      else
        jhi = 0;
      end

      for j = 0 : jhi

        if ( i < ntab )

          xval = ( ( 3 - j ) * xtab(i)     ...
                 + (     j ) * xtab(i+1) ) ...
                 / ( 3     );

        else

          xval = xtab(i);

        end

        yval = least_val_old ( xval, ndeg, b, c, d );

        ytrue = ( floor ( exp ( xval ) * 100.0 + 0.5 ) ) / 100.0;

        fprintf ( 1, '%14f  %14f  %14f  %14f\n', xval, yval, ytrue, ...
          yval - ytrue );

      end

    end

  end

  return
end


function [B1, C1, c1, B2, C2, c2] = ssad(a, b, A)
%SSAD  gives both solutions to the side-side-angle problem, in degrees.
%
%   SSAD(a, b, A) will result in NaNs if the existence condition
%   |sin b * sin A| <= | sin a |  is not met.
%
%   See also SSA, MALD, MSLD.

% Rody P.S. Oldenhuis
% Delft University of Technology
% oldenhuis@gmail.com
%
% Crated     : 23/Feb/2009
% Last edited: 30/Nov/2012

    % find both solutions by calling ssa directly
    r2d = 180/pi;
    d2r = 1/r2d;
    [B1, C1, c1, B2, C2, c2] = ssa(a*d2r, b*d2r, A*d2r);
    [B1, C1, c1, B2, C2, c2] = deal(B1*r2d, C1*r2d, c1*r2d, B2*r2d, C2*r2d, c2*r2d);

end


% Chapter 17 - Neural Networks.
% Programs_17a - The Generalized Delta Learning Rule (Figure 17.7).
% Copyright Birkhauser 2013. Stephen Lynch.

function Programs_17a
% Load Boston housing data.
load housing.txt
X = housing(:,[6 9 13]);
t = housing(:,14);

% Scale to zero mean, unit variance and introduce bias on input.
xmean = mean(X);
xstd = std(X);
X = (X-ones(size(X,1),1)*xmean)./(ones(size(X,1),1)*xstd);
X = [ones(size(X,1),1) X];
tmean = (max(t)+min(t))/2;
tstd = (max(t)-min(t))/2;
t = (t-tmean)/tstd;

% Initialise random weight vector.
randn('seed', 123456);
w(:,1) = 0.1*randn(size(X,2),1);
y1 = tanh(X*w(:,1));
e1 = t-y1;
mse(1) = var(e1);

% Do numEpochs iterations.
numEpochs = 10;
numPatterns = size(X,1);
eta = 0.001;
k = 1;
for m=1:numEpochs
  for n=1:numPatterns
	% Calculate feedforward output, error, and gradient.
	yk = tanh(X(n,:)*w(:,k));
	err = yk-t(n);
	g = X(n,:)'*((1-yk^2)*err);
	% Update the weight.
	w(:,k+1) = w(:,k) - eta*g;
	k = k+1;
  end
end

for m=1:size(w,1)
plot(1:k, w(m,:))
hold on
end

fsize=15;
set(gca,'XTick',0:2000:6000,'FontSize',fsize)
set(gca,'YTick',-0.3:0.1:0.3,'FontSize',fsize)
xlabel('Number of Iterations','FontSize',fsize)
ylabel('Weights','FontSize',fsize)
hold off

% End of Programs_17a.


function [W, Zhat] = ica(X,Nsources,Wprev)
%ICA  Perform independent component analysis
%  [W, ZHAT] = ICA(X) performs independent component analysis on data
%  observation matrix X of physiological observations.
%
%   Inputs:
%       X               = Observation matrix: rows should be observations, cols samples.
%       Nsources        = Number of source signals (optional).
%       Wprev           = Timepoint at which to start process (default = 0 seconds).
%
%   Outputs:
%       W               = Demixing matrix.
%       Zhat            = Source signal matrix.
%
%  This approach uses Cardoso's ICA
%  algorithm to estimate sources (ZHAT) and the de-mixing matrix W, an
%  approximation to A^{-1}, the original (unknown) mixing matrix.
%
% Daniel McDuff, Ethan Blackford, Justin Estepp, December 2018
% Based on an implementation by: G D Clifford (2004) gari AT mit DOT edu
% Licensed under the MIT License and the RAIL AI License.

[nRows, nCols] = size(X);
if nRows > nCols
    fprintf('Warning - The number of rows is cannot be greater than the number of columns.\n');
    error('Please transpose input.');
end

if Nsources > min([nRows nCols])
    Nsources = min([nRows nCols]);
    fprintf('Warning - The number of soures cannot exceed number of observation channels. \n')
    fprintf('The number of sources will be reduced to the number of observation channels (%i) \n',Nsources)
end

if exist('Vprev','var')
    [Winv, Zhat] = jade(X,Nsources,Wprev);
else
    [Winv, Zhat] = jade(X,Nsources);
end
W = pinv(Winv);


function varargout = sphereMesh(sphere, varargin)
%SPHEREMESH Create a 3D mesh representing a sphere.
%
%   [V, F] = sphereMesh(S)
%   Creates a 3D mesh representing the sphere S given by [xc yc zy r].
%
%   [V, F] = sphereMesh();
%   Assumes sphere is the unit sphere centered at the origin.
%
%   [V, F] = sphereMesh(S, 'nTheta', NT, 'nPhi', NP);
%   Specifies the number of discretisation steps for the meridians and the
%   parallels. Default values are nTheta = 16 and nPhi = 32.
%
%
%   Example
%     s = [10 20 30 40];
%     [v, f] = sphereMesh(s);
%     drawMesh(v, f);
%     view(3); axis equal; light; lighting gouraud;
%
%   See also
%     meshes3d, drawSphere, ellipsoidMesh, cylinderMesh, surfToMesh
%

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

if nargin == 0
    sphere = [0 0 0 1];
end

% number of meridians
nPhi    = 32;

% number of parallels
nTheta  = 16;

% process input arguments
while length(varargin) > 1
    paramName = varargin{1};
    switch lower(paramName)
        case 'ntheta', nTheta = varargin{2};
        case 'nphi', nPhi = varargin{2};
        otherwise
            error(['Could not recognise parameter: ' paramName]);
    end
    varargin(1:2) = [];
end

% extract sphere data
xc = sphere(:,1);
yc = sphere(:,2);
zc = sphere(:,3);
r  = sphere(:,4);

% compute spherical coordinates
theta   = linspace(0, pi, nTheta+1);
phi     = linspace(0, 2*pi, nPhi+1);

% convert to cartesian coordinates
sintheta = sin(theta);
x = xc + cos(phi') * sintheta * r;
y = yc + sin(phi') * sintheta * r;
z = zc + ones(length(phi),1) * cos(theta) * r;

% convert to FV mesh
[vertices, faces] = surfToMesh(x, y, z, 'yperiodic', true);

% format output
varargout = formatMeshOutput(nargout, vertices, faces);