The Counterpropagation Network


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.

Counterpropagation Network Simulator

/******************************************************************************

                      ==========================
        Network:      Counterpropagation Network
                      ==========================

        Application:  Vision
                      Determination of the Angle of Rotation

        Author:       Karsten Kutza
        Date:         30.4.96

        Reference:    R. Hecht-Nielsen
                      Counterpropagation Networks
                      Proceedings of the IEEE International Conference on
                      Neural Networks, II, IEEE Press, New York, NY, pp. 19-32,
                      1987

 ******************************************************************************/




/******************************************************************************
                            D E C L A R A T I O N S
 ******************************************************************************/


#include <stdlib.h>
#include <stdio.h>
#include <math.h>


typedef int           BOOL;
typedef char          CHAR;
typedef int           INT;
typedef double        REAL;

#define FALSE         0
#define TRUE          1
#define NOT           !
#define AND           &&
#define OR            ||

#define MIN_REAL      -HUGE_VAL
#define MAX_REAL      +HUGE_VAL
#define MIN(x,y)      ((x)<(y) ? (x) : (y))
#define MAX(x,y)      ((x)>(y) ? (x) : (y))

#define LO            0
#define HI            1

#define PI            (2*asin(1))
#define sqr(x)        ((x)*(x))


typedef struct {                     /* A LAYER OF A NET:                     */
        INT           Units;         /* - number of units in this layer       */
        REAL*         Output;        /* - output of ith unit                  */
        REAL**        Weight;        /* - connection weights to ith unit      */
        BOOL*         Winner;        /* - marker for winning instar           */
} LAYER;

typedef struct {                     /* A NET:                                */
        LAYER*        InputLayer;    /* - input layer                         */
        LAYER*        InstarLayer;   /* - instar layer                        */
        LAYER*        OutstarLayer;  /* - outstar layer                       */
        INT           Winners;       /* - allowed number of winning instars   */
        REAL          Alpha;         /* - hidden layer learning rate          */
        REAL          Beta;          /* - output layer learning rate          */
} 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      8
#define X             11
#define Y             11

#define N             (X * Y)
#define C             NUM_DATA
#define M             2

CHAR                  Pattern[NUM_DATA][Y][X] =  { { "           ",
                                                     "           ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "   OOOOO   ",
                                                     "   OOOOO   ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "        O  ",
                                                     "       O   ",
                                                     "     OOO   ",
                                                     "    OOO    ",
                                                     "   OOO     ",
                                                     " OOOOO     ",
                                                     "OOOOO      ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "           ",
                                                     "  OO       ",
                                                     "  OOOOO    ",
                                                     "  OOOOOOO  ",
                                                     "  OOOOO    ",
                                                     "  OO       ",
                                                     "           ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "OOOOO      ",
                                                     " OOOOO     ",
                                                     "   OOO     ",
                                                     "    OOO    ",
                                                     "     OOO   ",
                                                     "       O   ",
                                                     "        O  ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "   OOOOO   ",
                                                     "   OOOOO   ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "      OOOOO",
                                                     "     OOOOO ",
                                                     "     OOO   ",
                                                     "    OOO    ",
                                                     "   OOO     ",
                                                     "   O       ",
                                                     "  O        ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "           ",
                                                     "       OO  ",
                                                     "    OOOOO  ",
                                                     "  OOOOOOO  ",
                                                     "    OOOOO  ",
                                                     "       OO  ",
                                                     "           ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "  O        ",
                                                     "   O       ",
                                                     "   OOO     ",
                                                     "    OOO    ",
                                                     "     OOO   ",
                                                     "     OOOOO ",
                                                     "      OOOOO",
                                                     "           ",
                                                     "           "  } };

