📄 neuron.cc
字号:
/* YAKS, Optann, a Khepera simulator including a separate GA and ANN (Genetic Algoritm, Artificial Neural Net). Copyright (C) 2000 Johan Carlsson (johanc@ida.his.se) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "neuron.h"/** * Get a random number in the range [0..\a i] * @param i The upper limit, [0..\a i] * @return The random number generated */int nrand(int i){ return (int)fabs((rand()*(double)i)/(RAND_MAX+1));}/** * Get a unique identifier for the neuron * @return A unique identifier. */long int getUniqId(){ static long int uniqeID=0; return ++uniqeID;}/** * Get the unique identifier for the neuron * @return The identifier. */long int Neuron::getId(){ return id;}/** * Get the identifier of the neuron to which link \a index points at. * @see getNextLinkId * @return The identifier or -1 if \a index is out of range. */long int Neuron::getLinkToId(int index){ if(index < nrOfLinks && index >= 0){ linkCount = index; return getNextLinkId(); } else{ return(-1); }}/** * Get the identifier of the neuron to which the next link points at. * @attention You must call getLinkToId before calling getNextLinkId. * @see getLinkId * @return The identifier or -1 if there are no more links. */long int Neuron::getNextLinkId(){ if(linkCount < nrOfLinks && linkCount >= 0){ return links[linkCount++]->fromId; } else{ return(-1); }}/** * Get the number of links the neuron has. * @return The number of links. */int Neuron::getNrOfLinks(){ return nrOfLinks;}/** * Duplicate the neuron. * @warning I dont know if this method really does work... * @return An exact copy of the neuron. */class Neuron* Neuron::duplicate(){ Neuron *copy; copy = new Neuron(layerPriority,nType,actType); for(int i=0; i < nrOfLinks;i++){ copy->createLink(links[i]->fromNode,links[i]->weight,links[i]->typ); } return copy;}/** * Constructor for neuron, creates a new neuron with an unique identifier. * @param iLayerPriority The activatio priority of the new neuron. * @param NODE_T The neuron type (for example INPUT,INTERN,OUTPUT,BIAS,SCN). * @param iFuncT The activation function for the neuron. */Neuron::Neuron(int iLayerPriority,NODE_T inType, ACTIVATION_T iFuncT){ activationValue = new double(); *activationValue = 0.5; nrOfLinks = 0; layerPriority = iLayerPriority; actType = iFuncT; nType = inType; linkCount = 0; id=getUniqId(); scnUsed = 0;}/** * Constructor for neuron, creates a new neuron with a specified identifier. * @attention Only use this constructor if you know what you are doing. * @param iLayerPriority The activatio priority of the new neuron. * @param NODE_T The neuron type (for example INPUT,INTERN,OUTPUT,BIAS,SCN). * @param iFuncT The activation function for the neuron. * @param iId The unique identifier for the neuron. */Neuron::Neuron(int iLayerPriority,NODE_T inType, ACTIVATION_T iFuncT,long int iId){ activationValue = new double(); *activationValue = 1.0; nrOfLinks = 0; layerPriority = iLayerPriority; actType = iFuncT; nType = inType; linkCount = 0; id=iId; scnUsed = 0;}/** * Get the type of neuron. * @return The type. */NODE_T Neuron::getNodeType(){ return nType;}/** * Get the activation function for the neuron. * @return The activation function. */ACTIVATION_T Neuron::getActFunc(){ return actType;}/** * Get the weight of a link. * @attention This function will call exit(-1) if index is out of range. * @param index The internal index of the link. * @return The weight. * @see setLinkWeight * @see getLinkWeightPointer */int8_t Neuron::getLinkWeight(int index){ if(index < nrOfLinks && index >= 0) return links[index]->weight; fprintf(stderr,"WARNING Neuron::getLinkWeight got a index which was out of range\n"); exit(-1);}/** * Get a pointer to the weight of a link. * @attention This function will call exit(-1) if index is out of range. * @param index The internal index of the link. * @return The weight pointer. * @see getLinkWeight * @see setLinkWeight */int8_t *Neuron::getLinkWeightPointer(int index){ if(index < nrOfLinks && index >= 0) return &links[index]->weight; fprintf(stderr,"WARNING Neuron::getLinkWeightPointer got a index which was out of range\n Index %d",index); exit(-1);}/** * Set the weight for a link. * @attention This function will call exit(-1) if index is out of range. * @param index The internal index of the link. * @param iweight The new weight for the link. * @see getLinkWeight * @see getLinkWeightPointer */void Neuron::setLinkWeight(int index, int8_t iweight){ if(index < nrOfLinks && index >= 0) links[index]->weight=iweight; else{ fprintf(stderr,"WARNING Neuron::setLinkWeight got a index which was out of range\n"); exit(-1); }}/** * Deconstructor, deallocates all memory and links for the neuron. */Neuron::~Neuron(){ if(nrOfLinks>0){ for(int i=0;i < nrOfLinks; i++){ free(links[i]); } free(links); } delete(activationValue);}/** * Creates a link from the current neuron to \a toNeuron. * @param toNeuron The neuron from which the link starts. * @param iWeight Initial weight of the link. * @param iType The link type, for now there are just NORMAL. * @see Neuron::createSCNLink */void Neuron::createLink(class Neuron *toNeuron,int8_t iWeight,LINK_TO_T iType){ int nI; if(iType==SCN_L){ fprintf(stderr,"Neuron::createLink use Neuron::createSCNLink to create a SCN link"); exit(-1); } if(nrOfLinks==0){ links = (LINK_T**) malloc(sizeof(LINK_T*)); links[0] = (LINK_T*)malloc(sizeof(LINK_T)); nI=0; } else{ links = (LINK_T**) realloc(links,sizeof(LINK_T*)*(nrOfLinks+1)); links[nrOfLinks] =(LINK_T*) malloc(sizeof(LINK_T)); nI=nrOfLinks; } links[nI]->weight = iWeight; links[nI]->value=toNeuron->activationPointer(); links[nI]->fromNode=toNeuron; links[nI]->fromId=toNeuron->getId(); links[nI]->typ=iType; links[nI]->toNode=this; links[nI]->SCN=NULL; links[nI]->SCNid=-1; links[nI]->toId=id; links[nI]->slowness=0; nrOfLinks++;}/** * Creates a SCN link from the current neuron to \a toNeuron with the weight from \a SCNNeuron activation value. * @param toNeuron The neuron from which the link starts. *燖param SCNNeuron The neuron to get the weight from. * @see Neuron::createLink */void Neuron::createSCNLink(class Neuron *toNeuron,class Neuron *SCNNeuron){ int nI; if(nrOfLinks==0){ links = (LINK_T**) malloc(sizeof(LINK_T*)); links[0] = (LINK_T*)malloc(sizeof(LINK_T)); nI=0; } else{ links = (LINK_T**) realloc(links,sizeof(LINK_T*)*(nrOfLinks+1)); links[nrOfLinks] =(LINK_T*) malloc(sizeof(LINK_T)); nI=nrOfLinks; } links[nI]->weight = 0; links[nI]->value=toNeuron->activationPointer(); links[nI]->fromNode=toNeuron; links[nI]->fromId=toNeuron->getId(); links[nI]->typ=SCN_L; links[nI]->SCN=SCNNeuron; links[nI]->SCNid=SCNNeuron->getId(); links[nI]->toNode=this; links[nI]->toId=id; links[nI]->slowness=0; SCNNeuron->setSCNUsed(); nrOfLinks++;}/** * Toggle the stat of scnUsed (used to make sure that a SCN neuron is used only ones) */void Neuron::setSCNUsed(){ scnUsed = 1;}/** * Get the identifier of the SCN neuron for the SCN link \a index. * @return The identifier or -1 if \a index is out of range or the link is not an SCN link. */long int Neuron::getLinkSCNid(int index){ if(index >=0 && index < nrOfLinks) return links[index]->SCNid; else return(-1);}/** * Remove a link to the neuron. It is safe to call this function with an incorrect index. * @param index The internal index of the link. * @see removeLinksTo() */void Neuron::removeLink(int index){ if(index >= 0 && index < nrOfLinks){ if((index+1)!=nrOfLinks){ free(links[index]); for(int i=index; i < --nrOfLinks; i++){ links[i] = links[i+1]; } links = (LINK_T**) realloc(links,sizeof(LINK_T*)*nrOfLinks); } else{ free(links[index]); links = (LINK_T**) realloc(links,sizeof(LINK_T*)*--nrOfLinks); } }}/** * Remove all links to \a toNeuron. * @param toNeuron The neuron to lose all connections to. * @see removeLinksTo(long int) */void Neuron::removeLinksTo(class Neuron *toNeuron){ for(int i=0; i < nrOfLinks; i++){ if(links[i]->fromNode==toNeuron){ removeLink(i); } }}/** * Remove all links to \a toNeuron. * @param toNeuron The neuron to lose all connections to. * @see removeLinksTo(class Neuron) */void Neuron::removeLinksTo(long int toNeuron){ for(int i=0; i < nrOfLinks; i++){ if(links[i]->fromId==toNeuron){ removeLink(i); } }}/** * Get the current activation of the neuron. * @return The activation. */double Neuron::getActivationValue(){ return *activationValue;}/** * Set the current activation of the neuron. * @param iValue The new activation. */void Neuron::setActivationValue(double iValue){ *activationValue = iValue;}/** * Get a pointer to the activation. * @return The pointer. */double* Neuron::activationPointer(){ return activationValue; }/** * Get the activation priority of the neuron, * @return The activation priority. */int Neuron::getPriority(){ return layerPriority;}/** * Mutate all links to the neuron. Each bit in the links flips with a probability of \a bitMutateProbability. *@param bitMutateProbability The probability that a bit in a link will mutate. */void Neuron::mutateWeights(int bitMutateProbability){ uint8_t q; int cdna; for(int i=0; i < nrOfLinks; i++){ if(links[i]->typ!=SCN_L){ cdna = 0; for(q = 128; q; q >>= 1) if(bitMutateProbability > nrand(100)) cdna |= q; links[i]->weight ^= cdna; } }}/** * Wrapper to mutateWeights() which only will be called if the neuron has the layer priority of \a pri. *@param bitMutateProbability The probability that a bit in a link will mutate. * @param pri The selection criteria. */void Neuron::mutateWeightsWithPri(int bitMutateProbability, int pri){ if(pri==layerPriority){ mutateWeights(bitMutateProbability); }}/** * Rebuilds all activation pointers in links to the neuron indicated by \a toNeuron. *@param toNeuron The neuron to fix all links to. */void Neuron::correctAllLinksFrom(class Neuron *toNeuron){ for(int i=0; i < nrOfLinks; i++){ if(links[i]->fromNode==toNeuron) links[i]->value=toNeuron->activationPointer(); }}/** * Check if SCN capability has been used. * @return 0 if it has been used - 1 otherwise. * */int Neuron::SCNNotUsed() const{ return !scnUsed;}/** * Sigmoid activation function. * @param in Input to sigmoid function. * @return \f$ f(in)=(1.0 / (1.0 + e^-in)) \f$ */double Neuron::sigmoid(double in){ double act;#ifdef ANN_DEBUG printf("%f \n",in);#endif act =(1.0 / (1.0 + exp(0.0 - in)));#ifdef ANN_DEBUG printf("%f \n",act);#endif return act;}/** * Sigmoid activation function. * @param in Input to sigmoid function. * @return \f$ f(in)=(1.0 / (1.0 + e^-in)) \f$ */double Neuron::logistic(double in){ return (1.0 / (1.0 + exp(0.0 - in)));}/** * Step activation function. * @param in Input to step function. * @return \f$ f(in) = (1.0, in >= 0.0)/(0.0, in < 0.0) \f$ */double Neuron::step(double in){ double out; if(in < 0) out=0.0; else out=1.0; return out;}/** * Linear activation function. * @param in Input to linear function. * @return \f$ f(in)=in \f$ */double Neuron::linear(double in){ return in;}/** * Activate the neuron. Sums all links values and calls the activation function. */void Neuron::activate(){ int i; double sum=0; if(nrOfLinks>0){ for(i=0; i < nrOfLinks; i++){ if(links[i]->typ==NORMAL){#ifdef ANN_DEBUG cout << "link weight " << (double)links[i]->weight/12.8 << " activation value " <<\ (double)*((double*)links[i]->value) << endl;#endif /* Weights between -10 < w < 10 */ sum += (double)*((double*)links[i]->value)*(links[i]->weight/12.8); } else if(links[i]->typ==SCN_L){ sum += (double)*((double*)links[i]->value)*(links[i]->SCN->getActivationValue()); } else{ //NULLAD } } if(actType==LOGISTIC){ *activationValue = logistic(sum); } else if(actType==SIGMOID){ *activationValue = sigmoid(sum); } else if(actType==TANH){ *activationValue = tanh(sum); } else if(actType == STEP){ *activationValue = step(sum); } else if(actType == LINEAR){ *activationValue = linear(sum); } else if(actType == NONE){ /* Do nothing */ } else{ *activationValue = 1.0; fprintf(stderr,"Whooooaaaaa i smell an error in Neuron::activate this neuron does not have an activationfunction\n"); exit(-1); } }}/** * Get the link type for the link with the internal index \a index. * @param index The internal index. * @return The link type. */LINK_TO_T Neuron::getLinkType(int index) const{ return links[index]->typ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -