clear, clc;

% This is an example for running the function LogisticC
%
%  Problem:
%
%  min  f(x,c) = - weight_i * log (p_i) + 1/2 * rsL2 * ||x||_2^2
%  s.t. \|x\|_1 <=z
%
%  a_i denotes a training sample,
%      and a_i' corresponds to the i-th row of the data matrix A
%
%  y_i (either 1 or -1) is the response
%
%  p_i= 1/ (1+ exp(-y_i (x' * a_i + c) ) ) denotes the probability
%
%  weight_i denotes the weight for the i-th sample
%
% For detailed description of the function, please refer to the Manual.
%
%% Related papers
%
% [1]  Jun Liu and Jieping Ye, Efficient Euclidean Projections
%      in Linear Time, ICML 2009.
%
% [2]  Jun Liu and Jieping Ye, Sparse Learning with Efficient Euclidean
%      Projections onto the L1 Ball, Technical Report ASU, 2008.
%
% [3]  Jun Liu, Jianhui Chen, and Jieping Ye,
%      Large-Scale Sparse Logistic Regression, KDD, 2009.
%
%% ------------   History --------------------
%
% First version on August 10, 2009.
%
% September 5, 2009: adaptive line search is added
%
% For any problem, please contact Jun Liu (j.liu@asu.edu)

cd ..
cd ..

root=cd;
addpath(genpath([root '/SLEP']));
                     % add the functions in the folder SLEP to the path

% change to the original folder
cd Examples/L1;

m=1000;  n=1000;    % The data matrix is of size m x n

randNum=1;          % a random number

% ---------------------- generate random data ----------------------
randn('state',(randNum-1)*3+1);
A=randn(m,n);         % the data matrix

y=[ones(n/2,1);...
    -ones(n/2, 1)];  % the response

z=40;                % the radius of the L1 ball

%----------------------- Set optional items -----------------------
opts=[];

% Starting point
opts.init=2;        % starting from a zero point

% Termination
opts.tFlag=5;       % run .maxIter iterations
opts.maxIter=40;    % maximum number of iterations

% Normalization
opts.nFlag=0;       % without normalization

% Regularization
opts.rsL2=0;        % the squared two norm term

% Group Property
opts.sWeight=[1,1]; % set the weight for positive and negative samples

%----------------------- Run the code LogisticC -----------------------
fprintf('\n lFlag=0 \n');
opts.lFlag=0;       % Nemirovski's line search
tic;
[x1, c1,funVal1, ValueL1]= LogisticC(A, y, z, opts);
toc;

fprintf('\n lFlag=1 \n');
opts.lFlag=1;       % adaptive line search
opts.tFlag=2; opts.tol= funVal1(end);
tic;
[x2, c2, funVal2, ValueL2]= LogisticC(A, y, z, opts);
toc;

figure;
plot(funVal1,'-r');
hold on;
plot(funVal2,'--b');
legend('lFlag=0', 'lFlag=1');
xlabel('Iteration (i)');
ylabel('The objective function value');

% --------------------- compute the pathwise solutions ----------------
opts.fName='LogisticC';      % set the function name to 'LogisticC'
Z=[10, 20, 30, 40];          % set the parameters

% run the function pathSolutionLogistic
fprintf('\n Compute the pathwise solutions, please wait...');
[X,C]=pathSolutionLogistic(A, y, Z, opts);


function [ev,ee,ebound,xyp] = q1p0grid(x,y,xy,mv,bound,mbound);
%q1p0grid   Q1-P0 element grid generator
%   [ev,ee,ebound,xyp] = q1p0grid(x,y,xy,mv,bound,mbound);
%   input
%          x          x coordinate vector
%          y          y coordinate vector
%          xy         nodal coordinate vector
%          mv         Q2 macroelement mapping matrix
%          bound      boundary vertex vector
%          mbound     macroelement boundary vertex vector
%   output
%          ev         element vertex matrix
%          ee         element edge connection matrix
%          ebound     element boundary edge matrix
%          xyp        vertex coordinate vector
%
%   IFISS function: DJS; 28 February 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
xx=xy(:,1); yy=xy(:,2); nvtx=length(xx);
adj=sparse(nvtx,nvtx);
mel=length(mv(:,1)); nel=4*mel;
ev=zeros(nel,4);
%
%% loop over macroelements
k=1:mel;
% first element
ke=4*k-3;
ev(ke,1)=mv(k,1);
ev(ke,2)=mv(k,5);
ev(ke,3)=mv(k,9);
ev(ke,4)=mv(k,8);
% second element
ke=4*k-2;
ev(ke,1)=mv(k,5);
ev(ke,2)=mv(k,2);
ev(ke,3)=mv(k,6);
ev(ke,4)=mv(k,9);
% third element
ke=4*k-1;
ev(ke,1)=mv(k,9);
ev(ke,2)=mv(k,6);
ev(ke,3)=mv(k,3);
ev(ke,4)=mv(k,7);
% fourth element
ke=4*k;
ev(ke,1)=mv(k,8);
ev(ke,2)=mv(k,9);
ev(ke,3)=mv(k,7);
ev(ke,4)=mv(k,4);
%
%% define element edges
ect=1;
% bottom boundary edges
k1=find(mbound(:,2)==1)';
for k=mbound(k1)
   ebound(ect,1)=4*k-3; ebound(ect+1,1)=4*k-2;
   ebound(ect,2)=1    ; ebound(ect+1,2)=1;
   ect=ect+2;
end
% right boundary edges
k2=find(mbound(:,2)==2)';
for k=mbound(k2)
   ebound(ect,1)=4*k-2; ebound(ect+1,1)=4*k-1;
   ebound(ect,2)=2    ; ebound(ect+1,2)=2;
   ect=ect+2;
end
% top boundary edges
k3=find(mbound(:,2)==3)';
for k=mbound(k3)
   ebound(ect,1)=4*k-1; ebound(ect+1,1)=4*k;
   ebound(ect,2)=3    ; ebound(ect+1,2)=3;
   ect=ect+2;
end
% left boundary edges
k4=find(mbound(:,2)==4)';
for k=mbound(k4)
   ebound(ect,1)=4*k; ebound(ect+1,1)=4*k-3;
   ebound(ect,2)=4    ; ebound(ect+1,2)=4;
   ect=ect+2;
end
%%
% centroid coordinates
for ielem=1:nel
xc(ielem)=mean(xx(ev(ielem,:))); yc(ielem)=mean(yy(ev(ielem,:)));
end
xyp=[xc',yc'];
%
%% compute edge to edge connection array ee
      np=nel;
% initialise global matrices
      adj = sparse(nvtx,nvtx);
      ee = zeros(nel,4);
%
% evaluate element number on each edge in turn
% and assemble into adjacency matrix
%% nx= 0, ny=-1
		 adj=adj + sparse(ev(:,1),ev(:,2),1:np,nvtx,nvtx);
%% nx= 1, ny= 0
		 adj=adj + sparse(ev(:,2),ev(:,3),1:np,nvtx,nvtx);
%% nx= 0, ny= 1
		 adj=adj + sparse(ev(:,3),ev(:,4),1:np,nvtx,nvtx);
%% nx=-1, ny= 0
		 adj=adj + sparse(ev(:,4),ev(:,1),1:np,nvtx,nvtx);
%
       for el=1:nel
		   [ii,jj]=find(adj==el);
           ee(el,:)=diag(adj(jj,ii))';
		   end
           ee=ee(:,[2,4,3,1]);
%
% plotting of the grid
%
%if mel <=64,
	adj=sparse(nvtx,nvtx);
    for i=1:nel
	adj(ev(i,1),ev(i,2)) =1;
	adj(ev(i,2),ev(i,3)) =1;
	adj(ev(i,3),ev(i,4)) =1;
	adj(ev(i,4),ev(i,1)) =1;
    end
    figure(30)
    gplot(adj,xy,'b')
    axis('square')
    hold on
    adj=sparse(nvtx,nvtx);
    k1=find(ebound(:,2)==1);
    for k=1:length(k1)
    kk=ebound(k1(k));
    adj(ev(kk,1),ev(kk,2))=1;
    end
    k2=find(ebound(:,2)==2);
    for k=1:length(k2)
    kk=ebound(k2(k));
    adj(ev(kk,2),ev(kk,3))=1;
    end
    k3=find(ebound(:,2)==3);
    for k=1:length(k3)
    kk=ebound(k3(k));
    adj(ev(kk,3),ev(kk,4))=1;
    end
    k4=find(ebound(:,2)==4);
    for k=1:length(k4)
    kk=ebound(k4(k));
    adj(ev(kk,4),ev(kk,1))=1;
    end
%   gplot(adj,xy,'r')
%   axis('off')
plot(xy(:,1),xy(:,2),'ro')
xybd=xy(bound,:);
plot(xybd(:,1),xybd(:,2),'ko')
plot(xyp(:,1),xyp(:,2),'k*')
hold off
drawnow
title('Q1-P0 finite element subdivision')
%end
return


function y = trace_inv( varargin )

% TRACE_INV   Trace of the inverse of a PSD matrix.
%     For square matrix X, TRACE_INV(X) is TRACE(INV(X)) if X is Hermitian
%     or symmetric and positive definite; and +Inf otherwise.
%
%     An error results if X is not a square matrix.
%
%     Disciplined convex programming information:
%         TRACE_INV is convex and nonmonotonic (at least with respect to
%         elementwise comparison), so its argument must be affine.

persistent P
if isempty( P ),
    P.nargs     = 1;
    P.args      = [];
    P.empty     = 0;
    P.constant  = @trace_inv_diag;
    P.diagonal  = @trace_inv_diag;
    P.affine    = @trace_inv_aff;
    P.structure = 'psdeig';
end
y = cvx_matrix_op( P, varargin );

function z = trace_inv_diag( D )
z = sum( 1.0 ./ D );

function z = trace_inv_aff( X ) %#ok
cvx_begin sdp
    epigraph variable z nonnegative_
    variable Y(size(X)) hermitian_if(X)
    real(trace(Y)) <= z;
    [Y,eye(size(X));eye(size(X)),X] >= 0; %#ok
cvx_end

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function [label, model, L] = vbgm(X, init, prior)
% Perform variational Bayesian inference for Gaussian mixture.
%   X: d x n data matrix
%   init: k (1 x 1) or label (1 x n, 1<=label(i)<=k) or center (d x k)
% Reference: Pattern Recognition and Machine Learning by Christopher M. Bishop (P.474)
% Written by Michael Chen (sth4nth@gmail.com).

fprintf('Variational Bayesian Gaussian mixture: running ... \n');
[d,n] = size(X);
if nargin < 3
    prior.alpha = 1;
    prior.kappa = 1;
    prior.m = mean(X,2);
    prior.v = d+1;
    prior.M = eye(d);   % M = inv(W)
end
tol = 1e-20;
maxiter = 2000;
L = -inf(1,maxiter);
converged = false;
t = 1;

model.R = initialization(X,init);
while  ~converged && t < maxiter
    t = t+1;
    model = vmax(X, model, prior);
    model = vexp(X, model);
    L(t) = vbound(X,model,prior)/n;
    converged = abs(L(t)-L(t-1)) < tol*abs(L(t));
end
L = L(2:t);
label = zeros(1,n);
[~,label(:)] = max(model.R,[],2);
[~,~,label] = unique(label);
if converged
    fprintf('Converged in %d steps.\n',t-1);
else
    fprintf('Not converged in %d steps.\n',maxiter);
end

function R = initialization(X, init)
[d,n] = size(X);
if length(init) == 1  % random initialization
    k = init;
    idx = randsample(n,k);
    m = X(:,idx);
    [~,label] = max(bsxfun(@minus,m'*X,dot(m,m,1)'/2),[],1);
    [u,~,label] = unique(label);
    while k ~= length(u)
        idx = randsample(n,k);
        m = X(:,idx);
        [~,label] = max(bsxfun(@minus,m'*X,dot(m,m,1)'/2),[],1);
        [u,~,label] = unique(label);
    end
    R = full(sparse(1:n,label,1,n,k,n));
elseif size(init,1) == 1 && size(init,2) == n  % initialize with labels
    label = init;
    k = max(label);
    R = full(sparse(1:n,label,1,n,k,n));
elseif size(init,1) == d  %initialize with only centers
    k = size(init,2);
    m = init;
    [~,label] = max(bsxfun(@minus,m'*X,dot(m,m,1)'/2),[],1);
    R = full(sparse(1:n,label,1,n,k,n));
else
    error('ERROR: init is not valid.');
end
% Done
function model = vmax(X, model, prior)
alpha0 = prior.alpha;
kappa0 = prior.kappa;
m0 = prior.m;
v0 = prior.v;
M0 = prior.M;
R = model.R;

nk = sum(R,1); % 10.51
alpha = alpha0+nk; % 10.58
nxbar = X*R;
kappa = kappa0+nk; % 10.60
m = bsxfun(@times,bsxfun(@plus,kappa0*m0,nxbar),1./kappa); % 10.61
v = v0+nk; % 10.63

[d,k] = size(m);
M = zeros(d,d,k);
sqrtR = sqrt(R);

xbar = bsxfun(@times,nxbar,1./nk); % 10.52
xbarm0 = bsxfun(@minus,xbar,m0);
w = (kappa0*nk./(kappa0+nk));
for i = 1:k
    Xs = bsxfun(@times,bsxfun(@minus,X,xbar(:,i)),sqrtR(:,i)');
    xbarm0i = xbarm0(:,i);
    M(:,:,i) = M0+Xs*Xs'+w(i)*(xbarm0i*xbarm0i'); % 10.62
end

model.alpha = alpha;
model.kappa = kappa;
model.m = m;
model.v = v;
model.M = M; % Whishart: M = inv(W)
% Done
function model = vexp(X, model)
alpha = model.alpha; % Dirichlet
kappa = model.kappa;   % Gaussian
m = model.m;         % Gasusian
v = model.v;         % Whishart
M = model.M;         % Whishart: inv(W) = V'*V

n = size(X,2);
[d,k] = size(m);

logW = zeros(1,k);
EQ = zeros(n,k);
for i = 1:k
    U = chol(M(:,:,i));
    logW(i) = -2*sum(log(diag(U)));
    Q = (U'\bsxfun(@minus,X,m(:,i)));
    EQ(:,i) = d/kappa(i)+v(i)*dot(Q,Q,1);    % 10.64
end

ElogLambda = sum(psi(0,bsxfun(@minus,v+1,(1:d)')/2),1)+d*log(2)+logW; % 10.65
Elogpi = psi(0,alpha)-psi(0,sum(alpha)); % 10.66

logRho = (bsxfun(@minus,EQ,2*Elogpi+ElogLambda-d*log(2*pi)))/(-2); % 10.46
logR = bsxfun(@minus,logRho,logsumexp(logRho,2)); % 10.49
R = exp(logR);

model.logR = logR;
model.R = R;
% Done
function L = vbound(X, model, prior)
alpha0 = prior.alpha;
kappa0 = prior.kappa;
m0 = prior.m;
v0 = prior.v;
M0 = prior.M;

alpha = model.alpha; % Dirichlet
kappa = model.kappa;   % Gaussian
m = model.m;         % Gasusian
v = model.v;         % Whishart
M = model.M;         % Whishart: inv(W) = V'*V
R = model.R;
logR = model.logR;

[d,k] = size(m);
nk = sum(R,1); % 10.51

Elogpi = psi(0,alpha)-psi(0,sum(alpha));

Epz = dot(nk,Elogpi);
Eqz = dot(R(:),logR(:));
logCalpha0 = gammaln(k*alpha0)-k*gammaln(alpha0);
Eppi = logCalpha0+(alpha0-1)*sum(Elogpi);
logCalpha = gammaln(sum(alpha))-sum(gammaln(alpha));
Eqpi = dot(alpha-1,Elogpi)+logCalpha;
L = Epz-Eqz+Eppi-Eqpi;

U0 = chol(M0);
sqrtR = sqrt(R);
xbar = bsxfun(@times,X*R,1./nk); % 10.52

logW = zeros(1,k);
trSW = zeros(1,k);
trM0W = zeros(1,k);
xbarmWxbarm = zeros(1,k);
mm0Wmm0 = zeros(1,k);
for i = 1:k
    U = chol(M(:,:,i));
    logW(i) = -2*sum(log(diag(U)));

    Xs = bsxfun(@times,bsxfun(@minus,X,xbar(:,i)),sqrtR(:,i)');
    V = chol(Xs*Xs'/nk(i));
    Q = V/U;
    trSW(i) = dot(Q(:),Q(:));  % equivalent to tr(SW)=trace(S/M)
    Q = U0/U;
    trM0W(i) = dot(Q(:),Q(:));

    q = U'\(xbar(:,i)-m(:,i));
    xbarmWxbarm(i) = dot(q,q);
    q = U'\(m(:,i)-m0);
    mm0Wmm0(i) = dot(q,q);
end

ElogLambda = sum(psi(0,bsxfun(@minus,v+1,(1:d)')/2),1)+d*log(2)+logW; % 10.65
Epmu = sum(d*log(kappa0/(2*pi))+ElogLambda-d*kappa0./kappa-kappa0*(v.*mm0Wmm0))/2;
logB0 = v0*sum(log(diag(U0)))-0.5*v0*d*log(2)-logmvgamma(0.5*v0,d);
EpLambda = k*logB0+0.5*(v0-d-1)*sum(ElogLambda)-0.5*dot(v,trM0W);

Eqmu = 0.5*sum(ElogLambda+d*log(kappa/(2*pi)))-0.5*d*k;
logB =  -v.*(logW+d*log(2))/2-logmvgamma(0.5*v,d);
EqLambda = 0.5*sum((v-d-1).*ElogLambda-v*d)+sum(logB);

EpX = 0.5*dot(nk,ElogLambda-d./kappa-v.*trSW-v.*xbarmWxbarm-d*log(2*pi));

L = L+Epmu-Eqmu+EpLambda-EqLambda+EpX;


function value = year_length_coptic ( y )

%*****************************************************************************80
%
%% YEAR_LENGTH_COPTIC returns the number of days in a Coptic year.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 September 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y, the year to be checked.
%
%    Output, integer VALUE, the number of
%    days in the year.
%
  if ( year_is_leap_coptic ( y ) )
    value = 366;
  else
    value = 365;
  end

  return
end


function pass = test_jacobian( pref )
% Test Jacobian

if ( nargin == 0 )
    pref = chebfunpref;
end
tol = 100*pref.cheb2Prefs.chebfun2eps;

% Check definition:
F = chebfun2v(@(x,y) cos(x), @(x,y) sin(y));
Fx = diffx(F);
Fy = diffy(F);
jacF = Fx(1).*Fy(2) - Fx(2).*Fy(1);

pass(1) = ( norm(jacF - jacobian(F) ) < tol );

end


function [QAM_BER, QAM_SER] = QAM_Simulate(SNRs, varargin)

% Run M_QAM_Model.mdl to generate Monte Carlo simulation results for
% QAM signals over AWGN channels

if nargin>1
    simLines = varargin{1};
end

open_system('M_QAM_Model')
maxNumBits = 1e7;
maxNumErrs = 100;
Ts = 1e-6;

% SNRs = -4:28;
QAM_BER = zeros(9,length(SNRs));
QAM_SER = zeros(9,length(SNRs));

S = simset('SrcWorkspace','current', 'DstWorkspace','current');
k=1;
for M = [4, 8, 16, 32, 64, 128, 256, 512, 1024]
    for EbNo = SNRs
        % Don't try to simulate BER < 1e-5 (too long!)
        tBER = berawgn(EbNo,'qam',M);
        if (tBER>1e-4)
            fprintf('Simulating %i-QAM, %idB, ', M, EbNo)
            sim('M_QAM_Model',[], S)
            QAM_BER(k,EbNo+5) = BER(1);
            QAM_SER(k,EbNo+5) = SER(1);
            fprintf('BER=%e, SER=%e\n', BER(1), SER(1))
            % Add the result to the plot if it exists
            if nargin>1
                set(simLines(k),'YData',QAM_BER(k,:))
            end
        end
    end
    drawnow
    k=k+1;
end
close_system('M_QAM_Model')


function e = rmModelSearchFit_twoGaussianDoGfixed(p,Y,Xv,Yv,stim,t,sigmaRatio,betaRatioAlpha)
% rmModelSearchFit_twoGaussianDoGfixed - actual fit function of rmSearchFit
%
% error = rmModelSearchFit(_twoGaussianDoGfixed(p,Y,trends,Xgrid,YGrid,stimulusMatrix);
%
% Basic barebones fit of a single time-series. Error is returned in
% percentage: 100% is RSS of unfitted time-series. This way we can quantify
% the improvement of the fit independend of the variation in the raw
% time-series.
%
% 2006/06 SOD: wrote it.
% 2006/12 SOD: modifications for fmincon, this is litterally called >10000
% times so we cut every corner possible.
% 2009/12 SOD & WZ: adapted for dog fixed model

% make RF (taken from rfGaussian2d)
Xv = Xv - p(1);   % positive x0 moves center right
Yv = Yv - p(2);   % positive y0 moves center up
RF = exp( (Yv.*Yv + Xv.*Xv) ./ (-2.*(p(3).^2)) );

% make surround
%s2 = p(3).*sigmaRatio;
[tmp eccentricity] = cart2pol(p(1), p(2));
s2 = p(3).*sigmaRatio(1) + eccentricity.*sigmaRatio(2) + sigmaRatio(3);
RF2 = exp( (Yv.*Yv + Xv.*Xv) ./ (-2.*(s2.^2)) );

% full pRF
betaRatio = (p(3)./s2).^betaRatioAlpha;
RF = RF - betaRatio.*RF2;

% make prediction (taken from rfMakePrediction)
X = [stim*RF t];

% fit - inlining pinv
%b = pinv(X)*Y;
[U,S,V] = svd(X,0);
s = diag(S);
tol = numel(X) * eps(max(s));
r = sum(s > tol);
if (r == 0)
    pinvX = zeros(size(X'));
else
    s = diag(ones(r,1)./s(1:r));
    pinvX = V(:,1:r)*s*U(:,1:r)';
end
b = pinvX*Y;

% compute residual sum of squares (e)
% e = norm(Y - X*abs(b));
if b(1)>0,
    e = norm(Y - X*b);
else
    e = norm(Y).*(1+sum(abs(b(1))));
end
return;


function [sm,pro]=oper(A,B)

% This function computes the
% sum and the product of 2 matrices

sm=A+B;

pro=A*B;

% book : Signals and Systems Laboratory with MATLAB
% authors : Alex Palamides & Anastasia Veloni


function [f,g] = hs71F(x)

f = x(1)*x(4)*sum(x(1:3)) + x(3);

if(nargout > 1)
    g = [ x(1)*x(4) + x(4)*sum(x(1:3))
                    x(1)*x(4)
                    x(1)*x(4) + 1
                    x(1)*sum(x(1:3)) ];
end


function newImg = dtiResliceVolume(img, xform, boundingBox, mmPerVoxOut)
%
% newImg = dtiResliceVolume(img, xform, boundingBox, mmPerVoxOut)
%
% HISTORY:
%   2004.01.13 RFD (bob@white.stanford.edu) wrote it.

if(~exist('mmPerVoxOut') | isempty(mmPerVoxOut))
    mmPerVoxOut = [1 1 1];
end

if(~exist('boundingBox') | isempty(boundingBox))
    % create a default bounding box for the resliced data.
    % The following is the spm default bounding box. Note that the box is
    % defined in Talairach space (units = mm).
    boundingBox = [-78 -120 -60;
                    78  80   85];
end

% myCinterp3 likes [rows,columns,slices], so we need a permute here
img = double(permute(img,[2,1,3]));

x = (boundingBox(1,1):mmPerVoxOut(1):boundingBox(2,1));
y = (boundingBox(1,2):mmPerVoxOut(2):boundingBox(2,2));
z = (boundingBox(1,3):mmPerVoxOut(3):boundingBox(2,3));
[X,Y,Z] = meshgrid(x, y, z);
newSize = size(X);
clear x y z;
talCoords = [X(:) Y(:) Z(:)];
newSize = size(X);
clear X Y Z;

imgCoords = mrAnatXformCoords(xform, talCoords);
newImg = myCinterp3(img, [size(img,1) size(img,2)], size(img,3), imgCoords, 0.0);
newImg = squeeze(reshape(newImg,newSize));
return;


 function [kb, alpha, kb_m] = kaiser_bessel(x, J, alpha, kb_m, K_N)
%function [kb, alpha, kb_m] = kaiser_bessel(x, J, alpha, kb_m)
%function [kb, alpha, kb_m] = kaiser_bessel(x, J, 'best', 0, K_N)
%
% generalized Kaiser-Bessel function for x in support [-J/2,J/2]
% shape parameter "alpha" (default 2.34 J)
% order parameter "kb_m" (default 0)
% see (A1) in lewitt:90:mdi, JOSA-A, Oct. 1990
% in
%	x	[M,1]	arguments
% out
%	kb	[M,1]	KB function values, if x is numbers
%			or string for kernel(k,J), if x is 'string'
%			or inline function, if x is 'inline'
%	alpha
%	kb_m
%
% Copyright 2001-3-30, Jeff Fessler, The University of Michigan

% Modification 2002-10-29 by Samuel Matej
% - for Negative & NonInteger kb_m the besseli() function has
%	singular behavior at the boundaries - KB values shooting-up/down
%	(worse for small alpha) leading to unacceptable interpolators
% - for real arguments and higher/reasonable values of alpha the
%	besseli() gives similar values for positive and negative kb_m
%	except close to boundaries - tested for kb_m=-2.35:0.05:2.35
%	(besseli() gives exactly same values for integer +- kb_m)
%	=> besseli(kb_m,...) approximated by besseli(abs(kb_m),...), which
%	behaves well at the boundaries
% WARNING: it is not clear how correct the FT formula (JOSA) is
%	for this approximation (for NonInteger Negative kb_m)
% NOTE: Even for the original KB formula, the JOSA FT formula
%	is derived only for m > -1 !

% if no arguments, make example plots
if nargin < 2
	help(mfilename)
	J = 8; alpha = 2.34 * J;
	x = linspace(-(J+1)/2, (J+1)/2, 1001)';
%	x = linspace(J/2-1/4, J/2+1/4, 1001)';

	mlist = [-4 0 2 7];
	leg = {};
	for ii=1:length(mlist)
		kb_m = mlist(ii);
		yy(:,ii) = kaiser_bessel(x, J, alpha, kb_m);
		func = kaiser_bessel('inline', 0, alpha, kb_m);
		yf = func(x, J);
		if any(yf ~= yy(:,ii)),
		[yf yy(:,ii)]
		error 'bug', end
		leg{ii} = sprintf('m=%d', kb_m);
	end
	yb = kaiser_bessel(x, J, 'best', [], 2);
	plot(	x, yy(:,1), 'c-', x, yy(:,2), 'y-', ...
		x, yy(:,3), 'm-', x, yy(:,4), 'g-', x, yb, 'r--')
	leg{end+1} = 'best';
	axis tight, legend(leg)
%	axisy(0, 0.01)	% to see endpoints
	xlabel \kappa, ylabel F(\kappa)
	title(sprintf('KB functions, J=%g \\alpha=%g', J, alpha) )
return
end

if ~isvar('J'), J = 6; end
if ~isvar('alpha') | isempty('alpha'), alpha = 2.34 * J; end
if ~isvar('kb_m') | isempty('kb_m'), kb_m = 0; end

if ischar(alpha)
	[alpha kb_m] = kaiser_bessel_params(alpha, J, K_N);
end

if ischar(x)
	if ischar(alpha)
		if ~isvar('K_N'), error 'K_N required', end
		kb = 'kaiser_bessel(k, J, ''%s'', [], %g)';
		kb = sprintf(kb, alpha, K_N);
	else
		kernel_string = 'kaiser_bessel(k, J, %g, %g)';
		kb = sprintf(kernel_string, alpha, kb_m);
	end
	if streq(x, 'inline')
		kb = inline(kb, 'k', 'J');
	elseif ~streq(x, 'string')
		error '1st argument must be "inline" or "string"'
	end
return
end

%
% Warn about use of modified formula for negative kb_m
%
if (kb_m < 0) & ((abs(round(kb_m)-kb_m)) > eps)
	persistent warned
	if isempty(warned)	% only print this reminder the first time
		printf('\nWarning: Negative NonInt kb_m=%g in kaiser_bessel()', kb_m)
		printf('	- using modified definition of KB function\n')
		warned = 1;
	end
end

kb_m_bi = abs(kb_m);		% modified "kb_m" as described above
ii = abs(x) < J/2;
f = sqrt(1 - (x(ii)/(J/2)).^2);
denom = besseli(kb_m_bi,alpha);
if ~denom
	printf('m=%g alpha=%g', kb_m, alpha)
end
kb = zeros(size(x));
kb(ii) = f.^kb_m .* besseli(kb_m_bi, alpha*f) / denom;
kb = reale(kb);

%
% optimized shape and order parameters
%
function [alpha, kb_m] = kaiser_bessel_params(alpha, J, K_N)
if streq(alpha, 'best')
	if K_N ~= 2
		warning 'kaiser_bessel optimized only for K/N=2'
		printf('using good defaults: m=0 and alpha = 2.34*J')
		kb_m = 0;
		alpha = 2.34 * J;
	else
		kb_m = 0;	% hardwired, because it was nearly the best!
		try
			s = 'private/kaiser,m=0';
			s = load(s);
			ii = find(J == s.Jlist);
			if isempty(ii)
				ii = imin(abs(J - s.Jlist));
				warning(sprintf('J=%d not found, using %d', ...
					J, s.Jlist(ii)))
			end
			alpha = J * s.abest.zn(ii);
		catch
			warning(['could not open file "' s '" so using default alpha = 2.34 J which should be fine.'])
			alpha = 2.34 * J;
		end
	end
else
	error 'unknown alpha mode'
end


function [x, mx, sx] = standardise(x, dim, lim)

% STANDARDISE computes the zscore of a matrix along dimension dim
% has similar functionality as the stats-toolbox's zscore function
%
% Use as
%   x = standardise(x, dim)
%
% See also ZSCORE

% Copyright (C) 2009, Jan-Mathijs Schoffelen
%
% 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/>.
%
% $Id$

if nargin == 1,
  dim = find(size(x)>1,1,'first');
end

if nargin == 3,
  ft_error('third input argument is not used');
end

switch dim
case 1
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(ones(1,n),:,:,:,:,:,:,:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(ones(1,n),:,:,:,:,:,:,:);
case 2
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,ones(1,n),:,:,:,:,:,:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,ones(1,n),:,:,:,:,:,:);
case 3
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,:,ones(1,n),:,:,:,:,:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,:,ones(1,n),:,:,:,:,:);
case 4
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,:,:,ones(1,n),:,:,:,:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,:,:,ones(1,n),:,:,:,:);
case 5
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,:,:,:,ones(1,n),:,:,:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,:,:,:,ones(1,n),:,:,:);
case 6
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,:,:,:,:,ones(1,n),:,:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,:,:,:,:,ones(1,n),:,:);
case 7
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,:,:,:,:,:,ones(1,n),:);
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,:,:,:,:,:,ones(1,n),:);
case 8
  n  = size(x,dim);
  mx = mean(x,dim);
  x  = x-mx(:,:,:,:,:,:,:,ones(1,n));
  sx = sqrt(sum(abs(x).^2,dim)./n);
  x  = x./sx(:,:,:,:,:,:,:,ones(1,n));
otherwise
  ft_error('dim too large, standardise currently supports dimensionality up to 8');
end


 function [err, sn, T1] = nufft1_err_mm(om, N1, J1, K1, type, alpha, beta)
%function [err, sn, T1] = nufft1_err_mm(om, N1, J1, K1, type, alpha, beta)
% Compute worst-case error for each input frequency for min-max 1D NUFFT.
% in:
%	om	[M,1]	digital frequency omega in radians
%	N1		signal length
%	J1		# of neighbors used per frequency location
%	K1		FFT size (should be > N1)
%	type		'sinc' 'diric' 'qr'
%	alpha	[L,1]	Fourier series coefficients of scaling factors
%			trick: or, "sn" if length N1
%	beta		scale gamma=2pi/K by this in Fourier series
%			typically is K/N (me) or 0.5 (Liu)
% out:
%	err	[M,1]	worst-case error over unit-norm signals
%	sn	[N,1]	scaling factors corresponding to alpha,beta
%	T1	[J,J]	T matrix
%
% Copyright 2001-12-7, Jeff Fessler, The University of Michigan

% if no arguments, give an example
if nargin < 4
	help(mfilename)
	N = 100; K = 2*N; gam = 2*pi/K;
	J = 14;
	om = gam * linspace(0,1,101);
	[alpha, beta, ok] = nufft_best_alpha(J, 2, K/N);
	if ~ok, alpha = []; beta = 0.5; end
	errd = nufft1_err_mm(om, N, J, K, 'diric');
	errs = nufft1_err_mm(om, N, J, K, 'sinc');
	errq = nufft1_err_mm(om, N, J, K, 'qr');
	semilogy(om/gam, errs, 'g-x', om/gam, errd, 'y-+', om/gam, errq, 'c-o')
	xlabel '\omega / \gamma', ylabel 'E_{max}(\omega)'
	legend('Tr sinc', 'Tr diric', 'QR approach')
return
end

if ~isvar('type') | isempty(type),	type = 'sinc'; end
if ~isvar('alpha') | isempty(alpha)
	alpha = [1];	% default Fourier series coefficients of scaling factors
end
if ~isvar('beta') | isempty(beta)
	beta = 0.5;	% default is Liu version for now
end

use_qr = logical(0);
if streq(type, 'sinc')
	use_true_diric = logical(0);
elseif streq(type, 'diric')
	use_true_diric = logical(1);
elseif streq(type, 'qr')
	use_qr = logical(1);
else
	error 'unknown type'
end

%
% see if 'best' alpha is desired
%
if ischar(alpha)
	if streq(alpha, 'uniform')
		alpha = [1];
		beta = 0.5;
	else
		if streq(alpha, 'best')
			L = 0;
		elseif streq(alpha, 'best,L=1')
			L = 1;
		elseif streq(alpha, 'best,L=2')
			L = 2;
		else
			error 'unknown alpha argument'
		end
		[alpha, beta, ok] = nufft_best_alpha(J1, L, K1/N1);
		if ~ok
			tmp = 'optimal alpha unknown for J=%d, K/N=%g, L=%d';
			warning(sprintf(tmp, J1, K1/N1, L))
			sn = ones(N1,1);
			err = nan;
			return
		end
	end
end

%
% if requested, return corresponding scaling factors too
%
if length(alpha) == N1	% trick: special way to give explicit sn's
	sn = alpha;
	if ~use_qr, error 'give sn only allowed for QR version', end
elseif nargout > 1 | use_qr
	sn = nufft_scale(N1, K1, alpha, beta);
end

%
% QR approach to error
%
if use_qr
	n = [0:N1-1]' - (N1-1)/2;
	[nn, jj] = ndgrid(n, 1:J1);
	gam1 = 2*pi/K1;
	C = exp(i * gam1 * nn .* jj) / sqrt(N1);
	S = spdiag(sn);
	A = S' * C;
	[Q,R] = qr(S' * C, 0);	% [N,J] compact QR decomposition

	do = col(om - gam1*nufft_offset(om, J1, K1));
	Db = exp(i * n * do') / sqrt(N1);	% [N,M]
	err = Db - Q * (Q' * Db);
	err = sqrt(sum(abs(err).^2,1))';	% [M]
return
end

tol = 0;
T1 = nufft_T(N1, J1, K1, tol, alpha, beta, use_true_diric);	% [J,J]
r1 = nufft_r(om, N1, J1, K1, alpha, beta, use_true_diric);	% [J,M]

%
% worst-case error at each frequency
%
Tr1 = T1 * r1;			% [J,M]
err = sum(conj(r1) .* Tr1).';	% [M,1]
err = min(real(err), 1);
err = sqrt(1 - err);		% caution: this "1 -" may cause numerical error


function [out,Wc,Wo] = hankelsv(SYS)
%HANKELSV Compute Hankel singular values and grammians.
%
% [OUT,Wc,Wo] = HANKELSV(SYS) computes controllability and observability
%    grammians Wc, Wo, and the Hankel singular values OUT of an LTI
%    model SYS (created with either TF, ZPK, SS, or FRD). The model
%    SYS can be either continuous-time or discrete-time. However, only
%    in continuous-time case that SYS is allowed to be unstable.
%    The computed Hankel singular values are sorted in ascending order.
%
%    For unstable continuous-time system, state-space stable/anti-stable
%    decomposition is used instead, and OUT=[OUT_stable;OUT_anti-stable].
%    In addition, Wc={Wc_stable,Wc_anti-stable} and Wo is either.

%    The former version of HKSV employs an obsolete fashion in using the
%    Matlab function GRAM, i.e., instead of using GRAM(SYS,'c') and
%    GRAM(SYS,'o'), it uses GRAM(A,B) and GRAM(A',C'), respectively.
%    This restricts the computation of gramians to continuous-time case,
%    only, since GRAM(A,B) and GRAM(A',C') solve LYAP, not DLYAP.
%
%    This improved version also correct some other bugs in the former
%    version, for example, HKSV does not return gramians when SYS is
%    unstable, but not anti-stable.

%    Developer: Wathanyoo Khaisongkram
%    Date Developed: Oct 20, 2004
%    Email: sunboom15@yahoo.com
%    Improved version of HKSV by R. Y. Chiang & M. G. Safonov March, 1986
% -----------------------------------------------------------------------

SYS=ss(SYS);                            % convert to state-space model

% Discrete-time LTI model
if get(SYS,'Ts')~=0                     % discrete-time LTI model
   if max(abs(pole(SYS))) > 1           % unstable discrete system
      error('For discrete LTI model, system must be stable')
   end
   Wc = gram(SYS,'c');                  % controllability matrix
   Wo = gram(SYS,'o');                  % observability matrix
   out = sqrt(eig(Wc*Wo));              % Hankel singular values
   [no_use,index] = sort(out);          % index for sorting
   out = out(index);                    % sorted singular values
   return                               % end function
end

% Continuous-time LTI model
[A,B,C,D]=ssdata(SYS);                  % extract the system matrices
   mode = eig(A);                       % the eigen values of 'a'
   nrow = size(A,1);                    % the number of rows in 'a'
   nsta = length(find(real(mode) < 0)); % the number of unstable modes
if isequal(nsta,nrow),                  % completely stable
   Wc = gram(SYS,'c');                  % controllability matrix
   Wo = gram(SYS,'o');                  % observability matrix
   out = sqrt(eig(Wc*Wo));              % Hankel singular values
   [no_use,index] = sort(out);          % index for sorting
   out = out(index);                    % sorted singular values
elseif isequal(nsta,0),                 % completely unstable
   SYS=ss(-A,-B,C,D,SYS);               % change the dynamic and the input matrices to '-a' and '-b',
                                        % respectively with all LTI properties inherited from
                                        % original SYS, e.g., discrete or continuous domain.
   Wc = gram(SYS,'c');                  % controllability matrix
   Wo = gram(SYS,'o');                  % observability matrix
   out = sqrt(eig(Wc*Wo));              % Hankel singular values
   [no_use,index] = sort(out);          % index for sorting
   out = out(index);                    % sorted singular values
else, % 0 < nsta < nrow
   [SYSs,SYSu] = stabproj(SYS);         % decompose stable/anti-stable parts
   % Stable part
   Wcs = gram(SYSs,'c');                % controllability matrix
   Wos = gram(SYSs,'o');                % observability matrix
   outl = sqrt(eig(Wcs*Wos));           % Hankel singular values1
   [no_use,index] = sort(outl);         % index for sorting
   outl = outl(index);                  % sorted singular values
   % Anti-stable part
   [Au,Bu,Cu,Du]=ssdata(SYSu);          % obtain the system matrices of SYSu
   SYSu=ss(-Au,-Bu,Cu,Du,SYSu);         % change the dynamic and the input matrices to '-ar' and '-br'.
   Wcu = gram(SYSu,'c');                % controllability matrix
   Wou = gram(SYSu,'o');                % observability matrix
   outr = sqrt(eig(Wcu*Wou));           % Hankel singular values
   [no_use,index] = sort(outr);         % index for sorting
   outr = outr(index);                  % sorted singular values
   out = [outl;outr];                   % gather two cases
   Wc={Wcs,Wcu};                        % controllability gramian
   Wo={Wos,Wou};                        % observability gramian
end

% end of HKSV_MOD


%% (Internal) Design a filter to downsample signals prior printing to a report
%
%   b = design_downsample_filter( downsample_factor )
%
% Arguments:
%
%      + downsample_factor: times to downsample signal
%
% Output:
%
%      + b: filter coefficients
%
% Example:
%
% Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar
% Version: 0.1 beta
% Last update: 14/5/2014
% Birthdate  : 21/4/2015
% Copyright 2008-2015
%
function b = design_downsample_filter( downsample_factor )
% MATLAB Code
% Generated by MATLAB(R) 8.2 and the Signal Processing Toolbox 6.20.
% Generated on: 23-Jun-2014 10:45:52

% FIR least-squares Lowpass filter designed using the FIRLS function.

% All frequency values are normalized to 1.

N     = 60;   % Order
Fpass = 1/downsample_factor;  % Passband Frequency
Fstop = min(1, Fpass + 0.1);  % Stopband Frequency
Wpass = 1;    % Passband Weight
Wstop = 100;  % Stopband Weight

% Calculate the coefficients using the FIRLS function.
b  = firls(N, [0 Fpass Fstop 1], [1 1 0 0], [Wpass Wstop]);

% [EOF]


classdef ZXH_CF14 < PROBLEM
% <multi/many> <real> <large/none> <constrained>
% Constrained benchmark MOP proposed by Zhou, Xiang, and He

%------------------------------- Reference --------------------------------
% Y. Zhou, Y. Xiang, and X. He, Constrained multiobjective optimization:
% Test problem construction and performance evaluations, IEEE Transactions
% on Evolutionary Computation, 2021, 25(1): 172-186.
%------------------------------- 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
        k;  % Number of constrained variables
    end
    methods
        %% Default settings of the problem
        function Setting(obj)
            if isempty(obj.M); obj.M = 2; end
            if isempty(obj.D); obj.D = obj.M+10;  end
            obj.lower    = zeros(1,obj.D) + 1e-10;
            obj.upper    = ones(1,obj.D)  - 1e-10;
            obj.encoding = ones(1,obj.D);
            if obj.M <= 3
                obj.k = obj.M - 1;
            elseif obj.M > 3 && obj.M <= 8
                obj.k = floor(obj.M/2);
            else
                obj.k = 3;
            end
        end
        %% Evaluate multiple solutions
        function Population = Evaluation(obj,varargin)
            PopDec = varargin{1};
            OptX   = 0.2;
            [N,D]  = size(PopDec);
            M      = obj.M;
            % Step 1: Compute cumsum
            Sx = cumsum(PopDec(:,1:M).^2,2,'reverse');
            % Step 2: Compute theta
            THETA = 2/pi*atan(sqrt(Sx(:,2:end))./PopDec(:,1:M-1));
            % Step 3: Calculate Ackley function
            h = 20 - 20 * exp(-0.2 * sqrt(sum((PopDec(:,M+1:end)-OptX).^2,2)/(D-M))) + exp (1) - exp(sum(cos(2 * pi .*(PopDec(:,M+1:end)-OptX)),2)/(D-M));
            % Step 4: Compute T_
            T = (1 - Sx(:,1)).^2 + h;
            % Step 5: Objectives (linear)
            G      = [ones(N,1) cumprod(THETA,2)] .* [1-THETA ones(N,1)];
            PopObj = G .* repmat((1+T),1,M);
            % Step 6: Constraints
            PopCon(:,1) = Sx(:,1) + h - 1;
            PopCon(:,2) = -(Sx(:,1) + h - 1/4);
            for i = 1 : obj.k
                PopCon(:,i+2) = min(min(THETA(:,i)-1/10,4/5-THETA(:,i)),max(2/5-THETA(:,i),THETA(:,i)-7/10));
            end
            Population = SOLUTION(varargin{1},PopObj,PopCon,varargin{2:end});
            obj.FE     = obj.FE + length(Population);
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            R = UniformPoint(N,obj.M);
            T = zeros(size(R));
            for i = obj.M-1 : -1 : 1
                T(:,i) = R(:,i+1)./R(:,i)./(1-T(:,i+1)+R(:,i+1)./R(:,i));
            end
            THETA = T(:,1:obj.k);
            Valid = all(THETA<=1/10|THETA>=2/5&THETA<=7/10|THETA>=4/5,2);
            R     = R(Valid,:);
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            if obj.M == 2
                R = obj.GetOptimum(100);
            elseif obj.M == 3
                a = linspace(0,1,30)';
                R = {a*a',a*(1-a'),(1-a)*ones(size(a'))};
                T2 = R{3}./R{2}./(1+R{3}./R{2});
                T1 = R{2}./(1-T2);
                THETA = cat(3,T1,T2);
                Valid = all(THETA<=1/10|THETA>=2/5&THETA<=7/10|THETA>=4/5,3);
                R{1}(~Valid) = nan;
            else
                R = [];
            end
        end
    end
end


function [ quasi, seed ] = i4_sobol ( dim_num, seed )

%*****************************************************************************80
%
%% I4_SOBOL generates a new quasirandom Sobol vector with each call.
%
%  Discussion:
%
%    The routine adapts the ideas of Antonov and Saleev.
%
%    Thanks to Francis Dalaudier for pointing out that the range of allowed
%    values of DIM_NUM should start at 1, not 2!  17 February 2009.
%
%    This function was modified to use PERSISTENT variables rather than
%    GLOBAL variables, 13 December 2009.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 March 2012
%
%  Author:
%
%    Original FORTRAN77 version by Bennett Fox.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Antonov, Saleev,
%    USSR Computational Mathematics and Mathematical Physics,
%    Volume 19, 1980, pages 252 - 256.
%
%    Paul Bratley, Bennett Fox,
%    Algorithm 659:
%    Implementing Sobol's Quasirandom Sequence Generator,
%    ACM Transactions on Mathematical Software,
%    Volume 14, Number 1, pages 88-100, 1988.
%
%    Bennett Fox,
%    Algorithm 647:
%    Implementation and Relative Efficiency of Quasirandom
%    Sequence Generators,
%    ACM Transactions on Mathematical Software,
%    Volume 12, Number 4, pages 362-376, 1986.
%
%    Ilya Sobol,
%    USSR Computational Mathematics and Mathematical Physics,
%    Volume 16, pages 236-242, 1977.
%
%    Ilya Sobol, Levitan,
%    The Production of Points Uniformly Distributed in a Multidimensional
%    Cube (in Russian),
%    Preprint IPM Akad. Nauk SSSR,
%    Number 40, Moscow 1976.
%
%  Parameters:
%
%    Input, integer DIM_NUM, the number of spatial dimensions.
%    DIM_NUM must satisfy 1 <= DIM_NUM <= 40.
%
%    Input/output, integer SEED, the "seed" for the sequence.
%    This is essentially the index in the sequence of the quasirandom
%    value to be generated.  On output, SEED has been set to the
%    appropriate next value, usually simply SEED+1.
%    If SEED is less than 0 on input, it is treated as though it were 0.
%    An input value of 0 requests the first (0-th) element of the sequence.
%
%    Output, real QUASI(DIM_NUM), the next quasirandom vector.
%
  persistent atmost;
  persistent dim_max;
  persistent dim_num_save;
  persistent initialized;
  persistent lastq;
  persistent log_max;
  persistent maxcol;
  persistent poly;
  persistent recipd;
  persistent seed_save;
  persistent v;

  if ( isempty ( initialized ) )
    initialized = 0;
    dim_num_save = -1;
  end

  if ( ~initialized | dim_num ~= dim_num_save )

    initialized = 1;

    dim_max = 40;
    dim_num_save = -1;
    log_max = 30;
    seed_save = -1;
%
%  Initialize (part of) V.
%
    v(1:dim_max,1:log_max) = zeros(dim_max,log_max);

    v(1:40,1) = [ ...
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
      1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]';

    v(3:40,2) = [ ...
            1, 3, 1, 3, 1, 3, 3, 1, ...
      3, 1, 3, 1, 3, 1, 1, 3, 1, 3, ...
      1, 3, 1, 3, 3, 1, 3, 1, 3, 1, ...
      3, 1, 1, 3, 1, 3, 1, 3, 1, 3 ]';

    v(4:40,3) = [ ...
               7, 5, 1, 3, 3, 7, 5, ...
      5, 7, 7, 1, 3, 3, 7, 5, 1, 1, ...
      5, 3, 3, 1, 7, 5, 1, 3, 3, 7, ...
      5, 1, 1, 5, 7, 7, 5, 1, 3, 3 ]';

    v(6:40,4) = [ ...
                     1, 7, 9,13,11, ...
      1, 3, 7, 9, 5,13,13,11, 3,15, ...
      5, 3,15, 7, 9,13, 9, 1,11, 7, ...
      5,15, 1,15,11, 5, 3, 1, 7, 9 ]';

    v(8:40,5) = [ ...
                           9, 3,27, ...
     15,29,21,23,19,11,25, 7,13,17, ...
      1,25,29, 3,31,11, 5,23,27,19, ...
     21, 5, 1,17,13, 7,15, 9,31, 9 ]';

    v(14:40,6) = [ ...
              37,33, 7, 5,11,39,63, ...
     27,17,15,23,29, 3,21,13,31,25, ...
      9,49,33,19,29,11,19,27,15,25 ]';

    v(20:40,7) = [ ...
                                         13, ...
     33,115, 41, 79, 17, 29,119, 75, 73,105, ...
      7, 59, 65, 21,  3,113, 61, 89, 45,107 ]';

    v(38:40,8) = [ ...
                                7, 23, 39 ]';
%
%  Set POLY.
%
    poly(1:40)= [ ...
        1,   3,   7,  11,  13,  19,  25,  37,  59,  47, ...
       61,  55,  41,  67,  97,  91, 109, 103, 115, 131, ...
      193, 137, 145, 143, 241, 157, 185, 167, 229, 171, ...
      213, 191, 253, 203, 211, 239, 247, 285, 369, 299 ];

    atmost = 2^log_max - 1;
%
%  Find the number of bits in ATMOST.
%
    maxcol = i4_bit_hi1 ( atmost );
%
%  Initialize row 1 of V.
%
    v(1,1:maxcol) = 1;

  end
%
%  Things to do only if the dimension changed.
%
  if ( dim_num ~= dim_num_save )
%
%  Check parameters.
%
    if ( dim_num < 1 | dim_max < dim_num )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'I4_SOBOL - Fatal error!\n' );
      fprintf ( 1, '  The spatial dimension DIM_NUM should satisfy:\n' );
      fprintf ( 1, '    1 <= DIM_NUM <= %d\n', dim_max );
      fprintf ( 1, '  But this input value is DIM_NUM = %d\n', dim_num );
      return
    end

    dim_num_save = dim_num;
%
%  Initialize the remaining rows of V.
%
    for i = 2 : dim_num
%
%  The bits of the integer POLY(I) gives the form of polynomial I.
%
%  Find the degree of polynomial I from binary encoding.
%
      j = poly(i);
      m = 0;

      while ( 1 )

        j = floor ( j / 2 );

        if ( j <= 0 )
          break;
        end

        m = m + 1;

      end
%
%  Expand this bit pattern to separate components of the logical array INCLUD.
%
      j = poly(i);
      for k = m : -1 : 1
        j2 = floor ( j / 2 );
        includ(k) = ( j ~= 2 * j2 );
        j = j2;
      end
%
%  Calculate the remaining elements of row I as explained
%  in Bratley and Fox, section 2.
%
      for j = m + 1 : maxcol
        newv = v(i,j-m);
        l = 1;
        for k = 1 : m
          l = 2 * l;
          if ( includ(k) )
            newv = bitxor ( newv, l * v(i,j-k) );
          end
        end
        v(i,j) = newv;
      end
    end
%
%  Multiply columns of V by appropriate power of 2.
%
    l = 1;
    for j = maxcol-1 : -1 : 1
      l = 2 * l;
      v(1:dim_num,j) = v(1:dim_num,j) * l;
    end
%
%  RECIPD is 1/(common denominator of the elements in V).
%
    recipd = 1.0 / ( 2 * l );

    lastq(1:dim_num) = 0;

  end

  seed = floor ( seed );

  if ( seed < 0 )
    seed = 0;
  end

  if ( seed == 0 )

    l = 1;
    lastq(1:dim_num) = 0;

  elseif ( seed == seed_save + 1 )
%
%  Find the position of the right-hand zero in SEED.
%
    l = i4_bit_lo0 ( seed );

  elseif ( seed <= seed_save )

    seed_save = 0;
    l = 1;
    lastq(1:dim_num) = 0;

    for seed_temp = seed_save : seed - 1
      l = i4_bit_lo0 ( seed_temp );
      for i = 1 : dim_num
        lastq(i) = bitxor ( lastq(i), v(i,l) );
      end
    end

    l = i4_bit_lo0 ( seed );

  elseif ( seed_save + 1 < seed )

    for seed_temp = seed_save + 1 : seed - 1
      l = i4_bit_lo0 ( seed_temp );
      for i = 1 : dim_num
        lastq(i) = bitxor ( lastq(i), v(i,l) );
      end
    end

    l = i4_bit_lo0 ( seed );

  end
%
%  Check that the user is not calling too many times!
%
  if ( maxcol < l )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4_SOBOL - Fatal error!\n' );
    fprintf ( 1, '  Too many calls!\n' );
    fprintf ( 1, '  MAXCOL = %d\n', maxcol );
    fprintf ( 1, '  L =      %d\n', l );
    return
  end
%
%  Calculate the new components of QUASI.
%
  for i = 1 : dim_num
    quasi(i) = lastq(i) * recipd;
    lastq(i) = bitxor ( lastq(i), v(i,l) );
  end

  seed_save = seed;
  seed = seed + 1;

  return
end


function [f,p,r] = compute_f(T,H)

  if length(T) ~= length(H),
    size(T)
    size(H)
  end;

  N = length(T);
  numT = 0;
  numH = 0;
  numI = 0;
  for n=1:N,
    Tn = (T(n+1:end))==T(n);
    Hn = (H(n+1:end))==H(n);
    numT = numT + sum(Tn);
    numH = numH + sum(Hn);
    numI = numI + sum(Tn .* Hn);
  end;
  p = 1;
  r = 1;
  f = 1;
  if numH > 0,
    p = numI / numH;
  end;
  if numT > 0,
    r = numI / numT;
  end;
  if (p+r) == 0,
    f = 0;
  else
    f = 2 * p * r / (p + r);
  end;


		% Se sterge spatiul de lucru
clear;
        % Stabilirea numarului de necunoscute
N=1000;
        % Se genereaza matricea coeficientilor (a)
a=rand(N);
		% Se incarca vectorul termenilor liberi b
b=randn(N,1);
        % Setarea cronometrului
t0=cputime;
        % Se rezolva sistemul de ecuatii liniare cu prima metoda prezentata
x1=a\b;
        % Se calculeaza timpul de calcul necesar
t1=cputime-t0;
        % Setarea cronometrului
t0=cputime;
        % Se rezolva sistemul de ecuatii liniare cu a doua metoda prezentata
x2=inv(a)*b;
        % Se calculeaza timpul de calcul necesar
t2=cputime-t0;
        % Se afiseaza timpii de calcul
disp('Timp de calcul metoda 1:'); disp(t1');
disp('Timp de calcul metoda 2:'); disp(t2');


function val = m01Q1001(F10, F01)
%------------------------------------------------------------------------------
%
% Integrates interpolated gridfunction {F10 U F01} times y,
% interpolation is assumed piecewise constant.
% The result corresponds to a first order moment.
%
% See also: m01
%
% Design and implementation by:
% Dr. Paul M. de Zeeuw <Paul.de.Zeeuw@cwi.nl>  http://homepages.cwi.nl/~pauldz/
% Last Revision: December 12, 2000.
%  2000 Stichting CWI, Amsterdam
%------------------------------------------------------------------------------
[hx, hy] = Q1001gridfdims(F10, F01);
Qhxy = 2 * hx * hy;
%
[F10ycp, F01ycp] = Q1001ycpowp(F10, F01, 1, 0.0);
val = sum(sum( F10ycp.*F10 ));
clear F10ycp;
%
val = (val + sum(sum( F01ycp.*F01 ))) * Qhxy;
clear F01ycp;
%------------------------------------------------------------------------------


function [beta_gibbs omega_gibbs F_gibbs L_gibbs phi_gibbs sigma_gibbs lambda_t_gibbs sigma_t_gibbs sbar]=tvbvar2gibbs(G,sigmahat,T,chi,psi,kappa,betahat,q,n,It,Bu,I_tau,I_om,H,Xbar,y,alpha0,yt,Xbart,upsilon0,f0,delta0,gamma,pick,pickf)

% preliminary elements for the algorithm
% compute the product G'*I_gamma*G (to speed up computations of deltabar)
GIG=G'*I_om*G;
% set tau as a large value
tau=10000;
% set omega as a large value
om=5;
% compute psibar
chibar=(chi+T)/2;
% compute alphabar
kappabar=T+kappa;
% compute alphabar
alphabar=T+alpha0;

% initiate the Gibbs sampler
% initiate the counting of iterations
count=1;
pickcount=1;
% initiate the record matrices and cells
beta_gibbs=[];
omega_gibbs=[];
F_gibbs=[];
L_gibbs=[];
phi_gibbs=[];
sigma_gibbs=[];
lambda_t_gibbs={};
sigma_t_gibbs={};

% step 1: determine initial values for the algorithm

% initial value for B
B=kron(ones(T,1),betahat);
% initial value Omega
omega=diag(diag(betahat*betahat'));
% invert Omega
invomega=diag(1./diag(omega));
% initial value for f_2,...,f_n
% obtain the triangular factorisation of sigmahat
[Fhat Lambdahat]=bear.triangf(sigmahat);
% obtain the inverse of Fhat
[invFhat]=bear.invltod(Fhat,n);
% create the cell storing the different vectors of invF
Finv=cell(n,1);
% store the vectors
for ii=2:n
    Finv{ii,1}=invFhat(ii,1:ii-1);
end
% initial values for L_1,...,L_n
L=zeros(T,n);
% initial values for phi_1,...,phi_n
phi=ones(1,n);
% initiate invsigmabar
invsigmabar=sparse(kron(eye(T),inv(sigmahat)));

% step 2: determine the sbar values and Lambda
sbar=diag(Lambdahat);
Lambda=sparse(diag(sbar));

% step 3: recover the series of initial values for lambda_1,...,lambda_T and sigma_1,...,sigma_T
lambda_t=repmat(diag(sbar),1,1,T);
sigma_t=repmat(sigmahat,1,1,T);

hbar = bear.parfor_progressbar(It,'Progress of the Gibbs sampler');  %create the progress bar

% run the Gibbs sampler
while count<=It
    % count

    hbar.iterate(1);   % update progress by one iteration

    % step 4: draw B
    invomegabar=H'*kron(I_tau,invomega)*H+Xbar'*invsigmabar*Xbar;
    % compute the choleski of invomegabar
    C=chol(bear.nspds(invomegabar),'Lower');
    % compute temporary value
    temp=Xbar'*invsigmabar*y;
    % smoothing phase: solve by back substitution
    temp1=C\temp;
    % smoothing phase: solve by forward substitution
    Bbar=C'\temp1;
    % simulation phase:
    B=Bbar+C'\randn(q*T,1);
    % reshape
    Beta=reshape(B,q,T);

    % step 5: draw omega from its posterior
    % compute the summ
    summ=(1/tau)*Beta(:,1)*Beta(:,1)';
    for ii=2:T
        summ=summ+(Beta(:,ii)-Beta(:,ii-1))*(Beta(:,ii)-Beta(:,ii-1))';
    end
    summ=diag(summ);
    % obtain Qbar
    psibar=summ+psi;
    % draw omega
    omega=diag(arrayfun(@bear.igrandn,kron(ones(q,1),chibar),psibar));
    % invert it for next iteration
    invomega=diag(1./diag(omega));

    % step 6: draw the series f_2,...,f_n from their conditional posteriors
    % recover first the residuals
    for jj=1:T
        epst(:,:,jj)=yt(:,:,jj)-Xbart{jj,1}*Beta(:,jj);
    end
    % then draw the vectors in turn
    for jj=2:n
        % first compute the summations required for upsilonbar and fbar
        summ1=zeros(jj-1,jj-1);
        summ2=zeros(jj-1,1);
        % run the summation
        for kk=1:T
            prodt=epst(1:jj-1,1,kk)*exp(-L(kk,jj));
            summ1=summ1+prodt*epst(1:jj-1,1,kk)';
            summ2=summ2+prodt*epst(jj,1,kk)';
        end
        summ1=(1/sbar(jj,1))*summ1;
        summ2=(-1/sbar(jj,1))*summ2;
        % then obtain the inverse of upsilon0
        invupsilon0=diag(1./diag(upsilon0{jj,1}));
        % obtain upsilonbar
        invupsilonbar=summ1+invupsilon0;
        C=chol(bear.nspd(invupsilonbar));
        invC=C\speye(jj-1);
        upsilonbar=full(invC*invC');
        % recover fbar
        fbar=upsilonbar*(summ2+invupsilon0*f0{jj,1});
        % finally draw f_i^(-1)
        Finv{jj,1}=fbar+chol(bear.nspd(upsilonbar),'lower')*randn(jj-1,1);
    end
    % recover the inverse of F
    invF=eye(n);
    for jj=2:n
        invF(jj,1:jj-1)=Finv{jj,1};
    end
    % eventually recover F
    F=bear.invltod(invF,n);
    % then update sigma
    sigma=F*Lambda*F';

    % step 7: draw the series phi_1,...,phi_n from their conditional posteriors
    % draw the parameters in turn
    for jj=1:n
        % estimate deltabar
        deltabar=L(:,jj)'*GIG*L(:,jj)+delta0;
        % draw the value phi_i
        phi(1,jj)=bear.igrandn(alphabar/2,deltabar/2);
    end

    % step 8: draw the series lambda_i,t from their conditional posteriors, i=1,...,n and t=1,...,T
    % consider variables in turn
    for jj=1:n
        % consider periods in turn
        for kk=1:T
            % a candidate value will be drawn from N(lambdabar,phibar)
            % the definitions of lambdabar and phibar varies with the period, thus define them first
            % if the period is the first period
            if kk==1
                lambdabar=(gamma*L(2,jj))/(1/om+gamma^2);
                phibar=phi(1,jj)/(1/om+gamma^2);
                % if the period is the final period
            elseif kk==T
                lambdabar=gamma*L(T-1,jj);
                phibar=phi(1,jj);
                % if the period is any period in-between
            else
                lambdabar=(gamma/(1+gamma^2))*(L(kk-1,jj)+L(kk+1,jj));
                phibar=phi(1,jj)/(1+gamma^2);
            end
            % now draw the candidate
            cand=lambdabar+phibar^0.5*randn;
            % compute the acceptance probability
            prob=bear.mhprob2(jj,cand,L(kk,jj),sbar(jj,1),epst(:,1,kk),Finv{jj,1});
            % draw a uniform random number
            draw=rand;
            % keep the candidate if the draw value is lower than the prob
            if draw<=prob
                L(kk,jj)=cand;
                % if not, just keep the former value
            end
        end
    end
    % then recover the series of matrices lambda_t and sigma_t
    for jj=1:T
        lambda_t(:,:,jj)=diag(sbar).*diag(exp(L(jj,:)));
        sigma_t(:,:,jj)=F*lambda_t(:,:,jj)*F';
    end

    % record phase
    % if the burn-in sample phase is not yet over
    if count<=Bu
        % simply add 1 to the iteration count
        count=count+1;
        % on the other hand, if the burn-in sample phase is over
    elseif count>Bu
        % adding one iteration to the count will depend on wether post-burn selection applies
        % if there is no post burn selection
        if pick==0
            % record the results
            beta_gibbs(:,count-Bu)=B;
            omega_gibbs(:,count-Bu)=diag(omega);
            F_gibbs(:,:,count-Bu)=F;
            L_gibbs(:,:,count-Bu)=L;
            phi_gibbs(count-Bu,:)=phi;
            sigma_gibbs(:,count-Bu)=sigma(:);
            for jj=1:T
                lambda_t_gibbs{jj,1}(:,:,count-Bu)=lambda_t(:,:,jj);
                sigma_t_gibbs{jj,1}(:,:,count-Bu)=sigma_t(:,:,jj);
            end
            % then add one to the count
            count=count+1;
            % if there is post burn selection, only one draw over 'fpick' draws will be retained
        elseif pick==1
            % if the iteration does not correspond to fpick, don't record the results, don't increase the regular count, but do increase pickcount by 1, and do record the acceptance rate of the Metropolis-Hastings step
            if pickcount~=pickf
                pickcount=pickcount+1;
                % on the other hand, if the iteration does correspond to fpick
            elseif pickcount==pickf
                % do record the results
                beta_gibbs(:,count-Bu)=B;
                omega_gibbs(:,count-Bu)=diag(omega);
                F_gibbs(:,:,count-Bu)=F;
                L_gibbs(:,:,count-Bu)=L;
                phi_gibbs(count-Bu,:)=phi;
                sigma_gibbs(:,count-Bu)=sigma(:);
                for jj=1:T
                    lambda_t_gibbs{jj,1}(:,:,count-Bu)=lambda_t(:,:,jj);
                    sigma_t_gibbs{jj,1}(:,:,count-Bu)=sigma_t(:,:,jj);
                end
                % then increase the regular count by 1 and re-initialise pickcount
                count=count+1;
                pickcount=1;
            end
        end
    end
end
close(hbar);   %close progress bar

% turn beta_gibbs into cell
beta_gibbs=mat2cell(beta_gibbs,repmat(q,T,1),It-Bu);


function   IM=subplane(Z)
%SUBtract selected PLANE, or remove slope (detilt) from data matrix
%
%Call:
%           IM=subplane(Z)
%Input:
%           Z = (double) data matrix
%Output:
%           IM = Z - plane     (the SUBtracted PLANE is defined by manually selected points)
%
%Vassili Pastushenko	March	2005
%==============================
%figure;
imagesc(Z);
shg
set(gca,'fontsize',15)
%select at least three (x,y) points which define a plane in 3D
title('Click at least three coplanar points')
[x,y]=getpts(gca);

if numel(x)<3,
    title('More points please');
    [xx,yy]=getpts(gca);
    x=[x;xx];y=[y;yy];
end

x=round(x);
y=round(y);
PONT=numel(x);
ZIN=ones(PONT,1);
M=[x y ZIN];
for i=1:PONT
ZIN(i)=Z(y(i),x(i));
end

V=M\ZIN;
[VY,VX]=size(Z);
[X,Y]=meshgrid(1:VX,1:VY);
BAS=V(1)*X+V(2)*Y+V(3);
IM=Z-BAS;
imagesc(IM);
title('Detilted data')
shg


% File c:\M_files\shortcuts\rtdbimod.m
% mca of rtd circuit using pre-screened (bi-modal) inputs;
% uses MATLAB function G2a.m
% Revised and updated 3/10/04
% Since this is a DC circuit, SS arrays A,B,D,E are not used.
clc;clear
% Component values
R1=4.53;R2=34.8;R3=132;R4=9.09;R5=9.09;E1=5;
R6=4.53;R7=27.4;R8=20;R9=20;RT=1.915;
Nom=[R1 R2 R3 R4 R5 R6 R7 R8 R9 RT E1];
Vo=G2a(Nom);
%
% "Real world" tolerances
%
Tinit=0.001;Tlife=0.002;ppm=1e-6;
TC1=50*ppm;TC2=25*ppm;
Thi=Tinit+Tlife+35*TC1;Tlo=-Tinit-Tlife-80*TC1;
Trhi=8.1*1e-4;Trlo=-Trhi;Trefhi=0.02+35*TC2;
Treflo=-0.02-80*TC2;
%
p=1:9;T(1,p)=Tlo;T(2,p)=Thi;
T(1,10)=Trlo;T(2,10)=Trhi;T(1,11)=Treflo;T(2,11)=Trefhi;
%
Nk=10000; % Number of Monte Carlo samples
%
Nc=length(Nom); % Number of components
nb=30; % Number of bins in histograms
Ng=50; % Number of point in ideal Gaussian curve
randn('state',sum(100*clock)); % randomize normal RNG seed
Yn=zeros(Nk,Nc);sp=0.5; % sp is 1/2 of gap width
Rn=zeros(Nk,Nc);
% Get tolerance constants independent of samples k
p=1:Nc;tr1=(T(2,:)-T(1,:))/6;tr2=T(1,:)+1;
%
for w=1:Nc
	k=0;
	while k < Nk
		z=randn;
		if (z<-sp)|(z>sp) % accept only rv's outside of -sp to +sp gap
			k=k+1; % next rv
			Yn(k,w)=z; % store in Yn array
		end
	end
end
for k=1:Nk
   Rn(k,:)=Nom.*(tr1.*(Yn(k,:)+3)+tr2);
   Vm(k)=G2a(Rn(k,:));
end
%
% get Nc input histograms
%
for p=1:Nc
	Vav(p)=mean(Yn(:,p));
	Vsd(p)=3*std(Yn(:,p));
	hin(p,:)=hist(Yn(:,p),nb)/Nk;
	VL1(p)=min(Yn(:,p));VH1(p)=max(Yn(:,p));
	intv1(p)=(VH1(p)-VL1(p))/nb;
	q=1:nb;bin1(p,q)=VL1(p)+intv1(p)*(q-1);
end
%
% get output histogram
%
Vs=std(Vm);Vavg=mean(Vm);
hout=hist(Vm,nb)/Nk;VL2=min(Vm);VH2=max(Vm);
intv2=(VH2-VL2)/nb;
q=1:nb;bin2(q)=VL2+intv2*(q-1);
% Ideal Gaussian curve
intvn2=(VH2-VL2)/Ng;
c1=intv2/(Vs*sqrt(2*pi));
for q=1:Ng
   x1(q)=intvn2*(q-1)+VL2;
   y1(q)=c1*exp((-(x1(q)-Vavg)^2/(2*Vs^2)));
end
%
Vhi2=Vavg+Vs;Vlo2=Vavg-Vs;
Vsr=sprintf('%2.3f\n',3*Vs);Vavgr=sprintf('%2.3f\n',Vavg);
%
subplot(2,1,1)
set(gca,'FontSize',8);
bar(bin1(1,:),hin(1,:),1,'y');
%stairs(bin1(1,:),hin(1,:),'k');
%hold on
%stairs(bin1(2,:),hin(2,:),'b');stairs(bin1(3,:),hin(3,:),'g');
%stairs(bin1(4,:),hin(4,:),'k');stairs(bin1(5,:),hin(5,:),'k');
%stairs(bin1(6,:),hin(6,:),'k');stairs(bin1(7,:),hin(7,:),'k');
%stairs(bin1(8,:),hin(8,:),'k');hold off;
%title('8 of 11 Pre-screened inputs');
title('1 of 11 Pre-screened inputs');
grid off
xlabel('Sigma');
axis([-4 4 0 0.2]);
%
subplot(2,1,2)
bar(bin2,hout,1,'y');
set(gca,'FontSize',[8]);
hold on
h=plot(x1-intv2/2,y1,'k');
hold off
title('RTD output');xlabel('Volts dc')
xlabel('Volts DC');
axis([4.0 4.6 0 0.15]);
text(4.1,0.1,['Vavg=',Vavgr],'FontSize',8);
text(4.1,0.08,['3s=',Vsr],'FontSize',8);
text(4.1,0.06,['Nk = ',num2str(Nk)],'FontSize',8);
%
figure(1)


% test for dictionary learning with missing data
%
%   Copyright (c) 2007 Gabriel Peyre

path(path, 'toolbox/');
name = 'barb';

% size of the image to inpaint
n0 = 200;

redun = 2;        % redundandy of the dictionary
overtraining = 30;   % over training factor

w = 8; n = w^2;
m = round( n*redun );           % number of atoms
p = round( overtraining*m );    % number of samples
% load random patches
M0 = load_image(name);
M0 = rescale( crop(M0,n0) );
% destroy pixels
Mmask = rand(size(M0))>.3;
M = M0.*Mmask;

%% input exemplar for learning
H = compute_all_patch(M,w);
Hmask = compute_all_patch(Mmask,w);
H = reshape(H, n,size(H,4));
Hmask = reshape(Hmask, n,size(Hmask,4));
s = std(H); [tmp,sel] = sort(s); sel = sel(end:-1:1);
Y = H(:,sel(1:4:end)); Y = Y(:,1:p);
Ymask = Hmask(:,sel(1:4:end)); Ymask = Ymask(:,1:p);
Y = Y ./ repmat( sqrt(sum(Y.^2,1)), n,1 );

%% dictionary learning
options.K = m; % number of atoms
options.sparse_coder = 'omp';
options.sparse_coder = 'mp';
options.nbr_max_atoms = 4;
options.niter_grad = 60;
options.lambda_grad = .01; % gradient descent step
options.mask = Ymask;
options.niter_learning = 100;
options.use_bootstrapping = 1;
[D,X,err] = perform_dictionary_learning(Y,options);

%% display learned dictionary
nb = [10 floor(m/10)]; ndim = 2;
A = display_dictionnary(D, X, nb,ndim );
clf;
imageplot(A);

%% perform inpainting
niter_inpainting = 15;
options.sparse_coder = 'mp';
M1 = M;
for i=1:40
    M1 = perform_blurring(M1,1.2);
    M1(Mmask) = M(Mmask);
end
for i=1:niter_inpainting
    progressbar(i,niter_inpainting);
    Y1 = compute_all_patch(M1,w);
    Y1 = reshape(Y1, n,size(Y1,4));
    X1 = perform_omp(D,Y1,options);
    Y1 = reshape(D*X1,[w w 1 size(Y1,2)]);
    M1 = compute_all_patch(Y1,size(M1,1));
    % impose boundary pixels
    M1(Mmask) = M(Mmask);
end

%% display result
rep = 'results/inpainting/';
if not(exist(rep))
    mkdir(rep);
end
MM = M; MM(Mmask==0) = 0;
imageplot({M0,MM,A,M1}, {'Ground trust', 'Input','Dictionary','Inpainted'}, 2,2,1);
saveas(gcf, [rep name '-inpainted.png'], 'png');


% DEMVOWELSFGPLVM3 Model the vowels data with a 2-D FGPLVM using RBF kernel and back constraints, but without PCA initialisation.

% FGPLVM

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

dataSetName = 'vowels';
experimentNo = 3;

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

% Set up model
options = fgplvmOptions('fitc');
options.back = 'mlp';
options.backOptions = mlpOptions;
options.optimiseInitBack = 0;
options.numActive = 200;
latentDim = 2;
d = size(Y, 2);

model = fgplvmCreate(latentDim, d, Y, options);

% Optimise the model.
iters = 1000;
display = 1;

model = fgplvmOptimise(model, display, iters);

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

if exist('printDiagram') & printDiagram
  lvmPrintPlot(model, lbls, dataSetName, experimentNo);
end

% Load the results and display dynamically.
lvmResultsDynamic(dataSetName, experimentNo, 'vector')

errors = lvmNearestNeighbour(model, lbls);


function [cst,cstJac] = autoGen_cst_footVel(q1p,q2p,q4p,q5p,q1m,q2m,q4m,q5m,dq1p,dq2p,dq4p,dq5p,dq1m,dq2m,dq4m,dq5m,l1,l2,l4,l5)
%AUTOGEN_CST_FOOTVEL
%    [CST,CSTJAC] = AUTOGEN_CST_FOOTVEL(Q1P,Q2P,Q4P,Q5P,Q1M,Q2M,Q4M,Q5M,DQ1P,DQ2P,DQ4P,DQ5P,DQ1M,DQ2M,DQ4M,DQ5M,L1,L2,L4,L5)

%    This function was generated by the Symbolic Math Toolbox version 6.3.
%    25-Oct-2015 18:36:52

t2 = sin(q1p);
t3 = sin(q2p);
t4 = sin(q4p);
t5 = sin(q5p);
t6 = sin(q1m);
t7 = sin(q2m);
t8 = sin(q4m);
t9 = sin(q5m);
cst = [dq1p.*l1.*t2+dq2p.*l2.*t3-dq4p.*l4.*t4-dq5p.*l5.*t5;-dq1m.*l1.*t6-dq2m.*l2.*t7+dq4m.*l4.*t8+dq5m.*l5.*t9];
if nargout > 1
    cstJac = reshape([0.0,0.0,dq1p.*l1.*cos(q1p),0.0,dq2p.*l2.*cos(q2p),0.0,0.0,0.0,-dq4p.*l4.*cos(q4p),0.0,-dq5p.*l5.*cos(q5p),0.0,l1.*t2,0.0,l2.*t3,0.0,0.0,0.0,-l4.*t4,0.0,-l5.*t5,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,-dq1m.*l1.*cos(q1m),0.0,-dq2m.*l2.*cos(q2m),0.0,0.0,0.0,dq4m.*l4.*cos(q4m),0.0,dq5m.*l5.*cos(q5m),0.0,-l1.*t6,0.0,-l2.*t7,0.0,0.0,0.0,l4.*t8,0.0,l5.*t9,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],[2,32]);
end


% DEMOILFGPLVM1 Oil data with fully independent training conditional.

% FGPLVM

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

dataSetName = 'oil';
experimentNo = 1;

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

% Set up model
options = fgplvmOptions('fitc');
options.optimiser = 'scg';
latentDim = 2;
d = size(Y, 2);

model = fgplvmCreate(latentDim, d, Y, options);

% Optimise the model.
iters = 1000;
display = 1;

model = fgplvmOptimise(model, display, iters);

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

if exist('printDiagram') & printDiagram
  lvmPrintPlot(model, lbls, dataSetName, experimentNo);
end

% Load the results and display them.
lvmScatterPlot(model, lbls);

% compute the nearest neighbours errors in latent space.
errors = lvmNearestNeighbour(model, lbls);


function writeGrid(filename, grid_size, grid_spacing, pml_size, pml_alpha, Nt, dt, c_ref)
%WRITEGRID    Write grid and PML properties to a k-Wave HDF5 file.
%
% DESCRIPTION:
%       writeGrid creates and writes the wavenumber grids and PML variables
%       required by the k-Wave C++ code to the HDF5 file specified by the
%       user.
%
%       List of parameters that are written:
%           Nx
%           Ny
%           Nz
%           Nt
%           dt
%           dx
%           dy
%           dz
%           c_ref
%           ddx_k_shift_pos_r
%           ddx_k_shift_neg_r
%           ddy_k_shift_pos
%           ddy_k_shift_neg
%           ddz_k_shift_pos
%           ddz_k_shift_neg
%           x_shift_neg_r
%           y_shift_neg_r
%           z_shift_neg_r
%           pml_x_sgx
%           pml_y_sgy
%           pml_z_sgz
%           pml_x
%           pml_y
%           pml_z
%           pml_x_alpha
%           pml_y_alpha
%           pml_z_alpha
%           pml_x_size
%           pml_y_size
%           pml_z_size
%
% USAGE:
%       writeGrid(filename, grid_size, grid_spacing, pml_size, pml_alpha, Nt, dt, c_ref)
%
% INPUTS:
%       filename            - filename and location of the input HDF5 file
%       grid_size           - [Nx, Ny, Nz]
%       grid_spacing        - [dx, dy, dz]
%       pml_size            - [pml_x_size, pml_y_size, pml_z_size]
%       pml_alpha           - [pml_x_alpha, pml_y_alpha, pml_z_alpha]
%       Nt                  - number of time points
%       dt                  - time step
%       c_ref               - scalar sound speed used in the k-space
%                             operator and to define the pml variables
%
% ABOUT:
%       author              - Bradley Treeby
%       date                - 30th May 2013
%       last update         - 21st August 2014
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox
%
% See also h5writeatt, writeAttributes, writeFlags, writeMatrix

% This file is part of k-Wave. k-Wave is free software: you can
% redistribute it and/or modify it under the terms of the GNU Lesser
% General Public License as published by the Free Software Foundation,
% either version 3 of the License, or (at your option) any later version.
%
% k-Wave is distributed in the hope that it will be useful, but WITHOUT ANY
% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
% FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
% more details.
%
% You should have received a copy of the GNU Lesser General Public License
% along with k-Wave. If not, see <http://www.gnu.org/licenses/>.

%#ok<*INUSL>
%#ok<*NASGU>

% get literals
getH5Literals;

% unpack grid size inputs to make code easier to read
Nx          = grid_size(1);
Ny          = grid_size(2);
Nz          = grid_size(3);
dx          = grid_spacing(1);
dy          = grid_spacing(2);
dz          = grid_spacing(3);
pml_x_size  = pml_size(1);
pml_y_size  = pml_size(2);
pml_z_size  = pml_size(3);
pml_x_alpha = pml_alpha(1);
pml_y_alpha = pml_alpha(2);
pml_z_alpha = pml_alpha(3);

% =========================================================================
% CREATE WAVENUMBER AND PML VECTORS
% =========================================================================

% create the wavenumber grids (assuming Nx, Ny and Nz are even)
nx = ((-Nx/2:Nx/2-1)/Nx).';
nx(floor(Nx/2) + 1) = 0;
kx_vec = (2*pi/dx).*nx;

ny = ((-Ny/2:Ny/2-1)/Ny).';
ny(floor(Ny/2) + 1) = 0;
ky_vec = (2*pi/dy).*ny;

nz = ((-Nz/2:Nz/2-1)/Nz).';
nz(floor(Nz/2) + 1) = 0;
kz_vec = (2*pi/dz).*nz;

% force the vector operators be in the correct direction (Nx, 1, 1), (1, Ny, 1), (1, 1, Nz)
ky_vec = ky_vec.';
kz_vec = permute(kz_vec, [2 3 1]);

% create vector derivative and shift variables
ddx_k_shift_pos = ifftshift( 1i*kx_vec .* exp( 1i*kx_vec*dx/2), 1);
ddx_k_shift_neg = ifftshift( 1i*kx_vec .* exp(-1i*kx_vec*dx/2), 1);
ddy_k_shift_pos = ifftshift( 1i*ky_vec .* exp( 1i*ky_vec*dy/2), 2);
ddy_k_shift_neg = ifftshift( 1i*ky_vec .* exp(-1i*ky_vec*dy/2), 2);
ddz_k_shift_pos = ifftshift( 1i*kz_vec .* exp( 1i*kz_vec*dz/2), 3);
ddz_k_shift_neg = ifftshift( 1i*kz_vec .* exp(-1i*kz_vec*dz/2), 3);

% create vector shift operators
x_shift_neg = ifftshift( exp(-1i*kx_vec*dx/2), 1);
y_shift_neg = ifftshift( exp(-1i*ky_vec*dy/2), 2);
z_shift_neg = ifftshift( exp(-1i*kz_vec*dz/2), 3);

% create reduced variables for use with real-to-complex FFT
Nx_r                    = floor(Nx/2) + 1;
Ny_r                    = floor(Ny/2) + 1;
Nz_r                    = floor(Nz/2) + 1;
ddx_k_shift_pos_r       = ddx_k_shift_pos(1:Nx_r);
ddx_k_shift_neg_r       = ddx_k_shift_neg(1:Nx_r);
x_shift_neg_r           = x_shift_neg(1:Nx_r);
y_shift_neg_r           = y_shift_neg(1:Ny_r);
z_shift_neg_r           = z_shift_neg(1:Nz_r);

% create vector PML variables
pml_x       = getPML(Nx, dx, dt, c_ref, pml_x_size, pml_x_alpha, false, 1);
pml_x_sgx   = getPML(Nx, dx, dt, c_ref, pml_x_size, pml_x_alpha, true,  1);
pml_y       = getPML(Ny, dy, dt, c_ref, pml_y_size, pml_y_alpha, false, 2);
pml_y_sgy   = getPML(Ny, dy, dt, c_ref, pml_y_size, pml_y_alpha, true,  2);
pml_z       = getPML(Nz, dz, dt, c_ref, pml_z_size, pml_z_alpha, false, 3);
pml_z_sgz   = getPML(Nz, dz, dt, c_ref, pml_z_size, pml_z_alpha, true,  3);

% cleanup unused variables
clear ddx_k_shift_pos ddx_k_shift_neg x_shift_neg y_shift_neg z_shift_neg;

% =========================================================================
% STORE FLOATS
% =========================================================================

% list of variables stored as floats
variable_names = {...
    'dt', 'dx', 'dy', 'dz', ...
    'ddx_k_shift_pos_r', 'ddx_k_shift_neg_r', 'x_shift_neg_r', ...
    'ddy_k_shift_pos',   'ddy_k_shift_neg',   'y_shift_neg_r', ...
    'ddz_k_shift_pos',   'ddz_k_shift_neg',   'z_shift_neg_r', ...
    'pml_x_sgx',   'pml_y_sgy',   'pml_z_sgz', ...
    'pml_x',       'pml_y',       'pml_z', ...
    'pml_x_alpha', 'pml_y_alpha', 'pml_z_alpha', ...
    'c_ref'};

% change float variables to be in single precision (float in C++), then
% add to HDF5 file
for index = 1:length(variable_names)

    % cast matrix to single precision
    eval([variable_names{index} ' = ' MATRIX_DATA_TYPE_MATLAB '(' variable_names{index} ');']);

    % write to HDF5 file
    writeMatrix(filename, eval(variable_names{index}), variable_names{index});

end

% =========================================================================
% STORE INTEGERS
% =========================================================================

% integer variables
variable_names = {'Nx', 'Ny', 'Nz', 'Nt',...
    'pml_x_size' , 'pml_y_size' , 'pml_z_size'};

% change all the index variables to be in 64-bit unsigned integers (long in C++)
for index = 1:length(variable_names)

    % cast matrix to 64-bit unsigned integer
    eval([variable_names{index} ' = ' INTEGER_DATA_TYPE_MATLAB '(' variable_names{index} ');']);

    % write to HDF5 file
    writeMatrix(filename, eval(variable_names{index}), variable_names{index});

end


function []=Rotor(be,th,ze)% be=[0 10 2];
% th=[0 12 8];
% ze=[0 0 0];

load NACA632_615.txt;
xy=NACA632_615;

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

rR=10;
R=100;
Spar_Loc=[2*3.5;0;2*0.3];

x=x/5-Spar_Loc(1);
y=y/5-Spar_Loc(3);
x=[x;x(1)];
y=[y;y(1)];

deg=pi/180;
b=be*deg;
t=th*deg;
z=ze*deg;

beta=inline('b1+b2*cos(psi)+b3*sin(psi)','b1','b2','b3','psi');
zeta=inline('z1+z2*cos(psi)+z3*sin(psi)','z1','z2','z3','psi');
theta=inline('t1+t2*cos(psi)+t3*sin(psi)','t1','t2','t3','psi');

psi=linspace(0,2*pi,50);
n=10;
r=linspace(0,100,n);

[rr ssi]=meshgrid(r,psi);

bbb=beta(b(1),b(2),b(3),ssi);
zzz=zeta(z(1),z(2),z(3),ssi);

xx=rr.*cos(bbb).*cos(ssi-zzz);
yy=rr.*cos(bbb).*sin(ssi-zzz);
zz=rr.*sin(bbb);

zmin=-15;
zmax=max(max(zz));

Rotor_Cone=surf(xx,yy,zz,repmat(7,size(zz)),'FaceAlpha',0);   % handle !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
set(Rotor_Cone,'Visible','off')
hold on
HP=fill( 100*cos(psi),100*sin(psi),'w' );                       % handle !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
set(HP,'FaceAlpha',0)
set(HP,'Visible','off')

TPP=fill3(xx(:,n),yy(:,n),zz(:,n),'g','FaceAlpha',0.5);         % handle !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
set(TPP,'Visible','off')

NFP=fill3( 100*cos(psi),100*sin(psi),zeros(size(psi)),'m' ,'FaceAlpha',0.5);
rotate(NFP,[1 0 0],th(2),[0 0 0])
rotate(NFP,[0 1 0],th(3),[0 0 0])
set(NFP,'Visible','off')

HP_Cross(1)=plot3([-100 100],[0 0],[0 0]);
HP_Cross(2)=plot3([0 0],[-100 100],[0 0]);
set(HP_Cross,'Color','y','Linewidth',2)
set(HP_Cross,'Visible','off')

% ############################################## Plot limits ####################################################################
xlim([-100 100])
ylim([-100 100])
zlim([zmin zmax])

[Rotor_Shaft(1) Rotor_Shaft(2) Rotor_Shaft(3)]=Cylinder( [0 0 0],2.5,zmin,'z',15,'closed' );
set(Rotor_Shaft,'FaceColor','w')
set(Rotor_Shaft,'Visible','off')

[XAXIS(1) XAXIS(2) XAXIS(3)]=arrow3d( [0 0 0.5]',0.5,90,8,'x');
[YAXIS(1) YAXIS(2) YAXIS(3)]=arrow3d( [0 0 0.5]',0.5,90,8,'y');
[ZAXIS(1) ZAXIS(2) ZAXIS(3)]=arrow3d( [0 0 0.5]',0.5,40,4,'z');

XAXIS(4)=text(110,0,0,'X','Color','r','FontSize',12);
YAXIS(4)=text(0,110,0,'Y','Color','r','FontSize',12);
ZAXIS(4)=text(0,0,zmax+10,'Z','Color','r','FontSize',12);

set(XAXIS(1),'FaceColor','k','EdgeAlpha',0)
set(XAXIS(2),'FaceColor','r')
set(XAXIS(3),'FaceColor','k')

set(YAXIS(1),'FaceColor','k','EdgeAlpha',0)
set(YAXIS(2),'FaceColor','r')
set(YAXIS(3),'FaceColor','k')

set(ZAXIS(1),'FaceColor','k','EdgeAlpha',0)
set(ZAXIS(2),'FaceColor','r')
set(ZAXIS(3),'FaceColor','k')

set(XAXIS,'Visible','off')
set(YAXIS,'Visible','off')
set(ZAXIS,'Visible','off')

PSI=0:10:360;

Targetx=100*cos(PSI*pi/180);
Targety=100*sin(PSI*pi/180);
looktarget=plot3(Targetx',zeros(size(Targetx')),Targety',Targetx',Targety',zeros(size(Targetx')),zeros(size(Targetx')),Targetx',Targety');
set(looktarget,'Visible','off')

BETA(1,:)=beta(b(1),b(2),b(3),PSI*deg);
THETA(1,:)=theta(t(1),t(2),t(3),PSI*deg);
ZETA(1,:)=zeta(z(1),z(2),z(3),PSI*deg);

tr=[t(1) t(2)-b(3) b(2)+t(3)];
br=[b(1) 0 0];
zr=z;

BETA(2,:)=beta(br(1),br(2),br(3),PSI*deg);
THETA(2,:)=theta(tr(1),tr(2),tr(3),PSI*deg);
ZETA(2,:)=zeta(zr(1),zr(2),zr(3),PSI*deg);

br=[b(1) b(2)+t(3) b(3)-t(2)];
tr=[t(1) 0 0];
zr=z;

BETA(3,:)=beta(br(1),br(2),br(3),PSI*deg);
THETA(3,:)=theta(tr(1),tr(2),tr(3),PSI*deg);
ZETA(3,:)=zeta(zr(1),zr(2),zr(3),PSI*deg);

for i=1:37;
    Blade_Disk(i,:)=Make_Blade(x,y,rR,R,PSI(i),THETA(1,i)/deg,BETA(1,i)/deg,ZETA(1,i)/deg);
    set(Blade_Disk(i,:),'Visible','off')

    a_HP(i,1)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0,['HP: \psi = ' num2str(PSI(i)) ],'Color','k','FontSize',12);
    a_HP(i,2)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0-10,['HP: \beta = ' num2str(BETA(1,i)/deg) ],'Color','r','FontSize',12);
    a_HP(i,3)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0+10,['HP: \theta = ' num2str(THETA(1,i)/deg) ],'Color','m','FontSize',12);
    a_HP(i,4)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0+20,['HP: \zeta = ' num2str(ZETA(1,i)/deg) ],'Color','b','FontSize',12);
    set(a_HP(i,:),'Visible','off')

    a_TPP(i,1)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0,['TPP: \psi = ' num2str(PSI(i))],'Color','k','FontSize',12);
    a_TPP(i,2)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0-10,['TPP: \beta = ' num2str(BETA(2,i)/deg) ],'Color','r','FontSize',12);
    a_TPP(i,3)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0+10,['TPP: \theta = ' num2str(THETA(2,i)/deg) ],'Color','m','FontSize',12);
    a_TPP(i,4)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0+20,['TPP: \zeta = ' num2str(ZETA(2,i)/deg) ],'Color','b','FontSize',12);
    set(a_TPP(i,:),'Visible','off')

    a_NFP(i,1)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0,['NFPP: \psi = ' num2str(PSI(i)) ],'Color','k','FontSize',12);
    a_NFP(i,2)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0-10,['NFPP: \beta = ' num2str(BETA(3,i)/deg) ],'Color','r','FontSize',12);
    a_NFP(i,3)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0+10,['NFPP: \theta = ' num2str(THETA(3,i)/deg) ],'Color','m','FontSize',12);
    a_NFP(i,4)=text(90*cos(PSI(i)*deg),90*sin(PSI(i)*deg),0+20,['NFPP: \zeta = ' num2str(ZETA(3,i)/deg) ],'Color','b','FontSize',12);
    set(a_NFP(i,:),'Visible','off')
end

axis equal
axis off

daspect([1 1 1])
daspect('manual')
camlookat(looktarget)
camzoom(1.5)

save para Rotor_Shaft HP TPP Rotor_Cone  HP_Cross XAXIS YAXIS ZAXIS Blade_Disk NFP a_HP a_TPP a_NFP

save looktargetfile looktarget


function [dVVectNTW] = getNTWdvVect(dVVect, rVect, vVect)
%getNTWdvVect Summary of this function goes here
%   Detailed explanation goes here
    vVect = reshape(vVect, 3,1);
    dVVect = reshape(dVVect, 3,1);

    tHat = vVect/norm(vVect);
    wHat = cross(rVect,vVect)/norm(cross(rVect,vVect));
    nHat = cross(tHat,wHat)/norm(cross(tHat,wHat));
    ECI2TWNRotMat = [tHat,wHat,nHat];
    dVVectNTW = ECI2TWNRotMat \ dVVect;
end


function [ y, symm ] = cvx_s_symmetric_ut( m, n, symm )
%CVX_S_SYMMETRIC_UT Symmetric matrices (upper triangle storage).
if m ~= n,
    error( 'Symmetric structure requires square matrices.' );
end
symm = false;
nsq = n * n;
ntr = 0.5 * ( nsq + n );
c   = 0 : n - 1;
c   = c( ones( 1, n ), : );
r   = c';
mn  = min( r, c );
mx  = max( r, c );
y   = mn + 0.5 * mx .* ( mx + 1 ) + 1;
y   = sparse( y( : ), 1 : nsq, 1, ntr, nsq );

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function Ar = sladd(A0, As, d)
%SLADD Add a sub-array along some dimensions to an array
%
% $ Syntax $
%   - Ar = sladd(A0, As)
%   - Ar = sladd(A0, As, d)
%
% $ Arguments $
%   - A0:           the original array
%   - v:            the sub-array to be added to the array
%   - Ar:           the resultant array
%   - d:            the dimension along which the vector is added
%
% $ Description $
%   - Ar = sladd(A0, As) adds the sub-array As to the array A0 along
%     auto-selected dimensions. The dimensions are identified by the
%     dimension of As with size larger than 1. If As is a scalar, then
%     all elements of A0 will be added As.
%
%   - Ar = sladd(A0, As, d) adds the sub-array As to the array A0 along
%     the dimensions specified by d.
%
% $ Remarks $
%   # An empty As is allowed. In such case, the original array A0 will
%     be output, i.e. Ar = A0.
%   # The sizes of dimensions along which the sub-array is added should
%     match that of A0, otherwise, an error will be raised.
%   # By specifying the dimensions through d, the speed can be accelerated.
%
% $ Examples $
%   - Add a vector to a matrix.
%     \{
%         A = [1 2 3; 4 5 6];
%         v = [2; 5];
%         Ar = sladd(A, v)
%
%         Ar =
%
%             3     4     5
%             9    10    11
%
%     \}
%     It is equivalent to sladd(A, v, 1).
%
%  - Add a plane to a matrix
%    \{
%        A1 = [1 2 3; 4 5 6];
%        A2 = [7 8 9; 10 11 12];
%        A = cat(3, A1, A2);
%        v1 = [10; 20];
%        v2 = [30; 40];
%        As = cat(3, v1, v2)
%
%        Ar(:, :, 1) =
%
%            11    12    13
%            24    25    26
%
%        Ar(:, :, 2) =
%
%            37    38    39
%            50    51    52
%
%    \}
%
% $ History $
%   - Created by Dahua Lin on Nov 18th, 2005
%

%% parse and verify input
if nargin < 2
    raise_lackinput('sladd', 2);
end
if isempty(As)
    Ar = A0;
    return;
end
if ndims(As) > ndims(A0)
    error('sltoolbox:dimoverflow', ...
        'The dimension of As should not be larger than that of A0');
end
if nargin < 3 || isempty(d)
    % d is not specified, automatically determine d
    d = find(size(As) > 1);
end
siz_A0 = size(A0);
siz_As = size(As);
if ~isequal(siz_A0(d), siz_As(d))
    error('sltoolbox:dimmismatch', ...
        'The dimensions of As does not match that of A0 in the dimensions to be added');
end

%% compute
siz_A0(d) = 1;
Ar = A0 + repmat(As, siz_A0);


function [ kn, fn, wn ] = r4_nor_setup ( )

%*****************************************************************************80
%
%% R4_NOR_SETUP sets data needed by R4_NOR.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 October 2013
%
%  Author:
%
%    Original C version by George Marsaglia, Wai Wan Tsang
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    George Marsaglia, Wai Wan Tsang,
%    The Ziggurat Method for Generating Random Variables,
%    Journal of Statistical Software,
%    Volume 5, Number 8, October 2000, seven pages.
%
%  Parameters:
%
%    Output, uint32 KN(128), data needed by R4_NOR.
%
%    Output, real FN(128), WN(128), data needed by R4_NOR.
%
  kn = zeros ( 128, 'uint32' );
  fn = zeros ( 128 );
  wn = zeros ( 128 );

  m1 = 2147483648.0;
  vn = 9.91256303526217E-03;

  dn = 3.442619855899;
  tn = 3.442619855899;

  q = vn / exp ( - 0.5 * dn * dn );
  kn(1) = uint32 ( ( dn / q ) * m1 );
  kn(2) = 0;

  wn(1) = q / m1;
  wn(128) = dn / m1;

  fn(1) = 1.0;
  fn(128) = exp ( - 0.5 * dn * dn );

  for i = 127 : -1 : 2
    dn = sqrt ( - 2.0 * log ( vn / dn + exp ( - 0.5 * dn * dn ) ) );
    kn(i+1) = uint32 ( ( dn / tn ) * m1 );
    tn = dn;
    fn(i) = exp ( - 0.5 * dn * dn );
    wn(i) = dn / m1;
  end

  return
end


%   TTeMPS Toolbox.
%   Michael Steinlechner, 2013-2016
%   Questions and contact: michael.steinlechner@epfl.ch
%   BSD 2-clause license, see LICENSE.txt

function X = construct_initial_guess(L, F, r, n)
% Basicially only the first micro-step of ALS

X = TTeMPS_rand( r, n );
X = 1/norm(X) * X;

d = X.order;
n = X.size;

X = orthogonalize(X, 1);
Fi = contract( X, F, 1 );
sz = [X.rank(1), X.size(1), X.rank(2)];

[left, right] = Afun_prepare( L, X, 1 );
B1 =  prepare_precond( L.A{1}, X, 1 );

Ui = pcg( @(y) Afun( L, y, 1, sz, left, right), ...
         Fi(:), ...
         1e-10, 1000, ...
         @(y) apply_precond( L.A{1}, B1, y, sz ), [],...
         X.U{1}(:) );

X.U{1} = reshape( Ui, sz );

X = orth_at( X, 1, 'left', true );

end

function [left, right] = Afun_prepare( A, x, idx )
    y = A.apply(x);
    if idx == 1
        right = innerprod( x, y, 'RL', idx+1 );
        left = [];
    elseif idx == x.order
        left = innerprod( x, y, 'LR', idx-1 );
        right = [];
    else
        left = innerprod( x, y, 'LR', idx-1 );
        right = innerprod( x, y, 'RL', idx+1 );
    end
end

function res = Afun( A, U, idx, sz, left, right )

    V = reshape( U, sz );
    V = A.apply( V, idx );

    if idx == 1
        tmp = tensorprod_ttemps( V, right, 3 );
    elseif idx == A.order
        tmp = tensorprod_ttemps( V, left, 1 );
    else
        tmp = tensorprod_ttemps( V, right, 3);
        tmp = tensorprod_ttemps( tmp, left, 1);
    end

    res = tmp(:);
end

function B1 = prepare_precond( L0, X, idx )

    if idx == 1
        B1 = [];
        return
    end

    n = size(L0, 1);
    r = X.rank;

    X1 = matricize( X.U{1}, 2);
    Y = X;
    Y.U{1} = tensorize( L0*X1, 2, [r(1), n(1), r(2)] );
    B1 = innerprod( X, Y, 'LR', idx-1);
end

function res = apply_precond( L0, B1, rhs, sz )

    n = size(L0, 1);
    rhs = reshape( rhs, sz );
    if isempty(B1) %idx == 1
        res = L0 \ unfold( rhs, 'left' );
        res = reshape( res, sz );
    else
        res = B1 \ unfold(rhs, 'right');
        res = reshape( res, sz );
    end
    res = res(:);
end


function features = feature_extraction( x_flt, CSP, oldSMC, verbose )
% x_flt: cell(2, numsamples) : 2-class
%           x_flt{1, i} = [nChannels, nSamples, nTrials]

if verbose == 1
%     fprintf( '\tFeature Extraction...\n\t\t' );
end

[nclass, nparticles] = size( x_flt );
features = cell( nclass, nparticles );

for i=1:oldSMC.numBands
    if verbose == 1
        if mod(i, 5) == 0
%             fprintf( '%d', i );
        else
%             fprintf( '.' );
        end
        if mod(i, 100) == 0
%             fprintf( '\n' );
        end
    end

    for k=1:nclass
        [nc, ns, nt] = size( x_flt{k, i} );
        temp = reshape( x_flt{k, i}, [nc, ns*nt] );
        temp = CSP{i}.W' * temp;
        temp = reshape( temp, [size(temp, 1), ns, nt] );
        temp = permute( temp, [2 1 3] );
        features{k, i} = squeeze( log(var(temp, 0, 1)) );
    end
end
% fprintf( '\n' );


function [matrix_data] = Dvec2Dmat(vector_data,WIDTH,LENGTH,IND,nodata)
% function which converts a vector to a matrix:
% option 1: WIDTH only where it is assumed that the original grid was
%                  made using vector = reshape(matrix,[],1);
% option 2: WIDTH, LENGTH, IND where the IND has the same length as the vector_data
%                  and where IND relates to the positon in a matrix. Note
%                  that this method allows for a mask file to be included.
%                  You can use the matlab function IND = sub2ind([WIDTH LENGTH], I, J)
%                  to generate the IND variable
% nodata argument is optional and us used to fill the nodata. By default
% this is a NaN.
%
%     Copyright (C) 2016  Bekaert David
%     davidbekaert.com
%
%     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 2 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.,
%     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%
% Bekaert David
% modifications:
% 8/10/2016     DB  Add nodata option

%  checking of the input arguments
method =1;          % this is the width method
if nargin <2
    error(['Expecting two inputs: vector_data and WIDTH'])
end
if nargin>2 && nargin<4
    fprintf('WARNING: you need to specify 4 inputs when planning on using IND option, will fall back on width only \n')
end
if length(WIDTH)~=1
    error('WIDTH is given incorrect')
end
if nargin >=4
   if isempty(LENGTH) || isempty(IND)
       error('You need to specify LENGTH and IND')
   end
   if length(LENGTH)~=1
       error('LENGTH is given incorrect')
   end
   if length(IND)~=length(vector_data)
       error('Length of vector_data and IND needs to be consistent')
   end
   method = 2;      % change to the width, length and ind method
end
if nargin<5
    nodata=NaN;
end

%% storing the data again
if method ==1
    matrix_data = reshape(vector_data,WIDTH,[]);
elseif method ==2
    if isnan(nodata)
        matrix_data = NaN([WIDTH LENGTH]);
    elseif nodata==0
        matrix_data = zeros([WIDTH LENGTH]);
    else
        matrix_data = ones([WIDTH LENGTH]).*nodata;
    end
    matrix_data(IND)= vector_data;
end


function rs = realifft(data, N)

% inverse fft for fourier coefficents from real valued  original data
% needs the length of the original time series from which the fft was computed
% see also : realfft

data = data(:);
if mod(N,2) 	% odd length
	data = [data ; conj(data(end:-1:2))];
else			% even length
	data = [data ; conj(data(end-1:-1:2))];
end

rs = real(ifft(data)); % remove small imaginary components introduced by rounding errors


function prepare_data_gt(input_files, output_file_name, pca_dim)

%load the hyperspectral data
mat_load=load(input_files.data_file);
fields=fieldnames(mat_load);
fields=fields{1};
im=getfield(mat_load,fields);

%load the labels
gt_load=load(input_files.gt_file);
fields=fieldnames(gt_load);
fields=fields{1};
ip_gt=getfield(gt_load,fields);

%get statistics of the data
[h,w,ch]=size(im)
num_pix=length(find(ip_gt>0));%h*w;

im_cen=im;

%pad the im_cen
conv_size=5;
pad_no=(conv_size-1)/2;

%padded image
im_X=zeros(h+2*pad_no,w+2*pad_no,ch);
for i=1:ch
    im_i=im_cen(:,:,i);
    im_X(:,:,i)=padarray(im_i,[pad_no,pad_no],'symmetric');
end

ip_gt_pad=padarray(ip_gt,[pad_no,pad_no],'symmetric');

cnt=1;
X=zeros(num_pix,ch,conv_size,conv_size);
labels=zeros(num_pix,1);
verbose=false;

for y=1:h
    fprintf('\nRow num=%d of %d',y,h);
    for x=1:w
        if ip_gt(y,x)>0
             X(cnt,:,:,:)=permute(im_X(y:y+conv_size-1,x:x+conv_size-1,:),...
                [3,1,2]);
            labels(cnt)=ip_gt(y,x);

            if verbose
                figure(1);
                imagesc(ip_gt_pad);
                rectangle('Position',[x y conv_size conv_size],...
                    'EdgeColor','r','linewidth',2);
                title(sprintf('Label=%d',labels(cnt)));
            end
            drawnow;
            pause(0.01);
            cnt=cnt+1;
        end
    end
end

comp=pcExtract(permute(X,[2,1,3,4]),pca_dim);
X_r=permute(comp,[2,1,3,4]);

save(output_file_name,'X_r','labels','ip_gt','im','-v7.3');


function [w, b] = Train_SVR(samples, labels)
%Train_SVR creating a linear support vector regressor

    % liblinear training
    addpath('C:\liblinear\matlab');

    % Remove redundant data
    [samples, inds] = unique(samples, 'rows');
    labels = labels(inds,:);

    cmd = ['-s 11 -B 1 -q'];

    svr_regressor = train(labels, sparse(double(samples)), cmd);

    w = svr_regressor.w(1:end-1)';
    b = svr_regressor.w(end);

end


% =========================================================================
% This code is part of the Matlab-based toolbox
% LagLDDDM - A Lagrangian Gauss--Newton--Krylov Solver for Mass- and
%                        Intensity-Preserving Diffeomorphic Image Registration
%
% For details and license info see
% - https://github.com/C4IR/FAIR.m/tree/master/add-ons/LagLDDMM
%
% 2D Multilevel Mass-Preserving LDDMM Example using stationary velocity
% field and diffusion regularizer as described in Sec. 4 of the paper:
%
% @article{MangRuthotto2017,
%   Title = {A {L}agrangian {G}auss--{N}ewton--{K}rylov solver for mass- and intensity-preserving diffeomorphic image registration},
%   Year = {2017},
%   Journal = {SIAM Journal on Scientific Computing},
%   Author = {A. Mang, L. Ruthotto},
% }
%
% =========================================================================
close all; clc; clear all;
setup3DmouseData;
alpha = [50 0];
lvl = 4;
pad = 0;
mV = @(m) m;
nt = 0;
N  = 2;
minLevel = 4;
maxLevel = 6;
imgModel('reset','imgModel','linearInterMex')
% 1) setup grid for velocities (padded)
omegaV = omega; omegaV(1:2:end) = omegaV(1:2:end)-pad;  omegaV(2:2:end) = omega(2:2:end)+pad;

% 2) setup regularizer (and decide for stationary or nonstationary velocity)
regularizer('reset','regularizer','mfDiffusionCC','alpha',alpha,'nt',nt,'HessianShift',1e-2); % nonstationary velocity

%%
plots = 1;
NPIRpara    = optPara('NPIR-GN');
NPIRpara.maxIter = 40;
NPIRpara.scheme = @GaussNewtonLDDMM;

[vc,~,wc,his] = MLLDDMM(ML,'minLevel',minLevel,'maxLevel',maxLevel,'omegaV',omegaV,...
    'mV',mV,'N',N,'parametric',0,'plots',plots,'NPIRpara',NPIRpara,'NPIRobj',@MPLDDMMobjFctn);
switch regularizer
    case {'mfDiffusionST','mfCurvatureST'}
        yInv = getTrafoFromInstationaryVelocityRK4(vc,getNodalGrid(omega,m),'omega',omegaV,'m',m,'N',N,'nt',nt,'tspan',[1 0]);
    case {'mfDiffusionCC','mfCurvatureCC'}
        yInv = getTrafoFromVelocityRK4(vc,getNodalGrid(omega,m),'omega',omegaV,'m',m,'N',N,'tspan',[1 0]);
        nt = 0;
end

%%
yc = getTrafoFromVelocityRK4(vc,getNodalGrid(omega,m),'omega',omegaV,'m',m,'nt',nt,'tspan',[1,0],'N',N);
Jac = geometry(yInv,m,'Jac','omega',omega);
Topt = linearInterMex(dataT,omega,center(yInv,m)) .* Jac;
D0  = distance(dataT(:),dataR(:),omega,m);
DOpt = distance(Topt(:),dataR(:),omega,m);

fig = figure(); clf;
fig.Name = sprintf('Results for %s',mfilename);

subplot(2,3,1);
viewImage(dataR,omega,m);
title('reference');

subplot(2,3,4);
viewImage(dataT,omega,m);
title('template');

subplot(2,3,2);
viewImage(Topt,omega,m);
title('T(yc)')

subplot(2,3,3);
imgmontage(dataT(:)-dataR(:),omega,m);
title('init. residual, SSD=100%');

subplot(2,3,5);
imgmontage(Jac,omega,m);
title(sprintf('Jac, min=%1.2f max=%1.2f',min(Jac(:)),max(Jac(:))));

subplot(2,3,6);
imgmontage(Topt(:)-dataR(:),omega,m);
title(sprintf('opt residual, SSD=%1.2f%%',100*DOpt/D0));


function [PC,CC,DC,IC] = trim_with_spline(PA,CA,PB,CB,tol)
  % TRIM_WITH_SPLINE Trim a given spline (PA,CA) with a "solid" spline (PB,CB)
  %
  % [PC,CC,DC,IC] = trim_with_spline(PA,CA,PB,CB,tol)
  %
  % Inputs:
  %   PA  #PA by dim list of control point locations
  %   CA  #CA by 4 list of indices into PA of cubic Bezier curves
  %   PB  #PB by dim list of control point locations
  %   CB  #CB by 4 list of indices into PB of cubic Bezier curves
  %   tol  tolerance for intersection {1e-7}
  % Outputs:
  %   PC  #PC by dim list of control point locations
  %   CC  #CC by 4 list of indices into PC of cubic Bezier curves
  %   DC  #CC list of flags whether inside B
  %   IC  #CC list of indices into CA
  %

  function [PA,CA,DA,IA] = trim_with_spline_helper(PA,CA,PB,CB)

    [A1,A2] = box_each_element(PA,CA);
    [B1,B2] = box_each_element(PB,CB);
    I = box_intersect(A1,A2,B1,B2);
    T = cell(size(CA,1),1);
    % consider each intersection, gather splits
    for ii = 1:size(I,1)
      ca = I(ii,1);
      cb = I(ii,2);
      Tii = cubic_cubic_intersect(PA(CA(ca,:),:),PB(CB(cb,:),:),tol);
      if ~isempty(Tii)
        T{ca} = [T{ca};Tii(:,1)];
      end
    end
    % conduct all splits
    IA = (1:size(CA,1))';
    for ca = 1:size(CA,1)
      if ~isempty(T{ca})
        Tca = sort(T{ca});
        [PAa,CAa] = cubic_subdivide(PA(CA(ca,:),:),Tca);
        CAa = reshape([CA(ca,1) CAa(2:end-1)+size(PA,1)-2 CA(ca,end)],size(CAa));
        IA([ca size(CA,1)+(1:size(CAa,1)-1)],:) = IA(ca);
        CA([ca size(CA,1)+(1:size(CAa,1)-1)],:) = CAa;
        PA = [PA;PAa(3:end,:)];
      end
    end

    %%fprintf('trim_with_spline...\n');
    %% loop order is imporant
    %IA = (1:size(CA,1))';
    %for cb = 1:size(CB,1)
    %  %fprintf('  %04d/%04d:\n',cb,size(CB,1));
    %  for ca = 1:size(CA,1)
    %    %progressbar(ca,size(CA,1));
    %    T = cubic_cubic_intersect(PA(CA(ca,:),:),PB(CB(cb,:),:),tol);
    %    if ~isempty(T)
    %      [PAa,CAa] = cubic_subdivide(PA(CA(ca,:),:),T(:,1));
    %      CAa = reshape([CA(ca,1) CAa(2:end-1)+size(PA,1)-2 CA(ca,end)],size(CAa));
    %      IA([ca size(CA,1)+(1:size(CAa,1)-1)],:) = IA(ca);
    %      CA([ca size(CA,1)+(1:size(CAa,1)-1)],:) = CAa;
    %      PA = [PA;PAa(3:end,:)];
    %    end
    %  end
    %end

    % midpoints of each cubic
    %fprintf('midpoints...\n');
    M = zeros(size(CA,1),2);
    for ca = 1:size(CA,1)
      M(ca,:) = cubic_eval(PA(CA(ca,:),:),0.5);
    end
    %fprintf('spline_winding_number...\n');
    DA = abs(spline_winding_number(PB,CB,M))>0.5;
  end

  m = size(CA,1);
  embed = @(P,C) reshape(P(C,:),size(C,1),8);
  CB8 = embed(PB,CB);
  % In either direction
  RB8 = embed(PB,fliplr(CB));
  CA8 = embed(PA,CA);
  % find perfect matches (only considering that every control point is exactly
  % the same; not finding partial co-incidence )
  [idx,dist] = rangesearch([CB8;RB8],CA8,0);
  perfect = cellfun(@(i) ~isempty(i),idx);
  JN = find(~perfect);
  [PA,CN,DN,IN] = trim_with_spline_helper(PA,CA(JN,:),PB,CB);
  CA = [CN;CA(perfect,:)];
  JP = find(perfect);
  IA = [JN(IN);JP];
  DA = [DN;true(numel(JP),1)];
  assert(size(CA,1) == numel(IA));
  assert(max(IA) <= m);
  assert(size(CA,1) == numel(DA));

  % rename
  PC = PA;
  CC = CA;
  DC = DA;
  IC = IA;
end


function label = LSC(data,k,opts)
% label = LSC(data,k,opts): Landmark-based Spectral Clustering
% Input:
%       - data: the data matrix of size nSmp x nFea, where each row is a sample
%               point
%       - k: the number of clusters
%       opts: options for this algorithm
%           - p: the number of landmarks picked (default 1000)
%           - r: the number of nearest landmarks for representation (default 5)
%           - numRep: the number of replicates for the final kmeans (default 10)
%           - maxIter: the maximum number of iterations for final kmeans (default 100)
%           - mode: landmark selection method, currently support
%               - 'kmeans': use centers of clusters generated by kmeans (default)
%               - 'random': use randomly sampled points from the original
%                           data set
%           The following parameters are effective ONLY in mode 'kmeans'
%           - kmNumRep: the number of replicates for initial kmeans (default 1)
%           - kmMaxIter: the maximum number of iterations for initial kmeans (default 5)
% Output:
%       - label: the cluster assignment for each point
% Requre:
%       litekmeans.m
% Usage:
%       data = rand([100,50]);
%       label = LSC(data,10);
%Reference:
%
%	[1] Xinlei Chen, Deng Cai, "Large Scale Spectral Clustering with
%	Landmark-Based Representation," AAAI 2011.
%
%   [2] Deng Cai, Xinlei Chen: Large Scale Spectral Clustering Via
%   Landmark-Based Sparse Representation. IEEE Trans. Cybernetics 45(8):
%   1669-1680 (2015)
%
%   version 2.0 --Dec./2011
%   version 1.0 --Oct./2010
%
%   Written by Xinlei Chen (endernewton AT gmail.com)
%              Deng Cai (dengcai AT gmail.com)

% Set and parse parameters
if (~exist('opts','var'))
   opts = [];
end

p = 1000;
if isfield(opts,'p')
    p = opts.p;
end

r = 5;
if isfield(opts,'r')
    r = opts.r;
end

maxIter = 100;
if isfield(opts,'maxIter')
    maxIter = opts.maxIter;
end

numRep = 10;
if isfield(opts,'numRep')
    numRep = opts.numRep;
end

mode = 'kmeans';
if isfield(opts,'mode')
    mode = opts.mode;
end

nSmp=size(data,1);

% Landmark selection
if strcmp(mode,'kmeans')
    kmMaxIter = 5;
    if isfield(opts,'kmMaxIter')
        kmMaxIter = opts.kmMaxIter;
    end
    kmNumRep = 1;
    if isfield(opts,'kmNumRep')
        kmNumRep = opts.kmNumRep;
    end
    [~,marks]=litekmeans(data,p,'MaxIter',kmMaxIter,'Replicates',kmNumRep);
    clear kmMaxIter kmNumRep
elseif strcmp(mode,'random')
    indSmp = randperm(nSmp);
    marks = data(indSmp(1:p),:);
    clear indSmp
else
    error('mode does not support!');
end

% Z construction
D = EuDist2(data,marks);

if isfield(opts,'sigma')
    sigma = opts.sigma;
else
    sigma = mean(mean(D));
end

dump = zeros(nSmp,r);
idx = dump;
for i = 1:r
    [dump(:,i),idx(:,i)] = min(D,[],2);
    temp = (idx(:,i)-1)*nSmp+[1:nSmp]';
    D(temp) = 1e100;
end

dump = exp(-dump/(2*sigma^2));
sumD = sum(dump,2);
Gsdx = bsxfun(@rdivide,dump,sumD);
Gidx = repmat([1:nSmp]',1,r);
Gjdx = idx;
Z=sparse(Gidx(:),Gjdx(:),Gsdx(:),nSmp,p);

% Graph decomposition
feaSum = full(sqrt(sum(Z,1)));
feaSum = max(feaSum, 1e-12);
Z = Z./feaSum(ones(size(Z,1),1),:);
U = mySVD(Z,k+1);
U(:,1) = [];

U=U./repmat(sqrt(sum(U.^2,2)),1,k);

% Final kmeans
label=litekmeans(U,k,'MaxIter',maxIter,'Replicates',numRep);