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) 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_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

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

View File

@ -109,6 +109,13 @@ namespace fb
alloc.deallocate(children, type.argc()); 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 class tree_t
@ -120,10 +127,17 @@ 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_restricted(detail::node_helper_t details, 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, 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(); 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& 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 < max_height)
stack.emplace(node->children[i], depth + 1);
if (depth < min_height && !has_one_non_terminal) 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)]; 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); 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)) if (const auto& func_init = types.get_function_initializer(selection))
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;
continue; } else if (depth >= max_height)
}
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)]; 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); 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)) if (const auto& func_init = types.get_function_initializer(selection))
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);
continue; } else if (engine.choice())
}
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)]; 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); 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)) 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); node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
} else } else
{ {
// use grow() method, meaning select choice again // and use grow() method, meaning select choice again
if (engine.choice()) if (engine.choice())
{ {
// use non-terminals // to use non-terminals
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)];
func_t func(types.get_function_argc(selection), types.get_function(selection), type_category, selection); 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)) 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); node->children[i] = tree.alloc.template emplace<node_t>(func, tree.alloc);
} else } else
{ {
// use terminals // or use terminals
function_id selection = terminals[engine.random_long(0, terminals.size() - 1)]; 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); 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)) 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->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()}; 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); all_non_terminals.emplace_back(tid, id);
function_argc.insert(id, argc); function_argc.insert(id, argc);
if (auto& init = initializer) if (auto& init = initializer)
function_initializer.insert(id, init.value()); function_initializer.insert({id, init.value()});
return id; return id;
} }
@ -63,7 +63,7 @@ namespace fb
terminals.at(tid).push_back(id); terminals.at(tid).push_back(id);
function_argc.insert(id, 0); function_argc.insert(id, 0);
if (auto& init = initializer) if (auto& init = initializer)
function_initializer.insert(id, init.value()); function_initializer.insert({id, init.value()});
return id; return id;
} }
} }