/* * file: column.c * * Name Date Description * -------------- -------- ------------------------------------- * Andrew H. Fagg 09/05/93 Original * * * * * [DEFINE DESCRIPTION = Neural column class] * */ #include "nsl_include.h" #include "column.h" #include "alib.h" #include "gen.h" /*#define DEBUG */ /* #define DEBUG2*/ /* * column_class::column_class(char* local_name, name_class* parent, * * Create a column object. Sets up connector and creates gates. * */ column_class::column_class(char* local_name, name_class* parent, short sensor_weight_flags, column_parms_class* cparms, int n_gates, short gate_weight_flags, gate_parms_class* gparms) { int i; char nm[10]; /* Temporary name for gates */ /* Create name */ name = new name_class(local_name, parent); #ifdef DEBUG cout << "*** column_class::column_class() :" << name << " ***" nl; #endif /* Create connectors. */ sensory_connector = new connector_class(sensor_weight_flags); /* NULL weight vectors for now. */ sensory_weights = NULL; /* Parameters. */ parms = cparms; /* Create gates */ num_gates = n_gates; gates = new gate_class*[num_gates]; /* Gate array */ /* Create individual gates */ for(i = 0; i < num_gates; ++i) { sprintf(nm, "%02d", i); /* Compute local name. */ /* Create gate. */ gates[i] = new gate_class(nm, name, gate_weight_flags, gparms); } } /* * column_class::~column_class() * * Column class destructor : delete allocated vars and gates. */ column_class::~column_class() { int i; /* Connector and weights */ delete sensory_connector; if(sensory_weights != NULL) delete sensory_weights; delete name; /* Name */ /* Delete gates. */ for(i = 0; i < num_gates; ++i) delete gates[i]; } /* * void column_class::init_weights() //OVERLOAD CALL: init_weights: column.c(column_class), gate.c(gate_class), layer.c(layer_class) * * Intialize the weight vectors. First create, and then set * the vectors to the initial values stored in the connectors. * */ void column_class::init_weights() { #ifdef DEBUG cout << "*** Init weights for " << name << " ***" nl; #endif int weight_size; int i; /* Priming connector */ /* How big is vector? */ weight_size = sensory_connector->get_num_connections(); //OVERLOAD CALL: get_num_connections: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class) if(weight_size != 0) { /* Create weight vector */ sensory_weights = new nsl_vector(weight_size); /* Get initial values. */ *sensory_weights = sensory_connector->get_initial_weights(0,0,0); } /* Init the gate weights. */ for(i = 0; i < num_gates; ++i) gates[i]->init_weights(); //OVERLOAD CALL: init_weights: column.c(column_class), gate.c(gate_class), layer.c(layer_class) } /* * void column_class::clear_activities() //OVERLOAD CALL: clear_activities: column.c(column_class), gate.c(gate_class), layer.c(layer_class) * * Set all activity values of the column to 0. * */ void column_class::clear_activities() { int i; #ifdef DEBUG cout << "*** column_class::clear_activities() : " << name << " ***" nl; //OVERLOAD CALL: clear_activities: column.c(column_class), gate.c(gate_class), layer.c(layer_class) #endif collector_mem = 0; collector = 0; sensory_mem = 0; sensory = 0; output_mem = 0; output = 0; pet_pos = 0; pet_neg = 0; /* Clear gate states. */ for(i = 0; i < num_gates; ++i) gates[i]->clear_activities(); //OVERLOAD CALL: clear_activities: column.c(column_class), gate.c(gate_class), layer.c(layer_class) } /* * void column_class::forward_mem() //OVERLOAD CALL: forward_mem: column.c(column_class), layer.c(layer_class) * * Compute the membrane potential of the output unit, * with all supporting inputs: gates, collector, and sensory unit. * */ void column_class::forward_mem() { int i; #ifdef DEBUG cout << "*** column_class::forward_mem() " << name << " ***" nl; //OVERLOAD CALL: forward_mem: column.c(column_class), layer.c(layer_class) #endif pet_pos = 0; pet_neg = 0; /* Compute gate states */ for(i = 0; i < num_gates; ++i) gates[i]->forward(); /* Gates to collector */ collector_mem = 0; for(i = 0; i < num_gates; ++i) collector_mem = collector_mem + *gates[i]->get_support(); /* PET contribution from gates */ if(parms->pet_flag->elem() == 1.0) { for(i = 0; i < num_gates; ++i) { pet_pos = pet_pos + gates[i]->get_pet_pos(); //OVERLOAD CALL: get_pet_pos: column.c(column_class), gate.c(gate_class) pet_neg = pet_neg + gates[i]->get_pet_neg(); //OVERLOAD CALL: get_pet_neg: column.c(column_class), gate.c(gate_class) }; }; /* Collector activity value. */ collector = elevatedSAT(collector_mem, //OVERLOAD CALL: elevatedSAT: funcs.c(?), funcs.c(?) parms->collector_kx1->elem(), parms->collector_kx2->elem(), parms->collector_ky1->elem(), parms->collector_ky2->elem(), parms->collector_ky3->elem()); /* Sensory unit */ if(sensory_connector->get_num_connections() > 0) //OVERLOAD CALL: get_num_connections: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class) { sensory_mem = (*sensory_weights ^ sensory_connector->get_values()).sum(); //OVERLOAD CALL: get_values: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class) /* Compute PET contribution */ if(parms->pet_flag->elem() == 1.0) { pet_pos = pet_pos + (NSLramp(*sensory_weights ^ sensory_connector->get_values())).sum(); //OVERLOAD CALL: get_values: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class) pet_neg = pet_neg + (NSLramp(- *sensory_weights ^ sensory_connector->get_values())).sum(); //OVERLOAD CALL: get_values: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class) }; } else /* No inputs */ sensory_mem = 0; /* Sensory activity value. */ /* Note that kx2 is used as a gain here. */ /* bad notation? yes. but it is */ /* convenient. */ sensory = NSLramp(sensory_mem, parms->sensory_kx1->elem(), parms->sensory_ky1->elem(), parms->sensory_ky2->elem()); /* Apply gain only if above threshold */ if(sensory.elem() > parms->sensory_ky2->elem()) { sensory.elem() = parms->sensory_kx2->elem() * (sensory.elem() - parms->sensory_ky2->elem()) + parms->sensory_ky2->elem(); } /* Output unit (membrane potential). */ DIFF.eq(output_mem, *parms->tau) = -output_mem + collector + sensory; /* Hard lower limit */ if(output_mem.elem() < parms->minimum_output_mem->elem()) output_mem.elem() = parms->minimum_output_mem->elem(); } /* * void column_class::forward_act(); //OVERLOAD CALL: forward_act: column.c(column_class), layer.c(layer_class) * * Compute the activity level of the output unit. Note * membrane potential is computed first over the entire network * (thus implementing a parallel update scheme). * */ void column_class::forward_act() { /* output = threshlog(output_mem, parms->output_kx1->elem(), //OVERLOAD CALL: threshlog: funcs.c(?), funcs.c(?) // parms->output_kx2->elem(), parms->output_ky1->elem(), parms->output_ky2->elem()); */ output = threshexp(output_mem, parms->output_kx1->elem(), //OVERLOAD CALL: threshexp: funcs.c(?), funcs.c(?) parms->output_ky1->elem(), parms->output_ky2->elem(), parms->output_kx2->elem()); } /* * name_class* column_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* column_class::get_name() { return name; } /* * nsl_data* column_class::get_collector() //OVERLOAD CALL: get_collector: layer.c(layer_class), column.c(column_class) * * Return a pointer to the activation level of the column. * */ nsl_data* column_class::get_collector() { return &collector; } /* * nsl_data* column_class::get_collector_mem() //OVERLOAD CALL: get_collector_mem: column.c(column_class), layer.c(layer_class) * * Return a pointer to the membrane potential level of the column. * */ nsl_data* column_class::get_collector_mem() { return &collector_mem; } /* * nsl_data* column_class::get_sensory() //OVERLOAD CALL: get_sensory: layer.c(layer_class), column.c(column_class) * * Return a pointer to the activation level of the column. * */ nsl_data* column_class::get_sensory() { return &sensory; } /* * nsl_data* column_class::get_sensory_mem() //OVERLOAD CALL: get_sensory_mem: column.c(column_class), layer.c(layer_class) * * Return a pointer to the membrane potential level of the column. * */ nsl_data* column_class::get_sensory_mem() { return &sensory_mem; } /* * nsl_data* column_class::get_output() //OVERLOAD CALL: get_output: layer.c(layer_class), column.c(column_class) * * Return a pointer to the activation level of the column. * */ nsl_data* column_class::get_output() { return &output; } /* * nsl_data* column_class::get_output_mem() //OVERLOAD CALL: get_output_mem: column.c(column_class), layer.c(layer_class) * * Return a pointer to the membrane potential level of the column. * */ nsl_data* column_class::get_output_mem() { return &output_mem; } /* * nsl_vector* column_class::get_sensory_weights() * * Return a pointer to the sensory weight vector. * */ nsl_vector* column_class::get_sensory_weights() { return sensory_weights; } /* * connector_class* column_class::get_sensory_connector() * * Return a pointer to the column sensory connector. * */ connector_class* column_class::get_sensory_connector() { return sensory_connector; } /* * connector_class* column_class::get_gate_connector(int gate, int unit) //OVERLOAD CALL: get_gate_connector: column.c(column_class), layer.c(layer_class) * * Return the connector of the specified gate and unit. * */ connector_class* column_class::get_gate_connector(int gate, int unit) { if(gate < 0 || gate >= num_gates) { cout << "column_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_gates-1 << "." nl; return NULL; } return gates[gate]->get_connector(unit); } /* * void unit_class::report_column() //OVERLOAD CALL: report_column: column.c(column_class), layer.c(layer_class) * * Print out all unit state information. * */ void column_class::report_column(int gate_flag, int connector_flag) { int i; cout nl << "--------------------------" nl; cout << "Unit: " << name nl; cout << "collector mem = \t" << collector_mem; cout << "collector act = \t" << collector; cout << "sensory mem = \t" << sensory_mem; cout << "sensory act = \t" << sensory; cout << "output mem = \t" << output_mem; cout << "output act = \t" << output; cout nl; if(connector_flag) { cout nl << "Sensory Connector" nl; if(sensory_connector->get_num_connections()) //OVERLOAD CALL: get_num_connections: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class) { nsl_vector tmp = sensory_connector->get_values(); //OVERLOAD CALL: get_values: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class), sensor.c(sensor_class) sensory_connector->report_state(sensory_weights, &tmp, NULL, NULL); //OVERLOAD CALL: report_state: connector.c(connector_class), reverse_connector.c(reverse_connector_input_class), reverse_connector.c(reverse_connector_output_class) } else cout << "Empty" nl; } if(gate_flag) { cout nl << "GATES:" nl; for(i = 0; i < num_gates; ++i) gates[i]->report_gate(connector_flag); //OVERLOAD CALL: report_gate: column.c(column_class), gate.c(gate_class), layer.c(layer_class) } } /* * void column_class::report_gate(int index, int connector_flag) //OVERLOAD CALL: report_gate: column.c(column_class), gate.c(gate_class), layer.c(layer_class) * * Report information about a single gate. * */ void column_class::report_gate(int index, int connector_flag) { if(!num_gates) { cout << "column_class::report_gate() " << name //OVERLOAD CALL: report_gate: column.c(column_class), gate.c(gate_class), layer.c(layer_class) << "error : no gates to report." nl; return; } if(index < 0 || index >= num_gates) { cout << "column_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_gates - 1 nl; return; } gates[index]->report_gate(connector_flag); //OVERLOAD CALL: report_gate: column.c(column_class), gate.c(gate_class), layer.c(layer_class) } int column_class::stuff(ifstream& netfile) { int size; int i; char tmp[STRSIZE]; netfile >> size; #ifdef DEBUG2 cout << "Reading column " << name << ", number of gates = " << size nl; #endif /* Check to make sure size is legal */ if(size < 0 || size > num_gates) { 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_gates << " (" << size << ")." nl; return 0; } /* Read the set of gates */ for(i = 0; i < size; ++i) { netfile >> tmp; /* Get the gate header */ if(strncmp(tmp, "gate", STRSIZE)) { cout << "Stuffing column " << name << ", expected gate, but got:" nl; cout << tmp; return 0; } netfile >> tmp; /* Get the gate name */ /* Read the gate from the file */ if(!gates[i]->stuff(netfile)) //OVERLOAD CALL: stuff: gate.c(gate_class), layer.c(layer_class), column.c(column_class), connector.c(connector_class) return 0; /* Now get the sensory connector */ netfile >> tmp; /* support connector header: 'sensory' */ if(strncmp(tmp, "sensory", STRSIZE)) { cout << "Stuffing column " << name << ", expected sensory, but got:" nl; cout << tmp nl; return 0; } netfile >> tmp; /* Get 'connector' */ if(strncmp(tmp, "connector", STRSIZE)) { cout << "Stuffing column " << name << ", expected connector, but got:" nl; cout << tmp nl; return 0; } /* Get the connector */ if(!sensory_connector->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; }; /* * nsl_data* column_class::get_pet_pos() //OVERLOAD CALL: get_pet_pos: column.c(column_class), gate.c(gate_class) * * Return a pointer to the positive component of the * pet measure. * */ nsl_data* column_class::get_pet_pos() { return &pet_pos; } /* * nsl_data* column_class::get_pet_neg() //OVERLOAD CALL: get_pet_neg: column.c(column_class), gate.c(gate_class) * * Return a pointer to the negative component of the * pet measure. * */ nsl_data* column_class::get_pet_neg() { return &pet_neg; }