//******************************************************************************* // CSC 143 Computer Programming II Spring 1999 Instructor: Keith Hughes // // Homework 3 // File : \\Venus\katy\CIS143\Homework3\AdalineNetwork\base.cpp // // Purpose : Inplementation file for Neuron and Link classes // // Author : Hsin-yi F. Berg // Date : 5/9/1999 Sun. // Last Update: 5/28/1999 Fri. // Update Note: Error has been moved form Link class to Neuron class // Replace the dynamically allocated arrays of pointers to Links in // the Neuron class with singly-linked lists of pointers to Links //******************************************************************************* #include "base.h" #include <iostream.h> #include <assert.h> // Singly-linked list node that has a Link pointer and a next pointer struct LinkNode { // Data item for this node which is a pointer to a Link Link *pLink; // Next item in the list. LinkNode *next; }; /* Static member initialization and function definitions for class Neuron */ int Neuron::id_count = 0; /* Neuron::Neuron() Default constructor for an Neuron. Not connected to any link. */ Neuron::Neuron() { id = id_count++; input_link = NULL; size_input_link = 0; output_link = NULL; size_output_link = 0; threshold = 0.0; high = 1.0; low = -1.0; value = -1.0; error = 0.0; } /* Neuron::~Neuron() Destructor for the Neuron. Goes through the whole list and delete every node on the way. */ Neuron::~Neuron() { LinkNode *temp = NULL; // temp points to the node to be deleted // trasverse through the list, deleting each node along the way while (input_link != NULL) { temp = input_link; input_link = input_link->next; delete temp; } // No need to set input_link to NULL because it is now NULL. while (output_link != NULL) { temp = output_link; output_link = output_link->next; delete temp; } // No need to set output_link to NULL because it is now NULL. assert (input_link == NULL); // double check if input_link is really NULL assert (output_link == NULL); // double check if output_link is really NULL } /* void Neuron::Print(ostream &out) const Print the internal state of the Neuron to the client_supplied ostream. */ void Neuron::Print(ostream &out) const { out << "Neuron " << id << endl; out << "\tThreshold = " << threshold << endl; out << "\tLow Value = " << low << endl; out << "\tHigh Value = " << high << endl; out << "\tValue = " << value << endl; out << "\tError = " << error << endl; // we'll print out the Links backwards because of the way we add new links // (we added the newLinkNode to the front of the list). // print all the links in the input list out << "\tInput Links:"; if(size_input_link == 0) out << " None" << endl; else { out << endl; // temp trasverse the list, prints out every Link along the way for(LinkNode *temp = input_link; temp != NULL; temp = temp->next) { out << "\tID : " << temp->pLink->GetID(); out << "\tWeight : " << temp->pLink->GetWeight(); out << endl; } } // print all the links in the output list out << "\tOutput Links:"; if(size_output_link == 0) out << " None" << endl; else { out << endl; // temp trasverse the list, prints out every Link along the way for(LinkNode *temp = output_link; temp != NULL; temp = temp->next) { out << "\tID : " << temp->pLink->GetID(); out << "\tWeight : " << temp->pLink->GetWeight(); out << endl; } } } /* bool Neuron::InputRoom(void) const Returns true if there is room for a new input link, false otherwise. */ bool Neuron::InputRoom(void) const { return true; } /* void Neuron::AddInput(const Link &newLink) Add an input Link to the Neuron. There should be room in the Neuron for another input Link. */ void Neuron::AddInput(Link &newLink) { // create the new linkNode first LinkNode *newLinkNode = new LinkNode; assert(newLinkNode); // initialize it's pLink field points to the newLink, next field to NULL newLinkNode->pLink = &newLink; newLinkNode->next = NULL; // we'll add the newLink in front of the list (order does not matter) // if input_link is originally empty, just set input_link to the newLinkNode if(input_link == NULL) input_link = newLinkNode; // otherwise put it in front of the list else { // add the newLinkNode newLinkNode->next = input_link; input_link = newLinkNode; } size_input_link++; } /* bool Neuron::OutputRoom(void) const Returns true if there is room for a new output link, false otherwise. */ bool Neuron::OutputRoom(void) const { return true; } /* void Neuron::AddOutput(const Link &newLink) Add an output Link to the Neuron. There should be room in the Neuron for another output Link. */ void Neuron::AddOutput(Link &newLink) { // create the new linkNode first LinkNode *newLinkNode = new LinkNode; assert(newLinkNode); // initialize it's pLink field points to the newLink, next field to NULL newLinkNode->pLink = &newLink; newLinkNode->next = NULL; // we'll add the newLink in front of the list (order does not matter) // if output_link is originally empty, just set output_link to the newLinkNode if(output_link == NULL) output_link = newLinkNode; // otherwise put it in front of the list else { // add the newLinkNode newLinkNode->next = output_link; output_link = newLinkNode; } size_output_link++; } /* LinkNode *&Neuron::GetInputLink(void) Return the reference of input_link */ LinkNode *&Neuron::GetInputLink(void) { return input_link; } /* LinkNode *&Neuron::GetOutputLink(void) Return the reference of output_link */ LinkNode *&Neuron::GetOutputLink(void) { return output_link; } /* ID Neuron::GetID(void) const Return the ID of this neuron */ ID Neuron::GetID(void) const { return id; } /* void Neuron::SetValue(double newValue) Set the value of the Neuron to some new value. */ void Neuron::SetValue(double newValue) { value = newValue; } /* void Neuron::GetValue(void) const Return the value of the neuron. */ double Neuron::GetValue(void) const { return value; } /* void Neuron::SetError(double newError) Set the error of the Neuron to new error value. */ void Neuron::SetError(double newError) { error = newError; } /* void Neuron::GetError(void) const Get the error of this Neuron. */ double Neuron::GetError(void) const { return error; } /* void Neuron::Fire(void) Calculating the weighted sum from the input links, and applying the threshold function to the resulting sum and storing the chosen threshold output value as the neuron's value. */ void Neuron::Fire(void) { // weighted_sum is the sum of all the "input Neuron values * weight of the link" double weighted_sum = 0; // we need to go through the input_link linked list and calculate the weighted value // which is the input Neuron value * weight of the link as we go on for(LinkNode *temp = input_link; temp != NULL; temp = temp->next) weighted_sum += temp->pLink->GetWeightedInputValue(); // after calculating the weighted_sum, we need to compare it to // the threshold value to determine the thresholded value if(weighted_sum >= threshold) value = high; else value = low; } /* void Neuron::ReadFromFile(istream& in) Read data into this Neuron instance from file specified by "in" */ void Neuron::ReadFromFile(istream& in) { // id_count and id are already assigned when the Neuron is created // from the upper level (NeuronLayer, NeuralNet...) // input_link and output_link are also updated in interconnect in NeuralNet in >> size_input_link; in >> size_output_link; in >> threshold; in >> high; in >> low; in >> value; in >> error; } /* void Neuron::WriteToFile(ostream& out) Write data of this Neuron instance to file specified by "out" */ void Neuron::WriteToFile(ostream& out) { // put a blank after each information is essential for // ReadFromFile to recognize each field out << size_input_link << " "; out << size_output_link << " "; out << threshold << " "; out << high << " "; out << low << " "; out << value << " "; out << error << " "; } /* void Neuron::Learn(double learning_rate) Learn will recalculate the weight of the input Link according to the learning rate, its own error and its input Neuron value using generalized delta rule. */ void Neuron::Learn(double learning_rate) { LinkNode *temp = input_link; // loop through each input link of the Neuron // reset the weights according to generalized delta rule // to reduce the error of this Neuron while(temp != NULL) { // input Neuron value double input_value = temp->pLink->GetInputNeuron().GetValue(); // original weight of the link double old_weight = temp->pLink->GetWeight(); // generalized delta rule double new_weight = old_weight + learning_rate * error * input_value; // reset the weight of the link according to the calculation above temp->pLink->SetWeight(new_weight); temp = temp->next; } } /* Static member initialization and function definitions for class Link */ int Link::id_count = 0; /* Link::Link() Default constructor for a Link. Does not point to any Neuron. */ Link::Link() { id = id_count++; input = NULL; output = NULL; weight = 0.0; } /* Link::Link(const Neuron *Input, const Neuron *Output, double Weight) Constructor for a Link. Takes Input Neuron, OutputNeuron, and Weight. */ Link::Link( Neuron *Input, Neuron *Output, double Weight ) { id = id_count++; input = NULL; output = NULL; weight = 0.0; } /* Link::~Link() Destructor for a Link. */ Link::~Link() {} /* void Link::Print(ostream &out) const Print the input Neuron, output Neuron, and the Weight on the client_supplied ostream. */ void Link::Print(ostream &out) const { out << "Link " << id << endl; if(input == NULL) out << "\tInput : None" << endl; else out << "\tInput = " << input->GetID() << endl; if(output == NULL) out << "\tOutput : None" << endl; else out << "\tOutput = " << output->GetID() << endl; out << "\tWeight = " << weight << endl; return; } /* ID Link::GetID(void) const Return the ID of this Link. */ ID Link::GetID(void) const { return id; } /* void Link::SetNeurons(const Neuron &input_Neuron, const Neuron &output_Neuron) Set the input and output Neurons of this Link. */ void Link::SetNeurons( Neuron &input_Neuron, Neuron &output_Neuron ) { input = &input_Neuron; output = &output_Neuron; } /* Neuron & Link::GetInputNeuron(void) const Return the reference of the input Neruon of this Link. */ Neuron &Link::GetInputNeuron(void) const { return *input; } /* Neuron & Link::GetOutputNeuron(void) const Return the reference of the output Neruon of this Link. */ Neuron &Link::GetOutputNeuron(void) const { return *output; } /* void Link::SetWeight(double Weight) Set the weight of this link to the client-supplied weight. */ void Link::SetWeight(double Weight) { weight = Weight; return; } /* void Link::GetWeight(void) const Get the current weight of this link */ double Link::GetWeight(void) const { return weight; } /* double Link::GetWeightedInputValue() const Return the value of the input node times the weight of the link. */ double Link::GetWeightedInputValue(void) const { return (input->GetValue()) * weight; } /* void Link::ReadFromFile(istream &in) Read weight into this Link from file specified by "in" */ void Link::ReadFromFile(istream &in) { in >> weight; } /* void Link::WriteToFile(ostream &out) Write weight of this link to file specified by "out" */ void Link::WriteToFile(ostream &out) { out << weight << " "; }
Back Top