Bidirectional Associative Memory

advertisement
Bidirectional Associative Memory
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.
Bidirectional Associative Memory Simulator
/****************************************************************************
**
Network:
================================
Bidirectional Associative Memory
================================
Application:
Heteroassociative Memory
Association of Names and Phone Numbers
Author:
Date:
Karsten Kutza
24.1.96
Reference:
B. Kosko
Bidirectional Associative Memories
IEEE Transactions on Systems, Man, and Cybernetics, 18,
pp. 49-60, 1988
*****************************************************************************
*/
/****************************************************************************
**
D E C L A R A T I O N S
*****************************************************************************
*/
#include <stdlib.h>
#include <stdio.h>
typedef int
typedef char
BOOL;
CHAR;
typedef int
INT;
#define
#define
#define
#define
#define
0
1
!
&&
||
FALSE
TRUE
NOT
AND
OR
#define LO
#define HI
-1
+1
#define BINARY(x)
#define BIPOLAR(x)
((x)==LO ? FALSE : TRUE)
((x)==FALSE ? LO : HI)
typedef struct {
*/
INT
*/
INT*
*/
INT**
*/
} LAYER;
typedef struct {
*/
LAYER*
*/
LAYER*
*/
} NET;
/* A LAYER OF A NET:
Units;
/* - number of units in this layer
Output;
/* - output of ith unit
Weight;
/* - connection weights to ith unit
/* A NET:
X;
/* - X layer
Y;
/* - Y layer
/****************************************************************************
**
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);
}
BOOL RandomEqualBOOL()
{
return rand() % 2;
}
/****************************************************************************
**
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
#define IN_CHARS
#define OUT_CHARS
3
5
7
#define BITS_PER_CHAR 6
#define FIRST_CHAR
' '
#define N
#define M
(IN_CHARS * BITS_PER_CHAR)
(OUT_CHARS * BITS_PER_CHAR)
CHAR
Names [NUM_DATA][IN_CHARS]
= { "TINA ",
"ANTJE",
"LISA " };
CHAR
Names_[NUM_DATA][IN_CHARS]
= { "TINE ",
"ANNJE",
"RITA " };
CHAR
Phones[NUM_DATA][OUT_CHARS] = { "6843726",
"8034673",
"7260915" };
INT
INT
INT
Input [NUM_DATA][N];
Input_[NUM_DATA][N];
Output[NUM_DATA][M];
FILE*
f;
void InitializeApplication(NET* Net)
{
INT n,i,j,a,a_;
for (n=0; n<NUM_DATA; n++) {
for (i=0; i<IN_CHARS; i++) {
a = Names [n][i] - FIRST_CHAR;
a_ = Names_[n][i] - FIRST_CHAR;
for (j=0; j<BITS_PER_CHAR; j++) {
Input [n][i*BITS_PER_CHAR+j] = BIPOLAR(a % 2);
Input_[n][i*BITS_PER_CHAR+j] = BIPOLAR(a_ % 2);
a /= 2;
a_ /= 2;
}
}
for (i=0; i<OUT_CHARS; i++) {
a = Phones[n][i] - FIRST_CHAR;
for (j=0; j<BITS_PER_CHAR; j++) {
Output[n][i*BITS_PER_CHAR+j] = BIPOLAR(a % 2);
a /= 2;
}
}
}
f = fopen("BAM.txt", "w");
}
void WriteLayer(LAYER* Layer)
{
INT i,j,a,p;
for (i=0; i<(Layer->Units / BITS_PER_CHAR); i++) {
a = 0;
p = 1;
for (j=0; j<BITS_PER_CHAR; j++) {
a += BINARY(Layer->Output[i*BITS_PER_CHAR+j]) * p;
p *= 2;
}
fprintf(f, "%c", a + FIRST_CHAR);
}
}
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->X = (LAYER*) malloc(sizeof(LAYER));
Net->Y = (LAYER*) malloc(sizeof(LAYER));
Net->X->Units = N;
Net->X->Output = (INT*) calloc(N, sizeof(INT));
Net->X->Weight = (INT**) calloc(N, sizeof(INT*));
Net->Y->Units = M;
Net->Y->Output = (INT*) calloc(M, sizeof(INT));
Net->Y->Weight = (INT**) calloc(M, sizeof(INT*));
for (i=0; i<N; i++)
Net->X->Weight[i]
}
for (i=0; i<M; i++)
Net->Y->Weight[i]
}
}
{
= (INT*) calloc(M, sizeof(INT));
{
= (INT*) calloc(N, sizeof(INT));
void CalculateWeights(NET* Net)
{
INT i,j,n;
INT Weight;
for (i=0; i<Net->X->Units; i++) {
for (j=0; j<Net->Y->Units; j++) {
Weight = 0;
for (n=0; n<NUM_DATA; n++) {
Weight += Input[n][i] * Output[n][j];
}
Net->X->Weight[i][j] = Weight;
Net->Y->Weight[j][i] = Weight;
}
}
}
void SetInput(LAYER* Layer, INT* Input)
{
INT i;
for (i=0; i<Layer->Units; i++) {
Layer->Output[i] = Input[i];
}
WriteLayer(Layer);
}
void SetRandom(LAYER* Layer)
{
INT i;
for (i=0; i<Layer->Units; i++) {
Layer->Output[i] = BIPOLAR(RandomEqualBOOL());
}
WriteLayer(Layer);
}
void GetOutput(LAYER* Layer, INT* Output)
{
INT i;
for (i=0; i<Layer->Units; i++) {
Output[i] = Layer->Output[i];
}
WriteLayer(Layer);
}
/****************************************************************************
**
P R O P A G A T I N G
S I G N A L S
*****************************************************************************
*/
BOOL PropagateLayer(LAYER* From, LAYER* To)
{
INT i,j;
INT Sum, Out;
BOOL Stable;
Stable = TRUE;
for (i=0; i<To->Units; i++) {
Sum = 0;
for (j=0; j<From->Units; j++) {
Sum += To->Weight[i][j] * From->Output[j];
}
if (Sum != 0) {
if (Sum < 0) Out = LO;
if (Sum > 0) Out = HI;
if (Out != To->Output[i]) {
Stable = FALSE;
To->Output[i] = Out;
}
}
}
return Stable;
}
void PropagateNet(LAYER* From, LAYER* To)
{
BOOL Stable1, Stable2;
do {
Stable1 = PropagateLayer(From, To);
Stable2 = PropagateLayer(To, From);
} while (NOT (Stable1 AND Stable2));
}
/****************************************************************************
**
S I M U L A T I N G
T H E
N E T
*****************************************************************************
*/
void SimulateNet(LAYER* From, LAYER* To, INT* Pattern, INT* Input, INT*
Output)
{
SetInput(From, Pattern); fprintf(f, " -> ");
SetRandom(To);
fprintf(f, " | ");
PropagateNet(From, To);
GetOutput(From, Input); fprintf(f, " -> ");
GetOutput(To, Output);
fprintf(f, "\n\n");
}
/****************************************************************************
**
M A I N
*****************************************************************************
*/
void main()
{
NET Net;
INT n;
INT I[N], O[M];
InitializeRandoms();
GenerateNetwork(&Net);
InitializeApplication(&Net);
CalculateWeights(&Net);
for (n=0; n<NUM_DATA; n++) {
SimulateNet(Net.X, Net.Y, Input[n], I, O);
}
for (n=0; n<NUM_DATA; n++) {
SimulateNet(Net.Y, Net.X, Output[n], O, I);
}
for (n=0; n<NUM_DATA; n++) {
SimulateNet(Net.X, Net.Y, Input_[n], I, O);
}
FinalizeApplication(&Net);
}
Simulator Output for the Heteroassociative Memory
Application
TINA
-> P:*[HBQ
|
TINA
ANTJE -> !_+87&9
|
ANTJE -> 8034673
LISA
-> )@;ZV)-
|
LISA
6843726 -> SP4^L
|
6843726 -> TINA
8034673 -> ^;GI#
|
8034673 -> ANTJE
7260915 -> A-/%1
|
7260915 -> LISA
TINE
-> CW48F ^
|
TINA
ANNJE -> @ZB%8Q!
|
ANTJE -> 8034673
RITA
|
DIVA
-> H0(@=^/
-> 6843726
-> 7260915
-> 6843726
-> 6060737
Download