// // ANNe = Artificial Neural Network with Emotion Simulation // (c) Jiri Charvat 2008 // #include #include #include #include #include struct sStatistics { int ers_reached; //Number of pulses that reached the emotion related structure int attenuated; //Number of pulses terminated by too weak signal int looping; //Number of pulses terminated because of infinite looping in the neural network sStatistics() { ers_reached = attenuated = looping = 0; } } g_stat; class cNeuron; int g_second = 0; //Global cycle id for printout int g_pulse_count = 0; //Global pulse id within the simulation cycle const double Kwd = 0.693147181/(2*24*3600); //=ln(2)/864000 .. weights will drop to half in 1 day double g_current_emotion = 0; #define PULSE_LIMIT 10.0 #define WEIGHT_LIMIT 5.0 #define MAX_DENDRITS 100 /********************************************************************/ struct sDendrit { double Activate(double pulse_strength); // double GetCurrentWeight() { return m_weight*exp(-Kwd * ( g_second - m_weight_init_time )); } double GetCurrentWeight() { return m_weight; } double m_weight; //wi from neural network theory int m_weight_init_time; //time when weight was set, used for exponential decrease of weight with time cNeuron* m_my_neuron; //Pointer to the neuron of this dendrit }; /********************************************************************/ class cNeuron { public: cNeuron(); ~cNeuron(); double Activate(double pulse_strength); // Extended initialization void Init(int ID, sDendrit* axon_termination); sDendrit* AddDendrit(); void MarkAsEmotionRelated() { m_bEmotionRelatedStructure = true; } void Print(); private: sDendrit* m_axon_termination; //Points to a dendrit of another neuron int m_no_of_dendrits; //Number of dendrits of this neuron sDendrit m_dendrits[MAX_DENDRITS]; //The dendrits of this neuron bool m_bEmotionRelatedStructure; //Some neuron structures can generate emotions, http://en.wikipedia.org/wiki/Emotions#Brain_areas_related_to_emotion int m_id; //To identify this neuron for printouts int m_cycle; //Prevent infinite looping (last cycle in which this neuron was activated) }; /********************************************************************/ class cNeuralNetwork { public: cNeuralNetwork(int no_of_neurons); ~cNeuralNetwork(); double RunSimulation (int duration); //Returns average emotion in the simulation void Print(); private: int m_no_of_neurons; cNeuron* m_neurons; double m_emotion; }; /*************************** IMPLEMENTATION *************************/ /* IMPLEMENTATION: cNeuralNetwork */ cNeuralNetwork::cNeuralNetwork(int no_of_neurons) { m_no_of_neurons = no_of_neurons; m_neurons = new cNeuron[no_of_neurons]; m_emotion = 0; // The first neuron simulates the brain structures related to emotions m_neurons[0].MarkAsEmotionRelated(); m_neurons[0].Init(0, NULL); srand(time(NULL)); for (int i=1; i PULSE_LIMIT ? PULSE_LIMIT : peak_value; } g_current_emotion = peak_value * exp(- Ked * (g_second - peak_time)); // printf("peak_value=%f Ked=%f peak_time=%d g_sec=%d exp=%f current_emotion=%f\n", // peak_value, Ked, peak_time, g_second, - Ked * (g_second - peak_time), current_emotion); if (g_second%60 == 0) fprintf(fw, "%d %f\n", g_second, g_current_emotion); emotion_sum += g_current_emotion; } fclose (fw); return emotion_sum/duration; } /* IMPLEMENTATION: cNeuron */ cNeuron::cNeuron() { m_axon_termination = NULL; m_no_of_dendrits = 0; //m_dendrits = NULL; m_bEmotionRelatedStructure = false; m_cycle = -1; } void cNeuron::Print() { if (m_axon_termination) { printf("Neuron%02d connected with weight %f to Neuron%d\n",m_id,m_axon_termination->m_weight, m_axon_termination->m_my_neuron->m_id); } else { printf("Neuron%02d serving as the Emotion-Related-Structure\n",m_id); } } cNeuron::~cNeuron() { //if (m_dendrits) delete [] m_dendrits; m_axon_termination = NULL; m_no_of_dendrits = 0; //m_dendrits = NULL; } void cNeuron::Init(int ID, sDendrit* axon_termination) { m_id = ID; m_axon_termination = axon_termination; } sDendrit* cNeuron::AddDendrit() //Used from cNeuralNetwork::GrowConnections { if (m_no_of_dendrits == MAX_DENDRITS) return NULL; m_no_of_dendrits++; sDendrit* result = &m_dendrits[m_no_of_dendrits-1]; result->m_my_neuron = this; result->m_weight = (2*(double)rand())/RAND_MAX; //Between 0 and 2, RAND_MAX=0x7fff result->m_weight_init_time = 0; //The initial weight set-up at time=0 sec return result; } double cNeuron::Activate(double pulse_strength) { printf("Time %d sec: Neuron%02d: Weight=%f Pulse=%f PulseHopCnt=%d\n", g_second, m_id, m_axon_termination ? m_axon_termination->GetCurrentWeight() : 0, pulse_strength, g_pulse_count++); if (m_bEmotionRelatedStructure) { printf("Reason for pulse termination: Emotion-Related-Structure (neuron %d) reached.\n", m_id); g_stat.ers_reached++; return pulse_strength; } #define MIN_PULSE 0.01f if (m_cycle == g_second) { g_stat.looping++; printf("Reason for pulse termination: Infinite looping in network on Neuron%02d.\n", m_id); return 0; } if (pulse_strength < MIN_PULSE) { g_stat.attenuated++; printf("Reason for pulse termination: Too weak pulse (less than %f).\n", MIN_PULSE); return 0; } m_cycle = g_second; // if (pulse_strength > 1 && m_axon_termination) return m_axon_termination->Activate(pulse_strength); if (m_axon_termination) return m_axon_termination->Activate(pulse_strength); return 0; //Never comes here because either m_bEmotionRelatedStructure==true or m_axon_termination!=NULL } /* IMPLEMENTATION: sDendrit */ double sDendrit::Activate(double pulse_strength) { //if (pulse_strength * m_weight < 1) return 0; double current_weight = GetCurrentWeight(); double pulse = pulse_strength * current_weight; if (pulse > PULSE_LIMIT) pulse = PULSE_LIMIT; double result_emotion = m_my_neuron->Activate(pulse); // if (result_emotion > current_weight) { // m_weight = m_weight + result_emotion/WEIGHT_LIMIT; //Some increase of the weight // m_weight = m_weight > WEIGHT_LIMIT ? WEIGHT_LIMIT : m_weight; //Physical limit: Prevent growing of above all limits // m_weight_init_time = g_second; // } return result_emotion; } #define NUMBER_OF_NEURONS 1000 #define DURATION 10*24*60*60 /*************************** MAIN ***********************************/ int main(int argc, char* argv[]) { cNeuralNetwork ANNe(NUMBER_OF_NEURONS); ANNe.Print(); double average_emotion = ANNe.RunSimulation(DURATION); //Number of seconds printf("\nArtificial Neural Network simulation finished:\n"); printf("Statistics: ERS_Reached=%d, Attenuated=%d, InfiniteLooping=%d\n", g_stat.ers_reached, g_stat.attenuated, g_stat.looping); printf("Duration: %d seconds, Number of neurons: %d, Average emotion: %f\n", DURATION, NUMBER_OF_NEURONS, average_emotion); return 0; }