%BACK_PRO is a simple script that implements Backprop for the XOR function
% The derivations are for a two layer net
% Good results are obtained for the number of iterations >= 10000
% This script uses the files SIGMOID and LOG_SIG

% Written by S. H. Zak on March 9, 1999

clear
clc;
%m=input('Number of the net outputs is m = ');
%l=input('Number of the net hidden neurons is l = ');
%n=input('Number of the net inputs is n = ');

disp('                                ----------------------------------------------------')
disp('              Good results are obtained for the number of iterations >= 10000')
disp('                                ----------------------------------------------------')
n_iter=input('Number of iterations is n_iter = ');
m=1;
l=2;
n=2;
eta_h=0.75;
eta_o=0.75;
X=[0 1 0 1;0 1 1 0];
d=[0 0 1 1];
W_o=0.1*randn(m,l);
W_h=0.1*randn(l,n);
b=0.1*randn(m,1);
t=0.1*randn(l,1);
[n_row,n_col]=size(X);
for r=1:n_iter
   %   for q=1:n_col
   re=rem(r,5);
   if re==0
      q=1;
   else
      q=re;
      end
%feed_for, that is, forward pass ======================
      z=zeros(l,1);
for node=1:l
   z(node)=sigmoid(W_h(node,:)*X(:,q)-t(node));
end
%y=zeros(m,1);
%for node=1:m
%   y(node)=sigmoid(W_o(node,:)*z-b(node));
%end
y=sigmoid(W_o(1,:)*z-b);
%==================================
%cal_grad =====================
dW_h=zeros(2,2);
dt=zeros(l,1);
for node=1:l
   dW_h(node,:)=-(d(q)-y)*y*(1-y)*W_o(1,node)*z(node)*(1-z(node))*X(:,q)';
   dt(node)=(d(q)-y)*y*(1-y)*W_o(1,node)*z(node)*(1-z(node));
end
dW_o=zeros(1,2);
db=zeros(1,1);
%for node=1:m
%   dW_o(node,:)=-(d(q)-y)*y*(1-y)*z';
%   db(node)=(d(q)-y)*y*(1-y);
%end
dW_o=-(d(q)-y)*y*(1-y)*z';
db=(d(q)-y)*y*(1-y);
%====================================================
%upd_wei, that is, reverse pass =========================
W_h=W_h-eta_h*dW_h;
t=t-eta_h*dt;
W_o=W_o-eta_o*dW_o;
b=b-eta_o*db;
%===========================================
%   end
end
disp('Showing the values of the weights')
W_h
W_o
t
b
disp('=======================================================')
for q=1:4
vv1=log_sig(W_h(1,1)*X(1,q)+W_h(1,2)*X(2,q)-t(1));
vv2=log_sig(W_h(2,1)*X(1,q)+W_h(2,2)*X(2,q)-t(2));
output_test=log_sig(W_o(1,1)*vv1+W_o(1,2)*vv2-b);
disp('the actual output '),disp(output_test)
disp('desired output '),disp(d(q))
disp('--------------------')
end
xx=0:0.01:1;
yy=0:0.01:1;
[T1,T2]=meshgrid(xx,yy);
v1=log_sig(W_h(1,1)*T1+W_h(1,2)*T2-t(1));
v2=log_sig(W_h(2,1)*T1+W_h(2,2)*T2-t(2));
output=log_sig(W_o(1,1)*v1+W_o(1,2)*v2-b);
mesh(xx,yy,output)
set(gca,'Fontsize',12)
view(-20,75)
%view(-25,80)
xlabel('{\it x}_1','Fontsize',12)
ylabel('{\it x}_2','Fontsize',12)
