main
Brett 2024-03-15 12:06:47 -04:00
parent 2cc0814800
commit 6751127608
5 changed files with 75 additions and 20 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(lilfbtf5 VERSION 0.1.27)
project(lilfbtf5 VERSION 0.1.28)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

@ -23,7 +23,12 @@
namespace fb
{
class gp_system_t
{
};
}
#endif //LILFBTF5_SYSTEM_H

View File

@ -109,6 +109,13 @@ namespace fb
alloc.deallocate(children, type.argc());
}
};
struct node_helper_t
{
blt::bump_allocator<blt::BLT_2MB_SIZE, false>& alloc;
random& engine;
type_engine_t& types;
};
}
class tree_t
@ -120,10 +127,17 @@ 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_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, std::optional<type_id> starting_type = {});
static 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 = {});
std::pair<blt::unsafe::any_t, type_id> evaluate();
};

View File

@ -70,33 +70,26 @@ namespace fb
const auto& terminals = types.get_terminals(type_category);
const auto& non_terminals = types.get_non_terminals(type_category);
if (depth < max_height)
stack.emplace(node->children[i], depth + 1);
if (depth < min_height && !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)];
func_t func(types.get_function_argc(selection), types.get_function(selection), type_category, selection);
if (const auto& func_init = types.get_function_initializer(selection))
func_init.value()(func);
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
has_one_non_terminal = true;
continue;
}
if (depth >= max_height)
} else if (depth >= max_height)
{
// if we are above the max_height select only terminals
function_id selection = terminals[engine.random_long(0, terminals.size() - 1)];
func_t func(types.get_function_argc(selection), types.get_function(selection), type_category, selection);
if (const auto& func_init = types.get_function_initializer(selection))
func_init.value()(func);
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
continue;
}
if (engine.choice())
} else if (engine.choice())
{
// use full() method
// otherwise select between use full() method
function_id selection = non_terminals[engine.random_long(0, non_terminals.size() - 1)];
func_t func(types.get_function_argc(selection), types.get_function(selection), type_category, selection);
if (const auto& func_init = types.get_function_initializer(selection))
@ -104,10 +97,10 @@ namespace fb
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
} else
{
// use grow() method, meaning select choice again
// and use grow() method, meaning select choice again
if (engine.choice())
{
// use non-terminals
// to use non-terminals
function_id selection = non_terminals[engine.random_long(0, non_terminals.size() - 1)];
func_t func(types.get_function_argc(selection), types.get_function(selection), type_category, selection);
if (const auto& func_init = types.get_function_initializer(selection))
@ -115,7 +108,7 @@ namespace fb
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
} else
{
// use terminals
// or use terminals
function_id selection = terminals[engine.random_long(0, terminals.size() - 1)];
func_t func(types.get_function_argc(selection), types.get_function(selection), type_category, selection);
if (const auto& func_init = types.get_function_initializer(selection))
@ -123,6 +116,9 @@ namespace fb
node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
}
}
// node has children that need populated
if (node->children[i]->type.argc() != 0)
stack.emplace(node->children[i], depth + 1);
}
}
@ -155,5 +151,45 @@ 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)
{
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))
func_init.value()(func);
return details.alloc.template emplace<detail::node_t>(func, details.alloc);
}
detail::node_t* tree_t::allocate_terminal(detail::node_helper_t details, type_id type)
{
const auto& terminals = details.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);
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))
func_init.value()(func);
return details.alloc.template emplace<detail::node_t>(func, details.alloc);
}
detail::node_t* tree_t::allocate_non_terminal_restricted(detail::node_helper_t details, type_id type)
{
const auto& non_terminals = details.types.get_non_terminals(type);
function_id selection = 0;
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);
}
}

View File

@ -39,7 +39,7 @@ namespace fb
all_non_terminals.emplace_back(tid, id);
function_argc.insert(id, argc);
if (auto& init = initializer)
function_initializer.insert(id, init.value());
function_initializer.insert({id, init.value()});
return id;
}
@ -63,7 +63,7 @@ namespace fb
terminals.at(tid).push_back(id);
function_argc.insert(id, 0);
if (auto& init = initializer)
function_initializer.insert(id, init.value());
function_initializer.insert({id, init.value()});
return id;
}
}