home *** CD-ROM | disk | FTP | other *** search
- /* *********************************************************** */
- /* file int.c: Contains the network evaluation and weight */
- /* adjustment procedures for the integer versions */
- /* bp and sbp. */
- /* */
- /* Copyright (c) 1990 by Donald R. Tveter */
- /* */
- /* The code here has been optimized for use with the Motorola */
- /* MC 68010 processor and version 3.5 of the UNIX (tm) PC */
- /* C compiler where UNIX is a trademark of Bell Laboratories. */
- /* *********************************************************** */
-
- #include "ibp.h"
- #include <stdio.h>
-
- extern WTTYPE alpha;
- extern char backprop;
- extern WTTYPE D;
- extern WTTYPE decay;
- extern char deriv;
- extern WTTYPE eta;
- extern WTTYPE eta2;
- extern WTTYPE etamax;
- extern WTTYPE kappa;
- extern LAYER *last;
- extern LAYER *start;
- extern WTTYPE theta1;
- extern WTTYPE theta2;
- extern WTTYPE toler;
- extern int totaldiff;
- extern char update;
-
- void forward() /* computes unit activations */
- {
- register WTNODE *w;
- register UNIT *u;
- register UNIT *predu;
- LAYER *layer;
- register int sum;
- register int x;
- register short fract;
- register short val;
- register int intpart;
-
- layer = start->next;
- while (layer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- sum = 0;
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- predu = (UNIT *) w->backunit;
- #ifdef SMART
- # ifdef SYMMETRIC
- sum = sum + (*(w->weight) * predu->oj) / 1024;
- # else
- sum = sum + (w->weight * predu->oj) / 1024;
- # endif
- #else
- # ifdef SYMMETRIC
- x = (*(w->weight) * predu->oj);
- # else
- x = w->weight * predu->oj;
- # endif
- if (x >= 0) sum = sum + (x >> 10);
- else sum = sum - ( (-x) >> 10);
- #endif
- w = w->next;
- };
- sum = (D * sum) / 1024;
- if (sum > 0) x = sum; else x = -sum;
- intpart = x >> 10;
- fract = x - (intpart << 10);
- switch (intpart)
- {
- case 0: val = 512 + ((237 * fract) >> 10); /* 0 <= x < 1 */
- break;
- case 1: val = 748 + ((153 * fract) >> 10); /* 1 <= x < 2 */
- break;
- case 2: val = 901 + ((73 * fract) >> 10); /* 2 <= x < 3 */
- break;
- case 3:
- case 4: val = 976 + (((x - 3072) * 20) >> 10); /* 3 <= x < 5 */
- break;
- default: val = 1024; /* x >= 5 */
- };
- if (sum < 0) u->oj = 1024 - val; else u->oj = val;
- u = u->next;
- };
- layer = layer->next;
- };
- };
-
- short backoutput() /* computes weight changes from the output layer */
- {
- register short deltaj;
- register int temp;
- register short temp2;
- register short temp3;
- register short adiff;
- register UNIT *bunit;
- register WTNODE *w;
- register UNIT *u;
- register PATNODE *t;
- register short notclose;
-
- notclose = last->unitcount;
- u = (UNIT *) last->units;
- t = (PATNODE *) last->currentpat->pats;
- while (u != NULL)
- {
- temp3 = u->oj;
- temp2 = t->val - temp3;
- if (temp2 > 0) adiff = temp2; else adiff = -temp2;
- if (adiff < toler) notclose = notclose - 1;
- totaldiff = totaldiff + adiff;
- if (adiff >= toler || backprop) /* then compute errors */
- {
- if (deriv == 'd') /* diff. step size method */
- deltaj = temp2;
- else if (deriv == 'f') /* Fahlman's derivative */
- {
- temp = temp2 * (104448 + temp3 * ((short)(1024 - temp3)));
- if (temp > 0) deltaj = (temp + 524288) >> 20;
- else deltaj = -((524288 - temp) >> 20);
- }
- else /* the derivative in the original formula */
- {
- temp = temp2 * (temp3 * ((short)(1024 - temp3)));
- if (temp > 0) deltaj = (temp + 524288) >> 20;
- else deltaj = -((524288 - temp) >> 20);
- }
- w = (WTNODE *) u->wtlist;
- #ifdef SYMMETRIC
- while (w->next != NULL) /* skips threshold unit at end */
- #else
- while (w != NULL)
- #endif
- {
- bunit = (UNIT *) w->backunit;
- #ifdef SYMMETRIC
- *(w->total) = *(w->total) + deltaj * bunit->oj;
- #else
- w->total = w->total + deltaj * bunit->oj;
- if (bunit->layernumber > 1)
- bunit->error = bunit->error + deltaj * w->weight;
- #endif
- w = w->next;
- }
- };
- u = u->next;
- t = t->next;
- };
- return(notclose);
- }
-
- #ifndef SYMMETRIC
-
- void backinner() /* Computes slopes and passes back */
- { /* errors from hidden layers. */
- register short deltaj;
- register int temp;
- register short temp3;
- register UNIT *bunit;
- register WTNODE *w;
- register UNIT *u;
- LAYER *layer;
-
- layer = last->backlayer;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- temp3 = u->oj;
- if (deriv == 'f') /* Fahlman's derivative */
- temp = (((short)((temp3*((short)(1024-temp3))+512) >> 10))
- + 102) * u->error;
- else /* either for the original or diff. step size */
- temp = ((short)((temp3*((short)(1024-temp3))+512) >> 10))
- * u->error;
- if (temp > 0) deltaj = (temp + 524288) >> 20;
- else deltaj = -((524288 - temp) >> 20);
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- bunit = (UNIT *) w->backunit;
- w->total = w->total + deltaj * bunit->oj;
- if (bunit->layernumber > 1)
- bunit->error = bunit->error + deltaj * w->weight;
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- #endif
-
- void updatej() /* Jacob's delta-bar-delta method for weight updates */
- {
- register short rkappa;
- register short temp2;
- register short dbarm1;
- register short rdecay;
- register int temp;
- register UNIT *u;
- register WTNODE *w;
- LAYER *layer;
-
- /* w->olddw is used for delta-bar minus 1 */
-
- rkappa = kappa;
- rdecay = decay;
- layer = last;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
- {
- if (*(w->total) > 0) temp2 = (*(w->total) + 512) >> 10;
- else temp2 = -((512 - *(w->total)) >> 10);
- dbarm1 = *(w->olddw);
- temp = theta2 * temp2 + theta1 * dbarm1;
- if (temp > 0) *(w->olddw) = (temp + 512) >> 10;
- else *(w->olddw) = -((512 - temp) >> 10);
- if ((temp2 > 0) && (dbarm1 > 0))
- *(w->eta) = *(w->eta) + rkappa;
- else if ((temp2 < 0) && (dbarm1 < 0))
- *(w->eta) = *(w->eta) + rkappa;
- else if ((temp2 > 0) && (dbarm1 < 0))
- *(w->eta) = (*(w->eta) * rdecay) >> 10;
- else if ((temp2 < 0) && (dbarm1 > 0))
- *(w->eta) = (*(w->eta) * rdecay) >> 10;
- if (*(w->eta) > etamax) *(w->eta) = etamax;
- temp = temp2 * *(w->eta);
- if (temp > 0) temp2 = (temp + 512) >> 10;
- else temp2 = -((512 - temp) >> 10);
- *(w->weight) = *(w->weight) + temp2;
- };
- #else
- if (w->total > 0) temp2 = (w->total + 512) >> 10;
- else temp2 = -((512 - w->total) >> 10);
- dbarm1 = w->olddw;
- temp = theta2 * temp2 + theta1 * dbarm1;
- if (temp > 0) w->olddw = (temp + 512) >> 10;
- else w->olddw = -((512 - temp) >> 10);
- if (temp2 > 0 && dbarm1 > 0) w->eta = w->eta + rkappa;
- else if (temp2 < 0 && dbarm1 < 0) w->eta = w->eta + rkappa;
- else if (temp2 > 0 && dbarm1 < 0)
- w->eta = (w->eta * rdecay) >> 10;
- else if (temp2 < 0 && dbarm1 > 0)
- w->eta = (w->eta * rdecay) >> 10;
- if (w->eta > etamax) w->eta = etamax;
- temp = temp2 * w->eta;
- if (temp > 0) temp2 = (temp + 512) >> 10;
- else temp2 = -((512 - temp) >> 10);
- w->weight = w->weight + temp2;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- void updateo() /* update weights for the original method */
- { /* and the differential step size algorithm */
- register short reta;
- register short ralpha;
- register int temp;
- register UNIT *u;
- register WTNODE *w;
- LAYER *layer;
-
- ralpha = alpha;
- reta = eta;
- layer = last;
- while (layer->backlayer != NULL)
- {
- if (layer != last && update == 'd') reta = eta2;
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- #ifdef SYMMETRIC
- if (((UNIT *) w->backunit)->unitnumber > u->unitnumber)
- {
- if (*(w->total) > 0)
- temp = ((*(w->total) + 512) >> 10) * reta
- + ralpha * *(w->olddw);
- else temp = -((512 - *(w->total)) >> 10) * reta
- + ralpha * *(w->olddw);
- if (temp > 0) *(w->olddw) = (temp + 512) >> 10;
- else *(w->olddw) = -((512 - temp) >> 10);
- *(w->weight) = *(w->weight) + *(w->olddw);
- };
- #else
- if (w->total > 0)
- temp = ((w->total + 512) >> 10) * reta + ralpha * w->olddw;
- else
- temp = -((512 - w->total) >> 10) * reta + ralpha * w->olddw;
- if (temp > 0) w->olddw = (temp + 512) >> 10;
- else w->olddw = -((512 - temp) >> 10);
- w->weight = w->weight + w->olddw;
- #endif
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- short cbackoutput() /* The continuous update version */
- { /* of back-propagation */
- register short deltaj;
- register int etadeltaj;
- register int temp;
- register int temp2;
- register short temp3;
- register short adiff;
- register UNIT *bunit;
- register WTNODE *w;
- register UNIT *u;
- register PATNODE *t;
- register short ralpha;
- register short notclose;
-
- ralpha = alpha;
- notclose = last->unitcount;
- u = (UNIT *) last->units;
- t = (PATNODE *) last->currentpat->pats;
- while (u != NULL)
- {
- temp3 = u->oj;
- temp2 = t->val - temp3;
- if (temp2 > 0) adiff = temp2; else adiff = -temp2;
- if (adiff < toler) notclose = notclose - 1;
- totaldiff = totaldiff + adiff;
- if (adiff >= toler || backprop)
- {
- if (deriv == 'd') /* the differential step size method */
- deltaj = temp2;
- else if (deriv == 'f') /* Fahlman's derivative */
- { /* deltaj = (t->val - u->oj) * [0.1 + u->oj*(1.0 - u->oj)] */
- temp = temp2 * (104448 + temp3 * ((short)(1024 - temp3)));
- if(temp > 0) deltaj = (temp + 524288) >> 20;
- else deltaj = -((524288 - temp) >> 20);
- }
- else /* the original derivative */
- { /* deltaj = (t->val - u->oj) * u->oj * (1.0 - u->oj) */
- temp = temp2 * (temp3 * ((short)(1024 - temp3)));
- if(temp > 0) deltaj = (temp + 524288) >> 20;
- else deltaj = -((524288 - temp) >> 20);
- };
- etadeltaj = deltaj * eta;
- w = (WTNODE *) u->wtlist;
- #ifdef SYMMETRIC
- while (w->next != NULL)
- #else
- while (w != NULL)
- #endif
- { /* get a slope for each weight */
- bunit = (UNIT *) w->backunit;
- temp = etadeltaj * bunit->oj;
- if(temp > 0) temp = (temp + 524288) >> 20;
- else temp = -((524288 - temp) >> 20);
- #ifdef SYMMETRIC
- temp2 = ralpha * *(w->olddw);
- #else
- temp2 = ralpha * w->olddw;
- #endif
- if (temp2 > 0) temp3 = temp + ((temp2 + 512) >> 10);
- else temp3 = temp - ((512 - temp2) >> 10);
- #ifdef SYMMETRIC
- *(w->olddw) = temp3;
- #else
- w->olddw = temp3;
- #endif
- /* w->weight = w->weight + w->olddw */
- #ifdef SYMMETRIC
- temp3 = *(w->weight) + temp3;
- *(w->weight) = temp3;
- #else
- temp3 = w->weight + temp3;
- w->weight = temp3;
- if (bunit->layernumber > 1)
- bunit->error = bunit->error + deltaj * temp3;
- #endif
- w = w->next;
- }
- }
- u = u->next;
- t = t->next;
- }
- return(notclose);
- }
-
- #ifndef SYMMETRIC
-
- void cbackinner() /* Same as cbackoutput, except errors are */
- { /* calculated differently */
- register short deltaj;
- register int etadeltaj;
- register int temp;
- register int temp2;
- register short temp3;
- register short reta;
- register short ralpha;
- register UNIT *bunit;
- register WTNODE *w;
- register UNIT *u;
- LAYER *layer;
-
- if (update == 'C') reta = eta2; else reta = eta;
- ralpha = alpha;
- layer = last->backlayer;
- while (layer->backlayer != NULL)
- {
- u = (UNIT *) layer->units;
- while (u != NULL)
- {
- temp3 = u->oj;
- if (deriv == 'f') /* Fahlman's derivative */
- temp = (((temp3 * ((short)(1024 - temp3)) + 512) >> 10) + 102)
- * u->error;
- else /* diff. step size and original derivative */
- temp = ((temp3 * ((short)(1024 - temp3)) + 512) >> 10)
- * u->error;
- if (temp > 0) deltaj = (temp + 524288) >> 20;
- else deltaj = -((524288 - temp) >> 20);
- etadeltaj = reta * deltaj;
- w = (WTNODE *) u->wtlist;
- while (w != NULL)
- {
- bunit = (UNIT *) w->backunit;
- temp = etadeltaj * bunit->oj;
- if (temp > 0) temp = (temp + 524288) >> 20;
- else temp = -((524288 - temp) >> 20);
- temp2 = ralpha * w->olddw;
- if (temp2 > 0) temp3 = temp + ((temp2 + 512) >> 10);
- else temp3 = temp - ((512 - temp2) >> 10);
- w->olddw = temp3;
- temp3 = w->weight + temp3;
- w->weight = temp3;
- if (bunit->layernumber > 1)
- bunit->error = bunit->error + deltaj * temp3;
- w = w->next;
- };
- u = u->next;
- };
- layer = layer->backlayer;
- };
- }
-
- #endif
-