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))
#endifjohnsun@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.