about to remove the funny little tree init system and replace with something more useful
parent
10fe1e28cf
commit
319d385cd9
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(lilfbtf5 VERSION 0.1.29)
|
||||
project(lilfbtf5 VERSION 0.1.30)
|
||||
|
||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
||||
|
|
|
@ -72,6 +72,18 @@ namespace fb
|
|||
~func_t() = default;
|
||||
};
|
||||
|
||||
enum class tree_init_t
|
||||
{
|
||||
// standard grow method
|
||||
GROW,
|
||||
// standard full method
|
||||
FULL,
|
||||
// standard ramped half-and-half method
|
||||
RAMPED_HALF_HALF,
|
||||
// variant of grow/full method where at each level a choice is made between using only non-terminals or terminals
|
||||
BRETT_HALF_HALF
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class node_t
|
||||
|
@ -110,12 +122,19 @@ namespace fb
|
|||
}
|
||||
};
|
||||
|
||||
struct node_helper_t
|
||||
struct node_construction_info_t
|
||||
{
|
||||
blt::bump_allocator<blt::BLT_2MB_SIZE, false>& alloc;
|
||||
random& engine;
|
||||
type_engine_t& types;
|
||||
};
|
||||
|
||||
struct tree_construction_info_t
|
||||
{
|
||||
tree_init_t tree_type;
|
||||
random& engine;
|
||||
type_engine_t& types;
|
||||
};
|
||||
}
|
||||
|
||||
class tree_t
|
||||
|
@ -128,15 +147,18 @@ namespace fb
|
|||
inline blt::bump_allocator<blt::BLT_2MB_SIZE, false>& get_allocator()
|
||||
{ return alloc; }
|
||||
|
||||
static detail::node_t* allocate_non_terminal(detail::node_helper_t details, type_id type);
|
||||
static detail::node_t* allocate_non_terminal_restricted(detail::node_helper_t details, type_id type);
|
||||
static detail::node_t* allocate_non_terminal(detail::node_construction_info_t info, type_id type);
|
||||
|
||||
static detail::node_t* allocate_non_terminal_restricted(detail::node_construction_info_t info, type_id type);
|
||||
|
||||
static detail::node_t* allocate_terminal(detail::node_construction_info_t info, type_id type);
|
||||
|
||||
|
||||
static detail::node_t* allocate_terminal(detail::node_helper_t details, type_id type);
|
||||
|
||||
public:
|
||||
explicit tree_t(type_engine_t& types);
|
||||
|
||||
static tree_t make_tree(type_engine_t& types, random& engine, blt::size_t min_height, blt::size_t max_height,
|
||||
static tree_t make_tree(detail::tree_construction_info_t tree_info, blt::size_t min_depth, blt::size_t max_depth,
|
||||
std::optional<type_id> starting_type = {});
|
||||
|
||||
std::pair<blt::unsafe::any_t, type_id> evaluate();
|
||||
|
|
56
src/tree.cpp
56
src/tree.cpp
|
@ -28,7 +28,7 @@ namespace fb
|
|||
{}
|
||||
|
||||
tree_t tree_t::make_tree(type_engine_t& types, random& engine,
|
||||
blt::size_t min_height, blt::size_t max_height, std::optional<type_id> starting_type)
|
||||
blt::size_t min_depth, blt::size_t max_depth, std::optional<type_id> starting_type)
|
||||
{
|
||||
using detail::node_t;
|
||||
tree_t tree(types);
|
||||
|
@ -70,7 +70,7 @@ namespace fb
|
|||
const auto& terminals = types.get_terminals(type_category);
|
||||
const auto& non_terminals = types.get_non_terminals(type_category);
|
||||
|
||||
if (depth < min_height && !has_one_non_terminal)
|
||||
if (depth < min_depth && !has_one_non_terminal)
|
||||
{
|
||||
// make sure we have at least min height possible by using at least one non terminal
|
||||
function_id selection = non_terminals[engine.random_long(0, non_terminals.size() - 1)];
|
||||
|
@ -79,7 +79,7 @@ namespace fb
|
|||
func_init.value()(func);
|
||||
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
|
||||
has_one_non_terminal = true;
|
||||
} else if (depth >= max_height)
|
||||
} else if (depth >= max_depth)
|
||||
{
|
||||
// if we are above the max_height select only terminals
|
||||
function_id selection = terminals[engine.random_long(0, terminals.size() - 1)];
|
||||
|
@ -133,6 +133,7 @@ namespace fb
|
|||
|
||||
nodes.push(root);
|
||||
|
||||
// create the correct ordering for the node evaluation
|
||||
while (!nodes.empty())
|
||||
{
|
||||
auto* top = nodes.top();
|
||||
|
@ -151,48 +152,49 @@ namespace fb
|
|||
return {root->type.getValue(), root->type.getType()};
|
||||
}
|
||||
|
||||
detail::node_t* tree_t::allocate_non_terminal(detail::node_helper_t details, type_id type)
|
||||
detail::node_t* tree_t::allocate_non_terminal(detail::node_construction_info_t info, type_id type)
|
||||
{
|
||||
const auto& non_terminals = details.types.get_non_terminals(type);
|
||||
function_id selection = non_terminals[details.engine.random_long(0, non_terminals.size() - 1)];
|
||||
func_t func(details.types.get_function_argc(selection), details.types.get_function(selection), type, selection);
|
||||
if (const auto& func_init = details.types.get_function_initializer(selection))
|
||||
const auto& non_terminals = info.types.get_non_terminals(type);
|
||||
function_id selection = non_terminals[info.engine.random_long(0, non_terminals.size() - 1)];
|
||||
func_t func(info.types.get_function_argc(selection), info.types.get_function(selection), type, selection);
|
||||
if (const auto& func_init = info.types.get_function_initializer(selection))
|
||||
func_init.value()(func);
|
||||
return details.alloc.template emplace<detail::node_t>(func, details.alloc);
|
||||
return info.alloc.template emplace<detail::node_t>(func, info.alloc);
|
||||
}
|
||||
|
||||
detail::node_t* tree_t::allocate_terminal(detail::node_helper_t details, type_id type)
|
||||
detail::node_t* tree_t::allocate_terminal(detail::node_construction_info_t info, type_id type)
|
||||
{
|
||||
const auto& terminals = details.types.get_terminals(type);
|
||||
const auto& terminals = info.types.get_terminals(type);
|
||||
|
||||
// if we cannot allocate a terminal, we need to allocate a non-terminal in hopes of finding a closing path
|
||||
// for example bools might not have an ending terminal, it doesn't make sense to.
|
||||
if (terminals.empty())
|
||||
return allocate_non_terminal_restricted(details, type);
|
||||
return allocate_non_terminal_restricted(info, type);
|
||||
|
||||
function_id selection = terminals[details.engine.random_long(0, terminals.size() - 1)];
|
||||
func_t func(details.types.get_function_argc(selection), details.types.get_function(selection), type, selection);
|
||||
if (const auto& func_init = details.types.get_function_initializer(selection))
|
||||
function_id selection = terminals[info.engine.random_long(0, terminals.size() - 1)];
|
||||
func_t func(info.types.get_function_argc(selection), info.types.get_function(selection), type, selection);
|
||||
if (const auto& func_init = info.types.get_function_initializer(selection))
|
||||
func_init.value()(func);
|
||||
return details.alloc.template emplace<detail::node_t>(func, details.alloc);
|
||||
return info.alloc.template emplace<detail::node_t>(func, info.alloc);
|
||||
}
|
||||
|
||||
detail::node_t* tree_t::allocate_non_terminal_restricted(detail::node_helper_t details, type_id type)
|
||||
detail::node_t* tree_t::allocate_non_terminal_restricted(detail::node_construction_info_t info, type_id type)
|
||||
{
|
||||
function_id selection = 0;
|
||||
do {
|
||||
const auto& non_terminals = details.types.get_non_terminals(type);
|
||||
selection = details.engine.random_long(0, non_terminals.size() - 1);
|
||||
auto& sel_v = details.types.get_function_allowed_arguments(selection);
|
||||
// if it does not accept the type we are
|
||||
do
|
||||
{
|
||||
const auto& non_terminals = info.types.get_non_terminals(type);
|
||||
selection = info.engine.random_long(0, non_terminals.size() - 1);
|
||||
auto& sel_v = info.types.get_function_allowed_arguments(selection);
|
||||
// if it does not accept the type we are, we will accept this as a valid "temp" non-terminal
|
||||
if (std::find(sel_v.begin(), sel_v.end(), type) == sel_v.end())
|
||||
break;
|
||||
} while(true);
|
||||
} while (true);
|
||||
|
||||
func_t func(details.types.get_function_argc(selection), details.types.get_function(selection), type, selection);
|
||||
if (const auto& func_init = details.types.get_function_initializer(selection))
|
||||
func_init.value()(func);
|
||||
return details.alloc.template emplace<detail::node_t>(func, details.alloc);
|
||||
func_t func(info.types.get_function_argc(selection), info.types.get_function(selection), type, selection);
|
||||
if (const auto& func_init = info.types.get_function_initializer(selection))
|
||||
(*func_init)(func);
|
||||
return info.alloc.template emplace<detail::node_t>(func, info.alloc);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue