home *** CD-ROM | disk | FTP | other *** search
- /* modified for interactive input patterns - Marilyn Nelson, Feb. 1991 */
-
- /* ham.c
- * c version of the hamming net
- * david leasure
- * 9/25/87
- *
- * this routine is a hamming classification network
- * described in IEEE ASSP April 1987 by Richard P. Lippmann pg. 9
- * correcting for a presumed bug in the presented routine
- * the bug is the value set for THETA by Lippmann. When THETA is
- * N / 2 it so overwhelms the outputs from the lower net that only 0
- * activation values are passed up from the threshold function.
- * I have chosen to set epsilon to 1 / 2M and to not have an upper
- * limit on the threshold function so no saturation occurs
- *
- * the program is somewhat inefficient because of the use of
- * data storage for maxnet (t[k,l] in lippman's) and for output[t,M]
- * but they could be useful in a simulator of this network which allowed
- * things to be fiddled with.
- * the code could be improved by not encoding the size and values
- * of the node matrices directly, too, reading them instead from files
- * and/or a user interface.
- *
- * if you improve the code, please send me the diff's
- * david e. leasure
- * ihnp4!homxc!del or del@homxc.att.com
- *
- */
-
- /* EMACS_MODES: tabstop=4 c */
-
- #include <stdio.h>
- #include <ctype.h>
-
- /* number of bits per exemplar (7x5) */
- #define N 35
-
- /*number of exemplars */
- #define M 10
-
- /* presentation (r,c) */
- #define rows 7
- #define cols 5
-
- /* define maximum number of iterations before convergence */
- #define MAX_ITERATION 20
-
- /* define the exemplary training data */
- /* should be replaced later with a read routine */
-
- static int exemplars[M][N] = {
- /* 0 */
- -1,1,1,1,-1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,-1,
- /* 1 */
- -1,-1,-1,-1,1,
- -1,-1,-1,1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,-1,1,
- /* 2 */
- -1,1,1,1,-1,
- 1,-1,-1,-1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,1,-1,
- -1,-1,1,-1,-1,
- -1,1,-1,-1,-1,
- 1,1,1,1,1,
- /* 3 */
- 1,1,1,1,1,
- -1,-1,-1,1,-1,
- -1,-1,1,-1,-1,
- -1,1,1,1,-1,
- -1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,-1,
- /* 4 */
- -1,-1,-1,1,-1,
- -1,-1,1,1,-1,
- -1,1,-1,1,-1,
- 1,-1,-1,1,-1,
- 1,1,1,1,1,
- -1,-1,-1,1,-1,
- -1,-1,-1,1,-1,
- /* 5 */
- 1,1,1,1,1,
- 1,-1,-1,-1,-1,
- 1,1,1,1,-1,
- -1,-1,-1,-1,1,
- -1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,-1,
- /* 6 */
- -1,-1,1,1,-1,
- -1,1,-1,-1,-1,
- 1,-1,-1,-1,-1,
- 1,1,1,1,-1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,-1,
- /* 7 */
- 1,1,1,1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,1,-1,
- -1,-1,-1,1,-1,
- -1,-1,1,-1,-1,
- -1,-1,1,-1,-1,
- -1,-1,1,-1,-1,
- /* 8 */
- -1,1,1,1,-1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,-1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,-1,
- /* 9 */
- -1,1,1,1,-1,
- 1,-1,-1,-1,1,
- 1,-1,-1,-1,1,
- -1,1,1,1,1,
- -1,-1,-1,-1,1,
- -1,-1,-1,1,-1,
- -1,1,1,-1,-1};
-
- static float w[N][M]; /* weights of lower subnet */
- static float maxnet[M][M]; /* weights of maxnet */
- /* input pattern */
- static int x[N];
-
- /* input vector */
- static output[MAX_ITERATION][M]; /* output at time t matrix */
-
- #define THETA 0.0 /* N / 2.0 */
- #define EPSILON 1.0 / (2.0 * M)
-
- /* INIT_LOWER
- * initialize the weight matrix for the lower network
- */
- void init_lower()
- {
- int i, j;
-
- for (i=0; i<N; i++) {
- for (j=0; j<M; j++) {
-
- w[i][j] = exemplars[j][i]/2.0;
- }
- }
- }
-
- /* INIT_UPPER
- * init the weight matrix for the upper maxnet
- */
- void init_upper()
- {
- int k, l;
-
- for (k=0; k<M; k++) {
- for (l=0; l<M; l++) {
- if (k==l)
- maxnet[k][l] = 1.0;
- else
- maxnet[k][l] = -1.0 / 20.0;
- }
- }
- }
-
-
- /* INIT_SUM
- * the code to perform the summation of the weight/input value products
- * for each output, i.e. (sum(i=0..N-1) w[i][j]*x[i]) - THETA
- */
- float init_sum(j)
- int j;
- {
- int i;
- float sum;
-
- sum = 0;
- for (i=0; i<N; i++) {
- sum = sum + (w[i][j] * x[i]);
- }
- return(sum - THETA);
- }
-
- /* CONVERGE_SUM(J,T)
- * perform the sum for the maxnet output calculation
- * i.e., output[j](t) - epsilon * sum(k<>j where j,k=0..M)output[k](t)
- */
- float converge_sum(j,t)
- int j,t;
- {
- int k, sum;
-
- sum = 0;
- for (k=0; k<M; k++)
- if (k != j) sum = sum + output[t][k];
- sum = output[t][j] - EPSILON * sum;
- return(sum);
- }
-
- /* F_THRESH(ALPHA)
- * implement a simple threshold logic nonlinearity
- * I have chosen not to give it a saturation cutoff
- */
- float f_thresh(alpha)
- float alpha;
- {
- if (alpha <= 0.0)
- return(0.0);
- else
- return(alpha);
- }
-
- /* INIT_UNKNOWN()
- * apply the input to the lower net and derive state 0 of the maxnet
- */
- void init_unknown()
- {
- int j;
-
- for (j=0; j<M; j++) {
- output[0][j] = f_thresh(init_sum(j));
- }
- }
-
- /* CONVERGE()
- * perform up to MAX_ITERATIONs of the convergence function
- * answer found when only one of the maxnet outputs is high
- * that output indexes the exemplars for the correct pattern
- */
- int converge()
- {
- int t, count, j, winner;
-
- count = 2; /* prime the pump */
- winner = -1; /* start with "no winner" */
-
- for (t=1; t<MAX_ITERATION && count>1; t++) {
- count = 0;
- for (j=0; j<M; j++) {
- if ((output[t][j] = f_thresh(converge_sum(j,t - 1))) > 0) {
- winner = j;
- count++;
- }
- }
- }
- if (count != 1)
- winner = -1; /* error condition not supposed to occur */
- return(winner);
- }
-
- /* SHOW_EXEMPLAR(EX)
- * print the exemplar(ex) using .'s for -1 and *'s for +1
- * break the lines so the pattern is correctly seen
- */
- void show_exemplar(ex)
- int ex[];
- {
- int c, i;
-
- c = 0;
- for (i=0; i<N; i++) {
- if (ex[i] < 0) {
- printf(".");
- }
- else {
- printf("*");
- }
- if (++c == cols) {
- printf("\n");
- c = 0;
- }
- }
- printf("\n");
- }
-
- /* SHOW_EXEMPLARS()
- * show all the exemplars
- */
- void show_exemplars()
- {
- int j;
- char p; /* throw away char--for screen control only */
-
- for (j=0; j<M; j++) {
- printf("Exemplar %d:\n",j);
- show_exemplar(&exemplars[j][0]);
- if (((j+1)%2)==0 && j != 9)
- {
- printf("\n\n\nPress ENTER for next exemplar...");
- scanf("%c", &p);
- printf("\n\n\n\n");
- }
- }
- printf("\n");
- }
-
- void get_sample() /* routine added to enter patterns interactively */
- {
- int i,j;
- char temp[6];
-
- printf("\nPlease enter 5x7 sample for hamming net...\n");
- printf(" enter \"*\" to turn bit on; \".\" to turn bit off...\n");
- printf(" For example, enter the string \".***.\" \n\n");
-
- for (i=0;i<rows;i++)
- {
- printf("\nEnter pattern for row %d: ",i+1);
- scanf("%5s", temp);
- temp[5]='\0';
- for (j=0;j<cols;j++)
- {
- if (temp[j]=='*') x[5*i+j]=1;
- else x[5*i+j]=-1; /* default sets bit to -1 */
- }
- }
- }
-
- void save_sample() /* routine added to save created examples */
- {
- int i,stat;
- FILE *fp, *fopen();
- char save[20];
-
- printf("\nWould you like to save your example? (Y/N): ");
- scanf("%1s", save );
- if (save[0]=='Y' || save[0]=='y')
- {
- printf("\nEnter filename for saving: ");
- scanf("%s", save);
- if (fp = fopen(save, "w"))
- {
- for (i=0; i<rows*cols; i++)
- {
- stat = fprintf(fp, "%d%c", x[i], ' ');
- if (stat < 1)
- {
- printf("\nBad write, exit without saving\n");
- exit(0);
- }
- }
- fclose(fp);
- }
- else printf("\nCould not open file %s\n", save);
- }
- }
-
-
- void read_file(char *filename)
- {
- int i,stat;
- FILE *fp;
-
- fp = fopen(filename, "r");
- if (!fp)
- {
- printf("\nFailed to open file %s\n", filename);
- exit(0);
- }
- else
- {
- for (i=0; i<rows*cols; i++)
- {
- stat = fscanf(fp,"%d", &x[i]);
- if (stat != 1) printf("\nBad read for element %d\n",i);
- }
- fclose (fp);
- }
- }
-
-
- main(int argc, char *argv[])
- {
- int winner;
-
- printf("Hamming Neural Net Example\n\n");
-
- if (argc > 1) /* filename passed in */
- read_file(*++argv);
- else /* no filename passed in */
- {
- show_exemplars();
- get_sample();
- }
-
- init_lower();
- init_upper();
- init_unknown();
- winner = converge();
- if (winner >= 0) {
- printf("The winner is %d.\n", winner);
- printf("\nInput pattern:\n");
- show_exemplar(&x[0]);
- printf("\n\nExemplar:\n");
- show_exemplar(&exemplars[winner][0]);
- printf("\n");
- }
- else { /* according to lippmann, this should never happen */
- printf("Something's wrong. No winner.\n");
- }
- if (argc==1) /* created new example; want to save? */
- save_sample();
- exit(0);
- }
-