% FactorMarginalization Sums given variables out of a factor.
%   B = FactorMarginalization(A,V) computes the factor with the variables
%   in V summed out. The factor data structure has the following fields:
%       .var    Vector of variables in the factor, e.g. [1 2 3]
%       .card   Vector of cardinalities corresponding to .var, e.g. [2 2 2]
%       .val    Value table of size prod(.card)
%
%   The resultant factor should have at least one variable remaining or this
%   function will throw an error.
%
%   See also FactorProduct.m, IndexToAssignment.m, and AssignmentToIndex.m
%
% Copyright (C) Daphne Koller, Stanford Univerity, 2012

function B = FactorMarginalization(A, V)

% Check for empty factor or variable list
if (isempty(A.var) || isempty(V)), B = A; return; end;

% Construct the output factor over A.var \ V (the variables in A.var that are not in V)
% and mapping between variables in A and B
[B.var, mapB] = setdiff(A.var, V);

% Check for empty resultant factor
if isempty(B.var)
    %error('Error: Resultant factor has empty scope');
    B.var = [];
    B.card = [];
    B.val = [];
    return;
end;

% Initialize B.card and B.val
B.card = A.card(mapB);
B.val = zeros(1,prod(B.card));

% Compute some helper indices
% These will be very useful for calculating C.val
% so make sure you understand what these lines are doing
assignments = IndexToAssignment(1:length(A.val), A.card);
indxB = AssignmentToIndex(assignments(:, mapB), B.card);

for i = 1:length(A.val),
    B.val(indxB(i)) = B.val(indxB(i)) + A.val(i);
end;

end


clear all
close all

disp('Compute Model Evidence for Logistic Regression models using');
disp('Thermodynamic Integration');
disp('Explore effect of number of chains');

% Logistic model
[M{1},U{1}] = mci_logistic_struct ('dct');
P=[1 10 10]';
[g,Y]=mci_logistic_gen(P,M{1},U{1});
figure;
plot(g,'k','LineWidth',2);
set(gca,'FontSize',16);
grid on
xlabel('Time,t');
ylabel('p(Y=1|t)');

% MCMC parameters
mcmc.J=64; % Number of temperatures/chains
mcmc.ntune=500;
mcmc.nsamp=250;
setinit=1;
if setinit
    % Start sampling from this point
    for j=1:mcmc.J,
        mcmc.init{j}=P;
    end
    mcmc.nscale=0;
else
    mcmc.nscale=500;
end
mcmc.remove_burn_in=1;

% No sharing of samples between chains
mcmc.gprob=0;

j=[4,8,16,32,64];
for i=1:length(j),
    mcmc.J=j(i);
    tic;
    [P,logev,D] = spm_mci_pop (mcmc,M,U,Y);
    els(i)=toc;
    L(i)=logev.ti;
    disp(sprintf('J=%d: TI Log Evidence = %1.2f',j(i),logev.ti));
end

figure
plot(j,L,'k','LineWidth',2);
grid on
set(gca,'FontSize',16);
xlabel('Number of Chains');
ylabel('Log Evidence');
title('Thermodynamic Integration');

% Annealed Importance Sampling
mcmc.inference='ais';
mcmc.anneal='geometric';
mcmc.prop='lmc';
mcmc.nprop=1;
mcmc.maxits=64;

j=[4,8,16,32,64,128,256,512,1024];
for i=1:length(j),
    mcmc.J=j(i);
    tic;
    post = spm_mci_ais (mcmc,M{1},U{1},Y);
    els(i)=toc;
    L(i)=post.logev;
    disp(sprintf('J=%d: AIS Log Evidence = %1.2f',j(i),L(i)));
end

figure
semilogx(j,L,'k','LineWidth',2);
grid on
set(gca,'FontSize',16);
xlabel('Number of Chains');
ylabel('Log Evidence');
title('Annealed Importance Sampling');


function c=ref_edgt(f,g,a,M)
%REF_EDGT   Reference Even Discrete Gabor transform
%   Usage  c=ref_edgt(f,g,a,M);
%
%   The input window must be odd-centered.

L=size(f,1);
W=size(f,2);

N=L/a;
M=L/b;

F=zeros(L,M*N);

l=(0:L-1)';
for n=0:N-1
  for m=0:M-1
    F(:,1+m+n*M)=exp(2*pi*i*m.*(l+.5)*b/L).*circshift(g,n*a);
  end;
end;

c=F'*f;


function [e, edata, eprior] = gperr(net, x, t)
%GPERR	Evaluate error function for Gaussian Process.
%
%	Description
%	E = GPERR(NET, X, T) takes a Gaussian Process data structure NET
%	together  with a matrix X of input vectors and a matrix T of target
%	vectors, and evaluates the error function E. Each row of X
%	corresponds to one input vector and each row of T corresponds to one
%	target vector.
%
%	[E, EDATA, EPRIOR] = GPERR(NET, X, T) additionally returns the data
%	and hyperprior components of the error, assuming a Gaussian prior on
%	the weights with mean and variance parameters PRMEAN and PRVARIANCE
%	taken from the network data structure NET.
%
%	See also
%	GP, GPCOVAR, GPFWD, GPGRAD
%

%	Copyright (c) Ian T Nabney (1996-2001)

errstring = consist(net, 'gp', x, t);
if ~isempty(errstring);
  error(errstring);
end

cn = gpcovar(net, x);