CHAR                  Pattern_[NUM_DATA][Y][X] = { { "           ",
                                                     "           ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "   OOOOO   ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "    O O    ",
                                                     "    O O    ",
                                                     "    O O    ",
                                                     "   O   O   ",
                                                     "   O   O   ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "           ",
                                                     "     O     ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "   OOOOO   ",
                                                     "           ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "           ",
                                                     "           ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "    OOO    ",
                                                     "           ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "  O        ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "    OOO    ",
                                                     "    OO     ",
                                                     "    OOO   O",
                                                     "    OOOO   ",
                                                     "   OOOOO   ",
                                                     "           ",
                                                     "       O   "  },

                                                   { "           ",
                                                     "           ",
                                                     "     O     ",
                                                     "     O     ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "   OOOOO   ",
                                                     "   OOOOO   ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "       O   ",
                                                     "      O    ",
                                                     "    OOO    ",
                                                     "    OOO    ",
                                                     "   OOO     ",
                                                     "  OOOOO    ",
                                                     " OOOOO     ",
                                                     "           ",
                                                     "           "  },

                                                   { "           ",
                                                     "           ",
                                                     "        O  ",
                                                     "       O   ",
                                                     "     OOO   ",
                                                     "    OOO    ",
                                                     "   OOO     ",
                                                     " OOOOO     ",
                                                     "OOOOO      ",
                                                     "           ",
                                                     "           "  } };
                                                    
REAL                  Input [NUM_DATA][N];
REAL                  Input_[NUM_DATA][N];
REAL                  Output[NUM_DATA][M];

FILE*                 f;


void NormalizeInput()
{
  INT  n,i;
  REAL Length, Length_;

  for (n=0; n<NUM_DATA; n++) {
    Length  = 0;
    Length_ = 0;
    for (i=0; i<N; i++) {
      Length  += sqr(Input [n][i]);
      Length_ += sqr(Input_[n][i]);
    }
    Length  = sqrt(Length);
    Length_ = sqrt(Length_);
    for (i=0; i<N; i++) {
      Input [n][i] /= Length;
      Input_[n][i] /= Length_;
    }
  }
}


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] = (Pattern [n][i][j] == 'O') ? HI : LO;
        Input_[n][i*X+j] = (Pattern_[n][i][j] == 'O') ? HI : LO;
      }
    }
  }
  NormalizeInput();
  for (n=0; n<NUM_DATA; n++) {
    Output[n][0] = sin(n * 0.25 * PI);
    Output[n][1] = cos(n * 0.25 * PI);
  }
  f = fopen("CPN.txt", "w");
}


void WriteInput(NET* Net, REAL* Input)
{
  INT i;
   
  for (i=0; i<N; i++) {
    if (i%X == 0) {
      fprintf(f, "\n");
    }
    fprintf(f, "%c", (Input[i] != LO) ? 'O' : ' ');
  }
  fprintf(f, " -> ");
}


void WriteOutput(NET* Net, REAL* Output)
{
  REAL Angle;

  Angle = (atan2(Output[0], Output[1]) / PI) * 180;
  if (Angle < 0)
    Angle = Angle + 360;

  fprintf(f, "%0.0f°\n", Angle);
}


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->InputLayer   = (LAYER*) malloc(sizeof(LAYER));
  Net->InstarLayer  = (LAYER*) malloc(sizeof(LAYER));
  Net->OutstarLayer = (LAYER*) malloc(sizeof(LAYER));

  Net->InputLayer->Units    = N;
  Net->InputLayer->Output   = (REAL*)  calloc(N, sizeof(REAL));
      
  Net->InstarLayer->Units   = C;
  Net->InstarLayer->Output  = (REAL*)  calloc(C, sizeof(REAL));
  Net->InstarLayer->Weight  = (REAL**) calloc(C, sizeof(REAL*));
  Net->InstarLayer->Winner  = (BOOL*)  calloc(C, sizeof(BOOL));
      
  Net->OutstarLayer->Units  = M;
  Net->OutstarLayer->Output = (REAL*)  calloc(M, sizeof(REAL));
  Net->OutstarLayer->Weight = (REAL**) calloc(M, sizeof(REAL*));
      
  for (i=0; i<C; i++) {
    Net->InstarLayer->Weight[i] = (REAL*) calloc(N, sizeof(REAL));
  }
  for (i=0; i<M; i++) {
    Net->OutstarLayer->Weight[i] = (REAL*) calloc(C, sizeof(REAL));
  }

  Net->Winners = 1;
  Net->Alpha   = 0.1;
  Net->Beta    = 0.1;
}


