Fixed Crossover and added variable board size
This commit is contained in:
parent
03fe944c1c
commit
00b7981c81
186
src/chess.cpp
186
src/chess.cpp
@ -18,7 +18,7 @@ int GenerateRandomNumber(int generationLimit) {
|
|||||||
|
|
||||||
GeneticRules::GeneticRules(void) {
|
GeneticRules::GeneticRules(void) {
|
||||||
boardSize = 4;
|
boardSize = 4;
|
||||||
populationSize = 1;
|
populationSize = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneticRules::GeneticRules(unsigned int boardSize, unsigned int populationSize) {
|
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) {
|
Individual::Individual(const unsigned int boardSize) {
|
||||||
generationCount = 0;
|
|
||||||
InitializeGenerator();
|
|
||||||
// population init part of vector resize
|
// population init part of vector resize
|
||||||
board.resize(boardSize, 0);
|
board.resize(boardSize, 0);
|
||||||
for (int i = 0; i < board.size(); ++i) {
|
for (int i = 0; i < board.size(); ++i) {
|
||||||
board.at(i) = GenerateRandomNumber(boardSize);
|
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) {
|
void Individual::Print(void) {
|
||||||
std::cout << generationCount << ':' << std::endl;
|
|
||||||
for (int i : board) {
|
for (int i : board) {
|
||||||
std::cout << '[';
|
std::cout << '[';
|
||||||
for (int j = 0; j < board.size(); ++j) {
|
for (int j = 0; j < board.size(); ++j) {
|
||||||
@ -48,6 +51,7 @@ void Individual::Print(void) {
|
|||||||
std::cout << ']';
|
std::cout << ']';
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the fitness of the population
|
// Gets the fitness of the population
|
||||||
@ -56,97 +60,9 @@ unsigned int Individual::GetFitness(void) {
|
|||||||
for (unsigned int i : board) {
|
for (unsigned int i : board) {
|
||||||
if (!IsQueenThreatened(i)) { fitness++; }
|
if (!IsQueenThreatened(i)) { fitness++; }
|
||||||
}
|
}
|
||||||
std::cout << fitness << std::endl;
|
|
||||||
return fitness;
|
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
|
// Checks if the passed in queen is threatened on the board
|
||||||
// Impossible for queens to be threatened by same row
|
// Impossible for queens to be threatened by same row
|
||||||
bool Individual::IsQueenThreatened(const int queenRow) {
|
bool Individual::IsQueenThreatened(const int queenRow) {
|
||||||
@ -162,3 +78,87 @@ bool Individual::IsQueenThreatened(const int queenRow) {
|
|||||||
return false;
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ void InitializeGenerator(void);
|
|||||||
int GenerateRandomNumber(int generationLimit);
|
int GenerateRandomNumber(int generationLimit);
|
||||||
|
|
||||||
struct GeneticRules {
|
struct GeneticRules {
|
||||||
const float kProbabilityCrossover = 0.7; //crossover probability (typical val.)
|
const double kProbabilityCrossover = 0.7; //crossover probability (typical val.)
|
||||||
const float kProbabilityMutation = 0.001; //mutation probability (typical val.)
|
const double kProbabilityMutation = 0.001; //mutation probability (typical val.)
|
||||||
const unsigned int generationLimit = 10000; //number of generations (something huge)
|
const unsigned int generationLimit = 10000; //number of generations (something huge)
|
||||||
unsigned int boardSize; //board size
|
unsigned int boardSize; //board size
|
||||||
unsigned int populationSize; //population size (change to something even)
|
unsigned int populationSize; //population size (change to something even)
|
||||||
@ -19,15 +19,17 @@ struct GeneticRules {
|
|||||||
class Individual {
|
class Individual {
|
||||||
public:
|
public:
|
||||||
std::vector<unsigned int> board;
|
std::vector<unsigned int> board;
|
||||||
int generationCount;
|
|
||||||
Individual(const unsigned int boardSize);
|
Individual(const unsigned int boardSize);
|
||||||
|
void Init(const unsigned int boardSize);
|
||||||
void Print(void);
|
void Print(void);
|
||||||
unsigned int GetFitness(void);
|
unsigned int GetFitness(void);
|
||||||
void Selection(void);
|
|
||||||
void Crossover(void);
|
|
||||||
void Mutation(void);
|
|
||||||
private:
|
private:
|
||||||
bool IsQueenThreatened(const int queenRow);
|
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
|
#endif // CHESS_HPP
|
||||||
|
@ -1,13 +1,39 @@
|
|||||||
#include "chess.hpp"
|
#include "chess.hpp"
|
||||||
#include "genetic_algorithm.hpp"
|
#include "genetic_algorithm.hpp"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
int main() {
|
int main(int argc, char* argv[]) {
|
||||||
|
InitializeGenerator();
|
||||||
GeneticRules genetics;
|
GeneticRules genetics;
|
||||||
std::vector<Individual> population;
|
if (argc == 2) { genetics.boardSize = atoi(argv[1]); }
|
||||||
Individual person(genetics.boardSize);
|
std::cout << "argc: " << argc << std::endl;
|
||||||
person.Print();
|
std::vector<Individual> population(genetics.populationSize, genetics.boardSize);
|
||||||
person.GetFitness();
|
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};
|
unsigned char population[N] = {0};
|
||||||
@ -21,21 +47,21 @@ int main() {
|
|||||||
init_population(population);
|
init_population(population);
|
||||||
print_population(population);
|
print_population(population);
|
||||||
|
|
||||||
while (generation_count < G) {
|
while( generation_count < G ){
|
||||||
do_selection(population, selected);
|
do_selection(population, selected);
|
||||||
do_crossover(population, selected);
|
do_crossover(population, selected);
|
||||||
do_mutation(population);
|
do_mutation(population);
|
||||||
printf("%4d: ", generation_count);
|
printf("%4d: ", generation_count);
|
||||||
print_population(population);
|
print_population(population);
|
||||||
for (i = 0; i < N; i++) {
|
for( i=0; i<N; i++){
|
||||||
if (population[i] == 0xFF) {
|
if (population[i]==0xFF){
|
||||||
printf("Max fit reached.\n");
|
printf("Max fit reached.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
generation_count++;
|
generation_count++;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user