% seMCD: Sequentially implemented Monte Carlo depth computation with 
% statistical guarantees
% by Felix Gnettner, Claudia Kirch and Alicia Nieto-Reyes

% Code for Section 5.3.2

% Define the burn-in m, the number of steps N after which the seMCD 
% algorithm is forced to stop, the size n of the training data samples and 
% the weight function with its parameters gamma1 and gamma2

N=450000;
m=500;
gamma1=0.1;
gamma2=0.4;
n=1000;
f=@(t)((1+t).^(gamma1+gamma2-1))./t.^(gamma1);

% Load the banana data, set the value of the asymptotic quantile for the
% stopping rule as well as the seed for the random number generator
load('Section5_3_2Data.mat')
quant=2.666525073843499;
rng(15);

% Split the data set into two parts associated with the two classes
S1=BANANA(1:(INDEX-1),[1 2 4 6]);
S2=BANANA(INDEX:end,[1 2 4 6]);

% Split the data set into test and training data
Perm1=randperm(size(S1,1));
Perm2=randperm(size(S2,1));
Sample1=S1(Perm1(1:n),:);
Sample2=S2(Perm2(1:n),:);
SampleTest=[S1(Perm1((n+1):end),:);S2(Perm2((n+1):end),:)];

% Define the buckets
Buckets=[-1,0;
    -0.001,0.001;
    0,1];
Proba=unique(Buckets);

% Initialise the arrays for the stopping times, the buckets and the point
% estimates
iSmoothStopVarianceEstimate=zeros(size(SampleTest,1),1);
SSmoothStopVarianceEstimate=zeros(size(SampleTest,1),1);
BucketSmoothStopVarianceEstimate=zeros(size(SampleTest,1),2);

% Run the seMCD classification algorithm for each point in the test data
for j=1:1:size(SampleTest,1)

    % Initialise the sum S, the squared sum S2, the confidence sequence,
    % the counter i for the number of summands and a variable CONDITION for
    % checking if the stopping condition of the seMCD algorithm is
    % satisfied
    x=SampleTest(j,:);
    S=0;
    S2=0;
    UMaxSmoothVarianceEstimate=-1;
    LMinSmoothVarianceEstimate=1;
    i=1;
    CONDITION=0;
    
    % Run the seMCD algorithm as long as the stopping condition is not
    % satisfied
    while CONDITION==0
        % Sequential computation of the spherical depth difference  
        % including variance estimation
        INDEXSAMPLE1=randperm(n);
        INDEXSAMPLE2=randperm(n);
        DIFF=((Sample1(INDEXSAMPLE1(1),:)-x)*(Sample1(INDEXSAMPLE1(2),:)-x)'<=0)-((Sample2(INDEXSAMPLE2(1),:)-x)*(Sample2(INDEXSAMPLE2(2),:)-x)'<=0);
        S=S+(DIFF);
        S2=S2+(DIFF).^2;
        VarEstim=(S2-S^2/i)/(i-1);
        
        % Within the first 10 steps, the algorithm cannot stop in order to
        % appropriately estimate the variance
        if i>10
            
            % The algorithm can only stop when the estimated variance is
            % strictly positive
            if VarEstim>0
                
                % seMCD algorithm with updating the confidence sequence,
                % the current number of sampling steps and the current
                % value of the sequentially computed sum                
                if ~ismember([UMaxSmoothVarianceEstimate,LMinSmoothVarianceEstimate],Buckets,'rows')
                    IndexUSmoothVarianceEstimate=sum(S>=(i.*Proba + quant*sqrt(m*VarEstim)./(f(i./m))));
                    if IndexUSmoothVarianceEstimate>0
                        if (UMaxSmoothVarianceEstimate<Proba(IndexUSmoothVarianceEstimate))&&(CONDITION==0)
                            UMaxSmoothVarianceEstimate=Proba(IndexUSmoothVarianceEstimate);
                            if LMinSmoothVarianceEstimate-UMaxSmoothVarianceEstimate<=0
                                UMaxSmoothVarianceEstimate=Proba(IndexUSmoothVarianceEstimate-1);
                                CONDITION=1;
                            end
                        end
                    end
                    auxSmoothVarianceEstimate=sum(S<=(i.*Proba - quant*sqrt(m*VarEstim)./(f(i./m))));
                    IndexLSmoothVarianceEstimate=numel(Proba)-auxSmoothVarianceEstimate+1;
                    if auxSmoothVarianceEstimate>=1
                        if LMinSmoothVarianceEstimate>Proba(IndexLSmoothVarianceEstimate)&&(CONDITION==0)
                            LMinSmoothVarianceEstimate=Proba(IndexLSmoothVarianceEstimate);
                            if LMinSmoothVarianceEstimate-UMaxSmoothVarianceEstimate<=0
                                LMinSmoothVarianceEstimate=Proba(IndexLSmoothVarianceEstimate+1);
                                CONDITION=1;
                            end
                        end
                    end
                    iSmoothStopVarianceEstimate(j)=i;
                    SSmoothStopVarianceEstimate(j)=S;
                    BucketSmoothStopVarianceEstimate(j,:)=[UMaxSmoothVarianceEstimate,LMinSmoothVarianceEstimate];
                end
            end
        end

        % The algorithm stops as soon as the number of maximum sampling
        % steps has been reached or the confidence sequence entails a
        % sufficiently short confidence interval that falls into one of the
        % buckets        
        if i>N
            CONDITION=1;
        end 
        if sign(UMaxSmoothVarianceEstimate)*sign(LMinSmoothVarianceEstimate)>=0
            CONDITION=1;
        end
        if (UMaxSmoothVarianceEstimate==Buckets(2,1))&&(LMinSmoothVarianceEstimate==Buckets(2,2))
            CONDITION=1;
        end
        
        % Update the counter i
        i=i+1;
    end

end

% Compute the amount of correct and wrong classifications within the test
% data as well as the amount undecided classifications and the amount of
% terminations without any decision
CorrectlyClassified=(sum((BucketSmoothStopVarianceEstimate(2995:end,2)==0).*(BucketSmoothStopVarianceEstimate(2995:end,1)==-1))+...
sum((BucketSmoothStopVarianceEstimate(2995:end,2)==-0.001).*(BucketSmoothStopVarianceEstimate(2995:end,1)==-1))+...
sum((BucketSmoothStopVarianceEstimate(1:2994,2)==1).*(BucketSmoothStopVarianceEstimate(1:2994,1)==0.001))+...
sum((BucketSmoothStopVarianceEstimate(1:2994,2)==1).*(BucketSmoothStopVarianceEstimate(1:2994,1)==0)))/6000

WrongClassified=(sum((BucketSmoothStopVarianceEstimate(1:2994,2)==0).*(BucketSmoothStopVarianceEstimate(1:2994,1)==-1))+...
sum((BucketSmoothStopVarianceEstimate(1:2994,2)==-0.001).*(BucketSmoothStopVarianceEstimate(1:2994,1)==-1))+...
sum((BucketSmoothStopVarianceEstimate(2995:end,2)==1).*(BucketSmoothStopVarianceEstimate(2995:end,1)==0.001))+...
sum((BucketSmoothStopVarianceEstimate(2995:end,2)==1).*(BucketSmoothStopVarianceEstimate(2995:end,1)==0)))/6000

TerminatedAfterMaxIterations=sum(iSmoothStopVarianceEstimate==max(iSmoothStopVarianceEstimate))/6000

UndecidedClassified=(sum((BucketSmoothStopVarianceEstimate(1:end,1)==-0.001).*(BucketSmoothStopVarianceEstimate(1:end,2)==0.001))+...
sum((BucketSmoothStopVarianceEstimate(1:end,1)==0).*(BucketSmoothStopVarianceEstimate(1:end,2)==0.001))+...
sum((BucketSmoothStopVarianceEstimate(1:end,1)==-0.001).*(BucketSmoothStopVarianceEstimate(1:end,2)==0))+...
sum((BucketSmoothStopVarianceEstimate(1:end,1)==0).*(BucketSmoothStopVarianceEstimate(1:end,2)==0)))/6000

% Comparison with Naive Bayes Classifier
Mdl = fitcnb([Sample1;Sample2],[zeros(1000,1);ones(1000,1)]);
ClassifBayes=predict(Mdl,SampleTest);
CorrectlyClassifiedNaiveBayes=(sum(ClassifBayes(1:2994)==0)+sum(ClassifBayes(2995:end)==1))/6000;




