Skip to content

Commit

Permalink
Final touches and update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Pikurrot committed Feb 19, 2023
1 parent fbda5f6 commit 5173063
Show file tree
Hide file tree
Showing 18 changed files with 56 additions and 65 deletions.
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
Debug
__pycache__
.vs
images
x64
simulations
python_files/NN_visualizer.py
python_files/natural_selection_(outdated).py
Binary file added Natural-Selection-Proj.exe
Binary file not shown.
44 changes: 41 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ Prey are represented as green dots. The field of view of a prey, represented as

The properties of prey are as follows:
- A wide yet short field of view
- The split charge restores over time. Once it has reached a certain period, they split.
- When their energy drops to 0, they must rest and not move until they have reached a minimum level of energy.
- The split charge restores over time. Once it has reached a certain period, they split
- When their energy drops to 0, they must rest and not move until they have reached a minimum level of energy
- They can also move backwards

## Predators
Predators are represented as red dots, and their field of view is shown in the next image.
Expand All @@ -30,7 +31,8 @@ The properties of predators are as follows:
- The ability to eat prey, recover energy, and fill their split charge
- The split charge empties over time
- When their energy drops to 0, they die
- After eating, they have a digestion period during which they cannot restore energy or split charge. This is to prevent massive and pointless over-reproduction of predators when hunting large prey colonies.
- After eating, they have a digestion period during which they cannot restore energy or split charge. This is to prevent massive and pointless over-reproduction of predators when hunting large prey colonies
- They can only move forward

## Neural network
All entities possess an artificial neural network as their brain. The inputs to the network are the lidar rays of the field of view, and the outputs are the entity's speed and angular velocity. The neural network has weights (represented in orange if w > 0), biases (the neuron is filled if b > 0), and activation functions (tanh).
Expand Down Expand Up @@ -79,3 +81,39 @@ Here are some observations made during the simulation:
# Conclusion
Survival in this environment is a daunting task, and in most simulations, the entities do not overcome the second crisis. The constant parameters such as energy depletion, maximum speed, and field of view range have been meticulously adjusted to enhance survival. However, after numerous simulations, the pattern described above remains consistent. The best-adapted individuals that can cope with the prevailing conditions tend to survive longer.
> "It is not the strongest of the species that survives, nor the most intelligent that survives. It is the one that is the most adaptable to change." - Charles Darwin
# How to run the simulator
The project has been done in 2 languages: C++ for running and building the simulation, and Python for visualizing it in a vide-like format. You can visualize an already run simulation, run a new simulation with fixed parameters, or adjust the parameters, build and run the simulation.

## Visualize an already run simulation
### Requirements
Apart from Python 3, the following python libraries are required to be installed:
- numpy (1.19.5)
- pygame (2.1.2)
### Steps
1. Go to `python_files/` directory.
2. Run the `natural_selection_interface.py` program with python.
3. A pygame window, named "Simulation", should open. Here you can visualize the simulation.

## Run a new simulation with fixed parameters
### Requirements
- The same as in "Visualize an already run simulation".
### Steps
1. Run `Natural-Selection-Proj.exe` to run a new simulation. This might take a few minutes, depending on the computer.
2. The simulation will be automatically saved in `simulations/` in 2 files: `simulation1.bin` and `neural_nets1.bin`. So open `python_files/natural_selection_interface.py` to edit the code and change the `file_num` to `"1"` in line 234.
3. Run `natural_selection_interface.py` again to visualize the new simulation.

## Adjust the parameters, build and run a new simulation
### Requirements
- C++ installed, as well as the compiler.
- An IDE (such as Visual Studio) to edit the code, build and compile the project.
- The same as in "Visualize an already run simulation".
### Steps
1. Open the repository folder with the IDE and access the `cpp_files/`.
2. Edit the parameters you want. These are found in `entity.h`, `prey.h`, `predator.h`, `neural_network.h` and `main.cpp`. In the header files, the parameters are the ones that are `static` in the class declaration.
3. You can optionally change the `file_num` parameter in `main.cpp` and in `python_files/natural_selection_interface.py`, so that the simulation is saved in another file instead of replacing the old ones. You will also have to create a new `simulation<x>.bin` and `neural_nets<x>.bin` in the `simulations/` folder. For example, if `file_num = 2`, then name the files `simulation2.bin` and `neural_nets2.bin`.
4. Build and compile the project. Find the `Natural-Selection-Proj.exe` file (probably in `x64/Debug/`), copy it and paste it to the repository folder, replacing the old one.
5. Do the same as in "Run a new simulation with fixed parameters".

