home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume29
/
persim
/
part01
/
run.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-06
|
6KB
|
225 lines
/*Copyright (c) 1992 Adam Stein. All Rights Reserved.
Permission to use, copy, modify and distribute without
charge this software, documentation, images, etc. is grant-
ed, provided that this copyright and the author's name is
retained.
A fee may be charged for this program ONLY to recover costs
for distribution (i.e. media costs). No profit can be made
on this program.
The author assumes no responsibility for disasters (natural
or otherwise) as a consequence of use of this software.
Adam Stein (stein.wbst129@xerox.com)
*/
#include <stdio.h>
#include <signal.h>
#include <math.h>
#include "persim.h"
int quit,numepoch;
double *actual;
char *calloc();
extern double *input,*output,*desired,**weights;
extern NODE_ATTR *node_attr;
extern STATE state;
/*This routine will simulate a single layer perceptron.
Inputs: verbose - flag to indicate to run in verbose mode
Outputs: none - 0
Locals: convergence - flag indicating if weights have converged
loop - loop through weights arrays
loop2 - loop through weights array elements
old_wts - previous values of the weights
Globals: actual - actual output values
desired - desired output values
input - input values
node_attr - node attributes (function, threshold)
numepoch - number of the epoch
quit - flag indicating to quit simulation
state - system variables
weights - perceptron weights
NULL - 0
UNKNOWN - variable isn't set
*/
void run(verbose)
register int verbose;
{
register int loop,loop2,convergence;
double **old_wts;
void quitit(),snapshot();
/*Make sure all variables needed are set*/
if(state.inodes == UNKNOWN) {
puts("the number of input nodes has not been set");
return;
}
if(state.onodes == UNKNOWN) {
puts("the number of output nodes has not been set");
return;
}
if(input == (double *) NULL) {
puts("no input data points have been loaded");
return;
}
if(state.training && (desired == (double *) NULL)) {
puts("no desired output data points have been loaded");
return;
}
if(node_attr == (NODE_ATTR *) NULL) {
puts("node thresholds and functions haven't been set");
return;
}
/*If the weights haven't been set, initialize to random values*/
if(weights == (double **) NULL) {
puts("warning: weights not set, initializing to random values");
randomize();
}
if(state.training) {
old_wts = (double **) NULL;
alloc_wts(&old_wts,state.inodes,state.onodes);
}
if((actual = (double *) calloc(state.onodes,sizeof(double))) == NULL)
error();
/*Set up signals*/
signal(SIGINT,quitit);
if(!verbose) signal(SIGTSTP,snapshot);
/*Begin simulation*/
convergence = quit = 0;
numepoch = 1;
while(!convergence) {
do_epoch();
/*If training, adjust weights until convergence*/
if(state.training) {
convergence = 1;
for(loop = 0;loop < state.onodes;++loop)
for(loop2 = 0;loop2 < state.inodes;++loop2) {
old_wts[loop2][loop] = weights[loop2][loop];
weights[loop2][loop] += (state.alpha *
(desired[loop] - actual[loop]) *
input[loop2]);
if((fabs(weights[loop2][loop] - old_wts[loop2][loop]) >
0.000025) && !quit)
convergence = 0;
}
/*Print information if user requested verbosity*/
if(verbose) snapshot();
} else convergence = 1;
++numepoch;
}
alloc_data(state.onodes,&output);
bcopy((char *) actual,(char *) output,state.onodes*sizeof(double));
free((char *) actual);
if(state.training) {
for(loop = 0;loop < state.inodes;++loop)
free((char *) old_wts[loop]);
free((char *) old_wts);
}
/*Restore signals*/
signal(SIGINT,SIG_DFL);
signal(SIGTSTP,SIG_DFL);
}
/*This routine does the calculations that make up an epoch.
Inputs: none
Outputs: none
Locals: loop - loop through output nodes
loop2 - loop though inputs
sum - sum of an output node
Globals: actual - actual output values
input - input values
node_attr - node attributes (function, threshold)
quit - flag indicating to quit simulation
state - system variables
weights - perceptron weights
NULL - 0
*/
do_epoch()
{
register int loop,loop2;
register double sum;
for(loop = 0;loop < state.onodes;++loop) {
for(loop2 = 0,sum = 0.0;loop2 < state.inodes;++loop2)
sum += (weights[loop2][loop] * input[loop2]);
if(node_attr[loop].func == NULL) {
printf("the function for output node #%d hasn't been set ... quitting run\n",loop);
quit = 1;
return;
}
actual[loop] = node_attr[loop].func(sum - node_attr[loop].threshold);
}
}
/*This routine will set the weights to random numbers between 0.0 and 1.0.
Inputs: none
Outputs: none
Locals: from - from which input node
to - to which output node
Globals: state - system variables
weights - perceptron weights
*/
randomize()
{
register int from,to;
double drand48();
alloc_wts(&weights,state.inodes,state.onodes);
for(from = 0;from < state.inodes;++from)
for(to = 0;to < state.onodes;++to)
weights[from][to] = drand48();
}
/*This routine is called if ^C is pressed. It sets up the flag to exit
the simulator.
Inputs: none
Outputs: none
Locals: none
Globals: quit - flag indicating to quit simulation
*/
void quitit()
{
quit = 1;
}
void snapshot()
{
register int loop,loop2;
printf("Epoch #%d:\n",numepoch);
for(loop = 0;loop < state.onodes;++loop)
printf(" Actual Output Node #%d = %lf\n",loop+1,actual[loop]);
puts("");
for(loop = 0;loop < state.inodes;++loop)
for(loop2 = 0;loop2 < state.onodes;++loop2)
printf(" [New] From #%d, To #%d, Weight = %lf\n",loop+1,loop2+1,weights[loop][loop2]);
puts("");
}