Skip to content

Instantly share code, notes, and snippets.

@FONQRI
Created January 30, 2018 12:08
Show Gist options
  • Save FONQRI/856f1943fd5857752e5722b866e6ff85 to your computer and use it in GitHub Desktop.
Save FONQRI/856f1943fd5857752e5722b866e6ff85 to your computer and use it in GitHub Desktop.
Little example of how genetic algorithms can work in c++
#include <algorithm>
#include <chrono>
#include <cmath>
#include <iostream>
#include <thread>
#include <time.h>
#include <vector>
// lets create a population
struct Member {
std::string DNA;
size_t Fitness;
};
struct Population {
// this will create a population with 50k
// members, lets choose a lower number first
// to see the progress, works fine...
std::vector<Member> Members = std::vector<Member>(5000);
};
int main()
{
// for this example we are going to use a string as a kind of "goal" to
// achieve
std::string DNA =
"I am a DNA string that needs to be found, shall happen soon!";
bool sequenceFound{false};
std::string sequenceString{""};
// We are going to use this for mutation of genes
// 1000 = 100% 1 = .01% mutation rate
int mutationRate{25};
srand(static_cast<unsigned int>(time(NULL)));
// create a population and initialize it with random DNA, also set the
// fitness to 0
Population Pop;
for (auto &member : Pop.Members) {
member.DNA.resize(DNA.size());
for (size_t j = 0; j < DNA.size(); j++) {
member.DNA.at(j) =
static_cast<char>(std::abs(rand() % 96 + 32));
}
member.Fitness = 0;
}
std::clog << "initializing done !" << std::endl;
// we will use a variable to keep track of how many generations there have
// been
int generation = 0;
// our actuall work will be inside this loop, it will stop when the DNA
// sequence has fully evolved to the target
while (!sequenceFound) {
generation++;
// clear out the fitness here and then reevaluate for each
// member, also check if fitness has reached maximum
for (auto &member : Pop.Members) {
member.Fitness = 0;
for (size_t j = 0; j < member.DNA.size(); j++) {
if (member.DNA.at(j) == DNA.at(j)) {
member.Fitness += 10;
}
}
if (member.Fitness == DNA.size() * 10)
sequenceFound = true;
sequenceString = member.DNA;
}
// now lets sort the population by fitness, from highest to lowest
std::sort(Pop.Members.begin(), Pop.Members.end(),
[](Member const &a, Member &b) {
return a.Fitness > b.Fitness;
});
// select x amount of highest fitness members to pair from, lets use
// 2 parents in this case
std::vector<Member> Parents{Pop.Members.at(0), Pop.Members.at(1)};
// lets do some gene permutation and mating
for (auto &member : Pop.Members) {
for (size_t j = 0; j < member.DNA.size(); j++) {
// lets use an equal chance to take each parents
// gene (on a per gene basis)
size_t TempSelection = static_cast<size_t>(
static_cast<size_t>(rand()) % Parents.size());
member.DNA.at(j) =
Parents.at(TempSelection).DNA.at(j);
// dont forget to apply random mutation based on
// our value from above
if (rand() % 1000 < mutationRate) {
member.DNA.at(j) = static_cast<char>(
std::abs(rand() % 96 + 32));
}
}
}
// lets print some stuff
std::cout << "generation : " << generation
<< " Highest Fitness : " << Parents.at(0).Fitness
<< " With Sequence : " << Parents.at(0).DNA.c_str()
<< std::endl;
}
std::cout << "generation " << generation << " Evolved to the full sequence"
<< std::endl;
std::cout << "sequenceFound :" << sequenceFound << std::endl;
std::cout << "sequence DNA :" << sequenceString << std::endl;
return 0;
}
// done... :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment