diff --git a/CMakeLists.txt b/CMakeLists.txt index 71b8b92..0554e01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,7 @@ macro(blt_add_project name source type) project(skyscrapers-ga) endmacro() -project(skyscrapers-ga VERSION 0.0.6) +project(skyscrapers-ga VERSION 0.0.7) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) diff --git a/include/skyscrapers.h b/include/skyscrapers.h index bc01bf3..4c774cc 100644 --- a/include/skyscrapers.h +++ b/include/skyscrapers.h @@ -88,6 +88,11 @@ namespace sky return board_data[row * board_size + column]; } + void set(const blt::i32 row, const blt::i32 column, const blt::i32 value) + { + board_data[row * board_size + column] = value; + } + void print() const; void print(const problem_t& problem) const; diff --git a/src/genetic_algorithm.cpp b/src/genetic_algorithm.cpp index 495c6dd..08970c6 100644 --- a/src/genetic_algorithm.cpp +++ b/src/genetic_algorithm.cpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace sky { @@ -131,8 +132,8 @@ namespace sky { auto& random = get_random(); - const auto first_begin = random.get_size_t(0, first.board_size * first.board_size - 1); - const auto first_end = random.get_size_t(first_begin + 1, first.board_size * first.board_size); + const auto first_begin = random.get_size_t(0, first.board_data.size() - 1); + const auto first_end = random.get_size_t(first_begin + 1, first.board_data.size()); const auto size = first_end - first_begin; @@ -152,15 +153,56 @@ namespace sky { auto& random = get_random(); - // TODO: better mutation - const blt::i32 points = random.get_i32(0, 5); - for (blt::i32 i = 0; i < points; ++i) + switch (random.get_i32(0, 3)) // NOLINT { - const auto index = random.get_size_t(0, individual.board_size * individual.board_size); - const auto replacement = random.get_i32(m_problem.min(), m_problem.max() + 1); - individual.board_data[index] = replacement; + case 0: + { + const blt::i32 points = random.get_i32(0, 5); + for (blt::i32 i = 0; i < points; ++i) + { + const auto index = random.get_size_t(0, individual.board_data.size()); + const auto replacement = random.get_i32(m_problem.min(), m_problem.max() + 1); + individual.board_data[index] = replacement; + } + } + return individual; + case 1: + { + const blt::size_t s1 = random.get_size_t(0, individual.board_data.size()); + blt::size_t s2; + do + { + s2 = random.get_size_t(0, individual.board_data.size()); + } while (s1 == s2); + const auto temp = individual.board_data[s1]; + individual.board_data[s1] = individual.board_data[s2]; + individual.board_data[s2] = temp; + } + return individual; + case 2: + { + if (random.choice()) + { + const blt::i32 row = random.get_i32(0, individual.board_size); + std::vector temp; + for (blt::i32 column = 0; column < individual.board_size; column++) + temp.push_back(individual.get(row, column)); + std::shuffle(temp.begin(), temp.end(), random); + for (blt::i32 column = 0; column < individual.board_size; column++) + individual.set(row, column, temp[column]); + } else + { + const blt::i32 column = random.get_i32(0, individual.board_size); + std::vector temp; + for (blt::i32 row = 0; row < individual.board_size; row++) + temp.push_back(individual.get(row, column)); + std::shuffle(temp.begin(), temp.end(), random); + for (blt::i32 row = 0; row < individual.board_size; row++) + individual.set(row, column, temp[column]); + } + } + return individual; } - - return individual; + BLT_UNREACHABLE; } } diff --git a/src/main.cpp b/src/main.cpp index 819de65..39fff5f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,7 +70,7 @@ int main(int argc, const char** argv) sky::genetic_algorithm ga{problem_d, 500, 0.8, 0.1}; - for (blt::i32 i = 0; i < 50; i++) + for (blt::i32 i = 0; i < 500; i++) { ga.run_step(2, 5); BLT_TRACE("Ran GP generation %d with average fitness %lf", i, ga.average_fitness()); diff --git a/src/skyscrapers.cpp b/src/skyscrapers.cpp index 3e1b50c..ae36492 100644 --- a/src/skyscrapers.cpp +++ b/src/skyscrapers.cpp @@ -66,7 +66,7 @@ namespace sky return blt::unexpected(problem_t::error_t::MISSING_BOARD_DATA); } - blt::i32 index = 1; + blt::size_t index = 1; auto top_problems = blt::string::split(lines[index++], '\t');