refactor for using operator_info container, more cache local
parent
96d8b278e8
commit
5346a2c77a
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.44)
|
project(blt-gp VERSION 0.0.45)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,6 @@
|
||||||
|
|
||||||
namespace blt::gp
|
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
|
struct argc_t
|
||||||
{
|
{
|
||||||
|
@ -70,10 +67,11 @@ namespace blt::gp
|
||||||
blt::expanding_buffer<std::vector<std::pair<operator_id, blt::size_t>>> operators_ordered_terminals;
|
blt::expanding_buffer<std::vector<std::pair<operator_id, blt::size_t>>> operators_ordered_terminals;
|
||||||
// indexed from OPERATOR ID (operator number)
|
// indexed from OPERATOR ID (operator number)
|
||||||
blt::hashset_t<operator_id> static_types;
|
blt::hashset_t<operator_id> static_types;
|
||||||
blt::expanding_buffer<std::vector<type>> argument_types;
|
// blt::expanding_buffer<std::vector<type>> argument_types;
|
||||||
blt::expanding_buffer<argc_t> operator_argc;
|
// blt::expanding_buffer<argc_t> operator_argc;
|
||||||
std::vector<detail::callable_t> operators;
|
// std::vector<detail::callable_t> operators;
|
||||||
std::vector<detail::transfer_t> transfer_funcs;
|
// std::vector<detail::transfer_t> transfer_funcs;
|
||||||
|
std::vector<operator_info> operators;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context = detail::empty_t>
|
template<typename Context = detail::empty_t>
|
||||||
|
@ -96,27 +94,28 @@ namespace blt::gp
|
||||||
auto& operator_list = op.get_argc() == 0 ? storage.terminals : storage.non_terminals;
|
auto& operator_list = op.get_argc() == 0 ? storage.terminals : storage.non_terminals;
|
||||||
operator_list[return_type_id].push_back(operator_id);
|
operator_list[return_type_id].push_back(operator_id);
|
||||||
|
|
||||||
|
operator_info info;
|
||||||
|
|
||||||
if constexpr (sizeof...(Args) > 0)
|
if constexpr (sizeof...(Args) > 0)
|
||||||
{
|
{
|
||||||
(add_non_context_argument<Args>(operator_id), ...);
|
(add_non_context_argument<Args>(info.argument_types), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
argc_t argc;
|
info.argc.argc_context = info.argc.argc = sizeof...(Args);
|
||||||
argc.argc_context = argc.argc = sizeof...(Args);
|
info.return_type = system.get_type<Return>().id();
|
||||||
|
|
||||||
((std::is_same_v<detail::remove_cv_ref<Args>, Context> ? argc.argc -= 1 : (blt::size_t) nullptr), ...);
|
((std::is_same_v<detail::remove_cv_ref<Args>, 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;
|
info.function = op.template make_callable<Context>();
|
||||||
|
info.transfer = [](stack_allocator& to, stack_allocator& from, blt::ptrdiff_t offset) {
|
||||||
storage.operators.push_back(op.template make_callable<Context>());
|
|
||||||
storage.transfer_funcs.push_back([](stack_allocator& to, stack_allocator& from, blt::ptrdiff_t offset) {
|
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
to.push(from.pop<Return>());
|
to.push(from.pop<Return>());
|
||||||
else
|
else
|
||||||
to.push(from.from<Return>(offset));
|
to.push(from.from<Return>(offset));
|
||||||
});
|
};
|
||||||
|
storage.operators.push_back(info);
|
||||||
if (is_static)
|
if (is_static)
|
||||||
storage.static_types.insert(operator_id);
|
storage.static_types.insert(operator_id);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -142,9 +141,9 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
// count number of terminals
|
// count number of terminals
|
||||||
blt::size_t terminals = 0;
|
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++;
|
terminals++;
|
||||||
}
|
}
|
||||||
ordered_terminals.emplace_back(op, terminals);
|
ordered_terminals.emplace_back(op, terminals);
|
||||||
|
@ -153,7 +152,7 @@ namespace blt::gp
|
||||||
bool matches_argc = false;
|
bool matches_argc = false;
|
||||||
for (const auto& terms : ordered_terminals)
|
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;
|
matches_argc = true;
|
||||||
if (terms.second != 0)
|
if (terms.second != 0)
|
||||||
found_terminal_inputs = true;
|
found_terminal_inputs = true;
|
||||||
|
@ -187,11 +186,11 @@ namespace blt::gp
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
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<Context, detail::remove_cv_ref<T>>)
|
if constexpr (!std::is_same_v<Context, detail::remove_cv_ref<T>>)
|
||||||
{
|
{
|
||||||
storage.argument_types[operator_id].push_back(system.get_type<T>());
|
types.push_back(system.get_type<T>().id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,9 +262,9 @@ namespace blt::gp
|
||||||
return storage.operators_ordered_terminals[id][dist(engine)].first;
|
return storage.operators_ordered_terminals[id][dist(engine)].first;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::vector<type>& 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<operator_id>& get_type_terminals(type_id id)
|
inline std::vector<operator_id>& get_type_terminals(type_id id)
|
||||||
|
@ -278,21 +277,6 @@ namespace blt::gp
|
||||||
return storage.non_terminals[id];
|
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)
|
inline bool is_static(operator_id id)
|
||||||
{
|
{
|
||||||
return storage.static_types.contains(static_cast<blt::size_t>(id));
|
return storage.static_types.contains(static_cast<blt::size_t>(id));
|
||||||
|
|
|
@ -60,19 +60,21 @@ namespace blt::gp
|
||||||
auto top = tree_generator.top();
|
auto top = tree_generator.top();
|
||||||
tree_generator.pop();
|
tree_generator.pop();
|
||||||
|
|
||||||
|
auto& info = args.program.get_operator_info(top.id);
|
||||||
|
|
||||||
tree.get_operations().emplace_back(
|
tree.get_operations().emplace_back(
|
||||||
args.program.get_operation(top.id),
|
info.function,
|
||||||
args.program.get_transfer_func(top.id),
|
info.transfer,
|
||||||
args.program.is_static(top.id));
|
args.program.is_static(top.id));
|
||||||
max_depth = std::max(max_depth, top.depth);
|
max_depth = std::max(max_depth, top.depth);
|
||||||
|
|
||||||
if (args.program.is_static(top.id))
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& child : args.program.get_argument_types(top.id))
|
for (const auto& child : info.argument_types)
|
||||||
std::forward<Func>(perChild)(args.program, tree_generator, child, top.depth + 1);
|
std::forward<Func>(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)
|
tree_t grow_generator_t::generate(const generator_arguments& args)
|
||||||
{
|
{
|
||||||
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, const type& type, blt::size_t new_depth) {
|
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) {
|
||||||
if (new_depth >= args.max_depth)
|
if (new_depth >= args.max_depth)
|
||||||
{
|
{
|
||||||
if (program.get_type_terminals(type.id()).empty())
|
if (program.get_type_terminals(type).empty())
|
||||||
tree_generator.push({program.select_non_terminal_too_deep(type.id()), new_depth});
|
tree_generator.push({program.select_non_terminal_too_deep(type), new_depth});
|
||||||
else
|
else
|
||||||
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
tree_generator.push({program.select_terminal(type), new_depth});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (program.choice() || new_depth < args.min_depth)
|
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
|
else
|
||||||
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
tree_generator.push({program.select_terminal(type), new_depth});
|
||||||
}, args);
|
}, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_t full_generator_t::generate(const generator_arguments& args)
|
tree_t full_generator_t::generate(const generator_arguments& args)
|
||||||
{
|
{
|
||||||
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, const type& type, blt::size_t new_depth) {
|
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) {
|
||||||
if (new_depth >= args.max_depth)
|
if (new_depth >= args.max_depth)
|
||||||
{
|
{
|
||||||
if (program.get_type_terminals(type.id()).empty())
|
if (program.get_type_terminals(type).empty())
|
||||||
tree_generator.push({program.select_non_terminal_too_deep(type.id()), new_depth});
|
tree_generator.push({program.select_non_terminal_too_deep(type), new_depth});
|
||||||
else
|
else
|
||||||
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
tree_generator.push({program.select_terminal(type), new_depth});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tree_generator.push({program.select_non_terminal(type.id()), new_depth});
|
tree_generator.push({program.select_non_terminal(type), new_depth});
|
||||||
}, args);
|
}, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue