diff --git a/CMakeLists.txt b/CMakeLists.txt index caf7db2..27ddba2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.46) +project(blt-gp VERSION 0.0.47) include(CTest) diff --git a/examples/gp_test_1.cpp b/examples/gp_test_1.cpp index 8dce123..6114998 100644 --- a/examples/gp_test_1.cpp +++ b/examples/gp_test_1.cpp @@ -316,7 +316,7 @@ namespace blt::gp::detail inline blt::gp::detail::callable_t& operator[](blt::size_t index) { - return ops.operators[index]; + return ops.storage.operators[index].function; } private: diff --git a/examples/gp_test_2.cpp b/examples/gp_test_2.cpp index 8bd0277..8e15485 100644 --- a/examples/gp_test_2.cpp +++ b/examples/gp_test_2.cpp @@ -59,7 +59,7 @@ int main() silly.add_operator(pro_div); silly.add_operator(lit, true); - program.set_operations(std::move(silly)); + program.set_operations(silly.build()); blt::gp::grow_generator_t grow; auto tree = grow.generate(blt::gp::generator_arguments{program, type_system.get_type().id(), 3, 7}); diff --git a/examples/gp_test_3.cpp b/examples/gp_test_3.cpp index 699cab4..41edb8d 100644 --- a/examples/gp_test_3.cpp +++ b/examples/gp_test_3.cpp @@ -72,7 +72,7 @@ int main() silly.add_operator(lit, true); - program.set_operations(std::move(silly)); + program.set_operations(silly.build()); blt::gp::grow_generator_t grow; auto tree = grow.generate(blt::gp::generator_arguments{program, type_system.get_type().id(), 3, 7}); diff --git a/include/blt/gp/transformers.h b/include/blt/gp/transformers.h index 31c3781..25b103e 100644 --- a/include/blt/gp/transformers.h +++ b/include/blt/gp/transformers.h @@ -32,7 +32,8 @@ namespace blt::gp public: enum class error_t { - NO_VALID_TYPE + NO_VALID_TYPE, + TREE_TOO_SMALL }; struct result_t { diff --git a/lib/blt b/lib/blt index 57ddcfc..5e65416 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit 57ddcfca1e72245b8e7e59a2f6ccf2efda1b29b3 +Subproject commit 5e654166848d9a4bb06f93332e5997fc16d9388e diff --git a/src/transformers.cpp b/src/transformers.cpp index 90a8c7c..d079c8a 100644 --- a/src/transformers.cpp +++ b/src/transformers.cpp @@ -17,6 +17,7 @@ */ #include #include +#include #include namespace blt::gp @@ -32,8 +33,11 @@ namespace blt::gp auto& c1_ops = c1.get_operations(); auto& c2_ops = c2.get_operations(); - std::uniform_int_distribution op_sel1(1ul, c1_ops.size() - 1); - std::uniform_int_distribution op_sel2(1ul, c2_ops.size() - 1); + if (c1_ops.size() < 5 || c2_ops.size() < 5) + return blt::unexpected(error_t::TREE_TOO_SMALL); + + std::uniform_int_distribution op_sel1(3ul, c1_ops.size() - 1); + std::uniform_int_distribution op_sel2(3ul, c2_ops.size() - 1); blt::size_t crossover_point = op_sel1(program.get_random()); blt::size_t attempted_point = 0; @@ -69,7 +73,49 @@ namespace blt::gp } } while (crossover_point_type.return_type != attempted_point_type->return_type); - const auto& found_point_type = *attempted_point_type; + blt::i64 children_left = 0; + blt::size_t index = crossover_point; + + do + { + const auto& type = program.get_operator_info(c1_ops[index].id); + if (type.argc.argc > 0) + children_left += type.argc.argc; + else + children_left--; + index++; + } while (children_left > 0); + + auto crossover_point_end_itr = c1_ops.begin() + static_cast(index); + + children_left = 0; + index = attempted_point; + + do + { + const auto& type = program.get_operator_info(c2_ops[index].id); + if (type.argc.argc > 0) + children_left += type.argc.argc; + else + children_left--; + if (children_left > 0) + index++; + else + break; + } while (true); + + auto found_point_end_iter = c2_ops.begin() + static_cast(index); + + stack_allocator c1_stack_init = c1.get_values(); + stack_allocator c2_stack_init = c2.get_values(); + + std::vector c1_operators; + std::vector c2_operators; + + for (const auto& op : blt::enumerate(c1_ops.begin() + static_cast(crossover_point), crossover_point_end_itr)) + c1_operators.push_back(op); + for (const auto& op : blt::enumerate(c2_ops.begin() + static_cast(attempted_point), found_point_end_iter)) + c2_operators.push_back(op); return result; }