Skip to content

Instantly share code, notes, and snippets.

@KangDroid
Last active October 24, 2020 05:51
Show Gist options
  • Save KangDroid/c6fbdd9aa757a42e7c52d97269fc2ecd to your computer and use it in GitHub Desktop.
Save KangDroid/c6fbdd9aa757a42e7c52d97269fc2ecd to your computer and use it in GitHub Desktop.
AI-Genetic Algorithm Simulator[ONLY FOR EDUCATIONAL PURPOSE]
/*
* Copyright (c) 2020 KangDroid, aka Jason.HW.Kang[HyunWoo Kang]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <iomanip>
#include <vector>
//#define DEBUG
using namespace std;
class Elements {
public:
string number;
string population;
int x_value;
int fitness_value;
double pselect;
double expected_count;
int actual_count;
// After Muating info
string mate;
int crossover_site;
string after_mut;
int after_x;
int after_fitness;
Elements(string num, string value) {
this->number = num;
this->population = value;
this->x_value = 0;
this->fitness_value = 0;
this->pselect = 0;
this->expected_count = 0;
this->actual_count = 0;
this->init();
}
string getInfo() {
return this->number + "\t" + this->population + "\t" + to_string(this->x_value) + "\t" + to_string(this->fitness_value) + "\t" + to_string(this->pselect) + "\t" + to_string(this->expected_count) + "\t" + to_string(this->actual_count);
}
int round_expected() {
return (int)(this->expected_count + 0.5);
}
void init() {
int tmp = 0;
for (int i = population.length() - 1; i >= 0; i--) {
x_value += pow(2, tmp) * (population.at(i)-'0');
tmp++;
}
this->fitness_value = x_value * x_value;
}
void after_init(string apop, string mate, int cs) {
this->after_mut = apop;
this->mate = mate;
this->crossover_site = cs;
this->after_x = 0;
int tmp = 0;
for (int i = after_mut.length() - 1; i >= 0; i--) {
after_x += pow(2, tmp) * (after_mut.at(i)-'0');
tmp++;
}
this->after_fitness = after_x * after_x;
}
string after_info() {
return this->population + "\t" + (this->mate) + "\t" + to_string(this->crossover_site) + "\t" + this->after_mut + "\t" + to_string(this->after_x) + "\t" + to_string(this->after_fitness);
}
/**
* Migrate from mutated --> normal state
*/
void migrate() {
// Name remains the same.
this->population = this->after_mut;
this->x_value = 0;
this->fitness_value = 0;
this->pselect = 0;
this->expected_count = 0;
this->actual_count = 0;
this->init();
// Reset after variables
this->mate = "";
this->crossover_site = 0;
this->after_mut = "";
this->after_x = 0;
this->after_fitness = 0;
}
private:
};
bool compare(Elements a, Elements b) {
return a.expected_count > b.expected_count;
}
bool compare_number(Elements a, Elements b) {
return a.number < b.number;
}
typedef struct avrgmax {
double sum = 0;
double avrg = 0;
double max = 0;
} Avrgmax;
int main(void) {
srand(time(NULL));
// COUT
cout.precision(4);
vector<int> overall_value;
// Pushing back
vector<Elements> element_container;
element_container.push_back(Elements("1", "01101"));
element_container.push_back(Elements("2", "11000"));
element_container.push_back(Elements("3", "01000"));
element_container.push_back(Elements("4", "10011"));
for (int iteration_value = 0; iteration_value < 1000; iteration_value++) {
cout << "Gen. " << iteration_value+1 << endl;
// Fitness Area
Avrgmax fitness;
// PSelect Area
Avrgmax pselect;
// Expected CTR Area
Avrgmax expctctr;
// RWS Area
Avrgmax rws;
vector<Elements> selected_vector;
for (int i = 0; i < element_container.size(); i++) {
fitness.sum += element_container[i].fitness_value;
if (fitness.max < element_container[i].fitness_value) {
fitness.max = element_container[i].fitness_value;
}
}
overall_value.push_back(fitness.sum);
int tmp_sum = 0;
for (int i = 0; i < element_container.size(); i++) {
element_container[i].pselect = (double)(element_container[i].fitness_value) / fitness.sum;
element_container[i].expected_count = element_container[i].pselect * element_container.size();
if (element_container[i].round_expected() > 2) {
// Needs to be 2
element_container[i].actual_count = 2;
tmp_sum += 2;
} else {
element_container[i].actual_count = element_container[i].round_expected();
tmp_sum += element_container[i].actual_count;
}
// SUMS
pselect.sum +=element_container[i].pselect;
expctctr.sum += element_container[i].expected_count;
if (expctctr.max < element_container[i].expected_count) {
expctctr.max = element_container[i].expected_count;
}
if (pselect.max < element_container[i].pselect) {
pselect.max = element_container[i].pselect;
}
}
if (tmp_sum < 4) {
sort(element_container.begin(), element_container.end(), compare);
// Select Counter
for (int i = 0; i < element_container.size(); i++) {
if (element_container[i].actual_count < 2) {
element_container[i].actual_count++;
tmp_sum++;
}
if (tmp_sum == 4) {
break;
}
}
sort(element_container.begin(), element_container.end(), compare_number);
} else if (tmp_sum > 4) {
tmp_sum = 0;
for (int i = 0; i < element_container.size(); i++) {
element_container[i].actual_count = 0;
}
sort(element_container.begin(), element_container.end(), compare);
// Select Counter
for (int i = 0; i < element_container.size(); i++) {
if (element_container[i].round_expected() >= 2) {
if (tmp_sum + element_container[i].round_expected() > 4) {
element_container[i].actual_count = element_container[i].round_expected()-1;
tmp_sum += element_container[i].round_expected()-1;
} else {
element_container[i].actual_count = element_container[i].round_expected();
tmp_sum += element_container[i].round_expected();
}
} else {
element_container[i].actual_count = element_container[i].round_expected();
tmp_sum += element_container[i].round_expected();
}
if (tmp_sum == 4) {
break;
}
}
sort(element_container.begin(), element_container.end(), compare_number);
}
for (int i = 0; i < element_container.size(); i++) {
rws.sum += element_container[i].actual_count;
if (rws.max < element_container[i].actual_count) {
rws.max = element_container[i].actual_count;
}
}
for (int i = 0; i < element_container.size(); i++) {
cout << element_container[i].getInfo() << endl;
}
// Update AvrgMax
fitness.avrg = fitness.sum / (double)element_container.size();
pselect.avrg = pselect.sum / (double)element_container.size();
expctctr.avrg = expctctr.sum / (double)element_container.size();
rws.avrg = rws.sum / (double)element_container.size();
cout << endl;
cout << "\t\t\t" << fitness.sum << "\t" << to_string(pselect.sum) << "\t" << to_string(expctctr.sum) << "\t" << rws.sum << endl;
cout << "\t\t\t" << fitness.avrg << "\t" << to_string(pselect.avrg) << "\t" << to_string(expctctr.avrg) << "\t" << rws.avrg << endl;
cout << "\t\t\t" << fitness.max << "\t" << to_string(pselect.max) << "\t" << to_string(expctctr.max) << "\t" << rws.max << endl;
// MUTATE
// Select element to select(what?)
for (int i = 0; i < element_container.size(); i++) {
for (int j = 0; j < element_container[i].actual_count; j++) {
selected_vector.push_back(element_container[i]);
}
}
// Making Pair
int cur = 0;
bool is_done[selected_vector.size()];
vector<string> pair_vector;
while (pair_vector.size() < 2) {
int start = rand() % selected_vector.size();
int end = rand() % selected_vector.size();
if (is_done[start] || is_done[end] || start == end) {
continue;
}
if (selected_vector[start].number == selected_vector[end].number) {
// Reset is_done vector and empty pair_vector
pair_vector.clear();
for (int i = 0; i < selected_vector.size(); i++) {
is_done[i] = false;
}
continue;
}
if (start < end) {
pair_vector.push_back(to_string(start) + ", " + to_string(end));
} else {
pair_vector.push_back(to_string(end) + ", " + to_string(start));
}
is_done[start] = true;
is_done[end] = true;
}
#ifdef DEBUG
//Checking Pair
for (int i = 0; i < pair_vector.size(); i++) {
cout << pair_vector[i] << endl;
}
#endif
// Now mutate..
for (int i = 0; i < pair_vector.size(); i++) {
// Randomize location
int random_location = rand() % 3 + 1;
#ifdef DEBUG
cout << "Doing for: " << pair_vector[i] << endl;
cout << "Random location: " << random_location << endl;
#endif
// left/right = Each element's indexx
int left = stoi(pair_vector[i].substr(0, pair_vector[i].find(", ")));
int right = stoi(pair_vector[i].substr(pair_vector[i].find(", ")+ 2, pair_vector[i].length()));
#ifdef DEBUG
cout << "left: " << left << " right: " << right << endl;
#endif
// Split left population by random location
string left_population = element_container[left].population;
#ifdef DEBUG
cout << "BEFORE LEFT: " << left_population << endl;
#endif
string left_left = left_population.substr(0, random_location);
string left_right = left_population.substr(random_location, left_population.length() - random_location);
// Split right population by random location
string right_population = element_container[right].population;
#ifdef DEBUG
cout << "BEFORE RIGHT: " << right_population << endl;
#endif
string right_left = right_population.substr(0, random_location);
string right_right = right_population.substr(random_location, right_population.length() - random_location);
#ifdef DEBUG
cout << "New Mutation: " << left_left + right_right << endl;
cout << "New Mutation: " << right_left + left_right << endl;
#endif
// Update element
element_container[left].after_init(left_left + right_right, element_container[right].number, random_location);
element_container[right].after_init(right_left + left_right, element_container[left].number, random_location);
}
#ifdef DEBUG
// Checking Pair
for (int i = 0; i < pair_vector.size(); i++) {
cout << pair_vector[i] << endl;
}
#endif
cout << endl;
for (int i = 0; i < element_container.size(); i++) {
cout << element_container[i].after_info() << endl;
element_container[i].migrate();
}
cout << endl << endl;
}
for (int i = 0; i < overall_value.size(); i++) {
cout << overall_value[i] << endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment