% Classification of Iris dataset  into 2 classes using linear least squares,
%  linear and quadratic perceptron learning

  clear
 close all

%% Load the Iris data set
dataset_name = "Iris";
data = csvread("iris.csv");
Xiris = data(:, 1)';
Yiris = data(:, 2)';
Ciris = data(:, 3)';

x = Xiris(1, :);
y = Yiris(1, :);
class = Ciris(1, :);


d=1;  % degree of the polynomial

%number of discretization points or rows in the matrix A
m=size(x,2);

A=[];

classx1 = x(class==1);
classx2 = x(class==0);

classy1 = y(class==1);
classy2 = y(class==0);
  
hyp =   zeros(1,m);

%  LS for problem min ||A omega - t||   where A =[1; x; y], t = class
A = [ones(numel(x), 1) x' y'];
w = A\(class');

decision_linels = zeros(1,2);
coor(1)= min(x);
  coor(2)=max(x);
for i=1:1:2
decision_linels(i) =  (0.5-w(1))/w(3) - (w(2)/w(3))*coor(i);
end

%*************************************************************************
%*******************  perceptron learning algorithm **********************
%*************************************************************************
% init weights  
weight= rand(3,1);
hyp =   zeros(1,m);

x = Xiris(1, :);
y = Yiris(1, :);
class = Ciris(1, :);


% init learning rate
eta = 0.5;


while      sum(class ~= hyp)  
   

     count = 0; 
     
     for i=1:1:m
        if   weight(1) + weight(2)*x(i)  + weight(3)*y(i) > 0 
        hyp(i)=1;
    else  
        hyp(i)=0;
        end
     
     %update weights
      
     weight(1) = weight(1) + eta*(class(i) - hyp(i));   
     weight(2) = weight(2) + eta*(class(i) - hyp(i))*x(i);    
     weight(3) = weight(3) + eta*(class(i) - hyp(i))*y(i);   

end
     
count = count+1;
   % break out loop to avoid infnite loop
   if count > 1000
       count
       break
    end
end

       
decision_line = zeros(1,2);
coor(1)= min(x);
  coor(2)=max(x);
for i=1:1:2
  
decision_line(i) =  -weight(1)/weight(3) - (weight(2)/weight(3))*coor(i);
end

%*************************************************************************
% *****  division into 2 classes for quadratic perceptron  ***************
%*************************************************************************

hyp =   zeros(1,m);


x = Xiris(1, :);
y = Yiris(1, :);
class = Ciris(1, :);

%*****************  quadratic classification ******************************


 
% init weights  
weight= rand(6,1);

% init learning rate
eta = 0.5;
count = 0; 
   while      sum(class ~= hyp)
		  
     
     
     for i=1:1:m
          if   weight(1) + weight(2)*x(i)  + weight(3)*y(i)  + ...
                weight(4)*x(i)*x(i)  + weight(5)*x(i)*y(i) + ...
                weight(6)*y(i)*y(i)  > 0 
        hyp(i)=1; 
    else  
        hyp(i)=0;
        end
     
     %update weights
 
     weight(1) = weight(1) + eta*(class(i) - hyp(i));   
     weight(2) = weight(2) + eta*(class(i) - hyp(i))*x(i);    
     weight(3) = weight(3) + eta*(class(i) - hyp(i))*y(i); 
     weight(4) = weight(4) + eta*(class(i) - hyp(i))*x(i)*x(i);     
     weight(5) = weight(5) + eta*(class(i) - hyp(i))*x(i)*y(i);    
     weight(6) = weight(6) + eta*(class(i) - hyp(i))*y(i)*y(i);
     
     end
     
     count = count+1;
   
   if count > 10000
     %  count
       break
    end
end


 a=weight(6);
ynew1=zeros(1,m);
ynew2=zeros(1,m);

x=sort(x);

 for i=1:1:m
bb= weight(5)*x(i) + weight(3);
cc = weight(1) + weight(2)*x(i) + weight(4)*x(i)*x(i);
D = bb*bb - 4*a*cc;
ynew1(i) = (-bb + sqrt(D))/(2*a);
ynew2(i) = (-bb - sqrt(D))/(2*a);
 end

%*********************************************************
% presenting results


figure
%plot(x,y,'o r', 'linewidth',1)
%hold on

% compute approximation to this exact polynomial with comp. coefficients c

%approx = A*c;


hold on
% plot decision line computed via Least squares 
%plot(x,approx,'-- b', 'linewidth',3)


plot(coor,decision_linels,'-- b', 'linewidth',3);

% plot results of quadratic perceptron 

  plot(x,ynew1,'- g', 'linewidth',3);
  %plot(x,ynew2,'* r', 'linewidth',2);


% plot results of  linear  perceptron 
plot(coor,decision_line,' -. r', 'linewidth',3)




str_xlabel = ['poly.degree d=', num2str(d)];



xlabel('  x')



 plot(classx1, classy1,"ko", "MarkerSize", 7, "MarkerFaceColor", "c")
 plot(classx2,  classy2,"ks", "MarkerSize", 7, "MarkerFaceColor", "m")
 
%legend('exact  ',str_xlabel);
legend('LS', 'quadratic perceptron', 'linear perceptron', '  class 1', '   class 2');


%title(['LS vs. Perceptron, m= ',num2str(m),', ',str_xlabel])


hold off

title("Least Squares (LS) vs. Perceptron in IRIS data", "Interpreter", "Latex")
xlabel("x", "Interpreter", "Latex")
ylabel(" y ", "Interpreter", "Latex")
font_size = 12;
set(gca, "FontSize", font_size)


  % Export the plot
%set(gcf, "Units", "Inches", "Position", [0, 0, 7, 7], ...
      %   "PaperUnits", "Inches", "PaperSize", [5, 5])


 %  saveas(gcf, sprintf("Iris.pdf"))
