├── AnalysisScripts ├── DisplayNetwork.c ├── DisplayPlots.cc └── tdrstyle.h ├── BrainInWorld.cc ├── BrainInWorld_LEAN.cc ├── Makefile ├── README.md ├── doc ├── Brain.tex ├── BrainInWorld.tex ├── LearningI.tex ├── LearningII.tex ├── Neuron.tex ├── World.tex ├── c_potential_time.png ├── c_potential_time_sawtooth_a.png └── c_potential_time_sawtooth_b.png ├── interface ├── Bot.h ├── Brain.h ├── CommandLineArguments.h ├── Entity.h ├── Fire.h ├── Food.h ├── Neuron.h └── ToolBox.h ├── run.sh └── src ├── Bot.cc ├── Brain.cc ├── Entity.cc ├── Fire.cc ├── Food.cc └── Neuron.cc /AnalysisScripts/DisplayNetwork.c: -------------------------------------------------------------------------------- 1 | #include "TH2F.h" 2 | #include "TCanvas.h" 3 | #include "TEllipse.h" 4 | #include "TPaveText.h" 5 | #include "stdlib.h" 6 | 7 | #include "../../interface/ToolBox.h" 8 | 9 | // double pi=3.14159265358979; 10 | 11 | void DisplayNetwork(std::string filename) 12 | { 13 | TFile *file=new TFile(filename.c_str()); 14 | TH2F *h_distances=(TH2F*)file->Get("Brain/h_distances_matrix_6000"); 15 | 16 | TCanvas *c_network=new TCanvas("c_network", "c_network", 900, 900); 17 | c_network->Range(-200, -200, 200, 200); 18 | 19 | int nNeurons=h_distances->GetNbinsX(); 20 | for (unsigned int i=0; i<=nNeurons; ++i) 21 | { 22 | TEllipse *neuron=new TEllipse(100.*cos(2.*i*pi/double(nNeurons)), 100.*sin(2.*i*pi/double(nNeurons)), 5); 23 | neuron->Draw(); 24 | TPaveText *txt=new TPaveText(120.*cos(2.*i*pi/double(nNeurons)), 120.*sin(2.*i*pi/double(nNeurons)), 120.*cos(2.*i*pi/double(nNeurons))+10, 120.*sin(2.*i*pi/double(nNeurons))+10); 25 | txt->AddText(itoa(i).c_str()); 26 | txt->Draw(); 27 | } 28 | for (unsigned int i=0; i<=nNeurons; ++i) 29 | { 30 | for (unsigned int j=0; j<=nNeurons; ++j) 31 | { 32 | TArrow *arrow=new TArrow(100.*cos(2.*i*pi/double(nNeurons)), 100.*sin(2.*i*pi/double(nNeurons)), 100.*cos(2.*j*pi/double(nNeurons)), 100.*sin(2.*j*pi/double(nNeurons)), 0.01); 33 | double distance=int(h_distances->GetBinContent(i, j)*100.)-2; 34 | std::cout<<"distance = "<SetLineWidth(distance); 36 | if (distance>0) arrow->Draw(); 37 | } 38 | } 39 | 40 | c_network->Draw(); 41 | } 42 | -------------------------------------------------------------------------------- /AnalysisScripts/DisplayPlots.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "tdrstyle.h" 13 | 14 | void avgBrainSize_time(TFile *file) 15 | { 16 | TGraph *g_avgBrainSize_time=(TGraph*)file->Get("g_avgBrainSize_time"); 17 | TGraph *g_avgBrainSize_predator_time=(TGraph*)file->Get("g_avgBrainSize_predator_time"); 18 | TCanvas *c_avgBrainSize_time=new TCanvas("c_avgBrainSize_time", "c_avgBrainSize_time", 700, 700); 19 | g_avgBrainSize_time->SetLineColor(kBlue); g_avgBrainSize_time->Draw("AL"); 20 | g_avgBrainSize_predator_time->SetLineColor(kRed); g_avgBrainSize_predator_time->Draw("SAME"); 21 | TLegend *leg=new TLegend(0.15, 0.70, 0.55, 0.85); 22 | leg->AddEntry(g_avgBrainSize_time, "Prey", "l"); 23 | leg->AddEntry(g_avgBrainSize_predator_time, "Predator", "l"); 24 | leg->SetFillColor(kWhite); 25 | leg->Draw(); 26 | c_avgBrainSize_time->SaveAs("c_avgBrainSize_time.png"); 27 | } 28 | 29 | void avgBrainSize_generation(TFile *file) 30 | { 31 | TGraph *g_avgBrainSize_generation=(TGraph*)file->Get("g_avgBrainSize_generation"); 32 | TCanvas *c_avgBrainSize_generation=new TCanvas("c_avgBrainSize_generation", "c_avgBrainSize_generation", 700, 700); 33 | g_avgBrainSize_generation->SetLineColor(kBlue); 34 | g_avgBrainSize_generation->Draw("AL"); 35 | c_avgBrainSize_generation->SaveAs("c_avgBrainSize_generation.png"); 36 | } 37 | 38 | void avgBrainSize_predator_generation(TFile *file) 39 | { 40 | TGraph *g_avgBrainSize_predator_generation=(TGraph*)file->Get("g_avgBrainSize_predator_generation"); 41 | TCanvas *c_avgBrainSize_predator_generation=new TCanvas("c_avgBrainSize_predator_generation", "c_avgBrainSize_predator_generation", 700, 700); 42 | g_avgBrainSize_predator_generation->SetLineColor(kRed); 43 | g_avgBrainSize_predator_generation->Draw("AL"); 44 | c_avgBrainSize_predator_generation->SaveAs("c_avgBrainSize_predator_generation.png"); 45 | } 46 | 47 | void dtime_time(TFile *file) 48 | { 49 | TGraph *g_dtime_time=(TGraph*)file->Get("g_dtime_time"); 50 | TH1F *h_dtime_time=new TH1F("h_dtime_time", "; time; Average time to next meal", 100, 0, 1500000); 51 | for (unsigned int i=0; iGetN(); ++i) 52 | { 53 | double x, y; 54 | g_dtime_time->GetPoint(i, x, y); 55 | h_dtime_time->Fill(x, y); 56 | } 57 | h_dtime_time->SetLineColor(kBlue); 58 | TCanvas *c_dtime_time=new TCanvas("c_dtime_time", "c_dtime_time", 700, 700); 59 | h_dtime_time->Draw("HIST"); 60 | c_dtime_time->SaveAs("c_dtime_time.png"); 61 | } 62 | 63 | void dtime_generation(TFile *file) 64 | { 65 | TGraph *g_dtime_generation=(TGraph*)file->Get("g_dtime_generation"); 66 | unsigned int nGenerations=g_dtime_generation->GetN(); 67 | TH1F *h_dtime_generation=new TH1F("h_dtime_generation", "; generations; Average time to next meal", nGenerations, 0, nGenerations); 68 | for (unsigned int i=0; iGetPoint(i, x, y); 72 | h_dtime_generation->Fill(x, y); 73 | } 74 | int rebin=1000; 75 | h_dtime_generation->Rebin(rebin); 76 | h_dtime_generation->Scale(1./double(rebin)); 77 | h_dtime_generation->SetLineColor(kBlue); 78 | TCanvas *c_dtime_generation=new TCanvas("c_dtime_generation", "c_dtime_generation", 700, 700); 79 | c_dtime_generation->SetLogy(); 80 | h_dtime_generation->Draw("HIST E"); 81 | c_dtime_generation->SaveAs("c_dtime_generation.png"); 82 | } 83 | 84 | void dtime_predator_generation(TFile *file) 85 | { 86 | TGraph *g_dtime_predator_generation=(TGraph*)file->Get("g_dtime_predator_generation"); 87 | unsigned int nGenerations_predator=g_dtime_predator_generation->GetN(); 88 | TH1F *h_dtime_predator_generation=new TH1F("h_dtime_predator_generation", "; generations; Average time for predator to next meal", nGenerations_predator, 0, nGenerations_predator); 89 | for (unsigned int i=0; iGetPoint(i, x, y); 93 | h_dtime_predator_generation->Fill(x, y); 94 | } 95 | int rebin=100; 96 | h_dtime_predator_generation->Rebin(rebin); 97 | h_dtime_predator_generation->Scale(1./double(rebin)); 98 | h_dtime_predator_generation->SetLineColor(kRed); 99 | TCanvas *c_dtime_predator_generation=new TCanvas("c_dtime_predator_generation", "c_dtime_predator_generation", 700, 700); 100 | c_dtime_predator_generation->SetLogy(); 101 | h_dtime_predator_generation->Draw("HIST E"); 102 | c_dtime_predator_generation->SaveAs("c_dtime_predator_generation.png"); 103 | } 104 | 105 | void distances(TFile *file) 106 | { 107 | TH2F *h_distances=(TH2F*)file->Get("Brain/h_distances_matrix_50000"); 108 | TCanvas *c_distances=new TCanvas("c_distances", "c_distances", 700, 700); 109 | h_distances->Draw("colz"); 110 | TLegend *leg=new TLegend(0.1, 0.9, 0.9, 1.0); 111 | leg->AddEntry(h_distances, "AI Brain", ""); leg->SetLineColor(kWhite); leg->SetFillColor(kWhite); 112 | leg->Draw(); 113 | c_distances->SaveAs("c_distances.png"); 114 | } 115 | 116 | void spontaneity(TFile *file) 117 | { 118 | TH1F *h_spontaneity=(TH1F*)file->Get("Brain/h_spontaneity_50000"); 119 | TCanvas *c_spontaneity=new TCanvas("c_spontaneity", "c_spontaneity", 700, 700); 120 | h_spontaneity->GetYaxis()->SetTitle("spontaneity"); 121 | h_spontaneity->Draw("hist"); 122 | c_spontaneity->SaveAs("c_spontaneity.png"); 123 | } 124 | 125 | void DisplayPlots(std::string filename) 126 | { 127 | TFile *file=new TFile(filename.c_str()); 128 | 129 | TStyle *tdrStyle=setTDRStyle(); 130 | tdrStyle->cd(); 131 | tdrStyle->SetOptStat(0); 132 | 133 | // avgBrainSize_time(file); 134 | // avgBrainSize_generation(file); 135 | // avgBrainSize_predator_generation(file); 136 | // dtime_time(file); // This is interesting -- explain it 137 | dtime_generation(file); 138 | // dtime_predator_generation(file); 139 | distances(file); 140 | spontaneity(file); 141 | } 142 | 143 | 144 | -------------------------------------------------------------------------------- /AnalysisScripts/tdrstyle.h: -------------------------------------------------------------------------------- 1 | #include "TStyle.h" 2 | 3 | TStyle* setTDRStyle() 4 | { 5 | TStyle *tdrStyle = new TStyle("tdrStyle","Style for P-TDR"); 6 | 7 | // For the canvas 8 | tdrStyle->SetCanvasBorderMode(0); 9 | tdrStyle->SetCanvasColor(kWhite); 10 | tdrStyle->SetCanvasDefH(700); //Height of canvas 11 | tdrStyle->SetCanvasDefW(700); //Width of canvas 12 | tdrStyle->SetPalette(1,0); 13 | 14 | // For the Pad 15 | tdrStyle->SetPadRightMargin(0.08); 16 | tdrStyle->SetPadLeftMargin(0.14); 17 | tdrStyle->SetPadBorderMode(0); 18 | // tdrStyle->SetPadBorderSize(Width_t size = 1); 19 | tdrStyle->SetPadColor(kWhite); 20 | tdrStyle->SetPadGridX(false); 21 | tdrStyle->SetPadGridY(false); 22 | tdrStyle->SetGridColor(0); 23 | tdrStyle->SetGridStyle(3); 24 | tdrStyle->SetGridWidth(1); 25 | 26 | // For the frame 27 | tdrStyle->SetFrameBorderMode(0); 28 | tdrStyle->SetFrameBorderSize(1); 29 | tdrStyle->SetFrameFillColor(0); 30 | tdrStyle->SetFrameFillStyle(0); 31 | tdrStyle->SetFrameLineColor(1); 32 | tdrStyle->SetFrameLineStyle(1); 33 | tdrStyle->SetFrameLineWidth(1); 34 | 35 | // For the Axis Titles 36 | tdrStyle->SetTitleColor(1, "XYZ"); 37 | tdrStyle->SetTitleFont(62, "XYZ"); 38 | tdrStyle->SetTitleSize(0.04, "XYZ"); 39 | tdrStyle->SetTitleXOffset(1.0); 40 | tdrStyle->SetTitleYOffset(1.52); 41 | 42 | // For plots 43 | // tdrStyle->SetOptTitle(0); 44 | tdrStyle->SetOptStat(0); 45 | tdrStyle->SetHistLineWidth(2); 46 | // tdrStyle->SetErrorX(0.); 47 | 48 | // For Legends 49 | tdrStyle->SetLegendFillColor(0); 50 | tdrStyle->SetLegendFont(42); 51 | tdrStyle->SetLegendBorderSize(0); 52 | 53 | return tdrStyle; 54 | } 55 | -------------------------------------------------------------------------------- /BrainInWorld.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | BrainInWorld 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #include "interface/Bot.h" 37 | #include "interface/Neuron.h" 38 | #include "interface/Brain.h" 39 | #include "interface/Fire.h" 40 | #include "interface/Food.h" 41 | #include "interface/ToolBox.h" 42 | #include "interface/CommandLineArguments.h" 43 | 44 | int skipGenerations=0; 45 | int endGeneration=1000; 46 | int timeStep=200; 47 | double worldSize=100; 48 | double regenFood=1.0; 49 | int seed=100; 50 | 51 | unsigned int nFoods=5; 52 | unsigned int nBots=10; 53 | unsigned int nPredators=5; 54 | 55 | // Mutation parameters 56 | double mu_newNeuron=0; // 0.001; 57 | double mu_newConnection=0.05; 58 | double mu_modConnection=0.05; 59 | double mu_visualAngle=0.05; 60 | 61 | // Debug Levels 62 | // bits: xxxx 63 | // bit 0 = TCanvas visualization 64 | // bit 1 = Verbalization 65 | // bit 2 = Fill histograms 66 | // bit 3 = Draw the histograms 67 | int debug = 0x2; 68 | 69 | int main(int argc, char *argv[]) 70 | { 71 | // Get command line arguments 72 | std::map cmdMap=commandLineArguments(argc, argv); 73 | if (cmdMap.find("-debug")!=cmdMap.end()) debug=cmdMap["-debug"]; 74 | if (cmdMap.find("-skipGenerations")!=cmdMap.end()) skipGenerations=cmdMap["-skipGenerations"]; 75 | if (cmdMap.find("-endGeneration")!=cmdMap.end()) endGeneration=cmdMap["-endGeneration"]; 76 | if (cmdMap.find("-timeStep")!=cmdMap.end()) timeStep=cmdMap["-timeStep"]; 77 | if (cmdMap.find("-worldSize")!=cmdMap.end()) worldSize=cmdMap["-worldSize"]; 78 | if (cmdMap.find("-nBots")!=cmdMap.end()) nBots=cmdMap["-nBots"]; 79 | if (cmdMap.find("-nFoods")!=cmdMap.end()) nFoods=cmdMap["-nFoods"]; 80 | if (cmdMap.find("-nPredators")!=cmdMap.end()) nPredators=cmdMap["-nPredators"]; 81 | if (cmdMap.find("-seed")!=cmdMap.end()) seed=cmdMap["-seed"]; 82 | 83 | r3->SetSeed(seed); 84 | 85 | std::cout<<"debug = "<SetCanvasPreferGL(true); 90 | gStyle->SetPalette(1); 91 | 92 | typedef std::vector Bots; 93 | Bots bots; 94 | for (unsigned int i=0; iRndm()*worldSize, r3->Rndm()*worldSize, r3->Rndm()*2.*pi, pi/4., 30, kBlue, 1.0, "Bot_"+itoa(i), worldSize, debug); 97 | bots.push_back(bot); 98 | } 99 | std::cout<<"Instantiated bots."<Rndm()*worldSize, r3->Rndm()*worldSize, r3->Rndm()*2.*pi, pi/4., 30, kRed, 1.0, "Predator_"+itoa(i), worldSize, debug); 105 | predators.push_back(predator); 106 | } 107 | std::cout<<"Instantiated predators."< Foods; 110 | Foods foods; 111 | for (unsigned int i=0; iRndm()*worldSize, r3->Rndm()*worldSize, r3->Rndm()*2.*pi, worldSize); 114 | foods.push_back(food); 115 | } 116 | std::cout<<"Instantiated food."< time_vector; 119 | std::vector time_predator_vector; 120 | std::vector avgBrainSize_vector; 121 | std::vector avgBrainSize_predator_vector; 122 | std::vector generation_vector; 123 | std::vector generation_predator_vector; 124 | std::vector dtime_vector; 125 | std::vector dtime_predator_vector; 126 | 127 | TCanvas *c_World; 128 | TText *text=new TText(0.01, 0.01, "Generation 0"); 129 | text=new TText(0.01, 0.01, "Generation 0"); 130 | text->SetNDC(); 131 | text->SetTextFont(42); 132 | if (decodeDebug(debug, 0)==1) 133 | { 134 | c_World=new TCanvas("c_World", "Natural Neural Network in Genetic Algorithm", 700, 700); 135 | // Safety Circle 136 | // TEllipse *e_safe=new TEllipse(worldSize/2., worldSize/2., 70, 70); 137 | // e_safe->Draw(); 138 | c_World->Range(0,0,worldSize,worldSize); 139 | } 140 | 141 | TCanvas *c_Potential_Histograms; 142 | TCanvas *c_SynapticStrength_Histograms; 143 | TCanvas *c_Distance_Histograms; 144 | if (decodeDebug(debug, 3)==1) 145 | { 146 | c_Potential_Histograms=new TCanvas("c_Potential_Histograms", "Brain Data - Neural Potentials", 700, 700); 147 | c_SynapticStrength_Histograms=new TCanvas("c_SynapticStrength_Histograms", "Brain Data - Synaptic Strengths", 700, 700); 148 | c_Distance_Histograms=new TCanvas("c_Distance_Histograms", "Brain Data - Neural Distances", 700, 700); 149 | c_Potential_Histograms->Divide(ceil(bots.size()/3.), 3); 150 | c_SynapticStrength_Histograms->Divide(ceil(bots.size()/3.), 3); 151 | c_Distance_Histograms->Divide(ceil(bots.size()/3.), 3); 152 | } 153 | 154 | int time=0; 155 | int generations=0; 156 | int generations_predator=0; 157 | int oldGeneration=generations; 158 | int dtime=0; 159 | int dtime_predator=0; 160 | 161 | // Time loop 162 | while (foods.size()>0 && generationsseeFoods(&foods); 172 | // bots.at(i)->seeBots(&bots); 173 | bots.at(i)->seeBots(&predators); 174 | bots.at(i)->stepInTime(); 175 | } 176 | for (unsigned int i=0; imoveForward(); 179 | } 180 | for (unsigned int i=0; iseeFoods(&foods); 183 | predators.at(i)->seeBots(&bots); 184 | // predators.at(i)->seeBots(&predators); 185 | predators.at(i)->stepInTime(); 186 | } 187 | 188 | // check for bots eating food 189 | int nEaten=0; 190 | int nBots=bots.size(); 191 | for (unsigned int i=0; ix_-foods.at(j)->x_, 2)+pow(bots.at(i)->y_-foods.at(j)->y_, 2); 197 | if (d2<13) 198 | { 199 | eatenFood=j; 200 | if (decodeDebug(debug, 1)==1) std::cout<<"Bot "<name_<<" ate food "<name_<<" ate bot "<Draw(); 291 | c_World->Update(); 292 | // c_World->SaveAs(("Movie/c_World_"+itoa(time)+".png").c_str()); 293 | // c_World->Print("Movie/Movie_basic.gif+"); 294 | } 295 | 296 | if (decodeDebug(debug, 3)==1 && time%timeStep==0 && generations>skipGenerations) // Flash histograms 297 | { 298 | for (unsigned int i=0; icd(i+1); 301 | bots.at(i)->brain_->drawPotentials(); 302 | c_Distance_Histograms->cd(i+1); 303 | bots.at(i)->brain_->drawDistances(); 304 | c_SynapticStrength_Histograms->cd(i+1); 305 | bots.at(i)->brain_->drawSynapticStrengths(); 306 | } 307 | c_Potential_Histograms->Modified(); 308 | c_Potential_Histograms->Update(); 309 | c_SynapticStrength_Histograms->Modified(); 310 | c_SynapticStrength_Histograms->Update(); 311 | c_Distance_Histograms->Modified(); 312 | c_Distance_Histograms->Update(); 313 | 314 | // c_Potential_Histograms->SaveAs("c_Potential_Histograms.png"); 315 | // c_SynapticStrength_Histograms->SaveAs("c_SynapticStrength_Histograms.png"); 316 | // c_Distance_Histograms->SaveAs("c_Distance_Histograms.png"); 317 | } 318 | 319 | if (generations%100==0 && generations!=oldGeneration) 320 | { 321 | std::cout<<"Generation "<SetName("g_avgBrainSize_time"); 326 | g_avgBrainSize_time->SetTitle("; time steps; Average size of brains"); 327 | 328 | TGraph *g_avgBrainSize_generation=new TGraph(avgBrainSize_vector.size(), &generation_vector[0], &avgBrainSize_vector[0]); 329 | g_avgBrainSize_generation->SetName("g_avgBrainSize_generation"); 330 | g_avgBrainSize_generation->SetTitle("; generations; Average size of brains"); 331 | 332 | TGraph *g_dtime_generation=new TGraph(dtime_vector.size(), &generation_vector[0], &dtime_vector[0]); 333 | g_dtime_generation->SetName("g_dtime_generation"); 334 | g_dtime_generation->SetTitle("; generations; Time to next meal"); 335 | 336 | TGraph *g_dtime_time=new TGraph(dtime_vector.size(), &time_vector[0], &dtime_vector[0]); 337 | g_dtime_time->SetName("g_dtime_time"); 338 | g_dtime_time->SetTitle("; time steps; Time to next meal"); 339 | 340 | TGraph *g_avgBrainSize_predator_time=new TGraph(avgBrainSize_predator_vector.size(), &time_predator_vector[0], &avgBrainSize_predator_vector[0]); 341 | g_avgBrainSize_predator_time->SetName("g_avgBrainSize_predator_time"); 342 | g_avgBrainSize_predator_time->SetTitle("; time steps; Average size of predator brains"); 343 | 344 | TGraph *g_avgBrainSize_predator_generation=new TGraph(avgBrainSize_predator_vector.size(), &generation_predator_vector[0], &avgBrainSize_predator_vector[0]); 345 | g_avgBrainSize_predator_generation->SetName("g_avgBrainSize_predator_generation"); 346 | g_avgBrainSize_predator_generation->SetTitle("; generations; Average size of predator brains"); 347 | 348 | TGraph *g_dtime_predator_generation=new TGraph(dtime_predator_vector.size(), &generation_predator_vector[0], &dtime_predator_vector[0]); 349 | g_dtime_predator_generation->SetName("g_dtime_predator_generation"); 350 | g_dtime_predator_generation->SetTitle("; generations; Time for predator to next meal"); 351 | 352 | TGraph *g_dtime_predator_time=new TGraph(dtime_predator_vector.size(), &time_vector[0], &dtime_predator_vector[0]); 353 | g_dtime_predator_time->SetName("g_dtime_predator_time"); 354 | g_dtime_predator_time->SetTitle("; time steps; Time to next meal"); 355 | 356 | int nSizeMatrix=bots.at(0)->brain_->neurons_.size(); 357 | TH1F *h_spontaneity=new TH1F(("h_spontaneity_"+itoa(generations)).c_str(), "; i^{th} Neuron", nSizeMatrix, 0, nSizeMatrix); 358 | TH2F *h_distances_matrix=new TH2F(("h_distances_matrix_"+itoa(generations)).c_str(), "; i^{th} Neuron; j^{th} Neuron", nSizeMatrix, 0, nSizeMatrix, nSizeMatrix, 0, nSizeMatrix); 359 | TH1F *h_distances=new TH1F(("h_distances_Generation_"+itoa(generations)).c_str(), "; distance", 50, 0, 1.0); 360 | for (unsigned int i=0; imkdir(("Bot_brain_"+itoa(i)).c_str()); 363 | Brain *brain=bots.at(i)->brain_; 364 | for (unsigned int j=0; jneurons_.size(); ++j) 365 | { 366 | Neuron *neuron=brain->neurons_.at(j); 367 | h_spontaneity->Fill(j, neuron->spontaneousRate_/double(nBots)); 368 | double sumDistance=0; 369 | for (unsigned int k=0; kneuralRelations_.size(); ++k) 370 | { 371 | sumDistance+=neuron->neuralRelations_.at(k)->distance; 372 | h_distances_matrix->Fill(j, neuron->neuralRelations_.at(k)->index, (neuron->neuralRelations_.at(k)->distance)/double(nSizeMatrix*nBots)); 373 | } 374 | h_distances->Fill(sumDistance/double(brain->neurons_.size()), 1./double(nBots)); 375 | } 376 | } 377 | 378 | TFile *file; 379 | if (generations==100) 380 | { 381 | file=new TFile("AnalyzeThis.root", "recreate"); 382 | file->mkdir("Brain"); 383 | } 384 | else file=new TFile("AnalyzeThis.root", "update"); 385 | g_avgBrainSize_time->Write(g_avgBrainSize_time->GetName(), 5 ); 386 | g_avgBrainSize_generation->Write(g_avgBrainSize_generation->GetName(), 5 ); 387 | g_dtime_generation->Write(g_dtime_generation->GetName(), 5 ); 388 | g_dtime_time->Write(g_dtime_time->GetName(), 5 ); 389 | g_avgBrainSize_predator_time->Write(g_avgBrainSize_predator_time->GetName(), 5 ); 390 | g_avgBrainSize_predator_generation->Write(g_avgBrainSize_predator_generation->GetName(), 5 ); 391 | g_dtime_predator_generation->Write(g_dtime_predator_generation->GetName(), 5 ); 392 | g_dtime_predator_time->Write(g_dtime_predator_time->GetName(), 5 ); 393 | file->cd("Brain"); 394 | h_spontaneity->Write(); 395 | h_distances->Write(); 396 | h_distances_matrix->Write(); 397 | file->Close(); 398 | 399 | delete g_avgBrainSize_time; 400 | delete g_avgBrainSize_generation; 401 | delete g_dtime_generation; 402 | delete g_dtime_time; 403 | delete g_avgBrainSize_predator_time; 404 | delete g_avgBrainSize_predator_generation; 405 | delete g_dtime_predator_generation; 406 | delete g_dtime_predator_time; 407 | delete h_spontaneity; 408 | delete h_distances_matrix; 409 | delete h_distances; 410 | } 411 | } 412 | 413 | if (decodeDebug(debug, 0)==1) 414 | { 415 | c_World->Print("Movie/Movie_basic.gif++"); 416 | delete c_World; 417 | } 418 | 419 | std::cout<<"Exited program after "< 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | bool verb=false; 35 | bool EEG=false; 36 | int timeStep=100; 37 | double worldSize=100; 38 | 39 | double pi=3.14159265358979; 40 | 41 | TRandom3 *r3=new TRandom3(); 42 | 43 | double convertToZeroToPi(double angle) 44 | { 45 | if (angle<0) return 2.*pi+angle; 46 | else return angle; 47 | } 48 | 49 | double checkAngle(double theta) 50 | { 51 | if (theta<0) theta=2.*pi+theta; 52 | if (theta>2.*pi) theta=theta-2.*pi; 53 | return theta; 54 | } 55 | 56 | double pythDistance(double x1, double y1, double x2, double y2) 57 | { 58 | return pow(pow(x1-x2, 2)+pow(y1-y2, 2), 0.5); 59 | } 60 | 61 | bool inBetween(double a, double x1, double x2) 62 | { 63 | if (x1>a && a>x2) return true; 64 | else return false; 65 | } 66 | 67 | std::string itoa(int i) 68 | { 69 | char res[10]; 70 | sprintf(res, "%d", i); 71 | std::string ret(res); 72 | return ret; 73 | } 74 | 75 | struct NeuralRelation 76 | { 77 | int index; 78 | double synapticStrength; 79 | double distance; 80 | }; 81 | typedef std::vector NeuralRelations; 82 | 83 | class Neuron; 84 | typedef std::vector Neurons; 85 | 86 | class Neuron 87 | { 88 | public: 89 | double potential_; 90 | double potential_buffer_; 91 | NeuralRelations neuralRelations_; 92 | 93 | public: 94 | Neuron() 95 | { 96 | potential_=0; 97 | potential_buffer_=0; 98 | } 99 | 100 | void push_back_relation(NeuralRelation *relation) 101 | { 102 | neuralRelations_.push_back(relation); 103 | } 104 | 105 | void receive(double charge) 106 | { 107 | potential_buffer_+=charge; 108 | if (potential_buffer_>2.) potential_buffer_=2.; 109 | } 110 | 111 | void stepInTime1(Neurons *neurons); 112 | 113 | void stepInTime2() 114 | { 115 | potential_+=potential_buffer_; 116 | potential_buffer_=0; 117 | } 118 | 119 | double potential() 120 | { 121 | return potential_; 122 | } 123 | 124 | void print() 125 | { 126 | std::cout<<" === Neuron Properties === "<index 133 | <<", "<synapticStrength 134 | <<", "<distance<<" | "; 135 | } 136 | std::cout<=0.8 || r3->Rndm()>0.95) // fire 149 | { 150 | double totalSynapticWeight=0; 151 | for (unsigned int i=0; isynapticStrength; 152 | for (unsigned int i=0; iat(neuralRelations_.at(i)->index); 155 | double synapticStrength=neuralRelations_.at(i)->synapticStrength; 156 | targetNeuron->receive((synapticStrength/totalSynapticWeight)*(neuralRelations_.at(i)->distance)); 157 | neuralRelations_.at(i)->synapticStrength=synapticStrength+0.8*(1.-synapticStrength); 158 | } 159 | potential_=0; 160 | } 161 | else 162 | { 163 | for (unsigned int i=0; isynapticStrength)*=0.8; 166 | if (neuralRelations_.at(i)->synapticStrength<1e-6) (neuralRelations_.at(i)->synapticStrength)=1e-6; 167 | } 168 | } 169 | } 170 | 171 | class Brain 172 | { 173 | public: 174 | 175 | Neurons neurons; 176 | TH1F *h_potentials_; 177 | TH2F *h_synapticStrengths_, *h_distances_; 178 | 179 | Brain(int size) 180 | { 181 | int rand=r3->Rndm()*1000000; 182 | h_potentials_=new TH1F(("h_potentials_"+itoa(rand)).c_str(), "Neural Action Potentials", size, 0, size); 183 | h_synapticStrengths_=new TH2F(("h_synapticStrengths_"+itoa(rand)).c_str(), "Neural Synaptic Strengths", size, size, 0, size, 0, size); 184 | h_distances_=new TH2F(("h_distances_"+itoa(rand)).c_str(), "Neural Distances", size, size, 0, size, 0, size); 185 | for (int i=0; iRndm()>0.5) 192 | { 193 | NeuralRelation *n=new NeuralRelation; 194 | n->index=j; 195 | n->synapticStrength=r3->Rndm(); // Should be read from file 196 | n->distance=r3->Rndm(); // Should be read from file 197 | // n->synapticStrength=0.5; 198 | // n->distance=0.5; // Should be read from file 199 | neurons.at(i)->push_back_relation(n); 200 | 201 | h_synapticStrengths_->Fill(i, j, n->synapticStrength); 202 | h_distances_->Fill(i, j, n->distance); 203 | } 204 | } 205 | h_potentials_->Fill(i+1); 206 | } 207 | } 208 | 209 | ~Brain() 210 | { 211 | for (unsigned int i=0; istepInTime1(&neurons); 225 | } 226 | for (unsigned int i=0; istepInTime2(); 229 | if (EEG) 230 | { 231 | h_potentials_->SetBinContent(i+1, neurons.at(i)->potential_); 232 | NeuralRelations *neuralRelations=&(neurons.at(i)->neuralRelations_); 233 | for (unsigned int j=0; jsize(); ++j) 234 | { 235 | h_synapticStrengths_->SetBinContent(i, neuralRelations->at(j)->index, neuralRelations->at(j)->synapticStrength); 236 | } 237 | } 238 | } 239 | } 240 | 241 | void print() 242 | { 243 | for (unsigned int i=0; iprintSimple(); 246 | // std::cout<<" === Neuron # "<print(); 248 | } 249 | std::cout<Draw("CL"); 255 | } 256 | void drawSynapticStrengths() 257 | { 258 | h_synapticStrengths_->Draw("colz"); 259 | } 260 | void drawDistances() 261 | { 262 | h_distances_->Draw("colz"); 263 | } 264 | }; 265 | 266 | class Entity 267 | { 268 | public: 269 | 270 | TEllipse *circle_; 271 | 272 | public: 273 | 274 | double x_, y_, theta_; 275 | 276 | void turnLeft() 277 | { 278 | theta_=checkAngle(theta_+0.1);// std::cout<<"turning left!"<worldSize) x_=1; 290 | if (y_<0) y_=99; 291 | if (y_>worldSize) y_=1; 292 | } 293 | 294 | void bouncyBoundaries() 295 | { 296 | if (x_<0) {x_=2; theta_=pi-theta_;} 297 | if (x_>worldSize) {x_=98; theta_=pi-theta_;} 298 | if (y_<0) {y_=2; theta_=-theta_;} 299 | if (y_>worldSize) {y_=98; theta_=-theta_;} 300 | } 301 | }; 302 | 303 | 304 | class Fire: public Entity 305 | { 306 | public: 307 | 308 | Fire(double x, double y, double theta) 309 | { 310 | x_=x; 311 | y_=y; 312 | theta_=theta; 313 | circle_=new TEllipse(x, y, 5., 5.); 314 | circle_->SetLineColor(kRed); 315 | circle_->SetFillColor(kYellow); 316 | } 317 | 318 | void draw() 319 | { 320 | circle_->SetX1(x_); 321 | circle_->SetY1(y_); 322 | circle_->Draw(); 323 | } 324 | 325 | void moveForward() 326 | { 327 | x_=x_+0.01*cos(theta_); 328 | y_=y_+0.01*sin(theta_); 329 | bouncyBoundaries(); 330 | } 331 | }; 332 | 333 | class Food: public Entity 334 | { 335 | public: 336 | 337 | Food(double x, double y, double theta) 338 | { 339 | x_=x; 340 | y_=y; 341 | theta_=theta; 342 | circle_=new TEllipse(x, y, 3., 3.); 343 | circle_->SetLineColor(kGreen+2); 344 | circle_->SetFillColor(kGreen); 345 | } 346 | 347 | ~Food() 348 | { 349 | circle_->Delete(); 350 | } 351 | 352 | void draw() 353 | { 354 | circle_->SetX1(x_); 355 | circle_->SetY1(y_); 356 | circle_->Draw(); 357 | } 358 | 359 | void moveForward() 360 | { 361 | x_=x_+0.001*cos(theta_); 362 | y_=y_+0.001*sin(theta_); 363 | bouncyBoundaries(); 364 | } 365 | }; 366 | 367 | class Bot: public Entity 368 | { 369 | public: 370 | 371 | Brain* brain_; 372 | TLine *line1_, *line2_; 373 | 374 | public: 375 | 376 | Bot(double x, double y, double theta, int brainSize) 377 | { 378 | x_=x; 379 | y_=y; 380 | theta_=theta; 381 | circle_=new TEllipse(x, y, 2., 2., theta*180./pi+22.5, 360.+theta*180./pi-22.5); 382 | circle_->SetLineColor(kBlack); 383 | circle_->SetFillColor(kBlue); 384 | line1_=new TLine(x, y, x+20.*cos(theta+pi/16.), y+20.*sin(theta+pi/16.)); 385 | line2_=new TLine(x, y, x+20.*cos(theta-pi/16.), y+20.*sin(theta-pi/16.)); 386 | line1_->SetLineColor(kCyan); 387 | line2_->SetLineColor(kCyan); 388 | 389 | brain_=new Brain(brainSize); 390 | } 391 | 392 | Bot(double x, double y, double theta, Brain *brain) 393 | { 394 | x_=x; 395 | y_=y; 396 | theta_=theta; 397 | circle_=new TEllipse(x, y, 2., 2., theta*180./pi+22.5, 360.+theta*180./pi-22.5); 398 | circle_->SetLineColor(kBlack); 399 | circle_->SetFillColor(kBlue); 400 | line1_=new TLine(x, y, x+20.*cos(theta+pi/16.), y+20.*sin(theta+pi/16.)); 401 | line2_=new TLine(x, y, x+20.*cos(theta-pi/16.), y+20.*sin(theta-pi/16.)); 402 | line1_->SetLineColor(kCyan); 403 | line2_->SetLineColor(kCyan); 404 | 405 | double rnd=r3->Rndm(); 406 | int diffBrainSize=0; 407 | if (rnd<0.25) diffBrainSize=-1; 408 | else if (rnd>0.75) diffBrainSize=1; // && brain->neurons.size()<55 409 | int newBrainSize=brain->neurons.size()+diffBrainSize; 410 | brain_=new Brain(newBrainSize); 411 | if (diffBrainSize==0) 412 | { 413 | for (unsigned int i=0; ineurons.size(); ++i) 414 | { 415 | Neuron *neuron_=brain_->neurons.at(i); 416 | Neuron *neuron=brain->neurons.at(i); 417 | neuron_->neuralRelations_.clear(); 418 | NeuralRelations neuralRelations=neuron->neuralRelations_; 419 | for (unsigned int j=0; jindex=neuralRelations.at(j)->index; 423 | neuralRelation_->synapticStrength=r3->Rndm(); 424 | double dist=(neuralRelations.at(j)->distance)-0.05+0.1*r3->Rndm(); 425 | if (dist<0) dist=0; 426 | else if (dist>1) dist=1; 427 | neuralRelation_->distance=dist; 428 | neuron_->push_back_relation(neuralRelation_); 429 | } 430 | } 431 | } 432 | else if (diffBrainSize<0) 433 | { 434 | for (unsigned int i=0; ineurons.size(); ++i) 435 | { 436 | Neuron *neuron_=brain_->neurons.at(i); 437 | Neuron *neuron=brain->neurons.at(i); 438 | neuron_->neuralRelations_.clear(); 439 | NeuralRelations neuralRelations=neuron->neuralRelations_; 440 | for (unsigned int j=0; jindexneurons.size()) 443 | { 444 | NeuralRelation *neuralRelation_=new NeuralRelation; 445 | neuralRelation_->index=neuralRelations.at(j)->index; 446 | neuralRelation_->synapticStrength=r3->Rndm(); 447 | double dist=(neuralRelations.at(j)->distance)-0.05+0.1*r3->Rndm(); 448 | if (dist<0) dist=0; 449 | else if (dist>1) dist=1; 450 | neuralRelation_->distance=dist; 451 | neuron_->push_back_relation(neuralRelation_); 452 | } 453 | } 454 | } 455 | } 456 | else if (diffBrainSize>0) 457 | { 458 | for (unsigned int i=0; ineurons.size()-1; ++i) 459 | { 460 | Neuron *neuron_=brain_->neurons.at(i); 461 | Neuron *neuron=brain->neurons.at(i); 462 | neuron_->neuralRelations_.clear(); 463 | NeuralRelations neuralRelations=neuron->neuralRelations_; 464 | for (unsigned int j=0; jindex=neuralRelations.at(j)->index; 468 | neuralRelation_->synapticStrength=r3->Rndm(); 469 | double dist=(neuralRelations.at(j)->distance)-0.05+0.1*r3->Rndm(); 470 | if (dist<0) dist=0; 471 | else if (dist>1) dist=1; 472 | neuralRelation_->distance=dist; 473 | neuron_->push_back_relation(neuralRelation_); 474 | } 475 | if (r3->Rndm()>0.5) // Add one more neural relation to each neuron 476 | { 477 | int newIndex=int(r3->Rndm()*brain_->neurons.size()); 478 | if (i!=newIndex) 479 | { 480 | NeuralRelation *neuralRelation_=new NeuralRelation; 481 | neuralRelation_->index=newIndex; 482 | neuralRelation_->synapticStrength=r3->Rndm(); 483 | neuralRelation_->distance=r3->Rndm(); 484 | neuron_->push_back_relation(neuralRelation_); 485 | } 486 | } 487 | } 488 | } 489 | // Update the distance histograms 490 | if (EEG) 491 | { 492 | for (unsigned int i=0; ineurons.size(); ++i) 493 | { 494 | Neuron *neuron_=brain_->neurons.at(i); 495 | NeuralRelations *neuralRelations_=&(neuron_->neuralRelations_); 496 | for (unsigned int j=0; jsize(); ++j) 497 | { 498 | NeuralRelation *neuralRelation_=neuralRelations_->at(j); 499 | brain_->h_distances_->SetBinContent(i, neuralRelation_->index, neuralRelation_->distance); 500 | } 501 | } 502 | } 503 | } 504 | 505 | ~Bot() 506 | { 507 | circle_->Delete(); 508 | line1_->Delete(); 509 | line2_->Delete(); 510 | delete brain_; 511 | } 512 | 513 | void draw() 514 | { 515 | circle_->SetX1(x_); 516 | circle_->SetY1(y_); 517 | circle_->SetPhimin(theta_*180./pi+22.5); 518 | circle_->SetPhimax(360.+theta_*180./pi-22.5); 519 | line1_->SetX1(x_); 520 | line1_->SetY1(y_); 521 | line1_->SetX2(x_+20.*cos(theta_+pi/16.)); 522 | line1_->SetY2(y_+20.*sin(theta_+pi/16.)); 523 | line2_->SetX1(x_); 524 | line2_->SetY1(y_); 525 | line2_->SetX2(x_+20.*cos(theta_-pi/16.)); 526 | line2_->SetY2(y_+20.*sin(theta_-pi/16.)); 527 | 528 | circle_->Draw(); 529 | line1_->Draw(); 530 | line2_->Draw(); 531 | } 532 | 533 | void moveForward() 534 | { 535 | x_=x_+0.2*cos(theta_); 536 | y_=y_+0.2*sin(theta_); 537 | bouncyBoundaries(); 538 | } 539 | 540 | bool inSight(double x, double y) 541 | { 542 | double thetac=convertToZeroToPi(atan2((y-y_), (x-x_))); 543 | if (inBetween(thetac, theta_+pi/16., theta_-pi/16.)) return true; 544 | else return false; 545 | } 546 | 547 | void see(std::vector *foods) //,std::vector *fires) //, double &distance) 548 | { 549 | for (unsigned int i=0; isize(); ++i) 550 | { 551 | if (inSight(foods->at(i)->x_, foods->at(i)->y_)) 552 | { 553 | double dist=pow(pow(x_-foods->at(i)->x_, 2)+pow(y_-foods->at(i)->y_, 2), 0.5); 554 | brain_->neurons.at(0)->receive(1); 555 | if (dist<30.) brain_->neurons.at(1)->receive(1); 556 | else if (dist<60.) brain_->neurons.at(2)->receive(1); 557 | else brain_->neurons.at(3)->receive(1); 558 | 559 | break; 560 | } 561 | } 562 | /*for (unsigned int i=0; isize(); ++i) 563 | { 564 | if (inSight(fires->at(i)->x_, fires->at(i)->y_)) 565 | { 566 | 567 | double dist=pow(pow(x_-foods->at(i)->x_, 2)+pow(y_-foods->at(i)->y_, 2), 0.5); 568 | // brain_->neurons.at(1)->receive(1); 569 | if (dist<30.) brain_->neurons.at(1)->receive(1); 570 | //else if (dist<60.) brain_->neurons.at(2)->receive(1); 571 | //else if (dist>60.) brain_->neurons.at(3)->receive(1); 572 | 573 | break; 574 | } 575 | }*/ 576 | } 577 | 578 | void stepInTime() 579 | { 580 | brain_->stepInTime(); 581 | if (brain_->neurons.at(5)->potential()>0.8) moveForward(); 582 | if (brain_->neurons.at(6)->potential()>0.8) turnLeft(); 583 | if (brain_->neurons.at(7)->potential()>0.8) turnRight(); 584 | } 585 | 586 | void printBrain() 587 | { 588 | brain_->print(); 589 | } 590 | }; 591 | 592 | void BrainInWorld_LEAN() 593 | { 594 | r3->SetSeed(120); 595 | 596 | typedef std::vector Bots; 597 | Bots bots; 598 | unsigned int nBots=10; 599 | for (unsigned int i=0; iRndm()*worldSize, r3->Rndm()*worldSize, r3->Rndm()*2.*pi, 30); 602 | bots.push_back(bot); 603 | } 604 | std::cout<<"Made bots"< Fires; 607 | Fires fires; 608 | unsigned int nFires=0; 609 | for (unsigned int i=0; iRndm()*worldSize, r3->Rndm()*worldSize, r3->Rndm()*2.*pi); 612 | fires.push_back(fire); 613 | } 614 | 615 | typedef std::vector Foods; 616 | Foods foods; 617 | unsigned int nFoods=100; 618 | for (unsigned int i=0; iRndm()*worldSize, r3->Rndm()*worldSize, r3->Rndm()*2.*pi); 621 | foods.push_back(food); 622 | } 623 | std::cout<<"Made food"< avgBrainSize_vector; 626 | std::vector time_vector; 627 | 628 | gStyle->SetPalette(1); 629 | 630 | TCanvas *c_World=new TCanvas("c_World", "Natural Neural Network in Genetic Algorithm", 700, 700); 631 | c_World->Range(0,0,worldSize,worldSize); 632 | TCanvas *c_Potential_Histograms; 633 | TCanvas *c_SynapticStrength_Histograms; 634 | TCanvas *c_Distance_Histograms; 635 | if (EEG) 636 | { 637 | c_Potential_Histograms=new TCanvas("c_Potential_Histograms", "Brain Data - Neural Potentials", 700, 700); 638 | c_SynapticStrength_Histograms=new TCanvas("c_SynapticStrength_Histograms", "Brain Data - Synaptic Strengths", 700, 700); 639 | c_Distance_Histograms=new TCanvas("c_Distance_Histograms", "Brain Data - Neural Distances", 700, 700); 640 | c_Potential_Histograms->Divide(ceil(bots.size()/3.), 3); 641 | c_SynapticStrength_Histograms->Divide(ceil(bots.size()/3.), 3); 642 | c_Distance_Histograms->Divide(ceil(bots.size()/3.), 3); 643 | } 644 | int time=0; 645 | int generations=0; 646 | while (foods.size()>0 && bots.size()>0 && generations<50000) 647 | { 648 | ++time; 649 | double avgBrainSize=0; 650 | for (unsigned int i=0; isee(&foods); //, &fires); 653 | bots.at(i)->stepInTime(); 654 | } 655 | for (unsigned int i=0; imoveForward(); 658 | } 659 | for (unsigned int i=0; imoveForward(); 662 | } 663 | 664 | // check for bots eating food 665 | int nEaten=0; 666 | for (unsigned int i=0; ix_-foods.at(j)->x_, 2)+pow(bots.at(i)->y_-foods.at(j)->y_, 2); 672 | if (d2<13) 673 | { 674 | eatenFood=j; 675 | if (verb) std::cout<<"Bot "<=0) 680 | { 681 | ++nEaten; 682 | if (verb) std::cout<<"foods.size() = "<SaveAs("c_SynapticStrength_Histograms.png"); 756 | // c_Distance_Histograms->SaveAs("c_Distance_Histograms.png"); 757 | } 758 | } 759 | 760 | TGraph *g_avgBrainSize=new TGraph(avgBrainSize_vector.size(), &time_vector[0], &avgBrainSize_vector[0]); 761 | g_avgBrainSize->SetTitle("Average size of brains against time; time steps; Average size of brains"); 762 | TCanvas *c_avgBrainSize=new TCanvas("avgBrainSize", "Average Brain Size", 700, 700); 763 | g_avgBrainSize->Draw("AL*"); 764 | c_avgBrainSize->SaveAs("c_avgBrainSize.png"); 765 | 766 | TFile *file=new TFile("AnalyzeThis.root", "recreate"); 767 | g_avgBrainSize->Write(); 768 | file->Close(); 769 | 770 | } 771 | 772 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ROOTFLAGS = $(shell root-config --cflags) 2 | ROOTLIBS = $(shell root-config --libs) 3 | 4 | all: BrainInWorld 5 | 6 | clean: 7 | rm -rf BrainInWorld lib/*.o 8 | 9 | BrainInWorld: lib/Neuron.o lib/Brain.o lib/Entity.o lib/Fire.o lib/Food.o lib/Bot.o lib/BrainInWorld.o 10 | c++ lib/Neuron.o lib/Brain.o lib/Entity.o lib/Fire.o lib/Food.o lib/Bot.o lib/BrainInWorld.o -o BrainInWorld $(ROOTFLAGS) $(ROOTLIBS) -O3 11 | 12 | TestNeuron: Neuron.o TestNeuron.o 13 | c++ lib/Neuron.o lib/TestNeuron.o -o TestNeuron $(ROOTFLAGS) $(ROOTLIBS) -O3 14 | 15 | lib/Neuron.o: interface/Neuron.h src/Neuron.cc 16 | c++ -c src/Neuron.cc -o lib/Neuron.o -c $(ROOTFLAGS) -O3 17 | 18 | lib/Brain.o: interface/Brain.h src/Brain.cc 19 | c++ -c src/Brain.cc -o lib/Brain.o -c $(ROOTFLAGS) -O3 20 | 21 | lib/Entity.o: interface/Entity.h src/Entity.cc 22 | c++ -c src/Entity.cc -o lib/Entity.o -c $(ROOTFLAGS) -O3 23 | 24 | lib/Fire.o: interface/Fire.h src/Fire.cc 25 | c++ -c src/Fire.cc -o lib/Fire.o -c $(ROOTFLAGS) -O3 26 | 27 | lib/Food.o: interface/Food.h src/Food.cc 28 | c++ -c src/Food.cc -o lib/Food.o -c $(ROOTFLAGS) -O3 29 | 30 | lib/Bot.o: interface/Bot.h src/Bot.cc 31 | c++ -c src/Bot.cc -o lib/Bot.o -c $(ROOTFLAGS) -O3 32 | 33 | lib/BrainInWorld.o: BrainInWorld.cc 34 | c++ -c BrainInWorld.cc -o lib/BrainInWorld.o -c $(ROOTFLAGS) -O3 35 | 36 | lib/TestNeuron.o: test/TestNeuron.cc 37 | c++ -c test/TestNeuron.cc -o lib/TestNeuron.o -c $(ROOTFLAGS) -O3 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

A neural network in a genetic algorithm develops survival behavior

5 | 6 |

7 | I have been developing, in my leisure, an original simulation of a biology-inspired neural network (brain) evolving in a natural selection environment. Survival behavior is observed to emerge rapidly. This is not an effort to create an efficient learning system but an exploration of how learning mechanisms like backpropagation and reinforcement learning may emerge in biological brains. Below, I point out the salient features that set this neural network apart from traditional artificial neural networks. Thereafter, I discuss the behaviors I observe and various avenues that I think this research could take. 8 |

9 | 10 |

11 | I conjecture that evolution sets policy gradients for (genetic) survival over multiple generations. These policy gradients are burned into the network topology. The network topology, in turn, directs (something like) reinforcement learning implemented on synaptic weights such that the individual brain learns to optimize reward during the course of one lifetime. 12 |

13 | 14 |

15 | Animations and more details here. 16 |

17 | 18 | 19 | 20 | 24 | 28 | 29 |
21 |
22 | Bots with 30 neurons each search for and race after "food". Shown here is their behavior between generations 1000 and 1100. 23 |
25 |
26 | Punctuated equilibria leading to best possible 30 neuron brain for chasing food. 27 |
30 | 31 |

32 | Each bot (blue circle) is controlled by a neural network (brain). The brain has 9 sensory neurons that take input from its field of vision, represented here as a grid in front of each bot. The brain also has 3 motor neurons that tell the bot to take a step forward, turn a degree to the left, and turn a degree to the right, respectively. The rest of the neurons in the brain (30 or so) mediate signals from the sensory to motor neurons. The connection topology of the brain is initially random. The neural network operates in time steps. Each neuron has a time-stepped model of signal integration, activation, leakage and refraction. Each synapse has a time-stepped model of Hebbian reinforcement and leakage. The initial behaviors of the bots are purely random and show no correlation between what they see and what they do. Every time a bot bumps into food (green), a daughter bot is generated with the same brain as its parent but with small random mutations in its connection topology. At the same time, the oldest bot in the group has to die. This simple evolutionary rule causes the brain topology, over a few thousand generations, to generate survival-like behavior as the bots search for and dart towards food ever more effectively. 33 |

