Lösung Aufgabe 3b


#include <stdlib.h>
#include <math.h>
#define MAXSCHRITTE 100000.00
#define ANZAHLNEURONEN  16
#define SIGMOID_K 3
double gewicht[ANZAHLNEURONEN][ANZAHLNEURONEN];
double delta[ANZAHLNEURONEN];
double output[ANZAHLNEURONEN];
double input[ANZAHLNEURONEN];
void * ausgabefunktionen[ANZAHLNEURONEN];

eingabe_function(int i)
/* fuer die zellen mit eingabe, kopieren auf die ausgabe */
{ output[i] = input[i]; }
 
sigmoid_ausgabefunction(int i)
{ output[i] = 1.0 / (1.0 + exp(-SIGMOID_K *  input[i])) ; }  

oneloop()
{
int i,j;
double erg;
for (i=0;i<ANZAHLNEURONEN;i++) {
        for (erg=0.0,j=0;j<ANZAHLNEURONEN;j++) erg += gewicht[j][i]*output[j];
        input[i] = erg; }
/* neue eingaben sind bekannt */
for (i=0;i<ANZAHLNEURONEN;i++)        { int (*f)() = ausgabefunktionen[i]; f(i); } 
}

init_random_exor_netz()
{
	// zwei eingaben  0,1
	// drei erste ebene 2,3,4
	// drei zweite ebene 5,6,7
	// eine ausgabe 8
	// drei schwellwerte erste ebene 9,10,11
	// drei schwellwerte zweite ebene 12,13,14
	// ein schwellwert ausgabe 15
	int i;
	srand48(getpid()); // initialisieren der zufallswerte
	gewicht[0][2]=drand48(); gewicht[0][3]=drand48(); gewicht[0][4]=drand48();
	gewicht[1][2]=drand48(); gewicht[1][3]=drand48(); gewicht[1][4]=drand48();
	gewicht[2][5]=drand48(); gewicht[2][6]=drand48(); gewicht[2][7]=drand48();
	gewicht[3][5]=drand48(); gewicht[3][6]=drand48(); gewicht[3][7]=drand48();
	gewicht[4][5]=drand48(); gewicht[4][6]=drand48(); gewicht[4][7]=drand48();
	gewicht[5][8]=drand48(); gewicht[6][8]=drand48(); gewicht[7][8]=drand48();
	// fuer die schwellwerte
	gewicht[9][2]=drand48(); gewicht[10][3]=drand48(); gewicht[11][4]=drand48();
	gewicht[12][5]=drand48(); gewicht[13][6]=drand48(); gewicht[14][7]=drand48();
	gewicht[15][8]=drand48();
	for (i=0;i<2;i++) gewicht[i][i]=1.0;  // fuer eingabe
	for (i=9;i<16;i++) gewicht[i][i]=1.0;  // fuer schwellwerte
	for (i=9;i<16;i++) output[i]=1.0; // fuer schwellwerte
	for (i=0;i<2;i++) ausgabefunktionen[i] = (void *)eingabe_function;  // fuer eingabe
	for (i=9;i<16;i++) ausgabefunktionen[i] = (void *)eingabe_function;  // fuer schwellwerte
	for (i=2;i<9;i++) ausgabefunktionen[i] = (void *)sigmoid_ausgabefunction;  // fuer neuronen
}
printnetz()
{
	int i;
	printf("i:");for (i=0;i<ANZAHLNEURONEN;i++) printf("%2.2f ",input[i]); printf("\n");
	printf("o:");for (i=0;i<ANZAHLNEURONEN;i++) printf("%2.2f ",output[i]); printf("\n");
/*
	printf("g:");
	printf("0-2:%2.2f 0-3:%2.2f 0-4:%2.2f 1-2:%2.2f 1-3:%2.2f",
		 gewicht[0][2], gewicht[0][3], gewicht[0][4], gewicht[1][2], gewicht[1][3] );
	printf(" 1-4:%2.2f 2-5:%2.2f 2-6:%2.2f 2-7:%2.2f 3-5:%2.2f",
		gewicht[1][4], gewicht[2][5], gewicht[2][6], gewicht[2][7], gewicht[3][5]);
	printf(" 3-6:%2.2f 3-7:%2.2f 4-5:%2.2f 4-6:%2.2f 4-7:%2.2f",
		gewicht[3][6], gewicht[3][7], gewicht[4][5], gewicht[4][6], gewicht[4][7]);
	printf(" 5-8:%2.2f 6-8:%2.2f 7-8:%2.2f \n", gewicht[5][8], gewicht[6][8], gewicht[7][8]);
	printf("sw: %2.2f %2.2f %2.2f %2.2f %2.2f %2.2f %2.2f \n",
		gewicht[9][2], gewicht[10][3], gewicht[11][4], gewicht[12][5], gewicht[13][6], gewicht[14][7],
		gewicht[15][8]);
*/
}
back()
// gewichte zuletzt ändern
{
	float soll;

	static int loopcounter =1;
	float eta;
	float temp;

	eta = 1.0 -  loopcounter++/MAXSCHRITTE;
	if (input[0] == input[1]) soll = 0.0; else soll = 1.0;

// zuerst die ausgabewerte
	delta[8] = SIGMOID_K * output[8] * (1.0 - output[8] )*(soll - output[8]);

	// nun level 1

	delta[7] =  SIGMOID_K * output[7]*(1.0 - output[7]) * delta[8] * gewicht[7][8];
	delta[6] =  SIGMOID_K * output[6]*(1.0 - output[6]) * delta[8] * gewicht[6][8];
	delta[5] =  SIGMOID_K * output[5]*(1.0 - output[5]) * delta[8] * gewicht[5][8];
	 
	// level 2

	temp = delta[7] * gewicht[2][7] + delta [6] * gewicht[2][6] + delta [5]*gewicht[2][5];
	delta[2] =  SIGMOID_K * output[2] *(1.0 - output[2]) * temp;
 
	temp = delta[7] * gewicht[3][7] + delta [6] * gewicht[3][6] + delta [5]*gewicht[3][5];
	delta[3] =  SIGMOID_K * output[3]* (1.0 - output[3]) * temp;

	temp = delta[7] * gewicht[4][7] + delta [6] * gewicht[4][6] + delta [5]*gewicht[4][5];
	delta[4] =  SIGMOID_K * output[4]* (1.0 - output[4])  * temp;
 

	gewicht[5][8] += eta*delta[8]*output[5];
	gewicht[6][8] += eta*delta[8]*output[6];
	gewicht[7][8] += eta*delta[8]*output[7];
	gewicht[15][8] += eta*delta[8]*output[15];

        gewicht[2][7] += eta*delta[7]*output[2];
        gewicht[3][7] += eta*delta[7]*output[3];
        gewicht[4][7] += eta*delta[7]*output[4];
        gewicht[14][7] += eta*delta[7]*output[14];

        gewicht[2][6] += eta*delta[6]*output[2];
        gewicht[3][6] += eta*delta[6]*output[3];
        gewicht[4][6] += eta*delta[6]*output[4];
        gewicht[13][6] += eta*delta[6]*output[13];
	
        gewicht[2][5] += eta*delta[5]*output[2];
        gewicht[3][5] += eta*delta[5]*output[3];
        gewicht[4][5] += eta*delta[5]*output[4];
        gewicht[12][5] += eta*delta[5]*output[12];
	
        gewicht[0][2] += eta*delta[2]*output[0];
        gewicht[1][2] +=  eta*delta[2]*output[1];
        gewicht[9][2] +=  eta*delta[2]*output[9];

        gewicht[0][3] += eta*delta[3]*output[0]; 
        gewicht[1][3] += eta*delta[3]*output[1];
        gewicht[10][3] +=eta*delta[3]*output[10];

        gewicht[0][4] +=  eta*delta[4]*output[0]; 
        gewicht[1][4] +=eta*delta[4]*output[1];
        gewicht[11][4] += eta*delta[4]*output[11];
}


onestep()
{
double d = drand48()*4.0;
if (d < 1.0) { output[0]=0.0; output[1]=0.0; }
else if (d < 2.0) { output[0]=1.0; output[1]=0.0; }
else if (d < 3.0) { output[0]=1.0; output[1]=1.0; }
else  { output[0]=0.0; output[1]=1.0; }

oneloop(); oneloop(); oneloop(); 

printf("i0:%f i1:%f o8:%f\n",input[0],input[1],output[8]);
back();
}

main()
{
int i=1;
init_random_exor_netz();
while(i++ < MAXSCHRITTE) onestep();
}