partial transfer to types
parent
30372f1c71
commit
ab67289745
|
@ -27,7 +27,7 @@ macro(compile_options target_name)
|
||||||
sanitizers(${target_name})
|
sanitizers(${target_name})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
project(blt-gp VERSION 0.5.30)
|
project(blt-gp VERSION 0.5.31)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace blt::gp::example
|
||||||
BLT_DEBUG("Begin Generation Loop");
|
BLT_DEBUG("Begin Generation Loop");
|
||||||
while (!program.should_terminate())
|
while (!program.should_terminate())
|
||||||
{
|
{
|
||||||
BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation());
|
BLT_TRACE("------------\\{Begin Generation {}}------------", program.get_current_generation());
|
||||||
BLT_TRACE("Creating next generation");
|
BLT_TRACE("Creating next generation");
|
||||||
program.create_next_generation();
|
program.create_next_generation();
|
||||||
BLT_TRACE("Move to next generation");
|
BLT_TRACE("Move to next generation");
|
||||||
|
@ -87,7 +87,7 @@ namespace blt::gp::example
|
||||||
BLT_TRACE("Evaluate Fitness");
|
BLT_TRACE("Evaluate Fitness");
|
||||||
program.evaluate_fitness();
|
program.evaluate_fitness();
|
||||||
auto& stats = program.get_population_stats();
|
auto& stats = program.get_population_stats();
|
||||||
BLT_TRACE("Avg Fit: %lf, Best Fit: %lf, Worst Fit: %lf, Overall Fit: %lf",
|
BLT_TRACE("Avg Fit: {}, Best Fit: {}, Worst Fit: {}, Overall Fit: {}",
|
||||||
stats.average_fitness.load(std::memory_order_relaxed), stats.best_fitness.load(std::memory_order_relaxed),
|
stats.average_fitness.load(std::memory_order_relaxed), stats.best_fitness.load(std::memory_order_relaxed),
|
||||||
stats.worst_fitness.load(std::memory_order_relaxed), stats.overall_fitness.load(std::memory_order_relaxed));
|
stats.worst_fitness.load(std::memory_order_relaxed), stats.overall_fitness.load(std::memory_order_relaxed));
|
||||||
BLT_TRACE("----------------------------------------------");
|
BLT_TRACE("----------------------------------------------");
|
||||||
|
|
|
@ -52,6 +52,8 @@ namespace blt::gp
|
||||||
struct single_operation_tree_manipulator_t;
|
struct single_operation_tree_manipulator_t;
|
||||||
|
|
||||||
struct multi_operation_tree_manipulator_t;
|
struct multi_operation_tree_manipulator_t;
|
||||||
|
|
||||||
|
struct subtree_point_t;
|
||||||
|
|
||||||
class tree_t;
|
class tree_t;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#ifndef BLT_GP_TRANSFORMERS_H
|
#ifndef BLT_GP_TRANSFORMERS_H
|
||||||
#define BLT_GP_TRANSFORMERS_H
|
#define BLT_GP_TRANSFORMERS_H
|
||||||
|
|
||||||
#include <blt/std/utility.h>
|
|
||||||
#include <blt/gp/fwdecl.h>
|
#include <blt/gp/fwdecl.h>
|
||||||
#include <blt/gp/tree.h>
|
#include <blt/gp/tree.h>
|
||||||
#include <blt/gp/generators.h>
|
#include <blt/gp/generators.h>
|
||||||
|
@ -120,8 +119,8 @@ namespace blt::gp
|
||||||
public:
|
public:
|
||||||
struct crossover_point_t
|
struct crossover_point_t
|
||||||
{
|
{
|
||||||
tree_t::subtree_point_t p1_crossover_point;
|
subtree_point_t p1_crossover_point;
|
||||||
tree_t::subtree_point_t p2_crossover_point;
|
subtree_point_t p2_crossover_point;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +151,7 @@ namespace blt::gp
|
||||||
~subtree_crossover_t() override = default;
|
~subtree_crossover_t() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] std::optional<tree_t::subtree_point_t> get_point_traverse_retry(const tree_t& t, std::optional<type_id> type) const;
|
[[nodiscard]] std::optional<subtree_point_t> get_point_traverse_retry(const tree_t& t, std::optional<type_id> type) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class one_point_crossover_t : public crossover_t
|
class one_point_crossover_t : public crossover_t
|
||||||
|
@ -204,7 +203,7 @@ namespace blt::gp
|
||||||
virtual bool apply(gp_program& program, const tree_t& p, tree_t& c);
|
virtual bool apply(gp_program& program, const tree_t& p, tree_t& c);
|
||||||
|
|
||||||
// returns the point after the mutation
|
// returns the point after the mutation
|
||||||
size_t mutate_point(gp_program& program, tree_t& c, tree_t::subtree_point_t node) const;
|
size_t mutate_point(gp_program& program, tree_t& c, subtree_point_t node) const;
|
||||||
|
|
||||||
virtual ~mutation_t() = default;
|
virtual ~mutation_t() = default;
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#include "program.h"
|
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
|
@ -234,6 +232,16 @@ namespace blt::gp
|
||||||
|
|
||||||
struct subtree_point_t
|
struct subtree_point_t
|
||||||
{
|
{
|
||||||
|
subtree_point_t() = default;
|
||||||
|
|
||||||
|
explicit subtree_point_t(const size_t point): point(point), info(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit subtree_point_t(const ssize_t point): point(static_cast<size_t>(point)), info(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
subtree_point_t(const size_t point, const operator_info_t& info): point(point), info(&info) // NOLINT
|
subtree_point_t(const size_t point, const operator_info_t& info): point(point), info(&info) // NOLINT
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -254,13 +262,17 @@ namespace blt::gp
|
||||||
|
|
||||||
[[nodiscard]] const operator_info_t& get_info() const
|
[[nodiscard]] const operator_info_t& get_info() const
|
||||||
{
|
{
|
||||||
|
#if BLT_DEBUG_LEVEL > 0
|
||||||
|
if (info == nullptr)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Invalid subtree point, operator info was null! "
|
||||||
|
"(Point probably created with passthrough intentions or operator info was not available, "
|
||||||
|
"please manually acquire info from the program!)");
|
||||||
|
#endif
|
||||||
return *info;
|
return *info;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] type_id get_type() const
|
[[nodiscard]] type_id get_type() const;
|
||||||
{
|
|
||||||
return info->return_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t point;
|
size_t point;
|
||||||
const operator_info_t* info;
|
const operator_info_t* info;
|
||||||
|
@ -316,7 +328,7 @@ namespace blt::gp
|
||||||
* @param operators vector for storing subtree operators
|
* @param operators vector for storing subtree operators
|
||||||
* @param stack stack for storing subtree values
|
* @param stack stack for storing subtree values
|
||||||
*/
|
*/
|
||||||
void copy_subtree(const subtree_point_t point, tracked_vector<op_container_t>& operators, stack_allocator& stack) const;
|
void copy_subtree(subtree_point_t point, tracked_vector<op_container_t>& operators, stack_allocator& stack) const;
|
||||||
|
|
||||||
void copy_subtree(subtree_point_t point, ptrdiff_t extent, tree_t& out_tree) const;
|
void copy_subtree(subtree_point_t point, ptrdiff_t extent, tree_t& out_tree) const;
|
||||||
|
|
||||||
|
@ -376,19 +388,10 @@ namespace blt::gp
|
||||||
*/
|
*/
|
||||||
ptrdiff_t insert_subtree(subtree_point_t point, tree_t& other_tree) const;
|
ptrdiff_t insert_subtree(subtree_point_t point, tree_t& other_tree) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* temporarily moves the last bytes amount of data from the current stack. this can be useful for if you are going to do a lot
|
|
||||||
* of consecutive operations on the tree as this will avoid extra copy + reinsert.
|
|
||||||
* The object returned by this function will automatically move the data back in when it goes out of scope.
|
|
||||||
* @param operator_index operator index to move from. this is inclusive
|
|
||||||
*/
|
|
||||||
void temporary_move(const size_t)
|
|
||||||
{
|
|
||||||
// return obt_move_t{*this, operator_index};
|
|
||||||
}
|
|
||||||
|
|
||||||
void modify_operator(size_t point, operator_id new_id, std::optional<type_id> return_type = {}) const;
|
void modify_operator(size_t point, operator_id new_id, std::optional<type_id> return_type = {}) const;
|
||||||
|
|
||||||
|
void swap_operators(size_t point, tree_t& other_tree, size_t other_point) const;
|
||||||
|
|
||||||
tree_t* tree;
|
tree_t* tree;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -504,6 +507,11 @@ namespace blt::gp
|
||||||
|
|
||||||
tree_t& operator=(tree_t&& move) = default;
|
tree_t& operator=(tree_t&& move) = default;
|
||||||
|
|
||||||
|
tree_manipulator_t manipulate()
|
||||||
|
{
|
||||||
|
return tree_manipulator_t{*this};
|
||||||
|
}
|
||||||
|
|
||||||
void clear(gp_program& program);
|
void clear(gp_program& program);
|
||||||
|
|
||||||
void insert_operator(size_t index, const op_container_t& container);
|
void insert_operator(size_t index, const op_container_t& container);
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace blt::gp
|
||||||
if (!point)
|
if (!point)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
c1.swap_subtrees(point->p1_crossover_point, c2, point->p2_crossover_point);
|
c1.manipulate().easy_manipulator().swap_subtrees(point->p1_crossover_point, c2, point->p2_crossover_point);
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
if (!c1.check(detail::debug::context_ptr) || !c2.check(detail::debug::context_ptr))
|
if (!c1.check(detail::debug::context_ptr) || !c2.check(detail::debug::context_ptr))
|
||||||
|
@ -94,7 +94,7 @@ namespace blt::gp
|
||||||
const tree_t& c2) const
|
const tree_t& c2) const
|
||||||
{
|
{
|
||||||
const auto first = c1.select_subtree(config.terminal_chance);
|
const auto first = c1.select_subtree(config.terminal_chance);
|
||||||
const auto second = c2.select_subtree(first.type, config.max_crossover_tries, config.terminal_chance);
|
const auto second = c2.select_subtree(first.get_type(), config.max_crossover_tries, config.terminal_chance);
|
||||||
|
|
||||||
if (!second)
|
if (!second)
|
||||||
return {};
|
return {};
|
||||||
|
@ -108,13 +108,13 @@ namespace blt::gp
|
||||||
auto c1_point_o = get_point_traverse_retry(c1, {});
|
auto c1_point_o = get_point_traverse_retry(c1, {});
|
||||||
if (!c1_point_o)
|
if (!c1_point_o)
|
||||||
return {};
|
return {};
|
||||||
const auto c2_point_o = get_point_traverse_retry(c2, c1_point_o->type);
|
const auto c2_point_o = get_point_traverse_retry(c2, c1_point_o->get_type());
|
||||||
if (!c2_point_o)
|
if (!c2_point_o)
|
||||||
return {};
|
return {};
|
||||||
return {{*c1_point_o, *c2_point_o}};
|
return {{*c1_point_o, *c2_point_o}};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<tree_t::subtree_point_t> subtree_crossover_t::get_point_traverse_retry(const tree_t& t, const std::optional<type_id> type) const
|
std::optional<subtree_point_t> subtree_crossover_t::get_point_traverse_retry(const tree_t& t, const std::optional<type_id> type) const
|
||||||
{
|
{
|
||||||
if (type)
|
if (type)
|
||||||
return t.select_subtree_traverse(*type, config.max_crossover_tries, config.terminal_chance, config.depth_multiplier);
|
return t.select_subtree_traverse(*type, config.max_crossover_tries, config.terminal_chance, config.depth_multiplier);
|
||||||
|
@ -126,25 +126,25 @@ namespace blt::gp
|
||||||
// if (p1.size() < config.min_tree_size || p2.size() < config.min_tree_size)
|
// if (p1.size() < config.min_tree_size || p2.size() < config.min_tree_size)
|
||||||
// return false;
|
// return false;
|
||||||
|
|
||||||
tree_t::subtree_point_t point1, point2; // NOLINT
|
subtree_point_t point1, point2; // NOLINT
|
||||||
if (config.traverse)
|
if (config.traverse)
|
||||||
{
|
{
|
||||||
point1 = p1.select_subtree_traverse(config.terminal_chance, config.depth_multiplier);
|
point1 = p1.select_subtree_traverse(config.terminal_chance, config.depth_multiplier);
|
||||||
if (const auto val = p2.select_subtree_traverse(point1.type, config.max_crossover_tries, config.terminal_chance, config.depth_multiplier))
|
if (const auto val = p2.select_subtree_traverse(point1.get_type(), config.max_crossover_tries, config.terminal_chance, config.depth_multiplier))
|
||||||
point2 = *val;
|
point2 = *val;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
point1 = p1.select_subtree(config.terminal_chance);
|
point1 = p1.select_subtree(config.terminal_chance);
|
||||||
if (const auto val = p2.select_subtree(point1.type, config.max_crossover_tries, config.terminal_chance))
|
if (const auto val = p2.select_subtree(point1.get_type(), config.max_crossover_tries, config.terminal_chance))
|
||||||
point2 = *val;
|
point2 = *val;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& p1_operator = p1.get_operator(point1.pos);
|
const auto& p1_operator = p1.get_operator(point1.get_point());
|
||||||
const auto& p2_operator = p2.get_operator(point2.pos);
|
const auto& p2_operator = p2.get_operator(point2.get_point());
|
||||||
|
|
||||||
const auto& p1_info = program.get_operator_info(p1_operator.id());
|
const auto& p1_info = program.get_operator_info(p1_operator.id());
|
||||||
const auto& p2_info = program.get_operator_info(p2_operator.id());
|
const auto& p2_info = program.get_operator_info(p2_operator.id());
|
||||||
|
@ -163,8 +163,8 @@ namespace blt::gp
|
||||||
|
|
||||||
thread_local struct type_resolver_t
|
thread_local struct type_resolver_t
|
||||||
{
|
{
|
||||||
tracked_vector<tree_t::child_t> children_data_p1;
|
tracked_vector<child_t> children_data_p1;
|
||||||
tracked_vector<tree_t::child_t> children_data_p2;
|
tracked_vector<child_t> children_data_p2;
|
||||||
hashmap_t<type_id, std::vector<size_t>> missing_p1_types;
|
hashmap_t<type_id, std::vector<size_t>> missing_p1_types;
|
||||||
hashmap_t<type_id, std::vector<size_t>> missing_p2_types;
|
hashmap_t<type_id, std::vector<size_t>> missing_p2_types;
|
||||||
hashset_t<size_t> correct_types;
|
hashset_t<size_t> correct_types;
|
||||||
|
@ -231,7 +231,7 @@ namespace blt::gp
|
||||||
return correct_types.contains(index) || p2_correct_types.contains(index);
|
return correct_types.contains(index) || p2_correct_types.contains(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear(gp_program& program)
|
||||||
{
|
{
|
||||||
children_data_p1.clear();
|
children_data_p1.clear();
|
||||||
children_data_p2.clear();
|
children_data_p2.clear();
|
||||||
|
@ -249,7 +249,7 @@ namespace blt::gp
|
||||||
v.clear();
|
v.clear();
|
||||||
}
|
}
|
||||||
} resolver;
|
} resolver;
|
||||||
resolver.clear();
|
resolver.clear(program);
|
||||||
|
|
||||||
auto min_size = std::min(p1_info.argument_types.size(), p2_info.argument_types.size());
|
auto min_size = std::min(p1_info.argument_types.size(), p2_info.argument_types.size());
|
||||||
|
|
||||||
|
@ -321,19 +321,19 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we do the swap
|
// now we do the swap
|
||||||
p1.find_child_extends(resolver.children_data_p1, point1.pos, p1_info.argument_types.size());
|
p1.find_child_extends(resolver.children_data_p1, point1.get_point(), p1_info.argument_types.size());
|
||||||
p2.find_child_extends(resolver.children_data_p2, point2.pos, p2_info.argument_types.size());
|
p2.find_child_extends(resolver.children_data_p2, point2.get_point(), p2_info.argument_types.size());
|
||||||
|
|
||||||
for (const auto& [index1, index2] : resolver.p1_reorder_types)
|
for (const auto& [index1, index2] : resolver.p1_reorder_types)
|
||||||
{
|
{
|
||||||
BLT_DEBUG("Reordering in C1: {} -> {}", index1, index2);
|
BLT_DEBUG("Reordering in C1: {} -> {}", index1, index2);
|
||||||
c1.swap_subtrees(resolver.children_data_p1[index1], c1, resolver.children_data_p1[index2]);
|
c1.manipulate().easy_manipulator().swap_subtrees(resolver.children_data_p1[index1], c1, resolver.children_data_p1[index2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [index1, index2] : resolver.p2_reorder_types)
|
for (const auto& [index1, index2] : resolver.p2_reorder_types)
|
||||||
{
|
{
|
||||||
BLT_DEBUG("Reordering in C2: {} -> {}", index1, index2);
|
BLT_DEBUG("Reordering in C2: {} -> {}", index1, index2);
|
||||||
c2.swap_subtrees(resolver.children_data_p2[index1], c2, resolver.children_data_p2[index2]);
|
c2.manipulate().easy_manipulator().swap_subtrees(resolver.children_data_p2[index1], c2, resolver.children_data_p2[index2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto c1_insert = resolver.children_data_p1.back().end;
|
auto c1_insert = resolver.children_data_p1.back().end;
|
||||||
|
@ -342,14 +342,14 @@ namespace blt::gp
|
||||||
for (const auto& [p1_index, p2_index] : resolver.swap_types)
|
for (const auto& [p1_index, p2_index] : resolver.swap_types)
|
||||||
{
|
{
|
||||||
if (p1_index < p1_info.argument_types.size() && p2_index < p2_info.argument_types.size())
|
if (p1_index < p1_info.argument_types.size() && p2_index < p2_info.argument_types.size())
|
||||||
c1.swap_subtrees(resolver.children_data_p1[p1_index], c2, resolver.children_data_p2[p2_index]);
|
c1.manipulate().easy_manipulator().swap_subtrees(resolver.children_data_p1[p1_index], c2, resolver.children_data_p2[p2_index]);
|
||||||
else if (p1_index < p1_info.argument_types.size() && p2_index >= p2_info.argument_types.size())
|
else if (p1_index < p1_info.argument_types.size() && p2_index >= p2_info.argument_types.size())
|
||||||
{
|
{
|
||||||
BLT_TRACE("(P1 IS UNDER!) Trying to swap P1 {} for P2 {} (Sizes: P1: {} P2: {})", p1_index, p2_index, p1_info.argument_types.size(), p2_info.argument_types.size());
|
BLT_TRACE("(P1 IS UNDER!) Trying to swap P1 {} for P2 {} (Sizes: P1: {} P2: {})", p1_index, p2_index, p1_info.argument_types.size(), p2_info.argument_types.size());
|
||||||
BLT_TRACE("Inserting into P2 from P1!");
|
BLT_TRACE("Inserting into P2 from P1!");
|
||||||
c1.copy_subtree(resolver.children_data_p1[p1_index], resolver.temp_tree);
|
c1.manipulate().easy_manipulator().copy_subtree(resolver.children_data_p1[p1_index], resolver.temp_trees[0]);
|
||||||
c1.delete_subtree(resolver.children_data_p1[p1_index]);
|
c1.manipulate().easy_manipulator().delete_subtree(resolver.children_data_p1[p1_index]);
|
||||||
c2_insert = c2.insert_subtree(tree_t::subtree_point_t{c1_insert}, resolver.temp_tree);
|
c2_insert = c2.manipulate().easy_manipulator().insert_subtree(subtree_point_t{c1_insert}, resolver.temp_trees[0]);
|
||||||
} else if (p2_index < p2_info.argument_types.size() && p1_index >= p1_info.argument_types.size())
|
} else if (p2_index < p2_info.argument_types.size() && p1_index >= p1_info.argument_types.size())
|
||||||
{
|
{
|
||||||
BLT_TRACE("(P2 IS UNDER!) Trying to swap P1 {} for P2 {} (Sizes: P1: {} P2: {})", p1_index, p2_index, p1_info.argument_types.size(), p2_info.argument_types.size());
|
BLT_TRACE("(P2 IS UNDER!) Trying to swap P1 {} for P2 {} (Sizes: P1: {} P2: {})", p1_index, p2_index, p1_info.argument_types.size(), p2_info.argument_types.size());
|
||||||
|
@ -360,8 +360,8 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
c1.modify_operator(point1.pos, p2_operator.id(), p2_info.return_type);
|
c1.manipulate().easy_manipulator().modify_operator(point1.get_point(), p2_operator.id(), p2_info.return_type);
|
||||||
c2.modify_operator(point2.pos, p1_operator.id(), p1_info.return_type);
|
c2.manipulate().easy_manipulator().modify_operator(point2.get_point(), p1_operator.id(), p1_info.return_type);
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
if (!c1.check(detail::debug::context_ptr) || !c2.check(detail::debug::context_ptr))
|
if (!c1.check(detail::debug::context_ptr) || !c2.check(detail::debug::context_ptr))
|
||||||
|
@ -413,17 +413,17 @@ namespace blt::gp
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t mutation_t::mutate_point(gp_program& program, tree_t& c, const tree_t::subtree_point_t node) const
|
size_t mutation_t::mutate_point(gp_program& program, tree_t& c, const subtree_point_t node) const
|
||||||
{
|
{
|
||||||
auto& new_tree = tree_t::get_thread_local(program);
|
auto& new_tree = tree_t::get_thread_local(program);
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
auto previous_size = new_tree.size();
|
auto previous_size = new_tree.size();
|
||||||
auto previous_bytes = new_tree.total_value_bytes();
|
auto previous_bytes = new_tree.total_value_bytes();
|
||||||
#endif
|
#endif
|
||||||
config.generator.get().generate(new_tree, {program, node.type, config.replacement_min_depth, config.replacement_max_depth});
|
config.generator.get().generate(new_tree, {program, node.get_type(), config.replacement_min_depth, config.replacement_max_depth});
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
const auto old_op = c.get_operator(node.pos);
|
const auto old_op = c.get_operator(node.get_point());
|
||||||
if (!new_tree.check(detail::debug::context_ptr))
|
if (!new_tree.check(detail::debug::context_ptr))
|
||||||
{
|
{
|
||||||
BLT_ERROR("Mutate point new tree check failed!");
|
BLT_ERROR("Mutate point new tree check failed!");
|
||||||
|
@ -434,11 +434,11 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
c.replace_subtree(node, new_tree);
|
c.manipulate().easy_manipulator().replace_subtree(node, new_tree);
|
||||||
|
|
||||||
// this will check to make sure that the tree is in a correct and executable state. it requires that the evaluation is context free!
|
// this will check to make sure that the tree is in a correct and executable state. it requires that the evaluation is context free!
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
const auto new_op = c.get_operator(node.pos);
|
const auto new_op = c.get_operator(node.get_point());
|
||||||
if (!c.check(detail::debug::context_ptr))
|
if (!c.check(detail::debug::context_ptr))
|
||||||
{
|
{
|
||||||
print_mutate_stats();
|
print_mutate_stats();
|
||||||
|
@ -450,7 +450,7 @@ namespace blt::gp
|
||||||
#if defined(BLT_TRACK_ALLOCATIONS) || BLT_DEBUG_LEVEL >= 2
|
#if defined(BLT_TRACK_ALLOCATIONS) || BLT_DEBUG_LEVEL >= 2
|
||||||
++mutate_point_counter;
|
++mutate_point_counter;
|
||||||
#endif
|
#endif
|
||||||
return node.pos + new_tree.size();
|
return node.get_point() + new_tree.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool advanced_mutation_t::apply(gp_program& program, [[maybe_unused]] const tree_t& p, tree_t& c)
|
bool advanced_mutation_t::apply(gp_program& program, [[maybe_unused]] const tree_t& p, tree_t& c)
|
||||||
|
@ -496,7 +496,7 @@ namespace blt::gp
|
||||||
auto& replacement_func_info = program.get_operator_info(random_replacement);
|
auto& replacement_func_info = program.get_operator_info(random_replacement);
|
||||||
|
|
||||||
// cache memory used for offset data.
|
// cache memory used for offset data.
|
||||||
thread_local tracked_vector<tree_t::child_t> children_data;
|
thread_local tracked_vector<child_t> children_data;
|
||||||
children_data.clear();
|
children_data.clear();
|
||||||
|
|
||||||
c.find_child_extends(children_data, c_node, current_func_info.argument_types.size());
|
c.find_child_extends(children_data, c_node, current_func_info.argument_types.size());
|
||||||
|
@ -512,7 +512,7 @@ namespace blt::gp
|
||||||
{program, val.id, config.replacement_min_depth, config.replacement_max_depth});
|
{program, val.id, config.replacement_min_depth, config.replacement_max_depth});
|
||||||
|
|
||||||
auto& [child_start, child_end] = children_data[children_data.size() - 1 - index];
|
auto& [child_start, child_end] = children_data[children_data.size() - 1 - index];
|
||||||
c.replace_subtree(c.subtree_from_point(child_start), child_end, tree);
|
c.manipulate().easy_manipulator().replace_subtree(c.subtree_from_point(child_start), child_end, tree);
|
||||||
|
|
||||||
// shift over everybody after.
|
// shift over everybody after.
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
|
@ -537,7 +537,7 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
auto end_index = children_data[(current_func_info.argc.argc - replacement_func_info.argc.argc) - 1].end;
|
auto end_index = children_data[(current_func_info.argc.argc - replacement_func_info.argc.argc) - 1].end;
|
||||||
auto start_index = children_data.begin()->start;
|
auto start_index = children_data.begin()->start;
|
||||||
c.delete_subtree(tree_t::subtree_point_t(start_index), end_index);
|
c.manipulate().easy_manipulator().delete_subtree(subtree_point_t(start_index), end_index);
|
||||||
}
|
}
|
||||||
else if (current_func_info.argc.argc == replacement_func_info.argc.argc)
|
else if (current_func_info.argc.argc == replacement_func_info.argc.argc)
|
||||||
{
|
{
|
||||||
|
@ -561,11 +561,11 @@ namespace blt::gp
|
||||||
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
|
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
|
||||||
config.replacement_max_depth
|
config.replacement_max_depth
|
||||||
});
|
});
|
||||||
start_index = c.insert_subtree(tree_t::subtree_point_t(static_cast<ptrdiff_t>(start_index)), tree);
|
start_index = c.manipulate().easy_manipulator().insert_subtree(subtree_point_t(static_cast<ptrdiff_t>(start_index)), tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// now finally update the type.
|
// now finally update the type.
|
||||||
c.modify_operator(c_node, random_replacement, replacement_func_info.return_type);
|
c.manipulate().easy_manipulator().modify_operator(c_node, random_replacement, replacement_func_info.return_type);
|
||||||
}
|
}
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
if (!c.check(detail::debug::context_ptr))
|
if (!c.check(detail::debug::context_ptr))
|
||||||
|
@ -636,7 +636,7 @@ namespace blt::gp
|
||||||
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
|
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
|
||||||
config.replacement_max_depth
|
config.replacement_max_depth
|
||||||
});
|
});
|
||||||
start_index = c.insert_subtree(tree_t::subtree_point_t(static_cast<ptrdiff_t>(start_index)), tree);
|
start_index = c.manipulate().easy_manipulator().insert_subtree(subtree_point_t(static_cast<ptrdiff_t>(start_index)), tree);
|
||||||
}
|
}
|
||||||
start_index += size;
|
start_index += size;
|
||||||
// vals.copy_from(combined_ptr, for_bytes);
|
// vals.copy_from(combined_ptr, for_bytes);
|
||||||
|
@ -648,7 +648,7 @@ namespace blt::gp
|
||||||
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
|
program, replacement_func_info.argument_types[i].id, config.replacement_min_depth,
|
||||||
config.replacement_max_depth
|
config.replacement_max_depth
|
||||||
});
|
});
|
||||||
start_index = c.insert_subtree(tree_t::subtree_point_t(static_cast<ptrdiff_t>(start_index)), tree);
|
start_index = c.manipulate().easy_manipulator().insert_subtree(subtree_point_t(static_cast<ptrdiff_t>(start_index)), tree);
|
||||||
}
|
}
|
||||||
// vals.copy_from(combined_ptr + for_bytes, after_bytes);
|
// vals.copy_from(combined_ptr + for_bytes, after_bytes);
|
||||||
|
|
||||||
|
@ -690,7 +690,7 @@ namespace blt::gp
|
||||||
if (argument_index == -1ul)
|
if (argument_index == -1ul)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
thread_local tracked_vector<tree_t::child_t> child_data;
|
thread_local tracked_vector<child_t> child_data;
|
||||||
child_data.clear();
|
child_data.clear();
|
||||||
|
|
||||||
c.find_child_extends(child_data, c_node, info.argument_types.size());
|
c.find_child_extends(child_data, c_node, info.argument_types.size());
|
||||||
|
@ -700,9 +700,9 @@ namespace blt::gp
|
||||||
|
|
||||||
thread_local tree_t child_tree{program};
|
thread_local tree_t child_tree{program};
|
||||||
|
|
||||||
c.copy_subtree(tree_t::subtree_point_t(child.start), child.end, child_tree);
|
c.manipulate().easy_manipulator().copy_subtree(subtree_point_t(child.start), child.end, child_tree);
|
||||||
c.delete_subtree(tree_t::subtree_point_t(static_cast<ptrdiff_t>(c_node)));
|
c.manipulate().easy_manipulator().delete_subtree(subtree_point_t(static_cast<ptrdiff_t>(c_node)));
|
||||||
c.insert_subtree(tree_t::subtree_point_t(static_cast<ptrdiff_t>(c_node)), child_tree);
|
c.manipulate().easy_manipulator().insert_subtree(subtree_point_t(static_cast<ptrdiff_t>(c_node)), child_tree);
|
||||||
child_tree.clear(program);
|
child_tree.clear(program);
|
||||||
|
|
||||||
// auto for_bytes = c.total_value_bytes(child.start, child.end);
|
// auto for_bytes = c.total_value_bytes(child.start, child.end);
|
||||||
|
@ -769,7 +769,7 @@ namespace blt::gp
|
||||||
continue;
|
continue;
|
||||||
const auto to_index = program.get_random().select(potential_indexes);
|
const auto to_index = program.get_random().select(potential_indexes);
|
||||||
|
|
||||||
thread_local tracked_vector<tree_t::child_t> child_data;
|
thread_local tracked_vector<child_t> child_data;
|
||||||
child_data.clear();
|
child_data.clear();
|
||||||
|
|
||||||
c.find_child_extends(child_data, c_node, info.argument_types.size());
|
c.find_child_extends(child_data, c_node, info.argument_types.size());
|
||||||
|
@ -780,8 +780,8 @@ namespace blt::gp
|
||||||
const auto& [to_start, to_end] = child_data[child_to_index];
|
const auto& [to_start, to_end] = child_data[child_to_index];
|
||||||
|
|
||||||
thread_local tree_t copy_tree{program};
|
thread_local tree_t copy_tree{program};
|
||||||
c.copy_subtree(tree_t::subtree_point_t{from_start}, from_end, copy_tree);
|
c.manipulate().easy_manipulator().copy_subtree(subtree_point_t{from_start}, from_end, copy_tree);
|
||||||
c.replace_subtree(tree_t::subtree_point_t{to_start}, to_end, copy_tree);
|
c.manipulate().easy_manipulator().replace_subtree(subtree_point_t{to_start}, to_end, copy_tree);
|
||||||
copy_tree.clear(program);
|
copy_tree.clear(program);
|
||||||
|
|
||||||
#if BLT_DEBUG_LEVEL >= 2
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
|
|
39
src/tree.cpp
39
src/tree.cpp
|
@ -125,13 +125,10 @@ namespace blt::gp
|
||||||
create_indent(out, indent, pretty_print) << ")" << end_indent(pretty_print);
|
create_indent(out, indent, pretty_print) << ")" << end_indent(pretty_print);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
if (!pretty_print)
|
||||||
{
|
out << " ";
|
||||||
if (!pretty_print)
|
arguments_left.push(top - 1);
|
||||||
out << " ";
|
break;
|
||||||
arguments_left.push(top - 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (!arguments_left.empty())
|
while (!arguments_left.empty())
|
||||||
|
@ -252,7 +249,7 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<subtree_point_t> tree_t::select_subtree_traverse(const type_id type, const u32 max_tries, const double terminal_chance,
|
std::optional<subtree_point_t> tree_t::select_subtree_traverse(const type_id type, const u32 max_tries, const double terminal_chance,
|
||||||
const double depth_multiplier) const
|
const double depth_multiplier) const
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < max_tries; ++i)
|
for (u32 i = 0; i < max_tries; ++i)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +259,8 @@ namespace blt::gp
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void slow_tree_manipulator_t::copy_subtree(const subtree_point_t point, const ptrdiff_t extent, tracked_vector<op_container_t>& operators, stack_allocator& stack) const
|
void slow_tree_manipulator_t::copy_subtree(const subtree_point_t point, const ptrdiff_t extent, tracked_vector<op_container_t>& operators,
|
||||||
|
stack_allocator& stack) const
|
||||||
{
|
{
|
||||||
const auto point_begin_itr = tree->operations.begin() + point.get_spoint();
|
const auto point_begin_itr = tree->operations.begin() + point.get_spoint();
|
||||||
const auto point_end_itr = tree->operations.begin() + extent;
|
const auto point_end_itr = tree->operations.begin() + extent;
|
||||||
|
@ -310,7 +308,7 @@ namespace blt::gp
|
||||||
|
|
||||||
void slow_tree_manipulator_t::copy_subtree(const child_t subtree, tree_t& out_tree) const
|
void slow_tree_manipulator_t::copy_subtree(const child_t subtree, tree_t& out_tree) const
|
||||||
{
|
{
|
||||||
copy_subtree(subtree_point_t{subtree.start, tree->m_program->get_operator_info(tree->operations[subtree.start].id())}, subtree.end, out_tree);
|
copy_subtree(subtree_point_t{subtree.start}, subtree.end, out_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
void slow_tree_manipulator_t::swap_subtrees(const child_t our_subtree, tree_t& other_tree, const child_t other_subtree) const
|
void slow_tree_manipulator_t::swap_subtrees(const child_t our_subtree, tree_t& other_tree, const child_t other_subtree) const
|
||||||
|
@ -385,7 +383,7 @@ namespace blt::gp
|
||||||
void slow_tree_manipulator_t::swap_subtrees(const subtree_point_t our_subtree, tree_t& other_tree, const subtree_point_t other_subtree) const
|
void slow_tree_manipulator_t::swap_subtrees(const subtree_point_t our_subtree, tree_t& other_tree, const subtree_point_t other_subtree) const
|
||||||
{
|
{
|
||||||
swap_subtrees(child_t{our_subtree.get_spoint(), tree->find_endpoint(our_subtree.get_spoint())}, other_tree,
|
swap_subtrees(child_t{our_subtree.get_spoint(), tree->find_endpoint(our_subtree.get_spoint())}, other_tree,
|
||||||
child_t{other_subtree.get_spoint(), tree->find_endpoint(other_subtree.get_spoint())});
|
child_t{other_subtree.get_spoint(), other_tree.find_endpoint(other_subtree.get_spoint())});
|
||||||
}
|
}
|
||||||
|
|
||||||
void slow_tree_manipulator_t::replace_subtree(const subtree_point_t point, const ptrdiff_t extent, const tree_t& other_tree) const
|
void slow_tree_manipulator_t::replace_subtree(const subtree_point_t point, const ptrdiff_t extent, const tree_t& other_tree) const
|
||||||
|
@ -660,6 +658,17 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type_id subtree_point_t::get_type() const
|
||||||
|
{
|
||||||
|
#if BLT_DEBUG_LEVEL > 0
|
||||||
|
if (info == nullptr)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Invalid subtree point, operator info was null! (Point probably created with passthrough "
|
||||||
|
"intentions or operator info was not available, please manually acquire type)");
|
||||||
|
#endif
|
||||||
|
return info->return_type;
|
||||||
|
}
|
||||||
|
|
||||||
void single_operation_tree_manipulator_t::replace_subtree(tree_t& other_tree)
|
void single_operation_tree_manipulator_t::replace_subtree(tree_t& other_tree)
|
||||||
{
|
{
|
||||||
replace_subtree(other_tree.operations, other_tree.values);
|
replace_subtree(other_tree.operations, other_tree.values);
|
||||||
|
@ -667,7 +676,6 @@ namespace blt::gp
|
||||||
|
|
||||||
void single_operation_tree_manipulator_t::replace_subtree(tracked_vector<op_container_t>& operations, stack_allocator& stack)
|
void single_operation_tree_manipulator_t::replace_subtree(tracked_vector<op_container_t>& operations, stack_allocator& stack)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tree_t::copy_fast(const tree_t& copy)
|
void tree_t::copy_fast(const tree_t& copy)
|
||||||
|
@ -877,13 +885,18 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
if (move_data.empty())
|
if (move_data.empty())
|
||||||
{
|
{
|
||||||
const size_t after_bytes = calculate_ephemeral_size(tree->operations.begin() + static_cast<ptrdiff_t>(point) + 1, tree->operations.end());
|
const size_t after_bytes = calculate_ephemeral_size(tree->operations.begin() + static_cast<ptrdiff_t>(point) + 1,
|
||||||
|
tree->operations.end());
|
||||||
move_data.move(after_bytes);
|
move_data.move(after_bytes);
|
||||||
}
|
}
|
||||||
tree->handle_operator_inserted(tree->operations[point]);
|
tree->handle_operator_inserted(tree->operations[point]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void slow_tree_manipulator_t::swap_operators(size_t point, tree_t& other_tree, size_t other_point) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const tree_t& a, const tree_t& b)
|
bool operator==(const tree_t& a, const tree_t& b)
|
||||||
{
|
{
|
||||||
if (a.operations.size() != b.operations.size())
|
if (a.operations.size() != b.operations.size())
|
||||||
|
|
Loading…
Reference in New Issue