/* 
 * Thomas Pantzer: neuronal.cc, v0.4.7  8.6.99 16:32 
 * 
 * 
 * Copyright 1997 by Thomas Pantzer
 * 
 * Permission to use, copy, modify, and distribute this software for noncommercial 
 * use and without fee is hereby granted, provided that the above copyright notice 
 * appear in all copies and that both that copyright notice and this permission 
 * notice appear in supporting documentation, and that the name of the Author not be 
 * used in advertising or publicity pertaining to distribution of the software 
 * without specific, written prior permission. The Author makes no representations about
 * the suitability of this software for any purpose.  It is provided "as is" 
 * without expressed or implied warranty. 
 * 
 * 
 * pantec@aix520.informatik.uni-leipzig.de   (Thomas Pantzer) 
 * 
 */


// Output from p2c 1.21alpha-07.Dec.93, the Pascal-to-C translator
// From input file "/home/pantec/praktika/roboter/neuronal/neuronal.p"


// #include <p2c/p2c.h>

#include <stdio.h>
#include <string.h>
#include <math.h>

#include "copyright.h"

#define NEURONAL_G
#include "neuronal.h"

#ifdef hpux
 #include "timer.h"
#endif

#include "graphix.h"
#include "neuron_show.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  t_Synapse
//_______________________________________
void t_Synapse::Init(int i)
{
//  kind = HIDDEN_N;
  Axon = NULL;
  next = NULL;
//  Robot = NULL;
  Weight = 0.0;
  id = i;
}


void t_Synapse::Done(void)
{
  if (next != NULL)
     {
      next->Done();
      delete next;
      next = NULL;
     }
}


double t_Synapse::ReadInput(int stamp)
{
  double __Result__, d;

/*
    switch (kind)
      {
       case SPECIAL_N:
         __Result__ = 1.0;
         break;

       default:
*/
        // recursive sum over all inputs 
         d = 0.0;

#ifdef DEBUG
//   	fprintf(stderr,"begin\n");        
#endif        
         if (next != NULL)
            d = next->ReadInput(stamp);

         __Result__ = d + (Axon->Activation(stamp) * Weight);
#ifdef DEBUG
//        fprintf(stderr,"end rek with %g\n",__Result__);
#endif           
/*
         break;
    }
*/
  return __Result__;
}


void t_Synapse::Cut(t_Neuron *n)
{
  if (next == NULL)
    return;

  if (next->Axon != n)
     {
      next->Cut(n);
      return;
     }
    
  t_Synapse *p = next;
  next = p->next;
  p->Done();
  delete p;
}


void t_Synapse::Show(t_vector &pos)
{
#ifdef DEBUG
//   fprintf(stderr,"going to show synapse %d\n",id);
#endif   
   if (next != NULL)
      next->Show(pos);
      
   if (Axon != NULL)
       Show_Synapse(pos,Axon->pos,id,Weight/*,kind*/);      
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  t_Neuron
//_______________________________________
void t_Neuron::Init(int i, double px, double py, int t, double b)
{
  pos.x = px;
  pos.y = py;
  id = i;
  kind = t;
  Bias = b;
  next = NULL;
  act_val = 0.5;
  time_stamp = 0;
  Synapse = NULL;
}


void t_Neuron::Done(void)
{
  if (next != NULL)
     {
      next->Done();
      delete next;
      next = NULL;
     }

  if (Synapse != NULL)
     {
      Synapse->Done();
      delete Synapse;
      Synapse = NULL;
     }
}


char t_Neuron::IsActive(void)
{
//  double d = Activation();
  
  if (act_val > 0.5)
    return true;
  else
    return false;
}

double t_Neuron::Activation(int stamp)
{
   double d = 0.0;
//   t_Neuron N;  

   if (kind == _SPECIAL_N)
      return 1.0; 

   if (stamp == time_stamp)
      return act_val;	// this for recurrent networks
                                // return the old  activation -- don't loop endless         
   time_stamp = stamp;      // save the current time
       
   d = Synapse->ReadInput(stamp) + Bias;	// Bias is already a negative number from snns
   act_val = 1.0/(1.0 + exp(-d));		// the signum function

#ifdef DEBUG
//   fprintf(stderr,"neuron %d  act=%g bias=%g sum=%g\n",id,act,Bias,d);
#endif         
 
   return act_val;
}

char t_Neuron::InBox(int px, int py)
{
  if (px - NEURON_RADIUS < pos.x && pos.x < px + NEURON_RADIUS &&
      py - NEURON_RADIUS < pos.y && pos.y < py + NEURON_RADIUS)
    return true;
  else
    return false;
}


t_Neuron *t_Neuron::GetNeuron(int i)
{
  if (i == id)
    return (this);
  else if (next != NULL)
    return (next->GetNeuron(i));
  else
    return NULL;
}


void t_Neuron::Connect(t_Neuron *ToOther, double w)
{
  t_Synapse *dendrit,*p;
  int i;

  if (Synapse == NULL)
    {
     Synapse = new t_Synapse;
     Synapse->Init(0);
     dendrit = Synapse;
    }
  else
    {
     i = 1;
     p = Synapse;
     while (p->next != NULL)
       {
	p = p->next;
	i++;		// get a ID for the new synapse	
       }

     p->next = new t_Synapse;
     p->next->Init(i);	
     dendrit = p->next;
    }

  dendrit->Weight = w;
  dendrit->Axon = ToOther;
}



void t_Neuron::Cut(t_Neuron *n)
{
  if (next == NULL)
    return;

  if (next->next != n)
    {
     next->Cut(n);
     return;
    }

  t_Neuron *p = next;
  next = p->next;
  p->Done();
  delete p;
}

void t_Neuron::Cut(class t_Synapse *s)
{
  t_Synapse *S,*sp;
  
  if ((Synapse == NULL) || (s == NULL))
    return;
    
  S = Synapse;  
  
  if (S == s)
     {
      Synapse = Synapse->next;
//      S->Done();
      delete S;
      
      return;     // we are ready, only one Synapse to delete 
     }
    
  while (S->next != NULL)
    {
     if (S->next == s)
        {
         sp = S->next;
         S->next = S->next->next;
         
//         sp->Done();
         delete sp;
         
         return;   // we are ready, only one Synapse to delete  
        }
        
     S = S->next;   
    }  
}



void t_Neuron::WriteOutput(int stamp)
{
  if (next != NULL)
    next->WriteOutput(stamp);
}

/*
void t_Neuron::SetInputID(int i, RobotContext *Robot)
{
  Synapse = new t_Synapse;
  Synapse->Init(0);
  Synapse->Robot = Robot;
  Synapse->kind = i;
}

void t_Neuron::SetOutputID(int i)
{
  kind = i;
}
*/

void t_Neuron::Show(void)
{
#ifdef DEBUG
//   fprintf(stderr,"going to show neuron %d\n",id);
#endif   
   if (next != NULL)
      next->Show();
      
   if (Synapse != NULL)
      Synapse->Show(pos);   
   
   Show_Neuron(pos,id,act_val,kind);      
}


// End.







/**/
/**/
/**/
/**/
/**/
/**/
/**/
/**/
/*****  End Of File  ****************************/