edata = 0.5*(sum(log(eig(cn, 'nobalance'))) + t'*inv(cn)*t);

% Evaluate the hyperprior contribution to the error.
% The hyperprior is Gaussian with mean pr_mean and variance
% pr_variance
if isfield(net, 'pr_mean')
  w = gppak(net);
  m = repmat(net.pr_mean, size(w));
  if size(net.pr_mean) == [1 1]
    eprior = 0.5*((w-m)*(w-m)');
    e2 = eprior/net.pr_var;
  else
    wpr = repmat(w, size(net.pr_mean, 1), 1)';
    eprior = 0.5*(((wpr - m').^2).*net.index);
    e2 = (sum(eprior, 1))*(1./net.pr_var);
  end
else
  e2 = 0;
  eprior = 0;
end

e = edata + e2;


function [xEst,PEst]=batchLSLinMeasLinDyn(z,H,F,R,kD,Q,numMeas)
%%BATCHLSLINMEASLINDYN Perform batch least squares state estimation under a
%                linear measurement model and a linear dynamic model with
%                optional process noise.
%
%INPUTS: z The zDim X N matrix of measurements for the whole batch. It is
%          assumed that the measurements have the same dimensionality over
%          the batch. If an empty matrix is passed, then it is assumed that
%          the user only wants the covariance matrix and not xEst.
%        H The zDim X xDim X N hypermatrix of measurement matrices such
%          that H(:,:,k)*x+w is the measurement at time k, where x is the
%          state and w is zero-mean Gaussian noise with covariance matrix
%          R(:,:,k). Alternatively, if all of the measurement matrices are
%          the same, one can just pass a single zDim X xDim matrix.
%        F An xDim X xDim X (N-1) hypermatrix of  matrices. The state at
%          discrete-time k+1 is modeled as F(:,:,k) times the state at time
%          k plus zero-mean Gaussian process noise with covariance matrix
%          Q(:,:,k). Alternatively, if all of the state transition matrices
%          are the same, one can just pass a single xDim X xDim matrix.
%          Note that all of the F matrices must be invertible if kD is not
%          equal to one.
%        R The zDim X zDim X N hypermatrix of measurement covariance
%          matrices. Alternatively, if all of the measurement covariance
%          matrices are the same, one can just pass a single zDimXzDim
%          matrix.
%       kD The discrete time-step for which the covariance matrix of an
%          estimate is desired, where z(:,1) is at discrete time-step 1
%          (not 0).
%        Q The xDim X xDim X (N-1) hypermatrix of process noise covariance
%          matrices. Alternatively, if all of the process noise covariance
%          matrices are the same, one can just pass a single xDimXxDim
%          matrix. If an empty matrix is passed for Q, then the estimation
%          is performed assuming there is no process noise.
%  numMeas If an empty matrix is passed for z, then the numMeas parameter
%          must be passed indicating the number of measurements in the
%          batch. Otherwise, this parameter is
%                ignored.
%
%OUTPUTS: xEst The batch state estimate at step kD, unless an empty matrix
%              was passed for z, in which case xEst is empty.
%         PEst A covariance matrix estimate that goes with the state
%              estimate.
%
%The algorithm is an implementation of the method of Section 3.3.2 of [1]
%for a linear dynamic model. Note that the cases in equation 28 to 32 of
%the paper did not cover all of the possibilities, so the correct
%generalization had to be derived from E[epsilon_{p,k}*epsilon_{q,k}'].
%
%REFERENCES:
%[1] A. B. Poore, B. J. Slocumb, B. J. Suchomel, F. H. Obermeyer, S. M.
%    Herman, and S. M. Gadaleta, "Batch maximum likelihood (ML) and maximum
%    a posteriori (MAP) estimation with process noise for tracking
%    applications," in Proceedings of SPIE: Signal and Data Processing of
%    Small Targets, vol. 5204, San Diego, CA, 3 Aug. 2003, pp. 188-199.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(~isempty(z))
    numMeas=size(z,2);
end

xDim=size(F,1);
zDim=size(R,1);

if(size(H,3)==1)
    HMats=repmat(H,[1,1,numMeas]);
else
    HMats=H;
end

if(size(F,3)==1)
    F=repmat(F,[1,1,numMeas-1]);
end

if(size(R,3)==1)
    R=repmat(R,[1,1,numMeas]);
end

if(isempty(Q))
    Q=zeros(xDim,xDim,numMeas);
elseif(size(Q,3)==1)
    Q=repmat(Q,[1,1,numMeas-1]);
end

transMats=getTransMats(F);

WMat=zeros(zDim*numMeas,zDim*numMeas);
for p=1:numMeas
    pIdxMin=(p-1)*zDim+1;
    pIdxMax=p*zDim;
    pSpan=pIdxMin:pIdxMax;
    for q=1:numMeas
        qIdxMin=(q-1)*zDim+1;
        qIdxMax=q*zDim;
        qSpan=qIdxMin:qIdxMax;
        if(p<kD&&q<kD)
            CumMat=zeros(xDim,xDim);

            for i=(max(p,q)+1):kD
                CumMat=CumMat+transMats(:,:,p,i)*Q(:,:,i-1)*transMats(:,:,q,i)';
            end

            WMat(pSpan,qSpan)=HMats(:,:,p)*CumMat*HMats(:,:,q)'+KDelta(p-q)*R(:,:,p);
        elseif(p>kD&&q>kD)
            CumMat=zeros(xDim,xDim);

            for i=(kD+1):min(p,q)
                CumMat=CumMat+transMats(:,:,p,i)*Q(:,:,i-1)*transMats(:,:,q,i)';
            end

            WMat(pSpan,qSpan)=KDelta(p-q)*R(:,:,p)+HMats(:,:,p)*CumMat*HMats(:,:,q)';
        elseif(p==kD&&q==kD)
            WMat(pSpan,qSpan)=R(:,:,p);
        end
    end
end

%The propagated measurement matrices.
bigH=zeros(zDim*numMeas,xDim);
for curMeas=1:numMeas
    idxMin=(curMeas-1)*zDim+1;
    idxMax=curMeas*zDim;

    bigH(idxMin:idxMax,:)=HMats(:,:,curMeas)*transMats(:,:,curMeas,kD);
end

WInv=inv(WMat);
PEstInv=bigH'*WInv*bigH;
PEst=inv(PEstInv);
if(isempty(z))
    xEst=[];
else
    xEst=PEstInv\bigH'*(WMat\z(:));
end
end

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


function [pitch, roll, yaw] = q2att(qnb)
    q11 = qnb(1)*qnb(1); q12 = qnb(1)*qnb(2); q13 = qnb(1)*qnb(3); q14 = qnb(1)*qnb(4);
    q22 = qnb(2)*qnb(2); q23 = qnb(2)*qnb(3); q24 = qnb(2)*qnb(4);
    q33 = qnb(3)*qnb(3); q34 = qnb(3)*qnb(4);
    q44 = qnb(4)*qnb(4);
    C12=2*(q23-q14);
    C22=q11-q22+q33-q44;
    C31=2*(q24-q13); C32=2*(q34+q12); C33=q11-q22-q33+q44;

    pitch = asind(C32);
    roll = atan2d(-C31,C33);
    yaw = atan2d(C12,C22);
    yaw = yaw + (yaw<0)*360;
end


function [fx] = evolution0bisND(x,theta,u,in)
% 0-ToM's evolution function (without doubled hidden states)
% function [fx] = evolution0bisND(x,theta,u,in)
% 0-ToM is simply tracking the log-odds of P(o=1), where o is the
% opponent's action. This variable is updated according to a Laplace-Kalman
% filter, yielding 2 sufficient statistics, m and V. In this scheme, the
% only evolution param (theta) is 0-ToM's prior volatity about her
% opponent's log-odds.
% IN:
%   - x: sufficient statistics of log-odds of P(o=1):
%       x(1)= E[log-odds]
%       x(2)= log V[log-odds] (log-scale for numerical reasons)
%   - theta: 0-ToM's prior (log-) volatity
%   - u: u(1)= last opponent's move (o)
%   - in: [useless here]
% OUT:
%   - fx: updated sufficient statistics of log-odds of P(o=1)

if isempty(u)||isnan(u(1)) % missed trial
    fx = x; % no update
else % trial OK
    % -- deal with superceding competition with other generative models --
    % [See, e.g., f_metaTom.m]
    try
        w = inF.metaweight;
    catch
        w = 1;
    end
    % -- learning rule --
    m0 = x(1); % current E[log-odds]
    V0 = exp(x(2)); % current V[log-odds]
    p0 = VBA_sigmoid(m0); % current estimate of P(o=1)
    volatility = exp(theta(1));
    V = 1./((1./(volatility+V0))+w*p0*(1-p0)); % updated V[log-odds]
    m = m0 + w*V*(u(1)-p0); % updated E[log-odds] (Laplace-Kalman update rule)
    % wrap-up
    fx = [VBA_sigmoid(VBA_sigmoid(m),'inverse',true);log(V)]; % for numerical purposes
end


% confusion_matrix(1,1) = fraction of true 1 classified as 1
% confusion_matrix(1,2) = fraction of true 1 classified as 2
% confusion_matrix(1,3) = fraction of true 1 classified as unknown
% confusion_matrix(2,1) = fraction of true 2 classified as 1
% confusion_matrix(2,2) = fraction of true 2 classified as 2
% confusion_matrix(2,3) = fraction of true 2 classified as unknown
function confusion_matrix = ComputeConfusionMatrix(hs,diff_logprob,maxdiff_logprob1,mindiff_logprob2)

confusion_matrix = nan(2,3);
hsPr1 = diff_logprob < maxdiff_logprob1;
hsPr2 = diff_logprob > mindiff_logprob2;
n1 = nnz(hs==1);
n2 = nnz(hs==2);

confusion_matrix(1,1) = nnz(hsPr1(hs==1)) / n1;
confusion_matrix(1,2) = nnz(hsPr2(hs==1)) / n1;
confusion_matrix(1,3) = 1 - confusion_matrix(1,1) - confusion_matrix(1,2);

confusion_matrix(2,1) = nnz(hsPr1(hs==2)) / n2;
confusion_matrix(2,2) = nnz(hsPr2(hs==2)) / n2;
confusion_matrix(2,3) = 1 - confusion_matrix(2,1) - confusion_matrix(2,2);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: Setting up advection-diffusion solver
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [C,laplacian_C] = please_Update_Adv_Diff_Concentration_Flux_Limiter_FV(C,dt,dx,dy,uX,uY,k)

% C:     concentration
% dt:    time-step
% dx,dy: spatial steps in x and y, respectively
% uX:    x-Component of Velocity
% uY:    y-Component of Velocity
% k:     diffusion coefficient

% Compute Fluxes (Note: these calculations could be parallalized)
selection = 'superbee';
Fx = give_Necessary_Fluxes(C,dx,uX,'x',selection,dt); % Fluxes in x
Fy = give_Necessary_Fluxes(C,dy,uY,'y',selection,dt); % Fluxes in y

% "forward difference of fluxes in x"
F2x = [Fx(:,2:end) Fx(:,1)];
F1x = [Fx(:,end) Fx(:,1:end-1)];
diffX = 0.5/dx*( F2x - F1x );

% "forward differences of fluxes in y"
F2y = [Fy(2:end,:); Fy(1,:)];
F1y = [Fy(end,:); Fy(1:end-1,:)];
diffY = 0.5/dy*( F2y - F1y );

diffY=0;

% Compute 2nd Derivative Terms
Cxx = DD(C,dx,'x');
Cyy = DD(C,dy,'y');

% Forms Laplacian
laplacian_C = Cxx+Cyy;

% UPWIND
C = C - dt * ( diffX + diffY ) + dt*( k*laplacian_C );

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: Computes derivative based on sign of Velocity, u, using UPWIND
% approach
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function C_z = give_Necessary_Fluxes(C,dz,uZ,string,selection,dt)

C_z = zeros(size(C));
len = length(uZ(:,1));
signs = sign(uZ);

if strcmp(string,'x')

    %For periodicity on ends w/ UPWIND
    for i=1:len

        %left side of grid
        if signs(i,1) <= 0
            r = ( C(i,2) - C(i,1) ) / ( C(i,1) - C(i,len) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(i,1) =  uZ(i,1)*C(i,2) ;%  + 0.5*abs( uZ(i,1) )*( 1 - abs( 0.5*dt*uZ(i,1)/dz ) )*phi*( C(i,2) - C(i,len) );
        else
            r = ( C(i,1) - C(i,len) ) / ( C(i,2) - C(i,1) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(i,1) =  uZ(i,1)*C(i,len) ;%+ 0.5*abs( uZ(i,1) )*( 1 - abs( 0.5*dt*uZ(i,1)/dz ) )*phi*( C(i,2) - C(i,len) );
        end

        %right side of grid
        if signs(len,1) <= 0
            r = ( C(i,1) - C(i,len) ) / ( C(i,len) - C(i,len-1) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(i,len) =  uZ(i,len)*C(i,1)  ;%   + 0.5*abs( uZ(i,len) )*( 1 - 0.5*abs( dt*uZ(i,len)/dz ) )*phi*( C(i,1) - C(i,len-1) );
        else
            r = ( C(i,len) - C(i,len-1) ) / ( C(i,1) - C(i,len) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(i,len) =  uZ(i,len)*C(i,len-1);% + 0.5*abs( uZ(i,len) )*( 1 - 0.5*abs( dt*uZ(i,len)/dz ) )*phi*( C(i,1) - C(i,len-1) );
        end

    end
    %Standard Upwind
    for i=1:len
        for j=2:len-1
            if signs(i,j) <= 0
                r = ( C(i,j+1) - C(i,j) ) / ( C(i,j) - C(i,j-1) );
                phi = please_Give_Flux_Limiter(r,selection);
                C_z(i,j) = uZ(i,j)*C(i,j+1);% + 0.5*abs( uZ(i,j) )*( 1 - 0.5*abs( dt*uZ(i,j)/dz ) )*phi*( C(i,j+1) - C(i,j-1) );
            else
                r = ( C(i,j) - C(i,j-1) ) / ( C(i,j+1) - C(i,j) );
                phi = please_Give_Flux_Limiter(r,selection);
                C_z(i,j) = uZ(i,j)*C(i,j-1);% + 0.5*abs( uZ(i,j) )*( 1 - 0.5*abs( dt*uZ(i,j)/dz ) )*phi*( C(i,j+1) - C(i,j-1) );
            end
        end
    end

    % Ends x-Direction calculation %

elseif strcmp(string,'y')

    %For periodicity on ends w/ UPWIND
    for i=1:len

        %bottom of grid
        if signs(1,i) <= 0
            r = ( C(2,i) - C(1,i) ) / ( C(1,i) - C(len,i) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(1,i) =  uZ(1,i)*C(2,i)   + 0.5*abs( uZ(1,i) )*( 1 - abs( 0.5*dt*uZ(1,i)/dz ) )*phi*( C(2,i) - C(len,i) );
        else
            r = ( C(1,i) - C(len,i) ) / ( C(2,i) - C(1,i) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(1,i) =  uZ(1,i)*C(len,i) + 0.5*abs( uZ(1,i) )*( 1 - abs( 0.5*dt*uZ(1,i)/dz ) )*phi*( C(2,i) - C(len,i) );
        end

        %top of grid
        if signs(len,1) <= 0
            r = ( C(1,i) - C(len,i) ) / ( C(len,i) - C(len-1,i) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(len,i) =  uZ(len,i)*C(1,i)       + 0.5*abs( uZ(len,i) )*( 1 - abs( 0.5*dt*uZ(len,i)/dz ) )*phi*( C(1,i) - C(len-1,i) );
        else
            r = ( C(len,i) - C(len-1,i) ) / ( C(1,i) - C(len,i) );
            phi = please_Give_Flux_Limiter(r,selection);
            C_z(len,i) =  uZ(len,i)*C(len-1,i)   + 0.5*abs( uZ(len,i) )*( 1 - abs( 0.5*dt*uZ(len,i)/dz ) )*phi*( C(1,i) - C(len-1,i) );
        end

    end

    %Standard Upwind
    for i=1:len
        for j=2:len-1
            if signs(j,i) <= 0
                r = ( C(j+1,i) - C(j,i) ) / ( C(j,i) - C(j-1,i) );
                phi = please_Give_Flux_Limiter(r,selection);
                C_z(j,i) = uZ(j,i)*C(j+1,i) + 0.5*abs( uZ(j,i) )*( 1 - abs( 0.5*dt*uZ(j,i)/dz ) )*phi*( C(j+1,i) - C(j-1,i) );
            else
                r = ( C(j,i) - C(j-1,i) ) / ( C(j+1,i) - C(j,i) );
                phi = please_Give_Flux_Limiter(r,selection);
                C_z(j,i) = uZ(j,i)*C(j-1,i) + 0.5*abs( uZ(j,i) )*( 1 - abs( 0.5*dt*uZ(j,i)/dz ) )*phi*( C(j+1,i) - C(j-1,i) );
            end
        end
    end

    % Ends y-Direction calculation %

else

    fprintf('\n\n\n ERROR IN FUNCTION FOR COMPUTING FLUX LIMITERS\n');

end

clear signs; clear len;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: Finds CENTERED finite difference approximation to 2ND
% DERIVATIVE in z direction, specified by input and 'string'
% Note: It automatically accounts for periodicity of the domain.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function u_zz = DD(u,dz,string)

% u:      velocity
% dz:     spatial step in "z"-direction
% string: specifies which 2ND derivative to take (to enforce periodicity)

len = length(u(:,1));

if strcmp(string,'x')

    %For periodicity on ends
    u_zz(:,1) =  ( u(:,2) - 2*u(:,1)   + u(:,len) )   / (dz^2);
    u_zz(:,len)= ( u(:,1) - 2*u(:,len) + u(:,len-1) ) / (dz^2);

    %Standard Upwind Scheme (Centered Difference)
    for j=2:len-1
        u_zz(:,j) = ( u(:,j+1) - 2*u(:,j) + u(:,j-1) ) / (dz^2);
    end

elseif strcmp(string,'y')

    %For periodicity on ends
    u_zz(1,:) =  ( u(2,:) - 2*u(1,:)   + u(len,:) )   / (dz^2);
    u_zz(len,:)= ( u(1,:) - 2*u(len,:) + u(len-1,:) ) / (dz^2);

    %Standard Upwind Scheme (Centered Difference)
    for j=2:len-1
        u_zz(j,:) = ( u(j+1,:) - 2*u(j,:) + u(j-1,:) ) / (dz^2);
    end

else

    fprintf('\n\n\n ERROR IN FUNCTION DD FOR COMPUTING 2ND DERIVATIVE\n');
    fprintf('Need to specify which desired derivative, x or y.\n\n\n');

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: computes flux limiter with choice of which one
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function phi = please_Give_Flux_Limiter(r,selection)

if strcmp(selection,'superbee')
    max1 = max( min(1,2*r),min(2,r) );
    phi = max(0,max1);
elseif strcmp(selection,'vanLeer')
    phi = ( r + abs(r) ) / ( 1 + abs(r) );
else
    fprintf('\n\n');
    error('NEED TO CHOOSE AN APPROPRIATE FLUX LIMITER');
end


function o = logBarrierRound(problem)
%Input: a structure P with the following fields
%  .Aeq
%  .beq
%  .lb
%  .ub
% describing the polytope {Aeq x = beq, lb <= x <= ub}
%Output:
% o - problem structure

A = problem.Aeq; b = problem.beq;
lb = problem.lb; ub = problem.ub;

f = ConvexProgram.LinearProgram(A, b, [], lb, ub);
f.normalize();
assert(f.feasible, 'The problem is not feasible.')

A = double(f.A);
b = double(f.b);
x = double(f.interior);
lb = double(f.barrier.lb);
ub = double(f.barrier.ub);

x0 = f.x0;
idx = f.idx;
scale = double(f.scale);

o = struct;
o.P = struct('A', A, 'b', b, 'lb', lb, 'ub', ub, 'x', x); % rounded polytope with feasible point x
o.T = struct('x0', x0, 'idx', idx, 'scale', scale); % used to recover sample in original space by x(idx) = x0(idx) + scale.*samples
end


function [Population,z,znad] = EnvironmentalSelection(Population,W,N,z,znad)
% The environmental selection of theta-DEA

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

    %% Non-dominated sorting
    [FrontNo,MaxFNo] = NDSort(Population.objs,N);
    St = find(FrontNo<=MaxFNo);

    %% Normalization
    [PopObj,z,znad] = Normalization(Population(St).objs,z,znad);

    %% theta-non-dominated sorting
    tFrontNo = tNDSort(PopObj,W);

    %% Selection
    MaxFNo    = find(cumsum(hist(tFrontNo,1:max(tFrontNo)))>=N,1);
    LastFront = find(tFrontNo==MaxFNo);
    LastFront = LastFront(randperm(length(LastFront)));
    tFrontNo(LastFront(1:sum(tFrontNo<=MaxFNo)-N)) = inf;
    Next      = St(tFrontNo<=MaxFNo);
    % Population for next generation
    Population = Population(Next);
end

function tFrontNo = tNDSort(PopObj,W)
% Do theta-non-dominated sorting

    N  = size(PopObj,1);
    NW = size(W,1);

    %% Calculate the d1 and d2 values for each solution to each weight
    normP  = sqrt(sum(PopObj.^2,2));
    Cosine = 1 - pdist2(PopObj,W,'cosine');
    d1     = repmat(normP,1,size(W,1)).*Cosine;
    d2     = repmat(normP,1,size(W,1)).*sqrt(1-Cosine.^2);

    %% Clustering
    [~,class] = min(d2,[],2);

    %% Sort
    theta = zeros(1,NW) + 5;
    theta(sum(W>1e-4,2)==1) = 1e6;
    tFrontNo = zeros(1,N);
    for i = 1 : NW
        C = find(class==i);
        [~,rank] = sort(d1(C,i)+theta(i)*d2(C,i));
        tFrontNo(C(rank)) = 1 : length(C);
    end
end


classdef MOEADM2M_F5 < PROBLEM
% <multi> <real> <large/none>
% Benchmark MOP for testing MOEA/D-M2M

%------------------------------- Reference --------------------------------
% H. Liu, F. Gu, and Q. Zhang, Decomposition of a multiobjective
% optimization problem into a number of simple multiobjective subproblems,
% IEEE Transactions on Evolutionary Computation, 2014, 18(3): 450-455.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Default settings of the problem
        function Setting(obj)
            obj.M = 2;
            if isempty(obj.D); obj.D = 10; end
            obj.lower    = zeros(1,obj.D);
            obj.upper    = ones(1,obj.D);
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,X)
            t = X(:,2:end) - repmat(sin(pi/2*X(:,1)),1,size(X,2)-1);
            g = 2*abs(cos(pi*X(:,1))).*sum(-0.9*t.^2+abs(t).^0.6,2);
            PopObj(:,1) = (1+g).*X(:,1);
            PopObj(:,2) = (1+g).*(1-sqrt(X(:,1)));
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            R(:,1) = linspace(0,1,N)';
            R(:,2) = 1 - sqrt(R(:,1));
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            R = obj.GetOptimum(100);
        end
    end
end


% Count the number of self-loops in the graph
%
% INPUT: adjacency matrix, nxn
% OUTPUT: integer, number of self-loops
%
% Note: in the adjacency matrix representation loops appear as non-zeros on the diagonal
% GB: last updated, Sep 20 2012

function sl=selfLoops(adj)

sl=sum(diag(adj));


function [x,state] = struct_diag(z,task)
%STRUCT_DIAG Diagonal matrix.
%   [x,state] = struct_diag(z) generates x as a diagonal matrix with
%   the elements of the vector z on the diagonal. The structure state
%   stores information which is reused in computing the right and left
%   Jacobian-vector products.
%
%   struct_diag(z,task) computes the right or left Jacobian-vector product
%   of this transformation, depending on the structure task. Use the
%   structure state and add the field 'r' of the same shape as z or the
%   field 'l' of the same shape as x to obtain the structure task for
%   computing the right and left Jacobian-vector products
%
%      (dF(:)/dz(:).')*task.r(:) and
%      (dF(:)/dz(:).')'*task.l(:) + conj((dF(:)/dconj(z(:)).')'*task.l(:)),
%
%   respectively. Here, F(z) represents this transormation, (:) signifies
%   vectorization and the derivative w.r.t. z (conj(z)) is a partial
%   derivative which treats conj(z) (z) as constant. The output has the
%   same shape as x or z for the right and left Jacobian-vector products,
%   respectively.
%
%   See also struct_band, struct_tridiag, struct_tril, struct_triu.

%   Authors: Laurent Sorber (Laurent.Sorber@cs.kuleuven.be)
%            Marc Van Barel (Marc.VanBarel@cs.kuleuven.be)
%            Lieven De Lathauwer (Lieven.DeLathauwer@kuleuven-kulak.be)
%
%   References:
%   [1] L. Sorber, M. Van Barel, L. De Lathauwer, "Structured data fusion,"
%       ESAT-SISTA Internal Report 13-177, KU Leuven, 2013.

if nargin < 2, task = []; end
state = [];

if isempty(task) || (isempty(task.l) && isempty(task.r))
    x = diag(z);
elseif ~isempty(task.r)
    x = diag(task.r);
elseif ~isempty(task.l)
    x = diag(task.l);
end

end


function [GAmp,GTime]=ADCRadial(p)

global VCtl;
global VObj;

tMiddle=p.tMiddle;

% 2D radial encoding
FOV = VCtl.FOVFreq; % choose FOVFreq as real FOV
Res = VCtl.ResFreq; % choose ResFreq as real resolution
ERes = VCtl.R_SampPerSpoke; % choose R_SampPerSpoke as effective radial resolution

GxAmp=(1/FOV)/((VObj.Gyro/(2*pi))*(1/VCtl.BandWidth));
tHalf=1/(2*(VObj.Gyro/(2*pi))*GxAmp*(FOV/Res));
[GAmp1,GTime1]=StdTrap(tMiddle+VCtl.TEAnchorTime-tHalf-VCtl.MinUpdRate, ...
                       tMiddle+VCtl.TEAnchorTime+tHalf+VCtl.MinUpdRate, ...
                       tMiddle+VCtl.TEAnchorTime-tHalf,               ...
                       tMiddle+VCtl.TEAnchorTime+tHalf,               ...
                       1,2,ERes,2);

GAmp=[GAmp1];
GTime=[GTime1];
[GTime,m,n]=unique(GTime);
GAmp=GAmp(m);

end


function [out] = saturation_8(p1,p2,S,Smax,In)
%saturation_8

% Copyright (C) 2019, 2021 Wouter J.M. Knoben, Luca Trotter
% This file is part of the Modular Assessment of Rainfall-Runoff Models
% Toolbox (MARRMoT).
% MARRMoT is a free software (GNU GPL v3) and distributed WITHOUT ANY
% WARRANTY. See <https://www.gnu.org/licenses/> for details.

% Flux function
% ------------------
% Description:  Saturation excess flow from a store with different degrees
%               of saturation (min-max linear variant)
% Constraints:  -
% @(Inputs):    p1   - minimum fraction contributing area [-]
%               p2   - maximum fraction contributing area [-]
%               S    - current storage [mm]
%               Smax - maximum contributing storage [mm]
%               In   - incoming flux [mm/d]

out = (p1+(p2-p1)*S/Smax)*In;

end


function M = getmassmat3(node,elem2dof,volume,type,K)
%% GETMASSMAT Get mass matrix of the finite element space
%
% M = GETMASSMAT(node,elem2dof,volume,type,K) get mass matrix of the finite element
% space specified by elemType.
%
% The type can be:
% - 'P1': full mass matrix for P1 element
% - 'lump': lumped mass matrix for P1 element

N = size(node,1);
NT = length(volume);
Ndof = double(max(elem2dof(:)));

%% Coefficients and default type
if ~exist('type','var'), type = 'P1'; end
if ~exist('K','var'), K = []; end

%% Assembling
n = size(elem2dof,2);
switch n
    case 4  % P1 element
    if strcmp(type,'lump')
        %% Assemble the mass matrix by the mass lumping
        M = accumarray([elem2dof(:,1);elem2dof(:,2);elem2dof(:,3);elem2dof(:,4)],...
                       [volume;volume;volume;volume]/4,[N,1]);
        if exist('K','var') && ~isempty(K) && ~isnumeric(K) % K is a function
            M = K(node).*M;
        elseif exist('K','var') && ~isempty(K) && isnumeric(K) && size(K,1) == N
            M = K.*M;
        end
        M = spdiags(M,0,N,N);
    else
        %% Assemble the full mass matrix
        if exist('K','var') && ~isempty(K) && ~isnumeric(K) % K is a function
            center = (node(elem2dof(:,1),:) + node(elem2dof(:,2),:) + ...
                      node(elem2dof(:,3),:) + node(elem2dof(:,4),:))/4;
            volume = K(center).*volume;
        elseif exist('K','var') && ~isempty(K) && isnumeric(K) && size(K,1) == NT
            volume = K.*volume;
        end
        M = sparse(N,N);
        for i = 1:4
            for j = i:4
                ii = double(elem2dof(:,i));
                jj = double(elem2dof(:,j));
                if (j==i)
                    M = M + sparse(ii,jj,volume/10,N,N);
                else
                    M = M + sparse([ii;jj],[jj;ii],[volume/20; volume/20],N,N);
                end
            end
        end
    end
    case 10 % P2 element
        %% Assemble the full mass matrix using nodal basis
        % indexing follows Poisson3P2
        [lambda, w] = quadpts3(2);
        nQuad = size(lambda,1);
        ii = zeros(55*NT,1); % 55: # of upper triangular entries
        jj = zeros(55*NT,1);
        sM = zeros(55*NT,1);
        phi(:,1) = lambda(:,1).*(2*lambda(:,1)-1);
        phi(:,2) = lambda(:,2).*(2*lambda(:,2)-1);
        phi(:,3) = lambda(:,3).*(2*lambda(:,3)-1);
        phi(:,4) = lambda(:,4).*(2*lambda(:,4)-1);
        phi(:,5) = 4*lambda(:,1).*lambda(:,2);
        phi(:,6) = 4*lambda(:,1).*lambda(:,3);
        phi(:,7) = 4*lambda(:,1).*lambda(:,4);
        phi(:,8) = 4*lambda(:,2).*lambda(:,3);
        phi(:,9) = 4*lambda(:,2).*lambda(:,4);
        phi(:,10)= 4*lambda(:,3).*lambda(:,4);

        index = 0;
        for i = 1:10
            for j = i:10
                Mij = 0;
                for p = 1:nQuad; Mij = Mij + w(p)*phi(p,i).*phi(p,j); end
                Mij = Mij.*volume;
                ii(index+1:index+NT) = double(elem2dof(:,i));
                jj(index+1:index+NT) = double(elem2dof(:,j));
                sM(index+1:index+NT) = Mij;
                index = index + NT;
            end
        end
        diagIdx = (ii == jj);   upperIdx = ~diagIdx;
        M = sparse(ii(diagIdx),jj(diagIdx),sM(diagIdx),Ndof,Ndof);
        MU = sparse(ii(upperIdx),jj(upperIdx),sM(upperIdx),Ndof,Ndof);
        M = M + MU + MU';

end


function [tfr,rtfr,hat] = tfrrpwv(x,t,N,h,trace);
%TFRRPWV Reassigned  pseudo Wigner-Ville distribution.
%	[TFR,RTFR,HAT] = TFRRPWV(X,T,N,H,TRACE)
%	computes the pseudo Wigner-Ville distribution
%	and its reassigned version.
%
%	X     : analysed signal,
%	T     : the time instant(s)      (default : 1:length(X)).
%	N     : number of frequency bins (default : length(X)).
%	H     : frequency smoothing window, H(0) being forced to 1
%	                                 (default : Hamming(N/4)).
%	TRACE : if nonzero, the progression of the algorithm is shown
%	                                 (default : 0).
%	TFR,  : time-frequency representation and its reassigned
%	RTFR    version. When called without output arguments,
%	        TFRRPWV runs TFRQVIEW.
%	HAT   : Complex matrix of the reassignment vectors.
%
%	Example:
%	 sig=fmlin(128,0.1,0.4); t=1:2:128;
%	 h=tftb_window(17,'Kaiser'); tfrrpwv(sig,t,64,h,1);
%
%	See also all the time-frequency representations listed in
%	 the file CONTENTS (TFR*)

%	F. Auger, May-July 1994, July 1995.
%	Copyright (c) 1996 by CNRS (France).
%
%  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 St, Fifth Floor, Boston, MA  02110-1301  USA

if (nargin == 0),
 error('At least 1 parameter required');
end;
[xrow,xcol] = size(x);
if (nargin < 1),
 error('At least 1 parameter is required');
elseif (nargin <= 2),
 N=xrow;
end;

hlength=floor(N/4);
if (rem(hlength,2)==0),
 hlength=hlength+1;
end;

if (nargin == 1),
 t=1:xrow; h = tftb_window(hlength); trace=0;
elseif (nargin == 2)|(nargin == 3),
 h = tftb_window(hlength); trace=0;
elseif (nargin == 4),
 trace = 0;
end;

if (N<0),
 error('N must be greater than zero');
end;
[trow,tcol] = size(t);
if (xcol~=1),
 error('X must have only one column');
elseif (trow~=1),
 error('T must only have one row');
elseif (2^nextpow2(N)~=N),
 fprintf('For a faster computation, N should be a power of two\n');
end;

[hrow,hcol]=size(h); Lh=(hrow-1)/2; h=h/h(Lh+1);
if (hcol~=1)|(rem(hrow,2)==0),
 error('H must be a smoothing window with odd length');
end;

if (tcol==1),
 Dt=1;
else
 Deltat=t(2:tcol)-t(1:tcol-1);
 Mini=min(Deltat); Maxi=max(Deltat);
 if (Mini~=Maxi),
  error('The time instants must be regularly sampled.');
 else
  Dt=Mini;
 end;
 clear Deltat Mini Maxi;
end;

tfr= zeros(N,tcol); tf2= zeros(N,tcol);
if trace, disp('Pseudo Wigner-Ville distribution'); end;
Dh=dwindow(h);
for icol=1:tcol,
 ti= t(icol); taumax=min([ti-1,xrow-ti,round(N/2)-1,Lh]);
 tau=-taumax:taumax; indices= rem(N+tau,N)+1;
 if trace, disprog(icol,tcol,10); end;
 tfr(indices,icol)= h(Lh+1+tau).*x(ti+tau).*conj(x(ti-tau));
 tf2(indices,icol)=Dh(Lh+1+tau).*x(ti+tau).*conj(x(ti-tau));
 tau=round(N/2);
 if (ti<=xrow-tau)&(ti>=tau+1)&(tau<=Lh),
  tfr(tau+1,icol) = 0.5 * ( h(Lh+1+tau) * x(ti+tau,1) * conj(x(ti-tau,xcol))  + ...
                            h(Lh+1-tau) * x(ti-tau,1) * conj(x(ti+tau,xcol))) ;
  tf2(tau+1,icol) = 0.5 * (Dh(Lh+1+tau) * x(ti+tau,1) * conj(x(ti-tau,xcol))  + ...
                           Dh(Lh+1-tau) * x(ti-tau,1) * conj(x(ti+tau,xcol))) ;
 end;
end ;
tfr= real(fft(tfr));
tf2=imag(fft(tf2));
tfr=tfr(:);tf2=tf2(:);
avoid_warn=find(tfr~=0);
tf2(avoid_warn)=round(N*tf2(avoid_warn)./tfr(avoid_warn)/(2.0*pi));
%tf2= round(N*imag(fft(tf2))./tfr/(2.0*pi));
if trace, fprintf ('\nreassignment: \n'); end;
tfr=reshape(tfr,N,tcol);
tf2=reshape(tf2,N,tcol);

rtfr= zeros(N,tcol);
Ex=mean(abs(x(min(t):max(t))).^2); Threshold=1.0e-6*Ex;
for icol=1:tcol,
 if trace, disprog(icol,tcol,10); end;
 for jcol=1:N,
  if abs(tfr(jcol,icol))>Threshold,
   jcolhat= jcol - tf2(jcol,icol);
   jcolhat=rem(rem(jcolhat-1,N)+N,N)+1;
   rtfr(jcolhat,icol)=rtfr(jcolhat,icol) + tfr(jcol,icol) ;
   tf2(jcol,icol)=jcolhat;
  else
   tf2(jcol,icol)=inf;
   rtfr(jcol,icol)=rtfr(jcol,icol) + tfr(jcol,icol) ;
  end;
 end;
end;

if trace, fprintf('\n'); end;
if (nargout==0),
 TFTBcontinue=1;
 while (TFTBcontinue==1),
  choice=menu ('Choose the representation:',...
               'stop',...
               'pseudo Wigner-Ville distribution',...
               'reassigned pseudo Wigner-Ville distribution');
  if (choice==1), TFTBcontinue=0;
  elseif (choice==2),
   tfrqview(tfr,x,t,'tfrpwv',h);
  elseif (choice==3),
   tfrqview(rtfr,x,t,'tfrrpwv',h);
  end;
 end;
elseif (nargout>2),
 hat=tf2;
end;


function [y,bw] = erbspace(fmin,fmax,n)
%ERBSPACE  Equidistantly spaced points on erbscale
%   Usage: y=erbspace(fmin,fmax,n);
%
%   This is a wrapper around |audspace| that selects the erb-scale. Please
%   see the help on |audspace| for more information.
%
%   See also: audspace, freqtoaud

%   AUTHOR : Peter L. Søndergaard

[y,bw] = audspace(fmin,fmax,n,'erb');


function c = upc_check_digit ( p, l, r )

%*****************************************************************************80
%
%% UPC_CHECK_DIGIT returns the check digit of a UPC.
%
%  Discussion:
%
%    UPC stands for Universal Price Code.
%
%    A full UPC is a string of 12 digits, in groups of size 1, 5, 5, and 1,
%    of the form P-LLLLL-RRRRR-C, where:
%
%      P is the one-digit product type code.
%      L is the five-digit manufacturer code.
%      R is the five_digit product code
%      C is the check digit.
%
%  Example:
%
%    0-72890-00011-8
%    0-12345-67890-5
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer P, the one-digit product type code.
%
%    Input, integer L, the five-digit manufacturer code.
%
%    Input, integer R, the five-digit product code.
%
%    Output, integer C, the check digit.
%
  if ( p < 0 | 9 < p )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'UPC_CHECK_DIGIT - Fatal error!\n' );
    fprintf ( 1, '  P < 0 or 9 < P!\n' );
    error ( 'UPC_CHECK_DIGIT - Fatal error!' );
  end

  if ( l < 0 | 99999 < l )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'UPC_CHECK_DIGIT - Fatal error!\n' );
    fprintf ( 1, '  L < 0 or 99999 < L!\n' );
    error ( 'UPC_CHECK_DIGIT - Fatal error!' );
  end

  if ( r < 0 | 99999 < r )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'UPC_CHECK_DIGIT - Fatal error!\n' );
    fprintf ( 1, '  R < 0 or 99999 < R!\n' );
    error ( 'UPC_CHECK_DIGIT - Fatal error!' );
  end

  lc = i4_to_digits_decimal ( l, 5 );
  rc = i4_to_digits_decimal ( r, 5 );

  c = ( p + lc(2) + lc(4) + rc(1) + rc(3) + rc(5) ) * 3 ...
          + lc(1) + lc(3) + lc(5) + rc(2) + rc(4);

  c = mod ( c, 10 );

  c = mod ( 10 - c, 10 );

  return
end


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

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

% extract the velocity data
% note: size(ux) = [1:m+1, 1:n] and size(uy) = [1:m, 1:n+1]
ux = u.xvalue;
uy = u.yvalue;

% check the size of the variable and the mesh dimension
Nxy = phi.domain.dims;
Nx = Nxy(1); Ny = Nxy(2);

% assign to a temp variable for boundary corrections
phi_tmp = phi.value;

% correct the value of phi at the boundary (calculation trick)
% assign the value of the left boundary to the left ghost cells
phi_tmp(1,:) = (phi.value(1,:)+phi.value(2,:))/2;
% assign the value of the right boundary to the right ghost cells
phi_tmp(end,:) = (phi.value(end,:)+phi.value(end-1,:))/2;
% assign the value of the bottom boundary to the bottom ghost cells
phi_tmp(:,1) = (phi.value(:,1)+phi.value(:,2))/2;
% assign the value of the top boundary to the top ghost cells
phi_tmp(:,end) = (phi.value(:,end)+phi.value(:,end-1))/2;

% calculate the average value
xvalue = (ux>0).*phi_tmp(1:Nx+1,2:Ny+1)+ ...
                        (ux<0).*phi_tmp(2:Nx+2,2:Ny+1)+ ...
                        0.5*(ux==0).*(phi.value(1:Nx+1,2:Ny+1)+phi.value(2:Nx+2,2:Ny+1));
yvalue = (uy>0).*phi_tmp(2:Nx+1,1:Ny+1)+ ...
                        (uy<0).*phi_tmp(2:Nx+1,2:Ny+2)+ ...
                        0.5*(uy==0).*(phi.value(2:Nx+1,1:Ny+1)+phi.value(2:Nx+1,2:Ny+2));
phiFaceAverage=FaceVariable(phi.domain, xvalue, yvalue, []);


%% Copyright (C) 2016 Lagu
%% Copyright (C) 2019 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published
%% by the Free Software Foundation; either version 3 of the License,
%% or (at your option) any later version.
%%
%% This software 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 software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defmethod @@sym hilb (@var{n})
%% Return the symbolic Hilbert matrix.
%%
%% Example:
%% @example
%% @group
%% hilb (sym(2))
%%   @result{} ans = (sym 2×2 matrix)
%%       ⎡ 1   1/2⎤
%%       ⎢        ⎥
%%       ⎣1/2  1/3⎦
%% @end group
%% @end example
%%
%% @seealso{@@sym/invhilb}
%% @end defmethod

function y = hilb(x)
  if (nargin ~= 1)
    print_usage ();
  end

  y = pycall_sympy__ ('return Matrix(_ins[0], _ins[0], lambda i,j: 1 / (i + j + 1)),', x);

end

%!test
%! A = hilb (sym(3));
%! B = [sym(1) sym(1)/2 sym(1)/3; sym(1)/2 sym(1)/3 sym(1)/4; sym(1)/3 sym(1)/4 sym(1)/5];
%! assert (isequal (A, B))


function []=createCheckerBoardImage(Nrows,Ncols,squareSize,resolution,path)
%% function for writing a checker board image to be printed for camera clibration in step0.
% The function creates the image and saves it in the desired path.

% INPUT:
% * Nrows: number of rows (uneven)
% * Ncols: number of columns (even)
% * squareSize: size of each square (in meters)
% * resolution: image resolution (pixels per meter)
% * path: path where the image will be saves (including file name)

%%
squareSizePixel=squareSize*resolution;
CB = checkerboardBW(squareSizePixel,Nrows,Ncols);
figure; imshow(CB);
imwrite(CB,[path '\CB_' num2str(Nrows) '_' num2str(Nrows) '_' num2str(squareSize*1000) '.png'],'png','ResolutionUnit','meter','XResolution',resolution); %XResolution=pixels per meter

end

 %%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function fem1d_bvp_quadratic_test04 ( )

%*****************************************************************************80
%
%% FEM1D_BVP_QUADRATIC_TEST04 carries out test case #4.
%
%  Discussion:
%
%    Use A4, C4, F4, EXACT4, EXACT_UX4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 June 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Dianne O'Leary,
%    Scientific Computing with Case Studies,
%    SIAM, 2008,
%    ISBN13: 978-0-898716-66-5,
%    LC: QA401.O44.
%
  n = 11;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'FEM1D_BVP_QUADRATIC_TEST04\n' );
  fprintf ( 1, '  Solve -( A(x) U''(x) )'' + C(x) U(x) = F(x)\n' );
  fprintf ( 1, '  for 0 < x < 1, with U(0) = U(1) = 0.\n' );
  fprintf ( 1, '  A4(X)  = 1.0 + X * X\n' );
  fprintf ( 1, '  C4(X)  = 0.0\n' );
  fprintf ( 1, '  F4(X)  = ( X + 3 X^2 + 5 X^3 + X^4 ) * exp ( X )\n' );
  fprintf ( 1, '  U4(X)  = X * ( 1 - X ) * exp ( X )\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of nodes = %d\n', n );
%
%  Geometry definitions.
%
  x_first = 0.0;
  x_last = 1.0;
  x = linspace ( x_first, x_last, n );
  x = x(:);

  u = fem1d_bvp_quadratic ( n, @a4, @c4, @f4, x );

  uexact = exact4 ( x );

  fprintf ( 1, '\n' );
  fprintf ( 1, '     I    X         U         Uexact    Error\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    fprintf ( 1, '  %4d  %8f  %8f  %8f  %8e\n', ...
      i, x(i), u(i), uexact(i), abs ( u(i) - uexact(i) ) );
  end

  e1 = l1_error ( n, x, u, @exact4 );
  e2 = l2_error_quadratic ( n, x, u, @exact4 );
  h1s = h1s_error_quadratic ( n, x, u, @exact_ux4 );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  l1 norm of error  = %g\n', e1 );
  fprintf ( 1, '  L2 norm of error  = %g\n', e2 );
  fprintf ( 1, '  Seminorm of error = %g\n', h1s );

  return
end
function value = a4 ( x )

%*****************************************************************************80
%
%% A4 evaluates A function #4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 June 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the evaluation point.
%
%    Output, real VALUE, the value of A(X).
%
  value = 1.0 + x .* x;

  return
end
function value = c4 ( x )

%*****************************************************************************80
%
%% C4 evaluates C function #4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 June 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the evaluation point.
%
%    Output, real VALUE, the value of C(X).
%
  value = 0.0;

  return
end
function value = exact4 ( x )

%*****************************************************************************80
%
%% EXACT4 evaluates exact solution #4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 March 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the evaluation point.
%
%    Output, real VALUE, the value of U(X).
%
  value = x .* ( 1.0 - x ) .* exp ( x );

  return
end
function value = exact_ux4 ( x )

%*****************************************************************************80
%
%% EXACT_UX4 evaluates the derivative of exact solution #4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the evaluation point.
%
%    Output, real VALUE, the value of dUdX(X).
%
  value = ( 1.0 - x - x .* x ) .* exp ( x );

  return
end
function value = f4 ( x )

%*****************************************************************************80
%
%% F4 evaluates right hand side function #4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 March 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the evaluation point.
%
%    Output, real VALUE, the value of F(X).
%
  value = ( x + 3.0 * x.^2 + 5.0 * x.^3 + x.^4 ) .* exp ( x );

  return
end


function  [ fx ] = f_VBfree( x,P,u,in )
% IN:
% - x_t : two posterior moments of the mean and variance of u^(o)
% - P : volatility of the moments (2)
% - u_t : previous feedback
% - in : []

theta = exp(P);

o = u(2);
ia = 4*(1-u(1));

mu1 = x(1+ia);
s1 = x(2+ia);
mu2 = x(3+ia);
s2 = x(4+ia);

Eexpx2 = exp(-mu2);%+s2/2);
s1 = 1./(Eexpx2+1./(s1+theta(1)));
mu1 = mu1 + s1.*Eexpx2*(o-mu1);

Esquarederr = (o-mu1).^2 + s1;
s2 = 1./(exp(-mu2)*Esquarederr/2+1./(s2+theta(2)));
mu2 = mu2 - s2.*(1-exp(-mu2)*Esquarederr)/2;

fx = x;
fx(ia+[1:4]') = [mu1;s1;mu2;s2];


function b = r83_to_r8ge ( n, a )

%*****************************************************************************80
%
%% R83_TO_R8GE copies an R83 matrix to a R8GE matrix.
%
%  Discussion:
%
%    The R83 storage format is used for a tridiagonal matrix.
%    The superdiagonal is stored in entries (1,2:N), the diagonal in
%    entries (2,1:N), and the subdiagonal in (3,1:N-1).  Thus, the
%    original matrix is "collapsed" vertically into the array.
%
%  Example:
%
%    Here is how a R83 matrix of order 5 would be stored:
%
%       *  A12 A23 A34 A45
%      A11 A22 A33 A44 A55
%      A21 A32 A43 A54  *
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 January 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%    N must be at least 2.
%
%    Input, real A(3,N), the R83 matrix.
%
%    Output, real B(N,N), the R8GE matrix.
%
  for i = 1 : n
    for j = 1 : n

      if ( j == i-1 )
        b(i,j) = a(3,j);
      elseif ( j == i )
        b(i,j) = a(2,j);
      elseif ( j == i+1 )
        b(i,j) = a(1,j);
      else
        b(i,j) = 0.0;
      end

    end
  end

  return
end


function errplotl(sol,eldata,ev,xy,x,y,fig)
%errplotl   plots solution and error estimate on L-shaped domain
%   errplotl(sol,eldata,ev,xy,x,y,fig)
%   input
%          sol        nodal solution vector
%          eldata     element error vector
%          ev         element mapping matrix
%          xy         vertex coordinate vector
%          x          vector of x-axis interpolation points
%          y          vector of y-axis interpolation points
%          fig        figure number
%
%   IFISS function: DJS; 5 March 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
fprintf('plotting solution and estimated errors... ')
% interpolate to a cartesian product mesh
[X,Y]=meshgrid(x,y);
xysol = griddata(xy(:,1),xy(:,2),sol,X,Y);
[II,JJ]=find(X<0 & Y<0); xysol(II,JJ)=nan;
figure(fig)
subplot(221),contour(X,Y,xysol,20),axis('square')
axis('off'), ellx, title('Finite Element Solution')
subplot(222),mesh(X,Y,xysol),axis('square')
view(330,30)
%%
xx=xy(:,1); yy=xy(:,2);
nel=length(eldata);
% loop over elements
for ielem = 1:nel
xl = xx(ev(ielem,:));
yl = yy(ev(ielem,:));
xc(ielem,1) = 0.25*sum(xl);
xc(ielem,2) = 0.25*sum(yl);
end
%
% interpolate to a cartesian product mesh
x=0.5*(x(1:end-1)+x(2:end));
y=0.5*(y(1:end-1)+y(2:end));
[X,Y]=meshgrid(x,y);
xysol = griddata(xc(:,1),xc(:,2),eldata,X,Y);
[II,JJ]=find(X<0 & Y<0); xysol(II,JJ)=nan;
subplot(223),contour(X,Y,xysol,15),axis('square')
axis('off'), ellx, title('Estimated Error')
subplot(224),mesh(X,Y,xysol),axis('square')
view(330,30)
subplot(111)
fprintf('done\n')
return


classdef MOEADDE_F4 < PROBLEM
% <multi> <real> <large/none>
% Benchmark MOP for testing MOEA/D-DE

%------------------------------- Reference --------------------------------
% H. Li and Q. Zhang, Multiobjective optimization problems with complicated
% Pareto sets, MOEA/D and NSGA-II, IEEE Transactions on Evolutionary
% Computation, 2009, 13(2): 284-302.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Default settings of the problem
        function Setting(obj)
            obj.M = 2;
            if isempty(obj.D); obj.D = 30; end
            obj.lower    = [0,-ones(1,obj.D-1)];
            obj.upper    = ones(1,obj.D);
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,X)
            J1 = 3 : 2 : obj.D;
            J2 = 2 : 2 : obj.D;
            PopObj(:,1) = X(:,1)         + 2*mean((X(:,J1)-0.8*repmat(X(:,1),1,length(J1)).*cos(repmat(2*pi*X(:,1),1,length(J1))+repmat(J1*pi/obj.D/3,size(X,1),1))).^2,2);
            PopObj(:,2) = 1-sqrt(X(:,1)) + 2*mean((X(:,J2)-0.8*repmat(X(:,1),1,length(J2)).*sin(repmat(6*pi*X(:,1),1,length(J2))+repmat(J2*pi/obj.D,size(X,1),1))).^2,2);
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            R(:,1) = linspace(0,1,N)';
            R(:,2) = 1 - R(:,1).^0.5;
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            R = obj.GetOptimum(100);
        end
    end
end


function aij = r8cc_get ( m, n, nz_num, colptr, rowind, a, i, j )

%*****************************************************************************80
%
%% R8CC_GET gets a value of a R8CC matrix.
%
%  Discussion:
%
%    It is legal to request entries of the matrix for which no storage
%    was set aside.  In that case, a zero value will be returned.
%
%    The R8CC format is the double precision sparse compressed column
%    format.  Associated with this format, we have an M by N matrix
%    with NZ_NUM nonzero entries.  We construct the column pointer
%    vector COL of length N+1, such that entries of column J will be
%    stored in positions COL(J) through COL(J+1)-1.  This indexing
%    refers to both the ROW and A vectors, which store the row indices
%    and the values of the nonzero entries.  The entries of the
%    ROW vector corresponding to each column are assumed to be
%    ascending sorted.
%
%    The R8CC format is equivalent to the MATLAB "sparse" format,
%    and the Harwell Boeing "real unsymmetric assembled" (RUA) format.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Iain Duff, Roger Grimes, John Lewis,
%    User's Guide for the Harwell-Boeing Sparse Matrix Collection,
%    October 1992
%
%  Parameters:
%
%    Input, integer M, the number of rows of the matrix.
%
%    Input, integer N, the number of columns of the matrix.
%
%    Input, integer NZ_NUM, the number of nonzero entries.
%
%    Input, integer COLPTR(N+1), indicate where each column's data begins.
%
%    Input, integer ROWIND(NZ_NUM), the row indices.
%
%    Input, real A(NZ_NUM), the nonzero entries.
%
%    Input, integer I, J, the indices of the value to retrieve.
%
%    Output, real AIJ, the value of A(I,J).
%

%
%  Seek sparse index K corresponding to full index (I,J).
%
  k = r8cc_ijk ( m, n, nz_num, colptr, rowind, i, j );
%
%  If no K was found, then be merciful, and simply return 0.
%
  if ( k == -1 )
    aij = 0.0;
  else
    aij = a(k);
  end

  return
end


function geometry_test198 ( )

%*****************************************************************************80
%
%% TEST198 tests SHAPE_POINT_NEAR_2D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 December 2010
%
%  Author:
%
%    John Burkardt
%
  nside = 6;
  ntest = 8;
  center(1:2,1) = [ 3.0; 0.0 ];
  p1(1:2,1) = [ 5.0; 0.0 ];
  ptest(1:2,1:ntest) = [ ...
     3.0, 0.0; ...
     5.0, 0.0; ...
     4.0, 0.0; ...
    10.0, 0.0; ...
     4.0, 1.7320508; ...
     5.0, 2.0 * 1.7320508; ...
     3.0, 1.7320508; ...
     3.0, 1.7320508 / 2.0 ]';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST198\n' );
  fprintf ( 1, '  For a shape in 2D,\n' );
  fprintf ( 1, '  SHAPE_POINT_NEAR_2D computes the nearest\n' );
  fprintf ( 1, '    point to a point;\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of sides:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  %d\n', nside );

  r8vec_print ( 2, center, '  Hexagon center:' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Hexagon vertex #1:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  %8f  %8f\n', p1(1:2,1) );
  fprintf ( 1, '\n' );
  fprintf ( 1, '     I       X            Y              PN     Dist\n' );
  fprintf ( 1, '\n' );

  for i = 1 : ntest

    p(1:2,1) = ptest(1:2,i);

    [ pn, dist ] = shape_point_near_2d ( center, p1, nside, p ) ;

    fprintf ( 1, '  %6d  %10f  %10f  %10f  %10f  %10f\n', ...
      i, p(1:2,1), pn(1:2,1), dist );

  end

  return
end


function linpack_s_test07 ( )

%*****************************************************************************80
%
%% TEST07 tests SGBFA and SGBSL.
%
%  Discussion:
%
%    SGBFA and SGBSL are for general banded matrices.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 June 2009
%
%  Author:
%
%    John Burkardt
%
  n = 100;
  ml = 25;
  mu = 25;
  lda = 2*ml+mu+1;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST07\n' );
  fprintf ( 1, '  For a general banded matrix,\n' );
  fprintf ( 1, '  SGBFA factors the matrix,\n' );
  fprintf ( 1, '  SGBSL solves a factored linear system.\n' );
  fprintf ( 1, '  The matrix size is N = %d\n', n );
%
%  Assign values to matrix A and right hand side B.
%
%  We want to try a problem with a significant bandwidth.
%
  m = ml + mu + 1;
  fprintf ( 1, '  The bandwidth of the matrix is %d\n', m );

  for j = 1 : n

    ilo = max ( 1, j - mu );
    ihi = min ( n, j + ml );

    temp = 0.0;
    for i = ilo : ihi
      a(i-j+m,j) = -1.0;
      temp = temp - 1.0;
    end

    temp = temp + 1.0;
    a(m,j) = 4.0 - temp;
    b(j) = 4.0;

  end
%
%  Force B to be a column vector.
%
  b = b';
%
%  Factor the matrix A.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Factor the matrix.\n' );

  [ a, ipivot, info ] = sgbfa ( a, lda, n, ml, mu );

  if ( info ~= 0 )
   fprintf ( 1, '  Error!  SGBFA returns INFO = %d\n', info );
    return
  end
%
%  Call SGBSL to solve the linear system.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Solve the linear system.\n' );

  job = 0;
  b = sgbsl ( a, lda, n, ml, mu, ipivot, b, job );
%
%  Print the results.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The first and last 5 entries of the solution:\n' );
  fprintf ( 1, '  (All should be 1):\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    if ( i <= 5 | n-5 < i )
      fprintf ( 1, '  %6d  %14f\n', i, b(i) );
    end
    if ( i == 5 )
      fprintf ( 1, '  ......  ..............\n' );
    end
  end

  return
end


function triangle_ncc_rule_test03 ( )

%*****************************************************************************80
%
%% TEST03 tests TRIANGLE_NCC_RULE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 January 2007
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST03\n' );
  fprintf ( 1, '  TRIANGLE_NCC_RULE returns the points and weights\n' );
  fprintf ( 1, '  of an NCC rule for the triangle.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  In this test, we simply check that, for each\n' );
  fprintf ( 1, '  quadrature point, the barycentric coordinates\n' );
  fprintf ( 1, '  sum to 1.\n' );

  rule_num = triangle_ncc_rule_num ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, '      Rule   Suborder    Sum of coordinates\n' );
  fprintf ( 1, '\n' );

  for rule = 1 : rule_num

    suborder_num = triangle_ncc_suborder_num ( rule );

    [ suborder_xyz, suborder_w ] = triangle_ncc_subrule ( rule, suborder_num );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  %8d  %8d\n', rule, suborder_num );
    for suborder = 1 : suborder_num
      xyz_sum = sum ( suborder_xyz(1:3,suborder) );
      fprintf ( 1, '                      %25e\n', xyz_sum );
    end

  end

  return
end


function [ fplanes,cplanes,info ] = tfjigsawsep( f, varargin )
%TFJIGSAWSEP Time frequency jigsaw puzzle tonal-transient separation
%   Usage:  fplanes = tfjigsawsep(f);
%           fplanes = tfjigsawsep(f,r1,r2);
%           fplanes = tfjigsawsep(f,r1,r2,p);
%           [fplanes, cplanes, info] = tfjigsawsep(...);
%
%   Input parameters:
%            f        : Input signal
%            r1       : Significance level of the tonal layer refered to
%                       a white noise reference
%            r2       : Same for the transient layer
%            p        : Proportionfactor of the supertilesizes relative
%                       to the time-, and frequency stepsize
%
%   Output parameters:
%           fplanes   : signallength-by-3 array containing the 3 produced
%                       layers, tonal in fplanes(:,1), transient in
%                       fplanes(:,2) and the noisy residual in fplanes(:,3).
%           cplanes   : 3-by-1 cellarray containing the Gabor coefficients
%                       for the individual layers
%
%   `tfjigsawsep(f)` applies the separation algorithm on the input signal *f*
%   and returns the tonal, the transient and the residual parts.
%   The following default values are used, *r1=r2=0.95*, *p=4* and for the
%   3 Gabor systems:
%
%       "Tonal" system:     g1 = {'hann',4096}; a1 = 512; M1 = 4096;
%
%       "Transient" system: g2 = {'hann',256};  a2 = 32;  M2 = 256;
%
%       "Residual" system:  g3 = {'hann',2048}; a3 = 512; M3 = 2048;
%
%   `tfjigsawsep(f,r1,r2)` works as before, but allows changing threshold
%   parameters *r1* and *r2*. Good values are in range [0.85,0.95].
%   *t2* sometimes has to be chosen larger (~ 1.05), eg. for
%   percussions in music signals.
%
%   `tfjigsawsep(f,r1,r2,p)` (recommended) additionally allows changing the
%   size of the supertiles to a1*p in timesamples and b2*p in
%   frequencysamples. The choice of this particular proportion is
%   reasonable since it provides equal numbers of coefficients of the two
%   Gabor systems in each supertile. Good values are in the range of [1,10],
%   but it depends very much on the type of signal.
%   E.g. for speech signals, higher values yield better results.
%
%   `[fplanes, cplanes, info] = tfjigsawsep(...)` additionally returns
%   a 3 element cell array *cplanes* containing |dgtreal| coefficients
%   of the respective separated layers and a structure *info*, with the
%   parameters used in the algorithm. The relationship between *fplanes*
%   and *cplanes* is the following:

%   Additional parameters:
%   ----------------------
%
%   The function accepts the following flags:
%
%       'ver2' Uses the second version of the algorithm.
%
%       'plot' Plots the separated waveforms and the coefficients.
%
%       'verbose' Information about the boundary condition.
%
%
%   and the following key-value pairs:
%
%       'wintype' Requested windowtype
%
%       'winsize1' and 'winsize2' Windowlengths
%
%       'a1' and 'a2' Time stepsizes
%
%       'M1' and 'M2' Number of frequency channels
%
%       'T' and 'F' Supertile sizes in samples manually - alternative to p!
%
%       'maxit' Maximum number of iterations. The default value is 15.
%
%   Algorithm:
%   ----------
%
%   The algorithm is based on [1]. It transforms a signal into a two-windowed
%   Gabor expansion such that one wide window shall lead to a high frequency
%   resolution (tonal layer is represented well) and a narrow one to a high
%   time resolution (transient layer is repr. well). The resulting Gabor
%   coefficients are respectively considered within rectangular 'supertiles'
%   in the time-frequency plane. An entropy criterion chooses those tiles
%   respectively, where tonal and transient parts of the signal are
%   represented better and are below a estimated threshold. The rest is set
%   to zero. The leftover Gabor coefficients are transformed back and
%   subtracted from the original signal. By applying this procedure
%   iteratively on the residual, tonal and transient layers emerge.
%
%   Examples:
%   ---------
%
%   The following example shows the basic usage of the function:::
%
%     % Load the glockenspiel test signal and add some noise
%     [f,fs] = gspi; f = f + 0.001*randn(size(f));
%     % Setup the parameters
%     p = 2; r1 = 0.92; r2 = 0.93;
%     [fplanes,cplanes,info] = tfjigsawsep(f,r1,r2,p,'plot','ver2','fs',fs);
%
%   See also: dgtreal plottfjigsawsep
%
%   References: jato07

%AUTHOR: Daniel Haider, 2017

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Remarks %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   The residual condition is computed very heuristically, designing it   %
%   more flexible would be a nice improvement of the algorithm.           %
%   It would also be useful to provide parameter settings for specific    %
%   types of signals (ie. speech, music,...) .                            %
%                                                                         %
%   Version 1 of the algorithm (default) works particularly well for      %
%   speech signals, but also for depicting the transient layer            %
%   (eg. percussive elements) nicely in musical signals.                  %
%   Version 2 works particularly well for depicting a nice tonal layer.   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[f,Ls,W,wasrow,remembershape]=comp_sigreshape_pre(f,upper(mfilename),0);

if W>1
    error('%s: Multichannel inputs are not supported.',upper(mfilename));
end

definput.keyvals.r1 = [];
definput.keyvals.r2 = [];
definput.keyvals.p = [];
definput.keyvals.T = [];
definput.keyvals.F = [];
definput.keyvals.wintype = 'hann';
definput.keyvals.winsize1 = 4096;
definput.keyvals.a1 = 512;
definput.keyvals.M1 = 4096;
definput.keyvals.winsize2 = 512;
definput.keyvals.a2 = 64;
definput.keyvals.M2 = 512;
definput.keyvals.maxit = 15;
definput.keyvals.fs = [];
definput.flags.algver = {'ver1','ver2'};
definput.flags.plot = {'noplot','plot'};
definput.flags.verbose = {'noverbose','verbose'};
[flags,kv] = ltfatarghelper({'r1','r2','p','T','F','wintype','winsize1','a1','M1','winsize2','a2','M2'},definput,varargin);

% significance level
r1 = kv.r1;
r2 = kv.r2;
% Gabor system settings
wintype = kv.wintype;
winsize1 = kv.winsize1;
a1 = kv.a1;
M1 = kv.M1;
winsize2 = kv.winsize2;
a2 = kv.a2;
M2 = kv.M2;
% supertile sizes
if isempty(kv.T) && isempty(kv.F)
    if isempty(kv.p)
        p = 4;
    else
        p = kv.p;
    end
    T = a1*p;
    F = dgtlength(Ls,a2,M2)/M2*p;
elseif isempty(kv.p)
    T = kv.T;
    F = kv.F;
else
    error('%s: Use EITHER the proportional setting OR set T and F manually.',upper(mfilename));
end

if winsize1 < winsize2
    error('%s: The tonal system uses a shorter window than the transient system!',upper(mfilename));
end

% why this and not setting the kv on top?
if xor(isempty(r1),isempty(r2))
    error('%s: Both r1 and r2 must be defined.',upper(mfilename));
else
    if isempty(r1), r1 = 0.95; end
    if isempty(r2), r2 = 0.95; end
end

% windows
g1 = {wintype,winsize1};
g2 = {wintype,winsize2};

L1 = dgtlength(Ls,a1,M1);
L2 = dgtlength(Ls,a2,M2);
b1 = L1/M1;
b2 = L2/M2;

complainif_notposint(T,'T',mfilename);
if ~( T < min([L1,L2]) )
    error('%s: Supertile length must be smaller than the signal length [%i]',...
          upper(mfilename),min([L1,L2]));
elseif ~( F < min([L1/2+1,L2/2+1]) )
    error('%s: Supertile height must be smaller than the frequency range [%i]',...
      upper(mfilename),min([L1/2+1,L2/2+1]));
elseif ~( T > max([a1,a1]) )
    error('%s: Supertile length must be larger than the time stepsizes [%i]',...
          upper(mfilename),max([a1,a1]));
elseif ~( F > max([b1,b2]) )
    error('%s: Supertile height must be larger than the frequency stepsizes [%i]',...
          upper(mfilename),max([b1,b2]));
end

% entropy reference from noise signal
% thresholds tau1,tau2 for tonal resp. transient layer are chosen to have
% a certain significance with respect to the estimated reference
[ref1,ref2] = noisest(Ls,g1,g2,a1,a2,M1,M2,T,F);
tau1 = ref1*r1;
tau2 = ref2*r2;

% initialization of residual, layers, min and max number of iterations
% and epsilon, the upper limit for the residual condition, which is
% computed at the kmin-th iteration
% R = postpad(f,L);
R = f;
l1 = zeros(Ls,1);
l2 = zeros(Ls,1);
k = 1;
kmin = 5;
kmax = kv.maxit;
epsilon = 0;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%% main loop %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% runs until all values in R are below epsilon to exclude single peaks
while all(abs(R) < epsilon) ~= 1

    switch flags.algver
       case 'ver1'
        [x1,x2]=jigsaw1(R,g1,g2,a1,a2,M1,M2,T,F,tau1,tau2);
       case 'ver2'
        [x1,x2]=jigsaw2(R,g1,g2,a1,a2,M1,M2,T,F,tau1,tau2);
    end

    % residual parts of the signal
    R = R-x1-x2;
    l1 = l1+x1;
    l2 = l2+x2;

    if k == kmax
        break
    end

    if k == kmin
        % epsilon is computed as upper limit, corresponding to
        % an empirical p-quantile
        epsilon = sort(abs(R),'ascend');
        epsilon = 5/2*epsilon(round(0.998*numel(epsilon)));
        if flags.do_verbose
            disp(['The current maximum in the residual is ',num2str(max(abs(R)))])
            disp(['An upper bound is estimated to be ',num2str(epsilon)])
        end
    end

    k = k+1;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if flags.do_verbose
    disp('max. number of iteration reached: condition for residual is not fulfilled!')
    disp('Try to increase t2 slightly or change the size of the supertiles.')
end

% fplanes as Ls-by-3 array containing the layers
fplanes = [l1,l2,R];
fplanes = postpad(fplanes,Ls);

% info structure
info.g1 = {wintype, winsize1};
info.g2 = {wintype, winsize2};
info.g3 = {wintype, 2048};
info.M1 = M1;
info.M2 = M2;
info.M3 = 2048;
info.a1 = a1;
info.a2 = a2;
info.a3 = 512;
info.supertilesizes = [F,T];
info.noiseentropy_tonal = ref1;
info.threshold_tonal = tau1;
info.noiseentropy_transient = ref2;
info.threshold_transient = tau2;

% cplanes as 3-by-1 cell array containing
% the gabor coefficients corresp. to the layers
if nargout > 1 || flags.do_plot
    cplanes = cell(3,1);
    cplanes{1} = dgtreal(l1,g1,a1,M1);
    cplanes{2} = dgtreal(l2,g2,a2,M2);
    cplanes{3} = dgtreal(R,info.g3,info.a3,info.M3);
end

% option for plots
if flags.do_plot
    plottfjigsawsep(fplanes,cplanes,info,'fs',kv.fs,'showbuttons','equalyrange');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%% compiling functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [ r ] = renyi( t,alpha )

% computes the Renyi entropy for an array
% yields high values for peaky data and
% low values for almost constant

if isempty(t)
    r = inf;
elseif norm(t) == 0
    r = inf;
else
    switch nargin
        case 1
            alpha = 2.4;
            r = (1/(1-alpha))*log2(sum(sum(abs(t).^(2*alpha)))*(sum(sum(abs(t).^2)).^(-alpha)));
        case 2
            if alpha <= 0 || alpha == 1
                error('alpha must be chosen positive and unequal to 1.');
            else
                r = (1/(1-alpha))*log2(sum(sum(abs(t).^(2*alpha))).*norm(t(:),2)^(-2*alpha));
            end
        otherwise
            error('This function takes at least one input argument.');
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [ref1,ref2] = noisest (Ls,g1,g2,a1,a2,M1,M2,T,F)

% computes the entropy for a white noise signal within one supertile
% as estimation reference for the tresholds tau1,tau2

n = noise(Ls,'white');
n1 = dgtreal(n,g1,a1,M1);
n2 = dgtreal(n,g2,a2,M2);
r1 = n1(1:floor(F*M1/Ls),1:floor(T/a1));
r2 = n2(1:floor(F*M2/Ls),1:floor(T/a2));
ref1 = renyi(r1);
ref2 = renyi(r2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%% Version 1 of the jigsaw puzzle algorithm %%%%%%%%%%%%%%%%%%

function [x1,x2] = jigsaw1(R,g1,g2,a1,a2,M1,M2,T,F,tau1,tau2)

% error check?

% signal lengths
Ls = length(R);
L1 = dgtlength(Ls,a1,M1);
L2 = dgtlength(Ls,a2,M2);

% gabor transformations
c1 = dgtreal(R,g1,a1,M1); % M1/2+1-by-L/a1
c2 = dgtreal(R,g2,a2,M2); % M2/2+1-by-L/a2

% frequency hop sizes
b1 = L1/M1;
b2 = L2/M2;

% indices on the TF plane (L/2+1 x L), where the coefficients belong to
aa1 = 1:a1:L1;
aa2 = 1:a2:L2;
bb1 = 1:b1:L1/2+1;
bb2 = 1:b2:L2/2+1;

L = max([L1,L2]);

% find the indices for the coefficients in every single TF-supertile
for m=0:floor((L/2+1)/F)-1
    for n=0:floor(L/T)-1
        f1 = find(bb1<=(m+1)*F & bb1>m*F);
        f2 = find(bb2<=(m+1)*F & bb2>m*F);
        t1 = find(aa1<=(n+1)*T & aa1>n*T);
        t2 = find(aa2<=(n+1)*T & aa2>n*T);
        % look for parts of c1,c2 where tonal/transient parts are repr well
        [c1,c2] = decision1(c1,c2,f1,f2,t1,t2,tau1,tau2);
    end
end

% last column of remaining supertiles
for m=0:floor((L/2+1)/F-1)
    f1 = find(bb1<=(m+1)*F & bb1>m*F);
    f2 = find(bb2<=(m+1)*F & bb2>m*F);
    t1 = find(aa1<=L & aa1>floor(L/T)*T);
    t2 = find(aa2<=L & aa2>floor(L/T)*T);

    [c1,c2] = decision1(c1,c2,f1,f2,t1,t2,tau1,tau2);
end

% upper row of remaining supertiles
for n=0:floor(L/T-1)
    f1 = find(bb1<=L/2+1 & bb1>floor((L/2+1)/F)*F);
    f2 = find(bb2<=L/2+1 & bb2>floor((L/2+1)/F)*F);
    t1 = find(aa1<=(n+1)*T & aa1>n*T);
    t2 = find(aa2<=(n+1)*T & aa2>n*T);

    [c1,c2] = decision1(c1,c2,f1,f2,t1,t2,tau1,tau2);
end

% right upper remaining supertiles
f1 = find(bb1<=L/2+1 & bb1>floor((L/2+1)/F)*F);
f2 = find(bb2<=L/2+1 & bb2>floor((L/2+1)/F)*F);
t1 = find(aa1<=L & aa1>floor(L/T)*T);
t2 = find(aa2<=L & aa2>floor(L/T)*T);

[c1,c2] = decision1(c1,c2,f1,f2,t1,t2,tau1,tau2);

% synthesis with the canonical dual windows
x1 = idgtreal(c1,{'dual',g1},a1,M1,Ls);
x2 = idgtreal(c2,{'dual',g2},a2,M2,Ls);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [c1,c2] = decision1(c1,c2,f1,f2,t1,t2,tau1,tau2)

% decision procedure for version 1
%   case 1: both entropies are above their thresholds -> set them to zero
%   case 2: g1 has a better repr. and the entropy is below its
%           threshold -> set the tile corr. to g2 to zero
%   case 3: vice versa
%   case 4: g1 has a better repr. and its entropy is above its
%           threshold tau1 but despite of that, the entropy corr. to
%           g2 is below its threshold tau2 -> set the tile corr. to
%           g1 to zero
%   case 5: vice versa

E1 = renyi(c1(f1,t1));
E2 = renyi(c2(f2,t2));

if E1 > tau1 && E2 > tau2
    c1(f1,t1) = 0;
    c2(f2,t2) = 0;
else
    if (min([E1,E2]) == E1 && E1 < tau1) || (min([E1,E2]) == E2 && E2 > tau2 && E1 < tau1)
        c2(f2,t2) = 0;
    elseif (min([E1,E2]) == E2 && E2 < tau2) || (min([E1,E2]) == E1 && E1 > tau1 && E2 < tau2)
        c1(f1,t1) = 0;
    else
        warning('something went wrong with the decision criteria!');
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%% Version 2 of the jigsaw puzzle algorithm %%%%%%%%%%%%%%%%%%

function [x1,x2] = jigsaw2(R,g1,g2,a1,a2,M1,M2,T,F,tau1,tau2)

% signal lengths
Ls = length(R);
L1 = dgtlength(Ls,a1,M1);
L2 = dgtlength(Ls,a2,M2);

% frequency hop sizes
b1 = L1/M1;
b2 = L2/M2;

% gabor transformation
c1 = dgtreal(R,g1,a1,M1); % M1/2+1-by-L/a1
c2 = dgtreal(R,g2,a2,M2); % M2/2+1-by-L/a2

% indices on the TF plane (L/2+1 x L), where the coefficients belong to
aa1 = 1:a1:L1;
aa2 = 1:a2:L2;
bb1 = 1:b1:L1/2+1;
bb2 = 1:b2:L2/2+1;

L = max([L1,L2]);

for m=0:floor((L/2+1)/F)-1
    for n=0:floor(L/T)-1
        % find the indices for the coefficients in each TF-supertile
        f1 = find(bb1<=(m+1)*F & bb1>m*F);
        f2 = find(bb2<=(m+1)*F & bb2>m*F);
        t1 = find(aa1<=(n+1)*T & aa1>n*T);
        t2 = find(aa2<=(n+1)*T & aa2>n*T);
        % keep the tonals
        [c1,c2] = decision2ton(c1,c2,f1,f2,t1,t2,tau1);
    end
end

% last column of remaining supertiles
for m=0:floor((L/2+1)/F-1)
    f1 = find(bb1<=(m+1)*F & bb1>m*F);
    f2 = find(bb2<=(m+1)*F & bb2>m*F);
    t1 = find(aa1<=L & aa1>floor(L/T)*T);
    t2 = find(aa2<=L & aa2>floor(L/T)*T);
    % keep the tonals
    [c1,c2] = decision2ton(c1,c2,f1,f2,t1,t2,tau1);
end

% upper row of remaining supertiles
for n=0:floor(L/T-1)
    f1 = find(bb1<=L/2+1 & bb1>floor((L/2+1)/F)*F);
    f2 = find(bb2<=L/2+1 & bb2>floor((L/2+1)/F)*F);
    t1 = find(aa1<=(n+1)*T & aa1>n*T);
    t2 = find(aa2<=(n+1)*T & aa2>n*T);
    % keep the tonals
    [c1,c2] = decision2ton(c1,c2,f1,f2,t1,t2,tau1);
end

% right upper remaining supertile
f1 = find(bb1<=L/2+1 & bb1>floor((L/2+1)/F)*F);
f2 = find(bb2<=L/2+1 & bb2>floor((L/2+1)/F)*F);
t1 = find(aa1<=L & aa1>floor(L/T)*T);
t2 = find(aa2<=L & aa2>floor(L/T)*T);
% keep the tonals
[c1,~] = decision2ton(c1,c2,f1,f2,t1,t2,tau1);

% synthesis of the tonal parts with the canonical dual window of g1
x1 = idgtreal(c1,{'dual',g1},a1,M1,Ls);
RR = R-x1;

% the same procedure is now applied with respect to the narrow window g2

% gabor transformation
c1 = dgtreal(RR,g1,a1,M1); % M1/2+1-by-L/a1
c2 = dgtreal(RR,g2,a2,M2); % M2/2+1-by-L/a2

for m=0:floor((L/2+1)/F)-1
    for n=0:floor(L/T)-1
        % find the indices for the coefficients in each TF-supertile
        f1 = find(bb1<=(m+1)*F & bb1>m*F);
        f2 = find(bb2<=(m+1)*F & bb2>m*F);
        t1 = find(aa1<=(n+1)*T & aa1>n*T);
        t2 = find(aa2<=(n+1)*T & aa2>n*T);
        % keep the transients
        [~,c2] = decision2trans(c1,c2,f1,f2,t1,t2,tau2);
    end
end

% last column of remaining supertiles
for m=0:floor((L/2+1)/F-1)
    f1 = find(bb1<=(m+1)*F & bb1>m*F);
    f2 = find(bb2<=(m+1)*F & bb2>m*F);
    t1 = find(aa1<=L & aa1>floor(L/T)*T);
    t2 = find(aa2<=L & aa2>floor(L/T)*T);
    % keep the transients
    [~,c2] = decision2trans(c1,c2,f1,f2,t1,t2,tau2);
end

% upper row of remaining supertiles
for n=0:floor(L/T-1)
    f1 = find(bb1<=L/2+1 & bb1>floor((L/2+1)/F)*F);
    f2 = find(bb2<=L/2+1 & bb2>floor((L/2+1)/F)*F);
    t1 = find(aa1<=(n+1)*T & aa1>n*T);
    t2 = find(aa2<=(n+1)*T & aa2>n*T);
    % keep the transients
    [~,c2] = decision2trans(c1,c2,f1,f2,t1,t2,tau2);
end

% right upper remaining supertile
f1 = find(bb1<=L/2+1 & bb1>floor((L/2+1)/F)*F);
f2 = find(bb2<=L/2+1 & bb2>floor((L/2+1)/F)*F);
t1 = find(aa1<=L & aa1>floor(L/T)*T);
t2 = find(aa2<=L & aa2>floor(L/T)*T);
% keep the transients
[~,c2] = decision2trans(c1,c2,f1,f2,t1,t2,tau2);

% synthesis of the transient parts with the canonical dual window of g2
x2 = idgtreal(c2,{'dual',g2},a2,M2,Ls);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [c1,c2] = decision2ton(c1,c2,f1,f2,t1,t2,tau1)
% decision procedure for tonals

E1 = renyi(c1(f1,t1));
E2 = renyi(c2(f2,t2));

if min([E1,E2]) == E2 || E1 > tau1
    c1(f1,t1) = 0;
end

function [c1,c2] = decision2trans(c1,c2,f1,f2,t1,t2,tau2)
% decision procedure for transients

E1 = renyi(c1(f1,t1));
E2 = renyi(c2(f2,t2));

if min([E1,E2]) == E1 || E2 > tau2
    c2(f2,t2) = 0;
end


% Test file for trigtech/min.m

function pass = test_min(pref)

% Get preferences.
if ( nargin < 1 )
    pref = trigtech.techPref();
end

testclass = trigtech();

%%
% Spot-check the extrema for a few functions.

pass(1) = test_spotcheck_min(testclass, @(x) -exp(-cos(2*pi*x)), -exp(1), pref);
pass(2) = test_spotcheck_min(testclass, @(x) -sin(10*pi*x), -1, pref);

pass(3) = test_spotcheck_min(testclass, @(x) -exp(sin(pi*x).^100), -exp(1), pref);
pass(4) = test_spotcheck_min(testclass, @(x) -exp(-sin(pi*x).^100), -1, pref);

% Approx to sign function
pass(5) = test_spotcheck_min(testclass, @(x) -4/pi*(sin(pi*x) + ...
    1/3*sin(3*pi*x) + 1/5*sin(5*pi*x) + 1/7*sin(7*pi*x) + 1/9*sin(9*pi*x)), -1.182328208857607, pref);

%%
% Check operation for array-valued inputs.
fun_op = @(x) -[exp(-cos(2*pi*x)) sin(10*pi*x) exp(-sin(pi*(x-0.32)).^100)];
f = testclass.make(fun_op, [], pref);
[y, x] = min(f);
exact_min = -[exp(1) 1 1];
fx = -[exp(-cos(2*pi*x(1))) sin(10*pi*x(2)) exp(-sin(pi*(x(3)-0.32)).^100)];
pass(6) = (all(abs(y - exact_min) < 100*eps) && ...
           all(abs(fx - exact_min) < 10*eps));

%%
% Test for complex-valued trigtech objects.
f = testclass.make(@(x) cos(pi*x) + exp(1i*pi*x), [], pref);
[y, x] = min(f);
exact_min = 1i; % Could be +/- 1i depending on machine.
pass(7) = ( (abs(y - exact_min) < 1e2*vscale(f)*eps) || ...
            (abs(y + exact_min) < 1e2*vscale(f)*eps) );

end

% Spot-check the results for a given function.
function result = test_spotcheck_min(testclass, fun_op, exact_min, pref)

f = testclass.make(fun_op, [], pref);
[y, x] = min(f);
fx = fun_op(x);
result = ((abs(y - exact_min) < 100*vscale(f)*eps) && ...
          (abs(fx - exact_min) < 10*vscale(f)*eps));

end


function dr = Dice_Ratio(SEG, GT)
    % SEG, GT are the binary segmentation and ground truth areas, respectively.
    % dice ratio
    dr = 2*double(sum(uint8(SEG(:) & GT(:)))) / double(sum(uint8(SEG(:))) + sum(uint8(GT(:))));
end


function accuracy = crc(TrainSet, TestSet, train_num, test_num, class_num, lambda, options)
% Collaborative representation based classification (CRC) algorithm
%
% Inputs:
%       TrainSet            train sets of size dxn, where d is dimension and n is number of sets
%       TestSet             test sets of size dxn, where d is dimension and n is number of sets
%       train_num           numner of train sets
%       test_num            numner of test sets
%       class_num           numner of classes
%       lambda              regularization paramter
% Output:
%       accuracy            classification accurary
%
% References:
%       Lei Zhanga, Meng Yanga, and Xiangchu Feng
%       "Sparse Representation or Collaborative Representation: Which Helps Face Recognition?,"
%       Proceedings of the 2011 International Conference on Computer Vision (ICCV'11), pp. 471-478, 2011.
%
%
% Created by H.Kasai on July 04, 2017
%
% Note that this code partially refers the codes written by Meng Yang @ COMP HK-PolyU.

    % extract options
    if ~isfield(options, 'verbose')
        verbose = false;
    else
        verbose = options.verbose;
    end

    if ~isfield(options, 'eigenface')
        eigenface = true;
    else
        eigenface = options.eigenface;
    end

    if ~isfield(options, 'eigenface_dim')
        eigenface_dim = train_num;
    else
        eigenface_dim = options.eigenface_dim;
    end

    % calculate eigenface
    if eigenface
        [disc_set, ~, ~] = Eigenface_f(TrainSet.X, eigenface_dim);
        TrainSet.X_red  =  disc_set' * TrainSet.X;
        TestSet.X_red  =  disc_set' * TestSet.X;
    else
        TrainSet.X_red  =  TrainSet.X;
        TestSet.X_red  =  TestSet.X;
    end

    % normalize data to l2-norm
    [TrainSet_normalized.X, TrainSet_normalized.y] = data_normalization(TrainSet.X, TrainSet.y, 'std');
    [TestSet_normalized.X, TestSet_normalized.y] = data_normalization(TestSet.X, TestSet.y, 'std');

    % calculate projection matrix
    %P = inv(TrainSet_normalized.X' * TrainSet_normalized.X + lambda * eye(size(TrainSet_normalized.X,2))) * TrainSet_normalized.X';
    P = (TrainSet_normalized.X' * TrainSet_normalized.X + lambda * eye(size(TrainSet_normalized.X,2))) \ TrainSet_normalized.X';

    identity = zeros(1, test_num);
    for i = 1 : test_num

        y = TestSet_normalized.X(:,i);

        % CRC RLS classification function
        rho_hat =  P * y;
        err_array = zeros(1, class_num);
        for j = 1 : class_num
            rho_hat_class_j = rho_hat(TrainSet_normalized.y==j);
            X_class_j =  TrainSet_normalized.X(:,TrainSet_normalized.y==j);
            err_array(j) = norm(y - X_class_j*rho_hat_class_j) / sum(rho_hat_class_j.*rho_hat_class_j); % Eq.(10)
        end

        [~, label] = min(err_array);
        identity(i) = label;

        if verbose
            correct = (label == TestSet.y(1, i));
            fprintf('# CRC: test:%03d, predict class: %03d --> ground truth :%03d (%d)\n', i, label, TestSet.y(1, i), correct);
        end
    end

    % calculate accuracy
    correct_num = sum(identity == TestSet.y);
    accuracy = correct_num/test_num;
end


function  [im_out, par] = WSC_Sigma_1AG(par)
im_out    =   par.nim;
% parameters for noisy image
[h,  w, ch]      =  size(im_out);
par.h = h;
par.w = w;
par.ch = ch;
par = SearchNeighborIndex( par );
for ite  =  1 : par.outerIter
    %     % iterative regularization
    im_out = im_out+par.delta*(par.nim - im_out);
    % image to patches and estimate local noise variance
    Y = Image2Patch( im_out, par );
    % estimation of noise variance
    dif = mean( mean( mean( (par.nim-im_out).^2 ) ) );
    par.sigma = sqrt( abs( par.nSig^2 - dif ) );
    % estimation of noise variance
    if mod(ite-1, par.innerIter)==0
        par.nlsp = par.nlsp - par.nlspgap;
        % searching  non-local patches
        blk_arr = Block_Matching( Y, par );
    end
    % Weighted Sparse Coding
    Y_hat = zeros(par.ps2ch, par.maxrc, 'single');
    W_hat = zeros(par.ps2ch, par.maxrc, 'single');
    for i = 1:par.lenrc
        index = blk_arr(:, i);
        nlY = Y( : , index );
        DC = mean(nlY, 2);
        nDCnlY = bsxfun(@minus, nlY, DC);
        % update D and S
        [D, S, ~] = svd( full(nDCnlY), 'econ' );
        S = diag(S);
        % update weight for sparse coding
        Wsc = repmat(bsxfun( @rdivide, par.lambda*par.sigma^2, S + eps ), [1 size(nDCnlY, 2)]);
        % update C by soft thresholding
        B = D' * nDCnlY;
        C = sign(B) .* max( abs(B) - Wsc, 0 );
        % update Y
        nDCnlYhat = D * C;
        % add back DC components
        nlYhat = bsxfun(@plus, nDCnlYhat, DC);
        % aggregation
        Y_hat(:, index) = Y_hat(:, index) + nlYhat;
        W_hat(:, index) = W_hat(:, index) + ones(par.ps2ch, par.nlsp);
    end
    % Reconstruction
    im_out = PGs2Image(Y_hat, W_hat, par);
    % calculate the PSNR and SSIM
    PSNR =   csnr( im_out*255, par.I*255, 0, 0 );
    SSIM      =  cal_ssim( im_out*255, par.I*255, 0, 0 );
    fprintf('Iter %d : PSNR = %2.4f, SSIM = %2.4f\n', ite, PSNR, SSIM);
    par.PSNR(ite, par.image) = PSNR;
    par.SSIM(ite, par.image) = SSIM;
end
return;


function [cum_ret, cumprod_ret, daily_ret, daily_portfolio] ...
    = grw_start(fid, data, varargins, opts)
% This file is an entry for the EG strategy.
%
% function [cum_ret, cumprod_ret, daily_ret, daily_portfolio] ...
%            = grw_start(fid, data, varargins, opts)
% cum_ret: cumulative wealth achived at the end of a period.
% cumprod_ret: cumulative wealth achieved till the end each period.
% daily_ret: daily return achieved by a strategy.
% daily_portfolio: daily portfolios
%
% data: market sequence vectors
% fid: handle for write log file
% varargins: variable parameters
% opts: option parameter for behvaioral control
%
% Example: [cum_ret, cumprod_ret, daily_ret, daily_portfolio] ...
%          = grw_start(fid, data, {0.00005, 0}, opts)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of OLPS: http://OLPS.stevenhoi.org/
% Original authors: Bin LI, Steven C.H. Hoi
% Contributors:
% Change log:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Extract the parameters
sigma =varargins{1};    % Switching parameter
tc = varargins{2};      % transaction cost fee rate

% Run the grw algorithm multiple runs
N=[10 100 200];

fw = ones(3, 1);

for i = 1:3,
    [fw(i, 1)] = grw_run(fid, data, N(i), sigma, tc, opts);
end

A=[ones(1, 3); 1./N; 1./(N.^2)]';
beta = A\fw;

cum_ret = beta(1);

fprintf(1, 'cum_ret:%f\n', cum_ret);

% multiple times, ignore
cumprod_ret = 0;
daily_ret = 0;
daily_portfolio = 0;

end


function obj=stat_ellipse(obj,varargin)
%stat_ellipse() Create confidence ellipses around 2D groups of
% points
%
% Parameters:
% 'type': The default '95percentile' displays an ellipse that
% contains 95% of the points (assuming a bivariate normal
% distribution). The option 'ci' will first compute boostrapped
% 2D means and plot the 95% ellipse around these means
% 'geom': Sets how to display the result 'area' for a shaded
% area or 'line' for a simple contour line.
% 'patch_opts': Provide additional patch properties as name-value
% pairs in a cell array (as if those were options for Matlab's
% built in patch() function)

p=inputParser;
my_addParameter(p,'type','95percentile'); %ci
my_addParameter(p,'geom','area'); %line
my_addParameter(p,'patch_opts',{});
parse(p,varargin{:});

obj.geom=vertcat(obj.geom,{@(dobj,dd)my_ellipse(dobj,dd,p.Results)});
obj.results.stat_ellipse={};
end

function hndl=my_ellipse(obj,draw_data,params)

persistent elpoints;
persistent sphpoints;

%Cache unity ellipse points
if isempty(elpoints)
    res=30;
    ang=0:pi/(0.5*res):2*pi;
    elpoints=[cos(ang); sin(ang)];
    [x,y,z]=sphere(10);
    sphpoints=surf2patch(x,y,z);
end

combx=shiftdim(comb(draw_data.x));
comby=shiftdim(comb(draw_data.y));
combz=shiftdim(comb(draw_data.z));

%If we have "enough" points
if sum(~isnan(combx))>2 && sum(~isnan(comby))>2

    if isempty(draw_data.z)

        r=[combx comby];
        %Using a chi square with 2 degrees of freedom is proper
        %here (tested: generated ellipse do contain 1-alpha of the
        %points)
        k=@(alpha) sqrt(chi2inv(1-alpha,2));

        %If a CI on the mean is requested, we replace the original points
        %with bootstrapped mean samples
        if strcmp(params.type,'ci')
            r=bootstrp(obj.stat_options.nboot,@nanmean,r);
        end

        %Extract mean and covariance
        m=nanmean(r);
        cv=nancov(r);

        %Compute ellipse points
        conf_elpoints=sqrtm(cv)*elpoints*k(obj.stat_options.alpha);

        %Compute ellipse axes
        [evec,eval]=eig(cv);
        if eval(2,2)>eval(1,1) %Reorder
            evec=fliplr(evec);
            eval=fliplr(flipud(eval));
        end
        elaxes=sqrtm(cv)*evec*k(obj.stat_options.alpha);

        obj.results.stat_ellipse{obj.result_ind,1}.mean=m;
        obj.results.stat_ellipse{obj.result_ind,1}.cv=cv;
        obj.results.stat_ellipse{obj.result_ind,1}.major_axis=elaxes(:,1)';
        obj.results.stat_ellipse{obj.result_ind,1}.minor_axis=elaxes(:,2)';

        %plot([0 elaxes(1,1)]+m(1),[0 elaxes(2,1)]+m(2),'k')
        %plot([0 elaxes(1,2)]+m(1),[0 elaxes(2,2)]+m(2),'k')

        switch params.geom
            case 'area'
                hndl=patch(conf_elpoints(1,:)+m(1),conf_elpoints(2,:)+m(2),draw_data.color,'FaceColor',draw_data.color,'EdgeColor',draw_data.color,'LineWidth',2,'FaceAlpha',0.2);

            case 'line'
                hndl=patch(conf_elpoints(1,:)+m(1),conf_elpoints(2,:)+m(2),draw_data.color,'FaceColor','none','EdgeColor',draw_data.color,'LineWidth',2);
        end
        set(hndl,params.patch_opts{:});
        %One matlab version displayed stuff if no output value was set (but
        %crashes 2014a and earlier versions)
        %tmp = set(hndl,params.patch_opts{:});

        center_hndl=plot(m(1),m(2),'+','MarkerFaceColor',draw_data.color,'MarkerEdgeColor',draw_data.color,'MarkerSize',10);
    else

        r=[combx comby combz];
        k=@(alpha) sqrt(chi2inv(1-alpha,3));

        %If a CI on the mean is requested, we replace the original points
        %with bootstrapped mean samples
        if strcmp(params.type,'ci')
            r=bootstrp(obj.stat_options.nboot,@nanmean,r);
        end

        %Extract mean and covariance
        m=nanmean(r);
        cv=nancov(r);

        obj.results.stat_ellipse{obj.result_ind,1}.mean=m;
        obj.results.stat_ellipse{obj.result_ind,1}.cv=cv;
        obj.results.stat_ellipse{obj.result_ind,1}.major_axis=[];
        obj.results.stat_ellipse{obj.result_ind,1}.minor_axis=[];

        conf_sphpoints=sphpoints;
        conf_sphpoints.vertices=bsxfun(@plus,sqrtm(cv)*conf_sphpoints.vertices'*k(obj.stat_options.alpha),m')';
        hndl=patch(conf_sphpoints,'FaceColor',draw_data.color,'EdgeColor','none','LineWidth',2,'FaceAlpha',0.2);

        center_hndl=plot3(m(1),m(2),m(3),'+','MarkerFaceColor',draw_data.color,'MarkerEdgeColor',draw_data.color,'MarkerSize',10);
    end
    obj.results.stat_ellipse{obj.result_ind,1}.ellipse_handle=hndl;
    obj.results.stat_ellipse{obj.result_ind,1}.center_handle=center_hndl;
else
    warning('Not enough points for ellipse')

    obj.results.stat_ellipse{obj.result_ind,1}.mean=NaN;
    obj.results.stat_ellipse{obj.result_ind,1}.cv=NaN;
    obj.results.stat_ellipse{obj.result_ind,1}.major_axis=[];
    obj.results.stat_ellipse{obj.result_ind,1}.minor_axis=[];
    obj.results.stat_ellipse{obj.result_ind,1}.ellipse_handle=[];
    obj.results.stat_ellipse{obj.result_ind,1}.center_handle=[];
end
end


function X_hat = prox_l1(X, tau)
    X_hat = max(abs(X) - tau, 0) .* sign(X);
end


function [exp_apx]=exp_approx3(dboun, exp_par,show_res)

%convert i
nind=find(exp_par(:,2)<=0);
exp_par(nind,2)=-1*exp_par(nind,2);

dind1=dboun(1,1):dboun(1,2);
nd1=dboun(1,2)-dboun(1,1)+1;
dind2=dboun(2,1):dboun(2,2);
nd2=dboun(2,2)-dboun(2,1)+1;
dind3=dboun(3,1):dboun(3,2);
nd3=dboun(3,2)-dboun(3,1)+1;
dind4=dboun(4,1):dboun(4,2);
nd4=dboun(4,2)-dboun(4,1)+1;
nd=nd1+nd2+nd3+nd4;

H=zeros(nd,5);
Y=zeros(nd,1);

H(1:nd1,1)=dind1;
H(1:nd1,3)=1;
H((nd1+1):(nd1+nd2),2)=dind2;
H((nd1+1):(nd1+nd2),4)=1;
H((nd1+nd2+1):(nd1+nd2+nd3),1)=dind3;
H((nd1+nd2+1):(nd1+nd2+nd3),5)=1;
H((nd1+nd2+nd3+1):nd,2)=dind4;
H((nd1+nd2+nd3+1):nd,5)=1;

Rinv1=1./(linspace(dboun(1,1),dboun(1,2),length(dind1)));
Rinv2=1./(linspace(dboun(2,1),dboun(2,2),length(dind2)));
Rinv3=1./(linspace(dboun(3,1),dboun(3,2)^2,length(dind3)));
Rinv4=1./(linspace(dboun(4,1),dboun(4,2)^2,length(dind4)));
HR(1:nd1,1)=dind1.*Rinv1;
HR(1:nd1,3)=Rinv1;
HR((nd1+1):(nd1+nd2),2)=dind2.*Rinv2;
HR((nd1+1):(nd1+nd2),4)=Rinv2;
HR((nd1+nd2+1):(nd1+nd2+nd3),1)=dind3.*Rinv3;
HR((nd1+nd2+1):(nd1+nd2+nd3),5)=Rinv3;
HR((nd1+nd2+nd3+1):nd,2)=dind4.*Rinv4;
HR((nd1+nd2+nd3+1):nd,5)=Rinv4;

Y(1:nd1)=log(exp_par(1,2)*exp_par(1,1).^dind1);
Y((nd1+1):(nd1+nd2))=log(exp_par(2,2)*exp_par(2,1).^dind2);
Y((nd1+nd2+1):(nd1+nd2+nd3))=log(exp_par(3,2)*exp_par(3,1).^dind3);
Y((nd1+nd2+nd3+1):nd)=log(exp_par(4,2)*exp_par(4,1).^dind4);

res=inv(HR'*H)*HR'*Y;
exp_apx=[exp(res(1)) exp(res(3));exp(res(2)) exp(res(4));exp(res(1)) exp(res(5));exp(res(2)) exp(res(5))];
exp_apx(nind,2)=-1*exp_apx(nind,2);

if (show_res==1)
    exp_par(nind,2)=-1*exp_par(nind,2);
    figure;
    for i=1:4
        ind=0:dboun(i,2);
        plot(ind,exp_par(i,1).^ind*exp_par(i,2))
        hold on
        plot(ind,exp_apx(i,1).^ind*exp_apx(i,2),'r')
    end
    grid;
end


function clusterQuantity = clusterAverage(clu, spikeQuantity)
% function clusterQuantity = clusterAverage(clu, spikeQuantity)
%
% get the average of some quantity across spikes in each cluster, given the
% quantity for each spike
%
% e.g.
% > clusterDepths = clusterAverage(clu, spikeDepths);
%
% clu and spikeQuantity must be vector, same size

% using a super-tricky algorithm for this - when you make a sparse
% array, the values of any duplicate indices are added. So this is the
% fastest way I know to make the sum of the entries of spikeQuantity for each of
% the unique entries of clu
[~, spikeCounts] = countUnique(clu);

% convert clu to indices, i.e. just values between 1 and nClusters.
[~,~,cluInds] = unique(clu);

% summation
q = full(sparse(cluInds, ones(size(clu)), double(spikeQuantity)));

% had sums, so dividing by spike counts gives the mean depth of each cluster
clusterQuantity = q./spikeCounts;


function deviance = calc_deviance(trueStructNum,testStructNum,devMargin,planC)
% function deviance = calc_deviance(trueStructNum,testStructNum,devMargin,planC)
%
% Calculates the deviance of testStructNum from trueStructNum.
%
% Deviance = (volume of the true structure missed by the
% test structure + excess volume of the test structure over the true
% structure) / volume of the true structure.
%
% The true structure is 3-d contracted by the devMargin while computing the
% volume of the true structure missed by the test structure.
%
% The true structure is 3-d expanded by the devMargin while computing the
% excess volume of the test structure over the true structure.
%
% Example call:
% trueStructNum = 1; % structure index in planC
% testStructNum = 2; % structure index in planC
% devMargin = 0.2; % cm
% deviance = calc_deviance(trueStructNum,testStructNum,devMargin,planC);
%
% APA, 9/18/2017

if ~exist('planC','var')
    global planC
end
indexS = planC{end};

numStructs = length(planC{indexS.structures});

% Expand the test structure by amount equal to the devMargin
planC = createExpandedStructure(trueStructNum, devMargin, planC);
expandedStructNum = numStructs + 1;

% Contract the test structure by amount equal to the devMargin
planC = createExpandedStructure(trueStructNum, -devMargin, planC);
contracttructNum = numStructs + 2;

% Create a structure that's equal to the excess test volume
planC = createDifferenceStructure(testStructNum,expandedStructNum, planC);
excessTestStructNum = numStructs + 3;

% Create a structure that's equal to the excess true volume
planC = createDifferenceStructure(contracttructNum,testStructNum, planC);
excessTrueStructNum = numStructs + 4;

% Calculate the excess test and true volumes in cc
excessTestVol = getStructureVol(excessTestStructNum,planC);
excessTrueVol = getStructureVol(excessTrueStructNum,planC);

% delete the intermediate structures
for strToDelete = numStructs+4:-1:numStructs+1
    planC = deleteStructure(planC,strToDelete);
end

% Add them up
deviance = excessTestVol + excessTrueVol;

% Normalize by the true volume
trueVol = getStructureVol(trueStructNum,planC);

deviance = deviance / trueVol;