home *** CD-ROM | disk | FTP | other *** search
- /* ************************************************ */
- /* file io.c: contains most input/output functions */
- /* */
- /* Copyright (c) 1990 by Donald R. Tveter */
- /* */
- /* ************************************************ */
-
- #include <stdio.h>
- #ifdef INTEGER
- #include "ibp.h"
- #else
- #include "rbp.h"
- #endif
-
- extern char buffer[buffsize];
- extern int bufferend;
- extern int bufferptr;
- extern int ch;
- extern FILE *data;
- extern char datafilename[50];
- extern int echo;
- extern int format[maxformat];
- extern LAYER *last;
- extern int lastsave;
- extern short nlayers;
- extern char outformat;
- extern WTTYPE qmark;
- extern int readerror;
- extern int readingpattern;
- extern LAYER *start;
- extern WTTYPE toler;
- extern int totaliter;
- extern char wtformat;
-
- #ifdef INTEGER
-
- short scale(x) /* returns x as a scaled 16-bit value */
- double x;
- {
- short s;
- if (x > 31.999 || x < -32.0)
- {
- printf("magnitude of %lf is too large for the integer",x);
- printf(" representation\n",x);
- readerror = 1;
- return(0);
- };
- if (x > 0.0) s = x * 1024 + 0.5;
- else s = x * 1024 - 0.5;
- if (x != 0.0 && s == 0)
- {
- printf("warning: magnitude of %lf is too small for",x);
- printf(" the integer representation\n");
- return(0);
- };
- return(s);
- }
-
- double unscale(x) /* returns the double value of short x */
- short x;
- {
- double temp;
- temp = (double) x / 1024.0;
- return(temp);
- }
-
- double unscaleint(x) /* returns the double value of int x */
- int x;
- {
- double temp;
- temp = (double) x / 1024.0;
- return(temp);
- }
-
- #endif
-
- int readch() /* returns the next character in the input buffer */
- {
- int i, ch2;
- if (bufferptr > bufferend) /* then read next line into buffer */
- {
- ch2 = getc(data);
- if (ch2 == EOF) return(ch2);
- i = 0;
- while(ch2 != '\n' && i < buffsize)
- {
- if (ch2 == 015) ch2 = ' '; /* filter out carriage returns */
- buffer[i] = ch2;
- i = i + 1;
- ch2 = getc(data);
- };
- if (i == buffsize)
- {
- printf("line too long\n");
- exit(4);
- };
- buffer[i] = '\n';
- bufferend = i;
- bufferptr = 0;
- if (echo == 1)
- for(i = 0; i <= bufferend; i++) putchar(buffer[i]);
- }
- ch2 = buffer[bufferptr];
- bufferptr = bufferptr + 1;
- return(ch2);
- }
-
- void texterror() /* handles errors in text */
- {
- printf("unexpected text: ");
- bufferptr = bufferptr - 1;
- ch = readch();
- while (ch != '\n')
- {
- putchar(ch);
- ch = readch();
- };
- putchar('\n');
- bufferptr = bufferptr - 1;
- }
-
- int scanfordigit() /* used to scan for the leading */
- { /* digit of a number and trap mistakes */
- int sign;
-
- sign = 1;
- restart:
- ch = readch();
- while (ch == ' ' || ch == '\n') ch = readch();
- if (ch >= '0' && ch <= '9')
- {
- bufferptr = bufferptr - 1; /* unget the character */
- return(sign);
- };
- if (ch >= 'h' && ch <= 'k')
- {
- bufferptr = bufferptr - 1; /* unget the character */
- return(0);
- };
- switch (ch) {
- case EOF: printf("unexpected EOF\n");
- exit(2);
- case '*': while (ch != '\n') ch = readch();
- goto restart;
- case '-': sign = -sign;
- goto restart;
- case '?': bufferptr = bufferptr - 1; /* unget the character */
- return(0);
- default: readerror = 1;
- return(0);
- }; /* end switch */
- };
-
- int readint(min,max,command)
- int min, max; /* the minimum and maximum allowed values */
- char command;
- {
- int sign, number;
- readerror = 0;
- sign = scanfordigit();
- if (readerror == 1 || sign == 0)
- {
- readerror = 1;
- texterror();
- return(0);
- };
- number = 0;
- ch = readch();
- while (ch == ' ') ch = readch();
- while (ch >= '0' && ch <= '9')
- {
- number = number * 10 + (ch - '0');
- ch = readch();
- };
- bufferptr = bufferptr - 1; /* unget the character */
- number = sign * number;
- if (number < min || number > max)
- {
- printf("erroneous value: %d",number);
- if (data == stdin) putchar('\n');
- else printf(" in %c command\n",command);
- readerror = 1;
- };
- return(number);
- }
-
- double readreal(op,min,command)
- int op;
- double min;
- int command;
- {
- double number;
- double fractpart, divisor, intpart, sign;
- readerror = 0;
-
- sign = (double) scanfordigit();
- if (readerror == 1 || (sign == 0 && !readingpattern))
- {
- texterror();
- return(0);
- };
- ch = readch();
- if (ch == 'h' && readingpattern)
- return(unscale(HCODE));
- else if (ch == 'i' && readingpattern && nlayers >= 3)
- return(unscale(ICODE));
- else if (ch == 'j' && readingpattern && nlayers >= 4)
- return(unscale(JCODE));
- else if (ch == 'k' && readingpattern && nlayers >= 5)
- return(unscale(KCODE));
- else if (ch == '?' && readingpattern)
- return(unscale(qmark));
- intpart = 0.0;
- while (ch >= '0' && ch <= '9')
- {
- intpart = 10.0 * intpart + (ch - '0');
- ch = readch();
- };
- fractpart = 0.0;
- divisor = 1.0;
- if (ch == '.')
- {
- ch = readch();
- while (ch >= '0' && ch <= '9')
- {
- fractpart = fractpart * 10.0 + (ch - '0');
- divisor = divisor * 10.0;
- ch = readch();
- };
- };
- bufferptr = bufferptr - 1; /* unget the character */
- number = sign * (((double) intpart) +
- ((double) fractpart) / ((double) divisor));
- if (op == GT && number > min) return(number);
- else if (op == GE && number >= min) return(number);
- else
- {
- printf("erroneous value: %lf",number);
- if (data == stdin) putchar('\n');
- else printf(" in %c command\n",command);
- readerror = 1;
- return(0.0);
- };
- }
-
- WTTYPE rdr(op,min,command) /* reads double real numbers and converts */
- int op; /* them to 16-bit integers if necessary */
- double min;
- int command;
- {
- double x;
- WTTYPE ix;
-
- x = readreal(op,min,command);
- if (readerror == 1) return(0);
- ix = scale(x);
- if (readerror == 1) return(0);
- return(ix);
- }
-
- double readchar() /* reads data in compressed format */
- {
- readerror = 0;
- ch = readch();
- do {
- switch (ch) {
- case '\n':
- case ' ': ch = readch();
- break;
- case '1': return(1.0);
- case '0': return(0.0);
- case '?': return(unscale(qmark));
- case '*': do {ch = readch();} while(ch != '\n');
- break;
- case 'h': return(unscale(HCODE));
- case 'i': if (nlayers >= 3) return(unscale(ICODE));
- case 'j': if (nlayers >= 4) return(unscale(JCODE));
- case 'k': if (nlayers >= 5) return(unscale(KCODE));
- default: texterror();
- readerror = 1;
- return(0.0);
- }; /* end switch */
- } while (0 == 0);
- }
-
- void printoutunits(layer,printerr) /* prints values of units */
- LAYER *layer;
- int printerr;
- {
- double error, e;
- int counter, i;
- UNIT *u;
- WTTYPE upper, middle, diff;
- PATNODE *target;
-
- upper = scale(1.0) - toler; /* compute whether needed or not */
- middle = scale(0.5);
-
- u = (UNIT *) layer->units;
- if (layer == last) target = (PATNODE *) last->currentpat->pats;
- counter = 0;
- i = 1;
- if (printerr == 0) printf(" ");
- while (u != NULL)
- {
- counter = counter + 1;
- if (outformat == 'r')
- {
- printf("%5.2lf ",unscale(u->oj));
- if (format[i] == counter)
- {
- printf("\n ");
- if (i < maxformat - 1) i = i + 1;
- }
- }
- else if (outformat == 'a' && layer == last)
- {
- diff = target->val - u->oj;
- if (diff < 0) diff = -diff;
- if (diff < toler) putchar('c');
- else if (u->oj > upper) putchar('1');
- else if (u->oj < toler) putchar('0');
- else if (u->oj > target->val) putchar('^');
- else putchar('v');
- if (format[i] == counter)
- {
- putchar(' ');
- if (i < maxformat - 1) i = i + 1;
- }
- }
- else
- {
- if (u->oj > upper) putchar('1');
- else if (u->oj > middle) putchar('^');
- else if (u->oj < toler) putchar('0');
- else putchar('v');
- if (format[i] == counter)
- {
- putchar(' ');
- if (i < maxformat - 1) i = i + 1;
- }
- }
- u = u->next;
- if (layer == last) target = target->next;
- };
- if (printerr == 1)
- {
- error = 0.0;
- u = (UNIT *) layer->units;
- target = (PATNODE *) last->currentpat->pats;
- while (u != NULL)
- {
- e = unscale(target->val - u->oj);
- error = error + e * e;
- u = u->next;
- target = target->next;
- };
- printf(" (%7.5lf)",error);
- };
- printf("\n");
- }
-
- void wrb(wtfile,value,wtsize)
- FILE *wtfile;
- WTTYPE value;
- int wtsize;
- {
- int i;
- unsigned char *charptr, ch2;
-
- charptr = (unsigned char *) &value;
- for (i=1;i<=wtsize;i++)
- {
- ch2 = *charptr;
- putc(ch2,wtfile);
- charptr++;
- };
- }
-
- void saveweights() /* saves weights on the file weights */
- {
- FILE *weights;
- UNIT *u;
- LAYER *layer;
- WTNODE *w;
- WTTYPE wvalue, evalue, dvalue;
-
- weights = fopen("weights","w");
- fprintf(weights,"%d%c",totaliter,wtformat);
- if (wtformat == 'b' || wtformat == 'B') fprintf(weights,"%1d",WTSIZE);
- fprintf(weights," file = %s\n",datafilename);
- layer = start->next;
- while (layer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- wvalue = *(w->weight);
- evalue = *(w->eta);
- dvalue = *(w->olddw);
- #else
- wvalue = w->weight;
- evalue = w->eta;
- dvalue = w->olddw;
- #endif
- if (wtformat == 'r' || wtformat == 'R')
- {
- fprintf(weights,"%16.10lf",unscale(wvalue));
- if (wtformat == 'R')
- {
- fprintf(weights," %16.10lf",unscale(evalue));
- fprintf(weights," %16.10lf",unscale(dvalue));
- };
- putc('\n',weights);
- }
- else /* binary format; uses the least space */
- {
- wrb(weights,wvalue,WTSIZE);
- if (wtformat == 'B')
- {
- wrb(weights,evalue,WTSIZE);
- wrb(weights,dvalue,WTSIZE);
- };
- };
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->next;
- };
- fflush(weights);
- close(weights);
- lastsave = totaliter;
- }
-
- WTTYPE rdb(wtfile,wtsize) /* read binary and convert between sizes */
- FILE *wtfile;
- int wtsize;
- {
- int i;
- double value;
- short ivalue;
- unsigned char *charptr;
-
- if (wtsize == 2) charptr = (unsigned char *) &ivalue;
- else charptr = (unsigned char *) &value;
- for (i=1;i<=wtsize;i++)
- {
- *charptr = (unsigned char) getc(wtfile);
- charptr++;
- };
- if (WTSIZE == 2 && wtsize == 2) return(ivalue);
- else if (WTSIZE == 2 && wtsize == 8) return(scale(value));
- else if (WTSIZE == 8 && wtsize == 8) return(value);
- else if (WTSIZE == 8 && wtsize == 2) return(ivalue / 1024.0);
- }
-
- void restoreweights() /* restore weights from the file weights */
- {
- FILE *weights;
- UNIT *u;
- LAYER *layer;
- WTNODE *w;
- int ch2, fileformat;
- WTTYPE wvalue, evalue, dvalue;
- double temp;
- int wtsize;
-
- weights = fopen("weights","r");
- if (weights == NULL)
- {
- printf("cannot open file weights\n");
- return;
- };
- fscanf(weights,"%d",&totaliter);
- fileformat = getc(weights);
- if (fileformat != wtformat)
- printf("caution: weight format mismatch\n");
- if (fileformat == 'b' || fileformat == 'B')
- {
- wtsize = getc(weights) - '0';
- if (WTSIZE != wtsize)
- printf("caution: weight sizes mismatched\n");
- }
- else wtsize = WTSIZE;
- ch2 = getc(weights); /* skip over the file name */
- while (ch2 != '\n') ch2 = getc(weights);
- layer = start->next;
- while (layer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- if (fileformat == 'r' || fileformat == 'R')
- {
- fscanf(weights,"%lf",&temp);
- wvalue = scale(temp);
- if (fileformat == 'R')
- {
- fscanf(weights,"%lf",&temp);
- evalue = scale(temp);
- fscanf(weights,"%lf",&temp);
- dvalue = scale(temp);
- };
- }
- else
- {
- wvalue = rdb(weights,wtsize);
- if (fileformat == 'B')
- {
- evalue = rdb(weights,wtsize);
- dvalue = rdb(weights,wtsize);
- };
- };
- #ifdef SYMMETRIC
- *(w->weight) = wvalue;
- if (fileformat == 'R' || fileformat == 'B')
- {
- *(w->olddw) = dvalue;
- *(w->eta) = evalue;
- }
- else *(w->olddw) = 0;
- #else
- w->weight = wvalue;
- if (fileformat == 'R' || fileformat == 'B')
- {
- w->olddw = dvalue;
- w->eta = evalue;
- }
- else w->olddw = 0;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->next;
- };
- close(weights);
- }
-
- void printweights(u) /* print the weights leading into unit u */
- UNIT *u;
-
- {WTNODE *w;
- UNIT *bunit;
- WTTYPE value;
- #ifdef INTEGER
- int sum, input;
- #else
- double sum, input;
- #endif
- w = (WTNODE *) u->wtlist;
- sum = 0;
- printf("layer unit unit value weight input from unit\n");
- while (w != NULL)
- {
- bunit = (UNIT *) w->backunit;
- #ifdef SYMMETRIC
- value = *(w->weight);
- #else
- value = w->weight;
- #endif
- input = value * bunit->oj;
- #ifdef INTEGER
- input = input / 1024;
- #endif
- sum = sum + input;
- printf("%3d ",bunit->layernumber);
- if (bunit->unitnumber == 32767) printf(" t ");
- else printf("%4d ",bunit->unitnumber);
- printf("%10.5lf %10.5lf ",unscale(bunit->oj),unscaleint(value));
- printf("%18.5lf\n",unscaleint(input));
- w = w->next;
- };
- printf(" ");
- printf("sum = %9.5lf\n\n",unscaleint(sum));
- }
-
- void help()
- {
- printf("\n");
- ch = readch();
- while (ch == ' ' && ch != '\n') ch = readch();
- switch(ch) {
- default : printf("for help type h followed by letter of command\n");
- break;
- case '?': printf("? prints program status and parameters.\n");
- break;
- case '*': printf("* at the beginning of a line makes the line a");
- printf(" comment.\n");
- break;
- case '!': printf("Enter UNIX commands after the !.\n");
- break;
- case 'A': printf("A is used to set the details of the algorithm. ");
- printf("One or more\nof the following commands can go on ");
- printf("the same line as the 'A':\n\n");
- printf("a p sets the piecewise linear activation function\n");
- printf("a s sets the smooth activation function (rbp only).");
- printf("\n\nb + will backpropagate errors");
- printf(" even when a unit is close to it's target.\n");
- printf("b - will not backpropagate errors when a");
- printf(" unit is close to it's target.\n\n");
- printf("D <real> will set the sharpness of the sigmoid to");
- printf(" <real>.\n\n");
- printf("d d will use the derivative from the ");
- printf("differential step size algorithm.\n");
- printf("d f uses Fahlman's derivative.\n");
- printf("d o uses the original derivative.\n\n");
- printf("l <real> limits the weights to between +<real> ");
- printf("and -<real>. The default\n is to not check");
- printf(". To reset to not check, use l 0.\n\n");
- printf("s <int> will skip patterns that have been learned");
- printf(" for <int> iterations.\n\n");
- printf("u c will use the continuous update method.\n");
- printf("u C will use the continuous update method with the");
- printf(" differential step size etas.\n");
- printf("u d will use the differential step size update.\nu ");
- printf("j will use Jacob's delta-bar delta update method.\n");
- printf("u o will use the original weight update method.\n");
- break;
- case 'a': printf("a <real> sets the momentum parameter, alpha, to");
- printf(" <real>.\n");
- break;
- case 'b': printf("b <int1> <int2> ... <int10> puts a carriage return");
- printf(" after each <inti>\nvalues when the output format");
- printf(" is real and inserts a blank after each <inti>\n");
- printf("value if the format is condensed.\n");
- break;
- case 'C': printf("C clears the network and other relevant parameters");
- printf(" so the problem can be re-run\nwith different");
- printf(" initial weights. Added hidden units are not");
- printf(" removed.\n");
- break;
-
- #ifndef SYMMETRIC
- case 'c': printf("c <int1> <int2> <int3> <int4>\n");
- printf("Adds a connection from layer <int1> unit <int2>\n");
- printf("to layer <int3> unit <int4>.\n");
- break;
- #endif
-
- case 'E': printf("E1 echos input; E0 turns off echo of input.\n");
- break;
- case 'e': printf("e <real1> <real2> sets eta, the learning rate, to");
- printf(" <real1> and if\n");
- printf("<real2> is present, eta2 of the differential");
- printf(" step size algorithm\nis set to <real2>. If ");
- printf("<real2> is not present, eta2 = eta / 10.\n");
- break;
- case 'f': printf("f is used to set the input and output formats for");
- printf(" data.\nOne or more of the following commands can");
- printf(" go on the line:\n\n");
- printf("i c will read values in patterns as compressed.\n");
- printf("i r will read values in patterns are reals.\n\n");
- printf("o a will write node values as analog compressed.\n");
- printf("o c will write node values as compressed.\n");
- printf("o r will write node values as real.\n\n");
- printf("s + will summarize learning status instead of");
- printf(" listing each pattern.\n");
- printf("s - will not summarize learning status and will");
- printf(" list each pattern.\n\n");
- printf("w b will write the weights to the file weights as");
- printf(" binary values.\n");
- printf("w B will write the weights and weight changes and");
- printf(" etas as binary.\n");
- printf("w r will write the weights to the file weights as");
- printf(" real values.\n");
- printf("w R will write the weights and weight changes and");
- printf(" etas as real values.\n");
- break;
-
- #ifndef SYMMETRIC
- case 'H': printf("H <int> <real> adds a hidden unit to layer <int>\n");
- printf("Weights are initialized to between -<real> and");
- printf(" <real>.\n");
- break;
- #endif
-
- case 'h': printf("h <letter> gives help for command <letter>.\n");
- break;
- case 'i': printf("i <filename> takes commands from <filename>.\n");
- break;
- case 'j': printf("j is used to set parameters for Jacob's");
- printf(" delta-bar-delta method.\nOne or more of the");
- printf(" following commands can go on the line:\n\n");
- printf("d <real> sets the decay factor to <real>.\n");
- printf("e <real> sets the initial eta value to <real>.\n");
- printf("k <real> sets kappa to <real>.\n");
- printf("m <real> limits the maximum value of each eta to");
- printf(" <real>.\nt <real> sets theta to <real>.\n");
- break;
- case 'k': printf("k <real1> <real2> decreases all the weights in the ");
- printf("network whose values\nare greater than <real1> by a");
- printf(" random amount between 0 and <real2>.\nWeights ");
- printf("less than -<real1> are increased by an amount ");
- printf("between 0 and <real2>.\nIf <real1> = 0.0, and a ");
- printf("weight = 0.0 then the weight is changed to\na ");
- printf("value between -<real2> and +<real2>.\n");
- break;
- case 'l': printf("l <int> prints values of nodes on layer <int>.\n");
- break;
- case 'm': printf("m <int1> <int2> ... <intn> makes a network with\n");
- printf("<int1> units in the first layer, <int2> units in\n");
- printf("the second layer, ... , <intn> units in the nth");
- printf(" layer\n");
- break;
- case 'n': printf("n <int> <in1> <out1> ... <ini> <outi> ... <inN> ");
- printf("<outN>\nreplaces all patterns with <int> new ones");
- printf(".\n<ini> patterns go on the input units.\n");
- printf("<outi> patterns go on the output units.\n");
- break;
- case 'o': printf("o a outputs node values in analog compressed form.");
- printf("\no c outputs node values in compressed form.\n");
- printf("o r outputs node values as double.\n");
- break;
- case 'P': printf("P lists the outputs for all patterns.\n");
- printf("P <int> gives the output for pattern <int>.\n");
- break;
- case 'p': printf("p <pat> submits the pattern, <pat>, to the input");
- printf(" units.\n");
- break;
- case 'Q': printf("Q <real> sets the value of ? in compressed input");
- printf(" to be the value, <real>.\n");
- break;
- case 'q': printf("q ends the program.\n");
- break;
- case 'R': printf("R reloads weights from the file weights.\n");
- break;
- case 'r': printf("r <int1> <int2> runs <int1> iterations thru the ");
- printf("patterns. If <int2> is\npresent, the patterns are ");
- printf("printed (or summarized) every <int2> iterations.\n");
- break;
- case 'S': printf("S <int> saves the weights on the file ");
- printf("weights every <int> iterations.\nS saves the ");
- printf("weights immediately.\n");
- break;
- case 's': printf("s <int> sets the random number seed to <int>.\n");
- break;
-
- #ifdef SYMMETRIC
- case 'T': printf("T <real> freezes all threshold weights at <real>.\n");
- break;
- #endif
-
- case 't': printf("t <real> sets <real> as the tolerance used in ");
- printf("printing compressed values\nand in checking for");
- printf(" complete learning.\n");
- break;
- #ifndef SYMMETRIC
- case 'W': printf("W <real> removes links whose weights are less than ");
- printf("the absolute value\nof <real>, except links to ");
- printf("threshold units are not removed.\n");
- break;
- #endif
-
- case 'w': printf("w <int1> <int2> ");
- printf("prints weights into unit <int2> in layer <int1>.\n");
- break;
- case 'x': printf("x <int1> <in1> <out1> ... <ini> <outi> ... <inN>");
- printf(" <outN>\nadds the extra <int1> patterns.\n");
- printf("<in1> patterns go on the input units.\n");
- printf("<out1> patterns go on the output units.\n");
- break;
- }; /* end switch */
- putchar('\n');
- }
-