34 |

35 | The average time it takes for a bot to get to food decreases through punctuated equilibria over several generations. 36 |

37 | 38 | 39 |

Description of the Neural Network

40 | 41 |
    42 | 43 |
  • Time-stepped network 44 |
    Unlike ANNs used for computation, this neural network operates in time steps. The state of the network at time t1 is derived from the state of the entire network at time t0. This allows input (sensory) neurons to carry time signatures, e.g. a sequential firing of neurons A, then B, and then C could mean a different thing than A, then C, and then B. This also means that the output (motor) neurons can direct what it controls in sophisticated ways. The possibility of impulses traveling in closed loops in the brain is also set up. Such self-reinforced loops, if they emerge, could indicate a form of proto-memory. 45 |
    46 |
  • 47 | 48 |
  • Network topology 49 |
    This neural network has no predetermined layering or structure of connections between the neurons. The topology of the network is defined by a directed network of 0 or 1 connections between every pair of neurons in the brain. This topology-network, or the connectome, does not vary during the lifetime of the neural network. It can be thought of an underlying hard-wired network over which the network consisting of synapses must operate. It mutates as it is passed on to oppspring. Layerings and structures relevant for (reinforcement) learning are expected to emerge in the connectome. 50 |
    51 |
  • 52 | 53 |
  • Dynamic synaptic weights 54 |
    Synaptic weights are reinforced by Hebb's rule. When a neuron fires, it reinforces the synaptic weights of its fan-in that connect to neurons that also fired in the previous time step. Synaptic weights also decay slowly, exponentially. 55 |
    56 |
  • 57 | 58 |
