Compare commits
2 Commits
1e9442bbd4
...
db0c7da8e7
Author | SHA1 | Date |
---|---|---|
|
db0c7da8e7 | |
|
32a83e725c |
|
@ -27,7 +27,7 @@ macro(compile_options target_name)
|
||||||
sanitizers(${target_name})
|
sanitizers(${target_name})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
project(blt-gp VERSION 0.3.8)
|
project(blt-gp VERSION 0.3.9)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
@ -107,17 +107,17 @@ endif ()
|
||||||
|
|
||||||
if (${BUILD_GP_TESTS})
|
if (${BUILD_GP_TESTS})
|
||||||
|
|
||||||
blt_add_project(blt-stack tests/old/stack_tests.cpp test)
|
# blt_add_project(blt-stack tests/old/stack_tests.cpp test)
|
||||||
blt_add_project(blt-eval tests/old/evaluation_tests.cpp test)
|
# blt_add_project(blt-eval tests/old/evaluation_tests.cpp test)
|
||||||
blt_add_project(blt-order tests/old/order_tests.cpp test)
|
# blt_add_project(blt-order tests/old/order_tests.cpp test)
|
||||||
#blt_add_project(blt-destructor tests/destructor_test.cpp test)
|
#blt_add_project(blt-destructor tests/destructor_test.cpp test)
|
||||||
blt_add_project(blt-gp1 tests/old/gp_test_1.cpp test)
|
# blt_add_project(blt-gp1 tests/old/gp_test_1.cpp test)
|
||||||
blt_add_project(blt-gp2 tests/old/gp_test_2.cpp test)
|
# blt_add_project(blt-gp2 tests/old/gp_test_2.cpp test)
|
||||||
blt_add_project(blt-gp3 tests/old/gp_test_3.cpp test)
|
# blt_add_project(blt-gp3 tests/old/gp_test_3.cpp test)
|
||||||
blt_add_project(blt-gp4 tests/old/gp_test_4.cpp test)
|
# blt_add_project(blt-gp4 tests/old/gp_test_4.cpp test)
|
||||||
blt_add_project(blt-gp5 tests/old/gp_test_5.cpp test)
|
# blt_add_project(blt-gp5 tests/old/gp_test_5.cpp test)
|
||||||
blt_add_project(blt-gp6 tests/old/gp_test_6.cpp test)
|
# blt_add_project(blt-gp6 tests/old/gp_test_6.cpp test)
|
||||||
blt_add_project(blt-gp7 tests/old/gp_test_7.cpp test)
|
# blt_add_project(blt-gp7 tests/old/gp_test_7.cpp test)
|
||||||
|
|
||||||
blt_add_project(blt-symbolic-regression tests/symbolic_regression_test.cpp test)
|
blt_add_project(blt-symbolic-regression tests/symbolic_regression_test.cpp test)
|
||||||
|
|
||||||
|
|
|
@ -22,53 +22,13 @@
|
||||||
#include <blt/std/types.h>
|
#include <blt/std/types.h>
|
||||||
#include <blt/gp/typesystem.h>
|
#include <blt/gp/typesystem.h>
|
||||||
#include <blt/gp/stack.h>
|
#include <blt/gp/stack.h>
|
||||||
|
#include <blt/gp/util/meta.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<typename T>
|
|
||||||
using remove_cv_ref = std::remove_cv_t<std::remove_reference_t<T>>;
|
|
||||||
|
|
||||||
|
|
||||||
template<typename...>
|
|
||||||
struct first_arg;
|
|
||||||
|
|
||||||
template<typename First, typename... Args>
|
|
||||||
struct first_arg<First, Args...>
|
|
||||||
{
|
|
||||||
using type = First;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct first_arg<>
|
|
||||||
{
|
|
||||||
using type = void;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<bool b, typename... types>
|
|
||||||
struct is_same;
|
|
||||||
|
|
||||||
template<typename... types>
|
|
||||||
struct is_same<true, types...> : public std::false_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... types>
|
|
||||||
struct is_same<false, types...> : public std::is_same<types...>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... types>
|
|
||||||
constexpr bool is_same_v = is_same<sizeof...(types) == 0, types...>::value;
|
|
||||||
|
|
||||||
struct empty_t
|
|
||||||
{
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Return, typename... Args>
|
template<typename Return, typename... Args>
|
||||||
struct call_with
|
struct call_with
|
||||||
|
@ -102,7 +62,7 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename context = void, typename... NoCtxArgs>
|
template<typename context = void, typename... NoCtxArgs>
|
||||||
void call_destructors_without_first(stack_allocator& read_allocator)
|
void call_destructors_without_first(stack_allocator& read_allocator) const
|
||||||
{
|
{
|
||||||
if constexpr (sizeof...(NoCtxArgs) > 0)
|
if constexpr (sizeof...(NoCtxArgs) > 0)
|
||||||
{
|
{
|
||||||
|
@ -111,9 +71,9 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Func, typename... ExtraArgs>
|
template<typename Func, typename... ExtraArgs>
|
||||||
Return operator()(bool has_context, Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args)
|
Return operator()(const bool has_context, Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args)
|
||||||
{
|
{
|
||||||
constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
|
constexpr auto seq = std::make_integer_sequence<u64, sizeof...(Args)>();
|
||||||
#if BLT_DEBUG_LEVEL > 0
|
#if BLT_DEBUG_LEVEL > 0
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -213,16 +173,21 @@ namespace blt::gp
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto set_ephemeral()
|
auto set_ephemeral()
|
||||||
{
|
{
|
||||||
is_ephemeral_ = true;
|
is_ephemeral_ = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_ephemeral()
|
bool is_ephemeral() const
|
||||||
{
|
{
|
||||||
return is_ephemeral_;
|
return is_ephemeral_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool return_has_drop() const
|
||||||
|
{
|
||||||
|
return detail::has_func_drop_v<Return>;
|
||||||
|
}
|
||||||
|
|
||||||
operator_id id = -1;
|
operator_id id = -1;
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -57,6 +57,29 @@
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
struct operator_special_flags
|
||||||
|
{
|
||||||
|
explicit operator_special_flags(const bool is_ephemeral = false, const bool has_drop = false): m_ephemeral(is_ephemeral), m_drop(has_drop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool is_ephemeral() const
|
||||||
|
{
|
||||||
|
return m_ephemeral;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool has_drop() const
|
||||||
|
{
|
||||||
|
return m_drop;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_ephemeral : 1;
|
||||||
|
bool m_drop : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(operator_special_flags) == 1, "Size of operator flags struct is expected to be 1 byte!");
|
||||||
|
|
||||||
struct argc_t
|
struct argc_t
|
||||||
{
|
{
|
||||||
blt::u32 argc = 0;
|
blt::u32 argc = 0;
|
||||||
|
@ -90,11 +113,12 @@ namespace blt::gp
|
||||||
struct program_operator_storage_t
|
struct program_operator_storage_t
|
||||||
{
|
{
|
||||||
// indexed from return TYPE ID, returns index of operator
|
// indexed from return TYPE ID, returns index of operator
|
||||||
blt::expanding_buffer<tracked_vector<operator_id>> terminals;
|
expanding_buffer<tracked_vector<operator_id>> terminals;
|
||||||
blt::expanding_buffer<tracked_vector<operator_id>> non_terminals;
|
expanding_buffer<tracked_vector<operator_id>> non_terminals;
|
||||||
blt::expanding_buffer<tracked_vector<std::pair<operator_id, blt::size_t>>> operators_ordered_terminals;
|
expanding_buffer<tracked_vector<std::pair<operator_id, size_t>>> operators_ordered_terminals;
|
||||||
// indexed from OPERATOR ID (operator number)
|
// indexed from OPERATOR ID (operator number) to a bitfield of flags
|
||||||
blt::hashset_t<operator_id> ephemeral_leaf_operators;
|
hashmap_t<operator_id, operator_special_flags> operator_flags;
|
||||||
|
|
||||||
tracked_vector<operator_info_t> operators;
|
tracked_vector<operator_info_t> operators;
|
||||||
tracked_vector<operator_metadata_t> operator_metadata;
|
tracked_vector<operator_metadata_t> operator_metadata;
|
||||||
tracked_vector<detail::print_func_t> print_funcs;
|
tracked_vector<detail::print_func_t> print_funcs;
|
||||||
|
@ -128,33 +152,9 @@ namespace blt::gp
|
||||||
largest_returns)), ...);
|
largest_returns)), ...);
|
||||||
|
|
||||||
// largest = largest * largest_argc;
|
// largest = largest * largest_argc;
|
||||||
blt::size_t largest = largest_args * largest_argc * largest_returns * largest_argc;
|
size_t largest = largest_args * largest_argc * largest_returns * largest_argc;
|
||||||
|
|
||||||
storage.eval_func = [&operators..., largest](const tree_t& tree, void* context) -> evaluation_context& {
|
storage.eval_func = tree_t::make_execution_lambda<Context>(largest, operators...);
|
||||||
const auto& ops = tree.get_operations();
|
|
||||||
const auto& vals = tree.get_values();
|
|
||||||
|
|
||||||
static thread_local evaluation_context results{};
|
|
||||||
results.values.reset();
|
|
||||||
results.values.reserve(largest);
|
|
||||||
|
|
||||||
blt::size_t total_so_far = 0;
|
|
||||||
blt::size_t op_pos = 0;
|
|
||||||
|
|
||||||
for (const auto& operation : iterate(ops).rev())
|
|
||||||
{
|
|
||||||
op_pos++;
|
|
||||||
if (operation.is_value())
|
|
||||||
{
|
|
||||||
total_so_far += operation.type_size();
|
|
||||||
results.values.copy_from(vals.from(total_so_far), operation.type_size());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
call_jmp_table(operation.id(), context, results.values, results.values, operators...);
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
blt::hashset_t<type_id> has_terminals;
|
blt::hashset_t<type_id> has_terminals;
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ namespace blt::gp
|
||||||
out << "[Printing Value on '" << (op.get_name() ? *op.get_name() : "") << "' Not Supported!]";
|
out << "[Printing Value on '" << (op.get_name() ? *op.get_name() : "") << "' Not Supported!]";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
storage.destroy_funcs.push_back([](detail::destroy_t type, stack_allocator& alloc)
|
storage.destroy_funcs.push_back([](const detail::destroy_t type, stack_allocator& alloc)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -293,8 +293,7 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
storage.names.push_back(op.get_name());
|
storage.names.push_back(op.get_name());
|
||||||
if (op.is_ephemeral())
|
storage.operator_flags.emplace(operator_id, operator_special_flags{op.is_ephemeral(), op.return_has_drop()});
|
||||||
storage.ephemeral_leaf_operators.insert(operator_id);
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,48 +306,7 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Operator>
|
private:
|
||||||
static void execute(void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation)
|
|
||||||
{
|
|
||||||
if constexpr (std::is_same_v<detail::remove_cv_ref<typename Operator::First_Arg>, Context>)
|
|
||||||
{
|
|
||||||
write_stack.push(operation(context, read_stack));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
write_stack.push(operation(read_stack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <blt::size_t id, typename Operator>
|
|
||||||
static bool call(blt::size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation)
|
|
||||||
{
|
|
||||||
if (id == op)
|
|
||||||
{
|
|
||||||
execute(context, write_stack, read_stack, operation);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Operators, size_t... operator_ids>
|
|
||||||
static void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack,
|
|
||||||
std::integer_sequence<size_t, operator_ids...>, Operators&... operators)
|
|
||||||
{
|
|
||||||
if (op >= sizeof...(operator_ids))
|
|
||||||
{
|
|
||||||
BLT_UNREACHABLE;
|
|
||||||
}
|
|
||||||
(call<operator_ids>(op, context, write_stack, read_stack, operators) && ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename... Operators>
|
|
||||||
static void call_jmp_table(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack,
|
|
||||||
Operators&... operators)
|
|
||||||
{
|
|
||||||
call_jmp_table_internal(op, context, write_stack, read_stack, std::index_sequence_for<Operators...>(), operators...);
|
|
||||||
}
|
|
||||||
|
|
||||||
program_operator_storage_t storage;
|
program_operator_storage_t storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -756,9 +714,14 @@ namespace blt::gp
|
||||||
return current_stats;
|
return current_stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool is_operator_ephemeral(operator_id id)
|
[[nodiscard]] bool is_operator_ephemeral(const operator_id id) const
|
||||||
{
|
{
|
||||||
return storage.ephemeral_leaf_operators.contains(static_cast<blt::size_t>(id));
|
return storage.operator_flags.find(static_cast<size_t>(id))->second.is_ephemeral();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool operator_has_drop(const operator_id id) const
|
||||||
|
{
|
||||||
|
return storage.operator_flags.find(static_cast<size_t>(id))->second.has_drop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_operations(program_operator_storage_t op)
|
void set_operations(program_operator_storage_t op)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef BLT_GP_TREE_H
|
#ifndef BLT_GP_TREE_H
|
||||||
#define BLT_GP_TREE_H
|
#define BLT_GP_TREE_H
|
||||||
|
|
||||||
|
#include <blt/gp/util/meta.h>
|
||||||
#include <blt/gp/typesystem.h>
|
#include <blt/gp/typesystem.h>
|
||||||
#include <blt/gp/stack.h>
|
#include <blt/gp/stack.h>
|
||||||
#include <blt/gp/fwdecl.h>
|
#include <blt/gp/fwdecl.h>
|
||||||
|
@ -31,16 +32,17 @@
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
struct op_container_t
|
struct op_container_t
|
||||||
{
|
{
|
||||||
op_container_t(const size_t type_size, const operator_id id, const bool is_value):
|
op_container_t(const size_t type_size, const operator_id id, const bool is_value):
|
||||||
m_type_size(type_size), m_id(id), m_is_value(is_value), m_has_drop(false)
|
m_type_size(type_size), m_id(id), m_is_value(is_value), m_has_drop(false)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
op_container_t(const size_t type_size, const operator_id id, const bool is_value, const bool has_drop):
|
op_container_t(const size_t type_size, const operator_id id, const bool is_value, const bool has_drop):
|
||||||
m_type_size(type_size), m_id(id), m_is_value(is_value), m_has_drop(has_drop)
|
m_type_size(type_size), m_id(id), m_is_value(is_value), m_has_drop(has_drop)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto type_size() const
|
[[nodiscard]] auto type_size() const
|
||||||
{
|
{
|
||||||
|
@ -61,206 +63,292 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
return m_has_drop;
|
return m_has_drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t m_type_size;
|
size_t m_type_size;
|
||||||
operator_id m_id;
|
operator_id m_id;
|
||||||
bool m_is_value;
|
bool m_is_value;
|
||||||
bool m_has_drop;
|
bool m_has_drop;
|
||||||
};
|
};
|
||||||
|
|
||||||
class evaluation_context
|
class evaluation_context
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit evaluation_context() = default;
|
explicit evaluation_context() = default;
|
||||||
|
|
||||||
blt::gp::stack_allocator values;
|
blt::gp::stack_allocator values;
|
||||||
};
|
};
|
||||||
|
|
||||||
class tree_t
|
class tree_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit tree_t(gp_program& program);
|
explicit tree_t(gp_program& program);
|
||||||
|
|
||||||
tree_t(const tree_t& copy) = default;
|
tree_t(const tree_t& copy): func(copy.func)
|
||||||
|
{
|
||||||
tree_t& operator=(const tree_t& copy)
|
copy_fast(copy);
|
||||||
{
|
}
|
||||||
if (this == ©)
|
|
||||||
return *this;
|
tree_t& operator=(const tree_t& copy)
|
||||||
copy_fast(copy);
|
{
|
||||||
|
if (this == ©)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
copy_fast(copy);
|
||||||
|
return *this;
|
||||||
/**
|
}
|
||||||
* This function copies the data from the provided tree, will attempt to reserve and copy in one step.
|
|
||||||
* will avoid reallocation if enough space is already present.
|
/**
|
||||||
*/
|
* This function copies the data from the provided tree, will attempt to reserve and copy in one step.
|
||||||
void copy_fast(const tree_t& copy)
|
* will avoid reallocation if enough space is already present.
|
||||||
|
*
|
||||||
|
* This function is meant to copy into and replaces data inside the tree.
|
||||||
|
*/
|
||||||
|
void copy_fast(const tree_t& copy)
|
||||||
|
{
|
||||||
|
if (this == ©)
|
||||||
|
return;
|
||||||
|
|
||||||
|
operations.reserve(copy.operations.size());
|
||||||
|
|
||||||
|
auto copy_it = copy.operations.begin();
|
||||||
|
auto op_it = operations.begin();
|
||||||
|
|
||||||
|
for (; op_it != operations.end(); ++op_it)
|
||||||
{
|
{
|
||||||
if (this == ©)
|
if (op_it->has_drop())
|
||||||
return;
|
|
||||||
values.reserve(copy.values.stored());
|
|
||||||
values.reset();
|
|
||||||
values.insert(copy.values);
|
|
||||||
|
|
||||||
operations.reserve(copy.operations.size());
|
|
||||||
|
|
||||||
auto copy_it = copy.operations.begin();
|
|
||||||
auto op_it = operations.begin();
|
|
||||||
|
|
||||||
for (; op_it != operations.end(); ++op_it)
|
|
||||||
{
|
{
|
||||||
if (op_it->has_drop())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
if (copy_it == copy.operations.end())
|
|
||||||
break;
|
|
||||||
*op_it = *copy_it;
|
|
||||||
if (copy_it->has_drop())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
++copy_it;
|
|
||||||
}
|
}
|
||||||
const auto op_it_cpy = op_it;
|
if (copy_it == copy.operations.end())
|
||||||
for (;op_it != operations.end(); ++op_it)
|
break;
|
||||||
|
*op_it = *copy_it;
|
||||||
|
if (copy_it->has_drop())
|
||||||
{
|
{
|
||||||
if (op_it->has_drop())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
operations.erase(op_it_cpy, operations.end());
|
++copy_it;
|
||||||
for (; copy_it != copy.operations.end(); ++copy_it)
|
|
||||||
operations.emplace_back(*copy_it);
|
|
||||||
}
|
}
|
||||||
|
const auto op_it_cpy = op_it;
|
||||||
tree_t(tree_t&& move) = default;
|
for (; op_it != operations.end(); ++op_it)
|
||||||
|
|
||||||
tree_t& operator=(tree_t&& move) = default;
|
|
||||||
|
|
||||||
void clear(gp_program& program);
|
|
||||||
|
|
||||||
struct child_t
|
|
||||||
{
|
{
|
||||||
blt::ptrdiff_t start;
|
if (op_it->has_drop())
|
||||||
// one past the end
|
{
|
||||||
blt::ptrdiff_t end;
|
}
|
||||||
|
}
|
||||||
|
operations.erase(op_it_cpy, operations.end());
|
||||||
|
for (; copy_it != copy.operations.end(); ++copy_it)
|
||||||
|
operations.emplace_back(*copy_it);
|
||||||
|
|
||||||
|
values.reserve(copy.values.stored());
|
||||||
|
values.reset();
|
||||||
|
values.insert(copy.values);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_t(tree_t&& move) = default;
|
||||||
|
|
||||||
|
tree_t& operator=(tree_t&& move) = default;
|
||||||
|
|
||||||
|
void clear(gp_program& program);
|
||||||
|
|
||||||
|
struct child_t
|
||||||
|
{
|
||||||
|
ptrdiff_t start;
|
||||||
|
// one past the end
|
||||||
|
ptrdiff_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
void insert_operator(const op_container_t& container)
|
||||||
|
{
|
||||||
|
operations.emplace_back(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
void emplace_operator(Args&&... args)
|
||||||
|
{
|
||||||
|
operations.emplace_back(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline tracked_vector<op_container_t>& get_operations()
|
||||||
|
{
|
||||||
|
return operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline const tracked_vector<op_container_t>& get_operations() const
|
||||||
|
{
|
||||||
|
return operations;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline stack_allocator& get_values()
|
||||||
|
{
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline const blt::gp::stack_allocator& get_values() const
|
||||||
|
{
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, std::enable_if_t<!(std::is_pointer_v<T> || std::is_null_pointer_v<T>), bool> = true>
|
||||||
|
[[nodiscard]] evaluation_context& evaluate(const T& context) const
|
||||||
|
{
|
||||||
|
return (*func)(*this, const_cast<void*>(static_cast<const void*>(&context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] evaluation_context& evaluate() const
|
||||||
|
{
|
||||||
|
return (*func)(*this, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
blt::size_t get_depth(gp_program& program) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper template for returning the result of the last evaluation
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T get_evaluation_value(evaluation_context& context) const
|
||||||
|
{
|
||||||
|
return context.values.pop<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper template for returning the result of the last evaluation
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T& get_evaluation_ref(evaluation_context& context) const
|
||||||
|
{
|
||||||
|
return context.values.from<T>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper template for returning the result of evaluation (this calls it)
|
||||||
|
*/
|
||||||
|
template <typename T, typename Context>
|
||||||
|
T get_evaluation_value(const Context& context) const
|
||||||
|
{
|
||||||
|
return evaluate(context).values.template pop<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get_evaluation_value() const
|
||||||
|
{
|
||||||
|
return evaluate().values.pop<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(gp_program& program, std::ostream& output, bool print_literals = true, bool pretty_indent = false,
|
||||||
|
bool include_types = false) const;
|
||||||
|
|
||||||
|
bool check(gp_program& program, void* context) const;
|
||||||
|
|
||||||
|
void find_child_extends(gp_program& program, tracked_vector<child_t>& vec, blt::size_t parent_node, blt::size_t argc) const;
|
||||||
|
|
||||||
|
// places one past the end of the child. so it's [start, end)
|
||||||
|
blt::ptrdiff_t find_endpoint(blt::gp::gp_program& program, blt::ptrdiff_t start) const;
|
||||||
|
|
||||||
|
blt::ptrdiff_t find_parent(blt::gp::gp_program& program, blt::ptrdiff_t start) const;
|
||||||
|
|
||||||
|
// valid for [begin, end)
|
||||||
|
static size_t total_value_bytes(const detail::const_op_iter_t begin, const detail::const_op_iter_t end)
|
||||||
|
{
|
||||||
|
size_t total = 0;
|
||||||
|
for (auto it = begin; it != end; ++it)
|
||||||
|
{
|
||||||
|
if (it->is_value())
|
||||||
|
total += it->type_size();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t total_value_bytes(const size_t begin, const size_t end) const
|
||||||
|
{
|
||||||
|
return total_value_bytes(operations.begin() + static_cast<blt::ptrdiff_t>(begin),
|
||||||
|
operations.begin() + static_cast<blt::ptrdiff_t>(end));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t total_value_bytes(const size_t begin) const
|
||||||
|
{
|
||||||
|
return total_value_bytes(operations.begin() + static_cast<blt::ptrdiff_t>(begin), operations.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t total_value_bytes() const
|
||||||
|
{
|
||||||
|
return total_value_bytes(operations.begin(), operations.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context, typename... Operators>
|
||||||
|
static auto make_execution_lambda(size_t call_reserve_size, Operators&... operators)
|
||||||
|
{
|
||||||
|
return [call_reserve_size, &operators...](const tree_t& tree, void* context) -> evaluation_context& {
|
||||||
|
const auto& ops = tree.operations;
|
||||||
|
const auto& vals = tree.values;
|
||||||
|
|
||||||
|
thread_local evaluation_context results{};
|
||||||
|
results.values.reset();
|
||||||
|
results.values.reserve(call_reserve_size);
|
||||||
|
|
||||||
|
size_t total_so_far = 0;
|
||||||
|
|
||||||
|
for (const auto& operation : iterate(ops).rev())
|
||||||
|
{
|
||||||
|
if (operation.is_value())
|
||||||
|
{
|
||||||
|
total_so_far += operation.type_size();
|
||||||
|
results.values.copy_from(vals.from(total_so_far), operation.type_size());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
call_jmp_table<Context>(operation.id(), context, results.values, results.values, operators...);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
[[nodiscard]] inline tracked_vector<op_container_t>& get_operations()
|
|
||||||
|
private:
|
||||||
|
template <typename Context, typename Operator>
|
||||||
|
static void execute(void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<detail::remove_cv_ref<typename Operator::First_Arg>, Context>)
|
||||||
{
|
{
|
||||||
return operations;
|
write_stack.push(operation(context, read_stack));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
[[nodiscard]] inline const tracked_vector<op_container_t>& get_operations() const
|
|
||||||
{
|
{
|
||||||
return operations;
|
write_stack.push(operation(read_stack));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
[[nodiscard]] inline stack_allocator& get_values()
|
|
||||||
|
template <typename Context, size_t id, typename Operator>
|
||||||
|
static bool call(const size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation)
|
||||||
|
{
|
||||||
|
if (id == op)
|
||||||
{
|
{
|
||||||
return values;
|
execute<Context>(context, write_stack, read_stack, operation);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
[[nodiscard]] inline const blt::gp::stack_allocator& get_values() const
|
}
|
||||||
|
|
||||||
|
template <typename Context, typename... Operators, size_t... operator_ids>
|
||||||
|
static void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack,
|
||||||
|
std::integer_sequence<size_t, operator_ids...>, Operators&... operators)
|
||||||
|
{
|
||||||
|
if (op >= sizeof...(operator_ids))
|
||||||
{
|
{
|
||||||
return values;
|
BLT_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
(call<Context, operator_ids>(op, context, write_stack, read_stack, operators) && ...);
|
||||||
template<typename T, std::enable_if_t<!(std::is_pointer_v<T> || std::is_null_pointer_v<T>), bool> = true>
|
}
|
||||||
[[nodiscard]] evaluation_context& evaluate(const T& context) const
|
|
||||||
{
|
template <typename Context, typename... Operators>
|
||||||
return (*func)(*this, const_cast<void*>(static_cast<const void*>(&context)));
|
static void call_jmp_table(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack,
|
||||||
}
|
Operators&... operators)
|
||||||
|
{
|
||||||
[[nodiscard]] evaluation_context& evaluate() const
|
call_jmp_table_internal<Context>(op, context, write_stack, read_stack, std::index_sequence_for<Operators...>(), operators...);
|
||||||
{
|
}
|
||||||
return (*func)(*this, nullptr);
|
|
||||||
}
|
tracked_vector<op_container_t> operations;
|
||||||
|
stack_allocator values;
|
||||||
blt::size_t get_depth(gp_program& program) const;
|
detail::eval_func_t* func;
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper template for returning the result of the last evaluation
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
T get_evaluation_value(evaluation_context& context) const
|
|
||||||
{
|
|
||||||
return context.values.pop<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper template for returning the result of the last evaluation
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
T& get_evaluation_ref(evaluation_context& context) const
|
|
||||||
{
|
|
||||||
return context.values.from<T>(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper template for returning the result of evaluation (this calls it)
|
|
||||||
*/
|
|
||||||
template<typename T, typename Context>
|
|
||||||
T get_evaluation_value(const Context& context) const
|
|
||||||
{
|
|
||||||
return evaluate(context).values.template pop<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T get_evaluation_value() const
|
|
||||||
{
|
|
||||||
return evaluate().values.pop<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void print(gp_program& program, std::ostream& output, bool print_literals = true, bool pretty_indent = false,
|
|
||||||
bool include_types = false) const;
|
|
||||||
|
|
||||||
bool check(gp_program& program, void* context) const;
|
|
||||||
|
|
||||||
void find_child_extends(gp_program& program, tracked_vector<child_t>& vec, blt::size_t parent_node, blt::size_t argc) const;
|
|
||||||
|
|
||||||
// places one past the end of the child. so it's [start, end)
|
|
||||||
blt::ptrdiff_t find_endpoint(blt::gp::gp_program& program, blt::ptrdiff_t start) const;
|
|
||||||
|
|
||||||
blt::ptrdiff_t find_parent(blt::gp::gp_program& program, blt::ptrdiff_t start) const;
|
|
||||||
|
|
||||||
// valid for [begin, end)
|
|
||||||
static size_t total_value_bytes(const detail::const_op_iter_t begin, const detail::const_op_iter_t end)
|
|
||||||
{
|
|
||||||
size_t total = 0;
|
|
||||||
for (auto it = begin; it != end; ++it)
|
|
||||||
{
|
|
||||||
if (it->is_value())
|
|
||||||
total += it->type_size();
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] size_t total_value_bytes(const size_t begin, const size_t end) const
|
|
||||||
{
|
|
||||||
return total_value_bytes(operations.begin() + static_cast<blt::ptrdiff_t>(begin),
|
|
||||||
operations.begin() + static_cast<blt::ptrdiff_t>(end));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] size_t total_value_bytes(const size_t begin) const
|
|
||||||
{
|
|
||||||
return total_value_bytes(operations.begin() + static_cast<blt::ptrdiff_t>(begin), operations.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] size_t total_value_bytes() const
|
|
||||||
{
|
|
||||||
return total_value_bytes(operations.begin(), operations.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
tracked_vector<op_container_t> operations;
|
|
||||||
stack_allocator values;
|
|
||||||
detail::eval_func_t* func;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fitness_t
|
struct fitness_t
|
||||||
{
|
{
|
||||||
double raw_fitness = 0;
|
double raw_fitness = 0;
|
||||||
|
@ -268,12 +356,12 @@ namespace blt::gp
|
||||||
double adjusted_fitness = 0;
|
double adjusted_fitness = 0;
|
||||||
i64 hits = 0;
|
i64 hits = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct individual_t
|
struct individual_t
|
||||||
{
|
{
|
||||||
tree_t tree;
|
tree_t tree;
|
||||||
fitness_t fitness;
|
fitness_t fitness;
|
||||||
|
|
||||||
void copy_fast(const tree_t& copy)
|
void copy_fast(const tree_t& copy)
|
||||||
{
|
{
|
||||||
// fast copy of the tree
|
// fast copy of the tree
|
||||||
|
@ -281,131 +369,134 @@ namespace blt::gp
|
||||||
// reset fitness
|
// reset fitness
|
||||||
fitness = {};
|
fitness = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
individual_t() = delete;
|
individual_t() = delete;
|
||||||
|
|
||||||
explicit individual_t(tree_t&& tree): tree(std::move(tree))
|
explicit individual_t(tree_t&& tree): tree(std::move(tree))
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
explicit individual_t(const tree_t& tree): tree(tree)
|
explicit individual_t(const tree_t& tree): tree(tree)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
individual_t(const individual_t&) = default;
|
individual_t(const individual_t&) = default;
|
||||||
|
|
||||||
individual_t(individual_t&&) = default;
|
individual_t(individual_t&&) = default;
|
||||||
|
|
||||||
individual_t& operator=(const individual_t&) = delete;
|
individual_t& operator=(const individual_t&) = delete;
|
||||||
|
|
||||||
individual_t& operator=(individual_t&&) = default;
|
individual_t& operator=(individual_t&&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class population_t
|
class population_t
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
class population_tree_iterator
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
class population_tree_iterator
|
population_tree_iterator(tracked_vector<individual_t>& ind, blt::size_t pos): ind(ind), pos(pos)
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
population_tree_iterator(tracked_vector<individual_t>& ind, blt::size_t pos): ind(ind), pos(pos)
|
|
||||||
{}
|
|
||||||
|
|
||||||
auto begin()
|
|
||||||
{
|
|
||||||
return population_tree_iterator(ind, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto end()
|
|
||||||
{
|
|
||||||
return population_tree_iterator(ind, ind.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
population_tree_iterator operator++(int)
|
|
||||||
{
|
|
||||||
auto prev = pos++;
|
|
||||||
return {ind, prev};
|
|
||||||
}
|
|
||||||
|
|
||||||
population_tree_iterator operator++()
|
|
||||||
{
|
|
||||||
return {ind, ++pos};
|
|
||||||
}
|
|
||||||
|
|
||||||
tree_t& operator*()
|
|
||||||
{
|
|
||||||
return ind[pos].tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
tree_t& operator->()
|
|
||||||
{
|
|
||||||
return ind[pos].tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(population_tree_iterator a, population_tree_iterator b)
|
|
||||||
{
|
|
||||||
return a.pos == b.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(population_tree_iterator a, population_tree_iterator b)
|
|
||||||
{
|
|
||||||
return a.pos != b.pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
tracked_vector<individual_t>& ind;
|
|
||||||
blt::size_t pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
tracked_vector<individual_t>& get_individuals()
|
|
||||||
{
|
|
||||||
return individuals;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] const tracked_vector<individual_t>& get_individuals() const
|
|
||||||
{
|
|
||||||
return individuals;
|
|
||||||
}
|
|
||||||
|
|
||||||
population_tree_iterator for_each_tree()
|
|
||||||
{
|
|
||||||
return population_tree_iterator{individuals, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto begin()
|
auto begin()
|
||||||
{
|
{
|
||||||
return individuals.begin();
|
return population_tree_iterator(ind, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto end()
|
auto end()
|
||||||
{
|
{
|
||||||
return individuals.end();
|
return population_tree_iterator(ind, ind.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto begin() const
|
population_tree_iterator operator++(int)
|
||||||
{
|
{
|
||||||
return individuals.begin();
|
auto prev = pos++;
|
||||||
|
return {ind, prev};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto end() const
|
population_tree_iterator operator++()
|
||||||
{
|
{
|
||||||
return individuals.end();
|
return {ind, ++pos};
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
tree_t& operator*()
|
||||||
{
|
{
|
||||||
individuals.clear();
|
return ind[pos].tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
population_t() = default;
|
tree_t& operator->()
|
||||||
|
{
|
||||||
population_t(const population_t&) = default;
|
return ind[pos].tree;
|
||||||
|
}
|
||||||
population_t(population_t&&) = default;
|
|
||||||
|
friend bool operator==(population_tree_iterator a, population_tree_iterator b)
|
||||||
population_t& operator=(const population_t&) = delete;
|
{
|
||||||
|
return a.pos == b.pos;
|
||||||
population_t& operator=(population_t&&) = default;
|
}
|
||||||
|
|
||||||
|
friend bool operator!=(population_tree_iterator a, population_tree_iterator b)
|
||||||
|
{
|
||||||
|
return a.pos != b.pos;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tracked_vector<individual_t> individuals;
|
tracked_vector<individual_t>& ind;
|
||||||
|
blt::size_t pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
tracked_vector<individual_t>& get_individuals()
|
||||||
|
{
|
||||||
|
return individuals;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const tracked_vector<individual_t>& get_individuals() const
|
||||||
|
{
|
||||||
|
return individuals;
|
||||||
|
}
|
||||||
|
|
||||||
|
population_tree_iterator for_each_tree()
|
||||||
|
{
|
||||||
|
return population_tree_iterator{individuals, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto begin()
|
||||||
|
{
|
||||||
|
return individuals.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end()
|
||||||
|
{
|
||||||
|
return individuals.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto begin() const
|
||||||
|
{
|
||||||
|
return individuals.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto end() const
|
||||||
|
{
|
||||||
|
return individuals.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
individuals.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
population_t() = default;
|
||||||
|
|
||||||
|
population_t(const population_t&) = default;
|
||||||
|
|
||||||
|
population_t(population_t&&) = default;
|
||||||
|
|
||||||
|
population_t& operator=(const population_t&) = delete;
|
||||||
|
|
||||||
|
population_t& operator=(population_t&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tracked_vector<individual_t> individuals;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,108 +30,116 @@
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
struct operator_id : integer_type<blt::u64>
|
struct operator_id : integer_type<u64>
|
||||||
{
|
{
|
||||||
using integer_type<blt::u64>::integer_type;
|
using integer_type::integer_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct type_id : integer_type<blt::u64>
|
struct type_id : integer_type<u64>
|
||||||
{
|
{
|
||||||
using integer_type<blt::u64>::integer_type;
|
using integer_type::integer_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
class type
|
class type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
type() = default;
|
type() = default;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static type make_type(const type_id id)
|
static type make_type(const type_id id)
|
||||||
{
|
{
|
||||||
return type(stack_allocator::aligned_size<T>(), id, blt::type_string<T>());
|
return type(stack_allocator::aligned_size<T>(), id, blt::type_string<T>(), detail::has_func_drop<T>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline blt::size_t size() const
|
[[nodiscard]] size_t size() const
|
||||||
{
|
{
|
||||||
return size_;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline type_id id() const
|
[[nodiscard]] type_id id() const
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline std::string_view name() const
|
[[nodiscard]] std::string_view name() const
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
[[nodiscard]] bool has_drop() const
|
||||||
type(size_t size, type_id id, std::string_view name): size_(size), id_(id), name_(name)
|
{
|
||||||
{}
|
return has_drop_;
|
||||||
|
}
|
||||||
blt::size_t size_{};
|
private:
|
||||||
type_id id_{};
|
type(const size_t size, const type_id id, const std::string_view name, const bool has_drop): size_(size), id_(id), name_(name),
|
||||||
std::string name_{};
|
has_drop_(has_drop)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size_{};
|
||||||
|
type_id id_{};
|
||||||
|
std::string name_{};
|
||||||
|
bool has_drop_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is a provider for the set of types possible in a GP program
|
* Is a provider for the set of types possible in a GP program
|
||||||
* also provides a set of functions for converting between C++ types and BLT GP types
|
* also provides a set of functions for converting between C++ types and BLT GP types
|
||||||
*/
|
*/
|
||||||
class type_provider
|
class type_provider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
type_provider() = default;
|
type_provider() = default;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline void register_type()
|
void register_type()
|
||||||
{
|
{
|
||||||
if (has_type<T>())
|
if (has_type<T>())
|
||||||
return;
|
return;
|
||||||
auto t = type::make_type<T>(types.size());
|
auto t = type::make_type<T>(types.size());
|
||||||
types.insert({blt::type_string_raw<T>(), t});
|
types.insert({blt::type_string_raw<T>(), t});
|
||||||
types_from_id[t.id()] = t;
|
types_from_id[t.id()] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline type get_type()
|
type get_type()
|
||||||
{
|
{
|
||||||
return types[blt::type_string_raw<T>()];
|
return types[blt::type_string_raw<T>()];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool has_type(){
|
bool has_type()
|
||||||
return types.find(blt::type_string_raw<T>()) != types.end();
|
{
|
||||||
}
|
return types.find(blt::type_string_raw<T>()) != types.end();
|
||||||
|
}
|
||||||
inline type get_type(type_id id)
|
|
||||||
{
|
type get_type(type_id id)
|
||||||
return types_from_id[id];
|
{
|
||||||
}
|
return types_from_id[id];
|
||||||
|
}
|
||||||
/**
|
|
||||||
* This function is slow btw
|
/**
|
||||||
* @param engine
|
* This function is slow btw
|
||||||
* @return
|
* @param engine
|
||||||
*/
|
* @return
|
||||||
inline type select_type(std::mt19937_64& engine)
|
*/
|
||||||
{
|
type select_type(std::mt19937_64& engine)
|
||||||
std::uniform_int_distribution dist(0ul, types.size() - 1);
|
{
|
||||||
auto offset = dist(engine);
|
std::uniform_int_distribution dist(0ul, types.size() - 1);
|
||||||
auto itr = types.begin();
|
auto offset = dist(engine);
|
||||||
for ([[maybe_unused]] auto _ : blt::range(0ul, offset))
|
auto itr = types.begin();
|
||||||
itr = itr++;
|
for ([[maybe_unused]] auto _ : blt::range(0ul, offset))
|
||||||
return itr->second;
|
itr = itr++;
|
||||||
}
|
return itr->second;
|
||||||
|
}
|
||||||
private:
|
|
||||||
blt::hashmap_t<std::string, type> types;
|
private:
|
||||||
blt::expanding_buffer<type> types_from_id;
|
hashmap_t<std::string, type> types;
|
||||||
|
expanding_buffer<type> types_from_id;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
struct std::hash<blt::gp::operator_id>
|
struct std::hash<blt::gp::operator_id>
|
||||||
{
|
{
|
||||||
std::size_t operator()(const blt::gp::operator_id& s) const noexcept
|
std::size_t operator()(const blt::gp::operator_id& s) const noexcept
|
||||||
|
@ -140,7 +148,7 @@ struct std::hash<blt::gp::operator_id>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
struct std::hash<blt::gp::type_id>
|
struct std::hash<blt::gp::type_id>
|
||||||
{
|
{
|
||||||
std::size_t operator()(const blt::gp::type_id& s) const noexcept
|
std::size_t operator()(const blt::gp::type_id& s) const noexcept
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLT_GP_UTIL_META_H
|
||||||
|
#define BLT_GP_UTIL_META_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace blt::gp::detail
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
using remove_cv_ref = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||||
|
|
||||||
|
|
||||||
|
template <typename...>
|
||||||
|
struct first_arg;
|
||||||
|
|
||||||
|
template <typename First, typename... Args>
|
||||||
|
struct first_arg<First, Args...>
|
||||||
|
{
|
||||||
|
using type = First;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct first_arg<>
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool b, typename... types>
|
||||||
|
struct is_same;
|
||||||
|
|
||||||
|
template <typename... types>
|
||||||
|
struct is_same<true, types...> : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... types>
|
||||||
|
struct is_same<false, types...> : std::is_same<types...>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... types>
|
||||||
|
constexpr bool is_same_v = is_same<sizeof...(types) == 0, types...>::value;
|
||||||
|
|
||||||
|
struct empty_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //BLT_GP_UTIL_META_H
|
|
@ -61,7 +61,7 @@ namespace blt::gp
|
||||||
|
|
||||||
auto& info = args.program.get_operator_info(top.id);
|
auto& info = args.program.get_operator_info(top.id);
|
||||||
|
|
||||||
tree.get_operations().emplace_back(
|
tree.emplace_operator(
|
||||||
args.program.get_typesystem().get_type(info.return_type).size(),
|
args.program.get_typesystem().get_type(info.return_type).size(),
|
||||||
top.id,
|
top.id,
|
||||||
args.program.is_operator_ephemeral(top.id));
|
args.program.is_operator_ephemeral(top.id));
|
||||||
|
|
|
@ -308,6 +308,13 @@ namespace blt::gp
|
||||||
auto* f = &program.get_eval_func();
|
auto* f = &program.get_eval_func();
|
||||||
if (f != func)
|
if (f != func)
|
||||||
func = f;
|
func = f;
|
||||||
|
for (const auto& op : operations)
|
||||||
|
{
|
||||||
|
if (op.has_drop())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
operations.clear();
|
operations.clear();
|
||||||
values.reset();
|
values.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,22 +189,22 @@ inline void there(blt::size_t)
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
blt::gp::thread_manager_t threads{
|
// blt::gp::thread_manager_t threads{
|
||||||
std::thread::hardware_concurrency(), blt::gp::task_builder_t<test>::make_callable(
|
// std::thread::hardware_concurrency(), blt::gp::task_builder_t<test>::make_callable(
|
||||||
blt::gp::task_t{test::hello, hello},
|
// blt::gp::task_t{test::hello, hello},
|
||||||
blt::gp::task_t{test::there, there}
|
// blt::gp::task_t{test::there, there}
|
||||||
)
|
// )
|
||||||
};
|
// };
|
||||||
|
|
||||||
threads.add_task(test::hello);
|
// threads.add_task(test::hello);
|
||||||
threads.add_task(test::hello);
|
// threads.add_task(test::hello);
|
||||||
threads.add_task(test::hello);
|
// threads.add_task(test::hello);
|
||||||
threads.add_task(test::there);
|
// threads.add_task(test::there);
|
||||||
|
|
||||||
while (threads.has_tasks_left())
|
// while (threads.has_tasks_left())
|
||||||
threads.execute();
|
// threads.execute();
|
||||||
|
|
||||||
// for (int i = 0; i < 1; i++)
|
for (int i = 0; i < 1; i++)
|
||||||
// do_run();
|
do_run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue