function DV = GGCCDtiming(type2FS, defuzzMethod);

% DV = GGCCDtiming(type2FS, defuzzMethod);
% defuzzifies a generalised type-2 fuzzy set to give an x-value
% firstly type reduces the type-2 fuzzy set to a type-1 fuzzy set using GGCCD,
% secondly defuzzifies the type-1 set using defuzzMethod
%
% SG 080917

% TYPE REDUCTION [(x,u,z) --> (x,z)] --------------------------------------

matrixSize = size(type2FS);
domainSize = matrixSize(2);
codomainSize = matrixSize(1);

xVector = 0:1/(domainSize-1):1;
uVector = 0:1/(codomainSize-1):1;
VSCuVector = linspace(0,0,domainSize); % initialise u centroids of each VS
VSCzVector = linspace(0,0,domainSize); % initialise z centroids of each VS (z^j)
LMFuVector = linspace(0,0,domainSize); % initialise LMF primary membership grades
LMFzVector = []; % initialise vector of LMF secondary membership grades (z_0^j)
rVector  = linspace(0,0,domainSize); % initialise blur vector
RESAvector = linspace(0,0,domainSize); % initialise RESA
minSecGradeEmbSetMatrix = zeros(codomainSize, domainSize); % initialise minimum secondary grades of embedded sets
sumMinSecGradeEmbSetVector = linspace(0,0,domainSize); % initialise VS sums of minimum secondary grades of embedded sets
blurMatrix = zeros(codomainSize, domainSize); % initialise blur matrix

for columnCounter = 1:domainSize % work through all the VSs
    zVector = type2FS(:,columnCounter); % z grades on the VS
    VSCuVector(columnCounter) = defuzz(uVector, zVector, 'centroid');
    zGradeIndex = find(type2FS(:,columnCounter)); % indices of codomain with non-zero z grades
    numberNonZeroGrades = nnz(zGradeIndex);
    if (type2FS(1,columnCounter) == 0) & (type2FS(codomainSize,columnCounter) ~= 0)
        numberNonZeroGrades = numberNonZeroGrades+1;
    elseif (type2FS(1,columnCounter) ~= 0) & (type2FS(codomainSize,columnCounter) == 0)
        numberNonZeroGrades = numberNonZeroGrades+1;
    elseif (type2FS(1,columnCounter) == 0) & (type2FS(codomainSize,columnCounter) == 0)
        numberNonZeroGrades = numberNonZeroGrades+2;
    end
    VSCzVector(columnCounter) = sum(zVector)/numberNonZeroGrades; % vector of secondary membership function (as line) centroids
end

for columnCounter = 1:domainSize % work through all the VSs
    LMFuIndexVector(columnCounter) = find(type2FS(:,columnCounter)~=0, 1, 'first'); % vector of u index of first non-zero elements of each VS
    UMFuIndexVector(columnCounter) = find(type2FS(:,columnCounter)~=0, 1, 'last'); % vector of u index of last non-zero elements of each VS
end

for columnCounter = 1:domainSize % work through all the VSs
    LMFz = type2FS(LMFuIndexVector(columnCounter), columnCounter);
    LMFzVector = [LMFzVector LMFz]; % vector of LMF secondary membership grades (z_0^j)
end

for columnCounter = 1:domainSize % work through all the VSs
    for rowCounter = LMFuIndexVector(columnCounter):UMFuIndexVector(columnCounter) % work through all non-zero elements on the VSs
        minSecGradeEmbSetMatrix(rowCounter, columnCounter) = min([VSCzVector(1:columnCounter-1), type2FS(columnCounter, rowCounter), LMFzVector(columnCounter+1:domainSize)]); % minimum secondary grade of ES B^j_i (Z_B^j_i)
    end
end

LMFuVector = (LMFuIndexVector-1)/(codomainSize-1); % vector of u grade of LMF
scalarCardLMF = sum(LMFuVector); % scalar cardinality of LMF (||L||)

for columnCounter = 1:domainSize % work through all the VSs
    sumMinSecGradeEmbSetVector(columnCounter) =  sum(minSecGradeEmbSetMatrix(:,columnCounter)); % sum of Z_B^j_i on each VS (||B_I||)
end

for columnCounter = 1:domainSize % work through all the VSs
    for rowCounter = LMFuIndexVector(columnCounter):UMFuIndexVector(columnCounter) % work through all non-zero elements on the VSs
        blurMatrix(rowCounter, columnCounter) = (rowCounter - LMFuIndexVector(columnCounter))/(codomainSize-1); %- type2FS(columnCounter, LMFuIndexVector(columnCounter)) % blur of each primary membership grade relative to LMF (B^I_i)
    end
end

innerFractionNumerMatrix = blurMatrix .* minSecGradeEmbSetMatrix;
innerFractionDenomMatrix = scalarCardLMF + blurMatrix;
innerFractionMatrix = innerFractionNumerMatrix ./ innerFractionDenomMatrix;

for columnCounter = 1:domainSize % work through all the VSs
    sumInnerFractionVector(columnCounter) = sum(innerFractionMatrix(:,columnCounter));
end

outerFractionNumerVector = scalarCardLMF * sumInnerFractionVector;
outerFractionDenomVector = sumMinSecGradeEmbSetVector - sumInnerFractionVector;

for columnCounter = 1:domainSize % work through all the VSs
    if outerFractionDenomVector(columnCounter) < 0.0000001
        rVector(columnCounter) = 0;
    else
        rVector(columnCounter) = outerFractionNumerVector(columnCounter) ./ outerFractionDenomVector(columnCounter);
    end
end

RESAvector = LMFuVector + rVector;

% DEFUZZIFICATION [(x,z) --> x] -------------------------------------------

DV = defuzz(xVector, RESAvector, defuzzMethod); % defuzzify the type-1 fuzzy set 

% fprintf('\n')
% fprintf('Defuzzified value: %0.10f \n', DV)

% plot(xVector, RESAvector, 'LineWidth',2)
% xlabel('primary domain')
% ylabel('secondary domain')
