From 5346a2c77a7c85d108fa4443a8b37197296ee822 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Sun, 30 Jun 2024 20:20:11 -0400 Subject: [PATCH] refactor for using operator_info container, more cache local --- CMakeLists.txt | 2 +- include/blt/gp/program.h | 62 +++++++++++++++------------------------- src/generators.cpp | 32 +++++++++++---------- 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8428a72..85b171b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.0.44) +project(blt-gp VERSION 0.0.45) include(CTest) diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 369e247..5bba73f 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -43,9 +43,6 @@ namespace blt::gp { - static constexpr blt::size_t NONE_T = 0x0; - static constexpr blt::size_t STATIC_T = 0x1; - static constexpr blt::size_t TERMINAL_T = 0x2; struct argc_t { @@ -70,10 +67,11 @@ namespace blt::gp blt::expanding_buffer>> operators_ordered_terminals; // indexed from OPERATOR ID (operator number) blt::hashset_t static_types; - blt::expanding_buffer> argument_types; - blt::expanding_buffer operator_argc; - std::vector operators; - std::vector transfer_funcs; +// blt::expanding_buffer> argument_types; +// blt::expanding_buffer operator_argc; +// std::vector operators; +// std::vector transfer_funcs; + std::vector operators; }; template @@ -96,27 +94,28 @@ namespace blt::gp auto& operator_list = op.get_argc() == 0 ? storage.terminals : storage.non_terminals; operator_list[return_type_id].push_back(operator_id); + operator_info info; + if constexpr (sizeof...(Args) > 0) { - (add_non_context_argument(operator_id), ...); + (add_non_context_argument(info.argument_types), ...); } - argc_t argc; - argc.argc_context = argc.argc = sizeof...(Args); + info.argc.argc_context = info.argc.argc = sizeof...(Args); + info.return_type = system.get_type().id(); - ((std::is_same_v, Context> ? argc.argc -= 1 : (blt::size_t) nullptr), ...); + ((std::is_same_v, Context> ? info.argc.argc -= 1 : (blt::size_t) nullptr), ...); - BLT_ASSERT(argc.argc_context - 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!"); - storage.operator_argc[operator_id] = argc; - - storage.operators.push_back(op.template make_callable()); - storage.transfer_funcs.push_back([](stack_allocator& to, stack_allocator& from, blt::ptrdiff_t offset) { + 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)); - }); + }; + storage.operators.push_back(info); if (is_static) storage.static_types.insert(operator_id); return *this; @@ -142,9 +141,9 @@ namespace blt::gp { // count number of terminals blt::size_t terminals = 0; - for (const auto& type : storage.argument_types[op]) + for (const auto& type : storage.operators[op].argument_types) { - if (has_terminals.contains(type.id())) + if (has_terminals.contains(type)) terminals++; } ordered_terminals.emplace_back(op, terminals); @@ -153,7 +152,7 @@ namespace blt::gp bool matches_argc = false; for (const auto& terms : ordered_terminals) { - if (terms.second == storage.operator_argc[terms.first].argc) + if (terms.second == storage.operators[terms.first].argc.argc) matches_argc = true; if (terms.second != 0) found_terminal_inputs = true; @@ -187,11 +186,11 @@ namespace blt::gp private: template - void add_non_context_argument(blt::gp::operator_id operator_id) + void add_non_context_argument(decltype(operator_info::argument_types)& types) { if constexpr (!std::is_same_v>) { - storage.argument_types[operator_id].push_back(system.get_type()); + types.push_back(system.get_type().id()); } } @@ -263,9 +262,9 @@ namespace blt::gp return storage.operators_ordered_terminals[id][dist(engine)].first; } - inline std::vector& get_argument_types(operator_id id) + inline operator_info& get_operator_info(operator_id id) { - return storage.argument_types[id]; + return storage.operators[id]; } inline std::vector& get_type_terminals(type_id id) @@ -278,21 +277,6 @@ namespace blt::gp return storage.non_terminals[id]; } - inline argc_t get_argc(operator_id id) - { - return storage.operator_argc[id]; - } - - inline detail::callable_t& get_operation(operator_id id) - { - return storage.operators[id]; - } - - inline detail::transfer_t& get_transfer_func(operator_id id) - { - return storage.transfer_funcs[id]; - } - inline bool is_static(operator_id id) { return storage.static_types.contains(static_cast(id)); diff --git a/src/generators.cpp b/src/generators.cpp index 4e20e99..d66f59d 100644 --- a/src/generators.cpp +++ b/src/generators.cpp @@ -60,19 +60,21 @@ namespace blt::gp auto top = tree_generator.top(); tree_generator.pop(); + auto& info = args.program.get_operator_info(top.id); + tree.get_operations().emplace_back( - args.program.get_operation(top.id), - args.program.get_transfer_func(top.id), + info.function, + info.transfer, args.program.is_static(top.id)); max_depth = std::max(max_depth, top.depth); if (args.program.is_static(top.id)) { - args.program.get_operation(top.id)(nullptr, tree.get_values(), tree.get_values()); + info.function(nullptr, tree.get_values(), tree.get_values()); continue; } - for (const auto& child : args.program.get_argument_types(top.id)) + for (const auto& child : info.argument_types) std::forward(perChild)(args.program, tree_generator, child, top.depth + 1); } @@ -81,34 +83,34 @@ namespace blt::gp tree_t grow_generator_t::generate(const generator_arguments& args) { - return create_tree([args](gp_program& program, std::stack& tree_generator, const type& type, blt::size_t new_depth) { + return create_tree([args](gp_program& program, std::stack& tree_generator, type_id type, blt::size_t new_depth) { if (new_depth >= args.max_depth) { - if (program.get_type_terminals(type.id()).empty()) - tree_generator.push({program.select_non_terminal_too_deep(type.id()), new_depth}); + if (program.get_type_terminals(type).empty()) + tree_generator.push({program.select_non_terminal_too_deep(type), new_depth}); else - tree_generator.push({program.select_terminal(type.id()), new_depth}); + tree_generator.push({program.select_terminal(type), new_depth}); return; } if (program.choice() || new_depth < args.min_depth) - tree_generator.push({program.select_non_terminal(type.id()), new_depth}); + tree_generator.push({program.select_non_terminal(type), new_depth}); else - tree_generator.push({program.select_terminal(type.id()), new_depth}); + tree_generator.push({program.select_terminal(type), new_depth}); }, args); } tree_t full_generator_t::generate(const generator_arguments& args) { - return create_tree([args](gp_program& program, std::stack& tree_generator, const type& type, blt::size_t new_depth) { + return create_tree([args](gp_program& program, std::stack& tree_generator, type_id type, blt::size_t new_depth) { if (new_depth >= args.max_depth) { - if (program.get_type_terminals(type.id()).empty()) - tree_generator.push({program.select_non_terminal_too_deep(type.id()), new_depth}); + if (program.get_type_terminals(type).empty()) + tree_generator.push({program.select_non_terminal_too_deep(type), new_depth}); else - tree_generator.push({program.select_terminal(type.id()), new_depth}); + tree_generator.push({program.select_terminal(type), new_depth}); return; } - tree_generator.push({program.select_non_terminal(type.id()), new_depth}); + tree_generator.push({program.select_non_terminal(type), new_depth}); }, args); }