[ return ]

layer.c



/*
 * file: layer.c
 *
 * [DEFINE DESCRIPTION = Layer class]
 * 
 *  Name                Date        Description
 *  --------------      --------    -------------------------------------
 *  Andrew H. Fagg      09/05/93    Original
 *
 *
 *
 *
 *
 *
 */

#include "nsl_include.h"
#include "layer.h"
#include "alib.h"
#include "gen.h"

/* #define DEBUG2 */

/*#define DEBUG */

/*
  * layer_class::layer_class(char* local_name, int size,
  *
  *  Create the layer by creating a set of columns.
  *
  */

layer_class::layer_class(char* local_name, int size,
		            short sensor_weight_flags,
			    column_parms_class*  cparms,
			    int n_gates,
			    short gate_weight_flags,
			    gate_parms_class* gparms)

{
  int i;
  char nm[10];

				/* Create name. */
  name = new name_class(local_name, NULL);

#ifdef DEBUG
  cout << "*** layer_class::layer_class() " << name << " ***" nl;
#endif
				/* Create columns. */
  num_columns = size;
  columns = new column_class*[size];
  used_columns = 0;

  for(i = 0; i < size; ++i)
    {
      sprintf(nm, "%03d", i);	/* Local name for column. */

				/* Create column. */
      columns[i] = new column_class(nm, name,
				    sensor_weight_flags,
				    cparms, n_gates,
				    gate_weight_flags, gparms);
    }
}

/*
  * layer_class::~layer_class()
  *
  *  Delete a layer.
  *
  */

layer_class::~layer_class()
{
  int i;
#ifdef DEBUG
  cout << "*** ~layer_class() ***" nl;
#endif

				/* Delete each column. */
  for(i = 0; i < num_columns; ++i)
    delete columns[i];
}

/*
  * layer_class::init_weights()        //OVERLOAD CALL: init_weights: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
  *
  *  Initialize all weights in the layer.
  *
  */

void layer_class::init_weights()
{
  int i;

#ifdef DEBUG
  cout << "*** layer_class::init_weights() ***" nl;        //OVERLOAD CALL: init_weights: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
#endif

				/* Loop through each column. */
  for(i = 0; i < used_columns; ++i)
    columns[i]->init_weights();        //OVERLOAD CALL: init_weights: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
}

/*
  * layer_class::clear_activities()        //OVERLOAD CALL: clear_activities: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
  *
  *  Initialize all weights in the layer.
  *
  */

void layer_class::clear_activities()
{
  int i;

#ifdef DEBUG
  cout << "*** layer_class::clear_activities() ***" nl;        //OVERLOAD CALL: clear_activities: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
#endif

				/* Loop through each column. */
  for(i = 0; i < num_columns; ++i)
    columns[i]->clear_activities();        //OVERLOAD CALL: clear_activities: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
}


/*
  * layer_class::forward_mem()        //OVERLOAD CALL: forward_mem: column.c(column_class), layer.c(layer_class)
  *
  *  Initialize all weights in the layer.
  *
  */

void layer_class::forward_mem()
{
  int i;
#ifdef DEBUG
  cout << "*** layer_class::forward_mem() ***" nl;        //OVERLOAD CALL: forward_mem: column.c(column_class), layer.c(layer_class)
#endif

				/* Loop through each column. */
  for(i = 0; i < used_columns; ++i)
    columns[i]->forward_mem();        //OVERLOAD CALL: forward_mem: column.c(column_class), layer.c(layer_class)
}

/*
  * layer_class::forward_act()        //OVERLOAD CALL: forward_act: column.c(column_class), layer.c(layer_class)
  *
  *  Initialize all weights in the layer.
  *
  */

void layer_class::forward_act()
{
  int i;

#ifdef DEBUG
  cout << "*** layer_class::forward_act() ***" nl;        //OVERLOAD CALL: forward_act: column.c(column_class), layer.c(layer_class)
#endif


				/* Loop through each column. */
  for(i = 0; i < used_columns; ++i)
    columns[i]->forward_act();        //OVERLOAD CALL: forward_act: column.c(column_class), layer.c(layer_class)
}


/*
 * name_class* layer_class::get_name()        //OVERLOAD CALL: get_name: column.c(column_class), connector.c(connector_class), gate.c(gate_class), layer.c(layer_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class)
 *
 *  Return the column name.
 */

name_class* layer_class::get_name()
{
  return name;
}


/*
 * nsl_vector layer_class::get_collector()        //OVERLOAD CALL: get_collector: layer.c(layer_class), column.c(column_class)
 *
 * Return a vector of collector activity levels.
 *
 */

nsl_vector layer_class::get_collector()
{
  int i;
  nsl_vector out(num_columns);
				/* Loop through each column and get */
				/*  the collector value. */
  for(i = 0; i < num_columns; ++i) 
    out.elem(i) = columns[i]->get_collector()->elem();        //OVERLOAD CALL: get_collector: layer.c(layer_class), column.c(column_class)
  return out;
}

/*
 * nsl_vector layer_class::get_collector_mem()        //OVERLOAD CALL: get_collector_mem: column.c(column_class), layer.c(layer_class)
 *
 * Return a vector of collector membrane potential levels.
 *
 */

nsl_vector layer_class::get_collector_mem()
{
  int i;
  nsl_vector out(num_columns);
				/* Loop through each column and get */
				/*  the collector_mem value. */
  for(i = 0; i < num_columns; ++i) 
    out.elem(i) = columns[i]->get_collector_mem()->elem();        //OVERLOAD CALL: get_collector_mem: column.c(column_class), layer.c(layer_class)
  return out;
}


/*
 * nsl_vector layer_class::get_sensory()        //OVERLOAD CALL: get_sensory: layer.c(layer_class), column.c(column_class)
 *
 * Return a vector of sensory activity levels.
 *
 */

nsl_vector layer_class::get_sensory()
{
  int i;
  nsl_vector out(num_columns);
				/* Loop through each column and get */
				/*  the sensory value. */
  for(i = 0; i < num_columns; ++i) 
    out.elem(i) = columns[i]->get_sensory()->elem();        //OVERLOAD CALL: get_sensory: layer.c(layer_class), column.c(column_class)
  return out;
}

/*
 * nsl_vector layer_class::get_sensory_mem()        //OVERLOAD CALL: get_sensory_mem: column.c(column_class), layer.c(layer_class)
 *
 * Return a vector of sensory membrane potential levels.
 *
 */

nsl_vector layer_class::get_sensory_mem()
{
  int i;
  nsl_vector out(num_columns);
				/* Loop through each column and get */
				/*  the sensory_mem value. */
  for(i = 0; i < num_columns; ++i) 
    out.elem(i) = columns[i]->get_sensory_mem()->elem();        //OVERLOAD CALL: get_sensory_mem: column.c(column_class), layer.c(layer_class)
  return out;
}


/*
 * nsl_vector layer_class::get_output()        //OVERLOAD CALL: get_output: layer.c(layer_class), column.c(column_class)
 *
 * Return a vector of output activity levels.
 *
 */

nsl_vector layer_class::get_output()
{
  int i;
  nsl_vector out(num_columns);
				/* Loop through each column and get */
				/*  the output value. */
  for(i = 0; i < num_columns; ++i) 
    out.elem(i) = columns[i]->get_output()->elem();        //OVERLOAD CALL: get_output: layer.c(layer_class), column.c(column_class)
  return out;
}

/*
 * nsl_vector layer_class::get_output_mem()        //OVERLOAD CALL: get_output_mem: column.c(column_class), layer.c(layer_class)
 *
 * Return a vector of output membrane potential levels.
 *
 */

nsl_vector layer_class::get_output_mem()
{
  int i;
  nsl_vector out(num_columns);
				/* Loop through each column and get */
				/*  the output_mem value. */
  for(i = 0; i < num_columns; ++i) 
    out.elem(i) = columns[i]->get_output_mem()->elem();        //OVERLOAD CALL: get_output_mem: column.c(column_class), layer.c(layer_class)
  return out;
}


