crossover no longer produces an error on test 5

thread
Brett 2024-07-03 18:40:21 -04:00
parent 9faf7e5c61
commit 30a4a0e8d7
7 changed files with 110 additions and 67 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.48) project(blt-gp VERSION 0.0.49)
include(CTest) include(CTest)
@ -7,6 +7,7 @@ option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
option(ENABLE_TSAN "Enable the thread data race 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(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) 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_options(blt-gp PRIVATE -Wall -Wextra -Werror -Wpedantic -Wno-comment)
target_link_libraries(blt-gp PRIVATE BLT) target_link_libraries(blt-gp PRIVATE BLT)
target_compile_definitions(blt-gp PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL})
if (${ENABLE_ADDRSAN} MATCHES ON) if (${ENABLE_ADDRSAN} MATCHES ON)
target_compile_options(blt-gp PRIVATE -fsanitize=address) 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_compile_options(${name}-example PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
target_link_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) if (${ENABLE_ADDRSAN} MATCHES ON)
target_compile_options(${name}-example PRIVATE -fsanitize=address) target_compile_options(${name}-example PRIVATE -fsanitize=address)

View File

@ -43,22 +43,22 @@ static constexpr long SEED = 41912;
blt::gp::type_provider type_system; blt::gp::type_provider type_system;
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT 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 add([](float a, float b) { return a + b; }); // 0
blt::gp::operation_t sub([](float a, float b) { return a - b; }); 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; }); 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; }); 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 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; }); 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; }); 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; }); 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; }); 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; }); 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; }); 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<bool>(a ^ b); }); blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast<bool>(a ^ b); }); // 11
blt::gp::operation_t op_not([](bool b) { return !b; }); 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<float> dist(-32000, 32000); //static std::uniform_real_distribution<float> dist(-32000, 32000);
static std::uniform_real_distribution<float> dist(0.0f, 10.0f); static std::uniform_real_distribution<float> dist(0.0f, 10.0f);
return dist(program.get_random()); return dist(program.get_random());
@ -107,6 +107,7 @@ int main()
auto& ind = pop.getIndividuals(); auto& ind = pop.getIndividuals();
auto results = crossover.apply(program, ind[0], ind[1]); auto results = crossover.apply(program, ind[0], ind[1]);
BLT_INFO("Post crossover:");
if (results.has_value()) if (results.has_value())
{ {

View File

@ -54,7 +54,7 @@ namespace blt::gp
// context*, read stack, write stack // context*, read stack, write stack
using callable_t = std::function<void(void*, stack_allocator&, stack_allocator&)>; using callable_t = std::function<void(void*, stack_allocator&, stack_allocator&)>;
// to, from // to, from
using transfer_t = std::function<void(stack_allocator&, stack_allocator&, blt::ptrdiff_t)>; using transfer_t = std::function<void(stack_allocator&, stack_allocator&)>;
} }
} }

View File

@ -117,11 +117,15 @@ namespace blt::gp
BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!"); BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!");
info.function = op.template make_callable<Context>(); info.function = op.template make_callable<Context>();
info.transfer = [](stack_allocator& to, stack_allocator& from, blt::ptrdiff_t offset) { info.transfer = [](stack_allocator& to, stack_allocator& from) {
if (offset < 0) #if BLT_DEBUG_LEVEL >= 3
to.push(from.pop<Return>()); auto value = from.pop<Return>();
else BLT_TRACE_STREAM << value << "\n";
to.push(from.from<Return>(offset)); to.push(value);
#else
to.push(from.pop<Return>());
#endif
}; };
storage.operators.push_back(info); storage.operators.push_back(info);
if (is_static) if (is_static)

View File

@ -106,8 +106,25 @@ namespace blt::gp
void pop_bytes(blt::ptrdiff_t bytes) void pop_bytes(blt::ptrdiff_t bytes)
{ {
#if BLT_DEBUG_LEVEL >= 3
blt::size_t counter = 0;
#endif
while (bytes > 0) 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; 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 // 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 // and pop from it, update the amount of bytes to reflect the amount removed from the current block

View File

@ -27,8 +27,10 @@ namespace blt::gp
const auto& config = program.get_config(); const auto& config = program.get_config();
result_t result{p1, p2}; 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 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"); BLT_INFO("Child 2 Stack empty? %s", result.child2.get_values().empty() ? "true" : "false");
#endif
auto& c1 = result.child1; auto& c1 = result.child1;
auto& c2 = result.child2; auto& c2 = result.child2;
@ -82,6 +84,9 @@ namespace blt::gp
do do
{ {
const auto& type = program.get_operator_info(c1_ops[index].id); 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) if (type.argc.argc > 0)
children_left += type.argc.argc; children_left += type.argc.argc;
else else
@ -91,6 +96,9 @@ namespace blt::gp
auto crossover_point_begin_itr = c1_ops.begin() + static_cast<blt::ptrdiff_t>(crossover_point); auto crossover_point_begin_itr = c1_ops.begin() + static_cast<blt::ptrdiff_t>(crossover_point);
auto crossover_point_end_itr = c1_ops.begin() + static_cast<blt::ptrdiff_t>(index); auto crossover_point_end_itr = c1_ops.begin() + static_cast<blt::ptrdiff_t>(index);
#if BLT_DEBUG_LEVEL > 0
BLT_TRACE("[%ld %ld) %ld", crossover_point, index, index - crossover_point);
#endif
children_left = 0; children_left = 0;
index = attempted_point; index = attempted_point;
@ -98,19 +106,23 @@ namespace blt::gp
do do
{ {
const auto& type = program.get_operator_info(c2_ops[index].id); 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) if (type.argc.argc > 0)
children_left += type.argc.argc; children_left += type.argc.argc;
else else
children_left--; children_left--;
if (children_left > 0) index++;
index++; } while (children_left > 0);
else
break;
} while (true);
auto found_point_begin_itr = c2_ops.begin() + static_cast<blt::ptrdiff_t>(attempted_point); auto found_point_begin_itr = c2_ops.begin() + static_cast<blt::ptrdiff_t>(attempted_point);
auto found_point_end_itr = c2_ops.begin() + static_cast<blt::ptrdiff_t>(index); auto found_point_end_itr = c2_ops.begin() + static_cast<blt::ptrdiff_t>(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& c1_stack_init = c1.get_values();
stack_allocator& c2_stack_init = c2.get_values(); stack_allocator& c2_stack_init = c2.get_values();
@ -122,83 +134,92 @@ namespace blt::gp
for (const auto& op : blt::enumerate(found_point_begin_itr, found_point_end_itr)) for (const auto& op : blt::enumerate(found_point_begin_itr, found_point_end_itr))
c2_operators.push_back(op); 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_after_copy;
stack_allocator c1_stack_for_copy; stack_allocator c1_stack_for_copy;
stack_allocator c2_stack_after_copy; stack_allocator c2_stack_after_copy;
stack_allocator c2_stack_for_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 // 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--) for (auto it = c1_ops.end() - 1; it != crossover_point_end_itr - 1; it--)
{ {
if (it->is_value) 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. // transfer all values for the crossover point.
for (auto it = crossover_point_end_itr - 1; it != crossover_point_begin_itr - 1; it--) for (auto it = crossover_point_end_itr - 1; it != crossover_point_begin_itr - 1; it--)
{ {
if (it->is_value) 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 // transfer child2 values for copying back into c1
for (auto it = c2_ops.end() - 1; it != found_point_end_itr - 1; it--) for (auto it = c2_ops.end() - 1; it != found_point_end_itr - 1; it--)
{ {
if (it->is_value) 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--) for (auto it = found_point_end_itr - 1; it != found_point_begin_itr - 1; it--)
{ {
if (it->is_value) 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"); #if BLT_DEBUG_LEVEL > 1
BLT_TRACE("c1_stack_for_copy empty? %s", c1_stack_for_copy.empty() ? "true" : "false"); BLT_DEBUG("Transferring back for crossover 1:");
BLT_TRACE("c2_stack_after_copy empty? %s", c2_stack_after_copy.empty() ? "true" : "false"); #endif
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");
// now copy back into the respective children // now copy back into the respective children
for (auto it = found_point_begin_itr; it != found_point_end_itr; it++) for (auto it = found_point_begin_itr; it != found_point_end_itr; it++)
{ {
if (it->is_value) 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++) for (auto it = crossover_point_begin_itr; it != crossover_point_end_itr; it++)
{ {
if (it->is_value) 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"); #if BLT_DEBUG_LEVEL > 1
BLT_TRACE("c1_stack_for_copy empty? %s", c1_stack_for_copy.empty() ? "true" : "false"); BLT_DEBUG("Transferring back after crossover 1:");
BLT_TRACE("c2_stack_after_copy empty? %s", c2_stack_after_copy.empty() ? "true" : "false"); #endif
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");
// now copy after the crossover point back to the correct children // now copy after the crossover point back to the correct children
for (auto it = crossover_point_end_itr; it != c1_ops.end(); it++) for (auto it = crossover_point_end_itr; it != c1_ops.end(); it++)
{ {
if (it->is_value) 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++) for (auto it = found_point_end_itr; it != c2_ops.end(); it++)
{ {
if (it->is_value) 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 // now swap the operators
auto insert_point_c1 = crossover_point_begin_itr - 1; auto insert_point_c1 = crossover_point_begin_itr - 1;
auto insert_point_c2 = found_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); 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_c1, c2_operators.begin(), c2_operators.end());
c1_ops.insert(++insert_point_c2, c1_operators.begin(), c1_operators.end()); c2_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");
return result; return result;
} }

View File

@ -40,7 +40,7 @@ namespace blt::gp
operations_stack.pop_back(); operations_stack.pop_back();
if (operation.is_value) if (operation.is_value)
{ {
operation.transfer(values_process, value_stack, -1); operation.transfer(values_process, value_stack);
continue; continue;
} }
operation.func(context, values_process, value_stack); operation.func(context, values_process, value_stack);