diff --git a/.idea/editor.xml b/.idea/editor.xml
index 5fff85e..b0d69ef 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -240,5 +240,244 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 84ec579..b239ee6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,7 +27,7 @@ macro(compile_options target_name)
sanitizers(${target_name})
endmacro()
-project(blt-gp VERSION 0.3.24)
+project(blt-gp VERSION 0.3.25)
include(CTest)
diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h
index 36c74d0..fca0a56 100644
--- a/include/blt/gp/tree.h
+++ b/include/blt/gp/tree.h
@@ -221,9 +221,14 @@ namespace blt::gp
void move(size_t bytes_to_move);
+ [[nodiscard]] bool empty() const
+ {
+ return bytes == 0;
+ }
+
~byte_only_transaction_t()
{
- if (bytes > 0)
+ if (!empty())
{
tree.values.copy_from(data, bytes);
bytes = 0;
@@ -458,7 +463,7 @@ namespace blt::gp
* 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 operator_index)
+ void temporary_move(const size_t)
{
// return obt_move_t{*this, operator_index};
}
diff --git a/src/transformers.cpp b/src/transformers.cpp
index dba6549..88b2e9c 100644
--- a/src/transformers.cpp
+++ b/src/transformers.cpp
@@ -26,6 +26,26 @@
namespace blt::gp
{
+#if BLT_DEBUG_LEVEL >= 2
+ std::atomic_uint64_t mutate_point_counter = 0;
+ std::atomic_uint64_t mutate_expression_counter = 0;
+ std::atomic_uint64_t mutate_adjust_counter = 0;
+ std::atomic_uint64_t mutate_sub_func_counter = 0;
+ std::atomic_uint64_t mutate_jump_counter = 0;
+ std::atomic_uint64_t mutate_copy_counter = 0;
+
+ inline void print_mutate_stats()
+ {
+ std::cerr << "Mutation statistics:" << std::endl;
+ std::cerr << "\tSuccessful Point Mutations: " << mutate_point_counter << std::endl;
+ std::cerr << "\tSuccessful Expression Mutations: " << mutate_expression_counter << std::endl;
+ std::cerr << "\tSuccessful Adjust Mutations: " << mutate_adjust_counter << std::endl;
+ std::cerr << "\tSuccessful Sub Func Mutations: " << mutate_sub_func_counter << std::endl;
+ std::cerr << "\tSuccessful Func Jump Mutations: " << mutate_jump_counter << std::endl;
+ std::cerr << "\tSuccessful Copy Mutations: " << mutate_copy_counter << std::endl;
+ }
+#endif
+
grow_generator_t grow_generator;
inline tree_t& get_static_tree_tl(gp_program& program)
@@ -84,8 +104,6 @@ namespace blt::gp
throw std::runtime_error("Tree check failed");
#endif
- c1.get_depth(program);
-
return true;
}
@@ -137,7 +155,11 @@ namespace blt::gp
// 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 (!c.check(detail::debug::context_ptr))
+ {
+ print_mutate_stats();
throw std::runtime_error("Mutate Point tree check failed");
+ }
+ ++mutate_point_counter;
#endif
return node.pos + new_tree.size();
}
@@ -146,22 +168,12 @@ namespace blt::gp
{
for (size_t c_node = 0; c_node < c.size(); c_node++)
{
+#if BLT_DEBUG_LEVEL >= 2
+ auto c_copy = c;
+#endif
if (!program.get_random().choice(per_node_mutation_chance / static_cast(c.size())))
continue;
-#if BLT_DEBUG_LEVEL >= 2
- tree_t c_copy = c;
- if (!c.check(detail::debug::context_ptr))
- {
- std::cout << "Parent: " << std::endl;
- p.print(std::cout, false, false);
- std::cout << "Child Values:" << std::endl;
- c.print(std::cout, false, false);
- std::cout << std::endl;
- BLT_ABORT("Pre-check Tree Check Failed.");
- }
-#endif
-
// select an operator to apply
auto selected_point = static_cast(mutation_operator::COPY);
auto choice = program.get_random().get_double();
@@ -189,6 +201,9 @@ namespace blt::gp
{
case mutation_operator::EXPRESSION:
c_node += mutate_point(program, c, c.subtree_from_point(static_cast(c_node)));
+#if BLT_DEBUG_LEVEL >= 2
+ ++mutate_expression_counter;
+#endif
break;
case mutation_operator::ADJUST:
{
@@ -239,7 +254,11 @@ namespace blt::gp
#if BLT_DEBUG_LEVEL >= 2
if (!c.check(detail::debug::context_ptr))
+ {
+ print_mutate_stats();
throw std::runtime_error("Adjust Tree check failed");
+ }
+ ++mutate_adjust_counter;
#endif
}
}
@@ -286,8 +305,10 @@ namespace blt::gp
std::cout << "Child Values:" << std::endl;
c.print(std::cout, false, false);
std::cout << std::endl;
+ print_mutate_stats();
BLT_ABORT("Adjust Tree Check Failed.");
}
+ ++mutate_adjust_counter;
#endif
}
break;
@@ -373,8 +394,10 @@ namespace blt::gp
std::cout << "Child:" << std::endl;
c.print(std::cout, false, false);
std::cout << std::endl;
+ print_mutate_stats();
BLT_ABORT("SUB_FUNC Tree Check Failed.");
}
+ ++mutate_sub_func_counter;
#endif
}
break;
@@ -404,11 +427,6 @@ namespace blt::gp
thread_local tree_t child_tree{program};
c.copy_subtree(tree_t::subtree_point_t(child.start), child.end, child_tree);
- if (!child_tree.check(detail::debug::context_ptr))
- {
- child_tree.print(std::cout, false, true);
- BLT_ABORT("We found an error");
- }
c.delete_subtree(tree_t::subtree_point_t(static_cast(c_node)));
c.insert_subtree(tree_t::subtree_point_t(static_cast(c_node)), child_tree);
child_tree.clear(program);
@@ -448,8 +466,10 @@ namespace blt::gp
c.print(std::cout, false, false);
std::cout << std::endl;
BLT_ERROR("Failed at mutation index %lu/%lu", c_node, c.size());
+ print_mutate_stats();
BLT_ABORT("JUMP_FUNC Tree Check Failed.");
}
+ ++mutate_jump_counter;
#endif
}
break;
@@ -515,8 +535,10 @@ namespace blt::gp
std::cout << "Child Values:" << std::endl;
c.print(std::cout, false, false);
std::cout << std::endl;
+ print_mutate_stats();
BLT_ABORT("COPY Tree Check Failed.");
}
+ ++mutate_copy_counter;
#endif
// size_t from_bytes = c.total_value_bytes(from_child.start, from_child.end);
diff --git a/src/tree.cpp b/src/tree.cpp
index 42906a1..de22fc0 100644
--- a/src/tree.cpp
+++ b/src/tree.cpp
@@ -269,8 +269,13 @@ namespace blt::gp
const size_t after_bytes = accumulate_type_sizes(point_end_itr, operations.end());
- operators.reserve(operators.size() + std::distance(point_begin_itr, point_end_itr));
+ const size_t ops = std::distance(point_begin_itr, point_end_itr);
+ operators.reserve(operators.size() + ops);
+ // TODO something better!
+ for (size_t i = 0; i < ops; ++i)
+ operators.emplace_back(0,0,false, operator_special_flags{});
size_t for_bytes = 0;
+ size_t pos = 0;
for (auto& it : iterate(point_begin_itr, point_end_itr).rev())
{
if (it.is_value())
@@ -282,7 +287,7 @@ namespace blt::gp
++*ptr;
}
}
- operators.emplace_back(it);
+ operators[operators.size() - 1 - (pos++)] = it;
}
stack.copy_from(values, for_bytes, after_bytes);
@@ -682,6 +687,13 @@ namespace blt::gp
m_program->get_operator_flags(new_id)
};
if (operations[point].get_flags().is_ephemeral())
+ {
+ if (move_data.empty())
+ {
+ const size_t after_bytes = accumulate_type_sizes(operations.begin() + static_cast(point) + 1, operations.end());
+ move_data.move(after_bytes);
+ }
handle_operator_inserted(operations[point]);
+ }
}
}
diff --git a/tests/drop_test.cpp b/tests/drop_test.cpp
index 11046c9..0bfce8c 100644
--- a/tests/drop_test.cpp
+++ b/tests/drop_test.cpp
@@ -72,8 +72,8 @@ prog_config_t config = prog_config_t()
.set_initial_max_tree_size(6)
.set_elite_count(2)
.set_crossover_chance(0.8)
- .set_mutation_chance(0.1)
- .set_reproduction_chance(0.1)
+ .set_mutation_chance(0.0)
+ .set_reproduction_chance(0.0)
.set_max_generations(50)
.set_pop_size(50)
.set_thread_count(1);