# References
[Evolving AIs - Predator vs Prey, who will win?](https://www.youtube.com/watch?v=qwrp3lB-jkQ)
12 changes: 6 additions & 6 deletions cpp_files/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

using namespace std;

constexpr int MAP_W = 2500;
constexpr int MAP_H = 1800;
constexpr int MAX_PREYS = 900;
constexpr int MAX_PREDATORS = 500;
constexpr int STARTING_PREYS = 300;
constexpr int STARTING_PREDATORS = 250;
constexpr int MAP_W = 1600;
constexpr int MAP_H = 1400;
constexpr int MAX_PREYS = 800;
constexpr int MAX_PREDATORS = 400;
constexpr int STARTING_PREYS = 150;
constexpr int STARTING_PREDATORS = 50;
2 changes: 0 additions & 2 deletions cpp_files/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <random>
#include <iostream>
#include <string>
#include <Eigen/Dense>
#include <chrono>
#include "constants.h"
#include "functions.h"
Expand Down Expand Up @@ -126,7 +125,6 @@ float ang(float x1, float y1, float x2, float y2)

void activationFunction1(float &x)
{
// x = 1/(1+pow(M_E,-x));
float a = 2.5;
x = (pow(a, x) - pow(a, -x)) / (pow(a, x) + pow(a, -x));
}
Expand Down
2 changes: 1 addition & 1 deletion cpp_files/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main()

N = 30000;

file_num = "2";
file_num = "1";
sim_file.open("simulations/simulation" + file_num + ".bin", ios::binary);
brains_file.open("simulations/neural_nets" + file_num + ".bin", ios::binary);

Expand Down
55 changes: 6 additions & 49 deletions cpp_files/neural_network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,6 @@ NeuralNetwork::NeuralNetwork(int n_inputs, NeuralNetwork *parent)
biases = parent->biases;
}

/*for (l = 0; l < N_LAYERS; l++)
{
if (weights[l].size() == 0)
{
cout << "constructor: " << endl;
cout << this << ": " << l << " " << weights[l].size() << endl;
cout << N_LAYERS << endl;
cout << weights.size() << " " << weights[0].size() << " " << weights[1].size() << " " << weights[2].size() << endl;
cout << count << endl;
}
}*/

history.push_back(this);
count++;
}
Expand Down Expand Up @@ -86,19 +74,6 @@ vector<unsigned __int32> NeuralNetwork::getEncodedInfo()
unsigned __int32 val;
vector<unsigned __int32> encoded_info, encoded_w, encoded_b;

/*for (layer = 0; layer < N_LAYERS; layer++)
{
if (weights[layer].size() == 0)
{
cout << "getEncodedInfo: " << endl;
cout << this << ": " << layer << " " << weights[layer].size() << endl;
cout << N_LAYERS << endl;
cout << weights.size() << " " << weights[0].size() << " " << weights[1].size() << " " << weights[2].size() << endl;
cout << count << endl;
}
}*/

//cout << "0";
for (layer = 0; layer < N_LAYERS + 1; layer++)
{
val = 0;
Expand All @@ -107,27 +82,9 @@ vector<unsigned __int32> NeuralNetwork::getEncodedInfo()

if (layer == 0) n_neurons = n_inputs;
else n_neurons = N_NEURONS[layer - 1];
//cout << "1";

for (neuron = 0; neuron < n_neurons; neuron++)
{
//cout << layer << " " << weights[layer].size() << " " << neuron << "|";
/*if (weights[layer].size() == 0)
{
cout << this << ": " << n_neurons << " " << layer << " " << weights[layer].size() << " " << neuron << endl;
cout << weights.size() << " " << weights[0].size() << " " << weights[1].size() << " " << weights[2].size() << endl;
cout << count << endl;
cout << history.size() << endl;
cout << history[count - 1] << endl;
if (find(history.begin(), history.end(), this) != history.end())
{
cout << this << " is in the vector." << endl;
}
else
{
cout << this << " is not in the vector." << endl;
}
}*/
for (w = 0; w < weights[layer][neuron].size(); w++)
{
if (j == 32)
Expand All @@ -146,7 +103,7 @@ vector<unsigned __int32> NeuralNetwork::getEncodedInfo()
j++;
}
}
//cout << "2";

while (i < 4)
{
encoded_w.push_back(val);
Expand All @@ -159,7 +116,7 @@ vector<unsigned __int32> NeuralNetwork::getEncodedInfo()

if (layer == N_LAYERS) n_neurons = 2;
else n_neurons = N_NEURONS[layer];
//cout << "3";

for (b = 0; b < biases[layer].size(); b++)
{
if (biases[layer][b] != 0)
Expand All @@ -169,15 +126,15 @@ vector<unsigned __int32> NeuralNetwork::getEncodedInfo()

j++;
}
//cout << "4";

encoded_b.push_back(val);

}
//cout << "5";

encoded_info.reserve(encoded_w.size() + encoded_b.size());
encoded_info.insert(encoded_info.end(), encoded_w.begin(), encoded_w.end());
encoded_info.insert(encoded_info.end(), encoded_b.begin(), encoded_b.end());
//cout << "6";

return encoded_info;
}

Expand Down
Binary file added python_files/images/backward.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python_files/images/forward.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python_files/images/next.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python_files/images/pause.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python_files/images/play.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python_files/images/previous.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions python_files/natural_selection_interface.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np
import pygame
from math import pi, sin, cos, sqrt, atan2
from math import sqrt
from abc import ABC, abstractmethod

def sign(x):
Expand Down Expand Up @@ -231,7 +231,7 @@ def update_screen(tick):
draw_interface(tick)
pygame.display.update()

file_num = "2"
file_num = "0"
# read raw data
with open("simulations/simulation" + file_num + ".bin", "rb") as sim_file:
binary_data = sim_file.read()
Expand Down
Binary file added simulations/neural_nets0.bin
Binary file not shown.
Binary file added simulations/neural_nets1.bin
Binary file not shown.
Binary file added simulations/simulation0.bin
Binary file not shown.
Binary file added simulations/simulation1.bin
Binary file not shown.

0 comments on commit 5173063

Please sign in to comment.