all mutation from karl sim paper implemented
parent
859f1c9dba
commit
9675abd672
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(image-gp-6 VERSION 0.0.40)
|
project(image-gp-6 VERSION 0.0.42)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,6 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
EXPRESSION, // Generate a new random expression
|
EXPRESSION, // Generate a new random expression
|
||||||
ADJUST, // adjust the value of the type. (if it is a function it will mutate it to a different one)
|
ADJUST, // adjust the value of the type. (if it is a function it will mutate it to a different one)
|
||||||
//FUNC, // Change node into a different function. Args will be generated / removed.
|
|
||||||
SUB_FUNC, // subexpression becomes argument to new random function. Other args are generated.
|
SUB_FUNC, // subexpression becomes argument to new random function. Other args are generated.
|
||||||
JUMP_FUNC, // subexpression becomes this new node. Other arguments discarded.
|
JUMP_FUNC, // subexpression becomes this new node. Other arguments discarded.
|
||||||
COPY, // node can become copy of another subexpression.
|
COPY, // node can become copy of another subexpression.
|
||||||
|
@ -85,12 +84,11 @@ namespace blt::gp
|
||||||
double per_node_mutation_chance = 1.0;
|
double per_node_mutation_chance = 1.0;
|
||||||
|
|
||||||
static constexpr std::array<double, operators_size> mutation_operator_chances = aggregate_array<operators_size>(
|
static constexpr std::array<double, operators_size> mutation_operator_chances = aggregate_array<operators_size>(
|
||||||
0.01, // EXPRESSION
|
0.05, // EXPRESSION
|
||||||
0.11, // ADJUST
|
0.1, // ADJUST
|
||||||
//0.05, // FUNC
|
|
||||||
0.01, // SUB_FUNC
|
0.01, // SUB_FUNC
|
||||||
0.1, // JUMP_FUNC
|
0.15, // JUMP_FUNC
|
||||||
0.05 // COPY
|
0.12 // COPY
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6e45ea3d6de5c3686c969f9fdd706c527560cd8c
|
Subproject commit 766befd9495bb3b8ef399947801d6ea96b915779
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename>
|
template<typename>
|
||||||
static blt::u8* get_thread_pointer_for_size(blt::size_t bytes)
|
static blt::u8* get_thread_pointer_for_size(blt::size_t bytes)
|
||||||
{
|
{
|
||||||
|
@ -46,10 +45,9 @@ namespace blt::gp
|
||||||
auto& ops = c.get_operations();
|
auto& ops = c.get_operations();
|
||||||
auto& vals = c.get_values();
|
auto& vals = c.get_values();
|
||||||
|
|
||||||
double node_mutation_chance = per_node_mutation_chance * (1.0 / static_cast<double>(ops.size()));
|
|
||||||
|
|
||||||
for (blt::size_t c_node = 0; c_node < ops.size(); c_node++)
|
for (blt::size_t c_node = 0; c_node < ops.size(); c_node++)
|
||||||
{
|
{
|
||||||
|
double node_mutation_chance = per_node_mutation_chance / static_cast<double>(ops.size());
|
||||||
if (!program.get_random().choice(node_mutation_chance))
|
if (!program.get_random().choice(node_mutation_chance))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -95,33 +93,11 @@ namespace blt::gp
|
||||||
program.get_type_non_terminals(current_func_info.return_type.id));
|
program.get_type_non_terminals(current_func_info.return_type.id));
|
||||||
auto& replacement_func_info = program.get_operator_info(random_replacement);
|
auto& replacement_func_info = program.get_operator_info(random_replacement);
|
||||||
|
|
||||||
struct child_t
|
|
||||||
{
|
|
||||||
blt::ptrdiff_t start;
|
|
||||||
// one past the end
|
|
||||||
blt::ptrdiff_t end;
|
|
||||||
};
|
|
||||||
|
|
||||||
// cache memory used for offset data.
|
// cache memory used for offset data.
|
||||||
thread_local static std::vector<child_t> children_data;
|
thread_local static std::vector<tree_t::child_t> children_data;
|
||||||
children_data.clear();
|
children_data.clear();
|
||||||
|
|
||||||
while (children_data.size() < current_func_info.argument_types.size())
|
c.find_child_extends(program, children_data, c_node, current_func_info.argument_types.size());
|
||||||
{
|
|
||||||
auto current_point = children_data.size();
|
|
||||||
child_t prev{};
|
|
||||||
if (current_point == 0)
|
|
||||||
{
|
|
||||||
// first child.
|
|
||||||
prev = {static_cast<blt::ptrdiff_t>(c_node + 1),
|
|
||||||
c.find_endpoint(program, static_cast<blt::ptrdiff_t>(c_node + 1))};
|
|
||||||
children_data.push_back(prev);
|
|
||||||
continue;
|
|
||||||
} else
|
|
||||||
prev = children_data[current_point - 1];
|
|
||||||
child_t next = {prev.end, c.find_endpoint(program, prev.end)};
|
|
||||||
children_data.push_back(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& [index, val] : blt::enumerate(replacement_func_info.argument_types))
|
for (const auto& [index, val] : blt::enumerate(replacement_func_info.argument_types))
|
||||||
{
|
{
|
||||||
|
@ -286,8 +262,6 @@ namespace blt::gp
|
||||||
break;
|
break;
|
||||||
case mutation_operator::SUB_FUNC:
|
case mutation_operator::SUB_FUNC:
|
||||||
{
|
{
|
||||||
BLT_TRACE(ops[c_node].id);
|
|
||||||
BLT_TRACE(std::string(*program.get_name(ops[c_node].id)).c_str());
|
|
||||||
auto& current_func_info = program.get_operator_info(ops[c_node].id);
|
auto& current_func_info = program.get_operator_info(ops[c_node].id);
|
||||||
|
|
||||||
// need to:
|
// need to:
|
||||||
|
@ -376,11 +350,140 @@ namespace blt::gp
|
||||||
break;
|
break;
|
||||||
case mutation_operator::JUMP_FUNC:
|
case mutation_operator::JUMP_FUNC:
|
||||||
{
|
{
|
||||||
c.print(program, std::cout, false, true);
|
auto& info = program.get_operator_info(ops[c_node].id);
|
||||||
auto parent = c.find_parent(program, static_cast<blt::ptrdiff_t>(c_node));
|
blt::size_t argument_index = -1ul;
|
||||||
BLT_TRACE_STREAM << "Found Parent: " << *program.get_name(ops[parent].id) << " for child " << *program.get_name(ops[c_node].id) << "\n";
|
for (const auto& [index, v] : blt::enumerate(info.argument_types))
|
||||||
}break;
|
{
|
||||||
|
if (v.id == info.return_type.id)
|
||||||
|
{
|
||||||
|
argument_index = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argument_index == -1ul)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
static thread_local std::vector<tree_t::child_t> child_data;
|
||||||
|
child_data.clear();
|
||||||
|
|
||||||
|
c.find_child_extends(program, child_data, c_node, info.argument_types.size());
|
||||||
|
|
||||||
|
auto child_index = child_data.size() - 1 - argument_index;
|
||||||
|
auto child = child_data[child_index];
|
||||||
|
auto for_bytes = c.total_value_bytes(child.start, child.end);
|
||||||
|
auto after_bytes = c.total_value_bytes(child_data.back().end);
|
||||||
|
|
||||||
|
auto storage_ptr = get_thread_pointer_for_size<struct jump_func>(for_bytes + after_bytes);
|
||||||
|
vals.copy_to(storage_ptr + for_bytes, after_bytes);
|
||||||
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(after_bytes));
|
||||||
|
|
||||||
|
for (auto i = static_cast<blt::ptrdiff_t>(child_data.size() - 1); i > static_cast<blt::ptrdiff_t>(child_index); i--)
|
||||||
|
{
|
||||||
|
auto& cc = child_data[i];
|
||||||
|
auto bytes = c.total_value_bytes(cc.start, cc.end);
|
||||||
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(bytes));
|
||||||
|
ops.erase(ops.begin() + cc.start, ops.begin() + cc.end);
|
||||||
|
}
|
||||||
|
vals.copy_to(storage_ptr, for_bytes);
|
||||||
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(for_bytes));
|
||||||
|
for (auto i = static_cast<blt::ptrdiff_t>(child_index - 1); i >= 0; i--)
|
||||||
|
{
|
||||||
|
auto& cc = child_data[i];
|
||||||
|
auto bytes = c.total_value_bytes(cc.start, cc.end);
|
||||||
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(bytes));
|
||||||
|
ops.erase(ops.begin() + cc.start, ops.begin() + cc.end);
|
||||||
|
}
|
||||||
|
ops.erase(ops.begin() + static_cast<blt::ptrdiff_t>(c_node));
|
||||||
|
vals.copy_from(storage_ptr, for_bytes + after_bytes);
|
||||||
|
|
||||||
|
#if BLT_DEBUG_LEVEL >= 2
|
||||||
|
if (!c.check(program, nullptr))
|
||||||
|
{
|
||||||
|
std::cout << "Parent: " << std::endl;
|
||||||
|
p.print(program, std::cout, false, true);
|
||||||
|
std::cout << "Child Values:" << std::endl;
|
||||||
|
c.print(program, std::cout, true, true);
|
||||||
|
std::cout << std::endl;
|
||||||
|
BLT_ABORT("Tree Check Failed.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
case mutation_operator::COPY:
|
case mutation_operator::COPY:
|
||||||
|
{
|
||||||
|
auto& info = program.get_operator_info(ops[c_node].id);
|
||||||
|
blt::size_t pt = -1ul;
|
||||||
|
blt::size_t pf = -1ul;
|
||||||
|
for (const auto& [index, v] : blt::enumerate(info.argument_types))
|
||||||
|
{
|
||||||
|
for (blt::size_t i = index + 1; i < info.argument_types.size(); i++)
|
||||||
|
{
|
||||||
|
auto& v1 = info.argument_types[i];
|
||||||
|
if (v == v1)
|
||||||
|
{
|
||||||
|
if (pt == -1ul)
|
||||||
|
pt = index;
|
||||||
|
else
|
||||||
|
pf = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pt != -1ul && pf != -1ul)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pt == -1ul || pf == -1ul)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
blt::size_t from = 0;
|
||||||
|
blt::size_t to = 0;
|
||||||
|
|
||||||
|
if (program.get_random().choice())
|
||||||
|
{
|
||||||
|
from = pt;
|
||||||
|
to = pf;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
from = pf;
|
||||||
|
to = pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static thread_local std::vector<tree_t::child_t> child_data;
|
||||||
|
child_data.clear();
|
||||||
|
|
||||||
|
c.find_child_extends(program, child_data, c_node, info.argument_types.size());
|
||||||
|
|
||||||
|
auto from_index = child_data.size() - 1 - from;
|
||||||
|
auto to_index = child_data.size() - 1 - to;
|
||||||
|
auto& from_child = child_data[from_index];
|
||||||
|
auto& to_child = child_data[to_index];
|
||||||
|
blt::size_t from_bytes = c.total_value_bytes(from_child.start, from_child.end);
|
||||||
|
blt::size_t after_from_bytes = c.total_value_bytes(from_child.end);
|
||||||
|
blt::size_t to_bytes = c.total_value_bytes(to_child.start, to_child.end);
|
||||||
|
blt::size_t after_to_bytes = c.total_value_bytes(to_child.end);
|
||||||
|
|
||||||
|
auto after_bytes = std::max(after_from_bytes, after_to_bytes);
|
||||||
|
|
||||||
|
auto from_ptr = get_thread_pointer_for_size<struct copy>(from_bytes);
|
||||||
|
auto after_ptr = get_thread_pointer_for_size<struct copy_after>(after_bytes);
|
||||||
|
|
||||||
|
vals.copy_to(after_ptr, after_from_bytes);
|
||||||
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(after_from_bytes));
|
||||||
|
vals.copy_to(from_ptr, from_bytes);
|
||||||
|
vals.copy_from(after_ptr, after_from_bytes);
|
||||||
|
|
||||||
|
vals.copy_to(after_ptr, after_to_bytes);
|
||||||
|
vals.pop_bytes(static_cast<blt::ptrdiff_t>(after_to_bytes + to_bytes));
|
||||||
|
|
||||||
|
vals.copy_from(from_ptr, from_bytes);
|
||||||
|
vals.copy_from(after_ptr, after_to_bytes);
|
||||||
|
|
||||||
|
static std::vector<op_container_t> op_copy;
|
||||||
|
op_copy.clear();
|
||||||
|
op_copy.insert(op_copy.begin(), ops.begin() + from_child.start, ops.begin() + from_child.end);
|
||||||
|
|
||||||
|
ops.erase(ops.begin() + to_child.start, ops.begin() + to_child.end);
|
||||||
|
ops.insert(ops.begin() + to_child.start, op_copy.begin(), op_copy.end());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case mutation_operator::END:
|
case mutation_operator::END:
|
||||||
default:
|
default:
|
||||||
|
@ -404,8 +507,6 @@ namespace blt::gp
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BLT_TRACE("- - - - - - - - - Passed and finished - - - - - - - - -");
|
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue