//*******************************************************************************
// 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