function [data,model] genlsdata( dim, num_data, margin )
% GENLSDATA Generates linearly separable binary data.
%
Synopsis:
%  data = genlsdata(dim,num_data,margin)
%
Description:
%  It generates randomly binary labeled vectors which 
%  are linearly separable with prescribed margin. 

Input:
%  dim [1x1] Data dimension.
%  num_data [1x1] Number of generated data.
%  margin [1x1] Minimal ensured margin (distance of the closest
%   vector to the separating hyperplane).
%
Output:
%  data [struct] Generated data:
%   .X [dim x num_data] Sample data.
%   .y [1 x num_data] Data labels (1 or 2).
%
%  model [struct] Ground truth linear classifier:
%   .W [dim x 1] Normal vector of separating hyperplane.
%   .b [1x1] Bias of the hyperplane.
%
Example:
%  data = genlsdata(2,50,1);
%  model = ekozinec( data );
%  model.margin
%  figure; ppatterns(data); pline(model);
%
% See also 
%  PERCEPTRON, EKOZINEC, LINCLASS, SVM.
%

About: Statistical Pattern Recognition Toolbox
% (C) 1999-2003, Written by Vojtech Franc and Vaclav Hlavac
% <a href="http://www.cvut.cz">Czech Technical University Prague</a>
% <a href="http://www.feld.cvut.cz">Faculty of Electrical Engineering</a>
% <a href="http://cmp.felk.cvut.cz">Center for Machine Perception</a>

Modifications:
% 3-may-2004, VF
% 16-Feb-2003, VF
% 26-feb-2001 V.Franc


data.X = 2*rand(dim, num_data )-1;
if nargin == 3,
  data.X = data.X*margin*10;
end

model.W = 2*rand(dim,1)-1;
model.b = 0;
data.y = linclass(data.X,model);
model.b = rand(1);
data.X = data.X - model.b/sum(model.W);

if nargin ==3,

  inx1 = find(data.y == 1);
  proj1 = (model.W'*data.X(:,inx1) + model.b)/norm(model.W);
  shift1 = max([ones(1,length(inx1))*margin ; proj1]) - proj1;
  data.X(:,inx1) = data.X(:,inx1) + ...
      (model.W*ones(1,length(inx1))/norm(model.W)).*(ones(dim,1)*shift1);

  inx2 = find(data.y == 2);
  proj2 = -(model.W'*data.X(:,inx2) + model.b)/norm(model.W);
  shift2 = max([ones(1,length(inx2))*margin ; proj2]) - proj2;
  data.X(:,inx2) = data.X(:,inx2) - ...
      (model.W*ones(1,length(inx2))/norm(model.W)).*(ones(dim,1)*shift2);
end

return;