Initial file setup for project

This commit is contained in:
TriantaTV 2023-09-23 22:52:21 -05:00
parent c872462c97
commit 8f62df2f1f
7 changed files with 205 additions and 4 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.10)
project(
n-queens
n_queens
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11 CACHE STRING "The C++ standard to use")

View File

@ -1,6 +1,8 @@
add_executable(n-queens
./n-queens.cpp
add_executable(n_queens
./n_queens.cpp
./chess.cpp
./genetic_algorithm.cpp
)
target_include_directories(n-queens PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_include_directories(n_queens PUBLIC ${CMAKE_CURRENT_LIST_DIR})

0
src/chess.hpp Normal file
View File

145
src/genetic_algorithm.cpp Normal file
View File

@ -0,0 +1,145 @@
#include "genetic_algorithm.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Prints the population strings in a line */
void print_population(unsigned char population_in[]) {
int iterator = 0;
int member_count = 0;
char cur_member;
while (member_count < N){
cur_member = population_in[member_count];
while (iterator < L){
if (cur_member & 0x80){
printf("1");
}
else{
printf("0");
}
cur_member = cur_member << 1;
iterator++;
}
member_count++;
iterator = 0;
printf(" ");
}
printf("\n");
}
/* Fitness is determined by the number of
1's in the bitstring. */
int get_fitness(unsigned char string_in){
int count = 0;
unsigned char temp = string_in;
while (temp){
if (temp & 0x01){
count++;
}
temp = temp >> 1;
}
return count;
}
/* Randomly initialize the first population */
void init_population(unsigned char* population){
int i;
for ( i=0; i<N; i++){
population[i] = (char)(rand() % 0xFF);
}
}
/* Perform selection of population members based on fitness */
void do_selection(unsigned char* population, int* selected){
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;
}
}
/* compute a mask to use when crossing over parents*/
unsigned char get_mask(int locus_in){
int i = 0;
unsigned char ret;
for( i=0; i<locus_in; i++ ){
ret = ret << 1;
ret ^= 0x01;
}
return ret;
}
/* crossover members with probability P_c
if no crossover, then clone parents */
void do_crossover(unsigned char* population, int* selected){
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];
}
}
void do_mutation(unsigned char* population){
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
}
}
}
}

19
src/genetic_algorithm.hpp Normal file
View File

@ -0,0 +1,19 @@
#ifndef GENETIC_ALGORITHM_HPP
#define GENETIC_ALGORITHM_HPP
#define P_c 0.7 //crossover probability (typical val.)
#define P_m 0.001 //mutation probability (typical val.)
#define N 8 //population size (change to something even)
#define L 8 //string length (don't change)
#define G 10000 //number of generations (something huge)
void print_population(unsigned char population_in[]);
int get_fitness(unsigned char string_in);
void init_population(unsigned char* population);
void do_selection(unsigned char* population, int* selected);
unsigned char get_mask(int locus_in);
void do_crossover(unsigned char* population, int* selected);
void do_mutation(unsigned char* population);
#endif // GENETIC_ALGORITHM_HPP

35
src/n_queens.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "chess.hpp"
#include "genetic_algorithm.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
unsigned char population[N] = {0};
int selected[N] = {-1};
int generation_count = 0;
int i;
srand(time(NULL));
//basic genetic algorithm skeleton
init_population(population);
print_population(population);
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) {
printf("Max fit reached.\n");
return 0;
}
}
generation_count++;
}
return 0;
}