#include "chess.hpp" #include #include #include std::default_random_engine generator; void InitializeGenerator(void) { generator.seed(std::random_device{}()); } int GenerateRandomNumber(int generationLimit) { int generatedNumber; std::uniform_int_distribution<> distribution(0, generationLimit - 1); generatedNumber = distribution(generator); return generatedNumber; } GeneticRules::GeneticRules(void) { boardSize = 4; populationSize = 8; } GeneticRules::GeneticRules(unsigned int boardSize, unsigned int populationSize) { this->boardSize = boardSize; this->populationSize = populationSize; } Individual::Individual(const unsigned int boardSize) { // population init part of vector resize board.resize(boardSize, 0); for (int i = 0; i < board.size(); ++i) { board.at(i) = 0; } } void Individual::Init(const unsigned int boardSize) { for (int i = 0; i < board.size(); ++i) { board.at(i) = GenerateRandomNumber(boardSize); } } void Individual::Print(void) { for (int i : board) { std::cout << '['; for (int j = 0; j < board.size(); ++j) { if (j == i) { std::cout << "Q"; } else { std::cout << ' '; } } std::cout << ']'; std::cout << std::endl; } std::cout << std::endl; } // Gets the fitness of the population unsigned int Individual::GetFitness(void) { unsigned int fitness = 0; for (unsigned int i : board) { if (!IsQueenThreatened(i)) { fitness++; } } return fitness; } // Checks if the passed in queen is threatened on the board // Impossible for queens to be threatened by same row bool Individual::IsQueenThreatened(const int queenRow) { int queenCol = board.at(queenRow); int diffRow, diffCol; for (int row = 0; row < board.size(); ++row) { if (row == queenRow) { continue; } diffCol = abs(queenCol - (int)board.at(row)); diffRow = abs(queenRow - row); if (diffCol == 0) { return true; } // Column threat if (diffCol == diffRow) { return true; } } return false; } void PrintPopulation(std::vector population) { for (int i = 0; i < population.size(); ++i) { std::cout << "Individual " << i << ':' << std::endl; population[i].Print(); } } // void Selection(std::vector &population, std::vector &selected) { std::vector fitness(population.size(), 0); int fitness_sum = 0; // get fitness for all members of population for (int i = 0; i < population.size(); ++i ){ fitness.at(i) = population.at(i).GetFitness(); fitness_sum += fitness.at(i); } // this is simple fitness proportional selection // (roulette wheel sampling) int roll; int temp_sum = 0; int selection; for (int i = 0; i < population.size(); ++i) { temp_sum = 0; roll = GenerateRandomNumber(fitness_sum); for (int j = 0; j < population.size(); j++){ temp_sum += fitness.at(j); if ( roll < temp_sum ){ selection = j; break; } } selected.at(i) = selection; } } // Crossover on the population void Crossover(std::vector &population, std::vector &selected, const GeneticRules genetics) { double crossover_roll; int crossover_locus; std::vector temp_population(genetics.populationSize, genetics.boardSize); for (int i = 0; i < genetics.populationSize; i +=2) { crossover_roll = ((double) GenerateRandomNumber(RAND_MAX)) / ((double) RAND_MAX); if (crossover_roll <= genetics.kProbabilityCrossover) { //crossover crossover_locus = GenerateRandomNumber(genetics.boardSize); for (int j = 0; j < crossover_locus; ++j) { temp_population.at(i).board.at(j) = population.at(selected.at(i)).board.at(j); temp_population.at(i+1).board.at(j) = population.at(selected.at(i+1)).board.at(j); } for (int j = crossover_locus; j < genetics.boardSize; ++j) { temp_population.at(i).board.at(j) = population.at(selected.at(i+1)).board.at(j); temp_population.at(i+1).board.at(j) = population.at(selected.at(i)).board.at(j); } } else { //clone for (int j = 0; j < genetics.boardSize; ++j) { temp_population.at(i).board.at(j) = population.at(selected.at(i)).board.at(j); temp_population.at(i+1).board.at(j) = population.at(selected.at(i+1)).board.at(j); } } } //copy back to population for (int i = 0; i < population.size(); i++) { population[i] = temp_population[i]; } } // Mutates the population void Mutation(std::vector &population, const GeneticRules genetics) { double mutation_roll; int i, j; for (i = 0; i < population.size(); ++i){ for (j = 0; j < population[0].board.size(); ++j ){ mutation_roll = ((double) GenerateRandomNumber(RAND_MAX)) / ((double) RAND_MAX); if (mutation_roll <= genetics.kProbabilityMutation){ population[i].board.at(j) = GenerateRandomNumber(population[0].board.size()); //toggle bit } } } }