johnsun@hubcap.UUCP (John K Sun) (04/06/88)
/* Since many people is interested in my simulation, I have posted it right here. */ /* Neural Network implementation solving optimization problems using the generalized Hopfield model. The shelving problem. (Exploring the Neural Universe) Mix-Mode version. shelve - goes into interactive mode with default values. shelve goes into batch mode with default values. By John K. Sun, (C) Feb 25, 1988. status: This program may be freely used, modified, except for commercial purposes. */ # include <stdio.h> # include <time.h> # include <math.h> # include <curses.h> # include <memory.h> # include "local.h" # include "neural.h" Vector X, /* Coordinates */ Y; Matrix V, /* Output voltage */ u, /* Initial voltage */ Du, /* Change in U */ d, /* distance matrix */ I, /* Backup Current */ ExI; /* Current */ /* The conductance Multidimensional Array */ Table T; int Stop_Freq = 50, Iterations = 2000; double Threshold = 0.0001, C = 1.0, R = 300.0; /* Actually Tau = R * C = 300. */ int N, /* N neurons per row or column */ Gain_rate = 15, SAVE_RATE, Times_to_run = 20; double GAIN = 0.01, /* Starting variable gain */ Scale_factor = 0.28, Gain_factor = 1.05; double SAVE_GAIN, SAVE_FACTOR; /*************************************************************** * Fatal error exit routine * * syntax: error_exit(function_name, format, arg1, arg2, ...); ***************************************************************/ void error_exit(name, message) char *name, *message; { /* print out the name of the function causing error */ fprintf(stderr, "ERROR in %s: ", name); /* print out remainder of message */ fprintf(stderr, message); exit(-1); } /* error exit */ /******************************** * Amplifier function generator ********************************/ double g(u) double u; { return (0.5 * (1.0 + tanh(u * GAIN))); } /* Amplifier output V = g(u) */ /*********************************************************** * C * dUi/dt = -Ui / R + sum(TijVj) + Ii ***********************************************************/ double Delta_u(i, j) int i, j; { double sum; register int k, l; sum = 0.0; for (k = 1; k <= N; k++) for (l = 1; l <= N; l++) sum = sum + T [i] [j] [k] [l] * V[k] [l]; return( - u[i][j] / (R * C) + (sum + ExI[i][j]) / C ); } /* Delta_u */ /********************************* * Initialize conductance matrix *********************************/ void Make_T() { register int x, i, y, j; for (x = 1; x <= N; x ++) for (i = 1; i <= N; i ++) for (y = 1; y <= N; y ++) for (j = 1; j <= N; j ++) T [x][i][y][j] = 0.0; for (x = 1; x <= N; x++) for (i = 1; i <= N; i++) for (y = 1; y <= N; y++) for (j = 1; j <= N; j++) if ((i EQUAL j) AND (x UNEQUAL y) OR (x EQUAL y) AND (i UNEQUAL j)) T [x][i][y][j] = -2.0; } /* Make_T */ /****************************** * Initialize Output Voltages ******************************/ void Init_V() { register int i, j; for (i = 1; i <= N; i ++) for (j = 1; j <= N; j ++) V[i][j] = g(u[i][j]); } /* Init_V */ /******************************* * Initialize initial voltages *******************************/ void Init_u() { register int i, j; for (i = 1; i <= N; i ++) for (j = 1; j <= N; j ++) u[i][j] = -100.0; } /* Init_u */ /*********************** * Initialize Currents ***********************/ void Init_I() { register int i, j; ExI [1][1] = 10.0; ExI [1][2] = 5.0; ExI [1][3] = 4.0; ExI [1][4] = 6.0; ExI [1][5] = 5.0; ExI [1][6] = 1.0; ExI [2][1] = 6.0; ExI [2][2] = 4.0; ExI [2][3] = 9.0; ExI [2][4] = 7.0; ExI [2][5] = 3.0; ExI [2][6] = 2.0; ExI [3][1] = 1.0; ExI [3][2] = 8.0; ExI [3][3] = 3.0; ExI [3][4] = 6.0; ExI [3][5] = 4.0; ExI [3][6] = 6.0; ExI [4][1] = 5.0; ExI [4][2] = 3.0; ExI [4][3] = 7.0; ExI [4][4] = 2.0; ExI [4][5] = 1.0; ExI [4][6] = 4.0; ExI [5][1] = 3.0; ExI [5][2] = 2.0; ExI [5][3] = 5.0; ExI [5][4] = 6.0; ExI [5][5] = 8.0; ExI [5][6] = 7.0; ExI [6][1] = 7.0; ExI [6][2] = 6.0; ExI [6][3] = 4.0; ExI [6][4] = 1.0; ExI [6][5] = 3.0; ExI [6][6] = 2.0; for (i = 1; i <= N; i++) for (j = 1; j <= N; j++) { I [i][j] = ExI [i][j]; ExI [i][j] *= Scale_factor; } /* for */ } /* Init_I */ /****************/ BOOLEAN Stable() /****************/ { register int i, j; for (i = 1; i <= N; i++) for (j = 1; j <= N; j++) if ( (u[i][j] * Du[i][j] < 0.0) OR ((abs(V[i][j] - 1.0) > Threshold) AND (abs(V[i][j]) > Threshold)) ) return(False); return(True); } /* Stable */ /*********************/ double print_answer() /*********************/ { double Sum; register int i, j; Sum = 0.0; putchar('\n'); for (j = 1; j <= N; j++) for (i = 1; i <= N; i++) if (abs(V[i][j] - 1.0) <= Threshold) { Sum += I[i][j]; printf(" %d", i); } printf(" Total = %7.3f\n", Sum); return(Sum); } /* Total */ /*************************************************/ void change_value(msg_str, row, col, value) /*************************************************/ char *msg_str; int row, col; double *value; { move(PROMPT_ROW + 1, PROMPT_COL + 25); clrtoeol(); addstr(msg_str); refresh(); scanw("%lf", value); mvprintw(row, col + 10, "%7.3f", *value); refresh(); } /* change value */ /*****************************************/ void print_matrix(msg, matrix, row, col) /*****************************************/ char *msg; Matrix matrix; int row, col; { register int i, j; mvaddstr(MAT_ROW, MAT_COL, msg); addch('\n'); for (i = 1; i <= row; i++) { for (j = 1; j <= col; j++) printw(" %7.3f ", matrix[i][j]); addch('\n'); } /* for */ refresh(); } /* print matrix */ /********************/ void Restore_Values() /********************/ { GAIN = SAVE_GAIN; Gain_factor = SAVE_FACTOR; Gain_rate = SAVE_RATE; /* Initialize initial voltage for amplifiers */ Init_u(); /* Initialize Output voltage */ Init_V(); /* Initialize Currents */ Init_I(); } /* restore values */ /*******************/ void Save_Values() /*******************/ { SAVE_GAIN = GAIN; SAVE_FACTOR = Gain_factor; SAVE_RATE = Gain_rate; } /* Save Values */ /*****************/ double Energy() /*****************/ { register int x, i, y, j; double Sum1, Sum2; Sum1 = Sum2 = 0.0; for (x = 1; x <= N; x++) for (i = 1; i <= N; i++) { for (y = 1; y <= N; y++) for (j = 1; j <= N; j++) Sum1 += T [x][i][y][j] * V [x][i] * V [y][j]; Sum2 += V[x][i] * I[x][i]; } /* for */ return( -0.5 * Sum1 - Sum2 ); } /* System Energy */ /*********************/ void get_command() /*********************/ { register char c; double temp; do { move(PROMPT_ROW, PROMPT_COL + 1); refresh(); c = getch(); switch(c) { case 'C': case 'c': addstr("\nChange (g, f, r, s, i) :"); refresh(); c = getch(); switch(c) { case 'g': case 'G': change_value(" Gain = ", GAIN_ROW, GAIN_COL, &SAVE_GAIN); break; case 'f': case 'F': change_value(" Factor = ", GAINF_ROW, GAINF_COL, &SAVE_FACTOR); break; case 'r': case 'R': change_value(" Rate = ", GAINR_ROW, GAINR_COL, &temp); SAVE_RATE = (int) temp; break; case 's': case 'S': change_value(" Scale = ", SCALEF_ROW, SCALEF_COL, &Scale_factor); break; case 'i': case 'I': change_value(" Stp f = ", FREQ_ROW, FREQ_COL, &temp); Stop_Freq = (int) temp; break; default: addstr("Invalid Command!"); } /* end case */ refresh(); break; case 'P': case 'p': addstr("\nShow (V, U, Du) :"); clrtoeol(); refresh(); c = getch(); switch(c) { case 'u': case 'U': print_matrix("+++> Output Us <+++", u, N, N); break; case 'v': case 'V': print_matrix("---> Output Vs <---", V, N, N); break; case 'd': case 'D': print_matrix("---> Output Du <---", Du, N, N); break; default: addstr("Please try again!"); } /* end case */ refresh(); break; case 'g': case 'G': return; case 'r': case 'R': Restore_Values(); break; case 's': case 'S': Save_Values(); break; case 'q': case 'Q': endwin(); exit(1); default: addstr("Invalid command!"); } /* end case */ } while(True); } /* get command from user */ /****************/ main(argc, argv) /****************/ int argc; char **argv; { long now; double Answer = 0.0; register int Times, Counter, i, j, rand1, rand2, SqN; register int mode; N = 6; /* Problem dependent */ Save_Values(); if (argc UNEQUAL 1) { if (argv[1][0] UNEQUAL INTRACT_SW) mode = BATCH; else { mode = INTERACTIVE; stdscr = initscr(); clear(); addstr("Turbo NEURAL NETWORK -- OPTIMIZATION PROBLEMS"); addstr(" (c) 1988 John Sun "); if (argc EQUAL 2) goto nocomline; } /* else */ SAVE_GAIN = GAIN = (double) atof(argv[1 + mode]); SAVE_FACTOR = Gain_factor = (double) atof(argv[2 + mode]); SAVE_RATE = Gain_rate = (int) atoi(argv[3 + mode]); Times_to_run = (int) atoi(argv[4 + mode]); Scale_factor = (double) atof(argv[5 + mode]); } /* if */ nocomline: if (mode UNEQUAL BATCH) { mvprintw(FREQ_ROW, FREQ_COL, "Stop F = %7d", Stop_Freq); mvprintw(ENERGY_ROW, ENERGY_COL, "Energy = %7.3f", Energy()); mvprintw(GAIN_ROW, GAIN_COL, "Gain = %7.3f", GAIN); mvprintw(GAINF_ROW, GAINF_COL, "Factor = %7.3f", Gain_factor); mvprintw(GAINR_ROW, GAINR_COL, "Rate = %7d", Gain_rate); mvprintw(SCALEF_ROW, SCALEF_COL, "Scale = %7.3f", Scale_factor); mvaddch (PROMPT_ROW, PROMPT_COL, '>'); mvaddstr(HELP_ROW, HELP_COL, "(C)hange, (R)estore, (S)ave, (G)o, (P)rint or (Q)uit"); refresh(); } /* if */ else printf("\nGain = %6.3f, factor = %6.3f, rate = %7d, scale = %6.3f\n", GAIN, Gain_factor, Gain_rate, Scale_factor); if (N > Max) error_exit("main", "Subscript Out of range \n"); SqN = N * N; /* Initialize Connectivity Matrix */ Make_T(); Restore_Values(); if (mode UNEQUAL BATCH) get_command(); for (Times = 1; Times <= Times_to_run; Times ++) { /* Start at a random place. Note: srandom() and random() are available in BSD4.2 or higher and Ultrix only. For other Unix systems, use srand() and rand() instead. */ srandom((int) (time(&now) MOD 37) ); for (Counter = 1; Counter <= Iterations; Counter ++) { for (i = 1; i <= SqN; i++) { rand1 = 1 + (int) (random() % N); rand2 = 1 + (int) (random() % N); Du [ rand1 ] [ rand2 ] = Delta_u(rand1, rand2); u [ rand1 ] [ rand2 ] += Du [ rand1 ] [ rand2 ]; V [ rand1 ] [ rand2 ] = g( u[ rand1 ] [ rand2 ]); } /* for */ if (mode UNEQUAL BATCH) { mvprintw(ENERGY_ROW, ENERGY_COL, "Energy = %7.3f", Energy()); mvprintw(GAINC_ROW, GAINC_COL, "New Ga = %7.3f", GAIN); print_matrix("---> Output Vs <---", V, N, N); } /* if */ if (Stable()) break; if ((Counter MOD Gain_rate) EQUAL 0) GAIN *= Gain_factor; if (((Counter MOD Stop_Freq) EQUAL 0) AND (mode UNEQUAL BATCH) ) get_command(); } /* for */ Answer += (double) print_answer(); if (mode UNEQUAL BATCH) get_command(); else Restore_Values(); } /* for */ if (mode UNEQUAL BATCH) { move(END_ROW, END_COL); printw("\nRuns = %4d, Average = %7.3f\n", Times_to_run, Answer / (double) Times_to_run); refresh(); endwin(); } /* if */ else printf("\nRuns = %4d, Average = %7.3f\n", Times_to_run, Answer / (double) Times_to_run); } /* main */
johnsun@hubcap.UUCP (John K Sun) (04/06/88)
/**************************************** * Neural Network Include File * static char NeuralSid[] = "@(#)neural.h 1.3 4/3/88"; ****************************************/ #ifndef NEURAL_H #define NEURAL_H # define Max 10 # define ReservedElements (Max + 1) /* Reserve 0, use 1..Max */ # define GRAPHICS # define MONOGRAPHICS # define INTERACTIVE 1 # define BATCH 0 # define INTRACT_SW '-' # define SUN3GRAPH_SW '+' typedef double Vector [ ReservedElements ]; typedef Vector Matrix [ ReservedElements ]; typedef Matrix Table [ ReservedElements ] [ ReservedElements ]; # define PROMPT_ROW 3 # define PROMPT_COL 0 # define HELP_ROW 11 # define HELP_COL 0 # define MAT_ROW 4 # define MAT_COL 20 # define ANS_ROW 4 # define ANS_COL 0 # define END_ROW 11 # define END_COL 0 # define FREQ_ROW 1 # define FREQ_COL 1 # define GAIN_ROW 2 # define GAIN_COL 1 # define ENERGY_ROW 1 # define ENERGY_COL 20 # define GAINC_ROW 1 # define GAINC_COL 40 # define SCALEF_ROW 2 # define SCALEF_COL 60 # define GAINR_ROW 2 # define GAINR_COL 40 # define GAINF_ROW 2 # define GAINF_COL 20 /* Color definitions */ #define BLACK 0 /* white on b&w */ #define RED 1 /* black on b&w */ #define GREEN 2 /* black on b&w */ #define BLUE 3 /* black on b&w */ /* Position definitions */ #define ORIGIN_X 500 #define ORIGIN_Y 500 #define OFFSET_X 500 #define OFFSET_Y 500 #define MAX_X 2500 #define MAX_Y 2500 #endif
johnsun@hubcap.UUCP (John K Sun) (04/06/88)
/* static char LocalSid[] = "@(#)local.h 1.2 4/1/88"; */ # ifndef LOCAL_H # define LOCAL_H # define Mod % # define And && # define Or || # define Not ! # define EQUAL == # define UNEQUAL != # define NOT_FOUND (-1) # define ERROR (-1) # define NULL_CHAR ('\0') # define PARMS(x) () /* For non ANSI C */ # define COL_80 81 # define ASCII_TABLE 256 # define FOREVER for(;;) # define End_Of_File 26 # define NEW_PAGE '\014' typedef enum { True = 1, False = 0 } BOOLEAN; typedef enum { lt = -1, eq = 0, gt = 1 } RELATION; # define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) #endif
johnsun@hubcap.UUCP (John K Sun) (04/06/88)
hello folks, My recent Hopfield Neural Network should only be used for educational purposes ONLY. Please contact me *FIRST* for improvements, changes, bug reports, comments, etc. johnsun@hubcap.clemson.edu
bills@hpcllmv.HP.COM (Bill Serra) (04/14/88)
> My recent Hopfield Neural Network should only be used for educational >purposes ONLY. Please contact me *FIRST* for improvements, changes, >bug reports, comments, etc. > >johnsun@hubcap.clemson.edu >---------- John, thanks++ for submitting this source. I've compiled it without problems (except that our C compiler doesn't like AND/OR/MOD) but I'm getting this unsatisfied externals from the loader: ld: Unsatisfied symbols: $global$ (data) initscr (code) $$mulI (code) srandom (code) printf (code) endwin (code) fprintf (code) exit (code) atof (code) atoi (code) printw (code) mvprintw (code) tanh (code) wrefresh (code) _iob (data) abs (code) waddch (code) wclear (code) time (code) wmove (code) wgetch (code) stdscr (data) random (code) wclrtoeol (code) waddstr (code) scanw (code) $$remI (code) _flsbuf (code) I know some of them (atof, atoi, exit, fprintf, tanh...) and some other are completely unknown to me. Is there any special library I should link it into? or is there something I'm doing wrong, or missing an include file? Bill Serra (e-mail-> bills@hpda | {hpda,hplabs,hpfcla,hpfclp}!hpcllmv!bills) ---
bills@hpcllmv.HP.COM (Bill Serra) (04/15/88)
>John, thanks++ for submitting this source. I've compiled it without >problems (except that our C compiler doesn't like AND/OR/MOD) but >I'm getting this unsatisfied externals from the loader: > >ld: Unsatisfied symbols: > [..list..] > >Bill Serra (e-mail-> bills@hpda | {hpda,hplabs,hpfcla,hpfclp}!hpcllmv!bills) >--- Sorry, I didn't realize they were -lcurses... !!
bwk@mitre-bedford.ARPA (Barry W. Kort) (04/16/88)
I, too, had to do a bit of detective work to fix hopfield.c: First of all, the pre-processor variables "MOD", "AND", "NOT", and "OR" are defined in "local.h", except that they are spelled "Mod", "And", "Not", and "Or". I converted them to ALL UPPER CASE in "local.h" and that problem disappeared. Secondly, I guessed at the link libraries needed to resolve the external function calls. They turned out to be the math lib (-lm), the term lib (-ltermlib) and the curses lib (-lcurses). I have added the following comment to my copy of hopfield.c so that future users don't have to go into Sherlock mode to compile it: /* To Compile: cc -o hopfield hopfield.c -lm -lcurses -ltermlib */ I enjoy playing with interesting software like hopfield.c, but life would be easier if the creators of such programs would include comments on compilation, run-time switches, etc. Now if I could only figure out the rest of the story behind Hopfield Networks, I would understand what the program does! :-) --Barry Kort
ying@hubcap.UUCP (Ying Xie) (04/17/88)
In article <10370001@hpcllmv.HP.COM>, bills@hpcllmv.HP.COM (Bill Serra) writes: > problems (except that our C compiler doesn't like AND/OR/MOD) but for the AND/OR/MOD see local.h > I'm getting this unsatisfied externals from the loader: > > ld: Unsatisfied symbols: > $global$ (data) > initscr (code) > .... > etc. Hello folks, please compiled with: % cc -o hnn main.c -lcurses -ltermlib -lm & john. Sorry for the inconvienence.