59 | 60 | 61 |

Interesting results and observations

62 | 63 |
    64 | 65 |
  • Minimum input frequency for a neuron to fire 66 |
    If there is exactly 1 input to a neuron, given leakage of the neuron's potential, there has to be a minimum input frequency below which the neuron cannot get fired. One can derive an analytical expression for this minimum frequency. I posit such a condition should also exist in biology. If there is more than 1 input, a more complicated condition for the minimum input frequency for each input should exist. 67 |
    68 |
  • 69 | 70 |
  • Evolution through punctuated equilibria 71 |
    If we plot any quantity that measures "progress" in this natural selection environment, it is found to change through punctuated equilibria over generations. For example, if we plot the average time it takes for bots to get to food, it decreases through punctuated equilibria over almost 2 orders of magnitude. Mainstream theories of biology posit that changes to the environment trigger the punctuations between equilibria. Here, we have a toy example where the environment does not change and yet punctuated equilibria are observed. This can be attributed to local minima in the fitness landscape that lie close to the global minimum. 72 |
    73 |
  • 74 | 75 |
  • Complex behavior in predator-prey scenarios
    76 |
    77 | 78 |
    79 |
  • 80 | 81 |
82 | 83 | 84 |

Future directions

85 | 86 |
    87 | 88 |
  • Isolate bots for learning, not breeding 89 |
  • 90 | 91 |
  • More complex physical environments 92 |
  • 93 | 94 |
  • A social environment 95 |
    Mastering a complex physical game environment should result in complex brain topologies that are bounded by the complexity of the physical environment. The same can be said for mastering a set of game environments. Adversarial networks training as opponents in a game environment can take the behavioral complexity of the networks a bit farther. However, open-ended complexity may be achieved by creating a social environment between the neural networks. This would create arbitrarily complex behavior of the neural networks where much intelligence and abstract representation of the game environment would be carried in the inter-network communication. 96 |
    97 |
    A way to create a social environment through inter-network communication would be to allow some neurons of each brain to be permanently attached to some neurons of other brains in the game with synaptic weight = 1. There is a temptation to view this as a mega-brain composed of several brains connected through bottlenecks. However, this is not the case since each individual brain is pursuing its own (genetic) survival. 98 |
    99 |
    Within the communication between brains concepts like deceit and cooperation may arise. Given sufficient communication bandwidth between the brains and a sufficiently complex physical environment, it is conceivable that abstractions for social maneuvering fairly removed from direct representations of the game environment may arise in these communications. If such a thing happens, then the complexity achieved by these brains and the capacity for abstraction may truly be open-ended. This would parallel the evolutionary development of the neocortex seen in creatures that routinely navigate social environments -- primates, humans, dolphins and pilot whales. 100 |
    101 |
    Generating a social environment does not require the biologically-inspired neural network model described here. It can be generated among traditional neural networks with reinforcement learning. 102 |
    103 | 104 |
  • 105 | 106 |
