This program is copyright © 1996 by the author. It is made available as is, and no warranty - about the program, its performance, or its conformity to any specification - is given or implied. It may be used, modified, and distributed freely for private and commercial purposes, as long as the original author is credited as part of the final work.
/****************************************************************************** ============== Network: Hopfield Model ============== Application: Autoassociative Memory Associative Recall of Images and Pattern Completion Author: Karsten Kutza Date: 30.1.96 Reference: J.J. Hopfield Neural Networks and Physical Systems with Emergent Collective Computational Abilities Proceedings of the National Academy of Sciences, 79, pp. 2554-2558, 1982 ******************************************************************************/ /****************************************************************************** D E C L A R A T I O N S ******************************************************************************/ #include <stdlib.h> #include <stdio.h> typedef int BOOL; typedef char CHAR; typedef int INT; #define FALSE 0 #define TRUE 1 #define NOT ! #define AND && #define OR || #define LO -1 #define HI +1 #define BINARY(x) ((x)==LO ? FALSE : TRUE) #define BIPOLAR(x) ((x)==FALSE ? LO : HI) typedef struct { /* A NET: */ INT Units; /* - number of units in this net */ INT* Output; /* - output of ith unit */ INT* Threshold; /* - threshold of ith unit */ INT** Weight; /* - connection weights to ith unit */ } NET; /****************************************************************************** R A N D O M S D R A W N F R O M D I S T R I B U T I O N S ******************************************************************************/ void InitializeRandoms() { srand(4711); } INT RandomEqualINT(INT Low, INT High) { return rand() % (High-Low+1) + Low; } /****************************************************************************** A P P L I C A T I O N - S P E C I F I C C O D E ******************************************************************************/ #define NUM_DATA 5 #define X 10 #define Y 10 #define N (X * Y) CHAR Pattern[NUM_DATA][Y][X] = { { "O O O O O ", " O O O O O", "O O O O O ", " O O O O O", "O O O O O ", " O O O O O", "O O O O O ", " O O O O O", "O O O O O ", " O O O O O" }, { "OO OO OO", "OO OO OO", " OO OO ", " OO OO ", "OO OO OO", "OO OO OO", " OO OO ", " OO OO ", "OO OO OO", "OO OO OO" }, { "OOOOO ", "OOOOO ", "OOOOO ", "OOOOO ", "OOOOO ", " OOOOO", " OOOOO", " OOOOO", " OOOOO", " OOOOO" }, { "O O O O", " O O O ", " O O O ", "O O O O", " O O O ", " O O O ", "O O O O", " O O O ", " O O O ", "O O O O" }, { "OOOOOOOOOO", "O O", "O OOOOOO O", "O O O O", "O O OO O O", "O O OO O O", "O O O O", "O OOOOOO O", "O O", "OOOOOOOOOO" } }; CHAR Pattern_[NUM_DATA][Y][X] = { { " ", " ", " ", " ", " ", " O O O O O", "O O O O O ", " O O O O O", "O O O O O ", " O O O O O" }, { "OOO O O", " O OOO OO", " O O OO O", " OOO O ", "OO O OOO", " O OOO O", "O OO O O", " O OOO ", "OO OOO O ", " O O OOO" }, { "OOOOO ", "O O OOO ", "O O OOO ", "O O OOO ", "OOOOO ", " OOOOO", " OOO O O", " OOO O O", " OOO O O", " OOOOO" }, { "O OOOO O", "OO OOOO ", "OOO OOOO ", "OOOO OOOO", " OOOO OOO", " OOOO OO", "O OOOO O", "OO OOOO ", "OOO OOOO ", "OOOO OOOO" }, { "OOOOOOOOOO", "O O", "O O", "O O", "O OO O", "O OO O", "O O", "O O", "O O", "OOOOOOOOOO" } }; INT Input [NUM_DATA][N]; INT Input_[NUM_DATA][N]; FILE* f; void InitializeApplication(NET* Net) { INT n,i,j; for (n=0; n<NUM_DATA; n++) { for (i=0; i<Y; i++) { for (j=0; j<X; j++) { Input [n][i*X+j] = BIPOLAR(Pattern [n][i][j] == 'O'); Input_[n][i*X+j] = BIPOLAR(Pattern_[n][i][j] == 'O'); } } } f = fopen("HOPFIELD.txt", "w"); } void WriteNet(NET* Net) { INT i,j; for (i=0; i<Y; i++) { for (j=0; j<X; j++) { fprintf(f, "%c", BINARY(Net->Output[i*X+j]) ? 'O' : ' '); } fprintf(f, "\n"); } fprintf(f, "\n"); } void FinalizeApplication(NET* Net) { fclose(f); } /****************************************************************************** I N I T I A L I Z A T I O N ******************************************************************************/ void GenerateNetwork(NET* Net) { INT i; Net->Units = N; Net->Output = (INT*) calloc(N, sizeof(INT)); Net->Threshold = (INT*) calloc(N, sizeof(INT)); Net->Weight = (INT**) calloc(N, sizeof(INT*)); for (i=0; i<N; i++) { Net->Threshold[i] = 0; Net->Weight[i] = (INT*) calloc(N, sizeof(INT)); } } void CalculateWeights(NET* Net) { INT i,j,n; INT Weight; for (i=0; i<Net->Units; i++) { for (j=0; j<Net->Units; j++) { Weight = 0; if (i!=j) { for (n=0; n<NUM_DATA; n++) { Weight += Input[n][i] * Input[n][j]; } } Net->Weight[i][j] = Weight; } } } void SetInput(NET* Net, INT* Input) { INT i; for (i=0; i<Net->Units; i++) { Net->Output[i] = Input[i]; } WriteNet(Net); } void GetOutput(NET* Net, INT* Output) { INT i; for (i=0; i<Net->Units; i++) { Output[i] = Net->Output[i]; } WriteNet(Net); } /****************************************************************************** P R O P A G A T I N G S I G N A L S ******************************************************************************/ BOOL PropagateUnit(NET* Net, INT i) { INT j; INT Sum, Out; BOOL Changed; Changed = FALSE; Sum = 0; for (j=0; j<Net->Units; j++) { Sum += Net->Weight[i][j] * Net->Output[j]; } if (Sum != Net->Threshold[i]) { if (Sum < Net->Threshold[i]) Out = LO; if (Sum > Net->Threshold[i]) Out = HI; if (Out != Net->Output[i]) { Changed = TRUE; Net->Output[i] = Out; } } return Changed; } void PropagateNet(NET* Net) { INT Iteration, IterationOfLastChange; Iteration = 0; IterationOfLastChange = 0; do { Iteration++; if (PropagateUnit(Net, RandomEqualINT(0, Net->Units-1))) IterationOfLastChange = Iteration; } while (Iteration-IterationOfLastChange < 10*Net->Units); } /****************************************************************************** S I M U L A T I N G T H E N E T ******************************************************************************/ void SimulateNet(NET* Net, INT* Input) { INT Output[N]; SetInput(Net, Input); PropagateNet(Net); GetOutput(Net, Output); } /****************************************************************************** M A I N ******************************************************************************/ void main() { NET Net; INT n; InitializeRandoms(); GenerateNetwork(&Net); InitializeApplication(&Net); CalculateWeights(&Net); for (n=0; n<NUM_DATA; n++) { SimulateNet(&Net, Input[n]); } for (n=0; n<NUM_DATA; n++) { SimulateNet(&Net, Input_[n]); } FinalizeApplication(&Net); }
O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O -> O O O O O OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO OO -> OO OO OO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO OOOOO -> OOOOO O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O -> O O O O OOOOOOOOOO OOOOOOOOOO O O O O O OOOOOO O O OOOOOO O O O O O O O O O O O OO O O O O OO O O O O OO O O O O OO O O O O O O O O O O O OOOOOO O O OOOOOO O O O O O OOOOOOOOOO -> OOOOOOOOOO O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O -> O O O O O OOO O O OO OO OO O OOO OO OO OO OO O O OO O OO OO OOO O OO OO OO O OOO OO OO OO O OOO O OO OO OO O OO O O OO OO O OOO OO OO OO OOO O OO OO OO O O OOO -> OO OO OO OOOOO OOOOO O O OOO OOOOO O O OOO OOOOO O O OOO OOOOO OOOOO OOOOO OOOOO OOOOO OOO O O OOOOO OOO O O OOOOO OOO O O OOOOO OOOOO -> OOOOO O OOOO O O O O O OO OOOO O O O OOO OOOO O O O OOOO OOOO O O O O OOOO OOO O O O OOOO OO O O O O OOOO O O O O O OO OOOO O O O OOO OOOO O O O OOOO OOOO -> O O O O OOOOOOOOOO OOOOOOOOOO O O O O O O O OOOOOO O O O O O O O O OO O O O OO O O O OO O O O OO O O O O O O O O O O O OOOOOO O O O O O OOOOOOOOOO -> OOOOOOOOOO