%
% Demo of the perceptron learning rule.  Invoke with
% "perceptrondemo", then hit return to cycle through training
% examples.
%
% Originally downloaded from http://www.cs.cmu.edu/~gbordon/SVMs/perceptrondemo.m
% and subsequently modified by Marco Cuturi

function perceptrondemo
load cmap;
rand('state',0);
Npos=15;
Nneg=10;
figure(1)
clf

pos = randn(Npos,1)*.5+2;
neg = randn(Nneg,1)*.4+4.5;
xpos = [sin(pos)+.4*rand(size(pos)), cos(pos)+.4*rand(size(pos)), ones(size(pos))];
xneg = [sin(neg)+.4*rand(size(neg)), cos(neg)+.4*rand(size(neg)), ones(size(neg))];
xs = [xpos; xneg]; ys = [ones(size(pos)); -ones(size(neg))];
perm = randperm(Npos+Nneg);
xs = xs(perm,:);
ys = ys(perm);

w = -[1.3 1.95 .5]';



%% draw points only
oldw = w;

hyperp = @(x,y) [x,y,1]*w;
hold on

colormap(cmap);
colorbar;
plot(xpos(:,1),xpos(:,2),'ro',xneg(:,1),xneg(:,2),'bo', ...
    'LineWidth',2,'MarkerSize',10)
axis([-2 2 -2 2]);
pause;

%% draw first random line + points
ezcontourf(hyperp,[-2 2 -2 2]);
h = drawline(oldw,3);
set(h,'LineWidth',2);
h = drawline(w,3);
plot(xpos(:,1),xpos(:,2),'ro',xneg(:,1),xneg(:,2),'bx', ...
    'LineWidth',2,'MarkerSize',10)
axis([-2 2 -2 2]);
plot(0,0,'k+', 'MarkerSize',3);
title('Data points and separation surface');
hold off

pause;

%% Start loop
for j = 1:10,
    for i = 1:length(xs)        
        oldw = w;        
        ex = xs(i,:);
        py = sign(ex*w);      
        ty = ys(i);                

        hyperp = @(x,y) [x,y,1]*oldw;

        %',vect2str(w,'openingDelimiter','[','closingDelimiter',']'),')'
        clf;
        figure(1);
        hold on
        ezcontourf(hyperp,[-2 2 -2 2]);
        colormap(cmap);
        colorbar;

        plot(xpos(:,1),xpos(:,2),'ro',xneg(:,1),xneg(:,2),'bx', ...
            'LineWidth',2,'MarkerSize',10)
        hold on
        plot(ex(1),ex(2),'bs','MarkerSize',20);
        
        h = drawline(oldw,3);
        set(h,'LineWidth',3);
        
        if (py ~= ty)
            w = w + ex'*ty;
            pause;
        end

        
        h = drawline(w,3);
        
        axis equal
        axis([-2 2 -2 2]);
        plot(0,0,'k+', 'MarkerSize',3);
        title('Data points and separation surface');
        hold off
        pause
        
    end
end


function h = drawline(w, scale)

x = w(1);
y = w(2);
c = w(3);

len = sqrt(x*x+y*y+1e-6);
k = -c / (len*len);

nx = x/len;
ny = y/len;

h = line([k*x-ny*scale k*x+ny*scale], [k*y+nx*scale k*y-nx*scale]);