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)
|
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_ADDRSAN "Enable the address sanitizer" OFF)
|
||||||
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
||||||
|
|
|
@ -72,6 +72,18 @@ namespace fb
|
||||||
~func_t() = default;
|
~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
|
namespace detail
|
||||||
{
|
{
|
||||||
class node_t
|
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;
|
blt::bump_allocator<blt::BLT_2MB_SIZE, false>& alloc;
|
||||||
random& engine;
|
random& engine;
|
||||||
type_engine_t& types;
|
type_engine_t& types;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tree_construction_info_t
|
||||||
|
{
|
||||||
|
tree_init_t tree_type;
|
||||||
|
random& engine;
|
||||||
|
type_engine_t& types;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class tree_t
|
class tree_t
|
||||||
|
@ -128,15 +147,18 @@ namespace fb
|
||||||
inline blt::bump_allocator<blt::BLT_2MB_SIZE, false>& get_allocator()
|
inline blt::bump_allocator<blt::BLT_2MB_SIZE, false>& get_allocator()
|
||||||
{ return alloc; }
|
{ return alloc; }
|
||||||
|
|
||||||
static detail::node_t* allocate_non_terminal(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_helper_t details, 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:
|
public:
|
||||||
explicit tree_t(type_engine_t& types);
|
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::optional<type_id> starting_type = {});
|
||||||
|
|
||||||
std::pair<blt::unsafe::any_t, type_id> evaluate();
|
std::pair<blt::unsafe::any_t, type_id> evaluate();
|
||||||
|
|
54
src/tree.cpp
54
src/tree.cpp
|
@ -28,7 +28,7 @@ namespace fb
|
||||||
{}
|
{}
|
||||||
|
|
||||||
tree_t tree_t::make_tree(type_engine_t& types, random& engine,
|
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;
|
using detail::node_t;
|
||||||
tree_t tree(types);
|
tree_t tree(types);
|
||||||
|
@ -70,7 +70,7 @@ namespace fb
|
||||||
const auto& terminals = types.get_terminals(type_category);
|
const auto& terminals = types.get_terminals(type_category);
|
||||||
const auto& non_terminals = types.get_non_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
|
// 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)];
|
function_id selection = non_terminals[engine.random_long(0, non_terminals.size() - 1)];
|
||||||
|
@ -79,7 +79,7 @@ namespace fb
|
||||||
func_init.value()(func);
|
func_init.value()(func);
|
||||||
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
|
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
|
||||||
has_one_non_terminal = true;
|
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
|
// if we are above the max_height select only terminals
|
||||||
function_id selection = terminals[engine.random_long(0, terminals.size() - 1)];
|
function_id selection = terminals[engine.random_long(0, terminals.size() - 1)];
|
||||||
|
@ -133,6 +133,7 @@ namespace fb
|
||||||
|
|
||||||
nodes.push(root);
|
nodes.push(root);
|
||||||
|
|
||||||
|
// create the correct ordering for the node evaluation
|
||||||
while (!nodes.empty())
|
while (!nodes.empty())
|
||||||
{
|
{
|
||||||
auto* top = nodes.top();
|
auto* top = nodes.top();
|
||||||
|
@ -151,48 +152,49 @@ namespace fb
|
||||||
return {root->type.getValue(), root->type.getType()};
|
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);
|
const auto& non_terminals = info.types.get_non_terminals(type);
|
||||||
function_id selection = non_terminals[details.engine.random_long(0, non_terminals.size() - 1)];
|
function_id selection = non_terminals[info.engine.random_long(0, non_terminals.size() - 1)];
|
||||||
func_t func(details.types.get_function_argc(selection), details.types.get_function(selection), type, selection);
|
func_t func(info.types.get_function_argc(selection), info.types.get_function(selection), type, selection);
|
||||||
if (const auto& func_init = details.types.get_function_initializer(selection))
|
if (const auto& func_init = info.types.get_function_initializer(selection))
|
||||||
func_init.value()(func);
|
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
|
// 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.
|
// for example bools might not have an ending terminal, it doesn't make sense to.
|
||||||
if (terminals.empty())
|
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)];
|
function_id selection = terminals[info.engine.random_long(0, terminals.size() - 1)];
|
||||||
func_t func(details.types.get_function_argc(selection), details.types.get_function(selection), type, selection);
|
func_t func(info.types.get_function_argc(selection), info.types.get_function(selection), type, selection);
|
||||||
if (const auto& func_init = details.types.get_function_initializer(selection))
|
if (const auto& func_init = info.types.get_function_initializer(selection))
|
||||||
func_init.value()(func);
|
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;
|
function_id selection = 0;
|
||||||
do {
|
do
|
||||||
const auto& non_terminals = details.types.get_non_terminals(type);
|
{
|
||||||
selection = details.engine.random_long(0, non_terminals.size() - 1);
|
const auto& non_terminals = info.types.get_non_terminals(type);
|
||||||
auto& sel_v = details.types.get_function_allowed_arguments(selection);
|
selection = info.engine.random_long(0, non_terminals.size() - 1);
|
||||||
// if it does not accept the type we are
|
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())
|
if (std::find(sel_v.begin(), sel_v.end(), type) == sel_v.end())
|
||||||
break;
|
break;
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
func_t func(details.types.get_function_argc(selection), details.types.get_function(selection), type, selection);
|
func_t func(info.types.get_function_argc(selection), info.types.get_function(selection), type, selection);
|
||||||
if (const auto& func_init = details.types.get_function_initializer(selection))
|
if (const auto& func_init = info.types.get_function_initializer(selection))
|
||||||
func_init.value()(func);
|
(*func_init)(func);
|
||||||
return details.alloc.template emplace<detail::node_t>(func, details.alloc);
|
return info.alloc.template emplace<detail::node_t>(func, info.alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue