diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c65dbe..bcc7586 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.56) +project(blt-gp VERSION 0.0.57) include(CTest) diff --git a/examples/gp_test_7.cpp b/examples/gp_test_7.cpp index 34aeeeb..651baca 100644 --- a/examples/gp_test_7.cpp +++ b/examples/gp_test_7.cpp @@ -23,7 +23,7 @@ static constexpr long SEED = 41912; -blt::gp::prog_config_t config = blt::gp::prog_config_t().set_elite_count(0); +blt::gp::prog_config_t config = blt::gp::prog_config_t().set_elite_count(1); blt::gp::type_provider type_system; blt::gp::gp_program program(type_system, blt::gp::random_t{SEED}, config); // NOLINT @@ -53,13 +53,17 @@ blt::gp::operation_t lit([]() { // 13 void print_best() { BLT_TRACE("----{Current Gen: %ld}----", program.get_current_generation()); - auto best = program.get_best<10>(); + auto best = program.get_best_indexes<10>(); - for (auto& v : best) + for (auto& i : best) { - auto size = v.get().get_values().size(); - BLT_TRACE("%lf (depth: %ld) (size: t: %ld m: %ld u: %ld r: %ld) filled: %f%%", v.get().get_evaluation_value(nullptr), - v.get().get_depth(program), size.total_size_bytes, size.total_no_meta_bytes, size.total_used_bytes, size.total_remaining_bytes, + auto& v = program.get_current_pop().get_individuals()[i]; + auto& tree = v.tree; + auto size = tree.get_values().size(); + BLT_TRACE("%lf (fitness: %lf, raw: %lf) (depth: %ld) (blocks: %ld) (size: t: %ld m: %ld u: %ld r: %ld) filled: %f%%", + tree.get_evaluation_value(nullptr), v.adjusted_fitness, v.raw_fitness, + tree.get_depth(program), size.blocks, size.total_size_bytes, size.total_no_meta_bytes, size.total_used_bytes, + size.total_remaining_bytes, static_cast(size.total_used_bytes) / static_cast(size.total_no_meta_bytes)); } //std::string small("--------------------------"); @@ -101,10 +105,10 @@ int main() while (!program.should_terminate()) { program.evaluate_fitness([](blt::gp::tree_t& current_tree, decltype(result_container)& container, blt::size_t index) { - auto size = current_tree.get_values().size(); - BLT_DEBUG("(depth: %ld) (size: t: %ld m: %ld u: %ld r: %ld) filled: %f%%", - current_tree.get_depth(program), size.total_size_bytes, size.total_no_meta_bytes, size.total_used_bytes, - size.total_remaining_bytes, static_cast(size.total_used_bytes) / static_cast(size.total_no_meta_bytes)); + /*auto size = current_tree.get_values().size(); + BLT_DEBUG("(depth: %ld) (blocks: %ld) (size: t: %ld m: %ld u: %ld r: %ld) filled: %f%%", + current_tree.get_depth(program), size.blocks, size.total_size_bytes, size.total_no_meta_bytes, size.total_used_bytes, + size.total_remaining_bytes, static_cast(size.total_used_bytes) / static_cast(size.total_no_meta_bytes));*/ container[index] = current_tree.get_evaluation_value(nullptr); return container[index]; }, result_container); diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index e43ca0f..6b5316b 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -277,15 +277,18 @@ namespace blt::gp * NOTE: 0 is considered the best, in terms of standardized and adjusted fitness */ template - void evaluate_fitness(Callable&& fitness_function, Container& result_storage) + void evaluate_fitness(Callable&& fitness_function, Container& result_storage, bool larger_better = true) { - for (const auto& ind : blt::enumerate(current_pop.get_individuals())) - ind.second.raw_fitness = static_cast(fitness_function(ind.second.tree, result_storage, ind.first)); + for (const auto& ind : blt::enumerate(current_pop.get_individuals())) + ind.second.raw_fitness = static_cast(fitness_function(ind.second.tree, result_storage, ind.first)); double min = 0; + double max = 0; for (auto& ind : current_pop.get_individuals()) { if (ind.raw_fitness < min) min = ind.raw_fitness; + if (larger_better && ind.raw_fitness > max) + max = ind.raw_fitness; } double overall_fitness = 0; @@ -297,8 +300,13 @@ namespace blt::gp auto diff = -min; for (auto& ind : current_pop.get_individuals()) { + // make standardized fitness [0, +inf) auto standardized_fitness = ind.raw_fitness + diff; - ind.adjusted_fitness = 1.0 / (1.0 + standardized_fitness); + BLT_WARN(standardized_fitness); + if (larger_better) + standardized_fitness = (max + diff) - standardized_fitness; + BLT_WARN(standardized_fitness); + ind.adjusted_fitness = (1.0 / (1.0 + standardized_fitness)); if (ind.adjusted_fitness > worst_fitness) { @@ -325,6 +333,11 @@ namespace blt::gp current_generation++; } + inline auto& get_current_pop() + { + return current_pop; + } + template std::array get_best_indexes() { diff --git a/include/blt/gp/selection.h b/include/blt/gp/selection.h index 83f6d26..e8897a5 100644 --- a/include/blt/gp/selection.h +++ b/include/blt/gp/selection.h @@ -50,13 +50,34 @@ namespace blt::gp if (config.elites > 0) { std::vector> values; - + for (blt::size_t i = 0; i < config.elites; i++) values.emplace_back(i, current_pop.get_individuals()[i].adjusted_fitness); - - for (auto& ind : current_pop.get_individuals()) + + for (const auto& ind : blt::enumerate(current_pop.get_individuals())) { - + blt::i64 largest = -1; + double largest_fit = 0; + for (blt::size_t i = 0; i < config.elites; i++) + { + BLT_INFO("%lf < %lf? // %lf", ind.second.adjusted_fitness, values[i].second, ind.second.raw_fitness); + if (ind.second.adjusted_fitness < values[i].second && values[i].second > largest_fit) + { + largest = static_cast(i); + largest_fit = values[i].second; + } + } + if (largest > 0) + { + BLT_INFO("%ld %lf", largest, largest_fit); + values[largest] = {ind.first, ind.second.adjusted_fitness}; + } + } + + for (blt::size_t i = 0; i < config.elites; i++) + { + BLT_DEBUG("%lf %lf", values[i].second, current_pop.get_individuals()[values[i].first].tree.get_evaluation_value(nullptr)); + next_pop.get_individuals().push_back(current_pop.get_individuals()[values[i].first]); } } diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index fba8d7d..96bb304 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -42,6 +42,7 @@ namespace blt::gp blt::size_t total_used_bytes = 0; blt::size_t total_remaining_bytes = 0; blt::size_t total_no_meta_bytes = 0; + blt::size_t blocks = 0; }; @@ -78,9 +79,11 @@ namespace blt::gp head->metadata.offset -= TYPE_SIZE; if (head->used_bytes_in_block() == 0) { - auto ptr = head; + auto old = head; head = head->metadata.prev; - std::free(ptr); + if (head != nullptr) + head->metadata.next = nullptr; + std::free(old); } return t; } @@ -142,7 +145,10 @@ namespace blt::gp bytes -= head->used_bytes_in_block(); auto old = head; head = head->metadata.prev; - free(old); + // required to prevent silly memory :3 + if (head != nullptr) + head->metadata.next = nullptr; + std::free(old); if (diff == 0) break; } else @@ -184,13 +190,14 @@ namespace blt::gp [[nodiscard]] size_data_t size() { size_data_t size_data; - auto next = head; + auto* next = head; while (next != nullptr) { size_data.total_size_bytes += next->metadata.size; size_data.total_no_meta_bytes += next->storage_size(); size_data.total_remaining_bytes += next->remaining_bytes_in_block(); size_data.total_used_bytes += next->used_bytes_in_block(); + size_data.blocks++; next = next->metadata.next; } return size_data; @@ -325,7 +332,7 @@ namespace blt::gp template void push_block_for() { - push_block(std::max(PAGE_SIZE, to_nearest_page_size(sizeof(T)))); + push_block(aligned_size()); } void push_block(blt::size_t size) @@ -349,16 +356,6 @@ namespace blt::gp static block* allocate_block(blt::size_t bytes) { -#if BLT_DEBUG_LEVEL > 0 - if (bytes > 32000) - { - BLT_WARN("Size too big!"); - std::abort(); - } -#endif -#if BLT_DEBUG_LEVEL > 2 - BLT_DEBUG("Allocating bytes %ld", bytes); -#endif auto size = to_nearest_page_size(bytes); auto* data = std::aligned_alloc(PAGE_SIZE, size); new(data) block{size}; diff --git a/lib/blt b/lib/blt index b6048ed..4de3aeb 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit b6048ed39c9f34a4480f2a99c5d83817d3ccf1bf +Subproject commit 4de3aeb87c78a13f8e493e48477220084610c076