%% Part of discussion on ADC quadratic form calculations
% Probably old between Bob and Brian years ago.
%
% Could be fixed up or deprecated.
%

% Here is a standard ellipsoid.
[X,Y,Z] = ellipsoid(0,0,0,3,1,1);
figure(1), subplot(1,2,1), surf(X,Y,Z)
axis equal

sz = size(X);

% Here is how an ellipse looks like a peanut
%
% Assign a length equal to the square of their length on the ellipsoid.
% This corresponds to what I believe are the ADC (variance) values.  Notice
% the peanut shape.

% The length of each ellipsoid vector
tmp = [X(:),Y(:),Z(:)];
l = sqrt(diag(tmp*tmp'));
% Multiply each vector by its own length
tmp = diag(l)*tmp;

X2 = reshape(tmp(:,1),sz);
Y2 = reshape(tmp(:,2),sz);
Z2 = reshape(tmp(:,3),sz);
figure(1), subplot(1,2,2), surf(X2,Y2,Z2)


function [S, V, D, Sigma2] = MySVDtau(A, tau)
[m, n] = size(A);
if 2*m < n
    AAT = A*A';
    [S, Sigma2, D] = svd(AAT);
    Sigma2 = diag(Sigma2);
    V = sqrt(Sigma2);
    tol = max(size(A)) * eps(max(V));
    R = sum(V > max(tol, tau));

    %tol = min(size(A)) * eps(max(V));
    % R = sum(V > 1/tau)

%     tol = min(size(A)) * eps(max(V));
%     R = sum(V > tau)

    V = V(1:R);
    S = S(:,1:R);
    D = A'*S*diag(1./V);
    V = diag(V);
    return;
end
if m > 2*n
    [S, V, D, Sigma2] = MySVDtau(A', tau);
    mid = D;
    D = S;
    S = mid;
    return;
end
[S,V,D] = svd(A);
Sigma2 = diag(V).^2;
R = sum(diag(V) > tau);
S = S(:, 1:R);
V = V(1:R, 1:R);
D = D(:, 1:R);


% resolve more uncorrelated sources than the number of array elements using
% co-prime arrays
clear(); close all;

wavelength = 1; % normalized
d = wavelength / 2;
% this co-prime array only have 9 elements
design_cp = design_array_1d('coprime', [3 4], d);
% but we have 10 sources here
doas = linspace(-pi/3, pi/3, 10);
power_source = 1;
power_noise = 1;
snapshot_count = 100;
source_count = length(doas);

% stochastic (unconditional) model
[~, R] = snapshot_gen_sto(design_cp, doas, wavelength, snapshot_count, power_noise, power_source);

% SS-MUSIC and DA-MUSIC
[Rss, dss] = virtual_ula_cov_1d(design_cp, R, 'SS');
[Rda, dda] = virtual_ula_cov_1d(design_cp, R, 'DA');
sp_ss = music_1d(Rss, source_count, dss, wavelength, 1440);
sp_da = music_1d(Rda, source_count, dda, wavelength, 1440);
sp_ss.true_positions = doas;
sp_da.true_positions = doas;
figure;
subplot(2,1,1);
plot_sp(sp_ss, 'Title', ['SS-MUSIC using ' design_cp.name], 'ReuseFigure', true);
subplot(2,1,2);
plot_sp(sp_da, 'Title', ['DA-MUSIC using ' design_cp.name], 'ReuseFigure', true);

% apply MVDR directly
sp_mvdr = mvdr_1d(R, source_count, design_cp, wavelength, 1440, 'RefineEstimates', true);
sp_mvdr.true_positions = doas;
plot_sp(sp_mvdr, 'Title', ['Direct MVDR using ' design_cp.name]);

% use sparse recovery
sp_sparse = sparse_bpdn_1d(R, source_count, design_cp, wavelength, 360, 9, ...
    'Formulation', 'ConstrainedL2');
sp_sparse.true_positions = doas;
plot_sp(sp_sparse, 'Title', 'Sparse Recovery based DOA Estimation');


function [ Xt,Yt,Zt ] = multiplyEuMat( EuMat, X,Y,Z )
%MULTIPLYEUMAT takes the X, Y, Z coordinates of an object and returns the
%coordinates Xt, Yt, Zt of same object rotated using a rotation matrix

Xt=X;
Yt=Y;
Zt=Z;

resvec=[1;1;1];
for i=1:numel(X)
   temp=[X(i);Y(i);Z(i)];
   resvec=EuMat*temp;
   Xt(i)=resvec(1);
   Yt(i)=resvec(2);
   Zt(i)=resvec(3);
end


function logProbs = makeLogProbs(counts,varargin)
%function logProbs = makeLogProbs(counts,varargin)
%each row is a set of counts. convert to normalized log probabilities.
[min_log_prob] = process_options(varargin,'min-log-prob',-200);
logProbs = log(full(normalize_rows(counts)));
logProbs(logProbs < min_log_prob) = min_log_prob;
logProbs = log(normalize_rows(exp(logProbs)));
end


clear
patchSize = 8;

I = double(rgb2gray(imread('160068.jpg')))/255;

% load blurring kernel (you can download the kernels from Dilip Krishnan's
% website
% load kernels.mat
% K = kernel1;
K = fspecial('motion',10,45);
% K = fspecial('gaussian',[5 5],1);
noiseSD = 0.01;
patchSize = 8;

% convolve with kernel and add noise
ks = floor((size(K, 1) - 1)/2);
yorig = I;
y = conv2(yorig, K, 'valid');
y = y + noiseSD*randn(size(y));
y = double(uint8(y .* 255))./255;

% code excerpt taken from Krishnan et al.

% edgetaper to better handle circular boundary conditions
y = padarray(y, [1 1]*ks, 'replicate', 'both');
for a=1:4
  y = edgetaper(y, K);
end

noiseI = y;

% load GMM model
load GSModel_8x8_200_2M_noDC_zeromean.mat

% uncomment this line if you want the total cost calculated
% LogLFunc = @(Z) GMMLogL(Z,GS);

% initialize prior function handle
excludeList = [];
prior = @(Z,patchSize,noiseSD,imsize) aprxMAPGMM(Z,patchSize,noiseSD,imsize,GS,excludeList);

% comment this line if you want the total cost calculated
LogLFunc = [];

% deblur
tic
[cleanI,psnr,~] = EPLLhalfQuadraticSplitDeblur(noiseI,64/noiseSD^2,K,patchSize,50*[1 2 4 8 16 32 64],1,prior,I,LogLFunc);
toc

% output result
figure(1);
imshow(I); title('Original');
figure(2);
imshow(noiseI); title('Corrupted Image');
figure(3);
imshow(cleanI); title('Restored Image');


function A = create_3d_cubic_interp_matrix(T, varargin)
% A = create_3d_bilinear_interp_matrix(T, [szin])
% T should contain displacements in pixels
% size(T) = [sz1, sz2, sz3, 3]
%
% x_def = A * x(:);

sz = [size(T, 1), size(T, 2), size(T, 3)];
if numel(varargin) == 1
    szin = varargin{1};
else
    szin = sz;
end
npixin = szin(1) * szin(2) * szin(3);
npixout = sz(1) * sz(2) * sz(3);

[m1, m2, m3] = ndgrid(1:sz(1), 1:sz(2), 1:sz(3));
TT = T + cat(4, m1, m2, m3);
rowidx = floor(TT(:, :, :, 1));
colidx = floor(TT(:, :, :, 2));
dolidx = floor(TT(:, :, :, 3));
rowk = TT(:, :, :, 1) - rowidx;
colk = TT(:, :, :, 2) - colidx;
dolk = TT(:, :, :, 3) - dolidx;

Kr = koefs(rowk);
Kc = koefs(colk);
Kd = koefs(dolk);

for i = [-1, 0, 1, 2]
    for j = [-1, 0, 1, 2]
        for k = [-1, 0, 1, 2]
%             [i,j,k]
            r = rowidx(:) + i;
            c = colidx(:) + j;
            d = dolidx(:) + k;
            s = Kr{i+2} .* Kc{j+2} .* Kd{k+2};
            t = 1 : npixout;
            idx = (r <= szin(1)) & (r >= 1) & (c <= szin(2)) & (c >= 1) & (d >= 1) & (d <= szin(3));

            r = r(idx);
            c = c(idx);
            d = d(idx);
            s = s(idx);
            t = t(idx);

            sp_c_idx = r + szin(1) * (c - 1) + szin(1)*szin(2)* (d - 1);

            if i == -1 && j == -1 && k == -1
                A = sparse(t, sp_c_idx, s, npixout, npixin);
            else
                tmp = sparse(t, sp_c_idx, s, npixout, npixin);
                A = A + tmp;
            end
        end
    end
end
A = A/8;
end

function B = koefs(A)
    B{1} = A.*((2-A).*A-1);
    B{2} = A.^2.*(3*A-5)+2;
    B{3} = A.*((4-3*A).*A+1);
    B{4} = A.^2.*(A-1);
end


function L = levin(ntscIm)
% LEVIN Compute an image Laplacian according to the *code* accompanying
% "Colorization Using Optimization" [Levin et al. 2004]. Note that this is not
% the same as what is described in the *text* of the paper. This matrix is not
% symmetric and should be treated as a system matrix rather than a quadratic
% coefficient matrix of an energy.
%
% L = levin(ntscIm)
%
% Inputs:
%   ntscIm  h by w  Luminance image
% Outputs:
%   L  w*h by w*h spares Laplacian
%
% Note: Anat Levin's code, Alec's interpretation

n=size(ntscIm,1); m=size(ntscIm,2);
imgSize=n*m;

%nI(:,:,1)=ntscIm(:,:,1);

indsM=reshape([1:imgSize],n,m);

wd=1;

len=0;
consts_len=0;
col_inds=zeros(imgSize*(2*wd+1)^2,1);
row_inds=zeros(imgSize*(2*wd+1)^2,1);
vals=zeros(imgSize*(2*wd+1)^2,1);
gvals=zeros(1,(2*wd+1)^2);

for j=1:m
   for i=1:n
      consts_len=consts_len+1;

      %if (~colorIm(i,j))
        tlen=0;
        for ii=max(1,i-wd):min(i+wd,n)
           for jj=max(1,j-wd):min(j+wd,m)

              if (ii~=i)|(jj~=j)
                 len=len+1; tlen=tlen+1;
                 row_inds(len)= consts_len;
                 col_inds(len)=indsM(ii,jj);
                 gvals(tlen)=ntscIm(ii,jj,1);
              end
           end
        end
        t_val=ntscIm(i,j,1);
        gvals(tlen+1)=t_val;
        c_var=mean((gvals(1:tlen+1)-mean(gvals(1:tlen+1))).^2);
        csig=c_var*0.6;
        mgv=min((gvals(1:tlen)-t_val).^2);
        if (csig<(-mgv/log(0.01)))
	   csig=-mgv/log(0.01);
	end
	if (csig<0.000002)
	   csig=0.000002;
        end

        gvals(1:tlen)=exp(-(gvals(1:tlen)-t_val).^2/csig);
        gvals(1:tlen)=gvals(1:tlen)/sum(gvals(1:tlen));
        vals(len-tlen+1:len)=-gvals(1:tlen);
      %end

      len=len+1;
      row_inds(len)= consts_len;
      col_inds(len)=indsM(i,j);
      vals(len)=1;

   end
end

vals=vals(1:len);
col_inds=col_inds(1:len);
row_inds=row_inds(1:len);

L=sparse(row_inds,col_inds,vals,consts_len,imgSize);


function [str] = strengths_und(CIJ)
%STRENGTHS_UND        Strength
%
%   str = strengths_und(CIJ);
%
%   Node strength is the sum of weights of links connected to the node.
%
%   Input:      CIJ,    undirected weighted connection matrix
%
%   Output:     str,    node strength
%
%
%   Olaf Sporns, Indiana University, 2002/2006/2008

% compute strengths
str = sum(CIJ);        % strength


function [c] = redblue(m)
%
% redblue  	Shades of red to white to blue colormap.
%		REDBLUE(M) returns an M-by-3 matrix containing a
%		"redblue" colormap.
%               CAVEAT this actually only works properly for even length
%               colormaps.  Some fiddling will get it to work generally.
%
%		See also HSV, COLORMAP, RGBPLOT.

if nargin<1
  [m,n] = size(colormap);
end;

m0=floor(m*0.0);
m1=floor(m*0.20);
m2=floor(m*0.20);
m3=floor(m/2)-m2-m1;

b_= [ 0.4*(0:m1-1)'/(m1-1)+0.6; ones(m2+m3,1)];
g_=  [zeros(m1,1); (0:m2-1)'/(m2-1);ones(m3,1)];
r_=  [zeros(m1,1); zeros(m2,1); (0:m3-1)'/(m3-1)];

r=[r_; flipud(b_)];
g=[g_; flipud(g_)];
b=[b_; flipud(r_)];

c=[r g b];


function [en,S] = DSAFadapt_Morgan_cllp(un,dn,S)

% DSAFadapt_Morgan_cllp     Closed-Loop Delayless Subband Adaptive Filter Using the
%                           Weight Transformation Proposed by Morgan and Thi (Section 4.4.3.1)
% Arguments:
% un                        Input signal
% dn                        Desired signal
% S                         Adptive filter parameters as defined in MSAFinit.m
% en                        History of error signal
%
% Note:     Only N is even is implemented, where the conjugate symmetric of H_i(z)
%           and H_{N-1}(z) is exploited!!!
%
% by Lee, Gan, and Kuo, 2008
% Subband Adaptive Filtering: Theory and Implementation
% Publisher: John Wiley and Sons, Ltd

M = length(S.FULLcoeffs);
Ms = size(S.SUBcoeffs,1);
[L,N] = size(S.analysis);
D = S.decfac;
mu = S.step;
alpha = S.alpha;
AdaptStart = S.AdaptStart;
UpdateRate = S.UpdateRate;
H = S.analysis;
F = S.synthesis;
W = S.SUBcoeffs;                   % Adaptive subfilters
U = zeros(size(W));                % Tapped-delay lines of adaptive subfilters
w = S.FULLcoeffs;                  % Fullband adaptive filter
u = zeros(M,1);                    % Fullband tap-input vector
H = H(:,1:N/2+1);                  % Analysis filter (only the filrst N/2+1 is taken)
x = zeros(L,1);                    % Tapped-delay line of input signal (Analysis FB)
e = zeros(L,1);                    % Tapped-delay line of error signal (Analysis FB)

ITER = length(un);
en = zeros(1,ITER);

if isfield(S,'unknownsys')
    b = S.unknownsys;
    norm_b = norm(b);
    eml = zeros(1,ITER);
    ComputeEML = 1;
else
    ComputeEML = 0;
end

for n = 1:ITER
    x = [un(n); x(1:end-1)];       % Fullband input vector for subband filtering
    u = [un(n); u(1:end-1)];

    if ComputeEML == 1;
        eml(n) = norm(b-w)/norm_b; % System error norm (normalized)
    end

    en(n) = dn(n) - w.'*u;         % Error signal (open loop structure)
    e = [en(n); e(1:end-1)];

    if (mod(n-1,D)==0)             % Tap-weight adaptation at lowest sampling rate
        U = [x.'*H; U(1:end-1,:)]; % Each colums hold a subband regression vector
        eD = e.'*H;                % Row vector, each element is subband estimtion error
        if n >= AdaptStart
            W = W + conj(U)*diag(eD./(sum(U.*conj(U))+alpha))*mu;
            S.iter = S.iter + 1;
        end
    end
    if (n >= AdaptStart)& (mod(n-1,UpdateRate)==0)
        w = WeightTransform_Morgan(W,N,D,Ms);
                                   % Weight transformation (modified Morgan's method)
    end
end

S.FULLcoeffs = w;
S.SUBcoeffs = W;
if ComputeEML == 1;
    S.eml = eml;
end


function [pnt, tri] = mesh_cube()

% MESH_CUBE creates a triangulated cube
%
% Use as
%   [pos, tri] = mesh_cube()
%
% See also MESH_TETRAHEDRON, MESH_OCTAHEDRON, MESH_ICOSAHEDRON, MESH_SPHERE, MESH_CONE

% Copyright (C) 2019, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.

pnt = [
  -1 -1 -1
  -1  1 -1
   1  1 -1
   1 -1 -1
  -1 -1  1
  -1  1  1
   1  1  1
   1 -1  1
  ];

tri = [
  1 2 4
  2 3 4
  1 5 6
  1 6 2
  2 6 7
  2 7 3
  3 7 8
  3 8 4
  4 8 5
  4 5 1
  8 6 5
  8 7 6
  ];


function s = imMedian(img, varargin)
%IMMEDIAN Median value of a grayscale image, or of each color component
%
%   S = imMedian(IMG)
%   Computes the median value of pixels in image IMG. If image is grayscale
%   image, the result is a scalar. If image is a color image, the result is
%   1-by-3 row vector, each componenent corresponding to one color of the
%   image.
%
%   S = imMedian(IMG, MASK)
%   Computes the median value only in the area specified by MASK.
%
%   S = imMedian(..., 'color', COL)
%   Forces the function to consider the image as color (if COL is TRUE) or
%   as grascale (if COL is FALSE). This can be useful for vector image with
%   more than 3 color components.
%
%
%   Example
%   % apply to cameraman image
%   img = imread('cameraman.tif');
%   imMedian(img)
%   ans =
%       144
%
%   % apply to a RGB image
%   img = imread('peppers.png');
%   imMedian(img)
%   ans =
%       90    43    60
%
%   See also
%   imMin, imMax, imMean, imMode
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2010-07-30,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

%% Process input arguments

% detect if image is color
color = isColorImage(img);

% check if user specified 'color' option
if length(varargin)>1
    var = varargin{end-1};
    if ischar(var)
        if strcmpi(var, 'color')
            color = varargin{end};
            varargin(end-1:end) = [];
        end
    end
end

%% Process color image

if color
    % If image is color, process each band separately

    % compute image size and dimension (including color dimension)
    dim = size(img);
    nd = length(dim);

    % create idnexing structure
    inds = cell(1, nd);
    for i=1:nd
        inds{i} = 1:dim(i);
    end

    % iterate on colors
    nc = dim(3);
    s = zeros(1, nc);
    for i=1:nc
        % modify the indexing structure to work on the i-th component
        inds{3} = i;
        s(i) = imMedian(img(inds{:}), varargin{:});
    end

    return;
end

%% process grayscale image

if isempty(varargin)
    % compute sum over all image
    s = median(img(:));
else
    % use first argument as mask
    s = median(img(varargin{1}));
end


% DEMSWISSROLLVARGPLVM1 Run variational GPLVM on swiss roll data.

% VARGPLVM

% Fix seeds
randn('seed', 1e5);
rand('seed', 1e5);

dataSetName = 'swissRoll';
experimentNo = 1;

% load data
[Y, lbls] = lvmLoadData(dataSetName);

% Set up model
options = vargplvmOptions('dtcvar');
options.kern = {'rbfard2', 'bias', 'white'};
options.numActive = 100;
%options.initX = 'ppca';
%options.scale2var1 = 1; % scale data to have variance 1
options.tieParam = 'tied';

options.optimiser = 'scg';
latentDim = 3;
d = size(Y, 2);

% demo using the variational inference method for the gplvm model
model = vargplvmCreate(latentDim, d, Y, options);

model = vargplvmParamInit(model, model.m, model.X);
%model.vardist.covars = 10*ones(model.N,model.q) + 0.001*randn(model.N,model.q);

% Optimise the model.
iters = 15; % Default: 1500
display = 1;

model = vargplvmOptimise(model, display, iters);

% Save the results.
modelWriteResult(model, dataSetName, experimentNo);

if exist('printDiagram') & printDiagram
   % order wrt to the inputScales
  mm = vargplvmReduceModel(model,2);
  lvmPrintPlot(mm, lbls, dataSetName, experimentNo);
end

% Load the results and display dynamically.
lvmResultsDynamic(model.type, dataSetName, experimentNo, 'plot3', model.y)

lvmScatterPlotColor(mm, model.y(:, 2)); %%% ?

% See also: plotting with scatter3


function prob = survProbGenHazFun(t,b,hazardFun)
% survProbGeneralHazardFunction: Computes survival probability using the
% hazard function 'hazardFun'

h = @(t)hazardFun(t,b);

H = zeros(size(t));
H(1) = quad(h,0,t(1));
for i=2:length(H)
   H(i) = H(i-1) + quad(h,t(i-1),t(i));
end

prob = exp(-H);


function value = r8_log ( x )

%*****************************************************************************80
%
%% R8_LOG evaluates the logarithm of an R8.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 September 2011
%
%  Author:
%
%    Original FORTRAN77 version by Wayne Fullerton.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Wayne Fullerton,
%    Portable Special Function Routines,
%    in Portability of Numerical Software,
%    edited by Wayne Cowell,
%    Lecture Notes in Computer Science, Volume 57,
%    Springer 1977,
%    ISBN: 978-3-540-08446-4,
%    LC: QA297.W65.
%
%  Parameters:
%
%    Input, real X, the evaluation point.
%
%    Output, real VALUE, the logarithm of X.
%
  persistent alncen
  persistent alncs
  persistent center
  persistent nterms

  aln2 = 0.06814718055994530941723212145818;

  if ( isempty ( nterms ) )

    alncs = [ ...
      +0.13347199877973881561689386047187E+01, ...
      +0.69375628328411286281372438354225E-03, ...
      +0.42934039020450834506559210803662E-06, ...
      +0.28933847795432594580466440387587E-09, ...
      +0.20512517530340580901741813447726E-12, ...
      +0.15039717055497386574615153319999E-15, ...
      +0.11294540695636464284521613333333E-18, ...
      +0.86355788671171868881946666666666E-22, ...
      +0.66952990534350370613333333333333E-25, ...
      +0.52491557448151466666666666666666E-28, ...
      +0.41530540680362666666666666666666E-31 ]';

    center = [ 1.0, 1.25, 1.50, 1.75 ];

    alncen = [ ...
      +0.0, ...
      +0.22314355131420975576629509030983, ...
      +0.40546510810816438197801311546434, ...
      +0.55961578793542268627088850052682, ...
      +0.69314718055994530941723212145817 ]';

    nterms = r8_inits ( alncs, 11, 28.9 * r8_mach ( 3 ) );

  end

  if ( x <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8_LOG - Fatal error!\n' );
    fprintf ( 1, '  X <= 0.0\n' );
    error ( 'R8_LOG - Fatal error!' )
  end

  [ y, n ] = r8_upak ( x );

  xn = n - 1;
  y = 2.0 * y;
  ntrval = r8_aint ( 4.0 * y - 2.5 );

  if ( ntrval == 5 )
    t = ( ( y - 1.0 ) - 1.0 ) / ( y + 2.0 );
  elseif ( ntrval < 5 )
    t = ( y - center(ntrval) ) / ( y + center(ntrval) );
  end

  t2 = t * t;
  value = 0.625 * xn + ( aln2 * xn + alncen(ntrval) ...
    + 2.0 * t + t * t2 ...
    * r8_csevl ( 578.0 * t2 - 1.0, alncs, nterms ) );

  return
end


function [X,rho,eta,F] = pnu(A,L,W,b,k,nu,sm)
%PNU "Preconditioned" version of Brakhage's nu-method.
%
% [X,rho,eta,F] = pnu(A,L,W,b,k,nu,sm)
%
% Performs k steps of a `preconditioned' version of Brakhage's
% nu-method for the problem
%    min || (A*L_p) x - b || ,
% where L_p is the A-weighted generalized inverse of L.  Notice
% that the matrix W holding a basis for the null space of L must
% also be specified.
%
% The routine returns all k solutions, stored as columns of
% the matrix X.  The solution seminorm and residual norm are returned
% in eta and rho, respectively.
%
% If nu is not specified, nu = .5 is the default value, which gives
% the Chebychev method of Nemirovskii and Polyak.
%
% If the generalized singular values sm of (A,L) are also provided,
% then pnu computes the filter factors associated with each step and
% stores them columnwise in the matrix F.

% Reference: H. Brakhage, "On ill-posed problems and the method of
% conjugate gradients"; in H. W. Engl & G. W. Groetsch, "Inverse and
% Ill-Posed Problems", Academic Press, 1987.

% Martin Hanke, Institut fuer Praktische Mathematik, Universitaet
% Karlsruhe and Per Christian Hansen, IMM, 06/25/92.

% Set parameters.
l_steps = 3;      % Number of Lanczos steps for est. of || A*L_p ||.
fudge   = 0.99;   % Scale A and b by fudge/|| A*L_p ||.
fudge_thr = 1e-4; % Used to prevent filter factors from exploding.

% Initialization.
if (k < 1), error('Number of steps k must be positive'), end
if (nargin==5), nu = .5; end
[m,n] = size(A); p = size(L,1); X = zeros(n,k);
if (nargout > 1)
  rho = zeros(k,1); eta = rho;
end;
if (nargin==7)
  F = zeros(n,k); Fd = zeros(n,1); s = (sm(:,1)./sm(:,2)).^2;
end
V = zeros(p,l_steps); B = zeros(l_steps+1,l_steps);
v = zeros(p,1);

% Prepare for computations with L_p.
[NAA,x_0] = pinit(W,A,b); x1 = x_0;

% Compute a rough estimate of || A*L_p || by means of a few steps of
% Lanczos bidiagonalization, and scale A and b such that || A*L_p || is
% slightly less than one.
b_0 = b - A*x_0; beta = norm(b_0); u = b_0/beta;
for i=1:l_steps
  r = ltsolve(L,A'*u,W,NAA) - beta*v;
  alpha = norm(r); v = r/alpha;
  B(i,i) = alpha; V(:,i) = v;
  p = A*lsolve(L,v,W,NAA) - alpha*u;
  beta = norm(p); u = p/beta;
  B(i+1,i) = beta;
end
scale = fudge/norm(B); A = scale*A;
if (nargin==7), s = scale^2*s; end

% Prepare for iteration.
x  = x_0;
z  = -scale*b_0;
r  = A'*z;
d1 = ltsolve(L,r);
d  = lsolve(L,d1,W,NAA);
if (nargout>2), x1 = L*x_0; end

% Iterate.
for j=0:k-1

  % Updates.
  alpha = 4*(j+nu)*(j+nu+0.5)/(j+2*nu)/(j+2*nu+0.5);
  beta  = -(j+nu)*(j+1)*(j+0.5)/(j+2*nu)/(j+2*nu+0.5)/(j+nu+1);
  Ad  = A*d; AAd = A'*Ad;
  x   = x - alpha*d;
  r   = r - alpha*AAd;
  rr1 = ltsolve(L,r);
  rr  = lsolve(L,rr1,W,NAA);
  d   = rr - beta*d;
  X(:,j+1) = x;
  if (nargout>1 )
    z = z - alpha*Ad; rho(j+1) = norm(z)/scale;
  end
  if (nargout>2)
    x1 = x1 - alpha*d1; d1 = rr1 - beta*d1;
    eta(j+1) = norm(x1);
  end

  % Filter factors.
  if (nargin==7)
    if (j==0)
      F(:,1) = alpha*s;
      Fd = s - s.*F(:,1) + beta*s;
    else
      F(:,j+1) = F(:,j) + alpha*Fd;
      Fd = s - s.*F(:,j+1) + beta*Fd;
    end
    if (j > 1)
      f = find(abs(F(:,j)-1) < fudge_thr & abs(F(:,j-1)-1) < fudge_thr);
      if ~isempty(f), F(f,j+1) = ones(length(f),1); end
    end
  end

end


classdef RWMOP16 < PROBLEM
% <multi> <real> <constrained>
% Cantilever beam design problem

%------------------------------- Reference --------------------------------
% A. Kumar, G. Wu, M. Ali, Q. Luo, R. Mallipeddi, P. Suganthan, and S. Das,
% A benchmark-suite of real-world constrained multi-objective optimization
% problems and some baseline results, Swarm and Evolutionary Computation,
% 2021, 67: 100961.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Initialization
        function Setting(obj)
            obj.M        = 2;
            obj.D        = 2;
            obj.lower    = [0.01 0.20];
            obj.upper    = [0.05 1];
            obj.encoding = ones(1,obj.D);
        end
        %% Evaluate multiple solutions
        function Population = Evaluation(obj,varargin)
            x  = varargin{1};
            x1 = x(:,1);
            x2 = x(:,2);
            P  = 1;
            E  = 207000000;
            Sy = 300000;
            delta_max = 0.005;
            rho = 7800;
            % Objectives
            f(:,1) = 0.25 .* rho .* pi .* x2 .* x1.^2;
            f(:,2) = (64 .* P .* x2.^3)./(3 .* E .* pi .* x1.^4);
            % Constraints
            g(:,1) = -Sy + (32 .* P .* x2)./(pi .* x1.^3);
            g(:,2) = -delta_max + (64 .* P .* x2.^3)./(3 .* E .* pi .* x1.^4);
            Population = SOLUTION(varargin{1},f,g,varargin{2:end});
            obj.FE     = obj.FE + length(Population);
        end
        %% Generate a point for hypervolume calculation
        function R = GetOptimum(obj,~)
            R = [3.0630528e+00   2.0408763e-03];
        end
    end
end


function [data, clustPoints, idx, centers, slopes, lengths] = ...
    generateData( ...
        slope, ...
        slopeStd, ...
        numClusts, ...
        xClustAvgSep, ...
        yClustAvgSep, ...
        lengthAvg, ...
        lengthStd, ...
        lateralStd, ...
        totalPoints ...
    )
% GENERATEDATA Generates 2D data for clustering; data is created along
%              straight lines, which can be more or less parallel depending
%              on slopeStd argument.
%
% [data clustPoints idx centers slopes lengths] =
%    GENERATEDATA(slope, slopeStd, numClusts, xClustAvgSep, yClustAvgSep, ...
%                 lengthAvg, lengthStd, lateralStd, totalPoints)
%
% Inputs:
%        slope - Base direction of the lines on which clusters are based.
%     slopeStd - Standard deviation of the slope; used to obtain a random
%                slope variation from the normal distribution, which is
%                added to the base slope in order to obtain the final slope
%                of each cluster.
%    numClusts - Number of clusters (and therefore of lines) to generate.
% xClustAvgSep - Average separation of line centers along the X axis.
% yClustAvgSep - Average separation of line centers along the Y axis.
%    lengthAvg - The base length of lines on which clusters are based.
%    lengthStd - Standard deviation of line length; used to obtain a random
%                length variation from the normal distribution, which is
%                added to the base length in order to obtain the final
%                length of each line.
%   lateralStd - "Cluster fatness", i.e., the standard deviation of the
%                distance from each point to the respective line, in both x
%                and y directions; this distance is obtained from the
%                normal distribution.
%  totalPoints - Total points in generated data (will be
%                randomly divided among clusters).
%
% Outputs:
%         data - Matrix (totalPoints x 2) with the generated data
%  clustPoints - Vector (numClusts x 1) containing number of points in each
%                cluster
%          idx - Vector (totalPoints x 1) containing the cluster indices of
%                each point
%      centers - Matrix (numClusts x 2) containing centers from where
%                clusters were generated
%       slopes - Vector (numClusts x 1) containing the effective slopes
%                used to generate clusters
%      lengths - Vector (numClusts x 1) containing the effective lengths
%                used to generate clusters
%
% ----------------------------------------------------------
% Usage example:
%
%   [data cp idx] = GENERATEDATA(1, 0.5, 5, 15, 15, 5, 1, 2, 200);
%
% This creates 5 clusters with a total of 200 points, with a base slope
% of 1 (std=0.5), separated in average by 15 units in both x and y
% directions, with average length of 5 units (std=1) and a "fatness" or
% spread of 2 units.
%
% To take a quick look at the clusters just do:
%
%   scatter(data(:,1), data(:,2), 8, idx);

%  N. Fachada
%  Instituto Superior Técnico, Lisboa, Portugal

% Make sure totalPoints >= numClusts
if totalPoints < numClusts
    error('Number of points must be equal or larger than the number of clusters.');
end;

% Determine number of points in each cluster
clustPoints = abs(randn(numClusts, 1));
clustPoints = clustPoints / sum(clustPoints);
clustPoints = round(clustPoints * totalPoints);

% Make sure totalPoints is respected
while sum(clustPoints) < totalPoints
    % If one point is missing add it to the smaller cluster
    [C,I] = min(clustPoints);
    clustPoints(I(1)) = C + 1;
end;
while sum(clustPoints) > totalPoints
    % If there is one extra point, remove it from larger cluster
    [C,I] = max(clustPoints);
    clustPoints(I(1)) = C - 1;
end;

% Make sure there are no empty clusters
emptyClusts = find(clustPoints == 0);
if ~isempty(emptyClusts)
    % If there are empty clusters...
    numEmptyClusts = size(emptyClusts, 1);
    for i=1:numEmptyClusts
        % ...get a point from the largest cluster and assign it to the
        % empty cluster
        [C,I] = max(clustPoints);
        clustPoints(I(1)) = C - 1;
        clustPoints(emptyClusts(i)) = 1;
    end;
end;

% Initialize data matrix
data = zeros(sum(clustPoints), 2);

% Initialize idx (vector containing the cluster indices of each point)
idx = zeros(totalPoints, 1);

% Initialize lengths vector
lengths = zeros(numClusts, 1);

% Determine cluster centers
xCenters = xClustAvgSep * numClusts * (rand(numClusts, 1) - 0.5);
yCenters = yClustAvgSep * numClusts * (rand(numClusts, 1) - 0.5);
centers = [xCenters yCenters];

% Determine cluster slopes
slopes = slope + slopeStd * randn(numClusts, 1);

% Create clusters
for i=1:numClusts
    % Determine length of line where this cluster will be based
    lengths(i) = abs(lengthAvg + lengthStd*randn);
    % Determine how many points have been assigned to previous clusters
    sumClustPoints = 0;
    if i > 1
        sumClustPoints = sum(clustPoints(1:(i - 1)));
    end;
    % Create points for this cluster
    for j=1:clustPoints(i)
        % Determine where in the line the next point will be projected
        position = lengths(i) * rand - lengths(i) / 2;
        % Determine x coordinate of point projection
        delta_x = cos(atan(slopes(i))) * position;
        % Determine y coordinate of point projection
        delta_y = delta_x * slopes(i);
        % Get point distance from line in x coordinate
        delta_x = delta_x + lateralStd * randn;
        % Get point distance from line in y coordinate
        delta_y = delta_y + lateralStd * randn;
        % Determine the actual point
        data(sumClustPoints + j, :) = [(xCenters(i) + delta_x) (yCenters(i) + delta_y)];
    end;
    % Update idx
    idx(sumClustPoints + 1 : sumClustPoints + clustPoints(i)) = i;
end;


classdef CEC2020_F3 < PROBLEM
% <single> <real>
% Shifted and rotated Lunacek bi-Rastrigin function

%------------------------------- Reference --------------------------------
% C .T. Yue, K. V. Price, P. N. Suganthan, J. J. Liang, M. Z. Ali, B. Y.
% Qu, N. H. Awad, and P. P Biswas, Problem definitions and evaluation
% criteria for the CEC 2020 special session and competition on single
% objective bound constrained numerical optimization, Zhengzhou University,
% China and Nanyang Technological University, Singapore, 2019.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    properties
        O;      % Optimal decision vector
        Mat;	% Rotation matrix
    end
    methods
        %% Default settings of the problem
        function Setting(obj)
            CallStack = dbstack('-completenames');
            load(fullfile(fileparts(CallStack(1).file),'CEC2020.mat'),'Data');
            obj.O = Data{3}.o;
            obj.M = 1;
            if isempty(obj.D) || obj.D < 10
                obj.D   = 5;
                obj.Mat = Data{3}.M_5;
            elseif obj.D < 15
                obj.D   = 10;
                obj.Mat = Data{3}.M_10;
            elseif obj.D < 20
                obj.D   = 15;
                obj.Mat = Data{3}.M_15;
            else
                obj.D   = 20;
                obj.Mat = Data{3}.M_20;
            end
            obj.lower    = zeros(1,obj.D) - 100;
            obj.upper    = zeros(1,obj.D) + 100;
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,PopDec)
            s   = 1 - 1/(2*sqrt(obj.D+20)-8.2);
            mu0 = 2.5;
            mu1 = -sqrt((mu0^2-1)/s);
            Y   = (PopDec-repmat(obj.O(1:size(PopDec,2)),size(PopDec,1),1))/10;
            tmp = 2*repmat(sign(obj.O(1:size(PopDec,2))),size(PopDec,1),1).*Y + mu0;
            Z   = (tmp-mu0)*obj.Mat';
            PopObj = 700 + min(sum((tmp-mu0).^2,2),obj.D+s*sum((tmp-mu1).^2,2)) + 10*(obj.D-sum(cos(2*pi*Z),2));
        end
    end
end


function Rinv = est_calcInvCovMat(AR,C,invCov,mode,MAXITER)
%
% For any M-variate VAR[p] process fit to data X = [X1, X2, ... Xn],
% this function returns the [(Mp)^2 x (Mp)^2] covariance (or inverse covariance)
% matrix of the process. This is a block-toeplitz, hermitian matrix with
% format as described in [2].
%
% Briefly, let M=nvars, and Rhat be comprised of M x M submatrices
%
%           Rhat(u,v) = [R11(u,v) ... R1M
%                           ...        ...
%                        RM1(u,v) ... RMM(u,v)]
%
% where Rij(u,v) = cov(Xi(t-u),Xj(t-v)) for i,j=1:M and u,v = 1:p. Then
% Rhat is the (cross-)covariance matrix of the VAR[p] process up to lag p
% with inverse covariance matrix Rinv = inverse(Rhat).
%
% Inputs:
%
%   AR:     [nvars x nvar*morder] matrix of vector autoregressive
%           coefficients
%   C:      nvars x nvars noise covariance matrix
%   invCov: {def: 1}
%           true: return inverse of processes covariance matrix
%           fase: return process covariance matrix
%   mode:   {def: 3} Determines the method used to compute the covariance matrix
%           1: uses the standard approach from [2]
%           2: same as 1, but using sparse matrices.
%           3: uses the iterative doubling algorithm of Anderson and Moore
%              as proposed in [1]. For large matrices, generally much faster
%              and less memory intensive.
%   MAXITER:{def: 100}
%           Number of iterations for doubling algorithm (mode=3)
%
% Outputs:
%
%   Rinv:   [(nvars*p)^2 x (nvars*p)^2] (inverse) covariance matrix of the
%           VAR[p] process.
%
%
% References:
%
% [1] Barone, (1987) J. of Time series Analysis vol. 8 no. 2
% [2] Lutkepohl, H. (2007) New Introduction to Time Series Analysis.
% Springer. Sec 2.1.4.
%
% See Also: est_calcInvCovMatFourier(), est_calcInvCovMatPDC
%
% Author: Tim Mullen 2010, SCCN/INC, UCSD
% Email:  tim@sccn.ucsd.edu

% This function is part of the Source Information Flow Toolbox (SIFT)
%
% 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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

if nargin<4
    mode = 3;
end
if nargin<3
    invCov = 1;    % if 0, don't invert covariance matrix
end
if nargin<4
    MAXITER = 100;
end

% make sure the noise covariance matrix is valid
C = covfixer(C);

switch mode

    case 1

        % Standard covariance estimation. See [2] sec. 2.1.4

        M = size(C,1);          % nchans
        p = size(AR,2)/M;       % model order
        Mp=M*p;

        A = zeros(Mp);
        A(1:M,1:Mp) = AR;
        A(M+1:end,1:end-M) = eye(Mp-M);
        Eu = zeros(Mp);
        Eu(1:M,1:M) = C;

        Rinv = (eye(Mp^2)-kron(A,A))\Eu(:);

%         Rinv = reshape(Rinv,Mp,Mp)\eye(Mp);

        Rinv = inverse(reshape(Rinv,Mp,Mp));

    case 2

        % same as 1, but sparse approach

        M = size(C,1);          % nchans
        p = size(AR,2)/M;       % model order
        Mp=M*p;

        A = spalloc(Mp,Mp,M*Mp+M);
        A(1:M,1:Mp) = AR;
        A(M+1:end,1:end-M) = eye(Mp-M);

        Eu = spalloc(Mp,Mp,M^2);
        Eu(1:M,1:M) = single(C);

        Rinv = (speye(Mp^2)-kron(A,A))\Eu(:);

        % Rinv = symmlq(speye(Mp^2)-kron(A,A),Eu(:),1e-6,100);

        Rinv = full(reshape(Rinv,Mp,Mp)\speye(Mp));

    case 3

        % Anderson-Moore/Barone Doubling Algorithm [1]

        M = size(C,1);          % nchans
        p = size(AR,2)/M;       % model order
        Mp=M*p;
        A = zeros(Mp);
        A(1:M,1:Mp) = AR;
        A(M+1:end,1:end-M) = eye(Mp-M);

        K = [eye(M); zeros(M*(p-1),M)];
        N = {K*C*K'};
        N{2} = zeros(size(N{1}));

        for t=1:MAXITER
            N{2} = A*N{1}*A'+N{1};
            A = A^2;
            if norm(N{2}(:)-N{1}(:))<1e-15
                break
            end
            N{1}=N{2};
        end

        if t==MAXITER
            warning('SIFT:est_calcInvCovMat', 'Anderson-Moore did not converge. Results may be innacurate.\n');
        end

        % Rinv = L*N{2}*L';

        % ensure that the covariance matrix is a valid covariance matrix
        N{2} = covfixer(N{2});

        if invCov
            Rinv = inverse(N{2});
        else
            Rinv = N{2};
        end

end


function [ fea, out ] = ex_navierstokes3( varargin )
%EX_NAVIERSTOKES3 2D Example for incompressible stationary flow around a cylinder.
%
%   [ FEA, OUT ] = EX_NAVIERSTOKES3( VARARGIN ) Stationary flow around a cylinder. References:
%
%   [1] John V, Matthies G. Higher-order finite element discretizations in a
%       benchmark problem for incompressible flows. International Journal for
%       Numerical Methods in Fluids 2001.
%
%   [2] Nabh G. On higher order methods for the stationary incompressible
%       Navier-Stokes equations. PhD Thesis, Universitaet Heidelberg, 1998.
%
%   Accepts the following property/value pairs.
%
%       Input       Value/{Default}        Description
%       -----------------------------------------------------------------------------------
%       rho         scalar {1}             Density
%       miu         scalar {0.001}         Molecular/dynamic viscosity
%       umax        scalar {0.3}           Maximum magnitude of inlet velocity
%       igrid       scalar {2}             Grid type: >0 regular (igrid refinements)
%                                                     <0 unstruc. grid (with hmax=|igrid|)
%       sf_u        string {sflag1}        Shape function for velocity
%       sf_p        string {sflag1}        Shape function for pressure
%       iphys       scalar 0/{1}           Use physics mode to define problem (=1)
%       solver      string {}              Solver selection default, openfoam, su2, fenics
%       iplot       scalar 0/{1}           Plot solution (=1)
%                                                                                .
%       Output      Value/(Size)           Description
%       -----------------------------------------------------------------------------------
%       fea         struct                 Problem definition struct
%       out         struct                 Output struct
%
%   See also EX_NAVIERSTOKES3B

% Copyright 2013-2022 Precise Simulation, Ltd.

cOptDef = { ...
            'rho',      1;
            'miu',      0.001;
            'umax',     0.3;
            'igrid',    2;
            'sf_u',     'sflag1';
            'sf_p',     'sflag1';
            'iphys',    1;
            'solver',   '';
            'iplot',    1;
            'tol',      [0.05 0.35 0.1];
            'fid',      1 };
[got,opt] = parseopt(cOptDef,varargin{:});
fid       = opt.fid;

% Model parameters.
rho       = opt.rho;     % Density.
miu       = opt.miu;     % Molecular/dynamic viscosity.
umax      = opt.umax;    % Maximum magnitude of inlet velocity.
umean     = 2/3*umax;    % Mean inlet velocity.
% Geometry and grid parameters.
h         = 0.41;        % Height of rectangular domain.
l         = 2.2;         % Length of rectangular domain.
xc        = 0.2;         % x-coordinate of cylinder center.
yc        = 0.2;         % y-coordinate of cylinder center.
diam      = 0.1;         % Diameter of cylinder.
% Discretization parameters.
sf_u      = opt.sf_u;    % FEM shape function type for velocity.
sf_p      = opt.sf_p;    % FEM shape function type for pressure.

% Grid generation.
fea.sdim = { 'x' 'y' };
if( opt.igrid>=1 )
  fea.grid = cylbenchgrid( opt.igrid );
  fea.grid.s(:) = 1;
else
  gobj1 = gobj_rectangle( 0, 2.2, 0, 0.41, 'R1' );
  gobj2 = gobj_circle( [0.2 0.2], 0.05, 'C1' );
  fea.geom.objects = { gobj1 gobj2 };
  fea = geom_apply_formula( fea, 'R1-C1' );
  fea.grid = gridgen( fea, 'hmax', abs(opt.igrid), 'fid', fid );
end
if( opt.iphys==1 && strcmp(opt.solver,'fenics') &&  size(fea.grid.c,1)==4 )
  warning( 'Converting quadrilateral mesh to triangular to support FEniCS.' )
  fea.grid = quad2tri( fea.grid );
end
n_bdr = max(fea.grid.b(3,:));   % Number of boundaries.

% Boundary conditions.
dtol      = sqrt(eps)*1e3;
i_inflow  = findbdr( fea, ['x<=',num2str(dtol)] );     % Inflow boundary number.
i_outflow = findbdr( fea, ['x>=',num2str(l-dtol)] );   % Outflow boundary number.
s_inflow  = ['4*',num2str(umax),'*(y*(',num2str(h),'-y))/',num2str(h),'^2'];   % Definition of inflow profile.
i_cyl     = findbdr( fea, ['sqrt((x-',num2str(xc),').^2+(y-',num2str(yc),').^2)<=(',num2str(diam/2+dtol),')'] );    % Cylinder boundary number.

% Problem definition.
if ( opt.iphys==1 )

  fea = addphys(fea,@navierstokes);     % Add Navier-Stokes equations physics mode.
  fea.phys.ns.eqn.coef{1,end} = { rho };
  fea.phys.ns.eqn.coef{2,end} = { miu };
  fea.phys.ns.sfun            = { sf_u sf_u sf_p };     % Set shape functions.

  fea.phys.ns.bdr.sel(i_inflow)  = 2;
  fea.phys.ns.bdr.sel(i_outflow) = 4;
  fea.phys.ns.bdr.coef{2,end}{1,i_inflow} = s_inflow;   % Set inflow profile.
  fea = parsephys(fea);                 % Check and parse physics modes.

else

  fea.dvar  = { 'u'  'v'  'p'  };       % Dependent variable name.
  fea.sfun  = { sf_u sf_u sf_p };       % Shape function.

  % Define equation system.
  cvelx = [num2str(rho),'*',fea.dvar{1}];   % Convection velocity in x-direction.
  cvely = [num2str(rho),'*',fea.dvar{2}];   % Convection velocity in y-direction.
  fea.eqn.a.form = { [2 3 2 3;2 3 1 1]       [2;3]                   [1;2];
                     [3;2]                   [2 3 2 3;2 3 1 1]       [1;3];
                     [2;1]                   [3;1]                   []   };
  fea.eqn.a.coef = { {2*miu miu cvelx cvely}  miu                    -1;
                     miu                     {miu 2*miu cvelx cvely} -1;
                     1                       1                      [] };
  fea.eqn.f.form = { 1 1 1 };
  fea.eqn.f.coef = { 0 0 0 };

  % Define boundary conditions.
  fea.bdr.d = cell(3,n_bdr);
  [fea.bdr.d{1:2,:}]         = deal( 0);

  fea.bdr.d{1,i_inflow}      = s_inflow;

  [fea.bdr.d{:,i_outflow  }] = deal([]);

  fea.bdr.n = cell(3,n_bdr);
end

% Parse and solve problem.
fea = parseprob(fea);             % Check and parse problem struct.
if( opt.iphys==1 && strcmp(opt.solver,'openfoam') )
  logfid = fid; if( ~got.fid ), fid = []; end
  fea.sol.u = openfoam( fea, 'fid', fid, 'logfid', logfid );
  fid = logfid;
elseif( opt.iphys==1 && strcmp(opt.solver,'su2') )
  logfid = fid; if( ~got.fid ), fid = []; end
  fea.sol.u = su2( fea, 'fid', fid, 'logfid', logfid );
  fid = logfid;
elseif( opt.iphys==1 && strcmp(opt.solver,'fenics') )
  fea = fenics( fea, 'fid', fid );
else
  jac.form  = {[1;1] [1;1] [];[1;1] [1;1] []; [] [] []};
  jac.coef  = {[num2str(rho),'*ux'] [num2str(rho),'*uy'] []; [num2str(rho),'*vx'] [num2str(rho),'*vy'] []; [] [] []};
  fea.sol.u = solvestat( fea, 'fid', fid, 'nsolve', 2, 'jac', jac, 'nlrlx', '(1+(it>2))/2' );   % Call to stationary solver.
end

% Postprocessing.
s_velm = 'sqrt(u^2+v^2)';
if ( opt.iplot>0 )
  figure
  subplot(2,1,1)
  postplot( fea, 'surfexpr', s_velm )
  title( 'Velocity field' )
  subplot(2,1,2)
  postplot( fea, 'surfexpr', 'p' )
  title( 'Pressure' )
end

% Calculate benchmark quantities (line integration method).
s_tfx = ['nx*p+',num2str(miu),'*(-2*nx*ux-ny*(uy+vx))'];
s_tfy = ['ny*p+',num2str(miu),'*(-nx*(vx+uy)-2*ny*vy)'];
s_cd  = ['2*(',s_tfx,')/(',num2str(rho),'*',num2str(umean),'^2*',num2str(diam),')'];
s_cl  = ['2*(',s_tfy,')/(',num2str(rho),'*',num2str(umean),'^2*',num2str(diam),')'];
i_cub = 10;
c_d1  = intbdr(s_cd,fea,i_cyl,i_cub);
c_l1  = intbdr(s_cl,fea,i_cyl,i_cub);
dp    = evalexpr('p',[0.15 0.25;0.2 0.2],fea);

% Calculate benchmark quantities (volume integration method).
bdrm   = fea.bdr.bdrm{1};
ind_b  = [];
ind_bm = [];
for ii=i_cyl
  ind_b  = [ind_b  find(fea.grid.b(3,:)==ii)];
  ind_bm = [ind_bm find(bdrm(3,:)==ii)];
end
ind_c    = fea.grid.b(1,ind_b);
ind_gdof = bdrm(4,ind_bm);

% Create field 'a' with values one on the cylinder and zero everywhere else.
fea.dvar = [ fea.dvar, {'a'}       ];
fea.sfun = [ fea.sfun, fea.sfun(1) ];
fea      = parseprob(fea);
n_dof    = max(fea.eqn.dofm{1}(:));
u_a      = zeros(n_dof,1);
u_a(ind_gdof) = 1;
fea.sol.u= [fea.sol.u;u_a];
fea.eqn  = struct;
fea.bdr  = struct;
fea      = parseprob(fea);

s_tfx    = ['ax*p+',num2str(miu),'*(-2*ax*ux-ay*(uy+vx))-(u*ux+v*uy)*a'];
s_tfy    = ['ay*p+',num2str(miu),'*(-ax*(vx+uy)-2*ay*vy)-(u*vx+v*vy)*a'];
s_cd     = ['2*(',s_tfx,')/(',num2str(rho),'*',num2str(umean),'^2*',num2str(diam),')'];
s_cl     = ['2*(',s_tfy,')/(',num2str(rho),'*',num2str(umean),'^2*',num2str(diam),')'];
c_d2     = intsubd(s_cd,fea,[],[],3);
c_l2     = intsubd(s_cl,fea,[],[],3);

if( ~isempty(fid) )
  fprintf(fid,'\n\nBenchmark quantities:\n\n')

  fprintf(fid,'Drag coefficient,    cd = %6f (l), %6f (v) (Ref: 5.579535)\n',c_d1,c_d2)
  fprintf(fid,'Lift coefficient,    cl = %6f (l), %6f (v) (Ref: 0.010619)\n',c_l1,c_l2)
  fprintf(fid,'Pressure,            dp = %6f (Ref: 0.117520)\n',dp(1)-dp(2))
end

% Error checking.
out.cd   = [c_d1 c_d2];
out.cl   = [c_l1 c_l2];
out.dp   = dp(1)-dp(2);
out.err  = [abs(out.cd-5.579535)/5.579535;
            abs(out.cl-0.010619)/0.010619;
            abs(dp(1)-dp(2)-0.117520)/0.117520 0];
out.pass = (out.err(1,2)<opt.tol(1))&&(out.err(2,2)<opt.tol(2))&&(out.err(3,1)<opt.tol(3));
if ( nargout==0 )
  clear fea out
end

%------------------------------------------------------------------------------%
function [ grid ] = cylbenchgrid( nlev )
% CYLBENCHGRID Generate 2d quadrilateral grid for the DFG cylinder benchmark.

  ns = 8*2^(nlev-1);
  r  = [0.05 0.06 0.08 0.11 0.15];
  x  = [0.41 0.5 0.7 1 1.4 1.8 2.2];
  for ilev=2:nlev
    r = sort( [ r (r(1:end-1)+r(2:end))/2 ] );
    x = sort( [ x (x(1:end-1)+x(2:end))/2 ] );
  end

  grid1 = ringgrid( r, 4*ns, [], [], [0.2;0.2] );
  grid2 = holegrid( ns, 2^(nlev-1), [0 0.41;0 0.41], 0.15, [0.2;0.2] );
  grid2 = gridmerge( grid1, 5:8, grid2, 1:4 );
  grid3 = rectgrid( x, ns, [0.41 2.2;0 0.41] );
  grid  = gridmerge( grid3, 4, grid2, 6 );


function I = sum3(f)
%SUM3   Triple definite integral of a CHEBFUN3T over [a, b] x [c, d] x [e g].
%   This is a direct generalization of Clenshaw-Curtis quadrature as
%   implemented in Page 77 of Battles' PhD thesis.

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

if ( isempty(f) )
    I = [];
    return;
end

coeffs = f.coeffs;
% Rescaling factors:
rescaleFactor = 0.5*diff(f.domain(1:2));                 % (b - a)/2
rescaleFactor = rescaleFactor * 0.5*diff(f.domain(3:4)); % (d - c)/2
rescaleFactor = rescaleFactor * 0.5*diff(f.domain(5:6)); % (g - e)/2

if ( nargin == 1 )
    [nx, ny, nz] = size(coeffs);
    I1 = zeros(nx,ny);
    for i = 1:nx
        for j = 1:ny
            I1(i,j) = squeeze(coeffs(i,j,1:2:nz)).'*(2./(1-(0:2:nz-1)'.^2));
        end
    end
    I2 = zeros(nx,1);
    for i = 1:nx
        I2(i) = I1(i,1:2:ny)*(2./(1-(0:2:ny-1)'.^2));
    end
    I = I2(1:2:nx).'*(2./(1-(0:2:nx-1)'.^2));
end

% Rescale the output:
I = I*rescaleFactor;

end


function XRecovered = recoverData(reducedData, U, K)

% This function is used to recover the original data from the data set with
% reduced features. reducedData = (m x K), where m is the number of examples
% and K is the reduced number of features. U = (n x n). UReduced = (n x K),
% where K is the number of reduced features that we have. Therefore
% reducedData*(UReduced') becomes (m x n) , m examples made up of n features.

UReduced = U(:,1:K);
XRecovered = reducedData*(UReduced');


function [ output ] = fista( par )
% fista for stably principal component pursuit problem
%{
par.M = M;
par.iter = 1000;
%lambda = 1/sqrt(max(size(M))); % default lambda
par.lambda_1 = 0.1;
par.lambda_2 = 0.001;
out = fista(par);
subplot(1,3,1),imagesc(M);
subplot(1,3,2),imagesc(out.L);
subplot(1,3,3),imagesc(out.S);
show_results(M,out.L,out.S,[],size(M,2),m,n);
%}
%%  Cun Mu and John Wright, Mar '14

M = par.M; % data matrix
[m,n] = size(M); d = min(m,n);
Omega = ones(m,n); % if not specified, full observation
obj_target = -inf;

if isfield(par,'Omega') Omega = par.Omega;  end
if isfield(par,'iter') iter_no = par.iter; end
if isfield(par,'obj') obj_target = par.obj; end

lambda_1 = par.lambda_1;
lambda_2 = par.lambda_2;
%display = par.display;
lips = 2;

L = zeros(m,n); S = zeros(m,n);
sv = round(d/10);
iter = 1; hist = 0;

L_hat = zeros(m,n); S_hat = zeros(m,n); t = 1;
L_pre = zeros(m,n); S_pre = zeros(m,n);

while true

  temp_L = L_hat - Omega.*(L_hat+S_hat-M)/lips;
  temp_S = S_hat - Omega.*(L_hat+S_hat-M)/lips;

  S = max(temp_S - lambda_2/lips, 0);
  S = S+min(temp_S + lambda_2/lips, 0);

  if choosvd(n, sv) == 1
    [U s V] = lansvd(temp_L, sv, 'L');
    %[U s V] = svd(temp_L, 'econ');
  else
    [U s V] = svd(temp_L, 'econ');
  end
  diagS = diag(s);
  svp = size(find(diagS > lambda_1/lips),1);
  if svp < sv
    flag = 1;
    sv = min(svp + 1, d);
  else
    flag = 0;
    sv = min(svp + round(0.05*d), d);
  end

  newSingularValues = diagS(1:svp) - lambda_1/lips;
  newNuclearNorm = sum(newSingularValues);

  L = U(:, 1:svp) * diag(diagS(1:svp) - lambda_1/lips) * V(:, 1:svp)';

  obj_value = 0.5*norm(Omega.*(L+S-M),'fro')^2 + lambda_1*newNuclearNorm ...
    +lambda_2*norm(vec(S),1);

  fprintf('this is the %d th iteration; sv = %d; obj. value = %d \n',...
    iter, sv, obj_value);

  hist(iter) = obj_value;

  if flag
    if obj_value < obj_target
      break;
    end
  end

  t_pre = t;
  t = (1+4*t^2)^0.5/2 + 0.5;
  alpha = (t_pre-1)/t;

  L_hat = L + alpha*(L-L_pre);
  S_hat = S + alpha*(S-S_pre);

  iter = iter +1;
  L_pre = L;  S_pre = S;

  if(iter > iter_no)
    break;
  end
end

output.L = L;
output.S = S;
output.hist = hist;
end


function E = ShortTimeEnergy(signal, windowLength,step)
signal = signal / max(max(signal));
curPos = 1;
L = length(signal);
numOfFrames = floor((L-windowLength)/step) + 1;
%H = hamming(windowLength);
E = zeros(numOfFrames,1);
for (i=1:numOfFrames)
    window = (signal(curPos:curPos+windowLength-1));
    E(i) = (1/(windowLength)) * sum(abs(window.^2));
    curPos = curPos + step;
end
%Max = max(E);
%med = median(E);
%m = mean(E);
%a = length(find(E>2*med))/numOfFrames;
%b = length(find(E<(med/2)))/numOfFrames;

%S_EnergyM = length(find(E>2*med))/numOfFrames;
%S_EnergyV = length(find(E<(med/2)))/numOfFrames;
%S_EnergyM = std(E);
%S_EnergyV = a;


function [Dt, totalDist] = InterfiberZhangDistance(curve1, curve2, Tt)
%Distance between two 3D paths, defined as two 3xN sets of 3d coordinates.
%
% [Dt, totalDist] = InterfiberZhangDistance(curve1, curve2, [Tt=2])
%
% The terms Dt and totalDist need better definition here.
%
% The metric is described in Zhang et al. (2003) IEEE Transactions on
% Vizualization and Computer Graphics 9(4).  They write:
%
% �In order to emphasize important differences between a pair of
% trajectories, we average the distance between the curves only over the
% region where they are at least Tt apart; smaller differences are assumed
% to be insignificant�.
%
% Although arguable, it is natural to set Tt to data voxel size /not sure,
% before or after resampling/ (as Zhang 2003 did). Here the default value
% is set to 1mm despite the fact that out data are commonly 2x2x2.
%
% Calculated on a point by point basis.
% Note: by definition, if a point on a shorter fiber is closer to the other
% fiber than Tt, this point does NOT contribute to the overall
% curve-to-curve distance measure.
%
%Dt is above-the-threshold (that is, minus Tt) average point-to-curve
%distance  across all points on a shortest fiber to another fiber.
%
%  CLARIFY.
% The output variable totalDist is Dt+Tt, the average point-to-curve
% distance between the two fibers. These output arguments are different by
% a constant,  however included since the first one is the "definition" of
% the distance by Zhang et al., and the second one is easier to interpret.
% Also totalDist is reported as at least at Tt (even for two fibers which
% are closer than Tt).
%
%  Example:
%    curve1 = 10*rand(3,10);
%    curve2 = curve1 + 1;
%    Tt = 0;
%    [Dt, totalDist] = InterfiberZhangDistance(curve1, curve2,Tt)
%    [Dt, totalDist] = InterfiberZhangDistance(curve1, curve2,2)
%
%ER 11/2008
%ER 04/2009 added "totalDist" output and introduced a default value for Tt
%to be 0 (all points contribute to the distance measure).
%
% (c) Stanford VISTA Team

%Pairs of points in closer than Tt are not included when summing the
%distance between fibers.
if (~exist('Tt', 'var')), Tt=0; end

% Check curve sizes.
if size(curve1, 1) ~= 3 || size(curve2, 1) ~= 3
   error('Fiber coordinates must be represented as 3xN');
end

% Use  "nearpoints" to find the nearest point in curve 1 to curve 2.
% [indices, bestSqDist] = nearpoints(src, dest)
%-  src is a 3xM array of points
%-  dest is a 3xN array of points
%-  indices is a 1xM vector, whose elements identifies the closest point
%   in dest for each entry in src.
%   "bestSqDist" is the distance.
%

% For efficiency, choose which is the first term
if size(curve1, 2) < size(curve2, 2),
    [indices, bestSqDist] = nearpoints(curve1, curve2);
else
    [indices, bestSqDist] = nearpoints(curve2, curve1);
end

% Have a look at the data in the two curves.
% mrvNewGraphWin;
%  plot3(curve1(1,:),curve1(2,:),curve1(3,:),'bo'); hold on
%  plot3(curve2(1,:),curve2(2,:),curve2(3,:),'r.');
%

% I don't understand.  If there are no entries bigger than Tt, we set Dt to
% zero, I guess.
nPoints = length(find(bestSqDist > Tt));
if nPoints <= 0
    % Expansive but useless. Precisely,
    % Tt=sum(sqrt(bestSqDist))/length(bestSqDist);
    % We keep it as a constant Tt.
    Dt = 0;
else
    % Otherwise, we set Dt to this average.
    Dt = sum(sqrt(bestSqDist(bestSqDist > Tt)) - Tt) / nPoints;
end

% Then we add Tt back in.
totalDist = Dt + Tt;

return;

%%The slow way (gives equivalent result)
if size(curve1, 2)<size(curve2, 2)
    scurve=curve1;  %shorter
    lcurve=curve2; %longer curve
else
    scurve=curve2;
    lcurve=curve1;
end

countpoints=0;  sumdist=0;

for pnt=1:size(scurve,2)
    distVector = sqrt((lcurve(1, :)-scurve(1, pnt)).^2 + (lcurve(2, :)-scurve(2, pnt)).^2+(lcurve(3, :)-scurve(3, pnt)).^2);
    p2curveDist=min(distVector); %Shortest point to curve distance

    if p2curveDist>Tt
        countpoints=countpoints+1;
        sumdist= sumdist+ (p2curveDist-Tt);
    end

end

if countpoints>0
    Dt=sumdist/countpoints;
else
    Dt=0;
end


%% How do I know whether AR1 noise is an appropriate null hypothesis to test against?
% It is usually an appropriate null hypothesis if the theoretical AR1
% spectrum is  degreesa good model degrees for the power decay in the observed spectrum.
% I recommend to simply visually compare the two power spectra:

X=rednoise(200,.8);
[P,freq]=pburg(zscore(X),7,[],1);
aa=ar1(X);
Ptheoretical=(1-aa.^2)./(abs(1-aa.*exp(-2*pi*i*freq))).^2;
semilogy(freq,P/sum(P),freq,Ptheoretical/sum(Ptheoretical),'r');
legend('observed',sprintf('Theoretical AR1=%.2f',aa),'location','best')


% moving camera bundle adjustment problem

ncams = 10;  % number of cameras
npts = 110;  % number of landmark points
visprob = 0.65;  % probability of camera seeing a landmark
pixnoise = 0.5; % standard deviation of Gaussian noise added to camera projections
Tshift = SE3(-0.2, 0, 0);  % horizontal shift of camera at each view

% create a camera
cam = CentralCamera('default', 'noise', pixnoise)

% setup a bundle adjustment problem
ba = BundleAdjust(cam);

% create the camera nodes, all at the origin, and keep their handles ch(i)
for i=1:ncams
    if i == 1
        ch(i) = ba.add_camera( SE3, 'fixed' );
    else
        ch(i) = ba.add_camera( SE3 );
    end
end

% create a working volume containing npts random points
% x -3 -> 1
% y -2 -> 2
% z  4 -> 8
randinit
P = bsxfun(@plus, 2 * 2*(rand(3, npts) - 0.5), [-1, 0 , 6]');

% create the landmark nodes and keep their handles lh(j)
for j=1:numcols(P)
    lh(j) = ba.add_landmark( P(:,j) );
end

% slide the camera in the x-direciton
T = SE3;
for i=1:ncams
    % project all landmarks for this camera position
    [p, visible] = cam.project(P, 'pose', T);

    % find the subset of points that are visible
    for j=find(visible)'
        % add to the problem if visible
        if rand < visprob % with a probability
            ba.add_projection(ch(i), lh(j), p(:,j));
        end
    end
    T = T .* Tshift; % shift the camera
end

% display the problem summary
ba

figure(1)
ba.plot()

pause

% get the state vector
X = ba.getstate();

% get the initial error
ba.errors(X)

% display the Hessian
figure(2)
ba.spyH(X)
title('Hessian matrix sparsity')

% solve the problem
baf = ba.optimize(X);

figure(3)
baf.plot()


function  [ConSPix ConEdge]= find_connect_superpixel(labels, K, height ,width )
%%
% obtain the neighbour relationship of the super-pixels
% Input:
%         labels:    the super-pixel label obtained from SLIC
%         K:         the number of super-pixels
%         height:    the height of the image
%         width:     the width of the image
% Output:
%         ConPix:   the one layer neighbour relationship
%%%%=====================================================
ConSPix=zeros(K,K);
%the one outerboundary super
for i=1:height-1
    for j=1:width-1
        if labels(i,j)~=labels(i,j+1)
            ConSPix(labels(i,j) ,labels(i,j+1) )=1;
        end
        if labels(i,j)~=labels(i+1,j)
            ConSPix(labels(i,j) ,labels(i+1,j) )=1;
        end
    end
    if labels(i,j+1)~=labels(i+1,j+1)
        ConSPix(labels(i,j+1) ,labels(i+1,j+1 ) )=1;
    end
end
for j=1:width-1
    if labels(height,j)~=labels(height,j+1)
        ConSPix( labels(height,j),labels(height,j+1) )=1;
    end
end
for i=1:height-1
    for j=1:width-1
        if labels(i,j)~=labels(i+1,j+1)
            ConSPix( labels(i,j),labels(i+1,j+1) )=1;
        end
    end
end
for i=1:height-1
    for j=2:width
        if labels(i,j)~=labels(i+1,j-1)
            ConSPix( labels(i,j),labels(i+1,j-1) )=1;
        end
    end
end
 ConSPix = ConSPix + ConSPix';
 ConSPix(ConSPix>0)=1;
 [edges_x edges_y] = find(triu(ConSPix)==1);
 ConEdge = [edges_x edges_y];
 %[x y] = meshgrid(1:K,1:K);
 %ConEdge = [x(:) y(:)];


function demo3 (C, sym, name)
%DEMO3: Cholesky update/downdate
%
% Example:
%   demo3 (C, 1, 'name of system')
% See also: cs_demo

%   Copyright 2006-2007, Timothy A. Davis.
%   http://www.cise.ufl.edu/research/sparse

clf
subplot (2,2,1) ; cspy (C) ;
title (name, 'FontSize', 16, 'Interpreter', 'none') ;
drawnow

[m n] = size (C) ;
if (m ~= n | ~sym)                                                          %#ok
    return ;
end

b = rhs (n) ;
fprintf ('chol then update/downdate ') ;
print_order (0) ;

tic ;
[L,p] = cs_chol (C) ;
t = toc ;
fprintf ('\nchol  time: %8.2f\n', t) ;

subplot (2,2,2) ; cspy (L) ; title ('L') ;
drawnow

tic ;
x = b (p) ;
x = cs_lsolve (L,x) ;
x = cs_ltsolve (L,x) ;
x (p) = x ;
t = toc ;
fprintf ('solve time: %8.2f\n', t) ;

fprintf ('original: ') ;
print_resid (C, x, b) ;

k = fix (n/2) ;
w = L(k,k) * sprand (L (:,k)) ;

parent = cs_etree (C (p,p)) ;

tic ;
L2 = cs_updown (L, w, parent, '+') ;
t1 = toc ;
fprintf ('update:   time: %8.2f\n', t1) ;

subplot (2,2,3) ; cspy (L2) ; title ('updated L') ;
subplot (2,2,4) ; cspy (L-L2) ; title ('L - updated L') ;
drawnow

tic ;
x = b (p) ;
x = cs_lsolve (L2,x) ;
x = cs_ltsolve (L2,x) ;
x (p) = x ;
t = toc ;

w2 = sparse (n,1) ;
w2 (p) = w ;                    % w2 = P'*w
wt = cs_transpose (w2) ;
ww = cs_multiply (w2,wt) ;
E = cs_add (C, ww, 1, 1) ;      % E = C + w2*w2' ;

fprintf ('update:   time: %8.2f (incl solve) ', t1+t) ;
print_resid (E, x, b) ;

tic
[L,p2] = cs_chol (E) ;
x = b (p2) ;
x = cs_lsolve (L,x) ;
x = cs_ltsolve (L,x) ;
x (p2) = x ;
t = toc ;
fprintf ('rechol:   time: %8.2f (incl solve) ', t) ;
print_resid (E, x, b) ;

tic ;
L3 = cs_updown (L2, w, parent, '-') ;
t1 = toc ;
fprintf ('downdate: time: %8.2f\n', t1) ;

tic ;
x = b (p) ;
x = cs_lsolve (L3,x) ;
x = cs_ltsolve (L3,x) ;
x (p) = x ;
t = toc ;
fprintf ('downdate: time: %8.2f (incl solve) ', t1+t) ;
print_resid (C, x, b) ;


function [D PD] = allfitdist(data,sortby,varargin)
%ALLFITDIST Fit all valid parametric probability distributions to data.
%   [D PD] = ALLFITDIST(DATA) fits all valid parametric probability
%   distributions to the data in vector DATA, and returns a struct D of
%   fitted distributions and parameters and a struct of objects PD
%   representing the fitted distributions. PD is an object in a class
%   derived from the ProbDist class.
%
%   [...] = ALLFITDIST(DATA,SORTBY) returns the struct of valid distributions
%   sorted by the parameter SORTBY
%        NLogL - Negative of the log likelihood
%        BIC - Bayesian information criterion (default)
%        AIC - Akaike information criterion
%        AICc - AIC with a correction for finite sample sizes
%
%   [...] = ALLFITDIST(...,'DISCRETE') specifies it is a discrete
%   distribution and does not attempt to fit a continuous distribution
%   to the data
%
%   [...] = ALLFITDIST(...,'PDF') or (...,'CDF') plots either the PDF or CDF
%   of a subset of the fitted distribution. The distributions are plotted in
%   order of fit, according to SORTBY.
%
%   List of distributions it will try to fit
%     Continuous (default)
%       Beta
%       Birnbaum-Saunders
%       Exponential
%       Extreme value
%       Gamma
%       Generalized extreme value
%       Generalized Pareto
%       Inverse Gaussian
%       Logistic
%       Log-logistic
%       Lognormal
%       Nakagami
%       Normal
%       Rayleigh
%       Rician
%       t location-scale
%       Weibull
%
%     Discrete ('DISCRETE')
%       Binomial
%       Negative binomial
%       Poisson
%
%   Optional inputs:
%   [...] = ALLFITDIST(...,'n',N,...)
%   For the 'binomial' distribution only:
%      'n'            A positive integer specifying the N parameter (number
%                     of trials).  Not allowed for other distributions. If
%                     'n' is not given it is estimate by Method of Moments.
%                     If the estimated 'n' is negative then the maximum
%                     value of data will be used as the estimated value.
%   [...] = ALLFITDIST(...,'theta',THETA,...)
%   For the 'generalized pareto' distribution only:
%      'theta'        The value of the THETA (threshold) parameter for
%                     the generalized Pareto distribution. Not allowed for
%                     other distributions. If 'theta' is not given it is
%                     estimated by the minimum value of the data.
%
%   Note: ALLFITDIST does not handle nonparametric kernel-smoothing,
%   use FITDIST directly instead.
%
%
%   EXAMPLE 1
%     Given random data from an unknown continuous distribution, find the
%     best distribution which fits that data, and plot the PDFs to compare
%     graphically.
%        data = normrnd(5,3,1e4,1);         %Assumed from unknown distribution
%        [D PD] = allfitdist(data,'PDF');   %Compute and plot results
%        D(1)                               %Show output from best fit
%
%   EXAMPLE 2
%     Given random data from a discrete unknown distribution, with frequency
%     data, find the best discrete distribution which would fit that data,
%     sorted by 'NLogL', and plot the PDFs to compare graphically.
%        data = nbinrnd(20,.3,1e4,1);
%        values=unique(data); freq=histc(data,values);
%        [D PD] = allfitdist(values,'NLogL','frequency',freq,'PDF','DISCRETE');
%        PD{1}
%
%  EXAMPLE 3
%     Although the Geometric Distribution is not listed, it is a special
%     case of fitting the more general Negative Binomial Distribution. The
%     parameter 'r' should be close to 1. Show by example.
%        data=geornd(.7,1e4,1); %Random from Geometric
%        [D PD]= allfitdist(data,'PDF','DISCRETE');
%        PD{1}
%
%  EXAMPLE 4
%     Compare the resulting distributions under two different assumptions
%     of discrete data. The first, that it is known to be derived from a
%     Binomial Distribution with known 'n'. The second, that it may be
%     Binomial but 'n' is unknown and should be estimated. Note the second
%     scenario may not yield a Binomial Distribution as the best fit, if
%     'n' is estimated incorrectly. (Best to run example a couple times
%     to see effect)
%        data = binornd(10,.3,1e2,1);
%        [D1 PD1] = allfitdist(data,'n',10,'DISCRETE','PDF'); %Force binomial
%        [D2 PD2] = allfitdist(data,'DISCRETE','PDF');       %May be binomial
%        PD1{1}, PD2{1}                             %Compare distributions
%

%    Mike Sheppard
%    Last Modified: 17-Feb-2012

%% Check Inputs
if nargin == 0
    data = 10.^((normrnd(2,10,1e4,1))/10);
    sortby='BIC';
    varargin={'CDF'};
end
if nargin==1
    sortby='BIC';
end
sortbyname={'NLogL','BIC','AIC','AICc'};
if ~any(ismember(lower(sortby),lower(sortbyname)))
    oldvar=sortby; %May be 'PDF' or 'CDF' or other commands
    if isempty(varargin)
        varargin={oldvar};
    else
        varargin=[oldvar varargin];
    end
    sortby='BIC';
end
if nargin < 2, sortby='BIC'; end
distname={'beta', 'birnbaumsaunders', 'exponential', ...
    'extreme value', 'gamma', 'generalized extreme value', ...
    'generalized pareto', 'inversegaussian', 'logistic', 'loglogistic', ...
    'lognormal', 'nakagami', 'normal', ...
    'rayleigh', 'rician', 'tlocationscale', 'weibull'};
if ~any(strcmpi(sortby,sortbyname))
    error('allfitdist:SortBy','Sorting must be either NLogL, BIC, AIC, or AICc');
end
%Input may be mixed of numeric and strings, find only strings
vin=varargin;
strs=find(cellfun(@(vs)ischar(vs),vin));
vin(strs)=lower(vin(strs));
%Next check to see if 'PDF' or 'CDF' is listed
numplots=sum(ismember(vin(strs),{'pdf' 'cdf'}));
if numplots>=2
    error('ALLFITDIST:PlotType','Either PDF or CDF must be given');
end
if numplots==1
    plotind=true; %plot indicator
    indxpdf=ismember(vin(strs),'pdf');
    plotpdf=any(indxpdf);
    indxcdf=ismember(vin(strs),'cdf');
    vin(strs(indxpdf|indxcdf))=[]; %Delete 'PDF' and 'CDF' in vin
else
    plotind=false;
end
%Check to see if discrete
strs=find(cellfun(@(vs)ischar(vs),vin));
indxdis=ismember(vin(strs),'discrete');
discind=false;
if any(indxdis)
    discind=true;
    distname={'binomial', 'negative binomial', 'poisson'};
    vin(strs(indxdis))=[]; %Delete 'DISCRETE' in vin
end
strs=find(cellfun(@(vs)ischar(vs),vin));
n=numel(data); %Number of data points
data = data(:);
D=[];
%Check for NaN's to delete
deldatanan=isnan(data);
%Check to see if frequency is given
indxf=ismember(vin(strs),'frequency');
if any(indxf)
    freq=vin{1+strs((indxf))}; freq=freq(:);
    if numel(freq)~=numel(data)
        error('ALLFITDIST:PlotType','Matrix dimensions must agree');
    end
    delfnan=isnan(freq);
    data(deldatanan|delfnan)=[]; freq(deldatanan|delfnan)=[];
    %Save back into vin
    vin{1+strs((indxf))}=freq;
else
    data(deldatanan)=[];
end

%% Run through all distributions in FITDIST function
warning('off','all'); %Turn off all future warnings
for indx=1:length(distname)
    try
        dname=distname{indx};
        switch dname
            case 'binomial'
                PD=fitbinocase(data,vin,strs); %Special case
            case 'generalized pareto'
                PD=fitgpcase(data,vin,strs); %Special case
            otherwise
                %Built-in distribution using FITDIST
                PD = fitdist(data,dname,vin{:});
        end

        NLL=PD.NLogL; % -Log(L)
        %If NLL is non-finite number, produce error to ignore distribution
        if ~isfinite(NLL)
            error('non-finite NLL');
        end
        num=length(D)+1;
        PDs(num) = {PD}; %#ok<*AGROW>
        k=numel(PD.Params); %Number of parameters
        D(num).DistName=PD.DistName;
        D(num).NLogL=NLL;
        D(num).BIC=-2*(-NLL)+k*log(n);
        D(num).AIC=-2*(-NLL)+2*k;
        D(num).AICc=(D(num).AIC)+((2*k*(k+1))/(n-k-1));
        D(num).ParamNames=PD.ParamNames;
        D(num).ParamDescription=PD.ParamDescription;
        D(num).Params=PD.Params;
        D(num).Paramci=PD.paramci;
        D(num).ParamCov=PD.ParamCov;
        D(num).Support=PD.Support;
    catch err %#ok<NASGU>
        %Ignore distribution
    end
end
warning('on','all'); %Turn back on warnings
if numel(D)==0
    error('ALLFITDIST:NoDist','No distributions were found');
end

%% Sort distributions
indx1=1:length(D); %Identity Map
sortbyindx=find(strcmpi(sortby,sortbyname));
switch sortbyindx
    case 1
        [~,indx1]=sort([D.NLogL]);
    case 2
        [~,indx1]=sort([D.BIC]);
    case 3
        [~,indx1]=sort([D.AIC]);
    case 4
        [~,indx1]=sort([D.AICc]);
end
%Sort
D=D(indx1); PD = PDs(indx1);

%% Plot if requested
if plotind;
    plotfigs(data,D,PD,vin,strs,plotpdf,discind)
end

end

function PD=fitbinocase(data,vin,strs)
%% Special Case for Binomial
% 'n' is estimated if not given
vinbino=vin;
%Check to see if 'n' is given
indxn=any(ismember(vin(strs),'n'));
%Check to see if 'frequency' is given
indxfreq=ismember(vin(strs),'frequency');
if ~indxn
    %Use Method of Moment estimator
    %E[x]=np, V[x]=np(1-p) -> nhat=E/(1-(V/E));
    if isempty(indxfreq)||~any(indxfreq)
        %Raw data
        mnx=mean(data);
        nhat=round(mnx/(1-(var(data)/mnx)));
    else
        %Frequency data
        freq=vin{1+strs(indxfreq)};
        m1=dot(data,freq)/sum(freq);
        m2=dot(data.^2,freq)/sum(freq);
        mnx=m1; vx=m2-(m1^2);
        nhat=round(mnx/(1-(vx/mnx)));
    end
    %If nhat is negative, use maximum value of data
    if nhat<=0, nhat=max(data(:)); end
    vinbino{end+1}='n'; vinbino{end+1}=nhat;
end
PD = fitdist(data,'binomial',vinbino{:});
end

function PD=fitgpcase(data,vin,strs)
%% Special Case for Generalized Pareto
% 'theta' is estimated if not given
vingp=vin;
%Check to see if 'theta' is given
indxtheta=any(ismember(vin(strs),'theta'));
if ~indxtheta
    %Use minimum value for theta, minus small part
    thetahat=min(data(:))-10*eps;
    vingp{end+1}='theta'; vingp{end+1}=thetahat;
end
PD = fitdist(data,'generalized pareto',vingp{:});
end

function plotfigs(data,D,PD,vin,strs,plotpdf,discind)
%Plot functionality for continuous case due to Jonathan Sullivan
%Modified by author for discrete case

%Maximum number of distributions to include
%max_num_dist=Inf;  %All valid distributions
max_num_dist=4;

%Check to see if frequency is given
indxf=ismember(vin(strs),'frequency');
if any(indxf)
    freq=vin{1+strs((indxf))};
end

figure

%% Probability Density / Mass Plot
if plotpdf
    if ~discind
        %Continuous Data
        nbins = max(min(length(data)./10,100),50);
        xi = linspace(min(data),max(data),nbins);
        dx = mean(diff(xi));
        xi2 = linspace(min(data),max(data),nbins*10)';
        fi = histc(data,xi-dx);
        fi = fi./sum(fi)./dx;
        inds = 1:min([max_num_dist,numel(PD)]);
        ys = cellfun(@(PD) pdf(PD,xi2),PD(inds),'UniformOutput',0);
        ys = cat(2,ys{:});
        bar(xi,fi,'FaceColor',[160 188 254]/255,'EdgeColor','k');
        hold on;
        plot(xi2,ys,'LineWidth',1.5)
        legend(['empirical',{D(inds).DistName}],'Location','NE')
        xlabel('Value');
        ylabel('Probability Density');
        title('Probability Density Function');
        grid on
    else
        %Discrete Data
        xi2=min(data):max(data);
        %xi2=unique(x)'; %If only want observed x-values to be shown
        indxf=ismember(vin(strs),'frequency');
        if any(indxf)
            fi=zeros(size(xi2));
            fi((ismember(xi2,data)))=freq; fi=fi'./sum(fi);
        else
            fi=histc(data,xi2); fi=fi./sum(fi);
        end
        inds = 1:min([max_num_dist,numel(PD)]);
        ys = cellfun(@(PD) pdf(PD,xi2),PD(inds),'UniformOutput',0);
        ys=cat(1,ys{:})';
        bar(xi2,[fi ys]);
        legend(['empirical',{D(inds).DistName}],'Location','NE')
        xlabel('Value');
        ylabel('Probability Mass');
        title('Probability Mass Function');
        grid on
    end
else

%Cumulative Distribution
    if ~discind
        %Continuous Data
        [fi xi] = ecdf(data);
        inds = 1:min([max_num_dist,numel(PD)]);
        ys = cellfun(@(PD) cdf(PD,xi),PD(inds),'UniformOutput',0);
        ys = cat(2,ys{:});
        if max(xi)/min(xi) > 1e4; lgx = true; else lgx = false; end
        subplot(2,1,1)
        if lgx
            semilogx(xi,fi,'k',xi,ys)
        else
            plot(xi,fi,'k',xi,ys)
        end
        legend(['empirical',{D(inds).DistName}],'Location','NE')
        xlabel('Value');
        ylabel('Cumulative Probability');
        title('Cumulative Distribution Function');
        grid on
        subplot(2,1,2)
        y = 1.1*bsxfun(@minus,ys,fi);
        if lgx
            semilogx(xi,bsxfun(@minus,ys,fi))
        else
            plot(xi,bsxfun(@minus,ys,fi))
        end
        ybnds = max(abs(y(:)));
        ax = axis;
        axis([ax(1:2) -ybnds ybnds]);
        legend({D(inds).DistName},'Location','NE')
        xlabel('Value');
        ylabel('Error');
        title('CDF Error');
        grid on
    else
        %Discrete Data
        indxf=ismember(vin(strs),'frequency');
        if any(indxf)
            [fi xi] = ecdf(data,'frequency',freq);
        else
            [fi xi] = ecdf(data);
        end
        %Check unique xi, combine fi
        [xi,ign,indx]=unique(xi); %#ok<ASGLU>
        fi=accumarray(indx,fi);
        inds = 1:min([max_num_dist,numel(PD)]);
        ys = cellfun(@(PD) cdf(PD,xi),PD(inds),'UniformOutput',0);
        ys=cat(2,ys{:});
        subplot(2,1,1)
        stairs(xi,[fi ys]);
        legend(['empirical',{D(inds).DistName}],'Location','NE')
        xlabel('Value');
        ylabel('Cumulative Probability');
        title('Cumulative Distribution Function');
        grid on
        subplot(2,1,2)
        y = 1.1*bsxfun(@minus,ys,fi);
        stairs(xi,bsxfun(@minus,ys,fi))
        ybnds = max(abs(y(:)));
        ax = axis;
        axis([ax(1:2) -ybnds ybnds]);
        legend({D(inds).DistName},'Location','NE')
        xlabel('Value');
        ylabel('Error');
        title('CDF Error');
        grid on
    end
end

end


function linplus_test23 ( )

%*****************************************************************************80
%
%% TEST23 tests R8GB_FA, R8GB_TRF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 March 2009
%
%  Author:
%
%    John Burkardt
%
  m = 5;
  n = m;
  ml = 1;
  mu = 1;
  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST23\n' );
  fprintf ( 1, '  For a general banded matrix,\n' );
  fprintf ( 1, '  R8GB_FA factors, using LINPACK conventions;\n' );
  fprintf ( 1, '  R8GB_TRF factors, using LAPACK conventions;\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Matrix rows M              = %d\n', m );
  fprintf ( 1, '  Matrix columns N           = %d\n', n );
  fprintf ( 1, '  Lower bandwidth ML         = %d\n', ml );
  fprintf ( 1, '  Upper bandwidth MU         = %d\n', mu );
%
%  Set the matrix.
%
  [ a, seed ] = r8gb_random ( m, n, ml, mu, seed );
%
%  Factor the matrix.
%
  [ a_lu, pivot, info ] = r8gb_fa ( n, ml, mu, a );

  r8gb_print ( m, n, ml, mu, a_lu, '  The R8GB_FA factors:' );
%
%  Set the matrix.
%
  seed = 123456789;
  [ a, seed ] = r8gb_random ( m, n, ml, mu, seed );
%
%  Factor the matrix.
%
  [ a_lu, pivot, info ] = r8gb_trf ( m, n, ml, mu, a );

  r8gb_print ( m, n, ml, mu, a_lu, '  The R8GB_TRF factors:');

  return
end


%--------------------------------------------------------------------------
%	SurfBox-MATLAB (c)
%--------------------------------------------------------------------------
%
%	Yue M. Lu and Minh N. Do
%
%--------------------------------------------------------------------------
%
%	SurfEP.m
%
%	First created: 12-12-08
%	Last modified: 12-12-08
%
%--------------------------------------------------------------------------

function Ep = SurfEP(sz, Lev_array, Pyr_mode, bo, nRepeat)

%   Estimating the subband scaling coefficients of the surfacelet transform
%   using a Monte Carlo method.
%
%   Input:
%
%   sz: the size of a N-dimensional array (N >= 2)
%
%   Lev_array: an L by 1 cell array, with each cell being an N by N matrix
%   for NDFB decomposition, or a scaler (either 1 or 2) for dual-tree
%   wavelet decomposition.
%
%   Pyr_mode: type of multiscale pyramid, corresponding to different levels
%   of redundancy.
%   1:       ~ 6.4
%   1.5:     ~ 4.0
%   2:       ~ 3.4
%
%   bo: the order of the checkerboard filters. Default: bo = 12
%
%   nRepeat: the number of trials in the Monte Carlo method.
%
%   Output:
%
%   Ep: the estimated subband scaling coefficients

h = waitbar(0, ['Estimating the subband scaling coefficients.' ...
        'This can be a slow process, but it only needs to be done once for a given configuration.']);

for n = 1 : nRepeat
    X = randn(sz);
    [Y, Recinfo] = Surfdec(X, Pyr_mode, Lev_array, 'ritf', 'bo', bo);
    clear X; % to save some memory

    if n == 1
        Ep = Y;

        for j = 1 : length(Y) - 1
            for dd = 1 : length(Y{j})
                for sd = 1 : length(Y{j}{dd})
                    Ep{j}{dd}{sd} = Ep{j}{dd}{sd} .^ 2;
                end
            end
        end

    else
        for j = 1 : length(Y) - 1
            for dd = 1 : length(Y{j})
                for sd = 1 : length(Y{j}{dd})
                    Ep{j}{dd}{sd} = Ep{j}{dd}{sd} + Y{j}{dd}{sd} .^ 2;
                end
            end
        end
    end

    clear Y;

    waitbar(n / nRepeat, h);
end
close(h);

for j = 1 : length(Ep) - 1
    for dd = 1 : length(Ep{j})
        for sd = 1 : length(Ep{j}{dd})
            Ep{j}{dd}{sd} = sqrt(Ep{j}{dd}{sd} / (nRepeat - 1));
        end
    end
end


% function [Lh,Ph,Mu,Pi,LL]=mfa(X,M,K,cyc,tol);
%
% Maximum Likelihood Mixture of Factor Analysis using EM
%
% X - data matrix
% M - number of mixtures (default 1)
% K - number of factors in each mixture (default 2)
% cyc - maximum number of cycles of EM (default 100)
% tol - termination tolerance (prop change in likelihood) (default 0.0001)
%
% Lh - factor loadings
% Ph - diagonal uniquenesses matrix
% Mu - mean vectors
% Pi - priors
% LL - log likelihood curve
%
% Iterates until a proportional change < tol in the log likelihood
% or cyc steps of EM

function [Lh, Ph,  Mu, Pi, LL] = mfa(X,M,K,cyc,tol)

if nargin<5   tol=0.0001; end;
if nargin<4   cyc=100; end;
if nargin<3   K=2; end;
if nargin<2   M=1; end;

N=length(X(:,1));
D=length(X(1,:));
tiny=exp(-700);

%rand('state',0);

fprintf('\n');

if (M==1)
  [Lh,Ph,LL]=ffa(X,K,cyc,tol);
  Mu=mean(X);
  Pi=1;
else
  if N==1
    mX = X;
  else
    mX=mean(X);
  end
  cX=cov(X);
  scale=det(cX)^(1/D);
  randn('state',0);
  Lh=randn(D*M,K)*sqrt(scale/K);
  Ph=diag(cX)+tiny;
  Pi=ones(M,1)/M;
  %randn('state',0);
  Mu=randn(M,D)*sqrtm(cX)+ones(M,1)*mX;
  oldMu=Mu;
  I=eye(K);

  lik=0;
  LL=[];

  H=zeros(N,M); 	% E(w|x)
  EZ=zeros(N*M,K);
  EZZ=zeros(K*M,K);
  XX=zeros(D*M,D);
  s=zeros(M,1);
  const=(2*pi)^(-D/2);
  %%%%%%%%%%%%%%%%%%%%
  for i=1:cyc;

    %%%% E Step %%%%

    Phi=1./Ph;
    Phid=diag(Phi);
    for k=1:M
      Lht=Lh((k-1)*D+1:k*D,:);
      LP=Phid*Lht;
      MM=Phid-LP*inv(I+Lht'*LP)*LP';
      dM=sqrt(det(MM));
      Xk=(X-ones(N,1)*Mu(k,:));
      XM=Xk*MM;
      H(:,k)=const*Pi(k)*dM*exp(-0.5*rsum(XM.*Xk));
      EZ((k-1)*N+1:k*N,:)=XM*Lht;
    end;

    Hsum=rsum(H);
    oldlik=lik;
    lik=sum(log(Hsum+(Hsum==0)*exp(-744)));

    Hzero=(Hsum==0); Nz=sum(Hzero);
    H(Hzero,:)=tiny*ones(Nz,M)/M;
    Hsum(Hzero)=tiny*ones(Nz,1);

    H=rdiv(H,Hsum);
    s=csum(H);
    s=s+(s==0)*tiny;
    s2=sum(s)+tiny;

    for k=1:M
      kD=(k-1)*D+1:k*D;
      Lht=Lh(kD,:);
      LP=Phid*Lht;
      MM=Phid-LP*inv(I+Lht'*LP)*LP';
      Xk=(X-ones(N,1)*Mu(k,:));
      XX(kD,:)=rprod(Xk,H(:,k))'*Xk/s(k);
      beta=Lht'*MM;
      EZZ((k-1)*K+1:k*K,:)=I-beta*Lht +beta*XX(kD,:)*beta';
    end;

    %%%% log likelihood %%%%

    LL=[LL lik];
    fprintf('cycle %g   \tlog likelihood %g ',i,lik);

    if (i<=2)
      likbase=lik;
    elseif (lik<oldlik)
      fprintf(' violation');
    elseif ((lik-likbase)<(1 + tol)*(oldlik-likbase)||~isfinite(lik))
      break;
    end;

    fprintf('\n');

    %%%% M Step %%%%

    % means and covariance structure

    Ph=zeros(D,1);
    for k=1:M
      kD=(k-1)*D+1:k*D;
      kK=(k-1)*K+1:k*K;
      kN=(k-1)*N+1:k*N;

      T0=rprod(X,H(:,k));
      T1=T0'*[EZ(kN,:) ones(N,1)];
      XH=EZ(kN,:)'*H(:,k);
      T2=inv([s(k)*EZZ(kK,:) XH; XH' s(k)]);
      T3=T1*T2;
      Lh(kD,:)=T3(:,1:K);
      Mu(k,:)=T3(:,K+1)';
      T4=diag(T0'*X-T3*T1')/s2;
      Ph=Ph+T4.*(T4>0);
    end;

    Phmin=exp(-700);
    Ph=Ph.*(Ph>Phmin)+(Ph<=Phmin)*Phmin; % to avoid zero variances

    % priors
    Pi=s'/s2;

  end;
  fprintf('\n');
end;


function c=ref_dfft(f,order)
%REF_DFFT  Reference Discrete Fractional Fourier Transform
%   Usage:  c=ref_dfft(f,order);
%

L=size(f,1);

% Create matrix representation of the DFT
F=idft(eye(L));

c=(F^order)*f;


function logPr = calcMargLogPrData_ARMatrixNormalInvWishart( Xstats, PP )

[D DR K] = size( Xstats.XY );
LOG_PI =  1.144729885849400;

logPr = -Inf( 1, K );
for jj = 1:K
    XX = Xstats.XX(:,:,jj);
    XY = Xstats.XY(:,:,jj);
    YY = Xstats.YY(:,:,jj);
    CC = PP.invAScaleMatrix;

    degFreeN = PP.degFree + Xstats.nObs(jj);

    ScaleMatrixN = PP.ScaleMatrix + XX - ( XY/(YY + CC) )*XY';
    %ScaleMatrixN = PP.ScaleMatrix + XX - XY*( (YY+CC)\(XY') );

    logPr(jj) = logMvGamma( 0.5*degFreeN, D ) - logMvGamma( 0.5*PP.degFree, D ) ...
                  + 0.5*PP.degFree*log( det( PP.ScaleMatrix ) )   ...
                  - 0.5*degFreeN  *log( det(   ScaleMatrixN ) ) ...
                  + 0.5*D*log( det( CC ) ) ...
                  - 0.5*D*log( det( CC + YY ) );
end

N = sum(Xstats.nObs);
logPr = sum( logPr ) + -0.5*N*D*LOG_PI;


clear all; close all;
I=imread('coins.png');
I=imnoise(I, 'gaussian', 0, 0.01);
I=im2double(I);
M=2*size(I,1);
N=2*size(I,2);
u=-M/2:(M/2-1);
v=-N/2:(N/2-1);
[U,V]=meshgrid(u, v);
D=sqrt(U.^2+V.^2);
D0=50;
W=30;
H=double(or(D<(D0-W/2), D>D0+W/2));
J=fftshift(fft2(I, size(H, 1), size(H, 2)));
K=J.*H;
L=ifft2(ifftshift(K));
L=L(1:size(I,1), 1:size(I, 2));
figure;
subplot(121);
imshow(I);
subplot(122);
imshow(L);


classdef PoissonDistributionX < ProbabilityDistributionX
% PoissonDistributionX class
%
% Summary of PoissonDistributionX:
% This is a class implementation of a Poisson distribution
%
% PoissonDistributionX Properties:
%   + Mean - Mean of the Poisson distribution
%   + Covar - Variance of the Poisson distribution
%
% PoissonDistributionX Methods:
%   + PoissonDistributionX  - Constructor method
%   + reset - Reset the distribution with a new number of random variables
%   + random - Draw random samples from the multivariate normal distribution
%   + pdf - Evaluate the density of the multivariate normal distribution
%
% (+) denotes puplic properties/methods
%
% See also TransitionModelX, MeasurementModelX and ControlModelX template classes

    properties (Dependent)
        % Mean: scalar
        %   Mean of the Poisson distribution
        Mean

        % Covar: scalar
        %   Variance of the Poisson distribution
        Covar
    end

    properties (Access = private)
        % Underlying poisson distribution
        pd_ = makedist('Poisson');
    end

    methods
        function this = PoissonDistributionX(varargin)
        % PoissonDistributionX Construct a Poisson distribution
        %
        % Parameters
        % ----------
        % mean: non-negative scalar
        %   Mean of the Poisson distribution
            this.reset(varargin{:});
        end

        function samples = random(this, numSamples)
        % Samples Draw random samples from the Gaussian
        %
        % Parameters
        % ----------
        % numSamples: scalar
        %   The number of samples to be drawn from the mixture
        %
        % Returns
        % -------
        % samples: (NumVariables x numSamples) matrix
        %   The set of samples drawn from the mixture.

            assert(numSamples >= 1);

            % Incorporate actual mean
            samples = this.pd_.random(numSamples,1)';
        end

        function prob = pdf(this, samples)
        % pdf Evaluate the density of the poisson distribution
        %   PROB = PDF(OBJ, SAMPLES) returns the density of the poisson distribution,
        %   evaluated at each column of SAMPLES.
        %
            prob = this.pd_.pdf(samples);
        end

        function reset(this, varargin)
            if(nargin >= 2)
                mean = varargin{1};

                % Reset number of random variables. This will also take care of
                % input validation.
                this.NumVariables = size(mean,1);

                % Re-initialize the mean and covariance
                this.Mean = mean;
            end
        end
    end

    methods
        function meanValue = get.Mean(this)
        %get.Mean Getter for Mean property
            meanValue = this.pd_.mean();
        end

        function set.Mean(this, meanValue)
        %set.Mean - Setter for Mean property
            this.pd_ = makedist('Poisson','lambda',  meanValue);
        end

        function covariance = get.Covar(this)
        %get.Covariance Getter for Covariance property
            covariance = this.pd_.var();
        end
    end

end


%DEMO_REGRESSION_ADDITIVE2  Regression demonstration with additive Gaussian
%                           process using linear, squared exponential and
%                           neural network covariance fucntions
%
%  Description
%    Gaussian process solutions in 2D regression problem using
%    constant, linear, squared exponential (sexp) and neural
%    network covariance functions, and with various additive
%    combinations of these four covariance functions. The noisy
%    observations y are assumed to satisfy
%
%         y = f + e,    where e ~ N(0, s^2)
%
%    where f is an unknown underlying function. A zero mean Gaussian
%    process prior is assumed for f
%
%         f ~ N(0, K),
%
%    where K is the covariance matrix whose elements are given by one of
%    the following six covariance function:
%
%    - constant + linear
%    - costant + sexp for 1. input + linear for 2. input
%    - sexp for 1. input + sexp for 2. input
%    - sexp
%    - neural network for 1. input + neural network for 2. input
%    - neural network
%
%    A prior is assumed for parameters of the covariance functions,
%    and the inference is done with a MAP estimate for parameter
%    values.
%
%    For more detailed discussion of  covariance functions, see e.g.
%
%    Rasmussen, C. E. and Williams, C. K. I. (2006). Gaussian
%    Processes for Machine Learning. The MIT Press.
%
%
%  See also
%    DEMO_REGRESSION1
%
% Copyright (c) 2010 Jaakko Riihimäki, Aki Vehtari

% 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.

% REGRESSION TOY DATA
% Create an example regression data
x=rand(225,2)*2-1;
y=3*norm_cdf(2*x(:,2))+2*norm_cdf(4*x(:,1));
% add some noise
y=y+randn(size(y))*0.25;
y=y-mean(y);
[n, nin] = size(x);
% create equally spaced points to visualise the predictions:
[xt1,xt2]=meshgrid(-2:0.1:2,-2:0.1:2);
xt=[xt1(:) xt2(:)];
nxt=size(xt1,1);

% Assume a Student-t distribution for the GP parameters
pt = prior_t('nu', 4, 's2', 10);	% a prior structure

% Create a Gaussian noise model
lik = lik_gaussian('sigma2', 0.2^2);

% Set a small amount of jitter
jitter=1e-4;

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);

% CONSTANT + LINEAR COVARIANCE FUNCTION
disp('Constant + linear covariance function')
% constant covariance function
gpcf_c = gpcf_constant('constSigma2', 1, 'constSigma2_prior', pt);
% linear covariance function
gpcf_l = gpcf_linear('coeffSigma2_prior', pt);
gp = gp_set('lik', lik, 'cf', {gpcf_c gpcf_l}, 'jitterSigma2', jitter);

% Optimize with the scaled conjugate gradient method
gp=gp_optim(gp,x,y,'opt',opt);

% Compute predictions in a grid using the MAP estimate
Eft_map = gp_pred(gp, x, y, xt);

% Plot the prediction and data
figure
set(gcf, 'color', 'w')
mesh(xt1, xt2, reshape(Eft_map,nxt,nxt));
hold on
plot3(x(:,1), x(:,2), y, '*')
xlabel('x_1'), ylabel('x_2')
title('The predicted underlying function (constant + linear)');

% CONSTANT + SQUARED EXPONENTIAL COVARIANCE FUNCTION (W.R.T. THE
% FIRST INPUT DIMENSION) + LINEAR (W.R.T. THE SECOND INPUT
% DIMENSION)
fprintf(['Constant + squared exponential covariance function\n' ...
         '(w.r.t. the first input dimension) + linear (w.r.t.\n' ...
         'the second input dimension)\n'])

%Covariance function for the first input variable
gpcf_s1 = gpcf_sexp('selectedVariables', 1, 'lengthScale',0.5, ...
                    'lengthScale_prior', pt, 'magnSigma2', 0.15, ...
                    'magnSigma2_prior', pt);
% gpcf_s1 can be construted also as
%metric1 = metric_euclidean('components', {[1]}, 'lengthScale',[0.5], ...
%                           'lengthScale_prior', pt);
%gpcf_s1 = gpcf_sexp('magnSigma2', 0.15, 'magnSigma2_prior', pt, ...
%                    'metric', metric1);
%Covariance function for the second input variable
gpcf_l2 = gpcf_linear('selectedVariables', 2, 'coeffSigma2_prior', pt);
gp = gp_set('lik', lik, 'cf', {gpcf_c gpcf_s1 gpcf_l2}, 'jitterSigma2', jitter);

% Optimize with the scaled conjugate gradient method
gp=gp_optim(gp,x,y,'opt',opt);

% Compute predictions in a grid using the MAP estimate
Eft_map = gp_pred(gp, x, y, xt);

% Plot the prediction and data
figure
set(gcf, 'color', 'w')
mesh(xt1, xt2, reshape(Eft_map,nxt,nxt));
hold on
plot3(x(:,1), x(:,2), y, '*')
xlabel('x_1'), ylabel('x_2')
title('The predicted underlying function (sexp for 1. input + linear for 2. input )');

% ADDITIVE SQUARED EXPONENTIAL COVARIANCE FUNCTION
disp('Additive squared exponential covariance function')

% Covariance function for the second input variable
gpcf_s2 = gpcf_sexp('selectedVariables', 2,'lengthScale',0.5, ...
                    'lengthScale_prior', pt, 'magnSigma2', 0.15, ...
                    'magnSigma2_prior', pt);
% gpcf_s2 can be construted also as
%metric2 = metric_euclidean('components', {[2]},'lengthScale',[0.5], 'lengthScale_prior', pt);
%gpcf_s2 = gpcf_sexp('magnSigma2', 0.15, 'magnSigma2_prior', pt, 'metric', metric2);
gp = gp_set('lik', lik, 'cf', {gpcf_s1,gpcf_s2}, 'jitterSigma2', jitter);

% Optimize with the scaled conjugate gradient method
gp=gp_optim(gp,x,y,'opt',opt);

% Compute predictions in a grid using the MAP estimate
Eft_map = gp_pred(gp, x, y, xt);

% Plot the prediction and data
figure
set(gcf, 'color', 'w')
mesh(xt1, xt2, reshape(Eft_map,nxt,nxt));
hold on
plot3(x(:,1), x(:,2), y, '*')
xlabel('x_1'), ylabel('x_2')
title('The predicted underlying function (additive sexp)');

% SQUARED EXPONENTIAL COVARIANCE FUNCTION
disp('Squared exponential covariance function')

gpcf_s = gpcf_sexp('lengthScale', ones(1,nin), 'magnSigma2', 0.2^2, ...
                   'lengthScale_prior', pt, 'magnSigma2_prior', pt);
gp = gp_set('lik', lik, 'cf', {gpcf_s}, 'jitterSigma2', jitter);

% Optimize with the scaled conjugate gradient method
gp=gp_optim(gp,x,y,'opt',opt);

% Compute predictions in a grid using the MAP estimate
Eft_map = gp_pred(gp, x, y, xt);

% Plot the prediction and data
figure
set(gcf, 'color', 'w')
mesh(xt1, xt2, reshape(Eft_map,nxt,nxt));
hold on
plot3(x(:,1), x(:,2), y, '*')
xlabel('x_1'), ylabel('x_2')
title('The predicted underlying function (sexp)');

% ADDITIVE NEURAL NETWORK COVARIANCE FUNCTION
disp('Additive neural network covariance function');

gpcf_nn1 = gpcf_neuralnetwork('weightSigma2', 1, 'biasSigma2', 1, 'selectedVariables', [1], ...
                              'weightSigma2_prior', pt, 'biasSigma2_prior', pt);
gpcf_nn2 = gpcf_neuralnetwork('weightSigma2', 1, 'biasSigma2', 1, 'selectedVariables', [2], ...
                              'weightSigma2_prior', pt, 'biasSigma2_prior', pt);
gp = gp_set('lik', lik, 'cf', {gpcf_nn1,gpcf_nn2}, 'jitterSigma2', jitter);

% Optimize with the scaled conjugate gradient method
gp=gp_optim(gp,x,y,'opt',opt);

% Compute predictions in a grid using the MAP estimate
Eft_map = gp_pred(gp, x, y, xt);

% Plot the prediction and data
figure
set(gcf, 'color', 'w')
mesh(xt1, xt2, reshape(Eft_map,nxt,nxt));
hold on
plot3(x(:,1), x(:,2), y, '*')
xlabel('x_1'), ylabel('x_2')
title('The predicted underlying function (additive neural network)');

% NEURAL NETWORK COVARIANCE FUNCTION
disp('Neural network covariance function')

gpcf_nn = gpcf_neuralnetwork('weightSigma2', ones(1,nin), 'biasSigma2', 1, ...
                             'weightSigma2_prior', pt, 'biasSigma2_prior', pt);
gp = gp_set('lik', lik, 'cf', {gpcf_nn}, 'jitterSigma2', jitter);

% Optimize with the scaled conjugate gradient method
gp=gp_optim(gp,x,y,'opt',opt);

% Compute predictions in a grid using the MAP estimate
Eft_map = gp_pred(gp, x, y, xt);

% Plot the prediction and data
figure
set(gcf, 'color', 'w')
mesh(xt1, xt2, reshape(Eft_map,nxt,nxt));
hold on
plot3(x(:,1), x(:,2), y, '*')
xlabel('x_1'), ylabel('x_2')
title('The predicted underlying function (neural network)');


function outsig=rampsignal(insig,varargin)
%RAMPSIGNAL  Ramp signal
%   Usage: outsig=rampsignal(insig,L);
%
%   `rampsignal(insig,L)` applies a ramp function of length *L* to the
%   beginning and the end of the input signal. The default ramp is a
%   sinusoide starting from zero and ending at one (also known as a cosine
%   squared ramp).
%
%   If *L* is scalar, the starting and ending ramps will be of the same
%   length. If *L* is a vector of length 2, the first entry will be used
%   for the rising ramp, and the second for the falling.
%
%   If the input is a matrix or an N-D array, the ramp will be applied
%   along the first non-singleton dimension.
%
%   `rampsignal(insig)` will use a ramp length of half the signal.
%
%   `rampsignal(insig,L,wintype)` will use another window for ramping. This
%   may be any of the window types from |firwin|. Please see the help on
%   |firwin| for more information. The default is to use a piece of the
%   Hann window.
%
%   `rampsignal` accepts the following optional parameters:
%
%     'dim',d   Apply the ramp along dimension d. The default value of []
%               means to use the first non-singleton dimension.
%
%   See also: rampdown, rampsignal, firwin

definput.import={'firwin'};
definput.keyvals.dim=[];
definput.keyvals.L=[];
[flags,kv]=ltfatarghelper({'L','dim'},definput,varargin);

[insig,L,Ls,W,dim,permutedsize,order]=assert_sigreshape_pre(insig,[],kv.dim,'RAMPSIGNAL');
% Note: Meaning of L has changed, it is now the length of the signal.

switch numel(kv.L)
 case 0
  L1=L/2;
  L2=L/2;
 case 1
  L1=kv.L;
  L2=kv.L;
 case 2
  L1=kv.L(1);
  L2=kv.L(2);
 otherwise
  error('%s: The length must a scalar or vector.',upper(mfilename));
end;

if rem(L1,1)~=0 || rem(L2,1)~=0
  error('The length of the ramp must be an integer.');
end;

if L<L1+L2
  error(['%s: The length of the input signal must be greater than the length of the ramps ' ...
         'combined.'],upper(mfilename));
end;

r1=rampup(L1,flags.wintype);
r2=rampdown(L2,flags.wintype);

ramp=[r1;ones(L-L1-L2,1);r2];

% Apply the ramp
for ii=1:W
  insig(:,ii)=insig(:,ii).*ramp;
end;

outsig=assert_sigreshape_post(insig,dim,permutedsize,order);


function precision = precision_table ( rule )

%*****************************************************************************80
%
%% PRECISION_TABLE returns the precision of a Lebedev rule.
%
%  Modified:
%
%    15 September 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Vyacheslav Lebedev, Dmitri Laikov,
%    A quadrature formula for the sphere of the 131st
%    algebraic order of accuracy,
%    Russian Academy of Sciences Doklady Mathematics,
%    Volume 59, Number 3, 1999, pages 477-481.
%
%  Parameters:
%
%    Input, integer RULE, the index of the rule, between 1 and 65.
%
%    Output, integer PRECISION, the precision of the rule.
%
  rule_max = 65;

  table = [ ...
      3,   5,   7,   9,  11,  13,  15,  17,  19,  21, ...
     23,  25,  27,  29,  31,  33,  35,  37,  39,  41, ...
     43,  45,  47,  49,  51,  53,  55,  57,  59,  61, ...
     63,  65,  67,  69,  71,  73,  75,  77,  79,  81, ...
     83,  85,  87,  89,  91,  93,  95,  97,  99, 101, ...
    103, 105, 107, 109, 111, 113, 115, 117, 119, 121, ...
    123, 125, 127, 129, 131 ]';

  if ( rule < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PRECISION_TABLE - Fatal error!\n' );
    fprintf ( 1, '  RULE < 1.\n' );
    error ( 'PRECISION_TABLE - Fatal error!' );
  elseif ( rule_max < rule )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PRECISION_TABLE - Fatal error!\n' );
    fprintf ( 1, '  RULE_MAX < RULE.\n' );
    error ( 'PRECISION_TABLE - Fatal error!' );
  end

  precision = table(rule);

  return
end


%% Bubble sort algorithm:
function list = bubble_sort(list)
% function to sort vector 'list' with using the 'Bubble sort' algorithm
% INPUT: 'list' array
% OUTPUT: sorted array
changed = true;
count = numel(list);
while(changed)
    changed = false;
    count = count - 1;
    for index = (1:count)
        if(list(index) > list(index+1))
            list([index index+1]) = list([index+1 index]); %swap
            changed = true;
        end

    end
end
end