home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / Source / GPCHAP23 / NETWARE.ZIP / nnlist3.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-19  |  9.1 KB  |  331 lines

  1. // HOPFIELD NET SIMULATOR /////////////////////////////////////////////////////////
  2.  
  3. // this simulator created based on Hebb Net software, very similar except that
  4. // inputs act as outputs and weight matrix is always square
  5.  
  6. // INCLUDES //////////////////////////////////////////////////////////////////////
  7.  
  8. #include <conio.h>
  9. #include <stdlib.h>
  10. #include <malloc.h>
  11. #include <memory.h>
  12. #include <string.h>
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18.  
  19. // DEFINES ///////////////////////////////////////////////////////////////////////
  20.  
  21. #define MAX_NEURODES    16    // maximum number of inputs/outputs
  22.  
  23. #define ACTF_STEP        0    // use a binary step activation function fs(x)
  24. #define ACTF_LINEAR        1    // use a linear activation function fl(s)
  25. #define ACTF_EXP        2    // use an inverse exponential activation function fe(x)
  26.  
  27. // MACROS ////////////////////////////////////////////////////////////////////////
  28.  
  29. // used to retrieve the i,jth element of a linear, row major, matrix
  30.  
  31. #define MAT(mat,width,i,j) (mat[((width)*i)+(j)])
  32.  
  33. // GLOBALS ///////////////////////////////////////////////////////////////////////
  34.  
  35. float    input_xi[MAX_NEURODES],        // holds that input values
  36.         input_i[MAX_NEURODES],        // holds a single input vector
  37.         output_i[MAX_NEURODES],        // holds a single output vector 
  38.         input_act[MAX_NEURODES],    // holds the summed input activations 
  39.         output_yi[MAX_NEURODES],    // holds the output values
  40.         alpha = (float)1.0,            // needed for exponential activation function
  41.         *weight_matrix = NULL;        // dynamically allocated weight matrix
  42.         
  43. int        num_neurodes,                // number of inputs in heb net
  44.         activation_func = ACTF_STEP;// type of activation function to use
  45.  
  46. // FUNCTIONS /////////////////////////////////////////////////////////////////////
  47.  
  48. void Train_Net(void)
  49. {
  50. // this function is resposible for training the neural net using hebbian learning
  51.  
  52. // ask the user for another input/ouptput vector pair and then add the vectors contribution to
  53. // the weight matrix and bias
  54.  
  55. printf("\nHopfield Training System.");
  56. printf("\nTo train neural net you will enter each input vector to be recalled.");
  57. printf("\nAll input vectors must be in bipolar form (1,-1,...1).");
  58. printf("\nInput vectors an element at a time.");
  59.  
  60. printf("\n\nInput vectors have %d components",num_neurodes);
  61.  
  62. while(1)
  63.     {
  64.     // get the input vector
  65.     printf("\nEnter input vector elements\n");
  66.  
  67.     for (int index=0; index<num_neurodes; index++)
  68.         {
  69.         printf("Input Vector Element[%d]=?",index);
  70.         scanf("%f",&input_i[index]);
  71.         } // end for
  72.  
  73.     // train the net with new vector, note we process one neuron at a time
  74.  
  75.     for (int index_j=0; index_j<num_neurodes; index_j++)
  76.         {
  77.         for (int index_i=0; index_i<num_neurodes; index_i++)
  78.             {
  79.             // use hebb learning alg. w=w+input(transpose)*input
  80.             
  81.             MAT(weight_matrix,num_neurodes,index_i, index_j) += (input_i[index_i]*input_i[index_j]);
  82.             
  83.             // test if i=j
  84.  
  85.             if (index_i==index_j)
  86.                 MAT(weight_matrix,num_neurodes,index_i, index_j) =(float)0.0;
  87.  
  88.             } // end for index_i
  89.     
  90.         } // end for index_j
  91.  
  92.     printf("\nDo you wish to enter another input vector Y or N?");
  93.     char ans[8];
  94.     scanf("%s",ans);
  95.     if (toupper(ans[0])!='Y')
  96.         break;
  97.  
  98.     } // end while
  99.  
  100. } // end Train_Net
  101.  
  102. //////////////////////////////////////////////////////////////////////////////////
  103.  
  104. void Run_Net(void)
  105. {
  106. // this function is responsible for running the net, it allows the user to enter test
  107. // vectors and then computes the response of the network
  108.  
  109. printf("\nHopfield Autoassociative Memory Simulation System.");
  110. printf("\nYou will enter in test input vectors in binary form.");
  111. printf("\nAll inputs must have %d elements.\n",num_neurodes);
  112.  
  113. while(1)
  114.     {
  115.     // get the input vector
  116.     printf("\nEnter input vector elements\n");
  117.  
  118.     for (int index=0; index<num_neurodes; index++)
  119.         {
  120.         printf("Input Vector Element[%d]=?",index);
  121.         scanf("%f",&input_i[index]);
  122.         } // end for
  123.  
  124.     // now process the input by performing a matrix mutiply
  125.     // each weight vector is stored as a column in the weight matrix, so to process
  126.     // the input for each neurode, we simply must perform a dot product, and then input
  127.     // the result to the activation function, this is the basis of the parallel 
  128.     // processing a neural net performs, all outputs are independent of the others
  129.  
  130.     // loop thru the columns (outputs, neurodes)
  131.     for (int index_j=0; index_j<num_neurodes; index_j++)
  132.         {
  133.         // now compute a dot product with the input vector and the column
  134.  
  135.         input_act[index_j] = (float)0.0; // reset activation
  136.  
  137.         for (int index_i=0; index_i<num_neurodes; index_i++)
  138.             {
  139.             input_act[index_j] = input_act[index_j] + 
  140.                 (MAT(weight_matrix,num_neurodes,index_i, index_j) * input_i[index_i]);
  141.             } // end for index_i
  142.         
  143.         // now compute output based on activation function
  144.         // note step should be used in most cases
  145.         if (activation_func==ACTF_STEP)
  146.             {
  147.             // perform step activation
  148.             if (input_act[index_j]>=(float)0.0)
  149.                 output_yi[index_j] = (float)1.0;
  150.             else
  151.                 output_yi[index_j] = (float)0.0;
  152.  
  153.             } // end if
  154.         else
  155.         if (activation_func==ACTF_LINEAR)
  156.             {
  157.             // perform linear activation
  158.             output_yi[index_j] = input_act[index_j];
  159.             }
  160.         else
  161.             {
  162.             // must be exponential activation
  163.             output_yi[index_j] =(float)(1/(1+exp(-input_act[index_j]*alpha)));
  164.     
  165.             } // end else exp
  166.  
  167.         } // end for index_j
  168.  
  169.     // now that ouputs have been computed print everything out
  170.  
  171.     printf("\nNet inputs were:\n[");
  172.     for (index_j=0; index_j<num_neurodes; index_j++)
  173.         printf("%2.2f, ",input_act[index_j]);
  174.     printf("]\n");
  175.     
  176.     printf("\nFinal Outputs after activation functions are:\n[");
  177.     for (index_j=0; index_j<num_neurodes; index_j++)
  178.         printf("%2.2f, ",output_yi[index_j]);
  179.     printf("]\n");
  180.  
  181.     // test if input was recalled corretly
  182.     int bit_error=0;
  183.     for (int index_i = 0; index_i<num_neurodes; index_i++)
  184.         if (fabs(input_i[index_i]-output_yi[index_i])>.01)
  185.             {
  186.             bit_error++;
  187.             } // end if error
  188.  
  189.     if (bit_error)
  190.         printf("\nThere were %d bit error(s) in recall, try re-inputing the output.", bit_error);
  191.     else
  192.         printf("\nPerfect Recall!");
  193.  
  194.     printf("\nDo you wish to enter another test input Y or N?");
  195.     char ans[8];
  196.     scanf("%s",ans);
  197.     if (toupper(ans[0])!='Y')
  198.         break;
  199.  
  200.     } // end while
  201.  
  202. } // end Run_Net
  203.  
  204. //////////////////////////////////////////////////////////////////////////////////
  205.  
  206. void Print_Net(void)
  207. {
  208. // this function prints out the current weight matrix and biases along with the specifics
  209. // about the net
  210.  
  211. printf("\nThe Hopfield Net has %d neurodes/inputs/outputs",num_neurodes);
  212. printf("\nThe weight matrix is %dX%d",num_neurodes, num_neurodes);
  213. printf("\nThe W[i,j]th element refers to the weight from the ith to jth neurode\n");
  214.  
  215. for (int index_i = 0; index_i<num_neurodes;index_i++)
  216.     {
  217.     printf("\n|");
  218.     for (int index_j=0; index_j<num_neurodes; index_j++)
  219.         {
  220.         // data is in row major form
  221.         printf(" %2.2f ",MAT(weight_matrix,num_neurodes,index_i,index_j));
  222.  
  223.         } // end for index_j
  224.  
  225.     printf("|");
  226.     
  227. } // end for index_row
  228.  
  229. printf("\n");
  230.  
  231. } // end Print_Net
  232.  
  233. //////////////////////////////////////////////////////////////////////////////////
  234.  
  235. void Reset_Net(void)
  236. {
  237. // clear out all the matrices
  238. memset(weight_matrix,0,num_neurodes*num_neurodes*sizeof(float));
  239.  
  240. } // end Reset_Net
  241.  
  242. // MAIN //////////////////////////////////////////////////////////////////////////
  243.  
  244. void main(void)
  245. {
  246. float FORCE_FP_LINK=(float)1.0; // needed for bug in VC++ fp lib link
  247.  
  248. printf("\nHopfield Neural Network Simulator.\n");
  249.  
  250. // querry user for parmaters of network
  251.  
  252. printf("\nEnter number of inputs (which is the same as outputs)?");
  253. scanf("%d",&num_neurodes);
  254.  
  255. printf("\nSelect Activation Function (Hopfield usually uses Step)\n0=Step, 1=Linear, 2=Exponential?");
  256. scanf("%d",&activation_func);
  257.  
  258. // test for exponential, get alpha is needed
  259. if (activation_func == ACTF_EXP)
  260.     {
  261.     printf("\nEnter value for alpha (decimals allowed)?");
  262.     scanf("%f",&alpha);
  263.     } // end if
  264.  
  265. // allocate weight matrix it is mxn where m is the number of inputs and n is the
  266. // number of outputs
  267. weight_matrix = new float[num_neurodes*num_neurodes];
  268.  
  269. // clear out matrices
  270. Reset_Net();
  271.  
  272. // enter main event loop
  273.  
  274. int    sel=0,
  275.     done=0;
  276.  
  277. while(!done)
  278.     {
  279.     printf("\nHopfield Autoassociative Memory Main Menu\n");
  280.     printf("\n1. Input Training Vectors into Neural Net.");
  281.     printf("\n2. Run Neural Net.");
  282.     printf("\n3. Print Out Weight Matrix.");
  283.     printf("\n4. Reset Weight Matrix.");
  284.     printf("\n5. Exit Simulator.");
  285.     printf("\n\nSelect One Please?");
  286.     scanf("%d",&sel);
  287.  
  288.     // what was the selection
  289.     switch(sel)
  290.         {
  291.     
  292.         case 1: // Input Training Vectors into Neural Net
  293.             {
  294.             Train_Net();
  295.                 
  296.             } break;
  297.     
  298.         case 2: // Run Neural Net
  299.             {
  300.             Run_Net();
  301.             } break;
  302.     
  303.         case 3: // Print Out Weight Matrix
  304.             {
  305.             Print_Net();
  306.             } break;
  307.     
  308.         case 4: // Reset Weight Matrix
  309.             {
  310.             Reset_Net();
  311.             } break;
  312.     
  313.         case 5: // Exit Simulator
  314.             {
  315.             // set exit flag
  316.             done=1;
  317.  
  318.             } break;
  319.     
  320.         default:break;
  321.  
  322.         } // end swtich
  323.  
  324.     } // end while
  325.  
  326. // free up resources
  327.  
  328. delete [] weight_matrix;
  329.  
  330. } // end main
  331.