void SetInput(NET* Net, REAL* Input, BOOL Protocoling)
{
  INT i;
   
  for (i=0; i<Net->InputLayer->Units; i++) {
    Net->InputLayer->Output[i] = Input[i];
  }
  if (Protocoling) {
    WriteInput(Net, Input);
  }
}


void GetOutput(NET* Net, REAL* Output, BOOL Protocoling)
{
  INT i;
   
  for (i=0; i<Net->OutstarLayer->Units; i++) {
    Output[i] = Net->OutstarLayer->Output[i];
  }
  if (Protocoling) {
    WriteOutput(Net, Output);
  }
}


/******************************************************************************
                     P R O P A G A T I N G   S I G N A L S
 ******************************************************************************/


void PropagateToInstars(NET* Net)
{
  INT  w,i,j;
  REAL Sum, SumWinners, MaxOut;
  INT  Winner;

  for (i=0; i<Net->InstarLayer->Units; i++) {
    Sum = 0;
    for (j=0; j<Net->InputLayer->Units; j++) {
      Sum += Net->InstarLayer->Weight[i][j] * Net->InputLayer->Output[j];
    }
    Net->InstarLayer->Output[i] = Sum;
    Net->InstarLayer->Winner[i] = FALSE;
  }
  SumWinners = 0;
  for (w=0; w<Net->Winners; w++) {
    MaxOut = MIN_REAL;
    for (i=0; i<Net->InstarLayer->Units; i++) {
      if (NOT Net->InstarLayer->Winner[i] AND Net->InstarLayer->Output[i] > MaxOut)
        MaxOut = Net->InstarLayer->Output[Winner = i];
    }
    Net->InstarLayer->Winner[Winner] = TRUE;
    SumWinners += Net->InstarLayer->Output[Winner];
  }
  for (i=0; i<Net->InstarLayer->Units; i++) {
    if (Net->InstarLayer->Winner[i])
      Net->InstarLayer->Output[i] = Net->InstarLayer->Output[i] / SumWinners;
    else
      Net->InstarLayer->Output[i] = 0;
  }
}


void PropagateToOutstars(NET* Net)
{
  INT  i,j;
  REAL Sum;

  for (i=0; i<Net->OutstarLayer->Units; i++) {
    Sum = 0;
    for (j=0; j<Net->InstarLayer->Units; j++) {  
      Sum += Net->OutstarLayer->Weight[i][j] * Net->InstarLayer->Output[j];
    }
    Net->OutstarLayer->Output[i] = Sum;
  }
}


void PropagateNet(NET* Net)
{
  PropagateToInstars(Net);
  PropagateToOutstars(Net);
}


/******************************************************************************
                        T R A I N I N G   T H E   N E T
 ******************************************************************************/


INT Winner(NET* Net)
{
  INT i;

  for (i=0; i<Net->InstarLayer->Units; i++) {
    if (Net->InstarLayer->Winner[i])
      return i;
  }
}


void TrainInstars(NET* Net, INT Epochs)
{
  INT n,m,i,j;
   
  for (i=0; i<Net->InstarLayer->Units; i++) {
    for (j=0; j<Net->InputLayer->Units; j++) {
      Net->InstarLayer->Weight[i][j] = Input[i][j];
    }
  }
  Net->Winners = 1;
  for (m=0; m<Epochs*NUM_DATA; m++) {
    n = RandomEqualINT(0, NUM_DATA-1);
    SetInput(Net, Input[n], FALSE);
    PropagateToInstars(Net);
    i = Winner(Net);
    for (j=0; j<Net->InputLayer->Units; j++) {
      Net->InstarLayer->Weight[i][j] +=
        Net->Alpha * (Input[n][j] - Net->InstarLayer->Weight[i][j]);
    }
  }
}


void TrainOutstars(NET* Net, INT Epochs)
{
  INT n,m,i,j;
   
  for (i=0; i<Net->OutstarLayer->Units; i++) {
    for (j=0; j<Net->InstarLayer->Units; j++) {
      Net->OutstarLayer->Weight[i][j] = Output[j][i];
    }
  }
  Net->Winners = 1;
  for (m=0; m<Epochs*NUM_DATA; m++) {
    n = RandomEqualINT(0, NUM_DATA-1);
    SetInput(Net, Input[n], FALSE);
    PropagateToInstars(Net);
    j = Winner(Net);
    for (i=0; i<Net->OutstarLayer->Units; i++) {
      Net->OutstarLayer->Weight[i][j] +=
        Net->Beta * (Output[n][i] - Net->OutstarLayer->Weight[i][j]);
    }
  }
}


/******************************************************************************
                      S I M U L A T I N G   T H E   N E T
 ******************************************************************************/


void SimulateNet(NET* Net, REAL* Input)
{
  REAL Output[M];

  SetInput(Net, Input, TRUE);
  PropagateNet(Net);
  GetOutput(Net, Output, TRUE);
}


/******************************************************************************
                                    M A I N
 ******************************************************************************/


void main()
{
  NET Net;
  INT n;

  InitializeRandoms();
  GenerateNetwork(&Net);
  InitializeApplication(&Net);
  TrainInstars(&Net, 0);         /* weights are computed for this application */
  TrainOutstars(&Net, 0);        /* weights are computed for this application */

  Net.Winners = 2;
  for (n=0; n<NUM_DATA; n++) {
    SimulateNet(&Net, Input[n]);
  }
  for (n=0; n<NUM_DATA; n++) {
    SimulateNet(&Net, Input_[n]);
  }

  FinalizeApplication(&Net);
}

Simulator Output for the Vision Application

           
           
     O     
     O     
    OOO    
    OOO    
    OOO    
   OOOOO   
   OOOOO   
           
            -> 0°

           
           
        O  
       O   
     OOO   
    OOO    
   OOO     
 OOOOO     
OOOOO      
           
            -> 45°

           
           
           
  OO       
  OOOOO    
  OOOOOOO  
  OOOOO    
  OO       
           
           
            -> 90°

           
           
OOOOO      
 OOOOO     
   OOO     
    OOO    
     OOO   
       O   
        O  
           
            -> 135°

           
           
   OOOOO   
   OOOOO   
    OOO    
    OOO    
    OOO    
     O     
     O     
           
            -> 180°

           
           
      OOOOO
     OOOOO 
     OOO   
    OOO    
   OOO     
   O       
  O        
           
            -> 225°

           
           
           
       OO  
    OOOOO  
  OOOOOOO  
    OOOOO  
       OO  
           
           
            -> 270°

           
           
  O        
   O       
   OOO     
    OOO    
     OOO   
     OOOOO 
      OOOOO
           
            -> 315°

           
           
     O     
     O     
     O     
    OOO    
    OOO    
    OOO    
   OOOOO   
           
            -> 0°

           
           
     O     
     O     
    O O    
    O O    
    O O    
   O   O   
   O   O   
           
            -> 0°

           
           
           
     O     
    OOO    
    OOO    
    OOO    
   OOOOO   
           
           
            -> 0°

           
           
           
           
     O     
     O     
     O     
    OOO    
           
           
            -> 20°

           
  O        
     O     
     O     
    OOO    
    OO     
    OOO   O
    OOOO   
   OOOOO   
           
       O    -> 0°

           
           
     O     
     O     
    OOO    
    OOO    
    OOO    
   OOOOO   
   OOOOO   
           
            -> 0°

           
           
       O   
      O    
    OOO    
    OOO    
   OOO     
  OOOOO    
 OOOOO     
           
            -> 23°

           
           
        O  
       O   
     OOO   
    OOO    
   OOO     
 OOOOO     
OOOOO      
           
            -> 45°



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