From 30a4a0e8d778abfc1d85054e5ab03c074f8fcaaa Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Wed, 3 Jul 2024 18:40:21 -0400 Subject: [PATCH] crossover no longer produces an error on test 5 --- CMakeLists.txt | 5 +- examples/gp_test_5.cpp | 29 ++++++----- include/blt/gp/fwdecl.h | 2 +- include/blt/gp/program.h | 14 +++-- include/blt/gp/stack.h | 17 ++++++ src/transformers.cpp | 108 +++++++++++++++++++++++---------------- src/tree.cpp | 2 +- 7 files changed, 110 insertions(+), 67 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f6a0f3..74823a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.48) +project(blt-gp VERSION 0.0.49) include(CTest) @@ -7,6 +7,7 @@ option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) option(ENABLE_TSAN "Enable the thread data race sanitizer" OFF) option(BUILD_EXAMPLES "Build example programs. This is a single executable" OFF) +option(DEBUG_LEVEL "Enable debug features which prints extra information to the console, might slow processing down. [0, 3)" 0) set(CMAKE_CXX_STANDARD 17) @@ -21,6 +22,7 @@ target_compile_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comm target_link_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comment) target_link_libraries(blt-gp PRIVATE BLT) +target_compile_definitions(blt-gp PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL}) if (${ENABLE_ADDRSAN} MATCHES ON) target_compile_options(blt-gp PRIVATE -fsanitize=address) @@ -48,6 +50,7 @@ if (${BUILD_EXAMPLES}) target_compile_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment) target_link_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment) + target_compile_definitions(${name}-example PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL}) if (${ENABLE_ADDRSAN} MATCHES ON) target_compile_options(${name}-example PRIVATE -fsanitize=address) diff --git a/examples/gp_test_5.cpp b/examples/gp_test_5.cpp index 4bfd96f..1a25c19 100644 --- a/examples/gp_test_5.cpp +++ b/examples/gp_test_5.cpp @@ -43,22 +43,22 @@ static constexpr long SEED = 41912; blt::gp::type_provider type_system; blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT -blt::gp::operation_t add([](float a, float b) { return a + b; }); -blt::gp::operation_t sub([](float a, float b) { return a - b; }); -blt::gp::operation_t mul([](float a, float b) { return a * b; }); -blt::gp::operation_t pro_div([](float a, float b) { return b == 0 ? 0.0f : a / b; }); +blt::gp::operation_t add([](float a, float b) { return a + b; }); // 0 +blt::gp::operation_t sub([](float a, float b) { return a - b; }); // 1 +blt::gp::operation_t mul([](float a, float b) { return a * b; }); // 2 +blt::gp::operation_t pro_div([](float a, float b) { return b == 0 ? 0.0f : a / b; }); // 3 -blt::gp::operation_t op_if([](bool b, float a, float c) { return b ? a : c; }); -blt::gp::operation_t eq_f([](float a, float b) { return a == b; }); -blt::gp::operation_t eq_b([](bool a, bool b) { return a == b; }); -blt::gp::operation_t lt([](float a, float b) { return a < b; }); -blt::gp::operation_t gt([](float a, float b) { return a > b; }); -blt::gp::operation_t op_and([](bool a, bool b) { return a && b; }); -blt::gp::operation_t op_or([](bool a, bool b) { return a || b; }); -blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast(a ^ b); }); -blt::gp::operation_t op_not([](bool b) { return !b; }); +blt::gp::operation_t op_if([](bool b, float a, float c) { return b ? a : c; }); // 4 +blt::gp::operation_t eq_f([](float a, float b) { return a == b; }); // 5 +blt::gp::operation_t eq_b([](bool a, bool b) { return a == b; }); // 6 +blt::gp::operation_t lt([](float a, float b) { return a < b; }); // 7 +blt::gp::operation_t gt([](float a, float b) { return a > b; }); // 8 +blt::gp::operation_t op_and([](bool a, bool b) { return a && b; }); // 9 +blt::gp::operation_t op_or([](bool a, bool b) { return a || b; }); // 10 +blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast(a ^ b); }); // 11 +blt::gp::operation_t op_not([](bool b) { return !b; }); // 12 -blt::gp::operation_t lit([]() { +blt::gp::operation_t lit([]() { // 13 //static std::uniform_real_distribution dist(-32000, 32000); static std::uniform_real_distribution dist(0.0f, 10.0f); return dist(program.get_random()); @@ -107,6 +107,7 @@ int main() auto& ind = pop.getIndividuals(); auto results = crossover.apply(program, ind[0], ind[1]); + BLT_INFO("Post crossover:"); if (results.has_value()) { diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h index 2a4faee..dfbf903 100644 --- a/include/blt/gp/fwdecl.h +++ b/include/blt/gp/fwdecl.h @@ -54,7 +54,7 @@ namespace blt::gp // context*, read stack, write stack using callable_t = std::function; // to, from - using transfer_t = std::function; + using transfer_t = std::function; } } diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 14ac2e7..0c4f651 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -117,11 +117,15 @@ namespace blt::gp BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!"); info.function = op.template make_callable(); - info.transfer = [](stack_allocator& to, stack_allocator& from, blt::ptrdiff_t offset) { - if (offset < 0) - to.push(from.pop()); - else - to.push(from.from(offset)); + info.transfer = [](stack_allocator& to, stack_allocator& from) { +#if BLT_DEBUG_LEVEL >= 3 + auto value = from.pop(); + BLT_TRACE_STREAM << value << "\n"; + to.push(value); +#else + to.push(from.pop()); +#endif + }; storage.operators.push_back(info); if (is_static) diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index b1f1888..f600846 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -106,8 +106,25 @@ namespace blt::gp void pop_bytes(blt::ptrdiff_t bytes) { +#if BLT_DEBUG_LEVEL >= 3 + blt::size_t counter = 0; +#endif while (bytes > 0) { +#if BLT_DEBUG_LEVEL > 0 + if (head == nullptr) + { + BLT_WARN("Head is nullptr, unable to pop bytes!"); + BLT_WARN("This error is normally caused by an invalid tree!"); +#if BLT_DEBUG_LEVEL >= 3 + BLT_WARN("Made it to %ld iterations", counter); +#endif + return; + } + #if BLT_DEBUG_LEVEL >= 3 + counter++; + #endif +#endif auto diff = head->used_bytes_in_block() - bytes; // if there is not enough room left to pop completely off the block, then move to the next previous block // and pop from it, update the amount of bytes to reflect the amount removed from the current block diff --git a/src/transformers.cpp b/src/transformers.cpp index a429999..9b06139 100644 --- a/src/transformers.cpp +++ b/src/transformers.cpp @@ -26,9 +26,11 @@ namespace blt::gp { const auto& config = program.get_config(); result_t result{p1, p2}; - + +#if BLT_DEBUG_LEVEL > 0 BLT_INFO("Child 1 Stack empty? %s", result.child1.get_values().empty() ? "true" : "false"); BLT_INFO("Child 2 Stack empty? %s", result.child2.get_values().empty() ? "true" : "false"); +#endif auto& c1 = result.child1; auto& c2 = result.child2; @@ -82,6 +84,9 @@ namespace blt::gp do { const auto& type = program.get_operator_info(c1_ops[index].id); +#if BLT_DEBUG_LEVEL > 1 + BLT_TRACE("Crossover type: %s, op %ld", std::string(program.get_typesystem().get_type(type.return_type).name()).c_str(), c1_ops[index].id); +#endif if (type.argc.argc > 0) children_left += type.argc.argc; else @@ -91,6 +96,9 @@ namespace blt::gp auto crossover_point_begin_itr = c1_ops.begin() + static_cast(crossover_point); auto crossover_point_end_itr = c1_ops.begin() + static_cast(index); +#if BLT_DEBUG_LEVEL > 0 + BLT_TRACE("[%ld %ld) %ld", crossover_point, index, index - crossover_point); +#endif children_left = 0; index = attempted_point; @@ -98,18 +106,22 @@ namespace blt::gp do { const auto& type = program.get_operator_info(c2_ops[index].id); +#if BLT_DEBUG_LEVEL > 1 + BLT_TRACE("Found type: %s, op: %ld", std::string(program.get_typesystem().get_type(type.return_type).name()).c_str(), c2_ops[index].id); +#endif if (type.argc.argc > 0) children_left += type.argc.argc; else children_left--; - if (children_left > 0) - index++; - else - break; - } while (true); + index++; + } while (children_left > 0); auto found_point_begin_itr = c2_ops.begin() + static_cast(attempted_point); auto found_point_end_itr = c2_ops.begin() + static_cast(index); + +#if BLT_DEBUG_LEVEL > 0 + BLT_TRACE("[%ld %ld) %ld", attempted_point, index, index - attempted_point); +#endif stack_allocator& c1_stack_init = c1.get_values(); stack_allocator& c2_stack_init = c2.get_values(); @@ -121,84 +133,93 @@ namespace blt::gp c1_operators.push_back(op); for (const auto& op : blt::enumerate(found_point_begin_itr, found_point_end_itr)) c2_operators.push_back(op); + +#if BLT_DEBUG_LEVEL > 0 + BLT_TRACE("Sizes: %ld %ld || Ops size: %ld %ld", c1_operators.size(), c2_operators.size(), c1_ops.size(), c2_ops.size()); +#endif stack_allocator c1_stack_after_copy; stack_allocator c1_stack_for_copy; stack_allocator c2_stack_after_copy; stack_allocator c2_stack_for_copy; - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring past crossover 1:"); +#endif // transfer all values after the crossover point. these will need to be transferred back to child2 for (auto it = c1_ops.end() - 1; it != crossover_point_end_itr - 1; it--) { if (it->is_value) - it->transfer(c1_stack_after_copy, c1_stack_init, -1); + it->transfer(c1_stack_after_copy, c1_stack_init); } - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring for crossover 1:"); +#endif // transfer all values for the crossover point. for (auto it = crossover_point_end_itr - 1; it != crossover_point_begin_itr - 1; it--) { if (it->is_value) - it->transfer(c1_stack_for_copy, c1_stack_init, -1); + it->transfer(c1_stack_for_copy, c1_stack_init); } - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring past crossover 2:"); +#endif // transfer child2 values for copying back into c1 for (auto it = c2_ops.end() - 1; it != found_point_end_itr - 1; it--) { if (it->is_value) - it->transfer(c2_stack_after_copy, c2_stack_init, -1); + it->transfer(c2_stack_after_copy, c2_stack_init); } - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring for crossover 2:"); +#endif for (auto it = found_point_end_itr - 1; it != found_point_begin_itr - 1; it--) { if (it->is_value) - it->transfer(c2_stack_for_copy, c2_stack_init, -1); + it->transfer(c2_stack_for_copy, c2_stack_init); } - - BLT_TRACE("c1_stack_after_copy empty? %s", c1_stack_after_copy.empty() ? "true" : "false"); - BLT_TRACE("c1_stack_for_copy empty? %s", c1_stack_for_copy.empty() ? "true" : "false"); - BLT_TRACE("c2_stack_after_copy empty? %s", c2_stack_after_copy.empty() ? "true" : "false"); - BLT_TRACE("c2_stack_for_copy empty? %s", c2_stack_for_copy.empty() ? "true" : "false"); - BLT_INFO("Child 1 Stack empty? %s", result.child1.get_values().empty() ? "true" : "false"); - BLT_INFO("Child 2 Stack empty? %s", result.child2.get_values().empty() ? "true" : "false"); - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring back for crossover 1:"); +#endif // now copy back into the respective children for (auto it = found_point_begin_itr; it != found_point_end_itr; it++) { if (it->is_value) - it->transfer(c1.get_values(), c2_stack_for_copy, -1); + it->transfer(c1.get_values(), c2_stack_for_copy); } - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring back for crossover 2:"); +#endif for (auto it = crossover_point_begin_itr; it != crossover_point_end_itr; it++) { if (it->is_value) - it->transfer(c2.get_values(), c1_stack_for_copy, -1); + it->transfer(c2.get_values(), c1_stack_for_copy); } - - BLT_TRACE("c1_stack_after_copy empty? %s", c1_stack_after_copy.empty() ? "true" : "false"); - BLT_TRACE("c1_stack_for_copy empty? %s", c1_stack_for_copy.empty() ? "true" : "false"); - BLT_TRACE("c2_stack_after_copy empty? %s", c2_stack_after_copy.empty() ? "true" : "false"); - BLT_TRACE("c2_stack_for_copy empty? %s", c2_stack_for_copy.empty() ? "true" : "false"); - BLT_INFO("Child 1 Stack empty? %s", result.child1.get_values().empty() ? "true" : "false"); - BLT_INFO("Child 2 Stack empty? %s", result.child2.get_values().empty() ? "true" : "false"); - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring back after crossover 1:"); +#endif // now copy after the crossover point back to the correct children for (auto it = crossover_point_end_itr; it != c1_ops.end(); it++) { if (it->is_value) - it->transfer(c1.get_values(), c1_stack_after_copy, -1); + it->transfer(c1.get_values(), c1_stack_after_copy); } - + +#if BLT_DEBUG_LEVEL > 1 + BLT_DEBUG("Transferring back after crossover 2:"); +#endif for (auto it = found_point_end_itr; it != c2_ops.end(); it++) { if (it->is_value) - it->transfer(c2.get_values(), c2_stack_after_copy, -1); + it->transfer(c2.get_values(), c2_stack_after_copy); } - BLT_TRACE("c1_stack_after_copy empty? %s", c1_stack_after_copy.empty() ? "true" : "false"); - BLT_TRACE("c1_stack_for_copy empty? %s", c1_stack_for_copy.empty() ? "true" : "false"); - BLT_TRACE("c2_stack_after_copy empty? %s", c2_stack_after_copy.empty() ? "true" : "false"); - BLT_TRACE("c2_stack_for_copy empty? %s", c2_stack_for_copy.empty() ? "true" : "false"); - // now swap the operators auto insert_point_c1 = crossover_point_begin_itr - 1; auto insert_point_c2 = found_point_begin_itr - 1; @@ -208,10 +229,7 @@ namespace blt::gp c2_ops.erase(found_point_begin_itr, found_point_end_itr); c1_ops.insert(++insert_point_c1, c2_operators.begin(), c2_operators.end()); - c1_ops.insert(++insert_point_c2, c1_operators.begin(), c1_operators.end()); - - BLT_INFO("Child 1 Stack empty? %s", result.child1.get_values().empty() ? "true" : "false"); - BLT_INFO("Child 2 Stack empty? %s", result.child2.get_values().empty() ? "true" : "false"); + c2_ops.insert(++insert_point_c2, c1_operators.begin(), c1_operators.end()); return result; } diff --git a/src/tree.cpp b/src/tree.cpp index 3a0c690..dc5f9e4 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -40,7 +40,7 @@ namespace blt::gp operations_stack.pop_back(); if (operation.is_value) { - operation.transfer(values_process, value_stack, -1); + operation.transfer(values_process, value_stack); continue; } operation.func(context, values_process, value_stack);