i think it's shared now?
parent
3572539b74
commit
1789a9e474
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(blt-gp VERSION 0.1.35)
|
||||
project(blt-gp VERSION 0.1.36)
|
||||
|
||||
include(CTest)
|
||||
|
||||
|
@ -16,7 +16,7 @@ set(CMAKE_CXX_STANDARD 17)
|
|||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -g")
|
||||
#SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -g")
|
||||
|
||||
if (NOT TARGET BLT)
|
||||
add_subdirectory(lib/blt)
|
||||
|
|
|
@ -362,8 +362,11 @@ namespace blt::gp
|
|||
#ifdef BLT_TRACK_ALLOCATIONS
|
||||
auto gen_alloc = blt::gp::tracker.start_measurement();
|
||||
#endif
|
||||
BLT_ASSERT_MSG(current_pop.get_individuals().size() == config.population_size,
|
||||
("cur pop size: " + std::to_string(current_pop.get_individuals().size())).c_str());
|
||||
BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size,
|
||||
("next pop size: " + std::to_string(next_pop.get_individuals().size())).c_str());
|
||||
// should already be empty
|
||||
next_pop.clear();
|
||||
thread_helper.next_gen_left.store(config.population_size, std::memory_order_release);
|
||||
(*thread_execution_service)(0);
|
||||
#ifdef BLT_TRACK_ALLOCATIONS
|
||||
|
@ -375,8 +378,10 @@ namespace blt::gp
|
|||
|
||||
void next_generation()
|
||||
{
|
||||
BLT_ASSERT_MSG(current_pop.get_individuals().size() == config.population_size,
|
||||
("cur pop size: " + std::to_string(current_pop.get_individuals().size())).c_str());
|
||||
BLT_ASSERT_MSG(next_pop.get_individuals().size() == config.population_size,
|
||||
("pop size: " + std::to_string(next_pop.get_individuals().size())).c_str());
|
||||
("next pop size: " + std::to_string(next_pop.get_individuals().size())).c_str());
|
||||
std::swap(current_pop, next_pop);
|
||||
current_generation++;
|
||||
}
|
||||
|
@ -400,6 +405,7 @@ namespace blt::gp
|
|||
current_generation = 0;
|
||||
current_pop = config.pop_initializer.get().generate(
|
||||
{*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size});
|
||||
next_pop = population_t(current_pop);
|
||||
if (eval_fitness_now)
|
||||
evaluate_fitness_internal();
|
||||
}
|
||||
|
@ -465,21 +471,24 @@ namespace blt::gp
|
|||
}
|
||||
if (thread_helper.next_gen_left > 0)
|
||||
{
|
||||
static thread_local tracked_vector<tree_t> new_children;
|
||||
new_children.clear();
|
||||
auto args = get_selector_args(new_children);
|
||||
auto args = get_selector_args();
|
||||
|
||||
crossover_selection.pre_process(*this, current_pop);
|
||||
mutation_selection.pre_process(*this, current_pop);
|
||||
reproduction_selection.pre_process(*this, current_pop);
|
||||
|
||||
perform_elitism(args);
|
||||
perform_elitism(args, next_pop);
|
||||
|
||||
while (new_children.size() < config.population_size)
|
||||
func(args, crossover_selection, mutation_selection, reproduction_selection);
|
||||
blt::size_t start = config.elites;
|
||||
|
||||
for (auto& i : new_children)
|
||||
next_pop.get_individuals().emplace_back(std::move(i));
|
||||
while (start < config.population_size)
|
||||
{
|
||||
tree_t& c1 = next_pop.get_individuals()[start].tree;
|
||||
tree_t* c2 = nullptr;
|
||||
if (start + 1 < config.population_size)
|
||||
c2 = &next_pop.get_individuals()[start + 1].tree;
|
||||
start += func(args, crossover_selection, mutation_selection, reproduction_selection, c1, c2);
|
||||
}
|
||||
|
||||
thread_helper.next_gen_left = 0;
|
||||
}
|
||||
|
@ -542,9 +551,7 @@ namespace blt::gp
|
|||
}
|
||||
if (thread_helper.next_gen_left > 0)
|
||||
{
|
||||
static thread_local tracked_vector<tree_t> new_children;
|
||||
new_children.clear();
|
||||
auto args = get_selector_args(new_children);
|
||||
auto args = get_selector_args();
|
||||
if (id == 0)
|
||||
{
|
||||
current_stats.normalized_fitness.clear();
|
||||
|
@ -562,37 +569,35 @@ namespace blt::gp
|
|||
if (&crossover_selection != &reproduction_selection)
|
||||
reproduction_selection.pre_process(*this, current_pop);
|
||||
|
||||
perform_elitism(args);
|
||||
perform_elitism(args, next_pop);
|
||||
|
||||
for (auto& i : new_children)
|
||||
next_pop.get_individuals().emplace_back(std::move(i));
|
||||
thread_helper.next_gen_left -= new_children.size();
|
||||
new_children.clear();
|
||||
thread_helper.next_gen_left -= config.elites;
|
||||
}
|
||||
thread_helper.barrier.wait();
|
||||
|
||||
while (thread_helper.next_gen_left > 0)
|
||||
{
|
||||
blt::size_t size = 0;
|
||||
blt::size_t begin = 0;
|
||||
blt::size_t end = thread_helper.next_gen_left.load(std::memory_order_relaxed);
|
||||
do
|
||||
{
|
||||
size = std::min(end, config.evaluation_size);
|
||||
begin = end - size;
|
||||
} while (!thread_helper.next_gen_left.compare_exchange_weak(end, end - size,
|
||||
std::memory_order::memory_order_relaxed,
|
||||
std::memory_order::memory_order_relaxed));
|
||||
|
||||
while (new_children.size() < size)
|
||||
func(args, crossover_selection, mutation_selection, reproduction_selection);
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
std::scoped_lock lock(thread_helper.thread_generation_lock);
|
||||
for (auto& i : new_children)
|
||||
{
|
||||
if (next_pop.get_individuals().size() < config.population_size)
|
||||
next_pop.get_individuals().emplace_back(i);
|
||||
}
|
||||
auto index = config.elites + begin;
|
||||
tree_t& c1 = next_pop.get_individuals()[index].tree;
|
||||
tree_t* c2 = nullptr;
|
||||
if (index + 1 < end)
|
||||
c2 = &next_pop.get_individuals()[index + 1].tree;
|
||||
begin += func(args, crossover_selection, mutation_selection, reproduction_selection, c1, c2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
thread_helper.barrier.wait();
|
||||
|
@ -747,9 +752,9 @@ namespace blt::gp
|
|||
}
|
||||
|
||||
private:
|
||||
inline selector_args get_selector_args(tracked_vector<tree_t>& next_pop_trees)
|
||||
inline selector_args get_selector_args()
|
||||
{
|
||||
return {*this, next_pop_trees, current_pop, current_stats, config, get_random()};
|
||||
return {*this, current_pop, current_stats, config, get_random()};
|
||||
}
|
||||
|
||||
template<typename Return, blt::size_t size, typename Accessor, blt::size_t... indexes>
|
||||
|
@ -765,7 +770,7 @@ namespace blt::gp
|
|||
{
|
||||
statistic_history.push_back(current_stats);
|
||||
current_stats.clear();
|
||||
thread_helper.evaluation_left.store(current_pop.get_individuals().size(), std::memory_order_release);
|
||||
thread_helper.evaluation_left.store(config.population_size, std::memory_order_release);
|
||||
(*thread_execution_service)(0);
|
||||
|
||||
current_stats.average_fitness = current_stats.overall_fitness / static_cast<double>(config.population_size);
|
||||
|
@ -791,7 +796,6 @@ namespace blt::gp
|
|||
std::vector<std::unique_ptr<std::thread>> threads;
|
||||
|
||||
std::mutex thread_function_control{};
|
||||
std::mutex thread_generation_lock{};
|
||||
std::condition_variable thread_function_condition{};
|
||||
|
||||
std::atomic_uint64_t evaluation_left = 0;
|
||||
|
|
|
@ -32,15 +32,14 @@ namespace blt::gp
|
|||
struct selector_args
|
||||
{
|
||||
gp_program& program;
|
||||
tracked_vector<tree_t>& next_pop;
|
||||
population_t& current_pop;
|
||||
const population_t& current_pop;
|
||||
population_stats& current_stats;
|
||||
prog_config_t& config;
|
||||
random_t& random;
|
||||
};
|
||||
|
||||
constexpr inline auto perform_elitism = [](const selector_args& args) {
|
||||
auto& [program, next_pop, current_pop, current_stats, config, random] = args;
|
||||
constexpr inline auto perform_elitism = [](const selector_args& args, population_t& next_pop) {
|
||||
auto& [program, current_pop, current_stats, config, random] = args;
|
||||
|
||||
if (config.elites > 0)
|
||||
{
|
||||
|
@ -70,39 +69,38 @@ namespace blt::gp
|
|||
}
|
||||
|
||||
for (blt::size_t i = 0; i < config.elites; i++)
|
||||
next_pop.push_back(current_pop.get_individuals()[values[i].first].tree);
|
||||
next_pop.get_individuals()[i].copy_fast(current_pop.get_individuals()[values[i].first].tree);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Crossover, typename Mutation, typename Reproduction>
|
||||
constexpr inline auto default_next_pop_creator = [](
|
||||
blt::gp::selector_args& args, Crossover& crossover_selection, Mutation& mutation_selection, Reproduction& reproduction_selection) {
|
||||
auto& [program, next_pop, current_pop, current_stats, config, random] = args;
|
||||
blt::gp::selector_args& args, Crossover& crossover_selection, Mutation& mutation_selection, Reproduction& reproduction_selection,
|
||||
tree_t& c1, tree_t* c2) {
|
||||
auto& [program, current_pop, current_stats, config, random] = args;
|
||||
|
||||
int sel = random.get_i32(0, 3);
|
||||
switch (sel)
|
||||
{
|
||||
case 0:
|
||||
if (c2 == nullptr)
|
||||
return 0;
|
||||
// everyone gets a chance once per loop.
|
||||
if (random.choice(config.crossover_chance))
|
||||
{
|
||||
// auto state = tracker.start_measurement();
|
||||
// crossover
|
||||
auto& p1 = crossover_selection.select(program, current_pop);
|
||||
auto& p2 = crossover_selection.select(program, current_pop);
|
||||
|
||||
auto results = config.crossover.get().apply(program, p1, p2);
|
||||
|
||||
// if crossover fails, we can check for mutation on these guys. otherwise straight copy them into the next pop
|
||||
if (results)
|
||||
const tree_t* p1;
|
||||
const tree_t* p2;
|
||||
do
|
||||
{
|
||||
next_pop.push_back(std::move(results->child1));
|
||||
if (next_pop.size() != config.population_size)
|
||||
next_pop.push_back(std::move(results->child2));
|
||||
}
|
||||
p1 = &crossover_selection.select(program, current_pop);
|
||||
p2 = &crossover_selection.select(program, current_pop);
|
||||
} while (!config.crossover.get().apply(program, *p1, *p2, c1, *c2));
|
||||
// tracker.stop_measurement(state);
|
||||
// BLT_TRACE("Crossover Allocated %ld times with a total of %s", state.getAllocationDifference(),
|
||||
// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
|
@ -110,11 +108,15 @@ namespace blt::gp
|
|||
{
|
||||
// auto state = tracker.start_measurement();
|
||||
// mutation
|
||||
auto& p = mutation_selection.select(program, current_pop);
|
||||
next_pop.push_back(std::move(config.mutator.get().apply(program, p)));
|
||||
const tree_t* p;
|
||||
do
|
||||
{
|
||||
p = &mutation_selection.select(program, current_pop);
|
||||
} while (!config.mutator.get().apply(program, *p, c1));
|
||||
// tracker.stop_measurement(state);
|
||||
// BLT_TRACE("Mutation Allocated %ld times with a total of %s", state.getAllocationDifference(),
|
||||
// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
@ -122,11 +124,11 @@ namespace blt::gp
|
|||
{
|
||||
// auto state = tracker.start_measurement();
|
||||
// reproduction
|
||||
auto& p = reproduction_selection.select(program, current_pop);
|
||||
next_pop.push_back(p);
|
||||
c1 = reproduction_selection.select(program, current_pop);
|
||||
// tracker.stop_measurement(state);
|
||||
// BLT_TRACE("Reproduction Allocated %ld times with a total of %s", state.getAllocationDifference(),
|
||||
// blt::byte_convert_t(state.getAllocatedByteDifference()).convert_to_nearest_type().to_pretty_string().c_str());
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -136,6 +138,7 @@ namespace blt::gp
|
|||
BLT_UNREACHABLE;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
class selection_t
|
||||
|
@ -147,7 +150,7 @@ namespace blt::gp
|
|||
* @param stats the populations statistics
|
||||
* @return
|
||||
*/
|
||||
virtual tree_t& select(gp_program& program, population_t& pop) = 0;
|
||||
virtual const tree_t& select(gp_program& program, const population_t& pop) = 0;
|
||||
|
||||
virtual void pre_process(gp_program&, population_t&)
|
||||
{}
|
||||
|
@ -158,19 +161,19 @@ namespace blt::gp
|
|||
class select_best_t : public selection_t
|
||||
{
|
||||
public:
|
||||
tree_t& select(gp_program& program, population_t& pop) final;
|
||||
const tree_t& select(gp_program& program, const population_t& pop) final;
|
||||
};
|
||||
|
||||
class select_worst_t : public selection_t
|
||||
{
|
||||
public:
|
||||
tree_t& select(gp_program& program, population_t& pop) final;
|
||||
const tree_t& select(gp_program& program, const population_t& pop) final;
|
||||
};
|
||||
|
||||
class select_random_t : public selection_t
|
||||
{
|
||||
public:
|
||||
tree_t& select(gp_program& program, population_t& pop) final;
|
||||
const tree_t& select(gp_program& program, const population_t& pop) final;
|
||||
};
|
||||
|
||||
class select_tournament_t : public selection_t
|
||||
|
@ -182,7 +185,7 @@ namespace blt::gp
|
|||
BLT_ABORT("Unable to select with this size. Must select at least 1 individual_t!");
|
||||
}
|
||||
|
||||
tree_t& select(gp_program& program, population_t& pop) final;
|
||||
const tree_t& select(gp_program& program, const population_t& pop) final;
|
||||
|
||||
private:
|
||||
const blt::size_t selection_size;
|
||||
|
@ -191,7 +194,7 @@ namespace blt::gp
|
|||
class select_fitness_proportionate_t : public selection_t
|
||||
{
|
||||
public:
|
||||
tree_t& select(gp_program& program, population_t& pop) final;
|
||||
const tree_t& select(gp_program& program, const population_t& pop) final;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -57,16 +57,6 @@ namespace blt::gp
|
|||
class crossover_t
|
||||
{
|
||||
public:
|
||||
enum class error_t
|
||||
{
|
||||
NO_VALID_TYPE,
|
||||
TREE_TOO_SMALL
|
||||
};
|
||||
struct result_t
|
||||
{
|
||||
tree_t child1;
|
||||
tree_t child2;
|
||||
};
|
||||
struct crossover_point_t
|
||||
{
|
||||
blt::ptrdiff_t p1_crossover_point;
|
||||
|
@ -87,7 +77,7 @@ namespace blt::gp
|
|||
explicit crossover_t(const config_t& config): config(config)
|
||||
{}
|
||||
|
||||
blt::expected<crossover_t::crossover_point_t, error_t> get_crossover_point(gp_program& program, const tree_t& c1, const tree_t& c2) const;
|
||||
std::optional<crossover_t::crossover_point_t> get_crossover_point(gp_program& program, const tree_t& c1, const tree_t& c2) const;
|
||||
|
||||
/**
|
||||
* child1 and child2 are copies of the parents, the result of selecting a crossover point and performing standard subtree crossover.
|
||||
|
@ -97,7 +87,7 @@ namespace blt::gp
|
|||
* @param p2 reference to the second parent
|
||||
* @return expected pair of child otherwise returns error enum
|
||||
*/
|
||||
virtual blt::expected<result_t, error_t> apply(gp_program& program, const tree_t& p1, const tree_t& p2); // NOLINT
|
||||
virtual bool apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2); // NOLINT
|
||||
|
||||
virtual ~crossover_t() = default;
|
||||
|
||||
|
@ -126,7 +116,7 @@ namespace blt::gp
|
|||
explicit mutation_t(const config_t& config): config(config)
|
||||
{}
|
||||
|
||||
virtual tree_t apply(gp_program& program, const tree_t& p);
|
||||
virtual bool apply(gp_program& program, const tree_t& p, tree_t& c);
|
||||
|
||||
// returns the point after the mutation
|
||||
blt::size_t mutate_point(gp_program& program, tree_t& c, blt::size_t node);
|
||||
|
@ -155,7 +145,7 @@ namespace blt::gp
|
|||
explicit advanced_mutation_t(const config_t& config): mutation_t(config)
|
||||
{}
|
||||
|
||||
tree_t apply(gp_program& program, const tree_t& p) final;
|
||||
bool apply(gp_program& program, const tree_t& p, tree_t& c) final;
|
||||
|
||||
advanced_mutation_t& set_per_node_mutation_chance(double v)
|
||||
{
|
||||
|
|
|
@ -56,6 +56,37 @@ namespace blt::gp
|
|||
public:
|
||||
explicit tree_t(gp_program& program);
|
||||
|
||||
tree_t(const tree_t& copy) = default;
|
||||
|
||||
tree_t& operator=(const tree_t& copy)
|
||||
{
|
||||
if (this == ©)
|
||||
return *this;
|
||||
copy_fast(copy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function copies the data from the provided tree, will attempt to reserve and copy in one step.
|
||||
* will avoid reallocation if enough space is already present.
|
||||
*/
|
||||
void copy_fast(const tree_t& copy)
|
||||
{
|
||||
if (this == ©)
|
||||
return;
|
||||
values.reserve(copy.values.internal_storage_size());
|
||||
values.reset();
|
||||
values.insert(copy.values);
|
||||
|
||||
operations.clear();
|
||||
operations.reserve(copy.operations.size());
|
||||
operations.insert(operations.begin(), copy.operations.begin(), copy.operations.end());
|
||||
}
|
||||
|
||||
tree_t(tree_t&& move) = default;
|
||||
|
||||
tree_t& operator=(tree_t&& move) = default;
|
||||
|
||||
void clear(gp_program& program);
|
||||
|
||||
struct child_t
|
||||
|
@ -178,6 +209,14 @@ namespace blt::gp
|
|||
tree_t tree;
|
||||
fitness_t fitness;
|
||||
|
||||
void copy_fast(const tree_t& copy)
|
||||
{
|
||||
// fast copy of the tree
|
||||
tree.copy_fast(copy);
|
||||
// reset fitness
|
||||
fitness = {};
|
||||
}
|
||||
|
||||
individual_t() = delete;
|
||||
|
||||
explicit individual_t(tree_t&& tree): tree(std::move(tree))
|
||||
|
@ -284,6 +323,11 @@ namespace blt::gp
|
|||
return individuals;
|
||||
}
|
||||
|
||||
[[nodiscard]] const tracked_vector<individual_t>& get_individuals() const
|
||||
{
|
||||
return individuals;
|
||||
}
|
||||
|
||||
population_tree_iterator for_each_tree()
|
||||
{
|
||||
return population_tree_iterator{individuals, 0};
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
namespace blt::gp
|
||||
{
|
||||
|
||||
tree_t& select_best_t::select(gp_program&, population_t& pop)
|
||||
const tree_t& select_best_t::select(gp_program&, const population_t& pop)
|
||||
{
|
||||
auto& first = pop.get_individuals()[0];
|
||||
double best_fitness = first.fitness.adjusted_fitness;
|
||||
tree_t* tree = &first.tree;
|
||||
const tree_t* tree = &first.tree;
|
||||
for (auto& ind : pop.get_individuals())
|
||||
{
|
||||
if (ind.fitness.adjusted_fitness > best_fitness)
|
||||
|
@ -37,11 +37,11 @@ namespace blt::gp
|
|||
return *tree;
|
||||
}
|
||||
|
||||
tree_t& select_worst_t::select(gp_program&, population_t& pop)
|
||||
const tree_t& select_worst_t::select(gp_program&, const population_t& pop)
|
||||
{
|
||||
auto& first = pop.get_individuals()[0];
|
||||
double worst_fitness = first.fitness.adjusted_fitness;
|
||||
tree_t* tree = &first.tree;
|
||||
const tree_t* tree = &first.tree;
|
||||
for (auto& ind : pop.get_individuals())
|
||||
{
|
||||
if (ind.fitness.adjusted_fitness < worst_fitness)
|
||||
|
@ -53,12 +53,12 @@ namespace blt::gp
|
|||
return *tree;
|
||||
}
|
||||
|
||||
tree_t& select_random_t::select(gp_program& program, population_t& pop)
|
||||
const tree_t& select_random_t::select(gp_program& program, const population_t& pop)
|
||||
{
|
||||
return pop.get_individuals()[program.get_random().get_size_t(0ul, pop.get_individuals().size())].tree;
|
||||
}
|
||||
|
||||
tree_t& select_tournament_t::select(gp_program& program, population_t& pop)
|
||||
const tree_t& select_tournament_t::select(gp_program& program, const population_t& pop)
|
||||
{
|
||||
blt::u64 best = program.get_random().get_u64(0, pop.get_individuals().size());
|
||||
auto& i_ref = pop.get_individuals();
|
||||
|
@ -71,7 +71,7 @@ namespace blt::gp
|
|||
return i_ref[best].tree;
|
||||
}
|
||||
|
||||
tree_t& select_fitness_proportionate_t::select(gp_program& program, population_t& pop)
|
||||
const tree_t& select_fitness_proportionate_t::select(gp_program& program, const population_t& pop)
|
||||
{
|
||||
auto& stats = program.get_population_stats();
|
||||
auto choice = program.get_random().get_double();
|
||||
|
|
|
@ -59,23 +59,21 @@ namespace blt::gp
|
|||
mutation_t::config_t::config_t(): generator(grow_generator)
|
||||
{}
|
||||
|
||||
blt::expected<crossover_t::result_t, crossover_t::error_t> crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2) // NOLINT
|
||||
bool crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) // NOLINT
|
||||
{
|
||||
result_t result{p1, p2};
|
||||
|
||||
auto& c1 = result.child1;
|
||||
auto& c2 = result.child2;
|
||||
c1.copy_fast(p1);
|
||||
c2.copy_fast(p2);
|
||||
|
||||
auto& c1_ops = c1.get_operations();
|
||||
auto& c2_ops = c2.get_operations();
|
||||
|
||||
if (c1_ops.size() < 5 || c2_ops.size() < 5)
|
||||
return blt::unexpected(error_t::TREE_TOO_SMALL);
|
||||
return false;
|
||||
|
||||
auto point = get_crossover_point(program, c1, c2);
|
||||
auto point = get_crossover_point(program, p1, p2);
|
||||
|
||||
if (!point)
|
||||
return blt::unexpected(point.error());
|
||||
return false;
|
||||
|
||||
auto crossover_point_begin_itr = c1_ops.begin() + point->p1_crossover_point;
|
||||
auto crossover_point_end_itr = c1_ops.begin() + c1.find_endpoint(program, point->p1_crossover_point);
|
||||
|
@ -104,8 +102,8 @@ namespace blt::gp
|
|||
blt::size_t c2_stack_for_bytes = accumulate_type_sizes(found_point_begin_itr, found_point_end_itr);
|
||||
auto c1_total = static_cast<blt::ptrdiff_t>(c1_stack_after_bytes + c1_stack_for_bytes);
|
||||
auto c2_total = static_cast<blt::ptrdiff_t>(c2_stack_after_bytes + c2_stack_for_bytes);
|
||||
auto copy_ptr_c1 = get_thread_pointer_for_size<struct c1>(c1_total);
|
||||
auto copy_ptr_c2 = get_thread_pointer_for_size<struct c2>(c2_total);
|
||||
auto copy_ptr_c1 = get_thread_pointer_for_size<struct c1_t>(c1_total);
|
||||
auto copy_ptr_c2 = get_thread_pointer_for_size<struct c2_t>(c2_total);
|
||||
|
||||
c1_stack.copy_to(copy_ptr_c1, c1_total);
|
||||
c1_stack.pop_bytes(c1_total);
|
||||
|
@ -131,8 +129,8 @@ namespace blt::gp
|
|||
c2_ops.insert(++insert_point_c2, c1_operators.begin(), c1_operators.end());
|
||||
|
||||
#if BLT_DEBUG_LEVEL >= 2
|
||||
blt::size_t c1_found_bytes = result.child1.get_values().size().total_used_bytes;
|
||||
blt::size_t c2_found_bytes = result.child2.get_values().size().total_used_bytes;
|
||||
blt::size_t c1_found_bytes = c1.get_values().size().total_used_bytes;
|
||||
blt::size_t c2_found_bytes = c2.get_values().size().total_used_bytes;
|
||||
blt::size_t c1_expected_bytes = std::accumulate(result.child1.get_operations().begin(), result.child1.get_operations().end(), 0ul,
|
||||
[](const auto& v1, const auto& v2) {
|
||||
if (v2.is_value)
|
||||
|
@ -153,10 +151,10 @@ namespace blt::gp
|
|||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
blt::expected<crossover_t::crossover_point_t, crossover_t::error_t> crossover_t::get_crossover_point(gp_program& program, const tree_t& c1,
|
||||
std::optional<crossover_t::crossover_point_t> crossover_t::get_crossover_point(gp_program& program, const tree_t& c1,
|
||||
const tree_t& c2) const
|
||||
{
|
||||
auto& c1_ops = c1.get_operations();
|
||||
|
@ -194,10 +192,10 @@ namespace blt::gp
|
|||
}
|
||||
}
|
||||
if (!found)
|
||||
return blt::unexpected(error_t::NO_VALID_TYPE);
|
||||
return {};
|
||||
}
|
||||
// should we try again over the whole tree? probably not.
|
||||
return blt::unexpected(error_t::NO_VALID_TYPE);
|
||||
return {};
|
||||
} else
|
||||
{
|
||||
attempted_point = program.get_random().get_size_t(1ul, c2_ops.size());
|
||||
|
@ -213,13 +211,13 @@ namespace blt::gp
|
|||
return crossover_point_t{static_cast<blt::ptrdiff_t>(crossover_point), static_cast<blt::ptrdiff_t>(attempted_point)};
|
||||
}
|
||||
|
||||
tree_t mutation_t::apply(gp_program& program, const tree_t& p)
|
||||
bool mutation_t::apply(gp_program& program, const tree_t& p, tree_t& c)
|
||||
{
|
||||
auto c = p;
|
||||
c.copy_fast(p);
|
||||
|
||||
mutate_point(program, c, program.get_random().get_size_t(0ul, c.get_operations().size()));
|
||||
|
||||
return c;
|
||||
return true;
|
||||
}
|
||||
|
||||
blt::size_t mutation_t::mutate_point(gp_program& program, tree_t& c, blt::size_t node)
|
||||
|
@ -304,10 +302,10 @@ namespace blt::gp
|
|||
return begin_point + new_ops_r.size();
|
||||
}
|
||||
|
||||
tree_t advanced_mutation_t::apply(gp_program& program, const tree_t& p)
|
||||
bool advanced_mutation_t::apply(gp_program& program, const tree_t& p, tree_t& c)
|
||||
{
|
||||
// child tree
|
||||
tree_t c = p;
|
||||
c.copy_fast(p);
|
||||
|
||||
auto& ops = c.get_operations();
|
||||
auto& vals = c.get_values();
|
||||
|
@ -732,6 +730,6 @@ namespace blt::gp
|
|||
}
|
||||
#endif
|
||||
|
||||
return c;
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue