'/
ACTIVATION FUNCTIONS AND THEIR FIRST DERIVATIVES FOR ANnet FUNCTION

This script contains the activation functions and their derivatives to 
  be used by the ANnet function.

Specifications:
f()  --> Function: returns the value of the activation function
fd() --> Function: returns the value of the 1st derivative of the 
                   activation funtion
fn   --> The activation function name
a    --> Parameter a (optional)
b    --> Parameter b (optional)

Author: Arthur Hrast Essenfelder
E-mail: arthur.essenfelder@unive.it

Version: 1.0
Last update on: 04/12/2015
/'



#Importing Packages ----------------------------------------------------
#library(pracma);
#-----------------------------------------------------------------------



#Activation Function ---------------------------------------------------
f = function(Input, activation.function.name, 
             parameter.a, parameter.b) {
  
  #Get values
  fn = activation.function.name;
  X  = Input;
  
  #Check for missing arguments
  if (missing(parameter.a)) {
    if (fn == "signum") { a = 1.; }
    if (fn == "linear") { a = 1.; }
    if (fn == "logsig") { a = 1.; }
    if (fn == "tanh")   { a = 1.7159; }
  } else { a = as.double(parameter.a); }
  if (missing(parameter.b)) {
    if (fn == "signum") { b = 1.; }
    if (fn == "linear") { b = 1.; }
    if (fn == "logsig") { b = 1.; }
    if (fn == "tanh")   { b = 0.6667; }
  } else { b = as.double(parameter.b); }
  
  #Compute the function
  if      (fn == "signum") { f = ifelse(X > 0., X/X, -X/X);
                             f = ifelse(X == 0., 0./X, f); }
  else if (fn == "linear") { f = X; } 
  else if (fn == "logsig") { f = 1./(1.+exp(-a*X)); }
  else if (fn == "tanh")   { f = a*tanh(b*X); }
  
  return(f);
  
}
#-----------------------------------------------------------------------



#Activation Function - First Derivative --------------------------------
fd = function(Input, activation.function.name, 
              parameter.a, parameter.b) {
  
  #Get values
  fn = activation.function.name;
  X  = Input;
  
  #Check for missing arguments
  if (missing(parameter.a)) {
    if (fn == "signum") { a = 1.; }
    if (fn == "linear") { a = 1.; }
    if (fn == "logsig") { a = 1.; }
    if (fn == "tanh")   { a = 1.7159; }
  } else { a = as.double(parameter.a); }
  if (missing(parameter.b)) {
    if (fn == "signum") { b = 1.; }
    if (fn == "linear") { b = 1.; }
    if (fn == "logsig") { b = 1.; }
    if (fn == "tanh")   { b = 0.6667; }
  } else { b = as.double(parameter.b); }
  
  #Compute the function
  if      (fn == "signum") { fd = ifelse(X == 0., X/X, 0./X); }
  else if (fn == "linear") { fd = X/X; } 
  else if (fn == "logsig") { fd = a*(1./(1.+exp(-a*X))/
                                    (1-(1./(1.+exp(-a*X))))); }
  else if (fn == "tanh")   { fd = a*b*(1-tanh(b*X)^2); }
  
  # From Haykin
  #else if (fn == "linear") { fd = X; } 
  #else if (fn == "logsig") { fd = a*X*(1.-X); }
  #else if (fn == "tanh")   { fd = (a/b)*(a-X)*(a+X); }
  
  # else if (fn == "logsig") { fd = a*(plogis(X, scale=1/a)/
  #                                      (1-plogis(X, scale=1/a))); }

  return(fd);
  
}
#-----------------------------------------------------------------------