function r = clumpthem(mm,TolX,TolFun)
%   CLUMPTHEM aggregates solutions into according to unique minima.
% mm is a vector of GlobalOptimSolutions, as returned by MultiStart or
% GlobalSearch. TolX and TolFun are positive numbers. clumpthem places
% solutions in the same entry of the resulting vector mc when the
% solutions differ in value by less than TolFun, and differ in distance by
% less than TolX. The output r is a structure with the following fields:
% * X - the point with lowest Fval among those clumped together
% * Fval - the function value at the point X
% * Exitflag - the exit flag of the solution X
% * Output - the output structure of the solution X
% * X0 - cell array of all starting points that are clumped together

% Copyright 2009-2014 The MathWorks, Inc.

% Create a structure from the solution vector mm.
nSol = numel(mm); % Number of solutions
r = struct('X',[],'Fval',[],'Exitflag',[],'Output',[],'X0',{[]});
r = repmat(r,1,nSol);
for i = 1:nSol;
    r(i).X = mm(i).X;
    r(i).Fval = mm(i).Fval;
    r(i).Exitflag = mm(i).Exitflag;
    r(i).Output = mm(i).Output;
    r(i).X0 = mm(i).X0;
end

topnum = nSol; % Number of solutions left to examine
i = 1; % Prepare to examine all the results with similar Fval
while i < topnum
    fi = r(i).Fval; % Smallest Fval in this clump
    xi = r(i).X; % Location of smallest Fval
    j = i + 1;
    while (j <= topnum) && (r(j).Fval <= fi + TolFun) % Not too big an Fval
        if norm(r(j).X - xi) <= TolX % If close in X
            r(i).X0 = [r(i).X0,r(j).X0]; % Add to X0 array
            if j < topnum % Then remove that one
                r(j:end-1) = r(j+1:end);
             end
            r(end) = []; % Shrink solution structure
            topnum = topnum - 1; % Account for new size of structure
        else
            j = j + 1; % Otherwise look at next solution
        end
    end
    i = i + 1; % Start another clump, if there are solutions yet unclumped
end
