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) {
|
||||
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) = 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) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
@ -21,21 +47,21 @@ int main() {
|
||||
init_population(population);
|
||||
print_population(population);
|
||||
|
||||
while (generation_count < G) {
|
||||
while( generation_count < G ){
|
||||
do_selection(population, selected);
|
||||
do_crossover(population, selected);
|
||||
do_mutation(population);
|
||||
printf("%4d: ", generation_count);
|
||||
print_population(population);
|
||||
for (i = 0; i < N; i++) {
|
||||
if (population[i] == 0xFF) {
|
||||
for( i=0; i<N; i++){
|
||||
if (population[i]==0xFF){
|
||||
printf("Max fit reached.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
generation_count++;
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user