107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /doc/Brain.tex: -------------------------------------------------------------------------------- 1 | \section{The brain} 2 | 3 | \subsection{Neural connections} 4 | 5 | \subsection{Summary of mutation parameters} 6 | -------------------------------------------------------------------------------- /doc/BrainInWorld.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,letterpaper]{article} 2 | \usepackage{hyperref} 3 | \usepackage{graphicx} 4 | \usepackage{geometry} 5 | \usepackage{amsmath} 6 | 7 | \begin{document} 8 | 9 | \title{A biology-inspired neural network evolving through natural selection} 10 | \author{Souvik Das} 11 | \maketitle 12 | 13 | \begin{abstract} 14 | We describe a biology-inspired time-stepped simulation of a neural network that structures itself by competing against mutated copies of itself. The simulated neurons seek to capture the functional essence of a biological neuron as a function of time. We find a condition between the inputs to the neuron and its activation potential that needs to be met for the neuron to fire continuously, and conjecture that a similar condition may also exist in biology. The neural network encodes synaptic chemical concentrations between neurons that changes over the course of a network's lifetime based on simple rules of reinforcement and decay. The network also encodes the physical distance or connectivity between neurons that evolves over generations through natural selection. Multiple copies of these neural networks are instantiated in a game world, each with small random mutations in the connectivities. 15 | 16 | 17 | 18 | \end{abstract} 19 | \clearpage 20 | 21 | \tableofcontents 22 | \clearpage 23 | 24 | \input{Neuron} 25 | 26 | \input{Brain} 27 | 28 | \input{World} 29 | 30 | \input{LearningI} 31 | 32 | \input{LearningII} 33 | 34 | \end{document} 35 | 36 | -------------------------------------------------------------------------------- /doc/LearningI.tex: -------------------------------------------------------------------------------- 1 | \section{Learning to survive over generations} 2 | -------------------------------------------------------------------------------- /doc/LearningII.tex: -------------------------------------------------------------------------------- 1 | \section{Punctuated equilibria} 2 | 3 | -------------------------------------------------------------------------------- /doc/Neuron.tex: -------------------------------------------------------------------------------- 1 | \section{The simulated neuron} 2 | 3 | The simulated neuron used in this system tries to capture, through a time-stepped simulation, the functional essence of a biological neuron. A neuron receives input potentials $q_i$ (between -1 and 1) from the output of several other neurons, over time. The neuron sums up these potentials, at every time-step, and if the sum exceeds a threshold $Q_{th}$ it fires an activation potential that is then communicated via synapses to other neurons. After firing, the neuron's own potential drops to a small value below the baseline of 0 and then decays back to 0 by a factor of $k_p$ at every time-step. This decay constant for the potential, $k_p$, is always applied on the neuron and causes the potential to decay back to 0 even if the threshold has not been met and the neuron not been fired. Fig.~\ref{fig:c_potential_time} shows the potential of a single neuron that has been fired (red) and one that has not been fired (blue). 4 | 5 | \begin{figure}[thp] 6 | \centering 7 | \includegraphics[width=0.6\textwidth]{c_potential_time.png} 8 | \caption{The potential of a single neuron is plotted as a function of time. The red curve is for a neuron that is stimulated with a potential greater than the threshold $Q_{th}$ = 0.4 at time 50. It fires on its output and then drops its potential to -0.01. Thereafter, the potential decays by a factor of $k_p$ = 0.9 every time-step back to 0. In blue is the same neuron stimulated with a potential less than $Q_{th}$. It does not fire and the potential simply decays by $k_p$ back to 0.} 9 | \label{fig:c_potential_time} 10 | \end{figure} 11 | 12 | \subsection{Output frequency from input frequency} 13 | 14 | We can derive the frequency at which the neuron will fire if it is stimulated with a potential of $q$ applied every $t$ time-steps, i.e. with a frequency of $f_{in} = 1/t$. Since the potential will decay by a factor of $k_p$ at every time-step, the potential will reach $Q_{th}$ after $n$ time steps where: 15 | 16 | \begin{equation*} 17 | q(1 + k_p^t + k_p^{2t} ... + k_p^{nt}) = Q_{th} 18 | \end{equation*} 19 | 20 | This is the sum of a geometric series, and we can write it in closed form as Eq.~\ref{eq:neuron:eq1}. 21 | 22 | \begin{equation} 23 | \label{eq:neuron:eq1} 24 | \frac{Q_{th}}{q} = \frac{1-k^{t(n+1)}}{1-k^t} 25 | \end{equation} 26 | 27 | This can be solved for $n$ to derive the output frequency of the neuron $f_{out} = 1/nt$. The solution for $n$ is written in Eq.~\ref{eq:neuron:n}. 28 | 29 | \begin{equation} 30 | \label{eq:neuron:n} 31 | n = \frac{\log(1-\frac{Q_{th}}{q}(1-k^t))}{t\log(k)}-1 32 | \end{equation} 33 | 34 | For this to be true, i.e. for the total potential to ever reach $Q_{th}$, the argument of the logarithm in the numerator has to be positive. This implies a minimum frequency of input firing given by Eq.~\ref{eq:neuron:fin}. If this condition is not met, the neuron does not reach the firing threshold as shown by the blue curve in Fig.~\ref{fig:c_potential_time_sawtooth}a. When the condition is met, the neuron repeatedly fires in intervals of $nt$ given by Eq.~\ref{eq:neuron:n} as shown by the red curve in Fig.~\ref{fig:c_potential_time_sawtooth}b. \textit{We conjecture that such a condition may also exist for the firing of biological neurons.} 35 | 36 | \begin{equation} 37 | \label{eq:neuron:fin} 38 | \frac{1}{f_{in}} = t < \frac{\log(1-q/Q_{th})}{\log(k)} 39 | \end{equation} 40 | 41 | \begin{figure}[thp] 42 | \centering 43 | \includegraphics[width=0.49\textwidth]{c_potential_time_sawtooth_a.png} 44 | \includegraphics[width=0.49\textwidth]{c_potential_time_sawtooth_b.png} 45 | \caption{(a) LEFT. The neuron is programmed with a potential threshold $Q_{th}$ = 0.4, and a potential decay constant $k_p$ = 0.90. It is stimulated with potentials of $q$ = 0.1 applied every $t$ = 3 timesteps. According to Eq.~\ref{eq:neuron:fin}, $t$ needs to be less than 2.7 for the neuron to fire and therefore the neuron does not fire. (b) RIGHT. The neuron is now stimulated with $q$ = 0.1 applied every $t$ = 2 timesteps, and therefore it fires.} 46 | \label{fig:c_potential_time_sawtooth} 47 | \end{figure} 48 | 49 | ... \textit{Show the relationship between output and input frequencies. Connection with sigmoid.} 50 | 51 | \subsection{Synaptic weights} 52 | 53 | Neurons are connected to each other through synapses. We simulate the synaptic weight $w$ that corresponds to the concentration of a generic neurotransmitter in the synapse in time-steps as well. The value of the weight, $w$, lies between 0 and 1. If the output of neuron $i$ feeds into an input of neuron $j$, the synaptic weight is denoted by $w_{ij}$. When neuron $i$ fires, a fraction of the action potential $w_{ij}/\sum_{k}w_{ik}$ is transmitted to neuron $j$. $k$ is an index that runs over all the other neurons that neuron $i$ feeds into. 54 | 55 | The weight of a synapse is reinforced every time a signal passes through it. The reinforcement is implemented as an increase of the weight $w$ by $\alpha(1-w)$. This is a form of Hebbian learning that implements unsupervised learning in the neural network. The weight also decays by a factor of $\beta$ at every time-step. 56 | 57 | 58 | -------------------------------------------------------------------------------- /doc/World.tex: -------------------------------------------------------------------------------- 1 | \section{The natural selection environment} 2 | -------------------------------------------------------------------------------- /doc/c_potential_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/souvik1982/Brain/ab825709620804b3e5f10d6a5e17da3e28a75ba4/doc/c_potential_time.png -------------------------------------------------------------------------------- /doc/c_potential_time_sawtooth_a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/souvik1982/Brain/ab825709620804b3e5f10d6a5e17da3e28a75ba4/doc/c_potential_time_sawtooth_a.png -------------------------------------------------------------------------------- /doc/c_potential_time_sawtooth_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/souvik1982/Brain/ab825709620804b3e5f10d6a5e17da3e28a75ba4/doc/c_potential_time_sawtooth_b.png -------------------------------------------------------------------------------- /interface/Bot.h: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Bot 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "Brain.h" 18 | #include "Food.h" 19 | 20 | #include "TLine.h" 21 | 22 | class Bot: public Entity 23 | { 24 | public: 25 | 26 | Brain *brain_; 27 | std::string name_; 28 | TEllipse *visRange1_, *visRange2_, *visRange3_; 29 | TLine *visPeriphery1_, *visPeriphery2_; 30 | double visualAngle_; 31 | int bodyColor_; 32 | double speed_; 33 | double worldSize_; 34 | int debug_; 35 | int kids_; 36 | 37 | public: 38 | 39 | Bot(std::string type, double x, double y, double theta, double visualAngle, int brainSize, int bodyColor, double speed, std::string name, double worldSize, int debug = 1); 40 | Bot(Bot *parentBot, double mu_newNeuron, double mu_newConnection, double mu_modConnection, double mu_visualAngle); 41 | ~Bot(); 42 | 43 | void draw(); 44 | void moveForward(); 45 | void moveBackward(); 46 | void seeEntity(Entity *entity); 47 | void seeFoods(std::vector *foods); 48 | void seeBots(std::vector *bots); 49 | 50 | void stepInTime(); 51 | 52 | void printBrain(); 53 | }; 54 | -------------------------------------------------------------------------------- /interface/Brain.h: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Brain 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #pragma once 16 | 17 | #include "Neuron.h" 18 | 19 | #include "TH1F.h" 20 | #include "TH2F.h" 21 | 22 | class Brain 23 | { 24 | public: 25 | 26 | Neurons neurons_; 27 | 28 | TH1F *h_potentials_; 29 | TH2F *h_synapticStrengths_, *h_distances_; 30 | 31 | int debug_; 32 | std::string name_; 33 | 34 | public: 35 | 36 | Brain(int size, int debug = 0, std::string name = "0"); 37 | Brain(Brain *brain, int diffBrainSize, int debug = 0, std::string name = "0", double mu_newConnection=0.0, double mu_modConnection=0.0); 38 | ~Brain(); 39 | void stepInTime(); 40 | 41 | Neurons* getNeurons(); 42 | std::string getName(); 43 | TH1F* get_h_potentials(); 44 | TH2F* get_h_synapticStrengths(); 45 | TH2F* get_h_distances(); 46 | 47 | void print(); 48 | void drawPotentials(); 49 | void drawSynapticStrengths(); 50 | void drawDistances(); 51 | }; 52 | -------------------------------------------------------------------------------- /interface/CommandLineArguments.h: -------------------------------------------------------------------------------- 1 | #include "string" 2 | #include "map" 3 | 4 | std::map commandLineArguments(int argc, char *argv[]) 5 | { 6 | std::map cmdMap; 7 | for (unsigned int i=1; i 18 | 19 | struct NeuralRelation 20 | { 21 | int index; 22 | double synapticStrength; 23 | double distance; 24 | }; 25 | typedef std::vector NeuralRelations; 26 | 27 | class Neuron; 28 | typedef std::vector Neurons; 29 | 30 | class Neuron 31 | { 32 | public: 33 | double activationThreshold_; 34 | double synapticReinforcement_; 35 | double synapticDecay_; 36 | double potentialDecay_; 37 | 38 | double potential_; 39 | double potential_buffer_; 40 | double spontaneousRate_; 41 | NeuralRelations neuralRelations_; 42 | 43 | public: 44 | 45 | // Constructor 46 | Neuron(); 47 | 48 | // Update the neuron 49 | void push_back_relation(NeuralRelation *relation); 50 | void receive(double charge); 51 | void stepInTime1(Neurons *neurons); 52 | void stepInTime2(); 53 | 54 | // Debug the neuron 55 | double potential(); 56 | void print(); 57 | void printSimple(); 58 | }; 59 | -------------------------------------------------------------------------------- /interface/ToolBox.h: -------------------------------------------------------------------------------- 1 | #include "TMath.h" 2 | #include "TRandom3.h" 3 | 4 | #ifndef __GCCXML__ 5 | 6 | static const double pi=3.14159265358979; 7 | 8 | inline int decodeDebug(int d, int i) 9 | { 10 | return (d>>i)&0x1; 11 | } 12 | 13 | inline double convertToZeroToPi(double angle) 14 | { 15 | if (angle<0) return 2.*pi+angle; 16 | else return angle; 17 | } 18 | 19 | inline double checkAngle(double theta) 20 | { 21 | if (theta<0) theta=2.*pi+theta; 22 | if (theta>2.*pi) theta=theta-2.*pi; 23 | return theta; 24 | } 25 | 26 | inline double pythDistance(double x1, double y1, double x2, double y2) 27 | { 28 | return pow(pow(x1-x2, 2)+pow(y1-y2, 2), 0.5); 29 | } 30 | 31 | inline bool inBetween(double a, double x1, double x2) 32 | { 33 | if (x1>a && a>x2) return true; 34 | else return false; 35 | } 36 | 37 | inline std::string itoa(int i) 38 | { 39 | char res[10]; 40 | sprintf(res, "%d", i); 41 | std::string ret(res); 42 | return ret; 43 | } 44 | 45 | inline std::string ftoa(double i) 46 | { 47 | char res[10]; 48 | sprintf(res, "%f", i); 49 | std::string ret(res); 50 | return ret; 51 | } 52 | 53 | static TRandom3 *r3=new TRandom3(); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | # Debug Levels 2 | # bits: xxxx 3 | # bit 0 = TCanvas visualization 4 | # bit 1 = Verbalization 5 | # bit 2 = Fill histograms 6 | # bit 3 = Draw the histograms 7 | 8 | ./BrainInWorld -debug 1 -skipGenerations 100 -timeStep 200 -worldSize 500 -nBots 10 -nFoods 5 -nPredators 0 9 | -------------------------------------------------------------------------------- /src/Bot.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Bot 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include "../interface/Bot.h" 16 | #include "../interface/ToolBox.h" 17 | 18 | #include 19 | 20 | Bot::Bot(std::string type, double x, double y, double theta, double visualAngle, int brainSize, int bodyColor, double speed, std::string name, double worldSize, int debug): Entity(worldSize) 21 | { 22 | debug_=debug; 23 | worldSize_=worldSize; 24 | type_=type; 25 | name_=name; 26 | bodyColor_=bodyColor; 27 | speed_=speed; 28 | kids_=0; 29 | x_=x; 30 | y_=y; 31 | theta_=theta; 32 | visualAngle_=visualAngle; 33 | brain_=new Brain(brainSize, debug_, name_); 34 | if (decodeDebug(debug_, 0)==1) 35 | { 36 | circle_=new TEllipse(x, y, 2.); 37 | circle_->SetLineColor(kBlack); 38 | circle_->SetFillColor(bodyColor_); 39 | visRange1_=new TEllipse(x_, y_, 30, 30, 360.+(theta_-visualAngle_/2.)*180./pi, 360.+(theta_+visualAngle_/2.)*180./pi); 40 | visRange2_=new TEllipse(x_, y_, 60, 60, 360.+(theta_-visualAngle_/2.)*180./pi, 360.+(theta_+visualAngle_/2.)*180./pi); 41 | visRange3_=new TEllipse(x_, y_, 100, 100, 360.+(theta_-visualAngle_/2.)*180./pi, 360.+(theta_+visualAngle_/2.)*180./pi); 42 | visPeriphery1_=new TLine(x_, y_, x_+100.*cos(theta_+visualAngle_/6.), y_+100.*sin(theta_+visualAngle_/6.)); 43 | visPeriphery2_=new TLine(x_, y_, x_+100.*cos(theta_-visualAngle_/6.), y_+100.*sin(theta_-visualAngle_/6.)); 44 | visRange1_->SetFillStyle(0); 45 | visRange2_->SetFillStyle(0); 46 | visRange3_->SetFillStyle(0); 47 | visRange1_->SetLineColor(bodyColor_); 48 | visRange2_->SetLineColor(bodyColor_); 49 | visRange3_->SetLineColor(bodyColor_); 50 | visPeriphery1_->SetLineColor(bodyColor_); 51 | visPeriphery2_->SetLineColor(bodyColor_); 52 | } 53 | } 54 | 55 | Bot::Bot(Bot *parentBot, double mu_newNeuron, double mu_newConnection, double mu_modConnection, double mu_visualAngle): Entity(parentBot->worldSize_) 56 | { 57 | ++(parentBot->kids_); 58 | debug_=parentBot->debug_; 59 | worldSize_=parentBot->worldSize_; 60 | type_=parentBot->type_; 61 | name_=parentBot->name_+"_"+itoa(parentBot->kids_); 62 | bodyColor_=parentBot->bodyColor_; 63 | speed_=parentBot->speed_; 64 | kids_=0; 65 | x_=parentBot->x_; 66 | y_=parentBot->y_; 67 | theta_=parentBot->theta_; 68 | // std::cout<<"old visual angle = "<visualAngle_+mu_visualAngle*(-0.5+r3->Uniform()); 70 | // std::cout<<" new visual angle = "<pi) visualAngle_=pi; 73 | if (decodeDebug(debug_, 0)==1) 74 | { 75 | circle_=new TEllipse(x_, y_, 2.); 76 | circle_->SetLineColor(kBlack); 77 | circle_->SetFillColor(bodyColor_); 78 | visRange1_=new TEllipse(x_, y_, 30, 30, 360.+(theta_-visualAngle_/2.)*180./pi, 360.+(theta_+visualAngle_/2.)*180./pi); 79 | visRange2_=new TEllipse(x_, y_, 60, 60, 360.+(theta_-visualAngle_/2.)*180./pi, 360.+(theta_+visualAngle_/2.)*180./pi); 80 | visRange3_=new TEllipse(x_, y_, 100, 100, 360.+(theta_-visualAngle_/2.)*180./pi, 360.+(theta_+visualAngle_/2.)*180./pi); 81 | visPeriphery1_=new TLine(x_, y_, x_+100.*cos(theta_+visualAngle_/6.), y_+100.*sin(theta_+visualAngle_/6.)); 82 | visPeriphery2_=new TLine(x_, y_, x_+100.*cos(theta_-visualAngle_/6.), y_+100.*sin(theta_-visualAngle_/6.)); 83 | visRange1_->SetFillStyle(0); 84 | visRange2_->SetFillStyle(0); 85 | visRange3_->SetFillStyle(0); 86 | visRange1_->SetLineColor(bodyColor_); 87 | visRange2_->SetLineColor(bodyColor_); 88 | visRange3_->SetLineColor(bodyColor_); 89 | visPeriphery1_->SetLineColor(bodyColor_); 90 | visPeriphery2_->SetLineColor(bodyColor_); 91 | } 92 | 93 | double rnd=r3->Rndm(); 94 | int diffBrainSize=0; 95 | if (rndbrain_->neurons_.size()>20) diffBrainSize=-1; 96 | else if (rnd>1.-mu_newNeuron/2.) diffBrainSize=1; 97 | brain_=new Brain(parentBot->brain_, diffBrainSize, debug_, name_, mu_newConnection, mu_modConnection); 98 | } 99 | 100 | Bot::~Bot() 101 | { 102 | if (decodeDebug(debug_, 0)==1) 103 | { 104 | circle_->Delete(); 105 | visRange1_->Delete(); 106 | visRange2_->Delete(); 107 | visRange3_->Delete(); 108 | visPeriphery1_->Delete(); 109 | visPeriphery2_->Delete(); 110 | } 111 | delete brain_; 112 | } 113 | 114 | void Bot::draw() 115 | { 116 | if (decodeDebug(debug_, 0)==1) 117 | { 118 | circle_->SetX1(x_); 119 | circle_->SetY1(y_); 120 | double angle1=360.+(theta_-visualAngle_/2.)*180./pi; 121 | double angle2=360.+(theta_+visualAngle_/2.)*180./pi; 122 | visRange1_->SetX1(x_); 123 | visRange1_->SetY1(y_); 124 | visRange1_->SetPhimin(angle1); 125 | visRange1_->SetPhimax(angle2); 126 | visRange2_->SetX1(x_); 127 | visRange2_->SetY1(y_); 128 | visRange2_->SetPhimin(angle1); 129 | visRange2_->SetPhimax(angle2); 130 | visRange3_->SetX1(x_); 131 | visRange3_->SetY1(y_); 132 | visRange3_->SetPhimin(angle1); 133 | visRange3_->SetPhimax(angle2); 134 | visPeriphery1_->SetX1(x_); 135 | visPeriphery1_->SetY1(y_); 136 | visPeriphery1_->SetX2(x_+100.*cos(theta_+visualAngle_/6.)); 137 | visPeriphery1_->SetY2(y_+100.*sin(theta_+visualAngle_/6.)); 138 | visPeriphery2_->SetX1(x_); 139 | visPeriphery2_->SetY1(y_); 140 | visPeriphery2_->SetX2(x_+100.*cos(theta_-visualAngle_/6.)); 141 | visPeriphery2_->SetY2(y_+100.*sin(theta_-visualAngle_/6.)); 142 | 143 | circle_->Draw(); 144 | visRange1_->Draw(); 145 | visRange2_->Draw(); 146 | visRange3_->Draw(); 147 | visPeriphery1_->Draw(); 148 | visPeriphery2_->Draw(); 149 | } 150 | } 151 | 152 | void Bot::moveForward() 153 | { 154 | x_=x_+speed_*cos(theta_); 155 | y_=y_+speed_*sin(theta_); 156 | bouncyBoundaries(); 157 | } 158 | 159 | void Bot::moveBackward() 160 | { 161 | x_=x_-speed_*cos(theta_); 162 | y_=y_-speed_*sin(theta_); 163 | bouncyBoundaries(); 164 | } 165 | 166 | void Bot::seeEntity(Entity *entity) 167 | { 168 | if (entity!=this) 169 | { 170 | double x=entity->x_; 171 | double y=entity->y_; 172 | double distsq=pow(x_-x, 2)+pow(y_-y, 2); 173 | if (distsq<10000) // If beyond this, it doesn't see it 174 | { 175 | double thetac=convertToZeroToPi(atan2((y-y_), (x-x_))); 176 | bool seen=false; 177 | if (inBetween(thetac, theta_-visualAngle_/6., theta_-visualAngle_/2.)) 178 | { 179 | brain_->neurons_.at(3)->receive(1); 180 | seen=true; 181 | } 182 | else if (inBetween(thetac, theta_+visualAngle_/6., theta_-visualAngle_/6.)) 183 | { 184 | brain_->neurons_.at(4)->receive(1); 185 | seen=true; 186 | } 187 | else if (inBetween(thetac, theta_+visualAngle_/2., theta_+visualAngle_/6.)) 188 | { 189 | brain_->neurons_.at(5)->receive(1); 190 | seen=true; 191 | } 192 | 193 | if (seen) 194 | { 195 | // std::cout<<"Seen within fov"<neurons_.at(0)->receive(1); 200 | } 201 | else if (distsq<3600) 202 | { 203 | brain_->neurons_.at(1)->receive(1); 204 | } 205 | else 206 | { 207 | brain_->neurons_.at(2)->receive(1); 208 | } 209 | 210 | // What kind of an entity is seen? 211 | std::string type=entity->type_; 212 | if (type=="Food") 213 | { 214 | brain_->neurons_.at(6)->receive(1); 215 | } 216 | else if (type=="Bot") 217 | { 218 | brain_->neurons_.at(7)->receive(1); 219 | } 220 | else if (type=="Predator") 221 | { 222 | brain_->neurons_.at(8)->receive(1); 223 | } 224 | else 225 | { 226 | std::cout<<"ERROR: Entity seen has no known type!"< *foods) 234 | { 235 | for (unsigned int i=0; isize(); ++i) 236 | { 237 | seeEntity((Entity*)foods->at(i)); 238 | } 239 | } 240 | 241 | void Bot::seeBots(std::vector *bots) 242 | { 243 | for (unsigned int i=0; isize(); ++i) 244 | { 245 | seeEntity((Entity*)bots->at(i)); 246 | } 247 | } 248 | 249 | void Bot::stepInTime() 250 | { 251 | brain_->stepInTime(); 252 | if (brain_->neurons_.at(12)->potential()>0.4) moveForward(); 253 | if (brain_->neurons_.at(13)->potential()>0.4) turnLeft(); 254 | if (brain_->neurons_.at(14)->potential()>0.4) turnRight(); 255 | if (brain_->neurons_.at(15)->potential()>0.4) moveBackward(); 256 | } 257 | 258 | void Bot::printBrain() 259 | { 260 | brain_->print(); 261 | } 262 | -------------------------------------------------------------------------------- /src/Brain.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Brain 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include 16 | 17 | #include "../interface/Brain.h" 18 | #include "../interface/ToolBox.h" 19 | 20 | Brain::Brain(int size, int debug, std::string name) 21 | { 22 | debug_=debug; 23 | if (decodeDebug(debug_, 2)==1) 24 | { 25 | std::cout<<"Initialized histos"<Uniform()>0.5) 42 | { 43 | NeuralRelation *n = new NeuralRelation; 44 | n->index = j; 45 | n->synapticStrength = r3->Uniform(); 46 | n->distance=r3->Uniform(); 47 | neuron->push_back_relation(n); 48 | 49 | if (decodeDebug(debug_, 2)==1) 50 | { 51 | h_synapticStrengths_->Fill(i, j, n->synapticStrength); 52 | h_distances_->Fill(i, j, n->distance); 53 | } 54 | } 55 | if (decodeDebug(debug_, 2)==1) h_potentials_->Fill(i+1); 56 | } 57 | 58 | // Add the neuron to the brain 59 | neurons_.push_back(neuron); 60 | 61 | } 62 | } 63 | 64 | Brain::Brain(Brain *parentBrain, int diffBrainSize, int debug, std::string name, double mu_newConnection, double mu_modConnection) 65 | { 66 | int brainSize=parentBrain->neurons_.size()+diffBrainSize; 67 | 68 | debug_=debug; 69 | if (decodeDebug(debug_, 2)==1) 70 | { 71 | std::cout<<"Initialized histos"<neurons_.at(i); 83 | neuron->spontaneousRate_=parentNeuron->spontaneousRate_+mu_modConnection*0.1*(-0.5+r3->Uniform()); 84 | NeuralRelations parentNeuralRelations=parentNeuron->neuralRelations_; 85 | for (unsigned int j=0; jUniform(); 88 | if (rnd(1.-mu_newConnection/2.)) // Make a new connection 90 | { 91 | NeuralRelation *neuralRelation=new NeuralRelation; 92 | do 93 | { 94 | neuralRelation->index=int(brainSize*r3->Uniform()); 95 | } while (neuralRelation->index==i); 96 | neuralRelation->synapticStrength=r3->Uniform(); 97 | double newDistance=r3->Uniform(); 98 | // if (newDistance>0.1) 99 | { 100 | neuralRelation->distance=newDistance; 101 | neuron->push_back_relation(neuralRelation); 102 | } 103 | --j; 104 | } 105 | else // Modify the existing connection 106 | { 107 | if (parentNeuralRelations.at(j)->index < brainSize-1) 108 | { 109 | NeuralRelation *neuralRelation=new NeuralRelation; 110 | neuralRelation->index=parentNeuralRelations.at(j)->index; 111 | neuralRelation->synapticStrength=r3->Uniform(); 112 | double newDistance=(parentNeuralRelations.at(j)->distance)+mu_modConnection*(-0.5+r3->Uniform()); 113 | if (newDistance<0) newDistance=0; 114 | if (newDistance>1) newDistance=1; 115 | // if (newDistance>0.1) 116 | { 117 | neuralRelation->distance=newDistance; 118 | neuron->push_back_relation(neuralRelation); 119 | } 120 | } 121 | } 122 | } 123 | neurons_.push_back(neuron); 124 | } 125 | } 126 | else if (diffBrainSize==1) 127 | { 128 | Neuron *newNeuron=new Neuron(); 129 | for (unsigned int i=0; ineurons_.at(i); 133 | neuron->spontaneousRate_=parentNeuron->spontaneousRate_+mu_modConnection*0.1*(-0.5+r3->Uniform()); 134 | NeuralRelations parentNeuralRelations=parentNeuron->neuralRelations_; 135 | bool connectedToNewNeuron=false; 136 | for (unsigned int j=0; jUniform(); 139 | if (rnd1.-mu_newConnection/2.) // Make a new connection 141 | { 142 | NeuralRelation *neuralRelation=new NeuralRelation; 143 | do 144 | { 145 | neuralRelation->index=int((brainSize)*r3->Uniform()); 146 | } while (neuralRelation->index==i); 147 | if (neuralRelation->index==brainSize-1) connectedToNewNeuron=true; 148 | neuralRelation->synapticStrength=r3->Uniform(); 149 | double newDistance=r3->Uniform(); 150 | // if (newDistance>0.1) 151 | { 152 | neuralRelation->distance=newDistance; 153 | neuron->push_back_relation(neuralRelation); 154 | } 155 | --j; 156 | } 157 | else // Modify the existing connection 158 | { 159 | NeuralRelation *neuralRelation=new NeuralRelation; 160 | neuralRelation->index=parentNeuralRelations.at(j)->index; 161 | neuralRelation->synapticStrength=r3->Uniform(); 162 | double newDistance=(parentNeuralRelations.at(j)->distance)+mu_modConnection*(-0.5+r3->Uniform()); 163 | if (newDistance<0) newDistance=0; 164 | if (newDistance>1) newDistance=1; 165 | // if (newDistance>0.1) 166 | { 167 | neuralRelation->distance=newDistance; 168 | neuron->push_back_relation(neuralRelation); 169 | } 170 | } 171 | } 172 | neurons_.push_back(neuron); 173 | 174 | // With 50% probability do a fwd connection of the new neuron to other neurons 175 | if (connectedToNewNeuron) 176 | { 177 | NeuralRelation *neuralRelation=new NeuralRelation; 178 | neuralRelation->index=i; 179 | neuralRelation->synapticStrength=r3->Uniform(); 180 | double newDistance=r3->Uniform(); 181 | // if (newDistance>0.1) 182 | { 183 | neuralRelation->distance=newDistance; 184 | newNeuron->push_back_relation(neuralRelation); 185 | } 186 | } 187 | } 188 | neurons_.push_back(newNeuron); 189 | } 190 | 191 | if (decodeDebug(debug_, 2)==1) 192 | { 193 | for (unsigned int i=0; ineuralRelations_); 197 | for (unsigned int j=0; jsize(); ++j) 198 | { 199 | NeuralRelation *neuralRelation=neuralRelations->at(j); 200 | h_distances_->SetBinContent(i, neuralRelation->index, neuralRelation->distance); 201 | } 202 | } 203 | } 204 | } 205 | 206 | Brain::~Brain() 207 | { 208 | for (unsigned int i=0; istepInTime1(&neurons_); 225 | } 226 | for (unsigned int i=0; istepInTime2(); 229 | if (decodeDebug(debug_, 2)==1) 230 | { 231 | h_potentials_->SetBinContent(i+1, neurons_.at(i)->potential_); 232 | NeuralRelations *neuralRelations=&(neurons_.at(i)->neuralRelations_); 233 | for (unsigned int j=0; jsize(); ++j) 234 | { 235 | h_synapticStrengths_->SetBinContent(i, neuralRelations->at(j)->index, neuralRelations->at(j)->synapticStrength); 236 | } 237 | } 238 | } 239 | 240 | } 241 | 242 | void Brain::print() 243 | { 244 | for (unsigned int i=0; iprintSimple(); 247 | } 248 | std::cout<Draw("CL"); 254 | } 255 | 256 | void Brain::drawSynapticStrengths() 257 | { 258 | h_synapticStrengths_->Draw("colz"); 259 | } 260 | 261 | void Brain::drawDistances() 262 | { 263 | h_distances_->Draw("colz"); 264 | } 265 | 266 | -------------------------------------------------------------------------------- /src/Entity.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Entity 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include "../interface/Entity.h" 16 | #include "../interface/ToolBox.h" 17 | 18 | Entity::Entity(double worldSize) 19 | { 20 | worldSize_=worldSize; 21 | } 22 | 23 | void Entity::turnLeft() 24 | { 25 | theta_=checkAngle(theta_+0.1); 26 | // std::cout<<"turning left!"<worldSize_) x_=1; 39 | if (y_<0) y_=99; 40 | if (y_>worldSize_) y_=1; 41 | } 42 | 43 | void Entity::bouncyBoundaries() 44 | { 45 | if (x_<0) {x_=2; theta_=pi-theta_;} 46 | if (x_>worldSize_) {x_=worldSize_-2; theta_=pi-theta_;} 47 | if (y_<0) {y_=2; theta_=-theta_;} 48 | if (y_>worldSize_) {y_=worldSize_-2; theta_=-theta_;} 49 | } 50 | -------------------------------------------------------------------------------- /src/Fire.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Fire 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include "TMath.h" 16 | 17 | #include "../interface/Fire.h" 18 | 19 | Fire::Fire(double x, double y, double theta, double worldSize, int debug): Entity(worldSize) 20 | { 21 | x_=x; 22 | y_=y; 23 | theta_=theta; 24 | if (debug == 1) 25 | { 26 | circle_=new TEllipse(x, y, 5., 5.); 27 | circle_->SetLineColor(kRed); 28 | circle_->SetFillColor(kYellow); 29 | } 30 | } 31 | 32 | void Fire::draw() 33 | { 34 | circle_->SetX1(x_); 35 | circle_->SetY1(y_); 36 | circle_->Draw(); 37 | } 38 | 39 | void Fire::moveForward() 40 | { 41 | x_=x_+0.01*cos(theta_); 42 | y_=y_+0.01*sin(theta_); 43 | bouncyBoundaries(); 44 | } 45 | -------------------------------------------------------------------------------- /src/Food.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Food 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include "TMath.h" 16 | 17 | #include "../interface/Food.h" 18 | 19 | Food::Food(double x, double y, double theta, double worldSize, int debug): Entity(worldSize) 20 | { 21 | type_="Food"; 22 | x_=x; 23 | y_=y; 24 | theta_=theta; 25 | circle_=new TEllipse(x, y, 3., 3.); 26 | circle_->SetLineColor(kGreen+2); 27 | circle_->SetFillColor(kGreen); 28 | } 29 | 30 | Food::~Food() 31 | { 32 | circle_->Delete(); 33 | } 34 | 35 | void Food::draw() 36 | { 37 | circle_->SetX1(x_); 38 | circle_->SetY1(y_); 39 | circle_->Draw(); 40 | } 41 | 42 | void Food::moveForward() 43 | { 44 | x_=x_+0.01*cos(theta_); 45 | y_=y_+0.01*sin(theta_); 46 | bouncyBoundaries(); 47 | } 48 | -------------------------------------------------------------------------------- /src/Neuron.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================== 3 | Neuron 4 | 5 | An original simulation of a non-traditional 6 | biology-inspired neural network evolving in 7 | a naturally selective environment to demonstrate 8 | the emergence of directed survival behavior. 9 | 10 | Copyright (C) 11 November 2013 Souvik Das 11 | ALL RIGHTS RESERVED 12 | ================================================= 13 | */ 14 | 15 | #include 16 | 17 | #include "TRandom3.h" 18 | 19 | #include "../interface/Neuron.h" 20 | 21 | TRandom3 *r3=new TRandom3(); 22 | 23 | Neuron::Neuron() 24 | { 25 | activationThreshold_=0.4; 26 | synapticReinforcement_=0.8; 27 | synapticDecay_=0.999; // 0.999 28 | potentialDecay_=0.99; // 0.9 29 | 30 | potential_=0; 31 | potential_buffer_=0; 32 | spontaneousRate_=0.05; // 0.05 33 | } 34 | 35 | void Neuron::push_back_relation(NeuralRelation *relation) 36 | { 37 | neuralRelations_.push_back(relation); 38 | } 39 | 40 | void Neuron::receive(double charge) 41 | { 42 | potential_buffer_+=charge; 43 | if (potential_buffer_>1.) potential_buffer_=1.; 44 | if (potential_buffer_<-1.) potential_buffer_=-1.; 45 | } 46 | 47 | void Neuron::stepInTime1(Neurons *neurons) 48 | { 49 | if (potential_>=activationThreshold_ || r3->Rndm()synapticStrength; 53 | for (unsigned int i=0; iat(neuralRelations_.at(i)->index); 56 | double synapticStrength=neuralRelations_.at(i)->synapticStrength; 57 | targetNeuron->receive(0.5*(synapticStrength/totalSynapticWeight)*(neuralRelations_.at(i)->distance)); 58 | neuralRelations_.at(i)->synapticStrength=synapticStrength+synapticReinforcement_*(1.-synapticStrength); 59 | } 60 | potential_=0; // -0.01; 61 | // std::cout<<"Neuron fired"<synapticStrength)*=synapticDecay_; 68 | if (neuralRelations_.at(i)->synapticStrength<1e-6) (neuralRelations_.at(i)->synapticStrength)=1e-6; 69 | } 70 | potential_*=potentialDecay_; 71 | if (fabs(potential_)<1e-6) potential_=0; 72 | } 73 | } 74 | 75 | void Neuron::stepInTime2() 76 | { 77 | potential_+=potential_buffer_; 78 | potential_buffer_=0; 79 | } 80 | 81 | double Neuron::potential() 82 | { 83 | return potential_; 84 | } 85 | 86 | void Neuron::print() 87 | { 88 | std::cout<<" === Neuron Properties === "<index 95 | <<", "<synapticStrength 96 | <<", "<distance<<" | "; 97 | } 98 | std::cout<