1	#include<stdio.h>
     2	#include<math.h>
     3	#include<time.h>
     4	#include<stdlib.h>
     5	
     6	#define LAYER	3
     7	#define INPUT	2
     8	#define HIDDEN	2
     9	#define OUTPUT	1
    10	#define CTG		4
    11	
    12	#define ITERATIONS	100000
    13	
    14	#define ETA		1.50
    15	#define EPSILON	1.00
    16	#define ALPHA	0.90
    17	#define WD		2.00
    18	#define MIN_ERR	0.0001
    19	
    20	#define ON		0.9
    21	#define OFF		0.1
    22	#define SMAX	15
    23	#define SMIN	-15
    24	#define MAX		0.99995
    25	#define MIN		0.00005
    26	
    27	#ifdef	_Cdecl
    28	#define	drand() ((double)(rand()+1)/RAND_MAX-0.5)
    29	#else
    30	#define	drand() ((double)(rand()+1)/RAND_MAX-0.5)
    31	#endif
    32	
    33	#define sq(x) (x)*(x)
    34	
    35	double 	i_lay[CTG][INPUT+1],
    36			h_lay[HIDDEN+1],
    37			o_lay[OUTPUT],
    38			teach[CTG][OUTPUT];
    39			
    40	double	ih_w[INPUT+1][HIDDEN],
    41			ho_w[HIDDEN+1][OUTPUT];
    42			
    43	double	h_del[HIDDEN+1],
    44			o_del[OUTPUT];
    45	
    46	double	ih_dw[INPUT+1][HIDDEN],
    47			ho_dw[HIDDEN+1][OUTPUT];
    48			
    49	extern double sigmoid();
    50	
    51	main(argc,argv)
    52		int	argc;
    53		char **argv;
    54	{
    55	  int	i,j,ite,ctg;
    56	  double err,sum;
    57	  srand((int)time((long *)0));
    58	  
    59	  /* ExOR Problem */
    60	  i_lay[0][0]=OFF; i_lay[0][1]=OFF; i_lay[0][2]=ON; teach[0][0]=OFF;
    61	  i_lay[1][0]=ON;  i_lay[1][1]=OFF; i_lay[1][2]=ON; teach[1][0]=ON;
    62	  i_lay[2][0]=OFF; i_lay[2][1]=ON;  i_lay[2][2]=ON; teach[2][0]=ON;
    63	  i_lay[3][0]=ON; i_lay[3][1]=ON;  i_lay[3][2]=ON; teach[3][0]=OFF;
    64	
    65	  h_lay[HIDDEN]=ON;
    66		
    67	  for(j=0;j<HIDDEN;j++)
    68	    for(i=0;i<=INPUT;i++){
    69	      ih_w[i][j]=WD*drand();
    70	      ih_dw[i][j]=0.;
    71	    }
    72	  for(j=0;j<OUTPUT;j++)
    73	    for(i=0;i<=HIDDEN;i++){
    74	      ho_w[i][j]=WD*drand();
    75	      ho_dw[i][j]=0.;
    76	    }
    77	  for(ite=0;ite<=ITERATIONS; ite++){
    78	    for(ctg=0,err=0.;ctg<CTG;ctg++){
    79	      for(j=0;j<HIDDEN;j++){
    80		for(i=0,sum=0.;i<=INPUT;i++)
    81		  sum += i_lay[ctg][i]*ih_w[i][j];
    82		h_lay[j]=sigmoid(sum);
    83	      }
    84	      for(j=0;j<OUTPUT;j++){
    85		for(i=0,sum=0.;i<=HIDDEN;i++)
    86		  sum+=h_lay[i]*ho_w[i][j];
    87		o_lay[j]=sigmoid(sum);
    88	      }
    89	      for(i=0;i<OUTPUT;i++){
    90		err+=sq(teach[ctg][i]-o_lay[i])/2./(double)CTG;
    91		o_del[i]=EPSILON*(teach[ctg][i]-o_lay[i])*o_lay[i]*(1.-o_lay[i]);			}
    92	      for(j=0;j<=HIDDEN;j++){
    93		h_del[j]=0.;
    94		for(i=0;i<OUTPUT;i++)
    95		  h_del[j]+=o_del[i]*ho_w[j][i];
    96		h_del[j]*=EPSILON*h_lay[j]*(1.-h_lay[j]);
    97	      }
    98	      
    99	      for(j=0;j<=HIDDEN;j++)
   100		for(i=0;i<OUTPUT;i++){
   101		  ho_dw[j][i]=ETA*o_del[i]*h_lay[j]+ALPHA*ho_dw[j][i];
   102		  ho_w[j][i]+=ho_dw[j][i];
   103		}
   104	      for(j=0;j<=INPUT;j++)
   105		for(i=0;i<HIDDEN;i++){
   106		  ih_dw[j][i]=ETA*h_del[i]*i_lay[ctg][j]+ALPHA*ih_dw[j][i];
   107		  ih_w[j][i]+=ih_dw[j][i];
   108		}
   109	    }
   110	    fprintf(stderr,"iteration = %4d, error = %1.5f\n",ite,err);
   111	    if((err<MIN_ERR)||(ite==ITERATIONS)){
   112	      for(ctg=0;ctg<CTG;ctg++){
   113		fprintf(stderr,"ctg[%d] : ",ctg);
   114		for(i=0;i<INPUT;i++)
   115		  fprintf(stderr,"i[%d] = %1.1f  ",i,i_lay[ctg][i]);
   116		for(j=0;j<HIDDEN;j++){
   117		  for(i=0,sum=0.;i<=INPUT;i++)
   118		    sum+=i_lay[ctg][i]*ih_w[i][j];
   119		  h_lay[j]=sigmoid(sum);
   120		}
   121		for(j=0;j<OUTPUT;j++){
   122		  for(i=0,sum=0.;i<=HIDDEN;i++)
   123		    sum+=h_lay[i]*ho_w[i][j];
   124		  o_lay[j]=sigmoid(sum);
   125		  fprintf(stderr,"o[%d] = %1.5f, t{%d] = %1.1f\n",j,o_lay[j],j,teach[ctg][j]);
   126		}
   127	      }
   128	      fprintf(stderr,"iteration = %4d, error = %1.5f\n",ite,err);
   129	      break;
   130	    }
   131	  }
   132	}
   133	
   134	double sigmoid(s)
   135		double s;
   136	{
   137		double sm;
   138		
   139		sm=EPSILON*s;
   140		if(sm>SMAX)			return(MAX);
   141		else if(sm<SMIN)	return(MIN);
   142		else				return(1./(1.+exp(-sm)));
   143	}