From 339046cc36adfa007f48fcc7cbb60e6a7a514b60 Mon Sep 17 00:00:00 2001 From: Brett Date: Fri, 4 Apr 2025 02:06:21 -0400 Subject: [PATCH] no idea where the leak is coming from --- CMakeLists.txt | 2 +- include/gp_system.h | 2 +- include/image_storage.h | 11 +++- src/gp_system.cpp | 116 +++++++++++++++++++++++++++++----------- src/main.cpp | 29 ++++++++-- 5 files changed, 120 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c66d67..8f47cb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(image-gp-2 VERSION 0.0.7) +project(image-gp-2 VERSION 0.0.8) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) diff --git a/include/gp_system.h b/include/gp_system.h index ff58e92..6150081 100644 --- a/include/gp_system.h +++ b/include/gp_system.h @@ -27,7 +27,7 @@ void run_step(); bool should_terminate(); -image_storage_t& get_image(blt::size_t index); +std::array& get_image(blt::size_t index); void cleanup(); diff --git a/include/image_storage.h b/include/image_storage.h index 819026c..acba1b9 100644 --- a/include/image_storage.h +++ b/include/image_storage.h @@ -68,10 +68,11 @@ struct image_cleaner_t }; inline image_cleaner_t g_image_list; +inline std::atomic_uint64_t g_image_counter = 0; struct image_t { - image_t() + image_t(): id(++g_image_counter) { image_storage_t* front = nullptr; { @@ -87,8 +88,14 @@ struct image_t else data = new image_storage_t; ++g_allocated_blocks; + + BLT_TRACE("Allocated {}!", id); } + image_t(const image_t& other) = default; + + image_t& operator=(const image_t& other) = default; + void drop() { { @@ -97,6 +104,7 @@ struct image_t } data = nullptr; ++g_deallocated_blocks; + BLT_TRACE("Deallocated {}!", id); } [[nodiscard]] void* as_void_const() const @@ -129,6 +137,7 @@ struct image_t private: image_storage_t* data; + blt::size_t id; }; #endif //IMAGE_STORAGE_H diff --git a/src/gp_system.cpp b/src/gp_system.cpp index 1ebb2e2..5667970 100644 --- a/src/gp_system.cpp +++ b/src/gp_system.cpp @@ -53,6 +53,7 @@ void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t inde fitness.adjusted_fitness = -fitness.standardized_fitness; } +template void setup_operations(gp_program* program) { static operation_t op_image_x([]() { @@ -73,15 +74,13 @@ void setup_operations(gp_program* program) } return ret; }); - static operation_t op_image_xy([]() { + static auto op_image_ephemeral = operation_t([program]() { image_t ret; - for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x) - { - for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y) - ret.get_data().get(x, y) = static_cast(x + y) / static_cast((IMAGE_DIMENSIONS - 1) * (IMAGE_DIMENSIONS - 1)); - } + const auto value = program->get_random().get_float(); + for (auto& v : ret.get_data().data) + v = value; return ret; - }); + }).set_ephemeral(); static operation_t op_image_blend([](const image_t& a, const image_t& b, const float f) { const auto blend = std::min(std::max(f, 0.0f), 1.0f); const auto beta = 1.0f - blend; @@ -91,7 +90,32 @@ void setup_operations(gp_program* program) cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC1, ret.get_data().data.data()}; addWeighted(src1, blend, src2, beta, 0.0, dst); return ret; - }, "blend"); + }, "blend_image"); + static operation_t op_image_sin([](const image_t& a) { + image_t ret; + for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) + ret.get_data().data[i] = std::sin(v); + return ret; + }, "sin_image"); + static operation_t op_image_cos([](const image_t& a) { + image_t ret; + for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) + ret.get_data().data[i] = std::cos(v); + return ret; + }, "cos_image"); + static operation_t op_image_log([](const image_t& a) { + image_t ret; + for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data))) + { + if (blt::f_equal(v, 0)) + ret.get_data().data[i] = 0; + else if (v < 0) + ret.get_data().data[i] = -std::log(-v); + else + ret.get_data().data[i] = std::log(v); + } + return ret; + }, "sin_image"); static operation_t op_sin([](const float a) { return std::sin(a); }, "sin_float"); @@ -113,57 +137,85 @@ void setup_operations(gp_program* program) }, "lit_float").set_ephemeral(); operator_builder builder{}; - builder.build(make_add(), make_sub(), make_mul(), make_div(), op_image_x, op_image_y, op_image_xy, - make_add(), make_sub(), make_mul(), make_prot_div(), op_sin, op_cos, op_exp, op_log, lit); + builder.build(make_add(), make_sub(), make_mul(), make_div(), op_image_x, op_image_y, op_image_sin, + op_image_cos, op_image_log, make_add(), make_sub(), make_mul(), make_prot_div(), + op_sin, op_cos, op_exp, op_log, lit); program->set_operations(builder.grab()); } void setup_gp_system(const blt::size_t population_size) { prog_config_t config{}; - config.population_size = population_size; - config.elites = 2; - program = new gp_program{ - []() { - return std::random_device()(); - }, - config - }; + config.set_pop_size(1); + config.set_elite_count(0); + config.set_thread_count(0); + // config.set_crossover_chance(0); + // config.set_mutation_chance(0); + // config.set_reproduction_chance(0); + + const auto rand = std::random_device()(); + BLT_INFO("Random Seed: {}", rand); + for (auto& program : programs) + { + program = new gp_program{rand, config}; + } + setup_operations(programs[0]); + setup_operations(programs[1]); + setup_operations(programs[2]); images.resize(population_size); - setup_operations(); + static auto sel = select_tournament_t{}; - program->generate_initial_population(program->get_typesystem().get_type().id()); - program->setup_generational_evaluation(fitness_func, sel, sel, sel); + + for (const auto program : programs) + program->generate_initial_population(program->get_typesystem().get_type().id()); + + programs[0]->setup_generational_evaluation(fitness_func<0>, sel, sel, sel); + programs[1]->setup_generational_evaluation(fitness_func<1>, sel, sel, sel); + programs[2]->setup_generational_evaluation(fitness_func<2>, sel, sel, sel); } void run_step() { - BLT_TRACE("------------\\{Begin Generation {}}------------", program->get_current_generation()); + BLT_TRACE("------------\\{Begin Generation {}}------------", programs[0]->get_current_generation()); BLT_TRACE("Creating next generation"); - program->create_next_generation(); + for (const auto program : programs) + program->create_next_generation(); BLT_TRACE("Move to next generation"); - program->next_generation(); + for (const auto program : programs) + program->next_generation(); BLT_TRACE("Evaluate Fitness"); - program->evaluate_fitness(); - const auto& stats = program->get_population_stats(); - BLT_TRACE("Avg Fit: {:0.6f}, Best Fit: {:0.6f}, Worst Fit: {:0.6f}, Overall Fit: {:0.6f}", stats.average_fitness.load(std::memory_order_relaxed), - stats.best_fitness.load(std::memory_order_relaxed), stats.worst_fitness.load(std::memory_order_relaxed), - stats.overall_fitness.load(std::memory_order_relaxed)); + for (const auto program : programs) + program->evaluate_fitness(); + for (const auto [i, program] : blt::enumerate(programs)) + { + const auto& stats = program->get_population_stats(); + if (i == 0) + BLT_TRACE("Channel Red"); + else if (i == 1) + BLT_TRACE("Channel Green"); + else + BLT_TRACE("Channel Blue"); + BLT_TRACE("\tAvg Fit: {:0.6f}, Best Fit: {:0.6f}, Worst Fit: {:0.6f}, Overall Fit: {:0.6f}", + stats.average_fitness.load(std::memory_order_relaxed), stats.best_fitness.load(std::memory_order_relaxed), + stats.worst_fitness.load(std::memory_order_relaxed), stats.overall_fitness.load(std::memory_order_relaxed)); + } + BLT_TRACE("----------------------------------------------"); } bool should_terminate() { - return program->should_terminate(); + return programs[0]->should_terminate() || programs[1]->should_terminate() || programs[2]->should_terminate(); } -image_storage_t& get_image(blt::size_t index) +std::array& get_image(const blt::size_t index) { return images[index]; } void cleanup() { - delete program; + for (const auto program : programs) + delete program; } diff --git a/src/main.cpp b/src/main.cpp index 431d2a3..14b2ad1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,7 +70,7 @@ void update(const blt::gfx::window_data& data) ImGui::SetNextWindowSize(ImVec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y)); ImGui::Begin("MainWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | - ImGuiWindowFlags_NoBringToFrontOnFocus); + ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoBackground); // Create the tab bar if (ImGui::BeginTabBar("MainTabs")) @@ -132,7 +132,26 @@ void update(const blt::gfx::window_data& data) ImGui::End(); for (blt::size_t i = 0; i < population_size; i++) - gl_images[i]->upload(get_image(i).data.data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGBA, GL_FLOAT); + { + auto& image = get_image(i); + float min = std::numeric_limits::max(); + float max = std::numeric_limits::min(); + + for (auto& pixel : image) + { + if (std::isnan(pixel) || std::isinf(pixel)) + pixel = 0; + if (pixel > max) + max = pixel; + if (pixel < min) + min = pixel; + } + + for (auto& pixel : image) + pixel = (pixel - min) / (max - min); + + gl_images[i]->upload(get_image(i).data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGB, GL_FLOAT); + } constexpr int images_x = 10; constexpr int images_y = 6; @@ -142,12 +161,12 @@ void update(const blt::gfx::window_data& data) { constexpr float padding_x = 32; constexpr float padding_y = 32; - const float img_width = (static_cast(data.width) - padding_x * 2 - padding_x * (images_x-1) - 256) / images_x; - const float img_height = (static_cast(data.height) - padding_y * 2 - padding_y * (images_y-1) - 32) / images_y; + const float img_width = (static_cast(data.width) - padding_x * 2 - padding_x * (images_x - 1) - 256) / images_x; + const float img_height = (static_cast(data.height) - padding_y * 2 - padding_y * (images_y - 1) - 32) / images_y; const float x = 256 + static_cast(i) * img_width + padding_x * static_cast(i) + img_width; const float y = static_cast(data.height) - (16 + static_cast(j) * img_height + padding_y * static_cast(j) + img_height); - renderer_2d.drawRectangle(blt::gfx::rectangle2d_t{x, y, img_width, img_height}, std::to_string(i * j)); + renderer_2d.drawRectangle(blt::gfx::rectangle2d_t{x, y, img_width, img_height}, std::to_string(i * images_y + j)); } }