diff --git a/CMakeLists.txt b/CMakeLists.txt index a97ff82..fcb36e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(image-gp-6 VERSION 0.0.40) +project(image-gp-6 VERSION 0.0.42) include(FetchContent) diff --git a/include/custom_transformer.h b/include/custom_transformer.h index bbfe034..18f68bc 100644 --- a/include/custom_transformer.h +++ b/include/custom_transformer.h @@ -64,7 +64,6 @@ namespace blt::gp { EXPRESSION, // Generate a new random expression ADJUST, // adjust the value of the type. (if it is a function it will mutate it to a different one) - //FUNC, // Change node into a different function. Args will be generated / removed. SUB_FUNC, // subexpression becomes argument to new random function. Other args are generated. JUMP_FUNC, // subexpression becomes this new node. Other arguments discarded. COPY, // node can become copy of another subexpression. @@ -85,12 +84,11 @@ namespace blt::gp double per_node_mutation_chance = 1.0; static constexpr std::array mutation_operator_chances = aggregate_array( - 0.01, // EXPRESSION - 0.11, // ADJUST - //0.05, // FUNC + 0.05, // EXPRESSION + 0.1, // ADJUST 0.01, // SUB_FUNC - 0.1, // JUMP_FUNC - 0.05 // COPY + 0.15, // JUMP_FUNC + 0.12 // COPY ); }; } diff --git a/lib/blt-gp b/lib/blt-gp index 6e45ea3..766befd 160000 --- a/lib/blt-gp +++ b/lib/blt-gp @@ -1 +1 @@ -Subproject commit 6e45ea3d6de5c3686c969f9fdd706c527560cd8c +Subproject commit 766befd9495bb3b8ef399947801d6ea96b915779 diff --git a/src/custom_transformer.cpp b/src/custom_transformer.cpp index b70098a..c6617dd 100644 --- a/src/custom_transformer.cpp +++ b/src/custom_transformer.cpp @@ -23,7 +23,6 @@ namespace blt::gp { - template static blt::u8* get_thread_pointer_for_size(blt::size_t bytes) { @@ -46,10 +45,9 @@ namespace blt::gp auto& ops = c.get_operations(); auto& vals = c.get_values(); - double node_mutation_chance = per_node_mutation_chance * (1.0 / static_cast(ops.size())); - for (blt::size_t c_node = 0; c_node < ops.size(); c_node++) { + double node_mutation_chance = per_node_mutation_chance / static_cast(ops.size()); if (!program.get_random().choice(node_mutation_chance)) continue; @@ -95,33 +93,11 @@ namespace blt::gp program.get_type_non_terminals(current_func_info.return_type.id)); auto& replacement_func_info = program.get_operator_info(random_replacement); - struct child_t - { - blt::ptrdiff_t start; - // one past the end - blt::ptrdiff_t end; - }; - // cache memory used for offset data. - thread_local static std::vector children_data; + thread_local static std::vector children_data; children_data.clear(); - while (children_data.size() < current_func_info.argument_types.size()) - { - auto current_point = children_data.size(); - child_t prev{}; - if (current_point == 0) - { - // first child. - prev = {static_cast(c_node + 1), - c.find_endpoint(program, static_cast(c_node + 1))}; - children_data.push_back(prev); - continue; - } else - prev = children_data[current_point - 1]; - child_t next = {prev.end, c.find_endpoint(program, prev.end)}; - children_data.push_back(next); - } + c.find_child_extends(program, children_data, c_node, current_func_info.argument_types.size()); for (const auto& [index, val] : blt::enumerate(replacement_func_info.argument_types)) { @@ -286,8 +262,6 @@ namespace blt::gp break; case mutation_operator::SUB_FUNC: { - BLT_TRACE(ops[c_node].id); - BLT_TRACE(std::string(*program.get_name(ops[c_node].id)).c_str()); auto& current_func_info = program.get_operator_info(ops[c_node].id); // need to: @@ -358,8 +332,8 @@ namespace blt::gp ops.insert(ops.begin() + static_cast(c_node), {replacement_func_info.function, program.get_typesystem().get_type(replacement_func_info.return_type).size(), random_replacement, program.is_static(random_replacement)}); - - #if BLT_DEBUG_LEVEL >= 2 + +#if BLT_DEBUG_LEVEL >= 2 if (!c.check(program, nullptr)) { std::cout << "Parent: " << std::endl; @@ -371,16 +345,145 @@ namespace blt::gp std::cout << std::endl; BLT_ABORT("Tree Check Failed."); } - #endif +#endif } break; case mutation_operator::JUMP_FUNC: { - c.print(program, std::cout, false, true); - auto parent = c.find_parent(program, static_cast(c_node)); - BLT_TRACE_STREAM << "Found Parent: " << *program.get_name(ops[parent].id) << " for child " << *program.get_name(ops[c_node].id) << "\n"; - }break; + auto& info = program.get_operator_info(ops[c_node].id); + blt::size_t argument_index = -1ul; + for (const auto& [index, v] : blt::enumerate(info.argument_types)) + { + if (v.id == info.return_type.id) + { + argument_index = index; + break; + } + } + if (argument_index == -1ul) + continue; + + static thread_local std::vector child_data; + child_data.clear(); + + c.find_child_extends(program, child_data, c_node, info.argument_types.size()); + + auto child_index = child_data.size() - 1 - argument_index; + auto child = child_data[child_index]; + auto for_bytes = c.total_value_bytes(child.start, child.end); + auto after_bytes = c.total_value_bytes(child_data.back().end); + + auto storage_ptr = get_thread_pointer_for_size(for_bytes + after_bytes); + vals.copy_to(storage_ptr + for_bytes, after_bytes); + vals.pop_bytes(static_cast(after_bytes)); + + for (auto i = static_cast(child_data.size() - 1); i > static_cast(child_index); i--) + { + auto& cc = child_data[i]; + auto bytes = c.total_value_bytes(cc.start, cc.end); + vals.pop_bytes(static_cast(bytes)); + ops.erase(ops.begin() + cc.start, ops.begin() + cc.end); + } + vals.copy_to(storage_ptr, for_bytes); + vals.pop_bytes(static_cast(for_bytes)); + for (auto i = static_cast(child_index - 1); i >= 0; i--) + { + auto& cc = child_data[i]; + auto bytes = c.total_value_bytes(cc.start, cc.end); + vals.pop_bytes(static_cast(bytes)); + ops.erase(ops.begin() + cc.start, ops.begin() + cc.end); + } + ops.erase(ops.begin() + static_cast(c_node)); + vals.copy_from(storage_ptr, for_bytes + after_bytes); + +#if BLT_DEBUG_LEVEL >= 2 + if (!c.check(program, nullptr)) + { + std::cout << "Parent: " << std::endl; + p.print(program, std::cout, false, true); + std::cout << "Child Values:" << std::endl; + c.print(program, std::cout, true, true); + std::cout << std::endl; + BLT_ABORT("Tree Check Failed."); + } +#endif + } + break; case mutation_operator::COPY: + { + auto& info = program.get_operator_info(ops[c_node].id); + blt::size_t pt = -1ul; + blt::size_t pf = -1ul; + for (const auto& [index, v] : blt::enumerate(info.argument_types)) + { + for (blt::size_t i = index + 1; i < info.argument_types.size(); i++) + { + auto& v1 = info.argument_types[i]; + if (v == v1) + { + if (pt == -1ul) + pt = index; + else + pf = index; + break; + } + } + if (pt != -1ul && pf != -1ul) + break; + } + if (pt == -1ul || pf == -1ul) + continue; + + blt::size_t from = 0; + blt::size_t to = 0; + + if (program.get_random().choice()) + { + from = pt; + to = pf; + } else + { + from = pf; + to = pt; + } + + static thread_local std::vector child_data; + child_data.clear(); + + c.find_child_extends(program, child_data, c_node, info.argument_types.size()); + + auto from_index = child_data.size() - 1 - from; + auto to_index = child_data.size() - 1 - to; + auto& from_child = child_data[from_index]; + auto& to_child = child_data[to_index]; + blt::size_t from_bytes = c.total_value_bytes(from_child.start, from_child.end); + blt::size_t after_from_bytes = c.total_value_bytes(from_child.end); + blt::size_t to_bytes = c.total_value_bytes(to_child.start, to_child.end); + blt::size_t after_to_bytes = c.total_value_bytes(to_child.end); + + auto after_bytes = std::max(after_from_bytes, after_to_bytes); + + auto from_ptr = get_thread_pointer_for_size(from_bytes); + auto after_ptr = get_thread_pointer_for_size(after_bytes); + + vals.copy_to(after_ptr, after_from_bytes); + vals.pop_bytes(static_cast(after_from_bytes)); + vals.copy_to(from_ptr, from_bytes); + vals.copy_from(after_ptr, after_from_bytes); + + vals.copy_to(after_ptr, after_to_bytes); + vals.pop_bytes(static_cast(after_to_bytes + to_bytes)); + + vals.copy_from(from_ptr, from_bytes); + vals.copy_from(after_ptr, after_to_bytes); + + static std::vector op_copy; + op_copy.clear(); + op_copy.insert(op_copy.begin(), ops.begin() + from_child.start, ops.begin() + from_child.end); + + ops.erase(ops.begin() + to_child.start, ops.begin() + to_child.end); + ops.insert(ops.begin() + to_child.start, op_copy.begin(), op_copy.end()); + } break; case mutation_operator::END: default: @@ -404,8 +507,6 @@ namespace blt::gp } #endif - BLT_TRACE("- - - - - - - - - Passed and finished - - - - - - - - -"); - return c; }