2024-06-02 13:38:24 -04:00
|
|
|
/*
|
|
|
|
* <Short Description>
|
|
|
|
* 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/>.
|
2024-06-21 22:04:57 -04:00
|
|
|
*/
|
|
|
|
#include <blt/gp/generators.h>
|
2024-06-23 14:13:50 -04:00
|
|
|
#include <blt/gp/program.h>
|
2024-06-26 20:24:58 -04:00
|
|
|
#include <blt/std/logging.h>
|
2024-06-23 14:13:50 -04:00
|
|
|
#include <stack>
|
2024-06-21 22:04:57 -04:00
|
|
|
|
|
|
|
namespace blt::gp
|
|
|
|
{
|
2024-06-25 22:21:41 -04:00
|
|
|
// TODO: change how the generators work, but keep how nice everything is within the C++ file. less headers!
|
|
|
|
// maybe have tree call the generate functions with out variables as the members of tree_t
|
2024-06-21 22:04:57 -04:00
|
|
|
|
2024-06-23 14:13:50 -04:00
|
|
|
struct stack
|
|
|
|
{
|
|
|
|
blt::gp::operator_id id;
|
|
|
|
blt::size_t depth;
|
|
|
|
};
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
inline std::stack<stack> get_initial_stack(gp_program& program, type_id root_type)
|
2024-06-23 14:13:50 -04:00
|
|
|
{
|
|
|
|
std::stack<stack> tree_generator;
|
2024-06-25 22:21:41 -04:00
|
|
|
//
|
|
|
|
// auto& system = program.get_typesystem();
|
|
|
|
// // select a type which has a non-empty set of non-terminals
|
|
|
|
// type base_type;
|
|
|
|
// do
|
|
|
|
// {
|
|
|
|
// base_type = system.select_type(program.get_random());
|
|
|
|
// } while (program.get_type_non_terminals(base_type.id()).empty());
|
|
|
|
//
|
|
|
|
tree_generator.push(stack{program.select_non_terminal(root_type), 1});
|
2024-06-23 14:13:50 -04:00
|
|
|
|
|
|
|
return tree_generator;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Func>
|
2024-06-25 22:21:41 -04:00
|
|
|
inline tree_t create_tree(Func&& perChild, const generator_arguments& args)
|
2024-06-21 22:04:57 -04:00
|
|
|
{
|
2024-06-25 22:21:41 -04:00
|
|
|
std::stack<stack> tree_generator = get_initial_stack(args.program, args.root_type);
|
2024-06-24 21:56:51 -04:00
|
|
|
blt::size_t max_depth = 0;
|
2024-06-21 22:04:57 -04:00
|
|
|
tree_t tree;
|
2024-06-23 14:13:50 -04:00
|
|
|
|
|
|
|
while (!tree_generator.empty())
|
|
|
|
{
|
2024-06-24 21:56:51 -04:00
|
|
|
auto top = tree_generator.top();
|
|
|
|
tree_generator.pop();
|
|
|
|
|
2024-06-30 20:20:11 -04:00
|
|
|
auto& info = args.program.get_operator_info(top.id);
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
tree.get_operations().emplace_back(
|
2024-06-30 20:20:11 -04:00
|
|
|
info.function,
|
|
|
|
info.transfer,
|
2024-06-30 21:44:45 -04:00
|
|
|
top.id,
|
2024-06-29 10:47:27 -04:00
|
|
|
args.program.is_static(top.id));
|
2024-06-24 21:56:51 -04:00
|
|
|
max_depth = std::max(max_depth, top.depth);
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
if (args.program.is_static(top.id))
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-30 20:20:11 -04:00
|
|
|
info.function(nullptr, tree.get_values(), tree.get_values());
|
2024-06-24 21:56:51 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2024-06-30 20:20:11 -04:00
|
|
|
for (const auto& child : info.argument_types)
|
2024-06-25 22:21:41 -04:00
|
|
|
std::forward<Func>(perChild)(args.program, tree_generator, child, top.depth + 1);
|
2024-06-23 14:13:50 -04:00
|
|
|
}
|
|
|
|
|
2024-06-21 22:04:57 -04:00
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
tree_t grow_generator_t::generate(const generator_arguments& args)
|
2024-06-23 14:13:50 -04:00
|
|
|
{
|
2024-06-30 20:20:11 -04:00
|
|
|
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) {
|
2024-06-25 22:21:41 -04:00
|
|
|
if (new_depth >= args.max_depth)
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-30 20:20:11 -04:00
|
|
|
if (program.get_type_terminals(type).empty())
|
|
|
|
tree_generator.push({program.select_non_terminal_too_deep(type), new_depth});
|
2024-06-27 01:35:29 -04:00
|
|
|
else
|
2024-06-30 20:20:11 -04:00
|
|
|
tree_generator.push({program.select_terminal(type), new_depth});
|
2024-06-24 21:56:51 -04:00
|
|
|
return;
|
|
|
|
}
|
2024-06-25 22:21:41 -04:00
|
|
|
if (program.choice() || new_depth < args.min_depth)
|
2024-06-30 20:20:11 -04:00
|
|
|
tree_generator.push({program.select_non_terminal(type), new_depth});
|
2024-06-24 21:56:51 -04:00
|
|
|
else
|
2024-06-30 20:20:11 -04:00
|
|
|
tree_generator.push({program.select_terminal(type), new_depth});
|
2024-06-25 22:21:41 -04:00
|
|
|
}, args);
|
2024-06-23 14:13:50 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
tree_t full_generator_t::generate(const generator_arguments& args)
|
2024-06-21 22:04:57 -04:00
|
|
|
{
|
2024-06-30 20:20:11 -04:00
|
|
|
return create_tree([args](gp_program& program, std::stack<stack>& tree_generator, type_id type, blt::size_t new_depth) {
|
2024-06-25 22:21:41 -04:00
|
|
|
if (new_depth >= args.max_depth)
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-30 20:20:11 -04:00
|
|
|
if (program.get_type_terminals(type).empty())
|
|
|
|
tree_generator.push({program.select_non_terminal_too_deep(type), new_depth});
|
2024-06-27 01:35:29 -04:00
|
|
|
else
|
2024-06-30 20:20:11 -04:00
|
|
|
tree_generator.push({program.select_terminal(type), new_depth});
|
2024-06-24 21:56:51 -04:00
|
|
|
return;
|
|
|
|
}
|
2024-06-30 20:20:11 -04:00
|
|
|
tree_generator.push({program.select_non_terminal(type), new_depth});
|
2024-06-25 22:21:41 -04:00
|
|
|
}, args);
|
2024-06-24 21:56:51 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t grow_initializer_t::generate(const initializer_arguments& args)
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t pop;
|
|
|
|
|
|
|
|
for (auto i = 0ul; i < args.size; i++)
|
|
|
|
pop.getIndividuals().push_back(grow.generate(args.to_gen_args()));
|
|
|
|
|
|
|
|
return pop;
|
2024-06-24 21:56:51 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t full_initializer_t::generate(const initializer_arguments& args)
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t pop;
|
|
|
|
|
|
|
|
for (auto i = 0ul; i < args.size; i++)
|
|
|
|
pop.getIndividuals().push_back(full.generate(args.to_gen_args()));
|
|
|
|
|
|
|
|
return pop;
|
2024-06-24 21:56:51 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t half_half_initializer_t::generate(const initializer_arguments& args)
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t pop;
|
|
|
|
|
|
|
|
for (auto i = 0ul; i < args.size; i++)
|
|
|
|
{
|
|
|
|
if (args.program.choice())
|
|
|
|
pop.getIndividuals().push_back(full.generate(args.to_gen_args()));
|
|
|
|
else
|
|
|
|
pop.getIndividuals().push_back(grow.generate(args.to_gen_args()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return pop;
|
2024-06-24 21:56:51 -04:00
|
|
|
}
|
|
|
|
|
2024-06-25 22:21:41 -04:00
|
|
|
population_t ramped_half_initializer_t::generate(const initializer_arguments& args)
|
2024-06-24 21:56:51 -04:00
|
|
|
{
|
2024-06-25 22:21:41 -04:00
|
|
|
auto steps = args.max_depth - args.min_depth;
|
|
|
|
auto per_step = args.size / steps;
|
|
|
|
auto remainder = args.size % steps;
|
|
|
|
population_t pop;
|
|
|
|
|
|
|
|
for (auto depth : blt::range(args.min_depth, args.max_depth))
|
|
|
|
{
|
|
|
|
for (auto i = 0ul; i < per_step; i++)
|
|
|
|
{
|
|
|
|
if (args.program.choice())
|
|
|
|
pop.getIndividuals().push_back(full.generate({args.program, args.root_type, args.min_depth, depth}));
|
|
|
|
else
|
|
|
|
pop.getIndividuals().push_back(grow.generate({args.program, args.root_type, args.min_depth, depth}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto i = 0ul; i < remainder; i++)
|
|
|
|
{
|
|
|
|
if (args.program.choice())
|
|
|
|
pop.getIndividuals().push_back(full.generate(args.to_gen_args()));
|
|
|
|
else
|
|
|
|
pop.getIndividuals().push_back(grow.generate(args.to_gen_args()));
|
|
|
|
}
|
|
|
|
|
|
|
|
blt_assert(pop.getIndividuals().size() == args.size);
|
|
|
|
|
|
|
|
return pop;
|
2024-06-21 22:04:57 -04:00
|
|
|
}
|
|
|
|
}
|