home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / Source / NNV / NeuronCntrl.m < prev    next >
Encoding:
Text File  |  1992-05-15  |  8.5 KB  |  327 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "NeuronCntrl.h"
  5. #import "NeuronView.h"            // to access the NeuronView methods
  6. #import <appkit/Application.h>
  7. #import <streams/streams.h>
  8. #import <objc/NXStringTable.h>
  9. #import <sys/file.h>
  10. #import <appkit/Panel.h>
  11. #import <appkit/OpenPanel.h>
  12. #import <appkit/SavePanel.h>
  13. #import <math.h>            // for the sqrt function call
  14.  
  15. #define MAX_IN_WINDOW 9 // used for specifying how
  16.             // many in NNV window before resizing scrollview.
  17.              
  18. // GLOBAL VARIABLES
  19. NXStream    *inputstream,    // input file stream
  20.         *outputstream;    // output file stream
  21.  
  22. float *NeuronValues;    // values after calculation.
  23. float **Network;    // network matrix Network[][]
  24. NXPoint *NeuronLoc;     // array of neuron locations for displaying.    
  25.  
  26. int NUM_INPUTS = 0;            // network info derived from .network
  27. int NUM_NODES = 0;
  28. int NUM_OUTPUTS = 0;
  29. BOOL INPUT_OPENED = FALSE;        // boolean file open variables
  30. BOOL NETWORK_OPENED = FALSE;
  31. BOOL TEMPCLEAR = TRUE;            // boolean output buffer clear variable
  32.  
  33.  
  34. @implementation NeuronCntrl
  35.  
  36. // method called when application starts (init)
  37. - appDidInit:sender
  38. {
  39.   [super init];
  40.   // get instances of support objects
  41.   openReq = [OpenPanel new];
  42.   writeReq = [SavePanel new];
  43.  
  44.   return self;
  45. }
  46.  
  47.  
  48. // opens specified input file and stores 1st input set in NeuronValues[]
  49. - openInputFile:sender
  50. {
  51.     const char *fileName;
  52.     const char *const types[2] = {"input",NULL};
  53.     
  54.     if (NETWORK_OPENED) // only open if .network already openned.
  55.     {
  56.       if ([openReq runModalForTypes:types] && (fileName = [openReq filename]))
  57.       {    
  58.     inputstream = NXMapFile(fileName, NX_READONLY);    // open the file stream
  59.     INPUT_OPENED = TRUE;        // set the boolean flag
  60.     [self nextInputSet:sender];    // read in first input set
  61.       }
  62.       else        // error or <cancel> occurred
  63.         NXRunAlertPanel(NULL,"Error On Open Request!", NULL, NULL, NULL);
  64.     }
  65.     else
  66.       NXRunAlertPanel(NULL,
  67.       "Must Open Network file first!", NULL, NULL, NULL);
  68.       
  69.     return self;
  70. }
  71.  
  72.  
  73. // open network, read size, allocate memory, load Network matrix, count inputs, // outputs, resize view according to NUM_NODES, display network.
  74. // Then close file...
  75. - openNetworkFile:sender
  76. {
  77.     // used for resizable scrollview...
  78.     float viewArea,viewRatio;
  79.     NXRect theViewRect;
  80.     NXSize newView;
  81.     // others used in this method...
  82.     int i,j;
  83.     NXStream        *networkstream;    // network file stream
  84.    
  85.     const char *fileName;
  86.     const char *const types[2] = {"network",NULL};
  87.     
  88.     // initialize global variables
  89.     NUM_INPUTS = 0;
  90.     NUM_OUTPUTS =0;
  91.     NUM_NODES = 0;
  92.     
  93.     // attempt to open .network file
  94.     if ([openReq runModalForTypes:types] && (fileName = [openReq filename]))
  95.     {
  96.     networkstream = NXMapFile(fileName, NX_READONLY); // open the stream
  97.     
  98.     if (NETWORK_OPENED) // open a different network? (one already openned?)
  99.     {
  100.       // first free previous memory...
  101.       for(i=0; i < NUM_NODES; i++)
  102.         free(Network[i]);
  103.       free(NeuronValues);
  104.       free(NeuronLoc);
  105.     }
  106.     NETWORK_OPENED = TRUE;        // set boolean flag
  107.     NXScanf(networkstream,"%d\n",&NUM_NODES); // read in number of neurons.
  108.     
  109.     // allocate memory and initialize to 0's (done by calloc).
  110.     if( (NeuronValues = (float *) calloc(NUM_NODES,sizeof(float))) == NULL)
  111.       exit(308);
  112.     if( (NeuronLoc =(NXPoint *) calloc(NUM_NODES,sizeof(NXPoint))) == NULL)
  113.       exit(308);
  114.         if( (Network = (float **) calloc(NUM_NODES,sizeof(float *)))
  115.        == NULL)
  116.     {
  117.       printf("error callocing Network memory...!\n");
  118.       exit(308);       
  119.     }
  120.     for(i=0; i < NUM_NODES; i++)
  121.       if( (Network[i] = (float *) calloc(NUM_NODES,sizeof(float))) == NULL)
  122.         exit(308);
  123.     
  124.     
  125.     i= j =0; // initialize index's
  126.     while (!NXAtEOS(networkstream))    // while not at end of stream.
  127.     {
  128.       // scan in a row from .network file and store in network memory...
  129.       while (((NXGetc(networkstream)) !='\n') && (!NXAtEOS(networkstream)))
  130.         {
  131.             NXUngetc(networkstream);
  132.             NXScanf(networkstream,"%f",&Network[i][j]);
  133.             j++;
  134.         }
  135.         i++;
  136.         j=0;
  137.     }
  138.     
  139.     // count inputs / outputs according to rows/cols of zeros.
  140.     [self getNumOutputs];        // count output neurons.
  141.     [self getNumInputs];        // count input neurons.
  142.     
  143.     // compute newsize for NeuronView according to number of neurons...       
  144.     [[theNeuronView superview]getFrame:&theViewRect];  // retrieve view sz.
  145.     viewArea = (theViewRect.size.width * theViewRect.size.height);
  146.     viewRatio = (theViewRect.size.width / theViewRect.size.height);
  147.     viewArea = viewArea*NUM_NODES/MAX_IN_WINDOW;  // calc newarea.
  148.     newView.height = sqrt(viewArea/viewRatio);
  149.     newView.width = newView.height*viewRatio;
  150.     // resize theNeuronView
  151.     [theNeuronView sizeTo:newView.width :newView.height];                 
  152.     [theNeuronView display];    // call the methods to redraw
  153.     NXCloseMemory(networkstream, NX_FREEBUFFER);  // close networkstream...
  154.     }
  155.     else
  156.         NXRunAlertPanel(NULL,"Error On Open Request!", NULL, NULL, NULL);
  157.  
  158.     return self;
  159. }
  160.  
  161.  
  162. // the method saves the outputstream to a file
  163. // - either appending to old file
  164. // - saving to a new file.
  165. // - closing the file after and clearing the output buffer
  166. - writeOutput:sender
  167. {
  168.     const char *name;
  169.  
  170.     if ((!TEMPCLEAR) && [writeReq runModal] && (name = [writeReq filename]))
  171.     {
  172.      
  173.      NXSaveToFile(outputstream, name);
  174.      NXCloseMemory(outputstream, NX_FREEBUFFER);
  175.      TEMPCLEAR = TRUE;
  176.     }
  177.     else
  178.        NXRunAlertPanel(NULL,"Error On Write Output Request!",NULL,NULL,NULL);
  179.  
  180.     return self;
  181. }
  182.  
  183. // clear the outputstream (if not already clear) - start with a clear one.
  184. - clearTemp:sender
  185. {
  186.      if (!TEMPCLEAR)
  187.      {
  188.        NXCloseMemory(outputstream, NX_FREEBUFFER);
  189.        TEMPCLEAR = TRUE;
  190.      }
  191.      return self;
  192. }
  193.  
  194.  
  195. // read next input set from input file into NeuronValue[]
  196. - nextInputSet:sender
  197. {
  198.     int i, numread, endFileChoice;
  199.     
  200.     // initialize NeuronValues[]
  201.     for (i=0; i < NUM_NODES; i++)
  202.       NeuronValues[i] = 0.0;
  203.     i=0;
  204.     // if both .input & .network files are open...
  205.     if ( (INPUT_OPENED) && (NETWORK_OPENED) )    
  206.     {
  207.       // read in the next input set (next row)
  208.       while ( (NXGetc(inputstream) != '\n') && (!NXAtEOS(inputstream)) )
  209.       {
  210.     NXUngetc(inputstream);
  211.     NXScanf(inputstream,"%f",&NeuronValues[i]);
  212.     i++;
  213.       }
  214.       numread = i;
  215.       
  216.       if (NUM_INPUTS == numread)    // if everything OK
  217.         [self computeActivity];        // call computeActivity method
  218.       else    // at end of stream, restart at beginning
  219.       {
  220.           endFileChoice = NXRunAlertPanel(NULL,
  221.                 "End of input file or error reading...
  222.                 retry from beginning!",
  223.                  NULL, "No!", NULL);
  224.     switch(endFileChoice)
  225.     {
  226.       case NX_ALERTDEFAULT:        // OK ->read from beginning...
  227.         NXSeek(inputstream, 0, NX_FROMSTART);
  228.         [self nextInputSet:sender];
  229.         break;
  230.       case NX_ALERTALTERNATE:        // No! do nothing yet...
  231.         break;
  232.       default:
  233.         break;
  234.     }
  235.       }
  236.     }
  237.     else
  238.         NXRunAlertPanel(NULL,
  239.     "Must Open Network and Input files first!", NULL, NULL, NULL);
  240.  
  241.     return self;
  242. }
  243.  
  244.  
  245. // calculate the output values for each interior and output neurons,
  246. // then put the output neuron values in the outputstream.
  247. // Finally, call the displayActivity method within NeuronView object, pointed
  248. // to by theNeuronView outlet.
  249. - computeActivity
  250. {
  251.   int i,j;
  252.   double sum = 0.0;
  253.   
  254.   for (i = NUM_INPUTS; i < NUM_NODES; i++)
  255.   {
  256.       for (j = 0; j < i; j++)
  257.       sum += (Network[i][j] * NeuronValues[j]);
  258.     
  259.     NeuronValues[i] = (1.0 / (1.0 + exp(-sum)));
  260.     sum = 0.0;
  261.   }
  262.   
  263.   if (TEMPCLEAR)  //does outputstream need to be connected to memory?
  264.   {
  265.     outputstream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  266.     TEMPCLEAR = FALSE;
  267.   }
  268.  
  269.   // for each output, put value in the output stream...
  270.   for(i = (NUM_NODES-NUM_OUTPUTS); i < NUM_NODES; i++)
  271.       NXPrintf(outputstream,"%f ",NeuronValues[i]);
  272.   NXPrintf(outputstream,"\n");
  273.   
  274.   [theNeuronView displayActivity];  // only fill the circles...
  275.  
  276.   return self;
  277. }
  278.  
  279.  
  280. // count the columns at right with all zeros = outputs
  281. - getNumOutputs
  282. {
  283.   int i,j;
  284.   
  285.   NUM_OUTPUTS = NUM_NODES;
  286.   
  287.   // this could be modified to start looking from diagonal
  288.   // instead of the rt. side. -oh, well, it works now!
  289.   for (i = (NUM_NODES -1); i >=0; i--)
  290.   {
  291.     for (j = (NUM_NODES -1); j >=0; j--)
  292.       if (Network[i][j] != 0)
  293.         break;
  294.     if (NUM_OUTPUTS >= (NUM_NODES -j))
  295.       NUM_OUTPUTS = (NUM_NODES - j -1);
  296.   }
  297.  
  298.   return self;
  299. }
  300.  
  301.  
  302. // count the rows with all zeros = #inputs
  303. - getNumInputs
  304. {
  305.   int j,i=0;
  306.   BOOL INPUT_OK = TRUE;
  307.   
  308.   NUM_INPUTS = 0;
  309.   
  310.   while  ((i < NUM_NODES) && (INPUT_OK))
  311.   {
  312.     for (j = 0; j < NUM_NODES; j++)
  313.       if (Network[i][j] != 0)
  314.       {
  315.         INPUT_OK = FALSE;
  316.     break;
  317.       }
  318.     i++;
  319.   }
  320.   NUM_INPUTS = i-1;
  321.   
  322.   return self;
  323. }
  324.  
  325.  
  326. @end
  327.