[comp.sources.misc] v14i085: Fast Backpropagation Part 2 of 4

drt@chinet.chi.il.us (Donald Tveter) (09/16/90)

Posting-number: Volume 14, Issue 85
Submitted-by: Donald Tveter <drt@chinet.chi.il.us>
Archive-name: back-prop/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 4)."
# Contents:  bp.c
# Wrapped by drt@chinet on Fri Aug 31 08:17:40 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'bp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bp.c'\"
else
echo shar: Extracting \"'bp.c'\" \(36100 characters\)
sed "s/^X//" >'bp.c' <<'END_OF_FILE'
X/* ************************************************** */
X/* file bp.c:  contains the main program and network  */
X/*             creation routines.                     */
X/*                                                    */
X/* Copyright (c) 1990 by Donald R. Tveter             */
X/*                                                    */
X/* ************************************************** */
X
X#include <stdio.h>
X#include <malloc.h>
X#include <signal.h>
X#include <setjmp.h>
X#define SIGINT 2
X#define MAXINT 2147483647
X
X#ifdef INTEGER
X#include "ibp.h"
X#else
X#include "rbp.h"
X#endif
X
Xextern int rand();           /* built-in C function */
Xextern int srand();          /* built-in C function */
X
Xextern void forward();       /* from int.c or real.c */
X
X#ifdef INTEGER
Xextern int scale();          /* from io.c */
Xextern double unscale();     /* from io.c */
X#endif
X
Xextern int copyhidden();     /* from misc.c */
Xextern void findendofpats(); /* from misc.c */
Xextern void help();          /* from io.c */
Xextern void kick();          /* from misc.c */
Xextern void nullpatterns();  /* from misc.c */
Xextern void printoutunits(); /* from misc.c */
Xextern void printpats();     /* from misc.c */
Xextern void printweights();  /* from io.c */
Xextern void run();           /* from misc.c */
Xextern WTTYPE rdr();         /* from io.c */
Xextern int readch();         /* from io.c */
Xextern double readchar();    /* from io.c */
Xextern int readint();        /* from io.c */
Xextern void restoreweights();/* from io.c */
Xextern void saveweights();   /* from io.c */
Xextern void texterror();     /* from io.c */
Xextern void whittle();       /* from misc.c */
X
X/* global variables used in all versions */
X
Xchar activation;      /* activation function, p or s */
XWTTYPE alpha;         /* momentum term */
Xchar backprop;        /* flags whether to back propagate error for */
X                      /* units close to their targets */
Xint bufferend;        /* index of last character in input line */
Xint bufferptr;        /* position of next character in buffer */
Xchar buffer[buffsize];/* holds contents of one input line */
Xint ch;               /* general purpose character variable */
Xchar cmdfilename[50]; /* name of file to take extra commands from */
Xjmp_buf cmdloopstate; /* to save state in case of a SIGINT */
XWTTYPE D;             /* sigmoid sharpness */
XFILE *data;           /* file for original data */
Xchar datafilename[50];/* copy of the data file name saved here */
XWTTYPE dbdeta;        /* the initial eta value for the DBD method */
XWTTYPE decay;         /* the decay parameter for the DBD method */
Xchar deriv;           /* flags type of derivative to use */
Xint echo;             /* controls echoing of characters during input */
XWTTYPE eta;           /* basic learning rate */
XWTTYPE eta2;          /* DSZ learning rate for inner layers */
XWTTYPE etamax;        /* the maximum eta for the DBD method */
Xint extraconnect;     /* flags the use of connections between */
X                      /* non-adjacent layers */
Xint format[maxformat];/* each value in format indicates where to put */
X                      /* a blank for compressed output mode or a */
X                      /* carriage return for real output */
XUNIT *hlayer;         /* pointer to list of units in second layer */
XUNIT *ilayer;         /* pointer to list of units in third layer */
Xchar informat;        /* controls format to read numbers */
XWTTYPE initialkick;   /* the range weights are initialized to */
Xint iter;             /* for counting iterations in one run */
XUNIT *jlayer;         /* pointer to list of units in fourth layer */
XWTTYPE kappa;         /* the DBD learning parameter */
XUNIT *klayer;         /* pointer to list of units in fifth layer */
XLAYER *last;          /* has address of the output layer */
Xint lastprint;        /* last iteration pattern responses printed */
Xint lastsave;         /* last time weights were saved */
Xshort nlayers;        /* number of layers in network */
Xint npats;            /* number of patterns currently in use */
Xchar outformat;       /* controls format to print output */
Xint prevnpats;        /* previous number of patterns, initially 0 */
XWTTYPE qmark;         /* value for ? in compressed input */
Xint readerror;        /* flags an error in reading a value */
Xint readingpattern;   /* flags reading pattern state */
Xint saverate;         /* rate at which to save weights */
Xunsigned seed;        /* seed for generating random weights */
Xshort skiprate;       /* number of times to bypass a learned pattern */
XLAYER *start;         /* has address of the input layer */
Xchar summary;         /* flags summary output mode */
XWTTYPE theta1;        /* the DBD parameter */
XWTTYPE theta2;        /* 1 - theta1 */
XWTTYPE toler;         /* value used in testing for completion */
XWTTYPE toosmall;      /* weights smaller than toosmall were removed */
X#ifdef INTEGER
Xint totaldiff;        /* totals errors to find average error per unit */
X#else
Xdouble totaldiff;
X#endif
Xint totaliter;        /* counts total iterations for the program */
Xint unlearnedpats;    /* number unlearned in last learning cycle */
Xchar update;          /* flags type of update rule to use */
Xchar wtformat;        /* controls format to save and restore weights */
XWTTYPE wtlimit;       /* adjustable limit on weights */
Xchar wtlimithit;      /* flags whether the limit has been hit */
Xint wttotal;          /* total number of weights in use */
X
X/* global variable for the symmetric integer version */
X
X#ifdef SYMMETRIC
XWTTYPE  stdthresh;    /* the standard threshold weight value */
X#endif
X
XUNIT *locateunit(layerno,unitno)  /* given a layer number and unit */
Xint layerno, unitno;              /* number this routine returns the */
X{int i;                           /* address of the unit */
X UNIT *u;
X LAYER *layer;
X 
X if (layerno >= 1 && layerno <= nlayers)
X    {
X      layer = start;
X      for(i=1;i<=(layerno-1);i++) layer = layer->next;
X      u = (UNIT *) layer->units;
X      while (u != NULL && u->unitnumber != unitno) u = u->next;
X      if (u == NULL)
X         printf("there is no unit %3d in layer %3d\n",unitno,layerno);
X    }
X else
X    {
X      printf("there is no layer %3d\n",layerno);
X      return(NULL);
X    };
X return(u);     
X}
X
X#ifdef SYMMETRIC
X
Xint wtaddress(i,j,biasunit,type,size) /* Returns the address of a */
Xint i,j;                              /* weight (1), olddw (2),   */
Xint biasunit;                         /* eta (3) or total (4).    */
Xint type;                             /* One is created if it     */
Xint size;                             /* doesn't already exist.   */
X
X{ int k, addr;
X  UNIT *u;
X  WTNODE *w;
X
X  if (biasunit == 1) addr = (int) malloc(size);
X  else if (j >= i) addr = (int) malloc(size);
X  else /* the item already exists, so find its address */
X     {
X       u = locateunit(2,j);
X       w = (WTNODE *) u->wtlist;
X       k = 1;
X       while (k < i)
X          {
X            w = w->next;
X            k = k + 1;
X          };
X       if (type == 1) addr = (int) w->weight;
X       else if (type == 2) addr = (int) w->olddw;
X       else if (type == 3) addr = (int) w->eta;
X               else addr = (int) w->total;
X     };
X  return(addr);
X}
X
Xvoid setweight(w,i,j,biasunit) /* set initial values in w */
XWTNODE *w;
Xint i, j;
Xint biasunit;
X{WTTYPE *s;
X
X  s = (WTTYPE *) wtaddress(i,j,biasunit,1,WTSIZE);
X  *s = 0;
X  w->weight = s;
X  s = (WTTYPE *) wtaddress(i,j,biasunit,2,WTSIZE);
X  *s = 0;
X  w->olddw = s;
X  s = (WTTYPE *) wtaddress(i,j,biasunit,3,WTSIZE);
X  *s = eta;
X  w->eta = s;
X#ifdef INTEGER
X  w->total = (int *) wtaddress(i,j,biasunit,4,sizeof(int));
X#else
X  w->total = (double *) wtaddress(i,j,biasunit,4,WTSIZE);
X#endif
X}
X
X#else
X
Xvoid setweight(w,i,j,biasunit) /* set initial values in w */
XWTNODE *w;
Xshort i,j;
Xint biasunit;
X{
X  w->weight = 0;
X  w->olddw = 0;
X  w->eta = dbdeta;
X}
X
X#endif
X
XLAYER *mklayer(prevlayer,n)  /* creates a layer of n units, pointers */
XLAYER *prevlayer;            /* and weights back to the units in the */
Xint n;                       /* previous layer and links this new */
X                             /* layer into the list of layers */
X{UNIT *front, *p, *q, *bias, *prev, *ptr;
X WTNODE *wfront, *wprev, *w;
X LAYER *lptr;
X int i, j, count;
X
X/* make a list of nodes in this layer */
X
X count = 1;
X front = (UNIT *) malloc(sizeof(UNIT));
X front->unitnumber = count;
X front->layernumber = nlayers;
X prev = front;
X for(i=1;i<n;i++)
X    {
X      count = count + 1;
X      ptr = (UNIT *) malloc(sizeof(UNIT));
X      prev->next = ptr;
X      ptr->unitnumber = count;
X      ptr->layernumber = nlayers;
X      prev = ptr;
X    };
X prev->next = NULL;
X
X/* make a LAYER node to point to this list of units */
X
X lptr = (LAYER *) malloc(sizeof(LAYER));
X lptr->unitcount = n;
X lptr->patstart = NULL;
X lptr->currentpat = NULL;
X lptr->backlayer = prevlayer;
X lptr->next = NULL;
X (UNIT *) lptr->units = front;   /* connect the list of units */
X
X/* return if this is the input layer */
X
X if (prevlayer == NULL) return(lptr);
X prevlayer->next = lptr;
X
X/* If we are working on a deeper layer, for every node in this layer, */
X/* create a linked list back to units in the previous layer. */
X
X i = 1;
X q = front;
X while (q != NULL) /* do a unit */
X   {    
X     j = 1;            /* handle first connection */
X     p = (UNIT *) prevlayer->units;
X     wfront = (WTNODE *) malloc(sizeof(WTNODE));
X     wttotal = wttotal + 1;
X     (WTNODE *) q->wtlist = wfront;
X     wprev = wfront;
X     (UNIT *) wfront->backunit = p;
X     setweight(wfront,i,j,0);
X     p = p->next;
X     while (p != NULL) /* handle rest of connections */
X        {
X          j = j + 1;
X          w = (WTNODE *) malloc(sizeof(WTNODE));
X          wttotal = wttotal + 1;
X          wprev->next = w;
X          (UNIT *) w->backunit = p;
X          setweight(w,i,j,0);
X          wprev = w;
X          p = p->next;
X        };
X     j = j + 1;
X     bias = (UNIT *) malloc(sizeof(UNIT));   /* create a bias unit */
X     bias->oj = scale(1.0);
X     bias->layernumber = nlayers;
X     bias->unitnumber = 32767;           /* bias unit is unit 32767 */
X     w = (WTNODE *) malloc(sizeof(WTNODE)); /* connect to end of list */
X     wttotal = wttotal + 1;
X     wprev->next = w;
X     (UNIT *) w->backunit = bias;
X     setweight(w,n+2,i,1);
X     w->next = NULL;
X     q = q->next;
X     i = i + 1;
X   };
X return(lptr);
X}
X
X#ifndef SYMMETRIC
X
Xvoid connect(a,b,range)  /* add a connection from unit a to unit b */
XUNIT *a, *b;             /* connections go in increasing order */
XWTTYPE range;
X
X{WTNODE *wnew, *w, *wprev;
X UNIT *wunit;
X int farenough;
X
X wnew = (WTNODE *) malloc(sizeof(WTNODE));
X wttotal = wttotal + 1;
X wnew->eta = dbdeta;
X wnew->weight = range * rand() / 32768;
X if (rand() > 16383) wnew->weight = -wnew->weight;
X wnew->olddw = 0;
X (UNIT *) wnew->backunit = a;
X w = (WTNODE *) b->wtlist;
X wprev = NULL;
X wunit = (UNIT *) w->backunit;
X farenough = 0;                  /* insert the weight in order */
X while (w != NULL && !farenough)
X    if (wunit->layernumber > a->layernumber) farenough = 1;
X    else if (wunit->layernumber == a->layernumber)
X            {
X              while (w != NULL && !farenough)
X                 {
X                   if (wunit->unitnumber < a->unitnumber &&
X                       wunit->layernumber == a->layernumber)
X                      {
X                        wprev = w;
X                        w = w->next;
X                        wunit = (UNIT *) w->backunit;
X                      }
X                   else farenough = 1;
X                 };
X            }      
X    else
X       {
X         wprev = w;
X         w = w->next;
X         wunit = (UNIT *) w->backunit;
X       }
X if (wprev == NULL)
X    {
X      wnew->next = w;
X      (WTNODE *) b->wtlist = wnew;
X    }
X else
X    {
X      wnew->next = w;
X      wprev->next = wnew;
X    };
X}
X
Xvoid addhiddenunit(layerno,range)
Xint layerno;  /* add hidden unit to end of the layer */
XWTTYPE range;
X{
X LAYER *lptr, *prevlayer, *nextlayer;
X UNIT *u, *prevu, *p, *bias;
X WTNODE *wnode;
X int i, unitno;
X
X lptr = start;
X for (i=1;i <= (layerno - 1); i++) lptr = lptr->next;
X unitno = lptr->unitcount;
X lptr->unitcount = unitno + 1;
X prevu = locateunit(layerno,unitno);
X if (prevu == NULL) return;
X u = (UNIT *) malloc(sizeof(UNIT));
X prevu->next = u;
X u->next = NULL;
X u->unitnumber = unitno + 1;
X u->layernumber = layerno;
X bias = (UNIT *) malloc(sizeof(UNIT));
X bias->oj = scale(1.0);
X bias->layernumber = layerno;
X bias->unitnumber = 32767;           /* bias unit is unit 32767 */
X wnode = (WTNODE *) malloc(sizeof(WTNODE));
X wttotal = wttotal + 1;
X wnode->weight = range * rand() / 32768;
X if (rand() > 16383) wnode->weight = -wnode->weight;
X wnode->olddw = 0;
X wnode->eta = dbdeta;
X wnode->next = NULL;
X (UNIT *) wnode->backunit = bias;
X (WTNODE *) u->wtlist = wnode;
X prevlayer = lptr->backlayer;
X p = (UNIT *) prevlayer->units;
X while (p != NULL)
X    {
X      connect(p,u,range);
X      p = p->next;
X    };
X nextlayer = lptr->next;
X p = (UNIT *) nextlayer->units;
X while (p != NULL)
X    {
X      connect(u,p,range);
X      p = p->next;
X    };
X}      
X
X#endif
X
Xvoid readpatson(layer,command) /* reads the patterns for layer */
XLAYER *layer;
Xint command;
X
X{PATNODE *p, *prevp;
X PATLIST *pl;
X int i;
X
X pl = (PATLIST *) malloc(sizeof(PATLIST));
X pl->next = NULL;
X pl->bypass = 0;      /* number of times to bypass this pattern */
X pl->pats = NULL;     /* no patterns read yet */
X if (layer->patstart == NULL) (PATLIST *) layer->patstart = pl;
X else layer->currentpat->next = pl;
X layer->currentpat = pl;
X
X prevp = NULL; /* read in each number */
X for (i=1;i<=layer->unitcount;i++)
X    {
X      p = (PATNODE *) malloc(sizeof(PATNODE));
X      if (informat == 'r') p->val = rdr(GE,(double) HCODE,command);
X      else p->val = scale(readchar());
X      if (readerror == 1)
X         {
X           printf("pattern not read\n");
X           return;
X         };
X      p->next = NULL;
X      if (prevp == NULL) pl->pats = p; else prevp->next = p;
X      prevp = p;
X    };
X}
X
Xvoid readpats(new,command)  /* reads the input and output patterns */
Xint new;
Xint command;
X{ int i;
X  PATLIST *pl;
X  
X  for (i=prevnpats + 1;i<=npats;i++)
X     {
X       readpatson(start,command);
X       if (readerror == 1) goto failure;
X       readpatson(last,command);
X       if (readerror == 1) goto failure;
X     };
X  return;
Xfailure:
X  if (data != stdin)
X    {
X      printf("error while reading pattern %d\n",i);
X      exit(5);
X    };
X  if (new == 0)
X     {
X       resetpats();
X       for (i=1;i<prevnpats;i++) setonepat();
X       pl = (PATLIST *) start->currentpat;
X       pl->next = NULL;
X       pl = (PATLIST *) last->currentpat;
X       pl->next = NULL;
X     };
X  printf("no patterns added\n");
X  printf("%d patterns in use\n",prevnpats);   
X  npats = prevnpats;
X}
X
Xvoid init()    /* initializes almost everything */
X{int i;
X
X activation = 'p';          /* piece-wise activation function */
X alpha = scale(0.5);
X backprop = 1;              /* always back-propagate errors */
X bufferend = 0;
X bufferptr = buffsize + 1;
X ch = ' ';
X D = scale(1.0);
X dbdeta = scale(0.5);
X decay = scale(0.5);
X deriv = 'f';               /* use Fahlman's derivative */
X eta = scale(0.5);
X eta2 = scale(0.05);
X etamax = scale(30.0);
X extraconnect = 0;
X format[0] = 0;  /* set default places for breaks in output patterns */
X for(i=1;i<=maxformat-1;i++) format[i] = format[i-1] + 10;
X informat = 'c';            /* input format is compressed */
X initialkick = -1;          /* weights have not been kicked yet */
X kappa = scale(0.5);
X lastprint = 0;
X lastsave = 0;
X outformat = 'r';           /* output format is real */
X skiprate = 0;
X prevnpats = 0;
X qmark = scale(0.5);
X saverate = 100000;         /* effectively, never save weights */
X seed = 0;
X#ifdef SYMMETRIC
X stdthresh = -32768;        /* indicates no threshold set */
X#endif
X summary = '-';             /* don't summarize learning */
X theta1 = scale(0.5);
X theta2 = scale(1.0) - theta1;
X toler = scale(0.1);
X toosmall = -1;             /* indicates no weights whittled away */
X totaliter = 0;
X update = 'o';              /* update formulas are the original */
X wtformat = 'r';            /* save weights in real format */
X wtlimit = scale(0.0);      /* no limit on weights */
X wtlimithit = 0;            /* weight limit not yet hit */
X wttotal = 0;
X}
X
Xvoid restartcmdloop() /* for a SIGINT, restart in cmdloop */
X{
X if (data != stdin) ch = EOF;
X signal(SIGINT,restartcmdloop);
X longjmp(cmdloopstate,1);
X}
X 
Xvoid cmdloop()    /* read commands and process them */
X{
X int finished, layerno, unitno, layer1, layer2, node1, node2;
X int i, itemp, itemp2;
X WTTYPE temp, temp2;
X UNIT *u, *n1, *n2, *hunit, *iunit, *junit, *kunit;
X LAYER *p;
X char string[81];
X WTNODE *w;
X
X setjmp(cmdloopstate); /* position to recover from SIGINT */
X finished = 0;         /* loop until finished == 1 */
X do{
Xrestart:
X#ifdef SYMMETRIC
X    if (data == stdin) printf("[?!*AabCEefHhijklmnoPpQqRrSsTtWwx]? ");
X#else
X    if (data == stdin) printf("[?!*AabCcEefHhijklmnoPpQqRrSstWwx]? ");
X#endif
X     while(ch == ' ' || ch == '\n') ch = readch();
X     switch (ch) {
Xcase EOF: if (data == stdin) exit(6); else data = stdin;
X          printf("taking commands from stdin now\n");
X          bufferend = 0;             /* force a read from stdin */
X          bufferptr = buffsize + 1;  /* when readch is called */
X          ch = ' ';
X          goto restart;
Xcase '?': printf("\n%d iterations, s %1d  ",totaliter,seed);
X          printf("k 0 %5.3lf,  ",unscale(initialkick));
X          printf("file = %s\n",datafilename);
X          printf("Algorithm: a%c",activation);
X          if (backprop) printf(" b+"); else printf(" b-");
X          printf(" D%5.2lf d%c ",unscale(D),deriv);
X          printf("l%6.2lf s%1d u%c\n",unscale(wtlimit),skiprate,update);
X          printf("e %7.5lf %7.5lf",unscale(eta),unscale(eta2));
X          printf(" --- a %7.5lf\n",unscale(alpha));
X          printf("j d %8.5lf e %8.5lf",unscale(decay),unscale(dbdeta));
X          printf(" k %8.5lf m %8.5lf",unscale(kappa),unscale(etamax));
X          printf(" t %8.5lf\n",unscale(theta1));
X          printf("tolerance = %4.2lf\n",unscale(toler));
X          printf("f i%c o%c",informat,outformat);
X          printf(" s%c w%c\n",summary,wtformat);
X          printf("format breaks after: ");
X          for (i=1;i<=10;i++) printf("%4d",format[i]);
X          printf("\n                     ");
X          for (i=11;i<=maxformat-1;i++) printf("%4d",format[i]);
X          printf("\nlast time weights were saved: %d\n",lastsave);
X          printf("saving weights every %d iterations\n",saverate);
X          if (wtlimithit) printf(">>>>> WEIGHT LIMIT HIT <<<<<\n");
X          printf("network size: ");
X          p = start;
X          while (p != NULL)
X             {
X               printf(" %1d",p->unitcount);
X               p = p->next;
X             };
X          if (extraconnect == 1) printf(" with extra connections");
X          printf(" (total:  %1d weights)\n",wttotal);
X          if (toosmall != -1)
X             {
X               printf("removed non-bias weights with absolute ");
X               printf("value below  %4.2lf\n",unscale(toosmall));
X             };
X#ifdef SYMMETRIC
X          if (stdthresh != -32768)
X             printf("thresholds frozen at %lf\n", unscale(stdthresh));
X#endif
X          printf("%d patterns        ",npats);
X          printf("%d learned        ",npats-unlearnedpats);
X          printf("%d unlearned on last pass\n",unlearnedpats);
X          printf("? = %lf\n",unscale(qmark));
X          printf("for help, type h followed by");
X          printf(" the letter of the command\n\n");
X          break;
Xcase '!': i = 0;
X          ch = readch();
X          while (ch != '\n' && i <= 80)
X             {
X               string[i] = ch;
X               ch = readch();
X               i = i + 1;
X             };
X          bufferptr = bufferptr - 1; /* ungetc(ch,data); */
X          string[i] = '\0';
X          system(string);
X          break;
Xcase '*': break;  /* * on a line is a comment */
Xcase 'A': while (ch != '\n' && ch != '*')
X           {
X            ch = readch();
X            if (ch == 'a')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == 'p') activation = 'p';
X#ifndef INTEGER
X              else if (ch == 's') activation = 's';
X#endif
X              else texterror();
X             }
X            else if (ch == 'b')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == '+') backprop = 1;
X              else if (ch == '-') backprop = 0;
X              else texterror();
X             }
X            else if (ch == 'D')
X             {
X               temp = rdr(GT,0.0,'A');
X               if (readerror == 0) D = temp;
X             }
X            else if (ch == 'd')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == 'd' || ch == 'f' || ch == 'o') deriv = ch;
X              else texterror();
X             }
X            else if (ch == 'l')
X             {
X               temp = rdr(GE,0.0,'A');
X               if (readerror == 0)
X                  {
X                    wtlimit = temp;
X                    if (wtlimit == 0) wtlimithit = 0;
X                  };
X             }
X            else if (ch == 's')
X             {
X              itemp = readint(0,32767,'s');
X              if (readerror == 0) skiprate = itemp;
X             }
X            else if (ch == 'u')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == 'c' || ch == 'C' || ch == 'd' ||
X                  ch == 'j' || ch == 'o') update = ch;
X              else texterror();
X             }
X            else if (ch == '*' || ch == '\n' || ch == ' ');
X            else texterror();
X           }
X          bufferptr = bufferptr - 1;
X          break;
Xcase 'a': temp = rdr(GE,0.0,'a');
X          if (readerror == 0) alpha = temp;
X          break;
Xcase 'b': itemp = 0;
X          ch = readch();
X          while (ch != '\n' && ch != '*')
X             {
X               bufferptr = bufferptr - 1;
X               itemp2 = readint(format[itemp],MAXINT,'b');
X               if (readerror == 1) goto endb;
X               itemp = itemp + 1;
X               if (itemp < maxformat) format[itemp] = itemp2;
X               else printf("format too long\n");
X               ch = readch();
X               while (ch == ' ') ch = readch();
X               /* if its the start of a number, back up */
X               if (ch != '\n') bufferptr = bufferptr - 1;
X             };
X          if (itemp < maxformat-1)
X             for (i=itemp+1;i <= maxformat-1; i++)
X                format[i] = format[i-1] + 10;
X          bufferptr = bufferptr - 1;
X    endb: break;
Xcase 'C': if (toosmall != -1)
X             {
X               printf("cannot restart with the weights removed\n");
X               break;
X             };
X          wtlimithit = 0;
X          totaliter = 0;
X          lastsave = 0;
X          initialkick = -1;
X          lastprint = 0;
X          seed = 0;
X          p = start->next;
X          while (p != NULL)
X             {
X               u = (UNIT *) p->units;
X               while (u != NULL)
X                  {
X                    w = (WTNODE *) u->wtlist;
X                    while (w != NULL)
X                       {
X#ifdef SYMMETRIC
X                         if (w->next != NULL)
X                            { /* skip threshold weight */
X                              *(w->weight) = 0;
X                              *(w->olddw) = 0;
X                              *(w->eta) = dbdeta;
X                            };
X#else
X                         w->weight = 0;
X                         w->olddw = 0;
X                         w->eta = dbdeta;
X#endif
X                         w = w->next;
X                       };
X                    u = u->next;
X                  };
X               p = p->next;
X             };
X          break;
X#ifndef SYMMETRIC
Xcase 'c': layer1 = readint(1,nlayers,'c');
X          if (readerror == 1) break;
X          node1 = readint(1,MAXINT,'c');
X          if (readerror == 1) break;
X          layer2 = readint(1,nlayers,'c');
X          if (readerror == 1) break;
X          node2 = readint(1,MAXINT,'c');
X          if (readerror == 1) break;
X          if (layer1 >= layer2)
X             {
X               printf("backward connections in c command not");
X               printf(" implemented\n");
X               break;
X             };
X          n1 = locateunit(layer1,node1);
X          n2 = locateunit(layer2,node2);
X          if (n1 != NULL && n2 != NULL)
X             {
X               connect(n1,n2,0);
X               extraconnect = 1;
X             }
X          else printf("connection not made: %d %d %d %d\n",
X                       layer1, node1, layer2, node2);
X          break;
X#endif
X
Xcase 'E': itemp = readint(0,1,'E');
X          if (readerror == 1) break;
X          else echo = itemp;
X          break;
Xcase 'e': temp = rdr(GT,0.0,'e');
X          if (readerror == 0) eta = temp;
X          while (ch == ' ') ch = readch();
X          if (ch != '\n' && ch != '*')
X             {
X               bufferptr = bufferptr - 1;
X               temp = rdr(GT,0.0,'r');
X               if (readerror != 1) eta2 = temp;
X             }
X          else eta2 = eta / 10;
X          bufferptr = bufferptr - 1;
X          break;
Xcase 'f': while (ch != '\n' && ch != '*')
X           {
X            ch = readch();
X            if (ch == 'i')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == 'c' || ch == 'r') informat = ch;
X              else texterror();
X             }
X            else if (ch == 'o')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == 'a' || ch == 'c' || ch == 'r') outformat = ch;
X              else texterror();
X             }
X            else if (ch == 's')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == '+' || summary == '-') summary = ch;
X              else texterror();
X             }
X            else if (ch == 'w')
X             {
X              do ch = readch(); while (ch == ' ');
X              if (ch == 'r' || ch == 'R' || ch == 'b' || ch == 'B')
X                 wtformat = ch;
X              else texterror();
X             }
X            else if (ch == ' ' || ch == '*' || ch == '\n');
X            else texterror();
X           }
X          bufferptr = bufferptr - 1;
X          break;
X#ifndef SYMMETRIC
Xcase 'H': itemp = readint(2,nlayers,'H');
X          if (readerror == 1) break;
X          temp = rdr(GE,0.0,'H');
X          if (readerror == 0) addhiddenunit(itemp,temp);
X          break;
X#endif
Xcase 'h': help();
X          break;
Xcase 'i': ch = readch();
X          while(ch == ' ') ch = readch();
X          itemp = 0;
X          while(ch != ' ' && ch != '\n' && itemp < 49)
X             {
X               cmdfilename[itemp] = ch;
X               itemp = itemp + 1;
X               ch = readch();
X             };
X          cmdfilename[itemp] = '\0';
X          if ((data = fopen(cmdfilename,"r")) == (FILE *) NULL)
X             {
X               printf("cannot open: %s\n",cmdfilename);
X               data = stdin;
X               printf("taking commands from stdin now\n");
X             }
X          bufferend = 0;
X          bufferptr = buffsize + 1;
X          ch = ' ';
X          goto restart;
Xcase 'j': while (ch != '\n' && ch != '*')
X           {
X            ch = readch();
X            if (ch == 'd')
X             {
X              temp = rdr(GT,0.0,'j');
X              if (readerror == 0) decay = temp;
X             }
X            else if (ch == 'e')
X             {
X              temp = rdr(GT,0.0,'d');
X              if (readerror == 0)
X               {
X                dbdeta = temp;
X                p = start->next;
X                while (p != NULL)
X                 {
X                  u = (UNIT *) p->units;
X                  while (u != NULL)
X                   {
X                    w = (WTNODE *) u->wtlist;
X                    while (w != NULL)
X                     {
X#ifdef SYMMETRIC
X                      *(w->eta) = dbdeta;
X#else
X                      w->eta = dbdeta;
X#endif
X                      w = w->next;
X                     }
X                    u = u->next;
X                   }
X                  p = p->next;
X                 }
X               }
X             }
X            else if (ch == 'k')
X             {
X              temp = rdr(GT,0.0,'j');
X              if (readerror == 0) kappa = temp;
X             }
X            else if (ch == 'm')
X             {
X              temp = rdr(GT,0.0,'j');
X              if (readerror == 0) etamax = temp;
X             }
X            else if (ch == 't')
X             {
X              temp = rdr(GE,0.0,'j');
X              if (readerror == 0)
X                 {
X                  theta1 = temp;
X                  theta2 = scale(1.0) - theta1;
X                 };
X             }
X            else if (ch == '*' || ch == '\n' || ch == ' ');
X            else texterror();
X           }
X          bufferptr = bufferptr - 1;
X          break;
Xcase 'k': temp = rdr(GE,0.0,'k');
X          if (readerror == 1) break;
X          temp2 = rdr(GT,0.0,'k');
X          if (readerror == 0)
X           {
X            if (initialkick == -1 && temp == 0) initialkick = temp2;
X            kick(temp,temp2);
X           }
X          break;
Xcase 'l': layerno = readint(1,nlayers,'l'); 
X          if (readerror == 1) break;
X          p = start;
X          for (i=2;i<=layerno;i++) p = p->next;
X          printoutunits(p,0);
X          break;
Xcase 'm': nlayers = 0;
X          ch = readch();
X          p = NULL;
X          while (ch != '\n' && ch != '*')
X             {
X               itemp = readint(1,MAXINT,'m');
X               if (readerror == 1) goto endm;
X               nlayers = nlayers + 1;
X               p = mklayer(p,itemp);
X               if (nlayers == 1) start = p;
X               ch = readch();
X               while (ch == ' ') ch = readch();
X               /* if its the start of a number, back up */
X               if (ch != '\n') bufferptr = bufferptr - 1;
X             };
X          last = p;
X          p = start;
X          p = p->next;
X          hlayer = (UNIT *) p->units;
X          p = p->next;
X          if (p != NULL)
X             {
X               ilayer = (UNIT *) p->units;
X               p = p->next;
X               if (p != NULL)
X                  {
X                    jlayer = (UNIT *) p->units;
X                    p = p->next;
X                    if (p != NULL) klayer = (UNIT *) p->units;
X                  }
X             };
X          bufferptr = bufferptr - 1;
X          nullpatterns();
X    endm: break;
Xcase 'n': if (start == NULL)
X             {
X               printf("the network must be defined first\n");
X               break;
X             };
X          itemp = readint(1,MAXINT,'n');
X          if (readerror == 1) break;
X          nullpatterns();
X          npats = itemp;
X          readingpattern = 1;
X          readpats(1,'n');
X          readingpattern = 0;
X          unlearnedpats = npats;
X          break;
Xcase 'o': do ch = readch(); while (ch == ' ' || ch == '\n');
X          if (ch == 'r' || ch == 'a' || ch == 'c') outformat = ch;
X          else printf("incorrect output format: %c\n",ch);
X          break;
Xcase 'P': do ch = readch(); while (ch == ' ');
X          bufferptr = bufferptr - 1;
X          if (ch == '\n' || ch == '*') itemp = 0;
X          else
X             {
X               itemp = readint(0,npats,'P');
X               if (readerror == 1) break;
X             };
X          if (itemp == 0) printpats(1,npats,0,1,0);
X          else printpats(itemp,itemp,0,1,0);
X          break;
Xcase 'p': u = (UNIT *) start->units;
X          readingpattern = 1;
X          hunit = hlayer;
X          iunit = ilayer;
X          junit = jlayer;
X          kunit = klayer;
X          while (u != NULL)
X           {
X            if (informat == 'r') u->oj = rdr(GE,(double) HCODE,'p');
X            else u->oj = scale(readchar());
X            if (readerror == 1) goto endp;
X            if (u->oj <= KCODE) /* do hidden unit codes */
X             {
X              if (u->oj == HCODE)
X                 {if (copyhidden(u,&hunit,2) == 1) goto endp;}
X              else if (u->oj == ICODE)
X                 {if (copyhidden(u,&iunit,3) == 1) goto endp;}
X              else if (u->oj == JCODE)
X                 {if (copyhidden(u,&junit,4) == 1) goto endp;}
X              else if (copyhidden(u,&kunit,5) == 1) goto endp;
X             };
X            u = u->next;
X           };
X          forward();
X          printoutunits(last,0);
X    endp: readingpattern = 0;
X          break;
Xcase 'Q': temp = rdr(GT,(double) KCODE,'Q');
X          if (readerror == 0) qmark = temp;
X          break;
Xcase 'q': finished = 1;
X          break;
Xcase 'R': restoreweights();
X          break;
Xcase 'r': if (start == NULL)
X             {
X               printf("the network must be defined first\n");
X               break;
X             };
X          iter = readint(1,MAXINT,'r'); 
X          if (readerror == 1) break;
X          while (ch == ' ') ch = readch();
X          if (ch != '\n' && ch != '*')
X             {
X               bufferptr = bufferptr - 1;
X               itemp = readint(1,MAXINT,'r');
X               if (readerror != 1) run(iter,itemp);
X             }
X          else run(iter,-1);
X          bufferptr = bufferptr - 1;
X          break;
Xcase 'S': do ch = readch(); while (ch == ' ');
X          bufferptr = bufferptr - 1;
X          if (ch == '\n' || ch == '*') itemp = 0;
X          else
X             {
X               itemp = readint(0,MAXINT,'S');
X               if (readerror == 1) break;
X             };
X          if (itemp == 0) saveweights();
X          else saverate = itemp;
X          break;
Xcase 's': seed = readint(0,MAXINT,'s');
X          srand(seed);
X          break;
X#ifdef SYMMETRIC
Xcase 'T': stdthresh = rdr(GT,-unscale(32767),'T');
X          if (readerror == 1) break;
X          u = (UNIT *) last->units;
X          while (u != NULL)
X             {
X               w = (WTNODE *) u->wtlist;
X               while (w->next != NULL) w = w->next;
X               *(w->weight) = stdthresh;
X               u = u->next;
X             };
X          break;
X#endif
Xcase 't': temp = rdr(GT,0.0,'t');
X          if (readerror == 1) break;
X          else if (temp < scale(1.0)) toler = temp;
X          else printf("tolerance value out of range\n");
X          break;
X#ifndef SYMMETRIC
Xcase 'W': temp = rdr(GT,0.0,'W');
X          if (readerror == 0)
X             {
X               toosmall = temp;
X               whittle(temp);
X               printf("total weights now: %1d\n",wttotal);
X             };
X          break;
X#endif
Xcase 'w': layerno = readint(2,nlayers,'w');
X          if (readerror == 1) break;
X          unitno = readint(1,MAXINT,'w');
X          if (readerror == 1) break;
X          u = locateunit(layerno,unitno);
X          if (u != NULL) printweights(u);
X          break;
Xcase 'x': if (start == NULL)
X             {
X               printf("the network must be defined first\n");
X               break;
X             };
X          itemp = readint(1,MAXINT,'x');
X          if (readerror == 1) break;
X          prevnpats = npats;
X          npats = npats + itemp;
X          findendofpats(start);
X          findendofpats(last);
X          readingpattern = 1;
X          readpats(0,'x');
X          readingpattern = 0;
X          unlearnedpats = npats;
X          break;
Xdefault : texterror();
X          break;
X      };
X    ch = readch();
X    while(ch != '\n') ch = readch();
X  }while (finished == 0);
X}
X
Xvoid main(argc,argv)
Xint argc;
Xchar *argv[];
X{
X char *fnamestr, *i;
X
Xprintf("Fast Backpropagation Copyright (c) 1990 by Donald R. Tveter\n");
X
X setbuf(stdout,NULL);  /* set unbuffered output */
X if (argc == 1) /* check for file argument, if any */
X    {
X      printf("missing data file name, stdin assumed\n");
X      data = stdin;
X      *datafilename = '\0';
X    }
X else
X    if ((data = fopen(argv[1],"r")) == (FILE *) NULL)
X       {
X         printf("cannot open: %s\n",argv[1]);
X         exit(1);
X       }
X    else /* make a copy of the file name in a global variable */
X       {
X         fnamestr = argv[1];
X         i = datafilename;
X         while(*fnamestr != '\0') *i++ = *fnamestr++;
X       };
X init();
X signal(SIGINT,restartcmdloop); /* restart from interrrupt */
X cmdloop();
X}
END_OF_FILE
if test 36100 -ne `wc -c <'bp.c'`; then
    echo shar: \"'bp.c'\" unpacked with wrong size!
fi
# end of 'bp.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0