i think there is a jim nearby
parent
5346a2c77a
commit
580d017d3c
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.45)
|
project(blt-gp VERSION 0.0.46)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,14 @@ namespace blt::gp
|
||||||
blt::u32 argc_context = 0;
|
blt::u32 argc_context = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct config_t
|
||||||
|
{
|
||||||
|
// number of times crossover will try to pick a valid point in the tree. this is purely based on the return type of the operators
|
||||||
|
blt::u16 max_crossover_tries = 5;
|
||||||
|
// if we fail to find a point in the tree, should we search forward from the last point to the end of the operators?
|
||||||
|
bool should_crossover_try_forward = false;
|
||||||
|
};
|
||||||
|
|
||||||
struct operator_info
|
struct operator_info
|
||||||
{
|
{
|
||||||
std::vector<type_id> argument_types;
|
std::vector<type_id> argument_types;
|
||||||
|
@ -287,9 +295,15 @@ namespace blt::gp
|
||||||
storage = std::move(op);
|
storage = std::move(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline const config_t& get_config() const
|
||||||
|
{
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type_provider& system;
|
type_provider& system;
|
||||||
blt::gp::stack_allocator alloc;
|
blt::gp::stack_allocator alloc;
|
||||||
|
config_t config;
|
||||||
|
|
||||||
operator_storage storage;
|
operator_storage storage;
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,13 @@ namespace blt::gp
|
||||||
|
|
||||||
struct op_container_t
|
struct op_container_t
|
||||||
{
|
{
|
||||||
op_container_t(detail::callable_t& func, detail::transfer_t& transfer, bool is_value):
|
op_container_t(detail::callable_t& func, detail::transfer_t& transfer, operator_id id, bool is_value):
|
||||||
func(func), transfer(transfer), is_value(is_value)
|
func(func), transfer(transfer), id(id), is_value(is_value)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
detail::callable_t& func;
|
detail::callable_t& func;
|
||||||
detail::transfer_t& transfer;
|
detail::transfer_t& transfer;
|
||||||
|
operator_id id;
|
||||||
bool is_value;
|
bool is_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ namespace blt::gp
|
||||||
tree.get_operations().emplace_back(
|
tree.get_operations().emplace_back(
|
||||||
info.function,
|
info.function,
|
||||||
info.transfer,
|
info.transfer,
|
||||||
|
top.id,
|
||||||
args.program.is_static(top.id));
|
args.program.is_static(top.id));
|
||||||
max_depth = std::max(max_depth, top.depth);
|
max_depth = std::max(max_depth, top.depth);
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,60 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <blt/gp/transformers.h>
|
#include <blt/gp/transformers.h>
|
||||||
|
#include <blt/gp/program.h>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
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
|
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
|
||||||
{
|
{
|
||||||
|
const auto& config = program.get_config();
|
||||||
result_t result{p1, p2};
|
result_t result{p1, p2};
|
||||||
|
|
||||||
|
auto& c1 = result.child1;
|
||||||
|
auto& c2 = result.child2;
|
||||||
|
|
||||||
|
auto& c1_ops = c1.get_operations();
|
||||||
|
auto& c2_ops = c2.get_operations();
|
||||||
|
|
||||||
|
std::uniform_int_distribution op_sel1(1ul, c1_ops.size() - 1);
|
||||||
|
std::uniform_int_distribution op_sel2(1ul, c2_ops.size() - 1);
|
||||||
|
|
||||||
|
blt::size_t crossover_point = op_sel1(program.get_random());
|
||||||
|
blt::size_t attempted_point = 0;
|
||||||
|
|
||||||
|
const auto& crossover_point_type = program.get_operator_info(c1_ops[crossover_point].id);
|
||||||
|
operator_info* attempted_point_type = nullptr;
|
||||||
|
|
||||||
|
blt::size_t counter = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (counter >= config.max_crossover_tries)
|
||||||
|
{
|
||||||
|
if (config.should_crossover_try_forward)
|
||||||
|
{
|
||||||
|
for (auto i = attempted_point + 1; i < c2_ops.size(); i++)
|
||||||
|
{
|
||||||
|
auto* info = &program.get_operator_info(c2_ops[i].id);
|
||||||
|
if (info->return_type == crossover_point_type.return_type)
|
||||||
|
{
|
||||||
|
attempted_point = i;
|
||||||
|
attempted_point_type = info;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// should we try again over the whole tree? probably not.
|
||||||
|
return blt::unexpected(error_t::NO_VALID_TYPE);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
attempted_point = op_sel2(program.get_random());
|
||||||
|
attempted_point_type = &program.get_operator_info(c2_ops[attempted_point].id);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
} while (crossover_point_type.return_type != attempted_point_type->return_type);
|
||||||
|
|
||||||
|
const auto& found_point_type = *attempted_point_type;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace blt::gp
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
operation.func(context, values_process, value_stack);
|
operation.func(context, values_process, value_stack);
|
||||||
operations_stack.emplace_back(empty_callable, operation.transfer, true);
|
operations_stack.emplace_back(empty_callable, operation.transfer, operation.id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|
Loading…
Reference in New Issue