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:       Karsten Kutza
        Date:         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           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 LAYER OF A NET:                     */
        INT           Units;         /* - number of units in this layer       */
        INT*          Output;        /* - output of ith unit                  */
        INT**         Weight;        /* - connection weights to ith unit      */
} LAYER;

typedef struct {                     /* A NET:                                */
        LAYER*        X;             /* - X layer                             */
        LAYER*        Y;             /* - Y layer                             */
} 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);
}


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      3
#define IN_CHARS      5
#define OUT_CHARS     7

#define BITS_PER_CHAR 6
#define FIRST_CHAR    ' '

#define N             (IN_CHARS  * BITS_PER_CHAR)
#define M             (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                   Input [NUM_DATA][N];
INT                   Input_[NUM_DATA][N];
INT                   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] = (INT*) calloc(M, sizeof(INT));
  }
  for (i=0; i<M; i++) {
    Net->Y->Weight[i] = (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  -> 6843726

ANTJE -> !_+87&9  |  ANTJE -> 8034673

LISA  -> )@;ZV)-  |  LISA  -> 7260915

6843726 -> SP4^L  |  6843726 -> TINA 

8034673 -> ^;GI#  |  8034673 -> ANTJE

7260915 -> A-/%1  |  7260915 -> LISA 

TINE  -> CW48F ^  |  TINA  -> 6843726

ANNJE -> @ZB%8Q!  |  ANTJE -> 8034673

RITA  -> H0(@=^/  |  DIVA  -> 6060737



This page hosted by . Get your own free home page.