www.pudn.com > BPËã·¨Ô´Âë.zip > bp.c
/* ************************************************** */
/* file bp.c: contains the main program and network */
/* creation routines. */
/* */
/* Copyright (c) 1990-96 by Donald R. Tveter */
/* */
/* ************************************************** */
#ifdef INTEGER
#include "ibp.h"
#else
#include "rbp.h"
#endif
/* built-in C functions */
extern int rand();
extern void srand();
#ifdef INTEGER
extern int scale();
extern REAL unscale();
#endif
extern WTTYPE rdr();
extern int pg(), printoutunits(), readch(), readint(), eval();
extern int readpats(), evalone(), printstats(), popfile(), pushfile();
extern REAL readreal();
extern char *readstr();
extern int loadpat(), run();
extern void menus(), texterror(), help(), restoreweights();
extern void saveweights(), parameters(), printweights();
char sysstr[129]; /* string passed to OS with ! command */
int bufferend; /* index of last character in input line */
int bufferptr; /* position of next character in buffer */
char buffer[BUFFSIZE];/* holds contents of one input line */
char trfiles[RXSTRSIZE];/* data file name(s) */
int ch; /* general purpose character variable */
FILE *copy; /* file pointer to copy file */
char copyflag; /* + for copying, - for no copy */
int copyfilecount; /* to number the copy files */
jmp_buf cmdloopstate; /* to save state in case of a SIGINT */
FILE *data; /* file for original data */
char *datafile; /* copy of the data file name saved here */
WTTYPE dbdeta; /* the initial eta value for the DBD method */
WTTYPE kappa; /* the DBD learning parameter */
WTTYPE decay; /* the decay parameter for the DBD method */
WTTYPE etamax; /* the maximum eta for the DBD method */
WTTYPE theta1; /* the DBD parameter */
WTTYPE theta2; /* 1 - theta1 */
WTTYPE noise; /* noise parameter for dbd */
char deriv; /* flags type of derivative to use */
char echo; /* controls echoing of characters during input */
char emptystring; /* for unused string values */
WTTYPE eta; /* basic learning rate */
WTTYPE eta2; /* learning rate for lower layers */
WTTYPE alpha; /* momentum term */
char recurinit; /* intialize input and output at start of training */
int extraconnect; /* flags the use of connections between */
/* non-adjacent layers */
char *inputfile; /* name of file to take extra commands from */
FILE *filestack[MAXFILES]; /* allows for nested reads from files */
int filetimes[MAXFILES]; /* number of times to read file */
int filestackptr; /* has the index of the current file */
int format[MAXFORMAT];/* each value in format indicates where to put */
/* a blank for compressed output mode or a */
/* carriage return for real output */
int timestoread; /* number of times to read an input file */
char incrementseed; /* + advances seed, - resets to first value */
char informat; /* controls format to read numbers */
WTTYPE initrange; /* initial range of random weights */
WTTYPE kicksize; /* the minimum size weights that are affected */
WTTYPE kickrange; /* the range weights are initialized to */
char wtinitroutine; /* flags weight initialization algorithm */
long iotime; /* time used up printing */
short nlayers; /* number of layers in network */
int ioconnects; /* flags existence of input/output connections */
int originallypcc; /* saves kind of net to start with */
LAYER *last; /* has address of the output layer */
LAYER *start; /* has address of the input layer */
int stmsize; /* number of h layer units in a recurrent net */
int lastadd; /* iteration where last node was added */
REAL lastadderr; /* error at the last hidden unit addition */
int lastprint; /* last iteration pattern responses printed */
int lastsave; /* last time weights were saved */
int lineno; /* counts lines for paging */
int maxhidden; /* maximum number of hidden units allowed */
int maxiter; /* maximum iterations when not benchmarking */
char netbuild; /* the type of net to build */
char offby1; /* + means out of date stats for training set */
char outformat; /* controls format to print output */
char outstr[OUTSTRSIZE]; /* the output string */
int pagesize; /* size of page for pg */
char runningflag; /* +/- to print the "running . . ." message */
REAL pasterror; /* error from window iterations ago */
int pccnet; /* flags pseudo-cascade-correlation net */
char probtype; /* flags general or classification pattern format */
char debugoutput; /* turns on any debugging code I need */
int prevnpats; /* previous number of patterns, initially 0 */
int printrate; /* printrate when not benchmarking */
WTTYPE unknown; /* value for x in compressed input */
REAL qpdecayh; /* the quickprop weight decay hidden layer */
REAL qpdecayo; /* the quickprop weight decay output layer */
WTTYPE qpeta; /* the quickprop eta */
WTTYPE qpnoise; /* quickprop noise (integer version only) */
WTTYPE mu; /* the quickprop acceleration factor */
char qpslope; /* flags using slope in quickprop all the time */
int readerror; /* flags an error in reading a value */
int readingpattern; /* flags reading pattern state */
WTTYPE classoff; /* target value for class off value */
WTTYPE classon; /* target value for class on value */
char ringbell; /* flag to ring bell when finished */
int right; /* number of training patterns learned */
DATA s[2][2]; /* contains stats on pattern learning */
DATA rs[2][2]; /* stats on recurrent pattern learning */
int saverate; /* rate at which to save weights */
char saveonminimum; /* flags saving weights on minimum of test set */
REAL minimumsofar; /* lowest test set error so far */
unsigned seed; /* seed for generating random weights */
SEEDNODE *seedstart; /* the list of user defined seeds */
#ifdef LOOKUP
WTTYPE sigmoid[7808]; /* table to look up the sigmoid's value */
#endif
WTTYPE stdthresh; /* the bias WEIGHT value */
WTTYPE hbiasact; /* hidden layer bias activation VALUE */
WTTYPE obiasact; /* output layer bias activation VALUE */
char biasset; /* flags the setting of the bias WEIGHT */
char summary; /* flags summary output mode */
int testpat; /* pattern to skip when benchmarking; else 0 */
char *testfile; /* file to take test patterns from */
WTTYPE toler; /* tolerance based on targets */
REAL toloverall; /* tolerance based on average error */
WTTYPE toosmall; /* weights smaller than toosmall were removed */
#ifdef INTEGER
INT32 totaldiff; /* totals errors to find average error per unit */
#else
REAL totaldiff;
#endif
int totaliter; /* counts total iterations for the program */
char *trainfile; /* file to take training patterns from */
REAL trigger; /* trigger slope for dynamic node creation */
char update; /* flags type of update rule to use */
char up_to_date_stats;/* + does an extra forward pass after update */
int window; /* window over which trigger slope is computer */
int wrong; /* number of training patterns unlearned */
char wtfilename[FILENAMESIZE]="weights"; /* whole name for weight file */
char *wtfile; /* base file name for weights file */
int wtfilecount; /* counts weight files as they are written */
char wtformat; /* controls format to save and restore weights */
#ifdef INTEGER
char wtlimithit; /* flags whether the limit has been hit */
#endif
int wttotal; /* number of weights in the network */
int wtsinuse; /* number of weights in use */
char zeroderiv; /* flags zero deriviative when using A ap */
char ah; /* hidden layer activation function */
char ao; /* output layer activation function */
WTTYPE Dh; /* hidden layer D */
WTTYPE Do; /* output layer D */
REAL poft; /* temporal difference previous value */
/* given a layer no. and unit no. locateunit returns the address */
UNIT *locateunit(layerno,unitno)
int layerno, unitno;
{int i;
UNIT *u;
LAYER *layer;
if (layerno < 0 || layerno > nlayers)
{
pg(stdout,"bad layer number\n");
return(NULL);
};
layer = start;
for(i=1;i<=(layerno-1);i++) layer = layer->next;
u = (UNIT *) layer->units;
while (u != NULL && u->unitnumber != unitno) u = u->next;
if (u == NULL)
{
sprintf(outstr,"there is no unit %3d in layer %3d\n",unitno,layerno);
pg(stdout,outstr);
};
return(u);
}
#ifdef SYMMETRIC
INT32 wtaddress(i,j,biasunit,type,size) /* Returns the address of a */
int i,j; /* weight (1), olddw (2), */
int biasunit; /* eta (3), total (4), */
int type; /* or slope (5) */
int size; /* One is created if it */
/* doesn't already exist. */
{ int k;
INT32 addr;
UNIT *u;
WTNODE *w;
if (biasunit) addr = (INT32) malloc(size);
else if (j >= i) addr = (INT32) malloc(size);
else /* the item already exists, so find its address */
{
u = locateunit(2,j);
w = (WTNODE *) u->wtlist;
k = 1;
while (k < i)
{
w = w->next;
k = k + 1;
};
if (type == 1) addr = (INT32) w->weight;
else if (type == 2) addr = (INT32) w->olddw;
else if (type == 3) addr = (INT32) w->eta;
else if (type == 4) addr = (INT32) w->total;
else if (type == 5) addr = (INT32) w->slope;
else pg(stdout,"bad type in wtaddress\n");
};
return(addr);
}
void setweight(w,i,j,biasunit) /* set initial values in w */
WTNODE *w;
short i, j;
int biasunit;
{WTTYPE *s;
s = (WTTYPE *) wtaddress(i,j,biasunit,1,WTSIZE);
*s = 0;
w->weight = s;
s = (WTTYPE *) wtaddress(i,j,biasunit,2,WTSIZE);
*s = 0;
w->olddw = s;
s = (WTTYPE *) wtaddress(i,j,biasunit,3,WTSIZE);
*s = eta;
w->eta = s;
s = (WTTYPE *) wtaddress(i,j,biasunit,5,WTSIZE);
*s = 0;
w->slope = s;
w->inuse = 1;
#ifdef INTEGER
w->total = (INT32 *) wtaddress(i,j,biasunit,4,sizeof(INT32));
#else
w->total = (REAL *) wtaddress(i,j,biasunit,4,sizeof(REAL));
#endif
}
#else
void setweight(w,i,j,biasunit) /* set initial values in w */
WTNODE *w;
short i,j;
int biasunit;
{
w->weight = 0;
w->olddw = 0;
w->slope = 0;
w->eta = dbdeta;
if (biasunit) w->inuse = 2; else w->inuse = 1;
}
#endif
LAYER *mklayer(prevlayer,n) /* creates a layer of n units, pointers */
LAYER *prevlayer; /* and weights back to the units in the */
int n; /* previous layer and links this new */
/* layer into the list of layers */
{UNIT *front, *p, *q, *bias, *prev, *ptr;
WTNODE *wfront, *wprev, *w;
LAYER *lptr;
int i, j, count;
/* make a list of nodes in this layer */
count = 1;
front = (UNIT *) malloc(sizeof(UNIT));
front->unitnumber = count;
front->layernumber = nlayers;
front->oj = 0;
front->tj = 0;
front->translate = 0;
front->userscale = scale(1.0);
front->wtlist = NULL;
prev = front;
for(i=1;inext = ptr;
ptr->unitnumber = count;
ptr->layernumber = nlayers;
ptr->wtlist = NULL;
ptr->translate = 0;
ptr->userscale = scale(1.0);
front->oj = 0;
front->tj = 0;
prev = ptr;
};
prev->next = NULL;
/* make a LAYER node to point to this list of units */
lptr = (LAYER *) malloc(sizeof(LAYER));
lptr->unitcount = n;
lptr->initialcount = n;
lptr->D = scale(1.0);
lptr->biasact = scale(1.0);
lptr->patstart[TRAIN] = NULL;
lptr->currentpat[TRAIN] = NULL;
lptr->patstart[TEST] = NULL;
lptr->currentpat[TEST] = NULL;
lptr->backlayer = prevlayer;
lptr->next = NULL;
lptr->units = front; /* connect the list of units */
/* return if this is the input layer */
if (prevlayer == NULL) return(lptr);
prevlayer->next = lptr;
/* If we are working on a deeper layer, for every node in this layer, */
/* create a linked list back to units in the previous layer. */
i = 1;
q = front;
while (q != NULL) /* do a unit */
{
j = 1; /* handle first connection */
p = (UNIT *) prevlayer->units;
wfront = (WTNODE *) malloc(sizeof(WTNODE));
wttotal = wttotal + 1;
q->wtlist = wfront;
wprev = wfront;
wfront->backunit = p;
setweight(wfront,i,j,0);
p = p->next;
while (p != NULL) /* handle rest of connections */
{
j = j + 1;
w = (WTNODE *) malloc(sizeof(WTNODE));
wttotal = wttotal + 1;
wprev->next = w;
w->backunit = p;
setweight(w,i,j,0);
wprev = w;
p = p->next;
};
j = j + 1;
bias = (UNIT *) malloc(sizeof(UNIT)); /* create a bias unit */
bias->oj = scale(1.0);
bias->inuse = 1;
bias->layernumber = nlayers;
bias->unitnumber = 32767; /* bias unit is unit 32767 */
w = (WTNODE *) malloc(sizeof(WTNODE)); /* connect to end of list */
wttotal = wttotal + 1;
wprev->next = w;
w->backunit = bias;
setweight(w,n+2,i,1);
w->next = NULL;
q = q->next;
i = i + 1;
};
return(lptr);
}
#ifndef SYMMETRIC
void connect(a,b,range) /* add a connection from unit a to unit b */
UNIT *a, *b; /* connections go in increasing order */
WTTYPE range;
{WTNODE *wnew, *w, *wprev;
UNIT *wunit;
int farenough;
wnew = (WTNODE *) malloc(sizeof(WTNODE));
wttotal = wttotal + 1;
wnew->eta = dbdeta;
wnew->weight = range * (rand() & 32767) / 32768;
if ((rand() & 32767) > 16383) wnew->weight = -wnew->weight;
wnew->olddw = 0;
wnew->slope = 0;
wnew->inuse = 1;
wnew->backunit = a;
w = (WTNODE *) b->wtlist;
wprev = NULL;
wunit = (UNIT *) w->backunit;
farenough = 0; /* insert the weight in order */
while (w != NULL && !farenough)
if (wunit->layernumber > a->layernumber) farenough = 1;
else if (wunit->layernumber == a->layernumber)
while (w != NULL && !farenough)
{
if (wunit->unitnumber < a->unitnumber &&
wunit->layernumber == a->layernumber)
{
wprev = w;
w = w->next;
wunit = (UNIT *) w->backunit;
}
else farenough = 1;
}
else
{
wprev = w;
w = w->next;
wunit = (UNIT *) w->backunit;
};
if (wprev == NULL)
{
wnew->next = w;
b->wtlist = wnew;
}
else
{
wnew->next = w;
wprev->next = wnew;
};
}
void addunit(layerno,range)
int layerno; /* add hidden unit to end of the layer */
WTTYPE range;
{
LAYER *lptr, *prevlayer, *nextlayer;
UNIT *u, *prevu, *p, *bias;
WTNODE *wnode;
int i, unitno;
lptr = start;
for (i=1;i <= (layerno - 1); i++) lptr = lptr->next;
unitno = lptr->unitcount;
lptr->unitcount = unitno + 1;
prevu = locateunit(layerno,unitno);
if (prevu == NULL) return;
u = (UNIT *) malloc(sizeof(UNIT));
prevu->next = u;
u->next = NULL;
u->unitnumber = unitno + 1;
u->layernumber = layerno;
u->inuse = 1;
u->wtlist = NULL;
if (layerno > 1)
{
bias = (UNIT *) malloc(sizeof(UNIT));
bias->inuse = 1;
bias->oj = scale(1.0);
bias->layernumber = layerno;
bias->unitnumber = 32767; /* bias unit is unit 32767 */
wnode = (WTNODE *) malloc(sizeof(WTNODE));
wttotal = wttotal + 1;
wnode->weight = range * (rand() & 32767) / 32768;
if ((rand() & 32767) > 16383) wnode->weight = -wnode->weight;
wnode->olddw = 0;
wnode->slope = 0;
wnode->eta = dbdeta;
wnode->inuse = 2;
wnode->next = NULL;
wnode->backunit = bias;
u->wtlist = wnode;
prevlayer = lptr->backlayer;
p = (UNIT *) prevlayer->units;
while (p != NULL)
{
connect(p,u,range);
p = p->next;
};
};
nextlayer = lptr->next;
p = (UNIT *) nextlayer->units;
while (p != NULL)
{
connect(u,p,range);
p = p->next;
};
lastadd = totaliter;
lastadderr = s[TOL][TRAIN].avgerr;
}
#endif
void init()
{int i,j;
SEEDNODE *snode;
poft = scale(0.0); /* part of a temporal difference test */
alpha = scale(0.9); /* gradient descent parameters */
eta = scale(0.5);
eta2 = eta;
decay = scale(0.5); /* DBD parameters */
dbdeta = scale(0.5);
etamax = scale(30.0);
kappa = scale(0.5);
theta1 = scale(0.5);
theta2 = scale(1.0) - theta1;
mu = scale(1.75); /* quickprop parameters */
qpdecayh = 0;
qpdecayo = 0;
qpeta = scale(0.5);
qpnoise = 0;
qpslope = '+';
classoff = 0;
classon = scale(1.0);
debugoutput = '-';
inputfile = "(none)";
bufferend = 0;
bufferptr = BUFFSIZE + 1;
ch = ' ';
copyflag = '-';
copyfilecount = 0;
deriv = 'd';
echo = '-';
extraconnect = 0;
format[0] = 0;
for(i=1;i<=MAXFORMAT-1;i++) format[i] = format[i-1] + 10;
incrementseed = '-';
informat = 'r';
initrange = scale(1.0);
kickrange = 0;
kicksize = 0;
wtinitroutine = '0';
lastadd = 0;
lastprint = 0;
lastsave = 0;
probtype = 'g';
noise = 0;
offby1 = '-';
outformat = 'r';
pagesize = 24;
pccnet = 0;
ioconnects = 0;
stmsize = 0;
recurinit = '-';
prevnpats = 0;
printrate = 10;
ringbell = '-';
saverate = MAXINT;
minimumsofar = MAXINT;
saveonminimum = '-';
seedstart = (SEEDNODE *) malloc(sizeof(SEEDNODE));
snode = (SEEDNODE *) malloc(sizeof(SEEDNODE));
seedstart->next = snode;
snode->val = 0;
srand(0);
snode->next = NULL;
#ifdef LOOKUP
{
int i; double x,y;
for (i=0;i<=7807;i++)
{
x = (double) i / 1024.0;
y = 1.0 / (1.0 + exp(-x));
sigmoid[i] = (WTTYPE) (y * 1024.0 + 0.5);
};
}
#endif
for (i=TRAIN;i<=TEST;i++) for (j=TOL;j<=MAX;j++)
{
s[j][i].uncertain = 0;
s[j][i].npats = 0;
s[j][i].iterno = 0;
s[j][i].right = 0;
s[j][i].wrong = 0;
s[j][i].avgerr = 0.0;
s[j][i].pctright = 0.0;
};
stdthresh = 0;
biasset = 0;
sysstr[0] = '\0';
summary = '+';
timestoread = 1;
toler = scale(0.1);
toloverall = 0.0;
toosmall = 0; /* size of weights too small to use */
trigger = 0.1;
unknown = scale(0.5);
update = 'p';
up_to_date_stats = '-';
wtfilecount = 0;
wtfile = "weights";
trfiles[0] = '\0';
runningflag = '+';
wtformat = 'r';
#ifdef INTEGER
wtlimithit = 0;
#endif
wttotal = 0;
zeroderiv = 0;
maxiter = 100;
ah = 's';
ao = 's';
hbiasact = scale(1.0);
obiasact = scale(1.0);
Dh = scale(1.0);
Do = scale(1.0);
}
int nonetwork()
{
if (start != NULL) return(0);
pg(stdout,"there is no network\n");
return(1);
}
int nopatterns()
{
if (s[TOL][TRAIN].npats != 0) return(0);
pg(stdout,"there are no patterns\n");
return(1);
}
void setbiasact(layer) /* sets the bias unit ACTIVATION VALUE */
LAYER *layer;
{
UNIT *u;
WTNODE *w;
u = layer->units;
while (u != NULL)
{
w = u->wtlist;
while (w != NULL)
{
if (w->backunit->unitnumber == 32767)
w->backunit->oj = layer->biasact;
w = w->next;
};
u = u->next;
};
}
int patternencode(list) /* finds addresses of pattern values found */
int list; /* within the net */
{
PATNODE *pn;
PATLIST *pl;
int i, n, finished;
UNIT *u;
resetpats(list);
pl = start->currentpat[list];
nextpat(list);
while (pl != NULL)
{
pn = pl->pats;
n = start->unitcount;
i = 1;
finished = 0;
while (i <= n && !finished)
{
if (pn->addr != NULL && pn->addr != (WTTYPE *) -1)
{
u = locateunit((int) pn->layer, (int) pn->unitno);
pn->addr = &(u->oj);
};
i = i + 1;
pn++;
if (pn->unitno == CAPXCODE || pn->unitno == CAPHCODE) finished = 1;
};
nextpat(list);
};
}
/* for a SIGINT, restart in cmdloop */
#ifdef UNIX
void restartcmdloop()
#else
void restartcmdloop(int dummy)
#endif
{
while (data != stdin) popfile();
signal(SIGINT,restartcmdloop);
longjmp(cmdloopstate,1);
}
void cmdloop() /* read commands and process them */
{
int finished, layerno, unitno, layer1, layer2, node1, node2;
int i, itemp, itemp2;
WTTYPE temp, temp2, *target;
PATLIST *pl;
REAL rtemp;
LAYER *p;
UNIT *u, *n1, *n2;
WTNODE *w;
SEEDNODE *snode, *sprev;
setjmp(cmdloopstate); /* restart here from SIGINT */
finished = 0;
do{
if (data == stdin) pg(stdout,"[ACDFGMNPQTW?!acdefhlmopqrstw]? ");
if (data == stdin) lineno = 0;
while(ch == ' ' || ch == '\n') ch = readch();
switch (ch) {
case EOF:
popfile();
if (data == stdin) pg(stdout,"taking commands from stdin now\n");
break;
case '?': menus('?'); break;
case '!':
i = 0;
do ch = readch(); while (ch == ' ');
if (ch == '\n')
{
system(sysstr);
break;
}
else if (ch == '"') break; /* loading string but not executing */
while ((ch != '\n' && ch != '"') && i <= 80)
{
sysstr[i] = ch;
ch = readch();
i = i + 1;
};
if (ch == '"') sysstr[i-1] = '\0';
else
{
sysstr[i] = '\0';
system(sysstr);
};
bufferptr = bufferptr - 1;
break;
case '*': break; /* * on a line is a comment */
case 'a':
do ch = readch(); while (ch == ' ');
if (ch == '0' || ch == '.')
{
bufferptr = bufferptr - 1;
temp = rdr(GE,0.0,'a');
if (!readerror) alpha = temp;
goto enda;
}
else bufferptr = bufferptr - 1;
if (nonetwork()) goto enda;
while (ch != '\n' && ch != '*')
{
ch = readch();
if (ch == 'a')
{
do ch = readch(); while (ch == ' ');
if (ch == 'l' || ch == 's')
{
p = start;
while (p != NULL) {p->activation = ch; p = p->next;};
ah = ch;
ao = ch;
}
else if (ch == 'h')
{
do ch = readch(); while (ch == ' ');
if (ch == 'l' || ch == 's')
{
p = start;
while (p != last) {p->activation = ch; p = p->next;};
ah = ch;
}
else texterror();
}
else if (ch == 'o')
{
do ch = readch(); while (ch == ' ');
if (ch == 'l' || ch == 's')
{
last->activation = ch;
ao = ch;
}
else texterror();
}
else texterror();
}
else if (ch == 'D')
{
do ch = readch(); while (ch == ' ');
if (ch == 'h')
{
temp = rdr(GT,0.0,'a');
if (readerror) goto enda;
p = start;
while (p != last) {p->D = temp; p = p->next;};
Dh = temp;
}
else if (ch == 'o')
{
temp = rdr(GT,0.0,'a');
if (readerror) goto enda;
last->D = temp;
Do = temp;
}
else if (ch >= '0' && ch <= '9')
{
bufferptr = bufferptr - 1;
temp = rdr(GT,0.0,'a');
if (readerror) goto enda;
p = start;
while (p != NULL) {p->D = temp; p = p->next;};
Do = temp;
Dh = temp;
}
else texterror();
}
else if (ch == 'd')
{
do ch = readch(); while (ch == ' ');
if (ch == 'd' || ch == 'f' || ch == 'c' || ch == 'o') deriv = ch;
else texterror();
if (deriv == 'o') deriv = 'c';
}
else if (ch == 'i')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') recurinit = ch;
else texterror();
}
else if (ch == 'u')
{
do ch = readch(); while (ch == ' ');
if (ch == 'j') ch = 'd';
#ifdef SYMMETRIC
if (ch == 'C' || ch == 'c' || ch == 'p') update = ch;
#else
if (ch == 'C' || ch == 'c' || ch == 'p' || ch == 'd' || ch == 'q')
update = ch;
#endif
else texterror();
}
else if (ch == '*' || ch == '\n' || ch == ' ');
else texterror();
}
bufferptr = bufferptr - 1;
enda: break;
case 'c': {int initialize;
if (nonetwork()) goto endc;
initialize = 0;
do ch = readch(); while (ch == ' ');
if (ch == '\n' || ch == '*') goto clearnet;
else if (ch == 'i')
{
initialize = 1;
do ch = readch(); while (ch == ' ');
if (ch == '\n' || ch == '*') goto clearnet;
else
{
bufferptr = bufferptr - 1;
temp2 = rdr(GE,scale(0.0),'c');
if (readerror) goto endc;
initrange = temp2;
};
};
clearnet:
clear();
srand(seed);
if (initialize == 1)
{
kick((WTTYPE) 0,initrange);
sprintf(outstr,"seed = %d, range = -%5.2f to +%5.2f\n",seed,
unscale(initrange), unscale(initrange));
pg(stdout,outstr);
}
else {sprintf(outstr,"seed = %d\n",seed); pg(stdout,outstr);};
endc: break;};
#ifndef SYMMETRIC
case 'd':
while (ch != '\n' && ch != '*')
{
ch = readch();
if (ch == 'd')
{
temp = rdr(GT,0.0,'d');
if (!readerror) decay = temp;
}
else if (ch == 'e')
{
temp = rdr(GT,0.0,'d');
if (!readerror && !nonetwork())
{
dbdeta = temp;
initialize_etas(dbdeta);
};
}
else if (ch == 'k')
{
temp = rdr(GT,0.0,'d');
if (!readerror) kappa = temp;
}
else if (ch == 'm')
{
temp = rdr(GT,0.0,'d');
if (!readerror) etamax = temp;
}
else if (ch == 't')
{
temp = rdr(GE,0.0,'d');
if (!readerror)
{
theta1 = temp;
theta2 = scale(1.0) - theta1;
};
}
else if (ch == '*' || ch == '\n' || ch == ' ');
else texterror();
}
bufferptr = bufferptr - 1;
break;
#endif
case 'e':
temp = rdr(GT,0.0,'e');
if (!readerror) eta = temp;
do ch = readch(); while (ch == ' ');
bufferptr = bufferptr - 1;
if (ch != '\n' && ch != '*')
{
temp = rdr(GT,0.0,'r');
if (!readerror) eta2 = temp;
}
else eta2 = eta;
break;
case 'f':
while (ch != '\n' && ch != '*')
{
ch = readch();
if (ch == 'B')
{
itemp = 0;
do ch = readch(); while (ch == ' ');
while (ch >= '1' && ch <= '9')
{
bufferptr = bufferptr - 1;
itemp2 = readint(format[itemp],MAXINT,'f');
if (readerror) goto endf;
itemp = itemp + 1;
if (itemp < MAXFORMAT) format[itemp] = itemp2;
else pg(stdout,"format too long\n");
do ch = readch(); while (ch == ' ');
};
if (itemp < MAXFORMAT-1)
for (i=itemp+1;i<=MAXFORMAT-1; i++) format[i] = format[i-1] + 10;
}
else if (ch == 'b')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') ringbell = ch; else texterror();
}
else if (ch == 'c')
{
do ch = readch(); while (ch == ' ');
if (ch == '+')
{
if (copy != NULL) fflush(copy);
else copy = fopen("copy","w");
if (copy == NULL)
{sprintf(outstr,"cannot open file: %s\n",outstr); pg(stdout,outstr); };
copyflag = '+';
}
else if (ch == '-')
{
copyflag = '-';
if (copy != NULL)
{
fflush(copy);
fclose(copy);
}
}
else texterror();
}
else if (ch == 'd')
{/* with fd+ I can turn on a piece of debugging code (if it exists) */
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') debugoutput = ch;
else
{
texterror();
goto endf;
}
}
else if (ch == 'e')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') echo = ch;
}
else if (ch == 'i')
{
do ch = readch(); while (ch == ' ');
if (ch == 'c' || ch == 'r') informat = ch; else texterror();
}
else if (ch == 'O')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') offby1 = ch;
else texterror();
}
else if (ch == 'o')
{
do ch = readch(); while (ch == ' ');
if (ch == 'a' || ch == 'c' || ch == 'r' || ch == 'e' || ch == 's')
outformat = ch;
else texterror();
}
else if (ch == 'P')
{
itemp = readint(0,MAXINT,'f');
if (!readerror) pagesize = itemp;
}
else if (ch == 'p')
{
do ch = readch(); while (ch == ' ');
if (ch == 'c' || ch == 'g') probtype = ch;
else texterror();
}
else if (ch == 'R')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') runningflag = ch;
else texterror();
}
else if (ch == 's')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') summary = ch;
else texterror();
}
else if (ch == 'u')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') up_to_date_stats = ch; else texterror();
}
else if (ch == 'x')
{
temp = rdr(GT,(REAL) SKIPCODE,'f');
if (!readerror) unknown = temp;
}
else if (ch == ' ' || ch == '*' || ch == '\n');
else texterror();
}
bufferptr = bufferptr - 1;
endf:
break;
case 'h': help(); break;
case 'l':
if (nonetwork()) break;
layerno = readint(1,nlayers,'l');
if (readerror) break;
p = start;
for (i=2;i<=layerno;i++) p = p->next;
printoutunits(0,p,-1,0.0,(char) 0,(char) 0);
break;
/* make a network */
case 'm': {LAYER *layer; int itemp, itemp2;
nlayers = 0;
wttotal = 0;
pccnet = 0;
ioconnects = 0;
ch = readch();
p = NULL;
while (ch != 'x' && ch != '\n' && ch != '*')
{
itemp = readint(1,MAXINT,'m');
if (readerror)
{
wttotal = 0;
start = NULL;
goto endm;
};
/* check for + number for a recurrent net */
if (nlayers == 0)
{
do ch = readch(); while (ch == ' ');
if (ch != '+')
{
bufferptr = bufferptr - 1;
stmsize = 0;
}
else
{
itemp2 = readint(1,MAXINT,'m');
if (readerror)
{
wttotal = 0;
start = NULL;
goto endm;
};
stmsize = itemp2;
itemp = itemp + itemp2;
};
};
nlayers = nlayers + 1;
p = mklayer(p,itemp);
if (nlayers == 1) start = p;
ch = readch();
while (ch == ' ') ch = readch();
if (ch >= '0' && ch <= '9') bufferptr = bufferptr - 1;
};
last = p;
#ifndef SYMMETRIC
if (ch == 'x')
{
n1 = start->units;
while (n1 != NULL)
{
n2 = last->units;
while (n2 != NULL)
{
connect(n1,n2,(WTTYPE) 0);
n2 = n2->next;
};
n1 = n1->next;
}
ioconnects = 1;
};
#endif
wtsinuse = wttotal;
bufferptr = bufferptr - 1;
nullpatterns(TRAIN);
nullpatterns(TEST);
/* should really free up the old network structure as well */
last->activation = ao;
last->D = Do;
layer = last->backlayer;
while (layer != start)
{
layer->D = Dh;
layer->activation = ah;
layer = layer->backlayer;
};
clear();
endm: break;};
case 'o':
do ch = readch(); while (ch == ' ');
{
PATNODE *targetpn;
bufferptr = bufferptr - 1; /* unget the character */
if (nonetwork() || nopatterns()) break;
itemp = readint(1,s[TOL][TRAIN].npats,'o');
if (readerror) break;
resetpats(TRAIN);
for (i=1;i<=itemp;i++) nextpat(TRAIN);
/* setoutputpat(); */
u = (UNIT *) last->units;
pl = last->currentpat[TRAIN];
targetpn = pl->pats;
itemp2 = 0; /* unit counter */
i = 1; /* format counter */
while (u != NULL)
{
sprintf(outstr,"%5.2f",unscale(targetpn->val)); pg(stdout,outstr);
targetpn++;
itemp2 = itemp2 + 1;
if (format[i] == itemp2)
{
if (outformat == 'r') pg(stdout,"\n"); else pg(stdout," ");
if (i < MAXFORMAT - 1) i = i + 1;
};
u = u->next;
}
pg(stdout,"\n");
};
endo:
break;
case 'p':
do ch = readch(); while (ch == ' ');
bufferptr = bufferptr - 1;
if (ch == 'a' || ch == '\n' || ch == '*')
{int stopprinting;
if (nonetwork() || nopatterns()) break;
stopprinting = eval(TRAIN,1);
if (!stopprinting) printstats(stdout,TRAIN,0,s);
}
else
{
itemp = readint(0,s[TOL][TRAIN].npats,'p');
if (readerror) break;
if (nonetwork() || nopatterns()) break;
if (itemp == 0) {eval(TRAIN,0); printstats(stdout,TRAIN,0,s);}
else evalone(itemp,TRAIN,1,0);
};
break;
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'x':
case '-':
case '\\': {int status;
if (nonetwork()) break;
if (ch != '\\') bufferptr = bufferptr - 1;
status = loadpat();
if (status == 1) printoutunits(0,last,-1,0.0,(char) 0,(char) 0);
break;}
case 'q':
ch = readch();
if (ch == '\n') return;
#ifndef SYMMETRIC
else if (ch != 'p') texterror();
else
{
while (ch != '\n' && ch != '*')
{
ch = readch();
if (ch == 'd')
{REAL rtemp;
do ch = readch(); while (ch == ' ');
if (ch == 'h')
{
rtemp = readreal(GE,0.0,'q');
if (readerror) goto endq;
qpdecayh = rtemp;
}
else if (ch == 'o')
{
rtemp = readreal(GE,0.0,'q');
if (readerror) goto endq;
qpdecayo = rtemp;
}
else if (ch >= '0' && ch <= '9')
{
bufferptr = bufferptr - 1;
rtemp = readreal(GE,0.0,'q');
if (readerror) goto endq;
qpdecayh = rtemp;
qpdecayo = rtemp;
}
}
else if (ch == 'e')
{
temp = rdr(GT,0.0,'d');
if (!readerror && !nonetwork()) qpeta = temp;
}
else if (ch == 'm')
{
temp = rdr(GT,0.0,'d');
if (!readerror) mu = temp;
}
else if (ch == 'n')
{
temp = rdr(GE,0.0,'d');
if (!readerror) qpnoise = temp;
}
else if (ch == 's')
{
do (ch = readch()); while (ch == ' ');
if (ch == '+' || ch == '-') qpslope = ch;
else texterror();
}
else if (ch == '*' || ch == '\n' || ch == ' ');
else texterror();
}
};
endq:
bufferptr = bufferptr - 1;
break;
#endif
case 'r': /* r for run, rw for restore weights */
do ch = readch(); while (ch == ' ');
if (ch == '\n' || ch == '*')
{
if (nonetwork() || nopatterns()) goto endr;
run(maxiter,printrate);
}
else if (ch == 'w')
{
do ch = readch(); while (ch == ' ');
bufferptr = bufferptr - 1;
if (ch == '*' || ch == '\n') /* nothing */ ;
else
{
wtfile = readstr();
strcpy(wtfilename,wtfile);
if (saveonminimum == '+')
{int i, ok, temp;
i = 0;
while (wtfile[i] != '\0') i = i + 1;
while (wtfile[i] != '.') i = i - 1;
wtfile[i] = '\0';
ok = sscanf(&wtfilename[i+1],"%d",&temp);
if (ok == 1) wtfilecount = temp;
else
{
wtfilecount = 0;
pg(stdout,"weight file number error; number starts a 0\n");
};
};
};
if (nonetwork()) break; else restoreweights();
}
else if (ch == 't')
{
do ch = readch(); while (ch == ' ');
if (ch == '{') {/* nothing */}
else
{
bufferptr = bufferptr - 1;
trainfile = readstr();
itemp = MAXINT;
if (!pushfile(trainfile,1)) goto endr;
strcat(trfiles,"rt ");
strcat(trfiles,trainfile);
strcat(trfiles,"\n");
};
nullpatterns(TRAIN);
readingpattern = 1;
itemp2 = readpats(TRAIN,'r');
readingpattern = 0;
s[TOL][TRAIN].npats = itemp2;
s[MAX][TRAIN].npats = itemp2;
sprintf(outstr,"%d training patterns read\n\n",itemp2); pg(stdout,outstr);
goto endr;
}
else if (ch == 'x')
{
if (nonetwork()) break;
trainfile = readstr();
if (!pushfile(trainfile,1)) goto endr;
strcat(trfiles,"rx ");
strcat(trfiles,trainfile);
strcat(trfiles,"\n");
prevnpats = s[TOL][TRAIN].npats;
findendofpats(last);
findendofpats(start);
readingpattern = 1;
itemp2 = readpats(TRAIN,'r');
sprintf(outstr,"%d patterns added\n\n",itemp2); pg(stdout,outstr);
readingpattern = 0;
itemp = prevnpats + itemp2;
s[TOL][TRAIN].npats = itemp;
s[MAX][TRAIN].npats = itemp;
goto endr;
}
else if (ch >= '1' && ch <= '9')
{
bufferptr = bufferptr - 1;
itemp = readint(1,MAXINT,'r');
if (!readerror) maxiter = itemp; else goto endr;
itemp = readint(1,MAXINT,'r');
if (!readerror) printrate = itemp; else goto endr;
do ch = readch(); while (ch == ' ');
if (ch == '"') goto endr; else bufferptr = bufferptr - 1;
if (!nonetwork() && !nopatterns()) run(maxiter,printrate);
}
else texterror();
endr:
break;
case 's': /* s for seed, sw for save weights */
do ch = readch(); while (ch == ' ');
if (ch == 'w')
{
do ch = readch(); while (ch == ' ');
bufferptr = bufferptr - 1;
if (ch == '*' || ch == '\n') /* nothing */ ; else wtfile = readstr();
if (nonetwork()) break; else saveweights();
}
else if (ch == 'e' || ch == 'a')
{char *savefile;
FILE *sf;
saveweights();
do ch = readch(); while (ch == ' ' || ch == '\n');
bufferptr = bufferptr - 1;
savefile = readstr();
sf = fopen(savefile,"w");
if (sf == NULL)
{
sprintf(outstr,"cannot open the file: %s\n",savefile);
goto ends;
};
parameters(sf);
fflush(sf);
fclose(sf);
}
else if (ch == 'i' || (ch >= '0' && ch <= '9'))
{
bufferptr = bufferptr - 1;
sprev = seedstart;
while (ch != '\n' && ch != '*')
{
do ch = readch(); while (ch == ' ');
if (ch == 'i')
{
do ch = readch(); while (ch == ' ');
if (ch == '+' || ch == '-') incrementseed = ch;
else {texterror(); goto ends;};
}
else if (ch >= '0' && ch <= '9')
{
bufferptr = bufferptr - 1;
seed = readint(0,MAXINT,'s');
if (readerror) goto ends;
snode = (SEEDNODE *) malloc(sizeof(SEEDNODE));
snode->val = seed;
snode->next = NULL;
sprev->next = snode;
sprev = snode;
}
else if (ch == '\n' || ch == '*');
else {texterror(); goto ends;};
};
snode = seedstart->next;
seed = snode->val;
}
else if (ch == 'b')
{WTTYPE temp; LAYER *layer; UNIT *u;
if (nonetwork()) break;
temp = rdr(GT,(REAL) -unscale(32767),'s');
if (readerror) break;
stdthresh = temp;
layer = start->next;
while (layer != NULL)
{
u = (UNIT *) layer->units;
while (u != NULL)
{
w = (WTNODE *) u->wtlist;
while (w->next != NULL) w = w->next;
#ifdef SYMMETRIC
*(w->weight) = stdthresh;
#else
w->weight = stdthresh;
#endif
u = u->next;
};
layer = layer->next;
};
biasset = 1;
}
else texterror();
ends:
endsw:
break;
case 't':
do ch = readch(); while (ch == ' ');
if ((ch == 'a' || ch == '\n' || ch == '*') && (!nonetwork()))
{
if (s[TOL][TEST].npats == 0) pg(stdout,"no test patterns\n");
else
{
eval(TEST,1);
printstats(stdout,TEST,0,s);
bufferptr = bufferptr - 1;
};
}
else if (ch == 'o')
{
rtemp = readreal(GE,0.0,'t');
if (readerror) break;
toloverall = rtemp;
}
else if (ch == 'f')
{
do ch = readch(); while (ch == ' ');
bufferptr = bufferptr - 1;
testfile = readstr();
nullpatterns(TEST);
if (!pushfile(testfile,1)) goto endt;
readingpattern = 1;
itemp = readpats(TEST,'t');
readingpattern = 0;
sprintf(outstr,"%d test patterns read\n",itemp); pg(stdout,outstr);
s[TOL][TEST].npats = itemp;
s[MAX][TEST].npats = itemp;
}
else if (ch == 'r')
{
do ch = readch(); while (ch == ' ');
if (ch == 'p') itemp2 = 1;
else {itemp2 = 0; bufferptr = bufferptr - 1;};
itemp = readint(1,s[TOL][TEST].npats,'t');
if (!readerror) evalr(TEST,itemp2,itemp);
}
else
{
bufferptr = bufferptr - 1;
rtemp = readreal(GE,0.0,'t');
if (readerror) break;
else if (rtemp > 0 && rtemp < 1.0) toler = scale(rtemp);
else
{
bufferptr = bufferptr - 1;
if (s[TOL][TEST].npats == 0)
{
pg(stdout,"there is no test set\n");
break;
};
if (rtemp == 0.0) {eval(TEST,0); printstats(stdout,TEST,0,s);}
else
{
itemp = rtemp;
if (itemp > s[TOL][TEST].npats)
pg(stdout,"not that many patterns in the test set\n");
else evalone(itemp,TEST,1,0);
};
};
};
endt: break;
case 'w':
{int i;
if (nonetwork()) break;
layerno = readint(2,nlayers,'w');
if (readerror) break;
unitno = readint(1,MAXINT,'w');
if (readerror) break;
u = locateunit(layerno,unitno);
if (u != NULL) printweights(u,layerno);
break;
};
case 'g': /* a maze (game) problem for temporal difference */
{int ngames, nlevels, ndoors;
ngames = readint(1,10,'x');
nlevels = readint(1,10,'x');
ndoors = readint(1,10,'x');
maze(ngames,nlevels,ndoors);
ch = ' ';
break;
};
case 'z': /* reads in non-user set (hidden) parameters */
{REAL rtemp; int itemp;
rtemp = readreal(GE,0.0,'z');
if (readerror) break;
minimumsofar = rtemp; /* minimum test set error */
};
break;
default: if (ch >= 'A' && ch <= 'Z') menus(ch); else texterror();
break;
};
if (ch != '\n') do ch = readch(); while (ch != '\n');
}while (!finished);
}
void main(argc,argv)
int argc;
char *argv[];
{
setbuf(stdout,NULL); /* set unbuffered output */
#if defined(UNIX) && defined(HOTKEYS)
initraw();
#endif
lineno = 0;
pg(stdout,"Basis of AI Backprop (c) 1990-96 by Donald R. Tveter\n");
pg(stdout," drt@mcs.com - http://www.mcs.com/~drt/home.html\n");
pg(stdout," April 10, 1996 version.\n");
filestackptr = 0;
filestack[0] = stdin;
data = stdin;
emptystring = '\0';
trainfile = &emptystring;
testfile = &emptystring;
if (argc == 1)
{
printf("no data file, stdin assumed\n");
datafile = "stdin";
}
else
{
datafile = argv[1];
pushfile(datafile,1);
};
init();
signal(SIGINT,restartcmdloop); /* restart from interrupt */
cmdloop();
if (copy != NULL)
{
fflush(copy);
fclose(copy);
}
}