/* A perceptron simulator. * This is oversimplified version of 2 boolean inputs to 1 boolean output * by asakawa@twcu.ac.jp */ #include #include #include #include /* time.h is required for random number generator */ #define YES 1 #define NO 0 #define FROM 0 #define TO 30000 /* SEED and loadingtime are required to get random numbers */ unsigned int SEED; long loadingtime; /* Number of patterns to be learned */ #define NPATS 4 /* Each training pattern is stored as {input1,input2, and desired_output} */ /* int training_set[NPATS][3] = {{0,0, 1}, {0,1, 1}, {1,0, 0}, {1,1, 1}}; */ int training_set[NPATS][3] = {{0,0, 0}, {0,1, 1}, {1,0, 1}, {1,1, 1}}; /* Definition of a neuron: */ /* Among the members of the following structure, */ /* Ninp strands for a number of input from neurons. */ struct NEURON { double output; int Ninp; double *inp_wgt; struct NEURON **inp_neuron; }; typedef struct NEURON neuron; /* return random number from 0 to 1 */ double drand(void) { return ((double)(rand() % RAND_MAX) / (double)RAND_MAX); } /* return random number from -1 to 1 */ double drand2(void) { return (drand() * 2.0 - 1.0); } /* Initilazing neurons, defined by means of a struct NEURON described above,*/ /* and assigning an initial value as default to each variable */ void initialize_neuron(neuron *a, int N) { int i; a->output = 0.0; a->Ninp = N; a->inp_wgt = (double *)malloc(sizeof(double) * (a->Ninp)); if ( a->inp_wgt == NULL ) { fprintf(stderr, "Can not allocate memory\n"); exit (EXIT_FAILURE); } for (i=0; i< a->Ninp; i++) { a->inp_wgt[i] = drand2(); } a->inp_neuron = (neuron **)malloc(sizeof(neuron *) * (a->Ninp)); if ( a->inp_neuron == NULL ) { fprintf(stderr, "Can not allocate memory\n"); exit (EXIT_FAILURE); } for (i=0; i< a->Ninp; i++) { a->inp_neuron[i] = NULL; } } /* McCalloch and Pitts' formal neuron */ int output_f(double state) { return (state > 0) ? 1 : 0; } void calc_neuron(neuron *a) { double wrk = 0.0; int i; for(i=0; i< a->Ninp; i++){ wrk += a->inp_wgt[i] * (double)a->inp_neuron[i]->output; } a->output = output_f(wrk); } /* This is a famous perceptron rule */ void update_wgt(neuron *a, int error) { int i; for (i=0; iNinp; i++) { a->inp_wgt[i] += a->inp_neuron[i]->output * error; } } char update_char(int error) { if (error==0) return ' '; else if (error > 0) return '>'; else return '<'; } void print_result(int trial, neuron output, neuron *input,int error, int teacher) { printf("%3d. %5.2f%c %2d %5.2f%c %2d %5.2f%c %1d %1d\n", trial+1, output.inp_wgt[1], update_char((int)(output.inp_wgt[1]*error)), (int)input[1].output, output.inp_wgt[2], update_char((int)(output.inp_wgt[2]*error)), (int)input[2].output, output.inp_wgt[0], update_char((int)error), (int)output.output, (int)teacher); } /* Set values of each input neron */ void set_input(neuron *input, int pat, int *teacher) { input[0].output = 1.0; /* threshold */ input[1].output = (double)training_set[pat][0]; input[2].output = (double)training_set[pat][1]; *teacher = training_set[pat][2]; } int main() { neuron input[3], output; int t,i, pat, teacher, error; int error_exist = YES; /* initialize of random number sequence */ SEED = (unsigned)time(&loadingtime); srand(SEED); /* initialize each input neuron */ for(i=0; i<3; i++){ initialize_neuron(&input[i],0); } /* The output value of input[0] is supposed to be dealed as a threshold, therefore, input[0].output should be constantly set to 1. */ input[0].output = 1; /* initialize an output neuron */ initialize_neuron (&output,3); for (i=0; i<3; i++) { /* make a connect with each input neuron */ output.inp_neuron[i] = &input[i]; } #ifdef DEBUG /**** setting initial weights for each input neuron ****/ /* As I mentioned earlier, input[0] means threshold. */ /* The value of output.inp_wgt[0] is able to express the amount */ /* of contribution of threshold value */ output.inp_wgt[0] = -1.0; output.inp_wgt[1] = 1.0; output.inp_wgt[2] = -3.0; #endif printf("Trial w1 * x1 w2 * x2 threhold output teacher\n"); for (t=FROM; t