
/*
 * Copyright (1987) Jeff Elman.  University of California, San Diego
 * This software may be redistributed without charge; this notice
 * should be preserved.
 */

/*
 * activate2.c
 *	to be used when network is configured with
 *	explicit matrix
 *
 */

#include <stdio.h>
#include <math.h>
#include <sys/file.h>
#include "defs.h"

extern float	*exp_array;
extern float	exp_mult;
extern long	exp_add;

activate2()
{
	extern	int debug;
	extern	double exp();
	extern	float length();
	extern	int **condown;
	extern	float **d_tokenp;
	extern	float **weightp;
	extern	float *biasp;
	extern	float *nodep;
	extern	float *deltap;
	extern	float **layerp;
	extern	float decays[];
	extern	float *delta_x;
	extern	float eps;
	extern	float alpha;
	extern	float beta;
	extern	int nobias;
	extern	int bipolar;
	extern	int pcomp;
	extern	int all_linear;
	extern	int numin;
	extern	int numtotal;
	extern	int cur_token;
	extern	int rbp;
	register float net;
	register int i;
	register float *np;
	register float *lp;
	register int *cdp;
	register int **cdpp;
	float 	I;

	if (rbp == 0) {
		/*
		 * stick external input into input nodes
		 */
		for (i=0, np=nodep,lp= *layerp; i<numin; i++,np++,lp++) {
			*np = *lp;
		}
		/*
		 * go thru nodes and get input to them; 
		 */
		for (i=numin,cdpp=condown+numin; i<numtotal; i++, cdpp++) {
			if (decays[i] == 0)
				net = 0.0;
			else
				net = decays[i] * *(nodep+i);
			for (cdp= *cdpp; *cdp != -1; cdp++) {
				net += *(*(weightp+*cdp)+i) * *(nodep+*cdp);
			}
			/*
			 * if nobias == 0, we do use bias
			 */
			if (nobias==0)
				net += *(biasp+i);
			if (all_linear){
				if (net < -10.0)
					net = -10.0;
				else if (net > 10.0)
					net = 10.0;
				*(nodep+i) = net;
			} else {
				if (net < -10.0)
					net = -10.0;
				else if (net > 10.0)
					net = 10.0;
				*(nodep+i) = 1.0 / (1.0 + EXP(0.0 - net));
			}
			if (bipolar)
				*(nodep+i) = 2.0 * *(nodep+i) - 1.0;
		}
	} else if (rbp == 1) {
		/*
		 * This is a bit different than in the
		 * case of non-rbp.  
		 * 	1. initialize all nodes to 0.5
		 *	2. foreach node, collect internode input
		 *	3. threshold and subject to logistic
		 *	4. add in external input and (decayed) old value
		 *	5. add result into unit's new value 
		 */
		/* 
		 * initialize all nodes to 0.5
		 */
		for (i=0, np=nodep; i<numtotal; i++,np++) {
			*np = 0.5;
		}
		do {
		    if (debug > 5)
			fprintf(stdout, "I [%d]: ", cur_token);
		    for (i=0, cdpp=condown; i<numtotal; i++, cdpp++) {
		    	    net = 0.0;
			    /*
			     * get input from other units...
			     */
			    for (cdp= *cdpp; *cdp != -1; cdp++) {
				    net += *(*(weightp+*cdp)+i) * *(nodep+*cdp);
			    }
			    /* 
			     * get input from bias unit...
			     */
			    net += *(biasp+i);
			    if (net < -10.0)
				    net = -10.0;
			    else if (net > 10.0)
				    net = 10.0;
			    net = 1.0 / (1.0 + EXP(0.0 - net));
			    if (bipolar)
				    net = 2.0 * net - 1.0;
			    I = *(*(d_tokenp+cur_token)+i);
			    if (I <= -999999999.)
				I = 0.0;
		    if (debug >5)
				fprintf(stdout, "%f ", I);
			    *(delta_x+i) = (-alpha* *(nodep+i))+(beta*net)+I;
			    *(nodep+i) += *(delta_x+i);
		    }
		    if (debug > 5)
			    fprintf(stdout, "\n");
		} while (length(delta_x, numtotal) > eps);
	} 
}

float
length(vector, size)
	float	*vector;
	int	size;
{
	double	ss;
	float	*vp;
	register int i;

	vp = vector;
	ss = 0.0;
	for (i=0, vp = vector; i<size; i++, vp++)
		ss += *vp * *vp;
	return (float) pow(ss, 0.5);
}
