Fixed Crossover and added variable board size

This commit is contained in:
TriantaTV 2023-09-24 23:19:07 -05:00
parent 03fe944c1c
commit 00b7981c81
3 changed files with 137 additions and 109 deletions

View File

@ -18,7 +18,7 @@ int GenerateRandomNumber(int generationLimit) {
GeneticRules::GeneticRules(void) {
boardSize = 4;
populationSize = 1;
populationSize = 8;
}
GeneticRules::GeneticRules(unsigned int boardSize, unsigned int populationSize) {
@ -27,18 +27,21 @@ GeneticRules::GeneticRules(unsigned int boardSize, unsigned int populationSize)
}
Individual::Individual(const unsigned int boardSize) {
generationCount = 0;
InitializeGenerator();
// 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) {
std::cout << generationCount << ':' << std::endl;
for (int i : board) {
std::cout << '[';
for (int j = 0; j < board.size(); ++j) {
@ -48,6 +51,7 @@ void Individual::Print(void) {
std::cout << ']';
std::cout << std::endl;
}
std::cout << std::endl;
}
// Gets the fitness of the population
@ -56,97 +60,9 @@ unsigned int Individual::GetFitness(void) {
for (unsigned int i : board) {
if (!IsQueenThreatened(i)) { fitness++; }
}
std::cout << fitness << std::endl;
return fitness;
}
//
void Individual::Selection(void) {
/* TODO: Finish selection
int fitness[N] = {0};
int fitness_sum = 0;
int i, j;
// get fitness for all members of population
for ( i=0; i<N; i++ ){
fitness[i] = get_fitness(population[i]);
fitness_sum += fitness[i];
}
// this is simple fitness proportional selection
// (roulette wheel sampling)
int roll;
int temp_sum = 0;
int selection;
for ( i=0; i<N; i++ ){
temp_sum = 0;
roll = rand()%fitness_sum;
for ( j=0; j<N; j++ ){
temp_sum += fitness[j];
if ( roll < temp_sum ){
selection = j;
break;
}
}
selected[i] = selection;
}
*/
}
// Crossover on the population
void Individual::Crossover(void) {
/* TODO: Finish Crossover
double crossover_roll;
int crossover_locus;
int i;
unsigned char temp1;
unsigned char temp2;
unsigned char mask;
unsigned char temp_population[N];
for ( i=0; i<N; i+=2){
crossover_roll = ((double)rand())/((double)RAND_MAX);
temp1 = 0;
temp2 = 0;
if(crossover_roll <= P_c){ //crossover
crossover_locus = rand()%L;
mask = get_mask(crossover_locus);
temp1 = population[selected[i]] & mask;
temp1 ^= population[selected[i+1]] & ~mask;
temp2 = population[selected[i+1]] & mask;
temp2 ^= population[selected[i]] & ~mask;
temp_population[i] = temp1;
temp_population[i+1] = temp2;
}
else{ //clone
temp_population[i] = population[selected[i]];
temp_population[i+1] = population[selected[i+1]];
}
}
//copy back to population
for ( i=0; i<N; i++ ){
population[i] = temp_population[i];
}
*/
}
// Mutates the population
void Individual::Mutation(void) {
/* TODO: Finish Mutation
double mutation_roll;
int i, j;
for ( i=0; i<N; i++){
for ( j=0; j<L; j++ ){
mutation_roll = ((double)rand())/((double)RAND_MAX);
if ( mutation_roll <= P_m ){
population[i] ^= (1<<j); //toggle bit
}
}
}
*/
}
// 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) {
@ -162,3 +78,87 @@ bool Individual::IsQueenThreatened(const int queenRow) {
return false;
}
void PrintPopulation(std::vector<Individual> population) {
for (int i = 0; i < population.size(); ++i) {
std::cout << "Individual " << i << ':' << std::endl;
population[i].Print();
}
}
//
void Selection(std::vector<Individual> &population, std::vector<int> &selected) {
std::vector<int> 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<Individual> &population, std::vector<int> &selected, const GeneticRules genetics) {
double crossover_roll;
int crossover_locus;
std::vector<Individual> 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<Individual> &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
}
}
}
}

View File

@ -7,8 +7,8 @@ void InitializeGenerator(void);
int GenerateRandomNumber(int generationLimit);
struct GeneticRules {
const float kProbabilityCrossover = 0.7; //crossover probability (typical val.)
const float kProbabilityMutation = 0.001; //mutation probability (typical val.)
const double kProbabilityCrossover = 0.7; //crossover probability (typical val.)
const double kProbabilityMutation = 0.001; //mutation probability (typical val.)
const unsigned int generationLimit = 10000; //number of generations (something huge)
unsigned int boardSize; //board size
unsigned int populationSize; //population size (change to something even)
@ -19,15 +19,17 @@ struct GeneticRules {
class Individual {
public:
std::vector<unsigned int> board;
int generationCount;
Individual(const unsigned int boardSize);
void Init(const unsigned int boardSize);
void Print(void);
unsigned int GetFitness(void);
void Selection(void);
void Crossover(void);
void Mutation(void);
private:
bool IsQueenThreatened(const int queenRow);
};
void PrintPopulation(std::vector<Individual> population);
void Selection(std::vector<Individual> &population, std::vector<int> &selected);
void Crossover(std::vector<Individual> &population, std::vector<int> &selected, const GeneticRules genetics);
void Mutation(std::vector<Individual> &population, const GeneticRules genetics);
#endif // CHESS_HPP

View File

@ -1,13 +1,39 @@
#include "chess.hpp"
#include "genetic_algorithm.hpp"
#include <cstdlib>
#include <iostream>
#include <vector>
int main() {
int main(int argc, char* argv[]) {
InitializeGenerator();
GeneticRules genetics;
std::vector<Individual> population;
Individual person(genetics.boardSize);
person.Print();
person.GetFitness();
if (argc == 2) { genetics.boardSize = atoi(argv[1]); }
std::cout << "argc: " << argc << std::endl;
std::vector<Individual> population(genetics.populationSize, genetics.boardSize);
for (int i = 0; i < genetics.populationSize; ++i) { population[i].Init(genetics.boardSize); }
std::vector<int> selected(genetics.populationSize, -1);
int generationCount = 0;
std::cout << generationCount << ':' << std::endl;
PrintPopulation(population);
while (generationCount < genetics.generationLimit) {
Selection(population, selected);
Crossover(population, selected, genetics);
Mutation(population, genetics);
std::cout << generationCount << ':' << std::endl;
PrintPopulation(population);
for (auto i : population) {
if (i.GetFitness() == genetics.boardSize) {
std::cout << "Max fit reached." << std::endl;
return 0;
}
}
++generationCount;
}
if (generationCount == genetics.generationLimit) {
std::cout << "Generation limit reached." << std::endl;
}
return 0;
/*
unsigned char population[N] = {0};
@ -35,7 +61,7 @@ int main() {
}
generation_count++;
}
*/
return 0;
*/
}