/*
 * Created on Nov 22, 2004
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package jone;

/**
 * @author brian
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
class NeuralNetTBox
{
	/* creates constants for the different activation functions */
	public final static int tansig = 0;
	public final static int logsig = 1;
	public final static int purelin = 2;
	public final static int hardlim = 3;
	public final static int hardlims = 4;
	public final static int satlin = 5;
	public final static int satlins = 6;
	
	/* prints a double with d characters 
     */
    static String printDouble(double a, int d)
    {
    	String x = a + "      ";
    	int l = x.length() > d ? d : x.length();
    	return x.substring(0,l);
    }
    
	/* outputs an approximation to the tansig function at x */
    static double tansig(double x)
    {
    	/* this numerical approximation is sufficiently accurate and is much faster
    	 * than calling the tansig math routine
    	 */
    	return 2/(1+Math.exp(-2*x))-1;	
    }
    /* evaluates x at the derivative of tansig, dtansig = 1 - (tansig(x))^2
     */
    static double tansigd(double x)
    {
    	/* the derivative of tansig is simply 1-tansig^2(x) as shown in class
    	 */
    	double X = tansig(x);
    	return (1-X*X);
    }
    
    /* computes the activation function at x */
    static double f(double x, int func, boolean training)
    {
    	
    	if(training && (func == satlin || func == hardlim))
    		func = logsig;
    	if(training && (func == satlins || func == hardlims))
    		func = tansig;
    	
    	switch (func)
		{
    		case tansig : return tansig(x); 
    		case logsig : return logsig(x);
    		case purelin : return x;
    		case hardlim : return hardlim(x);
    		case hardlims : return hardlims(x);
    		case satlin : return satlin(x);
    		case satlins : return satlins(x);
    		    	
		}
    	return tansig(x);
    }
    
    /* computes the derivate for the activation function at x */
    static double df(double x, int func, boolean training)
    {
    	if(training && (func == satlin || func == hardlim))
    		func = logsig;
    	if(training && (func == satlins || func == hardlims))
    		func = tansig;
    	switch (func)
		{
    		case tansig : return tansigd(x); 
    		case logsig : return logsigd(x);
    		case purelin : return 1;
    		case hardlim : return hardlim(x);
    		case hardlims : return hardlims(x);
    		case satlin : return satlin(x);
    		case satlins : return satlins(x);
    		    	
		}
    	return tansig(x);
    }
    
    /* converts the activation function name to a corresponding 
     * constant */
    static int convertType(String type)
    {
    	if(type.equals("tansig"))
    		return tansig;
    	if(type.equals("logsig"))
    		return logsig;
    	if(type.equals("purelin"))
    		return purelin;
    	if(type.equals("hardlim"))
    		return hardlim;
    	if(type.equals("hardlims"))
    		return hardlims;
    	if(type.equals("satlin"))
    		return satlin;
    	if(type.equals("satlins"))
    		return satlins;
    	return tansig;
    }
    
    /* evaluates logsig at x */
    static double logsig(double x)
    {
    	return (1.0/(1.0+Math.exp(-x)));   	
    }
    
	/* evaluates x at the derivative of logsig */
    static double logsigd (double x)
    {
    	double lsig = logsig(x);
    	return lsig*(1.0-lsig);
    	
    }
    
    /* computes the hardlim of x, if x > 0, return 1 otherwise
     * return -1 */
    static double hardlim(double x)
        {
            if(x >= 0.0) 
            {
                return 1;
            }
            else 
            {
                return 0;
            }
            
        }
    
    /* computes the hardlim of x, if x > 0, return 1 otherwise
     * return -1 */
    static double hardlims(double x)
        {
            if(x >= 0.0) 
            {
                return 1;
            }
            else 
            {
                return -1;
            }
            
        }
    
    static double [] applyFAddBias(double [] v, int type, boolean t)
    {
    	double [] nextinputs = new double[v.length+1];
    	for(int i = 0; i < v.length; i++) {
    		nextinputs[i] = f(v[i],type,t);
    	}
    	nextinputs[nextinputs.length-1] = -1;
    	return nextinputs;
    }
    /* returns -1 if n < -1, 1 if n > 1, otherwise returns n */
    static double satlins(double x)
    {
    	if( x <= -1)
    		return -1;
    	if(x >= 1)
    		return 1;
    	
    	return x;
    	
    }
    
    /* returns 0 if n < 0, 1 if n > 1, otherwise returns n */
    static double satlin(double x)
    {
    	if( x <= 0)
    		return 0;
    	if(x >= 1)
    		return 1;
    	
    	return x;
    }
   
    /* prints a vector */
    static String printVector(double [] a, int n)
    {
    	String s = "";;
        for(int i = 0; i < n; i++)
        {
            s += NeuralNetTBox.printDouble(a[i],6) + " ";
        }
        return s;
    }
    
    /* multiplies vector p by matrix m with columns n, the number of 
     * elements in p must be <= the number of rows in m */         
    static double [] multvectorbymatrix(double [][] m, double [] p, int n)
    {
    	/* multiplies each input by the hidden neuron's weight for than input, 
    	 * matrix is inputs by hidden neurons
    	 */
    	double [] dot = new double[n];
    	for(int i = 0; i < n; i++) {
    		dot[i] = 0;
    		for(int j = 0; j < p.length; j++)
    			dot[i] += p[j]*m[j][i]; //check
    	}
    	return dot;  	
    }
    
    /* evaluates purelin at x */
    static double purelin(double x)
    {
    	return x;
    }
}
