function [samples, y, a, a0] = generate_data(nbNode, nbSamplePerNode, nbGroup, spaceDim)
% 
% Generate the samples
% 
% 
% SAMPLES: sample matrix
%   [nbNode * nbSamplePerNode, spaceDim] matrix
%   The indexing works as follow:
%       NodeID*nbSamplePerNode + [0;nbSamplePerNode]
% 
% Y: labels {-1; +1}
%   [nbNode * nbSamplePerNode, 1] matrix
% 
% A: hyperplane parameters, for each group. the parameters are stacked
% along the 2nd axis
%   [spaceDim, nbGroup] matrix
% 
% A0: intercept term for the hyperplane, for each group
%   [1, nbGroup] matrix
%   

if (mod(nbNode, nbGroup) ~= 0)
   warning('Most probably a mistake in the input'); 
end

if (spaceDim <= 0) || (nbGroup <= 0) || (nbSamplePerNode <=0) || (nbNode <= 0)
   error('Error in the input'); 
end


nbNodePerGroup = floor(nbNode/nbGroup);

% Initialize
y = [];
a = [];
a0 = [];
samples = [];


% We treat each group separately
% Each group has its own "ground truth" separating hyperplane [b', b0]'
for i=1:nbGroup
    
    % First we generate the separating hyperplane and the samples
    b0 = normrnd(0, 1);
    b = normrnd(0, 1, [spaceDim, 1]);
    noise = normrnd(0, 1, [nbNodePerGroup*nbSamplePerNode, 1]);
    groupSamples = normrnd(0, 1, [nbNodePerGroup * nbSamplePerNode, spaceDim]);

    % Then the labels
    z = sign(groupSamples * b + b0 + noise);
    % Finally, we update the record
    y = [y; z];
    a = [a, b];
    a0 = [a0,b0];
    samples = [samples; groupSamples];
end




end