/*
  * connector_class* layer_class::get_column_connector(int index)
  *
  *  Return the connector of the sensory unit of the specified column.
  *
  */

connector_class* layer_class::get_column_connector(int index)
{
				/* Make sure it is a valid index. */
  if(index < 0 || index >= num_columns)
    {
      cout << "layer_class::get_column_connector(): " << name
	<< "error: index must be between 0 and " << num_columns-1 << "." nl;
      return NULL;
    }
				/* Return the column's connector. */
  return columns[index]->get_sensory_connector();
}


/*
  * connector_class* layer_class::get_gate_connector(int index, int gate,        //OVERLOAD CALL: get_gate_connector: column.c(column_class), layer.c(layer_class)
  *                                                  int unit)
  *
  *  Return the connector of the specified columns' gate.
  *
  */

connector_class* layer_class::get_gate_connector(int index,
						 int gate, int unit)
{
				/* Make sure it is a valid index. */
  if(index < 0 || index >= num_columns)
    {
      cout << "layer_class::get_gate_connector(): " << name        //OVERLOAD CALL: get_gate_connector: column.c(column_class), layer.c(layer_class)
	<< "error: index must be between 0 and " << num_columns-1 << "." nl;
      return NULL;
    }
				/* Return the gate connector. */
  return columns[index]->get_gate_connector(gate, unit);        //OVERLOAD CALL: get_gate_connector: column.c(column_class), layer.c(layer_class)
}



/*
  * nsl_data* layer_class::get_column_output(int index)
  *
  *  Return a pointer to the output of the column.
  *
  */

nsl_data* layer_class::get_column_output(int index)
{
				/* Make sure it is a valid index. */
  if(index < 0 || index >= num_columns)
    {
      cout << "layer_class::get_column_output(): " << name
	<< " error: index must be between 0 and " << num_columns-1
	  << " (" << index << " given)." nl;
      return NULL;
    }
				/* Report the output. */
  return columns[index]->get_output();        //OVERLOAD CALL: get_output: layer.c(layer_class), column.c(column_class)
}

/*
  * nsl_data* layer_class::get_column_name(int index)
  *
  *  Return a pointer to the output of the column.
  *
  */

name_class* layer_class::get_column_name(int index)
{
				/* Make sure it is a valid index. */
  if(index < 0 || index >= num_columns)
    {
      cout << "layer_class::get_column_name(): " << name
	<< " error: index must be between 0 and " << num_columns-1
	  << " (" << index << " given)." nl;
      return NULL;
    }
				/* Report the name. */
  return columns[index]->get_name();        //OVERLOAD CALL: get_name: column.c(column_class), connector.c(connector_class), gate.c(gate_class), layer.c(layer_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class)
}


/*
  * void layer_class::report_column(int index, int gate_flag, int connector_flag)        //OVERLOAD CALL: report_column: column.c(column_class), layer.c(layer_class)
  *
  *  Give info on the column specified by <index>.
  *
  */

void layer_class::report_column(int index, int gate_flag, int connector_flag)
{
				/* Make sure it is a valid index. */
  if(index < 0 || index >= num_columns)
    {
      cout << "layer_class::report_column(): " << name        //OVERLOAD CALL: report_column: column.c(column_class), layer.c(layer_class)
	<< "error: index must be between 0 and " << num_columns-1 << "." nl;
      return;
    }
				/* Report the column. */
  columns[index]->report_column(gate_flag, connector_flag);        //OVERLOAD CALL: report_column: column.c(column_class), layer.c(layer_class)
}


/*
  * void layer_class::report_column(int index, int gate, int connector_flag)        //OVERLOAD CALL: report_column: column.c(column_class), layer.c(layer_class)
  *
  *  Give info on the gate specified by <index>, <gate>.
  *
  */

void layer_class::report_gate(int index, int gate, int connector_flag)
{
				/* Make sure it is a valid index. */
  if(index < 0 || index >= num_columns)
    {
      cout << "layer_class::report_gate(): " << name        //OVERLOAD CALL: report_gate: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
	<< "error: index must be between 0 and " << num_columns-1 << "." nl;
      return;
    }
				/* Report the column's gate. */
  columns[index]->report_gate(gate, connector_flag);        //OVERLOAD CALL: report_gate: column.c(column_class), gate.c(gate_class), layer.c(layer_class)
}


/*
  * int layer_class::stuff(ifstream& netfile)        //OVERLOAD CALL: stuff: gate.c(gate_class), layer.c(layer_class), column.c(column_class), connector.c(connector_class)
  *
  *  Read the layer from the opened stream.
  *  Return = 1 if no errors
  *         = 0 otherwise.
  *
  */

int layer_class::stuff(ifstream& netfile)
{
  int size;
  int i;
  char tmp[STRSIZE];

  netfile >> size;		/* Get number of columns */
				/* Check to make sure it is legal. */
#ifdef DEBUG2
  cout << "Reading layer " << name << ", size = " << size nl;
#endif

  if(size < 0 || size > num_columns)
    {
      cout << "stuff(): " << name << ".  Size must be between 0 and "        //OVERLOAD CALL: stuff: gate.c(gate_class), layer.c(layer_class), column.c(column_class), connector.c(connector_class)
	<< num_columns << " (" << size << ")." nl;
      return 0;
    }

  used_columns = size;		/* Assume columns are number 0..size-1 */

				/* Loop through each column and get  */
				/*  from file */
  for(i = 0; i < size; ++i)
    {
				/* Get the column header */
      netfile >> tmp;
      if(strncmp(tmp, "column", STRSIZE))
	{
	  cout << "Stuffing layer " << name << ", expecting column, but got:" nl;
	  cout << tmp nl;
	  return 0;
	}
      netfile >> tmp;		/* Get the column name and forget it*/

				/* If an error then return 0. */
      if(!columns[i]->stuff(netfile))        //OVERLOAD CALL: stuff: gate.c(gate_class), layer.c(layer_class), column.c(column_class), connector.c(connector_class)
	return 0;
    }
  return 1;
}


/*
  * int layer_class::get_num_columns()
  *
  *  Return the size of the layer.
  *
  */

int layer_class::get_num_columns()
{
  return(num_columns);
};


/*
  * column_class* layer_class::get_column(int index)
  *
  *  Return a pointer to the specified column.
  *  Returns NULL if there was an error.
  *
  */

column_class* layer_class::get_column(int index)
{
  if(index < 0 || index >= num_columns)
    {
      cout << "get_column(): bad index given.  Should fall between 0 and "
	<< num_columns-1 << " (received " << index << ")" nl;
      return(NULL);
    };
  return(columns[index]);
};


/*
  * void layer_class::stuff_pet_connector(connector_class* con, int type)
  *
  *  Connect <con> to the pet elements of all columns (positive or negative
  * contribution determined by <type>).
  *
  */

void layer_class::stuff_pet_connector(connector_class* con, int type)
{
  int i;
  nsl_data* val;

  for(i = 0; i < num_columns; ++i)
    {
				/* Positive or negative component? */
      switch (type)
	{
	case PET_POS:
	  val = columns[i]->get_pet_pos();        //OVERLOAD CALL: get_pet_pos: column.c(column_class), gate.c(gate_class)
	  break;
	case PET_NEG:
	  val = columns[i]->get_pet_neg();        //OVERLOAD CALL: get_pet_neg: column.c(column_class), gate.c(gate_class)
	  break;
	default:
	  cout << "layer_class::stuff_pet_connector() bad type (" << type << ")" nl;
	  break;
	};
				/* Add the connection to the pet element */
      con->add_connection(val, columns[i]->get_name(), 0);        //OVERLOAD CALL: add_connection: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class); get_name: column.c(column_class), connector.c(connector_class), gate.c(gate_class), layer.c(layer_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class)
    };
};


[ return ]