home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume29 / persim / part01 / run.c < prev    next >
C/C++ Source or Header  |  1992-04-06  |  6KB  |  225 lines

  1. /*Copyright  (c)   1992  Adam  Stein.   All  Rights Reserved.   
  2.  
  3.   Permission to use,  copy,  modify  and  distribute  without
  4.   charge this software, documentation, images, etc. is grant-
  5.   ed, provided that this copyright and the author's  name  is  
  6.   retained.   
  7.   
  8.   A fee may be charged for this program ONLY to recover costs   
  9.   for distribution (i.e. media costs).  No profit can be made            
  10.   on this program.   
  11.    
  12.   The author assumes no responsibility for disasters (natural   
  13.   or otherwise) as a consequence of use of this software.      
  14.    
  15.   Adam Stein (stein.wbst129@xerox.com)         
  16. */ 
  17.  
  18. #include <stdio.h>
  19. #include <signal.h>
  20. #include <math.h>
  21. #include "persim.h"
  22.  
  23. int quit,numepoch;
  24. double *actual;
  25. char *calloc();
  26. extern double *input,*output,*desired,**weights;
  27. extern NODE_ATTR *node_attr;
  28. extern STATE state;
  29.  
  30. /*This routine will simulate a single layer perceptron.
  31.  
  32.   Inputs:  verbose     - flag to indicate to run in verbose mode
  33.   Outputs: none        - 0
  34.   Locals:  convergence - flag indicating if weights have converged
  35.        loop        - loop through weights arrays
  36.        loop2       - loop through weights array elements
  37.        old_wts     - previous values of the weights
  38.   Globals: actual      - actual output values
  39.        desired     - desired output values
  40.        input       - input values
  41.        node_attr   - node attributes (function, threshold)
  42.        numepoch    - number of the epoch
  43.        quit        - flag indicating to quit simulation
  44.        state       - system variables
  45.        weights     - perceptron weights
  46.        NULL        - 0
  47.        UNKNOWN     - variable isn't set
  48. */
  49. void run(verbose)
  50. register int verbose;
  51. {
  52.     register int loop,loop2,convergence;
  53.     double **old_wts;
  54.     void quitit(),snapshot();
  55.  
  56.     /*Make sure all variables needed are set*/
  57.     if(state.inodes == UNKNOWN) {
  58.       puts("the number of input nodes has not been set");
  59.       return;
  60.     }
  61.     if(state.onodes == UNKNOWN) {
  62.       puts("the number of output nodes has not been set");
  63.       return;
  64.     }
  65.     if(input == (double *) NULL) {
  66.       puts("no input data points have been loaded");
  67.       return;
  68.     }
  69.     if(state.training && (desired == (double *) NULL)) {
  70.       puts("no desired output data points have been loaded");
  71.       return;
  72.     }
  73.     if(node_attr == (NODE_ATTR *) NULL) {
  74.     puts("node thresholds and functions haven't been set");
  75.     return;
  76.     }
  77.  
  78.     /*If the weights haven't been set, initialize to random values*/
  79.     if(weights == (double **) NULL) {
  80.       puts("warning: weights not set, initializing to random values");
  81.       randomize();
  82.     }
  83.  
  84.     if(state.training) {
  85.       old_wts = (double **) NULL;
  86.       alloc_wts(&old_wts,state.inodes,state.onodes);
  87.     }
  88.  
  89.     if((actual = (double *) calloc(state.onodes,sizeof(double))) == NULL)
  90.       error();
  91.  
  92.     /*Set up signals*/
  93.     signal(SIGINT,quitit);
  94.     if(!verbose) signal(SIGTSTP,snapshot);
  95.  
  96.     /*Begin simulation*/
  97.     convergence = quit = 0;
  98.     numepoch = 1;
  99.     while(!convergence) {
  100.       do_epoch();
  101.  
  102.       /*If training, adjust weights until convergence*/
  103.       if(state.training) {
  104.         convergence = 1;
  105.         for(loop = 0;loop < state.onodes;++loop)
  106.           for(loop2 = 0;loop2 < state.inodes;++loop2) {
  107.         old_wts[loop2][loop] = weights[loop2][loop];
  108.             weights[loop2][loop] += (state.alpha * 
  109.                      (desired[loop] - actual[loop]) *
  110.                          input[loop2]);
  111.  
  112.         if((fabs(weights[loop2][loop] - old_wts[loop2][loop]) >
  113.             0.000025) && !quit)
  114.           convergence = 0;
  115.           }
  116.  
  117.         /*Print information if user requested verbosity*/
  118.         if(verbose) snapshot();
  119.       } else convergence = 1;
  120.  
  121.       ++numepoch;
  122.     }
  123.  
  124.     alloc_data(state.onodes,&output);
  125.     bcopy((char *) actual,(char *) output,state.onodes*sizeof(double));
  126.  
  127.     free((char *) actual);
  128.     if(state.training) {
  129.       for(loop = 0;loop < state.inodes;++loop)
  130.         free((char *) old_wts[loop]);
  131.       free((char *) old_wts);
  132.     }
  133.  
  134.     /*Restore signals*/
  135.     signal(SIGINT,SIG_DFL);
  136.     signal(SIGTSTP,SIG_DFL);
  137. }
  138.  
  139. /*This routine does the calculations that make up an epoch.
  140.  
  141.   Inputs:  none
  142.   Outputs: none
  143.   Locals:  loop      - loop through output nodes
  144.        loop2     - loop though inputs
  145.        sum       - sum of an output node
  146.   Globals: actual    - actual output values
  147.        input     - input values
  148.        node_attr - node attributes (function, threshold)
  149.        quit      - flag indicating to quit simulation
  150.        state     - system variables
  151.        weights   - perceptron weights
  152.        NULL      - 0
  153. */
  154. do_epoch()
  155. {
  156.     register int loop,loop2;
  157.     register double sum;
  158.  
  159.     for(loop = 0;loop < state.onodes;++loop) {
  160.       for(loop2 = 0,sum = 0.0;loop2 < state.inodes;++loop2)
  161.         sum += (weights[loop2][loop] * input[loop2]);
  162.  
  163.       if(node_attr[loop].func == NULL) {
  164.         printf("the function for output node #%d hasn't been set ... quitting run\n",loop);
  165.         quit = 1;
  166.         return;
  167.       }
  168.  
  169.       actual[loop] = node_attr[loop].func(sum - node_attr[loop].threshold);
  170.     }
  171. }
  172.  
  173. /*This routine will set the weights to random numbers between 0.0 and 1.0.
  174.  
  175.   Inputs:  none
  176.   Outputs: none
  177.   Locals:  from    - from which input node
  178.        to      - to which output node
  179.   Globals: state   - system variables
  180.        weights - perceptron weights
  181. */
  182. randomize()
  183. {
  184.     register int from,to;
  185.     double drand48();
  186.  
  187.     alloc_wts(&weights,state.inodes,state.onodes);
  188.  
  189.     for(from = 0;from < state.inodes;++from)
  190.       for(to = 0;to < state.onodes;++to)
  191.         weights[from][to] = drand48();
  192. }
  193.  
  194. /*This routine is called if ^C is pressed.  It sets up the flag to exit
  195.   the simulator.
  196.  
  197.   Inputs:  none
  198.   Outputs: none
  199.   Locals:  none
  200.   Globals: quit - flag indicating to quit simulation
  201. */
  202. void quitit()
  203. {
  204.     quit = 1;
  205. }
  206.  
  207. void snapshot()
  208. {
  209.     register int loop,loop2;
  210.  
  211.     printf("Epoch #%d:\n",numepoch);
  212.  
  213.     for(loop = 0;loop < state.onodes;++loop)
  214.       printf("  Actual Output Node #%d = %lf\n",loop+1,actual[loop]);
  215.  
  216.     puts("");
  217.  
  218.     for(loop = 0;loop < state.inodes;++loop)
  219.       for(loop2 = 0;loop2 < state.onodes;++loop2)
  220.         printf("  [New] From #%d, To #%d, Weight = %lf\n",loop+1,loop2+1,weights[loop][loop2]);
  221.           
  222.     puts("");
  223. }
  224.  
  225.